Am Fri, 8 May 2015 11:04:22 +0000 Joseph Myers <jos...@codesourcery.com>:
> On Fri, 8 May 2015, Manuel López-Ibáñez wrote: > > > "At present, the first parameter in a function prototype must have > > some type specifier that is not an attribute specifier; this resolves > > an ambiguity in the interpretation of void f(int (__attribute__((foo)) > > x))" > > https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html#Attribute-Syntax > > > > But I don't understand the example given in the docs. > > This means that this example is interpreted as > > void f(int __attribute__((foo)) x); > > and not > > void f(int (*)(int __attribute__((foo)) x)); > > (with implicit int and adjustment of a parameter declared with function > type to have pointer to function type), which would be a valid parse if > you only consider the syntax productions without the above disambiguation. So this is merely a syntax issue unrelated to the original problem: void foo(__attribute__((nonnull)) int *a) { } void bar(__attribute__((nonnull)) int (*a)(int*)) { (*a)(0); } where the first works with clang but not with gcc (which gives a warning) and the latter applies the attribute to the parameter with clang, but to the pointed-to function with gcc. For clang, to get nonnull to apply to the pointed-to function, one has to put it into the parameter list of the pointed-to function. So more relevant seems this quote: "Where an attribute specifier is applied to a parameter declared as a function or an array, it should apply to the function or array rather than the pointer to which the parameter is implicitly converted, but this is not yet correctly implemented." Which may suggest that if the parameter is *not* declared as a function or an array, it is supposed to apply to the parameter itself instead... But then there is also: "For compatibility with existing code .... If an attribute that only applies to function types is applied to a pointer-to-function type, it is treated as applying to the pointer target type; " Which I guess applies here. So without breaking the existing behaviour of nonnull, we cannot make this work... We could add an entirely new attribute (e.g. nonzero) which is not a function attribute? Or just implement 'static', but this does not work for C++. From reading the documentation, it seems that attributes originally were supposed to only go with declarations and were not meant to be a general extension to the type system. But then there is the example: char *__attribute__((aligned(8))) *f; which implies that now (some) attributes could work similar to type qualifiers. Is this the idea? Martin