]> gcc.gnu.org Git - gcc.git/commitdiff
re PR fortran/29624 (Fortran 2003: Support intent for pointers)
authorTobias Burnus <burnus@gcc.gnu.org>
Fri, 5 Jan 2007 09:08:37 +0000 (10:08 +0100)
committerTobias Burnus <burnus@gcc.gnu.org>
Fri, 5 Jan 2007 09:08:37 +0000 (10:08 +0100)
fortran/
2007-01-05  Tobias Burnus  <burnus@net-b.de>

        PR fortran/29624
        * interface.c (compare_parameter_intent): New function.
          (check_intents): Support pointer intents.
        * symbol.c (check_conflict): Support pointer intents,
          better conflict_std message.
        * expr.c (gfc_check_assign,gfc_check_pointer_assign):
          Support pointer intents.
        * resolve.c (resolve_deallocate_expr,resolve_allocate_expr):
          Support pointer intents.

testsuite/
2006-01-05  Tobias Burnus  <burnus@net-b.de>

        PR fortran/29624
        * gfortran.dg/alloc_alloc_expr_1.f90: Add check for
          invalid deallocate.
        * gfortran.dg/allocatable_dummy_2.f90: Update dg-error.
        * gfortran.dg/protected_4.f90: Add pointer intent check.
        * gfortran.dg/protected_6.f90: Add pointer intent check.
        * gfortran.dg/pointer_intent_1.f90: New test.
        * gfortran.dg/pointer_intent_2.f90: New test.
        * gfortran.dg/pointer_intent_3.f90: New test.

From-SVN: r120472

13 files changed:
gcc/fortran/ChangeLog
gcc/fortran/expr.c
gcc/fortran/interface.c
gcc/fortran/resolve.c
gcc/fortran/symbol.c
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/alloc_alloc_expr_1.f90
gcc/testsuite/gfortran.dg/allocatable_dummy_2.f90
gcc/testsuite/gfortran.dg/pointer_intent_1.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/pointer_intent_2.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/pointer_intent_3.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/protected_4.f90
gcc/testsuite/gfortran.dg/protected_6.f90

index c18d9ba8744df55e72f489c21cdda79f9b052607..be3a9b5ebd6077b6f1edbe48886de7bd5ec70826 100644 (file)
@@ -1,3 +1,15 @@
+2007-01-05  Tobias Burnus  <burnus@net-b.de>
+
+       PR fortran/29624
+       * interface.c (compare_parameter_intent): New function.
+         (check_intents): Support pointer intents.
+       * symbol.c (check_conflict): Support pointer intents,
+         better conflict_std message.
+       * expr.c (gfc_check_assign,gfc_check_pointer_assign):
+         Support pointer intents.
+       * resolve.c (resolve_deallocate_expr,resolve_allocate_expr):
+         Support pointer intents.
+
 2007-01-03  Brooks Moses  <brooks.moses@codesourcery.com>
 
        PR 30371
index 7f6c699de59c8703d2af92ca3a53f06db4d07d24..7c2069c340b19193737c270c19470098ea86cf66 100644 (file)
@@ -2188,12 +2188,25 @@ try
 gfc_check_assign (gfc_expr * lvalue, gfc_expr * rvalue, int conform)
 {
   gfc_symbol *sym;
+  gfc_ref *ref;
+  int has_pointer;
 
   sym = lvalue->symtree->n.sym;
 
-  if (sym->attr.intent == INTENT_IN)
+  /* Check INTENT(IN), unless the object itself is the component or
+     sub-component of a pointer.  */
+  has_pointer = sym->attr.pointer;
+
+  for (ref = lvalue->ref; ref; ref = ref->next)
+    if (ref->type == REF_COMPONENT && ref->u.c.component->pointer)
+      {
+       has_pointer = 1;
+       break;
+      }
+
+  if (!has_pointer && sym->attr.intent == INTENT_IN)
     {
-      gfc_error ("Can't assign to INTENT(IN) variable '%s' at %L",
+      gfc_error ("Cannot assign to INTENT(IN) variable '%s' at %L",
                 sym->name, &lvalue->where);
       return FAILURE;
     }
@@ -2318,7 +2331,9 @@ try
 gfc_check_pointer_assign (gfc_expr * lvalue, gfc_expr * rvalue)
 {
   symbol_attribute attr;
+  gfc_ref *ref;
   int is_pure;
+  int pointer, check_intent_in;
 
   if (lvalue->symtree->n.sym->ts.type == BT_UNKNOWN)
     {
@@ -2336,8 +2351,29 @@ gfc_check_pointer_assign (gfc_expr * lvalue, gfc_expr * rvalue)
       return FAILURE;
     }
 
-  attr = gfc_variable_attr (lvalue, NULL);
-  if (!attr.pointer)
+
+  /* Check INTENT(IN), unless the object itself is the component or
+     sub-component of a pointer.  */
+  check_intent_in = 1;
+  pointer = lvalue->symtree->n.sym->attr.pointer;
+
+  for (ref = lvalue->ref; ref; ref = ref->next)
+    {
+      if (pointer)
+        check_intent_in = 0;
+
+      if (ref->type == REF_COMPONENT && ref->u.c.component->pointer)
+        pointer = 1;
+    }
+
+  if (check_intent_in && lvalue->symtree->n.sym->attr.intent == INTENT_IN)
+    {
+      gfc_error ("Cannot assign to INTENT(IN) variable '%s' at %L",
+                 lvalue->symtree->n.sym->name, &lvalue->where);
+      return FAILURE;
+    }
+
+  if (!pointer)
     {
       gfc_error ("Pointer assignment to non-POINTER at %L", &lvalue->where);
       return FAILURE;
index 7b0c4231b0e1d718e6811c6ea666c79c03374f85..8a1987dc6ec5553c53f6c24aba9427545ab90dad 100644 (file)
@@ -1664,6 +1664,27 @@ check_some_aliasing (gfc_formal_arglist * f, gfc_actual_arglist * a)
 }
 
 
+/* Given a symbol of a formal argument list and an expression,
+   return non-zero if their intents are compatible, zero otherwise.  */
+
+static int
+compare_parameter_intent (gfc_symbol * formal, gfc_expr * actual)
+{
+  if (actual->symtree->n.sym->attr.pointer
+      && !formal->attr.pointer)
+    return 1;
+
+  if (actual->symtree->n.sym->attr.intent != INTENT_IN)
+    return 1;
+
+  if (formal->attr.intent == INTENT_INOUT
+      || formal->attr.intent == INTENT_OUT)
+    return 0;
+
+  return 1;
+}
+
+
 /* Given formal and actual argument lists that correspond to one
    another, check that they are compatible in the sense that intents
    are not mismatched.  */
@@ -1671,7 +1692,7 @@ check_some_aliasing (gfc_formal_arglist * f, gfc_actual_arglist * a)
 static try
 check_intents (gfc_formal_arglist * f, gfc_actual_arglist * a)
 {
-  sym_intent a_intent, f_intent;
+  sym_intent f_intent;
 
   for (;; f = f->next, a = a->next)
     {
@@ -1683,12 +1704,9 @@ check_intents (gfc_formal_arglist * f, gfc_actual_arglist * a)
       if (a->expr == NULL || a->expr->expr_type != EXPR_VARIABLE)
        continue;
 
-      a_intent = a->expr->symtree->n.sym->attr.intent;
       f_intent = f->sym->attr.intent;
 
-      if (a_intent == INTENT_IN
-         && (f_intent == INTENT_INOUT
-             || f_intent == INTENT_OUT))
+      if (!compare_parameter_intent(f->sym, a->expr))
        {
 
          gfc_error ("Procedure argument at %L is INTENT(IN) while interface "
index 650a5a22c9175d2610a8c367904088f47edf555e..3c28d452ee43e4633f16d56f3dece8e41a9a635c 100644 (file)
@@ -3446,48 +3446,57 @@ static try
 resolve_deallocate_expr (gfc_expr * e)
 {
   symbol_attribute attr;
-  int allocatable;
+  int allocatable, pointer, check_intent_in;
   gfc_ref *ref;
 
+  /* Check INTENT(IN), unless the object is a sub-component of a pointer.  */
+  check_intent_in = 1;
+
   if (gfc_resolve_expr (e) == FAILURE)
     return FAILURE;
 
-  attr = gfc_expr_attr (e);
-  if (attr.pointer)
-    return SUCCESS;
-
   if (e->expr_type != EXPR_VARIABLE)
     goto bad;
 
   allocatable = e->symtree->n.sym->attr.allocatable;
+  pointer = e->symtree->n.sym->attr.pointer;
   for (ref = e->ref; ref; ref = ref->next)
-    switch (ref->type)
-      {
-      case REF_ARRAY:
-       if (ref->u.ar.type != AR_FULL)
-         allocatable = 0;
-       break;
+    {
+      if (pointer)
+        check_intent_in = 0;
 
-      case REF_COMPONENT:
-       allocatable = (ref->u.c.component->as != NULL
-                      && ref->u.c.component->as->type == AS_DEFERRED);
-       break;
+      switch (ref->type)
+        {
+        case REF_ARRAY:
+         if (ref->u.ar.type != AR_FULL)
+           allocatable = 0;
+         break;
 
-      case REF_SUBSTRING:
-       allocatable = 0;
-       break;
-      }
+        case REF_COMPONENT:
+         allocatable = (ref->u.c.component->as != NULL
+                        && ref->u.c.component->as->type == AS_DEFERRED);
+         pointer = ref->u.c.component->pointer;
+         break;
 
-  if (allocatable == 0)
+        case REF_SUBSTRING:
+         allocatable = 0;
+         break;
+        }
+    }
+
+  attr = gfc_expr_attr (e);
+
+  if (allocatable == 0 && attr.pointer == 0)
     {
     bad:
       gfc_error ("Expression in DEALLOCATE statement at %L must be "
                 "ALLOCATABLE or a POINTER", &e->where);
     }
 
-  if (e->symtree->n.sym->attr.intent == INTENT_IN)
+  if (check_intent_in
+      && e->symtree->n.sym->attr.intent == INTENT_IN)
     {
-      gfc_error ("Can't deallocate INTENT(IN) variable '%s' at %L",
+      gfc_error ("Cannot deallocate INTENT(IN) variable '%s' at %L",
                  e->symtree->n.sym->name, &e->where);
       return FAILURE;
     }
@@ -3609,7 +3618,7 @@ expr_to_initialize (gfc_expr * e)
 static try
 resolve_allocate_expr (gfc_expr * e, gfc_code * code)
 {
-  int i, pointer, allocatable, dimension;
+  int i, pointer, allocatable, dimension, check_intent_in;
   symbol_attribute attr;
   gfc_ref *ref, *ref2;
   gfc_array_ref *ar;
@@ -3618,6 +3627,9 @@ resolve_allocate_expr (gfc_expr * e, gfc_code * code)
   gfc_symbol *sym;
   gfc_alloc *a;
 
+  /* Check INTENT(IN), unless the object is a sub-component of a pointer.  */
+  check_intent_in = 1;
+
   if (gfc_resolve_expr (e) == FAILURE)
     return FAILURE;
 
@@ -3655,26 +3667,31 @@ resolve_allocate_expr (gfc_expr * e, gfc_code * code)
        }
 
       for (ref = e->ref; ref; ref2 = ref, ref = ref->next)
-       switch (ref->type)
-         {
-         case REF_ARRAY:
-           if (ref->next != NULL)
-             pointer = 0;
-           break;
-
-         case REF_COMPONENT:
-           allocatable = (ref->u.c.component->as != NULL
-                          && ref->u.c.component->as->type == AS_DEFERRED);
-
-           pointer = ref->u.c.component->pointer;
-           dimension = ref->u.c.component->dimension;
-           break;
+        {
+         if (pointer)
+           check_intent_in = 0;
 
-         case REF_SUBSTRING:
-           allocatable = 0;
-           pointer = 0;
-           break;
-         }
+         switch (ref->type)
+           {
+             case REF_ARRAY:
+               if (ref->next != NULL)
+                 pointer = 0;
+               break;
+
+             case REF_COMPONENT:
+               allocatable = (ref->u.c.component->as != NULL
+                             && ref->u.c.component->as->type == AS_DEFERRED);
+
+               pointer = ref->u.c.component->pointer;
+               dimension = ref->u.c.component->dimension;
+               break;
+
+             case REF_SUBSTRING:
+               allocatable = 0;
+               pointer = 0;
+               break;
+           }
+       }
     }
 
   if (allocatable == 0 && pointer == 0)
@@ -3684,9 +3701,10 @@ resolve_allocate_expr (gfc_expr * e, gfc_code * code)
       return FAILURE;
     }
 
-  if (e->symtree->n.sym->attr.intent == INTENT_IN)
+  if (check_intent_in
+      && e->symtree->n.sym->attr.intent == INTENT_IN)
     {
-      gfc_error ("Can't allocate INTENT(IN) variable '%s' at %L",
+      gfc_error ("Cannot allocate INTENT(IN) variable '%s' at %L",
                  e->symtree->n.sym->name, &e->where);
       return FAILURE;
     }
index 12c5749acec3a12c1b2d6cfb273569b7ddfb770a..a1aaae8fddff02e17d816da548e675bbbedfe49d 100644 (file)
@@ -288,7 +288,8 @@ check_conflict (symbol_attribute * attr, const char * name, locus * where)
     {
       a1 = pointer;
       a2 = intent;
-      goto conflict;
+      standard = GFC_STD_F2003;
+      goto conflict_std;
     }
 
   /* Check for attributes not allowed in a BLOCK DATA.  */
@@ -571,14 +572,14 @@ conflict:
 conflict_std:
   if (name == NULL)
     {
-      return gfc_notify_std (standard, "In the selected standard, %s attribute "
+      return gfc_notify_std (standard, "Fortran 2003: %s attribute "
                              "conflicts with %s attribute at %L", a1, a2,
                              where);
     }
   else
     {
-      return gfc_notify_std (standard, "In the selected standard, %s attribute "
-                             "conflicts with %s attribute in '%s' at %L",
+      return gfc_notify_std (standard, "Fortran 2003: %s attribute "
+                            "with %s attribute in '%s' at %L",
                              a1, a2, name, where);
     }
 }
index 0309fad98f507319c37a718f558d3c4016b83cf6..aae1b7a35bbc0d0067f2932975fca1ab28d81893 100644 (file)
@@ -1,4 +1,16 @@
-2006-01-04  Brooks Moses  <brooks.moses@codesourcery.com>
+2006-01-05  Tobias Burnus  <burnus@net-b.de>
+
+       PR fortran/29624
+       * gfortran.dg/alloc_alloc_expr_1.f90: Add check for
+         invalid deallocate.
+       * gfortran.dg/allocatable_dummy_2.f90: Update dg-error.
+       * gfortran.dg/protected_4.f90: Add pointer intent check.
+       * gfortran.dg/protected_6.f90: Add pointer intent check.
+       * gfortran.dg/pointer_intent_1.f90: New test.
+       * gfortran.dg/pointer_intent_2.f90: New test.
+       * gfortran.dg/pointer_intent_3.f90: New test.
+
+2007-01-04  Brooks Moses  <brooks.moses@codesourcery.com>
 
        PR 30235
        * gfortran.dg/altreturn_2.f90: new test.
index 477643855a2bd8763c1d7f08924c09d6967739f8..5545b0dce6c5491000405fcee96a155aa38ccbaa 100644 (file)
@@ -24,6 +24,8 @@ program fc011
 
   ALLOCATE(PTR,ALLOCS(PTR)) ! { dg-error "same ALLOCATE statement" }
 
-  print *, 'This program has three errors', PTR, ALLOC(1)
+  deallocate(ALLOCS(1)) ! { dg-error "must be ALLOCATABLE or a POINTER" }
+
+  print *, 'This program has four errors', PTR, ALLOC(1)
 
 end program fc011
index 46a6f4fa671947cd3de7f133b5f1c9703286a00b..c33ad13b8c57c3668d2d3c2d3db5786c45158939 100644 (file)
@@ -16,13 +16,13 @@ contains
     subroutine init2(x)
         integer, allocatable, intent(in) :: x(:)
 
-        allocate(x(3)) ! { dg-error "Can't allocate" }
+        allocate(x(3)) ! { dg-error "Cannot allocate" }
     end subroutine init2
 
     subroutine kill(x)
         integer, allocatable, intent(in) :: x(:)
         
-        deallocate(x) ! { dg-error "Can't deallocate" }
+        deallocate(x) ! { dg-error "Cannot deallocate" }
     end subroutine kill
 
 end program alloc_dummy
diff --git a/gcc/testsuite/gfortran.dg/pointer_intent_1.f90 b/gcc/testsuite/gfortran.dg/pointer_intent_1.f90
new file mode 100644 (file)
index 0000000..882c6a5
--- /dev/null
@@ -0,0 +1,71 @@
+! { dg-run }
+! { dg-options "-std=f2003 -fall-intrinsics" }
+! Pointer intent test
+! PR fortran/29624
+!
+! Valid program
+program test
+ implicit none
+ type myT
+   integer          :: x
+   integer, pointer :: point
+ end type myT
+ integer, pointer :: p
+ type(myT), pointer :: t
+ type(myT) :: t2
+ allocate(p,t)
+ allocate(t%point)
+ t%point = 55
+ p = 33
+ call a(p,t)
+ deallocate(p)
+ nullify(p)
+ call a(p,t)
+ call nonpointer(t2)
+contains
+  subroutine a(p,t)
+    integer, pointer,intent(in)    :: p
+    type(myT), pointer, intent(in) :: t
+    integer, pointer :: tmp
+    if(.not.associated(p)) return
+    if(p /= 33) call abort()
+    p = 7
+    if (associated(t)) then
+      ! allocating is valid as we don't change the status
+      ! of the pointer "t", only of it's target
+      t%x = -15
+      if(.not.associated(t%point)) call abort()
+      if(t%point /= 55) call abort()
+      nullify(t%point)
+      allocate(tmp)
+      t%point => tmp
+      deallocate(t%point)
+      t%point => null(t%point)
+      tmp => null(tmp)
+      allocate(t%point)
+      t%point = 27
+      if(t%point /= 27) call abort()
+      if(t%x     /= -15) call abort()
+      call foo(t)
+      if(t%x     /=  32) call abort()
+      if(t%point /= -98) call abort()
+    end if
+    call b(p)
+    if(p /= 5) call abort()
+  end subroutine
+  subroutine b(v)
+    integer, intent(out) :: v
+    v = 5
+  end subroutine b
+  subroutine foo(comp)
+    type(myT), intent(inout) :: comp
+    if(comp%x     /= -15) call abort()
+    !if(comp%point /=  27) call abort()
+    comp%x     = 32
+    comp%point = -98
+  end subroutine foo
+  subroutine nonpointer(t)
+     type(myT), intent(in) :: t
+     t%point = 7
+  end subroutine nonpointer
+end program
diff --git a/gcc/testsuite/gfortran.dg/pointer_intent_2.f90 b/gcc/testsuite/gfortran.dg/pointer_intent_2.f90
new file mode 100644 (file)
index 0000000..247016b
--- /dev/null
@@ -0,0 +1,19 @@
+! { dg-compile }
+! { dg-options "-std=f95" }
+! { dg-shouldfail "Fortran 2003 feature with -std=f95" }
+!
+! Pointer intent test
+! PR fortran/29624
+!
+! Fortran 2003 features in Fortran 95
+program test
+ implicit none
+ integer, pointer :: p
+ allocate(p)
+ p = 33
+ call a(p) ! { dg-error "Type/rank mismatch in argument" }
+contains
+  subroutine a(p)! { dg-error "has no IMPLICIT type" }
+    integer, pointer,intent(in) :: p ! { dg-error "POINTER attribute with INTENT attribute" }
+  end subroutine
+end program
diff --git a/gcc/testsuite/gfortran.dg/pointer_intent_3.f90 b/gcc/testsuite/gfortran.dg/pointer_intent_3.f90
new file mode 100644 (file)
index 0000000..e7ce590
--- /dev/null
@@ -0,0 +1,41 @@
+! { dg-compile }
+! { dg-options "-std=f2003 -fall-intrinsics" }
+! { dg-shouldfail "Invalid code" }
+!
+! Pointer intent test
+! PR fortran/29624
+!
+! Valid program
+program test
+ implicit none
+ type myT
+    integer :: j = 5
+    integer, pointer :: jp => null()
+ end type myT
+ integer, pointer :: p
+ type(myT) :: t
+ call a(p)
+ call b(t)
+contains
+  subroutine a(p)
+    integer, pointer,intent(in) :: p
+    p => null(p)! { dg-error "Cannot assign to INTENT\\(IN\\) variable" }
+    nullify(p)  ! { dg-error "Cannot assign to INTENT\\(IN\\) variable" }
+    allocate(p) ! { dg-error "Cannot allocate INTENT\\(IN\\) variable" }
+    call c(p)   ! { dg-error "is INTENT\\(IN\\) while interface specifies INTENT\\(INOUT\\)" }
+    deallocate(p) ! { dg-error "Cannot deallocate INTENT\\(IN\\) variable" }
+  end subroutine
+  subroutine c(p)
+    integer, pointer, intent(inout) :: p
+    nullify(p)
+  end subroutine c
+  subroutine b(t)
+    type(myT),intent(in) :: t
+    t%jp = 5
+    t%jp => null(t%jp)  ! { dg-error "Cannot assign to INTENT\\(IN\\) variable" }
+    nullify(t%jp) ! { dg-error "Cannot assign to INTENT\\(IN\\) variable" }
+    t%j = 7 ! { dg-error "Cannot assign to INTENT\\(IN\\) variable" }
+    allocate(t%jp) ! { dg-error "Cannot allocate INTENT\\(IN\\) variable" }
+    deallocate(t%jp) ! { dg-error "Cannot deallocate INTENT\\(IN\\) variable" }
+  end subroutine b
+end program
index be35b6bf60b20f0990cd0ed43014341f1df24675..7d2238e2ffd36ed210969362b253a50979f19bf8 100644 (file)
@@ -21,6 +21,7 @@ program main
   use protmod
   implicit none
   integer   :: j 
+  logical   :: asgnd
   protected :: j ! { dg-error "only allowed in specification part of a module" }
   a = 43       ! { dg-error "Assigning to PROTECTED variable" }
   ap => null() ! { dg-error "Assigning to PROTECTED variable" }
@@ -30,6 +31,8 @@ program main
   allocate(ap) ! { dg-error "Assigning to PROTECTED variable" }
   ap = 73      ! { dg-error "Assigning to PROTECTED variable" }
   call increment(a,at) ! { dg-error "use-associated with PROTECTED attribute" }
+  call pointer_assignments(ap) ! { dg-error "is use-associated with PROTECTED attribute" }
+  asgnd = pointer_check(ap)
 contains
   subroutine increment(a1,a3)
     integer, intent(inout) :: a1, a3
@@ -37,9 +40,14 @@ contains
     a3 = a3 + 1
   end subroutine increment
   subroutine pointer_assignments(p)
-    integer, pointer :: p ! with [pointer] intent(out)
-    p => null()           ! this is invalid
+    integer, pointer,intent(out) :: p
+    p => null()           
   end subroutine pointer_assignments
+  function pointer_check(p)
+    integer, pointer,intent(in) :: p
+    logical :: pointer_check
+    pointer_check = associated(p)
+  end function pointer_check
 end program main
 
 module test
index 50729495c8f8b8fd6536221ec47e9207e53188dc..5b71f8ba5744aea0c2edec5da9251be7ca4dcad8 100644 (file)
@@ -27,6 +27,7 @@ program main
   allocate(ap) ! { dg-error "Assigning to PROTECTED variable" }
   ap = 73      ! { dg-error "Assigning to PROTECTED variable" }
   call increment(a,at) ! { dg-error "use-associated with PROTECTED attribute" }
+  call pointer_assignments(ap) ! { dg-error "is use-associated with PROTECTED attribute" }
 contains
   subroutine increment(a1,a3)
     integer, intent(inout) :: a1, a3
@@ -34,8 +35,8 @@ contains
     a3 = a3 + 1
   end subroutine increment
   subroutine pointer_assignments(p)
-    integer, pointer :: p ! with [pointer] intent(out)
-    p => null()           ! this is invalid
+    integer, pointer,intent (inout) :: p
+    p => null()
   end subroutine pointer_assignments
 end program main
 
This page took 0.204454 seconds and 5 git commands to generate.