From patchwork Thu Feb 21 02:33:32 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: David Malcolm X-Patchwork-Id: 1045710 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-496782-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="dF4LDEeq"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 444cgK48Qkz9s5c for ; Thu, 21 Feb 2019 12:43:04 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-type:content-transfer-encoding; q=dns; s= default; b=sahNyDJeFl/4qOYamC8xIo5YxKm1M62CHFAhmvbW7nnP21qBgNL/Z FwIqJnDdWjDvx1CAAiYa58JXDEK2Z1qFRF1VwQhbILjTkQEuPFNoonrwM1oIg+BX CeexZVgMGSZCXQt1EAo+WcFqYRSURwfp17FUCSVwBDJtCFHdZCU4XA= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-type:content-transfer-encoding; s=default; bh=i3zh2CcuoT2zGTaxlNB05dJmYgs=; b=dF4LDEeq+A909SuGHW2K4o0O7NLf O8/+cMFSo871vmIHYqj2tswVacDCxM4mVeD2AajnXnLwP/bWdtKhaeCziaXLoWtk jOIKzHWopCMj54Pk9JWdn/uKy2HCdmpM4KKxAwbH2w5VJ3WtDIRmt3fJTA+4sgwm oje4hI0r61jJewE= Received: (qmail 99568 invoked by alias); 21 Feb 2019 01:42:55 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 99537 invoked by uid 89); 21 Feb 2019 01:42:55 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-25.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=qualification, consume, BIT_NOT_EXPR, cp_expr X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 21 Feb 2019 01:42:52 +0000 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 6AA258665D for ; Thu, 21 Feb 2019 01:42:51 +0000 (UTC) Received: from c64.redhat.com (ovpn-112-37.phx2.redhat.com [10.3.112.37]) by smtp.corp.redhat.com (Postfix) with ESMTP id 02DAE66080; Thu, 21 Feb 2019 01:42:49 +0000 (UTC) From: David Malcolm To: Jakub Jelinek Cc: Jason Merrill , gcc-patches@gcc.gnu.org, David Malcolm Subject: [PATCH v2] Capture source location of dtors (PR c++/89390) Date: Wed, 20 Feb 2019 21:33:32 -0500 Message-Id: <1550716412-45071-1-git-send-email-dmalcolm@redhat.com> In-Reply-To: <20190219193742.GY2135@tucnak> References: <20190219193742.GY2135@tucnak> MIME-Version: 1.0 X-IsSubscribed: yes On Tue, 2019-02-19 at 20:37 +0100, Jakub Jelinek wrote: > On Tue, Feb 19, 2019 at 02:44:55PM -0500, David Malcolm wrote: > > How about something like this? (on top of Jakub's patch) > > I had following queued for regtest, so if you want to go for the > make_location ^~, you should change more spots. > > > pr89390.C: In function 'void foo()': > > pr89390.C:9:6: error: '~A' is not a member of 'A' > > 9 | A::~A (); // { dg-error "6: '~A' is not a member of > > 'A'" } > > | ^~ > > pr89390.C: In function 'void test_2()': > > pr89390.C:17:10: error: '~ns::P' is not a member of 'ns::P' > > 17 | ns::P::~P (); // { dg-error "10: '~ns::P' is not a > > member of 'ns::P'" } > > | ^~ > > > > (Presumably gcc 10 material at this point; not yet bootstrapped). > > I wouldn't say so, it actually is even a regression: > $ /usr/src/gcc-6/obj/gcc/cc1plus -quiet pr89390.C > pr89390.C: In function ‘void foo()’: > pr89390.C:9:3: error: ‘~A’ is not a member of ‘A’ > A::~A (); // { dg-error "'~A' is not a member of 'A'" } > ^ > > $ /usr/src/gcc-7/obj/gcc/cc1plus -quiet pr89390.C > In function ‘void foo()’: > cc1plus: error: ‘~A’ is not a member of ‘A’ > > Feel free to take this over though. > > 2019-02-19 Jakub Jelinek > > PR c++/89390 > * parser.c (cp_parser_unqualified_id): For BIT_NOT_EXPR > remember > location of the ~ token and use it to build cp_expr. > > * g++.dg/diagnostic/pr89390.C (foo): Expect diagnostics at the > right > line. Thanks. Here's an updated version of the patch which use make_location, and merges in the changes from yours, and uses the loc in some other places (adding test coverage for them); hope that's not stretching things too far. Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu. OK for trunk? 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. --- gcc/cp/parser.c | 26 +++++++++++++------ gcc/testsuite/g++.dg/diagnostic/pr89390.C | 42 +++++++++++++++++++++++++++++-- 2 files changed, 58 insertions(+), 10 deletions(-) diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index ffecce4..f800360 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -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: diff --git a/gcc/testsuite/g++.dg/diagnostic/pr89390.C b/gcc/testsuite/g++.dg/diagnostic/pr89390.C index df35fcc..2e8c95a 100644 --- a/gcc/testsuite/g++.dg/diagnostic/pr89390.C +++ b/gcc/testsuite/g++.dg/diagnostic/pr89390.C @@ -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 "" } */