Hello world, the attached patch handles dumping prototypes for C functions returning function pointers. For the test case
MODULE test USE, INTRINSIC :: ISO_C_BINDING CONTAINS FUNCTION lookup(idx) BIND(C) type(C_FUNPTR) :: lookup integer(C_INT), VALUE :: idx lookup = C_FUNLOC(x1) END FUNCTION lookup subroutine x1() end subroutine x1 END MODULE test the prototype is void (*lookup (int idx)) (); Regression-tested. Again no test case because I don't know how. During testing, I also found that vtabs were dumped, this is also corrected. OK for trunk? Best regards Thomas gcc/fortran/ChangeLog: PR fortran/119419 * dump-parse-tree.cc (write_funptr_fcn): New function. (write_type): Invoke it for C_FUNPTR. (write_interop_decl): Do not dump vtabs.
diff --git a/gcc/fortran/dump-parse-tree.cc b/gcc/fortran/dump-parse-tree.cc index 1a15757b57b..837469c8aae 100644 --- a/gcc/fortran/dump-parse-tree.cc +++ b/gcc/fortran/dump-parse-tree.cc @@ -4038,6 +4038,7 @@ 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); +static void write_funptr_fcn (gfc_symbol *); /* Do we need to write out an #include <ISO_Fortran_binding.h> or not? */ @@ -4379,9 +4380,10 @@ write_type (gfc_symbol *sym) { gfc_component *c; - /* Don't dump our iso c module. */ + /* Don't dump our iso c module, nor vtypes. */ - if (sym->from_intmod == INTMOD_ISO_C_BINDING || sym->attr.flavor != FL_DERIVED) + if (sym->from_intmod == INTMOD_ISO_C_BINDING || sym->attr.flavor != FL_DERIVED + || sym->attr.vtype) return; fprintf (dumpfile, "typedef struct %s {\n", sym->name); @@ -4495,6 +4497,18 @@ write_formal_arglist (gfc_symbol *sym, bool bind_c) } +/* Write out an interoperable function returning a function pointer. Better + handled separately. As we know nothing about the type, assume + a C default return of int. */ + +static void +write_funptr_fcn (gfc_symbol *sym) +{ + fprintf (dumpfile, "int (*%s (", sym->binding_label); + write_formal_arglist (sym, 1); + fputs (")) ();\n", dumpfile); +} + /* Write out a procedure, including its arguments. */ static void write_proc (gfc_symbol *sym, bool bind_c) @@ -4552,7 +4566,13 @@ write_interop_decl (gfc_symbol *sym) else if (sym->attr.flavor == FL_DERIVED) write_type (sym); else if (sym->attr.flavor == FL_PROCEDURE) - write_proc (sym, true); + { + if (sym->ts.type == BT_DERIVED + && strcmp (sym->ts.u.derived->name, "c_funptr") == 0) + write_funptr_fcn (sym); + else + write_proc (sym, true); + } } /* This section deals with dumping the global symbol tree. */ diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc index 34c8210f66a..efc059908f7 100644 --- a/gcc/fortran/resolve.cc +++ b/gcc/fortran/resolve.cc @@ -12187,6 +12187,34 @@ caf_possible_reallocate (gfc_expr *e) return last_arr_ref && last_arr_ref->u.ar.type == AR_FULL; } +/* Handle C_FUNPTR assignments, for generating C prototypes and for warning if + pointers are assigned to procedures with different interfaces. */ + +static void +check_c_funptr_assign_interface (gfc_expr *lhs, gfc_expr *rhs) +{ + gfc_symbol *lsym, *l_derived_sym, *rsym; + if (lhs->expr_type != EXPR_VARIABLE) + return; + + lsym = lhs->symtree->n.sym; + if (lsym->ts.type != BT_DERIVED || !lsym->attr.is_bind_c) + return; + + l_derived_sym = lsym->ts.u.derived; + + if (!l_derived_sym->attr.is_c_interop + || strcmp (l_derived_sym->name, "c_funptr") != 0) + return; + + if (rhs->expr_type != EXPR_FUNCTION || !rhs->is_c_interop) + return; + + rsym = rhs->symtree->n.sym; + + fprintf (stderr,"%p %p\n", (void *) lhs, (void *) rhs); +} + /* Does everything to resolve an ordinary assignment. Returns true if this is an interface assignment. */ static bool @@ -12437,6 +12465,9 @@ resolve_ordinary_assign (gfc_code *code, gfc_namespace *ns) gfc_check_assign (lhs, rhs, 1); + if (warn_external_argument_mismatch) + check_c_funptr_assign_interface (lhs, rhs); + return false; }