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.
This commit is contained in:
parent
58fe131b91
commit
da879e01ec
|
@ -3263,11 +3263,10 @@ pushdecl (tree x)
|
||||||
else
|
else
|
||||||
thistype = type;
|
thistype = type;
|
||||||
b->u.type = TREE_TYPE (b->decl);
|
b->u.type = TREE_TYPE (b->decl);
|
||||||
if (TREE_CODE (b->decl) == FUNCTION_DECL
|
/* Propagate the type attributes to the decl. */
|
||||||
&& fndecl_built_in_p (b->decl))
|
thistype
|
||||||
thistype
|
= build_type_attribute_variant (thistype,
|
||||||
= build_type_attribute_variant (thistype,
|
TYPE_ATTRIBUTES (b->u.type));
|
||||||
TYPE_ATTRIBUTES (b->u.type));
|
|
||||||
TREE_TYPE (b->decl) = thistype;
|
TREE_TYPE (b->decl) = thistype;
|
||||||
bind (name, b->decl, scope, /*invisible=*/false, /*nested=*/true,
|
bind (name, b->decl, scope, /*invisible=*/false, /*nested=*/true,
|
||||||
locus);
|
locus);
|
||||||
|
|
|
@ -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" }
|
||||||
|
}
|
|
@ -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" }
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
|
@ -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" }
|
||||||
|
}
|
|
@ -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" } } */
|
|
@ -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" } } */
|
Loading…
Reference in New Issue