aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/pt.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/pt.c')
-rw-r--r--gcc/cp/pt.c445
1 files changed, 339 insertions, 106 deletions
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index fa3caac01dc..8d6d9103d2c 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -66,6 +66,8 @@ static size_t inline_parm_levels_used;
static GTY(()) tree current_tinst_level;
+static GTY(()) tree saved_access_scope;
+
/* A map from local variable declarations in the body of the template
presently being instantiated to the corresponding instantiated
local variables. */
@@ -87,6 +89,9 @@ static htab_t local_specializations;
#define GTB_IGNORE_TYPE 2 /* We don't need to try to unify the current
type with the desired type. */
+static void push_access_scope_real PARAMS ((tree, tree, tree));
+static void push_access_scope PARAMS ((tree));
+static void pop_access_scope PARAMS ((tree));
static int resolve_overloaded_unification PARAMS ((tree, tree, tree, tree,
unification_kind_t, int));
static int try_one_overload PARAMS ((tree, tree, tree, tree, tree,
@@ -166,6 +171,87 @@ static tree copy_default_args_to_explicit_spec_1 PARAMS ((tree, tree));
static void copy_default_args_to_explicit_spec PARAMS ((tree));
static int invalid_nontype_parm_type_p PARAMS ((tree, tsubst_flags_t));
+/* Make the current scope suitable for access checking when we are
+ processing T. T can be FUNCTION_DECL for instantiated function
+ template, TEMPLATE_DECL for uninstantiated one, or VAR_DECL for
+ static member variable (need by instantiate_decl). ARGS is the
+ template argument for TEMPLATE_DECL. If CONTEXT is not NULL_TREE,
+ this is used instead of the context of T. */
+
+void
+push_access_scope_real (t, args, context)
+ tree t, args, context;
+{
+ if (TREE_CODE (t) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (t))
+ {
+ /* When we are processing specialization `foo<Outer>' for code like
+
+ template <class U> typename U::Inner foo ();
+ class Outer {
+ struct Inner {};
+ friend Outer::Inner foo<Outer> ();
+ };
+
+ `T' is a TEMPLATE_DECL, but `Outer' is only a friend of one of
+ its specialization. We can get the FUNCTION_DECL with the right
+ information because this specialization has already been
+ registered by the friend declaration above. */
+
+ if (DECL_FUNCTION_TEMPLATE_P (t) && args)
+ {
+ tree full_args = tsubst_template_arg_vector
+ (DECL_TI_ARGS (DECL_TEMPLATE_RESULT (t)), args, tf_none);
+ tree spec = NULL_TREE;
+ if (full_args != error_mark_node)
+ spec = retrieve_specialization (t, full_args);
+ if (spec)
+ t = spec;
+ }
+ }
+
+ if (!context)
+ context = DECL_CONTEXT (t);
+ if (context && TYPE_P (context))
+ push_nested_class (context, 2);
+ else
+ push_to_top_level ();
+
+ if (TREE_CODE (t) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (t))
+ {
+ saved_access_scope = tree_cons
+ (NULL_TREE, current_function_decl, saved_access_scope);
+ current_function_decl = t;
+ }
+}
+
+/* Like push_access_scope_real, but always uses DECL_CONTEXT. */
+
+void
+push_access_scope (t)
+ tree t;
+{
+ push_access_scope_real (t, NULL_TREE, NULL_TREE);
+}
+
+/* Restore the scope set up by push_access_scope. T is the node we
+ are processing. */
+
+void
+pop_access_scope (t)
+ tree t;
+{
+ if (TREE_CODE (t) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (t))
+ {
+ current_function_decl = TREE_VALUE (saved_access_scope);
+ saved_access_scope = TREE_CHAIN (saved_access_scope);
+ }
+
+ if (DECL_CLASS_SCOPE_P (t))
+ pop_nested_class ();
+ else
+ pop_from_top_level ();
+}
+
/* Do any processing required when DECL (a member template declaration
using TEMPLATE_PARAMETERS as its innermost parameter list) is
finished. Returns the TEMPLATE_DECL corresponding to DECL, unless
@@ -681,8 +767,22 @@ void
maybe_process_partial_specialization (type)
tree type;
{
- if (IS_AGGR_TYPE (type) && CLASSTYPE_USE_TEMPLATE (type))
+ /* TYPE maybe an ERROR_MARK_NODE. */
+ tree context = TYPE_P (type) ? TYPE_CONTEXT (type) : NULL_TREE;
+
+ if (CLASS_TYPE_P (type) && CLASSTYPE_USE_TEMPLATE (type))
{
+ /* This is for ordinary explicit specialization and partial
+ specialization of a template class such as:
+
+ template <> class C<int>;
+
+ or:
+
+ template <class T> class C<T*>;
+
+ Make sure that `C<int>' and `C<T*>' are implicit instantiations. */
+
if (CLASSTYPE_IMPLICIT_INSTANTIATION (type)
&& !COMPLETE_TYPE_P (type))
{
@@ -700,6 +800,62 @@ maybe_process_partial_specialization (type)
else if (CLASSTYPE_TEMPLATE_INSTANTIATION (type))
error ("specialization of `%T' after instantiation", type);
}
+ else if (CLASS_TYPE_P (type)
+ && !CLASSTYPE_USE_TEMPLATE (type)
+ && CLASSTYPE_TEMPLATE_INFO (type)
+ && context && CLASS_TYPE_P (context)
+ && CLASSTYPE_TEMPLATE_INFO (context))
+ {
+ /* This is for an explicit specialization of member class
+ template according to [temp.expl.spec/18]:
+
+ template <> template <class U> class C<int>::D;
+
+ The context `C<int>' must be an implicit instantiation.
+ Otherwise this is just a member class template declared
+ earlier like:
+
+ template <> class C<int> { template <class U> class D; };
+ template <> template <class U> class C<int>::D;
+
+ In the first case, `C<int>::D' is a specialization of `C<T>::D'
+ while in the second case, `C<int>::D' is a primary template
+ and `C<T>::D' may not exist. */
+
+ if (CLASSTYPE_IMPLICIT_INSTANTIATION (context)
+ && !COMPLETE_TYPE_P (type))
+ {
+ tree t;
+
+ if (current_namespace
+ != decl_namespace_context (CLASSTYPE_TI_TEMPLATE (type)))
+ {
+ pedwarn ("specializing `%#T' in different namespace", type);
+ cp_pedwarn_at (" from definition of `%#D'",
+ CLASSTYPE_TI_TEMPLATE (type));
+ }
+
+ /* Check for invalid specialization after instantiation:
+
+ template <> template <> class C<int>::D<int>;
+ template <> template <class U> class C<int>::D; */
+
+ for (t = DECL_TEMPLATE_INSTANTIATIONS
+ (most_general_template (CLASSTYPE_TI_TEMPLATE (type)));
+ t; t = TREE_CHAIN (t))
+ if (TREE_VALUE (t) != type
+ && TYPE_CONTEXT (TREE_VALUE (t)) == context)
+ error ("specialization `%T' after instantiation `%T'",
+ type, TREE_VALUE (t));
+
+ /* Mark TYPE as a specialization. And as a result, we only
+ have one level of template argument for the innermost
+ class template. */
+ SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (type);
+ CLASSTYPE_TI_ARGS (type)
+ = INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type));
+ }
+ }
else if (processing_specialization)
error ("explicit specialization of non-template `%T'", type);
}
@@ -1655,6 +1811,18 @@ check_explicit_specialization (declarator, decl, template_count, flags)
return instantiate_template (tmpl, targs);
}
+ /* If we thought that the DECL was a member function, but it
+ turns out to be specializing a static member function,
+ make DECL a static member function as well. We also have
+ to adjust last_function_parms to avoid confusing
+ start_function later. */
+ if (DECL_STATIC_FUNCTION_P (tmpl)
+ && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
+ {
+ revert_static_member_fn (decl);
+ last_function_parms = TREE_CHAIN (last_function_parms);
+ }
+
/* If this is a specialization of a member template of a
template class. In we want to return the TEMPLATE_DECL,
not the specialization of it. */
@@ -1665,16 +1833,6 @@ check_explicit_specialization (declarator, decl, template_count, flags)
return tmpl;
}
- /* If we thought that the DECL was a member function, but it
- turns out to be specializing a static member function,
- make DECL a static member function as well. */
- if (DECL_STATIC_FUNCTION_P (tmpl)
- && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
- {
- revert_static_member_fn (decl);
- last_function_parms = TREE_CHAIN (last_function_parms);
- }
-
/* Set up the DECL_TEMPLATE_INFO for DECL. */
DECL_TEMPLATE_INFO (decl) = tree_cons (tmpl, targs, NULL_TREE);
@@ -3341,17 +3499,12 @@ convert_template_argument (parm, arg, args, complain, i, in_decl)
&& TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL)
|| TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
|| TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE);
- else if (CLASSTYPE_TEMPLATE_INFO (arg) && !CLASSTYPE_USE_TEMPLATE (arg)
- && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (arg)))
- {
- if (is_base_of_enclosing_class (arg, current_class_type))
- /* This is a template name used within the scope of the
- template. It could be the template, or it could be the
- instantiation. Choose whichever makes sense. */
- is_tmpl_type = requires_tmpl_type;
- else
- is_tmpl_type = 1;
- }
+ else if (CLASSTYPE_IS_TEMPLATE (arg)
+ && is_base_of_enclosing_class (arg, current_class_type))
+ /* This is a template name used within the scope of the
+ template. It could be the template, or it could be the
+ instantiation. Choose whichever makes sense. */
+ is_tmpl_type = requires_tmpl_type;
else
/* It is a non-template class, or a specialization of a template
class, or a non-template member of a template class. */
@@ -3916,6 +4069,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
tree template = NULL_TREE, parmlist;
tree t;
+ timevar_push (TV_NAME_LOOKUP);
if (TREE_CODE (d1) == IDENTIFIER_NODE)
{
if (IDENTIFIER_VALUE (d1)
@@ -3971,7 +4125,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
{
if (complain & tf_error)
error ("`%T' is not a template", d1);
- return error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
if (TREE_CODE (template) != TEMPLATE_DECL
@@ -3987,7 +4141,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
if (in_decl)
cp_error_at ("for template declaration `%D'", in_decl);
}
- return error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
if (DECL_TEMPLATE_TEMPLATE_PARM_P (template))
@@ -4022,10 +4176,10 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
arglist2 = coerce_template_parms (parmlist, arglist, template,
complain, /*require_all_args=*/1);
if (arglist2 == error_mark_node)
- return error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
parm = bind_template_template_parm (TREE_TYPE (template), arglist2);
- return parm;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, parm);
}
else
{
@@ -4112,7 +4266,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
if (arglist == error_mark_node)
/* We were unable to bind the arguments. */
- return error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
/* In the scope of a template class, explicit references to the
template class refer to the type of the template, not any
@@ -4149,7 +4303,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
}
}
if (found)
- return found;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, found);
for (tp = &DECL_TEMPLATE_INSTANTIATIONS (template);
*tp;
@@ -4165,7 +4319,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
= DECL_TEMPLATE_INSTANTIATIONS (template);
DECL_TEMPLATE_INSTANTIATIONS (template) = found;
- return TREE_VALUE (found);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, TREE_VALUE (found));
}
/* This type is a "partial instantiation" if any of the template
@@ -4181,7 +4335,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
found = xref_tag_from_type (TREE_TYPE (template),
DECL_NAME (template),
/*globalize=*/1);
- return found;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, found);
}
context = tsubst (DECL_CONTEXT (template), arglist,
@@ -4233,6 +4387,11 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
else
type_decl = TYPE_NAME (t);
+ TREE_PRIVATE (type_decl)
+ = TREE_PRIVATE (TYPE_STUB_DECL (template_type));
+ TREE_PROTECTED (type_decl)
+ = TREE_PROTECTED (TYPE_STUB_DECL (template_type));
+
/* Set up the template information. We have to figure out which
template is the immediate parent if this is a full
instantiation. */
@@ -4332,8 +4491,9 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
code that generates debugging information will crash. */
DECL_IGNORED_P (TYPE_STUB_DECL (t)) = 1;
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
+ timevar_pop (TV_NAME_LOOKUP);
}
struct pair_fn_data
@@ -5108,7 +5268,7 @@ instantiate_class_template (type)
TYPE_FIELDS (type) = TYPE_FIELDS (pattern);
TYPE_METHODS (type) = TYPE_METHODS (pattern);
CLASSTYPE_DECL_LIST (type) = CLASSTYPE_DECL_LIST (pattern);
- CLASSTYPE_TAGS (type) = CLASSTYPE_TAGS (pattern);
+ CLASSTYPE_NESTED_UDTS (type) = CLASSTYPE_NESTED_UDTS (pattern);
CLASSTYPE_VBASECLASSES (type) = CLASSTYPE_VBASECLASSES (pattern);
/* Pretend that the type is complete, so that we will look
@@ -5202,6 +5362,10 @@ instantiate_class_template (type)
if (ANON_AGGR_TYPE_P (pattern))
SET_ANON_AGGR_TYPE_P (type);
+ if (DECL_CLASS_SCOPE_P (TYPE_MAIN_DECL (pattern)))
+ /* First instantiate our enclosing class. */
+ complete_type (TYPE_CONTEXT (type));
+
if (TYPE_BINFO_BASETYPES (pattern))
{
tree base_list = NULL_TREE;
@@ -5270,7 +5434,7 @@ instantiate_class_template (type)
{
if (TYPE_P (t))
{
- /* Build new CLASSTYPE_TAGS. */
+ /* Build new CLASSTYPE_NESTED_UDTS. */
tree tag = t;
tree name = TYPE_IDENTIFIER (tag);
@@ -5363,10 +5527,10 @@ instantiate_class_template (type)
/* If it is a TYPE_DECL for a class-scoped ENUMERAL_TYPE,
such a thing will already have been added to the field
list by tsubst_enum in finish_member_declaration in the
- CLASSTYPE_TAGS case above. */
+ CLASSTYPE_NESTED_UDTS case above. */
if (!(TREE_CODE (r) == TYPE_DECL
&& TREE_CODE (TREE_TYPE (r)) == ENUMERAL_TYPE
- && TYPE_CONTEXT (TREE_TYPE (r)) == type))
+ && DECL_ARTIFICIAL (r)))
{
set_current_access_from_decl (r);
finish_member_declaration (r);
@@ -5415,12 +5579,8 @@ instantiate_class_template (type)
--processing_template_decl;
}
else
- {
- /* Build new DECL_FRIENDLIST. */
-
- add_friend (type,
- tsubst_friend_function (t, args));
- }
+ /* Build new DECL_FRIENDLIST. */
+ add_friend (type, tsubst_friend_function (t, args));
}
}
@@ -5456,6 +5616,9 @@ instantiate_class_template (type)
pop_from_top_level ();
pop_tinst_level ();
+ if (TYPE_CONTAINS_VPTR_P (type))
+ keyed_classes = tree_cons (NULL_TREE, type, keyed_classes);
+
return type;
}
@@ -5691,14 +5854,14 @@ tsubst_default_argument (fn, type, arg)
??? current_class_type affects a lot more than name lookup. This is
very fragile. Fortunately, it will go away when we do 2-phase name
binding properly. */
- if (DECL_CLASS_SCOPE_P (fn))
- pushclass (DECL_CONTEXT (fn), 2);
+
+ /* FN is already the desired FUNCTION_DECL. */
+ push_access_scope (fn);
arg = tsubst_expr (arg, DECL_TI_ARGS (fn),
tf_error | tf_warning, NULL_TREE);
- if (DECL_CLASS_SCOPE_P (fn))
- popclass ();
+ pop_access_scope (fn);
/* Make sure the default argument is reasonable. */
arg = check_default_argument (type, arg);
@@ -5874,6 +6037,10 @@ tsubst_decl (t, args, type, complain)
{
tree spec;
+ /* If T is not dependent, just return it. */
+ if (!uses_template_parms (DECL_TI_ARGS (t)))
+ return t;
+
/* Calculate the most general template of which R is a
specialization, and the complete set of arguments used to
specialize R. */
@@ -6793,7 +6960,7 @@ tsubst (t, args, complain, in_decl)
}
if (TREE_CODE (type) == REFERENCE_TYPE)
{
- if (complain)
+ if (complain & tf_error)
error ("creating pointer to member reference type `%T'", type);
return error_mark_node;
@@ -7795,17 +7962,17 @@ instantiate_template (tmpl, targ_ptr)
}
/* Make sure that we can see identifiers, and compute access
- correctly. */
- if (DECL_CLASS_SCOPE_P (gen_tmpl))
- pushclass (tsubst (DECL_CONTEXT (gen_tmpl), targ_ptr, tf_error,
- gen_tmpl), 1);
+ correctly. The desired FUNCTION_DECL for FNDECL may or may not be
+ created earlier. Let push_access_scope_real figure that out. */
+ push_access_scope_real
+ (gen_tmpl, targ_ptr, tsubst (DECL_CONTEXT (gen_tmpl), targ_ptr,
+ tf_error, gen_tmpl));
/* substitute template parameters */
fndecl = tsubst (DECL_TEMPLATE_RESULT (gen_tmpl),
targ_ptr, tf_error, gen_tmpl);
- if (DECL_CLASS_SCOPE_P (gen_tmpl))
- popclass ();
+ pop_access_scope (gen_tmpl);
/* The DECL_TI_TEMPLATE should always be the immediate parent
template, not the most general template. */
@@ -7877,7 +8044,7 @@ fn_type_unification (fn, explicit_targs, targs, args, return_type,
int result;
my_friendly_assert (TREE_CODE (fn) == TEMPLATE_DECL, 0);
-
+
fntype = TREE_TYPE (fn);
if (explicit_targs)
{
@@ -8055,6 +8222,12 @@ maybe_adjust_types_for_deduction (strict, parm, arg)
*parm = TREE_TYPE (*parm);
result |= UNIFY_ALLOW_OUTER_MORE_CV_QUAL;
}
+
+ /* DR 322. For conversion deduction, remove a reference type on parm
+ too (which has been swapped into ARG). */
+ if (strict == DEDUCE_CONV && TREE_CODE (*arg) == REFERENCE_TYPE)
+ *arg = TREE_TYPE (*arg);
+
return result;
}
@@ -8292,7 +8465,8 @@ resolve_overloaded_unification (tparms, targs, parm, arg, strict,
}
}
}
- else if (TREE_CODE (arg) == OVERLOAD)
+ else if (TREE_CODE (arg) == OVERLOAD
+ || TREE_CODE (arg) == FUNCTION_DECL)
{
for (; arg; arg = OVL_NEXT (arg))
{
@@ -8442,7 +8616,8 @@ try_class_unification (tparms, targs, parm, arg)
tree copy_of_targs;
if (!CLASSTYPE_TEMPLATE_INFO (arg)
- || CLASSTYPE_TI_TEMPLATE (arg) != CLASSTYPE_TI_TEMPLATE (parm))
+ || (most_general_template (CLASSTYPE_TI_TEMPLATE (arg))
+ != most_general_template (CLASSTYPE_TI_TEMPLATE (parm))))
return NULL_TREE;
/* We need to make a new template argument vector for the call to
@@ -8833,6 +9008,12 @@ unify (tparms, targs, parm, arg, strict)
}
else
{
+ /* If ARG is an offset type, we're trying to unify '*T' with
+ 'U C::*', which is ill-formed. See the comment in the
+ POINTER_TYPE case about this ugliness. */
+ if (TREE_CODE (arg) == OFFSET_TYPE)
+ return 1;
+
/* If PARM is `const T' and ARG is only `int', we don't have
a match unless we are allowing additional qualification.
If ARG is `const int' and PARM is just `T' that's OK;
@@ -9191,11 +9372,6 @@ mark_decl_instantiated (result, extern_p)
tree result;
int extern_p;
{
- if (TREE_CODE (result) != FUNCTION_DECL)
- /* The TREE_PUBLIC flag for function declarations will have been
- set correctly by tsubst. */
- TREE_PUBLIC (result) = 1;
-
/* We used to set this unconditionally; we moved that to
do_decl_instantiation so it wouldn't get set on members of
explicit class template instantiations. But we still need to set
@@ -9204,6 +9380,19 @@ mark_decl_instantiated (result, extern_p)
if (extern_p)
SET_DECL_EXPLICIT_INSTANTIATION (result);
+ /* If this entity has already been written out, it's too late to
+ make any modifications. */
+ if (TREE_ASM_WRITTEN (result))
+ return;
+
+ if (TREE_CODE (result) != FUNCTION_DECL)
+ /* The TREE_PUBLIC flag for function declarations will have been
+ set correctly by tsubst. */
+ TREE_PUBLIC (result) = 1;
+
+ /* This might have been set by an earlier implicit instantiation. */
+ DECL_COMDAT (result) = 0;
+
if (! extern_p)
{
DECL_INTERFACE_KNOWN (result) = 1;
@@ -9217,7 +9406,8 @@ mark_decl_instantiated (result, extern_p)
else if (TREE_PUBLIC (result))
maybe_make_one_only (result);
}
- else if (TREE_CODE (result) == FUNCTION_DECL)
+
+ if (TREE_CODE (result) == FUNCTION_DECL)
defer_fn (result);
}
@@ -9508,6 +9698,10 @@ most_general_template (decl)
if (TREE_CODE (DECL_TI_TEMPLATE (decl)) != TEMPLATE_DECL)
break;
+ if (CLASS_TYPE_P (TREE_TYPE (decl))
+ && CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)))
+ break;
+
/* Stop if we run into an explicitly specialized class template. */
if (!DECL_NAMESPACE_SCOPE_P (decl)
&& DECL_CONTEXT (decl)
@@ -9707,6 +9901,18 @@ mark_class_instantiated (t, extern_p)
}
}
+/* Called from do_type_instantiation through binding_table_foreach to
+ do recursive instantiation for the type bound in ENTRY. */
+static void
+bt_instantiate_type_proc (binding_entry entry, void *data)
+{
+ tree storage = *(tree *) data;
+
+ if (IS_AGGR_TYPE (entry->type)
+ && !uses_template_parms (CLASSTYPE_TI_ARGS (entry->type)))
+ do_type_instantiation (TYPE_MAIN_DECL (entry->type), storage, 0);
+}
+
/* Perform an explicit instantiation of template class T. STORAGE, if
non-null, is the RID for extern, inline or static. COMPLAIN is
nonzero if this is called from the parser, zero if called recursively,
@@ -9847,10 +10053,9 @@ do_type_instantiation (t, storage, complain)
instantiate_decl (tmp, /*defer_ok=*/1);
}
- for (tmp = CLASSTYPE_TAGS (t); tmp; tmp = TREE_CHAIN (tmp))
- if (IS_AGGR_TYPE (TREE_VALUE (tmp))
- && !uses_template_parms (CLASSTYPE_TI_ARGS (TREE_VALUE (tmp))))
- do_type_instantiation (TYPE_MAIN_DECL (TREE_VALUE (tmp)), storage, 0);
+ if (CLASSTYPE_NESTED_UDTS (t))
+ binding_table_foreach (CLASSTYPE_NESTED_UDTS (t),
+ bt_instantiate_type_proc, &storage);
}
}
@@ -9897,6 +10102,7 @@ regenerate_decl_from_template (decl, tmpl)
instantiation of a specialization, which it isn't: it's a full
instantiation. */
gen_tmpl = most_general_template (tmpl);
+ push_access_scope_real (gen_tmpl, args, DECL_CONTEXT (decl));
unregistered = unregister_specialization (decl, gen_tmpl);
/* If the DECL was not unregistered then something peculiar is
@@ -9904,11 +10110,6 @@ regenerate_decl_from_template (decl, tmpl)
register_specialization for it. */
my_friendly_assert (unregistered, 0);
- if (DECL_CLASS_SCOPE_P (decl))
- /* Make sure that we can see identifiers, and compute access
- correctly, for the class members used in the declaration of
- this static variable or function. */
- pushclass (DECL_CONTEXT (decl), 2);
/* Do the substitution to get the new declaration. */
new_decl = tsubst (code_pattern, args, tf_error, NULL_TREE);
@@ -9930,9 +10131,7 @@ regenerate_decl_from_template (decl, tmpl)
DECL_INITIAL (decl) = NULL_TREE;
}
- /* Pop the class context we pushed above. */
- if (DECL_CLASS_SCOPE_P (decl))
- popclass ();
+ pop_access_scope (decl);
/* The immediate parent of the new template is still whatever it was
before, even though tsubst sets DECL_TI_TEMPLATE up as the most
@@ -9979,6 +10178,9 @@ instantiate_decl (d, defer_ok)
my_friendly_assert (TREE_CODE (d) == FUNCTION_DECL
|| TREE_CODE (d) == VAR_DECL, 0);
+ if (TREE_CODE (d) == VAR_DECL)
+ defer_ok = 0;
+
/* Don't instantiate cloned functions. Instead, instantiate the
functions they cloned. */
if (TREE_CODE (d) == FUNCTION_DECL && DECL_CLONED_FUNCTION_P (d))
@@ -10060,12 +10262,15 @@ instantiate_decl (d, defer_ok)
code_pattern = DECL_TEMPLATE_RESULT (td);
- /* In the case of a friend template whose definition is provided
- outside the class, we may have too many arguments. Drop the ones
- we don't need. */
- args = get_innermost_template_args (gen_args,
- TMPL_PARMS_DEPTH
- (DECL_TEMPLATE_PARMS (td)));
+ if ((DECL_NAMESPACE_SCOPE_P (d) && !DECL_INITIALIZED_IN_CLASS_P (d))
+ || DECL_TEMPLATE_SPECIALIZATION (td))
+ /* In the case of a friend template whose definition is provided
+ outside the class, we may have too many arguments. Drop the
+ ones we don't need. The same is true for specializations. */
+ args = get_innermost_template_args
+ (gen_args, TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (td)));
+ else
+ args = gen_args;
if (TREE_CODE (d) == FUNCTION_DECL)
pattern_defined = (DECL_SAVED_TREE (code_pattern) != NULL_TREE);
@@ -10125,9 +10330,9 @@ instantiate_decl (d, defer_ok)
tree type = TREE_TYPE (gen);
/* Make sure that we can see identifiers, and compute access
- correctly. */
- if (DECL_CLASS_SCOPE_P (d))
- pushclass (DECL_CONTEXT (d), 1);
+ correctly. D is already the target FUNCTION_DECL with the
+ right context. */
+ push_access_scope (d);
if (TREE_CODE (gen) == FUNCTION_DECL)
{
@@ -10142,8 +10347,7 @@ instantiate_decl (d, defer_ok)
}
tsubst (type, gen_args, tf_error | tf_warning, d);
- if (DECL_CLASS_SCOPE_P (d))
- popclass ();
+ pop_access_scope (d);
}
if (TREE_CODE (d) == VAR_DECL && DECL_INITIALIZED_IN_CLASS_P (d)
@@ -10184,15 +10388,10 @@ instantiate_decl (d, defer_ok)
if (need_push)
push_to_top_level ();
- /* We're now committed to instantiating this template. Mark it as
- instantiated so that recursive calls to instantiate_decl do not
- try to instantiate it again. */
- DECL_TEMPLATE_INSTANTIATED (d) = 1;
-
/* Regenerate the declaration in case the template has been modified
by a subsequent redeclaration. */
regenerate_decl_from_template (d, td);
-
+
/* We already set the file and line above. Reset them now in case
they changed as a result of calling regenerate_decl_from_template. */
lineno = DECL_SOURCE_LINE (d);
@@ -10200,23 +10399,52 @@ instantiate_decl (d, defer_ok)
if (TREE_CODE (d) == VAR_DECL)
{
+ /* Clear out DECL_RTL; whatever was there before may not be right
+ since we've reset the type of the declaration. */
+ SET_DECL_RTL (d, NULL_RTX);
+
DECL_IN_AGGR_P (d) = 0;
- if (DECL_INTERFACE_KNOWN (d))
- DECL_EXTERNAL (d) = ! DECL_NOT_REALLY_EXTERN (d);
+ import_export_decl (d);
+ DECL_EXTERNAL (d) = ! DECL_NOT_REALLY_EXTERN (d);
+
+ if (DECL_EXTERNAL (d))
+ {
+ /* The fact that this code is executing indicates that:
+
+ (1) D is a template static data member, for which a
+ definition is available.
+
+ (2) An implicit or explicit instantiation has occured.
+
+ (3) We are not going to emit a definition of the static
+ data member at this time.
+
+ This situation is peculiar, but it occurs on platforms
+ without weak symbols when performing an implicit
+ instantiation. There, we cannot implicitly instantiate a
+ defined static data member in more than one translation
+ unit, so import_export_decl marks the declaration as
+ external; we must rely on explicit instantiation. */
+ }
else
{
- DECL_EXTERNAL (d) = 1;
- DECL_NOT_REALLY_EXTERN (d) = 1;
+ /* Mark D as instantiated so that recursive calls to
+ instantiate_decl do not try to instantiate it again. */
+ DECL_TEMPLATE_INSTANTIATED (d) = 1;
+ cp_finish_decl (d,
+ (!DECL_INITIALIZED_IN_CLASS_P (d)
+ ? DECL_INITIAL (d) : NULL_TREE),
+ NULL_TREE, 0);
}
- cp_finish_decl (d,
- (!DECL_INITIALIZED_IN_CLASS_P (d)
- ? DECL_INITIAL (d) : NULL_TREE),
- NULL_TREE, 0);
}
else if (TREE_CODE (d) == FUNCTION_DECL)
{
htab_t saved_local_specializations;
+ /* Mark D as instantiated so that recursive calls to
+ instantiate_decl do not try to instantiate it again. */
+ DECL_TEMPLATE_INSTANTIATED (d) = 1;
+
/* Save away the current list, in case we are instantiating one
template from within the body of another. */
saved_local_specializations = local_specializations;
@@ -10228,6 +10456,7 @@ instantiate_decl (d, defer_ok)
NULL);
/* Set up context. */
+ import_export_decl (d);
start_function (NULL_TREE, d, NULL_TREE, SF_PRE_PARSED);
/* Substitute into the body of the function. */
@@ -10239,7 +10468,8 @@ instantiate_decl (d, defer_ok)
local_specializations = saved_local_specializations;
/* Finish the function. */
- expand_body (finish_function (0));
+ d = finish_function (0);
+ expand_body (d);
}
/* We're not deferring instantiation any more. */
@@ -10365,9 +10595,12 @@ tsubst_initializer_list (t, argvec)
decl = tsubst_copy (TREE_PURPOSE (t), argvec, tf_error | tf_warning,
NULL_TREE);
+ decl = expand_member_init (decl);
+ if (decl && !DECL_P (decl))
+ in_base_initializer = 1;
+
init = tsubst_expr (TREE_VALUE (t), argvec, tf_error | tf_warning,
NULL_TREE);
-
if (!init)
;
else if (TREE_CODE (init) == TREE_LIST)
@@ -10376,9 +10609,11 @@ tsubst_initializer_list (t, argvec)
else if (init != void_type_node)
init = convert_from_reference (init);
- init = expand_member_init (decl, init);
- if (init)
+ in_base_initializer = 0;
+
+ if (decl)
{
+ init = build_tree_list (decl, init);
TREE_CHAIN (init) = inits;
inits = init;
}
@@ -10483,8 +10718,7 @@ get_mostly_instantiated_function_type (decl)
partial substitution here. It depends only on outer template
parameters, regardless of whether the innermost level is
specialized or not. */
- if (DECL_CLASS_SCOPE_P (decl))
- pushclass (DECL_CONTEXT (decl), 1);
+ push_access_scope (decl);
/* Now, do the (partial) substitution to figure out the
appropriate function type. */
@@ -10497,8 +10731,7 @@ get_mostly_instantiated_function_type (decl)
TREE_VEC_LENGTH (partial_args)--;
tparms = tsubst_template_parms (tparms, partial_args, tf_error);
- if (DECL_CLASS_SCOPE_P (decl))
- popclass ();
+ pop_access_scope (decl);
}
return fn_type;