From patchwork Thu Mar 10 15:20:45 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 86298 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 8AF04B6F8F for ; Fri, 11 Mar 2011 02:20:56 +1100 (EST) Received: (qmail 8567 invoked by alias); 10 Mar 2011 15:20:54 -0000 Received: (qmail 8556 invoked by uid 22791); 10 Mar 2011 15:20:53 -0000 X-SWARE-Spam-Status: No, hits=-6.2 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, SPF_HELO_PASS, T_RP_MATCHES_RCVD 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; Thu, 10 Mar 2011 15:20:47 +0000 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p2AFKkNo028183 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Thu, 10 Mar 2011 10:20:46 -0500 Received: from [127.0.0.1] (ovpn-113-58.phx2.redhat.com [10.3.113.58]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id p2AFKj6b021605 for ; Thu, 10 Mar 2011 10:20:45 -0500 Message-ID: <4D78EC4D.6080300@redhat.com> Date: Thu, 10 Mar 2011 10:20:45 -0500 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.13) Gecko/20101209 Fedora/3.1.7-0.35.b3pre.fc14 Lightning/1.0b2 Thunderbird/3.1.7 MIME-Version: 1.0 To: gcc-patches List Subject: C++ PATCH for c++/47198 (ice-after-error with invalid type-name) 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 The call to cp_parser_skip_to_end_of_block_or_statement from cp_parser_parse_and_diagnose_invalid_type_name means that we're done looking at the current declaration; in the testcase, we were continuing to try to parse a declaration after skipping past the ;, so we ended up treating the constructor declarator as going with the template header. Instead, we should clean up and return. This patch also slightly improves error recovery on a few other testcases. Tested x86_64-pc-linux-gnu, applied to trunk. commit 2659b79922e437e422612b2a4272c199446cf543 Author: Jason Merrill Date: Thu Mar 10 01:22:45 2011 -0500 PR c++/47198 * parser.c (cp_parser_single_declaration): Just return if cp_parser_parse_and_diagnose_invalid_type_name complained. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 510fcb1..7e9b286 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -20102,8 +20102,15 @@ cp_parser_single_declaration (cp_parser* parser, } /* Complain about missing 'typename' or other invalid type names. */ - if (!decl_specifiers.any_type_specifiers_p) - cp_parser_parse_and_diagnose_invalid_type_name (parser); + if (!decl_specifiers.any_type_specifiers_p + && cp_parser_parse_and_diagnose_invalid_type_name (parser)) + { + /* cp_parser_parse_and_diagnose_invalid_type_name calls + cp_parser_skip_to_end_of_block_or_statement, so don't try to parse + the rest of this declaration. */ + decl = error_mark_node; + goto out; + } /* If it's not a template class, try for a template function. If the next token is a `;', then this declaration does not declare @@ -20137,19 +20144,21 @@ cp_parser_single_declaration (cp_parser* parser, } } - pop_deferring_access_checks (); - - /* Clear any current qualification; whatever comes next is the start - of something new. */ - parser->scope = NULL_TREE; - parser->qualifying_scope = NULL_TREE; - parser->object_scope = NULL_TREE; /* Look for a trailing `;' after the declaration. */ if (!function_definition_p && (decl == error_mark_node || !cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON))) cp_parser_skip_to_end_of_block_or_statement (parser); + out: + pop_deferring_access_checks (); + + /* Clear any current qualification; whatever comes next is the start + of something new. */ + parser->scope = NULL_TREE; + parser->qualifying_scope = NULL_TREE; + parser->object_scope = NULL_TREE; + return decl; } diff --git a/gcc/testsuite/g++.dg/cpp0x/syntax-err1.C b/gcc/testsuite/g++.dg/cpp0x/syntax-err1.C new file mode 100644 index 0000000..ce1c9ee --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/syntax-err1.C @@ -0,0 +1,8 @@ +// PR c++/47198 +// { dg-options -std=c++0x } + +struct S +{ + template < int > sometype foo (); // { dg-error "sometype. does not name a type" } + S () = default; +}; diff --git a/gcc/testsuite/g++.dg/parse/error36.C b/gcc/testsuite/g++.dg/parse/error36.C index 0d7f8cf..8fcaa2f 100644 --- a/gcc/testsuite/g++.dg/parse/error36.C +++ b/gcc/testsuite/g++.dg/parse/error36.C @@ -30,4 +30,3 @@ void g(const A::type &t); // { dg-error "typename" } // PR c++/18451 template A::B A::b; // { dg-error "typename" } -// { dg-error "expected" "" { target *-*-* } 32 } diff --git a/gcc/testsuite/g++.old-deja/g++.pt/ctor2.C b/gcc/testsuite/g++.old-deja/g++.pt/ctor2.C index eb8f312..a8be91d 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/ctor2.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/ctor2.C @@ -10,4 +10,4 @@ struct A { template A::A() // { dg-error "constructor|qualified name" } { -} // { dg-error "end of input" } +} diff --git a/gcc/testsuite/g++.old-deja/g++.pt/typename3.C b/gcc/testsuite/g++.old-deja/g++.pt/typename3.C index 0708f1f..ad026a7 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/typename3.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/typename3.C @@ -18,4 +18,4 @@ struct B : public A template B::A_Type B::Func() { // { dg-error "typename" } implicit typename -} // { dg-error "expected" } +} diff --git a/gcc/testsuite/g++.old-deja/g++.pt/typename4.C b/gcc/testsuite/g++.old-deja/g++.pt/typename4.C index 7238470..47fb250 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/typename4.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/typename4.C @@ -23,4 +23,4 @@ struct C : public B template C::A_Type C::Func() { // { dg-error "typename" } implicit typename -} // { dg-error "expected" } +} diff --git a/gcc/testsuite/g++.old-deja/g++.pt/typename6.C b/gcc/testsuite/g++.old-deja/g++.pt/typename6.C index 0a5f018..7347812 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/typename6.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/typename6.C @@ -17,4 +17,4 @@ struct B : public A template A::A_Type B::Func() // { dg-error "typename" } function { -} // { dg-error "expected" } +}