diff options
Diffstat (limited to 'gcc')
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 */ |