diff options
author | Jason Merrill <jason@yorick.cygnus.com> | 1996-08-13 15:39:22 +0000 |
---|---|---|
committer | Mike Stump <mrs@gcc.gnu.org> | 1996-08-13 15:39:22 +0000 |
commit | 73aad9b9ff694fcaf423834d7e2c47046cac34cd (patch) | |
tree | e2b752085bc40e641e8888cd283761f6cb564dc0 /gcc | |
parent | c8c2dcdce1e0144357f43f9d3c015dfbab58957a (diff) | |
download | gcc-73aad9b9ff694fcaf423834d7e2c47046cac34cd.zip gcc-73aad9b9ff694fcaf423834d7e2c47046cac34cd.tar.gz gcc-73aad9b9ff694fcaf423834d7e2c47046cac34cd.tar.bz2 |
87th Cygnus<->FSF quick merge
From-SVN: r12630
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 46 | ||||
-rw-r--r-- | gcc/cp/call.c | 73 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 7 | ||||
-rw-r--r-- | gcc/cp/decl.c | 7 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 26 | ||||
-rw-r--r-- | gcc/cp/errfn.c | 11 | ||||
-rw-r--r-- | gcc/cp/parse.y | 14 | ||||
-rw-r--r-- | gcc/cp/pt.c | 352 | ||||
-rw-r--r-- | gcc/cp/tree.c | 31 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 10 |
10 files changed, 463 insertions, 114 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index f65965a..cf36384 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index b81f35f..8bc96d1 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -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) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 19d9868..8b9c6ba 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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)); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 98d3f14..3486634 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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); } diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index b4de01b..b5a0529 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -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); } diff --git a/gcc/cp/errfn.c b/gcc/cp/errfn.c index 4da07fa..b5ab8f7 100644 --- a/gcc/cp/errfn.c +++ b/gcc/cp/errfn.c @@ -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) diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index eedfd11..06c4d82 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -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); } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 40a4582..bb03706 100644 --- a/gcc/cp/pt.c +++ b/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) - --winner; + targs = get_bindings (pat2, pat1); + if (targs) + { + free (targs); + ++winner; + } - ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (pat2)); - targs = (tree *) malloc (sizeof (tree) * ntparms); + return winner; +} - i = type_unification (DECL_TEMPLATE_PARMS (pat2), targs, - TYPE_ARG_TYPES (TREE_TYPE (pat2)), - TYPE_ARG_TYPES (TREE_TYPE (pat1)), - &dummy, 0, 1); +/* Given two class template specialization list nodes PAT1 and PAT2, return: - free (targs); - if (i == 0) + 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; + + 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); - - 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); - } + 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) { @@ -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; +} diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 6a4263f..4551177 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -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; +} diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index a43443b..f2f069b 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -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); } |