aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2021-04-15 15:49:30 -0600
committerMartin Sebor <msebor@redhat.com>2021-04-15 15:51:00 -0600
commitda879e01ecd35737c18be1da3324f4560aba1961 (patch)
treef51df9e8918cf84bc287bbdd0e7f4b9300da023f
parent58fe131b91007793c0f12f5fe6cab3f1a017d0fa (diff)
downloadgcc-da879e01ecd35737c18be1da3324f4560aba1961.zip
gcc-da879e01ecd35737c18be1da3324f4560aba1961.tar.gz
gcc-da879e01ecd35737c18be1da3324f4560aba1961.tar.bz2
Propagate type attribute when merging extern declarations at local scope.
Resolves: PR c/99420 - bogus -Warray-parameter on a function redeclaration in function scope PR c/99972 - missing -Wunused-result on a call to a locally redeclared warn_unused_result function gcc/c/ChangeLog: PR c/99420 PR c/99972 * c-decl.c (pushdecl): Always propagate type attribute. gcc/testsuite/ChangeLog: PR c/99420 PR c/99972 * gcc.dg/Warray-parameter-9.c: New test. * gcc.dg/Wnonnull-6.c: New test. * gcc.dg/Wreturn-type3.c: New test. * gcc.dg/Wunused-result.c: New test. * gcc.dg/attr-noreturn.c: New test. * gcc.dg/attr-returns-nonnull.c: New test.
-rw-r--r--gcc/c/c-decl.c9
-rw-r--r--gcc/testsuite/gcc.dg/Warray-parameter-9.c54
-rw-r--r--gcc/testsuite/gcc.dg/Wnonnull-6.c93
-rw-r--r--gcc/testsuite/gcc.dg/Wreturn-type3.c54
-rw-r--r--gcc/testsuite/gcc.dg/Wunused-result.c50
-rw-r--r--gcc/testsuite/gcc.dg/attr-noreturn.c64
-rw-r--r--gcc/testsuite/gcc.dg/attr-returns-nonnull.c58
7 files changed, 377 insertions, 5 deletions
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 3c25451..3ea4708 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -3263,11 +3263,10 @@ pushdecl (tree x)
else
thistype = type;
b->u.type = TREE_TYPE (b->decl);
- if (TREE_CODE (b->decl) == FUNCTION_DECL
- && fndecl_built_in_p (b->decl))
- thistype
- = build_type_attribute_variant (thistype,
- TYPE_ATTRIBUTES (b->u.type));
+ /* Propagate the type attributes to the decl. */
+ thistype
+ = build_type_attribute_variant (thistype,
+ TYPE_ATTRIBUTES (b->u.type));
TREE_TYPE (b->decl) = thistype;
bind (name, b->decl, scope, /*invisible=*/false, /*nested=*/true,
locus);
diff --git a/gcc/testsuite/gcc.dg/Warray-parameter-9.c b/gcc/testsuite/gcc.dg/Warray-parameter-9.c
new file mode 100644
index 0000000..b5d3d96
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-parameter-9.c
@@ -0,0 +1,54 @@
+/* PR c/99420 - bogus -Warray-parameter on a function redeclaration
+ in function scope
+ { dg-do compile }
+ { dg-options "-Wall" } */
+
+extern int a1[1], a2[2], a3[3], a4[4];
+
+void fa1 (int [1]); // { dg-message "previously declared as 'int\\\[1]'" }
+void fa1 (int [1]);
+
+
+void nested_decl (void)
+{
+ void fa2 (int [2]);
+
+ fa2 (a1); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" }
+ fa2 (a2);
+ fa2 (a3);
+
+ void fa3 (int [3]);
+
+ fa3 (a2); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" }
+ fa3 (a3);
+}
+
+
+void nested_redecl (void)
+{
+ void fa1 (int [2]); // { dg-warning "argument 1 of type 'int\\\[2]' with mismatched bound" }
+
+ fa1 (a1 + 1); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" }
+ fa1 (a1);
+
+ void fa2 (int [2]); // { dg-bogus "\\\[-Warray-parameter" }
+
+ fa2 (a1); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" }
+ fa2 (a2);
+ fa2 (a3);
+
+ void fa3 (int [3]); // { dg-bogus "\\\[-Warray-parameter" }
+
+ fa3 (a2); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" }
+ fa3 (a3);
+
+ void fa4 (int [4]);
+}
+
+void fa4 (int [5]); // { dg-warning "\\\[-Warray-parameter" }
+
+void call_fa4 (void)
+{
+ fa4 (a4);
+ fa4 (a3); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" }
+}
diff --git a/gcc/testsuite/gcc.dg/Wnonnull-6.c b/gcc/testsuite/gcc.dg/Wnonnull-6.c
new file mode 100644
index 0000000..48f09da
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wnonnull-6.c
@@ -0,0 +1,93 @@
+/* Verify that attribute nonnull on global and local function declarations
+ or those to pointers to functions is merged.
+ { dg-do compile }
+ { dg-options "-Wall" } */
+
+void fnonnull_local_local (void)
+{
+ extern __attribute__ ((nonnull)) void fnonnull1 (void*);
+
+ fnonnull1 (0); // { dg-warning "\\\[-Wnonnull" }
+}
+
+void gnonnull_local_local (void)
+{
+ extern void fnonnull1 (void*);
+
+ fnonnull1 (0); // { dg-warning "\\\[-Wnonnull" }
+}
+
+
+void fnonnull_local_global (void)
+{
+ extern __attribute__ ((nonnull)) void fnonnull2 (void*);
+
+ fnonnull2 (0); // { dg-warning "\\\[-Wnonnull" }
+}
+
+extern void fnonnull2 (void*);
+
+void gnonnull_local_global (void)
+{
+ fnonnull2 (0); // { dg-warning "\\\[-Wnonnull" }
+}
+
+
+extern __attribute__ ((nonnull)) void fnonnull3 (void*);
+
+void fnonnull_global_local (void)
+{
+ fnonnull3 (0); // { dg-warning "\\\[-Wnonnull" }
+}
+
+void gnonnull_global_local (void)
+{
+ extern void fnonnull3 (void*);
+
+ fnonnull3 (0); // { dg-warning "\\\[-Wnonnull" }
+}
+
+
+void pfnonnull_local_local (void)
+{
+ extern __attribute__ ((nonnull)) void (*pfnonnull1) (void*);
+
+ pfnonnull1 (0); // { dg-warning "\\\[-Wnonnull" }
+}
+
+void gpnonnull_local_local (void)
+{
+ extern void (*pfnonnull1) (void*);
+
+ pfnonnull1 (0); // { dg-warning "\\\[-Wnonnull" "pr?????" { xfail *-*-* } }
+}
+
+
+void pfnonnull_local_global (void)
+{
+ extern __attribute__ ((nonnull)) void (*pfnonnull2) (void*);
+
+ pfnonnull2 (0); // { dg-warning "\\\[-Wnonnull" }
+}
+
+extern void (*pfnonnull2) (void*);
+
+void gpnonnull_local_global (void)
+{
+ pfnonnull2 (0); // { dg-warning "\\\[-Wnonnull" "pr?????" { xfail *-*-* } }
+}
+
+
+extern __attribute__ ((nonnull)) void (*pfnonnull3) (void*);
+
+void pfnonnull_global_local (void)
+{
+ pfnonnull3 (0); // { dg-warning "\\\[-Wnonnull" }
+}
+
+void gpnonnull_global_local (void)
+{
+ extern void (*pfnonnull3) (void*);
+
+ pfnonnull3 (0); // { dg-warning "\\\[-Wnonnull" }
+}
diff --git a/gcc/testsuite/gcc.dg/Wreturn-type3.c b/gcc/testsuite/gcc.dg/Wreturn-type3.c
new file mode 100644
index 0000000..93596b3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wreturn-type3.c
@@ -0,0 +1,54 @@
+/* Verify that attribute noreturn on global and local function declarations
+ is merged.
+ { dg-do compile }
+ { dg-options "-Wall" } */
+
+int fnr_local_local (void)
+{
+ __attribute__ ((noreturn)) void fnr1 (void);
+
+ fnr1 ();
+ // no return, no warning (good)
+}
+
+int gnr_local_local (void)
+{
+ void fnr1 (void);
+
+ fnr1 ();
+ // no return, no warning (good)
+}
+
+
+int fnr_local_global (void)
+{
+ __attribute__ ((noreturn)) void fnr2 (void);
+
+ fnr2 ();
+ // no return, no warning (good)
+}
+
+void fnr2 (void);
+
+int gnr_local_global (void)
+{
+ fnr2 ();
+ // no return, no warning (good)
+}
+
+
+__attribute__ ((noreturn)) void fnr3 (void);
+
+int fnr_global_local (void)
+{
+ fnr3 ();
+ // no return, no warning (good)
+}
+
+int gnr_global_local (void)
+{
+ void fnr3 (void);
+
+ fnr3 ();
+ // no return, no warning (good)
+}
diff --git a/gcc/testsuite/gcc.dg/Wunused-result.c b/gcc/testsuite/gcc.dg/Wunused-result.c
new file mode 100644
index 0000000..c0bb9ae
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wunused-result.c
@@ -0,0 +1,50 @@
+/* PR c/99972 - missing -Wunused-result on a call to a locally redeclared
+ warn_unused_result function
+ { dg-do compile }
+ { dg-options "-Wall" } */
+
+void gwur_local_local (void)
+{
+ __attribute__ ((warn_unused_result)) int fwur1 (void);
+
+ fwur1 (); // { dg-warning "\\\[-Wunused-result" }
+}
+
+void hwur_local_local (void)
+{
+ /* Verify the attribute from the declaration above is copied/merged
+ into the declaration below. */
+ int fwur1 (void);
+
+ fwur1 (); // { dg-warning "\\\[-Wunused-result" }
+}
+
+
+void gwur_local_global (void)
+{
+ __attribute__ ((warn_unused_result)) int fwur2 (void);
+
+ fwur2 (); // { dg-warning "\\\[-Wunused-result" }
+}
+
+int fwur2 (void);
+
+void hwur_local_global (void)
+{
+ fwur2 (); // { dg-warning "\\\[-Wunused-result" }
+}
+
+
+__attribute__ ((warn_unused_result)) int fwur3 (void);
+
+void gwur_global_local (void)
+{
+ fwur3 (); // { dg-warning "\\\[-Wunused-result" }
+}
+
+void hwur_global_local (void)
+{
+ int fwur3 (void);
+
+ fwur3 (); // { dg-warning "\\\[-Wunused-result" }
+}
diff --git a/gcc/testsuite/gcc.dg/attr-noreturn.c b/gcc/testsuite/gcc.dg/attr-noreturn.c
new file mode 100644
index 0000000..8d58f6e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/attr-noreturn.c
@@ -0,0 +1,64 @@
+/* Verify that attribute noreturn on global and local function declarations
+ is merged.
+ { dg-do compile }
+ { dg-options "-Wall -fdump-tree-optimized" } */
+
+void foo (void);
+
+int fnr_local_local (void)
+{
+ __attribute__ ((noreturn)) void fnr1 (void);
+
+ fnr1 ();
+
+ foo ();
+}
+
+int gnr_local_local (void)
+{
+ void fnr1 (void);
+
+ fnr1 ();
+
+ foo ();
+}
+
+
+int fnr_local_global (void)
+{
+ __attribute__ ((noreturn)) void fnr2 (void);
+
+ fnr2 ();
+
+ foo ();
+}
+
+void fnr2 (void);
+
+int gnr_local_global (void)
+{
+ fnr2 ();
+
+ foo ();
+}
+
+
+__attribute__ ((noreturn)) void fnr3 (void);
+
+int fnr_global_local (void)
+{
+ fnr3 ();
+
+ foo ();
+}
+
+int gnr_global_local (void)
+{
+ void fnr3 (void);
+
+ fnr3 ();
+
+ foo ();
+}
+
+/* { dg-final { scan-tree-dump-not "foo" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/attr-returns-nonnull.c b/gcc/testsuite/gcc.dg/attr-returns-nonnull.c
new file mode 100644
index 0000000..22ee30a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/attr-returns-nonnull.c
@@ -0,0 +1,58 @@
+/* Verify that attribute returns_nonnull on global and local function
+ declarations is merged.
+ { dg-do compile }
+ { dg-options "-Wall -fdump-tree-optimized" } */
+
+void foo (void);
+
+
+void frnn_local_local (void)
+{
+ __attribute__ ((returns_nonnull)) void* frnn1 (void);
+
+ if (!frnn1 ())
+ foo ();
+}
+
+void gnr_local_local (void)
+{
+ void* frnn1 (void);
+
+ if (!frnn1 ())
+ foo ();
+}
+
+void frnn_local_global (void)
+{
+ __attribute__ ((returns_nonnull)) void* frnn2 (void);
+
+ if (!frnn2 ())
+ foo ();
+}
+
+void* frnn2 (void);
+
+void gnr_local_global (void)
+{
+ if (!frnn2 ())
+ foo ();
+}
+
+__attribute__ ((returns_nonnull)) void* frnn3 (void);
+
+void frnn_global_local (void)
+{
+ if (!frnn3 ())
+ foo ();
+}
+
+void gnr_global_local (void)
+{
+ void* frnn3 (void);
+
+ if (!frnn3 ())
+ foo ();
+}
+
+
+/* { dg-final { scan-tree-dump-not "foo" "optimized" } } */