Тип (::x); действует?

Обсуждая Type(identifier); Синтаксис и как это объявление, я наткнулся Type(::x); не работает с Clang. Я ожидаю, что с учетом глобальной переменной x, это будет относиться ::x как выражение (::x + 2 работает) и снимали ::x в Type, Тем не менее, это дает ошибку компилятора.

Вот короткий пример:

int x;

int main() {
    int(::x); //does not compile
    int(::x + 2); //compiles
}

Ошибка компилятора, заданная Clang 3.5:

ошибка: определение или переопределение 'x' не может назвать глобальную область

GCC 4.9.0, однако, компилирует это просто отлично. Этот код действителен или нет?

2 ответа

Решение

Насколько я могу судить, это описано в разделе стандарта C++. 8.3 Значение пункта 6 деклараторов, который гласит (выделение мое в будущем):

В декларации T D, где D имеет вид

( D1)

тип содержимого объявления-идентификатора совпадает с типом содержимого объявления-объявления в объявлении

T D1

Круглые скобки не изменяют тип встроенного идентификатора объявления, но они могут изменять привязку сложных объявлений.

так:

int(::x);

эквивалентно:

int ::x ;

что явно недопустимо, и это также вызывает ту же ошибку. Так gcc 4.9 это не правильно, но так как это выглядит исправлено в gcc 4.8.3 который был выпущен позже, я ожидаю, что это будет исправлено в более поздних выпусках 4.9 также. Хотя я не вижу очевидных совпадений для этой проблемы в фиксированном списке ошибок gcc 4.8.3, но они не утверждают, что это полный список.

Второй случай - это функциональное явное преобразование типов, которое рассматривается в разделе 5.2.3 Явное преобразование типов (функциональная запись), которое говорит:

Спецификатор простого типа (7.1.6.2) или спецификатор typename (14.6), за которым следует список выражений в скобках, создает значение указанного типа по заданному списку выражений. Если список выражений является одним выражением, выражение преобразования типа эквивалентно (в определенности и если определено в значении) соответствующему приведенному выражению (5.4).[...]

Это однозначно, так как ::x + 2 это выражение.

Раздел, который охватывает, когда утверждение считается объявлением или выражением 6.8 Резолюция неоднозначности, которая гласит:

В грамматике существует двусмысленность, связанная с выражениями-выражениями и объявлениями: выражение-выражение с явным преобразованием типов в стиле функции (5.2.3) в качестве крайнего левого подвыражения может быть неотличимо от объявления, где первый декларатор начинается с (. В случаях, когда оператор является декларацией. [Примечание: Чтобы устранить неоднозначность, может потребоваться изучить весь оператор, чтобы определить, является ли он выражением-выражением или объявлением. Это устраняет неоднозначность во многих примерах.

и предоставляет следующие примеры:

T(a)->m = 7; // expression-statement
T(a)++; // expression-statement
T(a,5)<<c; // expression-statement
T(*d)(int); // declaration
T(e)[5]; // declaration
T(f) = { 1, 2 }; // declaration
T(*g)(double(3)); // declaration

Примечание: без () затем T ::D является квалифицированным идентификатором в случае T будучи классом, это покрыто грамматикой 5.1 Основные выражения.

Обновить

Подал отчет об ошибке gcc.

Ответ GCC таков:

Текущий G++ и EDG оба рассматривают его как правильное выражение (int)::x

Поскольку этот ответ подразумевает clang неверно (хотя я не согласен), я подал отчет об ошибке clang и более старый отчет об ошибке выглядит аналогично и, кажется, не согласен с gcc ответ.

Обновление 2

В ответ на clang bug report Ричард Смит соглашается, что это следует рассматривать как декларацию, и говорит:

Это не означает, что лязг неверен; На самом деле, Clang здесь прав, насколько я понимаю. (Я также отправил отчет об ошибке в EDG.)

Тем не менее, мы должны дать правильную ошибку "Вы попали в неприятный анализ, вот как устранить неоднозначность" в этом случае.

Обновление 3

gcc подтверждает, что это ошибка.

Это выглядит как самый неприятный разбор для меня. Если это может быть проанализировано как декларация, это будет. Первый может быть проанализирован как объявление переменной int (int ::x;), но :: в этом контексте незаконно. Второе должно быть выражением, и поэтому компилятор выполняет математические вычисления, преобразует его в int и выбрасывает результат.

Был ли это педантичный вопрос или есть еще одна проблема? Если у вас есть конкретная проблема, которую вы пытаетесь решить, дополнительная информация позволит обойти это решение.

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