PR c++/67074 - namespace aliases
authorNathan Sidwell <nathan@acm.org>
Tue, 20 Jun 2017 12:53:11 +0000 (12:53 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Tue, 20 Jun 2017 12:53:11 +0000 (12:53 +0000)
PR c++/67074 - namespace aliases
* decl.c (duplicate_decls): Don't error here on mismatched
namespace alias.
* name-lookup.c (name_lookup::add_value): Matching namespaces are
not ambiguous.
(diagnose_name_conflict): Namespaces are never redeclarations.
(update_binding): An alias can match a real namespace.

PR c++/67074
* g++.dg/lookup/pr67074.C: New.
* g++.dg/parse/namespace-alias-1.C: Adjust.

From-SVN: r249408

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

index 10d1ebd4859e5bce42875893bd2961a36f064d84..3ed58b260d29f9226fafef8af4ddb940b8b76de2 100644 (file)
@@ -1,3 +1,13 @@
+2017-06-20  Nathan Sidwell  <nathan@acm.org>
+
+       PR c++/67074 - namespace aliases
+       * decl.c (duplicate_decls): Don't error here on mismatched
+       namespace alias.
+       * name-lookup.c (name_lookup::add_value): Matching namespaces are
+       not ambiguous.
+       (diagnose_name_conflict): Namespaces are never redeclarations.
+       (update_binding): An alias can match a real namespace.
+
 2017-06-19  Jason Merrill  <jason@redhat.com>
 
        PR c++/80562 - ICE with constexpr if.
index 16cd2a50ffd9bf3c584c73b0dab490c5d7237d88..bb7c56f6a8d6003fd5b8a7327ecab68e1261b792 100644 (file)
@@ -1751,17 +1751,9 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
          && (DECL_NAMESPACE_ALIAS (newdecl)
              == DECL_NAMESPACE_ALIAS (olddecl)))
        return olddecl;
-      /* [namespace.alias]
-
-        A namespace-name or namespace-alias shall not be declared as
-        the name of any other entity in the same declarative region.
-        A namespace-name defined at global scope shall not be
-        declared as the name of any other entity in any global scope
-        of the program.  */
-      error ("conflicting declaration of namespace %q+D", newdecl);
-      inform (DECL_SOURCE_LOCATION (olddecl),
-             "previous declaration of namespace %qD here", olddecl);
-      return error_mark_node;
+
+      /* Leave it to update_binding to merge or report error.  */
+      return NULL_TREE;
     }
   else
     {
index e91b89cf15b29e0fe68ed9f486973440346aa323..54c9d7b6341d3278f25619ebeeb41fd4a2bb05c1 100644 (file)
@@ -450,7 +450,13 @@ name_lookup::add_value (tree new_val)
   else if ((TREE_CODE (value) == TYPE_DECL
            && TREE_CODE (new_val) == TYPE_DECL
            && same_type_p (TREE_TYPE (value), TREE_TYPE (new_val))))
-    ;
+    /* Typedefs to the same type. */;
+  else if (TREE_CODE (value) == NAMESPACE_DECL
+          && TREE_CODE (new_val) == NAMESPACE_DECL
+          && ORIGINAL_NAMESPACE (value) == ORIGINAL_NAMESPACE (new_val))
+    /* Namespace (possibly aliased) to the same namespace.  Locate
+       the namespace*/
+    value = ORIGINAL_NAMESPACE (value);
   else
     {
       if (deduping)
@@ -1630,10 +1636,10 @@ static void
 diagnose_name_conflict (tree decl, tree bval)
 {
   if (TREE_CODE (decl) == TREE_CODE (bval)
-      && (TREE_CODE (decl) != TYPE_DECL
-         || (DECL_ARTIFICIAL (decl) && DECL_ARTIFICIAL (bval))
-         || (!DECL_ARTIFICIAL (decl) && !DECL_ARTIFICIAL (bval)))
+      && TREE_CODE (decl) != NAMESPACE_DECL
       && !DECL_DECLARES_FUNCTION_P (decl)
+      && (TREE_CODE (decl) != TYPE_DECL
+         || DECL_ARTIFICIAL (decl) == DECL_ARTIFICIAL (bval))
       && CP_DECL_CONTEXT (decl) == CP_DECL_CONTEXT (bval))
     error ("redeclaration of %q#D", decl);
   else
@@ -1809,15 +1815,14 @@ update_binding (cp_binding_level *level, cxx_binding *binding, tree *slot,
     }
   else if (TREE_CODE (old) == NAMESPACE_DECL)
     {
-      if (DECL_NAMESPACE_ALIAS (old) && DECL_NAMESPACE_ALIAS (decl)
-         && ORIGINAL_NAMESPACE (old) == ORIGINAL_NAMESPACE (decl))
-       /* In a declarative region, a namespace-alias-definition can be
-          used to redefine a namespace-alias declared in that declarative
-          region to refer only to the namespace to which it already
-          refers.  [namespace.alias] */
-       return old;
-      else
+      /* Two maybe-aliased namespaces.  If they're to the same target
+        namespace, that's ok.  */
+      if (ORIGINAL_NAMESPACE (old) != ORIGINAL_NAMESPACE (decl))
        goto conflict;
+
+      /* The new one must be an alias at this point.  */
+      gcc_assert (DECL_NAMESPACE_ALIAS (decl));
+      return old;
     }
   else if (TREE_CODE (old) == VAR_DECL)
     {
index 28c97de8f3b6ccc5abf66aed9dfc244b2dc138b8..ee1a4e265b16196bd120b8bdcbc93dad6be1cada 100644 (file)
@@ -1,3 +1,9 @@
+2017-06-20  Nathan Sidwell  <nathan@acm.org>
+
+       PR c++/67074
+       * g++.dg/lookup/pr67074.C: New.
+       * g++.dg/parse/namespace-alias-1.C: Adjust.
+
 2017-06-20  Richard Biener  <rguenther@suse.de>
 
        PR middle-end/81097
diff --git a/gcc/testsuite/g++.dg/lookup/pr67074.C b/gcc/testsuite/g++.dg/lookup/pr67074.C
new file mode 100644 (file)
index 0000000..ce31ede
--- /dev/null
@@ -0,0 +1,18 @@
+// PR c++/67074 namespace aliases to the same place.
+
+namespace P {
+  namespace X {
+    static int i = 1;
+  }
+}
+namespace Q {
+  namespace X = P::X;
+}
+
+using namespace P;
+using namespace Q;
+
+void Frob () { X::i; }
+
+namespace N {}
+namespace N = N;
index 5986ab69d0064e901a71686997218ebebe367a06..220d5f9decd12ae44a80b35a6299583775ba7c76 100644 (file)
@@ -3,7 +3,7 @@
 namespace N
 {
   namespace M = N;  // { dg-message "previous declaration" }
-  namespace M {}    // { dg-error "declaration of namespace" }
+  namespace M {}    // { dg-error "conflicts with a previous declaration" }
 }
 
 namespace A