From patchwork Fri Sep 18 18:56:17 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ville Voutilainen X-Patchwork-Id: 519518 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 18D781400B7 for ; Sat, 19 Sep 2015 04:56:29 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=NZ3nxGW2; 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 :mime-version:in-reply-to:references:date:message-id:subject :from:to:cc:content-type; q=dns; s=default; b=m6uLysppwQBc0mKRS+ Yg+W1IQVOLKCymu3CDhVxnVyAbdnIVayKIGqm9f6z2WX8w/lUl2ekQASPz6hgs+A wKOAkchryxrB+ooJlqVvt5bTNh0kbaOmUiOYp3och+JsOHFt558RnU/3Ac8BWYUw n6P+4SErSX8QCfIdqcbIcCSIE= 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 :mime-version:in-reply-to:references:date:message-id:subject :from:to:cc:content-type; s=default; bh=kG89PQTg//KhQZCRLcDrbvYS g5o=; b=NZ3nxGW2h6sifDJF8u5SZgKinNlUFAWPV0VTMSTW3HWlNCPqMGEfbA8X aa/Aplfn1qy5n58HJE6ZkQkuaX9IdCZsv/NeNlvT9RtfCY3BkTSDQplzCLb3+Mvp KVkbW2tHYN5a9QQ5WS/Eh2m+UT/CuyY8OFIYfbNKVfURSyNiAzI= Received: (qmail 20590 invoked by alias); 18 Sep 2015 18:56:21 -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 20011 invoked by uid 89); 18 Sep 2015 18:56:20 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.6 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-vk0-f47.google.com Received: from mail-vk0-f47.google.com (HELO mail-vk0-f47.google.com) (209.85.213.47) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Fri, 18 Sep 2015 18:56:19 +0000 Received: by vkhf67 with SMTP id f67so35471110vkh.1 for ; Fri, 18 Sep 2015 11:56:17 -0700 (PDT) MIME-Version: 1.0 X-Received: by 10.31.58.142 with SMTP id h136mr4157670vka.58.1442602577131; Fri, 18 Sep 2015 11:56:17 -0700 (PDT) Received: by 10.103.37.195 with HTTP; Fri, 18 Sep 2015 11:56:17 -0700 (PDT) In-Reply-To: References: <55FB1E5F.3060902@redhat.com> <55FC3B8A.2030303@redhat.com> <55FC3D27.7020501@redhat.com> <55FC4940.7080408@redhat.com> Date: Fri, 18 Sep 2015 21:56:17 +0300 Message-ID: Subject: Re: [PATCH, RFC] Implement N4230, Nested namespace definition From: Ville Voutilainen To: Jason Merrill Cc: "gcc-patches@gcc.gnu.org" , Nathan Sidwell On 18 September 2015 at 20:46, Ville Voutilainen wrote: > Argh, no. An attribute immediately following a nesting namespace would need > to be parsed before the nested namespace definition handling is done, otherwise > the nested namespace definition handling is never entered because the next token > is not CPP_SCOPE. So the attributes should be parsed and rejected where they are > parsed now if they are followed by a CPP_SCOPE. That's easy, I'll just check > for non-null attribs and diagnose. New patch attached. I added tests for the partial attribute support in it. Ok for trunk? diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 4f424b6..e9353b0 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -16953,6 +16953,8 @@ cp_parser_namespace_definition (cp_parser* parser) tree identifier, attribs; bool has_visibility; bool is_inline; + cp_token* token; + int nested_definition_count = 0; cp_ensure_no_omp_declare_simd (parser); if (cp_lexer_next_token_is_keyword (parser->lexer, RID_INLINE)) @@ -16965,7 +16967,7 @@ cp_parser_namespace_definition (cp_parser* parser) is_inline = false; /* Look for the `namespace' keyword. */ - cp_parser_require_keyword (parser, RID_NAMESPACE, RT_NAMESPACE); + token = cp_parser_require_keyword (parser, RID_NAMESPACE, RT_NAMESPACE); /* Get the name of the namespace. We do not attempt to distinguish between an original-namespace-definition and an @@ -16979,11 +16981,38 @@ cp_parser_namespace_definition (cp_parser* parser) /* Parse any specified attributes. */ attribs = cp_parser_attributes_opt (parser); - /* Look for the `{' to start the namespace. */ - cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE); /* Start the namespace. */ push_namespace (identifier); + /* Parse any nested namespace definition. */ + if (cp_lexer_next_token_is (parser->lexer, CPP_SCOPE)) + { + if (attribs) + error_at (token->location, "a nested namespace definition cannot have attributes"); + if (cxx_dialect < cxx1z) + pedwarn (input_location, OPT_Wpedantic, + "nested namespace definitions only available with " + "-std=c++1z or -std=gnu++1z"); + if (is_inline) + error_at (token->location, "a nested namespace definition cannot be inline"); + while (cp_lexer_next_token_is (parser->lexer, CPP_SCOPE)) + { + cp_lexer_consume_token (parser->lexer); + if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) + identifier = cp_parser_identifier (parser); + else + { + cp_parser_error (parser, "nested identifier required"); + break; + } + ++nested_definition_count; + push_namespace (identifier); + } + } + + /* Look for the `{' to validate starting the namespace. */ + cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE); + /* "inline namespace" is equivalent to a stub namespace definition followed by a strong using directive. */ if (is_inline) @@ -17007,6 +17036,10 @@ cp_parser_namespace_definition (cp_parser* parser) if (has_visibility) pop_visibility (1); + /* Finish the nested namespace definitions. */ + while (nested_definition_count--) + pop_namespace (); + /* Finish the namespace. */ pop_namespace (); /* Look for the final `}'. */ diff --git a/gcc/testsuite/g++.dg/cpp1z/nested-namespace-def1.C b/gcc/testsuite/g++.dg/cpp1z/nested-namespace-def1.C new file mode 100644 index 0000000..ebdb70b --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/nested-namespace-def1.C @@ -0,0 +1,19 @@ +// { dg-options "-std=c++1z" } + +namespace A::B::C +{ + struct X {}; + namespace T::U::V { struct Y {}; } +} + +A::B::C::X x; +A::B::C::T::U::V::Y y; + +inline namespace D::E {} // { dg-error "cannot be inline" } + +namespace F::G:: {} // { dg-error "nested identifier required" } + +namespace G __attribute ((visibility ("default"))) ::H {} // { dg-error "cannot have attributes" } + +namespace H [[deprecated]] ::I {} // { dg-error "cannot have attributes|ignored" } + diff --git a/gcc/testsuite/g++.dg/cpp1z/nested-namespace-def2.C b/gcc/testsuite/g++.dg/cpp1z/nested-namespace-def2.C new file mode 100644 index 0000000..c47a94a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/nested-namespace-def2.C @@ -0,0 +1,5 @@ +// { dg-options "-std=c++11 -pedantic-errors" } + +namespace A::B::C // { dg-error "nested namespace definitions only available with" } +{ +} diff --git a/gcc/testsuite/g++.dg/cpp1z/nested-namespace-def3.C b/gcc/testsuite/g++.dg/cpp1z/nested-namespace-def3.C new file mode 100644 index 0000000..f2dac8f --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/nested-namespace-def3.C @@ -0,0 +1,5 @@ +// { dg-options "-std=c++11" } + +namespace A::B::C +{ +} diff --git a/gcc/testsuite/g++.dg/lookup/name-clash5.C b/gcc/testsuite/g++.dg/lookup/name-clash5.C index 74595c2..9673bb9 100644 --- a/gcc/testsuite/g++.dg/lookup/name-clash5.C +++ b/gcc/testsuite/g++.dg/lookup/name-clash5.C @@ -6,8 +6,8 @@ // "[Note: a namespace name or a class template name must be unique in its // declarative region (7.3.2, clause 14). ]" -namespace N -{ // { dg-message "previous declaration" } +namespace N // { dg-message "previous declaration" } +{ } class N; // { dg-error "redeclared" } diff --git a/gcc/testsuite/g++.dg/lookup/name-clash6.C b/gcc/testsuite/g++.dg/lookup/name-clash6.C index 6918142..f27e04a 100644 --- a/gcc/testsuite/g++.dg/lookup/name-clash6.C +++ b/gcc/testsuite/g++.dg/lookup/name-clash6.C @@ -8,6 +8,6 @@ class N; // { dg-message "previous declaration" } -namespace N -{ // { dg-error "redeclared" } +namespace N // { dg-error "redeclared" } +{ }