Bug 49112 - [4.6/4.7 Regression] [OOP] Missing type-bound procedure, "duplicate save" warnings and internal compiler error
Summary: [4.6/4.7 Regression] [OOP] Missing type-bound procedure, "duplicate save" war...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.6.1
: P4 major
Target Milestone: 4.6.2
Assignee: janus
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-05-22 16:12 UTC by John
Modified: 2011-08-05 17:06 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2011-05-28 10:31:09


Attachments
Test case (435 bytes, text/plain)
2011-05-22 16:15 UTC, John
Details
Test case for ICE (356 bytes, text/plain)
2011-05-22 16:16 UTC, John
Details

Note You need to log in before you can comment on or make changes to this bug.
Description John 2011-05-22 16:12:34 UTC
When I compile the following module:

module datetime_mod
    implicit none
    private
    save

    type, public :: DateTime
        integer :: year = 0, month = 0, day = 0, hh = 0, mm = 0, ss = 0, &
                   sss = 0
    contains
        procedure :: getString
        procedure :: getDateString
        procedure :: getTimeString
        procedure, private :: getFormattedString
    end type

    type(DateTime), parameter :: &                                      !***
        ISO_REFERENCE_DATE = DateTime(1875, 5, 20, 0, 0, 0, 0), &       !***
        GREGORIAN_REFERENCE_DATE = DateTime(1582, 10, 15, 0, 0, 0, 0)   !***

contains
    function getString(dt, FMT) result(string)
        character(:), allocatable :: string
        class(DateTime), intent(IN) :: dt
        integer, optional, intent(IN) :: FMT
    continue
        string = dt%getFormattedString(0, FMT)
    end function 

    function getDateString(dt, FMT) result(string)
        character(:), allocatable :: string
        class(DateTime), intent(IN) :: dt
        integer, optional, intent(IN) :: FMT
    continue
        string = dt%getFormattedString(1, FMT)
    end function 

    function getTimeString(dt, FMT) result(string)
        character(:), allocatable :: string
        class(DateTime), intent(IN) :: dt
        integer, optional, intent(IN) :: FMT
    continue
        string = dt%getFormattedString(2, FMT)
    end function 

    elemental function getFormattedString(this, FILTER, FMT) &
        result(string)
        character(:), allocatable :: string
        class(DateTime), intent(IN) :: this
        integer, optional, intent(IN) :: FILTER, FMT
    continue
        string = ''
    end function
end module datetime_mod



gfortran does not recognize getFormattedString as a type-bound procedure.  There are also errors related to the use of a deferred-length character as a function result (reported as Bug 49110), and an unnecessary warning about the duplicate save attribute.  The exact output is:

...:~$ gfortran -c  test_gfortran_missing_tbp.f90 
test_gfortran_missing_tbp.f90:27.38:

        string = dt%getFormattedString(0, FMT)
                                      1
Error: 'getformattedstring' at (1) is not a member of the 'datetime' structure
test_gfortran_missing_tbp.f90:35.38:

        string = dt%getFormattedString(1, FMT)
                                      1
Error: 'getformattedstring' at (1) is not a member of the 'datetime' structure
test_gfortran_missing_tbp.f90:43.38:

        string = dt%getFormattedString(2, FMT)
                                      1
Error: 'getformattedstring' at (1) is not a member of the 'datetime' structure
test_gfortran_missing_tbp.f90:46.4:

    elemental function getFormattedString(dt, FILTER, FMT) &
    1
Error: CHARACTER(*) function 'getformattedstring' at (1) cannot be pure
test_gfortran_missing_tbp.f90:46.4:

    elemental function getFormattedString(dt, FILTER, FMT) &
    1
Error: CHARACTER(*) function 'getformattedstring' at (1) cannot be pure
test_gfortran_missing_tbp.f90:46.4:

    elemental function getFormattedString(dt, FILTER, FMT) &
    1
Error: CHARACTER(*) function 'getformattedstring' at (1) cannot be pure
test_gfortran_missing_tbp.f90:18.62:

        ISO_REFERENCE_DATE = DateTime(1875, 5, 20, 0, 0, 0, 0), &       !***
                                                              1
Warning: Duplicate SAVE attribute specified at (1)
test_gfortran_missing_tbp.f90:18.62:

        ISO_REFERENCE_DATE = DateTime(1875, 5, 20, 0, 0, 0, 0), &       !***
                                                              1
Warning: Duplicate SAVE attribute specified at (1)



If I remove the three lines marked with "!***" and also remove the ELEMENTAL attribute from the getFormattedString function, and compile again, then I get an internal compiler error:

...:~$ gfortran -c  test_gfortran_ice.f90 
test_gfortran_ice.f90:20.41:

        class(DateTime), intent(IN) :: dt
                                         1
Warning: Duplicate SAVE attribute specified at (1)
test_gfortran_ice.f90:20.41:

        class(DateTime), intent(IN) :: dt
                                         1
Warning: Duplicate SAVE attribute specified at (1)
test_gfortran_ice.f90: In function ‘gettimestring’:
test_gfortran_ice.f90:41:0: internal compiler error: in fold_convert_loc, at fold-const.c:1906
Please submit a full bug report,
with preprocessed source if appropriate.
See <file:///usr/share/doc/gcc-4.6/README.Bugs> for instructions




The version information is:

...:~$ gfortran -v
Using built-in specs.
COLLECT_GCC=gfortran
COLLECT_LTO_WRAPPER=/usr/lib/x86_64-linux-gnu/gcc/x86_64-linux-gnu/4.6.1/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.6.0-3~ppa1'
--with-bugurl=file:///usr/share/doc/gcc-4.6/README.Bugs
--enable-languages=c,c++,fortran,objc,obj-c++,go --prefix=/usr
--program-suffix=-4.6 --enable-shared --enable-multiarch
--with-multiarch-defaults=x86_64-linux-gnu --enable-linker-build-id
--with-system-zlib --libexecdir=/usr/lib/x86_64-linux-gnu
--without-included-gettext --enable-threads=posix
--with-gxx-include-dir=/usr/include/c++/4.6 --libdir=/usr/lib/x86_64-linux-gnu
--enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug
--enable-libstdcxx-time=yes --enable-plugin --enable-objc-gc --disable-werror
--with-arch-32=i686 --with-tune=generic --enable-checking=release
--build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.6.1 20110409 (prerelease) (Ubuntu 4.6.0-3~ppa1) 


The system information (for Ubuntu 11.04) is:

...:~$ uname -srvmpio
Linux 2.6.38-8-generic #42-Ubuntu SMP Mon Apr 11 03:31:24 UTC 2011 x86_64
x86_64 x86_64 GNU/Linux
Comment 1 John 2011-05-22 16:15:24 UTC
Created attachment 24329 [details]
Test case
Comment 2 John 2011-05-22 16:16:25 UTC
Created attachment 24330 [details]
Test case for ICE
Comment 3 janus 2011-05-22 17:26:49 UTC
(In reply to comment #0)
> ...:~$ gfortran -c  test_gfortran_ice.f90 
> test_gfortran_ice.f90:20.41:
> 
>         class(DateTime), intent(IN) :: dt
>                                          1
> Warning: Duplicate SAVE attribute specified at (1)
> test_gfortran_ice.f90:20.41:
> 
>         class(DateTime), intent(IN) :: dt
>                                          1
> Warning: Duplicate SAVE attribute specified at (1)


Here is a reduced test case for the duplicate SAVE attribute:


module datetime_mod

    implicit none
    save

    type :: DateTime
    end type

contains

    character function getString (dt)
        class(DateTime) :: dt
    end function 

end module


At first glance I would save this is invalid, and should be rejected with an error. In particular, is it allowed to give a lonely SAVE statement? If yes, what effect should this have? Usually SAVE is specified as an attribute for a specific variable, right?
Comment 4 John 2011-05-22 17:58:39 UTC
(In reply to comment #3)
> (In reply to comment #0)
> > ...:~$ gfortran -c  test_gfortran_ice.f90 
> > test_gfortran_ice.f90:20.41:
> > 
> >         class(DateTime), intent(IN) :: dt
> >                                          1
> > Warning: Duplicate SAVE attribute specified at (1)
> > test_gfortran_ice.f90:20.41:
> > 
> >         class(DateTime), intent(IN) :: dt
> >                                          1
> > Warning: Duplicate SAVE attribute specified at (1)
> 
> 
> Here is a reduced test case for the duplicate SAVE attribute:
> 
> 
> module datetime_mod
> 
>     implicit none
>     save
> 
>     type :: DateTime
>     end type
> 
> contains
> 
>     character function getString (dt)
>         class(DateTime) :: dt
>     end function 
> 
> end module
> 
> 
> At first glance I would save this is invalid, and should be rejected with an
> error. In particular, is it allowed to give a lonely SAVE statement? If yes,
> what effect should this have? Usually SAVE is specified as an attribute for a
> specific variable, right?

SAVE can be either a statement or an attribute.  When it's statement, it affects all the variables within the containing unit (e.g., in the case of a module, it affects all the variables declared before the "contains").  When it's the attribute for a particular variable declaration, it affects the variable only.

Since in Fortran initialization implies SAVE, and the ISO_REFERENCE_DATE is being (sort of) initialized, the compiler is assuming a duplicate SAVE.

The standard also allows the confirmation, as an attribute, of the SAVE at the module level, so, for a "triple save" example:

module t1_mod
    save

    type :: t1
        integer :: dummy = 0
    end type

    type(t1), save :: a = t1(2), b = t1(3)
end type


Which also triggers a duplicate save warning.
Comment 5 janus 2011-05-28 10:03:36 UTC
(In reply to comment #4)
> SAVE can be either a statement or an attribute.  When it's statement, it
> affects all the variables within the containing unit

Yes, of course. I completely forgot about this possibility.

Btw, the code in comment #3 works with gfortran 4.5, so it is in fact a regression.


> The standard also allows the confirmation, as an attribute, of the SAVE at the
> module level, so, for a "triple save" example:
> 
> module t1_mod
>     save
> 
>     type :: t1
>         integer :: dummy = 0
>     end type
> 
>     type(t1), save :: a = t1(2), b = t1(3)
> end type
> 
> 
> Which also triggers a duplicate save warning.

This is at best a "double save", and I think the (F08) standard forbids it:

C580 (R553) If a SAVE statement with an omitted saved entity list appears in a scoping unit, no other appearance of the SAVE attr-spec or SAVE statement is permitted in that scoping unit.

So I think in this case gfortran correctly complains about a "Duplicate SAVE attribute".
Comment 6 janus 2011-05-28 10:31:09 UTC
(In reply to comment #0)
> ...:~$ gfortran -c  test_gfortran_missing_tbp.f90 
> test_gfortran_missing_tbp.f90:27.38:
> 
>         string = dt%getFormattedString(0, FMT)
>                                       1
> Error: 'getformattedstring' at (1) is not a member of the 'datetime' structure

Here is a reduced test case for this error, which is also a regression:


module datetime_mod

    implicit none

    type :: DateTime
        integer :: year, month, day
    contains
        procedure :: getFormattedString
    end type

    type(DateTime) :: ISO_REFERENCE_DATE = DateTime(1875, 5, 20)

contains

    character function getString(dt)
        class(DateTime) :: dt
        getString = dt%getFormattedString()
    end function 

    character function getFormattedString(dt)
        class(DateTime) :: dt
    end function

end module
Comment 7 janus 2011-05-28 10:53:18 UTC
Here is a reduced test case for the ICE:


module datetime_mod

    implicit none
    private

    type :: DateTime
    contains
        procedure :: getFormattedString
    end type

contains

    function getTimeString(dt, FMT) result(string)
        character(:), allocatable :: string
        class(DateTime), intent(IN) :: dt
        integer, optional, intent(IN) :: FMT

        string = dt%getFormattedString(2, FMT)
    end function 

    function getFormattedString(this, FILTER, FMT) &
        result(string)
        character(:), allocatable :: string
        class(DateTime), intent(IN) :: this
        integer, optional, intent(IN) :: FILTER, FMT

    end function

end module
Comment 8 John 2011-05-28 16:28:15 UTC
(In reply to comment #5)
> (In reply to comment #4)
> > SAVE can be either a statement or an attribute.  When it's statement, it
> > affects all the variables within the containing unit
> 
> Yes, of course. I completely forgot about this possibility.
> 
> Btw, the code in comment #3 works with gfortran 4.5, so it is in fact a
> regression.
> 
> 
> > The standard also allows the confirmation, as an attribute, of the SAVE at the
> > module level, so, for a "triple save" example:
> > 
> > module t1_mod
> >     save
> > 
> >     type :: t1
> >         integer :: dummy = 0
> >     end type
> > 
> >     type(t1), save :: a = t1(2), b = t1(3)
> > end type

Sorry, it should have been "end module"

> > 
> > 
> > Which also triggers a duplicate save warning.
> 
> This is at best a "double save", and I think the (F08) standard forbids it:
> 
> C580 (R553) If a SAVE statement with an omitted saved entity list appears in a
> scoping unit, no other appearance of the SAVE attr-spec or SAVE statement is
> permitted in that scoping unit.
> t
> So I think in this case gfortran correctly complains about a "Duplicate SAVE
> attribute".

Ups... I completely forgot about that constraint (I must have been thinking about section 5.3.16, which mentions an implicit SAVE statement for modules, and that one can be explicitly confirmed).  So yes, it's at best an extension to the standard.  Intel's and Sun's compilers complain about it:

...:~$ ifort -stand -c t1.f90 
t1.f90(8): warning #7652: The F2003 standard says that the SAVE attribute is invalid since there is an occurrence of a SAVE statement with an omitted save-entity-list in the same scoping unit.   [SAVE]
    type(t1), save :: a = t1(2), b = t1(3)

...:~$ sunf95 -ansi -c t1.f90 

    type(t1), save :: a = t1(2), b = t1(3)
              ^                            
"t1.f90", Line = 8, Column = 15: ANSI: The Fortran standard requires a SAVE statement with no saved-entity-list to be the only SAVE in the scoping unit.



One thing about the original code, is that the "duplicate save" warning is being issued for an entity with the PARAMETER attribute ---so the SAVE at the scoping unit shouldn't even affect it, since the entity is not really a variable.
Comment 9 janus 2011-05-30 19:28:52 UTC
(In reply to comment #3)
> Here is a reduced test case for the duplicate SAVE attribute:

The duplicate SAVE warning of comment #3 can be fixed with something like this:


Index: gcc/fortran/symbol.c
===================================================================
--- gcc/fortran/symbol.c        (revision 174416)
+++ gcc/fortran/symbol.c        (working copy)
@@ -3400,7 +3400,8 @@ save_symbol (gfc_symbol *sym)
   if (sym->attr.in_common
       || sym->attr.dummy
       || sym->attr.result
-      || sym->attr.flavor != FL_VARIABLE)
+      || sym->attr.flavor != FL_VARIABLE
+      || (sym->name[0]=='_' && sym->name[1]=='_'))
     return;
   /* Automatic objects are not saved.  */
   if (gfc_is_var_automatic (sym))


This prevents 'internal' symbols, starting with '__', from getting a SAVE attribute twice.
Comment 10 janus 2011-05-30 20:09:18 UTC
(In reply to comment #6)
> > 
> >         string = dt%getFormattedString(0, FMT)
> >                                       1
> > Error: 'getformattedstring' at (1) is not a member of the 'datetime' structure
> 
> Here is a reduced test case for this error, which is also a regression:

... probably due to my r163631:

http://gcc.gnu.org/viewcvs?view=revision&revision=163631


It can be fixed by this partial revert:

===================================================================
--- gcc/fortran/resolve.c	(revision 174415)
+++ gcc/fortran/resolve.c	(working copy)
@@ -964,9 +964,6 @@ resolve_structure_cons (gfc_expr *expr, int init)
 
   t = SUCCESS;
 
-  if (expr->ts.type == BT_DERIVED)
-    resolve_symbol (expr->ts.u.derived);
-
   cons = gfc_constructor_first (expr->value.constructor);
   /* A constructor may have references if it is the result of substituting a
      parameter variable.  In this case we just pull out the component we
Comment 11 janus 2011-06-20 19:55:54 UTC
(In reply to comment #10)
> It can be fixed by this partial revert:
> 
> ===================================================================
> --- gcc/fortran/resolve.c    (revision 174415)
> +++ gcc/fortran/resolve.c    (working copy)
> @@ -964,9 +964,6 @@ resolve_structure_cons (gfc_expr *expr, int init)
> 
>    t = SUCCESS;
> 
> -  if (expr->ts.type == BT_DERIVED)
> -    resolve_symbol (expr->ts.u.derived);
> -
>    cons = gfc_constructor_first (expr->value.constructor);
>    /* A constructor may have references if it is the result of substituting a
>       parameter variable.  In this case we just pull out the component we


Unfortunately this patchlet seems to induce the following testsuite regressions:

FAIL: gfortran.dg/func_assign_3.f90  -O0  (test for excess errors)
FAIL: gfortran.dg/func_result_6.f90  -O0  (test for excess errors)
FAIL: gfortran.dg/typebound_call_7.f03  -O  (test for excess errors)
FAIL: gfortran.dg/typebound_call_8.f03  -O  (test for excess errors)


The patch in comment #9, however, seems to be clean.
Comment 12 janus 2011-06-21 12:12:58 UTC
Author: janus
Date: Tue Jun 21 12:12:51 2011
New Revision: 175257

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=175257
Log:
2011-06-21  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/49112
	* class.c (gfc_find_derived_vtab): Make vtab and default initialization
	symbols SAVE_IMPLICIT.

2011-06-21  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/49112
	* gfortran.dg/class_44.f03: New.

Added:
    trunk/gcc/testsuite/gfortran.dg/class_44.f03
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/class.c
    trunk/gcc/testsuite/ChangeLog
Comment 13 janus 2011-06-21 12:20:33 UTC
Author: janus
Date: Tue Jun 21 12:20:28 2011
New Revision: 175259

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=175259
Log:
2011-06-21  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/49112
	* class.c (gfc_find_derived_vtab): Make vtab and default initialization
	symbols SAVE_IMPLICIT.

2011-06-21  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/49112
	* gfortran.dg/class_44.f03: New.

Added:
    branches/gcc-4_6-branch/gcc/testsuite/gfortran.dg/class_44.f03
Modified:
    branches/gcc-4_6-branch/gcc/fortran/ChangeLog
    branches/gcc-4_6-branch/gcc/fortran/class.c
    branches/gcc-4_6-branch/gcc/testsuite/ChangeLog
Comment 14 janus 2011-06-21 12:26:44 UTC
The "duplicate save" regression is fixed on trunk and 4.6. Remaining problems:

1) The structure constructor regression in comment #6.
2) The ICE in comment #7.
Comment 15 Jakub Jelinek 2011-06-27 12:33:00 UTC
GCC 4.6.1 is being released.
Comment 16 janus 2011-06-27 17:45:29 UTC
(In reply to comment #14)
> The "duplicate save" regression is fixed on trunk and 4.6. Remaining problems:
> 
> 1) The structure constructor regression in comment #6.
> 2) The ICE in comment #7.

The latter is tracked by the related PR49430, so for this PR only the regression in comment #6 is left to fix.
Comment 17 Tobias Burnus 2011-07-27 19:52:25 UTC
Janus, this regression (comment 6 remains to be done) is assigned to you. Are you still working on it?
Comment 18 janus 2011-07-27 21:56:36 UTC
(In reply to comment #17)
> Janus, this regression (comment 6 remains to be done) is assigned to you. Are
> you still working on it?

Well, at least it's on my (unfortunately long) to-do list. I'll try to find some time for it on the weekend.

After all it seems like I'm the one who is to blame for this regression, cf. comment #10 and #11.
Comment 19 janus 2011-07-31 10:25:11 UTC
Author: janus
Date: Sun Jul 31 10:25:07 2011
New Revision: 176971

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=176971
Log:
2011-07-31  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/49112
	* resolve.c (resolve_structure_cons): Don't do the full dt resolution,
	only call 'resolve_fl_derived0'.
	(resolve_typebound_procedures): Resolve typebound procedures of
	parent type.
	(resolve_fl_derived0): New function, which does a part of the work
	for 'resolve_fl_derived'.
	(resolve_fl_derived): Call 'resolve_fl_derived0' and do some additional
	things.


2011-07-31  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/49112
	* gfortran.dg/abstract_type_6.f03: Modified.
	* gfortran.dg/typebound_proc_24.f03: New.

Added:
    trunk/gcc/testsuite/gfortran.dg/typebound_proc_24.f03
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/resolve.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/gfortran.dg/abstract_type_6.f03
Comment 20 janus 2011-08-05 17:03:54 UTC
Author: janus
Date: Fri Aug  5 17:03:50 2011
New Revision: 177468

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=177468
Log:
2011-08-05  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/49112
	* resolve.c (resolve_structure_cons): Don't do the full dt resolution,
	only call 'resolve_fl_derived0'.
	(resolve_typebound_procedures): Resolve typebound procedures of
	parent type.
	(resolve_fl_derived0): New function, which does a part of the work
	for 'resolve_fl_derived'.
	(resolve_fl_derived): Call 'resolve_fl_derived0' and do some additional
	things.


2011-08-05  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/49112
	* gfortran.dg/abstract_type_6.f03: Modified.
	* gfortran.dg/typebound_proc_24.f03: New.

Added:
    branches/gcc-4_6-branch/gcc/testsuite/gfortran.dg/typebound_proc_24.f03
Modified:
    branches/gcc-4_6-branch/gcc/fortran/ChangeLog
    branches/gcc-4_6-branch/gcc/fortran/resolve.c
    branches/gcc-4_6-branch/gcc/testsuite/ChangeLog
    branches/gcc-4_6-branch/gcc/testsuite/gfortran.dg/abstract_type_6.f03
Comment 21 janus 2011-08-05 17:06:26 UTC
The regression of comment #6 has been fixed on 4.6 and trunk.

Since this was the last item in this PR, I'm closing it as fixed.