[C++ PATCH] structure tag lookup
authorNathan Sidwell <nathan@acm.org>
Tue, 4 Jun 2019 15:17:29 +0000 (15:17 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Tue, 4 Jun 2019 15:17:29 +0000 (15:17 +0000)
https://gcc.gnu.org/ml/gcc-patches/2019-06/msg00179.html
* name-lookup.c (lookup_type_scope_1): Reimplement, handle local
and namespace scopes separately.

From-SVN: r271912

gcc/cp/ChangeLog
gcc/cp/name-lookup.c

index 21b82df92c42bd485b9f70e150fb0c7a03fe2eeb..c28faf9014449a75cbb3c77d5de5be214dff398f 100644 (file)
@@ -1,3 +1,8 @@
+2019-06-04  Nathan Sidwell  <nathan@acm.org>
+
+       * name-lookup.c (lookup_type_scope_1): Reimplement, handle local
+       and namespace scopes separately.
+
 2019-06-04  Harald van Dijk  <harald@gigawatt.nl>
 
        PR c++/60531 - Wrong error about unresolved overloaded function
index 0bea41ffb91bf8f039e6760d64fcca43f1aaf4d7..632253a0d8c38732cfd896b3fa3e39f31b8cefa6 100644 (file)
@@ -6460,81 +6460,66 @@ lookup_name_prefer_type (tree name, int prefer_type)
 static tree
 lookup_type_scope_1 (tree name, tag_scope scope)
 {
-  cxx_binding *iter = NULL;
-  tree val = NULL_TREE;
-  cp_binding_level *level = NULL;
-
-  /* Look in non-namespace scope first.  */
-  if (current_binding_level->kind != sk_namespace)
-    iter = outer_binding (name, NULL, /*class_p=*/ true);
-  for (; iter; iter = outer_binding (name, iter, /*class_p=*/ true))
-    {
-      /* Check if this is the kind of thing we're looking for.
-        If SCOPE is TS_CURRENT, also make sure it doesn't come from
-        base class.  For ITER->VALUE, we can simply use
-        INHERITED_VALUE_BINDING_P.  For ITER->TYPE, we have to use
-        our own check.
-
-        We check ITER->TYPE before ITER->VALUE in order to handle
-          typedef struct C {} C;
-        correctly.  */
-
-      if (qualify_lookup (iter->type, LOOKUP_PREFER_TYPES)
-         && (scope != ts_current
-             || LOCAL_BINDING_P (iter)
-             || DECL_CONTEXT (iter->type) == iter->scope->this_entity))
-       val = iter->type;
-      else if ((scope != ts_current
-               || !INHERITED_VALUE_BINDING_P (iter))
-              && qualify_lookup (iter->value, LOOKUP_PREFER_TYPES))
-       val = iter->value;
-
-      if (val)
-       break;
-    }
+  cp_binding_level *b = current_binding_level;
 
-  /* Look in namespace scope.  */
-  if (val)
-    level = iter->scope;
-  else
-    {
-      tree ns = current_decl_namespace ();
+  if (b->kind != sk_namespace)
+    /* Look in non-namespace scopes.  */
+    for (cxx_binding *iter = NULL;
+        (iter = outer_binding (name, iter, /*class_p=*/ true)); )
+      {
+       /* First check we're supposed to be looking in this scope --
+          if we're not, we're done.  */
+       for (; b != iter->scope; b = b->level_chain)
+         if (!(b->kind == sk_cleanup
+               || b->kind == sk_template_parms
+               || b->kind == sk_function_parms
+               || (b->kind == sk_class
+                   && scope == ts_within_enclosing_non_class)))
+           return NULL_TREE;
+
+       /* Check if this is the kind of thing we're looking for.  If
+          SCOPE is TS_CURRENT, also make sure it doesn't come from
+          base class.  For ITER->VALUE, we can simply use
+          INHERITED_VALUE_BINDING_P.  For ITER->TYPE, we have to
+          use our own check.
+
+          We check ITER->TYPE before ITER->VALUE in order to handle
+            typedef struct C {} C;
+          correctly.  */
+       if (tree type = iter->type)
+         if ((scope != ts_current
+              || LOCAL_BINDING_P (iter)
+              || DECL_CONTEXT (type) == iter->scope->this_entity)
+             && qualify_lookup (iter->type, LOOKUP_PREFER_TYPES))
+           return iter->type;
+
+       if ((scope != ts_current
+            || !INHERITED_VALUE_BINDING_P (iter))
+           && qualify_lookup (iter->value, LOOKUP_PREFER_TYPES))
+         return iter->value;
+      }
 
-      if (tree *slot = find_namespace_slot (ns, name))
-       {
-         /* If this is the kind of thing we're looking for, we're done.  */
-         if (tree type = MAYBE_STAT_TYPE (*slot))
-           if (qualify_lookup (type, LOOKUP_PREFER_TYPES))
-             val = type;
-         if (!val)
-           {
-             if (tree decl = MAYBE_STAT_DECL (*slot))
-               if (qualify_lookup (decl, LOOKUP_PREFER_TYPES))
-                 val = decl;
-           }
-         level = NAMESPACE_LEVEL (ns);
-       }
-    }
+  /* Now check if we can look in namespace scope.  */
+  for (; b->kind != sk_namespace; b = b->level_chain)
+    if (!(b->kind == sk_cleanup
+         || b->kind == sk_template_parms
+         || b->kind == sk_function_parms
+         || (b->kind == sk_class
+             && scope == ts_within_enclosing_non_class)))
+      return NULL_TREE;
 
-  /* Type found, check if it is in the allowed scopes, ignoring cleanup
-     and template parameter scopes.  */
-  if (val)
+  /* Look in the innermost namespace.  */
+  tree ns = b->this_entity;
+  if (tree *slot = find_namespace_slot (ns, name))
     {
-      cp_binding_level *b = current_binding_level;
-      while (b)
-       {
-         if (level == b)
-           return val;
+      /* If this is the kind of thing we're looking for, we're done.  */
+      if (tree type = MAYBE_STAT_TYPE (*slot))
+       if (qualify_lookup (type, LOOKUP_PREFER_TYPES))
+         return type;
 
-         if (b->kind == sk_cleanup || b->kind == sk_template_parms
-             || b->kind == sk_function_parms)
-           b = b->level_chain;
-         else if (b->kind == sk_class
-                  && scope == ts_within_enclosing_non_class)
-           b = b->level_chain;
-         else
-           break;
-       }
+      if (tree decl = MAYBE_STAT_DECL (*slot))
+       if (qualify_lookup (decl, LOOKUP_PREFER_TYPES))
+         return decl;
     }
 
   return NULL_TREE;