summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog55
-rw-r--r--gcc/Makefile.in1
-rw-r--r--gcc/ada/ChangeLog5
-rw-r--r--gcc/ada/gcc-interface/trans.c3
-rw-r--r--gcc/c-family/ChangeLog7
-rw-r--r--gcc/c-family/c-common.c10
-rw-r--r--gcc/c-family/c-opts.c2
-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
-rw-r--r--gcc/cp/ChangeLog4
-rw-r--r--gcc/cp/error.c2
-rw-r--r--gcc/diagnostic.c34
-rw-r--r--gcc/fortran/ChangeLog10
-rw-r--r--gcc/fortran/error.c14
-rw-r--r--gcc/gcc-rich-location.c86
-rw-r--r--gcc/gcc-rich-location.h47
-rw-r--r--gcc/genmatch.c8
-rw-r--r--gcc/gimple.h6
-rw-r--r--gcc/input.c28
-rw-r--r--gcc/print-tree.c21
-rw-r--r--gcc/rtl-error.c2
-rw-r--r--gcc/testsuite/ChangeLog19
-rw-r--r--gcc/testsuite/gcc.dg/diagnostic-token-ranges.c120
-rw-r--r--gcc/testsuite/gcc.dg/diagnostic-tree-expr-ranges-2.c23
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic-test-expressions-1.c422
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-trees-1.c65
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_show_trees.c174
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c24
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_tree_expression_range.c98
-rw-r--r--gcc/testsuite/gcc.dg/plugin/plugin.exp4
-rw-r--r--gcc/toplev.c1
-rw-r--r--gcc/tree-cfg.c9
-rw-r--r--gcc/tree-inline.c5
-rw-r--r--gcc/tree.c60
-rw-r--r--gcc/tree.h33
39 files changed, 1485 insertions, 81 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9b2bd332845..a170b6015fa 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,58 @@
+2015-11-13 David Malcolm <dmalcolm@redhat.com>
+
+ * 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.
+
2015-11-13 Alan Lawrence <alan.lawrence@arm.com>
PR tree-optimization/67682
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 21796f233ab..d3fd5e96442 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1263,6 +1263,7 @@ OBJS = \
fold-const-call.o \
function.o \
fwprop.o \
+ gcc-rich-location.o \
gcse.o \
gcse-common.o \
ggc-common.o \
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 7155aa4a948..00c044a921f 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,8 @@
+2015-11-13 David Malcolm <dmalcolm@redhat.com>
+
+ * gcc-interface/trans.c (Sloc_to_locus): Add line_table param when
+ calling linemap_position_for_line_and_column.
+
2015-11-13 Hristian Kirtchev <kirtchev@adacore.com>
* exp_attr.adb: Minor reformatting.
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index ca66a03e47e..eeb2aaca5cf 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -9650,7 +9650,8 @@ Sloc_to_locus (Source_Ptr Sloc, location_t *locus, bool clear_column)
line = 1;
/* Translate the location. */
- *locus = linemap_position_for_line_and_column (map, line, column);
+ *locus = linemap_position_for_line_and_column (line_table, map,
+ line, column);
return true;
}
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 5611403ce56..e3f81ff6219 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,10 @@
+2015-11-13 David Malcolm <dmalcolm@redhat.com>
+
+ * 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.
+
2015-11-12 James Norris <jnorris@codesourcery.com>
Joseph Myers <joseph@codesourcery.com>
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 6e2ce0a736c..89e978d16de 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -1187,6 +1187,7 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
bool op0_const_self = true, op1_const_self = true, op2_const_self = true;
bool nowarning = TREE_NO_WARNING (expr);
bool unused_p;
+ source_range old_range;
/* This function is not relevant to C++ because C++ folds while
parsing, and may need changes to be correct for C++ when C++
@@ -1202,6 +1203,9 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
|| code == SAVE_EXPR)
return expr;
+ if (IS_EXPR_CODE_CLASS (kind))
+ old_range = EXPR_LOCATION_RANGE (expr);
+
/* Operands of variable-length expressions (function calls) have
already been folded, as have __builtin_* function calls, and such
expressions cannot occur in constant expressions. */
@@ -1626,7 +1630,11 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
TREE_NO_WARNING (ret) = 1;
}
if (ret != expr)
- protected_set_expr_location (ret, loc);
+ {
+ protected_set_expr_location (ret, loc);
+ if (IS_EXPR_CODE_CLASS (kind))
+ set_source_range (ret, old_range.m_start, old_range.m_finish);
+ }
return ret;
}
diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c
index 4da6f313fd3..9ae181f26ed 100644
--- a/gcc/c-family/c-opts.c
+++ b/gcc/c-family/c-opts.c
@@ -245,6 +245,8 @@ c_common_init_options (unsigned int decoded_options_count,
break;
}
}
+
+ global_dc->colorize_source_p = true;
}
/* Handle switch SCODE with argument ARG. VALUE is true, unless no-
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 8824f1845cb..810f2c6c575 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 a636474862d..9a222d8f511 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 ef0f9a2e4e6..ee9c2b5858d 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 82d5ce5f9ff..943d3e58d27 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 04991f7261c..6bc216af889 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 eb4e1fccc44..4db9bbf1c3c 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)
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 56806fb9b3c..52f95a04131 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,7 @@
+2015-11-13 David Malcolm <dmalcolm@redhat.com>
+
+ * error.c (pedwarn_cxx98): Pass line_table to rich_location ctor.
+
2015-11-12 James Norris <jnorris@codesourcery.com>
* parser.c (cp_parser_oacc_declare): Remove unused.
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 361e41af4bd..38548c72fe0 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -3673,7 +3673,7 @@ pedwarn_cxx98 (location_t location, int opt, const char *gmsgid, ...)
diagnostic_info diagnostic;
va_list ap;
bool ret;
- 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/diagnostic.c b/gcc/diagnostic.c
index ee034e77170..b4d3a7d59ce 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -867,7 +867,7 @@ diagnostic_append_note (diagnostic_context *context,
diagnostic_info diagnostic;
va_list ap;
const char *saved_prefix;
- rich_location richloc (location);
+ rich_location richloc (line_table, location);
va_start (ap, gmsgid);
diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_NOTE);
@@ -925,7 +925,7 @@ emit_diagnostic (diagnostic_t kind, location_t location, int opt,
diagnostic_info diagnostic;
va_list ap;
bool ret;
- rich_location richloc (location);
+ rich_location richloc (line_table, location);
va_start (ap, gmsgid);
if (kind == DK_PERMERROR)
@@ -952,7 +952,7 @@ inform (location_t location, 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, DK_NOTE);
@@ -981,7 +981,7 @@ inform_n (location_t location, int n, const char *singular_gmsgid,
{
diagnostic_info diagnostic;
va_list ap;
- rich_location richloc (location);
+ rich_location richloc (line_table, location);
va_start (ap, plural_gmsgid);
diagnostic_set_info_translated (&diagnostic,
@@ -1000,7 +1000,7 @@ warning (int opt, const char *gmsgid, ...)
diagnostic_info diagnostic;
va_list ap;
bool ret;
- rich_location richloc (input_location);
+ rich_location richloc (line_table, input_location);
va_start (ap, gmsgid);
diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_WARNING);
@@ -1021,7 +1021,7 @@ warning_at (location_t location, int opt, const char *gmsgid, ...)
diagnostic_info diagnostic;
va_list ap;
bool ret;
- rich_location richloc (location);
+ rich_location richloc (line_table, location);
va_start (ap, gmsgid);
diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_WARNING);
@@ -1059,7 +1059,7 @@ warning_n (location_t location, int opt, int n, const char *singular_gmsgid,
diagnostic_info diagnostic;
va_list ap;
bool ret;
- rich_location richloc (location);
+ rich_location richloc (line_table, location);
va_start (ap, plural_gmsgid);
diagnostic_set_info_translated (&diagnostic,
@@ -1091,7 +1091,7 @@ pedwarn (location_t location, int opt, const char *gmsgid, ...)
diagnostic_info diagnostic;
va_list ap;
bool ret;
- rich_location richloc (location);
+ rich_location richloc (line_table, location);
va_start (ap, gmsgid);
diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_PEDWARN);
@@ -1114,7 +1114,7 @@ permerror (location_t location, const char *gmsgid, ...)
diagnostic_info diagnostic;
va_list ap;
bool ret;
- rich_location richloc (location);
+ rich_location richloc (line_table, location);
va_start (ap, gmsgid);
diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
@@ -1150,7 +1150,7 @@ error (const char *gmsgid, ...)
{
diagnostic_info diagnostic;
va_list ap;
- rich_location richloc (input_location);
+ rich_location richloc (line_table, input_location);
va_start (ap, gmsgid);
diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_ERROR);
@@ -1166,7 +1166,7 @@ error_n (location_t location, int n, const char *singular_gmsgid,
{
diagnostic_info diagnostic;
va_list ap;
- rich_location richloc (location);
+ rich_location richloc (line_table, location);
va_start (ap, plural_gmsgid);
diagnostic_set_info_translated (&diagnostic,
@@ -1182,7 +1182,7 @@ error_at (location_t loc, const char *gmsgid, ...)
{
diagnostic_info diagnostic;
va_list ap;
- rich_location richloc (loc);
+ rich_location richloc (line_table, loc);
va_start (ap, gmsgid);
diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_ERROR);
@@ -1213,7 +1213,7 @@ sorry (const char *gmsgid, ...)
{
diagnostic_info diagnostic;
va_list ap;
- rich_location richloc (input_location);
+ rich_location richloc (line_table, input_location);
va_start (ap, gmsgid);
diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_SORRY);
@@ -1237,7 +1237,7 @@ fatal_error (location_t loc, const char *gmsgid, ...)
{
diagnostic_info diagnostic;
va_list ap;
- rich_location richloc (loc);
+ rich_location richloc (line_table, loc);
va_start (ap, gmsgid);
diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_FATAL);
@@ -1256,7 +1256,7 @@ internal_error (const char *gmsgid, ...)
{
diagnostic_info diagnostic;
va_list ap;
- rich_location richloc (input_location);
+ rich_location richloc (line_table, input_location);
va_start (ap, gmsgid);
diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_ICE);
@@ -1274,7 +1274,7 @@ internal_error_no_backtrace (const char *gmsgid, ...)
{
diagnostic_info diagnostic;
va_list ap;
- rich_location richloc (input_location);
+ rich_location richloc (line_table, input_location);
va_start (ap, gmsgid);
diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_ICE_NOBT);
@@ -1351,7 +1351,7 @@ real_abort (void)
DEBUG_FUNCTION void
source_range::debug (const char *msg) const
{
- rich_location richloc (m_start);
+ rich_location richloc (line_table, m_start);
richloc.add_range (m_start, m_finish, false);
inform_at_rich_loc (&richloc, "%s", msg);
}
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 4910f077e84..b2c1d9bcb05 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,13 @@
+2015-11-13 David Malcolm <dmalcolm@redhat.com>
+
+ * 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.
+
2015-11-12 Steven G. Kargl <kargl@gcc.gnu.org>
PR fortran/68318
diff --git a/gcc/fortran/error.c b/gcc/fortran/error.c
index 4b3d31ce4ba..b4f70203078 100644
--- a/gcc/fortran/error.c
+++ b/gcc/fortran/error.c
@@ -773,7 +773,7 @@ gfc_warning (int opt, const char *gmsgid, va_list ap)
va_copy (argp, ap);
diagnostic_info diagnostic;
- rich_location rich_loc (UNKNOWN_LOCATION);
+ rich_location rich_loc (line_table, UNKNOWN_LOCATION);
bool fatal_errors = global_dc->fatal_errors;
pretty_printer *pp = global_dc->printer;
output_buffer *tmp_buffer = pp->buffer;
@@ -1120,7 +1120,7 @@ gfc_warning_now_at (location_t loc, int opt, const char *gmsgid, ...)
{
va_list argp;
diagnostic_info diagnostic;
- rich_location rich_loc (loc);
+ rich_location rich_loc (line_table, loc);
bool ret;
va_start (argp, gmsgid);
@@ -1138,7 +1138,7 @@ gfc_warning_now (int opt, const char *gmsgid, ...)
{
va_list argp;
diagnostic_info diagnostic;
- rich_location rich_loc (UNKNOWN_LOCATION);
+ rich_location rich_loc (line_table, UNKNOWN_LOCATION);
bool ret;
va_start (argp, gmsgid);
@@ -1158,7 +1158,7 @@ gfc_error_now (const char *gmsgid, ...)
{
va_list argp;
diagnostic_info diagnostic;
- rich_location rich_loc (UNKNOWN_LOCATION);
+ rich_location rich_loc (line_table, UNKNOWN_LOCATION);
error_buffer.flag = true;
@@ -1176,7 +1176,7 @@ gfc_fatal_error (const char *gmsgid, ...)
{
va_list argp;
diagnostic_info diagnostic;
- rich_location rich_loc (UNKNOWN_LOCATION);
+ rich_location rich_loc (line_table, UNKNOWN_LOCATION);
va_start (argp, gmsgid);
diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc, DK_FATAL);
@@ -1242,7 +1242,7 @@ gfc_error (const char *gmsgid, va_list ap)
}
diagnostic_info diagnostic;
- rich_location richloc (UNKNOWN_LOCATION);
+ rich_location richloc (line_table, UNKNOWN_LOCATION);
bool fatal_errors = global_dc->fatal_errors;
pretty_printer *pp = global_dc->printer;
output_buffer *tmp_buffer = pp->buffer;
@@ -1288,7 +1288,7 @@ gfc_internal_error (const char *gmsgid, ...)
{
va_list argp;
diagnostic_info diagnostic;
- rich_location rich_loc (UNKNOWN_LOCATION);
+ rich_location rich_loc (line_table, UNKNOWN_LOCATION);
va_start (argp, gmsgid);
diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc, DK_ICE);
diff --git a/gcc/gcc-rich-location.c b/gcc/gcc-rich-location.c
new file mode 100644
index 00000000000..b0ec47bc001
--- /dev/null
+++ b/gcc/gcc-rich-location.c
@@ -0,0 +1,86 @@
+/* Implementation of gcc_rich_location class
+ Copyright (C) 2014-2015 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "rtl.h"
+#include "hash-set.h"
+#include "machmode.h"
+#include "vec.h"
+#include "double-int.h"
+#include "input.h"
+#include "alias.h"
+#include "symtab.h"
+#include "wide-int.h"
+#include "inchash.h"
+#include "tree-core.h"
+#include "tree.h"
+#include "diagnostic-core.h"
+#include "gcc-rich-location.h"
+#include "print-tree.h"
+#include "pretty-print.h"
+#include "intl.h"
+#include "cpplib.h"
+#include "diagnostic.h"
+
+/* Extract any source range information from EXPR and write it
+ to *R. */
+
+static bool
+get_range_for_expr (tree expr, location_range *r)
+{
+ if (EXPR_HAS_RANGE (expr))
+ {
+ source_range sr = EXPR_LOCATION_RANGE (expr);
+
+ /* Do we have meaningful data? */
+ if (sr.m_start && sr.m_finish)
+ {
+ r->m_start = expand_location (sr.m_start);
+ r->m_finish = expand_location (sr.m_finish);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* Add a range to the rich_location, covering expression EXPR. */
+
+void
+gcc_rich_location::add_expr (tree expr)
+{
+ gcc_assert (expr);
+
+ location_range r;
+ r.m_show_caret_p = false;
+ if (get_range_for_expr (expr, &r))
+ add_range (&r);
+}
+
+/* If T is an expression, add a range for it to the rich_location. */
+
+void
+gcc_rich_location::maybe_add_expr (tree t)
+{
+ if (EXPR_P (t))
+ add_expr (t);
+}
diff --git a/gcc/gcc-rich-location.h b/gcc/gcc-rich-location.h
new file mode 100644
index 00000000000..2f9291df6f4
--- /dev/null
+++ b/gcc/gcc-rich-location.h
@@ -0,0 +1,47 @@
+/* Declarations relating to class gcc_rich_location
+ Copyright (C) 2014-2015 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_RICH_LOCATION_H
+#define GCC_RICH_LOCATION_H
+
+/* A gcc_rich_location is libcpp's rich_location with additional
+ helper methods for working with gcc's types. */
+class gcc_rich_location : public rich_location
+{
+ public:
+ /* Constructors. */
+
+ /* Constructing from a location. */
+ gcc_rich_location (source_location loc) :
+ rich_location (line_table, loc) {}
+
+ /* Constructing from a source_range. */
+ gcc_rich_location (source_range src_range) :
+ rich_location (src_range) {}
+
+
+ /* Methods for adding ranges via gcc entities. */
+ void
+ add_expr (tree expr);
+
+ void
+ maybe_add_expr (tree t);
+};
+
+#endif /* GCC_RICH_LOCATION_H */
diff --git a/gcc/genmatch.c b/gcc/genmatch.c
index 1eb8c24da7d..9d74ed75a53 100644
--- a/gcc/genmatch.c
+++ b/gcc/genmatch.c
@@ -119,7 +119,7 @@ __attribute__((format (printf, 2, 3)))
#endif
fatal_at (const cpp_token *tk, const char *msg, ...)
{
- rich_location richloc (tk->src_loc);
+ rich_location richloc (line_table, tk->src_loc);
va_list ap;
va_start (ap, msg);
error_cb (NULL, CPP_DL_FATAL, 0, &richloc, msg, &ap);
@@ -132,7 +132,7 @@ __attribute__((format (printf, 2, 3)))
#endif
fatal_at (source_location loc, const char *msg, ...)
{
- rich_location richloc (loc);
+ rich_location richloc (line_table, loc);
va_list ap;
va_start (ap, msg);
error_cb (NULL, CPP_DL_FATAL, 0, &richloc, msg, &ap);
@@ -145,7 +145,7 @@ __attribute__((format (printf, 2, 3)))
#endif
warning_at (const cpp_token *tk, const char *msg, ...)
{
- rich_location richloc (tk->src_loc);
+ rich_location richloc (line_table, tk->src_loc);
va_list ap;
va_start (ap, msg);
error_cb (NULL, CPP_DL_WARNING, 0, &richloc, msg, &ap);
@@ -158,7 +158,7 @@ __attribute__((format (printf, 2, 3)))
#endif
warning_at (source_location loc, const char *msg, ...)
{
- rich_location richloc (loc);
+ rich_location richloc (line_table, loc);
va_list ap;
va_start (ap, msg);
error_cb (NULL, CPP_DL_WARNING, 0, &richloc, msg, &ap);
diff --git a/gcc/gimple.h b/gcc/gimple.h
index e45162d24e0..6486dff03b7 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -1740,11 +1740,7 @@ gimple_block (const gimple *g)
static inline void
gimple_set_block (gimple *g, tree block)
{
- if (block)
- g->location =
- COMBINE_LOCATION_DATA (line_table, g->location, block);
- else
- g->location = LOCATION_LOCUS (g->location);
+ g->location = set_block (g->location, block);
}
diff --git a/gcc/input.c b/gcc/input.c
index 0f6d448b546..ce84f100371 100644
--- a/gcc/input.c
+++ b/gcc/input.c
@@ -887,6 +887,10 @@ dump_line_table_statistics (void)
STAT_LABEL (s.adhoc_table_size));
fprintf (stderr, "Ad-hoc table entries used: %5ld\n",
s.adhoc_table_entries_used);
+ fprintf (stderr, "optimized_ranges: %i\n",
+ line_table->num_optimized_ranges);
+ fprintf (stderr, "unoptimized_ranges: %i\n",
+ line_table->num_unoptimized_ranges);
fprintf (stderr, "\n");
}
@@ -917,13 +921,14 @@ write_digit (FILE *stream, int digit)
static void
write_digit_row (FILE *stream, int indent,
+ const line_map_ordinary *map,
source_location loc, int max_col, int divisor)
{
fprintf (stream, "%*c", indent, ' ');
fprintf (stream, "|");
for (int column = 1; column < max_col; column++)
{
- source_location column_loc = loc + column;
+ source_location column_loc = loc + (column << map->m_range_bits);
write_digit (stream, column_loc / divisor);
}
fprintf (stream, "\n");
@@ -977,14 +982,20 @@ dump_location_info (FILE *stream)
fprintf (stream, " file: %s\n", ORDINARY_MAP_FILE_NAME (map));
fprintf (stream, " starting at line: %i\n",
ORDINARY_MAP_STARTING_LINE_NUMBER (map));
+ fprintf (stream, " column and range bits: %i\n",
+ map->m_column_and_range_bits);
fprintf (stream, " column bits: %i\n",
- ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map));
+ map->m_column_and_range_bits - map->m_range_bits);
+ fprintf (stream, " range bits: %i\n",
+ map->m_range_bits);
/* Render the span of source lines that this "map" covers. */
for (source_location loc = MAP_START_LOCATION (map);
loc < end_location;
- loc++)
+ loc += (1 << map->m_range_bits) )
{
+ gcc_assert (pure_location_p (line_table, loc) );
+
expanded_location exploc
= linemap_expand_location (line_table, map, loc);
@@ -1008,8 +1019,7 @@ dump_location_info (FILE *stream)
Render the locations *within* the line, by underlining
it, showing the source_location numeric values
at each column. */
- int max_col
- = (1 << ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map)) - 1;
+ int max_col = (1 << map->m_column_and_range_bits) - 1;
if (max_col > line_size)
max_col = line_size + 1;
@@ -1017,17 +1027,17 @@ dump_location_info (FILE *stream)
/* Thousands. */
if (end_location > 999)
- write_digit_row (stream, indent, loc, max_col, 1000);
+ write_digit_row (stream, indent, map, loc, max_col, 1000);
/* Hundreds. */
if (end_location > 99)
- write_digit_row (stream, indent, loc, max_col, 100);
+ write_digit_row (stream, indent, map, loc, max_col, 100);
/* Tens. */
- write_digit_row (stream, indent, loc, max_col, 10);
+ write_digit_row (stream, indent, map, loc, max_col, 10);
/* Units. */
- write_digit_row (stream, indent, loc, max_col, 1);
+ write_digit_row (stream, indent, map, loc, max_col, 1);
}
}
fprintf (stream, "\n");
diff --git a/gcc/print-tree.c b/gcc/print-tree.c
index 1b584b87ea0..cb0f1fd38f4 100644
--- a/gcc/print-tree.c
+++ b/gcc/print-tree.c
@@ -938,6 +938,27 @@ print_node (FILE *file, const char *prefix, tree node, int indent)
expanded_location xloc = expand_location (EXPR_LOCATION (node));
indent_to (file, indent+4);
fprintf (file, "%s:%d:%d", xloc.file, xloc.line, xloc.column);
+
+ /* Print the range, if any */
+ source_range r = EXPR_LOCATION_RANGE (node);
+ if (r.m_start)
+ {
+ xloc = expand_location (r.m_start);
+ fprintf (file, " start: %s:%d:%d", xloc.file, xloc.line, xloc.column);
+ }
+ else
+ {
+ fprintf (file, " start: unknown");
+ }
+ if (r.m_finish)
+ {
+ xloc = expand_location (r.m_finish);
+ fprintf (file, " finish: %s:%d:%d", xloc.file, xloc.line, xloc.column);
+ }
+ else
+ {
+ fprintf (file, " finish: unknown");
+ }
}
fprintf (file, ">");
diff --git a/gcc/rtl-error.c b/gcc/rtl-error.c
index 96da2bd275d..088bb8a8962 100644
--- a/gcc/rtl-error.c
+++ b/gcc/rtl-error.c
@@ -67,7 +67,7 @@ diagnostic_for_asm (const rtx_insn *insn, const char *msg, va_list *args_ptr,
diagnostic_t kind)
{
diagnostic_info diagnostic;
- rich_location richloc (location_for_asm (insn));
+ rich_location richloc (line_table, location_for_asm (insn));
diagnostic_set_info (&diagnostic, msg, args_ptr,
&richloc, kind);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ed4d7cb8aee..3124504a042 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,22 @@
+2015-11-13 David Malcolm <dmalcolm@redhat.com>
+
+ * 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.
+
2015-11-13 Alan Lawrence <alan.lawrence@arm.com>
PR tree-optimization/67682
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 00000000000..ac969e30d94
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/diagnostic-token-ranges.c
@@ -0,0 +1,120 @@
+/* { 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 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 "" } */
+}
+
+/* Various examples of bad type decls. */
+
+int float bogus; /* { dg-error "two or more data types in declaration specifiers" } */
+/* { dg-begin-multiline-output "" }
+ int float bogus;
+ ^~~~~
+ { dg-end-multiline-output "" } */
+
+long long long bogus2; /* { dg-error "'long long long' is too long for GCC" } */
+/* { dg-begin-multiline-output "" }
+ long long long bogus2;
+ ^~~~
+ { dg-end-multiline-output "" } */
+
+long short bogus3; /* { dg-error "both 'long' and 'short' in declaration specifiers" } */
+/* { dg-begin-multiline-output "" }
+ long short bogus3;
+ ^~~~~
+ { dg-end-multiline-output "" } */
+
+signed unsigned bogus4; /* { dg-error "both 'signed' and 'unsigned' in declaration specifiers" } */
+/* { dg-begin-multiline-output "" }
+ signed unsigned bogus4;
+ ^~~~~~~~
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/diagnostic-tree-expr-ranges-2.c b/gcc/testsuite/gcc.dg/diagnostic-tree-expr-ranges-2.c
new file mode 100644
index 00000000000..302e233a04a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/diagnostic-tree-expr-ranges-2.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized -fdiagnostics-show-caret" } */
+
+int test_uninit_1 (void)
+{
+ int result;
+ return result; /* { dg-warning "uninitialized" } */
+/* { dg-begin-multiline-output "" }
+ return result;
+ ^~~~~~
+ { dg-end-multiline-output "" } */
+}
+
+int test_uninit_2 (void)
+{
+ int result;
+ result += 3; /* { dg-warning "uninitialized" } */
+/* { dg-begin-multiline-output "" }
+ result += 3;
+ ~~~~~~~^~~~
+ { dg-end-multiline-output "" } */
+ return result;
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-expressions-1.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-expressions-1.c
new file mode 100644
index 00000000000..5485aafec01
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-expressions-1.c
@@ -0,0 +1,422 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdiagnostics-show-caret" } */
+
+/* This is a collection of unittests to verify that we're correctly
+ capturing the source code ranges of various kinds of expression.
+
+ It uses the various "diagnostic_test_*_expression_range_plugin"
+ plugins which handles "__emit_expression_range" by generating a warning
+ at the given source range of the input argument. Each of the
+ different plugins do this at a different phase of the internal
+ representation (tree, gimple, etc), so we can verify that the
+ source code range information is valid at each phase.
+
+ We want to accept an expression of any type. To do this in C, we
+ use variadic arguments, but C requires at least one argument before
+ the ellipsis, so we have a dummy one. */
+
+extern void __emit_expression_range (int dummy, ...);
+
+int global;
+
+void test_parentheses (int a, int b)
+{
+ __emit_expression_range (0, (a + b) ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, (a + b) );
+ ~~~^~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, (a + b) * (a - b) ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, (a + b) * (a - b) );
+ ~~~~~~~~^~~~~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, !(a && b) ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, !(a && b) );
+ ^~~~~~~~~
+ { dg-end-multiline-output "" } */
+}
+
+/* Postfix expressions. ************************************************/
+
+void test_array_reference (int *arr)
+{
+ __emit_expression_range (0, arr[100] ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, arr[100] );
+ ~~~^~~~~
+ { dg-end-multiline-output "" } */
+}
+
+int test_function_call (int p, int q, int r)
+{
+ __emit_expression_range (0, test_function_call (p, q, r) ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, test_function_call (p, q, r) );
+ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ { dg-end-multiline-output "" } */
+ return 0;
+}
+
+struct test_struct
+{
+ int field;
+};
+
+int test_structure_references (struct test_struct *ptr)
+{
+ struct test_struct local;
+ local.field = 42;
+
+ __emit_expression_range (0, local.field ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, local.field );
+ ~~~~~^~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, ptr->field ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, ptr->field );
+ ~~~^~~~~~~
+ { dg-end-multiline-output "" } */
+}
+
+int test_postfix_incdec (int i)
+{
+ __emit_expression_range (0, i++ ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, i++ );
+ ~^~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, i-- ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, i-- );
+ ~^~
+ { dg-end-multiline-output "" } */
+}
+
+/* Unary operators. ****************************************************/
+
+int test_prefix_incdec (int i)
+{
+ __emit_expression_range (0, ++i ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, ++i );
+ ^~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, --i ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, --i );
+ ^~~
+ { dg-end-multiline-output "" } */
+}
+
+void test_address_operator (void)
+{
+ __emit_expression_range (0, &global ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, &global );
+ ^~~~~~~
+ { dg-end-multiline-output "" } */
+}
+
+void test_indirection (int *ptr)
+{
+ __emit_expression_range (0, *ptr ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, *ptr );
+ ^~~~
+ { dg-end-multiline-output "" } */
+}
+
+void test_unary_minus (int i)
+{
+ __emit_expression_range (0, -i ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, -i );
+ ^~
+ { dg-end-multiline-output "" } */
+}
+
+void test_ones_complement (int i)
+{
+ __emit_expression_range (0, ~i ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, ~i );
+ ^~
+ { dg-end-multiline-output "" } */
+}
+
+void test_logical_negation (int flag)
+{
+ __emit_expression_range (0, !flag ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, !flag );
+ ^~~~~
+ { dg-end-multiline-output "" } */
+}
+
+/* Casts. ****************************************************/
+
+void test_cast (void *ptr)
+{
+ __emit_expression_range (0, (int *)ptr ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, (int *)ptr );
+ ^~~~~~~~~~
+ { dg-end-multiline-output "" } */
+
+}
+
+/* Binary operators. *******************************************/
+
+void test_multiplicative_operators (int lhs, int rhs)
+{
+ __emit_expression_range (0, lhs * rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs * rhs );
+ ~~~~^~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, lhs / rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs / rhs );
+ ~~~~^~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, lhs % rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs % rhs );
+ ~~~~^~~~~
+ { dg-end-multiline-output "" } */
+}
+
+void test_additive_operators (int lhs, int rhs)
+{
+ __emit_expression_range (0, lhs + rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs + rhs );
+ ~~~~^~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, lhs - rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs - rhs );
+ ~~~~^~~~~
+ { dg-end-multiline-output "" } */
+}
+
+void test_shift_operators (int lhs, int rhs)
+{
+ __emit_expression_range (0, lhs << rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs << rhs );
+ ~~~~^~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, lhs >> rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs >> rhs );
+ ~~~~^~~~~~
+ { dg-end-multiline-output "" } */
+}
+
+void test_relational_operators (int lhs, int rhs)
+{
+ __emit_expression_range (0, lhs < rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs < rhs );
+ ~~~~^~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, lhs > rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs > rhs );
+ ~~~~^~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, lhs <= rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs <= rhs );
+ ~~~~^~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, lhs >= rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs >= rhs );
+ ~~~~^~~~~~
+ { dg-end-multiline-output "" } */
+}
+
+void test_equality_operators (int lhs, int rhs)
+{
+ __emit_expression_range (0, lhs == rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs == rhs );
+ ~~~~^~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, lhs != rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs != rhs );
+ ~~~~^~~~~~
+ { dg-end-multiline-output "" } */
+}
+
+void test_bitwise_binary_operators (int lhs, int rhs)
+{
+ __emit_expression_range (0, lhs & rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs & rhs );
+ ~~~~^~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, lhs ^ rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs ^ rhs );
+ ~~~~^~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, lhs | rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs | rhs );
+ ~~~~^~~~~
+ { dg-end-multiline-output "" } */
+}
+
+void test_logical_operators (int lhs, int rhs)
+{
+ __emit_expression_range (0, lhs && rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs && rhs );
+ ~~~~^~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, lhs || rhs ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, lhs || rhs );
+ ~~~~^~~~~~
+ { dg-end-multiline-output "" } */
+}
+
+/* Conditional operator. *******************************************/
+
+void test_conditional_operators (int flag, int on_true, int on_false)
+{
+ __emit_expression_range (0, flag ? on_true : on_false ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, flag ? on_true : on_false );
+ ~~~~~~~~~~~~~~~^~~~~~~~~~
+ { dg-end-multiline-output "" } */
+}
+
+/* Assignment expressions. *******************************************/
+
+void test_assignment_expressions (int dest, int other)
+{
+ __emit_expression_range (0, dest = other ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, dest = other );
+ ~~~~~^~~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, dest *= other ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, dest *= other );
+ ~~~~~^~~~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, dest /= other ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, dest /= other );
+ ~~~~~^~~~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, dest %= other ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, dest %= other );
+ ~~~~~^~~~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, dest += other ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, dest += other );
+ ~~~~~^~~~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, dest -= other ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, dest -= other );
+ ~~~~~^~~~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, dest <<= other ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, dest <<= other );
+ ~~~~~^~~~~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, dest >>= other ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, dest >>= other );
+ ~~~~~^~~~~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, dest &= other ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, dest &= other );
+ ~~~~~^~~~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, dest ^= other ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, dest ^= other );
+ ~~~~~^~~~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0, dest |= other ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, dest |= other );
+ ~~~~~^~~~~~~~
+ { dg-end-multiline-output "" } */
+}
+
+/* Comma operator. *******************************************/
+
+void test_comma_operator (int a, int b)
+{
+ __emit_expression_range (0, (a++, a + b) ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, (a++, a + b) );
+ ~~~~^~~~~~~~
+ { dg-end-multiline-output "" } */
+}
+
+/* Examples of non-trivial expressions. ****************************/
+
+extern double sqrt (double x);
+
+void test_quadratic (double a, double b, double c)
+{
+ __emit_expression_range (0, b * b - 4 * a * c ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ __emit_expression_range (0, b * b - 4 * a * c );
+ ~~~~~~^~~~~~~~~~~
+ { dg-end-multiline-output "" } */
+
+ __emit_expression_range (0,
+ (-b + sqrt (b * b - 4 * a * c))
+ / (2 * a)); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+ (-b + sqrt (b * b - 4 * a * c))
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ / (2 * a));
+ ^~~~~~~~~
+ { dg-end-multiline-output "" } */
+
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-trees-1.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-trees-1.c
new file mode 100644
index 00000000000..7473a07961f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-trees-1.c
@@ -0,0 +1,65 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdiagnostics-show-caret" } */
+
+/* This is an example file for use with
+ diagnostic_plugin_show_trees.c.
+
+ The plugin handles "__show_tree" by recursively dumping
+ the internal structure of the second input argument.
+
+ We want to accept an expression of any type. To do this in C, we
+ use variadic arguments, but C requires at least one argument before
+ the ellipsis, so we have a dummy one. */
+
+extern void __show_tree (int dummy, ...);
+
+extern double sqrt (double x);
+
+void test_quadratic (double a, double b, double c)
+{
+ __show_tree (0,
+ (-b + sqrt (b * b - 4 * a * c))
+ / (2 * a));
+
+/* { dg-begin-multiline-output "" }
+ (-b + sqrt (b * b - 4 * a * c))
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ / (2 * a));
+ ^~~~~~~~~
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+ (-b + sqrt (b * b - 4 * a * c))
+ ~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+ (-b + sqrt (b * b - 4 * a * c))
+ ^~~~~~~~~~~~~~~~~~~~~~~~
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+ (-b + sqrt (b * b - 4 * a * c))
+ ~~~~~~^~~~~~~~~~~
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+ (-b + sqrt (b * b - 4 * a * c))
+ ~~^~~
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+ (-b + sqrt (b * b - 4 * a * c))
+ ~~~~~~^~~
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+ (-b + sqrt (b * b - 4 * a * c))
+ ~~^~~
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+ / (2 * a));
+ ~~~^~~~
+ { dg-end-multiline-output "" } */
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_show_trees.c b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_show_trees.c
new file mode 100644
index 00000000000..5a911c17a4e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_show_trees.c
@@ -0,0 +1,174 @@
+/* This plugin recursively dumps the source-code location ranges of
+ expressions, at the pre-gimplification tree stage. */
+/* { dg-options "-O" } */
+
+#include "gcc-plugin.h"
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "stringpool.h"
+#include "toplev.h"
+#include "basic-block.h"
+#include "hash-table.h"
+#include "vec.h"
+#include "ggc.h"
+#include "basic-block.h"
+#include "tree-ssa-alias.h"
+#include "internal-fn.h"
+#include "gimple-fold.h"
+#include "tree-eh.h"
+#include "gimple-expr.h"
+#include "is-a.h"
+#include "gimple.h"
+#include "gimple-iterator.h"
+#include "tree.h"
+#include "tree-pass.h"
+#include "intl.h"
+#include "plugin-version.h"
+#include "diagnostic.h"
+#include "context.h"
+#include "gcc-rich-location.h"
+#include "print-tree.h"
+
+/*
+ Hack: fails with linker error:
+./diagnostic_plugin_show_trees.so: undefined symbol: _ZN17gcc_rich_location8add_exprEP9tree_node
+ since nothing in the tree is using gcc_rich_location::add_expr yet.
+
+ I've tried various workarounds (adding DEBUG_FUNCTION to the
+ method, taking its address), but can't seem to fix it that way.
+ So as a nasty workaround, the following material is copied&pasted
+ from gcc-rich-location.c: */
+
+static bool
+get_range_for_expr (tree expr, location_range *r)
+{
+ if (EXPR_HAS_RANGE (expr))
+ {
+ source_range sr = EXPR_LOCATION_RANGE (expr);
+
+ /* Do we have meaningful data? */
+ if (sr.m_start && sr.m_finish)
+ {
+ r->m_start = expand_location (sr.m_start);
+ r->m_finish = expand_location (sr.m_finish);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* Add a range to the rich_location, covering expression EXPR. */
+
+void
+gcc_rich_location::add_expr (tree expr)
+{
+ gcc_assert (expr);
+
+ location_range r;
+ r.m_show_caret_p = false;
+ if (get_range_for_expr (expr, &r))
+ add_range (&r);
+}
+
+/* FIXME: end of material taken from gcc-rich-location.c */
+
+int plugin_is_GPL_compatible;
+
+static void
+show_tree (tree node)
+{
+ if (!CAN_HAVE_RANGE_P (node))
+ return;
+
+ gcc_rich_location richloc (EXPR_LOCATION (node));
+ richloc.add_expr (node);
+
+ if (richloc.get_num_locations () < 2)
+ {
+ error_at_rich_loc (&richloc, "range not found");
+ return;
+ }
+
+ enum tree_code code = TREE_CODE (node);
+
+ location_range *range = richloc.get_range (1);
+ inform_at_rich_loc (&richloc,
+ "%s at range %i:%i-%i:%i",
+ get_tree_code_name (code),
+ range->m_start.line,
+ range->m_start.column,
+ range->m_finish.line,
+ range->m_finish.column);
+
+ /* Recurse. */
+ int min_idx = 0;
+ int max_idx = TREE_OPERAND_LENGTH (node);
+ switch (code)
+ {
+ case CALL_EXPR:
+ min_idx = 3;
+ break;
+
+ default:
+ break;
+ }
+
+ for (int i = min_idx; i < max_idx; i++)
+ show_tree (TREE_OPERAND (node, i));
+}
+
+tree
+cb_walk_tree_fn (tree * tp, int * walk_subtrees,
+ void * data ATTRIBUTE_UNUSED)
+{
+ if (TREE_CODE (*tp) != CALL_EXPR)
+ return NULL_TREE;
+
+ tree call_expr = *tp;
+ tree fn = CALL_EXPR_FN (call_expr);
+ if (TREE_CODE (fn) != ADDR_EXPR)
+ return NULL_TREE;
+ fn = TREE_OPERAND (fn, 0);
+ if (TREE_CODE (fn) != FUNCTION_DECL)
+ return NULL_TREE;
+ if (strcmp (IDENTIFIER_POINTER (DECL_NAME (fn)), "__show_tree"))
+ return NULL_TREE;
+
+ /* Get arg 1; print it! */
+ tree arg = CALL_EXPR_ARG (call_expr, 1);
+
+ show_tree (arg);
+
+ return NULL_TREE;
+}
+
+static void
+callback (void *gcc_data, void *user_data)
+{
+ tree fndecl = (tree)gcc_data;
+ walk_tree (&DECL_SAVED_TREE (fndecl), cb_walk_tree_fn, NULL, NULL);
+}
+
+int
+plugin_init (struct plugin_name_args *plugin_info,
+ struct plugin_gcc_version *version)
+{
+ struct register_pass_info pass_info;
+ const char *plugin_name = plugin_info->base_name;
+ int argc = plugin_info->argc;
+ struct plugin_argument *argv = plugin_info->argv;
+
+ if (!plugin_default_version_check (version, &gcc_version))
+ return 1;
+
+ register_callback (plugin_name,
+ PLUGIN_PRE_GENERICIZE,
+ callback,
+ NULL);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c
index 8f5724ec27d..158c6124a99 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c
@@ -109,7 +109,8 @@ get_loc (unsigned int line_num, unsigned int col_num)
/* Convert from 0-based column numbers to 1-based column numbers. */
source_location loc
- = linemap_position_for_line_and_column (line_map,
+ = linemap_position_for_line_and_column (line_table,
+ line_map,
line_num, col_num + 1);
return loc;
@@ -163,7 +164,7 @@ test_show_locus (function *fun)
if (0 == strcmp (fnname, "test_simple"))
{
const int line = fnstart_line + 2;
- rich_location richloc (get_loc (line, 15));
+ rich_location richloc (line_table, get_loc (line, 15));
richloc.add_range (get_loc (line, 10), get_loc (line, 14), false);
richloc.add_range (get_loc (line, 16), get_loc (line, 16), false);
warning_at_rich_loc (&richloc, 0, "test");
@@ -172,7 +173,7 @@ test_show_locus (function *fun)
if (0 == strcmp (fnname, "test_simple_2"))
{
const int line = fnstart_line + 2;
- rich_location richloc (get_loc (line, 24));
+ rich_location richloc (line_table, get_loc (line, 24));
richloc.add_range (get_loc (line, 6),
get_loc (line, 22), false);
richloc.add_range (get_loc (line, 26),
@@ -183,7 +184,7 @@ test_show_locus (function *fun)
if (0 == strcmp (fnname, "test_multiline"))
{
const int line = fnstart_line + 2;
- rich_location richloc (get_loc (line + 1, 7));
+ rich_location richloc (line_table, get_loc (line + 1, 7));
richloc.add_range (get_loc (line, 7),
get_loc (line, 23), false);
richloc.add_range (get_loc (line + 1, 9),
@@ -194,7 +195,7 @@ test_show_locus (function *fun)
if (0 == strcmp (fnname, "test_many_lines"))
{
const int line = fnstart_line + 2;
- rich_location richloc (get_loc (line + 5, 7));
+ rich_location richloc (line_table, get_loc (line + 5, 7));
richloc.add_range (get_loc (line, 7),
get_loc (line + 4, 65), false);
richloc.add_range (get_loc (line + 5, 9),
@@ -223,7 +224,7 @@ test_show_locus (function *fun)
source_range src_range;
src_range.m_start = get_loc (line, 12);
src_range.m_finish = get_loc (line, 20);
- rich_location richloc (caret);
+ rich_location richloc (line_table, caret);
richloc.set_range (0, src_range, true, false);
warning_at_rich_loc (&richloc, 0, "test");
}
@@ -237,7 +238,7 @@ test_show_locus (function *fun)
source_range src_range;
src_range.m_start = get_loc (line, 90);
src_range.m_finish = get_loc (line, 98);
- rich_location richloc (caret);
+ rich_location richloc (line_table, caret);
richloc.set_range (0, src_range, true, false);
warning_at_rich_loc (&richloc, 0, "test");
}
@@ -248,7 +249,7 @@ test_show_locus (function *fun)
const int line = fnstart_line + 2;
location_t caret_a = get_loc (line, 7);
location_t caret_b = get_loc (line, 11);
- rich_location richloc (caret_a);
+ rich_location richloc (line_table, caret_a);
richloc.add_range (caret_b, caret_b, true);
global_dc->caret_chars[0] = 'A';
global_dc->caret_chars[1] = 'B';
@@ -269,7 +270,7 @@ test_show_locus (function *fun)
const int line = fnstart_line + 3;
location_t caret_a = get_loc (line, 5);
location_t caret_b = get_loc (line - 1, 19);
- rich_location richloc (caret_a);
+ rich_location richloc (line_table, caret_a);
richloc.add_range (caret_b, caret_b, true);
global_dc->caret_chars[0] = '1';
global_dc->caret_chars[1] = '2';
@@ -304,11 +305,6 @@ plugin_init (struct plugin_name_args *plugin_info,
if (!plugin_default_version_check (version, &gcc_version))
return 1;
- /* For now, tell the dc to expect ranges and thus to colorize the source
- lines, not just the carets/underlines. This will be redundant
- once the C frontend generates ranges. */
- global_dc->colorize_source_p = true;
-
for (int i = 0; i < argc; i++)
{
if (0 == strcmp (argv[i].key, "color"))
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_tree_expression_range.c b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_tree_expression_range.c
new file mode 100644
index 00000000000..89cc95acd99
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_tree_expression_range.c
@@ -0,0 +1,98 @@
+/* This plugin verifies the source-code location ranges of
+ expressions, at the pre-gimplification tree stage. */
+/* { dg-options "-O" } */
+
+#include "gcc-plugin.h"
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "stringpool.h"
+#include "toplev.h"
+#include "basic-block.h"
+#include "hash-table.h"
+#include "vec.h"
+#include "ggc.h"
+#include "basic-block.h"
+#include "tree-ssa-alias.h"
+#include "internal-fn.h"
+#include "gimple-fold.h"
+#include "tree-eh.h"
+#include "gimple-expr.h"
+#include "is-a.h"
+#include "gimple.h"
+#include "gimple-iterator.h"
+#include "tree.h"
+#include "tree-pass.h"
+#include "intl.h"
+#include "plugin-version.h"
+#include "diagnostic.h"
+#include "context.h"
+#include "print-tree.h"
+
+int plugin_is_GPL_compatible;
+
+static void
+emit_warning (location_t loc)
+{
+ source_range src_range = get_range_from_loc (line_table, loc);
+ warning_at (loc, 0,
+ "tree range %i:%i-%i:%i",
+ LOCATION_LINE (src_range.m_start),
+ LOCATION_COLUMN (src_range.m_start),
+ LOCATION_LINE (src_range.m_finish),
+ LOCATION_COLUMN (src_range.m_finish));
+}
+
+tree
+cb_walk_tree_fn (tree * tp, int * walk_subtrees,
+ void * data ATTRIBUTE_UNUSED)
+{
+ if (TREE_CODE (*tp) != CALL_EXPR)
+ return NULL_TREE;
+
+ tree call_expr = *tp;
+ tree fn = CALL_EXPR_FN (call_expr);
+ if (TREE_CODE (fn) != ADDR_EXPR)
+ return NULL_TREE;
+ fn = TREE_OPERAND (fn, 0);
+ if (TREE_CODE (fn) != FUNCTION_DECL)
+ return NULL_TREE;
+ if (strcmp (IDENTIFIER_POINTER (DECL_NAME (fn)), "__emit_expression_range"))
+ return NULL_TREE;
+
+ /* Get arg 1; print it! */
+ tree arg = CALL_EXPR_ARG (call_expr, 1);
+
+ emit_warning (EXPR_LOCATION (arg));
+
+ return NULL_TREE;
+}
+
+static void
+callback (void *gcc_data, void *user_data)
+{
+ tree fndecl = (tree)gcc_data;
+ walk_tree (&DECL_SAVED_TREE (fndecl), cb_walk_tree_fn, NULL, NULL);
+}
+
+int
+plugin_init (struct plugin_name_args *plugin_info,
+ struct plugin_gcc_version *version)
+{
+ struct register_pass_info pass_info;
+ const char *plugin_name = plugin_info->base_name;
+ int argc = plugin_info->argc;
+ struct plugin_argument *argv = plugin_info->argv;
+
+ if (!plugin_default_version_check (version, &gcc_version))
+ return 1;
+
+ register_callback (plugin_name,
+ PLUGIN_PRE_GENERICIZE,
+ callback,
+ NULL);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/plugin.exp b/gcc/testsuite/gcc.dg/plugin/plugin.exp
index ce0a18d0a98..06080cce8d2 100644
--- a/gcc/testsuite/gcc.dg/plugin/plugin.exp
+++ b/gcc/testsuite/gcc.dg/plugin/plugin.exp
@@ -66,6 +66,10 @@ set plugin_test_list [list \
{ diagnostic_plugin_test_show_locus.c \
diagnostic-test-show-locus-bw.c \
diagnostic-test-show-locus-color.c } \
+ { diagnostic_plugin_test_tree_expression_range.c \
+ diagnostic-test-expressions-1.c } \
+ { diagnostic_plugin_show_trees.c \
+ diagnostic-test-show-trees-1.c } \
{ levenshtein_plugin.c levenshtein-test-1.c } \
]
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 140e36ff237..588d89dce89 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -1130,6 +1130,7 @@ general_init (const char *argv0, bool init_signals)
linemap_init (line_table, BUILTINS_LOCATION);
line_table->reallocator = realloc_for_line_map;
line_table->round_alloc_size = ggc_round_alloc_size;
+ line_table->default_range_bits = 5;
init_ttree ();
/* Initialize register usage now so switches may override. */
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 5d98eec9f18..0c624aa3f3e 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -6719,10 +6719,7 @@ move_block_to_fn (struct function *dest_cfun, basic_block bb,
continue;
if (d->orig_block == NULL_TREE || block == d->orig_block)
{
- if (d->new_block == NULL_TREE)
- locus = LOCATION_LOCUS (locus);
- else
- locus = COMBINE_LOCATION_DATA (line_table, locus, d->new_block);
+ locus = set_block (locus, d->new_block);
gimple_phi_arg_set_location (phi, i, locus);
}
}
@@ -6782,9 +6779,7 @@ move_block_to_fn (struct function *dest_cfun, basic_block bb,
tree block = LOCATION_BLOCK (e->goto_locus);
if (d->orig_block == NULL_TREE
|| block == d->orig_block)
- e->goto_locus = d->new_block ?
- COMBINE_LOCATION_DATA (line_table, e->goto_locus, d->new_block) :
- LOCATION_LOCUS (e->goto_locus);
+ e->goto_locus = set_block (e->goto_locus, d->new_block);
}
}
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 17d97a8712e..205c869b88e 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -2348,10 +2348,7 @@ copy_phis_for_bb (basic_block bb, copy_body_data *id)
tree *n;
n = id->decl_map->get (LOCATION_BLOCK (locus));
gcc_assert (n);
- if (*n)
- locus = COMBINE_LOCATION_DATA (line_table, locus, *n);
- else
- locus = LOCATION_LOCUS (locus);
+ locus = set_block (locus, *n);
}
else
locus = LOCATION_LOCUS (locus);
diff --git a/gcc/tree.c b/gcc/tree.c
index 50e1db019d3..1d770c36a7b 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -11789,10 +11789,7 @@ tree_set_block (tree t, tree b)
if (IS_EXPR_CODE_CLASS (c))
{
- if (b)
- t->exp.locus = COMBINE_LOCATION_DATA (line_table, t->exp.locus, b);
- else
- t->exp.locus = LOCATION_LOCUS (t->exp.locus);
+ t->exp.locus = set_block (t->exp.locus, b);
}
else
gcc_unreachable ();
@@ -13813,5 +13810,60 @@ nonnull_arg_p (const_tree arg)
return false;
}
+/* Given location LOC, strip away any packed range information
+ or ad-hoc information. */
+
+static location_t
+get_pure_location (location_t loc)
+{
+ if (IS_ADHOC_LOC (loc))
+ loc
+ = line_table->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus;
+
+ if (loc >= LINEMAPS_MACRO_LOWEST_LOCATION (line_table))
+ return loc;
+
+ if (loc < RESERVED_LOCATION_COUNT)
+ return loc;
+
+ const line_map *map = linemap_lookup (line_table, loc);
+ const line_map_ordinary *ordmap = linemap_check_ordinary (map);
+
+ return loc & ~((1 << ordmap->m_range_bits) - 1);
+}
+
+/* Combine LOC and BLOCK to a combined adhoc loc, retaining any range
+ information. */
+
+location_t
+set_block (location_t loc, tree block)
+{
+ location_t pure_loc = get_pure_location (loc);
+ source_range src_range = get_range_from_loc (line_table, loc);
+ return COMBINE_LOCATION_DATA (line_table, pure_loc, src_range, block);
+}
+
+void
+set_source_range (tree expr, location_t start, location_t finish)
+{
+ source_range src_range;
+ src_range.m_start = start;
+ src_range.m_finish = finish;
+ set_source_range (expr, src_range);
+}
+
+void
+set_source_range (tree expr, source_range src_range)
+{
+ if (!EXPR_P (expr))
+ return;
+
+ location_t pure_loc = get_pure_location (EXPR_LOCATION (expr));
+ location_t adhoc = COMBINE_LOCATION_DATA (line_table,
+ pure_loc,
+ src_range,
+ NULL);
+ SET_EXPR_LOCATION (expr, adhoc);
+}
#include "gt-tree.h"
diff --git a/gcc/tree.h b/gcc/tree.h
index 1bb59f2ac8c..0b9c3b915dc 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1096,10 +1096,25 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
#define EXPR_FILENAME(NODE) LOCATION_FILE (EXPR_CHECK ((NODE))->exp.locus)
#define EXPR_LINENO(NODE) LOCATION_LINE (EXPR_CHECK (NODE)->exp.locus)
+#define CAN_HAVE_RANGE_P(NODE) (CAN_HAVE_LOCATION_P (NODE))
+#define EXPR_LOCATION_RANGE(NODE) (get_expr_source_range (EXPR_CHECK ((NODE))))
+
+#define EXPR_HAS_RANGE(NODE) \
+ (CAN_HAVE_RANGE_P (NODE) \
+ ? EXPR_LOCATION_RANGE (NODE).m_start != UNKNOWN_LOCATION \
+ : false)
+
/* True if a tree is an expression or statement that can have a
location. */
#define CAN_HAVE_LOCATION_P(NODE) ((NODE) && EXPR_P (NODE))
+static inline source_range
+get_expr_source_range (tree expr)
+{
+ location_t loc = EXPR_LOCATION (expr);
+ return get_range_from_loc (line_table, loc);
+}
+
extern void protected_set_expr_location (tree, location_t);
/* In a TARGET_EXPR node. */
@@ -2172,6 +2187,9 @@ extern machine_mode element_mode (const_tree t);
#define DECL_IS_BUILTIN(DECL) \
(LOCATION_LOCUS (DECL_SOURCE_LOCATION (DECL)) <= BUILTINS_LOCATION)
+#define DECL_LOCATION_RANGE(NODE) \
+ (get_decl_source_range (DECL_MINIMAL_CHECK (NODE)))
+
/* For FIELD_DECLs, this is the RECORD_TYPE, UNION_TYPE, or
QUAL_UNION_TYPE node that the field is a member of. For VAR_DECL,
PARM_DECL, FUNCTION_DECL, LABEL_DECL, RESULT_DECL, and CONST_DECL
@@ -5277,10 +5295,25 @@ type_with_alias_set_p (const_tree t)
return false;
}
+extern location_t set_block (location_t loc, tree block);
+
extern void gt_ggc_mx (tree &);
extern void gt_pch_nx (tree &);
extern void gt_pch_nx (tree &, gt_pointer_operator, void *);
extern bool nonnull_arg_p (const_tree);
+extern void
+set_source_range (tree expr, location_t start, location_t finish);
+
+extern void
+set_source_range (tree expr, source_range src_range);
+
+static inline source_range
+get_decl_source_range (tree decl)
+{
+ location_t loc = DECL_SOURCE_LOCATION (decl);
+ return get_range_from_loc (line_table, loc);
+}
+
#endif /* GCC_TREE_H */