mirror of
https://forge.sourceware.org/marek/gcc.git
synced 2026-02-22 03:47:02 -05:00
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>
This commit is contained in:
@@ -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
|
||||
|
||||
18
gcc/testsuite/g++.target/i386/cf_check-1.C
Normal file
18
gcc/testsuite/g++.target/i386/cf_check-1.C
Normal file
@@ -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)
|
||||
{
|
||||
}
|
||||
14
gcc/testsuite/g++.target/i386/cf_check-2.C
Normal file
14
gcc/testsuite/g++.target/i386/cf_check-2.C
Normal file
@@ -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 ();
|
||||
}
|
||||
19
gcc/testsuite/g++.target/i386/cf_check-3.C
Normal file
19
gcc/testsuite/g++.target/i386/cf_check-3.C
Normal file
@@ -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)
|
||||
{
|
||||
}
|
||||
23
gcc/testsuite/g++.target/i386/cf_check-4.C
Normal file
23
gcc/testsuite/g++.target/i386/cf_check-4.C
Normal file
@@ -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" } } */
|
||||
19
gcc/testsuite/gcc.target/i386/cf_check-10.c
Normal file
19
gcc/testsuite/gcc.target/i386/cf_check-10.c
Normal file
@@ -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)
|
||||
{
|
||||
}
|
||||
24
gcc/testsuite/gcc.target/i386/cf_check-11.c
Normal file
24
gcc/testsuite/gcc.target/i386/cf_check-11.c
Normal file
@@ -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" } } */
|
||||
20
gcc/testsuite/gcc.target/i386/cf_check-7.c
Normal file
20
gcc/testsuite/gcc.target/i386/cf_check-7.c
Normal file
@@ -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)
|
||||
{
|
||||
}
|
||||
11
gcc/testsuite/gcc.target/i386/cf_check-8.c
Normal file
11
gcc/testsuite/gcc.target/i386/cf_check-8.c
Normal file
@@ -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" } */
|
||||
{
|
||||
}
|
||||
15
gcc/testsuite/gcc.target/i386/cf_check-9.c
Normal file
15
gcc/testsuite/gcc.target/i386/cf_check-9.c
Normal file
@@ -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 ();
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user