parent
c8c2dcdce1
commit
73aad9b9ff
|
@ -1,3 +1,49 @@
|
|||
Mon Aug 12 00:09:18 1996 Jason Merrill <jason@yorick.cygnus.com>
|
||||
|
||||
* pt.c (end_template_decl): If we don't actually have parms, return.
|
||||
* parse.y (template_header): Accept 'template <>'.
|
||||
|
||||
* errfn.c: Allow 5 args.
|
||||
|
||||
Sun Aug 11 15:20:58 1996 Jason Merrill <jason@yorick.cygnus.com>
|
||||
|
||||
* tree.c (make_temp_vec): New fn.
|
||||
* pt.c (push_template_decl): Handle partial specs.
|
||||
(instantiate_class_template): Ditto.
|
||||
(more_specialized): Use get_bindings.
|
||||
(more_specialized_class): New fn.
|
||||
(get_class_bindings): New fn.
|
||||
(most_specialized_class): New fn.
|
||||
(do_function_instantiation): List candidates for ambiguous case.
|
||||
* decl.c (duplicate_decls): Lose reference to DECL_TEMPLATE_MEMBERS.
|
||||
(shadow_tag): Call push_template_decl for partial specializations.
|
||||
* parse.y: Ditto.
|
||||
* cp-tree.h (DECL_TEMPLATE_SPECIALIZATIONS): Replaces
|
||||
DECL_TEMPLATE_MEMBERS.
|
||||
* call.c (print_z_candidates): Reduce duplication.
|
||||
|
||||
Fri Aug 9 14:36:08 1996 Jason Merrill <jason@yorick.cygnus.com>
|
||||
|
||||
* decl2.c (lang_decode_option): Allow -fansi-overloading.
|
||||
|
||||
Thu Aug 8 17:04:18 1996 Jason Merrill <jason@yorick.cygnus.com>
|
||||
|
||||
* pt.c (get_bindings): New fn.
|
||||
(most_specialized): Ditto.
|
||||
(do_function_instantiation): Use them.
|
||||
(add_maybe_template): New fn.
|
||||
* cp-tree.h (DECL_MAYBE_TEMPLATE): New macro.
|
||||
* call.c (build_new_op): Handle guiding decls.
|
||||
(build_new_function_call): Ditto.
|
||||
* decl2.c (finish_file): Ditto.
|
||||
|
||||
* decl2.c (mark_used): Do synthesis here.
|
||||
* call.c (build_method_call): Not here.
|
||||
(build_over_call): Or here.
|
||||
* typeck.c (build_function_call_real): Or here.
|
||||
* tree.c (bot_manip): Call mark_used on functions used in default
|
||||
args.
|
||||
|
||||
Thu Aug 8 17:48:16 1996 Michael Meissner <meissner@tiktok.cygnus.com>
|
||||
|
||||
* decl2.c (import_export_vtable): Delete code that disabled vtable
|
||||
|
|
|
@ -2468,12 +2468,6 @@ build_method_call (instance, name, parms, basetype_path, flags)
|
|||
function = DECL_MAIN_VARIANT (function);
|
||||
mark_used (function);
|
||||
|
||||
/* Is it a synthesized method that needs to be synthesized? */
|
||||
if (DECL_ARTIFICIAL (function) && ! DECL_INITIAL (function)
|
||||
/* Kludge: don't synthesize for default args. */
|
||||
&& current_function_decl)
|
||||
synthesize_method (function);
|
||||
|
||||
if (pedantic && DECL_THIS_INLINE (function) && ! DECL_ARTIFICIAL (function)
|
||||
&& ! DECL_INITIAL (function) && ! DECL_PENDING_INLINE_INFO (function)
|
||||
&& ! (DECL_TEMPLATE_INFO (function)
|
||||
|
@ -4157,48 +4151,27 @@ static void
|
|||
print_z_candidates (candidates)
|
||||
struct z_candidate *candidates;
|
||||
{
|
||||
if (! candidates)
|
||||
return;
|
||||
|
||||
if (TREE_CODE (candidates->fn) == IDENTIFIER_NODE)
|
||||
{
|
||||
if (candidates->fn == ansi_opname [COND_EXPR])
|
||||
cp_error ("candidates are: %D(%T, %T, %T) <builtin>", candidates->fn,
|
||||
TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)),
|
||||
TREE_TYPE (TREE_VEC_ELT (candidates->convs, 1)),
|
||||
TREE_TYPE (TREE_VEC_ELT (candidates->convs, 2)));
|
||||
else if (TREE_VEC_LENGTH (candidates->convs) == 2)
|
||||
cp_error ("candidates are: %D(%T, %T) <builtin>", candidates->fn,
|
||||
TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)),
|
||||
TREE_TYPE (TREE_VEC_ELT (candidates->convs, 1)));
|
||||
else
|
||||
cp_error ("candidates are: %D(%T) <builtin>", candidates->fn,
|
||||
TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)));
|
||||
}
|
||||
else
|
||||
cp_error_at ("candidates are: %D", candidates->fn);
|
||||
candidates = candidates->next;
|
||||
|
||||
char *str = "candidates are:";
|
||||
for (; candidates; candidates = candidates->next)
|
||||
{
|
||||
if (TREE_CODE (candidates->fn) == IDENTIFIER_NODE)
|
||||
{
|
||||
if (candidates->fn == ansi_opname [COND_EXPR])
|
||||
cp_error (" %D(%T, %T, %T) <builtin>",
|
||||
candidates->fn,
|
||||
cp_error ("%s %D(%T, %T, %T) <builtin>", str, candidates->fn,
|
||||
TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)),
|
||||
TREE_TYPE (TREE_VEC_ELT (candidates->convs, 1)),
|
||||
TREE_TYPE (TREE_VEC_ELT (candidates->convs, 2)));
|
||||
else if (TREE_VEC_LENGTH (candidates->convs) == 2)
|
||||
cp_error (" %D(%T, %T) <builtin>", candidates->fn,
|
||||
cp_error ("%s %D(%T, %T) <builtin>", str, candidates->fn,
|
||||
TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)),
|
||||
TREE_TYPE (TREE_VEC_ELT (candidates->convs, 1)));
|
||||
else
|
||||
cp_error (" %D(%T) <builtin>", candidates->fn,
|
||||
cp_error ("%s %D(%T) <builtin>", str, candidates->fn,
|
||||
TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)));
|
||||
}
|
||||
else
|
||||
cp_error_at (" %D", candidates->fn);
|
||||
cp_error_at ("%s %+D", str, candidates->fn);
|
||||
str = " ";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4334,6 +4307,7 @@ build_new_function_call (fn, args, obj)
|
|||
if (obj == NULL_TREE && TREE_CODE (fn) == TREE_LIST)
|
||||
{
|
||||
tree t;
|
||||
tree templates = NULL_TREE;
|
||||
|
||||
for (t = args; t; t = TREE_CHAIN (t))
|
||||
if (TREE_VALUE (t) == error_mark_node)
|
||||
|
@ -4342,8 +4316,11 @@ build_new_function_call (fn, args, obj)
|
|||
for (t = TREE_VALUE (fn); t; t = DECL_CHAIN (t))
|
||||
{
|
||||
if (TREE_CODE (t) == TEMPLATE_DECL)
|
||||
candidates = add_template_candidate
|
||||
(candidates, t, args, LOOKUP_NORMAL);
|
||||
{
|
||||
templates = decl_tree_cons (NULL_TREE, t, templates);
|
||||
candidates = add_template_candidate
|
||||
(candidates, t, args, LOOKUP_NORMAL);
|
||||
}
|
||||
else
|
||||
candidates = add_function_candidate
|
||||
(candidates, t, args, LOOKUP_NORMAL);
|
||||
|
@ -4369,6 +4346,12 @@ build_new_function_call (fn, args, obj)
|
|||
return error_mark_node;
|
||||
}
|
||||
|
||||
/* 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, args, LOOKUP_NORMAL);
|
||||
}
|
||||
|
||||
|
@ -4482,6 +4465,7 @@ build_new_op (code, flags, arg1, arg2, arg3)
|
|||
struct z_candidate *candidates = 0, *cand;
|
||||
tree fns, mem_arglist, arglist, fnname, *p;
|
||||
enum tree_code code2 = NOP_EXPR;
|
||||
tree templates = NULL_TREE;
|
||||
|
||||
if (arg1 == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
@ -4602,7 +4586,11 @@ build_new_op (code, flags, arg1, arg2, arg3)
|
|||
for (; fns; fns = DECL_CHAIN (fns))
|
||||
{
|
||||
if (TREE_CODE (fns) == TEMPLATE_DECL)
|
||||
candidates = add_template_candidate (candidates, fns, arglist, flags);
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
@ -4715,6 +4703,13 @@ build_new_op (code, flags, arg1, arg2, arg3)
|
|||
if (DECL_FUNCTION_MEMBER_P (cand->fn))
|
||||
enforce_access (cand->basetype_path, cand->fn);
|
||||
|
||||
/* 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);
|
||||
|
||||
return build_over_call
|
||||
(cand->fn, cand->convs,
|
||||
TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE
|
||||
|
@ -4999,12 +4994,6 @@ build_over_call (fn, convs, args, flags)
|
|||
converted_args = nreverse (converted_args);
|
||||
|
||||
mark_used (fn);
|
||||
/* Is it a synthesized method that needs to be synthesized? */
|
||||
if (DECL_ARTIFICIAL (fn) && ! DECL_INITIAL (fn)
|
||||
&& DECL_CLASS_CONTEXT (fn)
|
||||
/* Kludge: don't synthesize for default args. */
|
||||
&& current_function_decl)
|
||||
synthesize_method (fn);
|
||||
|
||||
if (pedantic && DECL_THIS_INLINE (fn) && ! DECL_ARTIFICIAL (fn)
|
||||
&& ! DECL_INITIAL (fn) && ! DECL_PENDING_INLINE_INFO (fn)
|
||||
|
|
|
@ -1135,7 +1135,7 @@ struct lang_decl
|
|||
#if 0 /* UNUSED */
|
||||
/* Nonzero in IDENTIFIER_NODE means that this name is overloaded, and
|
||||
should be looked up in a non-standard way. */
|
||||
#define DECL_OVERLOADED(NODE) (DECL_LANG_FLAG_4 (NODE))
|
||||
#define DECL_OVERLOADED(NODE) (FOO)
|
||||
#endif
|
||||
|
||||
/* Nonzero if this (non-TYPE)_DECL has its virtual attribute set.
|
||||
|
@ -1331,7 +1331,7 @@ extern int flag_new_for_scope;
|
|||
/* Accessor macros for C++ template decl nodes. */
|
||||
#define DECL_TEMPLATE_PARMS(NODE) DECL_ARGUMENTS(NODE)
|
||||
/* For class templates. */
|
||||
#define DECL_TEMPLATE_MEMBERS(NODE) DECL_SIZE(NODE)
|
||||
#define DECL_TEMPLATE_SPECIALIZATIONS(NODE) DECL_SIZE(NODE)
|
||||
/* For function, method, class-data templates. */
|
||||
#define DECL_TEMPLATE_RESULT(NODE) DECL_RESULT(NODE)
|
||||
#define DECL_TEMPLATE_INSTANTIATIONS(NODE) DECL_VINDEX(NODE)
|
||||
|
@ -1380,6 +1380,8 @@ extern int flag_new_for_scope;
|
|||
#define SET_CLASSTYPE_EXPLICIT_INSTANTIATION(NODE) \
|
||||
(CLASSTYPE_USE_TEMPLATE(NODE) = 3)
|
||||
|
||||
/* This function may be a guiding decl for a template. */
|
||||
#define DECL_MAYBE_TEMPLATE(NODE) DECL_LANG_FLAG_4 (NODE)
|
||||
/* We know what we're doing with this decl now. */
|
||||
#define DECL_INTERFACE_KNOWN(NODE) DECL_LANG_FLAG_5 (NODE)
|
||||
|
||||
|
@ -2308,6 +2310,7 @@ extern tree instantiate_decl PROTO((tree));
|
|||
extern tree classtype_mangled_name 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));
|
||||
|
||||
/* in search.c */
|
||||
extern void push_memoized_context PROTO((tree, int));
|
||||
|
|
|
@ -2869,7 +2869,6 @@ duplicate_decls (newdecl, olddecl)
|
|||
|
||||
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
|
||||
{
|
||||
DECL_TEMPLATE_MEMBERS (newdecl) = DECL_TEMPLATE_MEMBERS (olddecl);
|
||||
DECL_TEMPLATE_INSTANTIATIONS (newdecl)
|
||||
= DECL_TEMPLATE_INSTANTIATIONS (olddecl);
|
||||
if (DECL_CHAIN (newdecl) == NULL_TREE)
|
||||
|
@ -5646,7 +5645,11 @@ shadow_tag (declspecs)
|
|||
{
|
||||
if (CLASSTYPE_IMPLICIT_INSTANTIATION (value)
|
||||
&& TYPE_SIZE (value) == NULL_TREE)
|
||||
SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (value);
|
||||
{
|
||||
SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (value);
|
||||
if (current_template_parms)
|
||||
push_template_decl (TYPE_MAIN_DECL (value));
|
||||
}
|
||||
else if (CLASSTYPE_TEMPLATE_INSTANTIATION (value))
|
||||
cp_error ("specialization after instantiation of `%T'", value);
|
||||
}
|
||||
|
|
|
@ -498,11 +498,6 @@ lang_decode_option (p)
|
|||
flag_alt_external_templates = 0;
|
||||
found = 1;
|
||||
}
|
||||
else if (!strcmp (p, "ansi-overloading"))
|
||||
{
|
||||
warning ("-fansi-overloading is no longer meaningful");
|
||||
found = 1;
|
||||
}
|
||||
else if (!strcmp (p, "repo"))
|
||||
{
|
||||
flag_use_repository = 1;
|
||||
|
@ -2876,6 +2871,7 @@ build_cleanup (decl)
|
|||
|
||||
extern int parse_time, varconst_time;
|
||||
extern tree pending_templates;
|
||||
extern tree maybe_templates;
|
||||
|
||||
#define TIMEVAR(VAR, BODY) \
|
||||
do { int otime = get_run_time (); BODY; VAR += get_run_time () - otime; } while (0)
|
||||
|
@ -2952,6 +2948,20 @@ finish_file ()
|
|||
instantiate_decl (decl);
|
||||
}
|
||||
|
||||
for (fnname = maybe_templates; fnname; fnname = TREE_CHAIN (fnname))
|
||||
{
|
||||
tree *args, fn, decl = TREE_VALUE (fnname);
|
||||
|
||||
if (DECL_INITIAL (decl))
|
||||
continue;
|
||||
|
||||
fn = TREE_PURPOSE (fnname);
|
||||
args = get_bindings (fn, decl);
|
||||
fn = instantiate_template (fn, args);
|
||||
free (args);
|
||||
instantiate_decl (fn);
|
||||
}
|
||||
|
||||
/* Push into C language context, because that's all
|
||||
we'll need here. */
|
||||
push_lang_context (lang_name_c);
|
||||
|
@ -3848,6 +3858,12 @@ mark_used (decl)
|
|||
if (current_template_parms)
|
||||
return;
|
||||
assemble_external (decl);
|
||||
/* Is it a synthesized method that needs to be synthesized? */
|
||||
if (TREE_CODE (decl) == FUNCTION_DECL && DECL_CLASS_CONTEXT (decl)
|
||||
&& DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl)
|
||||
/* Kludge: don't synthesize for default args. */
|
||||
&& current_function_decl)
|
||||
synthesize_method (decl);
|
||||
if (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl))
|
||||
instantiate_decl (decl);
|
||||
}
|
||||
|
|
|
@ -44,11 +44,12 @@ extern int cp_line_of PROTO((tree));
|
|||
|
||||
#define STRDUP(f) (ap = (char *) alloca (strlen (f) +1), strcpy (ap, (f)), ap)
|
||||
|
||||
#define NARGS 4
|
||||
#define arglist a1, a2, a3, a4
|
||||
#define arglist_dcl HOST_WIDE_INT a1, a2, a3, a4;
|
||||
#define ARGSINIT args[0] = a1; args[1] = a2; args[2] = a3; args[3] = a4;
|
||||
#define ARGSLIST args[0], args[1], args[2], args[3]
|
||||
#define NARGS 5
|
||||
#define arglist a1, a2, a3, a4, a5
|
||||
#define arglist_dcl HOST_WIDE_INT a1, a2, a3, a4, a5;
|
||||
#define ARGSINIT \
|
||||
args[0] = a1; args[1] = a2; args[2] = a3; args[3] = a4; args[4] = a5;
|
||||
#define ARGSLIST args[0], args[1], args[2], args[3], args[4]
|
||||
|
||||
static void
|
||||
cp_thing (errfn, atarg1, format, arglist)
|
||||
|
|
|
@ -418,6 +418,8 @@ template_header:
|
|||
{ begin_template_parm_list (); }
|
||||
template_parm_list '>'
|
||||
{ $$ = end_template_parm_list ($4); }
|
||||
| TEMPLATE '<' '>'
|
||||
{ $$ = NULL_TREE; }
|
||||
;
|
||||
|
||||
template_parm_list:
|
||||
|
@ -2321,7 +2323,11 @@ named_class_head:
|
|||
{
|
||||
if (CLASSTYPE_IMPLICIT_INSTANTIATION ($$)
|
||||
&& TYPE_SIZE ($$) == NULL_TREE)
|
||||
SET_CLASSTYPE_TEMPLATE_SPECIALIZATION ($$);
|
||||
{
|
||||
SET_CLASSTYPE_TEMPLATE_SPECIALIZATION ($$);
|
||||
if (current_template_parms)
|
||||
push_template_decl (TYPE_MAIN_DECL ($$));
|
||||
}
|
||||
else if (CLASSTYPE_TEMPLATE_INSTANTIATION ($$))
|
||||
cp_error ("specialization after instantiation of `%T'", $$);
|
||||
}
|
||||
|
@ -2525,7 +2531,11 @@ left_curly: '{'
|
|||
{
|
||||
if (CLASSTYPE_IMPLICIT_INSTANTIATION (t)
|
||||
&& TYPE_SIZE (t) == NULL_TREE)
|
||||
SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (t);
|
||||
{
|
||||
SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (t);
|
||||
if (current_template_parms)
|
||||
push_template_decl (TYPE_MAIN_DECL (t));
|
||||
}
|
||||
else if (CLASSTYPE_TEMPLATE_INSTANTIATION (t))
|
||||
cp_error ("specialization after instantiation of `%T'", t);
|
||||
}
|
||||
|
|
352
gcc/cp/pt.c
352
gcc/cp/pt.c
|
@ -53,6 +53,9 @@ HOST_WIDE_INT processing_template_decl;
|
|||
tree pending_templates;
|
||||
static tree *template_tail = &pending_templates;
|
||||
|
||||
tree maybe_templates;
|
||||
static tree *maybe_template_tail = &maybe_templates;
|
||||
|
||||
int minimal_parse_mode;
|
||||
|
||||
#define obstack_chunk_alloc xmalloc
|
||||
|
@ -65,6 +68,9 @@ void pop_template_decls ();
|
|||
tree classtype_mangled_name ();
|
||||
static char * mangle_class_name_for_template ();
|
||||
tree tsubst_expr_values ();
|
||||
tree most_specialized_class PROTO((tree, tree));
|
||||
tree get_class_bindings PROTO((tree, tree, tree));
|
||||
tree make_temp_vec PROTO((int));
|
||||
|
||||
/* We've got a template header coming up; push to a new level for storing
|
||||
the parms. */
|
||||
|
@ -181,6 +187,9 @@ end_template_parm_list (parms)
|
|||
void
|
||||
end_template_decl ()
|
||||
{
|
||||
if (! current_template_parms)
|
||||
return;
|
||||
|
||||
/* This matches the pushlevel in begin_template_parm_list. */
|
||||
poplevel (0, 0, 0);
|
||||
|
||||
|
@ -229,6 +238,30 @@ push_template_decl (decl)
|
|||
args = nreverse (args);
|
||||
args = TREE_VALUE (args);
|
||||
|
||||
/* Partial specialization. */
|
||||
if (TREE_CODE (decl) == TYPE_DECL
|
||||
&& CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)))
|
||||
{
|
||||
tree type = TREE_TYPE (decl);
|
||||
tree maintmpl = CLASSTYPE_TI_TEMPLATE (type);
|
||||
tree mainargs = CLASSTYPE_TI_ARGS (type);
|
||||
tree spec = DECL_TEMPLATE_SPECIALIZATIONS (maintmpl);
|
||||
|
||||
for (; spec; spec = TREE_CHAIN (spec))
|
||||
{
|
||||
/* purpose: args to main template
|
||||
value: spec template */
|
||||
if (comp_template_args (TREE_PURPOSE (spec), mainargs))
|
||||
return;
|
||||
}
|
||||
|
||||
DECL_TEMPLATE_SPECIALIZATIONS (maintmpl) = perm_tree_cons
|
||||
(mainargs, TREE_VALUE (current_template_parms),
|
||||
DECL_TEMPLATE_SPECIALIZATIONS (maintmpl));
|
||||
TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)) = type;
|
||||
return;
|
||||
}
|
||||
|
||||
if (! ctx || TYPE_BEING_DEFINED (ctx))
|
||||
{
|
||||
tmpl = build_lang_decl (TEMPLATE_DECL, DECL_NAME (decl), NULL_TREE);
|
||||
|
@ -237,6 +270,9 @@ push_template_decl (decl)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (CLASSTYPE_TEMPLATE_INSTANTIATION (ctx))
|
||||
cp_error ("must specialize `%#T' before defining member `%#D'",
|
||||
ctx, decl);
|
||||
if (TREE_CODE (decl) == TYPE_DECL)
|
||||
tmpl = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl));
|
||||
else if (! DECL_TEMPLATE_INFO (decl))
|
||||
|
@ -1004,11 +1040,36 @@ instantiate_class_template (type)
|
|||
template = TI_TEMPLATE (template_info);
|
||||
my_friendly_assert (TREE_CODE (template) == TEMPLATE_DECL, 279);
|
||||
args = TI_ARGS (template_info);
|
||||
pattern = TREE_TYPE (template);
|
||||
|
||||
t = most_specialized_class
|
||||
(DECL_TEMPLATE_SPECIALIZATIONS (template), args);
|
||||
|
||||
if (t == error_mark_node)
|
||||
{
|
||||
char *str = "candidates are:";
|
||||
cp_error ("ambiguous class template instantiation for `%#T'", type);
|
||||
for (t = DECL_TEMPLATE_SPECIALIZATIONS (template); t; t = TREE_CHAIN (t))
|
||||
{
|
||||
if (get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), args))
|
||||
{
|
||||
cp_error_at ("%s %+#T", str, TREE_TYPE (t));
|
||||
str = " ";
|
||||
}
|
||||
}
|
||||
TYPE_BEING_DEFINED (type) = 1;
|
||||
return;
|
||||
}
|
||||
else if (t)
|
||||
pattern = TREE_TYPE (t);
|
||||
else
|
||||
pattern = TREE_TYPE (template);
|
||||
|
||||
if (TYPE_SIZE (pattern) == NULL_TREE)
|
||||
return type;
|
||||
|
||||
if (t)
|
||||
args = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), args);
|
||||
|
||||
TYPE_BEING_DEFINED (type) = 1;
|
||||
|
||||
if (! push_tinst_level (type))
|
||||
|
@ -2785,34 +2846,207 @@ int
|
|||
more_specialized (pat1, pat2)
|
||||
tree pat1, pat2;
|
||||
{
|
||||
int ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (pat1));
|
||||
tree *targs = (tree *) malloc (sizeof (tree) * ntparms);
|
||||
int i, dummy = 0, winner = 0;
|
||||
tree *targs;
|
||||
int winner = 0;
|
||||
|
||||
i = type_unification (DECL_TEMPLATE_PARMS (pat1), targs,
|
||||
TYPE_ARG_TYPES (TREE_TYPE (pat1)),
|
||||
TYPE_ARG_TYPES (TREE_TYPE (pat2)),
|
||||
&dummy, 0, 1);
|
||||
targs = get_bindings (pat1, pat2);
|
||||
if (targs)
|
||||
{
|
||||
free (targs);
|
||||
--winner;
|
||||
}
|
||||
|
||||
free (targs);
|
||||
if (i == 0)
|
||||
targs = get_bindings (pat2, pat1);
|
||||
if (targs)
|
||||
{
|
||||
free (targs);
|
||||
++winner;
|
||||
}
|
||||
|
||||
return winner;
|
||||
}
|
||||
|
||||
/* Given two class template specialization list nodes PAT1 and PAT2, return:
|
||||
|
||||
1 if PAT1 is more specialized than PAT2 as described in [temp.class.order].
|
||||
-1 if PAT2 is more specialized than PAT1.
|
||||
0 if neither is more specialized. */
|
||||
|
||||
int
|
||||
more_specialized_class (pat1, pat2)
|
||||
tree pat1, pat2;
|
||||
{
|
||||
tree targs;
|
||||
int winner = 0;
|
||||
|
||||
targs = get_class_bindings
|
||||
(TREE_VALUE (pat1), TREE_PURPOSE (pat1), TREE_PURPOSE (pat2));
|
||||
if (targs)
|
||||
--winner;
|
||||
|
||||
ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (pat2));
|
||||
targs = (tree *) malloc (sizeof (tree) * ntparms);
|
||||
|
||||
i = type_unification (DECL_TEMPLATE_PARMS (pat2), targs,
|
||||
TYPE_ARG_TYPES (TREE_TYPE (pat2)),
|
||||
TYPE_ARG_TYPES (TREE_TYPE (pat1)),
|
||||
&dummy, 0, 1);
|
||||
|
||||
free (targs);
|
||||
if (i == 0)
|
||||
targs = get_class_bindings
|
||||
(TREE_VALUE (pat2), TREE_PURPOSE (pat2), TREE_PURPOSE (pat1));
|
||||
if (targs)
|
||||
++winner;
|
||||
|
||||
return winner;
|
||||
}
|
||||
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
tree
|
||||
get_class_bindings (tparms, parms, args)
|
||||
tree tparms, parms, args;
|
||||
{
|
||||
int i, dummy, ntparms = TREE_VEC_LENGTH (tparms);
|
||||
tree vec = make_temp_vec (ntparms);
|
||||
|
||||
for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
|
||||
{
|
||||
switch (unify (tparms, &TREE_VEC_ELT (vec, 0), ntparms,
|
||||
TREE_VEC_ELT (parms, i), TREE_VEC_ELT (args, i),
|
||||
&dummy, 1))
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
return NULL_TREE;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ntparms; ++i)
|
||||
if (! TREE_VEC_ELT (vec, i))
|
||||
return NULL_TREE;
|
||||
|
||||
return vec;
|
||||
}
|
||||
|
||||
/* Return the most specialized of the list of templates in FNS that can
|
||||
produce an instantiation matching DECL. */
|
||||
|
||||
tree
|
||||
most_specialized (fns, decl)
|
||||
tree fns, decl;
|
||||
{
|
||||
tree fn, champ, *args, *p;
|
||||
int fate;
|
||||
|
||||
for (p = &fns; *p; )
|
||||
{
|
||||
args = get_bindings (TREE_VALUE (*p), decl);
|
||||
if (args)
|
||||
{
|
||||
free (args);
|
||||
p = &TREE_CHAIN (*p);
|
||||
}
|
||||
else
|
||||
*p = TREE_CHAIN (*p);
|
||||
}
|
||||
|
||||
if (! fns)
|
||||
return NULL_TREE;
|
||||
|
||||
fn = fns;
|
||||
champ = TREE_VALUE (fn);
|
||||
fn = TREE_CHAIN (fn);
|
||||
for (; fn; fn = TREE_CHAIN (fn))
|
||||
{
|
||||
fate = more_specialized (champ, TREE_VALUE (fn));
|
||||
if (fate == 1)
|
||||
;
|
||||
else
|
||||
{
|
||||
if (fate == 0)
|
||||
{
|
||||
fn = TREE_CHAIN (fn);
|
||||
if (! fn)
|
||||
return error_mark_node;
|
||||
}
|
||||
champ = TREE_VALUE (fn);
|
||||
}
|
||||
}
|
||||
|
||||
for (fn = fns; fn && TREE_VALUE (fn) != champ; fn = TREE_CHAIN (fn))
|
||||
{
|
||||
fate = more_specialized (champ, TREE_VALUE (fn));
|
||||
if (fate != 1)
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
return champ;
|
||||
}
|
||||
|
||||
/* Return the most specialized of the class template specializations in
|
||||
SPECS that can produce an instantiation matching ARGS. */
|
||||
|
||||
tree
|
||||
most_specialized_class (specs, mainargs)
|
||||
tree specs, mainargs;
|
||||
{
|
||||
tree list = NULL_TREE, t, args, champ;
|
||||
int fate;
|
||||
|
||||
for (t = specs; t; t = TREE_CHAIN (t))
|
||||
{
|
||||
args = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), mainargs);
|
||||
if (args)
|
||||
{
|
||||
list = decl_tree_cons (TREE_PURPOSE (t), TREE_VALUE (t), list);
|
||||
TREE_TYPE (list) = TREE_TYPE (t);
|
||||
}
|
||||
}
|
||||
|
||||
if (! list)
|
||||
return NULL_TREE;
|
||||
|
||||
t = list;
|
||||
champ = t;
|
||||
t = TREE_CHAIN (t);
|
||||
for (; t; t = TREE_CHAIN (t))
|
||||
{
|
||||
fate = more_specialized_class (champ, t);
|
||||
if (fate == 1)
|
||||
;
|
||||
else
|
||||
{
|
||||
if (fate == 0)
|
||||
{
|
||||
t = TREE_CHAIN (t);
|
||||
if (! t)
|
||||
return error_mark_node;
|
||||
}
|
||||
champ = t;
|
||||
}
|
||||
}
|
||||
|
||||
for (t = list; t && t != champ; t = TREE_CHAIN (t))
|
||||
{
|
||||
fate = more_specialized (champ, t);
|
||||
if (fate != 1)
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
return champ;
|
||||
}
|
||||
|
||||
/* called from the parser. */
|
||||
|
||||
void
|
||||
|
@ -2844,6 +3078,7 @@ do_function_instantiation (declspecs, declarator, storage)
|
|||
}
|
||||
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))
|
||||
|
@ -2852,31 +3087,30 @@ do_function_instantiation (declspecs, declarator, storage)
|
|||
break;
|
||||
}
|
||||
else if (TREE_CODE (fn) == TEMPLATE_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)
|
||||
{
|
||||
if (result)
|
||||
{
|
||||
int win = more_specialized (DECL_TI_TEMPLATE (result), fn);
|
||||
templates = decl_tree_cons (NULL_TREE, fn, templates);
|
||||
|
||||
if (win == 0)
|
||||
cp_error ("ambiguous template instantiation for `%D' requested", decl);
|
||||
else if (win == -1)
|
||||
result = instantiate_template (fn, targs);
|
||||
/* else keep current winner */
|
||||
}
|
||||
else
|
||||
result = instantiate_template (fn, targs);
|
||||
}
|
||||
free (targs);
|
||||
}
|
||||
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)
|
||||
{
|
||||
|
@ -3195,3 +3429,31 @@ add_tree (t)
|
|||
{
|
||||
last_tree = TREE_CHAIN (last_tree) = t;
|
||||
}
|
||||
|
||||
/* D is an undefined function declaration in the presence of templates with
|
||||
the same name, listed in FNS. If one of them can produce D as an
|
||||
instantiation, remember this so we can instantiate it at EOF if D has
|
||||
not been defined by that time. */
|
||||
|
||||
void
|
||||
add_maybe_template (d, fns)
|
||||
tree d, fns;
|
||||
{
|
||||
tree t;
|
||||
|
||||
if (DECL_MAYBE_TEMPLATE (d))
|
||||
return;
|
||||
|
||||
t = most_specialized (fns, d);
|
||||
if (! t)
|
||||
return;
|
||||
if (t == error_mark_node)
|
||||
{
|
||||
cp_error ("ambiguous template instantiation for `%D'", d);
|
||||
return;
|
||||
}
|
||||
|
||||
*maybe_template_tail = perm_tree_cons (t, d, NULL_TREE);
|
||||
maybe_template_tail = &TREE_CHAIN (*maybe_template_tail);
|
||||
DECL_MAYBE_TEMPLATE (d) = 1;
|
||||
}
|
||||
|
|
|
@ -1772,8 +1772,21 @@ bot_manip (t)
|
|||
if (TREE_CODE (t) != TREE_LIST && ! TREE_SIDE_EFFECTS (t))
|
||||
return t;
|
||||
else if (TREE_CODE (t) == TARGET_EXPR)
|
||||
return build_cplus_new (TREE_TYPE (t),
|
||||
break_out_target_exprs (TREE_OPERAND (t, 1)));
|
||||
{
|
||||
if (TREE_CODE (TREE_OPERAND (t, 1)) == NEW_EXPR)
|
||||
{
|
||||
mark_used (TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (t, 1), 0), 0));
|
||||
return build_cplus_new
|
||||
(TREE_TYPE (t), break_out_target_exprs (TREE_OPERAND (t, 1)));
|
||||
}
|
||||
t = copy_node (t);
|
||||
TREE_OPERAND (t, 0) = build (VAR_DECL, TREE_TYPE (t));
|
||||
layout_decl (TREE_OPERAND (t, 0), 0);
|
||||
return t;
|
||||
}
|
||||
else if (TREE_CODE (t) == CALL_EXPR)
|
||||
mark_used (TREE_OPERAND (TREE_OPERAND (t, 0), 0));
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
|
@ -2078,3 +2091,17 @@ cp_tree_equal (t1, t2)
|
|||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Similar to make_tree_vec, but build on a temporary obstack. */
|
||||
|
||||
tree
|
||||
make_temp_vec (len)
|
||||
int len;
|
||||
{
|
||||
register tree node;
|
||||
push_obstacks_nochange ();
|
||||
resume_temporary_allocation ();
|
||||
node = make_tree_vec (len);
|
||||
pop_obstacks ();
|
||||
return node;
|
||||
}
|
||||
|
|
|
@ -2545,15 +2545,7 @@ build_function_call_real (function, params, require_complete, flags)
|
|||
needs to be separately compiled). */
|
||||
|
||||
if (DECL_INLINE (function))
|
||||
{
|
||||
/* Is it a synthesized method that needs to be synthesized? */
|
||||
if (DECL_ARTIFICIAL (function) && ! DECL_INITIAL (function)
|
||||
/* Kludge: don't synthesize for default args. */
|
||||
&& current_function_decl)
|
||||
synthesize_method (function);
|
||||
|
||||
function = inline_conversion (function);
|
||||
}
|
||||
function = inline_conversion (function);
|
||||
else
|
||||
function = build_addr_func (function);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue