On 2014-03-25 15:48, Jason Merrill wrote:
On 03/18/2014 10:46 PM, Adam Butcher wrote:
+             if (TYPE_BEING_DEFINED (scope->this_entity))
+               if (scope->level_chain == 0
+                   || scope->this_entity != scope->level_chain->this_entity)
+                 break;

I don't think this is an adequate test; if you have another class
wrapping B, you'll have two levels of context pushed for the
declarator, so the this_entities will compare unequal.  I think we
need some way to designate a scope that actually corresponds to a
class-specifier.

I don't follow.  Are you suggesting a case like the following?

  struct A
  {
    struct X
    {
      struct B
      {
        void foo(auto);
      };
    };

    void X::B::foo(auto) {}  // { dg-error "cannot define" }
  };

If so, it is handled. The code you are referring to is within a level_chain traversal loop so handles arbitrary levels of pushed context. The end result is the same though; we arrive at an 'A::' scope that is not the defining class scope but has the same 'this_entity' as it (so TYPE_BEING_DEFINED returns true). The scope chain is as if the following was used to declare it:

  struct A
  {
    ...
    void A::X::B::foo(auto);
  };

It is the two levels of 'A' entity scopes that caused the ICE due the previous version of the loop stopping to inject the template parameter list between the 'A::' and the 'X::', rather than unwinding back to the scope defining 'A'.

Apologies if I've completely misunderstood your point here. I've got a feeling that I may have.

Adam

Reply via email to