aboutsummaryrefslogtreecommitdiff
path: root/gcc/c
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2015-11-13 16:29:59 +0000
committerDavid Malcolm <dmalcolm@gcc.gnu.org>2015-11-13 16:29:59 +0000
commitebedc9a3414d842274607b77597759bd36e0f3e0 (patch)
treed1ab10c369a8f1ec9f67e1e8cb70acef36897f21 /gcc/c
parent1ba91a49a97955057bb8a07b42feb901ee9cee4e (diff)
downloadgcc-ebedc9a3414d842274607b77597759bd36e0f3e0.zip
gcc-ebedc9a3414d842274607b77597759bd36e0f3e0.tar.gz
gcc-ebedc9a3414d842274607b77597759bd36e0f3e0.tar.bz2
Source range tracking in libcpp and C FE, with bit-packing optimization
This patch combines: [PATCH 05/10] Add ranges to libcpp tokens (via ad-hoc data, unoptimized) [PATCH 06/10] Track expression ranges in C frontend [PATCH 07/10] Add plugin to recursively dump the source-ranges in a tree (v2) [PATCH 08/10] Wire things up so that libcpp users get token underlines [PATCH 09/10] Delay some resolution of ad-hoc locations, preserving ranges [PATCH 10/10] Compress short ranges into source_location [PATCH] libcpp: add examples to source_location description along with fixes for the nits identified during review. gcc/ChangeLog: * Makefile.in (OBJS): Add gcc-rich-location.o. * diagnostic.c (diagnostic_append_note): Pass line_table to rich_location ctor. (emit_diagnostic): Likewise. (inform): Likewise. (inform_n): Likewise. (warning): Likewise. (warning_at): Likewise. (warning_n): Likewise. (pedwarn): Likewise. (permerror): Likewise. (error): Likewise. (error_n): Likewise. (error_at): Likewise. (sorry): Likewise. (fatal_error): Likewise. (internal_error): Likewise. (internal_error_no_backtrace): Likewise. (source_range::debug): Likewise. * gcc-rich-location.c: New file. * gcc-rich-location.h: New file. * genmatch.c (fatal_at): Pass line_table to rich_location ctor. (warning_at): Likewise. * gimple.h (gimple_set_block): Use set_block function. * input.c (dump_line_table_statistics): Dump stats on how many ranges were optimized vs how many needed ad-hoc table. (write_digit_row): Add "map" param; use its range_bits to calculate the per-character offset. (dump_location_info): Print the range and column bits for each ordinary map. Use the range bits to calculate the per-character offset. Pass the map as a new param to the various calls to write_digit_row. Eliminate uses of ORDINARY_MAP_NUMBER_OF_COLUMN_BITS. * print-tree.c (print_node): Print any source range information. * rtl-error.c (diagnostic_for_asm): Likewise. * toplev.c (general_init): Initialize line_table's default_range_bits. * tree-cfg.c (move_block_to_fn): Likewise. (move_block_to_fn): Likewise. * tree-inline.c (copy_phis_for_bb): Likewise. * tree.c (tree_set_block): Likewise. (get_pure_location): New function. (set_source_range): New functions. (set_block): New function. (set_source_range): New functions. * tree.h (CAN_HAVE_RANGE_P): New. (EXPR_LOCATION_RANGE): New. (EXPR_HAS_RANGE): New. (get_expr_source_range): New inline function. (DECL_LOCATION_RANGE): New. (set_source_range): New decls. (get_decl_source_range): New inline function. gcc/ada/ChangeLog: * gcc-interface/trans.c (Sloc_to_locus): Add line_table param when calling linemap_position_for_line_and_column. gcc/c-family/ChangeLog: * c-common.c (c_fully_fold_internal): Capture existing souce_range, and store it on the result. * c-opts.c (c_common_init_options): Set global_dc->colorize_source_p. gcc/c/ChangeLog: * c-decl.c (warn_defaults_to): Pass line_table to rich_location ctor. * c-errors.c (pedwarn_c99): Likewise. (pedwarn_c90): Likewise. * c-parser.c (set_c_expr_source_range): New functions. (c_token::get_range): New method. (c_token::get_finish): New method. (c_parser_expr_no_commas): Call set_c_expr_source_range on the ret based on the range from the start of the LHS to the end of the RHS. (c_parser_conditional_expression): Likewise, based on the range from the start of the cond.value to the end of exp2.value. (c_parser_binary_expression): Call set_c_expr_source_range on the stack values for TRUTH_ANDIF_EXPR and TRUTH_ORIF_EXPR. (c_parser_cast_expression): Call set_c_expr_source_range on ret based on the cast_loc through to the end of the expr. (c_parser_unary_expression): Likewise, based on the op_loc through to the end of op. (c_parser_sizeof_expression) Likewise, based on the start of the sizeof token through to either the closing paren or the end of expr. (c_parser_postfix_expression): Likewise, using the token range, or from the open paren through to the close paren for parenthesized expressions. (c_parser_postfix_expression_after_primary): Likewise, for various kinds of expression. * c-tree.h (struct c_expr): Add field "src_range". (c_expr::get_start): New method. (c_expr::get_finish): New method. (set_c_expr_source_range): New decls. * c-typeck.c (parser_build_unary_op): Call set_c_expr_source_range on ret for prefix unary ops. (parser_build_binary_op): Likewise, running from the start of arg1.value through to the end of arg2.value. gcc/cp/ChangeLog: * error.c (pedwarn_cxx98): Pass line_table to rich_location ctor. gcc/fortran/ChangeLog: * error.c (gfc_warning): Pass line_table to rich_location ctor. (gfc_warning_now_at): Likewise. (gfc_warning_now): Likewise. (gfc_error_now): Likewise. (gfc_fatal_error): Likewise. (gfc_error): Likewise. (gfc_internal_error): Likewise. gcc/testsuite/ChangeLog: * gcc.dg/diagnostic-token-ranges.c: New file. * gcc.dg/diagnostic-tree-expr-ranges-2.c: New file. * gcc.dg/plugin/diagnostic-test-expressions-1.c: New file. * gcc.dg/plugin/diagnostic-test-show-trees-1.c: New file. * gcc.dg/plugin/diagnostic_plugin_show_trees.c: New file. * gcc.dg/plugin/diagnostic_plugin_test_show_locus.c (get_loc): Add line_table param when calling linemap_position_for_line_and_column. (test_show_locus): Pass line_table to rich_location ctors. (plugin_init): Remove setting of global_dc->colorize_source_p. * gcc.dg/plugin/diagnostic_plugin_test_tree_expression_range.c: New file. * gcc.dg/plugin/plugin.exp (plugin_test_list): Add diagnostic_plugin_test_tree_expression_range.c, diagnostic-test-expressions-1.c, diagnostic_plugin_show_trees.c, and diagnostic-test-show-trees-1.c. libcpp/ChangeLog: * errors.c (cpp_diagnostic): Pass pfile->line_table to rich_location ctor. (cpp_diagnostic_with_line): Likewise. * include/cpplib.h (struct cpp_token): Update comment for src_loc to indicate that the range of the token is "baked into" the source_location. * include/line-map.h (source_location): Update the descriptive comment to reflect the packing scheme for short ranges, adding worked examples of location encoding. (struct line_map_ordinary): Drop field "column_bits" in favor of field "m_column_and_range_bits"; add field "m_range_bits". (ORDINARY_MAP_NUMBER_OF_COLUMN_BITS): Delete. (location_adhoc_data): Add source_range field. (struct line_maps): Add fields "default_range_bits", "num_optimized_ranges" and "num_unoptimized_ranges". (get_combined_adhoc_loc): Add source_range param. (get_range_from_loc): New declaration. (pure_location_p): New prototype. (COMBINE_LOCATION_DATA): Add source_range param. (SOURCE_LINE): Update for renaming of column_bits. (SOURCE_COLUMN): Likewise. Shift the column right by the map's range_bits. (LAST_SOURCE_LINE_LOCATION): Update for renaming of column_bits. (linemap_position_for_line_and_column): Add line_maps * params. (rich_location::rich_location): Likewise. * lex.c (_cpp_lex_direct): Capture the range of the token, baking it into token->src_loc via a call to COMBINE_LOCATION_DATA. * line-map.c (LINE_MAP_MAX_COLUMN_NUMBER): Reduce from 1U << 17 to 1U << 12. (location_adhoc_data_hash): Add the src_range into the hash value. (location_adhoc_data_eq): Require equality of the src_range values. (can_be_stored_compactly_p): New function. (get_combined_adhoc_loc): Add src_range param, and store it, via a bit-packing scheme for short ranges, otherwise within the lookaside table. Remove the requirement that data is non-NULL. (get_range_from_adhoc_loc): New function. (get_range_from_loc): New function. (pure_location_p): New function. (linemap_add): Ensure that start_location has zero for the range_bits, unless we're past LINE_MAP_MAX_LOCATION_WITH_COLS. Initialize range_bits to zero. Assert that the start_location is "pure". (linemap_line_start): Assert that the column_and_range_bits >= range_bits. Update determinination of whether we need to start a new map using the effective column bits, without the range bits. Use the set's default_range_bits in new maps, apart from those with column_bits == 0, which should also have 0 range_bits. Increase the column bits for new maps by the range bits. When adding lines to an existing map, use set->highest_line directly rather than offsetting highest by SOURCE_COLUMN. Add assertions to sanity-check the return value. (linemap_position_for_column): Offset to_column by range_bits. Update set->highest_location if necessary. (linemap_position_for_line_and_column): Add line_maps * param. Update the calculation to offset the column by range_bits, and conditionalize it on being <= LINE_MAP_MAX_LOCATION_WITH_COLS. Bound it by LINEMAPS_MACRO_LOWEST_LOCATION. Update set->highest_location if necessary. (linemap_position_for_loc_and_offset): Handle ad-hoc locations; pass "set" to linemap_position_for_line_and_column. (linemap_macro_map_loc_unwind_toward_spelling): Add line_maps param. Handle ad-hoc locations. (linemap_location_in_system_header_p): Pass on "set" to call to linemap_macro_map_loc_unwind_toward_spelling. (linemap_macro_loc_to_spelling_point): Retain ad-hoc locations. Pass on "set" to call to linemap_macro_map_loc_unwind_toward_spelling. (linemap_resolve_location): Retain ad-hoc locations. Pass on "set" to call to linemap_macro_map_loc_unwind_toward_spelling. (linemap_unwind_toward_expansion): Pass on "set" to call to linemap_macro_map_loc_unwind_toward_spelling. (linemap_expand_location): Extract the data pointer before extracting the location. (rich_location::rich_location): Add line_maps param; use it to extract the range from the source_location. * location-example.txt: Regenerate, showing new representation. From-SVN: r230331
Diffstat (limited to 'gcc/c')
-rw-r--r--gcc/c/ChangeLog37
-rw-r--r--gcc/c/c-decl.c2
-rw-r--r--gcc/c/c-errors.c4
-rw-r--r--gcc/c/c-parser.c92
-rw-r--r--gcc/c/c-tree.h19
-rw-r--r--gcc/c/c-typeck.c10
6 files changed, 158 insertions, 6 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 8824f18..810f2c6 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,40 @@
+2015-11-13 David Malcolm <dmalcolm@redhat.com>
+
+ * c-decl.c (warn_defaults_to): Pass line_table to
+ rich_location ctor.
+ * c-errors.c (pedwarn_c99): Likewise.
+ (pedwarn_c90): Likewise.
+ * c-parser.c (set_c_expr_source_range): New functions.
+ (c_token::get_range): New method.
+ (c_token::get_finish): New method.
+ (c_parser_expr_no_commas): Call set_c_expr_source_range on the ret
+ based on the range from the start of the LHS to the end of the
+ RHS.
+ (c_parser_conditional_expression): Likewise, based on the range
+ from the start of the cond.value to the end of exp2.value.
+ (c_parser_binary_expression): Call set_c_expr_source_range on
+ the stack values for TRUTH_ANDIF_EXPR and TRUTH_ORIF_EXPR.
+ (c_parser_cast_expression): Call set_c_expr_source_range on ret
+ based on the cast_loc through to the end of the expr.
+ (c_parser_unary_expression): Likewise, based on the
+ op_loc through to the end of op.
+ (c_parser_sizeof_expression) Likewise, based on the start of the
+ sizeof token through to either the closing paren or the end of
+ expr.
+ (c_parser_postfix_expression): Likewise, using the token range,
+ or from the open paren through to the close paren for
+ parenthesized expressions.
+ (c_parser_postfix_expression_after_primary): Likewise, for
+ various kinds of expression.
+ * c-tree.h (struct c_expr): Add field "src_range".
+ (c_expr::get_start): New method.
+ (c_expr::get_finish): New method.
+ (set_c_expr_source_range): New decls.
+ * c-typeck.c (parser_build_unary_op): Call set_c_expr_source_range
+ on ret for prefix unary ops.
+ (parser_build_binary_op): Likewise, running from the start of
+ arg1.value through to the end of arg2.value.
+
2015-11-13 Marek Polacek <polacek@redhat.com>
PR c/68320
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index a636474..9a222d8 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -5278,7 +5278,7 @@ warn_defaults_to (location_t location, int opt, const char *gmsgid, ...)
{
diagnostic_info diagnostic;
va_list ap;
- rich_location richloc (location);
+ rich_location richloc (line_table, location);
va_start (ap, gmsgid);
diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
diff --git a/gcc/c/c-errors.c b/gcc/c/c-errors.c
index ef0f9a2..ee9c2b5 100644
--- a/gcc/c/c-errors.c
+++ b/gcc/c/c-errors.c
@@ -37,7 +37,7 @@ pedwarn_c99 (location_t location, int opt, const char *gmsgid, ...)
diagnostic_info diagnostic;
va_list ap;
bool warned = false;
- rich_location richloc (location);
+ rich_location richloc (line_table, location);
va_start (ap, gmsgid);
/* If desired, issue the C99/C11 compat warning, which is more specific
@@ -76,7 +76,7 @@ pedwarn_c90 (location_t location, int opt, const char *gmsgid, ...)
{
diagnostic_info diagnostic;
va_list ap;
- rich_location richloc (location);
+ rich_location richloc (line_table, location);
va_start (ap, gmsgid);
/* Warnings such as -Wvla are the most specific ones. */
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 82d5ce5..943d3e5 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -59,6 +59,23 @@ along with GCC; see the file COPYING3. If not see
#include "gimple-expr.h"
#include "context.h"
+void
+set_c_expr_source_range (c_expr *expr,
+ location_t start, location_t finish)
+{
+ expr->src_range.m_start = start;
+ expr->src_range.m_finish = finish;
+ set_source_range (expr->value, start, finish);
+}
+
+void
+set_c_expr_source_range (c_expr *expr,
+ source_range src_range)
+{
+ expr->src_range = src_range;
+ set_source_range (expr->value, src_range);
+}
+
/* Initialization routine for this file. */
@@ -164,6 +181,16 @@ struct GTY (()) c_token {
location_t location;
/* The value associated with this token, if any. */
tree value;
+
+ source_range get_range () const
+ {
+ return get_range_from_loc (line_table, location);
+ }
+
+ location_t get_finish () const
+ {
+ return get_range ().m_finish;
+ }
};
/* A parser structure recording information about the state and
@@ -6117,6 +6144,7 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after,
ret.value = build_modify_expr (op_location, lhs.value, lhs.original_type,
code, exp_location, rhs.value,
rhs.original_type);
+ set_c_expr_source_range (&ret, lhs.get_start (), rhs.get_finish ());
if (code == NOP_EXPR)
ret.original_code = MODIFY_EXPR;
else
@@ -6147,7 +6175,7 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after,
tree omp_atomic_lhs)
{
struct c_expr cond, exp1, exp2, ret;
- location_t cond_loc, colon_loc, middle_loc;
+ location_t start, cond_loc, colon_loc, middle_loc;
gcc_assert (!after || c_dialect_objc ());
@@ -6155,6 +6183,10 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after,
if (c_parser_next_token_is_not (parser, CPP_QUERY))
return cond;
+ if (cond.value != error_mark_node)
+ start = cond.get_start ();
+ else
+ start = UNKNOWN_LOCATION;
cond_loc = c_parser_peek_token (parser)->location;
cond = convert_lvalue_to_rvalue (cond_loc, cond, true, true);
c_parser_consume_token (parser);
@@ -6230,6 +6262,7 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after,
? t1
: NULL);
}
+ set_c_expr_source_range (&ret, start, exp2.get_finish ());
return ret;
}
@@ -6382,6 +6415,7 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after,
{
enum c_parser_prec oprec;
enum tree_code ocode;
+ source_range src_range;
if (parser->error)
goto out;
switch (c_parser_peek_token (parser)->type)
@@ -6470,6 +6504,7 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after,
switch (ocode)
{
case TRUTH_ANDIF_EXPR:
+ src_range = stack[sp].expr.src_range;
stack[sp].expr
= convert_lvalue_to_rvalue (stack[sp].loc,
stack[sp].expr, true, true);
@@ -6477,8 +6512,10 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after,
(stack[sp].loc, default_conversion (stack[sp].expr.value));
c_inhibit_evaluation_warnings += (stack[sp].expr.value
== truthvalue_false_node);
+ set_c_expr_source_range (&stack[sp].expr, src_range);
break;
case TRUTH_ORIF_EXPR:
+ src_range = stack[sp].expr.src_range;
stack[sp].expr
= convert_lvalue_to_rvalue (stack[sp].loc,
stack[sp].expr, true, true);
@@ -6486,6 +6523,7 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after,
(stack[sp].loc, default_conversion (stack[sp].expr.value));
c_inhibit_evaluation_warnings += (stack[sp].expr.value
== truthvalue_true_node);
+ set_c_expr_source_range (&stack[sp].expr, src_range);
break;
default:
break;
@@ -6554,6 +6592,8 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after)
expr = convert_lvalue_to_rvalue (expr_loc, expr, true, true);
}
ret.value = c_cast_expr (cast_loc, type_name, expr.value);
+ if (ret.value && expr.value)
+ set_c_expr_source_range (&ret, cast_loc, expr.get_finish ());
ret.original_code = ERROR_MARK;
ret.original_type = NULL;
return ret;
@@ -6603,6 +6643,7 @@ c_parser_unary_expression (c_parser *parser)
struct c_expr ret, op;
location_t op_loc = c_parser_peek_token (parser)->location;
location_t exp_loc;
+ location_t finish;
ret.original_code = ERROR_MARK;
ret.original_type = NULL;
switch (c_parser_peek_token (parser)->type)
@@ -6642,8 +6683,10 @@ c_parser_unary_expression (c_parser *parser)
c_parser_consume_token (parser);
exp_loc = c_parser_peek_token (parser)->location;
op = c_parser_cast_expression (parser, NULL);
+ finish = op.get_finish ();
op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
ret.value = build_indirect_ref (op_loc, op.value, RO_UNARY_STAR);
+ set_c_expr_source_range (&ret, op_loc, finish);
return ret;
case CPP_PLUS:
if (!c_dialect_objc () && !in_system_header_at (input_location))
@@ -6731,8 +6774,15 @@ static struct c_expr
c_parser_sizeof_expression (c_parser *parser)
{
struct c_expr expr;
+ struct c_expr result;
location_t expr_loc;
gcc_assert (c_parser_next_token_is_keyword (parser, RID_SIZEOF));
+
+ location_t start;
+ location_t finish = UNKNOWN_LOCATION;
+
+ start = c_parser_peek_token (parser)->location;
+
c_parser_consume_token (parser);
c_inhibit_evaluation_warnings++;
in_sizeof++;
@@ -6746,6 +6796,7 @@ c_parser_sizeof_expression (c_parser *parser)
expr_loc = c_parser_peek_token (parser)->location;
type_name = c_parser_type_name (parser);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+ finish = parser->tokens_buf[0].location;
if (type_name == NULL)
{
struct c_expr ret;
@@ -6761,17 +6812,19 @@ c_parser_sizeof_expression (c_parser *parser)
expr = c_parser_postfix_expression_after_paren_type (parser,
type_name,
expr_loc);
+ finish = expr.get_finish ();
goto sizeof_expr;
}
/* sizeof ( type-name ). */
c_inhibit_evaluation_warnings--;
in_sizeof--;
- return c_expr_sizeof_type (expr_loc, type_name);
+ result = c_expr_sizeof_type (expr_loc, type_name);
}
else
{
expr_loc = c_parser_peek_token (parser)->location;
expr = c_parser_unary_expression (parser);
+ finish = expr.get_finish ();
sizeof_expr:
c_inhibit_evaluation_warnings--;
in_sizeof--;
@@ -6779,8 +6832,11 @@ c_parser_sizeof_expression (c_parser *parser)
if (TREE_CODE (expr.value) == COMPONENT_REF
&& DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
error_at (expr_loc, "%<sizeof%> applied to a bit-field");
- return c_expr_sizeof_expr (expr_loc, expr);
+ result = c_expr_sizeof_expr (expr_loc, expr);
}
+ if (finish != UNKNOWN_LOCATION)
+ set_c_expr_source_range (&result, start, finish);
+ return result;
}
/* Parse an alignof expression. */
@@ -7200,12 +7256,14 @@ 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 tok_range = c_parser_peek_token (parser)->get_range ();
expr.original_code = ERROR_MARK;
expr.original_type = NULL;
switch (c_parser_peek_token (parser)->type)
{
case CPP_NUMBER:
expr.value = c_parser_peek_token (parser)->value;
+ set_c_expr_source_range (&expr, tok_range);
loc = c_parser_peek_token (parser)->location;
c_parser_consume_token (parser);
if (TREE_CODE (expr.value) == FIXED_CST
@@ -7220,6 +7278,7 @@ c_parser_postfix_expression (c_parser *parser)
case CPP_CHAR32:
case CPP_WCHAR:
expr.value = c_parser_peek_token (parser)->value;
+ set_c_expr_source_range (&expr, tok_range);
c_parser_consume_token (parser);
break;
case CPP_STRING:
@@ -7228,6 +7287,7 @@ c_parser_postfix_expression (c_parser *parser)
case CPP_WSTRING:
case CPP_UTF8STRING:
expr.value = c_parser_peek_token (parser)->value;
+ set_c_expr_source_range (&expr, tok_range);
expr.original_code = STRING_CST;
c_parser_consume_token (parser);
break;
@@ -7235,6 +7295,7 @@ c_parser_postfix_expression (c_parser *parser)
gcc_assert (c_dialect_objc ());
expr.value
= objc_build_string_object (c_parser_peek_token (parser)->value);
+ set_c_expr_source_range (&expr, tok_range);
c_parser_consume_token (parser);
break;
case CPP_NAME:
@@ -7248,6 +7309,7 @@ c_parser_postfix_expression (c_parser *parser)
(c_parser_peek_token (parser)->type
== CPP_OPEN_PAREN),
&expr.original_type);
+ set_c_expr_source_range (&expr, tok_range);
break;
}
case C_ID_CLASSNAME:
@@ -7336,6 +7398,7 @@ c_parser_postfix_expression (c_parser *parser)
else
{
/* A parenthesized expression. */
+ location_t loc_open_paren = c_parser_peek_token (parser)->location;
c_parser_consume_token (parser);
expr = c_parser_expression (parser);
if (TREE_CODE (expr.value) == MODIFY_EXPR)
@@ -7343,6 +7406,8 @@ c_parser_postfix_expression (c_parser *parser)
if (expr.original_code != C_MAYBE_CONST_EXPR)
expr.original_code = ERROR_MARK;
/* Don't change EXPR.ORIGINAL_TYPE. */
+ location_t loc_close_paren = c_parser_peek_token (parser)->location;
+ set_c_expr_source_range (&expr, loc_open_paren, loc_close_paren);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
"expected %<)%>");
}
@@ -7933,6 +7998,8 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
vec<tree, va_gc> *exprlist;
vec<tree, va_gc> *origtypes = NULL;
vec<location_t> arg_loc = vNULL;
+ location_t start;
+ location_t finish;
while (true)
{
@@ -7969,7 +8036,10 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
{
c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
"expected %<]%>");
+ start = expr.get_start ();
+ finish = parser->tokens_buf[0].location;
expr.value = build_array_ref (op_loc, expr.value, idx);
+ set_c_expr_source_range (&expr, start, finish);
}
}
expr.original_code = ERROR_MARK;
@@ -8012,9 +8082,13 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
"%<memset%> used with constant zero length parameter; "
"this could be due to transposed parameters");
+ start = expr.get_start ();
+ finish = parser->tokens_buf[0].get_finish ();
expr.value
= c_build_function_call_vec (expr_loc, arg_loc, expr.value,
exprlist, origtypes);
+ set_c_expr_source_range (&expr, start, finish);
+
expr.original_code = ERROR_MARK;
if (TREE_CODE (expr.value) == INTEGER_CST
&& TREE_CODE (orig_expr.value) == FUNCTION_DECL
@@ -8043,8 +8117,11 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
expr.original_type = NULL;
return expr;
}
+ start = expr.get_start ();
+ finish = c_parser_peek_token (parser)->get_finish ();
c_parser_consume_token (parser);
expr.value = build_component_ref (op_loc, expr.value, ident);
+ set_c_expr_source_range (&expr, start, finish);
expr.original_code = ERROR_MARK;
if (TREE_CODE (expr.value) != COMPONENT_REF)
expr.original_type = NULL;
@@ -8072,12 +8149,15 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
expr.original_type = NULL;
return expr;
}
+ start = expr.get_start ();
+ finish = c_parser_peek_token (parser)->get_finish ();
c_parser_consume_token (parser);
expr.value = build_component_ref (op_loc,
build_indirect_ref (op_loc,
expr.value,
RO_ARROW),
ident);
+ set_c_expr_source_range (&expr, start, finish);
expr.original_code = ERROR_MARK;
if (TREE_CODE (expr.value) != COMPONENT_REF)
expr.original_type = NULL;
@@ -8093,6 +8173,8 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
break;
case CPP_PLUS_PLUS:
/* Postincrement. */
+ start = expr.get_start ();
+ finish = c_parser_peek_token (parser)->get_finish ();
c_parser_consume_token (parser);
/* If the expressions have array notations, we expand them. */
if (flag_cilkplus
@@ -8104,11 +8186,14 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
expr.value = build_unary_op (op_loc,
POSTINCREMENT_EXPR, expr.value, 0);
}
+ set_c_expr_source_range (&expr, start, finish);
expr.original_code = ERROR_MARK;
expr.original_type = NULL;
break;
case CPP_MINUS_MINUS:
/* Postdecrement. */
+ start = expr.get_start ();
+ finish = c_parser_peek_token (parser)->get_finish ();
c_parser_consume_token (parser);
/* If the expressions have array notations, we expand them. */
if (flag_cilkplus
@@ -8120,6 +8205,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
expr.value = build_unary_op (op_loc,
POSTDECREMENT_EXPR, expr.value, 0);
}
+ set_c_expr_source_range (&expr, start, finish);
expr.original_code = ERROR_MARK;
expr.original_type = NULL;
break;
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index 04991f7..6bc216a 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -132,6 +132,17 @@ struct c_expr
The type of an enum constant is a plain integer type, but this
field will be the enum type. */
tree original_type;
+
+ /* The source range of this expression. This is redundant
+ for node values that have locations, but not all node kinds
+ have locations (e.g. constants, and references to params, locals,
+ etc), so we stash a copy here. */
+ source_range src_range;
+
+ /* Access to the first and last locations within the source spelling
+ of this expression. */
+ location_t get_start () const { return src_range.m_start; }
+ location_t get_finish () const { return src_range.m_finish; }
};
/* Type alias for struct c_expr. This allows to use the structure
@@ -708,4 +719,12 @@ extern void pedwarn_c90 (location_t, int opt, const char *, ...)
extern bool pedwarn_c99 (location_t, int opt, const char *, ...)
ATTRIBUTE_GCC_DIAG(3,4);
+extern void
+set_c_expr_source_range (c_expr *expr,
+ location_t start, location_t finish);
+
+extern void
+set_c_expr_source_range (c_expr *expr,
+ source_range src_range);
+
#endif /* ! GCC_C_TREE_H */
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index eb4e1fc..4db9bbf 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -3460,6 +3460,12 @@ parser_build_unary_op (location_t loc, enum tree_code code, struct c_expr arg)
overflow_warning (loc, result.value);
}
+ /* We are typically called when parsing a prefix token at LOC acting on
+ ARG. Reflect this by updating the source range of the result to
+ start at LOC and end at the end of ARG. */
+ set_c_expr_source_range (&result,
+ loc, arg.get_finish ());
+
return result;
}
@@ -3497,6 +3503,10 @@ parser_build_binary_op (location_t location, enum tree_code code,
if (location != UNKNOWN_LOCATION)
protected_set_expr_location (result.value, location);
+ set_c_expr_source_range (&result,
+ arg1.get_start (),
+ arg2.get_finish ());
+
/* Check for cases such as x+y<<z which users are likely
to misinterpret. */
if (warn_parentheses)