From 71bbbd133f65c26f65709037401154362210560e Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Tue, 20 Jun 2017 12:53:11 +0000 Subject: [PATCH] PR c++/67074 - namespace aliases 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 | 10 +++++++ gcc/cp/decl.c | 14 ++------- gcc/cp/name-lookup.c | 29 +++++++++++-------- gcc/testsuite/ChangeLog | 6 ++++ gcc/testsuite/g++.dg/lookup/pr67074.C | 18 ++++++++++++ .../g++.dg/parse/namespace-alias-1.C | 2 +- 6 files changed, 55 insertions(+), 24 deletions(-) create mode 100644 gcc/testsuite/g++.dg/lookup/pr67074.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 10d1ebd4859..3ed58b260d2 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2017-06-20 Nathan Sidwell + + 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 PR c++/80562 - ICE with constexpr if. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 16cd2a50ffd..bb7c56f6a8d 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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 { diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index e91b89cf15b..54c9d7b6341 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -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) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 28c97de8f3b..ee1a4e265b1 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2017-06-20 Nathan Sidwell + + PR c++/67074 + * g++.dg/lookup/pr67074.C: New. + * g++.dg/parse/namespace-alias-1.C: Adjust. + 2017-06-20 Richard Biener 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 index 00000000000..ce31ede1588 --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/pr67074.C @@ -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; diff --git a/gcc/testsuite/g++.dg/parse/namespace-alias-1.C b/gcc/testsuite/g++.dg/parse/namespace-alias-1.C index 5986ab69d00..220d5f9decd 100644 --- a/gcc/testsuite/g++.dg/parse/namespace-alias-1.C +++ b/gcc/testsuite/g++.dg/parse/namespace-alias-1.C @@ -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 -- 2.30.2