diff options
Diffstat (limited to 'gcc/cp/pt.c')
-rw-r--r-- | gcc/cp/pt.c | 524 |
1 files changed, 287 insertions, 237 deletions
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 3813c38ed41..9a869eaecd2 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 nonzero 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 member 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))) @@ -8017,7 +8058,12 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) tsubst_expr (ASM_OUTPUTS (t), args, complain, in_decl), tsubst_expr (ASM_INPUTS (t), args, complain, in_decl), tsubst_expr (ASM_CLOBBERS (t), args, complain, in_decl)); - ASM_INPUT_P (tmp) = ASM_INPUT_P (t); + { + tree asm_expr = tmp; + if (TREE_CODE (asm_expr) == CLEANUP_POINT_EXPR) + asm_expr = TREE_OPERAND (asm_expr, 0); + ASM_INPUT_P (asm_expr) = ASM_INPUT_P (t); + } break; case TRY_BLOCK: @@ -8736,7 +8782,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 +8797,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 +10856,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 +11043,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; |