[dcl.attr] (original) (raw)

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.

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-specifiercontains an attribute-using-prefix, the attribute-list following that attribute-using-prefixshall not contain an attribute-scoped-tokenand every attribute-token in that attribute-listis treated as if its identifier were prefixed with N​::​, where N is the attribute-namespacespecified in the attribute-using-prefix.

[Note 1:

This rule imposes no constraints on how an attribute-using-prefixaffects the tokens in an attribute-argument-clause.

— _end note_]

[Example 1: [[using CC: opt(1), debug]] void f() {} [[using CC: opt(1)]] [[CC::debug]] void g() {} [[using CC: CC::opt(1)]] void h() {} — _end example_]

[Note 2:

For each individual attribute, the form of thebalanced-token-seq will be specified.

— _end note_]

In an attribute-list, an ellipsis may appear only if thatattribute's specification permits it.

An attribute-specifier that contains no attributes has no effect.

The order in which the attribute-tokens appear in anattribute-list is not significant.

Noname lookup is performed on any of the identifiers contained in anattribute-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-seqappertains to a friend declaration ([class.friend]), that declaration shall be a definition.

[Note 3:

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

Each implementation should choose a distinctive name for theattribute-namespace in an attribute-scoped-token.

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 4:

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 2: int p[10];void f() { int x = 42, y[5];int(p[[x] { return x; }()]); y[[] { return 2; }()] = 2; int i [[vendor::attr([[]])]]; } — _end example_]

9.12.2 Alignment specifier [dcl.align]

When the alignment-specifier is of the formalignas( constant-expression ):

The alignment requirement of an entity is the strictest nonzero alignment specified by its alignment-specifiers, if any; otherwise, the alignment-specifiers have no effect.

The combined effect of all alignment-specifiers in a declaration shall not specify an alignment that is less strict than the alignment that would be required for the entity being declared if all alignment-specifier_s_appertaining to that entity were omitted.

[Example 1: struct alignas(8) S {};struct alignas(1) U { S s;}; — _end example_]

If the defining declaration of an entity has analignment-specifier, any non-defining declaration of that entity shall either specify equivalent alignment or have noalignment-specifier.

Conversely, if any declaration of an entity has analignment-specifier, every defining declaration of that entity shall specify an equivalent alignment.

No diagnostic is required if declarations of an entity have different alignment-specifier_s_in different translation units.

[Example 2: struct S { int x; } s, *p = &s;struct alignas(16) S; extern S* p; — _end example_]

[Example 3:

An aligned buffer with an alignment requirement of A and holding N elements of type Tcan be declared as:alignas(T) alignas(A) T buffer[N];

Specifying alignas(T) ensures that the final requested alignment will not be weaker than alignof(T), and therefore the program will not be ill-formed.

— _end example_]

[Example 4: alignas(double) void f(); alignas(double) unsigned char c[sizeof(double)]; extern unsigned char c[sizeof(double)]; alignas(float) extern unsigned char c[sizeof(double)]; — _end example_]

9.12.3 Carries dependency attribute [dcl.attr.depend]

The attribute-token carries_­dependency specifies dependency propagation into and out of functions.

It shall appear at most once in each attribute-list and noattribute-argument-clause shall be present.

The attribute may also be applied to the declarator-id of a function declaration, in which case it specifies that the return value, if any, carries a dependency to the evaluation of the function call expression.

The first declaration of a function shall specify the carries_­dependency attribute for itsdeclarator-id if any declaration of the function specifies thecarries_­dependency attribute.

Furthermore, the first declaration of a function shall specify the carries_­dependency attribute for a parameter if any declaration of that function specifies the carries_­dependency attribute for that parameter.

If a function or one of its parameters is declared with the carries_­dependency attribute in its first declaration in one translation unit and the same function or one of its parameters is declared without thecarries_­dependency attribute in its first declaration in another translation unit, the program is ill-formed, no diagnostic required.

[Note 1:

The carries_­dependency attribute does not change the meaning of the program, but might result in generation of more efficient code.

— _end note_]

[Example 1: struct foo { int* a; int* b; }; std::atomic<struct foo *> foo_head[10];int foo_array[10][10];[[carries_dependency]] struct foo* f(int i) { return foo_head[i].load(memory_order::consume);} int g(int* x, int* y [[carries_dependency]]) { return kill_dependency(foo_array[*x][*y]);} [[carries_dependency]] struct foo* f(int i);int g(int* x, int* y [[carries_dependency]]);int c = 3;void h(int i) { struct foo* p; p = f(i); do_something_with(g(&c, p->a)); do_something_with(g(p->a, &c));}

The carries_­dependency attribute on function f means that the return value carries a dependency out of f, so that the implementation need not constrain ordering upon return from f.

Implementations off and its caller may choose to preserve dependencies instead of emitting hardware memory ordering instructions (a.k.a. fences).

Function g's second parameter has a carries_­dependency attribute, but its first parameter does not.

Therefore, function h's first call tog carries a dependency into g, but its second call does not.

The implementation might need to insert a fence prior to the second call tog.

— _end example_]

9.12.4 Deprecated attribute [dcl.attr.deprecated]

The attribute-token deprecated can be used to mark names and entities whose use is still allowed, but is discouraged for some reason.

[Note 1:

In particular,deprecated is appropriate for names and entities that are deemed obsolescent or unsafe.

— _end note_]

It shall appear at most once in each attribute-list.

Anattribute-argument-clause may be present and, if present, it shall have the form:

[Note 2:

The string-literal in the attribute-argument-clausecan be used to explain the rationale for deprecation and/or to suggest a replacing entity.

— _end note_]

The attribute may be applied to the declaration of a class, a typedef-name, a variable, a non-static data member, a function, a namespace, an enumeration, an enumerator, or a template specialization.

A name or entity declared without the deprecated attribute can later be redeclared with the attribute and vice-versa.

[Note 3:

Thus, an entity initially declared without the attribute can be marked as deprecated by a subsequent redeclaration.

However, after an entity is marked as deprecated, later redeclarations do not un-deprecate the entity.

— _end note_]

Redeclarations using different forms of the attribute (with or without theattribute-argument-clause or with differentattribute-argument-clauses) are allowed.

Recommended practice: Implementations should use the deprecated attribute to produce a diagnostic message in case the program refers to a name or entity other than to declare it, after a declaration that specifies the attribute.

The diagnostic message should include the text provided within the attribute-argument-clause of any deprecated attribute applied to the name or entity.

9.12.5 Fallthrough attribute [dcl.attr.fallthrough]

The attribute-token fallthroughmay be applied to a null statement;such a statement is a fallthrough statement.

The attribute-token fallthroughshall appear at most once in each attribute-list and no attribute-argument-clause shall be present.

A fallthrough statement may only appear within an enclosing switch statement.

The next statement that would be executed after a fallthrough statement shall be a labeled statement whose label is a case label or default label for the same switch statement and, if the fallthrough statement is contained in an iteration statement, the next statement shall be part of the same execution of the substatement of the innermost enclosing iteration statement.

The program is ill-formed if there is no such statement.

Recommended practice: The use of a fallthrough statement should suppress a warning that an implementation might otherwise issue for a case or default label that is reachable from another case or default label along some path of execution.

Implementations should issue a warning if a fallthrough statement is not dynamically reachable.

[Example 1: void f(int n) { void g(), h(), i();switch (n) { case 1: case 2: g();[[fallthrough]];case 3: do { [[fallthrough]]; } while (false);case 6: do { [[fallthrough]]; } while (n--);case 7: while (false) { [[fallthrough]]; } case 5: h();case 4: i();[[fallthrough]]; } } — _end example_]

9.12.6 Likelihood attributes [dcl.attr.likelihood]

The attribute-tokens likely and unlikelymay be applied to labels or statements.

The attribute-tokens likely and unlikelyshall appear at most once in each attribute-listand no attribute-argument-clause shall be present.

The attribute-token likelyshall not appear in an attribute-specifier-seqthat contains the attribute-token unlikely.

Recommended practice: The use of the likely attribute is intended to allow implementations to optimize for the case where paths of execution including it are arbitrarily more likely than any alternative path of execution that does not include such an attribute on a statement or label.

The use of the unlikely attribute is intended to allow implementations to optimize for the case where paths of execution including it are arbitrarily more unlikely than any alternative path of execution that does not include such an attribute on a statement or label.

A path of execution includes a label if and only if it contains a jump to that label.

[Note 1:

Excessive usage of either of these attributes is liable to result in performance degradation.

— _end note_]

[Example 1: void g(int);int f(int n) { if (n > 5) [[unlikely]] { g(0);return n * 2 + 1;} switch (n) { case 1: g(1);[[fallthrough]];[[likely]] case 2: g(2); break;} return 3;} — _end example_]

9.12.7 Maybe unused attribute [dcl.attr.unused]

The attribute-token maybe_­unusedindicates that a name or entity is possibly intentionally unused.

It shall appear at most once in each attribute-list and no attribute-argument-clause shall be present.

The attribute may be applied to the declaration of a class, a typedef-name, a variable (including a structured binding declaration), a non-static data member, a function, an enumeration, or an enumerator.

A name or entity declared without the maybe_­unused attribute can later be redeclared with the attribute and vice versa.

An entity is considered marked after the first declaration that marks it.

Recommended practice: For an entity marked maybe_­unused, implementations should not emit a warning that the entity or its structured bindings (if any) are used or unused.

For a structured binding declaration not marked maybe_­unused, implementations should not emit such a warning unless all of its structured bindings are unused.

[Example 1: [[maybe_unused]] void f([[maybe_unused]] bool thing1,[[maybe_unused]] bool thing2) { [[maybe_unused]] bool b = thing1 && thing2; assert(b);}

Implementations should not warn that b is unused, whether or not NDEBUG is defined.

— _end example_]

9.12.8 Nodiscard attribute [dcl.attr.nodiscard]

The attribute-token nodiscardmay be applied to the declarator-idin a function declaration or to the declaration of a class or enumeration.

It shall appear at most once in each attribute-list.

An attribute-argument-clause may be present and, if present, shall have the form:

A name or entity declared without the nodiscard attribute can later be redeclared with the attribute and vice-versa.

[Note 1:

Thus, an entity initially declared without the attribute can be marked as nodiscardby a subsequent redeclaration.

However, after an entity is marked as nodiscard, later redeclarations do not remove the nodiscardfrom the entity.

— _end note_]

Redeclarations using different forms of the attribute (with or without the attribute-argument-clauseor with different attribute-argument-clauses) are allowed.

A nodiscard type is a (possibly cv-qualified) class or enumeration type marked nodiscard in a reachable declaration.

A nodiscard call is either

Recommended practice: Appearance of a nodiscard call as a potentially-evaluated discarded-value expression ([expr.prop]) is discouraged unless explicitly cast to void.

Implementations should issue a warning in such cases.

[Note 2:

This is typically because discarding the return value of a nodiscard call has surprising consequences.

— _end note_]

The string-literalin a nodiscard attribute-argument-clauseshould be used in the message of the warning as the rationale for why the result should not be discarded.

[Example 1: struct [[nodiscard]] my_scopeguard { };struct my_unique { my_unique() = default; [[nodiscard]] my_unique(int fd) { } ~my_unique() noexcept { } };struct [[nodiscard]] error_info { }; error_info enable_missile_safety_mode();void launch_missiles();void test_missiles() { my_scopeguard(); (void)my_scopeguard(), launch_missiles(); my_unique(42); my_unique(); enable_missile_safety_mode(); launch_missiles();}error_info &foo();void f() { foo(); } — _end example_]

9.12.9 Noreturn attribute [dcl.attr.noreturn]

The attribute-token noreturn specifies that a function does not return.

It shall appear at most once in each attribute-list and noattribute-argument-clause shall be present.

The attribute may be applied to thedeclarator-id in a function declaration.

The first declaration of a function shall specify the noreturn attribute if any declaration of that function specifies thenoreturn attribute.

If a function is declared with the noreturn attribute in one translation unit and the same function is declared without the noreturn attribute in another translation unit, the program is ill-formed, no diagnostic required.

If a function f is called where f was previously declared with the noreturnattribute and f eventually returns, the behavior is undefined.

[Note 1:

The function may terminate by throwing an exception.

— _end note_]

Recommended practice: Implementations should issue a warning if a function marked [[noreturn]] might return.

[Example 1: [[ noreturn ]] void f() { throw "error"; } [[ noreturn ]] void q(int i) { if (i > 0) throw "positive";} — _end example_]

9.12.10 No unique address attribute [dcl.attr.nouniqueaddr]

The attribute-token no_­unique_­addressspecifies that a non-static data member is a potentially-overlapping subobject ([intro.object]).

It shall appear at most once in each attribute-listand no attribute-argument-clause shall be present.

The attribute may appertain to a non-static data member other than a bit-field.

[Note 1:

The non-static data member can share the address of another non-static data member or that of a base class, and any padding that would normally be inserted at the end of the object can be reused as storage for other members.

— _end note_]

[Example 1: template<typename Key, typename Value,typename Hash, typename Pred, typename Allocator> class hash_map { [[no_unique_address]] Hash hasher;[[no_unique_address]] Pred pred;[[no_unique_address]] Allocator alloc; Bucket *buckets;public: };

Here, hasher, pred, and alloccould have the same address as bucketsif their respective types are all empty.

— _end example_]