Implement P1094R2, Nested inline namespaces.
authorMarek Polacek <polacek@redhat.com>
Wed, 28 Nov 2018 21:39:42 +0000 (21:39 +0000)
committerMarek Polacek <mpolacek@gcc.gnu.org>
Wed, 28 Nov 2018 21:39:42 +0000 (21:39 +0000)
* parser.c (cp_parser_namespace_definition): Parse the optional inline
keyword in a nested-namespace-definition.  Adjust push_namespace call.
Formatting fix.

* g++.dg/cpp2a/nested-inline-ns1.C: New test.
* g++.dg/cpp2a/nested-inline-ns2.C: New test.

From-SVN: r266592

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp2a/nested-inline-ns1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/nested-inline-ns2.C [new file with mode: 0644]

index 8b8a857bd3710cbb59a48d5466b5ea8534acd921..f7f20206550c21bb7d2f69db0d930407aebd9c13 100644 (file)
@@ -1,3 +1,10 @@
+2018-11-28  Marek Polacek  <polacek@redhat.com>
+
+       Implement P1094R2, Nested inline namespaces.
+       * parser.c (cp_parser_namespace_definition): Parse the optional inline
+       keyword in a nested-namespace-definition.  Adjust push_namespace call.
+       Formatting fix.
+
 2018-11-28  Nathan Sidwell  <nathan@acm.org>
 
        PR c++/87531
index 3a98ed900cdd5a9061bf81cf575d72f134946710..3ef1eda451885ad31ee3bb1dce74d1772b3d709a 100644 (file)
@@ -19004,6 +19004,7 @@ cp_parser_namespace_definition (cp_parser* parser)
   cp_ensure_no_oacc_routine (parser);
 
   bool is_inline = cp_lexer_next_token_is_keyword (parser->lexer, RID_INLINE);
+  const bool topmost_inline_p = is_inline;
 
   if (is_inline)
     {
@@ -19022,6 +19023,17 @@ cp_parser_namespace_definition (cp_parser* parser)
     {
       identifier = NULL_TREE;
       
+      bool nested_inline_p = cp_lexer_next_token_is_keyword (parser->lexer,
+                                                            RID_INLINE);
+      if (nested_inline_p && nested_definition_count != 0)
+       {
+         if (cxx_dialect < cxx2a)
+           pedwarn (cp_lexer_peek_token (parser->lexer)->location,
+                    OPT_Wpedantic, "nested inline namespace definitions only "
+                    "available with -std=c++2a or -std=gnu++2a");
+         cp_lexer_consume_token (parser->lexer);
+       }
+
       if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
        {
          identifier = cp_parser_identifier (parser);
@@ -19036,7 +19048,14 @@ cp_parser_namespace_definition (cp_parser* parser)
        }
 
       if (cp_lexer_next_token_is_not (parser->lexer, CPP_SCOPE))
-       break;
+       {
+         /* Don't forget that the innermost namespace might have been
+            marked as inline.  Use |= because we cannot overwrite
+            IS_INLINE in case the outermost namespace is inline, but
+            there are no nested inlines.  */
+         is_inline |= nested_inline_p;
+         break;
+       }
   
       if (!nested_definition_count && cxx_dialect < cxx17)
         pedwarn (input_location, OPT_Wpedantic,
@@ -19045,7 +19064,9 @@ cp_parser_namespace_definition (cp_parser* parser)
 
       /* Nested namespace names can create new namespaces (unlike
         other qualified-ids).  */
-      if (int count = identifier ? push_namespace (identifier) : 0)
+      if (int count = (identifier
+                      ? push_namespace (identifier, nested_inline_p)
+                      : 0))
        nested_definition_count += count;
       else
        cp_parser_error (parser, "nested namespace name required");
@@ -19058,7 +19079,7 @@ cp_parser_namespace_definition (cp_parser* parser)
   if (nested_definition_count && attribs)
     error_at (token->location,
              "a nested namespace definition cannot have attributes");
-  if (nested_definition_count && is_inline)
+  if (nested_definition_count && topmost_inline_p)
     error_at (token->location,
              "a nested namespace definition cannot be inline");
 
@@ -19067,7 +19088,7 @@ cp_parser_namespace_definition (cp_parser* parser)
 
   bool has_visibility = handle_namespace_attrs (current_namespace, attribs);
 
-  warning  (OPT_Wnamespaces, "namespace %qD entered", current_namespace);
+  warning (OPT_Wnamespaces, "namespace %qD entered", current_namespace);
 
   /* Look for the `{' to validate starting the namespace.  */
   matching_braces braces;
index 740671978b8bb25a072aefa4586e4c211322f786..0ba033a08ae9eba3c18f27aefe281262e678fd25 100644 (file)
@@ -1,3 +1,9 @@
+2018-11-28  Marek Polacek  <polacek@redhat.com>
+
+       Implement P1094R2, Nested inline namespaces.
+       * g++.dg/cpp2a/nested-inline-ns1.C: New test.
+       * g++.dg/cpp2a/nested-inline-ns2.C: New test.
+
 2018-11-28  Nathan Sidwell  <nathan@acm.org>
 
        PR c++/87531
diff --git a/gcc/testsuite/g++.dg/cpp2a/nested-inline-ns1.C b/gcc/testsuite/g++.dg/cpp2a/nested-inline-ns1.C
new file mode 100644 (file)
index 0000000..8c9573e
--- /dev/null
@@ -0,0 +1,29 @@
+// P1094R2
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wpedantic" }
+
+namespace A::inline B::C { // { dg-warning "nested inline namespace definitions only" "" { target c++17_down } }
+// { dg-warning "nested namespace definitions only available" "" { target c++14_down } .-1 }
+  int i;
+}
+
+namespace D::E::inline F { // { dg-warning "nested inline namespace definitions only" "" { target c++17_down } }
+// { dg-warning "nested namespace definitions only available" "" { target c++14_down } .-1 }
+  int j;
+}
+
+inline namespace X {
+  int x;
+}
+
+// Make sure the namespaces are marked inline.
+void
+g ()
+{
+  A::B::C::i++;
+  A::C::i++;
+  D::E::j++;
+  D::E::F::j++;
+  X::x++;
+  x++;
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/nested-inline-ns2.C b/gcc/testsuite/g++.dg/cpp2a/nested-inline-ns2.C
new file mode 100644 (file)
index 0000000..9b5f2ca
--- /dev/null
@@ -0,0 +1,26 @@
+// P1094R2
+// { dg-do compile { target c++2a } }
+
+inline namespace A::B { // { dg-error "a nested namespace definition cannot be inline" }
+  int i;
+}
+
+namespace inline C::D { // { dg-error "expected|does not name a type" }
+  int i;
+}
+
+namespace E::F inline { // { dg-error "expected" }
+  int i;
+}
+
+namespace inline G { // { dg-error "expected|does not name a type" }
+  int i;
+}
+
+inline namespace inline H { // { dg-error "expected|does not name a type" }
+  int i;
+}
+
+inline namespace inline I::J { // { dg-error "expected|does not name a type" }
+  int i;
+}