Member Templates
Mark Mitchell
mmitchell@usa.net
Fri Sep 5 15:57:00 GMT 1997
Several of you are trying out the C++ member templates patch I posted
several days ago. Thank you!
Thanks to Jason Merrill, who has provided considerable insight, I have
a much improved version of the patch. Since so many of you have sent
me mail saying that you're trying the patch, I thought I should post
the newest version, which fixes several of the most obvious bugs in
the original.
It seems probable that this version will be in the next snapshot.
I'd appreciate reports of success or failure with this new version.
The patch below is against the 970904 snapshot.
Thanks,
--
Mark Mitchell mmitchell@usa.net
Stanford University http://www.stanford.edu
Index: gcc/cp/ChangeLog
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/ChangeLog,v
retrieving revision 1.1.1.4
retrieving revision 1.4
diff -c -p -r1.1.1.4 -r1.4
*** ChangeLog 1997/09/04 18:09:44 1.1.1.4
--- ChangeLog 1997/09/05 20:23:58 1.4
***************
*** 1,3 ****
--- 1,45 ----
+ Fri Sep 5 01:37:17 1997 Mark Mitchell <mmitchell@usa.net>
+
+ * cp-tree.h (INNERMOST_TEMPLATE_PARMS): New macro.
+ (DECL_INNERMOST_TEMPLATE_PARMS): Likewise.
+ (PRIMARY_TEMPLATE_P): Use it.
+ * call.c (build_overload_call_real): Use it.
+ * class.c (instantiate_type): Likewise.
+ * decl.c (decls_match): Likewise.
+ * method.c (build_overload_identifier): Likewise.
+ * pt.c (push_template_decl): Likewise.
+ (classtype_mangled_name): Likewise.
+ (lookup_template_class): Likewise.
+
+ * cp-tree.h (DECL_NTPARMS): Change name from DECL_NT_PARMS to
+ DECL_NTPARMS to conform to usage elsewhere.
+ * call.c (add_template_candidate): Likewise.
+ * class.c (instantiate_type): Likewise.
+ * pt.c (instantiate_template): Likewise.
+ (get_bindings): Likewise.
+
+ * class.c (grow_method): Use DECL_FUNCTION_TEMPLATE_P instead of
+ is_member_template.
+
+ * pt.c (unify): Undo changes to allow multiple levels of template
+ parameters.
+ (type_unification): Likewise.
+ (fn_type_unification): Likewise.
+ (get_class_bindings): Likewise.
+ * cp-tree.h (Likewise).
+
+ * decl.c (replace_defarg): Check that the type of the default
+ parameter does not invlove a template type before complaining
+ about the initialization.
+
+ * error.c (dump_expr): Deal with template constant parameters in
+ member templates correctly.
+
+ * pt.c (is_member_template): Deal with class specializations
+ correctly.
+ (tsubst): Handle "partial instantiation" of member templates
+ correctly.
+
Wed Sep 3 11:09:25 1997 Jason Merrill <jason@yorick.cygnus.com>
* typeck.c (c_expand_return): Always convert_for_initialization
*************** Wed Sep 3 00:02:53 1997 Jason Merrill
*** 15,20 ****
--- 57,159 ----
* typeck.c (convert_arguments): Don't arbitrarily choose the first
of a set of overloaded functions.
+
+ Wed Sep 3 12:30:24 1997 Mark Mitchell <mmitchell@usa.net>
+
+ * pt.c (type_uniciation): Change calling squence to allow for
+ multiple levels of template parameters.
+ (tsubst_expr): Likewise.
+ (tsubst): Likewise.
+ (tsubst_copy): Likewise.
+ (instantiate_template): Likewise.
+ (unify): Likewise.
+ * call.c (build_overload_call_real): Use it.
+ (add_builtin_candidate): Use it.
+ (build_new_method_call): Use it.
+ * class.c (instantiate_type): Use it.
+ * decl.c (grokdeclarator): Use it.
+ * decl2.c (finish_file): Use it.
+ * method.c (build_overload_identifier): Use it.
+
+ * call.c (add_template_candidate): Add additional parameter for
+ the function return type. Call fn_type_unification istead of
+ type_unification.
+ (build_user_type_conversion_1): Handle member templates.
+ (build_new_function_call): Likewise.
+ (build_new_op): Likewise.
+ (build_new_method_call): Likewise.
+
+ * class.c (grow_method): Don't give an error message indicating
+ that two member templates with the same name are ambiguous.
+ (finish_struct): Treat member template functions just like member
+ functions.
+
+ * cp-tree.h (check_member_template): Add declaration.
+ (begin_member_template_processing): Likewise.
+ (end_member_template_processing): Likewise.
+ (fn_type_unification): Likewise.
+ (is_member_template): Likewise.
+ (tsubst): Change prototype.
+ (tsubst_expr): Likewise.
+ (tsubst_copy): Likewise.
+ (instantiate_template): Likewise.
+ (get_bindings): Likewise.
+
+ * decl.c (decls_match): Handle multiple levels of template
+ parameters.
+ (pushdecl): Handle template type params just like other type
+ declarations.
+ (push_class_level_binding): Return immediately if the
+ class_binding_level is NULL.
+ (grokfndecl): If check_classfn() returns a member_template, use
+ the result of the template, not the template itself.
+
+ * decl2.c (check_member_template): New function. Check to see
+ that the entity declared to be a member template can be one.
+ (check_classfn): Allow redeclaration of member template functions
+ with different types; the new functions can be specializations or
+ explicit instantiations.
+
+ * error.c (dump_decl): Handle multiple levels of template
+ parametesr.
+ (dump_function_decl): Update to handle function templates.
+
+ * lex.c (do_pending_inlines): Set up template parameter context
+ for member templates.
+ (process_next_inline): Likewise.
+
+ * method. (build_overload_identifier): Adjust for multiple levels
+ of template parameters.
+
+ * parse.y (fn.def2): Add member templates.
+ (component_decl_1): Likewise.
+
+ * pt.c (begin_member_template_processing): New function.
+ (end_member_template_processing): Likewise.
+ (is_member_template): Likewise.
+ (fn_type_unification): Likewise.
+ (current_template_parms): Return a vector of all the template
+ parms, not just the innermost level of parms.
+ (push_template_decl): Deal with the possibility of member
+ templates.
+ (lookup_template_class): Likewise.
+ (uses_template_parms): Likewise.
+ (tsubst): Modify processing to TEMPLATE_TYPE_PARM and
+ TEMPLATE_CONST_PARM to deal with multiple levels of template
+ arguments. Add processing of TEMPLATE_DECL to produce new
+ TEMPLATE_DECLs from old ones.
+ (do_decl_instantiation): Handle member templates.
+
+ * search.c (lookup_fnfields_1): Handle member template conversion
+ operators.
+
+ * tree.c (cp_tree_equal): Check the levels, as well as the
+ indices, of TEMPLATE_CONST_PARMs.
+
+ * typeck.c (comptypes): Check the levels, as well as the indices,
+ fo TEMPLATE_TYPE_PARMs.
+ (build_x_function_call): Treat member templates like member
+ functions.
Tue Sep 2 12:09:13 1997 Jason Merrill <jason@yorick.cygnus.com>
Index: gcc/cp/call.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/call.c,v
retrieving revision 1.1.1.4
retrieving revision 1.4
diff -c -p -r1.1.1.4 -r1.4
*** call.c 1997/09/04 18:09:45 1.1.1.4
--- call.c 1997/09/05 20:23:59 1.4
*************** static tree build_this PROTO((tree));
*** 77,83 ****
static struct z_candidate * splice_viable PROTO((struct z_candidate *));
static int any_viable PROTO((struct z_candidate *));
static struct z_candidate * add_template_candidate
! PROTO((struct z_candidate *, tree, tree, int));
static struct z_candidate * add_builtin_candidates
PROTO((struct z_candidate *, enum tree_code, enum tree_code,
tree, tree *, int));
--- 77,83 ----
static struct z_candidate * splice_viable PROTO((struct z_candidate *));
static int any_viable PROTO((struct z_candidate *));
static struct z_candidate * add_template_candidate
! PROTO((struct z_candidate *, tree, tree, tree, int));
static struct z_candidate * add_builtin_candidates
PROTO((struct z_candidate *, enum tree_code, enum tree_code,
tree, tree *, int));
*************** build_overload_call_real (fnname, parms,
*** 2838,2848 ****
}
if (TREE_CODE (function) == TEMPLATE_DECL)
{
! int ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (function));
! tree *targs = (tree *) alloca (sizeof (tree) * ntparms);
int i;
! i = type_unification (DECL_TEMPLATE_PARMS (function), targs,
TYPE_ARG_TYPES (TREE_TYPE (function)),
parms, &template_cost, 0, 0);
if (i == 0)
--- 2838,2849 ----
}
if (TREE_CODE (function) == TEMPLATE_DECL)
{
! int ntparms = DECL_NTPARMS (function);
! tree targs = make_tree_vec (ntparms);
int i;
! i = type_unification (DECL_INNERMOST_TEMPLATE_PARMS (function),
! &TREE_VEC_ELT (targs, 0),
TYPE_ARG_TYPES (TREE_TYPE (function)),
parms, &template_cost, 0, 0);
if (i == 0)
*************** add_builtin_candidates (candidates, code
*** 4144,4163 ****
}
static struct z_candidate *
! add_template_candidate (candidates, tmpl, arglist, flags)
struct z_candidate *candidates;
! tree tmpl, arglist;
int flags;
{
! int ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (tmpl));
! tree *targs = (tree *) alloca (sizeof (tree) * ntparms);
struct z_candidate *cand;
! int i, dummy = 0;
tree fn;
! i = type_unification (DECL_TEMPLATE_PARMS (tmpl), targs,
! TYPE_ARG_TYPES (TREE_TYPE (tmpl)),
! arglist, &dummy, 0, 0);
if (i != 0)
return candidates;
--- 4145,4163 ----
}
static struct z_candidate *
! add_template_candidate (candidates, tmpl, arglist, return_type, flags)
struct z_candidate *candidates;
! tree tmpl, arglist, return_type;
int flags;
{
! int ntparms = DECL_NTPARMS (tmpl);
! tree targs = make_tree_vec (ntparms);
struct z_candidate *cand;
! int i;
tree fn;
! i = fn_type_unification (tmpl, targs, arglist, return_type, 0);
!
if (i != 0)
return candidates;
*************** build_user_type_conversion_1 (totype, ex
*** 4253,4258 ****
--- 4253,4259 ----
tree fromtype = TREE_TYPE (expr);
tree ctors = NULL_TREE, convs = NULL_TREE, *p;
tree args;
+ tree templates = NULL_TREE;
if (IS_AGGR_TYPE (totype))
ctors = lookup_fnfields (TYPE_BINFO (totype), ctor_identifier, 0);
*************** build_user_type_conversion_1 (totype, ex
*** 4279,4287 ****
if (DECL_NONCONVERTING_P (ctors))
continue;
! candidates = add_function_candidate (candidates, ctors, args, flags);
! candidates->second_conv = build1 (IDENTITY_CONV, totype, NULL_TREE);
! candidates->basetype_path = TYPE_BINFO (totype);
}
if (convs)
--- 4280,4301 ----
if (DECL_NONCONVERTING_P (ctors))
continue;
! if (TREE_CODE (ctors) == TEMPLATE_DECL)
! {
! templates = decl_tree_cons (NULL_TREE, ctors, templates);
! candidates =
! add_template_candidate (candidates, ctors,
! args, NULL_TREE, flags);
! }
! else
! candidates = add_function_candidate (candidates, ctors,
! args, flags);
!
! if (candidates)
! {
! candidates->second_conv = build1 (IDENTITY_CONV, totype, NULL_TREE);
! candidates->basetype_path = TYPE_BINFO (totype);
! }
}
if (convs)
*************** build_user_type_conversion_1 (totype, ex
*** 4308,4318 ****
else if (ics)
for (; fn; fn = DECL_CHAIN (fn))
{
! candidates = add_function_candidate (candidates, fn, args, flags);
! candidates->second_conv = ics;
! candidates->basetype_path = TREE_PURPOSE (convs);
! if (candidates->viable == 1 && ICS_BAD_FLAG (ics))
! candidates->viable = -1;
}
}
--- 4322,4345 ----
else if (ics)
for (; fn; fn = DECL_CHAIN (fn))
{
! if (TREE_CODE (fn) == TEMPLATE_DECL)
! {
! templates = decl_tree_cons (NULL_TREE, fn, templates);
! candidates =
! add_template_candidate (candidates, fn, args,
! totype, flags);
! }
! else
! candidates = add_function_candidate (candidates, fn,
! args, flags);
!
! if (candidates)
! {
! candidates->second_conv = ics;
! candidates->basetype_path = TREE_PURPOSE (convs);
! if (candidates->viable == 1 && ICS_BAD_FLAG (ics))
! candidates->viable = -1;
! }
}
}
*************** build_user_type_conversion_1 (totype, ex
*** 4354,4359 ****
--- 4381,4393 ----
for (p = &(cand->second_conv); TREE_CODE (*p) != IDENTITY_CONV; )
p = &(TREE_OPERAND (*p, 0));
+ /* Pedantically, it is ill-formed to define a function that could
+ also be a template instantiation, but we won't implement that
+ until things settle down. */
+ if (templates && ! cand->template && ! DECL_INITIAL (cand->fn)
+ && TREE_CODE (TREE_TYPE (cand->fn)) != METHOD_TYPE)
+ add_maybe_template (cand->fn, templates);
+
*p = build
(USER_CONV,
(DECL_CONSTRUCTOR_P (cand->fn)
*************** build_new_function_call (fn, args, obj)
*** 4427,4433 ****
{
templates = decl_tree_cons (NULL_TREE, t, templates);
candidates = add_template_candidate
! (candidates, t, args, LOOKUP_NORMAL);
}
else
candidates = add_function_candidate
--- 4461,4467 ----
{
templates = decl_tree_cons (NULL_TREE, t, templates);
candidates = add_template_candidate
! (candidates, t, args, NULL_TREE, LOOKUP_NORMAL);
}
else
candidates = add_function_candidate
*************** build_new_op (code, flags, arg1, arg2, a
*** 4713,4719 ****
{
templates = decl_tree_cons (NULL_TREE, fns, templates);
candidates = add_template_candidate
! (candidates, fns, arglist, flags);
}
else
candidates = add_function_candidate (candidates, fns, arglist, flags);
--- 4747,4753 ----
{
templates = decl_tree_cons (NULL_TREE, fns, templates);
candidates = add_template_candidate
! (candidates, fns, arglist, TREE_TYPE (fnname), flags);
}
else
candidates = add_function_candidate (candidates, fns, arglist, flags);
*************** build_new_op (code, flags, arg1, arg2, a
*** 4730,4742 ****
mem_arglist = tree_cons (NULL_TREE, build_this (arg1), TREE_CHAIN (arglist));
for (; fn; fn = DECL_CHAIN (fn))
{
if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
! candidates = add_function_candidate
! (candidates, fn, mem_arglist, flags);
else
! candidates = add_function_candidate (candidates, fn, arglist, flags);
!
! candidates->basetype_path = TREE_PURPOSE (fns);
}
}
--- 4764,4790 ----
mem_arglist = tree_cons (NULL_TREE, build_this (arg1), TREE_CHAIN (arglist));
for (; fn; fn = DECL_CHAIN (fn))
{
+ tree this_arglist;
+
if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
! this_arglist = mem_arglist;
else
! this_arglist = arglist;
!
! if (TREE_CODE (fn) == TEMPLATE_DECL)
! {
! /* A member template. */
! templates = decl_tree_cons (NULL_TREE, fn, templates);
! candidates = add_template_candidate
! (candidates, fn, this_arglist,
! TREE_TYPE (fnname), LOOKUP_NORMAL);
! }
! else
! candidates = add_function_candidate
! (candidates, fn, this_arglist, flags);
!
! if (candidates)
! candidates->basetype_path = TREE_PURPOSE (fns);
}
}
*************** build_over_call (fn, convs, args, flags)
*** 5189,5195 ****
/* This came from a template. Instantiate the default arg here,
not in tsubst. */
arg = tsubst_expr (arg,
! &TREE_VEC_ELT (DECL_TI_ARGS (fn), 0),
TREE_VEC_LENGTH (DECL_TI_ARGS (fn)), NULL_TREE);
converted_args = tree_cons
(NULL_TREE, convert_default_arg (TREE_VALUE (parm), arg),
--- 5237,5243 ----
/* This came from a template. Instantiate the default arg here,
not in tsubst. */
arg = tsubst_expr (arg,
! DECL_TI_ARGS (fn),
TREE_VEC_LENGTH (DECL_TI_ARGS (fn)), NULL_TREE);
converted_args = tree_cons
(NULL_TREE, convert_default_arg (TREE_VALUE (parm), arg),
*************** build_new_method_call (instance, name, a
*** 5332,5337 ****
--- 5380,5386 ----
tree basetype, mem_args, fns, instance_ptr;
tree pretty_name;
tree user_args = args;
+ tree templates = NULL_TREE;
/* If there is an extra argument for controlling virtual bases,
remove it for error reporting. */
*************** build_new_method_call (instance, name, a
*** 5412,5428 ****
mem_args = tree_cons (NULL_TREE, instance_ptr, args);
for (; t; t = DECL_CHAIN (t))
{
/* We can end up here for copy-init of same or base class. */
if (name == ctor_identifier
&& (flags & LOOKUP_ONLYCONVERTING)
&& DECL_NONCONVERTING_P (t))
continue;
if (TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE)
! candidates = add_function_candidate
! (candidates, t, mem_args, flags);
else
! candidates = add_function_candidate (candidates, t, args, flags);
! candidates->basetype_path = TREE_PURPOSE (fns);
}
}
--- 5461,5494 ----
mem_args = tree_cons (NULL_TREE, instance_ptr, args);
for (; t; t = DECL_CHAIN (t))
{
+ tree this_arglist;
+
/* We can end up here for copy-init of same or base class. */
if (name == ctor_identifier
&& (flags & LOOKUP_ONLYCONVERTING)
&& DECL_NONCONVERTING_P (t))
continue;
if (TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE)
! this_arglist = mem_args;
else
! this_arglist = args;
!
! if (TREE_CODE (t) == TEMPLATE_DECL)
! {
! /* A member template. */
! templates = decl_tree_cons (NULL_TREE, t, templates);
! candidates =
! add_template_candidate (candidates, t,
! this_arglist,
! TREE_TYPE (name),
! LOOKUP_NORMAL);
! }
! else
! candidates = add_function_candidate (candidates, t,
! this_arglist, flags);
!
! if (candidates)
! candidates->basetype_path = TREE_PURPOSE (fns);
}
}
*************** build_new_method_call (instance, name, a
*** 5463,5468 ****
--- 5529,5540 ----
&& ((instance == current_class_ref && (dtor_label || ctor_label))
|| resolves_to_fixed_type_p (instance, 0)))
flags |= LOOKUP_NONVIRTUAL;
+
+ /* Pedantically, it is ill-formed to define a function that could
+ also be a template instantiation, but we won't implement that
+ until things settle down. */
+ if (templates && ! cand->template && ! DECL_INITIAL (cand->fn))
+ add_maybe_template (cand->fn, templates);
return build_over_call
(cand->fn, cand->convs,
Index: gcc/cp/class.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/class.c,v
retrieving revision 1.1.1.2
retrieving revision 1.4
diff -c -p -r1.1.1.2 -r1.4
*** class.c 1997/08/29 02:03:51 1.1.1.2
--- class.c 1997/09/05 20:23:59 1.4
*************** grow_method (fndecl, method_vec_ptr)
*** 1883,1889 ****
cp_error_at ("`%D' overloaded", fndecl);
cp_error_at ("previous declaration as `%D' here", x);
}
! if (DECL_ASSEMBLER_NAME (fndecl) == DECL_ASSEMBLER_NAME (x))
{
/* Friend-friend ambiguities are warned about outside
this loop. */
--- 1883,1891 ----
cp_error_at ("`%D' overloaded", fndecl);
cp_error_at ("previous declaration as `%D' here", x);
}
! if (DECL_ASSEMBLER_NAME (fndecl) == DECL_ASSEMBLER_NAME (x)
! && ! DECL_FUNCTION_TEMPLATE_P (x)
! && ! DECL_FUNCTION_TEMPLATE_P (fndecl))
{
/* Friend-friend ambiguities are warned about outside
this loop. */
*************** finish_struct (t, list_of_fieldlists, at
*** 4384,4390 ****
}
}
! if (TREE_CODE (x) == FUNCTION_DECL)
{
DECL_CLASS_CONTEXT (x) = t;
if (last_x)
--- 4386,4393 ----
}
}
! if (TREE_CODE (x) == FUNCTION_DECL
! || DECL_FUNCTION_TEMPLATE_P (x))
{
DECL_CLASS_CONTEXT (x) = t;
if (last_x)
*************** instantiate_type (lhstype, rhs, complain
*** 5062,5073 ****
for (elem = get_first_fn (rhs); elem; elem = DECL_CHAIN (elem))
if (TREE_CODE (elem) == TEMPLATE_DECL)
{
! int n = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (elem));
! tree *t = (tree *) alloca (sizeof (tree) * n);
int i, d = 0;
! i = type_unification (DECL_TEMPLATE_PARMS (elem), t,
! TYPE_ARG_TYPES (TREE_TYPE (elem)),
! TYPE_ARG_TYPES (lhstype), &d, 0, 1);
if (i == 0)
{
if (save_elem)
--- 5065,5078 ----
for (elem = get_first_fn (rhs); elem; elem = DECL_CHAIN (elem))
if (TREE_CODE (elem) == TEMPLATE_DECL)
{
! int n = DECL_NTPARMS (elem);
! tree t = make_tree_vec (n);
int i, d = 0;
! i =
! type_unification (DECL_INNERMOST_TEMPLATE_PARMS (elem),
! &TREE_VEC_ELT (t, 0),
! TYPE_ARG_TYPES (TREE_TYPE (elem)),
! TYPE_ARG_TYPES (lhstype), &d, 0, 1);
if (i == 0)
{
if (save_elem)
Index: gcc/cp/cp-tree.def
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/cp-tree.def,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -c -p -r1.1.1.1 -r1.2
*** cp-tree.def 1997/08/26 06:23:55 1.1.1.1
--- cp-tree.def 1997/09/02 06:38:38 1.2
*************** DEFTREECODE (TYPENAME_TYPE, "typename_ty
*** 91,97 ****
/* Index into a template parameter list. This parameter must not be a
type. */
! DEFTREECODE (TEMPLATE_CONST_PARM, "template_const_parm", "c", 2)
/* A thunk is a stub function.
--- 91,97 ----
/* Index into a template parameter list. This parameter must not be a
type. */
! DEFTREECODE (TEMPLATE_CONST_PARM, "template_const_parm", "c", 3)
/* A thunk is a stub function.
Index: gcc/cp/cp-tree.h
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.1.1.1
retrieving revision 1.4
diff -c -p -r1.1.1.1 -r1.4
*** cp-tree.h 1997/08/26 06:23:55 1.1.1.1
--- cp-tree.h 1997/09/05 20:23:59 1.4
*************** struct lang_decl
*** 1091,1096 ****
--- 1091,1097 ----
#define CLASSTYPE_TI_TEMPLATE(NODE) TI_TEMPLATE (CLASSTYPE_TEMPLATE_INFO (NODE))
#define CLASSTYPE_TI_ARGS(NODE) TI_ARGS (CLASSTYPE_TEMPLATE_INFO (NODE))
#define CLASSTYPE_TI_SPEC_INFO(NODE) TI_SPEC_INFO (CLASSTYPE_TEMPLATE_INFO (NODE))
+ #define INNERMOST_TEMPLATE_PARMS(NODE) TREE_VALUE(NODE)
#define DECL_SAVED_TREE(NODE) DECL_MEMFUNC_POINTER_TO (NODE)
#define COMPOUND_STMT_NO_SCOPE(NODE) TREE_LANG_FLAG_0 (NODE)
*************** extern int flag_new_for_scope;
*** 1334,1339 ****
--- 1335,1344 ----
/* Accessor macros for C++ template decl nodes. */
#define DECL_TEMPLATE_PARMS(NODE) DECL_ARGUMENTS(NODE)
+ #define DECL_INNERMOST_TEMPLATE_PARMS(NODE) \
+ INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (NODE))
+ #define DECL_NTPARMS(NODE) \
+ TREE_VEC_LENGTH (DECL_INNERMOST_TEMPLATE_PARMS (NODE))
/* For class templates. */
#define DECL_TEMPLATE_SPECIALIZATIONS(NODE) DECL_SIZE(NODE)
/* For function, method, class-data templates. */
*************** extern int flag_new_for_scope;
*** 1346,1352 ****
&& TREE_CODE (DECL_TEMPLATE_RESULT (NODE)) == FUNCTION_DECL)
#define PRIMARY_TEMPLATE_P(NODE) \
! (TREE_TYPE (DECL_TEMPLATE_PARMS (NODE)) == (NODE))
#define CLASSTYPE_TEMPLATE_LEVEL(NODE) \
(TREE_INT_CST_HIGH (TREE_PURPOSE (CLASSTYPE_TI_TEMPLATE (NODE))))
--- 1351,1357 ----
&& TREE_CODE (DECL_TEMPLATE_RESULT (NODE)) == FUNCTION_DECL)
#define PRIMARY_TEMPLATE_P(NODE) \
! (TREE_TYPE (DECL_INNERMOST_TEMPLATE_PARMS (NODE)) == (NODE))
#define CLASSTYPE_TEMPLATE_LEVEL(NODE) \
(TREE_INT_CST_HIGH (TREE_PURPOSE (CLASSTYPE_TI_TEMPLATE (NODE))))
*************** extern tree grok_alignof PROTO((tree))
*** 2112,2117 ****
--- 2117,2123 ----
extern tree grok_array_decl PROTO((tree, tree));
extern tree delete_sanity PROTO((tree, tree, int, int));
extern tree check_classfn PROTO((tree, tree));
+ extern void check_member_template PROTO((tree));
extern tree grokfield PROTO((tree, tree, tree, tree, tree));
extern tree grokbitfield PROTO((tree, tree, tree));
extern tree groktypefield PROTO((tree, tree));
*************** extern void synthesize_method PROTO((t
*** 2299,2308 ****
extern tree get_id_2 PROTO((char *, tree));
/* in pt.c */
! extern tree tsubst PROTO ((tree, tree*, int, tree));
! extern tree tsubst_expr PROTO ((tree, tree*, int, tree));
! extern tree tsubst_copy PROTO ((tree, tree*, int, tree));
extern tree tsubst_chain PROTO((tree, tree));
extern void begin_template_parm_list PROTO((void));
extern tree process_template_parm PROTO((tree, tree));
extern tree end_template_parm_list PROTO((tree));
--- 2305,2316 ----
extern tree get_id_2 PROTO((char *, tree));
/* in pt.c */
! extern tree tsubst PROTO ((tree, tree, int, tree));
! extern tree tsubst_expr PROTO ((tree, tree, int, tree));
! extern tree tsubst_copy PROTO ((tree, tree, int, tree));
extern tree tsubst_chain PROTO((tree, tree));
+ extern void begin_member_template_processing PROTO((tree));
+ extern void end_member_template_processing PROTO((void));
extern void begin_template_parm_list PROTO((void));
extern tree process_template_parm PROTO((tree, tree));
extern tree end_template_parm_list PROTO((tree));
*************** extern void push_template_decl PROTO((
*** 2312,2319 ****
extern tree lookup_template_class PROTO((tree, tree, tree));
extern int uses_template_parms PROTO((tree));
extern tree instantiate_class_template PROTO((tree));
! extern tree instantiate_template PROTO((tree, tree *));
extern void overload_template_name PROTO((tree));
extern int type_unification PROTO((tree, tree *, tree, tree, int *, int, int));
struct tinst_level *tinst_for_decl PROTO((void));
extern void mark_decl_instantiated PROTO((tree, int));
--- 2320,2328 ----
extern tree lookup_template_class PROTO((tree, tree, tree));
extern int uses_template_parms PROTO((tree));
extern tree instantiate_class_template PROTO((tree));
! extern tree instantiate_template PROTO((tree, tree));
extern void overload_template_name PROTO((tree));
+ extern int fn_type_unification PROTO((tree, tree, tree, tree, int));
extern int type_unification PROTO((tree, tree *, tree, tree, int *, int, int));
struct tinst_level *tinst_for_decl PROTO((void));
extern void mark_decl_instantiated PROTO((tree, int));
*************** extern void do_type_instantiation PROTO
*** 2324,2330 ****
extern tree instantiate_decl PROTO((tree));
extern tree lookup_nested_type_by_name PROTO((tree, tree));
extern tree do_poplevel PROTO((void));
! extern tree *get_bindings PROTO((tree, tree));
/* CONT ... */
extern void add_tree PROTO((tree));
extern void add_maybe_template PROTO((tree, tree));
--- 2333,2339 ----
extern tree instantiate_decl PROTO((tree));
extern tree lookup_nested_type_by_name PROTO((tree, tree));
extern tree do_poplevel PROTO((void));
! extern tree get_bindings PROTO((tree, tree));
/* CONT ... */
extern void add_tree PROTO((tree));
extern void add_maybe_template PROTO((tree, tree));
*************** extern tree most_specialized PROTO((tr
*** 2333,2338 ****
--- 2342,2348 ----
extern tree most_specialized_class PROTO((tree, tree));
extern int more_specialized_class PROTO((tree, tree));
extern void do_pushlevel PROTO((void));
+ extern int is_member_template PROTO((tree));
/* in repo.c */
extern void repo_template_used PROTO((tree));
Index: gcc/cp/decl.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/decl.c,v
retrieving revision 1.1.1.3
retrieving revision 1.4
diff -c -p -r1.1.1.3 -r1.4
*** decl.c 1997/09/04 18:09:46 1.1.1.3
--- decl.c 1997/09/05 20:24:00 1.4
*************** decls_match (newdecl, olddecl)
*** 2306,2328 ****
{
tree newargs = DECL_TEMPLATE_PARMS (newdecl);
tree oldargs = DECL_TEMPLATE_PARMS (olddecl);
! int i, len = TREE_VEC_LENGTH (newargs);
! if (TREE_VEC_LENGTH (oldargs) != len)
! return 0;
!
! for (i = 0; i < len; i++)
{
! tree newarg = TREE_VALUE (TREE_VEC_ELT (newargs, i));
! tree oldarg = TREE_VALUE (TREE_VEC_ELT (oldargs, i));
! if (TREE_CODE (newarg) != TREE_CODE (oldarg))
! return 0;
! else if (TREE_CODE (newarg) == TYPE_DECL)
! /* continue */;
! else if (! comptypes (TREE_TYPE (newarg), TREE_TYPE (oldarg), 1))
return 0;
}
if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
types_match = 1;
else
--- 2306,2345 ----
{
tree newargs = DECL_TEMPLATE_PARMS (newdecl);
tree oldargs = DECL_TEMPLATE_PARMS (olddecl);
! int i;
! /* Run through all the levels of template parmaters, checking
! that they match. */
! while (newargs && oldargs)
{
! int len = TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS (newargs));
!
! if (TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS (oldargs)) != len)
return 0;
+
+ for (i = 0; i < len; i++)
+ {
+ tree newarg =
+ TREE_VALUE (TREE_VEC_ELT
+ (INNERMOST_TEMPLATE_PARMS (newargs), i));
+ tree oldarg =
+ TREE_VALUE (TREE_VEC_ELT
+ (INNERMOST_TEMPLATE_PARMS (oldargs), i));
+ if (TREE_CODE (newarg) != TREE_CODE (oldarg))
+ return 0;
+ else if (TREE_CODE (newarg) == TYPE_DECL)
+ /* continue */;
+ else if (! comptypes (TREE_TYPE (newarg), TREE_TYPE (oldarg), 1))
+ return 0;
+ }
+ newargs = TREE_CHAIN (newargs);
+ oldargs = TREE_CHAIN (oldargs);
}
+ if ((newargs == NULL_TREE) != (oldargs == NULL_TREE))
+ /* One declaration has more levels that the other. */
+ return 0;
+
if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
types_match = 1;
else
*************** pushdecl (x)
*** 3003,3009 ****
/* Type are looked up using the DECL_NAME, as that is what the rest of the
compiler wants to use. */
if (TREE_CODE (x) == TYPE_DECL || TREE_CODE (x) == VAR_DECL
! || TREE_CODE (x) == NAMESPACE_DECL)
name = DECL_NAME (x);
if (name)
--- 3020,3026 ----
/* Type are looked up using the DECL_NAME, as that is what the rest of the
compiler wants to use. */
if (TREE_CODE (x) == TYPE_DECL || TREE_CODE (x) == VAR_DECL
! || TREE_CODE (x) == NAMESPACE_DECL || TREE_CODE (x) == TEMPLATE_TYPE_PARM)
name = DECL_NAME (x);
if (name)
*************** push_class_level_binding (name, x)
*** 3493,3498 ****
--- 3510,3520 ----
tree name;
tree x;
{
+ /* The class_binding_level will be NULL if x is a template
+ parameter name in a member template. */
+ if (!class_binding_level)
+ return;
+
if (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)
&& purpose_member (name, class_binding_level->class_shadowed))
return;
*************** grokfndecl (ctype, type, declarator, vir
*** 7232,7237 ****
--- 7254,7263 ----
if (check)
{
tmp = check_classfn (ctype, decl);
+
+ if (tmp && TREE_CODE (tmp) == TEMPLATE_DECL)
+ tmp = DECL_TEMPLATE_RESULT(tmp);
+
if (tmp && DECL_ARTIFICIAL (tmp))
cp_error ("definition of implicitly-declared `%D'", tmp);
if (tmp && duplicate_decls (decl, tmp))
*************** grokfndecl (ctype, type, declarator, vir
*** 7270,7275 ****
--- 7296,7305 ----
if (ctype != NULL_TREE && check)
{
tmp = check_classfn (ctype, decl);
+
+ if (tmp && TREE_CODE (tmp) == TEMPLATE_DECL)
+ tmp = DECL_TEMPLATE_RESULT(tmp);
+
if (tmp && DECL_STATIC_FUNCTION_P (tmp)
&& TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
{
*************** grokdeclarator (declarator, declspecs, d
*** 8934,8941 ****
&& uses_template_parms (current_class_type))
{
tree args = current_template_args ();
! type = tsubst (type, &TREE_VEC_ELT (args, 0),
! TREE_VEC_LENGTH (args), NULL_TREE);
}
/* This pop_nested_class corresponds to the
--- 8964,8973 ----
&& uses_template_parms (current_class_type))
{
tree args = current_template_args ();
! type = tsubst (type, args,
! TREE_VEC_LENGTH (TREE_VEC_ELT
! (args, 0)),
! NULL_TREE);
}
/* This pop_nested_class corresponds to the
*************** void
*** 10038,10044 ****
replace_defarg (arg, init)
tree arg, init;
{
! if (! processing_template_decl
&& ! can_convert_arg (TREE_VALUE (arg), TREE_TYPE (init), init))
cp_pedwarn ("invalid type `%T' for default argument to `%T'",
TREE_TYPE (init), TREE_VALUE (arg));
--- 10070,10076 ----
replace_defarg (arg, init)
tree arg, init;
{
! if (! processing_template_decl && ! uses_template_parms (TREE_VALUE (arg))
&& ! can_convert_arg (TREE_VALUE (arg), TREE_TYPE (init), init))
cp_pedwarn ("invalid type `%T' for default argument to `%T'",
TREE_TYPE (init), TREE_VALUE (arg));
Index: gcc/cp/decl2.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/decl2.c,v
retrieving revision 1.1.1.3
retrieving revision 1.3
diff -c -p -r1.1.1.3 -r1.3
*** decl2.c 1997/09/04 18:09:46 1.1.1.3
--- decl2.c 1997/09/04 20:27:28 1.3
*************** delete_sanity (exp, size, doing_vec, use
*** 1282,1287 ****
--- 1282,1343 ----
}
}
+
+ /* Report an error if the indicated template declaration is not the
+ sort of thing that should be a member template.
+ */
+
+ void
+ check_member_template (tmpl)
+ tree tmpl;
+ {
+ tree decl;
+
+ my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0);
+ decl = DECL_TEMPLATE_RESULT (tmpl);
+
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ {
+ if (current_function_decl)
+ /* 14.5.2.2 [temp.mem]
+
+ A local class shall not have member templates. */
+ cp_error ("declaration of of member template `%#D' in local class",
+ decl);
+
+ if (DECL_VIRTUAL_P (decl))
+ {
+ /* 14.5.2.3 [temp.mem]
+
+ A member function template shall not be virtual. */
+ cp_error
+ ("invalid use of `virtual' in template declaration of `%#D'",
+ decl);
+ DECL_VIRTUAL_P (decl) = 0;
+ }
+
+ /* The debug-information generating code doesn't know what to do
+ with member templates. */
+ DECL_IGNORED_P (tmpl) = 1;
+ }
+ else if (TREE_CODE (decl) == TYPE_DECL &&
+ AGGREGATE_TYPE_P (TREE_TYPE (decl)))
+ {
+ if (current_function_decl)
+ /* 14.5.2.2 [temp.mem]
+
+ A local class shall not have member templates. */
+ cp_error ("declaration of of member template `%#D' in local class",
+ decl);
+
+ /* We don't handle member template classes yet. */
+ sorry ("member templates classes");
+ }
+ else
+ cp_error ("template declaration of `%#D'", decl);
+ }
+
+
/* Sanity check: report error if this function FUNCTION is not
really a member of the class (CTYPE) it is supposed to belong to.
CNAME is the same here as it is for grokclassfn above. */
*************** check_classfn (ctype, function)
*** 1295,1300 ****
--- 1351,1357 ----
tree method_vec = CLASSTYPE_METHOD_VEC (complete_type (ctype));
tree *methods = 0;
tree *end = 0;
+ tree templates = NULL_TREE;
if (method_vec != 0)
{
*************** check_classfn (ctype, function)
*** 1311,1316 ****
--- 1368,1374 ----
while (++methods != end)
{
+ fndecl = *methods;
if (fn_name == DECL_NAME (*methods))
{
got_it:
*************** check_classfn (ctype, function)
*** 1342,1356 ****
--- 1400,1439 ----
TREE_TYPE (TREE_TYPE (fndecl)), 1)
&& compparms (p1, p2, 3))
return fndecl;
+
+ if (is_member_template (fndecl))
+ /* This function might be an instantiation
+ or specialization of fndecl. */
+ templates =
+ tree_cons (NULL_TREE, fndecl, templates);
}
#endif
fndecl = DECL_CHAIN (fndecl);
}
break; /* loser */
}
+ else if (TREE_CODE (fndecl) == TEMPLATE_DECL
+ && IDENTIFIER_TYPENAME_P (DECL_NAME (fndecl))
+ && IDENTIFIER_TYPENAME_P (fn_name))
+ /* The method in the class is a member template
+ conversion operator. We are declaring another
+ conversion operator. It is possible that even though
+ the names don't match, there is some specialization
+ occurring. */
+ templates =
+ tree_cons (NULL_TREE, fndecl, templates);
}
}
+ if (templates)
+ /* This function might be an instantiation or a specialization.
+ We should verify that this is possible. If it is, we must
+ somehow add the new declaration to the method vector for the
+ class. Perhaps we should use add_method? For now, we simply
+ return NULL_TREE, which lets the caller know that this
+ function is new, but we don't print an error message. */
+ return NULL_TREE;
+
if (methods != end)
{
tree fndecl = *methods;
*************** finish_file ()
*** 2792,2798 ****
for (fnname = maybe_templates; fnname; fnname = TREE_CHAIN (fnname))
{
! tree *args, fn, decl = TREE_VALUE (fnname);
if (DECL_INITIAL (decl))
continue;
--- 2875,2881 ----
for (fnname = maybe_templates; fnname; fnname = TREE_CHAIN (fnname))
{
! tree args, fn, decl = TREE_VALUE (fnname);
if (DECL_INITIAL (decl))
continue;
*************** finish_file ()
*** 2800,2806 ****
fn = TREE_PURPOSE (fnname);
args = get_bindings (fn, decl);
fn = instantiate_template (fn, args);
- free (args);
instantiate_decl (fn);
}
--- 2883,2888 ----
Index: gcc/cp/error.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/error.c,v
retrieving revision 1.1.1.2
retrieving revision 1.5
diff -c -p -r1.1.1.2 -r1.5
*** error.c 1997/08/29 02:03:54 1.1.1.2
--- error.c 1997/09/05 20:24:00 1.5
*************** dump_decl (t, v)
*** 722,754 ****
case TEMPLATE_DECL:
{
! tree args = DECL_TEMPLATE_PARMS (t);
! int i, len = args ? TREE_VEC_LENGTH (args) : 0;
! OB_PUTS ("template <");
! for (i = 0; i < len; i++)
{
! tree arg = TREE_VEC_ELT (args, i);
! tree defval = TREE_PURPOSE (arg);
! arg = TREE_VALUE (arg);
! if (TREE_CODE (arg) == TYPE_DECL)
! {
! OB_PUTS ("class ");
! OB_PUTID (DECL_NAME (arg));
! }
! else
! dump_decl (arg, 1);
! if (defval)
{
! OB_PUTS (" = ");
! dump_decl (defval, 1);
! }
! OB_PUTC2 (',', ' ');
}
! if (len != 0)
! OB_UNPUT (2);
! OB_PUTC2 ('>', ' ');
if (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == TYPE_DECL)
dump_type (TREE_TYPE (t), v);
--- 722,763 ----
case TEMPLATE_DECL:
{
! tree orig_args = DECL_TEMPLATE_PARMS (t);
! tree args;
! int i;
! for (args = orig_args = nreverse (orig_args);
! args;
! args = TREE_CHAIN (args))
{
! int len = TREE_VEC_LENGTH (TREE_VALUE (args));
! OB_PUTS ("template <");
! for (i = 0; i < len; i++)
{
! tree arg = TREE_VEC_ELT (TREE_VALUE (args), i);
! tree defval = TREE_PURPOSE (arg);
! arg = TREE_VALUE (arg);
! if (TREE_CODE (arg) == TYPE_DECL)
! {
! OB_PUTS ("class ");
! OB_PUTID (DECL_NAME (arg));
! }
! else
! dump_decl (arg, 1);
!
! if (defval)
! {
! OB_PUTS (" = ");
! dump_decl (defval, 1);
! }
! OB_PUTC2 (',', ' ');
! }
! if (len != 0)
! OB_UNPUT (2);
! OB_PUTC2 ('>', ' ');
}
! nreverse(orig_args);
if (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == TYPE_DECL)
dump_type (TREE_TYPE (t), v);
*************** dump_function_decl (t, v)
*** 801,811 ****
tree t;
int v;
{
! tree name = DECL_ASSEMBLER_NAME (t);
! tree fntype = TREE_TYPE (t);
! tree parmtypes = TYPE_ARG_TYPES (fntype);
tree cname = NULL_TREE;
/* Friends have DECL_CLASS_CONTEXT set, but not DECL_CONTEXT. */
if (DECL_CONTEXT (t))
cname = DECL_CLASS_CONTEXT (t);
--- 810,827 ----
tree t;
int v;
{
! tree name;
! tree fntype;
! tree parmtypes;
tree cname = NULL_TREE;
+ if (TREE_CODE (t) == TEMPLATE_DECL)
+ t = DECL_TEMPLATE_RESULT (t);
+
+ name = DECL_ASSEMBLER_NAME (t);
+ fntype = TREE_TYPE (t);
+ parmtypes = TYPE_ARG_TYPES (fntype);
+
/* Friends have DECL_CLASS_CONTEXT set, but not DECL_CONTEXT. */
if (DECL_CONTEXT (t))
cname = DECL_CLASS_CONTEXT (t);
*************** dump_expr (t, nop)
*** 1349,1356 ****
case TEMPLATE_CONST_PARM:
if (current_template_parms)
{
! tree r = TREE_VEC_ELT (TREE_VALUE (current_template_parms),
! TEMPLATE_CONST_IDX (t));
dump_decl (TREE_VALUE (r), -1);
}
else
--- 1365,1381 ----
case TEMPLATE_CONST_PARM:
if (current_template_parms)
{
! int i;
! tree parms;
! tree r;
!
! for (parms = current_template_parms;
! TREE_CHAIN (parms);
! parms = TREE_CHAIN (parms))
! ;
!
! r = TREE_VEC_ELT (TREE_VALUE (parms),
! TEMPLATE_CONST_IDX (t));
dump_decl (TREE_VALUE (r), -1);
}
else
Index: gcc/cp/lex.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/lex.c,v
retrieving revision 1.1.1.2
diff -c -p -r1.1.1.2 lex.c
*** lex.c 1997/09/04 18:09:46 1.1.1.2
--- lex.c 1997/09/05 07:32:06
*************** do_pending_inlines ()
*** 1190,1195 ****
--- 1190,1197 ----
context = hack_decl_function_context (t->fndecl);
if (context)
push_cp_function_context (context);
+ if (is_member_template (t->fndecl))
+ begin_member_template_processing (DECL_TI_ARGS (t->fndecl));
if (t->len > 0)
{
feed_input (t->buf, t->len);
*************** process_next_inline (t)
*** 1226,1232 ****
{
tree context;
struct pending_inline *i = (struct pending_inline *) TREE_PURPOSE (t);
! context = hack_decl_function_context (i->fndecl);
if (context)
pop_cp_function_context (context);
i = i->next;
--- 1228,1236 ----
{
tree context;
struct pending_inline *i = (struct pending_inline *) TREE_PURPOSE (t);
! context = hack_decl_function_context (i->fndecl);
! if (is_member_template (i->fndecl))
! end_member_template_processing ();
if (context)
pop_cp_function_context (context);
i = i->next;
*************** process_next_inline (t)
*** 1249,1254 ****
--- 1253,1260 ----
context = hack_decl_function_context (i->fndecl);
if (context)
push_cp_function_context (context);
+ if (is_member_template (i->fndecl))
+ begin_member_template_processing (DECL_TI_ARGS (i->fndecl));
feed_input (i->buf, i->len);
lineno = i->lineno;
input_filename = i->filename;
Index: gcc/cp/method.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/method.c,v
retrieving revision 1.1.1.2
retrieving revision 1.4
diff -c -p -r1.1.1.2 -r1.4
*** method.c 1997/09/04 18:09:47 1.1.1.2
--- method.c 1997/09/05 20:24:00 1.4
*************** build_overload_identifier (name)
*** 648,654 ****
arglist = TREE_VALUE (template);
template = TREE_PURPOSE (template);
tname = DECL_NAME (template);
! parmlist = DECL_ARGUMENTS (template);
nparms = TREE_VEC_LENGTH (parmlist);
OB_PUTC ('t');
icat (IDENTIFIER_LENGTH (tname));
--- 648,654 ----
arglist = TREE_VALUE (template);
template = TREE_PURPOSE (template);
tname = DECL_NAME (template);
! parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
nparms = TREE_VEC_LENGTH (parmlist);
OB_PUTC ('t');
icat (IDENTIFIER_LENGTH (tname));
*************** build_overload_identifier (name)
*** 666,672 ****
}
else
{
! parm = tsubst (parm, &TREE_VEC_ELT (arglist, 0),
TREE_VEC_LENGTH (arglist), NULL_TREE);
/* It's a PARM_DECL. */
build_overload_name (TREE_TYPE (parm), 0, 0);
--- 666,672 ----
}
else
{
! parm = tsubst (parm, arglist,
TREE_VEC_LENGTH (arglist), NULL_TREE);
/* It's a PARM_DECL. */
build_overload_name (TREE_TYPE (parm), 0, 0);
Index: gcc/cp/parse.y
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/parse.y,v
retrieving revision 1.1.1.2
retrieving revision 1.3
diff -c -p -r1.1.1.2 -r1.3
*** parse.y 1997/09/04 18:09:47 1.1.1.2
--- parse.y 1997/09/04 20:27:31 1.3
*************** fn.def2:
*** 699,704 ****
--- 699,720 ----
$$ = start_method (specs, $2); goto rest_of_mdef; }
| constructor_declarator
{ $$ = start_method (NULL_TREE, $$); goto rest_of_mdef; }
+ | template_header fn.def2
+ {
+ end_template_decl ();
+ if ($2 && DECL_TEMPLATE_INFO ($2))
+ {
+ $$ = DECL_TI_TEMPLATE ($2);
+ check_member_template ($$);
+ }
+ else if ($2)
+ $$ = $2;
+ else
+ {
+ cp_error("invalid member template declaration");
+ $$ = NULL_TREE;
+ }
+ }
;
return_id:
*************** component_decl_1:
*** 2711,2717 ****
build_tree_list ($3, NULL_TREE)); }
| using_decl
{ $$ = do_class_using_decl ($1); }
! ;
/* The case of exactly one component is handled directly by component_decl. */
/* ??? Huh? ^^^ */
--- 2727,2748 ----
build_tree_list ($3, NULL_TREE)); }
| using_decl
{ $$ = do_class_using_decl ($1); }
! | template_header component_decl_1
! {
! end_template_decl ();
! if ($2 && DECL_TEMPLATE_INFO ($2))
! {
! $$ = DECL_TI_TEMPLATE ($2);
! check_member_template ($$);
! }
! else if ($2)
! $$ = $2;
! else
! {
! cp_error("invalid member template declaration");
! $$ = NULL_TREE;
! }
! }
/* The case of exactly one component is handled directly by component_decl. */
/* ??? Huh? ^^^ */
Index: gcc/cp/pt.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/pt.c,v
retrieving revision 1.1.1.2
retrieving revision 1.4
diff -c -p -r1.1.1.2 -r1.4
*** pt.c 1997/09/04 18:09:47 1.1.1.2
--- pt.c 1997/09/05 20:24:01 1.4
*************** static int comp_template_args PROTO((tre
*** 76,82 ****
static int list_eq PROTO((tree, tree));
static tree get_class_bindings PROTO((tree, tree, tree));
static tree coerce_template_parms PROTO((tree, tree, tree));
! static tree tsubst_enum PROTO((tree, tree *, int));
/* We've got a template header coming up; push to a new level for storing
the parms. */
--- 76,226 ----
static int list_eq PROTO((tree, tree));
static tree get_class_bindings PROTO((tree, tree, tree));
static tree coerce_template_parms PROTO((tree, tree, tree));
! static tree tsubst_enum PROTO((tree, tree, int));
! static tree add_to_template_args PROTO((tree, tree));
!
! /* Restore the template parameter context. */
!
! void
! begin_member_template_processing (parms)
! tree parms;
! {
! int i;
!
! ++processing_template_decl;
! current_template_parms
! = tree_cons (build_int_2 (0, processing_template_decl),
! parms, current_template_parms);
! for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
! {
! tree parm = TREE_VEC_ELT (parms, i);
!
! switch (TREE_CODE (parm))
! {
! case TEMPLATE_TYPE_PARM:
! pushdecl (TYPE_NAME (parm));
! break;
!
! case TEMPLATE_CONST_PARM:
! pushdecl (parm);
! break;
!
! default:
! my_friendly_abort (0);
! }
! }
! }
!
! /* Undo the effects of begin_member_template_processing. */
!
! void
! end_member_template_processing ()
! {
! if (! processing_template_decl)
! return;
!
! --processing_template_decl;
! current_template_parms = TREE_CHAIN (current_template_parms);
! }
!
! /* Returns non-zero iff T is a member template function. Works if T
! is either a FUNCTION_DECL or a TEMPLATE_DECL. */
!
! int
! is_member_template (t)
! tree t;
! {
! int r = 0;
!
! if (DECL_FUNCTION_MEMBER_P (t) ||
! (TREE_CODE (t) == TEMPLATE_DECL &&
! DECL_FUNCTION_MEMBER_P (DECL_TEMPLATE_RESULT (t))))
! {
! tree tmpl = NULL_TREE;
!
! if (DECL_FUNCTION_TEMPLATE_P (t))
! tmpl = t;
! else if (DECL_TEMPLATE_INFO (t)
! && DECL_FUNCTION_TEMPLATE_P (DECL_TI_TEMPLATE (t)))
! tmpl = DECL_TI_TEMPLATE (t);
!
! if (tmpl)
! {
! tree parms = DECL_TEMPLATE_PARMS (tmpl);
! int parm_levels = list_length (parms);
! int template_class_levels = 0;
! tree ctx = DECL_CLASS_CONTEXT (t);
!
! if (CLASSTYPE_TEMPLATE_INFO (ctx))
! {
! tree args;
!
! /* Here, we should really count the number of levels
! deep ctx is, making sure not to count any levels that
! are just specializations. Since there are no member
! template classes yet, we don't have to do all that. */
!
! if (!CLASSTYPE_TEMPLATE_SPECIALIZATION (ctx))
! template_class_levels = 1;
! else
! {
! int i;
!
! args = CLASSTYPE_TI_ARGS (ctx);
!
! if (args == NULL_TREE)
! template_class_levels = 1;
! else
! for (i = 0; i < TREE_VEC_LENGTH (args); ++i)
! if (uses_template_parms (TREE_VEC_ELT (args, i)))
! {
! template_class_levels++;
! break;
! }
! }
! }
!
! if (parm_levels > template_class_levels)
! r = 1;
! }
! }
!
! return r;
! }
!
!
!
! /* Return a new template argument vector which contains all of ARGS,
! but has as its innermost set of arguments the EXTRA_ARGS. */
!
! tree
! add_to_template_args(args, extra_args)
! tree args;
! tree extra_args;
! {
! tree new_args;
!
! if (TREE_CODE (TREE_VEC_ELT (args, 0)) != TREE_VEC)
! {
! new_args = make_tree_vec (2);
! TREE_VEC_ELT (new_args, 0) = args;
! }
! else
! {
! int i;
!
! new_args = make_tree_vec (TREE_VEC_LENGTH (args) - 1);
!
! for (i = 0; i < TREE_VEC_LENGTH (args); ++i)
! TREE_VEC_ELT (new_args, i) = TREE_VEC_ELT (args, i);
! }
!
! TREE_VEC_ELT (new_args,
! TREE_VEC_LENGTH (new_args) - 1) = extra_args;
!
! return new_args;
! }
!
/* We've got a template header coming up; push to a new level for storing
the parms. */
*************** tree
*** 216,222 ****
current_template_args ()
{
tree header = current_template_parms;
! tree args = NULL_TREE;
while (header)
{
tree a = copy_node (TREE_VALUE (header));
--- 360,369 ----
current_template_args ()
{
tree header = current_template_parms;
! int length = list_length (header);
! tree args = make_tree_vec (length);
! int l = length;
!
while (header)
{
tree a = copy_node (TREE_VALUE (header));
*************** current_template_args ()
*** 224,243 ****
TREE_TYPE (a) = NULL_TREE;
while (i--)
{
! tree t = TREE_VALUE (TREE_VEC_ELT (a, i));
! if (TREE_CODE (t) == TYPE_DECL)
! t = TREE_TYPE (t);
! else
! t = DECL_INITIAL (t);
TREE_VEC_ELT (a, i) = t;
}
! args = tree_cons (TREE_PURPOSE (header), a, args);
header = TREE_CHAIN (header);
}
- args = nreverse (args);
-
- /* FIXME Remove this when we support member templates. */
- args = TREE_VALUE (args);
return args;
}
--- 371,397 ----
TREE_TYPE (a) = NULL_TREE;
while (i--)
{
! tree t = TREE_VEC_ELT (a, i);
!
! /* t will be a list if we are called from withing a
! begin/end_template_parm_list pair, but a vector directly
! if withing a begin/end_member_template_processing pair.
! */
! if (TREE_CODE (t) == TREE_LIST)
! {
! t = TREE_VALUE (t);
!
! if (TREE_CODE (t) == TYPE_DECL)
! t = TREE_TYPE (t);
! else
! t = DECL_INITIAL (t);
! }
!
TREE_VEC_ELT (a, i) = t;
}
! TREE_VEC_ELT (args, --l) = a;
header = TREE_CHAIN (header);
}
return args;
}
*************** push_template_decl (decl)
*** 290,301 ****
if (! ctx || TYPE_BEING_DEFINED (ctx))
{
tmpl = build_lang_decl (TEMPLATE_DECL, DECL_NAME (decl), NULL_TREE);
! DECL_TEMPLATE_PARMS (tmpl) = TREE_VALUE (current_template_parms);
DECL_CONTEXT (tmpl) = DECL_CONTEXT (decl);
}
else
{
tree t;
if (CLASSTYPE_TEMPLATE_INSTANTIATION (ctx))
cp_error ("must specialize `%#T' before defining member `%#D'",
--- 444,458 ----
if (! ctx || TYPE_BEING_DEFINED (ctx))
{
tmpl = build_lang_decl (TEMPLATE_DECL, DECL_NAME (decl), NULL_TREE);
! DECL_TEMPLATE_PARMS (tmpl) = current_template_parms;
DECL_CONTEXT (tmpl) = DECL_CONTEXT (decl);
+ if (DECL_LANG_SPECIFIC (decl))
+ DECL_CLASS_CONTEXT (tmpl) = DECL_CLASS_CONTEXT (decl);
}
else
{
tree t;
+ tree a;
if (CLASSTYPE_TEMPLATE_INSTANTIATION (ctx))
cp_error ("must specialize `%#T' before defining member `%#D'",
*************** push_template_decl (decl)
*** 309,327 ****
}
else
tmpl = DECL_TI_TEMPLATE (decl);
if (CLASSTYPE_TEMPLATE_SPECIALIZATION (ctx))
! t = TREE_VALUE (CLASSTYPE_TI_SPEC_INFO (ctx));
! else
! t = DECL_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (ctx));
! if (TREE_VEC_LENGTH (t) != TREE_VEC_LENGTH (args))
{
cp_error ("got %d template parameters for `%#D'",
! TREE_VEC_LENGTH (args), decl);
cp_error (" but `%#T' has %d", ctx, TREE_VEC_LENGTH (t));
}
}
DECL_TEMPLATE_RESULT (tmpl) = decl;
TREE_TYPE (tmpl) = TREE_TYPE (decl);
--- 466,519 ----
}
else
tmpl = DECL_TI_TEMPLATE (decl);
+
+ if (is_member_template (tmpl))
+ {
+ a = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1);
+ t = DECL_INNERMOST_TEMPLATE_PARMS (DECL_TI_TEMPLATE (decl));
+ if (TREE_VEC_LENGTH (t)
+ != TREE_VEC_LENGTH (a))
+ {
+ cp_error ("got %d template parameters for `%#D'",
+ TREE_VEC_LENGTH (a), decl);
+ cp_error (" but %d required", TREE_VEC_LENGTH (t));
+ }
+ if (TREE_VEC_LENGTH (args) > 1)
+ /* Get the template parameters for the enclosing template
+ class. */
+ a = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 2);
+ else
+ a = NULL_TREE;
+ }
+ else
+ a = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1);
+
+ t = NULL_TREE;
if (CLASSTYPE_TEMPLATE_SPECIALIZATION (ctx))
! {
! /* When processing an inline member template of a
! specialized class, there is no CLASSTYPE_TI_SPEC_INFO. */
! if (CLASSTYPE_TI_SPEC_INFO (ctx))
! t = TREE_VALUE (CLASSTYPE_TI_SPEC_INFO (ctx));
! }
! else if (CLASSTYPE_TEMPLATE_INFO (ctx))
! t = DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (ctx));
!
! /* There should be template arguments if and only if there is a
! template class. */
! my_friendly_assert((a != NULL_TREE) == (t != NULL_TREE), 0);
! if (t != NULL_TREE
! && TREE_VEC_LENGTH (t) != TREE_VEC_LENGTH (a))
{
cp_error ("got %d template parameters for `%#D'",
! TREE_VEC_LENGTH (a), decl);
cp_error (" but `%#T' has %d", ctx, TREE_VEC_LENGTH (t));
}
}
+ /* Get the innermost set of template arguments. */
+ args = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1);
DECL_TEMPLATE_RESULT (tmpl) = decl;
TREE_TYPE (tmpl) = TREE_TYPE (decl);
*************** push_template_decl (decl)
*** 330,336 ****
tmpl = pushdecl_top_level (tmpl);
if (primary)
! TREE_TYPE (DECL_TEMPLATE_PARMS (tmpl)) = tmpl;
info = perm_tree_cons (tmpl, args, NULL_TREE);
--- 522,528 ----
tmpl = pushdecl_top_level (tmpl);
if (primary)
! TREE_TYPE (DECL_INNERMOST_TEMPLATE_PARMS (tmpl)) = tmpl;
info = perm_tree_cons (tmpl, args, NULL_TREE);
*************** push_template_decl (decl)
*** 345,352 ****
DECL_TEMPLATE_INFO (decl) = info;
}
- tree tsubst PROTO ((tree, tree*, int, tree));
-
/* Convert all template arguments to their appropriate types, and return
a vector containing the resulting values. If any error occurs, return
error_mark_node. */
--- 537,542 ----
*************** coerce_template_parms (parms, arglist, i
*** 401,410 ****
else if (TREE_CODE (TREE_VALUE (TREE_VEC_ELT (parms, i)))
== TYPE_DECL)
arg = tsubst (TREE_PURPOSE (TREE_VEC_ELT (parms, i)),
! &TREE_VEC_ELT (vec, 0), i, in_decl);
else
arg = tsubst_expr (TREE_PURPOSE (TREE_VEC_ELT (parms, i)),
! &TREE_VEC_ELT (vec, 0), i, in_decl);
TREE_VEC_ELT (vec, i) = arg;
}
--- 591,600 ----
else if (TREE_CODE (TREE_VALUE (TREE_VEC_ELT (parms, i)))
== TYPE_DECL)
arg = tsubst (TREE_PURPOSE (TREE_VEC_ELT (parms, i)),
! vec, i, in_decl);
else
arg = tsubst_expr (TREE_PURPOSE (TREE_VEC_ELT (parms, i)),
! vec, i, in_decl);
TREE_VEC_ELT (vec, i) = arg;
}
*************** coerce_template_parms (parms, arglist, i
*** 460,466 ****
}
else
{
! tree t = tsubst (TREE_TYPE (parm), &TREE_VEC_ELT (vec, 0),
TREE_VEC_LENGTH (vec), in_decl);
if (processing_template_decl)
val = arg;
--- 650,656 ----
}
else
{
! tree t = tsubst (TREE_TYPE (parm), vec,
TREE_VEC_LENGTH (vec), in_decl);
if (processing_template_decl)
val = arg;
*************** classtype_mangled_name (t)
*** 656,662 ****
tree name = DECL_NAME (CLASSTYPE_TI_TEMPLATE (t));
char *mangled_name = mangle_class_name_for_template
(IDENTIFIER_POINTER (name),
! DECL_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (t)),
CLASSTYPE_TI_ARGS (t));
tree id = get_identifier (mangled_name);
IDENTIFIER_TEMPLATE (id) = name;
--- 846,852 ----
tree name = DECL_NAME (CLASSTYPE_TI_TEMPLATE (t));
char *mangled_name = mangle_class_name_for_template
(IDENTIFIER_POINTER (name),
! DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (t)),
CLASSTYPE_TI_ARGS (t));
tree id = get_identifier (mangled_name);
IDENTIFIER_TEMPLATE (id) = name;
*************** lookup_template_class (d1, arglist, in_d
*** 740,746 ****
if (PRIMARY_TEMPLATE_P (template))
{
! parmlist = DECL_TEMPLATE_PARMS (template);
arglist = coerce_template_parms (parmlist, arglist, template);
if (arglist == error_mark_node)
--- 930,936 ----
if (PRIMARY_TEMPLATE_P (template))
{
! parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
arglist = coerce_template_parms (parmlist, arglist, template);
if (arglist == error_mark_node)
*************** instantiate_class_template (type)
*** 1209,1215 ****
tree elt;
TREE_VEC_ELT (bases, i) = elt
! = tsubst (TREE_VEC_ELT (pbases, i), &TREE_VEC_ELT (args, 0),
TREE_VEC_LENGTH (args), NULL_TREE);
BINFO_INHERITANCE_CHAIN (elt) = binfo;
--- 1399,1405 ----
tree elt;
TREE_VEC_ELT (bases, i) = elt
! = tsubst (TREE_VEC_ELT (pbases, i), args,
TREE_VEC_LENGTH (args), NULL_TREE);
BINFO_INHERITANCE_CHAIN (elt) = binfo;
*************** instantiate_class_template (type)
*** 1241,1247 ****
/* These will add themselves to CLASSTYPE_TAGS for the new type. */
if (TREE_CODE (tag) == ENUMERAL_TYPE)
{
! tree e, newtag = tsubst_enum (tag, &TREE_VEC_ELT (args, 0),
TREE_VEC_LENGTH (args));
*field_chain = grok_enum_decls (newtag, NULL_TREE);
--- 1431,1437 ----
/* These will add themselves to CLASSTYPE_TAGS for the new type. */
if (TREE_CODE (tag) == ENUMERAL_TYPE)
{
! tree e, newtag = tsubst_enum (tag, args,
TREE_VEC_LENGTH (args));
*field_chain = grok_enum_decls (newtag, NULL_TREE);
*************** instantiate_class_template (type)
*** 1252,1258 ****
}
}
else
! tsubst (tag, &TREE_VEC_ELT (args, 0),
TREE_VEC_LENGTH (args), NULL_TREE);
}
--- 1442,1448 ----
}
}
else
! tsubst (tag, args,
TREE_VEC_LENGTH (args), NULL_TREE);
}
*************** instantiate_class_template (type)
*** 1260,1266 ****
for (t = TYPE_FIELDS (pattern); t; t = TREE_CHAIN (t))
if (TREE_CODE (t) != CONST_DECL)
{
! tree r = tsubst (t, &TREE_VEC_ELT (args, 0),
TREE_VEC_LENGTH (args), NULL_TREE);
if (TREE_CODE (r) == VAR_DECL)
{
--- 1450,1456 ----
for (t = TYPE_FIELDS (pattern); t; t = TREE_CHAIN (t))
if (TREE_CODE (t) != CONST_DECL)
{
! tree r = tsubst (t, args,
TREE_VEC_LENGTH (args), NULL_TREE);
if (TREE_CODE (r) == VAR_DECL)
{
*************** instantiate_class_template (type)
*** 1288,1305 ****
DECL_FRIENDLIST (TYPE_MAIN_DECL (type))
= tsubst (DECL_FRIENDLIST (TYPE_MAIN_DECL (pattern)),
! &TREE_VEC_ELT (args, 0), TREE_VEC_LENGTH (args), NULL_TREE);
{
tree d = CLASSTYPE_FRIEND_CLASSES (type)
! = tsubst (CLASSTYPE_FRIEND_CLASSES (pattern), &TREE_VEC_ELT (args, 0),
TREE_VEC_LENGTH (args), NULL_TREE);
/* This does injection for friend classes. */
for (; d; d = TREE_CHAIN (d))
TREE_VALUE (d) = xref_tag_from_type (TREE_VALUE (d), NULL_TREE, 1);
! d = tsubst (DECL_TEMPLATE_INJECT (template), &TREE_VEC_ELT (args, 0),
TREE_VEC_LENGTH (args), NULL_TREE);
for (; d; d = TREE_CHAIN (d))
--- 1478,1495 ----
DECL_FRIENDLIST (TYPE_MAIN_DECL (type))
= tsubst (DECL_FRIENDLIST (TYPE_MAIN_DECL (pattern)),
! args, TREE_VEC_LENGTH (args), NULL_TREE);
{
tree d = CLASSTYPE_FRIEND_CLASSES (type)
! = tsubst (CLASSTYPE_FRIEND_CLASSES (pattern), args,
TREE_VEC_LENGTH (args), NULL_TREE);
/* This does injection for friend classes. */
for (; d; d = TREE_CHAIN (d))
TREE_VALUE (d) = xref_tag_from_type (TREE_VALUE (d), NULL_TREE, 1);
! d = tsubst (DECL_TEMPLATE_INJECT (template), args,
TREE_VEC_LENGTH (args), NULL_TREE);
for (; d; d = TREE_CHAIN (d))
*************** lookup_nested_type_by_name (ctype, name)
*** 1382,1388 ****
tree
tsubst (t, args, nargs, in_decl)
! tree t, *args;
int nargs;
tree in_decl;
{
--- 1572,1578 ----
tree
tsubst (t, args, nargs, in_decl)
! tree t, args;
int nargs;
tree in_decl;
{
*************** tsubst (t, args, nargs, in_decl)
*** 1471,1485 ****
}
case TEMPLATE_TYPE_PARM:
{
! tree arg = args[TEMPLATE_TYPE_IDX (t)];
! return cp_build_type_variant
! (arg, TYPE_READONLY (arg) || TYPE_READONLY (t),
! TYPE_VOLATILE (arg) || TYPE_VOLATILE (t));
}
! case TEMPLATE_CONST_PARM:
! return args[TEMPLATE_CONST_IDX (t)];
case FUNCTION_DECL:
{
--- 1661,1769 ----
}
case TEMPLATE_TYPE_PARM:
+ case TEMPLATE_CONST_PARM:
{
! int idx;
! int level;
!
! if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
! {
! idx = TEMPLATE_TYPE_IDX (t);
! level = TEMPLATE_TYPE_LEVEL (t);
! }
! else
! {
! idx = TEMPLATE_CONST_IDX (t);
! level = TEMPLATE_CONST_LEVEL (t);
! }
!
! if (TREE_VEC_LENGTH (args) > 0)
! {
! tree arg = NULL_TREE;
!
! if (TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
! {
! if (TREE_VEC_LENGTH (args) >= level - 1)
! arg =
! TREE_VEC_ELT
! (TREE_VEC_ELT (args, level - 1), idx);
! }
! else if (level == 1)
! arg = TREE_VEC_ELT (args, idx);
!
! if (arg != NULL_TREE)
! {
! if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
! return cp_build_type_variant
! (arg, TYPE_READONLY (arg) || TYPE_READONLY (t),
! TYPE_VOLATILE (arg) || TYPE_VOLATILE (t));
! else
! return arg;
! }
! }
!
! /* If we get here, we must have been looking at a parm for a
! more deeply nested template. */
! my_friendly_assert((TREE_CODE (t) == TEMPLATE_CONST_PARM
! && TEMPLATE_CONST_LEVEL (t) > 1)
! || (TREE_CODE (t) == TEMPLATE_TYPE_PARM
! && TEMPLATE_TYPE_LEVEL (t) > 1),
! 0);
! return t;
}
! case TEMPLATE_DECL:
! {
! /* We can get here when processing a member template function
! of a template class. */
! tree tmpl;
! tree decl = DECL_TEMPLATE_RESULT (t);
! tree new_decl;
! tree parms;
! int i;
!
! /* We might already have an instance of this template. */
! tree instances = DECL_TEMPLATE_INSTANTIATIONS (t);
! tree ctx = tsubst (DECL_CLASS_CONTEXT (t), args, nargs, in_decl);
!
! for (; instances; instances = TREE_CHAIN (instances))
! if (DECL_CLASS_CONTEXT (TREE_VALUE (instances)) == ctx)
! return TREE_VALUE (instances);
!
! /* Make a new template decl. It will be similar to the
! original, but will record the current template arguments.
! We also create a new function declaration, which is just
! like the old one, but points to this new template, rather
! than the old one. */
! tmpl = copy_node (t);
! copy_lang_decl (tmpl);
! my_friendly_assert (DECL_LANG_SPECIFIC (tmpl) != 0, 0);
! DECL_CHAIN (tmpl) = NULL_TREE;
! TREE_CHAIN (tmpl) = NULL_TREE;
! DECL_TEMPLATE_INFO (tmpl) = build_tree_list (t, args);
! new_decl = tsubst (decl, args, nargs, in_decl);
! DECL_RESULT (tmpl) = new_decl;
! DECL_INITIAL (new_decl) = DECL_INITIAL (decl);
! DECL_TI_TEMPLATE (new_decl) = tmpl;
! TREE_TYPE (tmpl) = TREE_TYPE (new_decl);
! DECL_TEMPLATE_INSTANTIATIONS(tmpl) = NULL_TREE;
!
! /* The template parameters for this new template are all the
! template parameters for the old template, except the
! outermost level of parameters. */
! DECL_TEMPLATE_PARMS (tmpl) =
! copy_node (DECL_TEMPLATE_PARMS (tmpl));
! for (parms = DECL_TEMPLATE_PARMS (tmpl);
! TREE_CHAIN (parms) != NULL_TREE;
! parms = TREE_CHAIN (parms))
! TREE_CHAIN (parms) = copy_node (TREE_CHAIN (parms));
!
! /* Record this partial instantiation. */
! DECL_TEMPLATE_INSTANTIATIONS (t) =
! perm_tree_cons (NULL_TREE, tmpl,
! DECL_TEMPLATE_INSTANTIATIONS (t));
! return tmpl;
! }
case FUNCTION_DECL:
{
*************** tsubst (t, args, nargs, in_decl)
*** 1622,1629 ****
{
tree tmpl = DECL_TI_TEMPLATE (t);
tree *declsp = &DECL_TEMPLATE_INSTANTIATIONS (tmpl);
! tree argvec = tsubst (TREE_VALUE (DECL_TEMPLATE_INFO (t)),
! args, nargs, in_decl);
DECL_TEMPLATE_INFO (r) = perm_tree_cons (tmpl, argvec, NULL_TREE);
*declsp = perm_tree_cons (argvec, r, *declsp);
--- 1906,1923 ----
{
tree tmpl = DECL_TI_TEMPLATE (t);
tree *declsp = &DECL_TEMPLATE_INSTANTIATIONS (tmpl);
! tree argvec;
!
! if (DECL_TEMPLATE_INFO (tmpl) == NULL_TREE
! || DECL_TI_ARGS (tmpl) == NULL_TREE)
! argvec = tsubst (TREE_VALUE (DECL_TEMPLATE_INFO (t)),
! args, nargs, in_decl);
! else
! argvec =
! add_to_template_args
! (DECL_TI_ARGS (tmpl),
! tsubst (TREE_VALUE (DECL_TEMPLATE_INFO (t)),
! args, nargs, in_decl));
DECL_TEMPLATE_INFO (r) = perm_tree_cons (tmpl, argvec, NULL_TREE);
*declsp = perm_tree_cons (argvec, r, *declsp);
*************** do_poplevel ()
*** 2013,2019 ****
tree
tsubst_copy (t, args, nargs, in_decl)
! tree t, *args;
int nargs;
tree in_decl;
{
--- 2307,2313 ----
tree
tsubst_copy (t, args, nargs, in_decl)
! tree t, args;
int nargs;
tree in_decl;
{
*************** tsubst_copy (t, args, nargs, in_decl)
*** 2048,2053 ****
--- 2342,2353 ----
mark_used (t);
return t;
+ case TEMPLATE_DECL:
+ if (is_member_template (t))
+ return tsubst (t, args, nargs, in_decl);
+ else
+ return t;
+
#if 0
case IDENTIFIER_NODE:
return do_identifier (t, 0);
*************** tsubst_copy (t, args, nargs, in_decl)
*** 2241,2247 ****
tree
tsubst_expr (t, args, nargs, in_decl)
! tree t, *args;
int nargs;
tree in_decl;
{
--- 2541,2547 ----
tree
tsubst_expr (t, args, nargs, in_decl)
! tree t, args;
int nargs;
tree in_decl;
{
*************** tsubst_expr (t, args, nargs, in_decl)
*** 2543,2549 ****
tree
instantiate_template (tmpl, targ_ptr)
! tree tmpl, *targ_ptr;
{
tree fndecl;
int i, len;
--- 2843,2849 ----
tree
instantiate_template (tmpl, targ_ptr)
! tree tmpl, targ_ptr;
{
tree fndecl;
int i, len;
*************** instantiate_template (tmpl, targ_ptr)
*** 2555,2566 ****
function_maybepermanent_obstack = &permanent_obstack;
my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 283);
! len = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (tmpl));
i = len;
while (i--)
{
! tree t = targ_ptr [i];
if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
{
tree nt = target_type (t);
--- 2855,2866 ----
function_maybepermanent_obstack = &permanent_obstack;
my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 283);
! len = DECL_NTPARMS (tmpl);
i = len;
while (i--)
{
! tree t = TREE_VEC_ELT (targ_ptr, i);
if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
{
tree nt = target_type (t);
*************** instantiate_template (tmpl, targ_ptr)
*** 2572,2580 ****
goto out;
}
}
! targ_ptr[i] = copy_to_permanent (t);
}
/* substitute template parameters */
fndecl = tsubst (DECL_RESULT (tmpl), targ_ptr, len, tmpl);
--- 2872,2883 ----
goto out;
}
}
! TREE_VEC_ELT (targ_ptr, i) = copy_to_permanent (t);
}
+ if (DECL_TEMPLATE_INFO (tmpl) && DECL_TI_ARGS (tmpl))
+ targ_ptr = add_to_template_args (DECL_TI_ARGS (tmpl), targ_ptr);
+
/* substitute template parameters */
fndecl = tsubst (DECL_RESULT (tmpl), targ_ptr, len, tmpl);
*************** overload_template_name (type)
*** 2606,2611 ****
--- 2909,2952 ----
pushdecl_class_level (decl);
}
+
+ /* Like type_unfication but designed specially to handle conversion
+ operators. */
+
+ int
+ fn_type_unification (fn, targs, args, return_type, strict)
+ tree fn, targs, args, return_type;
+ int strict;
+ {
+ int i, dummy = 0;
+ tree fn_arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
+ tree decl_arg_types = args;
+
+ my_friendly_assert (TREE_CODE (fn) == TEMPLATE_DECL, 0);
+
+ if (IDENTIFIER_TYPENAME_P (DECL_NAME (fn)))
+ {
+ /* This is a template conversion operator. Use the return types
+ as well as the argument types. */
+ fn_arg_types = tree_cons (NULL_TREE,
+ TREE_TYPE (TREE_TYPE (fn)),
+ fn_arg_types);
+ decl_arg_types = tree_cons (NULL_TREE,
+ return_type,
+ decl_arg_types);
+ }
+
+ i = type_unification (DECL_INNERMOST_TEMPLATE_PARMS (fn),
+ &TREE_VEC_ELT (targs, 0),
+ fn_arg_types,
+ decl_arg_types,
+ &dummy, 0, strict);
+
+
+ return i;
+ }
+
+
/* Type unification.
We have a function template signature with one or more references to
*************** type_unification (tparms, targs, parms,
*** 2718,2727 ****
/* Have to back unify here */
arg = TREE_VALUE (arg);
nsubsts = 0;
! ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (arg));
targs = (tree *) alloca (sizeof (tree) * ntparms);
parm = tree_cons (NULL_TREE, parm, NULL_TREE);
! return type_unification (DECL_TEMPLATE_PARMS (arg), targs,
TYPE_ARG_TYPES (TREE_TYPE (arg)),
parm, &nsubsts, 0, strict);
}
--- 3059,3069 ----
/* Have to back unify here */
arg = TREE_VALUE (arg);
nsubsts = 0;
! ntparms = DECL_NTPARMS (arg);
targs = (tree *) alloca (sizeof (tree) * ntparms);
parm = tree_cons (NULL_TREE, parm, NULL_TREE);
! return type_unification (DECL_INNERMOST_TEMPLATE_PARMS (arg),
! targs,
TYPE_ARG_TYPES (TREE_TYPE (arg)),
parm, &nsubsts, 0, strict);
}
*************** int
*** 3022,3041 ****
more_specialized (pat1, pat2)
tree pat1, pat2;
{
! tree *targs;
int winner = 0;
targs = get_bindings (pat1, pat2);
if (targs)
{
- free (targs);
--winner;
}
targs = get_bindings (pat2, pat1);
if (targs)
{
- free (targs);
++winner;
}
--- 3364,3381 ----
more_specialized (pat1, pat2)
tree pat1, pat2;
{
! tree targs;
int winner = 0;
targs = get_bindings (pat1, pat2);
if (targs)
{
--winner;
}
targs = get_bindings (pat2, pat1);
if (targs)
{
++winner;
}
*************** more_specialized_class (pat1, pat2)
*** 3071,3090 ****
/* Return the template arguments that will produce the function signature
DECL from the function template FN. */
! tree *
get_bindings (fn, decl)
tree fn, decl;
{
! int ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (fn));
! tree *targs = (tree *) malloc (sizeof (tree) * ntparms);
! int i, dummy = 0;
! i = type_unification (DECL_TEMPLATE_PARMS (fn), targs,
! TYPE_ARG_TYPES (TREE_TYPE (fn)),
! TYPE_ARG_TYPES (TREE_TYPE (decl)),
! &dummy, 0, 1);
if (i == 0)
return targs;
- free (targs);
return 0;
}
--- 3411,3431 ----
/* Return the template arguments that will produce the function signature
DECL from the function template FN. */
! tree
get_bindings (fn, decl)
tree fn, decl;
{
! int ntparms = DECL_NTPARMS (fn);
! tree targs = make_tree_vec (ntparms);
! int i;
!
! i = fn_type_unification (fn, targs,
! TYPE_ARG_TYPES (TREE_TYPE (decl)),
! TREE_TYPE (TREE_TYPE (decl)),
! 1);
!
if (i == 0)
return targs;
return 0;
}
*************** tree
*** 3122,3128 ****
most_specialized (fns, decl)
tree fns, decl;
{
! tree fn, champ, *args, *p;
int fate;
for (p = &fns; *p; )
--- 3463,3469 ----
most_specialized (fns, decl)
tree fns, decl;
{
! tree fn, champ, args, *p;
int fate;
for (p = &fns; *p; )
*************** most_specialized (fns, decl)
*** 3130,3136 ****
args = get_bindings (TREE_VALUE (*p), decl);
if (args)
{
- free (args);
p = &TREE_CHAIN (*p);
}
else
--- 3471,3476 ----
*************** do_decl_instantiation (declspecs, declar
*** 3234,3239 ****
--- 3574,3580 ----
tree fn;
tree result = NULL_TREE;
int extern_p = 0;
+ tree templates = NULL_TREE;
if (! DECL_LANG_SPECIFIC (decl))
{
*************** do_decl_instantiation (declspecs, declar
*** 3261,3270 ****
fn = IDENTIFIER_GLOBAL_VALUE (name),
fn && DECL_TEMPLATE_INSTANTIATION (fn))
result = fn;
}
else if (name = DECL_NAME (decl), fn = IDENTIFIER_GLOBAL_VALUE (name), fn)
{
- tree templates = NULL_TREE;
for (fn = get_first_fn (fn); fn; fn = DECL_CHAIN (fn))
if (decls_match (fn, decl)
&& DECL_DEFER_OUTPUT (fn))
--- 3602,3640 ----
fn = IDENTIFIER_GLOBAL_VALUE (name),
fn && DECL_TEMPLATE_INSTANTIATION (fn))
result = fn;
+ else
+ {
+ /* Maybe this is an instantiation of a member template
+ function. */
+ name = DECL_NAME (decl);
+ fn = IDENTIFIER_CLASS_VALUE (name);
+
+ if (! fn && IDENTIFIER_TYPENAME_P (name))
+ {
+ /* If we haven't found it, it could be a member template
+ conversion operator. */
+ tree ctype = DECL_CONTEXT (decl);
+
+ fn = lookup_fnfields (TYPE_BINFO (ctype), name, 1);
+
+ if (fn)
+ fn = TREE_VALUE (fn);
+ }
+
+ for (; fn; fn = DECL_CHAIN (fn))
+ if (decls_match (fn, decl)
+ && DECL_DEFER_OUTPUT (fn))
+ {
+ result = fn;
+ break;
+ }
+ else if (TREE_CODE (fn) == TEMPLATE_DECL)
+ templates = decl_tree_cons (NULL_TREE, fn,
+ templates);
+ }
}
else if (name = DECL_NAME (decl), fn = IDENTIFIER_GLOBAL_VALUE (name), fn)
{
for (fn = get_first_fn (fn); fn; fn = DECL_CHAIN (fn))
if (decls_match (fn, decl)
&& DECL_DEFER_OUTPUT (fn))
*************** do_decl_instantiation (declspecs, declar
*** 3274,3303 ****
}
else if (TREE_CODE (fn) == TEMPLATE_DECL)
templates = decl_tree_cons (NULL_TREE, fn, templates);
! if (! result)
{
! tree *args;
! result = most_specialized (templates, decl);
! if (result == error_mark_node)
! {
! char *str = "candidates are:";
! cp_error ("ambiguous template instantiation for `%D' requested", decl);
! for (fn = templates; fn; fn = TREE_CHAIN (fn))
! {
! cp_error_at ("%s %+#D", str, TREE_VALUE (fn));
! str = " ";
! }
! return;
! }
! else if (result)
{
! args = get_bindings (result, decl);
! result = instantiate_template (result, args);
! free (args);
}
}
}
if (! result)
{
cp_error ("no matching template for `%D' found", decl);
--- 3644,3673 ----
}
else if (TREE_CODE (fn) == TEMPLATE_DECL)
templates = decl_tree_cons (NULL_TREE, fn, templates);
+ }
! if (templates && !result)
! {
! tree args;
! result = most_specialized (templates, decl);
! if (result == error_mark_node)
{
! char *str = "candidates are:";
! cp_error ("ambiguous template instantiation for `%D' requested", decl);
! for (fn = templates; fn; fn = TREE_CHAIN (fn))
{
! cp_error_at ("%s %+#D", str, TREE_VALUE (fn));
! str = " ";
}
+ return;
+ }
+ else if (result)
+ {
+ args = get_bindings (result, decl);
+ result = instantiate_template (result, args);
}
}
+
if (! result)
{
cp_error ("no matching template for `%D' found", decl);
*************** instantiate_decl (d)
*** 3477,3483 ****
{
pushclass (DECL_CONTEXT (d), 2);
DECL_INITIAL (d) = tsubst_expr
! (DECL_INITIAL (pattern), &TREE_VEC_ELT (args, 0),
TREE_VEC_LENGTH (args), tmpl);
popclass (1);
}
--- 3847,3853 ----
{
pushclass (DECL_CONTEXT (d), 2);
DECL_INITIAL (d) = tsubst_expr
! (DECL_INITIAL (pattern), args,
TREE_VEC_LENGTH (args), tmpl);
popclass (1);
}
*************** instantiate_decl (d)
*** 3527,3533 ****
/* Trick tsubst into giving us a new decl in case the template changed. */
save_ti = DECL_TEMPLATE_INFO (pattern);
DECL_TEMPLATE_INFO (pattern) = NULL_TREE;
! td = tsubst (pattern, &TREE_VEC_ELT (args, 0), TREE_VEC_LENGTH (args), tmpl);
DECL_TEMPLATE_INFO (pattern) = save_ti;
/* And set up DECL_INITIAL, since tsubst doesn't. */
--- 3897,3903 ----
/* Trick tsubst into giving us a new decl in case the template changed. */
save_ti = DECL_TEMPLATE_INFO (pattern);
DECL_TEMPLATE_INFO (pattern) = NULL_TREE;
! td = tsubst (pattern, args, TREE_VEC_LENGTH (args), tmpl);
DECL_TEMPLATE_INFO (pattern) = save_ti;
/* And set up DECL_INITIAL, since tsubst doesn't. */
*************** instantiate_decl (d)
*** 3535,3541 ****
{
pushclass (DECL_CONTEXT (d), 2);
DECL_INITIAL (td) = tsubst_expr
! (DECL_INITIAL (pattern), &TREE_VEC_ELT (args, 0),
TREE_VEC_LENGTH (args), tmpl);
popclass (1);
}
--- 3905,3911 ----
{
pushclass (DECL_CONTEXT (d), 2);
DECL_INITIAL (td) = tsubst_expr
! (DECL_INITIAL (pattern), args,
TREE_VEC_LENGTH (args), tmpl);
popclass (1);
}
*************** instantiate_decl (d)
*** 3570,3576 ****
{
store_return_init
(TREE_OPERAND (t, 0),
! tsubst_expr (TREE_OPERAND (t, 1), &TREE_VEC_ELT (args, 0),
TREE_VEC_LENGTH (args), tmpl));
t = TREE_CHAIN (t);
}
--- 3940,3946 ----
{
store_return_init
(TREE_OPERAND (t, 0),
! tsubst_expr (TREE_OPERAND (t, 1), args,
TREE_VEC_LENGTH (args), tmpl));
t = TREE_CHAIN (t);
}
*************** instantiate_decl (d)
*** 3591,3597 ****
keep_next_level ();
my_friendly_assert (TREE_CODE (t) == COMPOUND_STMT, 42);
! tsubst_expr (t, &TREE_VEC_ELT (args, 0),
TREE_VEC_LENGTH (args), tmpl);
finish_function (lineno, 0, nested);
--- 3961,3967 ----
keep_next_level ();
my_friendly_assert (TREE_CODE (t) == COMPOUND_STMT, 42);
! tsubst_expr (t, args,
TREE_VEC_LENGTH (args), tmpl);
finish_function (lineno, 0, nested);
*************** tsubst_chain (t, argvec)
*** 3613,3625 ****
{
if (t)
{
! tree first = tsubst (t, &TREE_VEC_ELT (argvec, 0),
TREE_VEC_LENGTH (argvec), NULL_TREE);
tree last = first;
for (t = TREE_CHAIN (t); t; t = TREE_CHAIN (t))
{
! tree x = tsubst (t, &TREE_VEC_ELT (argvec, 0),
TREE_VEC_LENGTH (argvec), NULL_TREE);
TREE_CHAIN (last) = x;
last = x;
--- 3983,3995 ----
{
if (t)
{
! tree first = tsubst (t, argvec,
TREE_VEC_LENGTH (argvec), NULL_TREE);
tree last = first;
for (t = TREE_CHAIN (t); t; t = TREE_CHAIN (t))
{
! tree x = tsubst (t, argvec,
TREE_VEC_LENGTH (argvec), NULL_TREE);
TREE_CHAIN (last) = x;
last = x;
*************** tsubst_expr_values (t, argvec)
*** 3639,3647 ****
for (; t; t = TREE_CHAIN (t))
{
! tree pur = tsubst_copy (TREE_PURPOSE (t), &TREE_VEC_ELT (argvec, 0),
TREE_VEC_LENGTH (argvec), NULL_TREE);
! tree val = tsubst_expr (TREE_VALUE (t), &TREE_VEC_ELT (argvec, 0),
TREE_VEC_LENGTH (argvec), NULL_TREE);
*p = build_tree_list (pur, val);
p = &TREE_CHAIN (*p);
--- 4009,4017 ----
for (; t; t = TREE_CHAIN (t))
{
! tree pur = tsubst_copy (TREE_PURPOSE (t), argvec,
TREE_VEC_LENGTH (argvec), NULL_TREE);
! tree val = tsubst_expr (TREE_VALUE (t), argvec,
TREE_VEC_LENGTH (argvec), NULL_TREE);
*p = build_tree_list (pur, val);
p = &TREE_CHAIN (*p);
*************** add_maybe_template (d, fns)
*** 3691,3697 ****
static tree
tsubst_enum (tag, args, nargs)
! tree tag, *args;
int nargs;
{
tree newtag = start_enum (TYPE_IDENTIFIER (tag));
--- 4061,4067 ----
static tree
tsubst_enum (tag, args, nargs)
! tree tag, args;
int nargs;
{
tree newtag = start_enum (TYPE_IDENTIFIER (tag));
Index: gcc/cp/search.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/search.c,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -c -p -r1.1.1.1 -r1.3
*** search.c 1997/08/26 06:23:56 1.1.1.1
--- search.c 1997/09/04 20:27:32 1.3
*************** lookup_fnfields_1 (type, name)
*** 1637,1642 ****
--- 1637,1659 ----
if (DECL_NAME (*methods) == name)
break;
}
+
+ /* If we didn't find it, it might have been a template
+ conversion operator. (Note that we don't look for this case
+ above so that we will always find specializations first.) */
+ if (methods == end
+ && IDENTIFIER_TYPENAME_P (name))
+ {
+ methods = &TREE_VEC_ELT (method_vec, 0) + 1;
+
+ while (++methods != end)
+ {
+ if (TREE_CODE (*methods) == TEMPLATE_DECL
+ && IDENTIFIER_TYPENAME_P (DECL_NAME (*methods)))
+ break;
+ }
+ }
+
if (methods != end)
return methods - &TREE_VEC_ELT (method_vec, 0);
}
Index: gcc/cp/tree.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/tree.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -c -p -r1.1.1.1 -r1.2
*** tree.c 1997/08/26 06:23:57 1.1.1.1
--- tree.c 1997/09/02 06:38:44 1.2
*************** cp_tree_equal (t1, t2)
*** 2005,2011 ****
return 0;
case TEMPLATE_CONST_PARM:
! return TEMPLATE_CONST_IDX (t1) == TEMPLATE_CONST_IDX (t2);
case SIZEOF_EXPR:
if (TREE_CODE (TREE_OPERAND (t1, 0)) != TREE_CODE (TREE_OPERAND (t2, 0)))
--- 2005,2012 ----
return 0;
case TEMPLATE_CONST_PARM:
! return TEMPLATE_CONST_IDX (t1) == TEMPLATE_CONST_IDX (t2)
! && TEMPLATE_CONST_LEVEL (t1) == TEMPLATE_CONST_LEVEL (t2);
case SIZEOF_EXPR:
if (TREE_CODE (TREE_OPERAND (t1, 0)) != TREE_CODE (TREE_OPERAND (t2, 0)))
Index: gcc/cp/typeck.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/typeck.c,v
retrieving revision 1.1.1.3
retrieving revision 1.3
diff -c -p -r1.1.1.3 -r1.3
*** typeck.c 1997/09/04 18:09:48 1.1.1.3
--- typeck.c 1997/09/04 20:27:32 1.3
*************** comptypes (type1, type2, strict)
*** 832,838 ****
break;
case TEMPLATE_TYPE_PARM:
! return TEMPLATE_TYPE_IDX (t1) == TEMPLATE_TYPE_IDX (t2);
case TYPENAME_TYPE:
if (TYPE_IDENTIFIER (t1) != TYPE_IDENTIFIER (t2))
--- 832,839 ----
break;
case TEMPLATE_TYPE_PARM:
! return TEMPLATE_TYPE_IDX (t1) == TEMPLATE_TYPE_IDX (t2)
! && TEMPLATE_TYPE_LEVEL (t1) == TEMPLATE_TYPE_LEVEL (t2);
case TYPENAME_TYPE:
if (TYPE_IDENTIFIER (t1) != TYPE_IDENTIFIER (t2))
*************** build_x_function_call (function, params,
*** 2296,2302 ****
{
tree basetype = NULL_TREE;
! if (TREE_CODE (function) == FUNCTION_DECL)
{
basetype = DECL_CLASS_CONTEXT (function);
--- 2297,2304 ----
{
tree basetype = NULL_TREE;
! if (TREE_CODE (function) == FUNCTION_DECL
! || DECL_FUNCTION_TEMPLATE_P (function))
{
basetype = DECL_CLASS_CONTEXT (function);
Index: libstdc++/std/bastring.h
===================================================================
RCS file: /home/mitchell/Repository/egcs/libstdc++/std/bastring.h,v
retrieving revision 1.1.1.2
retrieving revision 1.2
diff -c -p -r1.1.1.2 -r1.2
cvs diff: Diffing libstdc++/stl
Index: libstdc++/stl/ChangeLog
===================================================================
RCS file: /home/mitchell/Repository/egcs/libstdc++/stl/ChangeLog,v
retrieving revision 1.1.1.1
diff -c -p -r1.1.1.1 ChangeLog
*** ChangeLog 1997/08/26 06:24:11 1.1.1.1
--- ChangeLog 1997/09/03 21:23:31
***************
*** 1,3 ****
--- 1,7 ----
+ Wed Sep 3 14:23:12 1997 Mark Mitchell <mmitchell@usa.net>
+
+ * stl_config.h (__STL_MEMBER_TEMPLATES): Enable.
+
Tue Aug 5 17:06:01 1997 Jason Merrill <jason@yorick.cygnus.com>
* deque.h, function.h, hashtable.h, list.h, rope.h, ropeimpl.h,
Index: libstdc++/stl/stl_config.h
===================================================================
RCS file: /home/mitchell/Repository/egcs/libstdc++/stl/stl_config.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -c -p -r1.1.1.1 -r1.2
*** stl_config.h 1997/08/26 06:24:12 1.1.1.1
--- stl_config.h 1997/09/02 06:38:49 1.2
***************
*** 88,93 ****
--- 88,94 ----
# define __STL_NEED_EXPLICIT
# else
# define __STL_CLASS_PARTIAL_SPECIALIZATION
+ # define __STL_MEMBER_TEMPLATES
# endif
# ifdef __EXCEPTIONS
# define __STL_USE_EXCEPTIONS
More information about the Gcc
mailing list