From 52ffa82671d74d4b1bf4551643e48213e57ae5c4 Mon Sep 17 00:00:00 2001 From: Paolo Carlini Date: Thu, 13 Jun 2019 08:45:46 +0000 Subject: [PATCH] decl.c (grokdeclarator): Use id_loc in five additional places in the last part of the function. /cp 2019-06-13 Paolo Carlini * decl.c (grokdeclarator): Use id_loc in five additional places in the last part of the function. /testsuite 2019-06-13 Paolo Carlini * g++.dg/diagnostic/variably-modified-type-1.C: New. * g++.dg/cpp0x/alias-decl-1.C: Test the location too. * g++.dg/other/pr84792-1.C: Likewise. * g++.dg/other/pr84792-2.C: Likewise. * g++.dg/parse/error24.C: Likewise. * g++.dg/parse/error32.C: Likewise. * g++.dg/parse/error33.C: Likewise. * g++.dg/parse/saved1.C: Likewise. * g++.dg/template/operator6.C: Likewise. * g++.dg/template/pr61745.C: Likewise. * g++.dg/template/typedef41.C: Likewise. * g++.old-deja/g++.jason/crash10.C: Likewise. /cp 2019-06-13 Paolo Carlini * decl.c (grokdeclarator): Move further up the declaration of id_loc, use it immediately, update its value after the loop over declarator, use it again in the final part of function; improve locations of error messages about multiple data types and conflicting specifiers. /testsuite 2019-06-13 Paolo Carlini * g++.dg/diagnostic/conflicting-specifiers-1.C: New. * g++.dg/diagnostic/two-or-more-data-types-1.C: Likewise. * g++.dg/parse/error10.C: Adjust location. * g++.dg/parse/pragma2.C: Likewise. From-SVN: r272236 --- gcc/cp/ChangeLog | 13 ++++ gcc/cp/decl.c | 75 ++++++++++--------- gcc/testsuite/ChangeLog | 22 ++++++ gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C | 3 +- .../diagnostic/conflicting-specifiers-1.C | 1 + .../diagnostic/two-or-more-data-types-1.C | 1 + .../diagnostic/variably-modified-type-1.C | 12 +++ gcc/testsuite/g++.dg/other/pr84792-1.C | 2 +- gcc/testsuite/g++.dg/other/pr84792-2.C | 2 +- gcc/testsuite/g++.dg/parse/error10.C | 2 +- gcc/testsuite/g++.dg/parse/error24.C | 2 +- gcc/testsuite/g++.dg/parse/error32.C | 2 +- gcc/testsuite/g++.dg/parse/error33.C | 2 +- gcc/testsuite/g++.dg/parse/pragma2.C | 3 +- gcc/testsuite/g++.dg/parse/saved1.C | 3 +- gcc/testsuite/g++.dg/template/operator6.C | 2 +- gcc/testsuite/g++.dg/template/pr61745.C | 3 +- gcc/testsuite/g++.dg/template/typedef41.C | 2 +- .../g++.old-deja/g++.jason/crash10.C | 2 +- 19 files changed, 105 insertions(+), 49 deletions(-) create mode 100644 gcc/testsuite/g++.dg/diagnostic/conflicting-specifiers-1.C create mode 100644 gcc/testsuite/g++.dg/diagnostic/two-or-more-data-types-1.C create mode 100644 gcc/testsuite/g++.dg/diagnostic/variably-modified-type-1.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index da5dec37b19..c6823b57aa7 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,16 @@ +2019-06-13 Paolo Carlini + + * decl.c (grokdeclarator): Use id_loc in five additional places + in the last part of the function. + +2019-06-13 Paolo Carlini + + * decl.c (grokdeclarator): Move further up the declaration of + id_loc, use it immediately, update its value after the loop + over declarator, use it again in the final part of function; + improve locations of error messages about multiple data types + and conflicting specifiers. + 2019-06-13 Richard Biener PR c++/90801 diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index ca248111eb5..0a3ef452536 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -10456,6 +10456,10 @@ grokdeclarator (const cp_declarator *declarator, if (typespec_loc == UNKNOWN_LOCATION) typespec_loc = input_location; + location_t id_loc = declarator ? declarator->id_loc : input_location; + if (id_loc == UNKNOWN_LOCATION) + id_loc = input_location; + /* Look inside a declarator for the name being declared and get it as a string, for an error message. */ for (id_declarator = declarator; @@ -10620,8 +10624,7 @@ grokdeclarator (const cp_declarator *declarator, D1 ( parameter-declaration-clause) ... */ if (funcdef_flag && innermost_code != cdk_function) { - error_at (declarator->id_loc, - "function definition does not declare parameters"); + error_at (id_loc, "function definition does not declare parameters"); return error_mark_node; } @@ -10629,8 +10632,7 @@ grokdeclarator (const cp_declarator *declarator, && innermost_code != cdk_function && ! (ctype && !declspecs->any_specifiers_p)) { - error_at (declarator->id_loc, - "declaration of %qD as non-function", dname); + error_at (id_loc, "declaration of %qD as non-function", dname); return error_mark_node; } @@ -10639,8 +10641,7 @@ grokdeclarator (const cp_declarator *declarator, if (UDLIT_OPER_P (dname) && innermost_code != cdk_function) { - error_at (declarator->id_loc, - "declaration of %qD as non-function", dname); + error_at (id_loc, "declaration of %qD as non-function", dname); return error_mark_node; } @@ -10648,14 +10649,12 @@ grokdeclarator (const cp_declarator *declarator, { if (typedef_p) { - error_at (declarator->id_loc, - "declaration of %qD as %", dname); + error_at (id_loc, "declaration of %qD as %", dname); return error_mark_node; } else if (decl_context == PARM || decl_context == CATCHPARM) { - error_at (declarator->id_loc, - "declaration of %qD as parameter", dname); + error_at (id_loc, "declaration of %qD as parameter", dname); return error_mark_node; } } @@ -10705,13 +10704,16 @@ grokdeclarator (const cp_declarator *declarator, issue an error message. */ if (declspecs->multiple_types_p) { - error ("two or more data types in declaration of %qs", name); + error_at (typespec_loc, + "two or more data types in declaration of %qs", name); return error_mark_node; } if (declspecs->conflicting_specifiers_p) { - error ("conflicting specifiers in declaration of %qs", name); + error_at (min_location (declspecs->locations[ds_typedef], + declspecs->locations[ds_storage_class]), + "conflicting specifiers in declaration of %qs", name); return error_mark_node; } @@ -11861,6 +11863,8 @@ grokdeclarator (const cp_declarator *declarator, } } + id_loc = declarator ? declarator->id_loc : input_location; + /* A `constexpr' specifier used in an object declaration declares the object as `const'. */ if (constexpr_p && innermost_code != cdk_function) @@ -11884,8 +11888,6 @@ grokdeclarator (const cp_declarator *declarator, unqualified_id = dname; } - location_t loc = declarator ? declarator->id_loc : input_location; - /* If TYPE is a FUNCTION_TYPE, but the function name was explicitly qualified with a class-name, turn it into a METHOD_TYPE, unless we know that the function is static. We take advantage of this @@ -11912,7 +11914,7 @@ grokdeclarator (const cp_declarator *declarator, friendp = 0; } else - permerror (loc, "extra qualification %<%T::%> on member %qs", + permerror (id_loc, "extra qualification %<%T::%> on member %qs", ctype, name); } else if (/* If the qualifying type is already complete, then we @@ -11941,7 +11943,7 @@ grokdeclarator (const cp_declarator *declarator, if (current_class_type && (!friendp || funcdef_flag || initialized)) { - error_at (loc, funcdef_flag || initialized + error_at (id_loc, funcdef_flag || initialized ? G_("cannot define member function %<%T::%s%> " "within %qT") : G_("cannot declare member function %<%T::%s%> " @@ -11952,7 +11954,7 @@ grokdeclarator (const cp_declarator *declarator, } else if (typedef_p && current_class_type) { - error_at (loc, "cannot declare member %<%T::%s%> within %qT", + error_at (id_loc, "cannot declare member %<%T::%s%> within %qT", ctype, name, current_class_type); return error_mark_node; } @@ -12000,9 +12002,11 @@ grokdeclarator (const cp_declarator *declarator, && variably_modified_type_p (type, NULL_TREE)) { if (decl_context == FIELD) - error ("data member may not have variably modified type %qT", type); + error_at (id_loc, + "data member may not have variably modified type %qT", type); else - error ("parameter may not have variably modified type %qT", type); + error_at (id_loc, + "parameter may not have variably modified type %qT", type); type = error_mark_node; } @@ -12106,14 +12110,14 @@ grokdeclarator (const cp_declarator *declarator, if (id_declarator && declarator->u.id.qualifying_scope) { - error ("typedef name may not be a nested-name-specifier"); + error_at (id_loc, "typedef name may not be a nested-name-specifier"); type = error_mark_node; } if (decl_context == FIELD) - decl = build_lang_decl_loc (loc, TYPE_DECL, unqualified_id, type); + decl = build_lang_decl_loc (id_loc, TYPE_DECL, unqualified_id, type); else - decl = build_decl (loc, TYPE_DECL, unqualified_id, type); + decl = build_decl (id_loc, TYPE_DECL, unqualified_id, type); if (decl_context != FIELD) { @@ -12130,7 +12134,7 @@ grokdeclarator (const cp_declarator *declarator, } else if (current_class_type && constructor_name_p (unqualified_id, current_class_type)) - permerror (input_location, "ISO C++ forbids nested type %qD with same name " + permerror (id_loc, "ISO C++ forbids nested type %qD with same name " "as enclosing class", unqualified_id); @@ -12288,7 +12292,7 @@ grokdeclarator (const cp_declarator *declarator, /* Only functions may be declared using an operator-function-id. */ if (dname && IDENTIFIER_ANY_OP_P (dname)) { - error ("declaration of %qD as non-function", dname); + error_at (id_loc, "declaration of %qD as non-function", dname); return error_mark_node; } @@ -12398,8 +12402,8 @@ grokdeclarator (const cp_declarator *declarator, if (in_system_header_at (input_location)) /* Do not warn on flexible array members in system headers because glibc uses them. */; - else if (name && declarator) - pedwarn (declarator->id_loc, OPT_Wpedantic, + else if (name) + pedwarn (id_loc, OPT_Wpedantic, "ISO C++ forbids flexible array member %qs", name); else pedwarn (input_location, OPT_Wpedantic, @@ -12551,7 +12555,7 @@ grokdeclarator (const cp_declarator *declarator, initialized == SD_DELETED, sfk, funcdef_flag, late_return_type_p, template_count, in_namespace, - attrlist, declarator->id_loc); + attrlist, id_loc); decl = set_virt_specifiers (decl, virt_specifiers); if (decl == NULL_TREE) return error_mark_node; @@ -12584,8 +12588,7 @@ grokdeclarator (const cp_declarator *declarator, { if (unqualified_id) { - error_at (declarator->id_loc, - "field %qD has incomplete type %qT", + error_at (id_loc, "field %qD has incomplete type %qT", unqualified_id, type); cxx_incomplete_type_inform (strip_array_types (type)); } @@ -12600,8 +12603,8 @@ grokdeclarator (const cp_declarator *declarator, { if (friendp) { - if (unqualified_id && declarator) - error_at (declarator->id_loc, + if (unqualified_id) + error_at (id_loc, "%qE is neither function nor member function; " "cannot be declared friend", unqualified_id); else @@ -12645,7 +12648,7 @@ grokdeclarator (const cp_declarator *declarator, { /* C++ allows static class members. All other work for this is done by grokfield. */ - decl = build_lang_decl_loc (loc, VAR_DECL, + decl = build_lang_decl_loc (id_loc, VAR_DECL, unqualified_id, type); set_linkage_for_static_data_member (decl); if (concept_p) @@ -12693,7 +12696,7 @@ grokdeclarator (const cp_declarator *declarator, unqualified_id); constexpr_p = false; } - decl = build_decl (loc, FIELD_DECL, unqualified_id, type); + decl = build_decl (id_loc, FIELD_DECL, unqualified_id, type); DECL_NONADDRESSABLE_P (decl) = bitfield; if (bitfield && !unqualified_id) { @@ -12811,7 +12814,7 @@ grokdeclarator (const cp_declarator *declarator, funcdef_flag, late_return_type_p, template_count, in_namespace, attrlist, - declarator->id_loc); + id_loc); if (decl == NULL_TREE) return error_mark_node; @@ -12858,7 +12861,7 @@ grokdeclarator (const cp_declarator *declarator, concept_p, template_count, ctype ? ctype : in_namespace, - loc); + id_loc); if (decl == NULL_TREE) return error_mark_node; @@ -12904,7 +12907,7 @@ grokdeclarator (const cp_declarator *declarator, if (innermost_code == cdk_decomp) { gcc_assert (declarator && declarator->kind == cdk_decomp); - DECL_SOURCE_LOCATION (decl) = declarator->id_loc; + DECL_SOURCE_LOCATION (decl) = id_loc; DECL_ARTIFICIAL (decl) = 1; fit_decomposition_lang_decl (decl, NULL_TREE); } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f82dc9e09ed..865408b76dd 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,25 @@ +2019-06-13 Paolo Carlini + + * g++.dg/diagnostic/variably-modified-type-1.C: New. + * g++.dg/cpp0x/alias-decl-1.C: Test the location too. + * g++.dg/other/pr84792-1.C: Likewise. + * g++.dg/other/pr84792-2.C: Likewise. + * g++.dg/parse/error24.C: Likewise. + * g++.dg/parse/error32.C: Likewise. + * g++.dg/parse/error33.C: Likewise. + * g++.dg/parse/saved1.C: Likewise. + * g++.dg/template/operator6.C: Likewise. + * g++.dg/template/pr61745.C: Likewise. + * g++.dg/template/typedef41.C: Likewise. + * g++.old-deja/g++.jason/crash10.C: Likewise. + +2019-06-13 Paolo Carlini + + * g++.dg/diagnostic/conflicting-specifiers-1.C: New. + * g++.dg/diagnostic/two-or-more-data-types-1.C: Likewise. + * g++.dg/parse/error10.C: Adjust location. + * g++.dg/parse/pragma2.C: Likewise. + 2019-06-13 Feng Xue PR tree-optimization/89713 diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C index c52ab46aa5e..43284d76978 100644 --- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C @@ -11,5 +11,6 @@ template using Ptr = U*; template struct Ptr {}; // { dg-error "specialization" } struct A { - using A = int;//{ dg-error "nested|has|same name as|class|in which|declared" } + using A = int; // { dg-error "11:ISO C\\+\\+ forbids nested type .A." } +// { dg-error "same name as" "" { target c++11 } .-1 } }; diff --git a/gcc/testsuite/g++.dg/diagnostic/conflicting-specifiers-1.C b/gcc/testsuite/g++.dg/diagnostic/conflicting-specifiers-1.C new file mode 100644 index 00000000000..1a8ac02b77e --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/conflicting-specifiers-1.C @@ -0,0 +1 @@ +static typedef int i __attribute__((unused)); // { dg-error "1:conflicting specifiers" } diff --git a/gcc/testsuite/g++.dg/diagnostic/two-or-more-data-types-1.C b/gcc/testsuite/g++.dg/diagnostic/two-or-more-data-types-1.C new file mode 100644 index 00000000000..4323a369e18 --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/two-or-more-data-types-1.C @@ -0,0 +1 @@ +char int i __attribute__((unused)); // { dg-error "1:two or more data types" } diff --git a/gcc/testsuite/g++.dg/diagnostic/variably-modified-type-1.C b/gcc/testsuite/g++.dg/diagnostic/variably-modified-type-1.C new file mode 100644 index 00000000000..4402d129733 --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/variably-modified-type-1.C @@ -0,0 +1,12 @@ +// { dg-options "" } + +void foo () +{ + int n; + typedef int X[n]; + struct Z + { + X x __attribute__((unused)); // { dg-error "7:data member may not have variably modified type" } + void bar (X x __attribute__((unused))); // { dg-error "17:parameter may not have variably modified type" } + }; +} diff --git a/gcc/testsuite/g++.dg/other/pr84792-1.C b/gcc/testsuite/g++.dg/other/pr84792-1.C index 23df8ae18ad..9949efd0959 100644 --- a/gcc/testsuite/g++.dg/other/pr84792-1.C +++ b/gcc/testsuite/g++.dg/other/pr84792-1.C @@ -3,4 +3,4 @@ struct A {}; typedef struct { virtual void foo() {} -} A::B; // { dg-error "typedef" } +} A::B; // { dg-error "3:typedef" } diff --git a/gcc/testsuite/g++.dg/other/pr84792-2.C b/gcc/testsuite/g++.dg/other/pr84792-2.C index a393d5771ce..082baae747f 100644 --- a/gcc/testsuite/g++.dg/other/pr84792-2.C +++ b/gcc/testsuite/g++.dg/other/pr84792-2.C @@ -3,4 +3,4 @@ struct A {}; typedef struct { void foo() {} -} A::B; // { dg-error "typedef" } +} A::B; // { dg-error "3:typedef" } diff --git a/gcc/testsuite/g++.dg/parse/error10.C b/gcc/testsuite/g++.dg/parse/error10.C index 46c9eff7bbc..4750e5cbb5a 100644 --- a/gcc/testsuite/g++.dg/parse/error10.C +++ b/gcc/testsuite/g++.dg/parse/error10.C @@ -14,4 +14,4 @@ template void foo() enum typename A::E e4; } -// { dg-error "28:two or more data types in declaration of 'e4'" "2 or more" { target *-*-* } 14 } +// { dg-error "3:two or more data types in declaration of 'e4'" "2 or more" { target *-*-* } 14 } diff --git a/gcc/testsuite/g++.dg/parse/error24.C b/gcc/testsuite/g++.dg/parse/error24.C index c8ab6d9921a..190812e9f0a 100644 --- a/gcc/testsuite/g++.dg/parse/error24.C +++ b/gcc/testsuite/g++.dg/parse/error24.C @@ -2,7 +2,7 @@ // PR c++/19395 struct A { - typedef int ::X; // { dg-error "17:typedef name may not be a nested-name-specifier" } + typedef int ::X; // { dg-error "15:typedef name may not be a nested-name-specifier" } }; diff --git a/gcc/testsuite/g++.dg/parse/error32.C b/gcc/testsuite/g++.dg/parse/error32.C index da27afdda2b..1993c068b47 100644 --- a/gcc/testsuite/g++.dg/parse/error32.C +++ b/gcc/testsuite/g++.dg/parse/error32.C @@ -3,7 +3,7 @@ struct A {}; -typedef void (A::T)(); /* { dg-error "typedef name may not be a nested-name-specifier" } */ +typedef void (A::T)(); /* { dg-error "15:typedef name may not be a nested-name-specifier" } */ void foo() { diff --git a/gcc/testsuite/g++.dg/parse/error33.C b/gcc/testsuite/g++.dg/parse/error33.C index e3a7166edda..0d25386a879 100644 --- a/gcc/testsuite/g++.dg/parse/error33.C +++ b/gcc/testsuite/g++.dg/parse/error33.C @@ -6,7 +6,7 @@ struct A void foo(); }; -typedef void (A::T)(); /* { dg-error "typedef name may not be a nested" } */ +typedef void (A::T)(); /* { dg-error "15:typedef name may not be a nested" } */ void bar(T); /* { dg-message "note: declared here" } */ diff --git a/gcc/testsuite/g++.dg/parse/pragma2.C b/gcc/testsuite/g++.dg/parse/pragma2.C index c5616ff74f5..c7d4f10751c 100644 --- a/gcc/testsuite/g++.dg/parse/pragma2.C +++ b/gcc/testsuite/g++.dg/parse/pragma2.C @@ -4,5 +4,6 @@ // does not. int f(int x, #pragma interface // { dg-error "not allowed here" } +// { dg-bogus "two or more" "" { xfail *-*-* } .-1 } // The parser gets confused and issues an error on the next line. - int y); // { dg-bogus "" "" { xfail *-*-* } } + int y); diff --git a/gcc/testsuite/g++.dg/parse/saved1.C b/gcc/testsuite/g++.dg/parse/saved1.C index 0153fb2a1a6..979a05676d2 100644 --- a/gcc/testsuite/g++.dg/parse/saved1.C +++ b/gcc/testsuite/g++.dg/parse/saved1.C @@ -1,6 +1,7 @@ // Test that the parser doesn't go into an infinite loop from ignoring the // PRE_PARSED_FUNCTION_DECL token. -class C { static void* operator new(size_t); }; // { dg-error "" } +class C { static void* operator new(size_t); }; // { dg-error "24:declaration of .operator new. as non-function" } +// { dg-error "expected|ISO C\\+\\+ forbids" "" { target *-*-* } .-1 } void* C::operator new(size_t) { return 0; } // { dg-error "" } class D { D(int i): integer(i){}}; // { dg-error "" } diff --git a/gcc/testsuite/g++.dg/template/operator6.C b/gcc/testsuite/g++.dg/template/operator6.C index 94a869bccd5..189dcc26e15 100644 --- a/gcc/testsuite/g++.dg/template/operator6.C +++ b/gcc/testsuite/g++.dg/template/operator6.C @@ -1,4 +1,4 @@ // PR c++/27315 // { dg-do compile } -template void operator+; // { dg-error "non-function" } +template void operator+; // { dg-error "15:declaration of .operator\\+. as non-function" } diff --git a/gcc/testsuite/g++.dg/template/pr61745.C b/gcc/testsuite/g++.dg/template/pr61745.C index da5973e3867..a44bfa8afe1 100644 --- a/gcc/testsuite/g++.dg/template/pr61745.C +++ b/gcc/testsuite/g++.dg/template/pr61745.C @@ -20,5 +20,6 @@ public: Zp operator-() const { return Zp(p-val); } // In C++2A, we have an unqualified-id (operator-) followed by // '<', and name lookup found a function. - friend Zp operator- <>(const Zp& a, const Zp& b); // { dg-error "declaration|expected" "" { target c++17_down } } + friend Zp operator- <>(const Zp& a, const Zp& b); // { dg-error "20:declaration of .operator\\-. as non-function" "" { target c++17_down } } + // { dg-error "expected" "" { target c++17_down } .-1 } }; diff --git a/gcc/testsuite/g++.dg/template/typedef41.C b/gcc/testsuite/g++.dg/template/typedef41.C index dc25518bf06..e6619d7dccd 100644 --- a/gcc/testsuite/g++.dg/template/typedef41.C +++ b/gcc/testsuite/g++.dg/template/typedef41.C @@ -2,7 +2,7 @@ template struct A { - typedef int ::X; // { dg-error "" } + typedef int ::X; // { dg-error "15:typedef name" } }; A<0> a; diff --git a/gcc/testsuite/g++.old-deja/g++.jason/crash10.C b/gcc/testsuite/g++.old-deja/g++.jason/crash10.C index cd9b7b0b2d2..2d1f71db192 100644 --- a/gcc/testsuite/g++.old-deja/g++.jason/crash10.C +++ b/gcc/testsuite/g++.old-deja/g++.jason/crash10.C @@ -5,4 +5,4 @@ struct A { enum foo { bar }; }; -typedef A::foo A::foo; // { dg-error "" } causes compiler segfault +typedef A::foo A::foo; // { dg-error "16:typedef name" } causes compiler segfault -- 2.30.2