diff options
author | Martin Sebor <msebor@redhat.com> | 2021-04-15 15:49:30 -0600 |
---|---|---|
committer | Martin Sebor <msebor@redhat.com> | 2021-04-15 15:51:00 -0600 |
commit | da879e01ecd35737c18be1da3324f4560aba1961 (patch) | |
tree | f51df9e8918cf84bc287bbdd0e7f4b9300da023f /gcc | |
parent | 58fe131b91007793c0f12f5fe6cab3f1a017d0fa (diff) | |
download | gcc-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.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/c/c-decl.c | 9 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/Warray-parameter-9.c | 54 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/Wnonnull-6.c | 93 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/Wreturn-type3.c | 54 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/Wunused-result.c | 50 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/attr-noreturn.c | 64 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/attr-returns-nonnull.c | 58 |
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" } } */ |