Implement nested namespace definitions.
authorVille Voutilainen <ville.voutilainen@gmail.com>
Sat, 19 Sep 2015 04:44:01 +0000 (07:44 +0300)
committerVille Voutilainen <ville@gcc.gnu.org>
Sat, 19 Sep 2015 04:44:01 +0000 (07:44 +0300)
/cp
2015-09-18  Ville Voutilainen  <ville.voutilainen@gmail.com>

Implement nested namespace definitions.
* parser.c (cp_parser_namespace_definition): Grok nested namespace
definitions.

/testsuite
2015-09-18  Ville Voutilainen  <ville.voutilainen@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.

From-SVN: r227932

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp1z/nested-namespace-def1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/nested-namespace-def2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/nested-namespace-def3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/lookup/name-clash5.C
gcc/testsuite/g++.dg/lookup/name-clash6.C

index c72e913e1b3d17c8f7e21235d23f22d9048d141b..373937aef93197a21e539b2579a80f721c5663c6 100644 (file)
@@ -1,3 +1,9 @@
+2015-09-18  Ville Voutilainen  <ville.voutilainen@gmail.com>
+
+       Implement nested namespace definitions.
+       * parser.c (cp_parser_namespace_definition): Grok nested namespace
+       definitions.
+
 2015-09-18  Manuel López-Ibáñez  <manu@gcc.gnu.org>
 
        * parser.c (pragma_lex): Add loc argument. Rearrange the code to
index 637118c2b271c8ac0fdd754717afbdf99f2c3c5e..2071276dfcb8035516463fec8a06ed1c3060ca20 100644 (file)
@@ -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 `}'.  */
index 95a19a7818181513c06e232a2192d1795a467a32..a5901a15c501d1a372de07fdf851166ebd984f13 100644 (file)
@@ -1,3 +1,12 @@
+2015-09-18  Ville Voutilainen  <ville.voutilainen@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.
+
 2015-09-18  Manuel López-Ibáñez  <manu@gcc.gnu.org>
 
        * gcc.dg/pragma-diag-5.c: New test.
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 (file)
index 0000000..ebdb70b
--- /dev/null
@@ -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 (file)
index 0000000..c47a94a
--- /dev/null
@@ -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 (file)
index 0000000..f2dac8f
--- /dev/null
@@ -0,0 +1,5 @@
+// { dg-options "-std=c++11" }
+
+namespace A::B::C
+{
+}
index 74595c26871bc0e274b4021f32c8874deee20cf6..9673bb9d8c692e2f3d55c62bb32eae1e21ec0060 100644 (file)
@@ -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" }
index 6918142f22220a35c80419296f901ba2c6a74010..f27e04aff83af1f7b41c7f96d70164412dcf4ffc 100644 (file)
@@ -8,6 +8,6 @@
 
 class N; // { dg-message "previous declaration" }
 
-namespace N
-{ // { dg-error "redeclared" }
+namespace N // { dg-error "redeclared" }
+{
 }