[RFC C++ PATCH] Improve locations of id-expressions and operator "" (PR c++/87386)

Jakub Jelinek jakub@redhat.com
Tue Nov 20 20:57:00 GMT 2018


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



More information about the Gcc-patches mailing list