From 2dac4037aa79029c73444ef73667621e0cbac3bf Mon Sep 17 00:00:00 2001 From: Paolo Carlini Date: Tue, 3 Jul 2018 21:03:51 +0000 Subject: [PATCH] decl.c (min_location): New. /cp 2018-07-03 Paolo Carlini * decl.c (min_location): New. (smallest_type_quals_location): Use the latter. (check_concept_fn): Use DECL_SOURCE_LOCATION. (grokdeclarator): Use accurate locations in a number of error messages involving ds_thread, ds_storage_class, ds_virtual, ds_constexpr, ds_typedef and ds_friend; exploit min_location. /testsuite 2018-07-03 Paolo Carlini * g++.dg/other/locations1.C: New. * g++.dg/tls/locations1.C: Likewise. * g++.dg/diagnostic/virtual-constexpr.C: Likewise. * g++.dg/diagnostic/virtual-static.C: Likewise. * g++.dg/concepts/fn-concept2.C: Test the locations too. * g++.dg/cpp0x/constexpr-virtual5.C: Likewise. * g++.dg/cpp0x/pr51463.C: Likewise. * g++.dg/other/typedef1.C: Likewise. * g++.dg/parse/dtor13.C: Likewise. * g++.dg/template/error44.C: Likewise. * g++.dg/template/typedef4.C: Likewise. * g++.dg/template/typedef5.C: Likewise. * g++.dg/tls/diag-2.C: Likewise. * g++.old-deja/g++.brendan/crash11.C: Likewise. From-SVN: r262358 --- gcc/cp/ChangeLog | 9 ++ gcc/cp/decl.c | 98 +++++++++++++------ gcc/testsuite/ChangeLog | 17 ++++ gcc/testsuite/g++.dg/concepts/fn-concept2.C | 7 +- .../g++.dg/cpp0x/constexpr-virtual5.C | 2 +- gcc/testsuite/g++.dg/cpp0x/pr51463.C | 3 +- .../g++.dg/diagnostic/virtual-constexpr.C | 16 +++ .../g++.dg/diagnostic/virtual-static.C | 15 +++ gcc/testsuite/g++.dg/other/locations1.C | 1 + gcc/testsuite/g++.dg/other/typedef1.C | 11 ++- gcc/testsuite/g++.dg/parse/dtor13.C | 3 +- gcc/testsuite/g++.dg/template/error44.C | 11 ++- gcc/testsuite/g++.dg/template/typedef4.C | 3 +- gcc/testsuite/g++.dg/template/typedef5.C | 11 ++- gcc/testsuite/g++.dg/tls/diag-2.C | 14 +-- gcc/testsuite/g++.dg/tls/locations1.C | 4 + .../g++.old-deja/g++.brendan/crash11.C | 5 +- 17 files changed, 171 insertions(+), 59 deletions(-) create mode 100644 gcc/testsuite/g++.dg/diagnostic/virtual-constexpr.C create mode 100644 gcc/testsuite/g++.dg/diagnostic/virtual-static.C create mode 100644 gcc/testsuite/g++.dg/other/locations1.C create mode 100644 gcc/testsuite/g++.dg/tls/locations1.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e4202e161ba..c27e2deb2ce 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2018-07-03 Paolo Carlini + + * decl.c (min_location): New. + (smallest_type_quals_location): Use the latter. + (check_concept_fn): Use DECL_SOURCE_LOCATION. + (grokdeclarator): Use accurate locations in a number of error + messages involving ds_thread, ds_storage_class, ds_virtual, + ds_constexpr, ds_typedef and ds_friend; exploit min_location. + 2018-07-03 Marek Polacek PR c++/86201 diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index c04b9b7d457..0ea3c4a3490 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -8545,15 +8545,18 @@ check_concept_fn (tree fn) { // A constraint is nullary. if (DECL_ARGUMENTS (fn)) - error ("concept %q#D declared with function parameters", fn); + error_at (DECL_SOURCE_LOCATION (fn), + "concept %q#D declared with function parameters", fn); // The declared return type of the concept shall be bool, and // it shall not be deduced from it definition. tree type = TREE_TYPE (TREE_TYPE (fn)); if (is_auto (type)) - error ("concept %q#D declared with a deduced return type", fn); + error_at (DECL_SOURCE_LOCATION (fn), + "concept %q#D declared with a deduced return type", fn); else if (type != boolean_type_node) - error ("concept %q#D with non-% return type %qT", fn, type); + error_at (DECL_SOURCE_LOCATION (fn), + "concept %q#D with non-% return type %qT", fn, type); } /* Helper function. Replace the temporary this parameter injected @@ -9795,6 +9798,18 @@ create_array_type_for_decl (tree name, tree type, tree size) return build_cplus_array_type (type, itype); } +/* Returns the smallest location that is not UNKNOWN_LOCATION. */ + +static location_t +min_location (location_t loca, location_t locb) +{ + if (loca == UNKNOWN_LOCATION + || (locb != UNKNOWN_LOCATION + && linemap_location_before_p (line_table, locb, loca))) + return locb; + return loca; +} + /* Returns the smallest location != UNKNOWN_LOCATION among the three stored in LOCATIONS[ds_const], LOCATIONS[ds_volatile], and LOCATIONS[ds_restrict]. */ @@ -9807,13 +9822,11 @@ smallest_type_quals_location (int type_quals, const location_t* locations) if (type_quals & TYPE_QUAL_CONST) loc = locations[ds_const]; - if ((type_quals & TYPE_QUAL_VOLATILE) - && (loc == UNKNOWN_LOCATION || locations[ds_volatile] < loc)) - loc = locations[ds_volatile]; + if (type_quals & TYPE_QUAL_VOLATILE) + loc = min_location (loc, locations[ds_volatile]); - if ((type_quals & TYPE_QUAL_RESTRICT) - && (loc == UNKNOWN_LOCATION || locations[ds_restrict] < loc)) - loc = locations[ds_restrict]; + if (type_quals & TYPE_QUAL_RESTRICT) + loc = min_location (loc, locations[ds_restrict]); return loc; } @@ -10710,14 +10723,20 @@ grokdeclarator (const cp_declarator *declarator, { if (staticp == 2) { - error ("member %qD cannot be declared both % " - "and %", dname); + rich_location richloc (line_table, declspecs->locations[ds_virtual]); + richloc.add_range (declspecs->locations[ds_storage_class], false); + error_at (&richloc, "member %qD cannot be declared both % " + "and %", dname); storage_class = sc_none; staticp = 0; } if (constexpr_p) - error ("member %qD cannot be declared both % " - "and %", dname); + { + rich_location richloc (line_table, declspecs->locations[ds_virtual]); + richloc.add_range (declspecs->locations[ds_constexpr], false); + error_at (&richloc, "member %qD cannot be declared both % " + "and %", dname); + } } friendp = decl_spec_seq_has_spec_p (declspecs, ds_friend); @@ -10726,18 +10745,27 @@ grokdeclarator (const cp_declarator *declarator, { if (typedef_p) { - error ("typedef declaration invalid in parameter declaration"); + error_at (declspecs->locations[ds_typedef], + "typedef declaration invalid in parameter declaration"); return error_mark_node; } else if (template_parm_flag && storage_class != sc_none) { - error ("storage class specified for template parameter %qs", name); + error_at (min_location (declspecs->locations[ds_thread], + declspecs->locations[ds_storage_class]), + "storage class specified for template parameter %qs", + name); return error_mark_node; } else if (storage_class == sc_static || storage_class == sc_extern || thread_p) - error ("storage class specifiers invalid in parameter declarations"); + { + error_at (min_location (declspecs->locations[ds_thread], + declspecs->locations[ds_storage_class]), + "storage class specified for parameter %qs", name); + return error_mark_node; + } /* Function parameters cannot be concept. */ if (concept_p) @@ -10871,15 +10899,15 @@ grokdeclarator (const cp_declarator *declarator, ; else { + location_t loc + = min_location (declspecs->locations[ds_thread], + declspecs->locations[ds_storage_class]); if (decl_context == FIELD) - error ("storage class specified for %qs", name); + error_at (loc, "storage class specified for %qs", name); + else if (decl_context == PARM || decl_context == CATCHPARM) + error_at (loc, "storage class specified for parameter %qs", name); else - { - if (decl_context == PARM || decl_context == CATCHPARM) - error ("storage class specified for parameter %qs", name); - else - error ("storage class specified for typename"); - } + error_at (loc, "storage class specified for typename"); if (storage_class == sc_register || storage_class == sc_auto || storage_class == sc_extern @@ -10900,7 +10928,8 @@ grokdeclarator (const cp_declarator *declarator, && storage_class != sc_static) { if (declspecs->gnu_thread_keyword_p) - pedwarn (input_location, 0, "function-scope %qs implicitly auto and " + pedwarn (declspecs->locations[ds_thread], + 0, "function-scope %qs implicitly auto and " "declared %<__thread%>", name); /* When thread_local is applied to a variable of block scope the @@ -10912,7 +10941,10 @@ grokdeclarator (const cp_declarator *declarator, if (storage_class && friendp) { - error ("storage class specifiers invalid in friend function declarations"); + error_at (min_location (declspecs->locations[ds_thread], + declspecs->locations[ds_storage_class]), + "storage class specifiers invalid in friend function " + "declarations"); storage_class = sc_none; staticp = 0; } @@ -11238,7 +11270,8 @@ grokdeclarator (const cp_declarator *declarator, if (virtualp) { /* Cannot be both friend and virtual. */ - error ("virtual functions cannot be friends"); + error_at (declspecs->locations[ds_friend], + "virtual functions cannot be friends"); friendp = 0; } if (decl_context == NORMAL) @@ -12369,15 +12402,18 @@ grokdeclarator (const cp_declarator *declarator, else if (thread_p) { if (declspecs->gnu_thread_keyword_p) - error ("storage class %<__thread%> invalid for function %qs", - name); + error_at (declspecs->locations[ds_thread], + "storage class %<__thread%> invalid for function %qs", + name); else - error ("storage class % invalid for function %qs", - name); + error_at (declspecs->locations[ds_thread], + "storage class % invalid for " + "function %qs", name); } if (virt_specifiers) - error ("virt-specifiers in %qs not allowed outside a class definition", name); + error ("virt-specifiers in %qs not allowed outside a class " + "definition", name); /* Function declaration not at top level. Storage classes other than `extern' are not allowed and `extern' makes no difference. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d18061088b8..d4f97d24162 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,20 @@ +2018-07-03 Paolo Carlini + + * g++.dg/other/locations1.C: New. + * g++.dg/tls/locations1.C: Likewise. + * g++.dg/diagnostic/virtual-constexpr.C: Likewise. + * g++.dg/diagnostic/virtual-static.C: Likewise. + * g++.dg/concepts/fn-concept2.C: Test the locations too. + * g++.dg/cpp0x/constexpr-virtual5.C: Likewise. + * g++.dg/cpp0x/pr51463.C: Likewise. + * g++.dg/other/typedef1.C: Likewise. + * g++.dg/parse/dtor13.C: Likewise. + * g++.dg/template/error44.C: Likewise. + * g++.dg/template/typedef4.C: Likewise. + * g++.dg/template/typedef5.C: Likewise. + * g++.dg/tls/diag-2.C: Likewise. + * g++.old-deja/g++.brendan/crash11.C: Likewise. + 2018-07-03 Marek Polacek PR c++/86201 diff --git a/gcc/testsuite/g++.dg/concepts/fn-concept2.C b/gcc/testsuite/g++.dg/concepts/fn-concept2.C index 9acc24177ce..fe88dce1bd4 100644 --- a/gcc/testsuite/g++.dg/concepts/fn-concept2.C +++ b/gcc/testsuite/g++.dg/concepts/fn-concept2.C @@ -1,7 +1,10 @@ // { dg-options "-std=c++17 -fconcepts" } template - concept auto C1() { return 0; } // { dg-error "deduced return type" } + concept auto C1() { return 0; } // { dg-error "16:concept .concept auto C1\\(\\). declared with a deduced return type" } template - concept int C2() { return 0; } // { dg-error "return type" } + concept int C2() { return 0; } // { dg-error "15:concept .concept int C2\\(\\). with non-.bool. return type .int." } + +template + concept bool C3(int) { return 0; } // { dg-error "16:concept .concept bool C3\\(int\\). declared with function parameters" } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-virtual5.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-virtual5.C index 895de506d67..2465f9d9b4f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-virtual5.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-virtual5.C @@ -2,5 +2,5 @@ // { dg-do compile { target c++11 } } struct S { - constexpr virtual int f() { return 1; } // { dg-error "both 'virtual' and 'constexpr'" } + constexpr virtual int f() { return 1; } // { dg-error "13:member .f. cannot be declared both .virtual. and .constexpr." } }; diff --git a/gcc/testsuite/g++.dg/cpp0x/pr51463.C b/gcc/testsuite/g++.dg/cpp0x/pr51463.C index 75de47d60e4..472a812205a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr51463.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr51463.C @@ -3,5 +3,6 @@ struct A { - static virtual int i = 0; // { dg-error "both 'virtual' and 'static'|declared as" } + static virtual int i = 0; // { dg-error "10:member .i. cannot be declared both .virtual. and .static." } + // { dg-error "declared as" "" { target *-*-* } .-1 } }; diff --git a/gcc/testsuite/g++.dg/diagnostic/virtual-constexpr.C b/gcc/testsuite/g++.dg/diagnostic/virtual-constexpr.C new file mode 100644 index 00000000000..2c83236cae9 --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/virtual-constexpr.C @@ -0,0 +1,16 @@ +// { dg-options "-fdiagnostics-show-caret" } +// { dg-do compile { target c++11 } } + +struct S +{ + virtual constexpr void foo(); // { dg-error "3:member .foo. cannot be declared both .virtual. and .constexpr." } +/* { dg-begin-multiline-output "" } + virtual constexpr void foo(); + ^~~~~~~ ~~~~~~~~~ + { dg-end-multiline-output "" } */ + constexpr virtual void bar(); // { dg-error "13:member .bar. cannot be declared both .virtual. and .constexpr." } +/* { dg-begin-multiline-output "" } + constexpr virtual void bar(); + ~~~~~~~~~ ^~~~~~~ + { dg-end-multiline-output "" } */ +}; diff --git a/gcc/testsuite/g++.dg/diagnostic/virtual-static.C b/gcc/testsuite/g++.dg/diagnostic/virtual-static.C new file mode 100644 index 00000000000..bffb05e5b81 --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/virtual-static.C @@ -0,0 +1,15 @@ +// { dg-options "-fdiagnostics-show-caret" } + +struct S +{ + virtual static void foo(); // { dg-error "3:member .foo. cannot be declared both .virtual. and .static." } +/* { dg-begin-multiline-output "" } + virtual static void foo(); + ^~~~~~~ ~~~~~~ + { dg-end-multiline-output "" } */ + static virtual void bar(); // { dg-error "10:member .bar. cannot be declared both .virtual. and .static." } +/* { dg-begin-multiline-output "" } + static virtual void bar(); + ~~~~~~ ^~~~~~~ + { dg-end-multiline-output "" } */ +}; diff --git a/gcc/testsuite/g++.dg/other/locations1.C b/gcc/testsuite/g++.dg/other/locations1.C new file mode 100644 index 00000000000..77b009f19c8 --- /dev/null +++ b/gcc/testsuite/g++.dg/other/locations1.C @@ -0,0 +1 @@ +void foo(static int p); // { dg-error "10:storage class specified" } diff --git a/gcc/testsuite/g++.dg/other/typedef1.C b/gcc/testsuite/g++.dg/other/typedef1.C index ef1684d7aef..83eab1625b8 100644 --- a/gcc/testsuite/g++.dg/other/typedef1.C +++ b/gcc/testsuite/g++.dg/other/typedef1.C @@ -1,7 +1,10 @@ // PR c++/27572 // { dg-do compile } -void f1(typedef) {} // { dg-error "no type|typedef declaration" } -void f2(typedef x) {} // { dg-error "type|typedef declaration" } -void f3(typedef x[]) {} // { dg-error "type|typedef declaration" } -void f4(typedef int x) {} // { dg-error "typedef declaration" } +void f1(typedef) {} // { dg-error "9:typedef declaration" } +// { dg-error "no type" "" { target *-*-* } .-1 } +void f2(typedef x) {} // { dg-error "9:typedef declaration" } +// { dg-error "type" "" { target *-*-* } .-1 } +void f3(typedef x[]) {} // { dg-error "9:typedef declaration" } +// { dg-error "type" "" { target *-*-* } .-1 } +void f4(typedef int x) {} // { dg-error "9:typedef declaration" } diff --git a/gcc/testsuite/g++.dg/parse/dtor13.C b/gcc/testsuite/g++.dg/parse/dtor13.C index 96c0d227b04..c68d41e8372 100644 --- a/gcc/testsuite/g++.dg/parse/dtor13.C +++ b/gcc/testsuite/g++.dg/parse/dtor13.C @@ -3,6 +3,7 @@ struct A { - static friend A::~A(); /* { dg-error "storage class specifiers|extra qualification|implicitly friend" } */ + static friend A::~A(); /* { dg-error "3:storage class specifiers" } */ + /* { dg-error "extra qualification|implicitly friend" "" { target *-*-* } .-1 } */ }; diff --git a/gcc/testsuite/g++.dg/template/error44.C b/gcc/testsuite/g++.dg/template/error44.C index 51053b2d8db..8cf40801efb 100644 --- a/gcc/testsuite/g++.dg/template/error44.C +++ b/gcc/testsuite/g++.dg/template/error44.C @@ -1,7 +1,8 @@ // PR c++/32056 -template struct A {}; // { dg-error "storage class specified|two or more" } -template struct B {}; // { dg-error "storage class specified" } -template struct C {}; // { dg-error "storage class specified" } -template struct D {}; // { dg-error "storage class specified" } -template struct E {}; // { dg-error "storage class specified" } +template struct A {}; // { dg-error "11:storage class specified" "" { target c++98_only } } +// { dg-error "two or more" "" { target c++11 } .-1 } +template struct B {}; // { dg-error "11:storage class specified" } +template struct C {}; // { dg-error "11:storage class specified" } +template struct D {}; // { dg-error "11:storage class specified" } +template struct E {}; // { dg-error "11:storage class specified" } diff --git a/gcc/testsuite/g++.dg/template/typedef4.C b/gcc/testsuite/g++.dg/template/typedef4.C index 2676d8fec1d..f776f331c66 100644 --- a/gcc/testsuite/g++.dg/template/typedef4.C +++ b/gcc/testsuite/g++.dg/template/typedef4.C @@ -1,7 +1,8 @@ // PR c++/27572 // { dg-do compile } -template void foo(); // { dg-error "no type|typedef declaration|template" } +template void foo(); // { dg-error "10:typedef declaration" } +// { dg-error "no type|template" "" { target *-*-* } .-1 } void bar() { diff --git a/gcc/testsuite/g++.dg/template/typedef5.C b/gcc/testsuite/g++.dg/template/typedef5.C index 04b8eac3bcc..eaa61433556 100644 --- a/gcc/testsuite/g++.dg/template/typedef5.C +++ b/gcc/testsuite/g++.dg/template/typedef5.C @@ -1,7 +1,10 @@ // PR c++/27572 // { dg-do compile } -template struct A1; // { dg-error "no type|typedef declaration|default argument" } -template struct A2; // { dg-error "type|typedef declaration|default argument" } -template struct A3; // { dg-error "no type|typedef declaration|expected" } -template struct A4; // { dg-error "typedef declaration|default argument" } +template struct A1; // { dg-error "10:typedef declaration" } +// { dg-error "no type|default argument" "" { target *-*-* } .-1 } +template struct A2; // { dg-error "10:typedef declaration" } +// { dg-error "type|default argument" "" { target *-*-* } .-1 } +template struct A3; // { dg-error "typedef declaration|no type|expected" } +template struct A4; // { dg-error "10:typedef declaration" } +// { dg-error "default argument" "" { target *-*-* } .-1 } diff --git a/gcc/testsuite/g++.dg/tls/diag-2.C b/gcc/testsuite/g++.dg/tls/diag-2.C index f76763f3431..c247a9787a2 100644 --- a/gcc/testsuite/g++.dg/tls/diag-2.C +++ b/gcc/testsuite/g++.dg/tls/diag-2.C @@ -8,19 +8,19 @@ typedef __thread int g4; /* { dg-error "multiple storage classes" } */ void foo() { - __thread int l1; /* { dg-error "implicitly auto and declared '__thread'" } */ + __thread int l1; /* { dg-error "3:function-scope .l1. implicitly auto and declared '__thread'" } */ auto __thread int l2; /* { dg-error "multiple storage classes|data types" } */ __thread extern int l3; /* { dg-error "'__thread' before 'extern'" } */ register __thread int l4; /* { dg-error "multiple storage classes" } */ } /* { dg-error "ISO C\\+\\+17 does not allow 'register' storage class specifier" "" { target c++17 } .-1 } */ -__thread void f1 (); /* { dg-error "invalid for function" } */ -extern __thread void f2 (); /* { dg-error "invalid for function" } */ -static __thread void f3 (); /* { dg-error "invalid for function" } */ -__thread void f4 () { } /* { dg-error "invalid for function" } */ +__thread void f1 (); /* { dg-error "1:storage class .__thread. invalid for function" } */ +extern __thread void f2 (); /* { dg-error "8:storage class .__thread. invalid for function" } */ +static __thread void f3 (); /* { dg-error "8:storage class .__thread. invalid for function" } */ +__thread void f4 () { } /* { dg-error "1:storage class .__thread. invalid for function" } */ -void bar(__thread int p1); /* { dg-error "(invalid in parameter)|(specified for parameter)" } */ +void bar(__thread int p1); /* { dg-error "10:storage class specified for parameter" } */ struct A { - __thread int i; /* { dg-error "storage class specified" } */ + __thread int i; /* { dg-error "3:storage class specified" } */ }; diff --git a/gcc/testsuite/g++.dg/tls/locations1.C b/gcc/testsuite/g++.dg/tls/locations1.C new file mode 100644 index 00000000000..8ca3c6eb1f6 --- /dev/null +++ b/gcc/testsuite/g++.dg/tls/locations1.C @@ -0,0 +1,4 @@ +/* { dg-require-effective-target tls } */ + +template <__thread int T> struct F {}; // { dg-error "11:storage class specified" } +template struct G {}; // { dg-error "11:storage class specified" } diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/crash11.C b/gcc/testsuite/g++.old-deja/g++.brendan/crash11.C index 1683de2b47f..246f5a03aa5 100644 --- a/gcc/testsuite/g++.old-deja/g++.brendan/crash11.C +++ b/gcc/testsuite/g++.old-deja/g++.brendan/crash11.C @@ -9,13 +9,14 @@ class A { int h; A() { i=10; j=20; } virtual void f1() { printf("i=%d j=%d\n",i,j); } - friend virtual void f2() { printf("i=%d j=%d\n",i,j); }// { dg-error "" } virtual.* + friend virtual void f2() { printf("i=%d j=%d\n",i,j); } // { dg-error "2:virtual functions cannot be friends" } }; class B : public A { public: virtual void f1() { printf("i=%d j=%d\n",i,j); }// { dg-error "" } member.*// ERROR - member.* - friend virtual void f2() { printf("i=%d j=%d\n",i,j); }// { dg-error "" } virtual.*// ERROR - member.*// ERROR - member.* + friend virtual void f2() { printf("i=%d j=%d\n",i,j); } // { dg-error "2:virtual functions cannot be friends" } +// { dg-error "private" "" { target *-*-* } .-1 } }; int -- 2.30.2