diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index bd15ca1d3b6c..b267d2869ebb 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -4,6 +4,31 @@ Sun Nov 9 01:29:55 1997 Jim Wilson (wilson@cygnus.com) * init.c (build_vec_delete_1): Delete build_block and add_block_current_level calls. +Mon Nov 10 20:25:31 1997 Jason Merrill + + * call.c (build_new_method_call): Handle getting a + TEMPLATE_ID_EXPR around a TEMPLATE_DECL. Don't look for a field + if we got template parms. + * typeck.c (build_x_function_call): Remember the TEMPLATE_ID_EXPR, + not just the args. + * decl2.c (build_expr_from_tree): Tweak last change. + * pt.c (tsubst_copy): Use get_first_fn instead of TREE_VALUE. + (maybe_fold_nontype_arg): Split out from tsubst_copy. + * tree.c (get_first_fn): Just return a TEMPLATE_ID_EXPR. + +Mon Nov 10 20:08:38 1997 Kriang Lerdsuwanakij + + * pt.c (tsubst_copy): Handle explicit template arguments in + function calls. + * typeck.c (build_x_function_call): Likewise. + * decl2.c (build_expr_from_tree): Lookup function name if it + hasn't been done. + + * pt.c (tsubst): Instantiate template functions properly when + template parameter does not appear in function arguments and return + type. + (comp_template_args): Handle member templates required by tsubst. + Mon Nov 10 20:08:38 1997 Jason Merrill * decl.c (grokdeclarator): Tweak conditions for pedwarn in diff --git a/gcc/cp/call.c b/gcc/cp/call.c index eaa39c69e720..da1d50ca692b 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -5474,6 +5474,8 @@ build_new_method_call (instance, name, args, basetype_path, flags) { explicit_targs = TREE_OPERAND (name, 1); name = TREE_OPERAND (name, 0); + if (TREE_CODE (name) == TEMPLATE_DECL) + name = DECL_NAME (name); template_only = 1; } @@ -5526,10 +5528,13 @@ build_new_method_call (instance, name, args, basetype_path, flags) { instance_ptr = build_this (instance); - /* XXX this should be handled before we get here. */ - fns = build_field_call (basetype_path, instance_ptr, name, args); - if (fns) - return fns; + if (! template_only) + { + /* XXX this should be handled before we get here. */ + fns = build_field_call (basetype_path, instance_ptr, name, args); + if (fns) + return fns; + } } else { diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index b51e6602fa6a..5d94797e2994 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -3406,10 +3406,9 @@ build_expr_from_tree (t) return do_identifier (TREE_OPERAND (t, 0), 0); case TEMPLATE_ID_EXPR: - return lookup_template_function (build_expr_from_tree - (TREE_OPERAND (t, 0)), - build_expr_from_tree - (TREE_OPERAND (t, 1))); + return (lookup_template_function + (build_expr_from_tree (TREE_OPERAND (t, 0)), + build_expr_from_tree (TREE_OPERAND (t, 1)))); case INDIRECT_REF: return build_x_indirect_ref @@ -3568,7 +3567,8 @@ build_expr_from_tree (t) else { tree name = TREE_OPERAND (t, 0); - if (! really_overloaded_fn (name)) + if (TREE_CODE (name) == TEMPLATE_ID_EXPR + || ! really_overloaded_fn (name)) name = build_expr_from_tree (name); return build_x_function_call (name, build_expr_from_tree (TREE_OPERAND (t, 1)), diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index dff871d42888..8e05af3b613f 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -1157,7 +1157,13 @@ comp_template_args (oldargs, newargs) continue; if (TREE_CODE (nt) != TREE_CODE (ot)) return 0; - if (TREE_CODE_CLASS (TREE_CODE (ot)) == 't') + if (TREE_CODE (nt) == TREE_VEC) + { + /* For member templates */ + if (comp_template_args (nt, ot)) + continue; + } + else if (TREE_CODE_CLASS (TREE_CODE (ot)) == 't') { if (comptypes (ot, nt, 1)) continue; @@ -2025,6 +2031,39 @@ lookup_nested_type_by_name (ctype, name) return NULL_TREE; } +/* If arg is a non-type template parameter that does not depend on template + arguments, fold it like we weren't in the body of a template. */ + +static tree +maybe_fold_nontype_arg (arg) + tree arg; +{ + if (TREE_CODE_CLASS (TREE_CODE (arg)) != 't' + && !uses_template_parms (arg)) + { + /* Sometimes, one of the args was an expression involving a + template constant parameter, like N - 1. Now that we've + tsubst'd, we might have something like 2 - 1. This will + confuse lookup_template_class, so we do constant folding + here. We have to unset processing_template_decl, to + fool build_expr_from_tree() into building an actual + tree. */ + + int saved_processing_template_decl = processing_template_decl; + processing_template_decl = 0; + arg = fold (build_expr_from_tree (arg)); + processing_template_decl = saved_processing_template_decl; + } + return arg; +} + +/* Take the tree structure T and replace template parameters used therein + with the argument vector ARGS. NARGS is the number of args; should + be removed. IN_DECL is an associated decl for diagnostics. + + tsubst is used for dealing with types, decls and the like; for + expressions, use tsubst_expr or tsubst_copy. */ + tree tsubst (t, args, nargs, in_decl) tree t, args; @@ -2246,14 +2285,6 @@ tsubst (t, args, nargs, in_decl) type = tsubst (type, args, nargs, in_decl); } - if (type == TREE_TYPE (t) - && (! member || ctx == DECL_CLASS_CONTEXT (t))) - { - t = copy_node (t); - copy_lang_decl (t); - return t; - } - /* Do we already have this instantiation? */ if (DECL_TEMPLATE_INFO (t) != NULL_TREE) { @@ -2262,7 +2293,8 @@ tsubst (t, args, nargs, in_decl) for (; decls; decls = TREE_CHAIN (decls)) if (TREE_TYPE (TREE_VALUE (decls)) == type - && DECL_CLASS_CONTEXT (TREE_VALUE (decls)) == ctx) + && DECL_CLASS_CONTEXT (TREE_VALUE (decls)) == ctx + && comp_template_args (TREE_PURPOSE (decls), args)) return TREE_VALUE (decls); } @@ -2616,24 +2648,8 @@ tsubst (t, args, nargs, in_decl) for (i = 0; i < len; i++) { - elts[i] = tsubst_expr (TREE_VEC_ELT (t, i), args, nargs, in_decl); - - if (TREE_CODE_CLASS (TREE_CODE (elts[i])) != 't' - && !uses_template_parms (elts[i])) - { - /* Sometimes, one of the args was an expression involving a - template constant parameter, like N - 1. Now that we've - tsubst'd, we might have something like 2 - 1. This will - confuse lookup_template_class, so we do constant folding - here. We have to unset processing_template_decl, to - fool build_expr_from_tree() into building an actual - tree. */ - - int saved_processing_template_decl = processing_template_decl; - processing_template_decl = 0; - elts[i] = fold (build_expr_from_tree (elts[i])); - processing_template_decl = saved_processing_template_decl; - } + elts[i] = maybe_fold_nontype_arg + (tsubst_expr (TREE_VEC_ELT (t, i), args, nargs, in_decl)); if (elts[i] != TREE_VEC_ELT (t, i)) need_new = 1; @@ -2847,6 +2863,10 @@ do_poplevel () return t; } +/* Like tsubst, but deals with expressions. This function just replaces + template parms; to finish processing the resultant expression, use + tsubst_expr. */ + tree tsubst_copy (t, args, nargs, in_decl) tree t, args; @@ -2966,7 +2986,7 @@ tsubst_copy (t, args, nargs, in_decl) { tree fn = TREE_OPERAND (t, 0); if (really_overloaded_fn (fn)) - fn = tsubst_copy (TREE_VALUE (fn), args, nargs, in_decl); + fn = tsubst_copy (get_first_fn (fn), args, nargs, in_decl); else fn = tsubst_copy (fn, args, nargs, in_decl); return build_nt @@ -3028,10 +3048,14 @@ tsubst_copy (t, args, nargs, in_decl) case TEMPLATE_ID_EXPR: { - tree r = lookup_template_function - (tsubst_copy (TREE_OPERAND (t, 0), args, nargs, in_decl), - tsubst_copy (TREE_OPERAND (t, 1), args, nargs, in_decl)); - return r; + /* Substituted template arguments */ + tree targs = tsubst_copy (TREE_OPERAND (t, 1), args, nargs, in_decl); + tree chain; + for (chain = targs; chain; chain = TREE_CHAIN (chain)) + TREE_VALUE (chain) = maybe_fold_nontype_arg (TREE_VALUE (chain)); + + return lookup_template_function + (tsubst_copy (TREE_OPERAND (t, 0), args, nargs, in_decl), targs); } case TREE_LIST: @@ -3089,6 +3113,8 @@ tsubst_copy (t, args, nargs, in_decl) } } +/* Like tsubst_copy, but also does semantic processing and RTL expansion. */ + tree tsubst_expr (t, args, nargs, in_decl) tree t, args; diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 9d2589fec6dc..e94fd554057d 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -1306,7 +1306,8 @@ tree get_first_fn (from) tree from; { - if (TREE_CODE (from) == FUNCTION_DECL + if (TREE_CODE (from) == FUNCTION_DECL + || TREE_CODE (from) == TEMPLATE_ID_EXPR || DECL_FUNCTION_TEMPLATE_P (from)) return from; diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 4b774d23220e..54f8c83726ec 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -2281,6 +2281,7 @@ build_x_function_call (function, params, decl) tree function, params, decl; { tree type; + tree template_id = NULL_TREE; int is_method; if (function == error_mark_node) @@ -2289,6 +2290,13 @@ build_x_function_call (function, params, decl) if (processing_template_decl) return build_min_nt (CALL_EXPR, function, params, NULL_TREE); + /* Save explicit template arguments if found */ + if (TREE_CODE (function) == TEMPLATE_ID_EXPR) + { + template_id = function; + function = TREE_OPERAND (function, 0); + } + type = TREE_TYPE (function); if (TREE_CODE (type) == OFFSET_TYPE @@ -2383,6 +2391,9 @@ build_x_function_call (function, params, decl) decl = build_indirect_ref (decl, NULL_PTR); } + /* Put back explicit template arguments, if any. */ + if (template_id) + function = template_id; return build_method_call (decl, function, params, NULL_TREE, LOOKUP_NORMAL); } @@ -2411,7 +2422,12 @@ build_x_function_call (function, params, decl) tree val = TREE_VALUE (function); if (flag_ansi_overloading) - return build_new_function_call (function, params, NULL_TREE); + { + /* Put back explicit template arguments, if any. */ + if (template_id) + function = template_id; + return build_new_function_call (function, params, NULL_TREE); + } if (TREE_CODE (val) == TEMPLATE_DECL) return build_overload_call_real