GCC has recently implemented generalised attributes. In this post I will discuss what they are and how they can be useful.

Generalised attributes are an extendible means to specify compiler specific attributes for particular language constructs. Previously these have had compiler specific syntax, and as such, wouldn’t even compile with the wrong compiler. The GNU compiler uses __attribute__ , and the Microsoft compiler uses the __declspec keyword.

Attributes are declared by placing an attribute specifier in a declaration. An attribute specifier is said to appertain to a particular entity in the declaration. In other words, the specifier applies to some part of the declaration. The specifier is either an alignas specification, or a list of attributes inside double square brackets ( [[]] ).

Note that the standard now prohibits the appearance of two left square brackets next to each other, even if it is an otherwise valid construct. The following is an example from 7.6.1 paragraph 6 of the standard of what is not allowed:

int p[10]; void f() { int x = 42, y[5]; int(p[[x] { return x; }()]); y[[] { return 2; }()] = 2; }

An attribute can usually appear in several places in a declaration, and it applies to a specific entity in the declaration depending on where it is placed. It usually applies to the entity to the left, although if it appears at the front of a declaration then it applies to the entities declared by that declaration.

For example, suppose that we had the following code:

[[attr1]] class [[attr2]] A { } a; A b;

then attr1 will be applied to variable a , and attr2 will be applied to the whole class A . Therefore, the variable b , as an object of A , will have any attributes applicable to A , as defined by attr2 .

Attributes can have arguments or not, attributes can be in a namespace, and the tokens appearing inside the [[]] can be anything other than [, ], (, ), {, } . Here are some examples from the GCC test suite.

[[gnu::unused]] int five(void) [[gnu::noreturn]] // { dg-warning "ignored" } {} // You can make NON-template typedefs with a large alignment. typedef double AlignedDoubleType [[gnu::aligned(16)]]; typedef int (*F [[gnu::warn_unused_result]]) (int); typedef int (*F2 [[gnu::warn_unused_result]]) (int); [[gnu::packed]] struct A // { dg-warning "attribute" } { char c; int x; void f(); };

The noreturn attribute

One of the attributes defined in the standard is the noreturn attribute. Specifying that a function has the attribute noreturn means that it will not return. If such a function does return, then the behaviour is undefined. An example of a function that could have the noreturn attribute is exit .