c++: DECL_FRIEND_P cleanup
DECL_FRIEND_P's meaning has changed over time. It now (almost) means the the friend function decl has not been met via an explicit decl. This completes that transition, renaming it to DECL_UNIQUE_FRIEND_P, so one doesn't think it is the sole indicator of friendliness (plenty of friends do not have the flag set). This allows reduction in the complexity of managing the field -- all in duplicate_decls now. gcc/cp/ * cp-tree.h (struct lang_decl_fn): Adjust context comment. (DECL_FRIEND_P): Replace with ... (DECL_UNIQUE_FRIEND_P): ... this. Only for FUNCTION_DECLs. (DECL_FRIEND_CONTEXT): Adjust. * class.c (add_implicitly_declared_members): Detect friendly spaceship from context. * constraint.cc (remove_constraints): Use a checking assert. (maybe_substitute_reqs_for): Use DECL_UNIQUE_FRIEND_P. * decl.c (check_no_redeclaration_friend_default_args): DECL_UNIQUE_FRIEND_P is signficant, not hiddenness. (duplicate_decls): Adjust DECL_UNIQUE_FRIEND_P clearing. (redeclaration_error_message): Use DECL_UNIQUE_FRIEND_P. (start_preparsed_function): Correct in-class friend processing. Refactor some initializers. (grokmethod): Directly check friend decl-spec. * decl2.c (grokfield): Check DECL_UNIQUE_FRIEND_P. * friend.c (do_friend): Set DECL_UNIQUE_FRIEND_P first, remove extraneous conditions. Don't re set it afterwards. * name-lookup.c (lookup_elaborated_type_1): Simplify revealing code. (do_pushtag): Likewise. * pt.c (optimize_specialization_lookup_p): Check DECL_UNIQUE_FRIEND_P. (push_template_decl): Likewise. Drop unneeded friend setting. (type_dependent_expression_p): Check DECL_UNIQUE_FRIEND_P. libcc1/ * libcp1plugin.cc (plugin_add_friend): Set DECL_UNIQUE_FRIEND_P.
This commit is contained in:
parent
06bec55e80
commit
068644a149
@ -3283,7 +3283,8 @@ add_implicitly_declared_members (tree t, tree* access_decls,
|
||||
{
|
||||
tree eq = implicitly_declare_fn (sfk_comparison, t, false, space,
|
||||
NULL_TREE);
|
||||
if (DECL_FRIEND_P (space))
|
||||
bool is_friend = DECL_CONTEXT (space) != t;
|
||||
if (is_friend)
|
||||
do_friend (NULL_TREE, DECL_NAME (eq), eq,
|
||||
NULL_TREE, NO_SPECIAL, true);
|
||||
else
|
||||
@ -3292,7 +3293,7 @@ add_implicitly_declared_members (tree t, tree* access_decls,
|
||||
DECL_CHAIN (eq) = TYPE_FIELDS (t);
|
||||
TYPE_FIELDS (t) = eq;
|
||||
}
|
||||
maybe_add_class_template_decl_list (t, eq, DECL_FRIEND_P (space));
|
||||
maybe_add_class_template_decl_list (t, eq, is_friend);
|
||||
}
|
||||
|
||||
while (*access_decls)
|
||||
|
@ -1201,7 +1201,7 @@ set_constraints (tree t, tree ci)
|
||||
void
|
||||
remove_constraints (tree t)
|
||||
{
|
||||
gcc_assert (DECL_P (t));
|
||||
gcc_checking_assert (DECL_P (t));
|
||||
if (TREE_CODE (t) == TEMPLATE_DECL)
|
||||
t = DECL_TEMPLATE_RESULT (t);
|
||||
|
||||
@ -1217,11 +1217,16 @@ maybe_substitute_reqs_for (tree reqs, const_tree decl_)
|
||||
{
|
||||
if (reqs == NULL_TREE)
|
||||
return NULL_TREE;
|
||||
|
||||
tree decl = CONST_CAST_TREE (decl_);
|
||||
tree result = STRIP_TEMPLATE (decl);
|
||||
if (DECL_FRIEND_P (result))
|
||||
|
||||
if (DECL_UNIQUE_FRIEND_P (result))
|
||||
{
|
||||
tree tmpl = decl == result ? DECL_TI_TEMPLATE (result) : decl;
|
||||
tree tmpl = decl;
|
||||
if (TREE_CODE (decl) != TEMPLATE_DECL)
|
||||
tmpl = DECL_TI_TEMPLATE (result);
|
||||
|
||||
tree gargs = generic_targs_for (tmpl);
|
||||
processing_template_decl_sentinel s;
|
||||
if (uses_template_parms (gargs))
|
||||
|
@ -2736,12 +2736,14 @@ struct GTY(()) lang_decl_fn {
|
||||
thunked to function decl. */
|
||||
tree befriending_classes;
|
||||
|
||||
/* For a non-virtual FUNCTION_DECL, this is
|
||||
DECL_FRIEND_CONTEXT. For a virtual FUNCTION_DECL for which
|
||||
/* For a virtual FUNCTION_DECL for which
|
||||
DECL_THIS_THUNK_P does not hold, this is DECL_THUNKS. Both
|
||||
this pointer and result pointer adjusting thunks are
|
||||
chained here. This pointer thunks to return pointer thunks
|
||||
will be chained on the return pointer thunk. */
|
||||
will be chained on the return pointer thunk.
|
||||
For a DECL_CONSTUCTOR_P FUNCTION_DECL, this is the base from
|
||||
whence we inherit. Otherwise, it is the class in which a
|
||||
(namespace-scope) friend is defined (if any). */
|
||||
tree context;
|
||||
|
||||
union lang_decl_u5
|
||||
@ -3088,10 +3090,14 @@ struct GTY(()) lang_decl {
|
||||
(DECL_LANG_SPECIFIC (VAR_OR_FUNCTION_DECL_CHECK (DECL)) \
|
||||
->u.base.odr_used)
|
||||
|
||||
/* Nonzero for DECL means that this decl is just a friend declaration,
|
||||
and should not be added to the list of members for this class. */
|
||||
#define DECL_FRIEND_P(NODE) \
|
||||
(DECL_LANG_SPECIFIC (TYPE_FUNCTION_OR_TEMPLATE_DECL_CHECK (NODE)) \
|
||||
/* Nonzero for FUNCTION_DECL means that this is a friend that is
|
||||
either not pushed into a namespace/looked up in a class (because it
|
||||
is a dependent type, in an uninstantiated template), or it has
|
||||
/only/ been subject to hidden friend injection from one or more
|
||||
befriending classes. Once another decl matches, the flag is
|
||||
cleared. There are requirements on its default parms. */
|
||||
#define DECL_UNIQUE_FRIEND_P(NODE) \
|
||||
(DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (NODE)) \
|
||||
->u.base.friend_or_tls)
|
||||
|
||||
/* Nonzero if the thread-local variable was declared with __thread as
|
||||
@ -3290,8 +3296,8 @@ struct GTY(()) lang_decl {
|
||||
|
||||
the DECL_FRIEND_CONTEXT for `f' will be `S'. */
|
||||
#define DECL_FRIEND_CONTEXT(NODE) \
|
||||
((DECL_DECLARES_FUNCTION_P (NODE) \
|
||||
&& DECL_FRIEND_P (NODE) && !DECL_FUNCTION_MEMBER_P (NODE)) \
|
||||
((DECL_DECLARES_FUNCTION_P (NODE) && !DECL_VIRTUAL_P (NODE) \
|
||||
&& !DECL_CONSTRUCTOR_P (NODE)) \
|
||||
? LANG_DECL_FN_CHECK (NODE)->context \
|
||||
: NULL_TREE)
|
||||
|
||||
|
@ -1340,18 +1340,17 @@ check_redeclaration_no_default_args (tree decl)
|
||||
the function or function template in the translation unit." */
|
||||
|
||||
static void
|
||||
check_no_redeclaration_friend_default_args (tree olddecl, tree newdecl,
|
||||
bool olddecl_hidden_p)
|
||||
check_no_redeclaration_friend_default_args (tree olddecl, tree newdecl)
|
||||
{
|
||||
if (!olddecl_hidden_p && !DECL_FRIEND_P (newdecl))
|
||||
if (!DECL_UNIQUE_FRIEND_P (olddecl) && !DECL_UNIQUE_FRIEND_P (newdecl))
|
||||
return;
|
||||
|
||||
for (tree t1 = FUNCTION_FIRST_USER_PARMTYPE (olddecl),
|
||||
t2 = FUNCTION_FIRST_USER_PARMTYPE (newdecl);
|
||||
t1 && t1 != void_list_node;
|
||||
t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2))
|
||||
if ((olddecl_hidden_p && TREE_PURPOSE (t1))
|
||||
|| (DECL_FRIEND_P (newdecl) && TREE_PURPOSE (t2)))
|
||||
if ((DECL_UNIQUE_FRIEND_P (olddecl) && TREE_PURPOSE (t1))
|
||||
|| (DECL_UNIQUE_FRIEND_P (newdecl) && TREE_PURPOSE (t2)))
|
||||
{
|
||||
auto_diagnostic_group d;
|
||||
if (permerror (DECL_SOURCE_LOCATION (newdecl),
|
||||
@ -1444,8 +1443,7 @@ tree
|
||||
duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
|
||||
{
|
||||
unsigned olddecl_uid = DECL_UID (olddecl);
|
||||
int olddecl_friend = 0, types_match = 0;
|
||||
int olddecl_hidden_friend = 0;
|
||||
int types_match = 0;
|
||||
int new_defines_function = 0;
|
||||
tree new_template_info;
|
||||
location_t olddecl_loc = DECL_SOURCE_LOCATION (olddecl);
|
||||
@ -1987,8 +1985,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
|
||||
argument expression, that declaration... shall be the only
|
||||
declaration of the function or function template in the
|
||||
translation unit." */
|
||||
check_no_redeclaration_friend_default_args
|
||||
(olddecl, newdecl, was_hidden);
|
||||
check_no_redeclaration_friend_default_args (olddecl, newdecl);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2135,12 +2132,6 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
|
||||
else
|
||||
DECL_ATTRIBUTES (olddecl) = DECL_ATTRIBUTES (newdecl);
|
||||
|
||||
if (DECL_DECLARES_FUNCTION_P (olddecl))
|
||||
{
|
||||
olddecl_friend = DECL_FRIEND_P (STRIP_TEMPLATE (olddecl));
|
||||
olddecl_hidden_friend = olddecl_friend && was_hidden;
|
||||
}
|
||||
|
||||
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
|
||||
{
|
||||
tree old_result = DECL_TEMPLATE_RESULT (olddecl);
|
||||
@ -2167,8 +2158,10 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
|
||||
declaration of the function or function template in the
|
||||
translation unit." */
|
||||
check_no_redeclaration_friend_default_args
|
||||
(old_result, new_result, olddecl_hidden_friend);
|
||||
(old_result, new_result);
|
||||
}
|
||||
if (!DECL_UNIQUE_FRIEND_P (old_result))
|
||||
DECL_UNIQUE_FRIEND_P (new_result) = false;
|
||||
|
||||
check_default_args (newdecl);
|
||||
|
||||
@ -2366,6 +2359,9 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
|
||||
&& !DECL_FUNCTION_SPECIFIC_OPTIMIZATION (newdecl))
|
||||
DECL_FUNCTION_SPECIFIC_OPTIMIZATION (newdecl)
|
||||
= DECL_FUNCTION_SPECIFIC_OPTIMIZATION (olddecl);
|
||||
|
||||
if (!DECL_UNIQUE_FRIEND_P (olddecl))
|
||||
DECL_UNIQUE_FRIEND_P (newdecl) = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2885,8 +2881,6 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
|
||||
}
|
||||
|
||||
DECL_UID (olddecl) = olddecl_uid;
|
||||
if (olddecl_friend)
|
||||
DECL_FRIEND_P (olddecl) = true;
|
||||
|
||||
/* NEWDECL contains the merged attribute lists.
|
||||
Update OLDDECL to be the same. */
|
||||
@ -3062,7 +3056,7 @@ redeclaration_error_message (tree newdecl, tree olddecl)
|
||||
definition and shall be the only declaration of the
|
||||
function template in the translation unit. */
|
||||
if ((cxx_dialect != cxx98)
|
||||
&& TREE_CODE (ot) == FUNCTION_DECL && DECL_FRIEND_P (ot)
|
||||
&& TREE_CODE (ot) == FUNCTION_DECL && DECL_UNIQUE_FRIEND_P (ot)
|
||||
&& !check_default_tmpl_args (nt, DECL_TEMPLATE_PARMS (newdecl),
|
||||
/*is_primary=*/true,
|
||||
/*is_partial=*/false,
|
||||
@ -3073,7 +3067,8 @@ redeclaration_error_message (tree newdecl, tree olddecl)
|
||||
return NULL;
|
||||
}
|
||||
else if (VAR_P (newdecl)
|
||||
&& CP_DECL_THREAD_LOCAL_P (newdecl) != CP_DECL_THREAD_LOCAL_P (olddecl)
|
||||
&& (CP_DECL_THREAD_LOCAL_P (newdecl)
|
||||
!= CP_DECL_THREAD_LOCAL_P (olddecl))
|
||||
&& (! DECL_LANG_SPECIFIC (olddecl)
|
||||
|| ! CP_DECL_THREADPRIVATE_P (olddecl)
|
||||
|| CP_DECL_THREAD_LOCAL_P (newdecl)))
|
||||
@ -16110,36 +16105,21 @@ bool
|
||||
start_preparsed_function (tree decl1, tree attrs, int flags)
|
||||
{
|
||||
tree ctype = NULL_TREE;
|
||||
tree fntype;
|
||||
tree restype;
|
||||
int doing_friend = 0;
|
||||
cp_binding_level *bl;
|
||||
tree current_function_parms;
|
||||
struct c_fileinfo *finfo
|
||||
= get_fileinfo (LOCATION_FILE (DECL_SOURCE_LOCATION (decl1)));
|
||||
bool honor_interface;
|
||||
bool doing_friend = false;
|
||||
|
||||
/* Sanity check. */
|
||||
gcc_assert (VOID_TYPE_P (TREE_VALUE (void_list_node)));
|
||||
gcc_assert (TREE_CHAIN (void_list_node) == NULL_TREE);
|
||||
|
||||
fntype = TREE_TYPE (decl1);
|
||||
tree fntype = TREE_TYPE (decl1);
|
||||
if (TREE_CODE (fntype) == METHOD_TYPE)
|
||||
ctype = TYPE_METHOD_BASETYPE (fntype);
|
||||
|
||||
/* ISO C++ 11.4/5. A friend function defined in a class is in
|
||||
the (lexical) scope of the class in which it is defined. */
|
||||
if (!ctype && DECL_FRIEND_P (decl1))
|
||||
else
|
||||
{
|
||||
ctype = DECL_FRIEND_CONTEXT (decl1);
|
||||
|
||||
/* CTYPE could be null here if we're dealing with a template;
|
||||
for example, `inline friend float foo()' inside a template
|
||||
will have no CTYPE set. */
|
||||
if (ctype && TREE_CODE (ctype) != RECORD_TYPE)
|
||||
ctype = NULL_TREE;
|
||||
else
|
||||
doing_friend = 1;
|
||||
if (ctype)
|
||||
doing_friend = true;
|
||||
}
|
||||
|
||||
if (DECL_DECLARED_INLINE_P (decl1)
|
||||
@ -16206,7 +16186,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
|
||||
by push_nested_class.) */
|
||||
if (processing_template_decl)
|
||||
{
|
||||
tree newdecl1 = push_template_decl (decl1, DECL_FRIEND_P (decl1));
|
||||
tree newdecl1 = push_template_decl (decl1, doing_friend);
|
||||
if (newdecl1 == error_mark_node)
|
||||
{
|
||||
if (ctype || DECL_STATIC_FUNCTION_P (decl1))
|
||||
@ -16222,7 +16202,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
|
||||
check_function_type (decl1, DECL_ARGUMENTS (decl1));
|
||||
|
||||
/* Build the return declaration for the function. */
|
||||
restype = TREE_TYPE (fntype);
|
||||
tree restype = TREE_TYPE (fntype);
|
||||
|
||||
if (DECL_RESULT (decl1) == NULL_TREE)
|
||||
{
|
||||
@ -16312,7 +16292,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
|
||||
|
||||
/* Save the parm names or decls from this function's declarator
|
||||
where store_parm_decls will find them. */
|
||||
current_function_parms = DECL_ARGUMENTS (decl1);
|
||||
tree current_function_parms = DECL_ARGUMENTS (decl1);
|
||||
|
||||
/* Let the user know we're compiling this function. */
|
||||
announce_function (decl1);
|
||||
@ -16329,7 +16309,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
|
||||
even when processing a template; this is how we get
|
||||
CFUN set up, and our per-function variables initialized.
|
||||
FIXME factor out the non-RTL stuff. */
|
||||
bl = current_binding_level;
|
||||
cp_binding_level *bl = current_binding_level;
|
||||
allocate_struct_function (decl1, processing_template_decl);
|
||||
|
||||
/* Initialize the language data structures. Whenever we start
|
||||
@ -16384,14 +16364,16 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
|
||||
}
|
||||
}
|
||||
|
||||
honor_interface = (!DECL_TEMPLATE_INSTANTIATION (decl1)
|
||||
/* Implicitly-defined methods (like the
|
||||
destructor for a class in which no destructor
|
||||
is explicitly declared) must not be defined
|
||||
until their definition is needed. So, we
|
||||
ignore interface specifications for
|
||||
compiler-generated functions. */
|
||||
&& !DECL_ARTIFICIAL (decl1));
|
||||
bool honor_interface = (!DECL_TEMPLATE_INSTANTIATION (decl1)
|
||||
/* Implicitly-defined methods (like the
|
||||
destructor for a class in which no destructor
|
||||
is explicitly declared) must not be defined
|
||||
until their definition is needed. So, we
|
||||
ignore interface specifications for
|
||||
compiler-generated functions. */
|
||||
&& !DECL_ARTIFICIAL (decl1));
|
||||
struct c_fileinfo *finfo
|
||||
= get_fileinfo (LOCATION_FILE (DECL_SOURCE_LOCATION (decl1)));
|
||||
|
||||
if (processing_template_decl)
|
||||
/* Don't mess with interface flags. */;
|
||||
@ -17311,18 +17293,17 @@ grokmethod (cp_decl_specifier_seq *declspecs,
|
||||
/* We process method specializations in finish_struct_1. */
|
||||
if (processing_template_decl && !DECL_TEMPLATE_SPECIALIZATION (fndecl))
|
||||
{
|
||||
fndecl = push_template_decl (fndecl, DECL_FRIEND_P (fndecl));
|
||||
/* Avoid calling decl_spec_seq... until we have to. */
|
||||
bool friendp = decl_spec_seq_has_spec_p (declspecs, ds_friend);
|
||||
fndecl = push_template_decl (fndecl, friendp);
|
||||
if (fndecl == error_mark_node)
|
||||
return fndecl;
|
||||
}
|
||||
|
||||
if (! DECL_FRIEND_P (fndecl))
|
||||
if (DECL_CHAIN (fndecl) && !decl_spec_seq_has_spec_p (declspecs, ds_friend))
|
||||
{
|
||||
if (DECL_CHAIN (fndecl))
|
||||
{
|
||||
fndecl = copy_node (fndecl);
|
||||
TREE_CHAIN (fndecl) = NULL_TREE;
|
||||
}
|
||||
fndecl = copy_node (fndecl);
|
||||
TREE_CHAIN (fndecl) = NULL_TREE;
|
||||
}
|
||||
|
||||
cp_finish_decl (fndecl, NULL_TREE, false, NULL_TREE, 0);
|
||||
|
@ -1021,7 +1021,7 @@ grokfield (const cp_declarator *declarator,
|
||||
asmspec_tree, flags);
|
||||
|
||||
/* Pass friends back this way. */
|
||||
if (DECL_FRIEND_P (value))
|
||||
if (DECL_UNIQUE_FRIEND_P (value))
|
||||
return void_type_node;
|
||||
|
||||
DECL_IN_AGGR_P (value) = 1;
|
||||
|
@ -481,8 +481,8 @@ do_friend (tree ctype, tree declarator, tree decl,
|
||||
gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
|
||||
gcc_assert (!ctype || MAYBE_CLASS_TYPE_P (ctype));
|
||||
|
||||
/* Every decl that gets here is a friend of something. */
|
||||
DECL_FRIEND_P (decl) = 1;
|
||||
/* Friend functions are unique, until proved otherwise. */
|
||||
DECL_UNIQUE_FRIEND_P (decl) = 1;
|
||||
|
||||
if (DECL_OVERRIDE_P (decl) || DECL_FINAL_P (decl))
|
||||
error ("friend declaration %qD may not have virt-specifiers",
|
||||
@ -581,17 +581,11 @@ do_friend (tree ctype, tree declarator, tree decl,
|
||||
error ("member %qD declared as friend before type %qT defined",
|
||||
decl, ctype);
|
||||
}
|
||||
/* A global friend.
|
||||
@@ or possibly a friend from a base class ?!? */
|
||||
else if (TREE_CODE (decl) == FUNCTION_DECL)
|
||||
else
|
||||
{
|
||||
/* Namespace-scope friend function. */
|
||||
int is_friend_template = PROCESSING_REAL_TEMPLATE_DECL_P ();
|
||||
|
||||
/* Friends must all go through the overload machinery,
|
||||
even though they may not technically be overloaded.
|
||||
|
||||
Note that because classes all wind up being top-level
|
||||
in their scope, their friend wind up in top-level scope as well. */
|
||||
if (funcdef_flag)
|
||||
SET_DECL_FRIEND_CONTEXT (decl, current_class_type);
|
||||
|
||||
@ -653,7 +647,6 @@ do_friend (tree ctype, tree declarator, tree decl,
|
||||
add_friend (current_class_type,
|
||||
is_friend_template ? DECL_TI_TEMPLATE (decl) : decl,
|
||||
/*complain=*/true);
|
||||
DECL_FRIEND_P (decl) = 1;
|
||||
}
|
||||
|
||||
return decl;
|
||||
|
@ -6719,8 +6719,6 @@ lookup_elaborated_type_1 (tree name, TAG_how how)
|
||||
typedef struct C {} C;
|
||||
correctly. */
|
||||
|
||||
tree found = NULL_TREE;
|
||||
bool reveal = false;
|
||||
if (tree type = iter->type)
|
||||
{
|
||||
if (qualify_lookup (type, LOOK_want::TYPE)
|
||||
@ -6728,9 +6726,11 @@ lookup_elaborated_type_1 (tree name, TAG_how how)
|
||||
|| LOCAL_BINDING_P (iter)
|
||||
|| DECL_CONTEXT (type) == iter->scope->this_entity))
|
||||
{
|
||||
found = type;
|
||||
if (how != TAG_how::HIDDEN_FRIEND)
|
||||
reveal = HIDDEN_TYPE_BINDING_P (iter);
|
||||
/* It is no longer a hidden binding. */
|
||||
HIDDEN_TYPE_BINDING_P (iter) = false;
|
||||
|
||||
return type;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -6739,33 +6739,13 @@ lookup_elaborated_type_1 (tree name, TAG_how how)
|
||||
&& (how != TAG_how::CURRENT_ONLY
|
||||
|| !INHERITED_VALUE_BINDING_P (iter)))
|
||||
{
|
||||
found = iter->value;
|
||||
if (how != TAG_how::HIDDEN_FRIEND)
|
||||
reveal = !iter->type && HIDDEN_TYPE_BINDING_P (iter);
|
||||
if (how != TAG_how::HIDDEN_FRIEND && !iter->type)
|
||||
/* It is no longer a hidden binding. */
|
||||
HIDDEN_TYPE_BINDING_P (iter) = false;
|
||||
|
||||
return iter->value;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
if (reveal)
|
||||
{
|
||||
/* It is no longer a hidden binding. */
|
||||
HIDDEN_TYPE_BINDING_P (iter) = false;
|
||||
|
||||
/* Unanticipate the decl itself. */
|
||||
DECL_FRIEND_P (found) = false;
|
||||
|
||||
gcc_checking_assert (TREE_CODE (found) != TEMPLATE_DECL);
|
||||
|
||||
if (tree ti = TYPE_TEMPLATE_INFO (TREE_TYPE (found)))
|
||||
{
|
||||
tree tmpl = TI_TEMPLATE (ti);
|
||||
DECL_FRIEND_P (tmpl) = false;
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now check if we can look in namespace scope. */
|
||||
@ -6781,62 +6761,32 @@ lookup_elaborated_type_1 (tree name, TAG_how how)
|
||||
if (tree *slot = find_namespace_slot (ns, name))
|
||||
{
|
||||
/* If this is the kind of thing we're looking for, we're done. */
|
||||
tree found = NULL_TREE;
|
||||
bool reveal = false;
|
||||
|
||||
if (tree type = MAYBE_STAT_TYPE (*slot))
|
||||
{
|
||||
found = type;
|
||||
if (how != TAG_how::HIDDEN_FRIEND)
|
||||
{
|
||||
reveal = STAT_TYPE_HIDDEN_P (*slot);
|
||||
STAT_TYPE_HIDDEN_P (*slot) = false;
|
||||
}
|
||||
/* No longer hidden. */
|
||||
STAT_TYPE_HIDDEN_P (*slot) = false;
|
||||
|
||||
return type;
|
||||
}
|
||||
else if (tree decl = MAYBE_STAT_DECL (*slot))
|
||||
{
|
||||
if (qualify_lookup (decl, LOOK_want::TYPE))
|
||||
{
|
||||
found = decl;
|
||||
|
||||
if (how != TAG_how::HIDDEN_FRIEND && STAT_HACK_P (*slot))
|
||||
if (how != TAG_how::HIDDEN_FRIEND && STAT_HACK_P (*slot)
|
||||
&& STAT_DECL_HIDDEN_P (*slot))
|
||||
{
|
||||
reveal = STAT_DECL_HIDDEN_P (*slot);
|
||||
if (reveal)
|
||||
{
|
||||
if (STAT_TYPE (*slot))
|
||||
STAT_DECL_HIDDEN_P (*slot) = false;
|
||||
else
|
||||
/* There is no type, just remove the stat
|
||||
hack. */
|
||||
*slot = decl;
|
||||
}
|
||||
if (STAT_TYPE (*slot))
|
||||
STAT_DECL_HIDDEN_P (*slot) = false;
|
||||
else
|
||||
/* There is no type, just remove the stat
|
||||
hack. */
|
||||
*slot = decl;
|
||||
}
|
||||
|
||||
return decl;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
if (reveal)
|
||||
{
|
||||
/* Reveal the previously hidden thing. */
|
||||
DECL_FRIEND_P (found) = false;
|
||||
|
||||
if (TREE_CODE (found) == TEMPLATE_DECL)
|
||||
{
|
||||
tree res = DECL_TEMPLATE_RESULT (found);
|
||||
if (DECL_LANG_SPECIFIC (res))
|
||||
DECL_FRIEND_P (res) = false;
|
||||
}
|
||||
else if (tree ti = TYPE_TEMPLATE_INFO (TREE_TYPE (found)))
|
||||
{
|
||||
tree tmpl = TI_TEMPLATE (ti);
|
||||
DECL_FRIEND_P (tmpl) = false;
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL_TREE;
|
||||
@ -7017,18 +6967,8 @@ do_pushtag (tree name, tree type, TAG_how how)
|
||||
|
||||
tdef = create_implicit_typedef (name, type);
|
||||
DECL_CONTEXT (tdef) = FROB_CONTEXT (context);
|
||||
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. */
|
||||
retrofit_lang_decl (tdef);
|
||||
DECL_FRIEND_P (tdef) = 1;
|
||||
}
|
||||
|
||||
decl = maybe_process_template_type_declaration (type, is_friend, b);
|
||||
decl = maybe_process_template_type_declaration
|
||||
(type, how == TAG_how::HIDDEN_FRIEND, b);
|
||||
if (decl == error_mark_node)
|
||||
return decl;
|
||||
|
||||
|
12
gcc/cp/pt.c
12
gcc/cp/pt.c
@ -1181,7 +1181,7 @@ optimize_specialization_lookup_p (tree tmpl)
|
||||
not have template information. The optimized lookup relies
|
||||
on having ARGS be the template arguments for both the class
|
||||
and the function template. */
|
||||
&& !DECL_FRIEND_P (DECL_TEMPLATE_RESULT (tmpl)));
|
||||
&& !DECL_UNIQUE_FRIEND_P (DECL_TEMPLATE_RESULT (tmpl)));
|
||||
}
|
||||
|
||||
/* Make sure ARGS doesn't use any inappropriate typedefs; we should have
|
||||
@ -5701,7 +5701,7 @@ push_template_decl (tree decl, bool is_friend)
|
||||
/* No surprising friend functions. */
|
||||
gcc_checking_assert (is_friend
|
||||
|| !(TREE_CODE (decl) == FUNCTION_DECL
|
||||
&& DECL_FRIEND_P (decl)));
|
||||
&& DECL_UNIQUE_FRIEND_P (decl)));
|
||||
|
||||
if (is_friend)
|
||||
/* For a friend, we want the context of the friend, not
|
||||
@ -6022,10 +6022,6 @@ push_template_decl (tree decl, bool is_friend)
|
||||
if (!ctx
|
||||
&& !(is_friend && template_class_depth (current_class_type) > 0))
|
||||
{
|
||||
/* Hide template friend classes that haven't been declared yet. */
|
||||
if (is_friend && TREE_CODE (decl) == TYPE_DECL)
|
||||
DECL_FRIEND_P (tmpl) = 1;
|
||||
|
||||
tmpl = pushdecl_namespace_level (tmpl, /*hiding=*/is_friend);
|
||||
if (tmpl == error_mark_node)
|
||||
return error_mark_node;
|
||||
@ -13960,7 +13956,7 @@ tsubst_function_decl (tree t, tree args, tsubst_flags_t complain,
|
||||
if (!lambda_fntype)
|
||||
set_constraints (r, ci);
|
||||
|
||||
if (DECL_FRIEND_P (t) && DECL_FRIEND_CONTEXT (t))
|
||||
if (DECL_FRIEND_CONTEXT (t))
|
||||
SET_DECL_FRIEND_CONTEXT (r,
|
||||
tsubst (DECL_FRIEND_CONTEXT (t),
|
||||
args, complain, in_decl));
|
||||
@ -27049,7 +27045,7 @@ type_dependent_expression_p (tree expression)
|
||||
&& !(DECL_CLASS_SCOPE_P (expression)
|
||||
&& dependent_type_p (DECL_CONTEXT (expression)))
|
||||
&& !(DECL_LANG_SPECIFIC (expression)
|
||||
&& DECL_FRIEND_P (expression)
|
||||
&& DECL_UNIQUE_FRIEND_P (expression)
|
||||
&& (!DECL_FRIEND_CONTEXT (expression)
|
||||
|| dependent_type_p (DECL_FRIEND_CONTEXT (expression))))
|
||||
&& !DECL_LOCAL_DECL_P (expression))
|
||||
|
@ -1649,7 +1649,7 @@ plugin_add_friend (cc1_plugin::connection * /* self */,
|
||||
make_friend_class (type, TREE_TYPE (decl), true);
|
||||
else
|
||||
{
|
||||
DECL_FRIEND_P (decl) = true;
|
||||
DECL_UNIQUE_FRIEND_P (decl) = true;
|
||||
add_friend (type, decl, true);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user