[PATCH 10/22] C++ FE: Use token ranges for various diagnostics
David Malcolm
dmalcolm@redhat.com
Thu Sep 10 20:13:00 GMT 2015
Screenshot:
https://dmalcolm.fedorapeople.org/gcc/2015-09-09/c++-token-ranges.html
gcc/cp/ChangeLog:
* parser.c (cp_parser_string_literal): Show ranges of both
string literals in the "unsupported concatenation" error.
(cp_parser_primary_expression): Use token range rather than
location for two errors.
(cp_parser_namespace_alias_definition): Likewise for one error.
(cp_parser_init_declarator): Likewise.
(cp_parser_base_specifier): Likewise for two errors.
(cp_parser_std_attribute): Likewise for an error and a warning.
(cp_parser_function_definition_after_declarator): Likewise for an
error.
(cp_parser_explicit_template_declaration): Add "tok_range" param
and use it for the errors.
(cp_parser_template_declaration_after_export): Pass the range
of the "template" token to
cp_parser_explicit_template_declaration.
gcc/testsuite/ChangeLog:
* g++.dg/diagnostic/token-ranges.C: New.
---
gcc/cp/parser.c | 45 +++++++----
gcc/testsuite/g++.dg/diagnostic/token-ranges.C | 104 +++++++++++++++++++++++++
2 files changed, 132 insertions(+), 17 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/diagnostic/token-ranges.C
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 7c59c58..17b7de0 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -3734,6 +3734,8 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok,
gcc_obstack_init (&str_ob);
count = 0;
+ source_range range_of_prior_literal = tok->range;
+
do
{
cp_lexer_consume_token (parser->lexer);
@@ -3767,11 +3769,17 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok,
if (type == CPP_STRING)
type = curr_type;
else if (curr_type != CPP_STRING)
- error_at (tok->location,
- "unsupported non-standard concatenation "
- "of string literals");
+ {
+ rich_location rich_loc (tok->range);
+ rich_loc.add_range (range_of_prior_literal);
+ error_at_rich_loc (&rich_loc,
+ "unsupported non-standard concatenation "
+ "of string literals");
+ }
}
+ range_of_prior_literal.m_finish = tok->range.m_finish;
+
obstack_grow (&str_ob, &str, sizeof (cpp_string));
tok = cp_lexer_peek_token (parser->lexer);
@@ -4549,7 +4557,7 @@ cp_parser_primary_expression (cp_parser *parser,
cp_lexer_consume_token (parser->lexer);
if (parser->local_variables_forbidden_p)
{
- error_at (token->location,
+ error_at (token->range,
"%<this%> may not be used in this context");
return error_mark_node;
}
@@ -4672,7 +4680,7 @@ cp_parser_primary_expression (cp_parser *parser,
&& (cp_lexer_peek_nth_token (parser->lexer, 2)->type
== CPP_LESS))
{
- error_at (token->location,
+ error_at (token->range,
"a template declaration cannot appear at block scope");
cp_parser_skip_to_end_of_block_or_statement (parser);
return error_mark_node;
@@ -16829,7 +16837,7 @@ cp_parser_namespace_alias_definition (cp_parser* parser)
if (!cp_parser_uncommitted_to_tentative_parse_p (parser)
&& cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
{
- error_at (token->location, "%<namespace%> definition is not allowed here");
+ error_at (token->range, "%<namespace%> definition is not allowed here");
/* Skip the definition. */
cp_lexer_consume_token (parser->lexer);
if (cp_parser_skip_to_closing_brace (parser))
@@ -17602,7 +17610,7 @@ cp_parser_init_declarator (cp_parser* parser,
"an asm-specification is not allowed "
"on a function-definition");
if (attributes)
- error_at (attributes_start_token->location,
+ error_at (attributes_start_token->range,
"attributes are not allowed "
"on a function-definition");
/* This is a function-definition. */
@@ -22016,10 +22024,10 @@ cp_parser_base_specifier (cp_parser* parser)
{
token = cp_lexer_peek_token (parser->lexer);
if (!processing_template_decl)
- error_at (token->location,
+ error_at (token->range,
"keyword %<typename%> not allowed outside of templates");
else
- error_at (token->location,
+ error_at (token->range,
"keyword %<typename%> not allowed in this context "
"(the base class is implicitly a type)");
cp_lexer_consume_token (parser->lexer);
@@ -22971,10 +22979,12 @@ cp_parser_std_attribute (cp_parser *parser)
{
tree attribute, attr_ns = NULL_TREE, attr_id = NULL_TREE, arguments;
cp_token *token;
+ source_range name_range;
/* First, parse name of the attribute, a.k.a attribute-token. */
token = cp_lexer_peek_token (parser->lexer);
+ name_range = token->range;
if (token->type == CPP_NAME)
attr_id = token->u.value;
else if (token->type == CPP_KEYWORD)
@@ -23002,7 +23012,7 @@ cp_parser_std_attribute (cp_parser *parser)
attr_id = ridpointers[(int) token->keyword];
else
{
- error_at (token->location,
+ error_at (token->range,
"expected an identifier for the attribute name");
return error_mark_node;
}
@@ -23021,7 +23031,7 @@ cp_parser_std_attribute (cp_parser *parser)
else if (cxx_dialect >= cxx11 && is_attribute_p ("deprecated", attr_id))
{
if (cxx_dialect == cxx11)
- pedwarn (token->location, OPT_Wpedantic,
+ pedwarn (name_range, OPT_Wpedantic,
"%<deprecated%> is a C++14 feature;"
" use %<gnu::deprecated%>");
TREE_PURPOSE (TREE_PURPOSE (attribute)) = get_identifier ("gnu");
@@ -24383,7 +24393,7 @@ cp_parser_function_definition_after_declarator (cp_parser* parser,
returned. */
cp_parser_identifier (parser);
/* Issue an error message. */
- error_at (token->location,
+ error_at (token->range,
"named return values are no longer supported");
/* Skip tokens until we reach the start of the function body. */
while (true)
@@ -24654,11 +24664,11 @@ cp_parser_template_introduction (cp_parser* parser, bool member_p)
/* Parse a normal template-declaration following the template keyword. */
static void
-cp_parser_explicit_template_declaration (cp_parser* parser, bool member_p)
+cp_parser_explicit_template_declaration (cp_parser* parser, bool member_p,
+ source_range tok_range)
{
tree parameter_list;
bool need_lang_pop;
- location_t location = input_location;
/* Look for the `<' token. */
if (!cp_parser_require (parser, CPP_LESS, RT_LESS))
@@ -24668,7 +24678,7 @@ cp_parser_explicit_template_declaration (cp_parser* parser, bool member_p)
/* 14.5.2.2 [temp.mem]
A local class shall not have member templates. */
- error_at (location,
+ error_at (tok_range,
"invalid declaration of member template in local class");
cp_parser_skip_to_end_of_block_or_statement (parser);
return;
@@ -24678,7 +24688,7 @@ cp_parser_explicit_template_declaration (cp_parser* parser, bool member_p)
A template ... shall not have C linkage. */
if (current_lang_name == lang_name_c)
{
- error_at (location, "template with C linkage");
+ error_at (tok_range, "template with C linkage");
/* Give it C++ linkage to avoid confusing other parts of the
front end. */
push_lang_context (lang_name_cplusplus);
@@ -24737,8 +24747,9 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
{
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TEMPLATE))
{
+ source_range tok_range = cp_lexer_peek_token (parser->lexer)->range;
cp_lexer_consume_token (parser->lexer);
- cp_parser_explicit_template_declaration (parser, member_p);
+ cp_parser_explicit_template_declaration (parser, member_p, tok_range);
return true;
}
else if (flag_concepts)
diff --git a/gcc/testsuite/g++.dg/diagnostic/token-ranges.C b/gcc/testsuite/g++.dg/diagnostic/token-ranges.C
new file mode 100644
index 0000000..bc830ad
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/token-ranges.C
@@ -0,0 +1,104 @@
+/* { dg-options "-fdiagnostics-show-caret -std=c++11 -Wpedantic" } */
+
+/* Verify that various diagnostics show source code ranges. */
+
+/* These ones merely use token ranges; they don't use tree ranges. */
+
+void bad_namespace () {
+ namespace foo { // { dg-error "'namespace' definition is not allowed here" }
+ }
+/* { dg-begin-multiline-output "" }
+ namespace foo {
+ ^~~~~~~~~
+ { dg-end-multiline-output "" } */
+}
+
+
+void fn_defn_with_attribute ()
+ __attribute__((constructor (0))) // { dg-error "attributes are not allowed on a function-definition" }
+{
+ /* { dg-begin-multiline-output "" }
+ __attribute__((constructor (0)))
+ ^~~~~~~~~~~~~
+ { dg-end-multiline-output "" } */
+}
+
+class foo {};
+class bar : public typename foo // { dg-error "keyword 'typename' not allowed outside of templates" }
+{
+};
+/* { dg-begin-multiline-output "" }
+ class bar : public typename foo
+ ^~~~~~~~
+ { dg-end-multiline-output "" } */
+
+
+// C++11 attributes
+
+void bogus_scoped_attribute [[foo::400]] (); // { dg-error "expected an identifier for the attribute name" }
+/* { dg-begin-multiline-output "" }
+ void bogus_scoped_attribute [[foo::400]] ();
+ ^~~
+ { dg-end-multiline-output "" } */
+
+void meta_deprecation [[deprecated]] (); // { dg-warning "use 'gnu::deprecated'" }
+/* { dg-begin-multiline-output "" }
+ void meta_deprecation [[deprecated]] ();
+ ^~~~~~~~~~
+ { dg-end-multiline-output "" } */
+
+
+int foo() return bar {} // { dg-error "named return values are no longer supported" }
+/* { dg-begin-multiline-output "" }
+ int foo() return bar {}
+ ^~~~~~
+ { dg-end-multiline-output "" } */
+
+template<typename T> void foo(T)
+{
+ struct A
+ {
+ template<int> struct B {} // { dg-error "local class" }
+
+/* { dg-begin-multiline-output "" }
+ template<int> struct B {}
+ ^~~~~~~~
+ { dg-end-multiline-output "" } */
+ };
+}
+
+extern "C" { template<typename T> void foo(T); } // { dg-error "C linkage" }
+/* { dg-begin-multiline-output "" }
+ extern "C" { template<typename T> void foo(T); }
+ ^~~~~~~~
+ { dg-end-multiline-output "" } */
+// TODO: It would be nice to inform the user of the location of the
+// relevant extern "C".
+
+const void *s = u8"a" u"b"; // { dg-error "non-standard concatenation" }
+/* { dg-begin-multiline-output "" }
+ const void *s = u8"a" u"b";
+ ~~~~~ ^~~~
+ { dg-end-multiline-output "" } */
+
+const void *s2 = u"a" u"b" u8"c"; // { dg-error "non-standard concatenation" }
+/* { dg-begin-multiline-output "" }
+ const void *s2 = u"a" u"b" u8"c";
+ ~~~~~~~~~~ ^~~~~
+ { dg-end-multiline-output "" } */
+
+
+void default_arg_of_this (void *ptr = this); // { dg-error "'this'" }
+/* { dg-begin-multiline-output "" }
+ void default_arg_of_this (void *ptr = this);
+ ^~~~
+ { dg-end-multiline-output "" } */
+
+void template_inside_fn ()
+{
+ int i = template < // { dg-error "cannot appear at block scope" }
+/* { dg-begin-multiline-output "" }
+ int i = template <
+ ^~~~~~~~
+ { dg-end-multiline-output "" } */
+}
--
1.8.5.3
More information about the Gcc-patches
mailing list