On Mon, 2019-02-18 at 14:07 -1000, Jason Merrill wrote: > On 2/18/19 12:50 PM, Jakub Jelinek wrote: > > Hi! > > > > On the following testcase we ICE because name is BIT_NOT_EXPR and > > suggest_alternative_in_scoped_enum assumes it is called on > > IDENTIFIER_NODE > > only. > > > > Fixed thusly, bootstrapped/regtested on x86_64-linux and i686- > > linux, ok for > > trunk? > > OK. > > > There is another issue, starting with 7.x we don't use sensible > > location in > > the diagnostics, 6.x emitted > > pr89390.C: In function ‘void foo()’: > > pr89390.C:9:3: error: ‘~A’ is not a member of ‘A’ > > A::~A (); // { dg-error "'~A' is not a member of 'A'" } > > ^ > > but 7.x and later emits: > > In function ‘void foo()’: > > cc1plus: error: ‘~A’ is not a member of ‘A’ > > > > This patch doesn't deal with that, but would be nice to provide > > location, > > dunno if it is enough to just use location of ~, or if we need to > > spend > > memory and build ~A as combined range with caret on ~.
It should only cost memory if strlen(A) is > 30, since otherwise the result will have caret==start and strlen() <= 31 and so hit the optimized range representation. > > I think having a range for a destructor id-expression would be > appropriate. > > Jason How about something like this? (on top of Jakub's patch) pr89390.C: In function 'void foo()': pr89390.C:9:6: error: '~A' is not a member of 'A' 9 | A::~A (); // { dg-error "6: '~A' is not a member of 'A'" } | ^~ pr89390.C: In function 'void test_2()': pr89390.C:17:10: error: '~ns::P' is not a member of 'ns::P' 17 | ns::P::~P (); // { dg-error "10: '~ns::P' is not a member of 'ns::P'" } | ^~ (Presumably gcc 10 material at this point; not yet bootstrapped). gcc/cp/ChangeLog: PR c++/89390 * parser.c (cp_parser_unqualified_id): Capture locations for destructors. gcc/testsuite/ChangeLog: PR c++/89390 * g++.dg/diagnostic/pr89390.C: Update expected location of error. Add testcase within namespace. --- gcc/cp/parser.c | 9 ++++++++- gcc/testsuite/g++.dg/diagnostic/pr89390.C | 10 +++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index ffecce4..e6fdb34 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -5976,6 +5976,7 @@ cp_parser_unqualified_id (cp_parser* parser, tree object_scope; tree scope; bool done; + location_t tilde_loc = token->location; /* Consume the `~' token. */ cp_lexer_consume_token (parser->lexer); @@ -6049,8 +6050,14 @@ cp_parser_unqualified_id (cp_parser* parser, || (CLASS_TYPE_P (scope) && constructor_name_p (token->u.value, scope)))) { + /* Create a location with caret == start at the tilde, + finishing at the end of the peeked token, e.g: + ~class_name + ^~~~~~~~~~~. */ + location_t loc + = make_location (tilde_loc, tilde_loc, token->location); cp_lexer_consume_token (parser->lexer); - return build_nt (BIT_NOT_EXPR, scope); + return cp_expr (build_nt (BIT_NOT_EXPR, scope), loc); } /* ~auto means the destructor of whatever the object is. */ diff --git a/gcc/testsuite/g++.dg/diagnostic/pr89390.C b/gcc/testsuite/g++.dg/diagnostic/pr89390.C index df35fcc..91a6422 100644 --- a/gcc/testsuite/g++.dg/diagnostic/pr89390.C +++ b/gcc/testsuite/g++.dg/diagnostic/pr89390.C @@ -6,5 +6,13 @@ enum class A { B, C }; void foo () { - A::~A (); // { dg-error "'~A' is not a member of 'A'" "" { target *-*-* } 0 } + A::~A (); // { dg-error "6: '~A' is not a member of 'A'" } +} + +namespace ns { enum class P { Q, R }; } + +void +test_2 () +{ + ns::P::~P (); // { dg-error "10: '~ns::P' is not a member of 'ns::P'" } } -- 1.8.5.3