https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117303

--- Comment #9 from Kirill Chilikin <chilikin.k at gmail dot com> ---
(In reply to anlauf from comment #8)

Thanks for the replies! I think I understood now what is going on here.
LTO at the beginning loads call graphs. Call graphs are created by
symbol_table::finalize_compilation_unit() from gcc/cgraphunit.cc.
It then calls

#0  (anonymous namespace)::pass_build_cgraph_edges::execute (this=0x4be23a0,
fun=0x7ffff7fba5b0) at ../../gcc/gcc/cgraphbuild.cc:366
#1  0x00000000018d9b3f in execute_one_pass (pass=0x4be23a0) at
../../gcc/gcc/passes.cc:2656
#2  0x00000000018d9f83 in execute_pass_list_1 (pass=0x4be23a0) at
../../gcc/gcc/passes.cc:2769
#3  0x00000000018da00d in execute_pass_list (fn=0x7ffff7fba5b0, pass=0x4be1e60)
at ../../gcc/gcc/passes.cc:2780
#4  0x00000000012f1350 in cgraph_node::analyze (this=0x7ffff6cae660) at
../../gcc/gcc/cgraphunit.cc:701

The first function here, ::pass_build_cgraph_edges::execute(), looks like

  FOR_EACH_LOCAL_DECL (fun, ix, decl)
    if (VAR_P (decl)
        && (TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
        && !DECL_HAS_VALUE_EXPR_P (decl)
        && TREE_TYPE (decl) != error_mark_node)
      varpool_node::finalize_decl (decl);

The declarations decl here need to be of the type VAR_P and property flag
TREE_STATIC to be added to the list of references. But the result of
the processing of CALL(C_FUNLOC(S1)) created in trans-expr.cc:10735 has
a different type, CONST_DECL. Even if CONST_DECL is allowed in the code above,
it does not change anything, because such declarations do not survive to
this point, they are removed during the pass "lower" in record_vars_into()
from gcc/gimple-low.cc. One can modify the code to propagate CONST_DECL
to this stage changing the conditions in record_vars_into() and
add_local_decl() from gcc/function.cc, but then internal compiler error
happens

internal compiler error: tree check: expected var_decl or parm_decl or
result_decl, have const_decl in execute, at cgraphbuild.cc:369

0x38441aa internal_error(char const*, ...)
        ../../gcc/gcc/diagnostic-global-context.cc:787
0x1edce23 tree_check_failed(tree_node const*, char const*, int, char const*,
...)
        ../../gcc/gcc/tree.cc:9204
0x1111373 tree_check3(tree_node*, char const*, int, char const*, tree_code,
tree_code, tree_code)
        ../../gcc/gcc/tree.h:3805
0x13018ac execute
        ../../gcc/gcc/cgraphbuild.cc:369

Thus, it looks like the expected behavior here is to create
a temporary variable. As for LTO, since nothing refers to S1
in the symbol table starting from the main function, it is simply never loaded
at all. The first LTO tree dump test2.ltrans0.ltrans.105t.fixup_cfg3
does not contain it.

This patch fixes it for me:

diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc
index 722ea933249..7b9bd279c01 100644
--- a/gcc/fortran/trans-intrinsic.cc
+++ b/gcc/fortran/trans-intrinsic.cc
@@ -9864,7 +9864,11 @@ conv_isocbinding_function (gfc_se *se, gfc_expr *expr)
       se->expr = gfc_evaluate_now (se->expr, &se->pre);
     }
   else if (expr->value.function.isym->id == GFC_ISYM_C_FUNLOC)
-    gfc_conv_expr_reference (se, arg->expr);
+    {
+      gfc_conv_expr_reference (se, arg->expr);
+      se->expr = convert (pvoid_type_node, se->expr);
+      se->expr = gfc_evaluate_now (se->expr, &se->pre);
+    }
   else if (expr->value.function.isym->id == GFC_ISYM_C_ASSOCIATED)
     {
       gfc_se arg1se;

This code is simply copied from the block just above for C_LOC.

Reply via email to