diff options
author | Mark Mitchell <mark@codesourcery.com> | 2000-06-03 21:42:49 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2000-06-03 21:42:49 +0000 |
commit | f9a7ae04e9619a0f1255ca922ca5b8e2db417bd7 (patch) | |
tree | c8c18186a914c188e0eea1b59ef946c745c24831 /gcc | |
parent | 22ad59662f441c8cf3c3bf8dba16d3815897fa04 (diff) | |
download | gcc-f9a7ae04e9619a0f1255ca922ca5b8e2db417bd7.zip gcc-f9a7ae04e9619a0f1255ca922ca5b8e2db417bd7.tar.gz gcc-f9a7ae04e9619a0f1255ca922ca5b8e2db417bd7.tar.bz2 |
cp-tree.h (TMPL_ARGS_LEVEL): Clarify comment.
* cp-tree.h (TMPL_ARGS_LEVEL): Clarify comment.
(INNERMOST_TEMPLATE_ARGS): New macro.
(innermost_args): Remove.
(get_innermost_template_args): New function.
* decl2.c (arg_assoc_class): Use INNERMOST_TEMPLATE_ARGS.
* error.c (dump_function_decl): Be caution when using
most_general_template.
* method.c (build_template_parm_names): Use
INNERMOST_TEMPLATE_ARGS.
* pt.c (add_to_template_args): Tidy comment
(get_innermost_template_args): New function.
(check_explicit_specialization): Clear DECL_INITIAL for a new
specialization.
(process_partial_specialization): Use INNERMOST_TEMPLATE_ARGS.
Tidy.
(push_template_decl): Always register specializations of the most
general template.
(convert_template_argument): Use INNERMOST_TEMPLATE_ARGS.
(coerce_template_parms): Likewise.
(lookup_template_class): Likewise.
(innermost_args): Remove.
(tsubst_decl): Use INNERMOST_TEMPLATE_ARGS.
(tsubst_decl): Handle tricky specializations. Use
get_innermost_template_args.
(instantiate_template): Simplify handling of partial
instantiations.
(get_class_bindings): Use INNERMOST_TEMPLATE_ARGS.
(most_general_template): Reimplement, in a more straightforward
manner.
(regenerate_decl_from_template): Tweak formatting. Use
TMPL_ARGS_DEPTH for clarity.
(set_mangled_name_for_template_decl): Use INNERMOST_ARGS.
* dump.c (dequeue_and_dump): Dump information about thunks.
From-SVN: r34384
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 37 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 10 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 2 | ||||
-rw-r--r-- | gcc/cp/dump.c | 7 | ||||
-rw-r--r-- | gcc/cp/error.c | 11 | ||||
-rw-r--r-- | gcc/cp/method.c | 2 | ||||
-rw-r--r-- | gcc/cp/pt.c | 223 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/memtemp96.C | 17 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/memtemp97.C | 16 |
9 files changed, 228 insertions, 97 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 20e5058..9930544 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,40 @@ +2000-06-03 Mark Mitchell <mark@codesourcery.com> + + * cp-tree.h (TMPL_ARGS_LEVEL): Clarify comment. + (INNERMOST_TEMPLATE_ARGS): New macro. + (innermost_args): Remove. + (get_innermost_template_args): New function. + * decl2.c (arg_assoc_class): Use INNERMOST_TEMPLATE_ARGS. + * error.c (dump_function_decl): Be caution when using + most_general_template. + * method.c (build_template_parm_names): Use + INNERMOST_TEMPLATE_ARGS. + * pt.c (add_to_template_args): Tidy comment + (get_innermost_template_args): New function. + (check_explicit_specialization): Clear DECL_INITIAL for a new + specialization. + (process_partial_specialization): Use INNERMOST_TEMPLATE_ARGS. + Tidy. + (push_template_decl): Always register specializations of the most + general template. + (convert_template_argument): Use INNERMOST_TEMPLATE_ARGS. + (coerce_template_parms): Likewise. + (lookup_template_class): Likewise. + (innermost_args): Remove. + (tsubst_decl): Use INNERMOST_TEMPLATE_ARGS. + (tsubst_decl): Handle tricky specializations. Use + get_innermost_template_args. + (instantiate_template): Simplify handling of partial + instantiations. + (get_class_bindings): Use INNERMOST_TEMPLATE_ARGS. + (most_general_template): Reimplement, in a more straightforward + manner. + (regenerate_decl_from_template): Tweak formatting. Use + TMPL_ARGS_DEPTH for clarity. + (set_mangled_name_for_template_decl): Use INNERMOST_ARGS. + + * dump.c (dequeue_and_dump): Dump information about thunks. + 2000-06-02 Jason Merrill <jason@casey.soma.redhat.com> * exception.cc (__cp_pop_exception): If we aren't popping or diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 888e73e..b9a9eb6 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2325,8 +2325,8 @@ struct lang_decl #define TMPL_ARGS_DEPTH(NODE) \ (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (NODE) ? TREE_VEC_LENGTH (NODE) : 1) -/* The LEVELth level of the template ARGS. Note that template - parameter levels are indexed from 1, not from 0. */ +/* The LEVELth level of the template ARGS. The outermost level of of + args is level 1, not level 0. */ #define TMPL_ARGS_LEVEL(ARGS, LEVEL) \ (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (ARGS) \ ? TREE_VEC_ELT ((ARGS), (LEVEL) - 1) : ARGS) @@ -2352,6 +2352,10 @@ struct lang_decl : (TREE_CODE (NODE) == TREE_VEC \ ? TREE_VEC_LENGTH (NODE) : list_length (NODE))) +/* Returns the innermost level of template arguments in ARGS. */ +#define INNERMOST_TEMPLATE_ARGS(NODE) \ + (get_innermost_template_args ((NODE), 1)) + /* The number of levels of template parameters given by NODE. */ #define TMPL_PARMS_DEPTH(NODE) \ (TREE_INT_CST_HIGH (TREE_PURPOSE (NODE))) @@ -4298,7 +4302,7 @@ extern int maybe_clone_body PARAMS ((tree)); /* in pt.c */ extern void init_pt PARAMS ((void)); extern void check_template_shadow PARAMS ((tree)); -extern tree innermost_args PARAMS ((tree)); +extern tree get_innermost_template_args PARAMS ((tree, int)); extern tree tsubst PARAMS ((tree, tree, int, tree)); extern tree tsubst_expr PARAMS ((tree, tree, int, tree)); extern tree tsubst_copy PARAMS ((tree, tree, int, tree)); diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 8f1c681..a942bd7 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -4798,7 +4798,7 @@ arg_assoc_class (k, type) /* Process template arguments. */ if (CLASSTYPE_TEMPLATE_INFO (type)) { - list = innermost_args (CLASSTYPE_TI_ARGS (type)); + list = INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type)); for (i = 0; i < TREE_VEC_LENGTH (list); ++i) arg_assoc_template_arg (k, TREE_VEC_ELT (list, i)); } diff --git a/gcc/cp/dump.c b/gcc/cp/dump.c index 16cbba3..09fbf4b 100644 --- a/gcc/cp/dump.c +++ b/gcc/cp/dump.c @@ -578,6 +578,13 @@ dequeue_and_dump (di) dump_string (di, "operator"); if (DECL_CONV_FN_P (t)) dump_string (di, "conversion"); + if (DECL_THUNK_P (t)) + { + dump_string (di, "thunk"); + dump_int (di, "dlta", THUNK_DELTA (t)); + dump_int (di, "vcll", THUNK_VCALL_OFFSET (t)); + dump_child ("fn", DECL_INITIAL (t)); + } if (DECL_GLOBAL_CTOR_P (t) || DECL_GLOBAL_DTOR_P (t)) { if (DECL_GLOBAL_CTOR_P (t)) diff --git a/gcc/cp/error.c b/gcc/cp/error.c index f4c116b..82ba33d 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -1111,10 +1111,15 @@ dump_function_decl (t, flags) /* Pretty print template instantiations only. */ if (DECL_USE_TEMPLATE (t) && DECL_TEMPLATE_INFO (t)) { + tree tmpl; + template_args = DECL_TI_ARGS (t); - t = most_general_template (t); - if (TREE_CODE (t) == TEMPLATE_DECL) - template_parms = DECL_TEMPLATE_PARMS (t); + tmpl = most_general_template (t); + if (tmpl && TREE_CODE (tmpl) == TEMPLATE_DECL) + { + template_parms = DECL_TEMPLATE_PARMS (tmpl); + t = tmpl; + } } fntype = TREE_TYPE (t); diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 1981e77..578e1c8 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -945,7 +945,7 @@ build_template_parm_names (parmlist, arglist) tree arglist; { int i, nparms; - tree inner_args = innermost_args (arglist); + tree inner_args = INNERMOST_TEMPLATE_ARGS (arglist); nparms = TREE_VEC_LENGTH (parmlist); icat (nparms); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index e414d84..18b0d6a 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -474,9 +474,7 @@ is_member_template_class (t) #endif /* Return a new template argument vector which contains all of ARGS, - but has as its innermost set of arguments the EXTRA_ARGS. The - resulting vector will be built on a temporary obstack, and so must - be explicitly copied to the permanent obstack, if required. */ + but has as its innermost set of arguments the EXTRA_ARGS. */ static tree add_to_template_args (args, extra_args) @@ -535,6 +533,39 @@ add_outermost_template_args (args, extra_args) return new_args; } +/* Return the N levels of innermost template arguments from the ARGS. */ + +tree +get_innermost_template_args (args, n) + tree args; + int n; +{ + tree new_args; + int extra_levels; + int i; + + my_friendly_assert (n >= 0, 20000603); + + /* If N is 1, just return the innermost set of template arguments. */ + if (n == 1) + return TMPL_ARGS_LEVEL (args, TMPL_ARGS_DEPTH (args)); + + /* If we're not removing anything, just return the arguments we were + given. */ + extra_levels = TMPL_ARGS_DEPTH (args) - n; + my_friendly_assert (extra_levels >= 0, 20000603); + if (extra_levels == 0) + return args; + + /* Make a new set of arguments, not containing the outer arguments. */ + new_args = make_tree_vec (n); + for (i = 1; i <= n; ++i) + SET_TMPL_ARGS_LEVEL (new_args, i, + TMPL_ARGS_LEVEL (args, i + extra_levels)); + + return new_args; +} + /* We've got a template header coming up; push to a new level for storing the parms. */ @@ -1484,13 +1515,13 @@ check_explicit_specialization (declarator, decl, template_count, flags) return instantiate_template (tmpl, targs); } - /* If this is both a template specialization, then it's a - specialization of a member template of a template class. - In that case we want to return the TEMPLATE_DECL, not the - specialization of it. */ + /* 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. */ if (tsk == tsk_template) { SET_DECL_TEMPLATE_SPECIALIZATION (tmpl); + DECL_INITIAL (DECL_TEMPLATE_RESULT (tmpl)) = NULL_TREE; return tmpl; } @@ -2025,7 +2056,7 @@ process_partial_specialization (decl) tree type = TREE_TYPE (decl); tree maintmpl = CLASSTYPE_TI_TEMPLATE (type); tree specargs = CLASSTYPE_TI_ARGS (type); - tree inner_args = innermost_args (specargs); + tree inner_args = INNERMOST_TEMPLATE_ARGS (specargs); tree inner_parms = INNERMOST_TEMPLATE_PARMS (current_template_parms); tree main_inner_parms = DECL_INNERMOST_TEMPLATE_PARMS (maintmpl); int nargs = TREE_VEC_LENGTH (inner_args); @@ -2082,7 +2113,7 @@ process_partial_specialization (decl) if (tpd.parms[i] == 0) { /* One of the template parms was not used in the - specialization. */ + specialization. */ if (!did_error_intro) { cp_error ("template parameters not used in partial specialization:"); @@ -2097,9 +2128,10 @@ process_partial_specialization (decl) The argument list of the specialization shall not be identical to the implicit argument list of the primary template. */ - if (comp_template_args (inner_args, - innermost_args (CLASSTYPE_TI_ARGS (TREE_TYPE - (maintmpl))))) + if (comp_template_args + (inner_args, + INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (TREE_TYPE + (maintmpl))))) cp_error ("partial specialization `%T' does not specialize any template arguments", type); /* [temp.class.spec] @@ -2502,7 +2534,9 @@ push_template_decl_real (decl, is_friend) DECL_TEMPLATE_INFO (new_tmpl) = tree_cons (tmpl, args, NULL_TREE); - register_specialization (new_tmpl, tmpl, args); + register_specialization (new_tmpl, + most_general_template (tmpl), + args); return decl; } @@ -3124,7 +3158,7 @@ convert_template_argument (parm, arg, args, complain, i, in_decl) tree inner_args; int is_type, requires_type, is_tmpl_type, requires_tmpl_type; - inner_args = innermost_args (args); + inner_args = INNERMOST_TEMPLATE_ARGS (args); if (TREE_CODE (arg) == TREE_LIST && TREE_TYPE (arg) != NULL_TREE @@ -3322,7 +3356,7 @@ coerce_template_parms (parms, args, in_decl, tree new_args; tree new_inner_args; - inner_args = innermost_args (args); + inner_args = INNERMOST_TEMPLATE_ARGS (args); nargs = NUM_TMPL_ARGS (inner_args); nparms = TREE_VEC_LENGTH (parms); @@ -3469,7 +3503,7 @@ mangle_class_name_for_template (name, parms, arglist) cat (name); ccat ('<'); nparms = TREE_VEC_LENGTH (parms); - arglist = innermost_args (arglist); + arglist = INNERMOST_TEMPLATE_ARGS (arglist); my_friendly_assert (nparms == TREE_VEC_LENGTH (arglist), 268); for (i = 0; i < nparms; i++) { @@ -3824,7 +3858,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope) else arglist = coerce_template_parms (INNERMOST_TEMPLATE_PARMS (parmlist), - innermost_args (arglist), + INNERMOST_TEMPLATE_ARGS (arglist), template, 1, 1); if (arglist == error_mark_node) @@ -5143,17 +5177,6 @@ maybe_fold_nontype_arg (arg) return arg; } -/* Return the TREE_VEC with the arguments for the innermost template header, - where ARGS is either that or the VEC of VECs for all the - arguments. */ - -tree -innermost_args (args) - tree args; -{ - return TMPL_ARGS_LEVEL (args, TMPL_ARGS_DEPTH (args)); -} - /* Substitute ARGS into the vector of template arguments T. */ static tree @@ -5548,7 +5571,7 @@ tsubst_decl (t, args, type, in_decl) spec_args, /*complain=*/1, in_decl); DECL_TI_TEMPLATE (new_fn) = fn; register_specialization (new_fn, r, - innermost_args (spec_args)); + INNERMOST_TEMPLATE_ARGS (spec_args)); } /* Record this partial instantiation. */ @@ -5593,7 +5616,19 @@ tsubst_decl (t, args, type, in_decl) break; } - /* Here, we deal with the peculiar case: + /* We can see more levels of arguments than parameters if + there was a specialization of a member template, like + this: + + template <class T> struct S { template <class U> void f(); } + template <> template <class U> void S<int>::f(U); + + Here, we'll be subtituting into the specialization, + because that's where we can find the code we actually + want to generate, but we'll have enough arguments for + the most general template. + + We also deal with the peculiar case: template <class T> struct S { template <class U> friend void f(); @@ -5618,21 +5653,7 @@ tsubst_decl (t, args, type, in_decl) TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (DECL_TI_TEMPLATE (t))); if (args_depth > parms_depth && !DECL_TEMPLATE_SPECIALIZATION (t)) - { - my_friendly_assert (DECL_FRIEND_P (t), 0); - - if (parms_depth > 1) - { - int i; - - args = make_tree_vec (parms_depth); - for (i = 0; i < parms_depth; ++i) - TREE_VEC_ELT (args, i) = - TREE_VEC_ELT (args, i + (args_depth - parms_depth)); - } - else - args = TREE_VEC_ELT (args, args_depth - parms_depth); - } + args = get_innermost_template_args (args, parms_depth); } else { @@ -7440,25 +7461,23 @@ instantiate_template (tmpl, targ_ptr) if (spec != NULL_TREE) return spec; - if (DECL_TEMPLATE_INFO (tmpl) && !DECL_TEMPLATE_SPECIALIZATION (tmpl)) + gen_tmpl = most_general_template (tmpl); + if (tmpl != gen_tmpl) { /* The TMPL is a partial instantiation. To get a full set of arguments we must add the arguments used to perform the partial instantiation. */ targ_ptr = add_outermost_template_args (DECL_TI_ARGS (tmpl), targ_ptr); - gen_tmpl = most_general_template (tmpl); /* Check to see if we already have this specialization. */ spec = retrieve_specialization (gen_tmpl, targ_ptr); if (spec != NULL_TREE) return spec; } - else - gen_tmpl = tmpl; len = DECL_NTPARMS (gen_tmpl); - inner_args = innermost_args (targ_ptr); + inner_args = INNERMOST_TEMPLATE_ARGS (targ_ptr); i = len; while (i--) { @@ -8885,7 +8904,7 @@ get_class_bindings (tparms, parms, args) int i, ntparms = TREE_VEC_LENGTH (tparms); tree vec = make_tree_vec (ntparms); - args = innermost_args (args); + args = INNERMOST_TEMPLATE_ARGS (args); if (unify (tparms, vec, parms, args, UNIFY_ALLOW_NONE)) return NULL_TREE; @@ -8970,7 +8989,9 @@ most_specialized (fns, decl, explicit_args) } /* If DECL is a specialization of some template, return the most - general such template. For example, given: + general such template. Otherwise, returns NULL_TREE. + + For example, given: template <class T> struct S { template <class U> void f(U); }; @@ -8987,14 +9008,37 @@ tree most_general_template (decl) tree decl; { - while (DECL_TEMPLATE_INFO (decl) - && !(TREE_CODE (decl) == TEMPLATE_DECL - && DECL_TEMPLATE_SPECIALIZATION (decl)) - /* The DECL_TI_TEMPLATE can be a LOOKUP_EXPR or - IDENTIFIER_NODE in some cases. (See cp-tree.h for - details.) */ - && TREE_CODE (DECL_TI_TEMPLATE (decl)) == TEMPLATE_DECL) - decl = DECL_TI_TEMPLATE (decl); + /* If DECL is a FUNCTION_DECL, find the TEMPLATE_DECL of which it is + an immediate specialization. */ + if (TREE_CODE (decl) == FUNCTION_DECL) + { + if (DECL_TEMPLATE_INFO (decl)) { + decl = DECL_TI_TEMPLATE (decl); + + /* The DECL_TI_TEMPLATE can be an IDENTIFIER_NODE for a + template friend. */ + if (TREE_CODE (decl) != TEMPLATE_DECL) + return NULL_TREE; + } else + return NULL_TREE; + } + + /* Look for more and more general templates. */ + while (DECL_TEMPLATE_INFO (decl)) + { + /* The DECL_TI_TEMPLATE can be a LOOKUP_EXPR or IDENTIFIER_NODE + in some cases. (See cp-tree.h for details.) */ + if (TREE_CODE (DECL_TI_TEMPLATE (decl)) != TEMPLATE_DECL) + break; + + /* Stop if we run into an explicitly specialized class template. */ + if (!DECL_NAMESPACE_SCOPE_P (decl) + && DECL_CONTEXT (decl) + && CLASSTYPE_TEMPLATE_SPECIALIZATION (DECL_CONTEXT (decl))) + break; + + decl = DECL_TI_TEMPLATE (decl); + } return decl; } @@ -9345,10 +9389,13 @@ regenerate_decl_from_template (decl, tmpl) 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; - tree gen_tmpl; int unregistered; args = DECL_TI_ARGS (decl); @@ -9474,32 +9521,30 @@ instantiate_decl (d, defer_ok) and an instantiation of S<double>::f<int>. We want TD to be the specialization S<T>::f<int>, not the more general S<T>::f<U>. */ td = tmpl; - for (td = tmpl; - /* An instantiation cannot have a definition, so we need a - more general template. */ - DECL_TEMPLATE_INSTANTIATION (td) - /* We must also deal with friend templates. Given: - - template <class T> struct S { - template <class U> friend void f() {}; - }; - - S<int>::f<U> say, is not an instantiation of S<T>::f<U>, - so far as the language is concerned, but that's still - where we get the pattern for the instantiation from. On - ther hand, if the definition comes outside the class, say: - - template <class T> struct S { - template <class U> friend void f(); - }; - template <class U> friend void f() {} - - we don't need to look any further. That's what the check for - DECL_INITIAL is for. */ - || (TREE_CODE (d) == FUNCTION_DECL - && DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (td) - && !DECL_INITIAL (DECL_TEMPLATE_RESULT (td))); - ) + while (/* An instantiation cannot have a definition, so we need a + more general template. */ + DECL_TEMPLATE_INSTANTIATION (td) + /* We must also deal with friend templates. Given: + + template <class T> struct S { + template <class U> friend void f() {}; + }; + + S<int>::f<U> say, is not an instantiation of S<T>::f<U>, + so far as the language is concerned, but that's still + where we get the pattern for the instantiation from. On + ther hand, if the definition comes outside the class, say: + + template <class T> struct S { + template <class U> friend void f(); + }; + template <class U> friend void f() {} + + we don't need to look any further. That's what the check for + DECL_INITIAL is for. */ + || (TREE_CODE (d) == FUNCTION_DECL + && DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (td) + && !DECL_INITIAL (DECL_TEMPLATE_RESULT (td)))) { /* The present template, TD, should not be a definition. If it were a definition, we should be using it! Note that we @@ -9941,7 +9986,7 @@ set_mangled_name_for_template_decl (decl) /* Replace the innermost level of the TARGS with NULL_TREEs to let tsubst know not to subsitute for those parameters. */ - partial_args = make_tree_vec (TREE_VEC_LENGTH (targs)); + partial_args = make_tree_vec (TMPL_ARGS_DEPTH (targs)); for (i = 1; i < TMPL_ARGS_DEPTH (targs); ++i) SET_TMPL_ARGS_LEVEL (partial_args, i, TMPL_ARGS_LEVEL (targs, i)); @@ -9966,7 +10011,7 @@ set_mangled_name_for_template_decl (decl) /* Now, get the innermost parameters and arguments, and figure out the parameter and return types. */ tparms = INNERMOST_TEMPLATE_PARMS (tparms); - targs = innermost_args (targs); + targs = INNERMOST_TEMPLATE_ARGS (targs); ret_type = TREE_TYPE (fn_type); parm_types = TYPE_ARG_TYPES (fn_type); diff --git a/gcc/testsuite/g++.old-deja/g++.pt/memtemp96.C b/gcc/testsuite/g++.old-deja/g++.pt/memtemp96.C new file mode 100644 index 0000000..caeceea --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/memtemp96.C @@ -0,0 +1,17 @@ +// Build don't link: +// Origin: Jason Merrill <jason@cygnus.com> + +template <class T> struct A { + template <class U> void f(U); +}; + +template <> +template <class U> +void A<int>::f(U); + +A<int> a; + +void g () +{ + a.f (3); +} diff --git a/gcc/testsuite/g++.old-deja/g++.pt/memtemp97.C b/gcc/testsuite/g++.old-deja/g++.pt/memtemp97.C new file mode 100644 index 0000000..511beae --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/memtemp97.C @@ -0,0 +1,16 @@ +// Origin: Mark Mitchell <mark@codesourcery.com> + +template <class T> struct A { + template <class U> int f(U) { return 1; } +}; + +template <> +template <class U> +int A<int>::f(U) { return 0; } + +A<int> a; + +int main () +{ + return a.f (3); +} |