Самый неприятный разбор с квалифицированным идентификатором - или нет?

Рассматривать:

struct Foo {
     enum { bar };
     explicit Foo(int){}
};

struct Baz { explicit Baz(Foo){} };

Baz b(Foo(Foo::bar)); // #1

Строка № 1 - самый неприятный анализ, хотя Foo::bar является квалифицированным идентификатором и не может быть допустимым именем параметра? Clang и GCC не согласны; какой компилятор правильный?

1 ответ

Clang прав.

Несколько удивительно, что грамматика для объявления параметров допускает как квалифицированные, так и неквалифицированные идентификаторы, потому что она принимает все объявления:

parameter-declaration:
    attribute-specifier-seq_opt decl-specifier-seq declarator
    attribute-specifier-seq_opt decl-specifier-seq declarator = initializer-clause
    attribute-specifier-seq_opt decl-specifier-seq abstract-declarator_opt
    attribute-specifier-seq_opt decl-specifier-seq abstract-declarator_opt = initializer-clause

а грамматика для декларатора допускает как квалифицированные, так и неквалифицированные идентификаторы. Правило "нет квалифицированного идентификатора для имен параметров функции", к лучшему или худшему, является семантическим правилом, даже если легко написать грамматику для объявления параметров, которая напрямую исключает квалифицированные идентификаторы.

Как и ситуация в этом вопросе, правило устранения неоднозначности является чисто синтетическим, и поскольку

Baz b(Foo(Foo::bar));

может быть синтаксически проанализирован как объявление функции, поэтому он анализируется, даже если устранение неоднозначности в этом случае приводит к тому, что никогда не скомпилируется.

Смотрите также лягушка ошибка 4594.

Другие вопросы по тегам