[cfe-dev] Error on valid; and q. about using tentative parse

Robinson, Paul Paul.Robinson at am.sony.com
Thu Feb 7 11:56:23 PST 2013


From: Robinson, Paul
> From: Dmitri Gribenko [mailto:gribozavr at gmail.com]
> > On Wed, Feb 6, 2013 at 10:24 PM, Robinson, Paul
> > <Paul.Robinson at am.sony.com> wrote:
> > > Clang is giving a compile time error on the following test case:
> > >
> > >     template<int V0>
> > >     struct T0
> > >     {
> > >         enum { E = V0 };
> > >     };
> > >
> > >     template<int V1>
> > >     struct T1
> > >     {
> > >         // The name declared here is the same as the type template
> > >         // declared above.
> > >         static int const T0 = T0<V1>::E;
> > >     };
> > >
> > > with the compile time error:
> > >
> > >     test.cpp:12:35: error: no member named 'E' in the global
> namespace
> > >       static int const T0 = T0<V1>::E;
> >
> > I believe this is correct, the code is parsed as (T0 less-than V1)
> > greater-than ::E.
> >
> > ::T0<V1>::E would do what you want.
> >
> > Dmitri
> 
> Okay, I see that the point-of-declaration of the int T0 is prior to the
> initializer, so unqualified lookup of the T0 from T0<V1>::E will find
> the int T0.  I guess I was confused by the similar-seeming case where
> struct T0 is not a template, and if we see
>   static int const T0 = T0::E;
> then the T0::E is resolved as a qualified reference to member E of
> struct T0.  But delving deeper into the standard, I guess T0<V1> doesn't
> count as a nested-name-specifier, so I do need the leading :: to get the
> effect I want.
> 
> Thanks,
> --paulr

I take it back.  Looking at the grammar rules in the standard:
(.opt means optional in the grammar quoted below)

   5.1.1p8 [expr.prim.general]
   nested-name-specifier:
     ::.opt  type-name ::

   7.1.6.2p1 [dcl.type.simple]
   type-name:
     simple-template-id

   14.2p1 [temp.names]
   simple-template-id:
     template-name < template-argument-list.opt >

so T0<V1> does count as a nested-name-specifier, unless there's some
verbiage I didn't notice that excludes this case in the above context.

I did consider the rule in 3.4p2 [basic.lookup]
  A name "looked up in the context of an expression" is looked up as
  an unqualified name in the scope where the expression is found.

But, that would exclude the non-template T0::E example, which
clearly handles T0 as a nested-name-specifier rather than a sequence
of (static int) T0 followed by (global scope) ::E.

So why is the non-template T0:: a nested-name-specifier but the
templated T0<V1>:: is not?

Thanks,
--paulr






More information about the cfe-dev mailing list