GCC и MSVC принимают «alignas», тогда как Clang отклоняет его

Я написал следующую программу, которая компилируется с GCC и MSVC, но Clang ее отвергает. Программа:

int a[2] alignas(16) [5]; //GCC: Ok, Clang: No, MSVC: OK

Демо

Каково правильное поведение в соответствии с последним стандартом C++?

Выглядит неправильно, но два компилятора, принявшие это, удивляют.

user12002570 31.08.2024 16:35

читая это может быть все в порядке. Анализ грамматики C++ немного сложен, поэтому не публикую ответ.

NathanOliver 31.08.2024 16:46

@NathanOliver noptr-declarator не позволяет повторять [...], поэтому это выглядит неправильно. В грамматике может повторяться только attributespecifier-seq.

user12002570 31.08.2024 16:49
github.com/llvm/llvm-project/issues/106551
Artyer 31.08.2024 18:14
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
4
96
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Программа неправильно сформирована, потому что dcl.align не позволяет применять alignas(16) к типу массива (int[2] здесь), а через CWG2005 в вашем примере alignas(16) относится к типу массива int[2].

Спецификатор выравнивания может применяться к переменной или элементу данных класса, но он не должен применяться к битовому полю, параметру функции или объявлению исключения ([кроме.handle]). Спецификатор выравнивания также может применяться к объявлению класса (в подробном спецификаторе типа ([dcl.type.elab]) или заголовке класса ([class]) соответственно). Спецификатор выравнивания с многоточием представляет собой расширение пакета ([temp.variadic]).

По сути, вы говорите, что объявления многомерных массивов невозможны...

user17732522 31.08.2024 16:53

Возьмите декларатор -> ptr-declarator -> noptr-declarator -> noptr-declarator [constant-expressionopt] атрибут-спецификатор-seqopt, а затем снова noptr-declarator [constant-expressionopt] атрибут-спецификатор-seqopt для внутреннего noptr-декларатора.

user17732522 31.08.2024 16:54

@ user17732522 Обновлено.

user12002570 31.08.2024 17:00

«Программа неправильно сформирована согласно dcl.align» — это настоящий скачок, это даже не подразумевается, она просто перечисляет некоторые места, где спецификатор может быть размещен, а некоторые — нет. . Ни один из них не указывает массивы, хотя массивы являются подтипом переменной или элемента данных класса, поэтому их также следует разрешить.

Blindy 31.08.2024 17:05

@Blindy Ваша логика ошибочна, потому что по вашей логике int тоже должно быть разрешено, но это не так. См. этот комментарий, где член комитета C++ указал ту же причину неправильного формирования типа int.

user12002570 31.08.2024 17:08

Если нет причин запрещать это (и все основные компиляторы, похоже, смогли реализовать int как таковой, согласно комментарию, на который вы ссылаетесь), то, по моему мнению, это должно быть разрешено. Так что да, по крайней мере первая часть вашего комментария верна.

Blindy 31.08.2024 22:20

В позиции, которую вы написали alignas(16), это относится к типу внутреннего массива (а не к объявленной переменной). alignas(16) нельзя применить к типу массива (или к любому типу вне объявленных классов), и поэтому, как поясняется CWG 2205, он имеет неправильную форму. Кланг прав.

alignas(16) может применяться только к переменным, членам данных класса или объявлениям классов. Это вообще не применимо к типам, за последним исключением.

Важно отметить, что alignas никогда не становится частью типа и не имеет никакого значения в системе типов. Это не спецификатор типа. Это потенциально отличается от некоторой реализации нестандартных атрибутов alignas (например, __attribute__((aligned(...)))), которые потенциально можно считать частью системы типов, аналогичной, например, спецификатор типа const. В этом случае имело бы смысл применить его к типу в объявлении переменной, а не к самой переменной.

Позиции, в которых alignas относится к самой переменной, кстати:

  • В начале объявления, где он относится к каждой сущности, объявленной этим объявлением (поскольку вы можете объявить несколько переменных и функций в одном объявлении):

    alignas(16) int a[2][5];
    
  • Сразу после идентификатора декларатора, т. е. имени объявляемой переменной, и в этом случае оно относится только к этой переменной, если в одном объявлении объявлено несколько сущностей:

    int a alignas(16) [2][5];
    

@NathanOliver В проблеме CWG говорится, что это неправильно, если это специально не разрешено, даже если оно грамматически правильное. eel.is/c++draft/dcl.align#1 указывает, где alignas разрешено, что не включает типы (за одним упомянутым мной исключением).

user17732522 31.08.2024 16:58

@NathanOliver Каждый атрибут или alignas относится к одному конкретному объекту. Эта сущность может быть, например, переменной или типом, но, что важно, это не одна и та же сущность. Объявлено, что переменная как сущность имеет определенный тип, который является другой сущностью. Сам тип может состоять из нескольких других типов, каждый из которых также является сущностью. Согласно eel.is/c++draft/dcl.array#3.sentence-2alignas в позиции OP относится к типу массива, сформированному предыдущими скобками, а не к объявленной переменной.

user17732522 31.08.2024 17:01

@NathanOliver alignas для типа, а не для объявленной переменной, не имеет смысла, поскольку типы не различаются по их выравниванию в системе типов, например. int всегда имеет одинаковые требования к выравниванию. Не существует второго типа, называемого int alignas(16) или чего-то в этом роде, который вел бы себя идентично int, за исключением его подразумеваемого выравнивания. Это другое, кстати. чем некоторые компиляторы обрабатывают нестандартный __attribute__((alignas(...))) или аналогичный, который может стать частью типа.

user17732522 31.08.2024 17:03

комментарии удалены, теперь я понимаю, к чему это идет. +1.

NathanOliver 31.08.2024 17:16

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