From patchwork Fri Sep 28 15:39:34 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Dodji Seketeli X-Patchwork-Id: 187809 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 909352C00C7 for ; Sat, 29 Sep 2012 01:39:52 +1000 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1349451592; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Received:From:To:Cc:Subject:Date:Message-ID:User-Agent: MIME-Version:Content-Type:Content-Transfer-Encoding:Mailing-List: Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:Sender:Delivered-To; bh=zAxFhMpTaYdh1BcO8cvdhkBHsrI=; b=nbnCuWorSGAGf4fcMsSyUngJJGw1hSVJDk39afvwOUfr2fR+kaGIgm/scLjtHB GzsDUyVfU+fGiRiM8BPTg+xk+9X6EvMYJErUc8gmHMr8bXPzpx16DhE+6Lthu2Bx U28qb22cL5uMJMITw/eRNtpeES2pgboIjqujrcc2LHMCI= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:Received:Received:From:To:Cc:Subject:X-URL:Date:Message-ID:User-Agent:MIME-Version:Content-Type:Content-Transfer-Encoding:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=e4cP/sloQM7xcW7vQ8ZS51STIHLQu/z4b3ep2ePjlKxuTRqHC2BCtckl3dS1bl u778djeCCZjDZHBfxrJrTpCvS91sxalEfk5mKTHAQRmW+k2Fe3GJWl0HeleVECwj tKEnea25eGJNOH1Gig21sejAqmOYGITPNGmHnNUUlr2l0=; Received: (qmail 26962 invoked by alias); 28 Sep 2012 15:39:46 -0000 Received: (qmail 26947 invoked by uid 22791); 28 Sep 2012 15:39:44 -0000 X-SWARE-Spam-Status: No, hits=-6.3 required=5.0 tests=AWL, BAYES_00, KHOP_RCVD_UNTRUST, RCVD_IN_DNSWL_HI, RCVD_IN_HOSTKARMA_W, RP_MATCHES_RCVD, SPF_HELO_PASS, TW_CX X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 28 Sep 2012 15:39:39 +0000 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q8SFddcA003865 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 28 Sep 2012 11:39:39 -0400 Received: from localhost (ovpn-116-53.ams2.redhat.com [10.36.116.53]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q8SFdagK008055 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Fri, 28 Sep 2012 11:39:37 -0400 Received: by localhost (Postfix, from userid 1000) id 296652C007C; Fri, 28 Sep 2012 17:39:34 +0200 (CEST) From: Dodji Seketeli To: GCC Patches Cc: Gabriel Dos Reis , Jason Merrill Subject: [PATCH] PR c++/54401 - Confusing diagnostics about type-alias at class scope X-URL: http://www.redhat.com Date: Fri, 28 Sep 2012 17:39:34 +0200 Message-ID: <87626yupft.fsf@redhat.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.1 (gnu/linux) MIME-Version: 1.0 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 Hello, Consider this invalid example given in the PR, where T is not defined: 1 template 2 struct X { 3 using type = T; 4 }; g++ yields the confusing diagnostics: test.cc:3:10: error: expected nested-name-specifier before 'type' using type = T; ^ test.cc:3:10: error: using-declaration for non-member at class scope test.cc:3:15: error: expected ';' before '=' token using type = T; ^ test.cc:3:15: error: expected unqualified-id before '=' token I think this is because in cp_parser_member_declaration we tentatively parse an alias declaration; we then have a somewhat meaningful diagnostic which alas is not emitted because we are parsing tentatively. As the parsing didn't succeed (because the input is invalid) we try to parse a using declaration, which fails as well; but then the diagnostic emitted is the one for the failed attempt at parsing a using declaration, not an alias declaration. Oops. The idea of this patch is to detect in advance that we want to parse an alias declaration, parse it non-tentatively, and then if an error arises, emit it. I also changed cp_parser_alias_declaration to get out directly when it detects that the type-id is invalid, rather than going on nonetheless and emitting more (irrelevant) error diagnostics. We are now getting the following output: test.cc:3:18: erreur: expected type-specifier before ‘T’ using type = T; ^ test.cc:3:18: erreur: ‘T’ does not name a type I don't really like the "before 'T'" there, but I think we maybe could revisit the format of what cp_parser_error emits in general, now that we have caret diagnostics; We could maybe do away with the "before T" altogether? In the mean time, it seems to me that this patch brings an improvement over what we already have in trunk, and the issue above could be addressed separately. Tested on x86_64-unknown-linux-gnu against trunk. gcc/cp/ * parser.c (cp_parser_expecting_alias_declaration_p): New static function. (cp_parser_block_declaration): Use it. (cp_parser_member_declaration): Likewise. Don't parse the using declaration tentatively. (cp_parser_alias_declaration): Get out if the type-id is invalid. gcc/testsuite/ * g++.dg/cpp0x/alias-decl-23.C: New test. --- gcc/cp/parser.c | 38 +++++++++++++++++++++++------- gcc/testsuite/g++.dg/cpp0x/alias-decl-23.C | 7 ++++++ 2 files changed, 36 insertions(+), 9 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/alias-decl-23.C diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index e8c0378..cab2d09 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -1937,6 +1937,8 @@ static bool cp_parser_using_declaration (cp_parser *, bool); static void cp_parser_using_directive (cp_parser *); +static bool cp_parser_expecting_alias_declaration_p + (cp_parser*); static tree cp_parser_alias_declaration (cp_parser *); static void cp_parser_asm_definition @@ -10292,11 +10294,7 @@ cp_parser_block_declaration (cp_parser *parser, cp_parser_using_directive (parser); /* If the second token after 'using' is '=', then we have an alias-declaration. */ - else if (cxx_dialect >= cxx0x - && token2->type == CPP_NAME - && ((cp_lexer_peek_nth_token (parser->lexer, 3)->type == CPP_EQ) - || (cp_lexer_peek_nth_token (parser->lexer, 3)->keyword - == RID_ATTRIBUTE))) + else if (cp_parser_expecting_alias_declaration_p (parser)) cp_parser_alias_declaration (parser); /* Otherwise, it's a using-declaration. */ else @@ -15079,6 +15077,24 @@ cp_parser_using_declaration (cp_parser* parser, return true; } +/* Return TRUE if the coming tokens reasonably denote the beginning of + an alias declaration. */ + +static bool +cp_parser_expecting_alias_declaration_p (cp_parser* parser) +{ + if (cxx_dialect < cxx0x) + return false; + cp_parser_parse_tentatively (parser); + cp_parser_require_keyword (parser, RID_USING, RT_USING); + cp_parser_identifier (parser); + cp_parser_attributes_opt (parser); + cp_parser_require (parser, CPP_EQ, RT_EQ); + bool is_ok = !cp_parser_error_occurred (parser); + cp_parser_abort_tentative_parse (parser); + return is_ok; +} + /* Parse an alias-declaration. alias-declaration: @@ -15141,6 +15157,9 @@ cp_parser_alias_declaration (cp_parser* parser) if (parser->num_template_parameter_lists) parser->type_definition_forbidden_message = saved_message; + if (type == error_mark_node) + return error_mark_node; + cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); if (cp_parser_error_occurred (parser)) @@ -18849,10 +18868,11 @@ cp_parser_member_declaration (cp_parser* parser) else { tree decl; - cp_parser_parse_tentatively (parser); - decl = cp_parser_alias_declaration (parser); - if (cp_parser_parse_definitely (parser)) - finish_member_declaration (decl); + if (cp_parser_expecting_alias_declaration_p (parser)) + { + decl = cp_parser_alias_declaration (parser); + finish_member_declaration (decl); + } else cp_parser_using_declaration (parser, /*access_declaration_p=*/false); diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-23.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-23.C new file mode 100644 index 0000000..086b5e5 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-23.C @@ -0,0 +1,7 @@ +// Origin: PR c++/54401 +// { dg-do compile { target c++11 } } + +template +struct X { + using type = T; // { dg-error "expected type-specifier|does not name a type" } +};