cp-tree.h (SCOPE_DEPTH): New.
authorNathan Sidwell <nathan@acm.org>
Tue, 16 May 2017 11:32:40 +0000 (11:32 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Tue, 16 May 2017 11:32:40 +0000 (11:32 +0000)
* 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
gcc/cp/cp-tree.h
gcc/cp/name-lookup.c
gcc/cp/name-lookup.h
gcc/cp/pt.c

index fe99fa779ec1578e66205b3162cf83889c2dbec6..120d2b060628772f8e2194677538651592ad6550 100644 (file)
@@ -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
index 85cdf07cb91905263197cbc1897cb4e4a549119f..8244a768c91050b82fa424fe7ed1c6d042b13b84 100644 (file)
@@ -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))
index 375376a89a8d1c47ec6e1817d9d8d8573c3d4286..7b4d27f44d02d946606a431c2151d66b900856fc 100644 (file)
@@ -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;
 
index 824ea3386a70eda0a66749e9a87a78ac07a0323f..4d0fe632093763956040c2b045a375701b8d41aa 100644 (file)
@@ -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);
index e7e2aa669f735bce614c0bee8f24b8eeec8d5b12..cc38e819f32403f2ddb4172908d65eb313adea2c 100644 (file)
@@ -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 "