[cfe-dev] Weird diagnostic about non-type template argument

Chandler Carruth chandlerc at google.com
Mon Aug 16 01:55:01 PDT 2010


On Mon, Aug 16, 2010 at 1:42 AM, Abramo Bagnara <abramo.bagnara at gmail.com>wrote:

> Il 16/08/2010 10:22, Chandler Carruth ha scritto:
> > On Mon, Aug 16, 2010 at 12:31 AM, Abramo Bagnara
> > <abramo.bagnara at gmail.com <mailto:abramo.bagnara at gmail.com>> wrote:
> >
> >
> >     The following typescript show the issue:
> >
> >     $ cat t.cc
> >
> >     template <int *ptr>
> >     struct S1 { };
> >
> >     template <bool b>
> >     struct S2 { };
> >
> >     int v1;
> >
> >     S1<(&v1)> x;
> >     S2<(2>2)> y;
> >     $ clang -c t.cc
> >     t.cc:10:4: error: non-type template argument cannot be surrounded by
> >     parentheses
> >     S1<(&v1)> x;
> >       ^~~~~
> >     1 error generated.
> >
> >     My notes:
> >
> >     1) in my opinion the diagnostic is due to a needless too strong
> >     interpretation of the standard:
> >
> >     - comeau and intel does not mark this as an error
> >
> >     - gcc seems to mark this as an error due to some bug (the diagnostic
>  is
> >     very weird)
> >
> >
> > The standard seems really really clear here -- the argument is *not* an
> > expression, it's an address. You're only provided one mechanism for
> > writing an address in this context: '& id-expression', with the '&'
> > being optional in certain cases. You can't even write '0' here. I think
> > it's actually useful to preclude parentheses as they make this look like
> > an expression, which it simply is not. You can't write '(&foo +
> > sizeof(int))' to advance past one element of an int array either.
> >
>
> Hmmm... perhaps not so clear...
>
> If you look at standard grammar, you read this:
>
> template-argument:
>  constant-expression
>  type-id
>  id-expression
>
> Of course S1<v1> is in the 'id-expression' case, but both S1<&v1> and
> S1<(&v1)> are in 'constant-expression' case.
>
> Don't you think that if the intention was to inhibit parenthesis use the
> standard would have been written as:
>
> template-argument:
>  constant-expression
>  type-id
>  '&'opt id-expression
>
> ?
>

No, because the general grammar is not meant to be normative. You can't read
one piece of grammar and know what is or is not a valid program. In this
case, you're citing text from 14.2 (C++0x rather than '03, but I'll stick
with '0x for now -- if anything '03 is *more* restrictive here!), but the
detail of what goes into a template argument is more fully explained by
14.3.2 [template.arg.nontype]. Here, it clearly lists what
constant-expression arguments are allowed:
— an integral constant expression (including a constant expression of
literal class type that can be used as an integral constant expression as
described in 5.19); or
— a constant expression that evaluates to a null pointer value (4.10); or
— a constant expression that evaluates to a null member pointer value
(4.11); or

That's it. The only way you get an address of an actual object is:
— the address of an object or function with external linkage, including
function templates and function template-ids but excluding non-static class
members, expressed as & id-expression where the & is optional if the name
refers to a function or array, or if the corresponding template-parameter is
a reference

This is very clear that it is *restricting* the syntax allowed to represent
the address of an object. It seems to specifically preclude pointer
arithmetic and other expressions on the address.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20100816/05466beb/attachment.html>


More information about the cfe-dev mailing list