[PATCH] D130511: [pseudo][wip] Eliminate simple-type-specifier ambiguities.

Sam McCall via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Jul 26 04:28:09 PDT 2022


sammccall added a comment.

TL;DR: I suspect this is valid but guarding `nested-name-specifier := :: [guard=PrevNotIdentifier]` may be equivalent and clearer.

In D130511#3678938 <https://reviews.llvm.org/D130511#3678938>, @hokein wrote:

> In D130511#3677423 <https://reviews.llvm.org/D130511#3677423>, @sammccall wrote:
>
>> My main concern here is that this might reject valid code (and if it doesn't, it's not obvious why).
>> It does look like C++ forbids the cases I can come up with (e.g. trying to provide a definition for `::Foo` is rejected by clang with "definition or redeclaration of Foo cannot name the global scope).
>> But I'd be way more comfortable if we could connect the specific guard rules here with spec language.
>
> The qualified declarator is tricky (it was forbidden until https://cplusplus.github.io/CWG/issues/482.html).
>
> The closest thing I can find in the standard is basic.lookup.qual.general <https://eel.is/c++draft/basic.lookup.qual.general>:
>
>> If a name, template-id, or decltype-specifier is followed by a ​::​, it shall designate a namespace, class, enumeration, or dependent type, and the ​::​ is never interpreted as a complete nested-name-specifier.

OK, so just spelling this out so I don't get lost...

A `name` is an identifier or operator name.
>From the grammar `nested-name-specifier` can have components preceding `::`:

- nothing (global scope)
- type-name, namespace-name: these are identifiers = names
- decltype-specifier,
- (simple)-template-id

So the rule is saying that if the `::` can bind to the thing on its left, it must (*all* the non-null components are either names, template IDs, or decltype-specifiers).

I think this is probably what you've implemented here, though it's not totally obvious to me.

It seems most natural/more obviously-correct to express this as a guard on `namespace-specifier := ::`, as that's what the rule directly restricts. It's not simple to decide in general (in `c < d > :: a`, `c<d>` can be a template-id or not), but we can rule out the cases where the preceding token is an identifier (which is a limitation of your patch, right?).

Does `nested-name-specifier := :: [guard=PrevTokenNotIdentifier]` work for your testcases?
I think this is easier to tie to the [basic.language.qual.general] language you quoted.
(If you *don't* find this clearer, please do push back)


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130511/new/

https://reviews.llvm.org/D130511



More information about the cfe-commits mailing list