diff options
author | Nathan Sidwell <nathan@acm.org> | 2017-05-16 11:32:40 +0000 |
---|---|---|
committer | Nathan Sidwell <nathan@gcc.gnu.org> | 2017-05-16 11:32:40 +0000 |
commit | 322763f5df41223003720e8333c011b953bc1b4f (patch) | |
tree | e7909fa2339db555bb0f5e64f7841591c5fff828 /gcc | |
parent | 51f01fc387a2fb580108ccb27f945ee4bd1cfd34 (diff) | |
download | gcc-322763f5df41223003720e8333c011b953bc1b4f.zip gcc-322763f5df41223003720e8333c011b953bc1b4f.tar.gz gcc-322763f5df41223003720e8333c011b953bc1b4f.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 5 | ||||
-rw-r--r-- | gcc/cp/name-lookup.c | 41 | ||||
-rw-r--r-- | gcc/cp/name-lookup.h | 2 | ||||
-rw-r--r-- | 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 <nathan@acm.org> + + * 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 <nathan@acm.org> 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 " |