diff mbox

[Fortran] PR 63674: procedure pointer and non/pure procedure

Message ID CAKwh3qjzcpjGXszr9WCzLaBpD+U7x37aWgPRnA4LhiOkdv6qCQ@mail.gmail.com
State New
Headers show

Commit Message

Janus Weil Dec. 14, 2014, 10:32 a.m. UTC
>> Regtested on x86_64-unknown-linux-gnu. Ok for trunk?
>
> s/'%s'/%qs/g
> nowadays.

Good point, thank you. Updated patch attached.

I guess I still new formal approval by someone with reviewer status ...

Cheers,
Janus

Comments

FX Coudert Dec. 14, 2014, 11 a.m. UTC | #1
> Good point, thank you. Updated patch attached.
> I guess I still new formal approval by someone with reviewer status …

OK
Janus Weil Dec. 14, 2014, 12:05 p.m. UTC | #2
2014-12-14 12:00 GMT+01:00 FX <fxcoudert@gmail.com>:
>> Good point, thank you. Updated patch attached.
>> I guess I still new formal approval by someone with reviewer status …
>
> OK

Thanks, committed as r218717.

Cheers,
Janus
Tobias Burnus Dec. 15, 2014, 6:34 a.m. UTC | #3
Janus Weil wrote:
> 2014-12-14 12:00 GMT+01:00 FX <fxcoudert@gmail.com>:
>>> Good point, thank you. Updated patch attached.
>>> I guess I still new formal approval by someone with reviewer status …
>> OK
> Thanks, committed as r218717.

Can you change "non-pure" to "impure"? That would better match the 
Fortran naming, where "impure" is the default unless "pure" or 
"elemental" is used. (It was added to permit "impure elemental" procedures.)

Tobias
Janus Weil Dec. 15, 2014, 10:35 a.m. UTC | #4
2014-12-15 7:34 GMT+01:00 Tobias Burnus <burnus@net-b.de>:
> Can you change "non-pure" to "impure"? That would better match the Fortran
> naming, where "impure" is the default unless "pure" or "elemental" is used.
> (It was added to permit "impure elemental" procedures.)

Yes, sure. I have committed this change as r218738.

Cheers,
Janus
diff mbox

Patch

Index: gcc/fortran/resolve.c
===================================================================
--- gcc/fortran/resolve.c	(Revision 218705)
+++ gcc/fortran/resolve.c	(Arbeitskopie)
@@ -2746,6 +2746,7 @@  static int
 pure_function (gfc_expr *e, const char **name)
 {
   int pure;
+  gfc_component *comp;
 
   *name = NULL;
 
@@ -2754,8 +2755,14 @@  pure_function (gfc_expr *e, const char **name)
         && 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;
     }
@@ -2801,6 +2808,40 @@  pure_stmt_function (gfc_expr *e, gfc_symbol *sym)
 }
 
 
+/* 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.  */
 
@@ -2809,7 +2850,6 @@  resolve_function (gfc_expr *expr)
 {
   gfc_actual_arglist *arg;
   gfc_symbol *sym;
-  const char *name;
   bool t;
   int temp;
   procedure_type p = PROC_INTRINSIC;
@@ -2982,34 +3022,10 @@  resolve_function (gfc_expr *expr)
 #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;
-	}
+  if (!check_pure_function(expr))
+    t = false;
 
-      gfc_unset_implicit_pure (NULL);
-    }
-
   /* Functions without the RECURSIVE attribution are not allowed to
    * call themselves.  */
   if (expr->value.function.esym && !expr->value.function.esym->attr.recursive)
@@ -3056,23 +3072,32 @@  resolve_function (gfc_expr *expr)
 
 /************* 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;
 }
 
 
@@ -3087,7 +3112,8 @@  resolve_generic_s0 (gfc_code *c, gfc_symbol *sym)
       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;
 	}
 
@@ -3190,7 +3216,8 @@  found:
   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;
 }
@@ -3260,9 +3287,7 @@  found:
 
   c->resolved_sym = sym;
 
-  pure_subroutine (c, sym);
-
-  return true;
+  return pure_subroutine (sym, sym->name, &c->loc);
 }
 
 
@@ -6036,6 +6061,9 @@  resolve_ppc_call (gfc_code* c)
 				 && 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;
@@ -6074,6 +6102,9 @@  resolve_expr_ppc (gfc_expr* e)
   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;
Index: gcc/testsuite/gfortran.dg/pure_dummy_length_1.f90
===================================================================
--- gcc/testsuite/gfortran.dg/pure_dummy_length_1.f90	(Revision 218705)
+++ gcc/testsuite/gfortran.dg/pure_dummy_length_1.f90	(Arbeitskopie)
@@ -24,6 +24,6 @@ 
          character(*), intent(in) :: string
          integer(4), intent(in) :: ignore_case
          integer i
-         if (end > impure (self)) & ! { dg-error "non-PURE procedure" }
+         if (end > impure (self)) & ! { dg-error "non-PURE function" }
            return
    end function
Index: gcc/testsuite/gfortran.dg/stfunc_6.f90
===================================================================
--- gcc/testsuite/gfortran.dg/stfunc_6.f90	(Revision 218705)
+++ gcc/testsuite/gfortran.dg/stfunc_6.f90	(Arbeitskopie)
@@ -22,7 +22,7 @@ 
 contains
   pure integer function u (x)
     integer,intent(in) :: x
-    st2 (i) = i * v(i) ! { dg-error "non-PURE procedure" }
+    st2 (i) = i * v(i) ! { dg-error "non-PURE function" }
     u = st2(x)
   end function
   integer function v (x)
Index: gcc/testsuite/gfortran.dg/typebound_operator_4.f03
===================================================================
--- gcc/testsuite/gfortran.dg/typebound_operator_4.f03	(Revision 218705)
+++ gcc/testsuite/gfortran.dg/typebound_operator_4.f03	(Arbeitskopie)
@@ -75,8 +75,8 @@  PURE SUBROUTINE iampure2 ()
   TYPE(myreal) :: x
 
   x = 0.0 ! { dg-error "is not PURE" }
-  x = x + 42.0 ! { dg-error "to a non-PURE procedure" }
-  x = x .PLUS. 5.0 ! { dg-error "to a non-PURE procedure" }
+  x = x + 42.0 ! { dg-error "non-PURE function" }
+  x = x .PLUS. 5.0 ! { dg-error "non-PURE function" }
 END SUBROUTINE iampure2
 
 PROGRAM main