Implement DR2061
authorNathan Sidwell <nathan@acm.org>
Fri, 26 May 2017 18:13:53 +0000 (18:13 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Fri, 26 May 2017 18:13:53 +0000 (18:13 +0000)
gcc/
Implement DR2061
* name-lookup.c (push_inline_namespaces): New.
(push_namespace): Look inside inline namespaces.

testsuite/
* g++.dg/cpp0x/dr2061.C: New.
* g++.dg/parse/namespace-alias-1.C: Add more test.

From-SVN: r248521

gcc/cp/ChangeLog
gcc/cp/name-lookup.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/dr2061.C [new file with mode: 0644]
gcc/testsuite/g++.dg/parse/namespace-alias-1.C

index 1890449..8e3530f 100644 (file)
@@ -1,5 +1,9 @@
 2017-05-26  Nathan Sidwell  <nathan@acm.org>
 
+       Implement DR2061
+       * name-lookup.c (push_inline_namespaces): New.
+       (push_namespace): Look inside inline namespaces.
+
        Inline and using namespace representation change.
        * cp-tree.h (struct lang_decl_ns): Delete ns_using.  Add usings,
        inlinees as vector.
index dc03877..9c03901 100644 (file)
@@ -6057,6 +6057,23 @@ pushdecl_top_level_and_finish (tree x, tree init)
   return x;
 }
 
+/* Enter the namespaces from current_namerspace to NS.  */
+
+static int
+push_inline_namespaces (tree ns)
+{
+  int count = 0;
+  if (ns != current_namespace)
+    {
+      gcc_assert (ns != global_namespace);
+      count += push_inline_namespaces (CP_DECL_CONTEXT (ns));
+      resume_scope (NAMESPACE_LEVEL (ns));
+      current_namespace = ns;
+      count++;
+    }
+  return count;
+}
+
 /* Push into the scope of the NAME namespace.  If NAME is NULL_TREE,
    then we enter an anonymous namespace.  If MAKE_INLINE is true, then
    we create an inline namespace (it is up to the caller to check upon
@@ -6076,43 +6093,36 @@ push_namespace (tree name, bool make_inline)
   if (!name)
     name = anon_identifier;
 
-  /* Check whether this is an extended namespace definition.  */
-  tree ns = get_namespace_binding (current_namespace, name);
-  if (ns && TREE_CODE (ns) == NAMESPACE_DECL)
-    {
-      if (tree dna = DECL_NAMESPACE_ALIAS (ns))
-       {
-         /* We do some error recovery for, eg, the redeclaration of M
-            here:
-
-            namespace N {}
-            namespace M = N;
-            namespace M {}
-
-            However, in nasty cases like:
-
-            namespace N
-            {
-              namespace M = N;
-              namespace M {}
-            }
-
-            we just error out below, in duplicate_decls.  */
-         if (NAMESPACE_LEVEL (dna)->level_chain == current_binding_level)
-           {
-             error ("namespace alias %qD not allowed here, "
-                    "assuming %qD", ns, dna);
-             ns = dna;
-           }
-         else
-           ns = NULL_TREE;
-       }
-    }
-  else
-    ns = NULL_TREE;
+  tree ns = NULL_TREE;
+  {
+    name_lookup lookup (name, 0);
+    if (!lookup.search_qualified (current_namespace, /*usings=*/false))
+      ;
+    else if (TREE_CODE (lookup.value) != NAMESPACE_DECL)
+      ;
+    else if (tree dna = DECL_NAMESPACE_ALIAS (lookup.value))
+      {
+       /* A namespace alias is not allowed here, but if the alias
+          is for a namespace also inside the current scope,
+          accept it with a diagnostic.  That's better than dying
+          horribly.  */
+       if (is_nested_namespace (current_namespace, CP_DECL_CONTEXT (dna)))
+         {
+           error ("namespace alias %qD not allowed here, "
+                  "assuming %qD", lookup.value, dna);
+           ns = dna;
+         }
+      }
+    else
+      ns = lookup.value;
+  }
 
   bool new_ns = false;
-  if (!ns)
+  if (ns)
+    /* DR2061.  NS might be a member of an inline namespace.  We
+       need to push into those namespaces.  */
+    count += push_inline_namespaces (CP_DECL_CONTEXT (ns));
+  else
     {
       ns = build_lang_decl (NAMESPACE_DECL, name, void_type_node);
       SCOPE_DEPTH (ns) = SCOPE_DEPTH (current_namespace) + 1;
index 5136e4a..8eca177 100644 (file)
@@ -1,3 +1,8 @@
+2017-05-26  Nathan Sidwell  <nathan@acm.org>
+
+       * g++.dg/cpp0x/dr2061.C: New.
+       * g++.dg/parse/namespace-alias-1.C: Add more test.
+
 2017-05-26  Bin Cheng  <bin.cheng@arm.com>
 
        PR tree-optimization/80815
diff --git a/gcc/testsuite/g++.dg/cpp0x/dr2061.C b/gcc/testsuite/g++.dg/cpp0x/dr2061.C
new file mode 100644 (file)
index 0000000..302279b
--- /dev/null
@@ -0,0 +1,46 @@
+// { dg-do compile { target c++11 } }
+
+// DR2061, look inside inline namespace when pushing a namespace.
+
+inline namespace One
+{
+  namespace Term 
+  {
+  }
+  inline namespace Two
+  {
+    namespace Space
+    {
+    }
+  }
+}
+
+namespace Term
+{
+  void bob ();
+}
+
+namespace Space
+{
+  void bill ();
+}
+
+inline namespace Two
+{
+  void weed ();
+}
+
+void One::Term::bob () {}
+void One::Two::Space::bill () {}
+void One::Two::weed () {}
+
+void Thing ()
+{
+  Term::bob ();
+  Space::bill ();
+  weed ();
+}
+
+// { dg-final { scan-assembler "_ZN3One4Term3bobEv:" } }
+// { dg-final { scan-assembler "_ZN3One3Two5Space4billEv:" } }
+// { dg-final { scan-assembler "_ZN3One3Two4weedEv:" } }
index 4b44335..5986ab6 100644 (file)
@@ -5,3 +5,18 @@ namespace N
   namespace M = N;  // { dg-message "previous declaration" }
   namespace M {}    // { dg-error "declaration of namespace" }
 }
+
+namespace A
+{
+  namespace B 
+  {
+    namespace C
+    {
+    }
+  }
+
+  namespace D = B::C;
+  namespace D  // { dg-error "not allowed" }
+  {
+  }
+}