Member Templates Patch
Mark Mitchell
mmitchell@usa.net
Mon Sep 8 02:20:00 GMT 1997
Below, I've enclosed a patch that fixes all of the member template
bugs reported by Todd and Oleg. Their test-cases have also exposed
some template bugs that are not specific to member templates; I'm
going to take a look at them, too. These are diffs against the 970907
snapshot.
(Jason, you'll note that I put the pushlevel()/poplevel() pair back in
begin_member_tempate_processing(), but for a different reason: more
than one member template might use the same template parameter names.)
Thanks,
--
Mark Mitchell mmitchell@usa.net
Stanford University http://www.stanford.edu
Mon Sep 8 01:21:43 1997 Mark Mitchell <mmitchell@usa.net>
* pt.c (begin_member_template_processing): Take a function as
argument, not a set of template arguments. Use the template
parameters, rather than the arguments. Handle non-type parameters
correctly. Push a binding level for the parameters so that multiple
member templates using the same parameter names can be declared.
(end_member_template_processing): Pop the binding level.
(push_template_decl): Mark member templates as static when
appropriate.
* lex.c (do_pending_inlines): Pass the function, not its template
arguments, to begin_member_template_processing.
(process_next_inline): Likewise.
(do_pending_defargs): Likewise.
* error.c (dump_expr): Obtain the correct declaration for a
TEMPLATE_CONST_PARM.
* call.c (add_template_conv_candidate): New function.
(build_object_call): Handle member templates, as done in the other
build_ functions.
Index: call.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/call.c,v
retrieving revision 1.1.1.5
diff -c -p -r1.1.1.5 call.c
*** call.c 1997/09/08 05:23:53 1.1.1.5
--- call.c 1997/09/08 08:23:27
*************** static struct z_candidate * splice_viabl
*** 78,83 ****
--- 78,85 ----
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_template_conv_candidate
+ PROTO((struct z_candidate *, tree, tree, tree, tree));
static struct z_candidate * add_builtin_candidates
PROTO((struct z_candidate *, enum tree_code, enum tree_code,
tree, tree *, int));
*************** add_template_candidate (candidates, tmpl
*** 4170,4175 ****
--- 4172,4204 ----
return cand;
}
+
+ static struct z_candidate *
+ add_template_conv_candidate (candidates, tmpl, obj, arglist, return_type)
+ struct z_candidate *candidates;
+ tree tmpl, obj, arglist, return_type;
+ {
+ 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;
+
+ fn = instantiate_template (tmpl, targs);
+ if (fn == error_mark_node)
+ return candidates;
+
+ cand = add_conv_candidate (candidates, fn, obj, arglist);
+ cand->template = DECL_TEMPLATE_INFO (fn);
+ return cand;
+ }
+
+
static int
any_viable (cands)
struct z_candidate *cands;
*************** build_object_call (obj, args)
*** 4508,4513 ****
--- 4537,4543 ----
struct z_candidate *candidates = 0, *cand;
tree fns, convs, mem_args;
tree type = TREE_TYPE (obj);
+ tree templates = NULL_TREE;
fns = lookup_fnfields (TYPE_BINFO (type), ansi_opname [CALL_EXPR], 0);
*************** build_object_call (obj, args)
*** 4523,4531 ****
for (; fn; fn = DECL_CHAIN (fn))
{
! candidates = add_function_candidate
! (candidates, fn, mem_args, LOOKUP_NORMAL);
! candidates->basetype_path = TREE_PURPOSE (fns);
}
}
--- 4553,4571 ----
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,
! mem_args, NULL_TREE,
! LOOKUP_NORMAL);
! }
! else
! candidates = add_function_candidate
! (candidates, fn, mem_args, LOOKUP_NORMAL);
!
! if (candidates)
! candidates->basetype_path = TREE_PURPOSE (fns);
}
}
*************** build_object_call (obj, args)
*** 4540,4547 ****
&& TREE_CODE (TREE_TYPE (totype)) == FUNCTION_TYPE)
for (; fn; fn = DECL_CHAIN (fn))
{
! candidates = add_conv_candidate (candidates, fn, obj, args);
! candidates->basetype_path = TREE_PURPOSE (convs);
}
}
--- 4580,4599 ----
&& TREE_CODE (TREE_TYPE (totype)) == FUNCTION_TYPE)
for (; fn; fn = DECL_CHAIN (fn))
{
! if (TREE_CODE (fn) == TEMPLATE_DECL)
! {
! templates = decl_tree_cons (NULL_TREE, fn, templates);
! candidates = add_template_conv_candidate (candidates,
! fn,
! obj,
! args,
! totype);
! }
! else
! candidates = add_conv_candidate (candidates, fn, obj, args);
!
! if (candidates)
! candidates->basetype_path = TREE_PURPOSE (convs);
}
}
Index: error.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/error.c,v
retrieving revision 1.1.1.3
diff -c -p -r1.1.1.3 error.c
*** error.c 1997/09/08 05:23:57 1.1.1.3
--- error.c 1997/09/08 05:38:04
*************** dump_expr (t, nop)
*** 1366,1378 ****
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));
--- 1366,1380 ----
if (current_template_parms)
{
int i;
! int l = list_length (current_template_parms);
! tree parms = current_template_parms;
tree r;
! for (i = 0; i < l - TEMPLATE_CONST_LEVEL (t); ++i)
! {
! parms = TREE_CHAIN (parms);
! my_friendly_assert (parms != NULL_TREE, 0);
! }
r = TREE_VEC_ELT (TREE_VALUE (parms),
TEMPLATE_CONST_IDX (t));
Index: lex.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/lex.c,v
retrieving revision 1.1.1.3
diff -c -p -r1.1.1.3 lex.c
*** lex.c 1997/09/08 05:23:57 1.1.1.3
--- lex.c 1997/09/08 05:38:36
*************** do_pending_inlines ()
*** 1191,1197 ****
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);
--- 1191,1197 ----
if (context)
push_cp_function_context (context);
if (is_member_template (t->fndecl))
! begin_member_template_processing (t->fndecl);
if (t->len > 0)
{
feed_input (t->buf, t->len);
*************** process_next_inline (t)
*** 1254,1260 ****
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;
--- 1254,1260 ----
if (context)
push_cp_function_context (context);
if (is_member_template (i->fndecl))
! begin_member_template_processing (i->fndecl);
feed_input (i->buf, i->len);
lineno = i->lineno;
input_filename = i->filename;
*************** do_pending_defargs ()
*** 1874,1880 ****
push_nested_class (TREE_PURPOSE (defarg_fns), 1);
pushlevel (0);
if (is_member_template (defarg_fn))
! begin_member_template_processing (DECL_TI_ARGS (defarg_fn));
if (TREE_CODE (defarg_fn) == FUNCTION_DECL)
{
--- 1874,1880 ----
push_nested_class (TREE_PURPOSE (defarg_fns), 1);
pushlevel (0);
if (is_member_template (defarg_fn))
! begin_member_template_processing (defarg_fn);
if (TREE_CODE (defarg_fn) == FUNCTION_DECL)
{
Index: pt.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/pt.c,v
retrieving revision 1.1.1.3
diff -c -p -r1.1.1.3 pt.c
*** pt.c 1997/09/08 05:23:58 1.1.1.3
--- pt.c 1997/09/08 08:08:51
*************** static tree add_to_template_args PROTO((
*** 82,110 ****
/* 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);
}
--- 82,121 ----
/* Restore the template parameter context. */
void
! begin_member_template_processing (decl)
! tree decl;
{
+ tree parms;
int i;
+ parms = DECL_INNERMOST_TEMPLATE_PARMS (DECL_TI_TEMPLATE (decl));
+
++processing_template_decl;
current_template_parms
= tree_cons (build_int_2 (0, processing_template_decl),
parms, current_template_parms);
+ pushlevel (0);
for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
{
! tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
! my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (parm)) == 'd', 0);
!
switch (TREE_CODE (parm))
{
! case TYPE_DECL:
pushdecl (parm);
break;
!
! case PARM_DECL:
! {
! /* Make a CONST_DECL as is done in process_template_parm. */
! tree decl = build_decl (CONST_DECL, DECL_NAME (parm),
! TREE_TYPE (parm));
! DECL_INITIAL (decl) = DECL_INITIAL (parm);
! pushdecl (decl);
! }
! break;
!
default:
my_friendly_abort (0);
}
*************** end_member_template_processing ()
*** 121,126 ****
--- 132,138 ----
--processing_template_decl;
current_template_parms = TREE_CHAIN (current_template_parms);
+ poplevel (0, 0, 0);
}
/* Returns non-zero iff T is a member template function. Works if T
*************** push_template_decl (decl)
*** 449,455 ****
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
{
--- 461,471 ----
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);
! DECL_STATIC_FUNCTION_P (tmpl) =
! DECL_STATIC_FUNCTION_P (decl);
! }
}
else
{
More information about the Gcc
mailing list