diff options
author | Mark Mitchell <mark@codesourcery.com> | 2004-10-07 17:48:36 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2004-10-07 17:48:36 +0000 |
commit | c7222c02245141fe7dbe018593717e1b63389d23 (patch) | |
tree | 8114b15819ae2f47168dcdfac92c99c8df72ce80 /gcc | |
parent | d0e75c71c9a2586b0de06873febcdddd0eb7f01b (diff) | |
download | gcc-c7222c02245141fe7dbe018593717e1b63389d23.zip gcc-c7222c02245141fe7dbe018593717e1b63389d23.tar.gz gcc-c7222c02245141fe7dbe018593717e1b63389d23.tar.bz2 |
cp-tree.h (ICS_USER_FLAG): Remove comment about obsolete flag.
* cp-tree.h (ICS_USER_FLAG): Remove comment about obsolete flag.
(DECL_MEMBER_TEMPLATE_P): New macro.
(is_member_template): Remove.
(class_method_index_for_fn): New function.
* pt.c (build_over_call): Use DECL_MEMBER_TEMPLATE_P.
* class.c (finish_struct_methods): Remove out-of-date comment.
* decl.c (copy_fn_p): Use DECL_MBMER_TEMPLATE_P.
* decl2.c (check_classfn): Use DECL_MEMBER_TEMPLATE_P and
class_method_index_for_fn.
* pt.c (is_member_template): Remove.
(is_member_template_class): Likewise.
(optimize_specialization_lookup_p): New function.
(retrieve_specialization): Optimize lookups for members that are
not member templates.
(register_specialization): Adjust accordingly.
(build_template_decl): Add member_template_p parameter. Set
DECL_MEMBER_TEMPLATE_P.
(process_partial_specialization): Adjust call to
retrieve_specialization.
(push_template_decl_real): Determine whether the template is a
member template.
(lookup_template_class): Use retrieve_specialization.
(tsubst_decl): Adjust call to retrieve_specialization.
(tsubst_exception_specification): New function.
(tsubst): Use it.
(tsubst_copy): Use DECL_MEMBER_TEMPLATE_P.
(instantiate_template): Adjust call to retrieve_specialization.
(regenerate_decl_from_template): Do not actually generate a new
DECL.
(instantiate_decl): Adjust call to retrieve_specialization.
(class_method_index_for_fn): New method.
From-SVN: r88697
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 34 | ||||
-rw-r--r-- | gcc/cp/call.c | 2 | ||||
-rw-r--r-- | gcc/cp/class.c | 16 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 9 | ||||
-rw-r--r-- | gcc/cp/decl.c | 3 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 8 | ||||
-rw-r--r-- | gcc/cp/pt.c | 517 | ||||
-rw-r--r-- | gcc/cp/search.c | 16 |
8 files changed, 345 insertions, 260 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 364d1be..8b104c7 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,37 @@ +2004-10-07 Mark Mitchell <mark@codesourcery.com> + + * cp-tree.h (ICS_USER_FLAG): Remove comment about obsolete flag. + (DECL_MEMBER_TEMPLATE_P): New macro. + (is_member_template): Remove. + (class_method_index_for_fn): New function. + * pt.c (build_over_call): Use DECL_MEMBER_TEMPLATE_P. + * class.c (finish_struct_methods): Remove out-of-date comment. + * decl.c (copy_fn_p): Use DECL_MBMER_TEMPLATE_P. + * decl2.c (check_classfn): Use DECL_MEMBER_TEMPLATE_P and + class_method_index_for_fn. + * pt.c (is_member_template): Remove. + (is_member_template_class): Likewise. + (optimize_specialization_lookup_p): New function. + (retrieve_specialization): Optimize lookups for members that are + not member templates. + (register_specialization): Adjust accordingly. + (build_template_decl): Add member_template_p parameter. Set + DECL_MEMBER_TEMPLATE_P. + (process_partial_specialization): Adjust call to + retrieve_specialization. + (push_template_decl_real): Determine whether the template is a + member template. + (lookup_template_class): Use retrieve_specialization. + (tsubst_decl): Adjust call to retrieve_specialization. + (tsubst_exception_specification): New function. + (tsubst): Use it. + (tsubst_copy): Use DECL_MEMBER_TEMPLATE_P. + (instantiate_template): Adjust call to retrieve_specialization. + (regenerate_decl_from_template): Do not actually generate a new + DECL. + (instantiate_decl): Adjust call to retrieve_specialization. + (class_method_index_for_fn): New method. + 2004-10-07 Andrew Pinski <pinskia@physics.uc.edu> * parser.c (cp_parser_asm_definition): Look passed the diff --git a/gcc/cp/call.c b/gcc/cp/call.c index bd607ab..7d4e963 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -4614,7 +4614,7 @@ build_over_call (struct z_candidate *cand, int flags) primary template because `B<T>::g' and `B<int>::g' may have different access. */ if (DECL_TEMPLATE_INFO (fn) - && is_member_template (DECL_TI_TEMPLATE (fn))) + && DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (fn))) perform_or_defer_access_check (cand->access_path, DECL_TI_TEMPLATE (fn)); else diff --git a/gcc/cp/class.c b/gcc/cp/class.c index c2ac0a6..e955560 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -1657,17 +1657,7 @@ resort_type_method_vec (void* obj, } } -/* Warn about duplicate methods in fn_fields. Also compact method - lists so that lookup can be made faster. - - Data Structure: List of method lists. The outer list is a - TREE_LIST, whose TREE_PURPOSE field is the field name and the - TREE_VALUE is the DECL_CHAIN of the FUNCTION_DECLs. TREE_CHAIN - links the entire list of methods for TYPE_METHODS. Friends are - chained in the same way as member functions (? TREE_CHAIN or - DECL_CHAIN), but they live in the TREE_TYPE field of the outer - list. That allows them to be quickly deleted, and requires no - extra storage. +/* Warn about duplicate methods in fn_fields. Sort methods that are not special (i.e., constructors, destructors, and type conversion operators) so that we can find them faster in @@ -1686,11 +1676,9 @@ finish_struct_methods (tree t) len = VEC_length (tree, method_vec); - /* First fill in entry 0 with the constructors, entry 1 with destructors, - and the next few with type conversion operators (if any). */ + /* Clear DECL_IN_AGGR_P for all functions. */ for (fn_fields = TYPE_METHODS (t); fn_fields; fn_fields = TREE_CHAIN (fn_fields)) - /* Clear out this flag. */ DECL_IN_AGGR_P (fn_fields) = 0; if (TYPE_HAS_DESTRUCTOR (t) && !CLASSTYPE_DESTRUCTORS (t)) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 5ff38b7..58dae73 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -39,7 +39,6 @@ struct diagnostic_context; DELETE_EXPR_USE_GLOBAL (in DELETE_EXPR). COMPOUND_EXPR_OVERLOADED (in COMPOUND_EXPR). TREE_INDIRECT_USING (in NAMESPACE_DECL). - ICS_USER_FLAG (in _CONV) CLEANUP_P (in TRY_BLOCK) AGGR_INIT_VIA_CTOR_P (in AGGR_INIT_EXPR) PTRMEM_OK_P (in ADDR_EXPR, OFFSET_REF) @@ -90,6 +89,7 @@ struct diagnostic_context; DECL_MUTABLE_P (in FIELD_DECL) 1: C_TYPEDEF_EXPLICITLY_SIGNED (in TYPE_DECL). DECL_TEMPLATE_INSTANTIATED (in a VAR_DECL or a FUNCTION_DECL) + DECL_MEMBER_TEMPLATE_P (in TEMPLATE_DECL) 2: DECL_THIS_EXTERN (in VAR_DECL or FUNCTION_DECL). DECL_IMPLICIT_TYPEDEF_P (in a TYPE_DECL) 3: DECL_IN_AGGR_P. @@ -2177,6 +2177,11 @@ struct lang_decl GTY(()) #define INNERMOST_TEMPLATE_PARMS(NODE) TREE_VALUE (NODE) +/* Nonzero if NODE (a TEMPLATE_DECL) is a member template, in the + sense of [temp.mem]. */ +#define DECL_MEMBER_TEMPLATE_P(NODE) \ + (DECL_LANG_FLAG_1 (TEMPLATE_DECL_CHECK (NODE))) + /* Nonzero if the NODE corresponds to the template parameters for a member template, whose inline definition is being processed after the class definition is complete. */ @@ -3930,7 +3935,6 @@ 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); -extern int is_member_template (tree); extern int comp_template_parms (tree, tree); extern int template_class_depth (tree); extern int is_specialization_of (tree, tree); @@ -3990,6 +3994,7 @@ extern int accessible_p (tree, tree); extern tree lookup_field_1 (tree, tree, bool); extern tree lookup_field (tree, tree, int, bool); extern int lookup_fnfields_1 (tree, tree); +extern int class_method_index_for_fn (tree, tree); extern tree lookup_fnfields (tree, tree, int); extern tree lookup_member (tree, tree, int, bool); extern int look_for_overrides (tree, tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 078e2f9..919b619 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -8477,7 +8477,8 @@ copy_fn_p (tree d) gcc_assert (DECL_FUNCTION_MEMBER_P (d)); - if (DECL_TEMPLATE_INFO (d) && is_member_template (DECL_TI_TEMPLATE (d))) + if (DECL_TEMPLATE_INFO (d) + && DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (d))) /* Instantiations of template member functions are never copy functions. Note that member functions of templated classes are represented as template functions internally, and we must diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 3c1f9b4..896fdfc 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -596,7 +596,7 @@ check_classfn (tree ctype, tree function, tree template_parms) if (DECL_USE_TEMPLATE (function) && !(TREE_CODE (function) == TEMPLATE_DECL && DECL_TEMPLATE_SPECIALIZATION (function)) - && is_member_template (DECL_TI_TEMPLATE (function))) + && DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (function))) /* Since this is a specialization of a member template, we're not going to find the declaration in the class. For example, in: @@ -622,11 +622,7 @@ check_classfn (tree ctype, tree function, tree template_parms) /* OK, is this a definition of a member template? */ is_template = (template_parms != NULL_TREE); - ix = lookup_fnfields_1 (complete_type (ctype), - DECL_CONSTRUCTOR_P (function) ? ctor_identifier : - DECL_DESTRUCTOR_P (function) ? dtor_identifier : - DECL_NAME (function)); - + ix = class_method_index_for_fn (complete_type (ctype), function); if (ix >= 0) { VEC(tree) *methods = CLASSTYPE_METHOD_VEC (ctype); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 3813c38..0d24d06 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -117,12 +117,9 @@ static int for_each_template_parm (tree, tree_fn_t, void*, htab_t); static tree build_template_parm_index (int, int, int, tree, tree); static int inline_needs_template_parms (tree); static void push_inline_template_parms_recursive (tree, int); -static tree retrieve_specialization (tree, tree); static tree retrieve_local_specialization (tree); -static tree register_specialization (tree, tree, tree); static void register_local_specialization (tree, tree); static tree reduce_template_parm_level (tree, tree, int); -static tree build_template_decl (tree, tree); static int mark_template_parm (tree, void *); static int template_parm_this_level_p (tree, void *); static tree tsubst_friend_function (tree, tree); @@ -441,67 +438,6 @@ maybe_end_member_template_processing (void) } } -/* Returns nonzero iff T is a member template function. We must be - careful as in - - template <class T> class C { void f(); } - - Here, f is a template function, and a member, but not a member - template. This function does not concern itself with the origin of - T, only its present state. So if we have - - template <class T> class C { template <class U> void f(U); } - - then neither C<int>::f<char> nor C<T>::f<double> is considered - to be a member template. But, `template <class U> void - C<int>::f(U)' is considered a member template. */ - -int -is_member_template (tree t) -{ - if (!DECL_FUNCTION_TEMPLATE_P (t)) - /* Anything that isn't a function or a template function is - certainly not a member template. */ - return 0; - - /* A local class can't have member templates. */ - if (decl_function_context (t)) - return 0; - - return (DECL_FUNCTION_MEMBER_P (DECL_TEMPLATE_RESULT (t)) - /* If there are more levels of template parameters than - there are template classes surrounding the declaration, - then we have a member template. */ - && (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (t)) > - template_class_depth (DECL_CONTEXT (t)))); -} - -#if 0 /* UNUSED */ -/* Returns nonzero iff T is a member template class. See - is_member_template for a description of what precisely constitutes - a member template. */ - -int -is_member_template_class (tree t) -{ - if (!DECL_CLASS_TEMPLATE_P (t)) - /* Anything that isn't a class template, is certainly not a member - template. */ - return 0; - - if (!DECL_CLASS_SCOPE_P (t)) - /* Anything whose context isn't a class type is surely not a - member template. */ - return 0; - - /* If there are more levels of template parameters than there are - template classes surrounding the declaration, then we have a - member template. */ - return (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (t)) > - template_class_depth (DECL_CONTEXT (t))); -} -#endif - /* Return a new template argument vector which contains all of ARGS, but has as its innermost set of arguments the EXTRA_ARGS. */ @@ -826,30 +762,122 @@ maybe_process_partial_specialization (tree type) error ("explicit specialization of non-template %qT", type); } +/* Returns onzero if we can optimize the retrieval of specializations + for TMPL, a TEMPLATE_DECL. In particular, for such a template, we + do not use DECL_TEMPLATE_SPECIALIZATIONS at all. */ + +static inline bool +optimize_specialization_lookup_p (tree tmpl) +{ + return (DECL_FUNCTION_TEMPLATE_P (tmpl) + && DECL_CLASS_SCOPE_P (tmpl) + /* DECL_CLASS_SCOPE_P holds of T::f even if T is a template + parameter. */ + && CLASS_TYPE_P (DECL_CONTEXT (tmpl)) + && !DECL_MEMBER_TEMPLATE_P (tmpl) + && !DECL_CONV_FN_P (tmpl) + /* It is possible to have a template that is not a member + template and is not a member of a template class: + + template <typename T> + struct S { friend A::f(); }; + + Here, the friend function is a template, but the context does + 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))); +} + /* Retrieve the specialization (in the sense of [temp.spec] - a specialization is either an instantiation or an explicit specialization) of TMPL for the given template ARGS. If there is no such specialization, return NULL_TREE. The ARGS are a vector of arguments, or a vector of vectors of arguments, in the case of - templates with more than one level of parameters. */ + templates with more than one level of parameters. + + If TMPL is a type template and CLASS_SPECIALIZATIONS_P is true, + then we search for a partial specialization matching ARGS. This + parameter is ignored if TMPL is not a class template. */ static tree -retrieve_specialization (tree tmpl, tree args) +retrieve_specialization (tree tmpl, tree args, + bool class_specializations_p) { - tree s; - gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL); /* There should be as many levels of arguments as there are levels of parameters. */ gcc_assert (TMPL_ARGS_DEPTH (args) == TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl))); - - for (s = DECL_TEMPLATE_SPECIALIZATIONS (tmpl); - s != NULL_TREE; - s = TREE_CHAIN (s)) - if (comp_template_args (TREE_PURPOSE (s), args)) - return TREE_VALUE (s); + + if (optimize_specialization_lookup_p (tmpl)) + { + tree class_template; + tree class_specialization; + VEC(tree) *methods; + tree fns; + int idx; + + /* The template arguments actually apply to the containing + class. Find the class specialization with those + arguments. */ + class_template = CLASSTYPE_TI_TEMPLATE (DECL_CONTEXT (tmpl)); + class_specialization + = retrieve_specialization (class_template, args, + /*class_specializations_p=*/false); + if (!class_specialization) + return NULL_TREE; + /* Now, find the appropriate entry in the CLASSTYPE_METHOD_VEC + for the specialization. */ + idx = class_method_index_for_fn (class_specialization, tmpl); + if (idx == -1) + return NULL_TREE; + /* Iterate through the methods with the indicated name, looking + for the one that has an instance of TMPL. */ + methods = CLASSTYPE_METHOD_VEC (class_specialization); + for (fns = VEC_index (tree, methods, idx); fns; fns = OVL_NEXT (fns)) + { + tree fn = OVL_CURRENT (fns); + if (DECL_TEMPLATE_INFO (fn) && DECL_TI_TEMPLATE (fn) == tmpl) + return fn; + } + return NULL_TREE; + } + else + { + tree *sp; + tree *head; + + /* Class templates store their instantiations on the + DECL_TEMPLATE_INSTANTIATIONS list; other templates use the + DECL_TEMPLATE_SPECIALIZATIONS list. */ + if (!class_specializations_p + && TREE_CODE (DECL_TEMPLATE_RESULT (tmpl)) == TYPE_DECL) + sp = &DECL_TEMPLATE_INSTANTIATIONS (tmpl); + else + sp = &DECL_TEMPLATE_SPECIALIZATIONS (tmpl); + head = sp; + /* Iterate through the list until we find a matching template. */ + while (*sp != NULL_TREE) + { + tree spec = *sp; + + if (comp_template_args (TREE_PURPOSE (spec), args)) + { + /* Use the move-to-front heuristic to speed up future + searches. */ + if (spec != *head) + { + *sp = TREE_CHAIN (*sp); + TREE_CHAIN (spec) = *head; + *head = spec; + } + return TREE_VALUE (spec); + } + sp = &TREE_CHAIN (spec); + } + } return NULL_TREE; } @@ -1035,7 +1063,7 @@ is_specialization_of_friend (tree decl, tree friend) static tree register_specialization (tree spec, tree tmpl, tree args) { - tree s; + tree fn; gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL); @@ -1059,73 +1087,67 @@ register_specialization (tree spec, tree tmpl, tree args) gcc_assert (TMPL_ARGS_DEPTH (args) == TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl))); - for (s = DECL_TEMPLATE_SPECIALIZATIONS (tmpl); - s != NULL_TREE; - s = TREE_CHAIN (s)) + fn = retrieve_specialization (tmpl, args, + /*class_specializations_p=*/false); + /* We can sometimes try to re-register a specialization that we've + already got. In particular, regenerate_decl_from_template calls + duplicate_decls which will update the specialization list. But, + we'll still get called again here anyhow. It's more convenient + to simply allow this than to try to prevent it. */ + if (fn == spec) + return spec; + else if (fn && DECL_TEMPLATE_SPECIALIZATION (spec)) { - tree fn = TREE_VALUE (s); - - /* We can sometimes try to re-register a specialization that we've - already got. In particular, regenerate_decl_from_template - calls duplicate_decls which will update the specialization - list. But, we'll still get called again here anyhow. It's - more convenient to simply allow this than to try to prevent it. */ - if (fn == spec) - return spec; - else if (DECL_TEMPLATE_SPECIALIZATION (spec) - && comp_template_args (TREE_PURPOSE (s), args)) + if (DECL_TEMPLATE_INSTANTIATION (fn)) { - if (DECL_TEMPLATE_INSTANTIATION (fn)) + if (TREE_USED (fn) + || DECL_EXPLICIT_INSTANTIATION (fn)) { - if (TREE_USED (fn) - || DECL_EXPLICIT_INSTANTIATION (fn)) - { - error ("specialization of %qD after instantiation", fn); - return spec; - } - else - { - /* This situation should occur only if the first - specialization is an implicit instantiation, the - second is an explicit specialization, and the - implicit instantiation has not yet been used. - That situation can occur if we have implicitly - instantiated a member function and then - specialized it later. - - We can also wind up here if a friend declaration - that looked like an instantiation turns out to be - a specialization: - - template <class T> void foo(T); - class S { friend void foo<>(int) }; - template <> void foo(int); - - We transform the existing DECL in place so that - any pointers to it become pointers to the updated - declaration. - - If there was a definition for the template, but - not for the specialization, we want this to look - as if there were no definition, and vice - versa. */ - DECL_INITIAL (fn) = NULL_TREE; - duplicate_decls (spec, fn); - - return fn; - } + error ("specialization of %qD after instantiation", + fn); + return spec; } - else if (DECL_TEMPLATE_SPECIALIZATION (fn)) + else { - if (!duplicate_decls (spec, fn) && DECL_INITIAL (spec)) - /* Dup decl failed, but this is a new definition. Set - the line number so any errors match this new - definition. */ - DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (spec); + /* This situation should occur only if the first + specialization is an implicit instantiation, the + second is an explicit specialization, and the + implicit instantiation has not yet been used. That + situation can occur if we have implicitly + instantiated a member function and then specialized + it later. + + We can also wind up here if a friend declaration that + looked like an instantiation turns out to be a + specialization: + + template <class T> void foo(T); + class S { friend void foo<>(int) }; + template <> void foo(int); + + We transform the existing DECL in place so that any + pointers to it become pointers to the updated + declaration. + + If there was a definition for the template, but not + for the specialization, we want this to look as if + there were no definition, and vice versa. */ + DECL_INITIAL (fn) = NULL_TREE; + duplicate_decls (spec, fn); return fn; } } + else if (DECL_TEMPLATE_SPECIALIZATION (fn)) + { + if (!duplicate_decls (spec, fn) && DECL_INITIAL (spec)) + /* Dup decl failed, but this is a new definition. Set the + line number so any errors match this new + definition. */ + DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (spec); + + return fn; + } } /* A specialization must be declared in the same namespace as the @@ -1134,8 +1156,9 @@ register_specialization (tree spec, tree tmpl, tree args) && !check_specialization_namespace (tmpl)) DECL_CONTEXT (spec) = decl_namespace_context (tmpl); - DECL_TEMPLATE_SPECIALIZATIONS (tmpl) - = tree_cons (args, spec, DECL_TEMPLATE_SPECIALIZATIONS (tmpl)); + if (!optimize_specialization_lookup_p (tmpl)) + DECL_TEMPLATE_SPECIALIZATIONS (tmpl) + = tree_cons (args, spec, DECL_TEMPLATE_SPECIALIZATIONS (tmpl)); return spec; } @@ -2393,14 +2416,16 @@ current_template_args (void) } /* Return a TEMPLATE_DECL corresponding to DECL, using the indicated - template PARMS. Used by push_template_decl below. */ + template PARMS. If MEMBER_TEMPLATE_P is true, the new template is + a mebmer template. Used by push_template_decl below. */ static tree -build_template_decl (tree decl, tree parms) +build_template_decl (tree decl, tree parms, bool member_template_p) { tree tmpl = build_lang_decl (TEMPLATE_DECL, DECL_NAME (decl), NULL_TREE); DECL_TEMPLATE_PARMS (tmpl) = parms; DECL_CONTEXT (tmpl) = DECL_CONTEXT (decl); + DECL_MEMBER_TEMPLATE_P (tmpl) = member_template_p; if (DECL_LANG_SPECIFIC (decl)) { DECL_STATIC_FUNCTION_P (tmpl) = DECL_STATIC_FUNCTION_P (decl); @@ -2636,7 +2661,8 @@ process_partial_specialization (tree decl) } } - if (retrieve_specialization (maintmpl, specargs)) + if (retrieve_specialization (maintmpl, specargs, + /*class_specializations_p=*/true)) /* We've already got this specialization. */ return decl; @@ -2826,6 +2852,9 @@ push_template_decl_real (tree decl, int is_friend) int primary; int is_partial; int new_template_p = 0; + /* True if the template is a member template, in the sense of + [temp.mem]. */ + bool member_template_p = false; if (decl == error_mark_node) return decl; @@ -2862,6 +2891,8 @@ push_template_decl_real (tree decl, int is_friend) if (primary) { + if (DECL_CLASS_SCOPE_P (decl)) + member_template_p = true; if (current_lang_name == lang_name_c) error ("template with C linkage"); else if (TREE_CODE (decl) == TYPE_DECL @@ -2941,7 +2972,8 @@ push_template_decl_real (tree decl, int is_friend) } else { - tmpl = build_template_decl (decl, current_template_parms); + tmpl = build_template_decl (decl, current_template_parms, + member_template_p); new_template_p = 1; if (DECL_LANG_SPECIFIC (decl) @@ -2984,7 +3016,7 @@ push_template_decl_real (tree decl, int is_friend) if (DECL_FUNCTION_TEMPLATE_P (tmpl) && DECL_TEMPLATE_INFO (decl) && DECL_TI_ARGS (decl) && DECL_TEMPLATE_SPECIALIZATION (decl) - && is_member_template (tmpl)) + && DECL_MEMBER_TEMPLATE_P (tmpl)) { tree new_tmpl; @@ -2996,7 +3028,8 @@ push_template_decl_real (tree decl, int is_friend) args = DECL_TI_ARGS (decl); new_tmpl - = build_template_decl (decl, current_template_parms); + = build_template_decl (decl, current_template_parms, + member_template_p); DECL_TEMPLATE_RESULT (new_tmpl) = decl; TREE_TYPE (new_tmpl) = TREE_TYPE (decl); DECL_TI_TEMPLATE (decl) = new_tmpl; @@ -4342,7 +4375,6 @@ lookup_template_class (tree d1, tree gen_tmpl; tree type_decl; tree found = NULL_TREE; - tree *tp; int arg_depth; int parm_depth; int is_partial_instantiation; @@ -4466,22 +4498,11 @@ lookup_template_class (tree d1, if (found) POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, found); - for (tp = &DECL_TEMPLATE_INSTANTIATIONS (template); - *tp; - tp = &TREE_CHAIN (*tp)) - if (comp_template_args (TREE_PURPOSE (*tp), arglist)) - { - found = *tp; - - /* Use the move-to-front heuristic to speed up future - searches. */ - *tp = TREE_CHAIN (*tp); - TREE_CHAIN (found) - = DECL_TEMPLATE_INSTANTIATIONS (template); - DECL_TEMPLATE_INSTANTIATIONS (template) = found; - - POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, TREE_VALUE (found)); - } + /* If we already have this specialization, return it. */ + found = retrieve_specialization (template, arglist, + /*class_specializations_p=*/false); + if (found) + POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, found); /* This type is a "partial instantiation" if any of the template arguments still involve template parameters. Note that we set @@ -6069,7 +6090,8 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain) changed. */ gcc_assert (full_args != tmpl_args); - spec = retrieve_specialization (t, full_args); + spec = retrieve_specialization (t, full_args, + /*class_specializations_p=*/true); if (spec != NULL_TREE) { r = spec; @@ -6181,7 +6203,8 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain) args, complain, in_decl); /* Check to see if we already have this specialization. */ - spec = retrieve_specialization (gen_tmpl, argvec); + spec = retrieve_specialization (gen_tmpl, argvec, + /*class_specializations_p=*/false); if (spec) { @@ -6467,7 +6490,8 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain) tmpl = DECL_TI_TEMPLATE (t); gen_tmpl = most_general_template (tmpl); argvec = tsubst (DECL_TI_ARGS (t), args, complain, in_decl); - spec = retrieve_specialization (gen_tmpl, argvec); + spec = retrieve_specialization (gen_tmpl, argvec, + /*class_specializations_p=*/false); } else spec = retrieve_local_specialization (t); @@ -6657,6 +6681,39 @@ tsubst_function_type (tree t, return fntype; } +/* FNTYPE is a FUNCTION_TYPE or METHOD_TYPE. Substitute the template + ARGS into that specification, and return the substituted + specification. If there is no specification, return NULL_TREE. */ + +static tree +tsubst_exception_specification (tree fntype, + tree args, + tsubst_flags_t complain, + tree in_decl) +{ + tree specs; + tree new_specs; + + specs = TYPE_RAISES_EXCEPTIONS (fntype); + new_specs = NULL_TREE; + if (specs) + { + if (! TREE_VALUE (specs)) + new_specs = specs; + else + while (specs) + { + tree spec; + spec = tsubst (TREE_VALUE (specs), args, complain, in_decl); + if (spec == error_mark_node) + return spec; + new_specs = add_exception_specifier (new_specs, spec, complain); + specs = TREE_CHAIN (specs); + } + } + return new_specs; +} + /* Substitute into the PARMS of a call-declarator. */ static tree @@ -7089,32 +7146,16 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) case METHOD_TYPE: { tree fntype; - tree raises; - + tree specs; fntype = tsubst_function_type (t, args, complain, in_decl); if (fntype == error_mark_node) return error_mark_node; /* Substitute the exception specification. */ - raises = TYPE_RAISES_EXCEPTIONS (t); - if (raises) - { - tree list = NULL_TREE; - - if (! TREE_VALUE (raises)) - list = raises; - else - for (; raises != NULL_TREE; raises = TREE_CHAIN (raises)) - { - tree spec = TREE_VALUE (raises); - - spec = tsubst (spec, args, complain, in_decl); - if (spec == error_mark_node) - return spec; - list = add_exception_specifier (list, spec, complain); - } - fntype = build_exception_variant (fntype, list); - } + specs = tsubst_exception_specification (t, args, complain, + in_decl); + if (specs) + fntype = build_exception_variant (fntype, specs); return fntype; } case ARRAY_TYPE: @@ -7537,7 +7578,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) if (DECL_TEMPLATE_TEMPLATE_PARM_P (t)) return tsubst (TREE_TYPE (DECL_TEMPLATE_RESULT (t)), args, complain, in_decl); - else if (is_member_template (t)) + else if (DECL_FUNCTION_TEMPLATE_P (t) && DECL_MEMBER_TEMPLATE_P (t)) return tsubst (t, args, complain, in_decl); else if (DECL_CLASS_SCOPE_P (t) && uses_template_parms (DECL_CONTEXT (t))) @@ -8736,7 +8777,8 @@ instantiate_template (tree tmpl, tree targ_ptr, tsubst_flags_t complain) } /* Check to see if we already have this specialization. */ - spec = retrieve_specialization (tmpl, targ_ptr); + spec = retrieve_specialization (tmpl, targ_ptr, + /*class_specializations_p=*/false); if (spec != NULL_TREE) return spec; @@ -8750,7 +8792,8 @@ instantiate_template (tree tmpl, tree targ_ptr, tsubst_flags_t complain) targ_ptr); /* Check to see if we already have this specialization. */ - spec = retrieve_specialization (gen_tmpl, targ_ptr); + spec = retrieve_specialization (gen_tmpl, targ_ptr, + /*class_specializations_p=*/false); if (spec != NULL_TREE) return spec; } @@ -10808,75 +10851,76 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain) static void regenerate_decl_from_template (tree decl, tree tmpl) { - /* The most general version of TMPL. */ - tree gen_tmpl; /* The arguments used to instantiate DECL, from the most general template. */ tree args; tree code_pattern; - tree new_decl; - bool unregistered; args = DECL_TI_ARGS (decl); code_pattern = DECL_TEMPLATE_RESULT (tmpl); - /* Unregister the specialization so that when we tsubst we will not - just return DECL. We don't have to unregister DECL from TMPL - because if would only be registered there if it were a partial - instantiation of a specialization, which it isn't: it's a full - instantiation. */ - gen_tmpl = most_general_template (tmpl); - unregistered = reregister_specialization (decl, gen_tmpl, - /*new_spec=*/NULL_TREE); - - /* If the DECL was not unregistered then something peculiar is - happening: we created a specialization but did not call - register_specialization for it. */ - gcc_assert (unregistered); - /* Make sure that we can see identifiers, and compute access correctly. */ push_access_scope (decl); - /* Do the substitution to get the new declaration. */ - new_decl = tsubst (code_pattern, args, tf_error, NULL_TREE); + if (TREE_CODE (decl) == FUNCTION_DECL) + { + tree decl_parm; + tree pattern_parm; + tree specs; + int args_depth; + int parms_depth; + + args_depth = TMPL_ARGS_DEPTH (args); + parms_depth = TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)); + if (args_depth > parms_depth) + args = get_innermost_template_args (args, parms_depth); + + specs = tsubst_exception_specification (TREE_TYPE (code_pattern), + args, tf_error, NULL_TREE); + if (specs) + TREE_TYPE (decl) = build_exception_variant (TREE_TYPE (decl), + specs); + + /* Merge parameter declarations. */ + decl_parm = skip_artificial_parms_for (decl, + DECL_ARGUMENTS (decl)); + pattern_parm + = skip_artificial_parms_for (code_pattern, + DECL_ARGUMENTS (code_pattern)); + while (decl_parm) + { + tree parm_type; + + if (DECL_NAME (decl_parm) != DECL_NAME (pattern_parm)) + DECL_NAME (decl_parm) = DECL_NAME (pattern_parm); + parm_type = tsubst (TREE_TYPE (pattern_parm), args, tf_error, + NULL_TREE); + if (!same_type_p (TREE_TYPE (decl_parm), parm_type)) + TREE_TYPE (decl_parm) = parm_type; + decl_parm = TREE_CHAIN (decl_parm); + pattern_parm = TREE_CHAIN (pattern_parm); + } - if (TREE_CODE (decl) == VAR_DECL) + /* Merge additional specifiers from the CODE_PATTERN. */ + if (DECL_DECLARED_INLINE_P (code_pattern) + && !DECL_DECLARED_INLINE_P (decl)) + DECL_DECLARED_INLINE_P (decl) = 1; + if (DECL_INLINE (code_pattern) && !DECL_INLINE (decl)) + DECL_INLINE (decl) = 1; + } + else if (TREE_CODE (decl) == VAR_DECL) { - /* Set up DECL_INITIAL, since tsubst doesn't. */ - if (!DECL_INITIALIZED_IN_CLASS_P (decl)) - DECL_INITIAL (new_decl) = + if (!DECL_INITIALIZED_IN_CLASS_P (decl) + && DECL_INITIAL (code_pattern)) + DECL_INITIAL (decl) = tsubst_expr (DECL_INITIAL (code_pattern), args, tf_error, DECL_TI_TEMPLATE (decl)); } - else if (TREE_CODE (decl) == FUNCTION_DECL) - { - /* Convince duplicate_decls to use the DECL_ARGUMENTS from the - new decl. */ - DECL_INITIAL (new_decl) = error_mark_node; - /* And don't complain about a duplicate definition. */ - DECL_INITIAL (decl) = NULL_TREE; - } + else + gcc_unreachable (); 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 - general template. We also reset the DECL_ASSEMBLER_NAME since - tsubst always calculates the name as if the function in question - were really a template instance, and sometimes, with friend - functions, this is not so. See tsubst_friend_function for - details. */ - DECL_TI_TEMPLATE (new_decl) = DECL_TI_TEMPLATE (decl); - COPY_DECL_ASSEMBLER_NAME (decl, new_decl); - COPY_DECL_RTL (decl, new_decl); - DECL_USE_TEMPLATE (new_decl) = DECL_USE_TEMPLATE (decl); - - /* Call duplicate decls to merge the old and new declarations. */ - duplicate_decls (new_decl, decl); - - /* Now, re-register the specialization. */ - register_specialization (decl, gen_tmpl, args); } /* Return the TEMPLATE_DECL into which DECL_TI_ARGS(DECL) should be @@ -10994,7 +11038,8 @@ instantiate_decl (tree d, int defer_ok, int undefined_ok) DECL_TEMPLATE_SPECIALIZATION. */ gen_tmpl = most_general_template (tmpl); gen_args = DECL_TI_ARGS (d); - spec = retrieve_specialization (gen_tmpl, gen_args); + spec = retrieve_specialization (gen_tmpl, gen_args, + /*class_specializations_p=*/false); if (spec != NULL_TREE && DECL_TEMPLATE_SPECIALIZATION (spec)) return spec; diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 47d08f3..514f868 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -1464,6 +1464,22 @@ lookup_fnfields_1 (tree type, tree name) return -1; } +/* Like lookup_fnfields_1, except that the name is extracted from + FUNCTION, which is a FUNCTION_DECL or a TEMPLATE_DECL. */ + +int +class_method_index_for_fn (tree class_type, tree function) +{ + gcc_assert (TREE_CODE (function) == FUNCTION_DECL + || DECL_FUNCTION_TEMPLATE_P (function)); + + return lookup_fnfields_1 (class_type, + DECL_CONSTRUCTOR_P (function) ? ctor_identifier : + DECL_DESTRUCTOR_P (function) ? dtor_identifier : + DECL_NAME (function)); +} + + /* DECL is the result of a qualified name lookup. QUALIFYING_SCOPE is the class or namespace used to qualify the name. CONTEXT_CLASS is the class corresponding to the object in which DECL will be used. |