https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71544
--- Comment #11 from kargl at gcc dot gnu.org --- (In reply to Richard Biener from comment #9) > Confirmed as fortran FE bug. The FE manages to set ".r" as fn spec attribute > on save_cptr which specifies that its first argument does not escape. > > It's trans-types.c:create_fn_spec that does this by doing > > for (f = gfc_sym_get_dummy_args (sym); f; f = f->next) > if (spec_len < sizeof (spec)) > { > if (!f->sym || f->sym->attr.pointer || f->sym->attr.target > || f->sym->attr.external || f->sym->attr.cray_pointer > || (f->sym->ts.type == BT_DERIVED > && (f->sym->ts.u.derived->attr.proc_pointer_comp > || f->sym->ts.u.derived->attr.pointer_comp)) > || (f->sym->ts.type == BT_CLASS > && (CLASS_DATA (f->sym)->ts.u.derived->attr.proc_pointer_comp > || CLASS_DATA > (f->sym)->ts.u.derived->attr.pointer_comp))) > spec[spec_len++] = '.'; > else if (f->sym->attr.intent == INTENT_IN) > spec[spec_len++] = 'r'; > else if (f->sym) > spec[spec_len++] = 'w'; > } > > and it looks like the side-effect of marking arguments as not escaping as > soon > as you specify anything else than . was overlooked. > > Or Fortran really doesn't allow args to be stored away but has an exception > for > C binding types which needs handling above. This patch works around the inability of a programmer to type SAVE in the line 'integer(c_int), pointer :: a'. I'm not convinced that gfortran cannot optimize away the assignment 'a = 100' as 'a' is a local variable in subroutine init(). I can find nothing in the standard that requires a compiler to assume that the return result from c_loc() is cached somewhere. I have no intentions to commit this patch. It is recorded here so that I can clean up my development tree. If one thinks about its ramifications, one should arrive at the conclusion that the patch will cause a leak of memory. Index: match.c =================================================================== --- match.c (revision 237481) +++ match.c (working copy) @@ -1349,6 +1349,11 @@ gfc_match_assignment (void) gfc_set_sym_referenced (lvalue->symtree->n.sym); + if (lvalue->symtree->n.sym->attr.pointer == 1 + && lvalue->symtree->n.sym->attr.referenced == 1 + && lvalue->symtree->n.sym->attr.save == SAVE_NONE) + lvalue->symtree->n.sym->attr.save = SAVE_IMPLICIT; + new_st.op = EXEC_ASSIGN; new_st.expr1 = lvalue; new_st.expr2 = rvalue;