aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/resolve.c
diff options
context:
space:
mode:
authorJanus Weil <janus@gcc.gnu.org>2018-07-18 20:31:59 +0200
committerJanus Weil <janus@gcc.gnu.org>2018-07-18 20:31:59 +0200
commit6457b1f096d216ca742f8e1f2a93462ecb24b38d (patch)
treee42854bbf767584ce4c287893b494c6154cdea1c /gcc/fortran/resolve.c
parentc56e97274f164e704e7f13dfe53531ced3cb24ca (diff)
downloadgcc-6457b1f096d216ca742f8e1f2a93462ecb24b38d.zip
gcc-6457b1f096d216ca742f8e1f2a93462ecb24b38d.tar.gz
gcc-6457b1f096d216ca742f8e1f2a93462ecb24b38d.tar.bz2
re PR fortran/85599 (warn about short-circuiting of logical expressions for non-pure functions)
2018-07-18 Janus Weil <janus@gcc.gnu.org> Thomas Koenig <tkoenig@gcc.gnu.org> PR fortran/85599 * dump-parse-tree.c (show_attr): Add handling of implicit_pure. * frontend-passes.c (do_warn_function_elimination): Do not warn for pure functions. * gfortran.h: Add prototypes for gfc_pure_function and gfc_implicit_pure_function. * gfortran.texi: Add chapter on evaluation of logical expressions. * invoke.texi: Mention that -Wfunction-elimination is implied by -Wextra. * lang.opt: Make -Wextra imply -Wfunction-elimination. * resolve.c (pure_function): Rename to gfc_pure_function. (gfc_implicit_pure_function): New function. (check_pure_function): Use it here. (impure_function_callback): New function. (resolve_operator): Call it via gfc_expr_walker. 2018-07-18 Janus Weil <janus@gcc.gnu.org> PR fortran/85599 * gfortran.dg/function_optimize_5.f90: Add option '-faggressive-function-elimination' and update dg-warning clauses. * gfortran.dg/short_circuiting.f90: New test. Co-Authored-By: Thomas Koenig <tkoenig@gcc.gnu.org> From-SVN: r262860
Diffstat (limited to 'gcc/fortran/resolve.c')
-rw-r--r--gcc/fortran/resolve.c69
1 files changed, 64 insertions, 5 deletions
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index 9f88c26..40fa02d 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -2941,8 +2941,8 @@ is_external_proc (gfc_symbol *sym)
static int
pure_stmt_function (gfc_expr *, gfc_symbol *);
-static int
-pure_function (gfc_expr *e, const char **name)
+int
+gfc_pure_function (gfc_expr *e, const char **name)
{
int pure;
gfc_component *comp;
@@ -2982,6 +2982,21 @@ pure_function (gfc_expr *e, const char **name)
}
+/* Check if the expression is a reference to an implicitly pure function. */
+
+int
+gfc_implicit_pure_function (gfc_expr *e)
+{
+ gfc_component *comp = gfc_get_proc_ptr_comp (e);
+ if (comp)
+ return gfc_implicit_pure (comp->ts.interface);
+ else if (e->value.function.esym)
+ return gfc_implicit_pure (e->value.function.esym);
+ else
+ return 0;
+}
+
+
static bool
impure_stmt_fcn (gfc_expr *e, gfc_symbol *sym,
int *f ATTRIBUTE_UNUSED)
@@ -2996,7 +3011,7 @@ impure_stmt_fcn (gfc_expr *e, gfc_symbol *sym,
|| e->symtree->n.sym->attr.proc == PROC_ST_FUNCTION)
return false;
- return pure_function (e, &name) ? false : true;
+ return gfc_pure_function (e, &name) ? false : true;
}
@@ -3012,7 +3027,7 @@ pure_stmt_function (gfc_expr *e, gfc_symbol *sym)
static bool check_pure_function (gfc_expr *e)
{
const char *name = NULL;
- if (!pure_function (e, &name) && name)
+ if (!gfc_pure_function (e, &name) && name)
{
if (forall_flag)
{
@@ -3034,7 +3049,8 @@ static bool check_pure_function (gfc_expr *e)
"within a PURE procedure", name, &e->where);
return false;
}
- gfc_unset_implicit_pure (NULL);
+ if (!gfc_implicit_pure_function (e))
+ gfc_unset_implicit_pure (NULL);
}
return true;
}
@@ -3822,6 +3838,41 @@ 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 && !gfc_pure_function (f, &name)
+ && !gfc_implicit_pure_function (f))
+ {
+ if (name)
+ gfc_warning (OPT_Wfunction_elimination,
+ "Impure function %qs at %L might not be evaluated",
+ name, &f->where);
+ else
+ gfc_warning (OPT_Wfunction_elimination,
+ "Impure 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 +3981,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;
}