C++ Attributes (Using the GNU Compiler Collection (GCC))

### 8.7 C++-Specific Variable, Function, and Type Attributes ¶

Some attributes only make sense for C++ programs.

`abi_tag ("tag", ...)` ¶

  The `abi_tag` attribute can be applied to a function, variable, class declaration, or inline namespace.

  When applied to a function, variable, or class declaration, it modifies the mangled name of the entity to incorporate the tag name, in order to distinguish the function or class from an earlier version with a different ABI; perhaps the class has changed size, or the function has a different return type that is not encoded in the mangled name.

  When applied to an inline namespace, it does not affect the mangled name of the namespace; in this case it is only used for `-Wabi-tag` warnings and automatic tagging of functions and variables. Tagging inline namespaces is generally preferable to tagging individual declarations, but the latter is sometimes necessary, such as when only certain members of a class need to be tagged.

  The argument can be a list of strings of arbitrary length. The strings are sorted on output, so the order of the list is unimportant.

  A redeclaration of an entity must not add new ABI tags, since doing so would change the mangled name.

  The ABI tags apply to a name, so all instantiations and specializations of a template have the same tags. The attribute is ignored if applied to an explicit specialization or instantiation.

  The `-Wabi-tag` flag enables a warning about a class which does not have all the ABI tags used by its subobjects and virtual functions; if your code needs to coexist with an earlier ABI, using this option can help to find all affected types that need to be tagged.

  When a type involving an ABI tag is used as the type of a variable or return type of a function where that tag is not already present in the signature of the function, the tag is automatically applied to the variable or function. `-Wabi-tag` also warns about this situation; you can avoid this warning by explicitly tagging the variable or function or moving it into a tagged inline namespace.

`init_priority (priority)` ¶

  This attribute applies to namespace-scope variables.

  In Standard C++, objects defined at namespace scope are guaranteed to be initialized in an order in strict accordance with that of their definitions in a given translation unit. No guarantee is made for initializations across translation units. However, GNU C++ allows you to control the order of initialization of objects defined at namespace scope with the `init_priority` attribute by specifying a relative priority, with the same meaning as for the `constructor` attribute (see Common Attributes).

  In the following example, `A` is normally created before `B`, but the `init_priority` attribute reverses that order:

      Some_Class  A  __attribute__ ((init_priority (2000)));
      Some_Class  B  __attribute__ ((init_priority (543)));

  Note that the particular values of priority do not matter; only their relative ordering.

  As with the priority argument to the `constructor` and `destructor` attributes, a few targets do not support the `init_priority` attribute. In that case the attribute is rejected with an error rather than ignored.

`no_dangling` ¶

  This attribute can be applied to a class type, function, or member function.

  Dangling references to classes marked with this attribute have the `-Wdangling-reference` diagnostic suppressed; so do references returned from the `gnu::no_dangling`-marked functions. For example:

      class [[gnu::no_dangling]] S { ... };

  Or:

      class A {
        int *p;
        [[gnu::no_dangling]] int &foo() { return *p; }
      };

      [[gnu::no_dangling]] const int &
      foo (const int &i)
      {
        ...
      }

  This attribute takes an optional argument, which must be an expression that evaluates to true or false:

      template <typename T>
      struct [[gnu::no_dangling(std::is_reference_v<T>)]] S {
        ...
      };

  Or:

      template <typename T>
      [[gnu::no_dangling(std::is_lvalue_reference_v<T>)]]
      decltype(auto) foo(T&& t) {
        ...
      };

`warn_unused` ¶

  This attribute applies to types.

  For C++ types with non-trivial constructors and/or destructors, it is impossible for the compiler to determine whether a variable of this type is truly unused if it is not referenced. This type attribute informs the compiler that variables of this type should be warned about if they appear to be unused, just like variables of fundamental types.

  This attribute is appropriate for types which just represent a value, such as `std::string`; it is not appropriate for types which control a resource, such as `std::lock_guard`.

  This attribute is also accepted in C, but it is unnecessary because C does not have constructors or destructors.

`cold` ¶
`hot`

  In addition to functions and labels, GNU C++ allows the `cold` and `hot` attributes to be used on C++ classes, structs, or unions.

  Applying these attributes on a type has the effect of propagating it to every member function of the type, including implicit special member functions. See Common Attributes.

`trivial_abi` ¶

  The `trivial_abi` attribute can be applied to a C++ class, struct, or union. It instructs the compiler to pass and return the type using the C ABI for the underlying type when the type would otherwise be considered non-trivial for the purposes of calls.

  The attribute can be specified either as `__attribute__ ((trivial_abi))` or `[[clang::trivial_abi]]` for compatibility with the original implementation in Clang. To avoid portability complications, `[[gnu::trivial_abi]]` is ignored with a warning.

  A class annotated with `trivial_abi` can have non-trivial destructors or copy/move constructors without automatically becoming non-trivial for the purposes of calls. For example:

      // A is trivial for the purposes of calls despite the user-provided
      // special member functions.
      struct __attribute__ ((trivial_abi)) A {
        ~A();
        A(const A &);
        A(A &&);
        int x;
      };

      // B is trivial for the purposes of calls because A is.
      struct B {
        A a;
      };

  If a type is trivial for the purposes of calls, has a non-trivial destructor, and is passed as an argument by value, the convention is that the callee will destroy the object before returning. The lifetime of the copy of the parameter in the caller ends without a destructor call when the call begins.

  When a type marked with `trivial_abi` is used as a function argument, the compiler may omit the call to the copy constructor. Thus, side effects of the copy constructor are potentially not performed. For example, objects that contain pointers to themselves or otherwise depend on their address (or the address of their subobjects) should not be declared with `trivial_abi`.

  Attribute `trivial_abi` has no effect in the following cases:

  - The class has a virtual base or virtual member function.
  - Copy constructors and move constructors of the class are all deleted.
  - The class has a base class that is non-trivial for the purposes of calls.
  - The class has a non-static data member whose type is non-trivial for the purposes of calls, which includes:
    - classes that are non-trivial for the purposes of calls
    - arrays of any of the above
`no_specializations` ¶

  The `no_specializations` attribute can be applied to a C++ class template, variable template or function template, though not their specializations. It instructs the compiler to error if such a template is explicitly specialized. The primary use case for this attribute is the standard library where the standard specifies it is undefined behavior to specialize some template. The error can be disabled with `-Wno-invalid-specialization` or `#pragma GCC ignored "-Winvalid-specialization"`.

  The attribute can be specified either as `__attribute__ ((no_specializations))` or `[[clang::no_specializations]]` for compatibility with the original implementation in Clang. To avoid portability complications, `[[gnu::no_specializations]]` is ignored with a warning.

  The attribute has a single optional argument, a string literal, which is included in the diagnostics and can provide reason why some template should not be specialized.

      template <typename T>
      struct __attribute__ ((__no_specializations__)) A {};
      template <typename T, typename U>
      [[clang::no_specializations]] int b = 1;
      template <typename T>
      [[_Clang::__no_specializations__ ("foo cannot be specialized")]] int
      foo () { return 42; }
      template <> struct A <int> {}; // Error
      template <typename T> int b <T, T> = 2; // Error
      template <> int foo <int> () { return 43; } // Error
      };