From eedff70182852a43d62a463c4dd65cdd8d567c70 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Mon, 11 Dec 2017 23:21:55 +0000 Subject: [PATCH] PR c/81544 - attribute noreturn and warn_unused_result on the same function PR c/81544 - attribute noreturn and warn_unused_result on the same function accepted Add tests missed in r255469. From-SVN: r255557 --- gcc/testsuite/ChangeLog | 11 + gcc/testsuite/c-c++-common/Wattributes-2.c | 74 ++++ gcc/testsuite/c-c++-common/Wattributes.c | 439 +++++++++++++++++++++ gcc/testsuite/g++.dg/Wattributes-2.C | 35 ++ gcc/testsuite/gcc.dg/Wattributes-6.c | 439 +++++++++++++++++++++ gcc/testsuite/gcc.dg/Wattributes-7.c | 74 ++++ 6 files changed, 1072 insertions(+) create mode 100644 gcc/testsuite/c-c++-common/Wattributes-2.c create mode 100644 gcc/testsuite/c-c++-common/Wattributes.c create mode 100644 gcc/testsuite/g++.dg/Wattributes-2.C create mode 100644 gcc/testsuite/gcc.dg/Wattributes-6.c create mode 100644 gcc/testsuite/gcc.dg/Wattributes-7.c diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 884c722691f..ecb6ac659c1 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2017-12-11 Martin Sebor + + PR c/81544 + * c-c++-common/Wattributes-2.c: New test. + * c-c++-common/Wattributes.c: Ditto. + * g++.dg/Wattributes-2.C: Ditto. + * gcc.dg/Wattributes-6.c: Ditto. + * gcc.dg/Wattributes-7.c: Ditto. + + * ../../../git/gcc/testsuite/g++.dg/pr53037-4.C: + 2017-12-07 Carl Love * gcc.target/powerpc/altivec-12.c (main): Add tests for vec_avg. diff --git a/gcc/testsuite/c-c++-common/Wattributes-2.c b/gcc/testsuite/c-c++-common/Wattributes-2.c new file mode 100644 index 00000000000..0904742b01d --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wattributes-2.c @@ -0,0 +1,74 @@ +/* PR c/81566 - invalid attribute aligned accepted on functions + { dg-do compile } + { dg-options "-Wall -Wattributes -ftrack-macro-expansion=0" } */ + +#define ATTR(list) __attribute__ (list) +#define ALIGN(n) ATTR ((aligned (n))) + +/* It's okay to increase the alignment of a function. */ + +void ALIGN (16) ALIGN (32) +falign32_1 (void); + +void ALIGN (16) falign32_2 (void); +void ALIGN (32) falign32_2 (void); + +void falign32_2 (void) { } + +void ALIGN (32) falign32_2 (void); + +/* It's not okay to decrease it. */ + +void ALIGN (32) ALIGN (16) +falign64_3 (void); /* { dg-warning "ignoring attribute .aligned \\(16\\). because it conflicts with attribute .aligned \\(32\\)." } */ + +void ALIGN (32) +falign64_3 (void); + +void falign64_3 (void); + +void falign64_3 (void) { } + + +void ALIGN (32) +falign64_4 (void); /* { dg-message "previous declaration here" } */ + +void ALIGN (16) +falign64_4 (void); /* { dg-warning "ignoring attribute .aligned \\(16\\). because it conflicts with attribute .aligned \\(32\\)." } */ + +void ALIGN (32) +falign64_4 (void); /* { dg-message "previous declaration here" } */ + +void ALIGN (16) +falign64_4 (void); /* { dg-warning "ignoring attribute .aligned \\(16\\). because it conflicts with attribute .aligned \\(32\\)." } */ + +void ALIGN (64) +falign64_4 (void); + +void ALIGN (32) +falign64_4 (void); /* { dg-warning "ignoring attribute .aligned \\(32\\). because it conflicts with attribute .aligned \\(64\\)." } */ + +void falign64_4 (void); + +void ALIGN (64) +falign64_4 (void) { } + +void falign64_4 (void); + +void ALIGN (64) +falign64_4 (void); + + +void ATTR ((aligned (16), aligned (32))) +falign64_5 (void); + +void ATTR ((aligned (32), aligned (64))) +falign64_5 (void); + +void ATTR ((aligned (16), aligned (32), aligned (64))) +falign64_5 (void); /* { dg-warning "ignoring attribute .aligned \\(16\\). because it conflicts with attribute .aligned \\(64\\)." } */ + /* { dg-warning "ignoring attribute .aligned \\(32\\). because it conflicts with attribute .aligned \\(64\\)." "" { target *-*-* } .-1 } */ + + +void ATTR ((aligned (16), aligned (32), aligned (16))) +falign64_6 (void); /* { dg-warning "ignoring attribute .aligned \\(16\\). because it conflicts with attribute .aligned \\(32\\)." } */ diff --git a/gcc/testsuite/c-c++-common/Wattributes.c b/gcc/testsuite/c-c++-common/Wattributes.c new file mode 100644 index 00000000000..902bcb61c30 --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wattributes.c @@ -0,0 +1,439 @@ +/* { dg-do compile } + { dg-options "-Wall -Wattributes -ftrack-macro-expansion=0" } */ + +#define ATTR(attrlist) __attribute__ (attrlist) + +/* Exercise the handling of the mutually exclusive attributes + aligned and packed on a type definition. */ + +/* Pointless but benign. */ +struct ATTR ((aligned, aligned)) +AlignedAligned { int i; }; + +/* Aligned followed by packed on a type and vice versa has a valid use: + to decrease the alignment of a type to the specified boundary. */ +struct ATTR ((aligned, packed)) +AlignedPacked { int i; }; + +struct ATTR ((packed, aligned)) +PackedAligned { int i; }; + +struct ATTR ((aligned (2))) +AlignedMemberPacked +{ + int ATTR ((packed)) i; +}; + +struct ATTR ((packed)) +PackedMemberAligned +{ + int ATTR ((aligned (2))) i; +}; + +/* Silly but benign. */ +struct ATTR ((packed, packed)) +PackedPacked { int i; }; + + +/* Exercise the handling of the mutually exclusive attributes + aligned and packed on a function declaration. */ + +void ATTR ((aligned (8), packed)) +faligned8_1 (void); /* { dg-warning ".packed. attribute ignored" } */ + +void ATTR ((aligned (8))) +faligned8_2 (void); /* { dg-message "previous declaration here" "" { xfail *-*-* } } */ + +void ATTR ((packed)) +faligned8_2 (void); /* { dg-warning ".packed. attribute ignored" } */ + +/* Exercise the handling of the mutually exclusive attributes + always_inline and noinline (in that order). */ + +inline void ATTR ((always_inline)) +falways_inline1 (void); + +inline void ATTR ((__always_inline__)) +falways_inline1 (void); + +/* Verify that repeating attribute always_inline on the same declaration + doesn't trigger a warning. */ +inline void ATTR ((always_inline, __always_inline__)) +falways_inline1 (void); + +/* Verify that repeating attribute always_inline on a distinct declaration + doesn't trigger a warning. */ +inline void ATTR ((always_inline)) +falways_inline1 (void); /* { dg-message "previous declaration here" } */ + +/* Verify a warning for noinline conflict. */ +void ATTR ((noinline)) +falways_inline1 (void) { } /* { dg-warning "ignoring attribute .noinline. because it conflicts with attribute .always_inline." } */ + +/* And again. */ +void ATTR ((always_inline)) +falways_inline1 (void); + + +/* Exercise the handling of the mutually exclusive attributes + noinline and always_inline (in that order). */ + +void ATTR ((noinline)) +fnoinline1 (void); + +void ATTR ((__noinline__)) +fnoinline1 (void); + +/* Verify that repeating attribute noinline on the same declaration + doesn't trigger a warning. */ +void ATTR ((noinline, __noinline__)) +fnoinline1 (void); + +/* Verify that repeating attribute noinline on a distinct declaration + doesn't trigger a warning. */ +void ATTR ((noinline)) +fnoinline1 (void); /* { dg-message "previous declaration here" } */ + +/* Verify a warning for always_inline conflict. */ +void ATTR ((always_inline)) +fnoinline1 (void) { } /* { dg-warning "ignoring attribute .always_inline. because it conflicts with attribute .noinline." } */ + +/* Verify a warning for gnu_inline conflict. */ +inline void ATTR ((gnu_inline)) +fnoinline1 (void); /* { dg-warning "ignoring attribute .gnu_inline. because it conflicts with attribute .noinline." } */ + /* { dg-warning "follows declaration with attribute .noinline." "inline noinline" { target *-*-* } .-1 } */ + +/* And again. */ +void ATTR ((noinline)) +fnoinline1 (void); /* { dg-warning "follows inline declaration" } */ + + +/* Exercise the handling of the mutually exclusive attributes + noreturn and warn_unused_result. */ + +int ATTR ((__noreturn__)) +fnoret1 (void); + +int ATTR ((noreturn)) +fnoret1 (void); /* { dg-message "previous declaration here" } */ + +int ATTR ((warn_unused_result)) +fnoret1 (void); /* { dg-warning "ignoring attribute .warn_unused_result. because it conflicts with attribute .noreturn." } */ + +/* Verify that repeating attribute noreturn doesn't trigger a warning. */ +int ATTR ((noreturn)) fnoret1 (void); + +int call_noret1 (void) +{ + /* Verify that attribute warn_unused_result was, in fact, ignored + on the second declaration of fnoret1. */ + fnoret1 (); +} + +int ATTR ((noreturn, warn_unused_result)) +fnoret2 (void); /* { dg-warning "ignoring attribute .warn_unused_result. because it conflicts with attribute .noreturn." } */ + +/* Verify that repeating attribute noreturn doesn't trigger a warning. */ +int ATTR ((noreturn)) fnoret2 (void); + +int call_noret2 (void) +{ + /* Verify that attribute warn_unused_result was, in fact, ignored + on the second declaration of fnoret2. */ + fnoret2 (); +} + +/* Verify that attribute noreturn isn't diagnosed on a declaration + that was previously declared warn_unused_result and that attribute + was dropped (because the function returs void). */ + +void ATTR ((warn_unused_result)) +fnorety6 (void); /* { dg-warning ".warn_unused_result. attribute ignored" } */ + +void ATTR ((noreturn)) +fnoret6 (void); + + +/* Exercise the handling of the mutually exclusive attributes + noreturn and alloc_align. */ + +void* ATTR ((noreturn)) +fnoret_alloc_align1 (int); /* { dg-message "previous declaration here" } */ + +void* ATTR ((alloc_align (1))) +fnoret_alloc_align1 (int); /* { dg-warning "ignoring attribute .alloc_align. because it conflicts with attribute .noreturn." } */ + +void* ATTR ((noreturn, alloc_align (1))) +fnoret_alloc_align2 (int); /* { dg-warning "ignoring attribute .alloc_align. because it conflicts with attribute .noreturn." } */ + + +void* ATTR ((noreturn)) ATTR ((alloc_align (1))) +fnoret_alloc_align3 (int); /* { dg-warning "ignoring attribute .alloc_align. because it conflicts with attribute .noreturn." } */ + + +void* ATTR ((alloc_align (1))) +falloc_align_noret1 (int); /* { dg-message "previous declaration here" } */ + +void* ATTR ((noreturn)) +falloc_align_noret1 (int); /* { dg-warning "ignoring attribute .noreturn. because it conflicts with attribute .alloc_align." } */ + + +void* ATTR ((alloc_align (1), noreturn)) +falloc_align_noret2 (int); /* { dg-warning "ignoring attribute .(noreturn|alloc_align). because it conflicts with attribute .(alloc_align|noreturn)." } */ + +void* ATTR ((alloc_align (1))) ATTR ((noreturn)) +falloc_align_noret3 (int); /* { dg-warning "ignoring attribute .(noreturn|alloc_align). because it conflicts with attribute .(noreturn|alloc_align)." } */ + + +/* Exercise the handling of the mutually exclusive attributes + noreturn and alloc_size. */ + +void* ATTR ((noreturn)) +fnoret_alloc_size1 (int); /* { dg-message "previous declaration here" } */ + +void* ATTR ((alloc_size (1))) +fnoret_alloc_size1 (int); /* { dg-warning "ignoring attribute .alloc_size. because it conflicts with attribute .noreturn." } */ + +void* ATTR ((noreturn, alloc_size (1))) +fnoret_alloc_size2 (int); /* { dg-warning "ignoring attribute .alloc_size. because it conflicts with attribute .noreturn." } */ + + +void* ATTR ((noreturn)) ATTR ((alloc_size (1))) +fnoret_alloc_size3 (int); /* { dg-warning "ignoring attribute .alloc_size. because it conflicts with attribute .noreturn." } */ + + +void* ATTR ((alloc_size (1))) +falloc_size_noret1 (int); /* { dg-message "previous declaration here" } */ + +void* ATTR ((noreturn)) +falloc_size_noret1 (int); /* { dg-warning "ignoring attribute .noreturn. because it conflicts with attribute .alloc_size." } */ + + +void* ATTR ((alloc_size (1), noreturn)) +falloc_size_noret2 (int); /* { dg-warning "ignoring attribute .noreturn. because it conflicts with attribute .alloc_size." } */ + +void* ATTR ((alloc_size (1))) ATTR ((noreturn)) +falloc_size_noret3 (int); /* { dg-warning "ignoring attribute .noreturn. because it conflicts with attribute .alloc_size." } */ + + +/* Exercise the handling of the mutually exclusive attributes + noreturn and const. */ + +int ATTR ((noreturn)) +fnoret_const1 (int); /* { dg-message "previous declaration here" } */ + +int ATTR ((const)) +fnoret_const1 (int); /* { dg-warning "ignoring attribute .const. because it conflicts with attribute .noreturn." } */ + +/* Unfortunately, attributes on a single declarations may not be processed + in the same order as specified... */ +int ATTR ((noreturn, const)) +fnoret_const2 (int); /* { dg-warning "ignoring attribute .const. because it conflicts with attribute .noreturn." } */ + + +int ATTR ((noreturn)) ATTR ((const)) +fnoret_const3 (int); /* { dg-warning "ignoring attribute .const. because it conflicts with attribute .noreturn." } */ + + +int ATTR ((const)) +fconst_noret1 (int); /* { dg-message "previous declaration here" } */ + +int ATTR ((noreturn)) +fconst_noret1 (int); /* { dg-warning "ignoring attribute .noreturn. because it conflicts with attribute .const." } */ + + +int ATTR ((const, noreturn)) +fconst_noret2 (int); /* { dg-warning "ignoring attribute .noreturn. because it conflicts with attribute .const." } */ + +int ATTR ((const)) ATTR ((noreturn)) +fconst_noret3 (int); /* { dg-warning "ignoring attribute .noreturn. because it conflicts with attribute .const." } */ + + +/* Exercise the handling of the mutually exclusive attributes + noreturn and malloc. */ + +void* ATTR ((noreturn)) +fnoret_malloc1 (int); /* { dg-message "previous declaration here" } */ + +void* ATTR ((malloc)) +fnoret_malloc1 (int); /* { dg-warning "ignoring attribute .malloc. because it conflicts with attribute .noreturn." } */ + +/* Unfortunately, attributes on a single declarations may not be processed + in the same order as specified... */ +void* ATTR ((noreturn, malloc)) +fnoret_malloc2 (int); /* { dg-warning "ignoring attribute .malloc. because it conflicts with attribute .noreturn." } */ + + +void* ATTR ((noreturn)) ATTR ((malloc)) +fnoret_malloc3 (int); /* { dg-warning "ignoring attribute .malloc. because it conflicts with attribute .noreturn." } */ + + +void* ATTR ((__malloc__)) +fmalloc_noret1 (int); + +void* ATTR ((malloc)) +fmalloc_noret1 (int); /* { dg-message "previous declaration here" } */ + +void* ATTR ((noreturn)) +fmalloc_noret1 (int); /* { dg-warning "ignoring attribute .noreturn. because it conflicts with attribute .malloc." } */ + + +void* ATTR ((malloc, noreturn)) +fmalloc_noret2 (int); /* { dg-warning "ignoring attribute .noreturn. because it conflicts with attribute .malloc." } */ + +void* ATTR ((malloc)) ATTR ((noreturn)) +fmalloc_noret3 (int); /* { dg-warning "ignoring attribute .noreturn. because it conflicts with attribute .malloc." } */ + + +/* Exercise the handling of the mutually exclusive attributes + noreturn and pure. */ + +int ATTR ((noreturn)) +fnoret_pure1 (int); /* { dg-message "previous declaration here" } */ + +int ATTR ((pure)) +fnoret_pure1 (int); /* { dg-warning "ignoring attribute .pure. because it conflicts with attribute .noreturn." } */ + +/* Unfortunately, attributes on a single declarations may not be processed + in the same order as specified... */ +int ATTR ((noreturn, pure)) +fnoret_pure2 (int); /* { dg-warning "ignoring attribute .pure. because it conflicts with attribute .noreturn." } */ + + +int ATTR ((noreturn)) ATTR ((pure)) +fnoret_pure3 (int); /* { dg-warning "ignoring attribute .pure. because it conflicts with attribute .noreturn." } */ + + +int ATTR ((__pure__)) +fpure_noret1 (int); + +int ATTR ((pure)) +fpure_noret1 (int); /* { dg-message "previous declaration here" } */ + +int ATTR ((noreturn)) +fpure_noret1 (int); /* { dg-warning "ignoring attribute .noreturn. because it conflicts with attribute .pure." } */ + + +int ATTR ((pure, noreturn)) +fpure_noret2 (int); /* { dg-warning "ignoring attribute .noreturn. because it conflicts with attribute .pur." } */ + +int ATTR ((pure)) ATTR ((noreturn)) +fpure_noret3 (int); /* { dg-warning "ignoring attribute .noreturn. because it conflicts with attribute .pure." } */ + + +/* Exercise the handling of the mutually exclusive attributes + noreturn and returns_twice. */ + +int ATTR ((noreturn)) +fnoret_returns_twice1 (int); /* { dg-message "previous declaration here" } */ + +int ATTR ((returns_twice)) +fnoret_returns_twice1 (int); /* { dg-warning "ignoring attribute .returns_twice. because it conflicts with attribute .noreturn." } */ + +/* Unfortunately, attributes on a single declarations may not be processed + in the same order as specified... */ +int ATTR ((noreturn, returns_twice)) +fnoret_returns_twice2 (int); /* { dg-warning "ignoring attribute .returns_twice. because it conflicts with attribute .noreturn." } */ + + +int ATTR ((noreturn)) ATTR ((returns_twice)) +fnoret_returns_twice3 (int); /* { dg-warning "ignoring attribute .returns_twice. because it conflicts with attribute .noreturn." } */ + + +int ATTR ((returns_twice)) +freturns_twice_noret1 (int); /* { dg-message "previous declaration here" } */ + +int ATTR ((noreturn)) +freturns_twice_noret1 (int); /* { dg-warning "ignoring attribute .noreturn. because it conflicts with attribute .returns_twice." } */ + + +int ATTR ((returns_twice, noreturn)) +freturns_twice_noret2 (int); /* { dg-warning "ignoring attribute .noreturn. because it conflicts with attribute .returns_twice." } */ + +int ATTR ((returns_twice)) ATTR ((noreturn)) +freturns_twice_noret3 (int); /* { dg-warning "ignoring attribute .noreturn. because it conflicts with attribute .returns_twice." } */ + + +/* Exercise the interaction of multiple combinations of mutually + exclusive attributes specified on distinct declarations. */ + +inline int ATTR ((always_inline)) +finline_cold_noreturn (int); + +inline int ATTR ((cold)) +finline_cold_noreturn (int); + +inline int ATTR ((noreturn)) +finline_cold_noreturn (int); + +inline int ATTR ((noinline)) +finline_cold_noreturn (int); /* { dg-warning "ignoring attribute .noinline. because it conflicts with attribute .always_inline." } */ + +inline int ATTR ((hot)) +finline_cold_noreturn (int); /* { dg-warning "ignoring attribute .hot. because it conflicts with attribute .cold." } */ + +inline int ATTR ((warn_unused_result)) +finline_cold_noreturn (int); /* { dg-warning "ignoring attribute .warn_unused_result. because it conflicts with attribute .noreturn." } */ + +inline int ATTR ((always_inline)) +finline_cold_noreturn (int); + +/* Expect no warning for the missing return statement below because + the function is noreturn. */ +inline int ATTR ((noreturn)) +finline_cold_noreturn (int i) { (void)&i; __builtin_abort (); } + + +/* Exercise the interaction of multiple combinations of mutually + exclusive attributes with some specified on the same declaration + and some on distinct declarations. */ + +inline int ATTR ((always_inline, hot)) +finline_hot_noret_align (int); + +inline int ATTR ((noreturn, noinline)) +finline_hot_noret_align (int); /* { dg-warning "ignoring attribute .noinline. because it conflicts with attribute .always_inline." } */ + +inline int ATTR ((cold, aligned (8))) +finline_hot_noret_align (int); /* { dg-warning "ignoring attribute .cold. because it conflicts with attribute .hot." } */ + +inline int ATTR ((warn_unused_result)) +finline_hot_noret_align (int); /* { dg-warning "ignoring attribute .warn_unused_result. because it conflicts with attribute .noreturn." } */ + +inline int ATTR ((aligned (4))) +finline_hot_noret_align (int); /* { dg-warning "ignoring attribute .aligned \\(4\\). because it conflicts with attribute .aligned \\(8\\)." } */ + +inline int ATTR ((aligned (8))) +finline_hot_noret_align (int); + +inline int ATTR ((const)) +finline_hot_noret_align (int); /* { dg-warning "ignoring attribute .const. because it conflicts with attribute .noreturn." } */ + +/* Expect no warning for the missing return statement below because + the function is noreturn. */ +inline int ATTR ((noreturn)) +finline_hot_noret_align (int i) { (void)&i; __builtin_abort (); } + + +/* Exercise variable attributes. */ + +extern int ATTR ((common)) +decl_common1; /* { dg-message "previous declaration here" } */ + +extern int ATTR ((nocommon)) +decl_common1; /* { dg-warning "ignoring attribute .nocommon. because it conflicts with attribute .common." } */ + + +extern int ATTR ((nocommon)) +decl_common2; /* { dg-message "previous declaration here" } */ + +extern int ATTR ((common)) +decl_common2; /* { dg-warning "ignoring attribute .common. because it conflicts with attribute .nocommon." } */ + + +extern int ATTR ((common, nocommon)) +decl_common3; /* { dg-warning "ignoring attribute .nocommon. because it conflicts with attribute .common." } */ + + +extern int ATTR ((common, nocommon)) +decl_common4; /* { dg-warning "ignoring attribute .nocommon. because it conflicts with attribute .common." } */ diff --git a/gcc/testsuite/g++.dg/Wattributes-2.C b/gcc/testsuite/g++.dg/Wattributes-2.C new file mode 100644 index 00000000000..1470b16c567 --- /dev/null +++ b/gcc/testsuite/g++.dg/Wattributes-2.C @@ -0,0 +1,35 @@ +// Test to verify that attributes on distinct overloads of a function +// with the same name are properly looked up and applied. +// { dg-do compile } +// { dg-options "-Wall" } + +int +foo (int); + +int __attribute__ ((noreturn)) +foo (int, int); + +int __attribute__ ((warn_unused_result)) +foo (int, int, int); + +int call_foo_1 () +{ + foo (1); +} // { dg-warning "\\\[-Wreturn-type]" } + +int call_foo_2 () +{ + foo (1, 2); +} + +int call_foo_3 () +{ + foo (1, 2, 3); // { dg-warning "\\\[-Wunused-result]" } +} // { dg-warning "\\\[-Wreturn-type]" } + +int call_foo_4 () +{ + // Make sure an error doesn't trigger bogus warnings or an ICE. + foo (1, 2, 3, 4); // { dg-error "no matching function" } + return 0; +} diff --git a/gcc/testsuite/gcc.dg/Wattributes-6.c b/gcc/testsuite/gcc.dg/Wattributes-6.c new file mode 100644 index 00000000000..902bcb61c30 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wattributes-6.c @@ -0,0 +1,439 @@ +/* { dg-do compile } + { dg-options "-Wall -Wattributes -ftrack-macro-expansion=0" } */ + +#define ATTR(attrlist) __attribute__ (attrlist) + +/* Exercise the handling of the mutually exclusive attributes + aligned and packed on a type definition. */ + +/* Pointless but benign. */ +struct ATTR ((aligned, aligned)) +AlignedAligned { int i; }; + +/* Aligned followed by packed on a type and vice versa has a valid use: + to decrease the alignment of a type to the specified boundary. */ +struct ATTR ((aligned, packed)) +AlignedPacked { int i; }; + +struct ATTR ((packed, aligned)) +PackedAligned { int i; }; + +struct ATTR ((aligned (2))) +AlignedMemberPacked +{ + int ATTR ((packed)) i; +}; + +struct ATTR ((packed)) +PackedMemberAligned +{ + int ATTR ((aligned (2))) i; +}; + +/* Silly but benign. */ +struct ATTR ((packed, packed)) +PackedPacked { int i; }; + + +/* Exercise the handling of the mutually exclusive attributes + aligned and packed on a function declaration. */ + +void ATTR ((aligned (8), packed)) +faligned8_1 (void); /* { dg-warning ".packed. attribute ignored" } */ + +void ATTR ((aligned (8))) +faligned8_2 (void); /* { dg-message "previous declaration here" "" { xfail *-*-* } } */ + +void ATTR ((packed)) +faligned8_2 (void); /* { dg-warning ".packed. attribute ignored" } */ + +/* Exercise the handling of the mutually exclusive attributes + always_inline and noinline (in that order). */ + +inline void ATTR ((always_inline)) +falways_inline1 (void); + +inline void ATTR ((__always_inline__)) +falways_inline1 (void); + +/* Verify that repeating attribute always_inline on the same declaration + doesn't trigger a warning. */ +inline void ATTR ((always_inline, __always_inline__)) +falways_inline1 (void); + +/* Verify that repeating attribute always_inline on a distinct declaration + doesn't trigger a warning. */ +inline void ATTR ((always_inline)) +falways_inline1 (void); /* { dg-message "previous declaration here" } */ + +/* Verify a warning for noinline conflict. */ +void ATTR ((noinline)) +falways_inline1 (void) { } /* { dg-warning "ignoring attribute .noinline. because it conflicts with attribute .always_inline." } */ + +/* And again. */ +void ATTR ((always_inline)) +falways_inline1 (void); + + +/* Exercise the handling of the mutually exclusive attributes + noinline and always_inline (in that order). */ + +void ATTR ((noinline)) +fnoinline1 (void); + +void ATTR ((__noinline__)) +fnoinline1 (void); + +/* Verify that repeating attribute noinline on the same declaration + doesn't trigger a warning. */ +void ATTR ((noinline, __noinline__)) +fnoinline1 (void); + +/* Verify that repeating attribute noinline on a distinct declaration + doesn't trigger a warning. */ +void ATTR ((noinline)) +fnoinline1 (void); /* { dg-message "previous declaration here" } */ + +/* Verify a warning for always_inline conflict. */ +void ATTR ((always_inline)) +fnoinline1 (void) { } /* { dg-warning "ignoring attribute .always_inline. because it conflicts with attribute .noinline." } */ + +/* Verify a warning for gnu_inline conflict. */ +inline void ATTR ((gnu_inline)) +fnoinline1 (void); /* { dg-warning "ignoring attribute .gnu_inline. because it conflicts with attribute .noinline." } */ + /* { dg-warning "follows declaration with attribute .noinline." "inline noinline" { target *-*-* } .-1 } */ + +/* And again. */ +void ATTR ((noinline)) +fnoinline1 (void); /* { dg-warning "follows inline declaration" } */ + + +/* Exercise the handling of the mutually exclusive attributes + noreturn and warn_unused_result. */ + +int ATTR ((__noreturn__)) +fnoret1 (void); + +int ATTR ((noreturn)) +fnoret1 (void); /* { dg-message "previous declaration here" } */ + +int ATTR ((warn_unused_result)) +fnoret1 (void); /* { dg-warning "ignoring attribute .warn_unused_result. because it conflicts with attribute .noreturn." } */ + +/* Verify that repeating attribute noreturn doesn't trigger a warning. */ +int ATTR ((noreturn)) fnoret1 (void); + +int call_noret1 (void) +{ + /* Verify that attribute warn_unused_result was, in fact, ignored + on the second declaration of fnoret1. */ + fnoret1 (); +} + +int ATTR ((noreturn, warn_unused_result)) +fnoret2 (void); /* { dg-warning "ignoring attribute .warn_unused_result. because it conflicts with attribute .noreturn." } */ + +/* Verify that repeating attribute noreturn doesn't trigger a warning. */ +int ATTR ((noreturn)) fnoret2 (void); + +int call_noret2 (void) +{ + /* Verify that attribute warn_unused_result was, in fact, ignored + on the second declaration of fnoret2. */ + fnoret2 (); +} + +/* Verify that attribute noreturn isn't diagnosed on a declaration + that was previously declared warn_unused_result and that attribute + was dropped (because the function returs void). */ + +void ATTR ((warn_unused_result)) +fnorety6 (void); /* { dg-warning ".warn_unused_result. attribute ignored" } */ + +void ATTR ((noreturn)) +fnoret6 (void); + + +/* Exercise the handling of the mutually exclusive attributes + noreturn and alloc_align. */ + +void* ATTR ((noreturn)) +fnoret_alloc_align1 (int); /* { dg-message "previous declaration here" } */ + +void* ATTR ((alloc_align (1))) +fnoret_alloc_align1 (int); /* { dg-warning "ignoring attribute .alloc_align. because it conflicts with attribute .noreturn." } */ + +void* ATTR ((noreturn, alloc_align (1))) +fnoret_alloc_align2 (int); /* { dg-warning "ignoring attribute .alloc_align. because it conflicts with attribute .noreturn." } */ + + +void* ATTR ((noreturn)) ATTR ((alloc_align (1))) +fnoret_alloc_align3 (int); /* { dg-warning "ignoring attribute .alloc_align. because it conflicts with attribute .noreturn." } */ + + +void* ATTR ((alloc_align (1))) +falloc_align_noret1 (int); /* { dg-message "previous declaration here" } */ + +void* ATTR ((noreturn)) +falloc_align_noret1 (int); /* { dg-warning "ignoring attribute .noreturn. because it conflicts with attribute .alloc_align." } */ + + +void* ATTR ((alloc_align (1), noreturn)) +falloc_align_noret2 (int); /* { dg-warning "ignoring attribute .(noreturn|alloc_align). because it conflicts with attribute .(alloc_align|noreturn)." } */ + +void* ATTR ((alloc_align (1))) ATTR ((noreturn)) +falloc_align_noret3 (int); /* { dg-warning "ignoring attribute .(noreturn|alloc_align). because it conflicts with attribute .(noreturn|alloc_align)." } */ + + +/* Exercise the handling of the mutually exclusive attributes + noreturn and alloc_size. */ + +void* ATTR ((noreturn)) +fnoret_alloc_size1 (int); /* { dg-message "previous declaration here" } */ + +void* ATTR ((alloc_size (1))) +fnoret_alloc_size1 (int); /* { dg-warning "ignoring attribute .alloc_size. because it conflicts with attribute .noreturn." } */ + +void* ATTR ((noreturn, alloc_size (1))) +fnoret_alloc_size2 (int); /* { dg-warning "ignoring attribute .alloc_size. because it conflicts with attribute .noreturn." } */ + + +void* ATTR ((noreturn)) ATTR ((alloc_size (1))) +fnoret_alloc_size3 (int); /* { dg-warning "ignoring attribute .alloc_size. because it conflicts with attribute .noreturn." } */ + + +void* ATTR ((alloc_size (1))) +falloc_size_noret1 (int); /* { dg-message "previous declaration here" } */ + +void* ATTR ((noreturn)) +falloc_size_noret1 (int); /* { dg-warning "ignoring attribute .noreturn. because it conflicts with attribute .alloc_size." } */ + + +void* ATTR ((alloc_size (1), noreturn)) +falloc_size_noret2 (int); /* { dg-warning "ignoring attribute .noreturn. because it conflicts with attribute .alloc_size." } */ + +void* ATTR ((alloc_size (1))) ATTR ((noreturn)) +falloc_size_noret3 (int); /* { dg-warning "ignoring attribute .noreturn. because it conflicts with attribute .alloc_size." } */ + + +/* Exercise the handling of the mutually exclusive attributes + noreturn and const. */ + +int ATTR ((noreturn)) +fnoret_const1 (int); /* { dg-message "previous declaration here" } */ + +int ATTR ((const)) +fnoret_const1 (int); /* { dg-warning "ignoring attribute .const. because it conflicts with attribute .noreturn." } */ + +/* Unfortunately, attributes on a single declarations may not be processed + in the same order as specified... */ +int ATTR ((noreturn, const)) +fnoret_const2 (int); /* { dg-warning "ignoring attribute .const. because it conflicts with attribute .noreturn." } */ + + +int ATTR ((noreturn)) ATTR ((const)) +fnoret_const3 (int); /* { dg-warning "ignoring attribute .const. because it conflicts with attribute .noreturn." } */ + + +int ATTR ((const)) +fconst_noret1 (int); /* { dg-message "previous declaration here" } */ + +int ATTR ((noreturn)) +fconst_noret1 (int); /* { dg-warning "ignoring attribute .noreturn. because it conflicts with attribute .const." } */ + + +int ATTR ((const, noreturn)) +fconst_noret2 (int); /* { dg-warning "ignoring attribute .noreturn. because it conflicts with attribute .const." } */ + +int ATTR ((const)) ATTR ((noreturn)) +fconst_noret3 (int); /* { dg-warning "ignoring attribute .noreturn. because it conflicts with attribute .const." } */ + + +/* Exercise the handling of the mutually exclusive attributes + noreturn and malloc. */ + +void* ATTR ((noreturn)) +fnoret_malloc1 (int); /* { dg-message "previous declaration here" } */ + +void* ATTR ((malloc)) +fnoret_malloc1 (int); /* { dg-warning "ignoring attribute .malloc. because it conflicts with attribute .noreturn." } */ + +/* Unfortunately, attributes on a single declarations may not be processed + in the same order as specified... */ +void* ATTR ((noreturn, malloc)) +fnoret_malloc2 (int); /* { dg-warning "ignoring attribute .malloc. because it conflicts with attribute .noreturn." } */ + + +void* ATTR ((noreturn)) ATTR ((malloc)) +fnoret_malloc3 (int); /* { dg-warning "ignoring attribute .malloc. because it conflicts with attribute .noreturn." } */ + + +void* ATTR ((__malloc__)) +fmalloc_noret1 (int); + +void* ATTR ((malloc)) +fmalloc_noret1 (int); /* { dg-message "previous declaration here" } */ + +void* ATTR ((noreturn)) +fmalloc_noret1 (int); /* { dg-warning "ignoring attribute .noreturn. because it conflicts with attribute .malloc." } */ + + +void* ATTR ((malloc, noreturn)) +fmalloc_noret2 (int); /* { dg-warning "ignoring attribute .noreturn. because it conflicts with attribute .malloc." } */ + +void* ATTR ((malloc)) ATTR ((noreturn)) +fmalloc_noret3 (int); /* { dg-warning "ignoring attribute .noreturn. because it conflicts with attribute .malloc." } */ + + +/* Exercise the handling of the mutually exclusive attributes + noreturn and pure. */ + +int ATTR ((noreturn)) +fnoret_pure1 (int); /* { dg-message "previous declaration here" } */ + +int ATTR ((pure)) +fnoret_pure1 (int); /* { dg-warning "ignoring attribute .pure. because it conflicts with attribute .noreturn." } */ + +/* Unfortunately, attributes on a single declarations may not be processed + in the same order as specified... */ +int ATTR ((noreturn, pure)) +fnoret_pure2 (int); /* { dg-warning "ignoring attribute .pure. because it conflicts with attribute .noreturn." } */ + + +int ATTR ((noreturn)) ATTR ((pure)) +fnoret_pure3 (int); /* { dg-warning "ignoring attribute .pure. because it conflicts with attribute .noreturn." } */ + + +int ATTR ((__pure__)) +fpure_noret1 (int); + +int ATTR ((pure)) +fpure_noret1 (int); /* { dg-message "previous declaration here" } */ + +int ATTR ((noreturn)) +fpure_noret1 (int); /* { dg-warning "ignoring attribute .noreturn. because it conflicts with attribute .pure." } */ + + +int ATTR ((pure, noreturn)) +fpure_noret2 (int); /* { dg-warning "ignoring attribute .noreturn. because it conflicts with attribute .pur." } */ + +int ATTR ((pure)) ATTR ((noreturn)) +fpure_noret3 (int); /* { dg-warning "ignoring attribute .noreturn. because it conflicts with attribute .pure." } */ + + +/* Exercise the handling of the mutually exclusive attributes + noreturn and returns_twice. */ + +int ATTR ((noreturn)) +fnoret_returns_twice1 (int); /* { dg-message "previous declaration here" } */ + +int ATTR ((returns_twice)) +fnoret_returns_twice1 (int); /* { dg-warning "ignoring attribute .returns_twice. because it conflicts with attribute .noreturn." } */ + +/* Unfortunately, attributes on a single declarations may not be processed + in the same order as specified... */ +int ATTR ((noreturn, returns_twice)) +fnoret_returns_twice2 (int); /* { dg-warning "ignoring attribute .returns_twice. because it conflicts with attribute .noreturn." } */ + + +int ATTR ((noreturn)) ATTR ((returns_twice)) +fnoret_returns_twice3 (int); /* { dg-warning "ignoring attribute .returns_twice. because it conflicts with attribute .noreturn." } */ + + +int ATTR ((returns_twice)) +freturns_twice_noret1 (int); /* { dg-message "previous declaration here" } */ + +int ATTR ((noreturn)) +freturns_twice_noret1 (int); /* { dg-warning "ignoring attribute .noreturn. because it conflicts with attribute .returns_twice." } */ + + +int ATTR ((returns_twice, noreturn)) +freturns_twice_noret2 (int); /* { dg-warning "ignoring attribute .noreturn. because it conflicts with attribute .returns_twice." } */ + +int ATTR ((returns_twice)) ATTR ((noreturn)) +freturns_twice_noret3 (int); /* { dg-warning "ignoring attribute .noreturn. because it conflicts with attribute .returns_twice." } */ + + +/* Exercise the interaction of multiple combinations of mutually + exclusive attributes specified on distinct declarations. */ + +inline int ATTR ((always_inline)) +finline_cold_noreturn (int); + +inline int ATTR ((cold)) +finline_cold_noreturn (int); + +inline int ATTR ((noreturn)) +finline_cold_noreturn (int); + +inline int ATTR ((noinline)) +finline_cold_noreturn (int); /* { dg-warning "ignoring attribute .noinline. because it conflicts with attribute .always_inline." } */ + +inline int ATTR ((hot)) +finline_cold_noreturn (int); /* { dg-warning "ignoring attribute .hot. because it conflicts with attribute .cold." } */ + +inline int ATTR ((warn_unused_result)) +finline_cold_noreturn (int); /* { dg-warning "ignoring attribute .warn_unused_result. because it conflicts with attribute .noreturn." } */ + +inline int ATTR ((always_inline)) +finline_cold_noreturn (int); + +/* Expect no warning for the missing return statement below because + the function is noreturn. */ +inline int ATTR ((noreturn)) +finline_cold_noreturn (int i) { (void)&i; __builtin_abort (); } + + +/* Exercise the interaction of multiple combinations of mutually + exclusive attributes with some specified on the same declaration + and some on distinct declarations. */ + +inline int ATTR ((always_inline, hot)) +finline_hot_noret_align (int); + +inline int ATTR ((noreturn, noinline)) +finline_hot_noret_align (int); /* { dg-warning "ignoring attribute .noinline. because it conflicts with attribute .always_inline." } */ + +inline int ATTR ((cold, aligned (8))) +finline_hot_noret_align (int); /* { dg-warning "ignoring attribute .cold. because it conflicts with attribute .hot." } */ + +inline int ATTR ((warn_unused_result)) +finline_hot_noret_align (int); /* { dg-warning "ignoring attribute .warn_unused_result. because it conflicts with attribute .noreturn." } */ + +inline int ATTR ((aligned (4))) +finline_hot_noret_align (int); /* { dg-warning "ignoring attribute .aligned \\(4\\). because it conflicts with attribute .aligned \\(8\\)." } */ + +inline int ATTR ((aligned (8))) +finline_hot_noret_align (int); + +inline int ATTR ((const)) +finline_hot_noret_align (int); /* { dg-warning "ignoring attribute .const. because it conflicts with attribute .noreturn." } */ + +/* Expect no warning for the missing return statement below because + the function is noreturn. */ +inline int ATTR ((noreturn)) +finline_hot_noret_align (int i) { (void)&i; __builtin_abort (); } + + +/* Exercise variable attributes. */ + +extern int ATTR ((common)) +decl_common1; /* { dg-message "previous declaration here" } */ + +extern int ATTR ((nocommon)) +decl_common1; /* { dg-warning "ignoring attribute .nocommon. because it conflicts with attribute .common." } */ + + +extern int ATTR ((nocommon)) +decl_common2; /* { dg-message "previous declaration here" } */ + +extern int ATTR ((common)) +decl_common2; /* { dg-warning "ignoring attribute .common. because it conflicts with attribute .nocommon." } */ + + +extern int ATTR ((common, nocommon)) +decl_common3; /* { dg-warning "ignoring attribute .nocommon. because it conflicts with attribute .common." } */ + + +extern int ATTR ((common, nocommon)) +decl_common4; /* { dg-warning "ignoring attribute .nocommon. because it conflicts with attribute .common." } */ diff --git a/gcc/testsuite/gcc.dg/Wattributes-7.c b/gcc/testsuite/gcc.dg/Wattributes-7.c new file mode 100644 index 00000000000..0904742b01d --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wattributes-7.c @@ -0,0 +1,74 @@ +/* PR c/81566 - invalid attribute aligned accepted on functions + { dg-do compile } + { dg-options "-Wall -Wattributes -ftrack-macro-expansion=0" } */ + +#define ATTR(list) __attribute__ (list) +#define ALIGN(n) ATTR ((aligned (n))) + +/* It's okay to increase the alignment of a function. */ + +void ALIGN (16) ALIGN (32) +falign32_1 (void); + +void ALIGN (16) falign32_2 (void); +void ALIGN (32) falign32_2 (void); + +void falign32_2 (void) { } + +void ALIGN (32) falign32_2 (void); + +/* It's not okay to decrease it. */ + +void ALIGN (32) ALIGN (16) +falign64_3 (void); /* { dg-warning "ignoring attribute .aligned \\(16\\). because it conflicts with attribute .aligned \\(32\\)." } */ + +void ALIGN (32) +falign64_3 (void); + +void falign64_3 (void); + +void falign64_3 (void) { } + + +void ALIGN (32) +falign64_4 (void); /* { dg-message "previous declaration here" } */ + +void ALIGN (16) +falign64_4 (void); /* { dg-warning "ignoring attribute .aligned \\(16\\). because it conflicts with attribute .aligned \\(32\\)." } */ + +void ALIGN (32) +falign64_4 (void); /* { dg-message "previous declaration here" } */ + +void ALIGN (16) +falign64_4 (void); /* { dg-warning "ignoring attribute .aligned \\(16\\). because it conflicts with attribute .aligned \\(32\\)." } */ + +void ALIGN (64) +falign64_4 (void); + +void ALIGN (32) +falign64_4 (void); /* { dg-warning "ignoring attribute .aligned \\(32\\). because it conflicts with attribute .aligned \\(64\\)." } */ + +void falign64_4 (void); + +void ALIGN (64) +falign64_4 (void) { } + +void falign64_4 (void); + +void ALIGN (64) +falign64_4 (void); + + +void ATTR ((aligned (16), aligned (32))) +falign64_5 (void); + +void ATTR ((aligned (32), aligned (64))) +falign64_5 (void); + +void ATTR ((aligned (16), aligned (32), aligned (64))) +falign64_5 (void); /* { dg-warning "ignoring attribute .aligned \\(16\\). because it conflicts with attribute .aligned \\(64\\)." } */ + /* { dg-warning "ignoring attribute .aligned \\(32\\). because it conflicts with attribute .aligned \\(64\\)." "" { target *-*-* } .-1 } */ + + +void ATTR ((aligned (16), aligned (32), aligned (16))) +falign64_6 (void); /* { dg-warning "ignoring attribute .aligned \\(16\\). because it conflicts with attribute .aligned \\(32\\)." } */ -- 2.30.2