From: Martin Sebor Date: Thu, 4 Feb 2021 21:50:23 +0000 (-0700) Subject: PR c/97882 - Segmentation Fault on improper redeclaration of function X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=ce5720447c69286599b96bae53ae854b1bbe41fa;p=gcc.git PR c/97882 - Segmentation Fault on improper redeclaration of function gcc/c/ChangeLog: PR c/97882 * c-decl.c (locate_old_decl): Add type to diagnostic output. (diagnose_mismatched_decls): Same. (start_function): Introduce temporaries for better readability. * c-typeck.c (comptypes_internal): Only consider complete enum types in comparisons with integers. gcc/testsuite/ChangeLog: PR c/97882 * gcc.dg/decl-8.c: Adjust text of expected diagnostic. * gcc.dg/label-decl-4.c: Same. * gcc.dg/mismatch-decl-1.c: Same. * gcc.dg/old-style-then-proto-1.c: Same. * gcc.dg/parm-mismatch-1.c: Same. * gcc.dg/pr35445.c: Same. * gcc.dg/redecl-11.c: Same. * gcc.dg/redecl-12.c: Same. * gcc.dg/redecl-13.c: Same. * gcc.dg/redecl-15.c: Same. * gcc.dg/tls/thr-init-1.c: Same. * objc.dg/id-1.m: Same. * objc.dg/tls/diag-3.m: Same. * gcc.dg/pr97882.c: New test. * gcc.dg/qual-return-7.c: New test. * gcc.dg/qual-return-8.c: New test. --- diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index be95643fcf9..a5852a3bae7 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -1910,15 +1910,22 @@ validate_proto_after_old_defn (tree newdecl, tree newtype, tree oldtype) static void locate_old_decl (tree decl) { - if (TREE_CODE (decl) == FUNCTION_DECL && fndecl_built_in_p (decl) + if (TREE_CODE (decl) == FUNCTION_DECL + && fndecl_built_in_p (decl) && !C_DECL_DECLARED_BUILTIN (decl)) ; else if (DECL_INITIAL (decl)) - inform (input_location, "previous definition of %q+D was here", decl); + inform (input_location, + "previous definition of %q+D with type %qT", + decl, TREE_TYPE (decl)); else if (C_DECL_IMPLICIT (decl)) - inform (input_location, "previous implicit declaration of %q+D was here", decl); + inform (input_location, + "previous implicit declaration of %q+D with type %qT", + decl, TREE_TYPE (decl)); else - inform (input_location, "previous declaration of %q+D was here", decl); + inform (input_location, + "previous declaration of %q+D with type %qT", + decl, TREE_TYPE (decl)); } /* Subroutine of duplicate_decls. Compare NEWDECL to OLDDECL. @@ -2083,7 +2090,8 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, && C_DECL_IMPLICIT (olddecl) && !DECL_INITIAL (olddecl)) { pedwarned = pedwarn (input_location, 0, - "conflicting types for %q+D", newdecl); + "conflicting types for %q+D; have %qT", + newdecl, newtype); /* Make sure we keep void as the return type. */ TREE_TYPE (olddecl) = *oldtypep = oldtype = newtype; } @@ -2119,7 +2127,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, error ("conflicting type qualifiers for %q+D", newdecl); } else - error ("conflicting types for %q+D", newdecl); + error ("conflicting types for %q+D; have %qT", newdecl, newtype); diagnose_arglist_conflict (newdecl, olddecl, newtype, oldtype); locate_old_decl (olddecl); return false; @@ -9457,27 +9465,29 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator, current_function_prototype_locus = UNKNOWN_LOCATION; current_function_prototype_built_in = false; current_function_prototype_arg_types = NULL_TREE; - if (!prototype_p (TREE_TYPE (decl1))) + tree newtype = TREE_TYPE (decl1); + tree oldtype = old_decl ? TREE_TYPE (old_decl) : newtype; + if (!prototype_p (newtype)) { + tree oldrt = TREE_TYPE (oldtype); + tree newrt = TREE_TYPE (newtype); if (old_decl != NULL_TREE - && TREE_CODE (TREE_TYPE (old_decl)) == FUNCTION_TYPE - && comptypes (TREE_TYPE (TREE_TYPE (decl1)), - TREE_TYPE (TREE_TYPE (old_decl)))) + && TREE_CODE (oldtype) == FUNCTION_TYPE + && comptypes (oldrt, newrt)) { - if (stdarg_p (TREE_TYPE (old_decl))) + if (stdarg_p (oldtype)) { auto_diagnostic_group d; warning_at (loc, 0, "%q+D defined as variadic function " "without prototype", decl1); locate_old_decl (old_decl); } - TREE_TYPE (decl1) = composite_type (TREE_TYPE (old_decl), - TREE_TYPE (decl1)); + TREE_TYPE (decl1) = composite_type (oldtype, newtype); current_function_prototype_locus = DECL_SOURCE_LOCATION (old_decl); current_function_prototype_built_in = C_DECL_BUILTIN_PROTOTYPE (old_decl); current_function_prototype_arg_types - = TYPE_ARG_TYPES (TREE_TYPE (decl1)); + = TYPE_ARG_TYPES (newtype); } if (TREE_PUBLIC (decl1)) { diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 8ef08434e74..725dc510dc7 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -1107,7 +1107,9 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p, not transitive: two enumerated types in the same translation unit are compatible with each other only if they are the same type. */ - if (TREE_CODE (t1) == ENUMERAL_TYPE && TREE_CODE (t2) != ENUMERAL_TYPE) + if (TREE_CODE (t1) == ENUMERAL_TYPE + && COMPLETE_TYPE_P (t1) + && TREE_CODE (t2) != ENUMERAL_TYPE) { t1 = c_common_type_for_size (TYPE_PRECISION (t1), TYPE_UNSIGNED (t1)); if (TREE_CODE (t2) != VOID_TYPE) @@ -1118,7 +1120,9 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p, *different_types_p = true; } } - else if (TREE_CODE (t2) == ENUMERAL_TYPE && TREE_CODE (t1) != ENUMERAL_TYPE) + else if (TREE_CODE (t2) == ENUMERAL_TYPE + && COMPLETE_TYPE_P (t2) + && TREE_CODE (t1) != ENUMERAL_TYPE) { t2 = c_common_type_for_size (TYPE_PRECISION (t2), TYPE_UNSIGNED (t2)); if (TREE_CODE (t1) != VOID_TYPE) diff --git a/gcc/testsuite/gcc.dg/decl-8.c b/gcc/testsuite/gcc.dg/decl-8.c index 485065b7aa1..608ff97d7fc 100644 --- a/gcc/testsuite/gcc.dg/decl-8.c +++ b/gcc/testsuite/gcc.dg/decl-8.c @@ -3,8 +3,8 @@ /* { dg-do compile } */ /* { dg-options "-std=gnu89 -pedantic-errors" } */ -typedef int I; /* { dg-message "note: previous declaration of 'I' was here" } */ +typedef int I; /* { dg-message "note: previous declaration of 'I'" "note" } */ typedef int I; /* { dg-error "redefinition of typedef 'I'" } */ -typedef int I1; /* { dg-message "note: previous declaration of 'I1' was here" } */ +typedef int I1; /* { dg-message "note: previous declaration of 'I1'" "note" } */ typedef long I1; /* { dg-error "conflicting types for 'I1'" } */ diff --git a/gcc/testsuite/gcc.dg/label-decl-4.c b/gcc/testsuite/gcc.dg/label-decl-4.c index 5661e019d1e..82f1af050b0 100644 --- a/gcc/testsuite/gcc.dg/label-decl-4.c +++ b/gcc/testsuite/gcc.dg/label-decl-4.c @@ -7,8 +7,8 @@ void f (void) { __label__ a, b, a; /* { dg-error "duplicate label declaration 'a'" } */ - /* { dg-message "note: previous declaration of 'a' was here" "previous" { target *-*-* } .-1 } */ - __label__ c; /* { dg-message "note: previous declaration of 'c' was here" } */ + /* { dg-message "note: previous declaration of 'a'" "previous" { target *-*-* } .-1 } */ + __label__ c; /* { dg-message "note: previous declaration of 'c'" "note" } */ __label__ c; /* { dg-error "duplicate label declaration 'c'" } */ return; } diff --git a/gcc/testsuite/gcc.dg/mismatch-decl-1.c b/gcc/testsuite/gcc.dg/mismatch-decl-1.c index da4db0a57f0..b6dd5431a48 100644 --- a/gcc/testsuite/gcc.dg/mismatch-decl-1.c +++ b/gcc/testsuite/gcc.dg/mismatch-decl-1.c @@ -4,12 +4,12 @@ /* The bug this is testing is that if a new decl conflicts with an explicit decl, you don't get the "changes type of builtin" message, - but if there was *also* a builtin, you *also* don't get the - "previous declaration was here" message, leaving you with no clue - where the previous declaration came from. */ + but if there was *also* a builtin, you *also* don't get the "previous + declaration" message, leaving you with no clue where the previous + declaration came from. */ -extern char foo(int,int); /* { dg-message "previous declaration of 'foo' was here" } */ -extern char *index(const char *,int); /* { dg-message "previous declaration of 'index' was here" } */ +extern char foo(int,int); /* { dg-message "previous declaration of 'foo'" "note" } */ +extern char *index(const char *,int); /* { dg-message "previous declaration of 'index'" "note" } */ /* This changes the type of "index", which is both a builtin and an explicit decl. */ diff --git a/gcc/testsuite/gcc.dg/old-style-then-proto-1.c b/gcc/testsuite/gcc.dg/old-style-then-proto-1.c index 7d76287b0d1..e3e61861673 100644 --- a/gcc/testsuite/gcc.dg/old-style-then-proto-1.c +++ b/gcc/testsuite/gcc.dg/old-style-then-proto-1.c @@ -7,38 +7,38 @@ void f1() {} void f1(void); /* { dg-warning "prototype for 'f1' follows non-prototype definition" } */ -void f2() {} /* { dg-message "note: previous definition of 'f2' was here" } */ +void f2() {} /* { dg-message "note: previous definition of 'f2'" "note" } */ void f2(int); /* { dg-error "prototype for 'f2' declares more arguments than previous old-style definition" } */ -void f3(a) int a; {} /* { dg-message "note: previous definition of 'f3' was here" } */ +void f3(a) int a; {} /* { dg-message "note: previous definition of 'f3'" "note" } */ void f3(void); /* { dg-error "prototype for 'f3' declares fewer arguments than previous old-style definition" } */ void f4(a) int a; {} void f4(int); /* { dg-warning "prototype for 'f4' follows non-prototype definition" } */ -void f5(a) int a; {} /* { dg-message "note: previous definition of 'f5' was here" } */ +void f5(a) int a; {} /* { dg-message "note: previous definition of 'f5'" "note" } */ void f5(int, int); /* { dg-error "prototype for 'f5' declares more arguments than previous old-style definition" } */ -void f6(a) int a; {} /* { dg-message "note: previous definition of 'f6' was here" } */ +void f6(a) int a; {} /* { dg-message "note: previous definition of 'f6'" "note" } */ void f6(int, ...); /* { dg-error "conflicting types for 'f6'" } */ -void f7(a, b) int a, b; {} /* { dg-message "note: previous definition of 'f7' was here" } */ +void f7(a, b) int a, b; {} /* { dg-message "note: previous definition of 'f7'" "note" } */ void f7(int); /* { dg-error "prototype for 'f7' declares fewer arguments than previous old-style definition" } */ -void f8(a, b) int a, b; {} /* { dg-message "note: previous definition of 'f8' was here" } */ +void f8(a, b) int a, b; {} /* { dg-message "note: previous definition of 'f8'" "note" } */ void f8(int, ...); /* { dg-error "conflicting types for 'f8'" } */ void f9(a, b) int a, b; {} void f9(int, int); /* { dg-warning "prototype for 'f9' follows non-prototype definition" } */ -void f10(a, b) int a, b; {} /* { dg-message "note: previous definition of 'f10' was here" } */ +void f10(a, b) int a, b; {} /* { dg-message "note: previous definition of 'f10'" "note" } */ void f10(int, long); /* { dg-error "prototype for 'f10' declares argument 2 with incompatible type" } */ -void f11(a, b) int a, b; {} /* { dg-message "note: previous definition of 'f11' was here" } */ +void f11(a, b) int a, b; {} /* { dg-message "note: previous definition of 'f11'" "note" } */ void f11(long, int); /* { dg-error "prototype for 'f11' declares argument 1 with incompatible type" } */ void f12(a, b) const int a; volatile int b; {} void f12(volatile int, const int); /* { dg-warning "prototype for 'f12' follows non-prototype definition" } */ -void f13(a) const int a[2][2]; {} /* { dg-message "note: previous definition of 'f13' was here" } */ +void f13(a) const int a[2][2]; {} /* { dg-message "note: previous definition of 'f13'" "note" } */ void f13(volatile int [2][2]); /* { dg-error "prototype for 'f13' declares argument 1 with incompatible type" } */ diff --git a/gcc/testsuite/gcc.dg/parm-mismatch-1.c b/gcc/testsuite/gcc.dg/parm-mismatch-1.c index 058f2e856f5..d7621bcd6b2 100644 --- a/gcc/testsuite/gcc.dg/parm-mismatch-1.c +++ b/gcc/testsuite/gcc.dg/parm-mismatch-1.c @@ -4,15 +4,15 @@ /* { dg-do compile } */ /* { dg-options "" } */ -void f0(); /* { dg-message "note: previous declaration of 'f0' was here" } */ +void f0(); /* { dg-message "note: previous declaration of 'f0'" "note" } */ void f0(int, ...); /* { dg-error "conflicting types for 'f0'" } */ /* { dg-message "note: a parameter list with an ellipsis cannot match an empty parameter name list declaration" "note" { target *-*-* } .-1 } */ -void f1(int, ...); /* { dg-message "note: previous declaration of 'f1' was here" } */ +void f1(int, ...); /* { dg-message "note: previous declaration of 'f1'" "note" } */ void f1(); /* { dg-error "conflicting types for 'f1'" } */ /* { dg-message "note: a parameter list with an ellipsis cannot match an empty parameter name list declaration" "note" { target *-*-* } .-1 } */ -void f2(); /* { dg-message "note: previous declaration of 'f2' was here" } */ +void f2(); /* { dg-message "note: previous declaration of 'f2'" "note" } */ void f2(char); /* { dg-error "conflicting types for 'f2'" } */ /* { dg-message "note: an argument type that has a default promotion cannot match an empty parameter name list declaration" "note" { target *-*-* } .-1 } */ -void f3(char); /* { dg-message "note: previous declaration of 'f3' was here" } */ +void f3(char); /* { dg-message "note: previous declaration of 'f3'" "note" } */ void f3(); /* { dg-error "conflicting types for 'f3'" } */ /* { dg-message "note: an argument type that has a default promotion cannot match an empty parameter name list declaration" "note" { target *-*-* } .-1 } */ diff --git a/gcc/testsuite/gcc.dg/pr35445.c b/gcc/testsuite/gcc.dg/pr35445.c index 56ca6e2580a..30c29f4c3bc 100644 --- a/gcc/testsuite/gcc.dg/pr35445.c +++ b/gcc/testsuite/gcc.dg/pr35445.c @@ -2,5 +2,5 @@ /* { dg-do compile } */ extern int i; -extern int i; /* { dg-message "was here" } */ +extern int i; /* { dg-message "previous declaration of 'i'" } */ int i[] = { 0 }; /* { dg-error "conflicting types" } */ diff --git a/gcc/testsuite/gcc.dg/pr97882.c b/gcc/testsuite/gcc.dg/pr97882.c new file mode 100644 index 00000000000..48ea93d53c7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr97882.c @@ -0,0 +1,144 @@ +/* PR c/97882 - Segmentation Fault on improper redeclaration of function + { dg-do compile } + { dg-options "" } */ + +// Check pointer declaration incompatibiliies. + +extern enum E e_u; // { dg-message "note: previous declaration of 'e_u' with type 'enum E'" "note" } +unsigned e_u; // { dg-error "conflicting types for 'e_u'; have 'unsigned int'" } + + +extern enum E *p; // { dg-message "note: previous declaration of 'p' with type 'enum E \\*'" "note" } +unsigned *p; // { dg-error "conflicting types for 'p'; have 'unsigned int \\*'" } + +extern enum E **p2; // { dg-message "note: previous declaration of 'p2' with type 'enum E \\*\\*'" "note" } +unsigned **p2; // { dg-error "conflicting types for 'p2'; have 'unsigned int \\*\\*'" } + +extern enum E ***p3; // { dg-message "note: previous declaration of 'p3' with type 'enum E \\*\\*\\*'" "note" } +unsigned ***p3; // { dg-error "conflicting types for 'p3'; have 'unsigned int \\*\\*\\*'" } + +extern enum F *q; // { dg-message "note: previous declaration of 'q' with type 'enum F \\*'" "note" } +int *q; // { dg-error "conflicting types for 'q'; have 'int \\*'" } + +extern enum E* r[]; // { dg-message "note: previous declaration of 'r' with type 'enum E \\*\\\[]'" "note" } +extern unsigned *r[1]; // { dg-error "conflicting types for 'r'; have 'unsigned int \\*\\\[1]'" } + +extern enum E **r2[]; // { dg-message "note: previous declaration of 'r2' with type 'enum E \\*\\*\\\[]'" "note" } +extern unsigned **r2[2];// { dg-error "conflicting types for 'r2'; have 'unsigned int \\*\\*\\\[2]'" } + + +typedef enum E* EPAx[]; +typedef unsigned* UPAx[]; + +extern EPAx* peax; // { dg-message "note: previous declaration of 'peax' with type 'enum E \\* \\(\\*\\)\\\[]'" "note" } +extern UPAx* peax; // { dg-error "conflicting types for 'peax'; have 'unsigned int \\* \\(\\*\\)\\\[]'" } + + +/* Check incompatibilities in the return type in a redeclaration + of a function without a prototye. */ + +/* Verify the following isn't rejected. */ +void f_v (); +void f_v (void); + +enum E fE_u (); // { dg-message "previous declaration of 'fE_u' with type 'enum E\\(\\)'" "note" } +unsigned fE_u (); // { dg-error "conflicting types for 'fE_u'; have 'unsigned int\\(\\)'" } + +enum E* fpE_u (); // { dg-message "previous declaration of 'fpE_u' with type 'enum E \\*\\(\\)'" "note" } +unsigned* fpE_u (); // { dg-error "conflicting types for 'fpE_u'; have 'unsigned int \\*\\(\\)'" } + +enum E** fppE_u (); // { dg-message "previous declaration of 'fppE_u' with type 'enum E \\*\\*\\(\\)'" "note" } +unsigned** fppE_u (); // { dg-error "conflicting types for 'fppE_u'; have 'unsigned int \\*\\*\\(\\)'" } + +enum E** fppE_u (); // { dg-message "previous declaration of 'fppE_u' with type 'enum E \\*\\*\\(\\)'" "note" } +unsigned** fppE_u (); // { dg-error "conflicting types for 'fppE_u'; have 'unsigned int \\*\\*\\(\\)'" } + +enum E gE_u (); // { dg-message "previous declaration of 'gE_u' with type 'enum E\\(\\)'" "note" } +unsigned gE_u () // { dg-error "conflicting types for 'gE_u'; have 'unsigned int\\(\\)'" } +{ return 0; } + +enum E** gppE_u (); // { dg-message "previous declaration of 'gppE_u' with type 'enum E \\*\\*\\(\\)'" "note" } +unsigned** gppE_u () // { dg-error "conflicting types for 'gppE_u'; have 'unsigned int \\*\\*\\(\\)'" } +{ return 0; } + +unsigned fu_E (); // { dg-message "previous declaration of 'fu_E' with type 'unsigned int\\(\\)'" "note" } +enum E fu_E (); // { dg-error "conflicting types for 'fu_E'; have 'enum E\\(\\)'" } + +unsigned gu_E (); // { dg-message "previous declaration of 'gu_E' with type 'unsigned int\\(\\)'" "note" } +enum E gu_E () { } // { dg-error "conflicting types for 'gu_E'" } + // { dg-error "incomplete type" "return type" { target *-*-* } .-1 } + +typedef enum E FE_ (); +typedef unsigned Fuv (void); + +FE_* fpF_u (); // // { dg-message "previous declaration of 'fpF_u' with type 'enum E \\(\\*\\(\\)\\)\\(\\)'" "note" } +Fuv* fpF_u (); // { dg-error "conflicting types for 'fpF_u'; have 'unsigned int \\(\\*\\(\\)\\)\\(void\\)'" } + + +typedef void Fv_ (); +typedef void Fvv (void); + +/* Verify the following isn't rejected. */ +Fv_* f (); +Fvv* f (); + + +/* Check incompatibilities in argument types of a function redeclaration. */ + +void fvE_u (enum E); // { dg-message "note: previous declaration of 'fvE_u' with type 'void\\(enum E\\)'" "note" } +void fvE_u (unsigned); // { dg-error "conflicting types for 'fvE_u'; have 'void\\(unsigned int\\)'" } + +void fviE_u (int, enum E); // { dg-message "note: previous declaration of 'fviE_u' with type 'void\\(int, *enum E\\)'" "note" } +void fviE_u (int, unsigned); // { dg-error "conflicting types for 'fviE_u'; have 'void\\(int, *unsigned int\\)'" } + +void fvE_el (enum E, ...); // { dg-message "note: previous declaration of 'fvE_el' with type 'void\\(enum E, \\.\\.\\.\\)'" "note" } +void fvE_el (unsigned, ...); // { dg-error "conflicting types for 'fvE_el'; have 'void\\(unsigned int, \\.\\.\\.\\)'" } + + +/* Check incompatibilities in the return type in a redeclaration + of a nested function without a prototye. */ + +void f1 (void) +{ + enum G f11 (); // { dg-message "note: previous declaration of 'f11' with type 'enum G\\(\\)'" "note" } + unsigned f11 () { } // { dg-error "conflicting types for 'f11'; have 'unsigned int\\(\\)'" } +} + + +void f2 (void) +{ + const enum G f21 (); // { dg-message "note: previous declaration of 'f21' with type 'enum G\\(\\)'" "note" } + unsigned f21 () { } // { dg-error "conflicting types for 'f21'; have 'unsigned int\\(\\)'" } +} + + +void f3 (void) +{ + enum G f31 (); // { dg-message "note: previous declaration of 'f31' with type 'enum G\\(\\)'" "note" } + const unsigned f31 () { } // { dg-error "conflicting types for 'f31'; have 'unsigned int\\(\\)'" } +} + + +void f4 (void) +{ + auto enum G f31 (); // { dg-message "note: previous declaration of 'f31' with type 'enum G\\(\\)'" "note" } + const unsigned f31 () { } // { dg-error "conflicting types for 'f31'; have 'unsigned int\\(\\)'" } +} + + +void f5 (void) +{ + enum G* f51 (); // { dg-message "note: previous declaration of 'f51' with type 'enum G \\*\\(\\)'" "note" } + int* f51 () { } // { dg-error "conflicting types for 'f51'; have 'int \\*\\(\\)'" } +} + + +void f6 (void) +{ + enum G; + void f61 (enum G); // { dg-message "note: previous declaration of 'f61' with type 'void\\(enum G\\)'" "note" } + void f61 (unsigned) // { dg-error "conflicting types for 'f61'; have 'void\\(unsigned int\\)'" } + { } +} + +// { dg-prune-output "nested function '\[^\n\r ]+' declared but never defined" } diff --git a/gcc/testsuite/gcc.dg/qual-return-7.c b/gcc/testsuite/gcc.dg/qual-return-7.c new file mode 100644 index 00000000000..96f7f16305d --- /dev/null +++ b/gcc/testsuite/gcc.dg/qual-return-7.c @@ -0,0 +1,18 @@ +/* Same as qual-return-3.c but with nested functions. + { dg-do compile } + { dg-options "-std=gnu99" } */ + +void test_local (void) +{ + auto int foo (); /* { dg-message "note: previous declaration" "different qualifiers" } */ + + const int foo () { return 0; } /* { dg-error "conflicting types" "different qualifiers" } */ + + auto void bar (void); + volatile void bar () { } /* { dg-warning "qualified|volatile" "different qualifiers" } */ + + auto volatile void baz (void); + void baz () { } /* { dg-warning "not compatible" "different qualifiers" } */ +} + +/* { dg-prune-output "nested function 'foo' declared but never defined" } */ diff --git a/gcc/testsuite/gcc.dg/qual-return-8.c b/gcc/testsuite/gcc.dg/qual-return-8.c new file mode 100644 index 00000000000..de1e7cb7b64 --- /dev/null +++ b/gcc/testsuite/gcc.dg/qual-return-8.c @@ -0,0 +1,28 @@ +/* Same as qual-return-7.c but in C11 mode. + { dg-do compile } + { dg-options "-std=gnu11" } */ + +void test_local (void) +{ +#if 0 + /* _Atomic is not considered a qualifier and so is not ignored + on a return type. As a result, the redeclaration below isn't + valid. See also qual-return-5.c. */ + auto int fi_ai (); + _Atomic int fi_ai () { return 0; } +#endif + + auto int fi_ci (); + const int fi_ci () { return 0; } + + auto enum E fe_ce (); + + enum E { e }; + const enum E fe_ce () { return 0; } + + auto void fv_vv (void); + volatile void fv_vv () { } + + auto volatile void fvv_v (void); + void fvv_v () { } +} diff --git a/gcc/testsuite/gcc.dg/redecl-11.c b/gcc/testsuite/gcc.dg/redecl-11.c index 5540e40503c..3c6f64fca51 100644 --- a/gcc/testsuite/gcc.dg/redecl-11.c +++ b/gcc/testsuite/gcc.dg/redecl-11.c @@ -5,5 +5,5 @@ /* { dg-options "" } */ int f(int (*)[]); -void g() { int f(int (*)[2]); } /* { dg-message "note: previous declaration of 'f' was here" } */ +void g() { int f(int (*)[2]); } /* { dg-message "note: previous declaration of 'f'" "note" } */ int f(int (*)[3]); /* { dg-error "conflicting types for 'f'" } */ diff --git a/gcc/testsuite/gcc.dg/redecl-12.c b/gcc/testsuite/gcc.dg/redecl-12.c index 711b8a3fcae..9922cf49fc5 100644 --- a/gcc/testsuite/gcc.dg/redecl-12.c +++ b/gcc/testsuite/gcc.dg/redecl-12.c @@ -5,5 +5,5 @@ /* { dg-options "" } */ extern int a[]; -void f(void) { extern int a[]; extern int a[10]; } /* { dg-message "note: previous declaration of 'a' was here" } */ +void f(void) { extern int a[]; extern int a[10]; } /* { dg-message "note: previous declaration of 'a'" "note" } */ extern int a[5]; /* { dg-error "conflicting types for 'a'" } */ diff --git a/gcc/testsuite/gcc.dg/redecl-13.c b/gcc/testsuite/gcc.dg/redecl-13.c index 3f05d0fb168..556a3cd69b6 100644 --- a/gcc/testsuite/gcc.dg/redecl-13.c +++ b/gcc/testsuite/gcc.dg/redecl-13.c @@ -5,5 +5,5 @@ /* { dg-options "" } */ extern int a[]; -void f(void) { extern int a[10]; } /* { dg-message "note: previous declaration of 'a' was here" } */ +void f(void) { extern int a[10]; } /* { dg-message "note: previous declaration of 'a'" "note" } */ extern int a[5]; /* { dg-error "conflicting types for 'a'" } */ diff --git a/gcc/testsuite/gcc.dg/redecl-15.c b/gcc/testsuite/gcc.dg/redecl-15.c index ff484c99542..06d6523eea6 100644 --- a/gcc/testsuite/gcc.dg/redecl-15.c +++ b/gcc/testsuite/gcc.dg/redecl-15.c @@ -7,7 +7,7 @@ void f (void) { - g(); /* { dg-message "note: previous implicit declaration of 'g' was here" } */ + g(); /* { dg-message "note: previous implicit declaration of 'g'" } */ { void g(); /* { dg-warning "conflicting types for 'g'" } */ } diff --git a/gcc/testsuite/gcc.dg/tls/thr-init-1.c b/gcc/testsuite/gcc.dg/tls/thr-init-1.c index a9b60612be2..af51484b491 100644 --- a/gcc/testsuite/gcc.dg/tls/thr-init-1.c +++ b/gcc/testsuite/gcc.dg/tls/thr-init-1.c @@ -6,4 +6,4 @@ static __thread int fstat = 1 ; /* { dg-line fstat_prev } */ static __thread int fstat ; static __thread int fstat = 2; /* { dg-error "redefinition of 'fstat'" "" { target *-*-* } .-1 } */ -/* { dg-message "note: previous definition of 'fstat' was here" "" { target *-*-* } fstat_prev } */ +/* { dg-message "note: previous definition of 'fstat'" "note" { target *-*-* } fstat_prev } */ diff --git a/gcc/testsuite/objc.dg/id-1.m b/gcc/testsuite/objc.dg/id-1.m index 2bfcc63f9e7..271dbe64e96 100644 --- a/gcc/testsuite/objc.dg/id-1.m +++ b/gcc/testsuite/objc.dg/id-1.m @@ -2,6 +2,6 @@ /* { dg-do compile } */ typedef int id; /* { dg-error "conflicting types for .id." } */ -/* { dg-message "previous declaration of .id. was here" "" { target *-*-* } 0 } */ +/* { dg-message "previous declaration of .id." "" { target *-*-* } 0 } */ id b; diff --git a/gcc/testsuite/objc.dg/tls/diag-3.m b/gcc/testsuite/objc.dg/tls/diag-3.m index c71f66fb8f5..b39d5658c91 100644 --- a/gcc/testsuite/objc.dg/tls/diag-3.m +++ b/gcc/testsuite/objc.dg/tls/diag-3.m @@ -1,10 +1,10 @@ /* Report invalid extern and __thread combinations. */ /* { dg-require-effective-target tls } */ -extern int j; /* { dg-message "previous declaration of 'j' was here" } */ +extern int j; /* { dg-message "previous declaration of 'j'" } */ __thread int j; /* { dg-error "follows non-thread-local" } */ -extern __thread int i; /* { dg-message "previous declaration of 'i' was here" } */ +extern __thread int i; /* { dg-message "previous declaration of 'i'" } */ int i; /* { dg-error "follows thread-local" } */ extern __thread int k; /* This is fine. */