re PR fortran/16136 (Conflicting attributes ALLOCATABLE, DUMMY (F2003))
authorErik Edelmann <eedelman@gcc.gnu.org>
Sun, 5 Mar 2006 19:24:48 +0000 (19:24 +0000)
committerErik Edelmann <eedelman@gcc.gnu.org>
Sun, 5 Mar 2006 19:24:48 +0000 (19:24 +0000)
fortran/
2005-03-05  Erik Edelmann  <eedelman@gcc.gnu.org>

        PR fortran/16136
        * symbol.c (conf_std): New macro.
        (check_conflict): Use it to allow ALLOCATABLE dummy
        arguments for F2003.
        * trans-expr.c (gfc_conv_function_call): Pass the
        address of the array descriptor when dummy argument is
        ALLOCATABLE.
        * interface.c (compare_allocatable): New function.
        (compare_actual_formal): Use it.
        resolve.c (resolve_deallocate_expr,
        resolve_allocate_expr): Check that INTENT(IN) variables
        aren't (de)allocated.
        * gfortran.texi (Fortran 2003 status): List ALLOCATABLE
        dummy arguments as supported.

testsuite/
2005-03-05  Erik Edelmann  <eedelman@gcc.gnu.org>

        PR fortran/16136
        * allocatable_dummy_1.f90: New.
        * allocatable_dummy_2.f90: New.

From-SVN: r111741

gcc/fortran/ChangeLog
gcc/fortran/gfortran.texi
gcc/fortran/interface.c
gcc/fortran/resolve.c
gcc/fortran/symbol.c
gcc/fortran/trans-expr.c
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/allocatable_dummy_1.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/allocatable_dummy_2.f90 [new file with mode: 0644]

index 4e4b241f4880e9142060f4e06e9152d81ced5409..e3fb42c97b365ac446cc10fdaeee75489a8f14a2 100644 (file)
@@ -1,3 +1,20 @@
+2005-03-05  Erik Edelmann  <eedelman@gcc.gnu.org>
+
+       PR fortran/16136
+       * symbol.c (conf_std): New macro.
+       (check_conflict): Use it to allow ALLOCATABLE dummy
+       arguments for F2003.
+       * trans-expr.c (gfc_conv_function_call): Pass the
+       address of the array descriptor when dummy argument is
+       ALLOCATABLE.
+       * interface.c (compare_allocatable): New function.
+       (compare_actual_formal): Use it.
+       * resolve.c (resolve_deallocate_expr,
+       resolve_allocate_expr): Check that INTENT(IN) variables
+       aren't (de)allocated.
+       * gfortran.texi (Fortran 2003 status): List ALLOCATABLE
+       dummy arguments as supported.
+
 2006-03-03  Roger Sayle  <roger@eyesopen.com>
 
        * dependency.c (gfc_check_element_vs_element): Revert last change.
index c19b669a338d71a64df6dc612cafb5de85957b76..769696263910f09f862f41c024b1202ee7bfbbde 100644 (file)
@@ -1331,6 +1331,10 @@ Support for the declaration of enumeration constants via the
 @command{gcc} is guaranteed also for the case where the
 @command{-fshort-enums} command line option is given.
 
+@item
+@cindex @code{ALLOCATABLE} dummy arguments
+The @code{ALLOCATABLE} attribute for dummy arguments.
+
 @end itemize
 
 
index 7c8627952aff9be2163d58321841bf571f45e4d9..f4e522aadd95bed282ca2f14aa43065ca3e8e659 100644 (file)
@@ -1064,6 +1064,26 @@ symbol_rank (gfc_symbol * sym)
 }
 
 
+/* Given a symbol of a formal argument list and an expression, if the
+   formal argument is allocatable, check that the actual argument is
+   allocatable. Returns nonzero if compatible, zero if not compatible.  */
+
+static int
+compare_allocatable (gfc_symbol * formal, gfc_expr * actual)
+{
+  symbol_attribute attr;
+
+  if (formal->attr.allocatable)
+    {
+      attr = gfc_expr_attr (actual);
+      if (!attr.allocatable)
+       return 0;
+    }
+
+  return 1;
+}
+
+
 /* Given a symbol of a formal argument list and an expression, if the
    formal argument is a pointer, see if the actual argument is a
    pointer. Returns nonzero if compatible, zero if not compatible.  */
@@ -1276,6 +1296,15 @@ compare_actual_formal (gfc_actual_arglist ** ap,
          return 0;
        }
 
+      if (a->expr->expr_type != EXPR_NULL
+         && compare_allocatable (f->sym, a->expr) == 0)
+       {
+         if (where)
+           gfc_error ("Actual argument for '%s' must be ALLOCATABLE at %L",
+                      f->sym->name, &a->expr->where);
+         return 0;
+       }
+
       /* Check intent = OUT/INOUT for definable actual argument.  */
       if (a->expr->expr_type != EXPR_VARIABLE
             && (f->sym->attr.intent == INTENT_OUT
index 63b2cd9904d0027cce1239079d13a128eedc26bf..4bf394a1ff69dc4e9c65c30cf4bd921ed8cdffdf 100644 (file)
@@ -2914,6 +2914,13 @@ resolve_deallocate_expr (gfc_expr * e)
                 "ALLOCATABLE or a POINTER", &e->where);
     }
 
+  if (e->symtree->n.sym->attr.intent == INTENT_IN)
+    {
+      gfc_error ("Can't deallocate INTENT(IN) variable '%s' at %L",
+                 e->symtree->n.sym->name, &e->where);
+      return FAILURE;
+    }
+
   return SUCCESS;
 }
 
@@ -3015,6 +3022,13 @@ resolve_allocate_expr (gfc_expr * e, gfc_code * code)
       return FAILURE;
     }
 
+  if (e->symtree->n.sym->attr.intent == INTENT_IN)
+    {
+      gfc_error ("Can't allocate INTENT(IN) variable '%s' at %L",
+                 e->symtree->n.sym->name, &e->where);
+      return FAILURE;
+    }
+
   /* Add default initializer for those derived types that need them.  */
   if (e->ts.type == BT_DERIVED && (init_e = gfc_default_initializer (&e->ts)))
     {
index 285c276be9e898408df448aeea587c2854ca5677..e98556d2e1a13752af3f15f2e1cdd0757ad9b8fc 100644 (file)
@@ -251,6 +251,13 @@ gfc_set_default_type (gfc_symbol * sym, int error_flag, gfc_namespace * ns)
 
 #define conf(a, b) if (attr->a && attr->b) { a1 = a; a2 = b; goto conflict; }
 #define conf2(a) if (attr->a) { a2 = a; goto conflict; }
+#define conf_std(a, b, std) if (attr->a && attr->b)\
+                              {\
+                                a1 = a;\
+                                a2 = b;\
+                                standard = std;\
+                                goto conflict_std;\
+                              }
 
 static try
 check_conflict (symbol_attribute * attr, const char * name, locus * where)
@@ -268,6 +275,7 @@ check_conflict (symbol_attribute * attr, const char * name, locus * where)
   static const char *threadprivate = "THREADPRIVATE";
 
   const char *a1, *a2;
+  int standard;
 
   if (where == NULL)
     where = &gfc_current_locus;
@@ -328,7 +336,7 @@ check_conflict (symbol_attribute * attr, const char * name, locus * where)
     }
 
   conf (allocatable, pointer);
-  conf (allocatable, dummy);   /* TODO: Allowed in Fortran 200x.  */
+  conf_std (allocatable, dummy, GFC_STD_F2003);
   conf (allocatable, function);        /* TODO: Allowed in Fortran 200x.  */
   conf (allocatable, result);  /* TODO: Allowed in Fortran 200x.  */
   conf (elemental, recursive);
@@ -519,10 +527,25 @@ conflict:
               a1, a2, name, where);
 
   return FAILURE;
+
+conflict_std:
+  if (name == NULL)
+    {
+      return gfc_notify_std (standard, "In the selected standard, %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",
+                             a1, a2, name, where);
+    }
 }
 
 #undef conf
 #undef conf2
+#undef conf_std
 
 
 /* Mark a symbol as referenced.  */
index 9f5774bf815801ed1e0eefeeb9ec7a13db4a3f7e..1fc7f06feb0350e4776b29b117eeeecd8b8cd094 100644 (file)
@@ -1870,16 +1870,15 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym,
             }
          else
            {
-             /* If the procedure requires an explicit interface, the
-                actual argument is passed according to the
-                corresponding formal argument.  If the corresponding
-                formal argument is a POINTER or assumed shape, we do
-                not use g77's calling convention, and pass the
-                address of the array descriptor instead. Otherwise we
-                use g77's calling convention.  */
+              /* If the procedure requires an explicit interface, the actual
+                 argument is passed according to the corresponding formal
+                 argument.  If the corresponding formal argument is a POINTER,
+                 ALLOCATABLE or assumed shape, we do not use g77's calling
+                 convention, and pass the address of the array descriptor
+                 instead. Otherwise we use g77's calling convention.  */
              int f;
              f = (formal != NULL)
-                 && !formal->sym->attr.pointer
+                 && !(formal->sym->attr.pointer || formal->sym->attr.allocatable)
                  && formal->sym->as->type != AS_ASSUMED_SHAPE;
              f = f || !sym->attr.always_explicit;
              if (arg->expr->expr_type == EXPR_VARIABLE
index e6f9d5e4df99624f5ca692679c3b2686c84390e2..d38d9599825c1ce175ee0ce9b6dcc60a12fcd12c 100644 (file)
@@ -1,3 +1,9 @@
+2005-03-05  Erik Edelmann  <eedelman@gcc.gnu.org>
+
+       PR fortran/16136
+       * allocatable_dummy_1.f90: New.
+       * allocatable_dummy_2.f90: New.
+
 2006-03-05  Jerry DeLisle  <jvdelisle@gcc.gnu.org>
 
        PR libgfortran/26554
diff --git a/gcc/testsuite/gfortran.dg/allocatable_dummy_1.f90 b/gcc/testsuite/gfortran.dg/allocatable_dummy_1.f90
new file mode 100644 (file)
index 0000000..f0581ad
--- /dev/null
@@ -0,0 +1,32 @@
+! { dg-do run }
+! Test procedures with allocatable dummy arguments
+program alloc_dummy
+
+    implicit none
+    integer, allocatable :: a(:)
+
+    call init(a)
+    if (.NOT.allocated(a)) call abort()
+    if (.NOT.all(a == [ 1, 2, 3 ])) call abort()
+
+    call kill(a)
+    if (allocated(a)) call abort()
+
+
+contains
+
+    subroutine init(x)
+        integer, allocatable, intent(out) :: x(:)
+
+        allocate(x(3))
+        x = [ 1, 2, 3 ]
+    end subroutine init
+
+    
+    subroutine kill(x)
+        integer, allocatable, intent(out) :: x(:)
+
+        deallocate(x)
+    end subroutine kill
+
+end program alloc_dummy
diff --git a/gcc/testsuite/gfortran.dg/allocatable_dummy_2.f90 b/gcc/testsuite/gfortran.dg/allocatable_dummy_2.f90
new file mode 100644 (file)
index 0000000..46a6f4f
--- /dev/null
@@ -0,0 +1,28 @@
+! { dg-do compile }
+! Check a few constraints for ALLOCATABLE dummy arguments.
+program alloc_dummy
+
+    implicit none
+    integer :: a(5)
+
+    call init(a) ! { dg-error "must be ALLOCATABLE" }
+
+contains
+
+    subroutine init(x)
+        integer, allocatable, intent(out) :: x(:)
+    end subroutine init
+
+    subroutine init2(x)
+        integer, allocatable, intent(in) :: x(:)
+
+        allocate(x(3)) ! { dg-error "Can't allocate" }
+    end subroutine init2
+
+    subroutine kill(x)
+        integer, allocatable, intent(in) :: x(:)
+        
+        deallocate(x) ! { dg-error "Can't deallocate" }
+    end subroutine kill
+
+end program alloc_dummy