This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH] Improve locations of id-expressions and operator "" (PR c++/87386, take 3)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Jason Merrill <jason at redhat dot com>
- Cc: David Malcolm <dmalcolm at redhat dot com>, gcc-patches at gcc dot gnu dot org
- Date: Wed, 21 Nov 2018 23:10:51 +0100
- Subject: [C++ PATCH] Improve locations of id-expressions and operator "" (PR c++/87386, take 3)
- References: <20181120205711.GH11625@tucnak> <1542749546.4619.68.camel@redhat.com> <20181121155544.GN11625@tucnak> <0920aa8b-e99a-86ef-c6d3-12de0f0c8916@redhat.com> <20181121184948.GQ11625@tucnak>
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
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