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