Am 09.01.25 um 14:34 schrieb Thomas Koenig:
This patch fixes and reorganizes dumping C prototypes.

And here is the "five seconds later, I realized I had forgotten
to attach the patch" e-mail...

diff --git a/gcc/fortran/dump-parse-tree.cc b/gcc/fortran/dump-parse-tree.cc
index 8d31ddfcffb..826f4c6df7a 100644
--- a/gcc/fortran/dump-parse-tree.cc
+++ b/gcc/fortran/dump-parse-tree.cc
@@ -3802,27 +3802,93 @@ gfc_dump_parse_tree (gfc_namespace *ns, FILE *file)
   show_namespace (ns);
 }
 
-/* This part writes BIND(C) definition for use in external C programs.  */
+/* This part writes BIND(C) prototypes and declatations, and prototypes
+   for EXTERNAL preocedures, for use in a C programs.  */
 
 static void write_interop_decl (gfc_symbol *);
 static void write_proc (gfc_symbol *, bool);
+static void show_external_symbol (gfc_gsymbol *, void *);
+static void write_type (gfc_symbol *sym);
+
+/* Do we need to write out an #include <ISO_Fortran_binding.h> or not?  */
+
+static void
+has_cfi_cdesc (gfc_gsymbol *gsym, void *p)
+{
+  bool *data_p = (bool *) p;
+  gfc_formal_arglist *f;
+  gfc_symbol *sym;
+
+  if (*data_p)
+    return;
+
+  if (gsym->ns == NULL || gsym->sym_name == NULL )
+    return;
+
+  gfc_find_symbol (gsym->sym_name, gsym->ns, 0, &sym);
+
+  if (sym == NULL || sym->attr.flavor != FL_PROCEDURE || !sym->attr.is_bind_c)
+    return;
+
+  for (f = sym->formal; f; f = f->next)
+    {
+      gfc_symbol *s;
+      s = f->sym;
+      if (s->as && (s->as->type == AS_ASSUMED_RANK || s->as->type == AS_ASSUMED_SHAPE))
+	{
+	  *data_p = true;
+	  return;
+	}
+    }
+}
+
+static bool
+need_iso_fortran_binding ()
+{
+  bool needs_include = false;
+
+  if (gfc_gsym_root == NULL)
+    return false;
+
+  gfc_traverse_gsymbol (gfc_gsym_root, has_cfi_cdesc, (void *) &needs_include);
+  return needs_include;
+}
 
 void
-gfc_dump_c_prototypes (gfc_namespace *ns, FILE *file)
+gfc_dump_c_prototypes (FILE *file)
 {
+  bool bind_c = true;
   int error_count;
+  gfc_namespace *ns;
   gfc_get_errors (NULL, &error_count);
   if (error_count != 0)
     return;
+
+  if (gfc_gsym_root == NULL)
+    return;
+
   dumpfile = file;
-  gfc_traverse_ns (ns, write_interop_decl);
+  if (need_iso_fortran_binding ())
+    fputs ("#include <ISO_Fortran_binding.h>\n\n", dumpfile);
+
+  for (ns = gfc_global_ns_list; ns; ns = ns->sibling)
+    gfc_traverse_ns (ns, write_type);
+
+  gfc_traverse_gsymbol (gfc_gsym_root, show_external_symbol, (void *) &bind_c);
 }
 
-/* Loop over all global symbols, writing out their declarations.  */
+/* Loop over all external symbols, writing out their declarations.  */
 
 void
 gfc_dump_external_c_prototypes (FILE * file)
 {
+  bool bind_c = false;
+  int error_count;
+
+  gfc_get_errors (NULL, &error_count);
+  if (error_count != 0)
+    return;
+
   dumpfile = file;
   fprintf (dumpfile,
 	   _("/* Prototypes for external procedures generated from %s\n"
@@ -3831,18 +3897,47 @@ gfc_dump_external_c_prototypes (FILE * file)
 	     "   BIND(C) feature of standard Fortran instead.  */\n\n"),
 	   gfc_source_file, pkgversion_string, version_string);
 
-  for (gfc_current_ns = gfc_global_ns_list; gfc_current_ns;
-       gfc_current_ns = gfc_current_ns->sibling)
-    {
-      gfc_symbol *sym = gfc_current_ns->proc_name;
+  if (gfc_gsym_root == NULL)
+    return;
 
-      if (sym == NULL || sym->attr.flavor != FL_PROCEDURE
-	  || sym->attr.is_bind_c)
-	continue;
+  gfc_traverse_gsymbol (gfc_gsym_root, show_external_symbol, (void *) &bind_c);
+}
+
+/* Callback function for dumping external symbols, be they BIND(C) or
+ external.  */
+
+static void
+show_external_symbol (gfc_gsymbol *gsym, void *data)
+{
+  bool bind_c, *data_p;
+  gfc_symbol *sym;
+  const char *name;
+
+  if (gsym->ns == NULL)
+    return;
+
+  name = gsym->sym_name ? gsym->sym_name : gsym->name;
+
+  gfc_find_symbol (name, gsym->ns, 0, &sym);
+  if (sym == NULL)
+    return;
+
+  data_p = (bool *) data;
+  bind_c = *data_p;
 
+  if (bind_c)
+    {
+      if (!sym->attr.is_bind_c)
+	return;
+
+      write_interop_decl (sym);
+    }
+  else
+    {
+      if (sym->attr.flavor != FL_PROCEDURE || sym->attr.is_bind_c)
+	return;
       write_proc (sym, false);
     }
-  return;
 }
 
 enum type_return { T_OK=0, T_WARN, T_ERROR };
@@ -3863,6 +3958,15 @@ get_c_type_name (gfc_typespec *ts, gfc_array_spec *as, const char **pre,
   *asterisk = false;
   *post = "";
   *type_name = "<error>";
+
+  if (as && (as->type == AS_ASSUMED_RANK || as->type == AS_ASSUMED_SHAPE))
+    {
+      *asterisk = true;
+      *post = "";
+      *type_name = "CFI_cdesc_t";
+      return T_OK;
+    }
+
   if (ts->type == BT_REAL || ts->type == BT_INTEGER || ts->type == BT_COMPLEX
       || ts->type == BT_UNSIGNED)
     {
@@ -3982,20 +4086,24 @@ get_c_type_name (gfc_typespec *ts, gfc_array_spec *as, const char **pre,
       ret = T_OK;
     }
 
-  if (ret != T_ERROR && as)
+  if (ret != T_ERROR && as && as->type == AS_EXPLICIT)
     {
       mpz_t sz;
       bool size_ok;
       size_ok = spec_size (as, &sz);
-      gcc_assert (size_ok == true);
-      gmp_snprintf (post_buffer, sizeof(post_buffer), "[%Zd]", sz);
-      *post = post_buffer;
-      mpz_clear (sz);
+      if (size_ok)
+	{
+	  gmp_snprintf (post_buffer, sizeof(post_buffer), "[%Zd]", sz);
+	  *post = post_buffer;
+	  mpz_clear (sz);
+	  *asterisk = false;
+	}
     }
   return ret;
 }
 
 /* Write out a declaration.  */
+
 static void
 write_decl (gfc_typespec *ts, gfc_array_spec *as, const char *sym_name,
 	    bool func_ret, locus *where, bool bind_c)
@@ -4034,6 +4142,11 @@ write_type (gfc_symbol *sym)
 {
   gfc_component *c;
 
+  /* Don't dump our iso c module.  */
+
+  if (sym->from_intmod == INTMOD_ISO_C_BINDING || sym->attr.flavor != FL_DERIVED)
+    return;
+
   fprintf (dumpfile, "typedef struct %s {\n", sym->name);
   for (c = sym->components; c; c = c->next)
     {
@@ -4042,7 +4155,7 @@ write_type (gfc_symbol *sym)
       fputs (";\n", dumpfile);
     }
 
-  fprintf (dumpfile, "} %s;\n", sym->name);
+  fprintf (dumpfile, "} %s;\n\n", sym->name);
 }
 
 /* Write out a variable.  */
@@ -4108,7 +4221,7 @@ write_proc (gfc_symbol *sym, bool bind_c)
     {
       gfc_symbol *s;
       s = f->sym;
-      rok = get_c_type_name (&(s->ts), NULL, &pre, &type_name, &asterisk,
+      rok = get_c_type_name (&(s->ts), s->as, &pre, &type_name, &asterisk,
 			     &post, false);
       if (rok == T_ERROR)
 	{
@@ -4119,7 +4232,8 @@ write_proc (gfc_symbol *sym, bool bind_c)
 	  return;
 	}
 
-      if (!s->attr.value)
+      /* For explicit arrays, we already set the asterisk above.  */
+      if (!s->attr.value && !(s->as && s->as->type == AS_EXPLICIT))
 	asterisk = true;
 
       if (s->attr.intent == INTENT_IN && !s->attr.value)
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index aa495b5487e..b465285552d 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -4060,7 +4060,7 @@ void * gfc_delete_bbt (void *, void *, compare_fn);
 
 /* dump-parse-tree.cc */
 void gfc_dump_parse_tree (gfc_namespace *, FILE *);
-void gfc_dump_c_prototypes (gfc_namespace *, FILE *);
+void gfc_dump_c_prototypes (FILE *);
 void gfc_dump_external_c_prototypes (FILE *);
 void gfc_dump_global_symbols (FILE *);
 void debug (gfc_symbol *);
diff --git a/gcc/fortran/parse.cc b/gcc/fortran/parse.cc
index f65449df9e2..ba111bfe538 100644
--- a/gcc/fortran/parse.cc
+++ b/gcc/fortran/parse.cc
@@ -7529,11 +7529,7 @@ done:
 
   /* First dump BIND(C) prototypes.  */
   if (flag_c_prototypes)
-    {
-      for (gfc_current_ns = gfc_global_ns_list; gfc_current_ns;
-	   gfc_current_ns = gfc_current_ns->sibling)
-	gfc_dump_c_prototypes (gfc_current_ns, stdout);
-    }
+    gfc_dump_c_prototypes (stdout);
 
   /* Dump external prototypes.  */
   if (flag_c_prototypes_external)

Reply via email to