From patchwork Fri May 27 14:51:59 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Carlini X-Patchwork-Id: 627241 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]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3rGTWQ5fQtz9sdm for ; Sat, 28 May 2016 00:52:18 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=vbup6BLK; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to:cc :from:subject:message-id:date:mime-version:content-type; q=dns; s=default; b=gNlCx+VmHrcp35PSz9msiolbGoO/0S4jWlVuvVPynWyyuglwcJ xVGViJUiYdSEyuaPuIb9eNz8eiUcQqQrXRV+/hIZp4xXkY2wCIoDJ5wr52OAfdbv ac/E5lMl7NKboWJW4UPdUU+cW+d5CEfcW+fwo3P5KrokNU3WSoUjn+fuA= 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:to:cc :from:subject:message-id:date:mime-version:content-type; s= default; bh=yWoEnVP5IV3+z4CctUjyF2hoScQ=; b=vbup6BLKvE81+dinaQHh OlXM01qJZao3u3RnQPHi/tXpG7FfiTHZfCy6ypDtWuaMEKLMHWpiT+67sV0SEKZi pCiTCZ4yv5x7rk39GO1/m8U+trvUW7ooP1rIDAGc1bMmvdSUte5eLx+KZ1eyoJph 5UaA7GsW+Z4P1wNXIJ+Lynk= Received: (qmail 73927 invoked by alias); 27 May 2016 14:52:10 -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 73768 invoked by uid 89); 27 May 2016 14:52:09 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.5 required=5.0 tests=BAYES_00, KAM_ASCII_DIVIDERS, RP_MATCHES_RCVD, SPF_PASS autolearn=ham version=3.3.2 spammy=sk:push_in, bar1, succeed, crashing X-HELO: userp1040.oracle.com Received: from userp1040.oracle.com (HELO userp1040.oracle.com) (156.151.31.81) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Fri, 27 May 2016 14:52:08 +0000 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u4REq5iV023481 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 27 May 2016 14:52:05 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u4REq5Qm007039 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 27 May 2016 14:52:05 GMT Received: from abhmp0004.oracle.com (abhmp0004.oracle.com [141.146.116.10]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u4REq2Jh017898; Fri, 27 May 2016 14:52:03 GMT Received: from [192.168.1.4] (/79.12.211.42) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Fri, 27 May 2016 07:52:02 -0700 To: "gcc-patches@gcc.gnu.org" Cc: Jason Merrill From: Paolo Carlini Subject: [C++ Patch/RFC] PR 60385 and other issues about wrongly named namespaces (eg, c++/68723) Message-ID: <57485F0F.2020907@oracle.com> Date: Fri, 27 May 2016 16:51:59 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.7.0 MIME-Version: 1.0 X-IsSubscribed: yes Hi, we have these long standing issues with code like (c++/60385): float foo4(); namespace foo4 { // .... } where the name of the namespace conflicts with an existing declaration. Error recovery is currently suboptimal, for example, c++/60385 is about struct bar6 { friend wchar_t bar1(); }; inside the namespace: due to the code in do_friend: push_nested_namespace (ns); decl = pushdecl_namespace_level (decl, /*is_friend=*/true); pop_nested_namespace (ns); we issue duplicate diagnostic about the wrong name and later we crash in pop_namespace (the second time in push_namespace, IDENTIFIER_NAMESPACE_VALUE isn't found set for the malformed namespace, thus need_new is true, pushdecl is called...) Now, I'm wondering how far we want to go with error recovery for such snippets. Certainly, in analogy with the code at the beginning of cp_parser_class_specifier_1, we can completely skip the body of such malformed namespaces. That would be the first attached patchlet. Or we can go on in cp_parser_namespace_definition but remember that push_namespace didn't really succeed and keep things consistent, thus avoid crashing in pop_namespace later, as currently happens. That would be second patchlet. Both ideas pass testing and work for c++/68723 too (as expected, the first patchlet leads to particularly neat diagnostic for the very broken snippet in c++/68723, only the error about the wrong namespace name, as for c++/60385). Thanks! Paolo. ////////////////////// Index: name-lookup.c =================================================================== --- name-lookup.c (revision 236799) +++ name-lookup.c (working copy) @@ -3685,7 +3685,7 @@ handle_namespace_attrs (tree ns, tree attributes) /* Push into the scope of the NAME namespace. If NAME is NULL_TREE, then we select a name that is unique to this compilation unit. */ -void +bool push_namespace (tree name) { tree d = NULL_TREE; @@ -3759,7 +3759,11 @@ push_namespace (tree name) TREE_PUBLIC (d) = 0; else TREE_PUBLIC (d) = 1; - pushdecl (d); + if (pushdecl (d) == error_mark_node) + { + timevar_cond_stop (TV_NAME_LOOKUP, subtime); + return false; + } if (anon) { /* Clear DECL_NAME for the benefit of debugging back ends. */ @@ -3777,6 +3781,7 @@ push_namespace (tree name) current_namespace = d; timevar_cond_stop (TV_NAME_LOOKUP, subtime); + return true; } /* Pop from the scope of the current namespace. */ Index: name-lookup.h =================================================================== --- name-lookup.h (revision 236799) +++ name-lookup.h (working copy) @@ -312,7 +312,7 @@ extern tree push_inner_scope (tree); extern void pop_inner_scope (tree, tree); extern void push_binding_level (cp_binding_level *); -extern void push_namespace (tree); +extern bool push_namespace (tree); extern void pop_namespace (void); extern void push_nested_namespace (tree); extern void pop_nested_namespace (tree); Index: parser.c =================================================================== --- parser.c (revision 236799) +++ parser.c (working copy) @@ -17549,7 +17549,7 @@ cp_parser_namespace_definition (cp_parser* parser) } /* Start the namespace. */ - push_namespace (identifier); + bool ok = push_namespace (identifier); /* Parse any nested namespace definition. */ if (cp_lexer_next_token_is (parser->lexer, CPP_SCOPE)) @@ -17582,7 +17582,7 @@ cp_parser_namespace_definition (cp_parser* parser) /* "inline namespace" is equivalent to a stub namespace definition followed by a strong using directive. */ - if (is_inline) + if (is_inline && ok) { tree name_space = current_namespace; /* Set up namespace association. */ @@ -17610,7 +17610,8 @@ cp_parser_namespace_definition (cp_parser* parser) pop_namespace (); /* Finish the namespace. */ - pop_namespace (); + if (ok) + pop_namespace (); /* Look for the final `}'. */ cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE); } Index: name-lookup.c =================================================================== --- name-lookup.c (revision 236809) +++ name-lookup.c (working copy) @@ -3685,7 +3685,7 @@ handle_namespace_attrs (tree ns, tree attributes) /* Push into the scope of the NAME namespace. If NAME is NULL_TREE, then we select a name that is unique to this compilation unit. */ -void +bool push_namespace (tree name) { tree d = NULL_TREE; @@ -3759,7 +3759,11 @@ push_namespace (tree name) TREE_PUBLIC (d) = 0; else TREE_PUBLIC (d) = 1; - pushdecl (d); + if (pushdecl (d) == error_mark_node) + { + timevar_cond_stop (TV_NAME_LOOKUP, subtime); + return false; + } if (anon) { /* Clear DECL_NAME for the benefit of debugging back ends. */ @@ -3777,6 +3781,7 @@ push_namespace (tree name) current_namespace = d; timevar_cond_stop (TV_NAME_LOOKUP, subtime); + return true; } /* Pop from the scope of the current namespace. */ Index: name-lookup.h =================================================================== --- name-lookup.h (revision 236809) +++ name-lookup.h (working copy) @@ -312,7 +312,7 @@ extern tree push_inner_scope (tree); extern void pop_inner_scope (tree, tree); extern void push_binding_level (cp_binding_level *); -extern void push_namespace (tree); +extern bool push_namespace (tree); extern void pop_namespace (void); extern void push_nested_namespace (tree); extern void pop_nested_namespace (tree); Index: parser.c =================================================================== --- parser.c (revision 236809) +++ parser.c (working copy) @@ -17549,7 +17549,11 @@ cp_parser_namespace_definition (cp_parser* parser) } /* Start the namespace. */ - push_namespace (identifier); + if (!push_namespace (identifier)) + { + cp_parser_skip_to_end_of_block_or_statement (parser); + return; + } /* Parse any nested namespace definition. */ if (cp_lexer_next_token_is (parser->lexer, CPP_SCOPE))