From 322763f5df41223003720e8333c011b953bc1b4f Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Tue, 16 May 2017 11:32:40 +0000 Subject: [PATCH] cp-tree.h (SCOPE_DEPTH): New. * cp-tree.h (SCOPE_DEPTH): New. * name-lookup.h (is_nested_namespace): Declare. * name-lookup.c (is_nested_namespace): New. (is_ancestor): Use it. (set_decl_namespace): Likewise. (push_namespace): Set SCOPE_DEPTH. * pt.c (check_specialization_namespace): Use is_nested_namespace. (check_unqualigied_spec_or_inst): Likewise. From-SVN: r248095 --- gcc/cp/ChangeLog | 11 +++++++++++ gcc/cp/cp-tree.h | 5 +++++ gcc/cp/name-lookup.c | 41 ++++++++++++++++++++++++++++++++++------- gcc/cp/name-lookup.h | 2 ++ gcc/cp/pt.c | 10 ++++------ 5 files changed, 56 insertions(+), 13 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index fe99fa7..120d2b0 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +2017-05-16 Nathan Sidwell + + * cp-tree.h (SCOPE_DEPTH): New. + * name-lookup.h (is_nested_namespace): Declare. + * name-lookup.c (is_nested_namespace): New. + (is_ancestor): Use it. + (set_decl_namespace): Likewise. + (push_namespace): Set SCOPE_DEPTH. + * pt.c (check_specialization_namespace): Use is_nested_namespace. + (check_unqualigied_spec_or_inst): Likewise. + 2017-05-15 Nathan Sidwell PR c++/79369 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 85cdf07..8244a76 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2917,6 +2917,11 @@ struct GTY(()) lang_decl { #define LOCAL_CLASS_P(NODE) \ (decl_function_context (TYPE_MAIN_DECL (NODE)) != NULL_TREE) +/* The nesting depth of namespace, class or function. Makes is_ancestor much + simpler. Only 8 bits available. */ +#define SCOPE_DEPTH(NODE) \ + (NAMESPACE_DECL_CHECK (NODE)->base.u.bits.address_space) + /* Whether the namepace is an inline namespace. */ #define DECL_NAMESPACE_INLINE_P(NODE) \ TREE_LANG_FLAG_0 (NAMESPACE_DECL_CHECK (NODE)) diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 375376a..7b4d27f 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -3327,6 +3327,25 @@ do_local_using_decl (tree decl, tree scope, tree name) cp_emit_debug_info_for_using (orig_decl, current_scope()); } +/* Returns true if ANCESTOR encloses DESCENDANT, including matching. + Both are namespaces. */ + +bool +is_nested_namespace (tree ancestor, tree descendant, bool inline_only) +{ + int depth = SCOPE_DEPTH (ancestor); + + if (!depth && !inline_only) + /* The global namespace encloses everything. */ + return true; + + while (SCOPE_DEPTH (descendant) > depth + && (!inline_only || DECL_NAMESPACE_INLINE_P (descendant))) + descendant = CP_DECL_CONTEXT (descendant); + + return ancestor == descendant; +} + /* Returns true if ROOT (a namespace, class, or function) encloses CHILD. CHILD may be either a class type or a namespace. */ @@ -3343,19 +3362,22 @@ is_ancestor (tree root, tree child) if (root == global_namespace) return true; - while (true) + /* Search until we reach namespace scope. */ + while (TREE_CODE (child) != NAMESPACE_DECL) { - /* If we've run out of scopes, stop. */ - if (!child) - return false; /* 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 = DECL_CONTEXT (child); + child = CP_DECL_CONTEXT (child); } + + if (TREE_CODE (root) == NAMESPACE_DECL) + return is_nested_namespace (root, child); + + return false; } /* Enter the class or namespace scope indicated by T suitable for name @@ -4076,7 +4098,7 @@ set_decl_namespace (tree decl, tree scope, bool friendp) scope = ORIGINAL_NAMESPACE (scope); /* It is ok for friends to be qualified in parallel space. */ - if (!friendp && !is_ancestor (current_namespace, scope)) + if (!friendp && !is_nested_namespace (current_namespace, scope)) error ("declaration of %qD not in a namespace surrounding %qD", decl, scope); DECL_CONTEXT (decl) = FROB_CONTEXT (scope); @@ -4153,7 +4175,7 @@ set_decl_namespace (tree decl, tree scope, bool friendp) } if (found) { - if (!is_associated_namespace (scope, CP_DECL_CONTEXT (found))) + if (!is_nested_namespace (scope, CP_DECL_CONTEXT (found), true)) goto complain; if (DECL_HIDDEN_FRIEND_P (found)) { @@ -6499,6 +6521,11 @@ push_namespace (tree name, bool make_inline) if (!ns) { ns = build_lang_decl (NAMESPACE_DECL, name, void_type_node); + SCOPE_DEPTH (ns) = SCOPE_DEPTH (current_namespace) + 1; + if (!SCOPE_DEPTH (ns)) + /* We only allow depth 255. */ + sorry ("cannot nest more than %d namespaces", + SCOPE_DEPTH (current_namespace)); DECL_CONTEXT (ns) = FROB_CONTEXT (current_namespace); new_ns = true; diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h index 824ea33..4d0fe63 100644 --- a/gcc/cp/name-lookup.h +++ b/gcc/cp/name-lookup.h @@ -292,6 +292,8 @@ extern void print_binding_stack (void); extern void pop_everything (void); extern void keep_next_level (bool); extern bool is_ancestor (tree ancestor, tree descendant); +extern bool is_nested_namespace (tree parent, tree descendant, + bool inline_only = false); extern tree push_scope (tree); extern void pop_scope (tree); extern tree push_inner_scope (tree); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index e7e2aa6..cc38e81 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -784,9 +784,7 @@ check_specialization_namespace (tree tmpl) return false; } - if (cxx_dialect < cxx11 - ? is_associated_namespace (current_namespace, tpl_ns) - : is_ancestor (current_namespace, tpl_ns)) + if (is_nested_namespace (current_namespace, tpl_ns, cxx_dialect < cxx11)) /* Same or enclosing namespace. */ return true; else @@ -810,7 +808,7 @@ check_explicit_instantiation_namespace (tree spec) /* DR 275: An explicit instantiation shall appear in an enclosing namespace of its template. */ ns = decl_namespace_context (spec); - if (!is_ancestor (current_namespace, ns)) + if (!is_nested_namespace (current_namespace, ns)) permerror (input_location, "explicit instantiation of %qD in namespace %qD " "(which does not enclose namespace %qD)", spec, current_namespace, ns); @@ -2594,8 +2592,8 @@ check_unqualified_spec_or_inst (tree t, location_t loc) { tree tmpl = most_general_template (t); if (DECL_NAMESPACE_SCOPE_P (tmpl) - && !is_associated_namespace (current_namespace, - CP_DECL_CONTEXT (tmpl))) + && !is_nested_namespace (current_namespace, + CP_DECL_CONTEXT (tmpl), true)) { if (processing_specialization) permerror (loc, "explicit specialization of %qD outside its " -- 2.7.4