Dear Mikael, Thank you very much for the review. You raise some points that I had thought about and others that I hadn't. I also realised that such things as blocks, within the elemental function would through the fix as well. I'll defer doing anything with it until tomorrow night.
I reason that there is always going to be an 'ss', although I should check that it is not gfc_ss_terminator, and that it does not matter which one is flagged. I should add a comment to that effect; it's not quite as hackish as it looks, methinks. I will be back! Paul On 8 February 2015 at 18:27, Mikael Morin <mikael.mo...@sfr.fr> wrote: > Hello Paul, > > comments below > > Le 08/02/2015 16:24, Paul Richard Thomas a écrit : >> >> Index: gcc/fortran/gfortran.h >> =================================================================== >> *** gcc/fortran/gfortran.h (revision 220482) >> --- gcc/fortran/gfortran.h (working copy) >> *************** typedef struct >> *** 789,794 **** >> --- 789,798 ---- >> cannot alias. Note that this is zero for PURE procedures. */ >> unsigned implicit_pure:1; >> >> + /* This set for an elemental function that contains expressions for >> + arrays coming from outside its namespace. */ >> + unsigned potentially_aliased:1; >> + > aliased is more something about pointers, so how about naming it > something like array_outer_dependency? Anyway, that's minor. > > I wonder whether we should negate the meaning, that is set the flag if > there is no external dependency. > If we can get the conditions to set it exhaustively right, both are > equivalent. Otherwise... maybe not. > >> /* This is set if the subroutine doesn't return. Currently, this >> is only possible for intrinsic subroutines. */ >> unsigned noreturn:1; >> Index: gcc/fortran/trans.h >> =================================================================== >> *** gcc/fortran/trans.h (revision 220481) >> --- gcc/fortran/trans.h (working copy) >> *************** typedef struct gfc_ss_info >> *** 226,231 **** >> --- 226,235 ---- >> /* Suppresses precalculation of scalars in WHERE assignments. */ >> unsigned where:1; >> >> + /* Signals that an array argument of an elemental function might be >> aliased, >> + thereby generating a temporary in assignments. */ >> + unsigned potentially_aliased:1; >> + >> /* Tells whether the SS is for an actual argument which can be a NULL >> reference. In other words, the associated dummy argument is OPTIONAL. >> Used to handle elemental procedures. */ >> Index: gcc/fortran/resolve.c >> =================================================================== >> *** gcc/fortran/resolve.c (revision 220481) >> --- gcc/fortran/resolve.c (working copy) >> *************** resolve_variable (gfc_expr *e) >> *** 5054,5059 **** >> --- 5054,5067 ---- >> && gfc_current_ns->parent->parent == sym->ns))) >> sym->attr.host_assoc = 1; >> >> + if (sym->attr.dimension >> + && (sym->ns != gfc_current_ns >> + || sym->attr.use_assoc >> + || sym->attr.in_common) >> + && gfc_elemental (NULL) >> + && gfc_current_ns->proc_name->attr.function) >> + gfc_current_ns->proc_name->attr.potentially_aliased = 1; > I would expect the flag to also be copied between procedures in some > cases; namely if A calls B, and B has the flag, then A has the flag. > There is also the case of external procedures (for which the flag is not > known -> assume the worst) > >> + >> resolve_procedure: >> if (t && !resolve_procedure_expression (e)) >> t = false; >> Index: gcc/fortran/trans-array.c >> =================================================================== >> *** gcc/fortran/trans-array.c (revision 220482) >> --- gcc/fortran/trans-array.c (working copy) >> *************** gfc_conv_resolve_dependencies (gfc_loopi >> *** 4391,4396 **** >> --- 4391,4402 ---- >> { >> ss_expr = ss->info->expr; >> >> + if (ss->info->potentially_aliased) >> + { >> + nDepend = 1; >> + break; >> + } >> + >> if (ss->info->type != GFC_SS_SECTION) >> { >> if (flag_realloc_lhs >> *************** gfc_walk_function_expr (gfc_ss * ss, gfc >> *** 9096,9104 **** >> /* Walk the parameters of an elemental function. For now we always pass >> by reference. */ >> if (sym->attr.elemental || (comp && comp->attr.elemental)) >> ! return gfc_walk_elemental_function_args (ss, >> expr->value.function.actual, >> gfc_get_proc_ifc_for_expr (expr), >> GFC_SS_REFERENCE); >> >> /* Scalar functions are OK as these are evaluated outside the >> scalarization >> loop. Pass back and let the caller deal with it. */ >> --- 9102,9114 ---- >> /* Walk the parameters of an elemental function. For now we always pass >> by reference. */ >> if (sym->attr.elemental || (comp && comp->attr.elemental)) >> ! { >> ! ss = gfc_walk_elemental_function_args (ss, >> expr->value.function.actual, >> gfc_get_proc_ifc_for_expr (expr), >> GFC_SS_REFERENCE); >> + if (sym->attr.potentially_aliased) >> + ss->info->potentially_aliased = 1; >> + } > > This is somewhat hackish, potentially_aliased is a global thing, not > specific to SS, and this may end up marking gfc_ss_terminator as > potentiallly_aliased for example, but I don't see any other obvious way > to do it, so it's OK I guess. > > Anyway, the comp && comp->attr.elemental part of the if should be > handled too (always set the flag in that case?). I actually wonder why > it works without. > > I attach a few variants of the testcase, which don't work yet. > > Mikael > -- Outside of a dog, a book is a man's best friend. Inside of a dog it's too dark to read. Groucho Marx