Fix location of typeid() (PR c++/80014)
authorDavid Malcolm <dmalcolm@redhat.com>
Fri, 30 Jun 2017 15:20:55 +0000 (15:20 +0000)
committerDavid Malcolm <dmalcolm@gcc.gnu.org>
Fri, 30 Jun 2017 15:20:55 +0000 (15:20 +0000)
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.

From-SVN: r249845

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/plugin/diagnostic-test-expressions-1.C

index 4260bbf..6c230a9 100644 (file)
@@ -1,3 +1,9 @@
+2017-06-30  David Malcolm  <dmalcolm@redhat.com>
+
+       PR c++/80014
+       * parser.c (cp_parser_postfix_expression): Construct a location
+       for typeid expressions.
+
 2017-06-30  Nathan Sidwell  <nathan@acm.org>
 
        * cp-tree.h (lookup_fnfields_1, class_method_index_for_fn): Don't
index 375cd0a..c6a8e37 100644 (file)
@@ -6542,7 +6542,8 @@ 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);
        /* If all went well, simply lookup the type-id.  */
        if (cp_parser_parse_definitely (parser))
          postfix_expression = get_typeid (type, tf_warning_or_error);
@@ -6556,13 +6557,26 @@ 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);
          }
        /* 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.  */
+       if (close_paren)
+         {
+           location_t typeid_loc
+             = make_location (start_loc, start_loc, close_paren->location);
+           postfix_expression.set_location (typeid_loc);
+         }
       }
       break;
 
index f42ea73..f0555b9 100644 (file)
@@ -1,3 +1,10 @@
+2017-06-30  David Malcolm  <dmalcolm@redhat.com>
+
+       PR c++/80014
+       * g++.dg/plugin/diagnostic-test-expressions-1.C (std::type_info):
+       Add declaration.
+       (test_typeid): New test function.
+
 2017-06-30  Jakub Jelinek  <jakub@redhat.com>
 
        PR target/81225
index 2c004f3..62d3c36 100644 (file)
@@ -848,3 +848,35 @@ 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(int)); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, &typeid(int));
+                               ^~~~~~~~~~~~
+   { 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 "" } */
+}