This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH 08/22] C frontend: use token ranges in various diagnostics
- From: David Malcolm <dmalcolm at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: David Malcolm <dmalcolm at redhat dot com>
- Date: Thu, 10 Sep 2015 16:28:19 -0400
- Subject: [PATCH 08/22] C frontend: use token ranges in various diagnostics
- Authentication-results: sourceware.org; auth=none
- References: <1441916913-11547-1-git-send-email-dmalcolm at redhat dot com>
This patch makes use of token ranges in the C frontend to add underlines
to various diagnostics.
Screenshot:
https://dmalcolm.fedorapeople.org/gcc/2015-09-09/diagnostic-token-ranges.html
gcc/c/ChangeLog:
* c-decl.c (undeclared_variable): Convert param "loc" from a
location_t to a source_range.
* c-parser.c (c_lex_one_token): Use token's range rather than
location for "identifier conflicts with C++ keyword" warning.
(c_parser_declaration_or_fndef): Convert local "here" from a
location_t to a source_range.
(c_parser_parms_list_declarator): Use token's range rather than
location for "ISO C requires a named argument before ..." warning.
(c_parser_parameter_declaration): Likewise for "unknown type name"
error.
(c_parser_asm_string_literal): Likewise for
"wide string literal in asm" error.
(c_parser_label): Likewise for label-before-declaration error, and
show the label's range to the error.
(c_parser_statement_after_labels): Pass the token's range rather
than location to c_finish_bc_stmt.
(c_parser_postfix_expression): Likewise for call to
build_external_ref.
(c_parser_omp_variable_list): Likewise for call to
undeclared_variable.
* c-tree.h (undeclared_variable): Convert initial param from
location_t to source_range.
(build_external_ref): Likewise.
(c_finish_bc_stmt): Likewise.
* c-typeck.c (build_external_ref): Likewise.
(c_finish_bc_stmt): Likewise.
gcc/testsuite/ChangeLog:
* gcc.dg/diagnostic-token-ranges.c: New file.
---
gcc/c/c-decl.c | 2 +-
gcc/c/c-parser.c | 31 ++++---
gcc/c/c-tree.h | 6 +-
gcc/c/c-typeck.c | 22 ++---
gcc/testsuite/gcc.dg/diagnostic-token-ranges.c | 109 +++++++++++++++++++++++++
5 files changed, 143 insertions(+), 27 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/diagnostic-token-ranges.c
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index e6b6ba5..9fe8aa4 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -3409,7 +3409,7 @@ implicitly_declare (location_t loc, tree functionid)
in an appropriate scope, which will suppress further errors for the
same identifier. The error message should be given location LOC. */
void
-undeclared_variable (location_t loc, tree id)
+undeclared_variable (source_range loc, tree id)
{
static bool already = false;
struct c_scope *scope;
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 5d822ee..1c93d39 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -266,7 +266,7 @@ c_lex_one_token (c_parser *parser, c_token *token)
if (rid_code == RID_CXX_COMPAT_WARN)
{
- warning_at (token->location,
+ warning_at (token->range,
OPT_Wc___compat,
"identifier %qE conflicts with C++ keyword",
token->value);
@@ -1526,7 +1526,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
tree prefix_attrs;
tree all_prefix_attrs;
bool diagnosed_no_specs = false;
- location_t here = c_parser_peek_token (parser)->location;
+ source_range here = c_parser_peek_token (parser)->range;
if (static_assert_ok
&& c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
@@ -3575,7 +3575,7 @@ c_parser_parms_list_declarator (c_parser *parser, tree attrs, tree expr)
{
/* Suppress -Wold-style-definition for this case. */
ret->types = error_mark_node;
- error_at (c_parser_peek_token (parser)->location,
+ error_at (c_parser_peek_token (parser)->range,
"ISO C requires a named argument before %<...%>");
}
c_parser_consume_token (parser);
@@ -3670,7 +3670,7 @@ c_parser_parameter_declaration (c_parser *parser, tree attrs)
c_parser_set_source_position_from_token (token);
if (c_parser_next_tokens_start_typename (parser, cla_prefer_type))
{
- error_at (token->location, "unknown type name %qE", token->value);
+ error_at (token->range, "unknown type name %qE", token->value);
parser->error = true;
}
/* ??? In some Objective-C cases '...' isn't applicable so there
@@ -3731,7 +3731,7 @@ c_parser_asm_string_literal (c_parser *parser)
}
else if (c_parser_next_token_is (parser, CPP_WSTRING))
{
- error_at (c_parser_peek_token (parser)->location,
+ error_at (c_parser_peek_token (parser)->range,
"wide string literal in %<asm%>");
str = build_string (1, "");
c_parser_consume_token (parser);
@@ -4749,6 +4749,7 @@ c_parser_all_labels (c_parser *parser)
static void
c_parser_label (c_parser *parser)
{
+ source_range label_range = c_parser_peek_token (parser)->range;
location_t loc1 = c_parser_peek_token (parser)->location;
tree label = NULL_TREE;
if (c_parser_next_token_is_keyword (parser, RID_CASE))
@@ -4799,9 +4800,11 @@ c_parser_label (c_parser *parser)
{
if (c_parser_next_tokens_start_declaration (parser))
{
- error_at (c_parser_peek_token (parser)->location,
- "a label can only be part of a statement and "
- "a declaration is not a statement");
+ rich_location richloc (c_parser_peek_token (parser)->range);
+ richloc.add_range (label_range);
+ error_at_rich_loc (&richloc,
+ "a label can only be part of a statement and "
+ "a declaration is not a statement");
c_parser_declaration_or_fndef (parser, /*fndef_ok*/ false,
/*static_assert_ok*/ true,
/*empty_ok*/ true, /*nested*/ true,
@@ -4963,6 +4966,7 @@ static void
c_parser_statement_after_labels (c_parser *parser)
{
location_t loc = c_parser_peek_token (parser)->location;
+ source_range tok_range = c_parser_peek_token (parser)->range;
tree stmt = NULL_TREE;
bool in_if_block = parser->in_if_block;
parser->in_if_block = false;
@@ -5034,11 +5038,11 @@ c_parser_statement_after_labels (c_parser *parser)
goto expect_semicolon;
case RID_CONTINUE:
c_parser_consume_token (parser);
- stmt = c_finish_bc_stmt (loc, &c_cont_label, false);
+ stmt = c_finish_bc_stmt (tok_range, &c_cont_label, false);
goto expect_semicolon;
case RID_BREAK:
c_parser_consume_token (parser);
- stmt = c_finish_bc_stmt (loc, &c_break_label, true);
+ stmt = c_finish_bc_stmt (tok_range, &c_break_label, true);
goto expect_semicolon;
case RID_RETURN:
c_parser_consume_token (parser);
@@ -7128,6 +7132,7 @@ c_parser_postfix_expression (c_parser *parser)
struct c_expr expr, e1;
struct c_type_name *t1, *t2;
location_t loc = c_parser_peek_token (parser)->location;;
+ source_range src_range = c_parser_peek_token (parser)->range;
expr.original_code = ERROR_MARK;
expr.original_type = NULL;
switch (c_parser_peek_token (parser)->type)
@@ -7172,7 +7177,7 @@ c_parser_postfix_expression (c_parser *parser)
{
tree id = c_parser_peek_token (parser)->value;
c_parser_consume_token (parser);
- expr.value = build_external_ref (loc, id,
+ expr.value = build_external_ref (src_range, id,
(c_parser_peek_token (parser)->type
== CPP_OPEN_PAREN),
&expr.original_type);
@@ -10165,7 +10170,7 @@ c_parser_omp_variable_list (c_parser *parser,
if (t == NULL_TREE)
{
- undeclared_variable (c_parser_peek_token (parser)->location,
+ undeclared_variable (c_parser_peek_token (parser)->range,
c_parser_peek_token (parser)->value);
t = error_mark_node;
}
@@ -14933,7 +14938,7 @@ c_parser_cilk_clause_linear (c_parser *parser, tree clauses)
if (var == NULL)
{
- undeclared_variable (c_parser_peek_token (parser)->location,
+ undeclared_variable (c_parser_peek_token (parser)->range,
c_parser_peek_token (parser)->value);
c_parser_consume_token (parser);
}
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index df1ebb6..4b0ec22 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -491,7 +491,7 @@ extern tree build_enumerator (location_t, location_t, struct c_enum_contents *,
extern tree check_for_loop_decls (location_t, bool);
extern void mark_forward_parm_decls (void);
extern void declare_parm_level (void);
-extern void undeclared_variable (location_t, tree);
+extern void undeclared_variable (source_range, tree);
extern tree lookup_label_for_goto (location_t, tree);
extern tree declare_label (tree);
extern tree define_label (location_t, tree);
@@ -595,7 +595,7 @@ extern void mark_exp_read (tree);
extern tree composite_type (tree, tree);
extern tree build_component_ref (location_t, tree, tree);
extern tree build_array_ref (location_t, tree, tree);
-extern tree build_external_ref (location_t, tree, int, tree *);
+extern tree build_external_ref (source_range, tree, int, tree *);
extern void pop_maybe_used (bool);
extern struct c_expr c_expr_sizeof_expr (location_t, struct c_expr);
extern struct c_expr c_expr_sizeof_type (location_t, struct c_type_name *);
@@ -636,7 +636,7 @@ extern tree c_finish_stmt_expr (location_t, tree);
extern tree c_process_expr_stmt (location_t, tree);
extern tree c_finish_expr_stmt (location_t, tree);
extern tree c_finish_return (location_t, tree, tree);
-extern tree c_finish_bc_stmt (location_t, tree *, bool);
+extern tree c_finish_bc_stmt (source_range tok_range, tree *, bool);
extern tree c_finish_goto_label (location_t, tree);
extern tree c_finish_goto_ptr (location_t, tree);
extern tree c_expr_to_decl (tree, bool *, bool *);
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index dc22396..a755a7e 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -2587,7 +2587,7 @@ build_array_ref (location_t loc, tree array, tree index)
for CONST_DECLs defined as enum constants. If the type of the
identifier is not available, *TYPE is set to NULL. */
tree
-build_external_ref (location_t loc, tree id, int fun, tree *type)
+build_external_ref (source_range loc, tree id, int fun, tree *type)
{
tree ref;
tree decl = lookup_name (id);
@@ -2604,7 +2604,7 @@ build_external_ref (location_t loc, tree id, int fun, tree *type)
}
else if (fun)
/* Implicit function declaration. */
- ref = implicitly_declare (loc, id);
+ ref = implicitly_declare (loc.m_start, id);
else if (decl == error_mark_node)
/* Don't complain about something that's already been
complained about. */
@@ -2674,7 +2674,7 @@ build_external_ref (location_t loc, tree id, int fun, tree *type)
&& (!VAR_P (ref) || TREE_STATIC (ref))
&& ! TREE_PUBLIC (ref)
&& DECL_CONTEXT (ref) != current_function_decl)
- record_inline_static (loc, current_function_decl, ref,
+ record_inline_static (loc.m_start, current_function_decl, ref,
csi_internal);
return ref;
@@ -9873,7 +9873,7 @@ c_finish_loop (location_t start_locus, tree cond, tree incr, tree body,
}
tree
-c_finish_bc_stmt (location_t loc, tree *label_p, bool is_break)
+c_finish_bc_stmt (source_range tok_range, tree *label_p, bool is_break)
{
bool skip;
tree label = *label_p;
@@ -9890,7 +9890,7 @@ c_finish_bc_stmt (location_t loc, tree *label_p, bool is_break)
if (!label)
{
if (!skip)
- *label_p = label = create_artificial_label (loc);
+ *label_p = label = create_artificial_label (tok_range.m_start);
}
else if (TREE_CODE (label) == LABEL_DECL)
;
@@ -9898,21 +9898,23 @@ c_finish_bc_stmt (location_t loc, tree *label_p, bool is_break)
{
case 0:
if (is_break)
- error_at (loc, "break statement not within loop or switch");
+ error_at (tok_range, "break statement not within loop or switch");
else
- error_at (loc, "continue statement not within a loop");
+ error_at (tok_range, "continue statement not within a loop");
return NULL_TREE;
case 1:
gcc_assert (is_break);
- error_at (loc, "break statement used with OpenMP for loop");
+ error_at (tok_range, "break statement used with OpenMP for loop");
return NULL_TREE;
case 2:
if (is_break)
- error ("break statement within %<#pragma simd%> loop body");
+ error_at (tok_range,
+ "break statement within %<#pragma simd%> loop body");
else
- error ("continue statement within %<#pragma simd%> loop body");
+ error_at (tok_range,
+ "continue statement within %<#pragma simd%> loop body");
return NULL_TREE;
default:
diff --git a/gcc/testsuite/gcc.dg/diagnostic-token-ranges.c b/gcc/testsuite/gcc.dg/diagnostic-token-ranges.c
new file mode 100644
index 0000000..6bd9e0b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/diagnostic-token-ranges.c
@@ -0,0 +1,109 @@
+/* { dg-options "-fdiagnostics-show-caret -Wc++-compat" } */
+
+/* Verify that various diagnostics show source code ranges. */
+
+/* These ones merely use token ranges; they don't use tree ranges. */
+
+void undeclared_identifier (void)
+{
+ name; /* { dg-error "'name' undeclared" } */
+/*
+{ dg-begin-multiline-output "" }
+ name;
+ ^~~~
+{ dg-end-multiline-output "" }
+*/
+}
+
+void unknown_type_name (void)
+{
+ foo bar; /* { dg-error "unknown type name 'foo'" } */
+/*
+{ dg-begin-multiline-output "" }
+ foo bar;
+ ^~~
+{ dg-end-multiline-output "" }
+*/
+
+ qux *baz; /* { dg-error "unknown type name 'qux'" } */
+/*
+{ dg-begin-multiline-output "" }
+ qux *baz;
+ ^~~
+{ dg-end-multiline-output "" }
+*/
+}
+
+void test_identifier_conflicts_with_cplusplus (void)
+{
+ int new; /* { dg-warning "identifier 'new' conflicts with" } */
+/*
+{ dg-begin-multiline-output "" }
+ int new;
+ ^~~
+{ dg-end-multiline-output "" }
+*/
+}
+
+extern void
+bogus_varargs (...); /* { dg-error "ISO C requires a named argument before '...'" } */
+/*
+{ dg-begin-multiline-output "" }
+ bogus_varargs (...);
+ ^~~
+{ dg-end-multiline-output "" }
+*/
+
+extern void
+foo (unknown_type param); /* { dg-error "unknown type name 'unknown_type'" } */
+/*
+{ dg-begin-multiline-output "" }
+ foo (unknown_type param);
+ ^~~~~~~~~~~~
+{ dg-end-multiline-output "" }
+*/
+
+void wide_string_literal_in_asm (void)
+{
+ asm (L"nop"); /* { dg-error "wide string literal in 'asm'" } */
+/*
+{ dg-begin-multiline-output "" }
+ asm (L"nop");
+ ^~~~~~
+{ dg-end-multiline-output "" }
+*/
+}
+
+void label_in_front_of_decl (void)
+{
+ label:
+ int i; /* { dg-error "a label can only be part of a statement and a declaration is not a statement" } */
+/*
+{ dg-begin-multiline-output "" }
+ label:
+ ~~~~~
+ int i;
+ ^~~
+{ dg-end-multiline-output "" }
+*/
+ return;
+}
+
+void break_and_continue_in_wrong_places (void)
+{
+ if (0)
+ break; /* { dg-error "break statement not within loop or switch" } */
+/* { dg-begin-multiline-output "" }
+ break;
+ ^~~~~
+ { dg-end-multiline-output "" } */
+
+ if (1)
+ ;
+ else
+ continue; /* { dg-error "continue statement not within a loop" } */
+/* { dg-begin-multiline-output "" }
+ continue;
+ ^~~~~~~~
+ { dg-end-multiline-output "" } */
+}
--
1.8.5.3