Hello, I found a (unrelated) bug while playing with Andre's PR65894 patch. The dummy argument can get out of sync with the actual argument when there is an (optional) argument missing. I plan to commit the attached fix as obvious later today (after testing).
Mikael
2015-05-08 Mikael Morin <mik...@gcc.gnu.org> * trans-array.c (gfc_walk_elemental_function_args): Don't skip the advance to the next dummy argument when skipping absent optional args.
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c index a17f431..00334b1 100644 --- a/gcc/fortran/trans-array.c +++ b/gcc/fortran/trans-array.c @@ -9092,7 +9092,7 @@ gfc_walk_elemental_function_args (gfc_ss * ss, gfc_actual_arglist *arg, for (; arg; arg = arg->next) { if (!arg->expr || arg->expr->expr_type == EXPR_NULL) - continue; + goto loop_continue; newss = gfc_walk_subexpr (head, arg->expr); if (newss == head) @@ -9122,6 +9122,7 @@ gfc_walk_elemental_function_args (gfc_ss * ss, gfc_actual_arglist *arg, tail = tail->next; } +loop_continue: if (dummy_arg != NULL) dummy_arg = dummy_arg->next; }
! { dg-do run } ! ! The handling of scalar optional arguments passed to elemental procedure ! did not keep actual arguments and dummy arguments synchronized while ! walking them in gfc_walk_elemental_function_args, leading to a ! null pointer dereference in the generated code. ! implicit none integer, parameter :: n = 3 call do_test contains elemental function five(nonopt1, opt1, nonopt2, opt2) integer, intent(in), optional :: opt1, opt2 integer, intent(in) :: nonopt1, nonopt2 integer :: five if (.not. present(opt1) .and. .not. present(opt2)) then five = 5 else five = -7 end if end function five subroutine do_test(opt) integer, optional :: opt integer :: i = -1, a(n) = (/ (i, i=1,n) /) integer :: b(n) b = five(a, nonopt2=i, opt2=opt) if (any(b /= 5)) call abort end subroutine do_test end