Bug 55960 - [OOP] ICE in replace_comp, at fortran/expr.c:4356
Summary: [OOP] ICE in replace_comp, at fortran/expr.c:4356
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.8.0
: P3 normal
Target Milestone: 4.9.0
Assignee: Not yet assigned to anyone
URL:
Keywords: ice-on-valid-code
Depends on:
Blocks:
 
Reported: 2013-01-13 10:13 UTC by janus
Modified: 2016-11-16 15:34 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2013-01-19 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description janus 2013-01-13 10:13:52 UTC
Reported at http://gcc.gnu.org/ml/fortran/2013-01/msg00109.html.

Reduced test case:

module pdfs
  type, abstract :: pdf
  contains
    procedure(getdims), deferred :: getdims
    procedure(getx), deferred :: getx
  end type pdf

  abstract interface
    pure function getdims(this)
      import pdf
      class(pdf), intent(in) :: this
      integer getdims
    end function getdims

    pure function getx(this)
      import pdf
      class(pdf), intent(in) :: this
      real, dimension(getdims(this)) :: getx
    end function getx
  end interface

end module pdfs


Yields the ICE:

f951: internal compiler error: in replace_comp, at fortran/expr.c:4356
0x57af34 replace_comp
        /home/jweil/gcc48/trunk/gcc/fortran/expr.c:4356
0x57a3a5 gfc_traverse_expr(gfc_expr*, gfc_symbol*, bool (*)(gfc_expr*, gfc_symbol*, int*), int)
        /home/jweil/gcc48/trunk/gcc/fortran/expr.c:4073
0x57afa5 gfc_expr_replace_comp(gfc_expr*, gfc_component*)
        /home/jweil/gcc48/trunk/gcc/fortran/expr.c:4366
0x5f0c77 resolve_fl_derived0
        /home/jweil/gcc48/trunk/gcc/fortran/resolve.c:12622
0x5f1d9e resolve_fl_derived
        /home/jweil/gcc48/trunk/gcc/fortran/resolve.c:12961
0x5f296a resolve_symbol
        /home/jweil/gcc48/trunk/gcc/fortran/resolve.c:13229
0x611e1a do_traverse_symtree
        /home/jweil/gcc48/trunk/gcc/fortran/symbol.c:3449
0x611ee6 gfc_traverse_ns(gfc_namespace*, void (*)(gfc_symbol*))
        /home/jweil/gcc48/trunk/gcc/fortran/symbol.c:3474
0x5f68db resolve_types
        /home/jweil/gcc48/trunk/gcc/fortran/resolve.c:14889
0x5f6d28 gfc_resolve(gfc_namespace*)
        /home/jweil/gcc48/trunk/gcc/fortran/resolve.c:14989
0x5ce730 gfc_parse_file()
        /home/jweil/gcc48/trunk/gcc/fortran/parse.c:4603
0x61b4c1 gfc_be_parse_file
        /home/jweil/gcc48/trunk/gcc/fortran/f95-lang.c:189
Comment 1 janus 2013-01-13 10:32:08 UTC
With this variant:

module pdfs
  type :: pdf
  end type pdf

  abstract interface
    pure function getdims(this)
      import pdf
      class(pdf), intent(in) :: this
      integer getdims
    end function getdims
  end interface
  
contains

  pure function getx(this)
    class(pdf), intent(in) :: this
    real, dimension(getdims(this)) :: getx
  end function getx

end module pdfs


I get the correct error message (unfortunately twice):

    real, dimension(getdims(this)) :: getx
                    1
Error: ABSTRACT INTERFACE 'getdims' must not be referenced at (1)


I'm not completely sure if the usage of 'getdims' is valid in comment 0.
Comment 2 janus 2013-01-13 10:36:22 UTC
Yet another variant:


module pdfs
  type, abstract :: pdf
  contains
    procedure(getdims), deferred :: getdims
    procedure(getx), deferred :: getx
  end type pdf

  abstract interface
    pure function getdims(this)
      import pdf
      class(pdf), intent(in) :: this
      integer getdims
    end function getdims

    pure function getx(this)
      import pdf
      class(pdf), intent(in) :: this
      real, dimension(this%getdims()) :: getx
    end function getx
  end interface

end module pdfs



gives me (four times!):

      real, dimension(this%getdims()) :: getx
                      1
Error: Function 'this' at (1) must be PURE


which is of course bogus, since 'this' is not even a function, and getdims is actually pure.
Comment 3 janus 2013-01-13 16:57:18 UTC
This fixes the ICE in comment 0:

Index: gcc/fortran/expr.c
===================================================================
--- gcc/fortran/expr.c	(revision 195125)
+++ gcc/fortran/expr.c	(working copy)
@@ -4335,9 +4335,11 @@ replace_comp (gfc_expr *expr, gfc_symbol *sym, int
 	 the symtree rather than create a new one (and probably fail later).  */
       stree = gfc_find_symtree (ns ? ns->sym_root : gfc_current_ns->sym_root,
 		      		expr->symtree->n.sym->name);
-      gcc_assert (stree);
-      stree->n.sym->attr = expr->symtree->n.sym->attr;
-      expr->symtree = stree;
+      if (stree)
+	{
+	  stree->n.sym->attr = expr->symtree->n.sym->attr;
+	  expr->symtree = stree;
+	}
     }
   return false;
 }
Comment 4 janus 2013-01-19 15:14:31 UTC
(In reply to comment #2)
> Yet another variant:
> [...]
>
> gives me (four times!):
> 
>       real, dimension(this%getdims()) :: getx
>                       1
> Error: Function 'this' at (1) must be PURE
> 
> 
> which is of course bogus, since 'this' is not even a function, and getdims is
> actually pure.

The wording of the error message can be fixed by this patch:


Index: gcc/fortran/expr.c
===================================================================
--- gcc/fortran/expr.c	(revision 195310)
+++ gcc/fortran/expr.c	(working copy)
@@ -2962,18 +2962,24 @@ gfc_specification_expr (gfc_expr *e)
       return FAILURE;
     }
 
-  comp = gfc_get_proc_ptr_comp (e);
-  if (e->expr_type == EXPR_FUNCTION
-      && !e->value.function.isym
-      && !e->value.function.esym
-      && !gfc_pure (e->symtree->n.sym)
-      && (!comp || !comp->attr.pure))
+  if (e->expr_type == EXPR_FUNCTION)
     {
-      gfc_error ("Function '%s' at %L must be PURE",
-		 e->symtree->n.sym->name, &e->where);
-      /* Prevent repeat error messages.  */
-      e->symtree->n.sym->attr.pure = 1;
-      return FAILURE;
+      comp = gfc_get_proc_ptr_comp (e);
+      if (comp && !comp->attr.pure)
+	{
+	  gfc_error ("Procedure pointer component '%s' at %L must be PURE",
+		     comp->name, &e->where);
+	  return FAILURE;
+	}
+      else if (!comp && !e->value.function.isym && !e->value.function.esym
+	       && !gfc_pure (e->symtree->n.sym))
+	{
+	  gfc_error ("Function '%s' at %L must be PURE",
+		     e->symtree->n.sym->name, &e->where);
+	  /* Prevent repeat error messages.  */
+	  e->symtree->n.sym->attr.pure = 1;
+	  return FAILURE;
+	}
     }
 
   if (e->rank != 0)



With this ones gets:

      real, dimension(this%getdims()) :: getx
                      1
Error: Procedure pointer component 'getdims' at (1) must be PURE


This still leaves us with some problems:
1) That we get the error at all. The interface of getdims is clearly PURE, but it seems that its resolution happens too late, so that the attributes have not yet been copied from the interface when the pureness check is done.
2) getdims is identified as a PPC in the error message, though it is a type-bound procedure. The reason for this is that internally "this%getdims()" is resolved to "this->_vptr->getdims" (where getdims is a PPC of _vptr).
3) The error message still comes four times (not sure why).
Comment 5 janus 2014-02-04 15:38:50 UTC
Note that 'replace_comp' has been removed in r195562 (cf. PR 54107), with the consequence that the original ICE on comment 0 is fixed in 4.8.0 and above.

Also the double error message is reduced to a single one in 4.8.

For comment 2, 4.8 actually gives an ICE in mio_expr, but it compiles cleanly with trunk, so I'm closing this whole PR as fixed.
Comment 6 Sergio Losilla 2014-02-04 15:44:08 UTC
Well, a very similar case, with a non-abstract type throws an ICE with gfortran 4.8.1:

module Foo_class
    type :: Foo
        integer :: n
    contains
        procedure :: n2  => Foo_n2
        procedure :: vec => Foo_vec
    end type

contains

    pure function Foo_n2(self)
        class(Foo), intent(in) :: self
        integer                :: Foo_n2

        Foo_n2 = self%n**2
    end function

    function Foo_vec(self)
        class(Foo) :: self
        real       :: Foo_vec(self%n2())

        Foo_vec=1.0
    end function

end module
Comment 7 janus 2014-02-04 15:53:48 UTC
(In reply to Sergio Losilla from comment #6)
> Well, a very similar case, with a non-abstract type throws an ICE with
> gfortran 4.8.1:

Right. This comes from mio_expr and seems to be similar or identical to the ICE that 4.8 throws on comment 2. But both of them are gone with current trunk.