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]

[Patch, fortran] PR27122 - requirements for defined operators


:ADDPATCH fortran:

This patch follows from PR27122, in which it is noted that there is no checking of intent of the arguments of defined operator procedures. In fact, there is no checking whatsoever of the interfaces of defined operators! The patch supplies all the checks required by 12.3.2.1.1 of the standard and the testcase checks each one.

The fix is straightforward and does not need description here. What does need remarking upon is the impact of this patch on the fix for PR25084. I now believe that I misinterpreted Note 5.6 and have removed the general check on automatic character function interfaces. PR25084 is fixed by this patch and the more generalised restriction is incorrect. Fortunately, this is a sufficiently obscure area of fortran that nobody has encountered it as a problem in the last three months.

Regtested on FC3/Athlon. Ok for trunk and 4.1?

Paul


2006-04-17 Paul Thomas <pault@gcc.gnu.org>

	PR fortran/27122
	* resolve.c (reolve_function): Remove general restriction on auto
	character length function interfaces.
	(gfc_resolve_uops): Check restrictions on defined operator
	procedures.
	(resolve_types): Call the check for defined operators.

2006-04-17 Paul Thomas <pault@gcc.gnu.org>

	PR fortran/27122
	* gfortran.dg/defined_operators_1.f90: New test.
	* gfortran.dg/assumed_charlen_function_1.f90: Add new error and
	remove old ones associated, incorrectly with Note 5.46.
Index: gcc/fortran/resolve.c
===================================================================
*** gcc/fortran/resolve.c	(revision 112981)
--- gcc/fortran/resolve.c	(working copy)
*************** resolve_function (gfc_expr * expr)
*** 1237,1264 ****
    need_full_assumed_size--;
  
    if (sym && sym->ts.type == BT_CHARACTER
! 	  && sym->ts.cl && sym->ts.cl->length == NULL)
      {
-       if (sym->attr.if_source == IFSRC_IFBODY)
- 	{
- 	  /* This follows from a slightly odd requirement at 5.1.1.5 in the
- 	     standard that allows assumed character length functions to be
- 	     declared in interfaces but not used.  Picking up the symbol here,
- 	     rather than resolve_symbol, accomplishes that.  */
- 	  gfc_error ("Function '%s' can be declared in an interface to "
- 		     "return CHARACTER(*) but cannot be used at %L",
- 		     sym->name, &expr->where);
- 	  return FAILURE;
- 	}
- 
        /* Internal procedures are taken care of in resolve_contained_fntype.  */
!       if (!sym->attr.dummy && !sym->attr.contained)
! 	{
! 	  gfc_error ("Function '%s' is declared CHARACTER(*) and cannot "
! 		     "be used at %L since it is not a dummy argument",
! 		     sym->name, &expr->where);
! 	  return FAILURE;
! 	}
      }
  
  /* See if function is already resolved.  */
--- 1237,1252 ----
    need_full_assumed_size--;
  
    if (sym && sym->ts.type == BT_CHARACTER
! 	&& sym->ts.cl
! 	&& sym->ts.cl->length == NULL)
! 	&& !sym->attr.dummy
! 	&& !sym->attr.contained)
      {
        /* Internal procedures are taken care of in resolve_contained_fntype.  */
!       gfc_error ("Function '%s' is declared CHARACTER(*) and cannot "
! 		 "be used at %L since it is not a dummy argument",
! 		 sym->name, &expr->where);
!       return FAILURE;
      }
  
  /* See if function is already resolved.  */
*************** resolve_fntype (gfc_namespace * ns)
*** 6105,6110 ****
--- 6093,6162 ----
        }
  }
  
+ /* 12.3.2.1.1 Defined operators.  */
+ 
+ static void
+ gfc_resolve_uops(gfc_symtree *symtree)
+ {
+   gfc_interface *itr;
+   gfc_symbol *sym;
+   gfc_formal_arglist *formal;
+ 
+   if (symtree == NULL) 
+     return; 
+  
+   gfc_resolve_uops (symtree->left);
+   gfc_resolve_uops (symtree->right);
+ 
+   for (itr = symtree->n.uop->operator; itr; itr = itr->next)
+     {
+       sym = itr->sym;
+       if (!sym->attr.function)
+ 	gfc_error("User operator procedure '%s' at %L must be a FUNCTION",
+ 		  itr->sym->name, &itr->sym->declared_at);
+ 
+       if (sym->ts.type == BT_CHARACTER
+ 	    && !(sym->ts.cl && sym->ts.cl->length)
+ 	    && !(sym->result && sym->result->ts.cl && sym->result->ts.cl->length))
+ 	gfc_error("User operator procedure '%s' at %L cannot be assumed character "
+ 		  "length", itr->sym->name, &itr->sym->declared_at);
+ 
+       formal = itr->sym->formal;
+       if (!formal || !formal->sym)
+ 	{
+ 	  gfc_error("User operator procedure '%s' at %L must have at least "
+ 		    "one argument", itr->sym->name, &itr->sym->declared_at);
+ 	  continue;
+ 	}
+ 
+       sym = itr->sym->formal->sym;
+       if (sym->attr.intent != INTENT_IN)
+ 	gfc_error ("First argument of operator interface at %L must be "
+ 		   "INTENT(IN)", &itr->sym->declared_at);
+ 
+       if (sym->attr.optional)
+ 	gfc_error ("First argument of operator interface at %L connot be "
+ 		   "optional", &itr->sym->declared_at);
+ 
+       formal = formal->next;
+       if (!formal || !formal->sym)
+ 	continue;
+ 
+       sym = formal->sym;
+       if (sym->attr.intent != INTENT_IN)
+ 	gfc_error ("Second argument of operator interface at %L must be "
+ 		   "INTENT(IN)", &itr->sym->declared_at);
+ 
+       if (sym->attr.optional)
+ 	gfc_error ("Second argument of operator interface at %L connot be "
+ 		   "optional", &itr->sym->declared_at);
+ 
+       if (formal->next)
+ 	gfc_error ("Operator interface at %L must have, at most, two "
+ 		   "arguments", &itr->sym->declared_at);
+     }
+ }
+ 
  
  /* Examine all of the expressions associated with a program unit,
     assign types to all intermediate expressions, make sure that all
*************** resolve_types (gfc_namespace * ns)
*** 6164,6169 ****
--- 6216,6224 ----
    /* Warn about unused labels.  */
    if (gfc_option.warn_unused_labels)
      warn_unused_label (ns->st_labels);
+ 
+   gfc_resolve_uops (ns->uop_root);
+     
  }
  
  
Index: gcc/testsuite/gfortran.dg/defined_operators_1.f90
===================================================================
*** gcc/testsuite/gfortran.dg/defined_operators_1.f90	(revision 0)
--- gcc/testsuite/gfortran.dg/defined_operators_1.f90	(revision 0)
***************
*** 0 ****
--- 1,54 ----
+ ! { dg-do compile }
+ ! { dg-options "-std=legacy" }
+ ! Tests the fix for PR27122, in which the requirements of 12.3.2.1.1
+ ! for defined operators were not enforced.
+ ! 
+ ! Based on PR test by Thomas Koenig  <tkoenig@gcc.gnu.org>
+ !
+ module mymod
+   interface operator (.foo.)
+      module procedure foo_0 ! { dg-error "must have at least one argument" }
+      module procedure foo_1 ! { dg-error "must be INTENT" }
+      module procedure foo_2 ! { dg-error "connot be optional" }
+      module procedure foo_3 ! { dg-error "must have, at most, two arguments" }
+      module procedure foo_1_OK
+      module procedure foo_2_OK
+      function foo_chr (chr) ! { dg-error "cannot be assumed character length" }
+       character(*) :: foo_chr
+       character(*), intent(in) :: chr
+      end function foo_chr
+   end interface
+ contains
+   function foo_0 ()
+     integer :: foo_1
+     foo_0 = 1
+   end function foo_0
+   function foo_1 (a)
+     integer :: foo_1
+     integer :: a
+     foo_1 = 1
+   end function foo_1
+   function foo_1_OK (a)
+     integer :: foo_1_OK
+     integer, intent (in) :: a
+     foo_1_OK = 1
+   end function foo_1_OK
+   function foo_2 (a, b)
+     integer :: foo_2
+     integer, intent(in) :: a
+     integer, intent(in), optional :: b
+     foo_2 = 2 * a + b
+   end function foo_2
+   function foo_2_OK (a, b)
+     real :: foo_2_OK
+     real, intent(in) :: a
+     real, intent(in) :: b
+     foo_2_OK = 2.0 * a + b
+   end function foo_2_OK
+   function foo_3 (a, b, c)
+     integer :: foo_3
+     integer, intent(in) :: a, b, c
+     foo_3 = a + 3 * b - c
+   end function foo_3
+ end module mymod
+ 
Index: gcc/testsuite/gfortran.dg/assumed_charlen_function_1.f90
===================================================================
*** gcc/testsuite/gfortran.dg/assumed_charlen_function_1.f90	(revision 112980)
--- gcc/testsuite/gfortran.dg/assumed_charlen_function_1.f90	(working copy)
*************** END MODULE M1
*** 17,23 ****
  
  MODULE  INTEGER_SETS
   INTERFACE  OPERATOR  (.IN.)
!   FUNCTION ELEMENT(X,A)
       USE M1
       CHARACTER(LEN=*)      :: ELEMENT
       INTEGER, INTENT(IN)   ::  X
--- 17,23 ----
  
  MODULE  INTEGER_SETS
   INTERFACE  OPERATOR  (.IN.)
!   FUNCTION ELEMENT(X,A) ! { dg-error "cannot be assumed character length" }
       USE M1
       CHARACTER(LEN=*)      :: ELEMENT
       INTEGER, INTENT(IN)   ::  X
*************** function not_OK (ch)
*** 59,65 ****
    not_OK = ch
  end function not_OK
  
-   use INTEGER_SETS
    use m1
  
    character(4) :: answer
--- 59,64 ----
*************** end function not_OK
*** 74,84 ****
      end function ext
    end interface
  
-   answer = i.IN.z   ! { dg-error "cannot be used|Operands of user operator" }
-   answer = ext (2)  ! { dg-error "but cannot be used" }
- 
    answer = not_OK ("unOK") ! { dg-error "since it is not a dummy" }
  
  END
  
! ! { dg-final { cleanup-modules "M1 INTEGER_SETS" } }
--- 73,80 ----
      end function ext
    end interface
  
    answer = not_OK ("unOK") ! { dg-error "since it is not a dummy" }
  
  END
  
! ! { dg-final { cleanup-modules "M1" } }

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