This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PR c++/67074] Namespace aliases to same name


This patch fixes a couple of places where namespace aliases refer to the same namespace. These are not ambiguous or conflicting.

Firstly, aliases of the same name may exist in namespaces searched via using directives. Those should be merged in lookup, which is the change to add_value.

Secondly, an alias to an existing namespace of the same name in the same scope is ok. The change to duplicate_decls calms it down -- all it should do is say 'yup, this is the same decl', and disregard conflictingness -- that's pushdecl's problem. Which is the change to update_binding. As it happens, duplicate_decls will have already eliminated matching aliases, but it needs to be taught to permit an alias to the same named namespace to be allowed.

And finally diagnose_name_conflict needs to treat namespaces as always conflicting. It's confusing to say the second instance is a redeclaration.

Applied to trunk.

nathan
--
Nathan Sidwell
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.

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

Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 249384)
+++ cp/decl.c	(working copy)
@@ -1751,17 +1751,9 @@ duplicate_decls (tree newdecl, tree oldd
 	  && (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: cp/name-lookup.c
===================================================================
--- cp/name-lookup.c	(revision 249385)
+++ cp/name-lookup.c	(working copy)
@@ -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,
     }
   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: testsuite/g++.dg/lookup/pr67074.C
===================================================================
--- testsuite/g++.dg/lookup/pr67074.C	(nonexistent)
+++ testsuite/g++.dg/lookup/pr67074.C	(working copy)
@@ -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: testsuite/g++.dg/parse/namespace-alias-1.C
===================================================================
--- testsuite/g++.dg/parse/namespace-alias-1.C	(revision 249384)
+++ testsuite/g++.dg/parse/namespace-alias-1.C	(working copy)
@@ -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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]