This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[gfortran, PR20851] Disallow dummy arguments in init exprs in elemental procedures



Hi,


this turned out much easier than I thought it would.

Quoting from the standard:
"A dummy argument, or a subobject thereof, shall not appear in
aspecification-expr except as the argument to one of the intrinsic functions BIT_SIZE, KIND, LEN, or the numeric inquiry functions (13.11.8)."


The functions in 13.11.8 are: DIGITS, EPSILON, HUGE, MAXEXPONENT, MINEXPONENT,
PRECISION, RADIX, RANGE, TINY.


Fixing this issue turned out to be very simple, because valid expressions are folded by the simplifiers, i.e. the dummy argument doesn't appear in their simplified versions.

The change to resolve_fl_variable() was necessary to avoid a double error message being printed: is_non_constant_shape_array(), in spite of its name suggesting otherwise, has side-effects and may issue errors, therefore I moved it to the end of the logical expressions in order to ensure that it's only called in cases where its result is important.

Built and tested on i686-darwin. Ok?

Cheers,
- Tobi

:ADDPATCH fortran:
2007-10-07  Tobias Schlüter  <tobi@gcc.gnu.org>

	PR fortran/20851
fortran/
	* expr.c (check_inquiry): Typo fix in error message.
	(check_init_expr): Same * 3.
	(check_restricted): Verify that no dummy arguments appear in
	restricted expressions in ELEMENTAL procedures.
	* resolve.c (resolve_fl_variable): Exchange order of checks to
	avoid side-effect.
testsuite/
	* initialization_1.f90: Fix dg-error annotations.
	* initialization_14.f90: New.
	* initialization_7.f90: Fix dg-error annotations.
	* initialization_9.f90: Likewise.

diff -r 402335292960 gcc/fortran/expr.c
--- a/gcc/fortran/expr.c	Sat Oct 06 16:59:59 2007 +0000
+++ b/gcc/fortran/expr.c	Sun Oct 07 13:16:56 2007 +0200
@@ -2012,7 +2012,7 @@ check_inquiry (gfc_expr *e, int not_rest
 	    && ap->expr->symtree->n.sym->ts.type == BT_CHARACTER
 	    && ap->expr->symtree->n.sym->ts.cl->length == NULL)
 	  {
-	    gfc_error ("assumed character length variable '%s' in constant "
+	    gfc_error ("Assumed character length variable '%s' in constant "
 		       "expression at %L", e->symtree->n.sym->name, &e->where);
 	      return MATCH_ERROR;
 	  }
@@ -2204,19 +2204,19 @@ check_init_expr (gfc_expr *e)
 	  switch (e->symtree->n.sym->as->type)
 	    {
 	      case AS_ASSUMED_SIZE:
-		gfc_error ("assumed size array '%s' at %L is not permitted "
+		gfc_error ("Assumed size array '%s' at %L is not permitted "
 			   "in an initialization expression",
 			   e->symtree->n.sym->name, &e->where);
 		break;
 
 	      case AS_ASSUMED_SHAPE:
-		gfc_error ("assumed shape array '%s' at %L is not permitted "
+		gfc_error ("Assumed shape array '%s' at %L is not permitted "
 			   "in an initialization expression",
 			   e->symtree->n.sym->name, &e->where);
 		break;
 
 	      case AS_DEFERRED:
-		gfc_error ("deferred array '%s' at %L is not permitted "
+		gfc_error ("Deferred array '%s' at %L is not permitted "
 			   "in an initialization expression",
 			   e->symtree->n.sym->name, &e->where);
 		break;
@@ -2428,6 +2428,19 @@ check_restricted (gfc_expr *e)
     case EXPR_VARIABLE:
       sym = e->symtree->n.sym;
       t = FAILURE;
+
+      /* If a dummy argument appears in a context that is valid for a
+	 restricted expression in an elemental procedure, it will have
+	 already been simplified away once we get here.  Therefore we
+	 don't need to jump through hoops to distinguish valid from
+	 invalid cases.  */
+      if (sym->attr.dummy && sym->ns == gfc_current_ns
+	  && sym->ns->proc_name && sym->ns->proc_name->attr.elemental)
+	{
+	  gfc_error ("Dummy argument '%s' not allowed in expression at %L",
+		     sym->name, &e->where);
+	  break;
+	}
 
       if (sym->attr.optional)
 	{
diff -r 402335292960 gcc/fortran/resolve.c
--- a/gcc/fortran/resolve.c	Sat Oct 06 16:59:59 2007 +0000
+++ b/gcc/fortran/resolve.c	Sun Oct 07 13:16:56 2007 +0200
@@ -6968,22 +6968,20 @@ resolve_fl_variable (gfc_symbol *sym, in
      is_non_constant_shape_array.  */
   specification_expr = 1;
 
-  if (!sym->attr.use_assoc
+  if (sym->ns->proc_name
+      && (sym->ns->proc_name->attr.flavor == FL_MODULE
+	  || sym->ns->proc_name->attr.is_main_program)
+      && !sym->attr.use_assoc
       && !sym->attr.allocatable
       && !sym->attr.pointer
       && is_non_constant_shape_array (sym))
     {
-	/* The shape of a main program or module array needs to be
-	   constant.  */
-	if (sym->ns->proc_name
-	    && (sym->ns->proc_name->attr.flavor == FL_MODULE
-		|| sym->ns->proc_name->attr.is_main_program))
-	  {
-	    gfc_error ("The module or main program array '%s' at %L must "
-		       "have constant shape", sym->name, &sym->declared_at);
-	    specification_expr = 0;
-	    return FAILURE;
-	  }
+      /* The shape of a main program or module array needs to be
+	 constant.  */
+      gfc_error ("The module or main program array '%s' at %L must "
+		 "have constant shape", sym->name, &sym->declared_at);
+      specification_expr = 0;
+      return FAILURE;
     }
 
   if (sym->ts.type == BT_CHARACTER)
diff -r 402335292960 gcc/testsuite/gfortran.dg/initialization_1.f90
--- a/gcc/testsuite/gfortran.dg/initialization_1.f90	Sat Oct 06 16:59:59 2007 +0000
+++ b/gcc/testsuite/gfortran.dg/initialization_1.f90	Sun Oct 07 13:16:56 2007 +0200
@@ -24,10 +24,10 @@ contains
     real :: z(2, 2)
 
 ! However, this gives a warning because it is an initialization expression.
-    integer :: l1 = len (ch1)     ! { dg-warning "assumed character length variable" }
+    integer :: l1 = len (ch1)     ! { dg-warning "Assumed character length variable" }
 
 ! These are warnings because they are gfortran extensions.
-    integer :: m3 = size (x, 1)   ! { dg-error "assumed size array" }
+    integer :: m3 = size (x, 1)   ! { dg-error "Assumed size array" }
     integer :: m4(2) = shape (z)
 
 ! This does not depend on non-constant properties.
diff -r 402335292960 gcc/testsuite/gfortran.dg/initialization_14.f90
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gcc/testsuite/gfortran.dg/initialization_14.f90	Sun Oct 07 13:16:56 2007 +0200
@@ -0,0 +1,45 @@
+! { dg-do compile }
+! PR 20851
+! Dummy arguments are disallowed in initialization expressions in
+! elemental functions except as arguments to the intrinsic functions
+! BIT_SIZE, KIND, LEN, or to the numeric inquiry functions listed
+! in 13.11.8
+MODULE TT
+INTEGER M
+CONTAINS
+   ELEMENTAL REAL FUNCTION two(N)
+     INTEGER, INTENT(IN) :: N
+     INTEGER, DIMENSION(N) :: scr ! { dg-error "Dummy argument 'n' not allowed in expression" }
+   END FUNCTION
+
+   ELEMENTAL REAL FUNCTION twopointfive(N)
+     INTEGER, INTENT(IN) :: N
+     INTEGER, DIMENSION(MAX(N,2)) :: scr ! { dg-error "Dummy argument 'n' not allowed in expression" }
+   end FUNCTION twopointfive
+
+   REAL FUNCTION three(N)
+     INTEGER, INTENT(IN) :: N
+     INTEGER, DIMENSION(N) :: scr ! this time it's valid
+   END FUNCTION
+
+   ELEMENTAL REAL FUNCTION four(N)
+     INTEGER, INTENT(IN) :: N
+     INTEGER, DIMENSION(bit_size(N)) :: scr ! another valid variant
+   END FUNCTION
+
+   ELEMENTAL REAL FUNCTION gofourit(N)
+     INTEGER, INTENT(IN) :: N
+     INTEGER, DIMENSION(MIN(HUGE(N),1)) :: scr ! another valid variant
+   END FUNCTION
+
+   ELEMENTAL REAL FUNCTION fourplusone(N)
+     INTEGER, INTENT(IN) :: N
+     INTEGER, DIMENSION(M) :: scr ! another valid variant
+   END FUNCTION
+
+   ELEMENTAL REAL FUNCTION five(X)
+     real, intent(in) :: x
+     CHARACTER(LEN=PRECISION(X)) :: C ! valid again
+   END FUNCTION
+END MODULE
+END
diff -r 402335292960 gcc/testsuite/gfortran.dg/initialization_7.f90
--- a/gcc/testsuite/gfortran.dg/initialization_7.f90	Sat Oct 06 16:59:59 2007 +0000
+++ b/gcc/testsuite/gfortran.dg/initialization_7.f90	Sun Oct 07 13:16:56 2007 +0200
@@ -6,7 +6,7 @@
 
 subroutine probleme(p)
   real(kind=8), dimension(:) :: p
-  integer :: nx = size(p, 1)          ! { dg-error "deferred array" }
+  integer :: nx = size(p, 1)          ! { dg-error "Deferred array" }
   integer :: nix
 
   nix = nx
diff -r 402335292960 gcc/testsuite/gfortran.dg/initialization_9.f90
--- a/gcc/testsuite/gfortran.dg/initialization_9.f90	Sat Oct 06 16:59:59 2007 +0000
+++ b/gcc/testsuite/gfortran.dg/initialization_9.f90	Sun Oct 07 13:16:56 2007 +0200
@@ -5,7 +5,7 @@
 
    integer function xstrcmp(s1)
      character*(*), intent(in) :: s1
-     integer :: n1 = len(s1)            ! { dg-error "assumed character length variable" }
+     integer :: n1 = len(s1)            ! { dg-error "Assumed character length variable" }
      n1 = 1
      return
    end function xstrcmp

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]