pure_function (gfc_expr *e, const char **name)
{
int pure;
+ gfc_component *comp;
*name = NULL;
&& e->symtree->n.sym->attr.proc == PROC_ST_FUNCTION)
return pure_stmt_function (e, e->symtree->n.sym);
- if (e->value.function.esym)
+ comp = gfc_get_proc_ptr_comp (e);
+ if (comp)
+ {
+ pure = gfc_pure (comp->ts.interface);
+ *name = comp->name;
+ }
+ else if (e->value.function.esym)
{
pure = gfc_pure (e->value.function.esym);
*name = e->value.function.esym->name;
}
+/* Check if a non-pure function function is allowed in the current context. */
+
+static bool check_pure_function (gfc_expr *e)
+{
+ const char *name = NULL;
+ if (!pure_function (e, &name) && name)
+ {
+ if (forall_flag)
+ {
+ gfc_error ("Reference to non-PURE function %qs at %L inside a "
+ "FORALL %s", name, &e->where,
+ forall_flag == 2 ? "mask" : "block");
+ return false;
+ }
+ else if (gfc_do_concurrent_flag)
+ {
+ gfc_error ("Reference to non-PURE function %qs at %L inside a "
+ "DO CONCURRENT %s", name, &e->where,
+ gfc_do_concurrent_flag == 2 ? "mask" : "block");
+ return false;
+ }
+ else if (gfc_pure (NULL))
+ {
+ gfc_error ("Reference to non-PURE function %qs at %L "
+ "within a PURE procedure", name, &e->where);
+ return false;
+ }
+ gfc_unset_implicit_pure (NULL);
+ }
+ return true;
+}
+
+
/* Resolve a function call, which means resolving the arguments, then figuring
out which entity the name refers to. */
{
gfc_actual_arglist *arg;
gfc_symbol *sym;
- const char *name;
bool t;
int temp;
procedure_type p = PROC_INTRINSIC;
#undef GENERIC_ID
need_full_assumed_size = temp;
- name = NULL;
- if (!pure_function (expr, &name) && name)
- {
- if (forall_flag)
- {
- gfc_error ("Reference to non-PURE function %qs at %L inside a "
- "FORALL %s", name, &expr->where,
- forall_flag == 2 ? "mask" : "block");
- t = false;
- }
- else if (gfc_do_concurrent_flag)
- {
- gfc_error ("Reference to non-PURE function %qs at %L inside a "
- "DO CONCURRENT %s", name, &expr->where,
- gfc_do_concurrent_flag == 2 ? "mask" : "block");
- t = false;
- }
- else if (gfc_pure (NULL))
- {
- gfc_error ("Function reference to %qs at %L is to a non-PURE "
- "procedure within a PURE procedure", name, &expr->where);
- t = false;
- }
-
- gfc_unset_implicit_pure (NULL);
- }
+ if (!check_pure_function(expr))
+ t = false;
/* Functions without the RECURSIVE attribution are not allowed to
* call themselves. */
/************* Subroutine resolution *************/
-static void
-pure_subroutine (gfc_code *c, gfc_symbol *sym)
+static bool
+pure_subroutine (gfc_symbol *sym, const char *name, locus *loc)
{
if (gfc_pure (sym))
- return;
+ return true;
if (forall_flag)
- gfc_error ("Subroutine call to %qs in FORALL block at %L is not PURE",
- sym->name, &c->loc);
+ {
+ gfc_error ("Subroutine call to %qs in FORALL block at %L is not PURE",
+ name, loc);
+ return false;
+ }
else if (gfc_do_concurrent_flag)
- gfc_error ("Subroutine call to %qs in DO CONCURRENT block at %L is not "
- "PURE", sym->name, &c->loc);
+ {
+ gfc_error ("Subroutine call to %qs in DO CONCURRENT block at %L is not "
+ "PURE", name, loc);
+ return false;
+ }
else if (gfc_pure (NULL))
- gfc_error ("Subroutine call to %qs at %L is not PURE", sym->name,
- &c->loc);
+ {
+ gfc_error ("Subroutine call to %qs at %L is not PURE", name, loc);
+ return false;
+ }
gfc_unset_implicit_pure (NULL);
+ return true;
}
if (s != NULL)
{
c->resolved_sym = s;
- pure_subroutine (c, s);
+ if (!pure_subroutine (s, s->name, &c->loc))
+ return MATCH_ERROR;
return MATCH_YES;
}
gfc_procedure_use (sym, &c->ext.actual, &c->loc);
c->resolved_sym = sym;
- pure_subroutine (c, sym);
+ if (!pure_subroutine (sym, sym->name, &c->loc))
+ return MATCH_ERROR;
return MATCH_YES;
}
c->resolved_sym = sym;
- pure_subroutine (c, sym);
-
- return true;
+ return pure_subroutine (sym, sym->name, &c->loc);
}
&& comp->ts.interface->formal)))
return false;
+ if (!pure_subroutine (comp->ts.interface, comp->name, &c->expr1->where))
+ return false;
+
gfc_ppc_use (comp, &c->expr1->value.compcall.actual, &c->expr1->where);
return true;
if (!update_ppc_arglist (e))
return false;
+ if (!check_pure_function(e))
+ return false;
+
gfc_ppc_use (comp, &e->value.compcall.actual, &e->where);
return true;