From: Nathan Sidwell Date: Tue, 29 Sep 2020 16:38:34 +0000 (-0700) Subject: c++: Name lookup simplifications X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=adcf8a11c772e7a0c64d4ae3eb19a520566f32b9;p=gcc.git c++: Name lookup simplifications Here are a few cleanups, prior to landing the hidden decl changes. 1) Clear cxx_binding flags in the allocator, not at each user of the allocator. 2) Refactor update_binding. The logic was getting too convoluted. 3) Set friendliness and anticipatedness before pushing a template decl (not after). gcc/cp/ * name-lookup.c (create_local_binding): Do not clear INHERITED_VALUE_BINDING_P here. (name_lookup::process_binding): Move done hidden-decl triage to ... (name_lookup::search_namespace_only): ... here, its only caller. (cxx_binding_make): Clear flags here. (push_binding): Not here. (pop_local_binding): RAII. (update_binding): Refactor. (do_pushdecl): Assert we're never revealing a local binding. (do_pushdecl_with_scope): Directly call do_pushdecl. (get_class_binding): Do not clear LOCAL_BINDING_P here. * pt.c (push_template_decl): Set friend & anticipated before pushing. --- diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index f195e81280a..89f1a4c5d64 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -77,7 +77,6 @@ create_local_binding (cp_binding_level *level, tree name) { cxx_binding *binding = cxx_binding_make (NULL, NULL); - INHERITED_VALUE_BINDING_P (binding) = false; LOCAL_BINDING_P (binding) = true; binding->scope = level; binding->previous = IDENTIFIER_BINDING (name); @@ -480,22 +479,17 @@ name_lookup::add_type (tree new_type) } /* Process a found binding containing NEW_VAL and NEW_TYPE. Returns - true if we actually found something noteworthy. */ + true if we actually found something noteworthy. Hiddenness has + already been handled in the caller. */ bool name_lookup::process_binding (tree new_val, tree new_type) { /* Did we really see a type? */ if (new_type - && ((want & LOOK_want::TYPE_NAMESPACE) == LOOK_want::NAMESPACE - || (!bool (want & LOOK_want::HIDDEN_FRIEND) - && DECL_LANG_SPECIFIC (new_type) - && DECL_ANTICIPATED (new_type)))) + && (want & LOOK_want::TYPE_NAMESPACE) == LOOK_want::NAMESPACE) new_type = NULL_TREE; - if (new_val && !bool (want & LOOK_want::HIDDEN_FRIEND)) - new_val = ovl_skip_hidden (new_val); - /* Do we really see a value? */ if (new_val) switch (TREE_CODE (new_val)) @@ -544,8 +538,25 @@ name_lookup::search_namespace_only (tree scope) bool found = false; if (tree *binding = find_namespace_slot (scope, name)) - found |= process_binding (MAYBE_STAT_DECL (*binding), - MAYBE_STAT_TYPE (*binding)); + { + tree value = *binding, type = NULL_TREE; + + if (STAT_HACK_P (value)) + { + type = STAT_TYPE (value); + value = STAT_DECL (value); + + if (!bool (want & LOOK_want::HIDDEN_FRIEND) + && DECL_LANG_SPECIFIC (type) + && DECL_ANTICIPATED (type)) + type = NULL_TREE; + } + + if (!bool (want & LOOK_want::HIDDEN_FRIEND)) + value = ovl_skip_hidden (value); + + found |= process_binding (value, type); + } return found; } @@ -1954,15 +1965,17 @@ cxx_binding_init (cxx_binding *binding, tree value, tree type) static cxx_binding * cxx_binding_make (tree value, tree type) { - cxx_binding *binding; - if (free_bindings) - { - binding = free_bindings; - free_bindings = binding->previous; - } + cxx_binding *binding = free_bindings; + + if (binding) + free_bindings = binding->previous; else binding = ggc_alloc (); + /* Clear flags by default. */ + LOCAL_BINDING_P (binding) = false; + INHERITED_VALUE_BINDING_P (binding) = false; + cxx_binding_init (binding, value, type); return binding; @@ -2009,7 +2022,6 @@ push_binding (tree id, tree decl, cp_binding_level* level) /* Now, fill in the binding information. */ binding->previous = IDENTIFIER_BINDING (id); - INHERITED_VALUE_BINDING_P (binding) = 0; LOCAL_BINDING_P (binding) = (level != class_binding_level); /* And put it on the front of the list of bindings for ID. */ @@ -2022,8 +2034,6 @@ push_binding (tree id, tree decl, cp_binding_level* level) void pop_local_binding (tree id, tree decl) { - cxx_binding *binding; - if (id == NULL_TREE) /* It's easiest to write the loops that call this function without checking whether or not the entities involved have names. We @@ -2031,7 +2041,7 @@ pop_local_binding (tree id, tree decl) return; /* Get the innermost binding for ID. */ - binding = IDENTIFIER_BINDING (id); + cxx_binding *binding = IDENTIFIER_BINDING (id); /* The name should be bound. */ gcc_assert (binding != NULL); @@ -2356,9 +2366,16 @@ static tree update_binding (cp_binding_level *level, cxx_binding *binding, tree *slot, tree old, tree decl, bool hiding = false) { + tree old_type = NULL_TREE; + + if (!slot) + old_type = binding->type; + else if (STAT_HACK_P (*slot)) + old_type = STAT_TYPE (*slot); + tree to_val = decl; - tree old_type = slot ? MAYBE_STAT_TYPE (*slot) : binding->type; tree to_type = old_type; + bool local_overload = false; gcc_assert (level->kind == sk_namespace ? !binding : level->kind != sk_class && !slot); @@ -2375,16 +2392,20 @@ update_binding (cp_binding_level *level, cxx_binding *binding, tree *slot, if (old) { - /* Slide decl into the type slot, keep old unaltered */ + /* Put DECL into the type slot. */ + gcc_checking_assert (!to_type); to_type = decl; to_val = old; } + goto done; } if (old && DECL_IMPLICIT_TYPEDEF_P (old)) { - /* Slide old into the type slot. */ + /* OLD is an implicit typedef. Move it to to_type. */ + gcc_checking_assert (!to_type); + to_type = old; old = NULL_TREE; } @@ -2428,60 +2449,66 @@ update_binding (cp_binding_level *level, cxx_binding *binding, tree *slot, warning (OPT_Wshadow, "%q#D hides constructor for %q#D", decl, to_type); + local_overload = old && level->kind != sk_namespace; to_val = ovl_insert (decl, old); } - else if (!old) - ; - else if (TREE_CODE (old) != TREE_CODE (decl)) - /* Different kinds of decls conflict. */ - goto conflict; - else if (TREE_CODE (old) == TYPE_DECL) - { - if (same_type_p (TREE_TYPE (old), TREE_TYPE (decl))) - /* Two type decls to the same type. Do nothing. */ - return old; - else - goto conflict; - } - else if (TREE_CODE (old) == NAMESPACE_DECL) + else if (old) { - /* Two maybe-aliased namespaces. If they're to the same target - namespace, that's ok. */ - if (ORIGINAL_NAMESPACE (old) != ORIGINAL_NAMESPACE (decl)) + if (TREE_CODE (old) != TREE_CODE (decl)) + /* Different kinds of decls conflict. */ goto conflict; - - /* The new one must be an alias at this point. */ - gcc_assert (DECL_NAMESPACE_ALIAS (decl)); - return old; - } - else if (TREE_CODE (old) == VAR_DECL) - { - /* There can be two block-scope declarations of the same - variable, so long as they are `extern' declarations. */ - if (!DECL_EXTERNAL (old) || !DECL_EXTERNAL (decl)) - goto conflict; - else if (tree match = duplicate_decls (decl, old)) - return match; + else if (TREE_CODE (old) == TYPE_DECL) + { + if (same_type_p (TREE_TYPE (old), TREE_TYPE (decl))) + { + /* Two type decls to the same type. Do nothing. */ + gcc_checking_assert (!hiding); + return old; + } + else + goto conflict; + } + else if (TREE_CODE (old) == NAMESPACE_DECL) + { + /* Two maybe-aliased namespaces. If they're to the same target + namespace, that's ok. */ + if (ORIGINAL_NAMESPACE (old) != ORIGINAL_NAMESPACE (decl)) + goto conflict; + + /* The new one must be an alias at this point. */ + gcc_assert (DECL_NAMESPACE_ALIAS (decl) && !hiding); + return old; + } + else if (TREE_CODE (old) == VAR_DECL) + { + /* There can be two block-scope declarations of the same + variable, so long as they are `extern' declarations. */ + // FIXME: This is DECL_LOCAL_DECL_P type stuff. + if (!DECL_EXTERNAL (old) || !DECL_EXTERNAL (decl)) + goto conflict; + else if (tree match = duplicate_decls (decl, old)) + return match; + else + goto conflict; + } else - goto conflict; - } - else - { - conflict: - diagnose_name_conflict (decl, old); - to_val = NULL_TREE; + { + conflict: + diagnose_name_conflict (decl, old); + to_val = NULL_TREE; + } } done: if (to_val) { - if (level->kind == sk_namespace || to_type == decl || to_val == decl) - add_decl_to_level (level, decl); - else + if (local_overload) { gcc_checking_assert (binding->value && OVL_P (binding->value)); update_local_overload (binding, to_val); } + else + add_decl_to_level (level, decl); if (slot) { @@ -3059,12 +3086,8 @@ do_pushdecl (tree decl, bool hiding) tree head = iter.reveal_node (old); if (head != old) { - if (!ns) - { - update_local_overload (binding, head); - binding->value = head; - } - else if (STAT_HACK_P (*slot)) + gcc_checking_assert (ns); + if (STAT_HACK_P (*slot)) STAT_DECL (*slot) = head; else *slot = head; @@ -3859,7 +3882,7 @@ do_pushdecl_with_scope (tree x, cp_binding_level *level, bool hiding = false) current_function_decl = NULL_TREE; b = current_binding_level; current_binding_level = level; - x = pushdecl (x, hiding); + x = do_pushdecl (x, hiding); current_binding_level = b; current_function_decl = function_decl; } @@ -4398,8 +4421,6 @@ get_class_binding (tree name, cp_binding_level *scope) value_binding, type_binding, scope); - /* This is a class-scope binding, not a block-scope binding. */ - LOCAL_BINDING_P (binding) = 0; set_inherited_value_binding_p (binding, value_binding, class_type); } else diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 199fe658f71..a09633751ca 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -6018,16 +6018,16 @@ push_template_decl (tree decl, bool is_friend) if (!ctx && !(is_friend && template_class_depth (current_class_type) > 0)) { - tmpl = pushdecl_namespace_level (tmpl, /*hiding=*/is_friend); - if (tmpl == error_mark_node) - return error_mark_node; - /* Hide template friend classes that haven't been declared yet. */ if (is_friend && TREE_CODE (decl) == TYPE_DECL) { DECL_ANTICIPATED (tmpl) = 1; DECL_FRIEND_P (tmpl) = 1; } + + tmpl = pushdecl_namespace_level (tmpl, /*hiding=*/is_friend); + if (tmpl == error_mark_node) + return error_mark_node; } } else