PR c++/80014 reports an issue where no caret is printed when issuing an error for this bogus code: !typeid(void);
Root cause is that we're not setting up the location for the cp_expr for the typeid expression, so that !typeid(void) has start == caret at the '!', but finish == UNKNOWN_LOCATION, and so the layout ctor within diagnostic-show-locus.c filters out the primary range, and hence layout::should_print_annotation_line_p returns false. This patch fixes things by setting up a location for the typeid expression when parsing it. Successfully bootstrapped®rtested on x86_64-pc-linux-gnu. OK for trunk now, or should this wait until stage 1? gcc/cp/ChangeLog: PR c++/80014 * parser.c (cp_parser_postfix_expression): Construct a location for typeid expressions. gcc/testsuite/ChangeLog: PR c++/80014 * g++.dg/plugin/diagnostic-test-expressions-1.C (std::type_info): Add declaration. (test_typeid): New test function. --- gcc/cp/parser.c | 17 ++++++++++++-- .../g++.dg/plugin/diagnostic-test-expressions-1.C | 26 ++++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index c1b6496..aecf9a5 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -6513,7 +6513,10 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, /* Look for the `)' token. Otherwise, we can't be sure that we're not looking at an expression: consider `typeid (int (3))', for example. */ - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + cp_token *close_paren = cp_parser_require (parser, CPP_CLOSE_PAREN, + RT_CLOSE_PAREN); + location_t end_loc = close_paren ? + close_paren->location : UNKNOWN_LOCATION; /* If all went well, simply lookup the type-id. */ if (cp_parser_parse_definitely (parser)) postfix_expression = get_typeid (type, tf_warning_or_error); @@ -6527,13 +6530,23 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, /* Compute its typeid. */ postfix_expression = build_typeid (expression, tf_warning_or_error); /* Look for the `)' token. */ - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + close_paren + = cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + end_loc = close_paren ? close_paren->location : UNKNOWN_LOCATION; } /* Restore the saved message. */ parser->type_definition_forbidden_message = saved_message; /* `typeid' may not appear in an integral constant expression. */ if (cp_parser_non_integral_constant_expression (parser, NIC_TYPEID)) postfix_expression = error_mark_node; + + /* Construct a location e.g. : + typeid (expr) + ^~~~~~~~~~~~~ + ranging from the start of the "typeid" token to the final closing + paren, with the caret at the start. */ + location_t typeid_loc = make_location (start_loc, start_loc, end_loc); + postfix_expression.set_location (typeid_loc); } break; diff --git a/gcc/testsuite/g++.dg/plugin/diagnostic-test-expressions-1.C b/gcc/testsuite/g++.dg/plugin/diagnostic-test-expressions-1.C index 4d3b07c..3554086 100644 --- a/gcc/testsuite/g++.dg/plugin/diagnostic-test-expressions-1.C +++ b/gcc/testsuite/g++.dg/plugin/diagnostic-test-expressions-1.C @@ -782,3 +782,29 @@ tests::test_method_calls () ~~~~~~~~~~~~~~~~~~^~ { dg-end-multiline-output "" } */ } + +namespace std +{ + class type_info { public: int foo; }; +} + +void test_typeid (int i) +{ + __emit_expression_range (0, &typeid(i)); /* { dg-warning "range" } */ +/* { dg-begin-multiline-output "" } + __emit_expression_range (0, &typeid(i)); + ^~~~~~~~~~ + { dg-end-multiline-output "" } */ + + __emit_expression_range (0, &typeid(i * 2)); /* { dg-warning "range" } */ +/* { dg-begin-multiline-output "" } + __emit_expression_range (0, &typeid(i * 2)); + ^~~~~~~~~~~~~~ + { dg-end-multiline-output "" } */ + + __emit_expression_range (0, typeid(int).foo); /* { dg-warning "range" } */ +/* { dg-begin-multiline-output "" } + __emit_expression_range (0, typeid(int).foo); + ~~~~~~~~~~~~^~~ + { dg-end-multiline-output "" } */ +} -- 1.8.5.3