aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/dump-parse-tree.cc
diff options
context:
space:
mode:
authorThomas Koenig <tkoenig@gcc.gnu.org>2025-01-08 17:06:31 +0100
committerThomas Koenig <tkoenig@gcc.gnu.org>2025-01-16 20:09:18 +0100
commitc158f36027c316aedaa7bde83ca28a3365721fce (patch)
treef30f26f5ce61c293865264e29f9921f4adee9346 /gcc/fortran/dump-parse-tree.cc
parent7f8bb6498691cace5cced224bfc72d13724c9b82 (diff)
downloadgcc-c158f36027c316aedaa7bde83ca28a3365721fce.zip
gcc-c158f36027c316aedaa7bde83ca28a3365721fce.tar.gz
gcc-c158f36027c316aedaa7bde83ca28a3365721fce.tar.bz2
Allow CFI_cdesc_t in argument lists with -fc-prototypes.
This patch fixes and reorganizes dumping C prototypes. It makes the following changes: - BIND(C) types are now always output before any global symbols - CFI_cdesc_t is issued for assumed shape and assumed rank arguments. - BIND(C,NAME="...") entities were not always issued. gcc/fortran/ChangeLog: PR fortran/118359 * dump-parse-tree.cc (show_external_symbol): New function. (write_type): Add prototype, put in restrictions on what not to dump. (has_cfi_cdesc): New function. (need_iso_fortran_binding): New function. (gfc_dump_c_prototypes): Adjust to take only a file output. Add "#include <ISO_Fortran_binding.h" if CFI_cdesc_t is found. Traverse global namespaces to dump types and the globalsymol list to dump external symbols. (gfc_dump_external_c_prototypes): Traverse global namespaces. (get_c_type_name): Handle CFI_cdesc_t. (write_proc): Also pass array spec to get_c_type_name. * gfortran.h (gfc_dump_c_prototypes): Adjust prototype. * parse.cc (gfc_parse_file): Adjust call to gfc_dump_c_prototypes.
Diffstat (limited to 'gcc/fortran/dump-parse-tree.cc')
-rw-r--r--gcc/fortran/dump-parse-tree.cc154
1 files changed, 134 insertions, 20 deletions
diff --git a/gcc/fortran/dump-parse-tree.cc b/gcc/fortran/dump-parse-tree.cc
index 0f983e9..0ae1350 100644
--- a/gcc/fortran/dump-parse-tree.cc
+++ b/gcc/fortran/dump-parse-tree.cc
@@ -4015,27 +4015,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"
@@ -4044,18 +4110,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 };
@@ -4076,6 +4171,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)
{
@@ -4195,20 +4299,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)
@@ -4247,6 +4355,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)
{
@@ -4255,7 +4368,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. */
@@ -4321,7 +4434,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)
{
@@ -4332,7 +4445,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)