https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87535
Bug ID: 87535 Summary: multiple attribute assume_aligned interpreted inconsistently 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: --- The example below shows that attribute assume_aligned is interpreted inconsistently between apparently equivalent declarations of the same function. When two such attributes are specified on the same declaration the one specified last wins. When the same pair are specified on distinct declarations of the same function, the first one wins. Clang treats both forms consistently, but honors the attribute that was specified last. I think it's debatable whether that's preferable to honoring the most restrictive one as specified for _Alignas by C11. I'm leaning toward going with the C11 approach to minimize surprises due to an inconsistency. $ cat c.c && gcc -O2 -S -Wall -fdump-tree-optimized=/dev/stdout c.c __attribute ((assume_aligned (8), // ignored assume_aligned (32))) // overrdides prior attribute char* f (void); void f1 (void) { char *p = f (); if ((__INTPTR_TYPE__)p & 31) // folded to false __builtin_abort (); } __attribute ((assume_aligned (8))) // overrides subsequent attribute void* g (void); __attribute ((assume_aligned (32))) // attribute ignored void* g (void); void g1 (void) { void *p = g (); if ((__INTPTR_TYPE__)p & 31) // not folded __builtin_abort (); } ;; Function f1 (f1, funcdef_no=0, decl_uid=1908, cgraph_uid=1, symbol_order=0) f1 () { <bb 2> [local count: 1073741824]: f (); [tail call] return; } ;; Function g1 (g1, funcdef_no=1, decl_uid=1916, cgraph_uid=2, symbol_order=1) g1 () { void * p; long int p.1_1; long int _2; <bb 2> [local count: 1073741824]: p_5 = g (); p.1_1 = (long int) p_5; _2 = p.1_1 & 31; if (_2 != 0) goto <bb 3>; [0.00%] else goto <bb 4>; [99.96%] <bb 3> [count: 0]: __builtin_abort (); <bb 4> [local count: 1073312328]: return; }