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
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.
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.
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; }
(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).
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.
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
(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.