https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87592
Bug ID: 87592 Summary: overriding attribute constructor and destructor priority not diagnosed Product: gcc Version: 9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: middle-end Assignee: unassigned at gcc dot gnu.org Reporter: msebor at gcc dot gnu.org Target Milestone: --- Here's an example of another inconsistency in GCC's handling of attributes -- even though it implicates another attribute this bug is specifically about attribute constructor and destructor. When the aligned attribute is specified with different arguments on distinct declarations of the same variable, the most restrictive one wins. (This matches the C11 requirement on the _Alignas attribute and what other compilers do, although it isn't documented for attribute aligned in the manual.) In contrast, when the format_arg attribute is specified with different arguments on distinct declarations of the same function they are all (counter-inuitively) accepted. Clang accepts just the last one. But when the constructor attribute is specified with different arguments on distinct declarations of the same function, the first one wins and the subsequent ones are ignored, again with no warning. This is not only different from either of the two cases above but also from what Clang does: it accepts the attribute on the definition of the function. I'd say the Clang behavior makes more sense here because the attribute matters for definitions of the function, not for declarations. $ cat y.c && /ssd/build/gcc-81824/gcc/xgcc -B /ssd/build/gcc-81824/gcc -Wall y.c && ./a.out __attribute__ ((aligned (8))) char i; __attribute__ ((aligned (16))) char i; __attribute__ ((aligned (4))) char i; __attribute__ ((constructor (103))) void f103 (void) { __builtin_puts (__func__); } __attribute__ ((constructor (105))) void f105 (void) { __builtin_puts (__func__); } __attribute__ ((constructor (106))) void f10x (void); // accepted __attribute__ ((constructor (104))) void f10x (void) // ignored { __builtin_puts (__func__); } __attribute__ ((format_arg (2))) char* g (char*, char*); // accepted __attribute__ ((format_arg (1))) char* g (char *s, char *t) // accepted { return t; } void h (void) { __builtin_printf (g ("%i", "%s"), 123); // -Wformat __builtin_printf (g ("%i", "%s"), "abc"); // also -Wformat } int main (void) { __builtin_printf ("alignof (i) = %zu\n", __alignof__ (i)); } y.c: In function ‘h’: y.c:21:32: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=] 21 | __builtin_printf (g ("%i", "%s"), 123); // -Wformat | ~^ ~~~ | | | | | int | char * | %d y.c:22:26: warning: format ‘%i’ expects argument of type ‘int’, but argument 2 has type ‘char *’ [-Wformat=] 22 | __builtin_printf (g ("%i", "%s"), "abc"); // also -Wformat | ~^ ~~~~~ | | | | int char * | %s f103 f105 f10x alignof (i) = 16