static tree
tsubst_friend_class (tree friend_tmpl, tree args)
{
- tree friend_type;
tree tmpl;
- tree context;
if (DECL_TEMPLATE_TEMPLATE_PARM_P (friend_tmpl))
{
- tree t = tsubst (TREE_TYPE (friend_tmpl), args, tf_none, NULL_TREE);
- return TREE_TYPE (t);
- }
-
- context = CP_DECL_CONTEXT (friend_tmpl);
-
- if (context != global_namespace)
- {
- if (TREE_CODE (context) == NAMESPACE_DECL)
- push_nested_namespace (context);
- else
- push_nested_class (tsubst (context, args, tf_none, NULL_TREE));
+ tmpl = tsubst (TREE_TYPE (friend_tmpl), args, tf_none, NULL_TREE);
+ return TREE_TYPE (tmpl);
}
- /* Look for a class template declaration. We look for hidden names
- because two friend declarations of the same template are the
- same. For example, in:
-
- struct A {
- template <typename> friend class F;
- };
- template <typename> struct B {
- template <typename> friend class F;
- };
-
- both F templates are the same. */
- tmpl = lookup_name_real (DECL_NAME (friend_tmpl), 0, 0,
- /*block_p=*/true, 0, LOOKUP_HIDDEN);
-
- /* But, if we don't find one, it might be because we're in a
- situation like this:
-
- template <class T>
- struct S {
- template <class U>
- friend struct S;
- };
+ tree context = CP_DECL_CONTEXT (friend_tmpl);
+ if (TREE_CODE (context) == NAMESPACE_DECL)
+ push_nested_namespace (context);
+ else
+ push_nested_class (context);
- Here, in the scope of (say) S<int>, `S' is bound to a TYPE_DECL
- for `S<int>', not the TEMPLATE_DECL. */
- if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
- {
- tmpl = lookup_name_prefer_type (DECL_NAME (friend_tmpl), 1);
- tmpl = maybe_get_template_decl_from_type_decl (tmpl);
- }
+ tmpl = lookup_name_real (DECL_NAME (friend_tmpl), /*prefer_type=*/false,
+ /*non_class=*/false, /*block_p=*/false,
+ /*namespaces_only=*/false, LOOKUP_HIDDEN);
if (tmpl && DECL_CLASS_TEMPLATE_P (tmpl))
{
if (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (friend_tmpl))
> TMPL_ARGS_DEPTH (args))
{
- tree parms;
- location_t saved_input_location;
- parms = tsubst_template_parms (DECL_TEMPLATE_PARMS (friend_tmpl),
- args, tf_warning_or_error);
-
- saved_input_location = input_location;
+ tree parms = tsubst_template_parms (DECL_TEMPLATE_PARMS (friend_tmpl),
+ args, tf_warning_or_error);
+ location_t saved_input_location = input_location;
input_location = DECL_SOURCE_LOCATION (friend_tmpl);
tree cons = get_constraints (tmpl);
redeclare_class_template (TREE_TYPE (tmpl), parms, cons);
input_location = saved_input_location;
-
}
-
- friend_type = TREE_TYPE (tmpl);
}
else
{
/* The friend template has not already been declared. In this
case, the instantiation of the template class will cause the
- injection of this template into the global scope. */
+ injection of this template into the namespace scope. */
tmpl = tsubst (friend_tmpl, args, tf_warning_or_error, NULL_TREE);
- if (tmpl == error_mark_node)
- return error_mark_node;
- /* The new TMPL is not an instantiation of anything, so we
- forget its origins. We don't reset CLASSTYPE_TI_TEMPLATE for
- the new type because that is supposed to be the corresponding
- template decl, i.e., TMPL. */
- DECL_USE_TEMPLATE (tmpl) = 0;
- DECL_TEMPLATE_INFO (tmpl) = NULL_TREE;
- CLASSTYPE_USE_TEMPLATE (TREE_TYPE (tmpl)) = 0;
- CLASSTYPE_TI_ARGS (TREE_TYPE (tmpl))
- = INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (TREE_TYPE (tmpl)));
+ if (tmpl != error_mark_node)
+ {
+ /* The new TMPL is not an instantiation of anything, so we
+ forget its origins. We don't reset CLASSTYPE_TI_TEMPLATE
+ for the new type because that is supposed to be the
+ corresponding template decl, i.e., TMPL. */
+ DECL_USE_TEMPLATE (tmpl) = 0;
+ DECL_TEMPLATE_INFO (tmpl) = NULL_TREE;
+ CLASSTYPE_USE_TEMPLATE (TREE_TYPE (tmpl)) = 0;
+ CLASSTYPE_TI_ARGS (TREE_TYPE (tmpl))
+ = INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (TREE_TYPE (tmpl)));
+
+ /* It is hidden. */
+ retrofit_lang_decl (DECL_TEMPLATE_RESULT (tmpl));
+ DECL_ANTICIPATED (tmpl)
+ = DECL_ANTICIPATED (DECL_TEMPLATE_RESULT (tmpl)) = true;
- /* Inject this template into the global scope. */
- friend_type = TREE_TYPE (pushdecl_top_level (tmpl, true));
+ /* Inject this template into the enclosing namspace scope. */
+ tmpl = pushdecl_namespace_level (tmpl, true);
+ }
}
- if (context != global_namespace)
- {
- if (TREE_CODE (context) == NAMESPACE_DECL)
- pop_nested_namespace (context);
- else
- pop_nested_class ();
- }
+ if (TREE_CODE (context) == NAMESPACE_DECL)
+ pop_nested_namespace (context);
+ else
+ pop_nested_class ();
- return friend_type;
+ return TREE_TYPE (tmpl);
}
/* Returns zero if TYPE cannot be completed later due to circularity.