[Fortran] PR 57160: short-circuit IF only with -ffrontend-optimize

Message ID CAKwh3qjaqauqqujbTM0Qw_vdUaB5vm6+LxSGoL65d-LhLPARxQ@mail.gmail.com
State New
Headers show
Series
  • [Fortran] PR 57160: short-circuit IF only with -ffrontend-optimize
Related show

Commit Message

Janus Weil July 20, 2018, 9:37 p.m.
Hi all,

here is a follow-up patch to my recent commit for PR 85599, also
dealing with the short-circuiting of logical operators. In the course
of the extensive discussion of that PR it became clear that the
Fortran standard allows the short-circuiting of .AND. and .OR.
operators, but does not mandate it.

gfortran currently does short-circuiting, and after my patch for PR
85599 warns about cases where this might remove an impure function
call (which potentially can change results).

Now, this PR (57160) is about code which relies on the
short-circuiting behavior. Since short-circuiting is not guaranteed by
the standard, such code is invalid. Generating a warning or an error
at compile-time is a bit harder here, though, since there are multiple
variations of such a situation, e.g.:
* ASSOCIATED(p) .AND. p%T
* ALLOCATED(a) .AND. a%T
* i<ubound(x) .AND. x(i)
* ...

The suggestion in the PR was to do short-circuiting only with
optimization flags, but inhibit it with -O0, so that the faulty code
will run into a segfault (or runtime error) at least when
optimizations are disabled, and the problem can be identified.

I find this suggestion very reasonable. It makes it possible to detect
invalid code at -O0, while keeping good performance for valid code at
-O{1,2,3}. Also it is technically very simple to implement, and it
immediately identified a faulty test case that has lived in the
testsuite for eleven years without being detected.

The attached patch regtests cleanly on x86_64-linux-gnu. Ok for trunk?

Cheers,
Janus


2018-07-20  Janus Weil  <janus@gcc.gnu.org>

    PR fortran/57160
    * trans-expr.c (gfc_conv_expr_op): Use short-circuiting operators only
    with -ffrontend-optimize. Without that flag, make sure that both
    operands are evaluated.


2018-07-20  Janus Weil  <janus@gcc.gnu.org>

    PR fortran/57160
    * gfortran.dg/actual_pointer_function_1.f90: Fix invalid test case.

Patch

Index: gcc/fortran/trans-expr.c
===================================================================
--- gcc/fortran/trans-expr.c	(revision 262908)
+++ gcc/fortran/trans-expr.c	(working copy)
@@ -3348,12 +3348,12 @@  gfc_conv_expr_op (gfc_se * se, gfc_expr * expr)
       return;
 
     case INTRINSIC_AND:
-      code = TRUTH_ANDIF_EXPR;
+      code = flag_frontend_optimize ? TRUTH_ANDIF_EXPR : TRUTH_AND_EXPR;
       lop = 1;
       break;
 
     case INTRINSIC_OR:
-      code = TRUTH_ORIF_EXPR;
+      code = flag_frontend_optimize ? TRUTH_ORIF_EXPR : TRUTH_OR_EXPR;
       lop = 1;
       break;
 
Index: gcc/testsuite/gfortran.dg/actual_pointer_function_1.f90
===================================================================
--- gcc/testsuite/gfortran.dg/actual_pointer_function_1.f90	(revision 262908)
+++ gcc/testsuite/gfortran.dg/actual_pointer_function_1.f90	(working copy)
@@ -17,7 +17,11 @@  CONTAINS
 
   logical function cp_logger_log(logger)
     TYPE(cp_logger_type), POINTER ::logger
-    cp_logger_log = associated (logger) .and. (logger%a .eq. 42)
+    if (associated (logger)) then
+      cp_logger_log = (logger%a .eq. 42)
+    else
+      cp_logger_log = .false.
+    end if
   END function
 
   FUNCTION cp_get_default_logger(v) RESULT(res)