Bug 36361 - attribute declaration outside of INTERFACE body
Summary: attribute declaration outside of INTERFACE body
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.4.0
: P3 normal
Target Milestone: ---
Assignee: janus
URL:
Keywords: accepts-invalid
Depends on:
Blocks:
 
Reported: 2008-05-28 22:17 UTC by janus
Modified: 2008-06-02 21:53 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2008-05-29 20:06:26


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description janus 2008-05-28 22:17:37 UTC
The following code is invalid, but accepted by gfortran:

interface
  real function bar()
  end function bar
end interface
dimension :: bar(4)

It is invalid, since section 12.3.2.1 of the Fortran 2003 standard states:

"An interface body specifies all of the characteristics of the explicit specific interface or abstract interface. The specification part of an interface body may specify attributes or define values for data entities that do not determine characteristics of the procedure. Such specifications have no effect."

This means that there may be no additional attributes specified outside of the interface body.

g95 correctly gives the following error message for this test case:

dimension :: bar(4)
             1
Error: Attribute declaration of 'bar' at (1) is outside of the INTERFACE body

The test case also has to be rejected when the order of the statements is exchanged:

dimension :: bar(4)
interface
  real function bar()
  end function bar
end interface

This is probably even harder to detect. g95's error message for this case is:

dimension :: bar(4)
             1
Error: Symbol 'bar' at (1) conflicts with the same name in an encompassing program unit

I think it would be desirable for gfortran to print out the same message for both cases.
Comment 1 Tobias Burnus 2008-05-28 22:23:42 UTC
Similarly for:

interface
  function bar()
    real bar(:) ! wrong w/o allocatable
  end function bar
end interface
ALLOCATABLE :: bar ! <<<< WRONG
end
Comment 2 janus 2008-05-28 22:56:08 UTC
A related problem also occurs with the POINTER attribute:

interface
  real function bar()
  end function bar
end interface

pointer :: bar

Here I'm not really sure if it is forbidden, because one could interpret this as a procedure pointer. g95 gives the same error message as with DIMENSION (see above).

Assuming it is not forbidden, one would still have to distinguish it from:

interface
  function bar()
    real, pointer :: bar
  end function bar
end interface

This code clearly is valid (declaring a pointer-valued function).
Comment 3 Tobias Burnus 2008-05-29 11:24:58 UTC
> A related problem also occurs with the POINTER attribute:
> interface
>   real function bar()
>   end function bar
> end interface
> pointer :: bar

This allowed and means a procedure pointer. See

"5.1.2.6 EXTERNAL attribute"
"A procedure that has both the EXTERNAL and POINTER attributes is a procedure pointer."

While the following is a function (no proc pointer) with a pointer-valued return variable:

> interface
>   function bar()
>     real, pointer :: bar
>   end function bar
> end interface
Comment 4 janus 2008-05-29 20:06:25 UTC
Here is a first attempt to fix this. The following patch should cope with the original test case and the one in comment #1. The fix for the POINTER issues will go into my procedure pointer patch. Any other attributes we need to handle?


Index: gcc/fortran/symbol.c
===================================================================
--- gcc/fortran/symbol.c	(revision 136137)
+++ gcc/fortran/symbol.c	(working copy)
@@ -814,6 +814,14 @@ gfc_add_allocatable (symbol_attribute *a
       return FAILURE;
     }
 
+  if (attr->flavor == FL_PROCEDURE && attr->if_source == IFSRC_IFBODY
+      && gfc_find_state (COMP_INTERFACE) == FAILURE)
+    {
+      gfc_error ("Attribute ALLOCATABLE declared 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 *att
       return FAILURE;
     }
 
+  if (attr->flavor == FL_PROCEDURE && attr->if_source == IFSRC_IFBODY
+      && gfc_find_state (COMP_INTERFACE) == FAILURE)
+    {
+      gfc_error ("Attribute DIMENSION of %s declared outside of 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 *
       return FAILURE;
     }
 
+  if (source == IFSRC_IFBODY && (sym->attr.dimension || sym->attr.allocatable))
+    {
+      gfc_error ("Attribute declared outside of INTERFACE body for %s at %L",
+		 sym->name, where);
+      return FAILURE;
+    }
+
   sym->formal = formal;
   sym->attr.if_source = source;
 
Index: gcc/fortran/parse.c
===================================================================
--- gcc/fortran/parse.c	(revision 136137)
+++ gcc/fortran/parse.c	(working copy)
@@ -1915,8 +1915,13 @@ loop:
 
     case ST_SUBROUTINE:
       new_state = COMP_SUBROUTINE;
-      gfc_add_explicit_interface (gfc_new_block, IFSRC_IFBODY,
-				  gfc_new_block->formal, NULL);
+      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;
+	}
       if (current_interface.type != INTERFACE_ABSTRACT &&
 	 !gfc_new_block->attr.dummy &&
 	 gfc_add_external (&gfc_new_block->attr, &gfc_current_locus) == FAILURE)
@@ -1929,8 +1934,13 @@ loop:
 
     case ST_FUNCTION:
       new_state = COMP_FUNCTION;
-      gfc_add_explicit_interface (gfc_new_block, IFSRC_IFBODY,
-				  gfc_new_block->formal, NULL);
+      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;
+	}
       if (current_interface.type != INTERFACE_ABSTRACT &&
 	 !gfc_new_block->attr.dummy &&
 	 gfc_add_external (&gfc_new_block->attr, &gfc_current_locus) == FAILURE)
Comment 5 Tobias Burnus 2008-05-29 20:58:18 UTC
> Any other attributes we need to handle?
I think that's all. I looked through the list of attributes and most are not possible for procedures or are already rejected. Thus I think we have all.
Comment 6 janus 2008-06-02 21:51:08 UTC
Subject: Bug 36361

Author: janus
Date: Mon Jun  2 21:50:23 2008
New Revision: 136296

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=136296
Log:
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.

Added:
    trunk/gcc/testsuite/gfortran.dg/interface_24.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/decl.c
    trunk/gcc/fortran/parse.c
    trunk/gcc/fortran/symbol.c
    trunk/gcc/testsuite/ChangeLog

Comment 7 janus 2008-06-02 21:53:37 UTC
Fixed with r136296. Closing.