Bug 56243 - [4.8 regression] ICE in tree check: expected field_decl, have identifier_node in fixed_type_or_null, at cp/class.c:6645
Summary: [4.8 regression] ICE in tree check: expected field_decl, have identifier_node...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.8.0
: P1 normal
Target Milestone: 4.8.0
Assignee: fabien
URL:
Keywords: ice-on-valid-code
Depends on:
Blocks:
 
Reported: 2013-02-07 16:11 UTC by Paul Pluzhnikov
Modified: 2013-02-28 20:33 UTC (History)
3 users (show)

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


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Paul Pluzhnikov 2013-02-07 16:11:43 UTC
Google ref b/8153611
Looks very similar to PR53816.

Test:

class A
{
    virtual int String ();
};

class F: public A { };

template < typename V > class G
{
    V value;
};

class D
{
    template < int N > void Verify(const int (&p1)[N]) const {
      for (int iter; G < A > *x = 0;)
      {
        F& name = x->value;
        name.String ();
      }
    }
};



ICE with g++ (GCC) 4.8.0 20130205 (experimental).

g++ -c  t.ii  # ok

g++ -c -std=c++11 t.ii
t.ii: In member function ‘void D::Verify(const int (&)[N]) const’:
t.ii:19:22: internal compiler error: tree check: expected field_decl, have identifier_node in fixed_type_or_null, at cp/class.c:6645
         name.String ();
                      ^
0xc6159a tree_check_failed(tree_node const*, char const*, int, char const*, ...)
	../../gcc/tree.c:8946
0x5cd853 tree_check
	../../gcc/tree.h:3669
...
Comment 1 Jakub Jelinek 2013-02-07 18:13:55 UTC
Started with http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=193504
Comment 2 Jason Merrill 2013-02-22 21:02:04 UTC
Any news on this bug?  It's one of only a few P1 regressions left.
Comment 3 fabien 2013-02-23 10:42:55 UTC
(In reply to comment #2)
> Any news on this bug?  It's one of only a few P1 regressions left.

This bug triggers with --enable-checking on the constexpr stuff. I was looking at it yesterday, and tried to fix it in the same way than you fixed PR53816. It did work, but it caused a regression on constexpr-static10.C which I didn't manage to resolve yet. If I fail to find out what goes wrong this week-end, I will probably have to defer to someone more involved than me on the constexpr stuff.

I didn't check if it was a regression wrt 4.7 with --enable-checking
Comment 4 fabien 2013-02-23 22:00:44 UTC
I think the testcase is invalid
Shouldn't the below line be diagnosed, even if it is in a template ?
F& name = x->value;

We fail to return early, and the compiler is confused because of this error.
Comment 5 fabien 2013-02-23 22:02:16 UTC
reduced testcase:

class A
{
    virtual int String ();
};

class F: public A { };

template < typename V > class G
{
    V value;
};

class D
{
    template < int N > void Verify() {
      G<A>* x = 0;
      F& name = x->value;
      name.String();
    }
};
Comment 6 Paul Pluzhnikov 2013-02-23 23:06:18 UTC
(In reply to comment #4)
> I think the testcase is invalid

Looks like you are right, and it's been over-reduced.

> Shouldn't the below line be diagnosed, even if it is in a template ?
> F& name = x->value;

The error being that typeof(x->value) is A, not F, right?

If so, this corrected test case still triggers ICE:


class A
{
    virtual int String ();
};

class F: public A { };

template < typename V > class G
{
    V value;
};

class D
{
    template < int N > void Verify() {
      G<F>* x = 0;
      F& name = x->value;
      name.String();
    }
};
Comment 7 fabien 2013-02-25 20:56:42 UTC
(In reply to comment #6)
> (In reply to comment #4)
[...]
> If so, this corrected test case still triggers ICE:

Good point. Further reduced:

struct A
{
    virtual int String ();
};

class F: public A { };

struct G
{
  F value;
};

class D
{
  template <int>
  void Verify()
  {
    G x;
    F& name = x.value;
    name.String();
  }
};

I restarted the analysis from the beginning. My fix for c++/11750 was basically to restrict the cases where the unsafe front-end de-virtualization was done. It wouldn't help to refine that change because anyway, it would still be possible to find a testcase that shows the same ICE.

My attempts to fix the problem on the constexpr side failed probably because it is correct.

The problem is more related to the COMPONENT_REF 'G'. Probably because D::Verify is not instantiated yet, the field 'value' of G is still an IDENTIFIER_NODE instead of being a FIELD_DECL, which leads to a crash while calling DECL_FIELD_IS_BASE.

Hence, I can only see two solutions:
1) make 'value' a FIELD_DECL before or during the fold_non_dependent_expr_sfinae call. Not sure it is simple.
2) check that the first operand of a COMPONENT_REF is actually a FIELD_DECL before calling DECL_FIELD_IS_BASE on it.

Upcoming patch for the solution 2 on gcc-patch...
Comment 8 fabien 2013-02-25 21:04:59 UTC
(In reply to comment #6)
[...]
> 2) check that the first operand of a COMPONENT_REF is actually a FIELD_DECL
> before calling DECL_FIELD_IS_BASE on it.

As a consequency, while processing fold_non_dependent_expr_sfinae, fixed_type_or_null returns NULL_TREE on 'x.value' the and build_vtbl_ref_1 has not chance to call unshare_expr. Jason, is that a big deal ?
Comment 9 Jason Merrill 2013-02-28 16:01:28 UTC
Author: jason
Date: Thu Feb 28 16:01:09 2013
New Revision: 196343

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=196343
Log:
	PR c++/56243
	* call.c (build_over_call): Avoid virtual lookup in a template.

Added:
    trunk/gcc/testsuite/g++.dg/template/virtual4.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/call.c
Comment 10 Jason Merrill 2013-02-28 20:33:21 UTC
Fixed.