Bug 47745 - [OOP] Segfault with CLASS(*) and derived type dummy arguments
[OOP] Segfault with CLASS(*) and derived type dummy arguments
Status: RESOLVED FIXED
Product: gcc
Classification: Unclassified
Component: fortran
4.5.1
: P3 normal
: ---
Assigned To: janus
: ice-on-invalid-code
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2011-02-15 06:30 UTC by Rodney Polkinghorne
Modified: 2011-02-17 02:57 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2011-02-15 10:09:26


Attachments
This program crashes the compiler (269 bytes, application/octet-stream)
2011-02-15 06:30 UTC, Rodney Polkinghorne
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Rodney Polkinghorne 2011-02-15 06:30:33 UTC
Created attachment 23346 [details]
This program crashes the compiler

Attempting to compile the attached source, crashme.f08, does as follows.  Changing type(T) to integer, or deleting the line "add = 1", avoids the compiler crash.

% gfortran -v -c derived.f08
Using built-in specs.
COLLECT_GCC=gfortran
COLLECT_LTO_WRAPPER=/usr/local/gfortran/libexec/gcc/x86_64-apple-darwin10.3.0/4.5.1/lto-wrapper
Target: x86_64-apple-darwin10.3.0
Configured with: ../gcc-4_5-branch/configure --prefix=/usr/local/gfortran --enable-languages=c,c++,fortran --with-gmp=/Users/fx/devel/gcc/ibin45/../irun45 --enable-bootstrap --with-included-gettext --with-arch=nocona --with-tune=generic
Thread model: posix
gcc version 4.5.1 20100506 (prerelease) (GCC) 
COLLECT_GCC_OPTIONS='-mmacosx-version-min=10.6.6' '-v' '-c' '-mtune=generic' '-march=nocona'
 /usr/local/gfortran/libexec/gcc/x86_64-apple-darwin10.3.0/4.5.1/f951 derived.f08 -fPIC -quiet -dumpbase derived.f08 -mmacosx-version-min=10.6.6 -mtune=generic -march=nocona -auxbase derived -version -fintrinsic-modules-path /usr/local/gfortran/lib/gcc/x86_64-apple-darwin10.3.0/4.5.1/finclude -o /var/folders/9P/9PFGWXR+FHWaXgjuUM4v5U+++TU/-Tmp-//ccOLAgz5.s
GNU Fortran (GCC) version 4.5.1 20100506 (prerelease) (x86_64-apple-darwin10.3.0)
	compiled by GNU C version 4.5.1 20100506 (prerelease), GMP version 4.3.1, MPFR version 2.4.2-p2, MPC version 0.8.1
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
GNU Fortran (GCC) version 4.5.1 20100506 (prerelease) (x86_64-apple-darwin10.3.0)
	compiled by GNU C version 4.5.1 20100506 (prerelease), GMP version 4.3.1, MPFR version 2.4.2-p2, MPC version 0.8.1
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
derived.f08:8.23:

                class(*), intent(in) :: x
                       1
Error: Invalid character in name at (1)
f951: internal compiler error: Segmentation fault
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://gcc.gnu.org/bugs.html> for instructions.
Comment 1 Tobias Burnus 2011-02-15 06:59:53 UTC
Note: CLASS(*) -- i.e. unlimited polymorphism -- is not yet supported; however, there should be no an internal compiler error.
Comment 2 janus 2011-02-15 10:09:26 UTC
With 4.6 trunk I get:


crashme.f08:8.23:

                class(*), intent(in) :: x
                       1
Error: Invalid character in name at (1)
crashme.f08:6.29:

        class(T) function add(d, x)
                             1
Error: CLASS variable 'add' at (1) must be dummy, allocatable or pointer
f951: internal compiler error: Segmentation fault



I think the test case is actually invalid due to C407 in the Fortran 2008 standard (cf. second error message):

C407 An entity declared with the CLASS keyword shall be a dummy argument or have the ALLOCATABLE or POINTER attribute.
Comment 3 janus 2011-02-15 10:22:33 UTC
(In reply to comment #1)
> Note: CLASS(*) -- i.e. unlimited polymorphism -- is not yet supported; however,
> there should be no an internal compiler error.

Right. We definitely need a better rejection of CLASS(*). Draft patch:

Index: gcc/fortran/decl.c
===================================================================
--- gcc/fortran/decl.c	(revision 170156)
+++ gcc/fortran/decl.c	(working copy)
@@ -2613,6 +2613,16 @@ gfc_match_decl_type_spec (gfc_typespec *ts, int im
     ts->type = BT_DERIVED;
   else
     {
+      /* Match CLASS declarations.  */
+      m = gfc_match (" class ( * )");
+      if (m == MATCH_ERROR)
+	return MATCH_ERROR;
+      else if (m == MATCH_YES)
+	{
+	  gfc_fatal_error ("Unlimited polymorphism at %C not yet supported");
+	  return MATCH_ERROR;
+	}
+
       m = gfc_match (" class ( %n )", name);
       if (m != MATCH_YES)
 	return m;
Comment 4 janus 2011-02-15 10:26:40 UTC
However, the ICE itself seems unrelated to the CLASS(*) error. It still happens with the following reduction:


  type, abstract :: T 
  end type T
contains
  class(T) function add()
    add = 1
  end function
end



  class(T) function add()
                       1
Error: CLASS variable 'add' at (1) must be dummy, allocatable or pointer
f951: internal compiler error: Segmentation fault


It is correctly rejected, but then one gets an ICE (triggered by the assignment).
Comment 5 janus 2011-02-15 11:53:36 UTC
One can get rid of the ICE via these two hunks:


Index: gcc/fortran/interface.c
===================================================================
--- gcc/fortran/interface.c	(revision 170169)
+++ gcc/fortran/interface.c	(working copy)
@@ -2924,7 +2924,11 @@ matching_typebound_op (gfc_expr** tb_base,
 	gfc_try result;
 
 	if (base->expr->ts.type == BT_CLASS)
-	  derived = CLASS_DATA (base->expr)->ts.u.derived;
+	  {
+	    if (!gfc_expr_attr (base->expr).class_ok)
+	      continue;
+	    derived = CLASS_DATA (base->expr)->ts.u.derived;
+	  }
 	else
 	  derived = base->expr->ts.u.derived;
 
 Index: gcc/fortran/primary.c
===================================================================
--- gcc/fortran/primary.c	(revision 170169)
+++ gcc/fortran/primary.c	(working copy)
@@ -2033,7 +2033,7 @@ gfc_variable_attr (gfc_expr *expr, gfc_typespec *t
   sym = expr->symtree->n.sym;
   attr = sym->attr;
 
-  if (sym->ts.type == BT_CLASS)
+  if (sym->ts.type == BT_CLASS && sym->attr.class_ok)
     {
       dimension = CLASS_DATA (sym)->attr.dimension;
       pointer = CLASS_DATA (sym)->attr.class_pointer;
Comment 6 Dominique d'Humieres 2011-02-15 13:57:47 UTC
If I did not do any mistake, the patch in comment #5 breaks at least gfortran.dg/typebound_operator_6.f03:

/opt/gcc/_clean/gcc/testsuite/gfortran.dg/typebound_operator_6.f03:44.13:

      LST = (A%PT .LT. B%PT)
             1
Error: Operands of comparison operator '.lt.' at (1) are CLASS(dat)/CLASS(dat)
/opt/gcc/_clean/gcc/testsuite/gfortran.dg/typebound_operator_6.f03:52.14:

  USE NODE_MOD
              1
Fatal Error: Can't open module file 'node_mod.mod' for reading at (1): No such file or directory
Comment 7 janus 2011-02-15 15:22:10 UTC
(In reply to comment #6)
> If I did not do any mistake, the patch in comment #5 breaks at least
> gfortran.dg/typebound_operator_6.f03:

Yes, I'm seeing that too. The following should take care of it:

Index: decl.c
===================================================================
--- decl.c      (revision 170170)
+++ decl.c      (working copy)
@@ -1639,7 +1639,9 @@ scalar:
       bool delayed = (gfc_state_stack->sym == c->ts.u.derived)
                     || (!c->ts.u.derived->components
                         && !c->ts.u.derived->attr.zero_comp);
-      return gfc_build_class_symbol (&c->ts, &c->attr, &c->as, delayed);
+      c->attr.class_ok = c->attr.dummy | c->attr.pointer | c->attr.allocatable;
+      if (c->attr.class_ok)
+       return gfc_build_class_symbol (&c->ts, &c->attr, &c->as, delayed);
     }
 
   return t;


I will post a complete patch to the mailing list soon.
Comment 8 janus 2011-02-16 20:52:00 UTC
Author: janus
Date: Wed Feb 16 20:51:56 2011
New Revision: 170223

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

	PR fortran/47745
	* class.c (gfc_build_class_symbol): Set 'class_ok' attribute.
	* decl.c (build_sym,attr_decl1): Move setting of 'class_ok' into
	'gfc_build_class_symbol'.
	(gfc_match_decl_type_spec): Reject unlimited polymorphism.
	* interface.c (matching_typebound_op): Check for 'class_ok' attribute.
	* match.c (select_type_set_tmp): Move setting of 'class_ok' into
	'gfc_build_class_symbol'.
	* primary.c (gfc_variable_attr): Check for 'class_ok' attribute.

2011-02-16  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/47745
	* gfortran.dg/class_39.f03: New.

Added:
    trunk/gcc/testsuite/gfortran.dg/class_39.f03
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/class.c
    trunk/gcc/fortran/decl.c
    trunk/gcc/fortran/interface.c
    trunk/gcc/fortran/match.c
    trunk/gcc/fortran/primary.c
    trunk/gcc/testsuite/ChangeLog
Comment 9 janus 2011-02-16 20:53:58 UTC
Fixed with r170223. Closing.

Thanks for the report, Rodney!
Comment 10 rodneyp 2011-02-17 00:48:38 UTC
> Thanks for the report, Rodney!

Thanks for working so hard on the compiler.

I'm learning Fortran 03 and 08 at the moment, so I'm likely to compile
a lot of invalid code.  Should I report a bug every time gfortran
accepts code it should reject, or try to pick the serious ones?
Comment 11 kargl 2011-02-17 02:57:08 UTC
(In reply to comment #10)
> 
> I'm learning Fortran 03 and 08 at the moment, so I'm likely to compile
> a lot of invalid code.  Should I report a bug every time gfortran
> accepts code it should reject, or try to pick the serious ones?

Yes, report bugs.  This includes gfortran accepting
invalid code, crashing on valid code, crashing on 
invalid code.  Bugs, that go unreported, can't be
fixed.