aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@acm.org>2017-05-16 11:32:40 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2017-05-16 11:32:40 +0000
commit322763f5df41223003720e8333c011b953bc1b4f (patch)
treee7909fa2339db555bb0f5e64f7841591c5fff828 /gcc
parent51f01fc387a2fb580108ccb27f945ee4bd1cfd34 (diff)
downloadgcc-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/ChangeLog11
-rw-r--r--gcc/cp/cp-tree.h5
-rw-r--r--gcc/cp/name-lookup.c41
-rw-r--r--gcc/cp/name-lookup.h2
-rw-r--r--gcc/cp/pt.c10
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 "