https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108796
--- Comment #8 from joseph at codesourcery dot com <joseph at codesourcery dot com> --- On Thu, 16 Feb 2023, aaron at aaronballman dot com via Gcc-bugs wrote: > > The logic is that GNU attributes are declaration specifiers (and can mix > > anywhere with other declaration specifiers), but standard attributes > > aren't declaration specifiers; rather, they come in specified positions > > relative to declaration specifiers (the semantics before and after the > > declaration specifiers are different), and in the middle isn't such a > > position. > > How does that square with: > ``` > struct __attribute__((packed)) S { ... }; > void func(int *ip) __attribute__((nonnull(1))); > ``` > where the GNU attribute is not written where a declaration specifier is > allowed? GNU attributes are declaration specifiers *in the previous examples given here*, not necessarily in all other cases. The position in relation to other declaration specifiers does not matter in those examples. Whereas a standard attribute at the start of declaration specifiers appertains to the entity declared, while a standard attribute at the end of declaration specifiers appertains to the type in those declaration specifiers. That is [[noreturn]] void f(); declares a non-returning function f, but void [[noreturn]] f(); applies the attribute (invalidly) to the type void, not to the function f. While __attribute__((noreturn)) means exactly the same thing in both locations - it appertains to the function (and you could also have it in the middle of other declaration specifiers, with the same meaning). So the two kinds of attributes are not interchangable, and the semantics for arbitrary mixtures would not be clear. It might work to have arbitrary mixtures in the struct context. But in the void func(int *ip) __attribute__((nonnull(1))); context you again have attributes appertaining to different things: a GNU attribute in that position is in a particular position *in a declaration* (after any asm ("identifier"), before an initializer), and appertains to the entity declared, whereas a standard attribute in such a position is part of the declarator (immediately following a function-declarator or array-declarator) and appertains to the function type - although they look superficially like the same case in simple examples such as this one, they aren't at all. And so again it would be unclear what attributes in arbitrary mixtures should appertain to. (There is then logic in GCC to handle __attribute__ that, according to the syntax, should appertain to a particular entity, so that it's instead applied to some other related entity; for example, moving an attribute from a declaration to its type. This is deliberately *not* done for [[]] attribute syntax; those attributes are expected to be written in a correct location for the entity they appertain to.)