1

C++11 brought support for so-called "generalized attributes", along with two standard ones, noreturn and carries_dependency. C++14 added deprecated to the table. However, I cannot find anything clear on what are implementations mandated to do by the standard upon finding an attribute that's unknown to them. Perhaps it's just that the standard doesn't say anything on the matter. Nevertheless, I would like to know.

In practice, both gcc and clang have warnings regarding this situation that may be disabled. In particular, gcc gives the warning 'some_attribute' attribute directive ignored (-Wattributes), while clang complains with unknown attribute 'some_attribute' ignored (-Wunknown-attributes). I haven't been able to find documentation for those options, though; the Warning Options page for GCC merely mentions -Wattributes, while there doesn't even seem to be a similar list for Clang.

Why do I ask this? Well, some implementation-specific attributes are interesting. Take, for example, GCC's nonnull attribute. We could happily annotate some functions with it:

[[gnu::nonnull]] void my_function ( char * a , int * b );

If the implementation knows about the attribute, everything's fine. But what can we expect if it doesn't?

  • It ignores it and this behavior is backed by the standard. We can go on and add every interesting attribute we find in online docs. In particular, this would allow mixing visibility and dllexport without as many #ifs ~yay!

    #if BUILDING_DLL
    #define DLLEXIMPORT dllexport
    #else
    #define DLLEXIMPORT dllimport
    #endif
    
    // even if MSVC doesn't support specifying dllexport this way, Clang does, and it can
    // compile MSVC-compatible objects
    [[gnu::visibility("default"),DLLEXIMPORT]] void api_function ();
    
  • It complains about it and this behavior is backed by the standard. D'oh! We'll have to roll some ugly machinery to keep unknown attributes from the hands of those pesky implementations.

    With just one attribute, it's easy, as empty attribute lists are allowed by the standard:

    #if SOMETHING
    #define ATTRIBUTE_GNU_NONNULL gnu::nonnull
    #else
    #define ATTRIBUTE_GNU_NONNULL
    #endif
    
    // if ATTRIBUTE_GNU_NONNULL is defined to nothing, all that happens is that we get
    // an empty attribute list, which is 'standardly valid'
    [[ATTRIBUTE_GNU_NONNULL]] void my_function ( char * a , int * b );
    

    However, with more than one attribute, things become more tricky:

    #if SOMETHING
    #define ATTRIBUTE_GNU_NONNULL gnu::nonnull
    #else
    #define ATTRIBUTE_GNU_NONNULL
    #endif
    
    #if SOMETHING
    #define ATTRIBUTE_GNU_VISIBILITY( visibility_type ) gnu::visibility(#visibility_type)
    #else
    #define ATTRIBUTE_GNU_VISIBILITY( visibility_type )
    #endif
    
    // if any of the two macros is defined to nothing, it expands to [[,blah_blah]]
    // or [[blah_blah,]]  -  both of which are invalid
    [[ATTRIBUTE_GNU_NONNULL,ATTRIBUTE_GNU_VISIBILITY(default)]] void my_function
    ( char * a , int * b );
    

    The even-uglier solution that comes to mind is to have macros that combine attributes, like this:

    #if SOMETHING
    #define ATTRIBUTES_GNU_NONNULL_AND_GNU_VISIBILITY( visibility_type ) \
        gnu::nonnull,gnu::visibility(#visibility_type)
    #else
    #define ATTRIBUTES_GNU_NONNULL_AND_GNU_VISIBILITY( visibility_type )
    #endif
    
    [[ATTRIBUTES_GNU_NONNULL_AND_GNU_VISIBILITY(default)]] void my_function
    ( char * a , int * b );
    

    But I would be shot in the head for this :).

Thus, if the standard mandated that implementations ignore unknown attributes, I could pick every relevant attribute I found in online docs without fear and without ugly solutions — hence my interest.

djsp
  • 2,174
  • 2
  • 19
  • 40
  • Unsurprisingly: [dcl.attr.grammar]/5 For an attribute-token not specified in this International Standard, the behavior is implementation-defined. – user657267 Apr 23 '16 at 14:07
  • @user657267: Answers in the answer section please. If your comment were wrong (it's not) we would be unable to downvote it. It cannot be reviewed. It doesn't count towards whether the question has been answered. etc. etc. Comments are for requesting clarification. – Lightness Races in Orbit Apr 23 '16 at 14:09
  • The question is fairly well-formed but I must use the "no research effort" downvote button because the answer is trivially found by simply reading the chapter in the standard about attributes. – Lightness Races in Orbit Apr 23 '16 at 14:10
  • @LightnessRacesinOrbit Unfortunately, I don't have access to the standard. I was fairly sure empty attribute lists are allowed only because it's mentioned in the [proposal paper](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2761.pdf) (among the changes in revision 2: _allow empty attribute-lists_) — but, even regarding that, I didn't have _certainty_, as things may change before getting in the standard. – djsp Apr 23 '16 at 15:05
  • 1
    Recommended reading: **[Where do I find the current C or C++ standard documents?](http://stackoverflow.com/q/81656/560648)** – Lightness Races in Orbit Apr 23 '16 at 15:10
  • @LightnessRacesinOrbit I fear I'm one of those "starving students" mentioned in the first answer, but I guess the committee draft will do for me. Many thanks, up to know I thought no free-of-charge versions were available. – djsp Apr 23 '16 at 15:17

2 Answers2

2

7.6.1/3

[...] The use of an attribute-scoped-token is conditionally-supported, with implementation-defined behavior. [ Note: Each implementation should choose a distinctive name for the attribute-namespace in an attribute-scoped-token. —end note ]

7.6.1/5

For an attribute-token not specified in this International Standard, the behavior is implementation-defined.

In short, answer is: check compiler documentation.

Community
  • 1
  • 1
Revolver_Ocelot
  • 8,609
  • 3
  • 30
  • 48
1

[C++14: 7.6.1/5]: For an attribute-token not specified in this International Standard, the behavior is implementation-defined.

So, you will have to consult your implementation's documentation if you want any "guaranteed" behaviour when unrecognised attributes are encountered.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • 2
    Note that this changed in C++17, now "Any attribute-token that is not recognized by the implementation is ignored". – Marc Glisse Feb 02 '19 at 20:50