aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2017-12-11 23:21:55 +0000
committerMartin Sebor <msebor@gcc.gnu.org>2017-12-11 16:21:55 -0700
commiteedff70182852a43d62a463c4dd65cdd8d567c70 (patch)
treef29d5072d6dba41cdf24b54d18ce8be5bc426041
parent0242c7f0aac22e47b73046b2d60bb5de68057d6a (diff)
downloadgcc-eedff70182852a43d62a463c4dd65cdd8d567c70.zip
gcc-eedff70182852a43d62a463c4dd65cdd8d567c70.tar.gz
gcc-eedff70182852a43d62a463c4dd65cdd8d567c70.tar.bz2
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
-rw-r--r--gcc/testsuite/ChangeLog11
-rw-r--r--gcc/testsuite/c-c++-common/Wattributes-2.c74
-rw-r--r--gcc/testsuite/c-c++-common/Wattributes.c439
-rw-r--r--gcc/testsuite/g++.dg/Wattributes-2.C35
-rw-r--r--gcc/testsuite/gcc.dg/Wattributes-6.c439
-rw-r--r--gcc/testsuite/gcc.dg/Wattributes-7.c74
6 files changed, 1072 insertions, 0 deletions
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 884c722..ecb6ac6 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,14 @@
+2017-12-11 Martin Sebor <msebor@redhat.com>
+
+ 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 <cel@us.ibm.com>
* 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 0000000..0904742
--- /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 0000000..902bcb6
--- /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 0000000..1470b16
--- /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 0000000..902bcb6
--- /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 0000000..0904742
--- /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\\)." } */