The function form of attribute aligned is documented to take an argument but not without: aligned (alignment) This attribute specifies a minimum alignment for the function, measured in bytes. In addition, the manual states that You cannot use this attribute to decrease the alignment of a function, only to increase it. However, GCC accepts the attribute even without an argument, and it also accepts declarations that appear to decrease the alignment of a function only to proceed to silently ignore them. See the test case below. The manual should be updated and the effect of the attribute without an argument (or GCC changed to reject it), and the attribute handler should be enhanced to issue -Wattributes for attribute arguments that violate the requirements outlined in the manual. $ cat x.c && /ssd/build/gcc-git/gcc/xgcc -B /ssd/build/gcc-git/gcc -O2 -S -Wall -Wextra -Wpedantic -o/dev/stdout x.c int __attribute__ ((aligned)) f (void); int __attribute__ ((aligned (4))) f (void); int __attribute__ ((aligned (2))) f (void); int __attribute__ ((aligned (1))) f (void); int __attribute__ ((aligned (0))) f (void); int f (void) { return 0; } int __attribute__ ((aligned (2))) g (void); int __attribute__ ((aligned (1))) g (void); int __attribute__ ((aligned (0))) g (void); int g (void) { return 0; } .file "x.c" .text .align 16 .globl f .type f, @function f: .LFB0: .cfi_startproc xorl %eax, %eax ret .cfi_endproc .LFE0: .size f, .-f .align 2 .globl g .type g, @function g: .LFB1: .cfi_startproc xorl %eax, %eax ret .cfi_endproc .LFE1: .size g, .-g .ident "GCC: (GNU) 8.0.0 20170717 (experimental)" .section .note.GNU-stack,"",@progbits
Changing the Summary to make it clearer that there are two problems here.
The handle_aligned_attribute() function in c-family/c-attribs.c tries to detect and reject attribute aligned on declarations that attempt to relax a function's alignment (see the second if statement below) but that code is never reached apparently because of the test immediately before it. That test was added in r192199 (in GCC 4.9) that added C++ 11 alignas support. Prior to that GCC rejected a function declaration with conflicting attribute aligned. I cannot find any tests for the ineffective code in the test suite. else if (DECL_USER_ALIGN (decl) && DECL_ALIGN (decl) > (1U << i) * BITS_PER_UNIT) /* C++-11 [dcl.align/4]: When multiple alignment-specifiers are specified for an entity, the alignment requirement shall be set to the strictest specified alignment. This formally comes from the c++11 specification but we are doing it for the GNU attribute syntax as well. */ *no_add_attrs = true; else if (TREE_CODE (decl) == FUNCTION_DECL && DECL_ALIGN (decl) > (1U << i) * BITS_PER_UNIT) { if (DECL_USER_ALIGN (decl)) error ("alignment for %q+D was previously specified as %d " "and may not be decreased", decl, DECL_ALIGN (decl) / BITS_PER_UNIT); else error ("alignment for %q+D must be at least %d", decl, DECL_ALIGN (decl) / BITS_PER_UNIT); *no_add_attrs = true; }
Testing a patch.
Patch posted for review: https://gcc.gnu.org/ml/gcc-patches/2017-08/msg00601.html
GCC 5 branch is being closed
> gcc-6 t.c -S t.c:6:1: error: requested alignment is not a positive power of 2 int __attribute__ ((aligned (0))) f (void); ^~~ t.c:12:1: error: requested alignment is not a positive power of 2 int __attribute__ ((aligned (0))) g (void); ^~~ > gcc-7 t.c -S so GCC 6 works for the accepts-invalid. Splitting the bug might help. I guess it's reasonable to fix the accepts-invalid even for GCC 7.3.
Author: msebor Date: Thu Dec 7 16:32:03 2017 New Revision: 255469 URL: https://gcc.gnu.org/viewcvs?rev=255469&root=gcc&view=rev Log: PR c/81544 - attribute noreturn and warn_unused_result on the same function accepted PR c/81566 - invalid attribute aligned accepted on functions gcc/ada/ChangeLog: PR c/81544 * gcc-interface/utils.c (gnat_internal_attribute_table): Initialize new member of struct attribute_spec. gcc/c/ChangeLog: PR c/81544 * c-decl.c (c_decl_attributes): Look up existing declaration and pass it to decl_attributes. gcc/c-family/ChangeLog: PR c/81544 PR c/81566 * c-attribs.c (attr_aligned_exclusions): New array. (attr_alloc_exclusions, attr_cold_hot_exclusions): Same. (attr_common_exclusions, attr_const_pure_exclusions): Same. (attr_gnu_inline_exclusions, attr_inline_exclusions): Same. (attr_noreturn_exclusions, attr_returns_twice_exclusions): Same. (attr_warn_unused_result_exclusions): Same. (handle_hot_attribute, handle_cold_attribute): Simplify. (handle_const_attribute): Warn on function returning void. (handle_pure_attribute): Same. (handle_aligned_attribute): Diagnose conflicting attribute specifications. * c-warn.c (diagnose_mismatched_attributes): Simplify. gcc/cp/ChangeLog: PR c/81544 * cp-tree.h (decls_match): Add default argument. * decl.c (decls_match): Avoid calling into the target back end and triggering an error. * decl2.c (cplus_decl_attributes): Look up existing declaration and pass it to decl_attributes. * tree.c (cxx_attribute_table): Initialize new member of struct attribute_spec. gcc/fortran/ChangeLog: PR c/81544 * f95-lang.c (gfc_attribute_table): Initialize new member of struct attribute_spec. gcc/lto/ChangeLog: PR c/81544 * lto-lang.c (lto_attribute_table): Initialize new member of struct attribute_spec. gcc/ChangeLog: PR c/81544 * attribs.c (empty_attribute_table): Initialize new member of struct attribute_spec. (decl_attributes): Add argument. Handle mutually exclusive combinations of attributes. (selftests::test_attribute_exclusions): New function. (selftests::attribute_c_tests): Ditto. * attribs.h (decl_attributes): Add default argument. * selftest.h (attribute_c_tests): Declare. * selftest-run-tests.c (selftest::run_tests): Call attribute_c_tests. * tree-core.h (attribute_spec::exclusions, exclude): New type and member. * doc/extend.texi (Common Function Attributes): Update const and pure. gcc/testsuite/ChangeLog: PR c/81544 * c-c++-common/Wattributes-2.c: New test. * c-c++-common/Wattributes.c: New test. * c-c++-common/attributes-3.c: Adjust. * gcc.dg/Wattributes-6.c: New test. * gcc.dg/Wattributes-7.c: New test. * gcc.dg/attr-noinline.c * gcc.dg/pr44964.c: Same. * gcc.dg/torture/pr42363.c: Same. * gcc.dg/tree-ssa/ssa-ccp-2.c: Same. Modified: trunk/gcc/ChangeLog trunk/gcc/ada/ChangeLog trunk/gcc/ada/gcc-interface/utils.c trunk/gcc/attribs.c trunk/gcc/attribs.h trunk/gcc/brig/brig-lang.c trunk/gcc/c-family/ChangeLog trunk/gcc/c-family/c-attribs.c trunk/gcc/c-family/c-warn.c trunk/gcc/c/ChangeLog trunk/gcc/c/c-decl.c trunk/gcc/config/alpha/alpha.c trunk/gcc/config/arc/arc.c trunk/gcc/config/arm/arm.c trunk/gcc/config/avr/avr.c trunk/gcc/config/bfin/bfin.c trunk/gcc/config/cr16/cr16.c trunk/gcc/config/epiphany/epiphany.c trunk/gcc/config/h8300/h8300.c trunk/gcc/config/i386/i386.c trunk/gcc/config/ia64/ia64.c trunk/gcc/config/m32c/m32c.c trunk/gcc/config/m32r/m32r.c trunk/gcc/config/m68k/m68k.c trunk/gcc/config/mcore/mcore.c trunk/gcc/config/microblaze/microblaze.c trunk/gcc/config/mips/mips.c trunk/gcc/config/msp430/msp430.c trunk/gcc/config/nds32/nds32.c trunk/gcc/config/nvptx/nvptx.c trunk/gcc/config/powerpcspe/powerpcspe.c trunk/gcc/config/rl78/rl78.c trunk/gcc/config/rs6000/rs6000.c trunk/gcc/config/rx/rx.c trunk/gcc/config/s390/s390.c trunk/gcc/config/sh/sh.c trunk/gcc/config/sparc/sparc.c trunk/gcc/config/spu/spu.c trunk/gcc/config/stormy16/stormy16.c trunk/gcc/config/v850/v850.c trunk/gcc/config/visium/visium.c trunk/gcc/cp/ChangeLog trunk/gcc/cp/cp-tree.h trunk/gcc/cp/decl.c trunk/gcc/cp/decl2.c trunk/gcc/cp/tree.c trunk/gcc/doc/extend.texi trunk/gcc/fortran/ChangeLog trunk/gcc/fortran/f95-lang.c trunk/gcc/lto/ChangeLog trunk/gcc/lto/lto-lang.c trunk/gcc/selftest-run-tests.c trunk/gcc/selftest.h trunk/gcc/testsuite/ChangeLog trunk/gcc/testsuite/c-c++-common/attributes-3.c trunk/gcc/testsuite/gcc.dg/attr-noinline.c trunk/gcc/testsuite/gcc.dg/pr44964.c trunk/gcc/testsuite/gcc.dg/torture/pr42363.c trunk/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-2.c trunk/gcc/tree-core.h trunk/libstdc++-v3/ChangeLog trunk/libstdc++-v3/include/ext/mt_allocator.h
Fixed in 8.0 via r255469. GCC 8 issues the warnings below. Removing the 8 regression. The patch seems too big to backport to older branches though it may be possible to extract just the subset of the patch that fixes this issue and backport it. I don't expect to have the cycles to work on in in stage 3/4 so I'll unassign myself from the bug for now. pr81566.c:3:1: warning: ignoring attribute ‘aligned (4)’ because it conflicts with attribute ‘aligned (16)’ [-Wattributes] int __attribute__ ((aligned (4))) f (void); ^~~ pr81566.c:1:31: note: previous declaration here int __attribute__ ((aligned)) f (void); ^ pr81566.c:4:1: warning: ignoring attribute ‘aligned (2)’ because it conflicts with attribute ‘aligned (16)’ [-Wattributes] int __attribute__ ((aligned (2))) f (void); ^~~ pr81566.c:3:35: note: previous declaration here int __attribute__ ((aligned (4))) f (void); ^ pr81566.c:5:1: warning: ignoring attribute ‘aligned (1)’ because it conflicts with attribute ‘aligned (16)’ [-Wattributes] int __attribute__ ((aligned (1))) f (void); ^~~ pr81566.c:4:35: note: previous declaration here int __attribute__ ((aligned (2))) f (void); ^ pr81566.c:11:1: warning: ignoring attribute ‘aligned (1)’ because it conflicts with attribute ‘aligned (2)’ [-Wattributes] int __attribute__ ((aligned (1))) g (void); ^~~ pr81566.c:10:35: note: previous declaration here int __attribute__ ((aligned (2))) g (void); ^
GCC 6 branch is being closed
Fixed in GCC 8.