为什么 alignas 说明符会在 Clang 上抛出错误?

Why does the alignas specifier throw an error on Clang?

根据标准,new 表达式的语法允许提供 alignas 说明符和其他属性说明符。我已经看到其他代码使用它,但 GCC 会忽略属性说明符,即使它在最大对齐范围内,并且 Clang 会抛出错误。

我不是要解决具体问题,我只是想了解标准。

    int* example = new alignas(16) int[2];
    // alignof(std::max_align_t) = 16
    // sizeof(int) = 4, sizeof(example) = 8

海湾合作委员会:

prog.cc: In function 'int main()':
prog.cc:7:41: warning: attribute ignored [-Wattributes]
    7 |     int* example = new alignas(16) int[2];
      |                                         ^
prog.cc:7:41: note: an attribute that appertains to a type-specifier is ignored

叮当声:

 prog.cc:7:24: error: an attribute list cannot appear here:
               int* example = new alignas(16) int[2];

可在最新的 GCC 和 Clang 上重现,示例:http://cpp.sh/3hfl7

参考文献:

http://eel.is/c++draft/expr.new#nt:new-expression

new-type-id:
    type-specifier-seq new-declarator opt

type-specifier-seq:
    type-specifier attribute-specifier-seq opt
    type-specifier type-specifier-seq

(new-type-id -> type-specifier-seq -> attribute-specifier-seq -> attribute-specifier -> alignment-specifier is permitted by grammar)

attribute-specifier-seq 可以包含对齐说明符。

好吧,您引用的语法指出 attribute-specifier-seq 出现在 type-specifier-seq 中必须在所有 类型说明符 之后发生。因此,根据 [dcl.type]/1:

,您必须将它放在这里,以便使属性属于前面的 int
new int attribute-specifier-seq [2];

根据 [expr.new]/6:

,您必须将它放在这里才能使属性属于数组类型
new int [2] attribute-specifier-seq;

您也可以组合它们:您可以为数组类型和元素类型设置不同的属性。但我认为语法不允许您将属性放在 int.

之前

至于对齐说明符的具体问题:标准既不明确允许也不明确禁止将对齐说明符应用于 type-specifiertype- ID ([dcl.align]/1)。 Clang 似乎将该标准解释为禁止它。 GCC 似乎将该标准解释为允许它;然而,由于标准没有为对齐说明符指定任何语义,当它属于一个类型时,发出警告。考虑:

struct S {
    int x alignas(16);
    int alignas(16) y;
};

此处,S::x 的对齐要求为 16,但 S::y 的对齐说明符没有意义。所以如果你写 int alignas(16) y,GCC 警告你是有意义的,这样你就会意识到你把它放在了错误的地方。

要强制分配的内存在 16 字节边界上对齐,请使用放置语法显式调用采用对齐参数的 operator new 的重载:

int* x = new (std::align_val_t(16)) int [2];