Capture source location of dtors (PR c++/89390)
authorDavid Malcolm <dmalcolm@redhat.com>
Sat, 23 Feb 2019 01:19:38 +0000 (01:19 +0000)
committerDavid Malcolm <dmalcolm@gcc.gnu.org>
Sat, 23 Feb 2019 01:19:38 +0000 (01:19 +0000)
gcc/cp/ChangeLog:
PR c++/89390
* parser.c (cp_parser_unqualified_id): Capture and use locations
for destructors.

gcc/testsuite/ChangeLog:
PR c++/89390
* g++.dg/diagnostic/pr89390.C: Update expected location of error,
renaming to a multicharacter name, so that start != finish.  Add
tests for dtor locations.

From-SVN: r269145

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/diagnostic/pr89390.C

index 8381391..2a5056a 100644 (file)
@@ -1,3 +1,9 @@
+2019-02-22  David Malcolm  <dmalcolm@redhat.com>
+
+       PR c++/89390
+       * parser.c (cp_parser_unqualified_id): Capture and use locations
+       for destructors.
+
 2019-02-22  Marek Polacek  <polacek@redhat.com>
 
        PR c++/89420 - ICE with CAST_EXPR in explicit-specifier.
index 545047c..e976008 100644 (file)
@@ -5976,6 +5976,7 @@ cp_parser_unqualified_id (cp_parser* parser,
        tree object_scope;
        tree scope;
        bool done;
+       location_t tilde_loc = token->location;
 
        /* Consume the `~' token.  */
        cp_lexer_consume_token (parser->lexer);
@@ -6038,9 +6039,18 @@ cp_parser_unqualified_id (cp_parser* parser,
          }
        gcc_assert (!scope || TYPE_P (scope));
 
+       token = cp_lexer_peek_token (parser->lexer);
+
+       /* Create a location with caret == start at the tilde,
+          finishing at the end of the peeked token, e.g:
+          ~token
+          ^~~~~~.  */
+       location_t loc
+         = make_location (tilde_loc, tilde_loc, token->location);
+
        /* If the name is of the form "X::~X" it's OK even if X is a
           typedef.  */
-       token = cp_lexer_peek_token (parser->lexer);
+
        if (scope
            && token->type == CPP_NAME
            && (cp_lexer_peek_nth_token (parser->lexer, 2)->type
@@ -6050,18 +6060,18 @@ cp_parser_unqualified_id (cp_parser* parser,
                    && constructor_name_p (token->u.value, scope))))
          {
            cp_lexer_consume_token (parser->lexer);
-           return build_nt (BIT_NOT_EXPR, scope);
+           return cp_expr (build_nt (BIT_NOT_EXPR, scope), loc);
          }
 
        /* ~auto means the destructor of whatever the object is.  */
        if (cp_parser_is_keyword (token, RID_AUTO))
          {
            if (cxx_dialect < cxx14)
-             pedwarn (input_location, 0,
+             pedwarn (loc, 0,
                       "%<~auto%> only available with "
                       "-std=c++14 or -std=gnu++14");
            cp_lexer_consume_token (parser->lexer);
-           return build_nt (BIT_NOT_EXPR, make_auto ());
+           return cp_expr (build_nt (BIT_NOT_EXPR, make_auto (), loc));
          }
 
        /* If there was an explicit qualification (S::~T), first look
@@ -6152,7 +6162,7 @@ cp_parser_unqualified_id (cp_parser* parser,
                type_decl = cp_parser_identifier (parser);
                if (type_decl != error_mark_node)
                  type_decl = build_nt (BIT_NOT_EXPR, type_decl);
-               return type_decl;
+               return cp_expr (type_decl, loc);
              }
          }
        /* If an error occurred, assume that the name of the
@@ -6168,7 +6178,7 @@ cp_parser_unqualified_id (cp_parser* parser,
        if (declarator_p && scope && !check_dtor_name (scope, type_decl))
          {
            if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
-             error_at (token->location,
+             error_at (loc,
                        "declaration of %<~%T%> as member of %qT",
                        type_decl, scope);
            cp_parser_simulate_error (parser);
@@ -6183,11 +6193,11 @@ cp_parser_unqualified_id (cp_parser* parser,
            && !DECL_IMPLICIT_TYPEDEF_P (type_decl)
            && !DECL_SELF_REFERENCE_P (type_decl)
            && !cp_parser_uncommitted_to_tentative_parse_p (parser))
-         error_at (token->location,
+         error_at (loc,
                    "typedef-name %qD used as destructor declarator",
                    type_decl);
 
-       return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
+       return cp_expr (build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl), loc));
       }
 
     case CPP_KEYWORD:
index 4d3d307..4751104 100644 (file)
@@ -1,3 +1,10 @@
+2019-02-22  David Malcolm  <dmalcolm@redhat.com>
+
+       PR c++/89390
+       * g++.dg/diagnostic/pr89390.C: Update expected location of error,
+       renaming to a multicharacter name, so that start != finish.  Add
+       tests for dtor locations.
+
 2019-02-22  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/84676
index 8dae827..2e8c95a 100644 (file)
@@ -1,10 +1,48 @@
 // PR c++/89390
 // { dg-do compile { target c++11 } }
+// { dg-options "-fdiagnostics-show-caret" }
 
-enum class A { B, C };
+enum class bar { A, B, C };
 
 void
 foo ()
 {
-  A::~A ();    // { dg-error "'~A' is not a member of 'A'" "" { target *-*-* } 0 }
+  bar::~bar ();    // { dg-error "8: '~bar' is not a member of 'bar'" }
+  /* { dg-begin-multiline-output "" }
+   bar::~bar ();
+        ^~~~
+     { dg-end-multiline-output "" } */
 }
+
+namespace ns { enum class baz { P, Q, R }; }
+
+void
+test_2 ()
+{
+  ns::baz::~baz ();    // { dg-error "12: '~ns::baz' is not a member of 'ns::baz'" }
+  /* { dg-begin-multiline-output "" }
+   ns::baz::~baz ();
+            ^~~~
+     { dg-end-multiline-output "" } */
+}
+
+struct first;
+struct second;
+second::~first() {} // { dg-error "9: declaration of '~first' as member of 'second'" }
+  /* { dg-begin-multiline-output "" }
+ second::~first() {}
+         ^~~~~~
+     { dg-end-multiline-output "" } */
+
+struct test { ~test(); };
+typedef test test_t;
+~test_t();  // { dg-error "typedef-name 'test_t' used as destructor declarator" }
+// { dg-error "expected" "" { target *-*-* } .-1 }
+  /* { dg-begin-multiline-output "" }
+ ~test_t();
+ ^~~~~~~
+     { dg-end-multiline-output "" } */
+  /* { dg-begin-multiline-output "" }
+ ~test_t();
+          ^
+     { dg-end-multiline-output "" } */