Bug 81566 - [7 Regression] invalid attribute aligned accepted on functions
Summary: [7 Regression] invalid attribute aligned accepted on functions
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 8.0
: P2 normal
Target Milestone: 8.0
Assignee: Not yet assigned to anyone
URL:
Keywords: accepts-invalid, diagnostic, documentation, patch
Depends on:
Blocks:
 
Reported: 2017-07-26 19:59 UTC by Martin Sebor
Modified: 2024-04-19 00:33 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work: 4.8.3, 8.0
Known to fail: 4.9.3, 5.3.0, 6.4.0, 7.1.0, 7.5.0
Last reconfirmed: 2017-08-08 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Martin Sebor 2017-07-26 19:59:41 UTC
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
Comment 1 Martin Sebor 2017-08-02 02:14:12 UTC
Changing the Summary to make it clearer that there are two problems here.
Comment 2 Martin Sebor 2017-08-02 15:22:33 UTC
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;
    }
Comment 3 Martin Sebor 2017-08-08 15:22:51 UTC
Testing a patch.
Comment 4 Martin Sebor 2017-08-08 16:20:43 UTC
Patch posted for review:
https://gcc.gnu.org/ml/gcc-patches/2017-08/msg00601.html
Comment 5 Jakub Jelinek 2017-10-10 13:28:28 UTC
GCC 5 branch is being closed
Comment 6 Richard Biener 2017-12-07 14:53:53 UTC
> 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.
Comment 7 Martin Sebor 2017-12-07 16:32:34 UTC
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
Comment 8 Martin Sebor 2017-12-07 16:40:26 UTC
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);
                                   ^
Comment 9 Jakub Jelinek 2018-10-26 10:13:59 UTC
GCC 6 branch is being closed
Comment 10 Richard Biener 2019-11-14 10:14:14 UTC
Fixed in GCC 8.