When a class template is explicitly instantiated, its member should be too.
* cp-tree.h (instantiate_decl): new boolean parameter, undefined_ok. Current behavior is equivalent to its being 0. * decl2.c (mark_used): Add new argument when calling instantiate_decl * pt.c (mark_decl_instantiated): Unconditionally make instantiations explicit unconditionally (do_decl_instantiation): Don't call SET_DECL_EXPLICIT_INSTANTIATION, since mark_decl_instantiated now does it. (instantiate_class_member): New. Instantiate a member of an explicitly instantiated class template. (do_type_instantiation): Explicitly instantiate members of an explicitly instantiated class template. (instantiate_decl): if undefined_ok is nonzero, and if we're trying to explicitly instantiated a template with no definition, change it to an implicit instantiation. (instantiate_pending_templates): Add new argument to instantiate_decl. * tree.c (cp_cannot_inline_tree_fn): Likewise. From-SVN: r82585
This commit is contained in:
parent
b53dcf3e5c
commit
415c974c0b
@ -1,3 +1,22 @@
|
||||
2004-06-02 Matt Austern <austern@apple.com>
|
||||
|
||||
* cp-tree.h (instantiate_decl): new boolean parameter,
|
||||
undefined_ok. Current behavior is equivalent to its being 0.
|
||||
* decl2.c (mark_used): Add new argument when calling instantiate_decl
|
||||
* pt.c (mark_decl_instantiated): Unconditionally make
|
||||
instantiations explicit unconditionally
|
||||
(do_decl_instantiation): Don't call SET_DECL_EXPLICIT_INSTANTIATION,
|
||||
since mark_decl_instantiated now does it.
|
||||
(instantiate_class_member): New. Instantiate a member of an
|
||||
explicitly instantiated class template.
|
||||
(do_type_instantiation): Explicitly instantiate members of an
|
||||
explicitly instantiated class template.
|
||||
(instantiate_decl): if undefined_ok is nonzero, and if we're
|
||||
trying to explicitly instantiated a template with no definition,
|
||||
change it to an implicit instantiation.
|
||||
(instantiate_pending_templates): Add new argument to instantiate_decl.
|
||||
* tree.c (cp_cannot_inline_tree_fn): Likewise.
|
||||
|
||||
2004-06-02 Andrew Pinski <pinskia@physics.uc.edu>
|
||||
|
||||
* cp-tree.h: Fix typo.
|
||||
|
@ -3889,7 +3889,7 @@ extern int more_specialized (tree, tree, int, int);
|
||||
extern void mark_class_instantiated (tree, int);
|
||||
extern void do_decl_instantiation (tree, tree);
|
||||
extern void do_type_instantiation (tree, tree, tsubst_flags_t);
|
||||
extern tree instantiate_decl (tree, int);
|
||||
extern tree instantiate_decl (tree, int, int);
|
||||
extern int push_tinst_level (tree);
|
||||
extern void pop_tinst_level (void);
|
||||
extern int more_specialized_class (tree, tree, tree);
|
||||
|
@ -3069,7 +3069,7 @@ mark_used (tree decl)
|
||||
information. */
|
||||
|| cp_function_chain->can_throw);
|
||||
|
||||
instantiate_decl (decl, defer);
|
||||
instantiate_decl (decl, defer, /*undefined_ok=*/0);
|
||||
}
|
||||
}
|
||||
|
||||
|
80
gcc/cp/pt.c
80
gcc/cp/pt.c
@ -10131,12 +10131,6 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
|
||||
void
|
||||
mark_decl_instantiated (tree result, int extern_p)
|
||||
{
|
||||
/* 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
|
||||
it here for the 'extern template' case in order to suppress
|
||||
implicit instantiations. */
|
||||
if (extern_p)
|
||||
SET_DECL_EXPLICIT_INSTANTIATION (result);
|
||||
|
||||
/* If this entity has already been written out, it's too late to
|
||||
@ -10641,11 +10635,10 @@ do_decl_instantiation (tree decl, tree storage)
|
||||
error ("storage class `%D' applied to template instantiation",
|
||||
storage);
|
||||
|
||||
SET_DECL_EXPLICIT_INSTANTIATION (result);
|
||||
mark_decl_instantiated (result, extern_p);
|
||||
repo_template_instantiated (result, extern_p);
|
||||
if (! extern_p)
|
||||
instantiate_decl (result, /*defer_ok=*/1);
|
||||
instantiate_decl (result, /*defer_ok=*/1, /*undefined_ok=*/0);
|
||||
}
|
||||
|
||||
void
|
||||
@ -10674,6 +10667,18 @@ bt_instantiate_type_proc (binding_entry entry, void *data)
|
||||
do_type_instantiation (TYPE_MAIN_DECL (entry->type), storage, 0);
|
||||
}
|
||||
|
||||
/* Called from do_type_instantiation to instantiate a member
|
||||
(a member function or a static member variable) of an
|
||||
explicitly instantiated class template. */
|
||||
static void
|
||||
instantiate_class_member (tree decl, int extern_p)
|
||||
{
|
||||
mark_decl_instantiated (decl, extern_p);
|
||||
repo_template_instantiated (decl, extern_p);
|
||||
if (! extern_p)
|
||||
instantiate_decl (decl, /*defer_ok=*/1, /* undefined_ok=*/1);
|
||||
}
|
||||
|
||||
/* 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,
|
||||
@ -10773,7 +10778,6 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
|
||||
|
||||
{
|
||||
tree tmp;
|
||||
int explicitly_instantiate_members = 0;
|
||||
|
||||
/* In contrast to implicit instantiation, where only the
|
||||
declarations, and not the definitions, of members are
|
||||
@ -10789,50 +10793,18 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
|
||||
Of course, we can't instantiate member template classes, since
|
||||
we don't have any arguments for them. Note that the standard
|
||||
is unclear on whether the instantiation of the members are
|
||||
*explicit* instantiations or not. We choose to be generous,
|
||||
and not set DECL_EXPLICIT_INSTANTIATION. Therefore, we allow
|
||||
the explicit instantiation of a class where some of the members
|
||||
have no definition in the current translation unit. Exception:
|
||||
on some targets (e.g. Darwin), weak symbols do not get put in
|
||||
a static archive's TOC. The problematic case is if we're doing
|
||||
a non-extern explicit instantiation of an extern template: we
|
||||
have to put member functions in the TOC in that case, or we'll
|
||||
get unresolved symbols at link time. */
|
||||
|
||||
explicitly_instantiate_members =
|
||||
TARGET_EXPLICIT_INSTANTIATIONS_ONE_ONLY
|
||||
&& previous_instantiation_extern_p && ! extern_p
|
||||
&& ! TYPE_FOR_JAVA (t);
|
||||
*explicit* instantiations or not. However, the most natural
|
||||
interpretation is that it should be an explicit instantiation. */
|
||||
|
||||
if (! static_p)
|
||||
for (tmp = TYPE_METHODS (t); tmp; tmp = TREE_CHAIN (tmp))
|
||||
if (TREE_CODE (tmp) == FUNCTION_DECL
|
||||
&& DECL_TEMPLATE_INSTANTIATION (tmp))
|
||||
{
|
||||
if (explicitly_instantiate_members)
|
||||
do_decl_instantiation (tmp, NULL_TREE);
|
||||
else
|
||||
{
|
||||
mark_decl_instantiated (tmp, extern_p);
|
||||
repo_template_instantiated (tmp, extern_p);
|
||||
if (! extern_p)
|
||||
instantiate_decl (tmp, /*defer_ok=*/1);
|
||||
}
|
||||
}
|
||||
instantiate_class_member (tmp, extern_p);
|
||||
|
||||
for (tmp = TYPE_FIELDS (t); tmp; tmp = TREE_CHAIN (tmp))
|
||||
if (TREE_CODE (tmp) == VAR_DECL && DECL_TEMPLATE_INSTANTIATION (tmp))
|
||||
{
|
||||
if (explicitly_instantiate_members)
|
||||
do_decl_instantiation (tmp, NULL_TREE);
|
||||
else
|
||||
{
|
||||
mark_decl_instantiated (tmp, extern_p);
|
||||
repo_template_instantiated (tmp, extern_p);
|
||||
if (! extern_p)
|
||||
instantiate_decl (tmp, /*defer_ok=*/1);
|
||||
}
|
||||
}
|
||||
instantiate_class_member (tmp, extern_p);
|
||||
|
||||
if (CLASSTYPE_NESTED_UTDS (t))
|
||||
binding_table_foreach (CLASSTYPE_NESTED_UTDS (t),
|
||||
@ -10995,10 +10967,16 @@ template_for_substitution (tree decl)
|
||||
|
||||
/* Produce the definition of D, a _DECL generated from a template. If
|
||||
DEFER_OK is nonzero, then we don't have to actually do the
|
||||
instantiation now; we just have to do it sometime. */
|
||||
instantiation now; we just have to do it sometime. Normally it is
|
||||
an error if this is an explicit instantiation but D is undefined.
|
||||
If UNDEFINED_OK is nonzero, then instead we treat it as an implicit
|
||||
instantiation. UNDEFINED_OK is nonzero only if we are being used
|
||||
to instantiate the members of an explicitly instantiated class
|
||||
template. */
|
||||
|
||||
|
||||
tree
|
||||
instantiate_decl (tree d, int defer_ok)
|
||||
instantiate_decl (tree d, int defer_ok, int undefined_ok)
|
||||
{
|
||||
tree tmpl = DECL_TI_TEMPLATE (d);
|
||||
tree gen_args;
|
||||
@ -11105,6 +11083,9 @@ instantiate_decl (tree d, int defer_ok)
|
||||
import_export_decl (d);
|
||||
}
|
||||
|
||||
if (! pattern_defined && DECL_EXPLICIT_INSTANTIATION (d) && undefined_ok)
|
||||
SET_DECL_IMPLICIT_INSTANTIATION (d);
|
||||
|
||||
if (!defer_ok)
|
||||
{
|
||||
/* Recheck the substitutions to obtain any warning messages
|
||||
@ -11340,7 +11321,7 @@ instantiate_pending_templates (void)
|
||||
fn;
|
||||
fn = TREE_CHAIN (fn))
|
||||
if (! DECL_ARTIFICIAL (fn))
|
||||
instantiate_decl (fn, /*defer_ok=*/0);
|
||||
instantiate_decl (fn, /*defer_ok=*/0, /*undefined_ok=*/0);
|
||||
if (COMPLETE_TYPE_P (instantiation))
|
||||
{
|
||||
instantiated_something = 1;
|
||||
@ -11364,7 +11345,8 @@ instantiate_pending_templates (void)
|
||||
&& !DECL_TEMPLATE_INSTANTIATED (instantiation))
|
||||
{
|
||||
instantiation = instantiate_decl (instantiation,
|
||||
/*defer_ok=*/0);
|
||||
/*defer_ok=*/0,
|
||||
/*undefined_ok=*/0);
|
||||
if (DECL_TEMPLATE_INSTANTIATED (instantiation))
|
||||
{
|
||||
instantiated_something = 1;
|
||||
|
@ -2057,7 +2057,7 @@ cp_cannot_inline_tree_fn (tree* fnp)
|
||||
(template_for_substitution (fn))))
|
||||
return 1;
|
||||
|
||||
fn = *fnp = instantiate_decl (fn, /*defer_ok=*/0);
|
||||
fn = *fnp = instantiate_decl (fn, /*defer_ok=*/0, /*undefined_ok=*/0);
|
||||
|
||||
if (TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (fn)))
|
||||
return 1;
|
||||
|
Loading…
Reference in New Issue
Block a user