On 18 September 2015 at 02:02, Ville Voutilainen <ville.voutilai...@gmail.com> wrote: > Ahem, oops, the patch doesn't do any sort of a pedwarn for standard versions > below cpp1z; I'll do a new patch taking that into account tomorrow. I don't > think we have maybe_warn_cpp1z or anything like that? Any preferences > how to deal with that?
Here. Tested on Linux-PPC64. /cp 2015-09-18 Ville Voutilainen <ville.voutilai...@gmail.com> Implement nested namespace definitions. * parser.c (cp_parser_namespace_definition): Grok nested namespace definitions. /testsuite 2015-09-18 Ville Voutilainen <ville.voutilai...@gmail.com> Implement nested namespace definitions. * g++.dg/cpp1z/nested-namespace-def1.C: New. * g++.dg/cpp1z/nested-namespace-def2.C: Likewise. * g++.dg/cpp1z/nested-namespace-def3.C: Likewise. * g++.dg/lookup/name-clash5.C: Adjust. * g++.dg/lookup/name-clash6.C: Likewise.
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 4f424b6..602a90b 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,36 @@ 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 (cxx_dialect < cxx1z) + pedwarn (input_location, OPT_Wpedantic, + "nested namespace definitions only available with " + "-std=c++17 or -std=gnu++17"); + 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 +17034,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..d710ef1 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/nested-namespace-def1.C @@ -0,0 +1,14 @@ +// { 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" } 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" } +{ }