From: Janus Weil <janus@gcc.gnu.org>
To: gfortran <fortran@gcc.gnu.org>, gcc-patches <gcc-patches@gcc.gnu.org>
Subject: [Patch, Fortran] PR 85599: warn about short-circuiting of logical expressions for non-pure functions
Date: Wed, 11 Jul 2018 21:06:00 -0000 [thread overview]
Message-ID: <CAKwh3qgbSjoVqRS9s-fYB8ODrBXvDV4ePoT-8E02LDn-JXxQ8g@mail.gmail.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 1875 bytes --]
Hi all,
after the dust of the heated discussion around this PR has settled a
bit, here is another attempt to implement at least some basic warnings
about compiler-dependent behavior concerning the short-circuiting of
logical expressions.
As a reminder (and recap of the previous discussion), the Fortran
standard unfortunately is a bit sloppy in this area: It allows
compilers to short-circuit the second operand of .AND. / .OR.
operators, but does not require this. As a result, compilers can do
what they want without conflicting with the standard, and they do:
gfortran does short-circuiting (via TRUTH_ANDIF_EXPR/TRUTH_ORIF_EXPR),
ifort does not.
I'm continuing here the least-invasive approach of keeping gfortran's
current behavior, but warning about cases where compilers may produce
different results.
The attached patch is very close to the version I posted previously
(which was already approved by Janne), with the difference that the
warnings are now triggered by -Wextra and not -Wsurprising (which is
included in -Wall), as suggested by Nick Maclaren. I think this is
more reasonable, since not everyone may want to see these warnings.
Note that I don't want to warn about all possible optimizations that
might be allowed by the standard, but only about those that are
actually problematic in practice and result in compiler-dependent
behavior.
The patch regtests cleanly on x86_64-linux-gnu. Ok for trunk?
Cheers,
Janus
2018-07-11 Thomas Koenig <tkoenig@gcc.gnu.org>
Janus Weil <janus@gcc.gnu.org>
PR fortran/85599
* dump-parse-tree (show_attr): Add handling of implicit_pure.
* resolve.c (impure_function_callback): New function.
(resolve_operator): Call it vial gfc_expr_walker.
2018-07-11 Janus Weil <janus@gcc.gnu.org>
PR fortran/85599
* gfortran.dg/short_circuiting.f90: New test.
[-- Attachment #2: pr85599_v2.diff --]
[-- Type: text/x-patch, Size: 2415 bytes --]
Index: gcc/fortran/dump-parse-tree.c
===================================================================
--- gcc/fortran/dump-parse-tree.c (revision 262563)
+++ gcc/fortran/dump-parse-tree.c (working copy)
@@ -716,6 +716,8 @@ show_attr (symbol_attribute *attr, const char * mo
fputs (" ELEMENTAL", dumpfile);
if (attr->pure)
fputs (" PURE", dumpfile);
+ if (attr->implicit_pure)
+ fputs (" IMPLICIT_PURE", dumpfile);
if (attr->recursive)
fputs (" RECURSIVE", dumpfile);
Index: gcc/fortran/resolve.c
===================================================================
--- gcc/fortran/resolve.c (revision 262563)
+++ gcc/fortran/resolve.c (working copy)
@@ -3822,6 +3822,46 @@ lookup_uop_fuzzy (const char *op, gfc_symtree *uop
}
+/* Callback finding an impure function as an operand to an .and. or
+ .or. expression. Remember the last function warned about to
+ avoid double warnings when recursing. */
+
+static int
+impure_function_callback (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
+ void *data)
+{
+ gfc_expr *f = *e;
+ const char *name;
+ static gfc_expr *last = NULL;
+ bool *found = (bool *) data;
+
+ if (f->expr_type == EXPR_FUNCTION)
+ {
+ *found = 1;
+ if (f != last && !pure_function (f, &name))
+ {
+ /* This could still be a function without side effects, i.e.
+ implicit pure. Do not warn for that case. */
+ if (f->symtree == NULL || f->symtree->n.sym == NULL
+ || !gfc_implicit_pure (f->symtree->n.sym))
+ {
+ if (name)
+ gfc_warning (OPT_Wextra,
+ "Function %qs at %L might not be evaluated",
+ name, &f->where);
+ else
+ gfc_warning (OPT_Wextra,
+ "Function at %L might not be evaluated",
+ &f->where);
+ }
+ }
+ last = f;
+ }
+
+ return 0;
+}
+
+
/* Resolve an operator expression node. This can involve replacing the
operation with a user defined function call. */
@@ -3930,6 +3970,14 @@ resolve_operator (gfc_expr *e)
gfc_convert_type (op1, &e->ts, 2);
else if (op2->ts.kind < e->ts.kind)
gfc_convert_type (op2, &e->ts, 2);
+
+ if (e->value.op.op == INTRINSIC_AND || e->value.op.op == INTRINSIC_OR)
+ {
+ /* Warn about short-circuiting
+ with impure function as second operand. */
+ bool op2_f = false;
+ gfc_expr_walker (&op2, impure_function_callback, &op2_f);
+ }
break;
}
[-- Attachment #3: short_circuiting.f90 --]
[-- Type: text/x-fortran, Size: 629 bytes --]
! { dg-do compile }
! { dg-additional-options "-Wextra" }
!
! PR 85599: warn about short-circuiting of logical expressions for non-pure functions
!
! Contributed by Janus Weil <janus@gcc.gnu.org>
program short_circuit
logical :: flag
flag = .false.
flag = check() .and. flag
flag = flag .and. check() ! { dg-warning "might not be evaluated" }
flag = flag .and. pure_check()
contains
logical function check()
integer, save :: i = 1
print *, "check", i
i = i + 1
check = .true.
end function
logical pure function pure_check()
pure_check = .true.
end function
end
next reply other threads:[~2018-07-11 21:06 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-07-11 21:06 Janus Weil [this message]
2018-07-12 19:43 ` Janus Weil
2018-07-13 8:03 ` Janus Weil
2018-07-15 20:39 ` Janus Weil
2018-07-15 20:57 ` Thomas Koenig
2018-07-16 8:07 ` Janus Weil
2018-07-16 19:51 ` Thomas Koenig
2018-07-17 5:08 ` Janus Weil
2018-07-17 7:52 ` Janus Weil
2018-07-17 14:32 ` Janus Weil
2018-07-17 15:19 ` Fritz Reese
2018-07-17 17:19 ` Janus Weil
2018-07-17 17:34 ` Thomas Koenig
2018-07-17 18:36 ` Janus Weil
2018-07-17 18:55 ` Fritz Reese
2018-07-17 19:21 ` Janus Weil
2018-07-18 18:43 ` Janus Weil
2018-07-12 11:17 Dominique d'Humières
2018-07-12 14:12 ` Janus Weil
2018-07-12 14:35 ` Dominique d'Humières
2018-07-12 14:55 ` Janus Weil
2018-07-12 19:53 ` Thomas Koenig
2018-07-12 20:03 ` Janus Weil
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CAKwh3qgbSjoVqRS9s-fYB8ODrBXvDV4ePoT-8E02LDn-JXxQ8g@mail.gmail.com \
--to=janus@gcc.gnu.org \
--cc=fortran@gcc.gnu.org \
--cc=gcc-patches@gcc.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).