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.
This commit is contained in:
Nathan Sidwell 2020-09-25 10:24:09 -07:00
parent 0d8f3f612d
commit 00aaae03db
6 changed files with 84 additions and 96 deletions

View File

@ -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 *);

View File

@ -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<tree, va_gc> **);
@ -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 <class X> 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

View File

@ -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;
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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