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

Richard Smith richard at metafoo.co.uk
Thu Feb 7 13:32:34 PST 2013


On Thu, Feb 7, 2013 at 11:56 AM, Robinson, Paul
<Paul.Robinson at am.sony.com>wrote:

> 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.
>

T0 is not a template-name here, because name lookup finds the static data
member. See [temp.names]p1-p3.


> 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
>
>
>
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20130207/4985e600/attachment.html>


More information about the cfe-dev mailing list