https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88611
Richard Biener <rguenth at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|ASSIGNED |NEW CC| |burnus at gcc dot gnu.org Component|tree-optimization |fortran Assignee|rguenth at gcc dot gnu.org |unassigned at gcc dot gnu.org --- Comment #2 from Richard Biener <rguenth at gcc dot gnu.org> --- OK, so this is <var_decl 0x7ffff7fefab0 p type <pointer_type 0x7ffff6896000 type <void_type 0x7ffff688ff18 void VOID align:8 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x7ffff688ff18 pointer_to_this <pointer_type 0x7ffff6896000>> public unsigned DI size <integer_cst 0x7ffff687ab70 constant 64> unit-size <integer_cst 0x7ffff687ab88 constant 8> align:64 warn_if_not_align:0 symtab:0 alias-set 4 canonical-type 0x7ffff6896000 pointer_to_this <pointer_type 0x7ffff689b738>> readonly used static unsigned DI t.f90:8:0 size <integer_cst 0x7ffff687ab70 64> unit-size <integer_cst 0x7ffff687ab88 8> align:64 warn_if_not_align:0 context <function_decl 0x7ffff6a44c00 pr82869_8> initial <integer_cst 0x7ffff689a210 0> chain <var_decl 0x7ffff7fefb40 s>> where the DECL_INITIAL is <integer_cst 0x7ffff689a210 type <integer_type 0x7ffff688f738 integer(kind=8)> constant 0> so a frontend type mismatch we do not "expect" ... type(c_ptr) :: p = c_null_ptr My change uncovers this. The inital value is set here: tree gfc_get_symbol_decl (gfc_symbol * sym) { ... /* Add static initializer. For procedures, it is only needed if SAVE is specified otherwise they need to be reinitialized every time the procedure is entered. The TREE_STATIC is in this case due to -fmax-stack-var-size=. */ DECL_INITIAL (decl) = gfc_conv_initializer (sym->value, &sym->ts, TREE_TYPE (decl), sym->attr.dimension || (sym->attr.codimension && sym->attr.allocatable), sym->attr.pointer || sym->attr.allocatable || sym->ts.type == BT_CLASS, sym->attr.proc_pointer); and there /* Check if we have ISOCBINDING_NULL_PTR or ISOCBINDING_NULL_FUNPTR (these are the only two iso_c_binding derived types that can be used as initialization expressions). If so, we need to modify the 'expr' to be that for a (void *). */ if (expr != NULL && expr->ts.type == BT_DERIVED && expr->ts.is_iso_c && expr->ts.u.derived) { gfc_symbol *derived = expr->ts.u.derived; /* The derived symbol has already been converted to a (void *). Use its kind. */ if (derived->ts.kind == 0) derived->ts.kind = gfc_default_integer_kind; expr = gfc_get_int_expr (derived->ts.kind, NULL, 0); expr->ts.f90_type = derived->ts.f90_type; gfc_init_se (&se, NULL); gfc_conv_constant (&se, expr); gcc_assert (TREE_CODE (se.expr) != CONSTRUCTOR); return se.expr; but it looks like gfc_conv_constant doesn't do the pointer conversion required. It also looks overly complicated to me where at the same time it doesn't try to distinguish between (void *) and void (*)() or whatever type ISOCBINDING_NULL_FUNPTR is supposed to map to... Well. The following "fixes" this for me. Fortran folks? diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c index 27eb2d2ee38..798952c2336 100644 --- a/gcc/fortran/trans-expr.c +++ b/gcc/fortran/trans-expr.c @@ -7085,21 +7085,7 @@ gfc_conv_initializer (gfc_expr * expr, gfc_typespec * ts, tree type, the 'expr' to be that for a (void *). */ if (expr != NULL && expr->ts.type == BT_DERIVED && expr->ts.is_iso_c && expr->ts.u.derived) - { - gfc_symbol *derived = expr->ts.u.derived; - - /* The derived symbol has already been converted to a (void *). Use - its kind. */ - if (derived->ts.kind == 0) - derived->ts.kind = gfc_default_integer_kind; - expr = gfc_get_int_expr (derived->ts.kind, NULL, 0); - expr->ts.f90_type = derived->ts.f90_type; - - gfc_init_se (&se, NULL); - gfc_conv_constant (&se, expr); - gcc_assert (TREE_CODE (se.expr) != CONSTRUCTOR); - return se.expr; - } + return build_int_cst (ptr_type_node, 0); if (array && !procptr) {