Bug 56284 - [OOP] ICE with alternate return in type-bound procedure
Summary: [OOP] ICE with alternate return in type-bound procedure
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.7.2
: P3 normal
Target Milestone: 4.9.0
Assignee: janus
URL:
Keywords: ice-on-valid-code
Depends on:
Blocks:
 
Reported: 2013-02-11 08:58 UTC by Arjen Markus
Modified: 2016-11-16 15:37 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2013-02-11 00:00:00


Attachments
Code that causes the compiler to fail (317 bytes, text/plain)
2013-02-11 08:58 UTC, Arjen Markus
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Arjen Markus 2013-02-11 08:58:39 UTC
Created attachment 29414 [details]
Code that causes the compiler to fail

The attached code causes an ICE in gfortran 4.7.2 (and 4.7.1) on Windows 7.
The fact that the routine is contained in a derived type is essential for the 
occurrence of the ICE.

On my system there is just the message that an ICE occurred, if I comment out 
the lines "contains" and "procedure :: getRecord", then the compiler rightly 
complains about the mistake in the getRecord routine.
Comment 1 Arjen Markus 2013-02-11 09:01:29 UTC
Correcting the mistakes still causes an ICE
Comment 2 janus 2013-02-11 09:51:39 UTC
Reduced test case:

module try_this
    implicit none

    type :: table_t
    contains
        procedure, nopass :: getRecord
    end type

contains

  subroutine getRecord ( * )
  end subroutine

end module


ICEs with 4.6, 4.7 and trunk. Backtrace:

f951: internal compiler error: Segmentation fault
0xb0f2cd crash_signal
        /home/jweil/gcc48/trunk/gcc/toplev.c:332
0x57d360 compare_type_rank
        /home/jweil/gcc48/trunk/gcc/fortran/interface.c:522
0x57e327 check_dummy_characteristics
        /home/jweil/gcc48/trunk/gcc/fortran/interface.c:1027
0x57f25d gfc_compare_interfaces(gfc_symbol*, gfc_symbol*, char const*, int, int, char*, int, char const*, char const*)
        /home/jweil/gcc48/trunk/gcc/fortran/interface.c:1424
0x5d7600 resolve_structure_cons
        /home/jweil/gcc48/trunk/gcc/fortran/resolve.c:1221
0x5eb85f resolve_values
        /home/jweil/gcc48/trunk/gcc/fortran/resolve.c:10461
0x611b53 do_traverse_symtree
        /home/jweil/gcc48/trunk/gcc/fortran/symbol.c:3448
0x611c1f gfc_traverse_ns(gfc_namespace*, void (*)(gfc_symbol*))
        /home/jweil/gcc48/trunk/gcc/fortran/symbol.c:3473
0x5f663c resolve_types
        /home/jweil/gcc48/trunk/gcc/fortran/resolve.c:14913
0x5f69a0 gfc_resolve(gfc_namespace*)
        /home/jweil/gcc48/trunk/gcc/fortran/resolve.c:14995
0x5ce423 gfc_parse_file()
        /home/jweil/gcc48/trunk/gcc/fortran/parse.c:4608
0x61adcd gfc_be_parse_file
        /home/jweil/gcc48/trunk/gcc/fortran/f95-lang.c:189
Comment 3 janus 2013-02-11 10:09:39 UTC
(In reply to comment #2)
> 
>   subroutine getRecord ( * )
>   end subroutine

Ok, I admit that I had to look up the asterisk thingy. It's called "alternate return" and is a obsolescent feature since at least F95.

According to PR 40881, we should have a warning message for this, but it does not seem to trigger for the test case here. Should be fixed I guess (just as the ICE, although combining obsolescent features like alternate return with new stuff such as type binding is surely not recommended).
Comment 4 janus 2013-02-11 12:17:34 UTC
The following fixes the ICE:

Index: gcc/fortran/interface.c
===================================================================
--- gcc/fortran/interface.c	(revision 195915)
+++ gcc/fortran/interface.c	(working copy)
@@ -1023,6 +1023,9 @@ static gfc_try
 check_dummy_characteristics (gfc_symbol *s1, gfc_symbol *s2,
 			     bool type_must_agree, char *errmsg, int err_len)
 {
+  if (s1 == NULL || s2 == NULL)
+    return s1 == s2 ? SUCCESS : FAILURE;
+
   /* Check type and rank.  */
   if (type_must_agree && !compare_type_rank (s2, s1))
     {
Comment 5 janus 2013-02-11 12:36:46 UTC
... and this adds a warning about the obsolescent alternate return argument (with -std=f2003 or f2008):


Index: gcc/fortran/decl.c
===================================================================
--- gcc/fortran/decl.c	(revision 195915)
+++ gcc/fortran/decl.c	(working copy)
@@ -4487,7 +4487,15 @@ gfc_match_formal_arglist (gfc_symbol *progname, in
   for (;;)
     {
       if (gfc_match_char ('*') == MATCH_YES)
-	sym = NULL;
+	{
+	  sym = NULL;
+	  if (gfc_notify_std (GFC_STD_F95_OBS, "Alternate return argument "
+			      "at %C") == FAILURE)
+	    {
+	      m = MATCH_ERROR;
+	      goto cleanup;
+	    }
+	}
       else
 	{
 	  m = gfc_match_name (name);


Also: Mine.
Comment 6 janus 2013-02-11 13:57:36 UTC
The combined patches of comment 4 and 5 yield the following testsuite failures:

FAIL: gfortran.dg/altreturn_2.f90  -O  (test for excess errors)
FAIL: gfortran.dg/intrinsic_actual_3.f90  -O  (test for excess errors)
FAIL: gfortran.dg/invalid_interface_assignment.f90  -O  (test for excess errors)

(all of them are clearly due to comment 5)
Comment 7 Dominique d'Humieres 2013-02-11 19:06:10 UTC
> The combined patches of comment 4 and 5 yield the following testsuite failures:
>
> FAIL: gfortran.dg/altreturn_2.f90  -O  (test for excess errors)
> FAIL: gfortran.dg/intrinsic_actual_3.f90  -O  (test for excess errors)
> FAIL: gfortran.dg/invalid_interface_assignment.f90  -O  (test for excess
> errors)

These tests are complied with -pedantic-errors and after the patch in comment #5,
their compilation gives the corresponding warning:

Warning: Obsolescent feature: Alternate return argument at (1)

The tests pass with the following patch

--- /opt/gcc/_clean/gcc/testsuite/gfortran.dg/invalid_interface_assignment.f90	2010-02-10 17:54:15.000000000 +0100
+++ /opt/gcc/work/gcc/testsuite/gfortran.dg/invalid_interface_assignment.f90	2013-02-11 19:57:39.000000000 +0100
@@ -12,8 +12,9 @@ MODULE TT
    MODULE PROCEDURE set
  END INTERFACE
 CONTAINS
-  PURE SUBROUTINE set(x1,*) ! { dg-error "Alternate return cannot appear" }
+  PURE SUBROUTINE set(x1,*) ! { dg-warning "Obsolescent feature: Alternate return argument" }
     TYPE(data_type), INTENT(OUT) :: x1
     x1%i=0
   END SUBROUTINE set
 END MODULE
+! { dg-error "Alternate return cannot appear" "" { target *-*-* } 15 }
--- /opt/gcc/_clean/gcc/testsuite/gfortran.dg/intrinsic_actual_3.f90	2009-11-25 18:17:42.000000000 +0100
+++ /opt/gcc/work/gcc/testsuite/gfortran.dg/intrinsic_actual_3.f90	2013-02-11 19:50:13.000000000 +0100
@@ -6,7 +6,7 @@
 !
 program ar1
     interface random_seed
-      subroutine x (a, *)
+      subroutine x (a, *) ! { dg-warning "Obsolescent feature: Alternate return argument" }
         integer a
       end subroutine x
     end interface random_seed
--- /opt/gcc/_clean/gcc/testsuite/gfortran.dg/altreturn_2.f90	2009-11-25 18:17:47.000000000 +0100
+++ /opt/gcc/work/gcc/testsuite/gfortran.dg/altreturn_2.f90	2013-02-11 19:48:14.000000000 +0100
@@ -2,7 +2,7 @@
        program altreturn_2
          call foo()  ! { dg-error "Missing alternate return" }
        contains
-         subroutine foo(*)
+         subroutine foo(*) ! { dg-warning "Obsolescent feature: Alternate return argument" }
            return
          end subroutine
        end program

I don't know if it is the RIGHT fix, but at least it works (tested with

make -k check-gfortran RUNTESTFLAGS="dg.exp=invalid_interface_assignment.f90 --target_board=unix'{-m32,-m64}'"

and so on for the other two cases.
Comment 8 janus 2013-02-11 19:46:15 UTC
(In reply to comment #7)
> I don't know if it is the RIGHT fix, but at least it works (tested with

Yes, that's fine. Or one could just disable the errors with

! { dg-options "-std=legacy" }

in all three cases. Thought I had posted that already ...
Comment 9 Dominique d'Humieres 2013-02-12 12:57:55 UTC
Do you understand why the test in gfc_match_return (file match.c)

  if (gfc_notify_std (GFC_STD_F95_OBS, "Alternate RETURN "
                      "at %C") == FAILURE)
    return MATCH_ERROR;

is not used?

Note that the error is slightly different to the one used in comment #5.

Otherwise the patches fix this PR without regression. Thanks.
Comment 10 janus 2013-02-12 13:31:22 UTC
(In reply to comment #9)
> Do you understand why the test in gfc_match_return (file match.c)
> 
>   if (gfc_notify_std (GFC_STD_F95_OBS, "Alternate RETURN "
>                       "at %C") == FAILURE)
>     return MATCH_ERROR;
> 
> is not used?

Yeah. The reason is that this one only triggers on an actual RETURN statement, but not if an unused alt-return argument is declared (as e.g. in comment 2).


> Note that the error is slightly different to the one used in comment #5.

Yes, I did that on purpose, since both warn for slightly different things: The former for an ('alternate') RETURN statement and the latter for an alternate-return dummy argument.

In fact one could think about removing the error message in gfc_match_return and only keeping the one in gfc_match_formal_arglist. After all it makes no sense to have an alternate RETURN statement without an alternate-return dummy. However, since gfortran only gives a warning for this case(*), I think it does not hurt to keep both error messages.


(*) "Warning: An alternate return at (1) without a * dummy argument"
Comment 11 janus 2013-04-03 07:51:18 UTC
Fixed with this commit:

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

2013-04-03  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/56284
	PR fortran/40881
	* decl.c (gfc_match_formal_arglist): Warn about alternate-return
	arguments.
	* interface.c (check_dummy_characteristics): Return if symbols are NULL.

2013-04-03  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/56284
	PR fortran/40881
	* gfortran.dg/altreturn_8.f90: New.
	* gfortran.dg/altreturn_2.f90: Add -std=legacy.
	* gfortran.dg/intrinsic_actual_3.f90: Ditto.
	* gfortran.dg/invalid_interface_assignment.f90: Ditto.



Closing.