15
votes

Assume there is a declaration:

struct A { static int i; };
A a;

As I know, the input string int decltype(a)::i = 0; has no strictly described behaviour.

It can be parsed as int decltype(a)::i = 0;, where: int is a decl-specifier and decltype(a)::i the declarator.

However,it can be parsed as int decltype(a) ::i = 0;,where int and decltype(a) are parsed asdecl-specifers, and ::i is the (re)declaration of a global variable i - the compiler should give a error msg which goes like "a decl-specifier-seq should not contain two type-specifiers".

I clearly know the first way to parse should be the right one but I can't find any proof.

Anyway, in int A::a = 0;, A is sure to be parsed as part of declarator because A is a type-name and as described in standard

If a type-name is encountered while parsing a decl-specifier-seq, it is interpreted as part of the decl-specifier-seq if and only if there is no previous type-specifier other than a cv-qualifier in the decl-specifier-seq.

In constrant, decltype(a) is not a type-name, it's a type-specifier.

I am not 'finding a quarrel in a straw', I have this question because I'm writing my parser for C++.

So, I wonder if the description should be:

If a type-specifier is encountered while parsing a decl-specifier-seq, it is interpreted as part of the decl-specifier-seq if and only if there is no previous type-specifier other than a cv-qualifier in the decl-specifier-seq.

1
I have this question because I'm wrote my parser for C++ good luck; given how atrociously bad the C++ grammar is, it looks like a horrible way to spend a Sunday afternoon. If you are actually creating a tool of some sort (and you are not just parsing C++ for an exercise in masochism) you may be interested in libclang - let it deal with the grammar madness and do your stuff on a nice AST.Matteo Italia
Build pure C++ grammars is hard enough (stackoverflow.com/a/1004737/120163), partly because any grammar you produce must contain some ambiguous parses. What is harder is finding chapter&verse in the standard for each such ambiguous parse, that resolves its interpretation (partly because even the standard is, uh, ambiguous, in a number of places). Another answer has played language lawyer for you. I think the lesson is you are going to have this problem a lot, and you decide if you really want this war or you'd rather just pick one of several front ends that already does all this for you.Ira Baxter

1 Answers

3
votes

Your definition is explicitly disallowed by [dcl.meaning]/1:

The nested-name-specifier of a qualified declarator-id shall not begin with a decltype-specifier.

(GCC and VC++ are buggy in this respect.)

Your implementation's concrete diagnostic (whether referring to multiple type-specifiers or an invalid nested-name-specifier) is then just a QoI issue. In actuality, implementations will probably implement some variation of the maximum munch principle on type-specifiers, similar to what the original wording of your quote resembled (which is why GCC and VC++ accept your code). However, ICC gives the exact error message you expected:

error: invalid combination of type specifiers

Note that your "resolution" is also incorrect, because we can have multiple type-specifiers; see [dcl.type]/2. In fact, the wording is fine as is, because if the beginning of a valid declarator (in your invalid case, decltype(a)) is a type-specifier, it also is a type-name.