* [RFC C++ PATCH] Improve locations of id-expressions and operator "" (PR c++/87386)
@ 2018-11-20 20:57 Jakub Jelinek
2018-11-20 21:32 ` David Malcolm
0 siblings, 1 reply; 12+ messages in thread
From: Jakub Jelinek @ 2018-11-20 20:57 UTC (permalink / raw)
To: David Malcolm, Jason Merrill; +Cc: gcc-patches
Hi!
This PR is complaining about range covering the first token from
an id-expression:
pr87386.C:4:15: error: static assertion failed: foo
4 | static_assert(foo::test<int>::value, "foo");
| ^~~
The following patch adjust that to:
pr87386.C:4:31: error: static assertion failed: foo
4 | static_assert(foo::test<int>::value, "foo");
| ~~~~~~~~~~~~~~~~^~~~~
instead, though as the changes to the testsuite show, not really sure
if it is a good idea in all cases, because then we sometimes print:
... bar is not in foo namespace, did you mean 'baz'
foo::bar
~~~~~^~~
baz
where the baz is misaligned. Would it be better to just print
pr87386.C:4:31: error: static assertion failed: foo
4 | static_assert(foo::test<int>::value, "foo");
| ^~~~~
instead? That would mean dropping the cp_parser_id_expression change
and readjusting or dropping some testsuite changes.
2018-11-20 Jakub Jelinek <jakub@redhat.com>
PR c++/87386
* parser.c (cp_parser_primary_expression): Use
id_expression.get_location () instead of id_expr_token->location.
(cp_parser_id_expression): For nested_name_specifier_p, make a
range covering whole id-expression.
(cp_parser_operator): For operator "" make a range from "" to
the end of the suffix with caret at the start of the id.
gcc/testsuite/
* g++.dg/spellcheck-pr79298.C: Adjust expected diagnostics.
* g++.dg/lookup/suggestions2.C: Likewise.
* g++.dg/spellcheck-single-vs-multiple.C: Likewise.
* g++.dg/parse/error17.C: Likewise.
* g++.dg/spellcheck-pr77829.C: Likewise.
* g++.dg/spellcheck-pr78656.C: Likewise.
* g++.dg/cpp0x/pr51420.C: Likewise.
* g++.dg/cpp0x/udlit-declare-neg.C: Likewise.
* g++.dg/cpp0x/udlit-member-neg.C: Likewise.
libstdc++-v3/
* testsuite/20_util/scoped_allocator/69293_neg.cc: Adjust expected
line.
* testsuite/20_util/uses_allocator/cons_neg.cc: Likewise.
* testsuite/experimental/propagate_const/requirements2.cc: Likewise.
* testsuite/experimental/propagate_const/requirements3.cc: Likewise.
* testsuite/experimental/propagate_const/requirements4.cc: Likewise.
* testsuite/experimental/propagate_const/requirements5.cc: Likewise.
--- gcc/cp/parser.c.jj 2018-11-20 08:41:28.686923718 +0100
+++ gcc/cp/parser.c 2018-11-20 19:05:22.848941522 +0100
@@ -5602,7 +5602,7 @@ cp_parser_primary_expression (cp_parser
/*is_namespace=*/false,
/*check_dependency=*/true,
&ambiguous_decls,
- id_expr_token->location);
+ id_expression.get_location ());
/* If the lookup was ambiguous, an error will already have
been issued. */
if (ambiguous_decls)
@@ -5673,7 +5673,7 @@ cp_parser_primary_expression (cp_parser
if (parser->local_variables_forbidden_p
&& local_variable_p (decl))
{
- error_at (id_expr_token->location,
+ error_at (id_expression.get_location (),
"local variable %qD may not appear in this context",
decl.get_value ());
return error_mark_node;
@@ -5692,7 +5692,7 @@ cp_parser_primary_expression (cp_parser
id_expression.get_location ()));
if (error_msg)
cp_parser_error (parser, error_msg);
- decl.set_location (id_expr_token->location);
+ decl.set_location (id_expression.get_location ());
return decl;
}
@@ -5758,6 +5758,7 @@ cp_parser_id_expression (cp_parser *pars
{
bool global_scope_p;
bool nested_name_specifier_p;
+ location_t start_loc = cp_lexer_peek_token (parser->lexer)->location;
/* Assume the `template' keyword was not used. */
if (template_p)
@@ -5809,6 +5810,7 @@ cp_parser_id_expression (cp_parser *pars
parser->object_scope = saved_object_scope;
parser->qualifying_scope = saved_qualifying_scope;
+ unqualified_id.set_range (start_loc, unqualified_id.get_finish ());
return unqualified_id;
}
/* Otherwise, if we are in global scope, then we are looking at one
@@ -14931,7 +14933,7 @@ cp_literal_operator_id (const char* name
static cp_expr
cp_parser_operator (cp_parser* parser)
{
- tree id = NULL_TREE;
+ cp_expr id = NULL_TREE;
cp_token *token;
bool utf8 = false;
@@ -15219,8 +15221,9 @@ cp_parser_operator (cp_parser* parser)
if (id != error_mark_node)
{
const char *name = IDENTIFIER_POINTER (id);
- id = cp_literal_operator_id (name);
+ *id = cp_literal_operator_id (name);
}
+ id.set_range (start_loc, id.get_finish ());
return id;
}
@@ -15244,7 +15247,8 @@ cp_parser_operator (cp_parser* parser)
id = error_mark_node;
}
- return cp_expr (id, start_loc);
+ id.set_location (start_loc);
+ return id;
}
/* Parse a template-declaration.
--- gcc/testsuite/g++.dg/spellcheck-pr79298.C.jj 2018-10-31 10:31:13.281572644 +0100
+++ gcc/testsuite/g++.dg/spellcheck-pr79298.C 2018-11-20 19:14:19.208219955 +0100
@@ -11,7 +11,7 @@ int foo ()
return M::y; // { dg-error ".y. is not a member of .M." }
/* { dg-begin-multiline-output "" }
return M::y;
- ^
+ ~~~^
{ dg-end-multiline-output "" } */
}
@@ -20,7 +20,7 @@ int bar ()
return O::colour; // { dg-error ".colour. is not a member of .O.; did you mean 'color'\\?" }
/* { dg-begin-multiline-output "" }
return O::colour;
- ^~~~~~
- color
+ ~~~^~~~~~
+ color
{ dg-end-multiline-output "" } */
}
--- gcc/testsuite/g++.dg/lookup/suggestions2.C.jj 2018-10-31 10:31:06.928677642 +0100
+++ gcc/testsuite/g++.dg/lookup/suggestions2.C 2018-11-20 19:12:05.281395810 +0100
@@ -33,8 +33,8 @@ int test_1_long (void) {
return outer_ns::var_in_inner_ns_a; // { dg-error "did you mean 'var_in_outer_ns'" }
/* { dg-begin-multiline-output "" }
return outer_ns::var_in_inner_ns_a;
- ^~~~~~~~~~~~~~~~~
- var_in_outer_ns
+ ~~~~~~~~~~^~~~~~~~~~~~~~~~~
+ var_in_outer_ns
{ dg-end-multiline-output "" } */
}
@@ -45,7 +45,7 @@ int test_1_short (void) {
return outer_ns::a; // { dg-error "did you mean 'outer_ns::inner_ns_a::a'" }
/* { dg-begin-multiline-output "" }
return outer_ns::a;
- ^
+ ~~~~~~~~~~^
{ dg-end-multiline-output "" } */
// { dg-message "declared here" "" { target *-*-*} decl_of_a }
/* { dg-begin-multiline-output "" }
@@ -61,8 +61,8 @@ int test_2_long (void) {
return outer_ns::inner_ns_a::var_in_outer_ns; // { dg-error "did you mean 'var_in_inner_ns_a'" }
/* { dg-begin-multiline-output "" }
return outer_ns::inner_ns_a::var_in_outer_ns;
- ^~~~~~~~~~~~~~~
- var_in_inner_ns_a
+ ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~
+ var_in_inner_ns_a
{ dg-end-multiline-output "" } */
}
@@ -73,7 +73,7 @@ int test_2_short (void) {
return outer_ns::inner_ns_a::o; // { dg-error "did you mean 'outer_ns::o'" }
/* { dg-begin-multiline-output "" }
return outer_ns::inner_ns_a::o;
- ^
+ ~~~~~~~~~~~~~~~~~~~~~~^
{ dg-end-multiline-output "" } */
// { dg-message "declared here" "" { target *-*-*} decl_of_o }
/* { dg-begin-multiline-output "" }
@@ -89,8 +89,8 @@ int test_3_long (void) {
return outer_ns::inner_ns_a::var_in_inner_ns_b; // { dg-error "did you mean 'var_in_inner_ns_a'" }
/* { dg-begin-multiline-output "" }
return outer_ns::inner_ns_a::var_in_inner_ns_b;
- ^~~~~~~~~~~~~~~~~
- var_in_inner_ns_a
+ ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~
+ var_in_inner_ns_a
{ dg-end-multiline-output "" } */
}
@@ -101,7 +101,7 @@ int test_3_short (void) {
return outer_ns::inner_ns_a::b; // { dg-error "did you mean 'outer_ns::inner_ns_b::b'" }
/* { dg-begin-multiline-output "" }
return outer_ns::inner_ns_a::b;
- ^
+ ~~~~~~~~~~~~~~~~~~~~~~^
{ dg-end-multiline-output "" } */
// { dg-message "declared here" "" { target *-*-*} decl_of_b }
/* { dg-begin-multiline-output "" }
--- gcc/testsuite/g++.dg/spellcheck-single-vs-multiple.C.jj 2018-10-31 10:31:07.765663807 +0100
+++ gcc/testsuite/g++.dg/spellcheck-single-vs-multiple.C 2018-11-20 19:14:35.698952024 +0100
@@ -73,7 +73,7 @@ void test_3 ()
ns3::goo_3 (); // { dg-error "'goo_3' is not a member of 'ns3'; did you mean 'foo_3'\\?" }
/* { dg-begin-multiline-output "" }
ns3::goo_3 ();
- ^~~~~
- foo_3
+ ~~~~~^~~~~
+ foo_3
{ dg-end-multiline-output "" } */
}
--- gcc/testsuite/g++.dg/parse/error17.C.jj 2009-11-27 12:25:22.000000000 +0100
+++ gcc/testsuite/g++.dg/parse/error17.C 2018-11-20 19:12:35.212909527 +0100
@@ -6,4 +6,4 @@ template <typename T> struct B {
};
struct D : B<int>, B<char> {};
-int i2 = D::Bar(2); // { dg-error "10:reference to 'Bar' is ambiguous" }
+int i2 = D::Bar(2); // { dg-error "13:reference to 'Bar' is ambiguous" }
--- gcc/testsuite/g++.dg/spellcheck-pr77829.C.jj 2018-10-31 10:31:10.213623350 +0100
+++ gcc/testsuite/g++.dg/spellcheck-pr77829.C 2018-11-20 19:13:30.700008045 +0100
@@ -21,8 +21,8 @@ void fn_1_explicit ()
detail::some_type i; // { dg-error ".some_type. is not a member of .detail.; did you mean 'some_typedef'\\?" }
/* { dg-begin-multiline-output "" }
detail::some_type i;
- ^~~~~~~~~
- some_typedef
+ ~~~~~~~~^~~~~~~~~
+ some_typedef
{ dg-end-multiline-output "" } */
}
@@ -47,8 +47,8 @@ void fn_2_explicit (int i) {
detail::foo(i); // { dg-error ".foo. is not a member of .detail.; did you mean '_foo'\\?" }
/* { dg-begin-multiline-output "" }
detail::foo(i);
- ^~~
- _foo
+ ~~~~~~~~^~~
+ _foo
{ dg-end-multiline-output "" } */
}
@@ -72,8 +72,8 @@ void fn_3_explicit (int i) {
detail::something_els(i); // { dg-error ".something_els. is not a member of .detail.; did you mean 'something_else'\\?" }
/* { dg-begin-multiline-output "" }
detail::something_els(i);
- ^~~~~~~~~~~~~
- something_else
+ ~~~~~~~~^~~~~~~~~~~~~
+ something_else
{ dg-end-multiline-output "" } */
}
@@ -97,7 +97,7 @@ void fn_4_explicit (int i) {
detail::not_recognized(i); // { dg-error ".not_recognized. is not a member of .detail." }
/* { dg-begin-multiline-output "" }
detail::not_recognized(i);
- ^~~~~~~~~~~~~~
+ ~~~~~~~~^~~~~~~~~~~~~~
{ dg-end-multiline-output "" } */
}
--- gcc/testsuite/g++.dg/spellcheck-pr78656.C.jj 2018-10-31 10:31:10.213623350 +0100
+++ gcc/testsuite/g++.dg/spellcheck-pr78656.C 2018-11-20 19:14:04.161464402 +0100
@@ -7,8 +7,8 @@ void* allocate(std::size_t n)
return std::allocate<char>().allocate(n); // { dg-error ".allocate. is not a member of .std.; did you mean 'allocator'\\?" }
/* { dg-begin-multiline-output "" }
return std::allocate<char>().allocate(n);
- ^~~~~~~~
- allocator
+ ~~~~~^~~~~~~~
+ allocator
{ dg-end-multiline-output "" } */
// Various errors follow that we don't care about; suppress them:
@@ -20,8 +20,8 @@ void* test_2(std::size_t n)
return std::alocator<char>().allocate(n); // { dg-error ".alocator. is not a member of .std.; did you mean 'allocator'\\?" }
/* { dg-begin-multiline-output "" }
return std::alocator<char>().allocate(n);
- ^~~~~~~~
- allocator
+ ~~~~~^~~~~~~~
+ allocator
{ dg-end-multiline-output "" } */
// Various errors follow that we don't care about; suppress them:
--- gcc/testsuite/g++.dg/cpp0x/pr51420.C.jj 2016-05-30 23:22:54.772099149 +0200
+++ gcc/testsuite/g++.dg/cpp0x/pr51420.C 2018-11-20 19:06:05.236252077 +0100
@@ -3,6 +3,6 @@
void
foo()
{
- float x = operator"" _F(); // { dg-error "13:'operator\"\"_F' was not declared in this scope" }
+ float x = operator"" _F(); // { dg-error "24:'operator\"\"_F' was not declared in this scope" }
float y = 0_F; // { dg-error "unable to find numeric literal operator" }
}
--- gcc/testsuite/g++.dg/cpp0x/udlit-declare-neg.C.jj 2016-05-30 23:22:54.772099149 +0200
+++ gcc/testsuite/g++.dg/cpp0x/udlit-declare-neg.C 2018-11-20 19:07:08.835217615 +0100
@@ -2,14 +2,14 @@
// Check that undeclared literal operator calls and literals give appropriate errors.
-int i = operator"" _Bar('x'); // { dg-error "9:'operator\"\"_Bar' was not declared in this scope" }
+int i = operator"" _Bar('x'); // { dg-error "20:'operator\"\"_Bar' was not declared in this scope" }
int j = 'x'_Bar; // { dg-error "unable to find character literal operator|with|argument" }
-int ii = operator"" _BarCharStr("Howdy, Pardner!"); // { dg-error "10:'operator\"\"_BarCharStr' was not declared in this scope" }
+int ii = operator"" _BarCharStr("Howdy, Pardner!"); // { dg-error "21:'operator\"\"_BarCharStr' was not declared in this scope" }
int jj = "Howdy, Pardner!"_BarCharStr; // { dg-error "unable to find string literal operator|Possible missing length argument" }
-unsigned long long iULL = operator"" _BarULL(666ULL); // { dg-error "27:'operator\"\"_BarULL' was not declared in this scope" }
+unsigned long long iULL = operator"" _BarULL(666ULL); // { dg-error "38:'operator\"\"_BarULL' was not declared in this scope" }
unsigned long long jULL = 666_BarULL; // { dg-error "unable to find numeric literal operator" }
-long double iLD = operator"" _BarLD(666.0L); // { dg-error "19:'operator\"\"_BarLD' was not declared in this scope" }
+long double iLD = operator"" _BarLD(666.0L); // { dg-error "30:'operator\"\"_BarLD' was not declared in this scope" }
long double jLD = 666.0_BarLD; // { dg-error "unable to find numeric literal operator" }
--- gcc/testsuite/g++.dg/cpp0x/udlit-member-neg.C.jj 2018-06-14 21:01:40.000000000 +0200
+++ gcc/testsuite/g++.dg/cpp0x/udlit-member-neg.C 2018-11-20 19:22:56.470816139 +0100
@@ -7,7 +7,7 @@ public:
int operator"" _Bar(char32_t); // { dg-error "7:.int Foo::operator\"\"_Bar\\(char32_t\\). must be a non-member function" }
};
-int i = operator"" _Bar(U'x'); // { dg-error "9:'operator\"\"_Bar' was not declared in this scope" }
+int i = operator"" _Bar(U'x'); // { dg-error "20:'operator\"\"_Bar' was not declared in this scope" }
int j = U'x'_Bar; // { dg-error "unable to find character literal operator" }
int
--- libstdc++-v3/testsuite/20_util/scoped_allocator/69293_neg.cc.jj 2018-07-27 22:20:29.000000000 +0200
+++ libstdc++-v3/testsuite/20_util/scoped_allocator/69293_neg.cc 2018-11-20 21:20:25.123636254 +0100
@@ -46,5 +46,5 @@ test01()
scoped_alloc sa;
auto p = sa.allocate(1);
sa.construct(p); // this is required to be ill-formed
- // { dg-error "static assertion failed" "" { target *-*-* } 94 }
+ // { dg-error "static assertion failed" "" { target *-*-* } 96 }
}
--- libstdc++-v3/testsuite/20_util/uses_allocator/cons_neg.cc.jj 2018-07-27 22:20:29.000000000 +0200
+++ libstdc++-v3/testsuite/20_util/uses_allocator/cons_neg.cc 2018-11-20 21:21:12.868864599 +0100
@@ -43,4 +43,4 @@ void test01()
tuple<Type> t(allocator_arg, a, 1);
}
-// { dg-error "static assertion failed" "" { target *-*-* } 94 }
+// { dg-error "static assertion failed" "" { target *-*-* } 96 }
--- libstdc++-v3/testsuite/experimental/propagate_const/requirements3.cc.jj 2018-01-03 18:53:16.000000000 +0100
+++ libstdc++-v3/testsuite/experimental/propagate_const/requirements3.cc 2018-11-20 21:22:06.049005105 +0100
@@ -21,6 +21,6 @@
using std::experimental::propagate_const;
-// { dg-error "requires a class or a pointer to an object type" "" { target *-*-* } 105 }
+// { dg-error "requires a class or a pointer to an object type" "" { target *-*-* } 107 }
propagate_const<void (*)()> test1;
--- libstdc++-v3/testsuite/experimental/propagate_const/requirements4.cc.jj 2018-01-03 18:53:16.000000000 +0100
+++ libstdc++-v3/testsuite/experimental/propagate_const/requirements4.cc 2018-11-20 21:22:29.698622883 +0100
@@ -21,7 +21,7 @@
using std::experimental::propagate_const;
-// { dg-error "requires a class or a pointer to an object type" "" { target *-*-* } 105 }
+// { dg-error "requires a class or a pointer to an object type" "" { target *-*-* } 107 }
// { dg-error "invalid type" "" { target *-*-* } 66 }
// { dg-error "uninitialized reference member" "" { target *-*-* } 112 }
--- libstdc++-v3/testsuite/experimental/propagate_const/requirements5.cc.jj 2018-01-03 18:53:16.000000000 +0100
+++ libstdc++-v3/testsuite/experimental/propagate_const/requirements5.cc 2018-11-20 21:22:45.311370550 +0100
@@ -21,6 +21,6 @@
using std::experimental::propagate_const;
-// { dg-error "requires a class or a pointer to an object type" "" { target *-*-* } 105 }
+// { dg-error "requires a class or a pointer to an object type" "" { target *-*-* } 107 }
propagate_const<int[1]> test1;
--- libstdc++-v3/testsuite/experimental/propagate_const/requirements2.cc.jj 2018-01-03 18:53:16.000000000 +0100
+++ libstdc++-v3/testsuite/experimental/propagate_const/requirements2.cc 2018-11-20 21:21:43.959362116 +0100
@@ -21,7 +21,7 @@
using std::experimental::propagate_const;
-// { dg-error "requires a class or a pointer to an object type" "" { target *-*-* } 105 }
+// { dg-error "requires a class or a pointer to an object type" "" { target *-*-* } 107 }
// { dg-error "not a pointer-to-object type" "" { target *-*-* } 66 }
// { dg-error "forming pointer to reference type" "" { target *-*-* } 187 }
// { dg-error "forming pointer to reference type" "" { target *-*-* } 213 }
Jakub
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFC C++ PATCH] Improve locations of id-expressions and operator "" (PR c++/87386)
2018-11-20 20:57 [RFC C++ PATCH] Improve locations of id-expressions and operator "" (PR c++/87386) Jakub Jelinek
@ 2018-11-20 21:32 ` David Malcolm
2018-11-21 15:55 ` [C++ PATCH] Improve locations of id-expressions and operator "" (PR c++/87386, take 2) Jakub Jelinek
0 siblings, 1 reply; 12+ messages in thread
From: David Malcolm @ 2018-11-20 21:32 UTC (permalink / raw)
To: Jakub Jelinek, Jason Merrill; +Cc: gcc-patches
On Tue, 2018-11-20 at 21:57 +0100, Jakub Jelinek wrote:
> Hi!
>
> This PR is complaining about range covering the first token from
> an id-expression:
> pr87386.C:4:15: error: static assertion failed: foo
> 4 | static_assert(foo::test<int>::value, "foo");
> | ^~~
> The following patch adjust that to:
> pr87386.C:4:31: error: static assertion failed: foo
> 4 | static_assert(foo::test<int>::value, "foo");
> | ~~~~~~~~~~~~~~~~^~~~~
> instead, though as the changes to the testsuite show, not really sure
> if it is a good idea in all cases, because then we sometimes print:
> ... bar is not in foo namespace, did you mean 'baz'
> foo::bar
> ~~~~~^~~
> baz
> where the baz is misaligned.
Is the compiler suggesting the use of
(a) "foo::baz" or
(b) "::baz"?
Given the underlining, the fix-it hint would be suggesting the
replacement of "foo::bar" with "baz", which would be wrong if we mean
(a) above.
(c.f. "Fix-it hints should work" in https://gcc.gnu.org/onlinedocs/gcci
nt/Guidelines-for-Diagnostics.html )
FWIW in r265610 I ran into issues like this, which I resolved by
holding off on some fix-it hints for the case where we don't have a
location covering the whole of a qualified name.
> Would it be better to just print
> pr87386.C:4:31: error: static assertion failed: foo
> 4 | static_assert(foo::test<int>::value, "foo");
> | ^~~~~
> instead? That would mean dropping the cp_parser_id_expression change
> and readjusting or dropping some testsuite changes.
That might be better... let me look at the affected test cases.
[...snip...]
> /* Parse a template-declaration.
> --- gcc/testsuite/g++.dg/spellcheck-pr79298.C.jj 2018-10-31
> 10:31:13.281572644 +0100
> +++ gcc/testsuite/g++.dg/spellcheck-pr79298.C 2018-11-20
> 19:14:19.208219955 +0100
> @@ -11,7 +11,7 @@ int foo ()
> return M::y; // { dg-error ".y. is not a member of .M." }
> /* { dg-begin-multiline-output "" }
> return M::y;
> - ^
> + ~~~^
> { dg-end-multiline-output "" } */
> }
> @@ -20,7 +20,7 @@ int bar ()
> return O::colour; // { dg-error ".colour. is not a member of .O.;
> did you mean 'color'\\?" }
> /* { dg-begin-multiline-output "" }
> return O::colour;
> - ^~~~~~
> - color
> + ~~~^~~~~~
> + color
> { dg-end-multiline-output "" } */
> }
This makes the fix-it hint wrong: after the fix-it is applied, it will
become
return color;
(which won't compile), rather than
return O::color;
which will.
(I wish we had a good automated way of verifying that fix-it hints fix
things)
> --- gcc/testsuite/g++.dg/lookup/suggestions2.C.jj 2018-10-31
> 10:31:06.928677642 +0100
> +++ gcc/testsuite/g++.dg/lookup/suggestions2.C 2018-11-20
> 19:12:05.281395810 +0100
> @@ -33,8 +33,8 @@ int test_1_long (void) {
> return outer_ns::var_in_inner_ns_a; // { dg-error "did you mean
> 'var_in_outer_ns'" }
> /* { dg-begin-multiline-output "" }
> return outer_ns::var_in_inner_ns_a;
> - ^~~~~~~~~~~~~~~~~
> - var_in_outer_ns
> + ~~~~~~~~~~^~~~~~~~~~~~~~~~~
> + var_in_outer_ns
> { dg-end-multiline-output "" } */
> }
Again, this makes the fix-it hint wrong: after the fix-it is applied,
it will become
return var_in_outer_ns;
(which won't compile) rather than:
return outer_ns::var_in_outer_ns;
[...snip; I think there are more examples in this test file...]
> --- gcc/testsuite/g++.dg/spellcheck-single-vs-multiple.C.jj 20
> 18-10-31 10:31:07.765663807 +0100
> +++ gcc/testsuite/g++.dg/spellcheck-single-vs-multiple.C 2018-
> 11-20 19:14:35.698952024 +0100
> @@ -73,7 +73,7 @@ void test_3 ()
> ns3::goo_3 (); // { dg-error "'goo_3' is not a member of 'ns3';
> did you mean 'foo_3'\\?" }
> /* { dg-begin-multiline-output "" }
> ns3::goo_3 ();
> - ^~~~~
> - foo_3
> + ~~~~~^~~~~
> + foo_3
> { dg-end-multiline-output "" } */
> }
Again, the fix-it hint becomes wrong, it will become:
foo_3 ();
rather than:
ns3::foo_3 ();
[...snip...]
> --- gcc/testsuite/g++.dg/spellcheck-pr77829.C.jj 2018-10-31
> 10:31:10.213623350 +0100
> +++ gcc/testsuite/g++.dg/spellcheck-pr77829.C 2018-11-20
> 19:13:30.700008045 +0100
> @@ -21,8 +21,8 @@ void fn_1_explicit ()
> detail::some_type i; // { dg-error ".some_type. is not a member of
> .detail.; did you mean 'some_typedef'\\?" }
> /* { dg-begin-multiline-output "" }
> detail::some_type i;
> - ^~~~~~~~~
> - some_typedef
> + ~~~~~~~~^~~~~~~~~
> + some_typedef
> { dg-end-multiline-output "" } */
> }
Similar problems here.
[...snip...]
So it looks like the less invasive fix might be better (not that I've
looked at it in detail, though).
Hope this is constructive
Dave
^ permalink raw reply [flat|nested] 12+ messages in thread
* [C++ PATCH] Improve locations of id-expressions and operator "" (PR c++/87386, take 2)
2018-11-20 21:32 ` David Malcolm
@ 2018-11-21 15:55 ` Jakub Jelinek
2018-11-21 18:29 ` Jason Merrill
0 siblings, 1 reply; 12+ messages in thread
From: Jakub Jelinek @ 2018-11-21 15:55 UTC (permalink / raw)
To: David Malcolm, Jason Merrill; +Cc: gcc-patches
Hi!
On Tue, Nov 20, 2018 at 04:32:26PM -0500, David Malcolm wrote:
> This makes the fix-it hint wrong: after the fix-it is applied, it will
> become
> return color;
> (which won't compile), rather than
> return O::color;
> which will.
Here is an updated version of the patch, which still uses the whole
range of the id-expression when it is parsed as primary expression, but does
so not in cp_parser_id_expression, but in cp_parser_primary_expression after
all the diagnostics. Thus all the spell-checking etc. tests behave as
previously, they underline only the part after the last ::, and just
what uses the expression later on uses whole range.
The remaining needed tweeks in the testcases are minor and look correct to
me, e.g. for D::Bar the column is not at D but at B,
similarly for operator"" _F the column is under _ rather than first o.
The libstdc++ changes are because there are several large expressions like:
something<one, two,
three, four,
five, six>::value
and we used to diagnose on the something line (column of s)
but now we warn on value line (column of v).
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
2018-11-21 Jakub Jelinek <jakub@redhat.com>
PR c++/87386
* parser.c (cp_parser_primary_expression): Use
id_expression.get_location () instead of id_expr_token->location.
Adjust the range from id_expr_token->location to
id_expressio.get_finish ().
(cp_parser_operator): For operator "" make a range from "" to
the end of the suffix with caret at the start of the id.
gcc/testsuite/
* g++.dg/diagnostic/pr87386.C: New test.
* g++.dg/parse/error17.C: Adjust expected diagnostics.
* g++.dg/cpp0x/pr51420.C: Likewise.
* g++.dg/cpp0x/udlit-declare-neg.C: Likewise.
* g++.dg/cpp0x/udlit-member-neg.C: Likewise.
libstdc++-v3/
* testsuite/20_util/scoped_allocator/69293_neg.cc: Adjust expected
line.
* testsuite/20_util/uses_allocator/cons_neg.cc: Likewise.
* testsuite/20_util/uses_allocator/69293_neg.cc: Likewise.
* testsuite/experimental/propagate_const/requirements2.cc: Likewise.
* testsuite/experimental/propagate_const/requirements3.cc: Likewise.
* testsuite/experimental/propagate_const/requirements4.cc: Likewise.
* testsuite/experimental/propagate_const/requirements5.cc: Likewise.
--- gcc/cp/parser.c.jj 2018-11-21 11:35:43.698053550 +0100
+++ gcc/cp/parser.c 2018-11-21 12:23:20.701047164 +0100
@@ -5604,7 +5604,7 @@ cp_parser_primary_expression (cp_parser
/*is_namespace=*/false,
/*check_dependency=*/true,
&ambiguous_decls,
- id_expr_token->location);
+ id_expression.get_location ());
/* If the lookup was ambiguous, an error will already have
been issued. */
if (ambiguous_decls)
@@ -5675,7 +5675,7 @@ cp_parser_primary_expression (cp_parser
if (parser->local_variables_forbidden_p
&& local_variable_p (decl))
{
- error_at (id_expr_token->location,
+ error_at (id_expression.get_location (),
"local variable %qD may not appear in this context",
decl.get_value ());
return error_mark_node;
@@ -5694,7 +5694,8 @@ cp_parser_primary_expression (cp_parser
id_expression.get_location ()));
if (error_msg)
cp_parser_error (parser, error_msg);
- decl.set_location (id_expr_token->location);
+ decl.set_location (id_expression.get_location ());
+ decl.set_range (id_expr_token->location, id_expression.get_finish ());
return decl;
}
@@ -15051,7 +15052,7 @@ cp_literal_operator_id (const char* name
static cp_expr
cp_parser_operator (cp_parser* parser)
{
- tree id = NULL_TREE;
+ cp_expr id = NULL_TREE;
cp_token *token;
bool utf8 = false;
@@ -15339,8 +15340,9 @@ cp_parser_operator (cp_parser* parser)
if (id != error_mark_node)
{
const char *name = IDENTIFIER_POINTER (id);
- id = cp_literal_operator_id (name);
+ *id = cp_literal_operator_id (name);
}
+ id.set_range (start_loc, id.get_finish ());
return id;
}
@@ -15364,7 +15366,8 @@ cp_parser_operator (cp_parser* parser)
id = error_mark_node;
}
- return cp_expr (id, start_loc);
+ id.set_location (start_loc);
+ return id;
}
/* Parse a template-declaration.
--- gcc/testsuite/g++.dg/diagnostic/pr87386.C.jj 2018-11-21 14:40:58.377769686 +0100
+++ gcc/testsuite/g++.dg/diagnostic/pr87386.C 2018-11-21 14:40:19.064410070 +0100
@@ -0,0 +1,18 @@
+// PR c++/87386
+// { dg-do compile { target c++11 } }
+// { dg-options "-fdiagnostics-show-caret" }
+
+namespace foo {
+ template<typename> struct test { static constexpr bool value = false; };
+}
+static_assert (foo::test<int>::value, "foo"); // { dg-error "static assertion failed: foo" }
+/* { dg-begin-multiline-output "" }
+ static_assert (foo::test<int>::value, "foo");
+ ~~~~~~~~~~~~~~~~^~~~~
+ { dg-end-multiline-output "" } */
+
+static_assert (foo::test<int>::value && true, "bar"); // { dg-error "static assertion failed: bar" }
+/* { dg-begin-multiline-output "" }
+ static_assert (foo::test<int>::value && true, "bar");
+ ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
+ { dg-end-multiline-output "" } */
--- gcc/testsuite/g++.dg/parse/error17.C.jj 2018-11-20 21:39:01.844562232 +0100
+++ gcc/testsuite/g++.dg/parse/error17.C 2018-11-21 12:15:22.117967478 +0100
@@ -6,4 +6,4 @@ template <typename T> struct B {
};
struct D : B<int>, B<char> {};
-int i2 = D::Bar(2); // { dg-error "10:reference to 'Bar' is ambiguous" }
+int i2 = D::Bar(2); // { dg-error "13:reference to 'Bar' is ambiguous" }
--- gcc/testsuite/g++.dg/cpp0x/pr51420.C.jj 2018-11-20 21:39:02.000559703 +0100
+++ gcc/testsuite/g++.dg/cpp0x/pr51420.C 2018-11-21 12:15:22.117967478 +0100
@@ -3,6 +3,6 @@
void
foo()
{
- float x = operator"" _F(); // { dg-error "13:'operator\"\"_F' was not declared in this scope" }
+ float x = operator"" _F(); // { dg-error "24:'operator\"\"_F' was not declared in this scope" }
float y = 0_F; // { dg-error "unable to find numeric literal operator" }
}
--- gcc/testsuite/g++.dg/cpp0x/udlit-member-neg.C.jj 2018-11-20 21:39:02.049558910 +0100
+++ gcc/testsuite/g++.dg/cpp0x/udlit-member-neg.C 2018-11-21 12:15:22.117967478 +0100
@@ -7,7 +7,7 @@ public:
int operator"" _Bar(char32_t); // { dg-error "7:.int Foo::operator\"\"_Bar\\(char32_t\\). must be a non-member function" }
};
-int i = operator"" _Bar(U'x'); // { dg-error "9:'operator\"\"_Bar' was not declared in this scope" }
+int i = operator"" _Bar(U'x'); // { dg-error "20:'operator\"\"_Bar' was not declared in this scope" }
int j = U'x'_Bar; // { dg-error "unable to find character literal operator" }
int
--- gcc/testsuite/g++.dg/cpp0x/udlit-declare-neg.C.jj 2018-11-20 21:39:01.949560531 +0100
+++ gcc/testsuite/g++.dg/cpp0x/udlit-declare-neg.C 2018-11-21 12:15:22.117967478 +0100
@@ -2,14 +2,14 @@
// Check that undeclared literal operator calls and literals give appropriate errors.
-int i = operator"" _Bar('x'); // { dg-error "9:'operator\"\"_Bar' was not declared in this scope" }
+int i = operator"" _Bar('x'); // { dg-error "20:'operator\"\"_Bar' was not declared in this scope" }
int j = 'x'_Bar; // { dg-error "unable to find character literal operator|with|argument" }
-int ii = operator"" _BarCharStr("Howdy, Pardner!"); // { dg-error "10:'operator\"\"_BarCharStr' was not declared in this scope" }
+int ii = operator"" _BarCharStr("Howdy, Pardner!"); // { dg-error "21:'operator\"\"_BarCharStr' was not declared in this scope" }
int jj = "Howdy, Pardner!"_BarCharStr; // { dg-error "unable to find string literal operator|Possible missing length argument" }
-unsigned long long iULL = operator"" _BarULL(666ULL); // { dg-error "27:'operator\"\"_BarULL' was not declared in this scope" }
+unsigned long long iULL = operator"" _BarULL(666ULL); // { dg-error "38:'operator\"\"_BarULL' was not declared in this scope" }
unsigned long long jULL = 666_BarULL; // { dg-error "unable to find numeric literal operator" }
-long double iLD = operator"" _BarLD(666.0L); // { dg-error "19:'operator\"\"_BarLD' was not declared in this scope" }
+long double iLD = operator"" _BarLD(666.0L); // { dg-error "30:'operator\"\"_BarLD' was not declared in this scope" }
long double jLD = 666.0_BarLD; // { dg-error "unable to find numeric literal operator" }
--- libstdc++-v3/testsuite/20_util/scoped_allocator/69293_neg.cc.jj 2018-07-27 22:20:29.000000000 +0200
+++ libstdc++-v3/testsuite/20_util/scoped_allocator/69293_neg.cc 2018-11-20 21:20:25.123636254 +0100
@@ -46,5 +46,5 @@ test01()
scoped_alloc sa;
auto p = sa.allocate(1);
sa.construct(p); // this is required to be ill-formed
- // { dg-error "static assertion failed" "" { target *-*-* } 94 }
+ // { dg-error "static assertion failed" "" { target *-*-* } 96 }
}
--- libstdc++-v3/testsuite/20_util/uses_allocator/cons_neg.cc.jj 2018-07-27 22:20:29.000000000 +0200
+++ libstdc++-v3/testsuite/20_util/uses_allocator/cons_neg.cc 2018-11-20 21:21:12.868864599 +0100
@@ -43,4 +43,4 @@ void test01()
tuple<Type> t(allocator_arg, a, 1);
}
-// { dg-error "static assertion failed" "" { target *-*-* } 94 }
+// { dg-error "static assertion failed" "" { target *-*-* } 96 }
--- libstdc++-v3/testsuite/20_util/uses_allocator/69293_neg.cc.jj 2018-07-27 22:20:29.760136498 +0200
+++ libstdc++-v3/testsuite/20_util/uses_allocator/69293_neg.cc 2018-11-21 16:47:49.563516993 +0100
@@ -44,5 +44,5 @@ test01()
{
alloc_type a;
std::tuple<X> t(std::allocator_arg, a); // this is required to be ill-formed
- // { dg-error "static assertion failed" "" { target *-*-* } 94 }
+ // { dg-error "static assertion failed" "" { target *-*-* } 96 }
}
--- libstdc++-v3/testsuite/experimental/propagate_const/requirements3.cc.jj 2018-01-03 18:53:16.000000000 +0100
+++ libstdc++-v3/testsuite/experimental/propagate_const/requirements3.cc 2018-11-20 21:22:06.049005105 +0100
@@ -21,6 +21,6 @@
using std::experimental::propagate_const;
-// { dg-error "requires a class or a pointer to an object type" "" { target *-*-* } 105 }
+// { dg-error "requires a class or a pointer to an object type" "" { target *-*-* } 107 }
propagate_const<void (*)()> test1;
--- libstdc++-v3/testsuite/experimental/propagate_const/requirements4.cc.jj 2018-01-03 18:53:16.000000000 +0100
+++ libstdc++-v3/testsuite/experimental/propagate_const/requirements4.cc 2018-11-20 21:22:29.698622883 +0100
@@ -21,7 +21,7 @@
using std::experimental::propagate_const;
-// { dg-error "requires a class or a pointer to an object type" "" { target *-*-* } 105 }
+// { dg-error "requires a class or a pointer to an object type" "" { target *-*-* } 107 }
// { dg-error "invalid type" "" { target *-*-* } 66 }
// { dg-error "uninitialized reference member" "" { target *-*-* } 112 }
--- libstdc++-v3/testsuite/experimental/propagate_const/requirements5.cc.jj 2018-01-03 18:53:16.000000000 +0100
+++ libstdc++-v3/testsuite/experimental/propagate_const/requirements5.cc 2018-11-20 21:22:45.311370550 +0100
@@ -21,6 +21,6 @@
using std::experimental::propagate_const;
-// { dg-error "requires a class or a pointer to an object type" "" { target *-*-* } 105 }
+// { dg-error "requires a class or a pointer to an object type" "" { target *-*-* } 107 }
propagate_const<int[1]> test1;
--- libstdc++-v3/testsuite/experimental/propagate_const/requirements2.cc.jj 2018-01-03 18:53:16.000000000 +0100
+++ libstdc++-v3/testsuite/experimental/propagate_const/requirements2.cc 2018-11-20 21:21:43.959362116 +0100
@@ -21,7 +21,7 @@
using std::experimental::propagate_const;
-// { dg-error "requires a class or a pointer to an object type" "" { target *-*-* } 105 }
+// { dg-error "requires a class or a pointer to an object type" "" { target *-*-* } 107 }
// { dg-error "not a pointer-to-object type" "" { target *-*-* } 66 }
// { dg-error "forming pointer to reference type" "" { target *-*-* } 187 }
// { dg-error "forming pointer to reference type" "" { target *-*-* } 213 }
Jakub
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [C++ PATCH] Improve locations of id-expressions and operator "" (PR c++/87386, take 2)
2018-11-21 15:55 ` [C++ PATCH] Improve locations of id-expressions and operator "" (PR c++/87386, take 2) Jakub Jelinek
@ 2018-11-21 18:29 ` Jason Merrill
2018-11-21 18:49 ` Jakub Jelinek
0 siblings, 1 reply; 12+ messages in thread
From: Jason Merrill @ 2018-11-21 18:29 UTC (permalink / raw)
To: Jakub Jelinek, David Malcolm; +Cc: gcc-patches
On 11/21/18 10:55 AM, Jakub Jelinek wrote:
> Hi!
>
> On Tue, Nov 20, 2018 at 04:32:26PM -0500, David Malcolm wrote:
>> This makes the fix-it hint wrong: after the fix-it is applied, it will
>> become
>> return color;
>> (which won't compile), rather than
>> return O::color;
>> which will.
>
> Here is an updated version of the patch, which still uses the whole
> range of the id-expression when it is parsed as primary expression, but does
> so not in cp_parser_id_expression, but in cp_parser_primary_expression after
> all the diagnostics. Thus all the spell-checking etc. tests behave as
> previously, they underline only the part after the last ::, and just
> what uses the expression later on uses whole range.
>
> The remaining needed tweeks in the testcases are minor and look correct to
> me, e.g. for D::Bar the column is not at D but at B,
Sounds good.
> similarly for operator"" _F the column is under _ rather than first o.
I disagree with this one: the name of the declaration is operator""_F,
so I think the caret should go at the first o.
> The libstdc++ changes are because there are several large expressions like:
> something<one, two,
> three, four,
> five, six>::value
> and we used to diagnose on the something line (column of s)
> but now we warn on value line (column of v).
Makes sense.
Jason
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [C++ PATCH] Improve locations of id-expressions and operator "" (PR c++/87386, take 2)
2018-11-21 18:29 ` Jason Merrill
@ 2018-11-21 18:49 ` Jakub Jelinek
2018-11-21 22:11 ` [C++ PATCH] Improve locations of id-expressions and operator "" (PR c++/87386, take 3) Jakub Jelinek
2018-11-21 22:30 ` [C++ PATCH] Improve locations of id-expressions and operator "" (PR c++/87386, take 2) Jason Merrill
0 siblings, 2 replies; 12+ messages in thread
From: Jakub Jelinek @ 2018-11-21 18:49 UTC (permalink / raw)
To: Jason Merrill; +Cc: David Malcolm, gcc-patches
On Wed, Nov 21, 2018 at 01:29:15PM -0500, Jason Merrill wrote:
> > similarly for operator"" _F the column is under _ rather than first o.
>
> I disagree with this one: the name of the declaration is operator""_F, so I
> think the caret should go at the first o.
Right now when cp_parser_operator_function_id is called, it returns locus like:
operator new
^~~
operator delete []
^~~~~~~~~
operator ==
^
operator "" _foo
UNKNOWN_LOCATION
The last one is because for others we do return cp_expr (id, start_loc);
but for operator "" just return id;
So, do you suggest we should instead return
operator new
^~~~~~~~~~~~
operator delete []
^~~~~~~~~~~~~~~~~~
operator ==
^~~~~~~~~~~
operator "" _foo
^~~~~~~~~~~~~~~~
?
That would mean cp_parser_operator_function_id would need to pass
location_t start_loc (the start of the operator token) to cp_parser_operator and
let that create a range in all cases rather than just for operator
new/delete.
Jakub
^ permalink raw reply [flat|nested] 12+ messages in thread
* [C++ PATCH] Improve locations of id-expressions and operator "" (PR c++/87386, take 3)
2018-11-21 18:49 ` Jakub Jelinek
@ 2018-11-21 22:11 ` Jakub Jelinek
2018-11-21 22:34 ` Jason Merrill
2018-11-22 8:53 ` Andreas Schwab
2018-11-21 22:30 ` [C++ PATCH] Improve locations of id-expressions and operator "" (PR c++/87386, take 2) Jason Merrill
1 sibling, 2 replies; 12+ messages in thread
From: Jakub Jelinek @ 2018-11-21 22:11 UTC (permalink / raw)
To: Jason Merrill; +Cc: David Malcolm, gcc-patches
On Wed, Nov 21, 2018 at 07:49:48PM +0100, Jakub Jelinek wrote:
> So, do you suggest we should instead return
> operator new
> ^~~~~~~~~~~~
> operator delete []
> ^~~~~~~~~~~~~~~~~~
> operator ==
> ^~~~~~~~~~~
> operator "" _foo
> ^~~~~~~~~~~~~~~~
> ?
> That would mean cp_parser_operator_function_id would need to pass
> location_t start_loc (the start of the operator token) to cp_parser_operator and
> let that create a range in all cases rather than just for operator
> new/delete.
This version of the patch implements that.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
2018-11-21 Jakub Jelinek <jakub@redhat.com>
PR c++/87386
* parser.c (cp_parser_primary_expression): Use
id_expression.get_location () instead of id_expr_token->location.
Adjust the range from id_expr_token->location to
id_expressio.get_finish ().
(cp_parser_operator_function_id): Pass location of the operator
token down to cp_parser_operator.
(cp_parser_operator): Add start_loc argument, always construct a
location with caret at start_loc and range from start_loc to the
finish of the last token.
gcc/testsuite/
* g++.dg/diagnostic/pr87386.C: New test.
* g++.dg/parse/error17.C: Adjust expected diagnostics.
libstdc++-v3/
* testsuite/20_util/scoped_allocator/69293_neg.cc: Adjust expected
line.
* testsuite/20_util/uses_allocator/cons_neg.cc: Likewise.
* testsuite/20_util/uses_allocator/69293_neg.cc: Likewise.
* testsuite/experimental/propagate_const/requirements2.cc: Likewise.
* testsuite/experimental/propagate_const/requirements3.cc: Likewise.
* testsuite/experimental/propagate_const/requirements4.cc: Likewise.
* testsuite/experimental/propagate_const/requirements5.cc: Likewise.
--- gcc/cp/parser.c.jj 2018-11-21 17:42:18.003216049 +0100
+++ gcc/cp/parser.c 2018-11-21 20:56:43.694344258 +0100
@@ -2312,7 +2312,7 @@ static tree cp_parser_mem_initializer_id
static cp_expr cp_parser_operator_function_id
(cp_parser *);
static cp_expr cp_parser_operator
- (cp_parser *);
+ (cp_parser *, location_t);
/* Templates [gram.temp] */
@@ -5604,7 +5604,7 @@ cp_parser_primary_expression (cp_parser
/*is_namespace=*/false,
/*check_dependency=*/true,
&ambiguous_decls,
- id_expr_token->location);
+ id_expression.get_location ());
/* If the lookup was ambiguous, an error will already have
been issued. */
if (ambiguous_decls)
@@ -5675,7 +5675,7 @@ cp_parser_primary_expression (cp_parser
if (parser->local_variables_forbidden_p
&& local_variable_p (decl))
{
- error_at (id_expr_token->location,
+ error_at (id_expression.get_location (),
"local variable %qD may not appear in this context",
decl.get_value ());
return error_mark_node;
@@ -5694,7 +5694,8 @@ cp_parser_primary_expression (cp_parser
id_expression.get_location ()));
if (error_msg)
cp_parser_error (parser, error_msg);
- decl.set_location (id_expr_token->location);
+ decl.set_location (id_expression.get_location ());
+ decl.set_range (id_expr_token->location, id_expression.get_finish ());
return decl;
}
@@ -15011,11 +15012,12 @@ cp_parser_mem_initializer_id (cp_parser*
static cp_expr
cp_parser_operator_function_id (cp_parser* parser)
{
+ location_t start_loc = cp_lexer_peek_token (parser->lexer)->location;
/* Look for the `operator' keyword. */
if (!cp_parser_require_keyword (parser, RID_OPERATOR, RT_OPERATOR))
return error_mark_node;
/* And then the name of the operator itself. */
- return cp_parser_operator (parser);
+ return cp_parser_operator (parser, start_loc);
}
/* Return an identifier node for a user-defined literal operator.
@@ -15049,7 +15051,7 @@ cp_literal_operator_id (const char* name
human-readable spelling of the identifier, e.g., `operator +'. */
static cp_expr
-cp_parser_operator (cp_parser* parser)
+cp_parser_operator (cp_parser* parser, location_t start_loc)
{
tree id = NULL_TREE;
cp_token *token;
@@ -15058,7 +15060,7 @@ cp_parser_operator (cp_parser* parser)
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
- location_t start_loc = token->location;
+ location_t end_loc = token->location;
/* Figure out which operator we have. */
enum tree_code op = ERROR_MARK;
@@ -15077,7 +15079,7 @@ cp_parser_operator (cp_parser* parser)
break;
/* Consume the `new' or `delete' token. */
- location_t end_loc = cp_lexer_consume_token (parser->lexer)->location;
+ end_loc = cp_lexer_consume_token (parser->lexer)->location;
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
@@ -15093,7 +15095,6 @@ cp_parser_operator (cp_parser* parser)
end_loc = close_token->location;
op = op == NEW_EXPR ? VEC_NEW_EXPR : VEC_DELETE_EXPR;
}
- start_loc = make_location (start_loc, start_loc, end_loc);
consumed = true;
break;
}
@@ -15259,7 +15260,9 @@ cp_parser_operator (cp_parser* parser)
matching_parens parens;
parens.consume_open (parser);
/* Look for the matching `)'. */
- parens.require_close (parser);
+ token = parens.require_close (parser);
+ if (token)
+ end_loc = token->location;
op = CALL_EXPR;
consumed = true;
break;
@@ -15269,7 +15272,9 @@ cp_parser_operator (cp_parser* parser)
/* Consume the `['. */
cp_lexer_consume_token (parser->lexer);
/* Look for the matching `]'. */
- cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
+ token = cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
+ if (token)
+ end_loc = token->location;
op = ARRAY_REF;
consumed = true;
break;
@@ -15287,7 +15292,8 @@ cp_parser_operator (cp_parser* parser)
case CPP_STRING16_USERDEF:
case CPP_STRING32_USERDEF:
{
- tree str, string_tree;
+ cp_expr str;
+ tree string_tree;
int sz, len;
if (cxx_dialect == cxx98)
@@ -15302,6 +15308,7 @@ cp_parser_operator (cp_parser* parser)
{
string_tree = USERDEF_LITERAL_VALUE (str);
id = USERDEF_LITERAL_SUFFIX_ID (str);
+ end_loc = str.get_location ();
}
else
{
@@ -15309,7 +15316,10 @@ cp_parser_operator (cp_parser* parser)
/* Look for the suffix identifier. */
token = cp_lexer_peek_token (parser->lexer);
if (token->type == CPP_NAME)
- id = cp_parser_identifier (parser);
+ {
+ id = cp_parser_identifier (parser);
+ end_loc = token->location;
+ }
else if (token->type == CPP_KEYWORD)
{
error ("unexpected keyword;"
@@ -15341,7 +15351,8 @@ cp_parser_operator (cp_parser* parser)
const char *name = IDENTIFIER_POINTER (id);
id = cp_literal_operator_id (name);
}
- return id;
+ start_loc = make_location (start_loc, start_loc, get_finish (end_loc));
+ return cp_expr (id, start_loc);
}
default:
@@ -15364,6 +15375,7 @@ cp_parser_operator (cp_parser* parser)
id = error_mark_node;
}
+ start_loc = make_location (start_loc, start_loc, get_finish (end_loc));
return cp_expr (id, start_loc);
}
--- gcc/testsuite/g++.dg/diagnostic/pr87386.C.jj 2018-11-21 20:17:22.707086226 +0100
+++ gcc/testsuite/g++.dg/diagnostic/pr87386.C 2018-11-21 20:17:22.707086226 +0100
@@ -0,0 +1,18 @@
+// PR c++/87386
+// { dg-do compile { target c++11 } }
+// { dg-options "-fdiagnostics-show-caret" }
+
+namespace foo {
+ template<typename> struct test { static constexpr bool value = false; };
+}
+static_assert (foo::test<int>::value, "foo"); // { dg-error "static assertion failed: foo" }
+/* { dg-begin-multiline-output "" }
+ static_assert (foo::test<int>::value, "foo");
+ ~~~~~~~~~~~~~~~~^~~~~
+ { dg-end-multiline-output "" } */
+
+static_assert (foo::test<int>::value && true, "bar"); // { dg-error "static assertion failed: bar" }
+/* { dg-begin-multiline-output "" }
+ static_assert (foo::test<int>::value && true, "bar");
+ ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
+ { dg-end-multiline-output "" } */
--- gcc/testsuite/g++.dg/parse/error17.C.jj 2018-11-21 17:39:49.225651053 +0100
+++ gcc/testsuite/g++.dg/parse/error17.C 2018-11-21 20:17:22.707086226 +0100
@@ -6,4 +6,4 @@ template <typename T> struct B {
};
struct D : B<int>, B<char> {};
-int i2 = D::Bar(2); // { dg-error "10:reference to 'Bar' is ambiguous" }
+int i2 = D::Bar(2); // { dg-error "13:reference to 'Bar' is ambiguous" }
--- libstdc++-v3/testsuite/20_util/scoped_allocator/69293_neg.cc.jj 2018-07-27 22:20:29.000000000 +0200
+++ libstdc++-v3/testsuite/20_util/scoped_allocator/69293_neg.cc 2018-11-20 21:20:25.123636254 +0100
@@ -46,5 +46,5 @@ test01()
scoped_alloc sa;
auto p = sa.allocate(1);
sa.construct(p); // this is required to be ill-formed
- // { dg-error "static assertion failed" "" { target *-*-* } 94 }
+ // { dg-error "static assertion failed" "" { target *-*-* } 96 }
}
--- libstdc++-v3/testsuite/20_util/uses_allocator/cons_neg.cc.jj 2018-07-27 22:20:29.000000000 +0200
+++ libstdc++-v3/testsuite/20_util/uses_allocator/cons_neg.cc 2018-11-20 21:21:12.868864599 +0100
@@ -43,4 +43,4 @@ void test01()
tuple<Type> t(allocator_arg, a, 1);
}
-// { dg-error "static assertion failed" "" { target *-*-* } 94 }
+// { dg-error "static assertion failed" "" { target *-*-* } 96 }
--- libstdc++-v3/testsuite/20_util/uses_allocator/69293_neg.cc.jj 2018-07-27 22:20:29.760136498 +0200
+++ libstdc++-v3/testsuite/20_util/uses_allocator/69293_neg.cc 2018-11-21 16:47:49.563516993 +0100
@@ -44,5 +44,5 @@ test01()
{
alloc_type a;
std::tuple<X> t(std::allocator_arg, a); // this is required to be ill-formed
- // { dg-error "static assertion failed" "" { target *-*-* } 94 }
+ // { dg-error "static assertion failed" "" { target *-*-* } 96 }
}
--- libstdc++-v3/testsuite/experimental/propagate_const/requirements3.cc.jj 2018-01-03 18:53:16.000000000 +0100
+++ libstdc++-v3/testsuite/experimental/propagate_const/requirements3.cc 2018-11-20 21:22:06.049005105 +0100
@@ -21,6 +21,6 @@
using std::experimental::propagate_const;
-// { dg-error "requires a class or a pointer to an object type" "" { target *-*-* } 105 }
+// { dg-error "requires a class or a pointer to an object type" "" { target *-*-* } 107 }
propagate_const<void (*)()> test1;
--- libstdc++-v3/testsuite/experimental/propagate_const/requirements4.cc.jj 2018-01-03 18:53:16.000000000 +0100
+++ libstdc++-v3/testsuite/experimental/propagate_const/requirements4.cc 2018-11-20 21:22:29.698622883 +0100
@@ -21,7 +21,7 @@
using std::experimental::propagate_const;
-// { dg-error "requires a class or a pointer to an object type" "" { target *-*-* } 105 }
+// { dg-error "requires a class or a pointer to an object type" "" { target *-*-* } 107 }
// { dg-error "invalid type" "" { target *-*-* } 66 }
// { dg-error "uninitialized reference member" "" { target *-*-* } 112 }
--- libstdc++-v3/testsuite/experimental/propagate_const/requirements5.cc.jj 2018-01-03 18:53:16.000000000 +0100
+++ libstdc++-v3/testsuite/experimental/propagate_const/requirements5.cc 2018-11-20 21:22:45.311370550 +0100
@@ -21,6 +21,6 @@
using std::experimental::propagate_const;
-// { dg-error "requires a class or a pointer to an object type" "" { target *-*-* } 105 }
+// { dg-error "requires a class or a pointer to an object type" "" { target *-*-* } 107 }
propagate_const<int[1]> test1;
--- libstdc++-v3/testsuite/experimental/propagate_const/requirements2.cc.jj 2018-01-03 18:53:16.000000000 +0100
+++ libstdc++-v3/testsuite/experimental/propagate_const/requirements2.cc 2018-11-20 21:21:43.959362116 +0100
@@ -21,7 +21,7 @@
using std::experimental::propagate_const;
-// { dg-error "requires a class or a pointer to an object type" "" { target *-*-* } 105 }
+// { dg-error "requires a class or a pointer to an object type" "" { target *-*-* } 107 }
// { dg-error "not a pointer-to-object type" "" { target *-*-* } 66 }
// { dg-error "forming pointer to reference type" "" { target *-*-* } 187 }
// { dg-error "forming pointer to reference type" "" { target *-*-* } 213 }
Jakub
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [C++ PATCH] Improve locations of id-expressions and operator "" (PR c++/87386, take 2)
2018-11-21 18:49 ` Jakub Jelinek
2018-11-21 22:11 ` [C++ PATCH] Improve locations of id-expressions and operator "" (PR c++/87386, take 3) Jakub Jelinek
@ 2018-11-21 22:30 ` Jason Merrill
1 sibling, 0 replies; 12+ messages in thread
From: Jason Merrill @ 2018-11-21 22:30 UTC (permalink / raw)
To: Jakub Jelinek; +Cc: David Malcolm, gcc-patches
On 11/21/18 1:49 PM, Jakub Jelinek wrote:
> On Wed, Nov 21, 2018 at 01:29:15PM -0500, Jason Merrill wrote:
>>> similarly for operator"" _F the column is under _ rather than first o.
>>
>> I disagree with this one: the name of the declaration is operator""_F, so I
>> think the caret should go at the first o.
>
> Right now when cp_parser_operator_function_id is called, it returns locus like:
> operator new
> ^~~
> operator delete []
> ^~~~~~~~~
> operator ==
> ^
> operator "" _foo
> UNKNOWN_LOCATION
> The last one is because for others we do return cp_expr (id, start_loc);
> but for operator "" just return id;
>
> So, do you suggest we should instead return
> operator new
> ^~~~~~~~~~~~
> operator delete []
> ^~~~~~~~~~~~~~~~~~
> operator ==
> ^~~~~~~~~~~
> operator "" _foo
> ^~~~~~~~~~~~~~~~
> ?
Yes.
> That would mean cp_parser_operator_function_id would need to pass
> location_t start_loc (the start of the operator token) to cp_parser_operator and
> let that create a range in all cases rather than just for operator
> new/delete.
Sure.
Jason
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [C++ PATCH] Improve locations of id-expressions and operator "" (PR c++/87386, take 3)
2018-11-21 22:11 ` [C++ PATCH] Improve locations of id-expressions and operator "" (PR c++/87386, take 3) Jakub Jelinek
@ 2018-11-21 22:34 ` Jason Merrill
2018-11-22 8:53 ` Andreas Schwab
1 sibling, 0 replies; 12+ messages in thread
From: Jason Merrill @ 2018-11-21 22:34 UTC (permalink / raw)
To: Jakub Jelinek; +Cc: David Malcolm, gcc-patches
On 11/21/18 5:10 PM, Jakub Jelinek wrote:
> On Wed, Nov 21, 2018 at 07:49:48PM +0100, Jakub Jelinek wrote:
>> So, do you suggest we should instead return
>> operator new
>> ^~~~~~~~~~~~
>> operator delete []
>> ^~~~~~~~~~~~~~~~~~
>> operator ==
>> ^~~~~~~~~~~
>> operator "" _foo
>> ^~~~~~~~~~~~~~~~
>> ?
>> That would mean cp_parser_operator_function_id would need to pass
>> location_t start_loc (the start of the operator token) to cp_parser_operator and
>> let that create a range in all cases rather than just for operator
>> new/delete.
>
> This version of the patch implements that.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
OK.
Jason
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [C++ PATCH] Improve locations of id-expressions and operator "" (PR c++/87386, take 3)
2018-11-21 22:11 ` [C++ PATCH] Improve locations of id-expressions and operator "" (PR c++/87386, take 3) Jakub Jelinek
2018-11-21 22:34 ` Jason Merrill
@ 2018-11-22 8:53 ` Andreas Schwab
2018-11-22 9:12 ` Jakub Jelinek
1 sibling, 1 reply; 12+ messages in thread
From: Andreas Schwab @ 2018-11-22 8:53 UTC (permalink / raw)
To: Jakub Jelinek; +Cc: Jason Merrill, David Malcolm, gcc-patches
In file included from ../../gcc/c-family/c-common.h:26:0,
from ../../gcc/cp/cp-tree.h:40,
from ../../gcc/cp/parser.c:25:
../../gcc/cp/parser.c: In function 'cp_expr cp_parser_operator(cp_parser*, location_t)':
../../gcc/tree.h:383:33: error: invalid cast from type 'cp_expr' to type 'tree_userdef_literal*'
#define TREE_CHECK(T, CODE) (T)
^
./tree-check.h:234:34: note: in expansion of macro 'TREE_CHECK'
#define USERDEF_LITERAL_CHECK(t) TREE_CHECK (t, USERDEF_LITERAL)
^
../../gcc/c-family/c-common.h:1231:36: note: in expansion of macro 'USERDEF_LITERAL_CHECK'
(((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->value)
^
../../gcc/cp/parser.c:15309:20: note: in expansion of macro 'USERDEF_LITERAL_VALUE'
string_tree = USERDEF_LITERAL_VALUE (str);
^
../../gcc/tree.h:383:33: error: invalid cast from type 'cp_expr' to type 'tree_userdef_literal*'
#define TREE_CHECK(T, CODE) (T)
^
./tree-check.h:234:34: note: in expansion of macro 'TREE_CHECK'
#define USERDEF_LITERAL_CHECK(t) TREE_CHECK (t, USERDEF_LITERAL)
^
../../gcc/c-family/c-common.h:1228:36: note: in expansion of macro 'USERDEF_LITERAL_CHECK'
(((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->suffix_id)
^
../../gcc/cp/parser.c:15310:11: note: in expansion of macro 'USERDEF_LITERAL_SUFFIX_ID'
id = USERDEF_LITERAL_SUFFIX_ID (str);
^
Andreas.
--
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [C++ PATCH] Improve locations of id-expressions and operator "" (PR c++/87386, take 3)
2018-11-22 8:53 ` Andreas Schwab
@ 2018-11-22 9:12 ` Jakub Jelinek
2018-11-22 9:21 ` Andreas Schwab
0 siblings, 1 reply; 12+ messages in thread
From: Jakub Jelinek @ 2018-11-22 9:12 UTC (permalink / raw)
To: Andreas Schwab; +Cc: Jason Merrill, David Malcolm, gcc-patches
On Thu, Nov 22, 2018 at 09:53:13AM +0100, Andreas Schwab wrote:
> In file included from ../../gcc/c-family/c-common.h:26:0,
> from ../../gcc/cp/cp-tree.h:40,
> from ../../gcc/cp/parser.c:25:
> ../../gcc/cp/parser.c: In function 'cp_expr cp_parser_operator(cp_parser*, location_t)':
> ../../gcc/tree.h:383:33: error: invalid cast from type 'cp_expr' to type 'tree_userdef_literal*'
> #define TREE_CHECK(T, CODE) (T)
> ^
Is that with --enable-checking=release or something similar?
Built just fine for me with normal --enable-checking=yes,rtl,extra.
Jakub
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [C++ PATCH] Improve locations of id-expressions and operator "" (PR c++/87386, take 3)
2018-11-22 9:12 ` Jakub Jelinek
@ 2018-11-22 9:21 ` Andreas Schwab
2018-11-22 9:30 ` Jakub Jelinek
0 siblings, 1 reply; 12+ messages in thread
From: Andreas Schwab @ 2018-11-22 9:21 UTC (permalink / raw)
To: Jakub Jelinek; +Cc: Jason Merrill, David Malcolm, gcc-patches
On Nov 22 2018, Jakub Jelinek <jakub@redhat.com> wrote:
> Is that with --enable-checking=release
Yes.
Andreas.
--
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [C++ PATCH] Improve locations of id-expressions and operator "" (PR c++/87386, take 3)
2018-11-22 9:21 ` Andreas Schwab
@ 2018-11-22 9:30 ` Jakub Jelinek
0 siblings, 0 replies; 12+ messages in thread
From: Jakub Jelinek @ 2018-11-22 9:30 UTC (permalink / raw)
To: Andreas Schwab; +Cc: Jason Merrill, David Malcolm, gcc-patches
On Thu, Nov 22, 2018 at 10:21:53AM +0100, Andreas Schwab wrote:
> On Nov 22 2018, Jakub Jelinek <jakub@redhat.com> wrote:
>
> > Is that with --enable-checking=release
>
> Yes.
Ok, reproduced myself, fixed thusly, committed to unbreak it.
cp_expr has
operator tree () const { return m_value; }
tree & operator* () { return m_value; }
tree operator* () const { return m_value; }
tree & operator-> () { return m_value; }
tree operator-> () const { return m_value; }
so it does the right thing most of the time, like with:
TREE_CHECK (NODE, something)->something_else
even if #define TREE_CHECK(NODE) NODE
But in this case we have:
#define USERDEF_LITERAL_VALUE(NODE) \
(((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->value)
and so it works only if TREE_CHECK expands to something that forces the cast
to tree.
2018-11-22 Jakub Jelinek <jakub@redhat.com>
PR c++/87386
* parser.c (cp_parser_operator): Use str.get_value () instead of just
str in USERDEF_LITERAL_VALUE and USERDEF_LITERAL_SUFFIX_ID arguments.
--- gcc/cp/parser.c.jj 2018-11-21 23:40:10.999140630 +0100
+++ gcc/cp/parser.c 2018-11-22 10:19:47.384240264 +0100
@@ -15306,8 +15306,8 @@ cp_parser_operator (cp_parser* parser, l
return error_mark_node;
else if (TREE_CODE (str) == USERDEF_LITERAL)
{
- string_tree = USERDEF_LITERAL_VALUE (str);
- id = USERDEF_LITERAL_SUFFIX_ID (str);
+ string_tree = USERDEF_LITERAL_VALUE (str.get_value ());
+ id = USERDEF_LITERAL_SUFFIX_ID (str.get_value ());
end_loc = str.get_location ();
}
else
Jakub
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2018-11-22 9:30 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-11-20 20:57 [RFC C++ PATCH] Improve locations of id-expressions and operator "" (PR c++/87386) Jakub Jelinek
2018-11-20 21:32 ` David Malcolm
2018-11-21 15:55 ` [C++ PATCH] Improve locations of id-expressions and operator "" (PR c++/87386, take 2) Jakub Jelinek
2018-11-21 18:29 ` Jason Merrill
2018-11-21 18:49 ` Jakub Jelinek
2018-11-21 22:11 ` [C++ PATCH] Improve locations of id-expressions and operator "" (PR c++/87386, take 3) Jakub Jelinek
2018-11-21 22:34 ` Jason Merrill
2018-11-22 8:53 ` Andreas Schwab
2018-11-22 9:12 ` Jakub Jelinek
2018-11-22 9:21 ` Andreas Schwab
2018-11-22 9:30 ` Jakub Jelinek
2018-11-21 22:30 ` [C++ PATCH] Improve locations of id-expressions and operator "" (PR c++/87386, take 2) Jason Merrill
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).