From: Nathan Sidwell Date: Mon, 27 Jan 2020 13:49:43 +0000 (-0800) Subject: c++: Bogus error using namespace alias [PR91826] X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=feaa1640b3543c7c3a1f3a788bc449a3638cb780;p=gcc.git c++: Bogus error using namespace alias [PR91826] My changes to is_nested_namespace broke is_ancestor's use where a namespace alias might be passed in. This changes is_ancestor to look through the alias. PR c++/91826 * name-lookup.c (is_ancestor): Allow CHILD to be a namespace alias. --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b51d67fad2e..5324a6e574e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2020-01-27 Nathan Sidwell + + PR c++/91826 + * name-lookup.c (is_ancestor): Allow CHILD to be a namespace alias. + 2020-01-26 Jason Merrill PR c++/90992 diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 572100766cb..2447166a444 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -4012,38 +4012,46 @@ is_nested_namespace (tree ancestor, tree descendant, bool inline_only) return ancestor == descendant; } -/* Returns true if ROOT (a namespace, class, or function) encloses - CHILD. CHILD may be either a class type or a namespace. */ +/* Returns true if ROOT (a non-alias namespace, class, or function) + encloses CHILD. CHILD may be either a class type or a namespace + (maybe alias). */ bool is_ancestor (tree root, tree child) { - gcc_assert ((TREE_CODE (root) == NAMESPACE_DECL - || TREE_CODE (root) == FUNCTION_DECL - || CLASS_TYPE_P (root))); - gcc_assert ((TREE_CODE (child) == NAMESPACE_DECL - || CLASS_TYPE_P (child))); + gcc_checking_assert ((TREE_CODE (root) == NAMESPACE_DECL + && !DECL_NAMESPACE_ALIAS (root)) + || TREE_CODE (root) == FUNCTION_DECL + || CLASS_TYPE_P (root)); + gcc_checking_assert (TREE_CODE (child) == NAMESPACE_DECL + || CLASS_TYPE_P (child)); - /* The global namespace encloses everything. */ + /* The global namespace encloses everything. Early-out for the + common case. */ if (root == global_namespace) return true; - /* Search until we reach namespace scope. */ + /* Search CHILD until we reach namespace scope. */ while (TREE_CODE (child) != NAMESPACE_DECL) { /* If we've reached the ROOT, it encloses CHILD. */ if (root == child) return true; + /* Go out one level. */ if (TYPE_P (child)) child = TYPE_NAME (child); child = CP_DECL_CONTEXT (child); } - if (TREE_CODE (root) == NAMESPACE_DECL) - return is_nested_namespace (root, child); + if (TREE_CODE (root) != NAMESPACE_DECL) + /* Failed to meet the non-namespace we were looking for. */ + return false; + + if (tree alias = DECL_NAMESPACE_ALIAS (child)) + child = alias; - return false; + return is_nested_namespace (root, child); } /* Enter the class or namespace scope indicated by T suitable for name diff --git a/gcc/testsuite/g++.dg/lookup/pr91826.C b/gcc/testsuite/g++.dg/lookup/pr91826.C new file mode 100644 index 00000000000..2b313ece8a7 --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/pr91826.C @@ -0,0 +1,16 @@ +// PR 91826 bogus error with aliased namespace + +namespace N1 { class C1; } +namespace A1 = N1; +class A1::C1 {}; //Ok + +namespace N2 +{ + namespace N { class C2; } + namespace A2 = N; + class A2::C2 {}; // { dg_bogus "does not enclose" } +} + +namespace N3 { namespace N { class C3; } } +namespace A3 = N3::N; +class A3::C3 {}; //Ok