From 415c974c0bd00f130e7795c3342bad4e3f014c6e Mon Sep 17 00:00:00 2001 From: Matt Austern Date: Wed, 2 Jun 2004 21:12:54 +0000 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 19 +++++++++++ gcc/cp/cp-tree.h | 2 +- gcc/cp/decl2.c | 2 +- gcc/cp/pt.c | 82 +++++++++++++++++++----------------------------- gcc/cp/tree.c | 2 +- 5 files changed, 54 insertions(+), 53 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 636a33cb688..4eb93dcbcc6 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,22 @@ +2004-06-02 Matt Austern + + * 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 * cp-tree.h: Fix typo. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 50e9fe896f5..3db4ab69ddb 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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); diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 0b93a5815de..c5c4a55a1c4 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -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); } } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 824e8bf5aa0..7d915dc7390 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -10131,13 +10131,7 @@ 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); + SET_DECL_EXPLICIT_INSTANTIATION (result); /* If this entity has already been written out, it's too late to make any modifications. */ @@ -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; diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 365e0753074..81db7ca6389 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -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; -- 2.30.2