]> git.ipfire.org Git - people/ms/gcc.git/commitdiff
Propagate type attribute when merging extern declarations at local scope.
authorMartin Sebor <msebor@redhat.com>
Thu, 15 Apr 2021 21:49:30 +0000 (15:49 -0600)
committerMartin Sebor <msebor@redhat.com>
Thu, 15 Apr 2021 21:51:00 +0000 (15:51 -0600)
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.

gcc/c/c-decl.c
gcc/testsuite/gcc.dg/Warray-parameter-9.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wnonnull-6.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wreturn-type3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wunused-result.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/attr-noreturn.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/attr-returns-nonnull.c [new file with mode: 0644]

index 3c254511bd88f7d508aed40922df6ebc5136b6e0..3ea4708c5075d9274601a0676f86a6900a9345b0 100644 (file)
@@ -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 (file)
index 0000000..b5d3d96
--- /dev/null
@@ -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 (file)
index 0000000..48f09da
--- /dev/null
@@ -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 (file)
index 0000000..93596b3
--- /dev/null
@@ -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 (file)
index 0000000..c0bb9ae
--- /dev/null
@@ -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 (file)
index 0000000..8d58f6e
--- /dev/null
@@ -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 (file)
index 0000000..22ee30a
--- /dev/null
@@ -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" } } */