Hello,

for the case:
[...]
       use select_precision, only: wp => dp
       interface
           subroutine ode_derivative(x)
               import   :: wp
[...]

`wp' is currently imported in the subroutine namespace under its original name `dp', which leads to an error if one tries to use `wp'.

The core of the fix, which is basically a collection of the patches Tobias posted in the PR, uses the matched name instead of the original name for the symtree in the subroutine namespace. Tobias' patches regress on import7.f90 because variable_decl lookups for the type in the interface namespace (to check that it has been declared) using the original name (which is the only one available there). The fix I propose for that is to remove the regressing error, and try to trigger the existing generic code diagnosing undeclared types. The latter doesn't trigger currently because gfc_get_ha_symtree keep going up the parent namespace until it finds a symbol, so in an interface block, it is guaranteed to find a declared symbol, even if the latter hasn't been imported in the interface. The fix for that checks whether we are in an interface body without blank import statement, and aborts the lookup in that case. A few adjustments are then needed where the parent namespace is accessed directly, thus bypassing the above check.

The change from the interface-specific error to the more general error needs a few test cases to be adjusted, namely import2.f90, import8.f90, and interface_derived_type_1.f90
from:

type(fcnparms) :: fparams ! { dg-error "not been declared within the in
                                    1
Error: The type of 'fparams' at (1) has not been declared within the interface

to:

type(fcnparms) :: fparams ! { dg-error "not been declared within the in
                         1
Error: Derived type 'fcnparms' at (1) is being used before it is defined


The caret is slightly better, the message is slightly worse. I think it's OK, but could consider trying to issue a better error message.
Otherwise it passes the test suite. OK for trunk?

As the code impacts the name to symbol resolution code, it has a big potential for breakage; the bug is a regression however, so I plan to backport to 4.7 and 4.6, say, two weeks after trunk at least (if I don't forget). Does it sound good?

Mikael



fortran/

2013-01-10  Tobias Burnus  <bur...@net-b.de>
            Mikael Morin  <mik...@gcc.gnu.org>

        PR fortran/53537
        * symbol.c (gfc_find_sym_tree): Don't look for the symbol outside an
        interface block.
        (gfc_get_ha_symtree): Let gfc_find_sym_tree lookup the parent namespace.
        * decl.c (gfc_match_data_decl): Ditto.
        (variable_decl): Remove undeclared type error.
        (gfc_match_import): Use renamed instead of original name.



testsuite/

2013-01-10  Tobias Burnus  <bur...@net-b.de>
            Mikael Morin  <mik...@gcc.gnu.org>

        PR fortran/53537
        * gfortran.dg/import2.f90: Adjust undeclared type error message.
        * gfortran.dg/import8.f90: Likewise.
        * gfortran.dg/interface_derived_type_1.f90: Likewise.
        * gfortran.dg/import10.f90: New test.
        * gfortran.dg/import11.f90: Likewise


diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index 3a36cad..4af587b 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -1981,30 +1981,6 @@ variable_decl (int elem)
       goto cleanup;
     }
 
-  /* An interface body specifies all of the procedure's
-     characteristics and these shall be consistent with those
-     specified in the procedure definition, except that the interface
-     may specify a procedure that is not pure if the procedure is
-     defined to be pure(12.3.2).  */
-  if ((current_ts.type == BT_DERIVED || current_ts.type == BT_CLASS)
-      && gfc_current_ns->proc_name
-      && gfc_current_ns->proc_name->attr.if_source == IFSRC_IFBODY
-      && current_ts.u.derived->ns != gfc_current_ns)
-    {
-      gfc_symtree *st;
-      st = gfc_find_symtree (gfc_current_ns->sym_root, 
current_ts.u.derived->name);
-      if (!(current_ts.u.derived->attr.imported
-               && st != NULL
-               && gfc_find_dt_in_generic (st->n.sym) == current_ts.u.derived)
-           && !gfc_current_ns->has_import_set)
-       {
-           gfc_error ("The type of '%s' at %C has not been declared within the 
"
-                      "interface", name);
-           m = MATCH_ERROR;
-           goto cleanup;
-       }
-    }
-    
   if (check_function_name (name) == FAILURE)
     {
       m = MATCH_ERROR;
@@ -3242,14 +3218,14 @@ gfc_match_import (void)
              return MATCH_ERROR;
            }
 
-         if (gfc_find_symtree (gfc_current_ns->sym_root,name))
+         if (gfc_find_symtree (gfc_current_ns->sym_root, name))
            {
              gfc_warning ("'%s' is already IMPORTed from host scoping unit "
                           "at %C.", name);
              goto next_item;
            }
 
-         st = gfc_new_symtree (&gfc_current_ns->sym_root, sym->name);
+         st = gfc_new_symtree (&gfc_current_ns->sym_root, name);
          st->n.sym = sym;
          sym->refs++;
          sym->attr.imported = 1;
@@ -3261,8 +3237,8 @@ gfc_match_import (void)
                 lower-case name contains the associated generic function. */
              st = gfc_new_symtree (&gfc_current_ns->sym_root,
                        gfc_get_string ("%c%s",
-                               (char) TOUPPER ((unsigned char) sym->name[0]),
-                               &sym->name[1]));
+                               (char) TOUPPER ((unsigned char) name[0]),
+                               &name[1]));
              st->n.sym = sym;
              sym->refs++;
              sym->attr.imported = 1;
@@ -4317,7 +4293,7 @@ gfc_match_data_decl (void)
        goto ok;
 
       gfc_find_symbol (current_ts.u.derived->name,
-                      current_ts.u.derived->ns->parent, 1, &sym);
+                      current_ts.u.derived->ns, 1, &sym);
 
       /* Any symbol that we find had better be a type definition
         which has its components defined.  */
diff --git a/gcc/fortran/symbol.c b/gcc/fortran/symbol.c
index dbd5132..a3a6a6c 100644
--- a/gcc/fortran/symbol.c
+++ b/gcc/fortran/symbol.c
@@ -2679,6 +2679,11 @@ gfc_find_sym_tree (const char *name, gfc_namespace *ns, 
int parent_flag,
       if (!parent_flag)
        break;
 
+      /* Don't escape an interface block.  */
+      if (ns && !ns->has_import_set
+          && ns->proc_name && ns->proc_name->attr.if_source == IFSRC_IFBODY)
+       break;
+
       ns = ns->parent;
     }
   while (ns != NULL);
@@ -2837,17 +2842,14 @@ gfc_get_ha_sym_tree (const char *name, gfc_symtree 
**result)
       return i;
     }
 
-  if (gfc_current_ns->parent != NULL)
-    {
-      i = gfc_find_sym_tree (name, gfc_current_ns->parent, 1, &st);
-      if (i)
-       return i;
+  i = gfc_find_sym_tree (name, gfc_current_ns, 1, &st);
+  if (i)
+    return i;
 
-      if (st != NULL)
-       {
-         *result = st;
-         return 0;
-       }
+  if (st != NULL)
+    {
+      *result = st;
+      return 0;
     }
 
   return gfc_get_sym_tree (name, gfc_current_ns, result, false);
diff --git a/gcc/testsuite/gfortran.dg/import2.f90 
b/gcc/testsuite/gfortran.dg/import2.f90
index d9e65e3..9db2197 100644
--- a/gcc/testsuite/gfortran.dg/import2.f90
+++ b/gcc/testsuite/gfortran.dg/import2.f90
@@ -37,7 +37,7 @@ module testmod
   interface
     subroutine other(x,y)
       import ! { dg-error "Fortran 2003: IMPORT statement" }
-      type(modType) :: y ! { dg-error "not been declared within the interface" 
}
+      type(modType) :: y ! { dg-error "is being used before it is defined" }
       real(kind)    :: x ! { dg-error "has not been declared" }
     end subroutine
   end interface
@@ -56,13 +56,13 @@ program foo
   interface
     subroutine bar(x,y)
       import ! { dg-error "Fortran 2003: IMPORT statement" }
-      type(myType) :: x ! { dg-error "not been declared within the interface" }
+      type(myType) :: x ! { dg-error "is being used before it is defined" }
       integer(dp)  :: y ! { dg-error "has not been declared" }
     end subroutine bar
     subroutine test(x)
       import :: myType3 ! { dg-error "Fortran 2003: IMPORT statement" }
       import myType3 ! { dg-error "Fortran 2003: IMPORT statement" }
-      type(myType3) :: x ! { dg-error "not been declared within the interface" 
}
+      type(myType3) :: x ! { dg-error "is being used before it is defined" }
     end subroutine test
   end interface
 
diff --git a/gcc/testsuite/gfortran.dg/import8.f90 
b/gcc/testsuite/gfortran.dg/import8.f90
index 0d88e62..543b0a1 100644
--- a/gcc/testsuite/gfortran.dg/import8.f90
+++ b/gcc/testsuite/gfortran.dg/import8.f90
@@ -12,7 +12,7 @@ end type Connection
 abstract interface
     subroutine generic_desc(self)
         ! <<< missing IMPORT 
-        class(Connection) :: self ! { dg-error "has not been declared within 
the interface" }
+        class(Connection) :: self ! { dg-error "is being used before it is 
defined" }
     end subroutine generic_desc
 end interface
 end
diff --git a/gcc/testsuite/gfortran.dg/interface_derived_type_1.f90 
b/gcc/testsuite/gfortran.dg/interface_derived_type_1.f90
index 7c165b3..efd81fd 100644
--- a/gcc/testsuite/gfortran.dg/interface_derived_type_1.f90
+++ b/gcc/testsuite/gfortran.dg/interface_derived_type_1.f90
@@ -13,7 +13,7 @@ contains
   subroutine sim_1(func1,params)
     interface
       function func1(fparams)
-        type(fcnparms) :: fparams ! { dg-error "not been declared within the 
interface" }
+        type(fcnparms) :: fparams ! { dg-error "is being used before it is 
defined" }
         real :: func1
       end function func1
     end interface


! { dg-do compile }
!
! PR fortran/53537
! The use of WP in the ODE_DERIVATIVE interface used to be rejected because
! the symbol was imported under the original name DP.
!
! Original test case from Arjen Markus <arjen.mar...@deltares.nl>

module select_precision
    integer, parameter :: dp = kind(1.0)
end module select_precision

module ode_types
    use select_precision, only: wp => dp
    implicit none
    interface
        subroutine ode_derivative(x)
            import   :: wp
            real(wp) :: x
        end subroutine ode_derivative
    end interface
end module ode_types


! { dg-do compile }
!
! PR fortran/53537
! The definition of T1 in the interface used to be rejected because T3
! was imported under the original name T1.

       MODULE MOD
         TYPE T1
           SEQUENCE
           integer :: j
         END TYPE t1
       END
       PROGRAM MAIN
         USE MOD, T3 => T1
         INTERFACE SUBR
           SUBROUTINE SUBR1(X,y)
             IMPORT :: T3
             type t1
!               sequence
!               integer :: i
             end type t1
             TYPE(T3) X
!             TYPE(T1) X
           END SUBROUTINE
         END INTERFACE SUBR
       END PROGRAM MAIN


Reply via email to