re PR fortran/36361 (attribute declaration outside of INTERFACE body)
authorJanus Weil <janus@gcc.gnu.org>
Mon, 2 Jun 2008 21:50:23 +0000 (23:50 +0200)
committerJanus Weil <janus@gcc.gnu.org>
Mon, 2 Jun 2008 21:50:23 +0000 (23:50 +0200)
2008-06-02  Janus Weil  <janus@gcc.gnu.org>

PR fortran/36361
* symbol.c (gfc_add_allocatable,gfc_add_dimension,
gfc_add_explicit_interface): Added checks.
* decl.c (attr_decl1): Added missing "var_locus".
* parse.c (parse_interface): Checking for errors.

2008-06-02  Janus Weil  <janus@gcc.gnu.org>

PR fortran/36361
* gfortran.dg/interface_24.f90: New.

From-SVN: r136296

gcc/fortran/ChangeLog
gcc/fortran/decl.c
gcc/fortran/parse.c
gcc/fortran/symbol.c
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/interface_24.f90 [new file with mode: 0644]

index 1a3d2dac94aab6f3653233b40965e18d02a118b5..fd0817becbd3af40be3714d0734658674826f25e 100644 (file)
@@ -1,3 +1,11 @@
+2008-06-02  Janus Weil  <janus@gcc.gnu.org>
+
+       PR fortran/36361
+       * symbol.c (gfc_add_allocatable,gfc_add_dimension,
+       gfc_add_explicit_interface): Added checks.
+       * decl.c (attr_decl1): Added missing "var_locus".
+       * parse.c (parse_interface): Checking for errors.
+
 2008-06-02  Daniel Kraft  <d@domob.eu>
 
        * gfortran.h:  New statement-type ST_FINAL for FINAL declarations.
index f6884f2505ad1276c9575d69f6c9f86a041e67f7..ea87c211d4938677847e9ddc4e2773e7a65ff51b 100644 (file)
@@ -5216,7 +5216,7 @@ attr_decl1 (void)
   /* Update symbol table.  DIMENSION attribute is set
      in gfc_set_array_spec().  */
   if (current_attr.dimension == 0
-      && gfc_copy_attr (&sym->attr, &current_attr, NULL) == FAILURE)
+      && gfc_copy_attr (&sym->attr, &current_attr, &var_locus) == FAILURE)
     {
       m = MATCH_ERROR;
       goto cleanup;
index dc1a62b1a080980464080caa8f5f2e7db2d9f73f..33f13c92200734062929b67e12b63d0165f6d258 100644 (file)
@@ -1974,23 +1974,18 @@ loop:
       unexpected_eof ();
 
     case ST_SUBROUTINE:
-      new_state = COMP_SUBROUTINE;
-      gfc_add_explicit_interface (gfc_new_block, IFSRC_IFBODY,
-                                 gfc_new_block->formal, NULL);
-      if (current_interface.type != INTERFACE_ABSTRACT &&
-        !gfc_new_block->attr.dummy &&
-        gfc_add_external (&gfc_new_block->attr, &gfc_current_locus) == FAILURE)
+    case ST_FUNCTION:
+      if (st == ST_SUBROUTINE)
+       new_state = COMP_SUBROUTINE;
+      else if (st == ST_FUNCTION)
+       new_state = COMP_FUNCTION;
+      if (gfc_add_explicit_interface (gfc_new_block, IFSRC_IFBODY,
+                                 gfc_new_block->formal, NULL) == FAILURE)
        {
          reject_statement ();
          gfc_free_namespace (gfc_current_ns);
          goto loop;
        }
-      break;
-
-    case ST_FUNCTION:
-      new_state = COMP_FUNCTION;
-      gfc_add_explicit_interface (gfc_new_block, IFSRC_IFBODY,
-                                 gfc_new_block->formal, NULL);
       if (current_interface.type != INTERFACE_ABSTRACT &&
         !gfc_new_block->attr.dummy &&
         gfc_add_external (&gfc_new_block->attr, &gfc_current_locus) == FAILURE)
index 78561aac47dc226c2a73d522dade88abe6e43458..e4e43244d59ec4e4a8fddb9abd29de9037b42c95 100644 (file)
@@ -814,6 +814,14 @@ gfc_add_allocatable (symbol_attribute *attr, locus *where)
       return FAILURE;
     }
 
+  if (attr->flavor == FL_PROCEDURE && attr->if_source == IFSRC_IFBODY
+      && gfc_find_state (COMP_INTERFACE) == FAILURE)
+    {
+      gfc_error ("ALLOCATABLE specified outside of INTERFACE body at %L",
+                where);
+      return FAILURE;
+    }
+
   attr->allocatable = 1;
   return check_conflict (attr, NULL, where);
 }
@@ -832,6 +840,14 @@ gfc_add_dimension (symbol_attribute *attr, const char *name, locus *where)
       return FAILURE;
     }
 
+  if (attr->flavor == FL_PROCEDURE && attr->if_source == IFSRC_IFBODY
+      && gfc_find_state (COMP_INTERFACE) == FAILURE)
+    {
+      gfc_error ("DIMENSION specified for '%s' outside its INTERFACE body "
+                "at %L", name, where);
+      return FAILURE;
+    }
+
   attr->dimension = 1;
   return check_conflict (attr, name, where);
 }
@@ -1453,6 +1469,13 @@ gfc_add_explicit_interface (gfc_symbol *sym, ifsrc source,
       return FAILURE;
     }
 
+  if (source == IFSRC_IFBODY && (sym->attr.dimension || sym->attr.allocatable))
+    {
+      gfc_error ("'%s' at %L has attributes specified outside its INTERFACE "
+                "body", sym->name, where);
+      return FAILURE;
+    }
+
   sym->formal = formal;
   sym->attr.if_source = source;
 
index 0bfe14a35383a511c75684ebcd9bfcc7f2e54826..efb1b2ac6432a1a815c7e7d0bc47c3eff45c071d 100644 (file)
@@ -1,3 +1,8 @@
+2008-06-02  Janus Weil  <janus@gcc.gnu.org>
+
+       PR fortran/36361
+       * gfortran.dg/interface_24.f90: New.
+
 2008-06-02  Paolo Carlini  <paolo.carlini@oracle.com>
 
         PR c++/36404
diff --git a/gcc/testsuite/gfortran.dg/interface_24.f90 b/gcc/testsuite/gfortran.dg/interface_24.f90
new file mode 100644 (file)
index 0000000..1afc5ef
--- /dev/null
@@ -0,0 +1,66 @@
+! { dg-do compile }
+!
+! This tests the fix for PR36361: If a function was declared in an INTERFACE
+! statement, no attributes may be declared outside of the INTERFACE body.
+!
+! Contributed by Janus Weil <janus@gcc.gnu.org>
+
+module m1
+  interface
+    real function f1()
+    end function
+  end interface
+  dimension :: f1(4)  ! { dg-error "outside its INTERFACE body" }
+end module
+
+
+module m2
+  dimension :: f2(4)
+  interface
+    real function f2()  ! { dg-error "outside its INTERFACE body" }
+    !end function
+  end interface
+end module
+
+
+! valid
+module m3
+  interface
+    real function f3()
+      dimension :: f3(4)
+    end function
+  end interface
+end module
+
+
+module m4
+  interface
+    function f4()  ! { dg-error "cannot have a deferred shape" }
+      real :: f4(:)
+    end function
+  end interface
+  allocatable :: f4  ! { dg-error "outside of INTERFACE body" }
+end module
+
+
+module m5
+  allocatable :: f5(:)
+  interface
+    function f5()  ! { dg-error "outside its INTERFACE body" }
+      !real f5(:)
+    !end function
+  end interface
+end module
+
+
+!valid
+module m6
+  interface
+    function f6()
+      real f6(:)
+      allocatable :: f6
+    end function
+  end interface
+end module
+
+! { dg-final { cleanup-modules "m1 m2 m3 m4 m5 m6" } }