9 Declarations [dcl.dcl]

9.12 Attributes [dcl.attr]

9.12.1 Attribute syntax and semantics [dcl.attr.grammar]

Attributes specify additional information for various source constructs such as types, variables, names, blocks, or translation units.
attribute-specifier-seq:
	attribute-specifier-seq attribute-specifier
attribute-specifier:
	[ [ attribute-using-prefix attribute-list ] ]
	alignment-specifier
alignment-specifier:
	alignas ( type-id ... )
	alignas ( constant-expression ... )
attribute-using-prefix:
	using attribute-namespace :
attribute-list:
	attribute
	attribute-list , attribute
	attribute ...
	attribute-list , attribute ...
attribute:
	attribute-token attribute-argument-clause
attribute-token:
	identifier
	attribute-scoped-token
attribute-scoped-token:
	attribute-namespace :: identifier
attribute-namespace:
	identifier
attribute-argument-clause:
	( balanced-token-seq )
balanced-token-seq:
	balanced-token
	balanced-token-seq balanced-token
balanced-token:
	( balanced-token-seq )
	[ balanced-token-seq ]
	{ balanced-token-seq }
	any token other than a parenthesis, a bracket, or a brace
If an attribute-specifier contains an attribute-using-prefix, the attribute-list following that attribute-using-prefix shall not contain an attribute-scoped-token and every attribute-token in that attribute-list is treated as if its identifier were prefixed with N​::​, where N is the attribute-namespace specified in the attribute-using-prefix.
Note
:
This rule imposes no constraints on how an attribute-using-prefix affects the tokens in an attribute-argument-clause.
— end note
 ]
Example
:
[[using CC: opt(1), debug]]         // same as [[CC​::​opt(1), CC​::​debug]]
  void f() {}
[[using CC: opt(1)]] [[CC::debug]]  // same as [[CC​::​opt(1)]] [[CC​::​debug]]
  void g() {}
[[using CC: CC::opt(1)]]            // error: cannot combine using and scoped attribute token
  void h() {}
— end example
 ]
Note
:
For each individual attribute, the form of the balanced-token-seq will be specified.
— end note
 ]
In an attribute-list, an ellipsis may appear only if that attribute's specification permits it.
An attribute followed by an ellipsis is a pack expansion.
An attribute-specifier that contains no attributes has no effect.
The order in which the attribute-tokens appear in an attribute-list is not significant.
If a keyword or an alternative token that satisfies the syntactic requirements of an identifier is contained in an attribute-token, it is considered an identifier.
No name lookup is performed on any of the identifiers contained in an attribute-token.
The attribute-token determines additional requirements on the attribute-argument-clause (if any).
Each attribute-specifier-seq is said to appertain to some entity or statement, identified by the syntactic context where it appears ([stmt.stmt], [dcl.dcl], [dcl.decl]).
If an attribute-specifier-seq that appertains to some entity or statement contains an attribute or alignment-specifier that is not allowed to apply to that entity or statement, the program is ill-formed.
If an attribute-specifier-seq appertains to a friend declaration ([class.friend]), that declaration shall be a definition.
Note
:
An attribute-specifier-seq cannot appeartain to an explicit instantiation ([temp.explicit]).
— end note
 ]
For an attribute-token (including an attribute-scoped-token) not specified in this document, the behavior is implementation-defined.
Any attribute-token that is not recognized by the implementation is ignored.
An attribute-token is reserved for future standardization if
Note
:
Each implementation should choose a distinctive name for the attribute-namespace in an attribute-scoped-token.
— end note
 ]
Two consecutive left square bracket tokens shall appear only when introducing an attribute-specifier or within the balanced-token-seq of an attribute-argument-clause.
Note
:
If two consecutive left square brackets appear where an attribute-specifier is not allowed, the program is ill-formed even if the brackets match an alternative grammar production.
— end note
 ]
Example
:
int p[10];
void f() {
  int x = 42, y[5];
  int(p[[x] { return x; }()]);  // error: invalid attribute on a nested declarator-id and
                                // not a function-style cast of an element of p.
  y[[] { return 2; }()] = 2;    // error even though attributes are not allowed in this context.
  int i [[vendor::attr([[]])]]; // well-formed implementation-defined attribute.
}
— end example
 ]