From 4ebcf1c2194569884858b65454ec6cf479efc680 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Tue, 4 Jun 2019 15:17:29 +0000 Subject: [PATCH] [C++ PATCH] structure tag lookup 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 | 5 ++ gcc/cp/name-lookup.c | 125 +++++++++++++++++++------------------------ 2 files changed, 60 insertions(+), 70 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 21b82df92c4..c28faf90144 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2019-06-04 Nathan Sidwell + + * name-lookup.c (lookup_type_scope_1): Reimplement, handle local + and namespace scopes separately. + 2019-06-04 Harald van Dijk PR c++/60531 - Wrong error about unresolved overloaded function diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 0bea41ffb91..632253a0d8c 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -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; -- 2.30.2