diff options
| author | H.J. Lu <hjl.tools@gmail.com> | 2025-10-26 08:42:20 +0800 |
|---|---|---|
| committer | H.J. Lu <hjl.tools@gmail.com> | 2025-10-28 06:46:35 +0800 |
| commit | dcf69bdcd49bccd901bfb01db7c15530e9a70dc0 (patch) | |
| tree | 3ce12375d22c293d289b06720f6e695abaae6fc8 | |
| parent | 76943639ddd861dce3886d1def2a353ccfcdd585 (diff) | |
| download | gcc-dcf69bdcd49bccd901bfb01db7c15530e9a70dc0.zip gcc-dcf69bdcd49bccd901bfb01db7c15530e9a70dc0.tar.gz gcc-dcf69bdcd49bccd901bfb01db7c15530e9a70dc0.tar.bz2 | |
c: Try the type with the previous function attributes
When there are 2 conflicting function declarations, try the new type
with the previous TYPE_ATTRIBUTES if the current declaration has no
TYPE_ATTRIBUTES to support
extern void foo (void) __attribute__((nocf_check));
void
foo (void)
{
}
instead of issuing an error:
$ gcc -O2 -fcf-protection -S x.c
x.c:4:1: error: conflicting types for ‘foo’; have ‘void(void)’
4 | foo (void)
| ^~~
x.c:1:13: note: previous declaration of ‘foo’ with type ‘void(void)’
1 | extern void foo (void) __attribute__((nocf_check));
| ^~~
The resulting function definition is compatible with the previous
declaration.
gcc/c/
PR c/122427
* c-decl.cc (diagnose_mismatched_decls): For FUNCTION_DECL, if
OLDDECL has TYPE_ATTRIBUTES and NEWDECL doesn't, try the type
with the OLDDECL attributes.
gcc/testsuite/
PR c/122427
* g++.target/i386/cf_check-1.C: New test.
* g++.target/i386/cf_check-2.C: Likewise.
* g++.target/i386/cf_check-3.C: Likewise.
* g++.target/i386/cf_check-4.C: Likewise.
* gcc.target/i386/cf_check-7.c: Likewise.
* gcc.target/i386/cf_check-8.c: Likewise.
* gcc.target/i386/cf_check-9.c: Likewise.
* gcc.target/i386/cf_check-10.c: Likewise.
* gcc.target/i386/cf_check-11.c: Likewise.
* gcc.target/i386/no-callee-saved-12.c: Remove dg-error.
* gcc.target/i386/preserve-none-17.c: Likewise.
Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
| -rw-r--r-- | gcc/c/c-decl.cc | 38 | ||||
| -rw-r--r-- | gcc/testsuite/g++.target/i386/cf_check-1.C | 18 | ||||
| -rw-r--r-- | gcc/testsuite/g++.target/i386/cf_check-2.C | 14 | ||||
| -rw-r--r-- | gcc/testsuite/g++.target/i386/cf_check-3.C | 19 | ||||
| -rw-r--r-- | gcc/testsuite/g++.target/i386/cf_check-4.C | 23 | ||||
| -rw-r--r-- | gcc/testsuite/gcc.target/i386/cf_check-10.c | 19 | ||||
| -rw-r--r-- | gcc/testsuite/gcc.target/i386/cf_check-11.c | 24 | ||||
| -rw-r--r-- | gcc/testsuite/gcc.target/i386/cf_check-7.c | 20 | ||||
| -rw-r--r-- | gcc/testsuite/gcc.target/i386/cf_check-8.c | 11 | ||||
| -rw-r--r-- | gcc/testsuite/gcc.target/i386/cf_check-9.c | 15 | ||||
| -rw-r--r-- | gcc/testsuite/gcc.target/i386/no-callee-saved-12.c | 5 | ||||
| -rw-r--r-- | gcc/testsuite/gcc.target/i386/preserve-none-17.c | 5 |
12 files changed, 201 insertions, 10 deletions
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 061892a..2b31a43 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -2337,10 +2337,40 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, error ("conflicting type qualifiers for %q+D", newdecl); } else - error ("conflicting types for %q+D; have %qT", newdecl, newtype); - diagnose_arglist_conflict (newdecl, olddecl, newtype, oldtype); - locate_old_decl (olddecl); - return false; + { + if (TREE_CODE (olddecl) == FUNCTION_DECL) + { + tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (olddecl)); + if (attrs && !TYPE_ATTRIBUTES (TREE_TYPE (newdecl))) + { + /* Similar to the C++ front-end, for FUNCTION_DECL, + if OLDDECL has attributes and NEWDECL doesn't, + try the type with OLDDECL attributes. */ + tree rettype = TREE_TYPE (newtype); + tree tryargs = TYPE_ARG_TYPES (newtype); + tree trytype = c_build_function_type (rettype, + tryargs); + trytype = c_build_type_attribute_variant (trytype, + attrs); + if (comptypes (oldtype, trytype)) + { + *newtypep = newtype = trytype; + comptypes_result = 1; + } + } + } + + if (!comptypes_result) + error ("conflicting types for %q+D; have %qT", newdecl, + newtype); + } + if (!comptypes_result) + { + diagnose_arglist_conflict (newdecl, olddecl, newtype, + oldtype); + locate_old_decl (olddecl); + return false; + } } } /* Warn about enum/integer type mismatches. They are compatible types diff --git a/gcc/testsuite/g++.target/i386/cf_check-1.C b/gcc/testsuite/g++.target/i386/cf_check-1.C new file mode 100644 index 0000000..59fcca6 --- /dev/null +++ b/gcc/testsuite/g++.target/i386/cf_check-1.C @@ -0,0 +1,18 @@ +/* { dg-do compile { target { "i?86-*-* x86_64-*-*" } } } */ +/* { dg-options "-O2 -fcf-protection" } */ + +extern void foo (void) __attribute__((nocf_check)); +extern void foo (void); + +void +foo (void) +{ +} + +extern void bar (void); +extern void bar (void) __attribute__((nocf_check)); /* { dg-error "ambiguating new declaration" } */ + +void +bar (void) +{ +} diff --git a/gcc/testsuite/g++.target/i386/cf_check-2.C b/gcc/testsuite/g++.target/i386/cf_check-2.C new file mode 100644 index 0000000..5718ab2 --- /dev/null +++ b/gcc/testsuite/g++.target/i386/cf_check-2.C @@ -0,0 +1,14 @@ +/* { dg-do compile { target { "i?86-*-* x86_64-*-*" } } } */ +/* { dg-options "-O2 -fcf-protection" } */ + +extern void bar (void); +extern void bar (void) __attribute__((nocf_check)); /* { dg-error "ambiguating new declaration" } */ +extern void foo (void) __attribute__((nocf_check)); +extern void foo (void); + +void +func (void) +{ + bar (); + foo (); +} diff --git a/gcc/testsuite/g++.target/i386/cf_check-3.C b/gcc/testsuite/g++.target/i386/cf_check-3.C new file mode 100644 index 0000000..79d3a25 --- /dev/null +++ b/gcc/testsuite/g++.target/i386/cf_check-3.C @@ -0,0 +1,19 @@ +/* { dg-do compile { target { "i?86-*-* x86_64-*-*" } } } */ +/* { dg-options "-O2 -fcf-protection" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**_Z3foov: +**.LFB[0-9]+: +** .cfi_startproc +** ret +**... +*/ + +extern void foo (void) __attribute__((nocf_check)); + +void +foo (void) +{ +} diff --git a/gcc/testsuite/g++.target/i386/cf_check-4.C b/gcc/testsuite/g++.target/i386/cf_check-4.C new file mode 100644 index 0000000..57c40a5 --- /dev/null +++ b/gcc/testsuite/g++.target/i386/cf_check-4.C @@ -0,0 +1,23 @@ +/* { dg-do compile { target { "i?86-*-* x86_64-*-*" } } } */ +/* { dg-require-weak "" } */ +/* { dg-options "-O2 -fcf-protection" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**_Z3foov: +**.LFB[0-9]+: +** .cfi_startproc +** ret +**... +*/ + +extern void foo (void) __attribute__((nocf_check)); + +__attribute__((weak)) +void +foo (void) +{ +} + +/* { dg-final { scan-assembler ".weak\[ \t\]_?_Z3foov" } } */ diff --git a/gcc/testsuite/gcc.target/i386/cf_check-10.c b/gcc/testsuite/gcc.target/i386/cf_check-10.c new file mode 100644 index 0000000..a131672 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/cf_check-10.c @@ -0,0 +1,19 @@ +/* PR c/122427 */ +/* { dg-do compile { target { "i?86-*-* x86_64-*-*" } } } */ +/* { dg-options "-O2 -fcf-protection" } */ + +extern void foo (void) __attribute__((nocf_check)); +extern void foo (void); + +void +foo (void) +{ +} + +extern void bar (void); +extern void bar (void) __attribute__((nocf_check)); /* { dg-error "conflicting types" } */ + +void +bar (void) +{ +} diff --git a/gcc/testsuite/gcc.target/i386/cf_check-11.c b/gcc/testsuite/gcc.target/i386/cf_check-11.c new file mode 100644 index 0000000..9ed65ab --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/cf_check-11.c @@ -0,0 +1,24 @@ +/* PR c/122427 */ +/* { dg-do compile { target { "i?86-*-* x86_64-*-*" } } } */ +/* { dg-require-weak "" } */ +/* { dg-options "-O2 -fcf-protection" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**foo: +**.LFB[0-9]+: +** .cfi_startproc +** ret +**... +*/ + +extern void foo (void) __attribute__((nocf_check)); + +__attribute__((weak)) +void +foo (void) +{ +} + +/* { dg-final { scan-assembler ".weak\[ \t\]_?foo" } } */ diff --git a/gcc/testsuite/gcc.target/i386/cf_check-7.c b/gcc/testsuite/gcc.target/i386/cf_check-7.c new file mode 100644 index 0000000..b9a3b39 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/cf_check-7.c @@ -0,0 +1,20 @@ +/* PR c/122427 */ +/* { dg-do compile { target { "i?86-*-* x86_64-*-*" } } } */ +/* { dg-options "-O2 -fcf-protection" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**foo: +**.LFB[0-9]+: +** .cfi_startproc +** ret +**... +*/ + +extern void foo (void) __attribute__((nocf_check)); + +void +foo (void) +{ +} diff --git a/gcc/testsuite/gcc.target/i386/cf_check-8.c b/gcc/testsuite/gcc.target/i386/cf_check-8.c new file mode 100644 index 0000000..48e8cf1 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/cf_check-8.c @@ -0,0 +1,11 @@ +/* PR c/122427 */ +/* { dg-do compile { target { "i?86-*-* x86_64-*-*" } } } */ +/* { dg-options "-O2 -fcf-protection" } */ + +extern void foo (void); + +__attribute__((nocf_check)) +void +foo (void) /* { dg-error "conflicting types" } */ +{ +} diff --git a/gcc/testsuite/gcc.target/i386/cf_check-9.c b/gcc/testsuite/gcc.target/i386/cf_check-9.c new file mode 100644 index 0000000..057c60f --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/cf_check-9.c @@ -0,0 +1,15 @@ +/* PR c/122427 */ +/* { dg-do compile { target { "i?86-*-* x86_64-*-*" } } } */ +/* { dg-options "-O2 -fcf-protection" } */ + +extern void bar (void); +extern void bar (void) __attribute__((nocf_check)); /* { dg-error "conflicting types" } */ +extern void foo (void) __attribute__((nocf_check)); +extern void foo (void); + +void +func (void) +{ + bar (); + foo (); +} diff --git a/gcc/testsuite/gcc.target/i386/no-callee-saved-12.c b/gcc/testsuite/gcc.target/i386/no-callee-saved-12.c index 5524a4a..8f9b725 100644 --- a/gcc/testsuite/gcc.target/i386/no-callee-saved-12.c +++ b/gcc/testsuite/gcc.target/i386/no-callee-saved-12.c @@ -1,10 +1,9 @@ /* { dg-do compile } */ /* { dg-options "-O2" } */ -extern void foo (void) __attribute__ ((no_callee_saved_registers)); /* { dg-note "previous declaration" } */ +extern void foo (void) __attribute__ ((no_callee_saved_registers)); void -foo (void) /* { dg-error "conflicting types" } */ +foo (void) { } - diff --git a/gcc/testsuite/gcc.target/i386/preserve-none-17.c b/gcc/testsuite/gcc.target/i386/preserve-none-17.c index e105da1..0c62edd 100644 --- a/gcc/testsuite/gcc.target/i386/preserve-none-17.c +++ b/gcc/testsuite/gcc.target/i386/preserve-none-17.c @@ -1,10 +1,9 @@ /* { dg-do compile } */ /* { dg-options "-O2" } */ -extern void foo (void) __attribute__ ((preserve_none)); /* { dg-note "previous declaration" } */ +extern void foo (void) __attribute__ ((preserve_none)); void -foo (void) /* { dg-error "conflicting types" } */ +foo (void) { } - |
