From 00aaae03db249e61dde41facbf373c3fcde38154 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Fri, 25 Sep 2020 10:24:09 -0700 Subject: [PATCH] c++: Replace tag_scope with TAG_how I always found tag_scope confusing, as it is not a scope, but a direction of how to lookup or insert an elaborated type tag. This replaces it with a enum class TAG_how. I also add a new value, HIDDEN_FRIEND, to distinguish the two cases of innermost-non-class insertion that we currently conflate. Also renamed 'lookup_type_scope' to 'lookup_elaborated_type', because again, we're not providing a scope to lookup in. gcc/cp/ * name-lookup.h (enum tag_scope): Replace with ... (enum class TAG_how): ... this. Add HIDDEN_FRIEND value. (lookup_type_scope): Replace with ... (lookup_elaborated_type): ... this. (pushtag): Use TAG_how, not tag_scope. * cp-tree.h (xref_tag): Parameter is TAG_how, not tag_scope. * decl.c (lookup_and_check_tag): Likewise. Adjust. (xref_tag_1, xref_tag): Likewise. adjust. (start_enum): Adjust lookup_and_check_tag call. * name-lookup.c (lookup_type_scope_1): Rename to ... (lookup_elaborated_type_1) ... here. Use TAG_how, not tag_scope. (lookup_type_scope): Rename to ... (lookup_elaborated_type): ... here. Use TAG_how, not tag_scope. (do_pushtag): Use TAG_how, not tag_scope. Adjust. (pushtag): Likewise. * parser.c (cp_parser_elaborated_type_specifier): Adjust. (cp_parser_class_head): Likewise. gcc/objcp/ * objcp-decl.c (objcp_start_struct): Use TAG_how not tag_scope. (objcp_xref_tag): Likewise. --- gcc/cp/cp-tree.h | 2 +- gcc/cp/decl.c | 58 ++++++++++++++++++--------------------- gcc/cp/name-lookup.c | 62 ++++++++++++++++++++---------------------- gcc/cp/name-lookup.h | 32 ++++++++++------------ gcc/cp/parser.c | 22 +++++++-------- gcc/objcp/objcp-decl.c | 4 +-- 6 files changed, 84 insertions(+), 96 deletions(-) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index bd78f00ba97..321bb959120 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6507,7 +6507,7 @@ extern void grok_special_member_properties (tree); extern bool grok_ctor_properties (const_tree, const_tree); extern bool grok_op_properties (tree, bool); extern tree xref_tag (tag_types, tree, - tag_scope = ts_current, + TAG_how = TAG_how::CURRENT_ONLY, bool tpl_header_p = false); extern void xref_basetypes (tree, tree); extern tree start_enum (tree, tree, tree, tree, bool, bool *); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 1709dd9a370..b481bbd7b7d 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -75,7 +75,7 @@ static void record_unknown_type (tree, const char *); static int member_function_or_else (tree, tree, enum overload_flags); static tree local_variable_p_walkfn (tree *, int *, void *); static const char *tag_name (enum tag_types); -static tree lookup_and_check_tag (enum tag_types, tree, tag_scope, bool); +static tree lookup_and_check_tag (enum tag_types, tree, TAG_how, bool); static void maybe_deduce_size_from_array_init (tree, tree); static void layout_var_decl (tree); static tree check_initializer (tree, tree, int, vec **); @@ -14862,11 +14862,10 @@ check_elaborated_type_specifier (enum tag_types tag_code, static tree lookup_and_check_tag (enum tag_types tag_code, tree name, - tag_scope scope, bool template_header_p) + TAG_how how, bool template_header_p) { - tree t; tree decl; - if (scope == ts_global) + if (how == TAG_how::GLOBAL) { /* First try ordinary name lookup, ignoring hidden class name injected via friend declaration. */ @@ -14879,16 +14878,16 @@ lookup_and_check_tag (enum tag_types tag_code, tree name, If we find one, that name will be made visible rather than creating a new tag. */ if (!decl) - decl = lookup_type_scope (name, ts_within_enclosing_non_class); + decl = lookup_elaborated_type (name, TAG_how::INNERMOST_NON_CLASS); } else - decl = lookup_type_scope (name, scope); + decl = lookup_elaborated_type (name, how); if (decl && (DECL_CLASS_TEMPLATE_P (decl) - /* If scope is ts_current we're defining a class, so ignore a - template template parameter. */ - || (scope != ts_current + /* If scope is TAG_how::CURRENT_ONLY we're defining a class, + so ignore a template template parameter. */ + || (how != TAG_how::CURRENT_ONLY && DECL_TEMPLATE_TEMPLATE_PARM_P (decl)))) decl = DECL_TEMPLATE_RESULT (decl); @@ -14898,11 +14897,10 @@ lookup_and_check_tag (enum tag_types tag_code, tree name, class C { class C {}; }; */ - if (scope == ts_current && DECL_SELF_REFERENCE_P (decl)) + if (how == TAG_how::CURRENT_ONLY && DECL_SELF_REFERENCE_P (decl)) { error ("%qD has the same name as the class in which it is " - "declared", - decl); + "declared", decl); return error_mark_node; } @@ -14922,10 +14920,10 @@ lookup_and_check_tag (enum tag_types tag_code, tree name, class C *c2; // DECL_SELF_REFERENCE_P is true }; */ - t = check_elaborated_type_specifier (tag_code, - decl, - template_header_p - | DECL_SELF_REFERENCE_P (decl)); + tree t = check_elaborated_type_specifier (tag_code, + decl, + template_header_p + | DECL_SELF_REFERENCE_P (decl)); if (template_header_p && t && CLASS_TYPE_P (t) && (!CLASSTYPE_TEMPLATE_INFO (t) || (!PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t))))) @@ -14969,7 +14967,7 @@ lookup_and_check_tag (enum tag_types tag_code, tree name, static tree xref_tag_1 (enum tag_types tag_code, tree name, - tag_scope scope, bool template_header_p) + TAG_how how, bool template_header_p) { enum tree_code code; tree context = NULL_TREE; @@ -14996,22 +14994,22 @@ xref_tag_1 (enum tag_types tag_code, tree name, make type node and push name. Name lookup is not required. */ tree t = NULL_TREE; if (!IDENTIFIER_ANON_P (name)) - t = lookup_and_check_tag (tag_code, name, scope, template_header_p); + t = lookup_and_check_tag (tag_code, name, how, template_header_p); if (t == error_mark_node) return error_mark_node; - if (scope != ts_current && t && current_class_type + if (how != TAG_how::CURRENT_ONLY && t && current_class_type && template_class_depth (current_class_type) && template_header_p) { if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM) return t; - /* Since SCOPE is not TS_CURRENT, we are not looking at a - definition of this tag. Since, in addition, we are currently - processing a (member) template declaration of a template - class, we must be very careful; consider: + /* Since HOW is not TAG_how::CURRENT_ONLY, we are not looking at + a definition of this tag. Since, in addition, we are + currently processing a (member) template declaration of a + template class, we must be very careful; consider: template struct S1 @@ -15057,7 +15055,7 @@ xref_tag_1 (enum tag_types tag_code, tree name, /* Mark it as a lambda type right now. Our caller will correct the value. */ CLASSTYPE_LAMBDA_EXPR (t) = error_mark_node; - t = pushtag (name, t, scope); + t = pushtag (name, t, how); } else { @@ -15083,7 +15081,7 @@ xref_tag_1 (enum tag_types tag_code, tree name, return error_mark_node; } - if (scope != ts_within_enclosing_non_class && TYPE_HIDDEN_P (t)) + if (how != TAG_how::HIDDEN_FRIEND && TYPE_HIDDEN_P (t)) { /* This is no longer an invisible friend. Make it visible. */ @@ -15108,12 +15106,10 @@ xref_tag_1 (enum tag_types tag_code, tree name, tree xref_tag (enum tag_types tag_code, tree name, - tag_scope scope, bool template_header_p) + TAG_how how, bool template_header_p) { - tree ret; - bool subtime; - subtime = timevar_cond_start (TV_NAME_LOOKUP); - ret = xref_tag_1 (tag_code, name, scope, template_header_p); + bool subtime = timevar_cond_start (TV_NAME_LOOKUP); + tree ret = xref_tag_1 (tag_code, name, how, template_header_p); timevar_cond_stop (TV_NAME_LOOKUP, subtime); return ret; } @@ -15412,7 +15408,7 @@ start_enum (tree name, tree enumtype, tree underlying_type, forward reference. */ if (!enumtype) enumtype = lookup_and_check_tag (enum_type, name, - /*tag_scope=*/ts_current, + /*tag_scope=*/TAG_how::CURRENT_ONLY, /*template_header_p=*/false); /* In case of a template_decl, the only check that should be deferred diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index dbc6cc32dd8..0115a4bd386 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -6583,22 +6583,20 @@ lookup_name (tree name) } /* Look up NAME for type used in elaborated name specifier in - the scopes given by SCOPE. SCOPE can be either TS_CURRENT or - TS_WITHIN_ENCLOSING_NON_CLASS. Although not implied by the - name, more scopes are checked if cleanup or template parameter - scope is encountered. + the scopes given by HOW. Unlike lookup_name_1, we make sure that NAME is actually declared in the desired scope, not from inheritance, nor using directive. For using declaration, there is DR138 still waiting to be resolved. Hidden name coming from an earlier friend - declaration is also returned. + declaration is also returned, and will be made visible unless HOW + is TAG_how::HIDDEN_FRIEND. A TYPE_DECL best matching the NAME is returned. Catching error and issuing diagnostics are caller's responsibility. */ static tree -lookup_type_scope_1 (tree name, tag_scope scope) +lookup_elaborated_type_1 (tree name, TAG_how how) { cp_binding_level *b = current_binding_level; @@ -6613,28 +6611,28 @@ lookup_type_scope_1 (tree name, tag_scope scope) 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))) + || (b->kind == sk_class && how != TAG_how::CURRENT_ONLY))) 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. + HOW is TAG_how::CURRENT_ONLY, 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 (qualify_lookup (type, LOOK_want::TYPE) - && (scope != ts_current + && (how != TAG_how::CURRENT_ONLY || LOCAL_BINDING_P (iter) || DECL_CONTEXT (type) == iter->scope->this_entity)) return type; if (qualify_lookup (iter->value, LOOK_want::TYPE) - && (scope != ts_current + && (how != TAG_how::CURRENT_ONLY || !INHERITED_VALUE_BINDING_P (iter))) return iter->value; } @@ -6644,8 +6642,7 @@ lookup_type_scope_1 (tree name, tag_scope scope) 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))) + || (b->kind == sk_class && how != TAG_how::CURRENT_ONLY))) return NULL_TREE; /* Look in the innermost namespace. */ @@ -6664,15 +6661,14 @@ lookup_type_scope_1 (tree name, tag_scope scope) return NULL_TREE; } - + /* Wrapper for lookup_type_scope_1. */ tree -lookup_type_scope (tree name, tag_scope scope) +lookup_elaborated_type (tree name, TAG_how how) { - tree ret; bool subtime = timevar_cond_start (TV_NAME_LOOKUP); - ret = lookup_type_scope_1 (name, scope); + tree ret = lookup_elaborated_type_1 (name, how); timevar_cond_stop (TV_NAME_LOOKUP, subtime); return ret; } @@ -6782,7 +6778,7 @@ maybe_process_template_type_declaration (tree type, int is_friend, Returns TYPE upon success and ERROR_MARK_NODE otherwise. */ static tree -do_pushtag (tree name, tree type, tag_scope scope) +do_pushtag (tree name, tree type, TAG_how how) { tree decl; @@ -6799,10 +6795,9 @@ do_pushtag (tree name, tree type, tag_scope scope) declaration, these scopes are not scopes from the point of view of the language. */ || (b->kind == sk_template_parms - && (b->explicit_spec_p || scope == ts_global))) + && (b->explicit_spec_p || how == TAG_how::GLOBAL))) b = b->level_chain; - else if (b->kind == sk_class - && scope != ts_current) + else if (b->kind == sk_class && how != TAG_how::CURRENT_ONLY) { b = b->level_chain; if (b->kind == sk_template_parms) @@ -6836,7 +6831,7 @@ do_pushtag (tree name, tree type, tag_scope scope) : TYPE_P (cs) ? cs == current_class_type : cs == current_namespace); - if (scope == ts_current + if (how == TAG_how::CURRENT_ONLY || (cs && TREE_CODE (cs) == FUNCTION_DECL)) context = cs; else if (cs && TYPE_P (cs)) @@ -6856,18 +6851,19 @@ do_pushtag (tree name, tree type, tag_scope scope) tdef = create_implicit_typedef (name, type); DECL_CONTEXT (tdef) = FROB_CONTEXT (context); - if (scope == ts_within_enclosing_non_class) + bool is_friend = how == TAG_how::HIDDEN_FRIEND; + if (is_friend) { + // FIXME: can go away /* This is a friend. Make this TYPE_DECL node hidden from ordinary name lookup. Its corresponding TEMPLATE_DECL - will be marked in push_template_decl_real. */ + will be marked in push_template_decl. */ retrofit_lang_decl (tdef); DECL_ANTICIPATED (tdef) = 1; DECL_FRIEND_P (tdef) = 1; } - decl = maybe_process_template_type_declaration - (type, scope == ts_within_enclosing_non_class, b); + decl = maybe_process_template_type_declaration (type, is_friend, b); if (decl == error_mark_node) return decl; @@ -6888,7 +6884,8 @@ do_pushtag (tree name, tree type, tag_scope scope) } else if (b->kind != sk_template_parms) { - decl = do_pushdecl_with_scope (decl, b, /*is_friend=*/false); + decl = do_pushdecl_with_scope + (decl, b, /*hiding=*/(how == TAG_how::HIDDEN_FRIEND)); if (decl == error_mark_node) return decl; @@ -6954,11 +6951,10 @@ do_pushtag (tree name, tree type, tag_scope scope) /* Wrapper for do_pushtag. */ tree -pushtag (tree name, tree type, tag_scope scope) +pushtag (tree name, tree type, TAG_how how) { - tree ret; bool subtime = timevar_cond_start (TV_NAME_LOOKUP); - ret = do_pushtag (name, type, scope); + tree ret = do_pushtag (name, type, how); timevar_cond_stop (TV_NAME_LOOKUP, subtime); return ret; } diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h index 76ec8f23a9f..82f4d5155b7 100644 --- a/gcc/cp/name-lookup.h +++ b/gcc/cp/name-lookup.h @@ -124,22 +124,6 @@ enum scope_kind { sk_omp /* An OpenMP structured block. */ }; -/* The scope where the class/struct/union/enum tag applies. */ -enum tag_scope { - ts_current = 0, /* Current scope only. This is for the - class-key identifier; - case mentioned in [basic.lookup.elab]/2, - or the class/enum definition - class-key identifier { ... }; */ - ts_global = 1, /* All scopes. This is the 3.4.1 - [basic.lookup.unqual] lookup mentioned - in [basic.lookup.elab]/2. */ - ts_within_enclosing_non_class = 2, /* Search within enclosing non-class - only, for friend class lookup - according to [namespace.memdef]/3 - and [class.friend]/9. */ -}; - struct GTY(()) cp_class_binding { cxx_binding *base; /* The bound name. */ @@ -326,7 +310,19 @@ inline tree lookup_name (tree name, LOOK_want want) return lookup_name (name, LOOK_where::ALL, want); } -extern tree lookup_type_scope (tree, tag_scope); +enum class TAG_how +{ + CURRENT_ONLY = 0, // Look and insert only in current scope + + GLOBAL = 1, // Unqualified lookup, innermost-non-class insertion + + INNERMOST_NON_CLASS = 2, // Look and insert only into + // innermost-non-class + + HIDDEN_FRIEND = 3, // As INNERMOST_NON_CLASS, but hide it +}; + +extern tree lookup_elaborated_type (tree, TAG_how); extern tree get_namespace_binding (tree ns, tree id); extern void set_global_binding (tree decl); inline tree get_global_binding (tree id) @@ -371,7 +367,7 @@ extern tree pushdecl (tree, bool is_friend = false); extern tree pushdecl_outermost_localscope (tree); extern tree pushdecl_top_level (tree, bool is_friend = false); extern tree pushdecl_top_level_and_finish (tree, tree); -extern tree pushtag (tree, tree, tag_scope = ts_current); +extern tree pushtag (tree, tree, TAG_how = TAG_how::CURRENT_ONLY); extern int push_namespace (tree, bool make_inline = false); extern void pop_namespace (void); extern void push_nested_namespace (tree); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index ccfae78f651..8905833fbd6 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -19057,21 +19057,20 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, definition of a new type; a new type can only be declared in a declaration context. */ - tag_scope ts; - bool template_p; + TAG_how how; if (is_friend) /* Friends have special name lookup rules. */ - ts = ts_within_enclosing_non_class; + how = TAG_how::HIDDEN_FRIEND; else if (is_declaration && cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)) /* This is a `class-key identifier ;' */ - ts = ts_current; + how = TAG_how::CURRENT_ONLY; else - ts = ts_global; + how = TAG_how::GLOBAL; - template_p = + bool template_p = (template_parm_lists_apply && (cp_parser_next_token_starts_class_definition_p (parser) || cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))); @@ -19084,7 +19083,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, token->location, /*declarator=*/NULL)) return error_mark_node; - type = xref_tag (tag_type, identifier, ts, template_p); + + type = xref_tag (tag_type, identifier, how, template_p); } } @@ -24708,10 +24708,10 @@ cp_parser_class_head (cp_parser* parser, /* If the class was unnamed, create a dummy name. */ if (!id) id = make_anon_name (); - tag_scope tag_scope = (parser->in_type_id_in_expr_p - ? ts_within_enclosing_non_class - : ts_current); - type = xref_tag (class_key, id, tag_scope, + TAG_how how = (parser->in_type_id_in_expr_p + ? TAG_how::INNERMOST_NON_CLASS + : TAG_how::CURRENT_ONLY); + type = xref_tag (class_key, id, how, parser->num_template_parameter_lists); } diff --git a/gcc/objcp/objcp-decl.c b/gcc/objcp/objcp-decl.c index 087b5d50452..c6c4ee5ed36 100644 --- a/gcc/objcp/objcp-decl.c +++ b/gcc/objcp/objcp-decl.c @@ -41,7 +41,7 @@ objcp_start_struct (location_t loc ATTRIBUTE_UNUSED, if (!name) name = make_anon_name (); - s = xref_tag (record_type, name, ts_global); + s = xref_tag (record_type, name, TAG_how::GLOBAL); CLASSTYPE_DECLARED_CLASS (s) = 0; /* this is a 'struct', not a 'class'. */ xref_basetypes (s, NULL_TREE); /* no base classes here! */ @@ -84,7 +84,7 @@ objcp_finish_function (void) tree objcp_xref_tag (enum tree_code code ATTRIBUTE_UNUSED, tree name) { - return xref_tag (record_type, name, ts_global); + return xref_tag (record_type, name, TAG_how::GLOBAL); } int -- 2.30.2