[multiple changes]

Sat Sep 27 16:22:48 1997  Jason Merrill  <jason@yorick.cygnus.com>

	* friend.c (do_friend): Disable injection for all template-derived
 	decls.
	* decl2.c (lang_decode_option): Handle -fguiding-decls.
	* parse.y (notype_template_declarator): New nonterminal.
	(direct_notype_declarator): Use it.
	(complex_direct_notype_declarator): Likewise.
	(object_template_id): Accept any kind of identifier after TEMPLATE.
	(notype_qualified_id): Don't add template declarators here.

Sat Sep 27 16:21:58 1997  Mark Mitchell  <mmitchell@usa.net>

        * call.c (add_template_candidate): Add explicit_targs parameter.
        (build_scoped_method_call): Use it.
        (build_overload_call_real): Likewise.
        (build_user_type_conversion_1): Likewise.
        (build_new_function_call): Likewise.
        (build_object_call): Likewise.
        (build_new_op): Likewise.
        (build_new_method_call): Likewise.
        (build_new_function_call): Handle TEMPLATE_ID_EXPR.
        (build_new_method_call): Likewise.

        * class.c (finish_struct_methods): Add specialization pass to
        determine which methods were specializing which other methods.
        (instantiate_type): Handle TEMPLATE_ID_EXPR.

        * cp-tree.def (TEMPLATE_ID_EXPR): New tree code.

        * cp-tree.h (name_mangling_version): New variable.
	(flag_guiding_decls): Likewise.
        (build_template_decl_overload): New function.
        (begin_specialization): Likewise.
        (reset_specialization): Likewise.
        (end_specialization): Likewise.
        (determine_explicit_specialization): Likewise.
        (check_explicit_specialization): Likewise.
        (lookup_template_function): Likewise.
        (fn_type_unification): Add explicit_targs parameter.
        (type_unification): Likewise.

        * decl.c (duplicate_decls): Add smarts for explicit
        specializations.
        (grokdeclarator): Handle TEMPLATE_ID_EXPR, and function
        specializations.
        (grokfndecl): Call check_explicit_specialization.

        * decl2.c (lang_decode_option): Handle -fname-mangling-version.
        (build_expr_from_tree): Handle TEMPLATE_ID_EXPR.
        (check_classfn): Handle specializations.

        * error.c (dump_function_name): Print specialization arguments.

	* friend.c (do_friend): Don't call pushdecl for template
        instantiations.

        * init.c (build_member_call): Handle TEMPLATE_ID_EXPR.

        * lang-options.h: Add -fname-mangling-version, -fguiding-decls,
	and -fno-guiding-decls.

        * lex.c (identifier_type): Return PFUNCNAME for template function
        names.

        * method.c (build_decl_overload_real): New function.
        (build_template_parm_names): New function.
        (build_overload_identifier): Use it.
        (build_underscore_int): New function.
        (build_overload_int): Use it.  Add levels for template
        parameters.
        (build_overload_name): Likewise.  Also, handle TYPENAME_TYPEs.
        (build_overload_nested_names): Handle template type parameters.
        (build_template_decl_overload): New function.

        * parse.y (YYSTYPE): New ntype member.
        (nested_name_specifier): Use it.
        (nested_name_specifier_1): Likewise.
        (PFUNCNAME): New token.
        (template_id, object_template_id): New non-terminals.
        (template_parm_list): Note specializations.
        (template_def): Likewise.
        (structsp): Likewise.
        (fn.def2): Handle member template specializations.
        (component_decl_1): Likewise.
        (direct_notype_declarator): Handle template-ids.
        (component_decl_1): Likewise.
        (direct_notype_declarator): Handle template-ids.
        (primary): Handle TEMPLATE_ID_EXPR, and template-ids.

        * pt.c (processing_specializations): New variable.
        (template_header_count): Likewise.
        (type_unification_real): New function.
        (processing_explicit_specialization): Likewise.
        (note_template_header): Likewise.
        (is_member_template): Handle specializations.
        (end_template_decl): Call reset_specialization.
        (push_template_decl): Handle member template specializations.
        (tsubst): Likewise.
        (tsubst_copy): Handle TEMPLATE_ID_EXPR.
        (instantiate_template): Handle specializations.
        (instantiate_decl): Likewise.
        (fn_type_unification): Handle explicit_targs.
        (type_unification): Likewise.  Allow incomplete unification
        without an error message, if allow_incomplete.
        (get_bindings): Use new calling sequence for fn_type_unification.

        * spew.c (yylex): Handle PFUNCNAME.

        * tree.c (is_overloaded_fn): Handle TEMPLATE_ID_EXPR.
        (really_overloaded_fn): Likewise.
        (get_first_fn): Handle function templates.

        * typeck.c (build_x_function_call): Use really_overloaded_fn.
        Handle TEMPLATE_ID_EXPR.
        (build_x_unary_op): Likewise.
        (build_unary_op): Likewise.
        (mark_addressable): Templates whose address is taken are marked
        as used.

From-SVN: r15774
This commit is contained in:
Jason Merrill 1997-09-28 15:16:59 -04:00
parent e741306e3c
commit 386b8a85a6
22 changed files with 6213 additions and 4753 deletions

View File

@ -1,3 +1,123 @@
Sat Sep 27 16:22:48 1997 Jason Merrill <jason@yorick.cygnus.com>
* friend.c (do_friend): Disable injection for all template-derived
decls.
* decl2.c (lang_decode_option): Handle -fguiding-decls.
* parse.y (notype_template_declarator): New nonterminal.
(direct_notype_declarator): Use it.
(complex_direct_notype_declarator): Likewise.
(object_template_id): Accept any kind of identifier after TEMPLATE.
(notype_qualified_id): Don't add template declarators here.
Sat Sep 27 16:21:58 1997 Mark Mitchell <mmitchell@usa.net>
* call.c (add_template_candidate): Add explicit_targs parameter.
(build_scoped_method_call): Use it.
(build_overload_call_real): Likewise.
(build_user_type_conversion_1): Likewise.
(build_new_function_call): Likewise.
(build_object_call): Likewise.
(build_new_op): Likewise.
(build_new_method_call): Likewise.
(build_new_function_call): Handle TEMPLATE_ID_EXPR.
(build_new_method_call): Likewise.
* class.c (finish_struct_methods): Add specialization pass to
determine which methods were specializing which other methods.
(instantiate_type): Handle TEMPLATE_ID_EXPR.
* cp-tree.def (TEMPLATE_ID_EXPR): New tree code.
* cp-tree.h (name_mangling_version): New variable.
(flag_guiding_decls): Likewise.
(build_template_decl_overload): New function.
(begin_specialization): Likewise.
(reset_specialization): Likewise.
(end_specialization): Likewise.
(determine_explicit_specialization): Likewise.
(check_explicit_specialization): Likewise.
(lookup_template_function): Likewise.
(fn_type_unification): Add explicit_targs parameter.
(type_unification): Likewise.
* decl.c (duplicate_decls): Add smarts for explicit
specializations.
(grokdeclarator): Handle TEMPLATE_ID_EXPR, and function
specializations.
(grokfndecl): Call check_explicit_specialization.
* decl2.c (lang_decode_option): Handle -fname-mangling-version.
(build_expr_from_tree): Handle TEMPLATE_ID_EXPR.
(check_classfn): Handle specializations.
* error.c (dump_function_name): Print specialization arguments.
* friend.c (do_friend): Don't call pushdecl for template
instantiations.
* init.c (build_member_call): Handle TEMPLATE_ID_EXPR.
* lang-options.h: Add -fname-mangling-version, -fguiding-decls,
and -fno-guiding-decls.
* lex.c (identifier_type): Return PFUNCNAME for template function
names.
* method.c (build_decl_overload_real): New function.
(build_template_parm_names): New function.
(build_overload_identifier): Use it.
(build_underscore_int): New function.
(build_overload_int): Use it. Add levels for template
parameters.
(build_overload_name): Likewise. Also, handle TYPENAME_TYPEs.
(build_overload_nested_names): Handle template type parameters.
(build_template_decl_overload): New function.
* parse.y (YYSTYPE): New ntype member.
(nested_name_specifier): Use it.
(nested_name_specifier_1): Likewise.
(PFUNCNAME): New token.
(template_id, object_template_id): New non-terminals.
(template_parm_list): Note specializations.
(template_def): Likewise.
(structsp): Likewise.
(fn.def2): Handle member template specializations.
(component_decl_1): Likewise.
(direct_notype_declarator): Handle template-ids.
(component_decl_1): Likewise.
(direct_notype_declarator): Handle template-ids.
(primary): Handle TEMPLATE_ID_EXPR, and template-ids.
* pt.c (processing_specializations): New variable.
(template_header_count): Likewise.
(type_unification_real): New function.
(processing_explicit_specialization): Likewise.
(note_template_header): Likewise.
(is_member_template): Handle specializations.
(end_template_decl): Call reset_specialization.
(push_template_decl): Handle member template specializations.
(tsubst): Likewise.
(tsubst_copy): Handle TEMPLATE_ID_EXPR.
(instantiate_template): Handle specializations.
(instantiate_decl): Likewise.
(fn_type_unification): Handle explicit_targs.
(type_unification): Likewise. Allow incomplete unification
without an error message, if allow_incomplete.
(get_bindings): Use new calling sequence for fn_type_unification.
* spew.c (yylex): Handle PFUNCNAME.
* tree.c (is_overloaded_fn): Handle TEMPLATE_ID_EXPR.
(really_overloaded_fn): Likewise.
(get_first_fn): Handle function templates.
* typeck.c (build_x_function_call): Use really_overloaded_fn.
Handle TEMPLATE_ID_EXPR.
(build_x_unary_op): Likewise.
(build_unary_op): Likewise.
(mark_addressable): Templates whose address is taken are marked
as used.
1997-09-25 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
* decl.c (init_decl_processing): Declare __builtin_constant_p as

View File

@ -23,12 +23,8 @@
+ Static data member templates work.
+ Member function templates are now supported.
+ Partial specialization of class templates is now supported.
+ The new 'template <>' specialization syntax is now accepted and
ignored.
+ Explicit instantiation of template constructors and destructors is
now supported. For instance:
template A<int>::A(const A&);
+ Explicit specification of template parameters to function templates
is now supported.
Things you may need to fix in your code:
@ -43,6 +39,11 @@
http://www.cygnus.com/misc/wp/dec96pub/template.html#temp.res
+ Guiding declarations are no longer supported. Function declarations,
including friend declarations, do not refer to template instantiations.
You can restore the old behavior with -fguiding-decls until you fix
your code.
Other features:
+ Default function arguments in templates will not be evaluated (or
@ -52,13 +53,16 @@
+ The -ftemplate-depth-NN flag can be used to increase the maximum
recursive template instantiation depth, which defaults to 17. If you
need to use this flag, the compiler will tell you.
+ Explicit instantiation of template constructors and destructors is
now supported. For instance:
template A<int>::A(const A&);
Still not supported:
+ Member class templates.
+ Template template parameters.
+ Template friends.
+ Explicit qualification of function templates.
* Exception handling support has been significantly improved and is on by
default. This can result in significant runtime overhead. You can turn
@ -163,3 +167,14 @@
* On the HPPA, some classes that do not define a copy constructor
will be passed and returned in memory again so that functions
returning those types can be inlined.
*** The g++ team thanks everyone that contributed to this release,
but especially:
* Joe Buck <jbuck@synopsys.com>, the maintainer of the g++ FAQ.
* Brendan Kehoe <brendan@cygnus.com>, who coordinates testing of g++.
* Jason Merrill <jason@cygnus.com>, the g++ maintainer.
* Mark Mitchell <mmitchell@usa.net>, who implemented member function
templates and explicit qualification of function templates.
* Mike Stump <mrs@wrs.com>, the previous g++ maintainer, who did most of
the exception handling work.

View File

@ -77,7 +77,7 @@ static tree build_this PROTO((tree));
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));
PROTO((struct z_candidate *, tree, 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
@ -2847,7 +2847,7 @@ build_overload_call_real (fnname, parms, flags, final_cp, require_complete)
i = type_unification (DECL_INNERMOST_TEMPLATE_PARMS (function),
&TREE_VEC_ELT (targs, 0),
TYPE_ARG_TYPES (TREE_TYPE (function)),
parms, &template_cost, 0, 0);
parms, NULL_TREE, &template_cost, 0, 0);
if (i == 0)
{
function = instantiate_template (function, targs);
@ -4144,10 +4144,19 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
return candidates;
}
/* If TMPL can be successfully instantiated as indicated by
EXPLICIT_TARGS and ARGLIST, adds the instantiation to CANDIDATES.
TMPL is the template. EXPLICIT_TARGS are any explicit template arguments.
ARGLIST is the arguments provided at the call-site. The RETURN_TYPE
is the desired type for conversion operators. FLAGS are as for
add_function_candidate. */
static struct z_candidate *
add_template_candidate (candidates, tmpl, arglist, return_type, flags)
add_template_candidate (candidates, tmpl, explicit_targs,
arglist, return_type, flags)
struct z_candidate *candidates;
tree tmpl, arglist, return_type;
tree tmpl, explicit_targs, arglist, return_type;
int flags;
{
int ntparms = DECL_NTPARMS (tmpl);
@ -4156,7 +4165,8 @@ add_template_candidate (candidates, tmpl, arglist, return_type, flags)
int i;
tree fn;
i = fn_type_unification (tmpl, targs, arglist, return_type, 0);
i = fn_type_unification (tmpl, explicit_targs, targs, arglist,
return_type, 0);
if (i != 0)
return candidates;
@ -4182,7 +4192,7 @@ add_template_conv_candidate (candidates, tmpl, obj, arglist, return_type)
int i;
tree fn;
i = fn_type_unification (tmpl, targs, arglist, return_type, 0);
i = fn_type_unification (tmpl, NULL_TREE, targs, arglist, return_type, 0);
if (i != 0)
return candidates;
@ -4312,7 +4322,7 @@ build_user_type_conversion_1 (totype, expr, flags)
templates = decl_tree_cons (NULL_TREE, ctors, templates);
candidates =
add_template_candidate (candidates, ctors,
args, NULL_TREE, flags);
NULL_TREE, args, NULL_TREE, flags);
}
else
candidates = add_function_candidate (candidates, ctors,
@ -4353,8 +4363,8 @@ build_user_type_conversion_1 (totype, expr, flags)
{
templates = decl_tree_cons (NULL_TREE, fn, templates);
candidates =
add_template_candidate (candidates, fn, args,
totype, flags);
add_template_candidate (candidates, fn, NULL_TREE,
args, totype, flags);
}
else
candidates = add_function_candidate (candidates, fn,
@ -4409,9 +4419,10 @@ build_user_type_conversion_1 (totype, expr, flags)
p = &(TREE_OPERAND (*p, 0));
/* Pedantically, normal function declarations are never considered
to refer to template instantiations, but we won't implement that
until we implement full template instantiation syntax. */
if (templates && ! cand->template && ! DECL_INITIAL (cand->fn)
to refer to template instantiations, so we only do this with
-fguiding-decls. */
if (flag_guiding_decls && templates && ! cand->template
&& !DECL_INITIAL (cand->fn)
&& TREE_CODE (TREE_TYPE (cand->fn)) != METHOD_TYPE)
add_maybe_template (cand->fn, templates);
@ -4471,8 +4482,15 @@ build_new_function_call (fn, args, obj)
tree fn, args, obj;
{
struct z_candidate *candidates = 0, *cand;
if (obj == NULL_TREE && TREE_CODE (fn) == TREE_LIST)
tree explicit_targs = NULL_TREE;
if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
{
explicit_targs = TREE_OPERAND (fn, 1);
fn = TREE_OPERAND (fn, 0);
}
if (obj == NULL_TREE && really_overloaded_fn (fn))
{
tree t;
tree templates = NULL_TREE;
@ -4488,9 +4506,10 @@ build_new_function_call (fn, args, obj)
{
templates = decl_tree_cons (NULL_TREE, t, templates);
candidates = add_template_candidate
(candidates, t, args, NULL_TREE, LOOKUP_NORMAL);
(candidates, t, explicit_targs, args, NULL_TREE,
LOOKUP_NORMAL);
}
else
else if (explicit_targs == NULL_TREE)
candidates = add_function_candidate
(candidates, t, args, LOOKUP_NORMAL);
}
@ -4517,9 +4536,10 @@ build_new_function_call (fn, args, obj)
}
/* Pedantically, normal function declarations are never considered
to refer to template instantiations, but we won't implement that
until we implement full template instantiation syntax. */
if (templates && ! cand->template && ! DECL_INITIAL (cand->fn))
to refer to template instantiations, so we only do this with
-fguiding-decls. */
if (flag_guiding_decls && templates && ! cand->template
&& ! DECL_INITIAL (cand->fn))
add_maybe_template (cand->fn, templates);
return build_over_call (cand->fn, cand->convs, args, LOOKUP_NORMAL);
@ -4554,9 +4574,10 @@ build_object_call (obj, args)
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);
candidates
= add_template_candidate (candidates, fn, NULL_TREE,
mem_args, NULL_TREE,
LOOKUP_NORMAL);
}
else
candidates = add_function_candidate
@ -4804,8 +4825,10 @@ build_new_op (code, flags, arg1, arg2, arg3)
if (TREE_CODE (fns) == TEMPLATE_DECL)
{
templates = decl_tree_cons (NULL_TREE, fns, templates);
candidates = add_template_candidate
(candidates, fns, arglist, TREE_TYPE (fnname), flags);
candidates
= add_template_candidate (candidates, fns, NULL_TREE,
arglist, TREE_TYPE (fnname),
flags);
}
else
candidates = add_function_candidate (candidates, fns, arglist, flags);
@ -4833,9 +4856,10 @@ build_new_op (code, flags, arg1, arg2, arg3)
{
/* A member template. */
templates = decl_tree_cons (NULL_TREE, fn, templates);
candidates = add_template_candidate
(candidates, fn, this_arglist,
TREE_TYPE (fnname), LOOKUP_NORMAL);
candidates
= add_template_candidate (candidates, fn, NULL_TREE,
this_arglist, TREE_TYPE
(fnname), LOOKUP_NORMAL);
}
else
candidates = add_function_candidate
@ -4934,9 +4958,10 @@ build_new_op (code, flags, arg1, arg2, arg3)
enforce_access (cand->basetype_path, cand->fn);
/* Pedantically, normal function declarations are never considered
to refer to template instantiations, but we won't implement that
until we implement full template instantiation syntax. */
if (templates && ! cand->template && ! DECL_INITIAL (cand->fn)
to refer to template instantiations, so we only do this with
-fguiding-decls. */
if (flag_guiding_decls && templates && ! cand->template
&& ! DECL_INITIAL (cand->fn)
&& TREE_CODE (TREE_TYPE (cand->fn)) != METHOD_TYPE)
add_maybe_template (cand->fn, templates);
@ -5435,11 +5460,18 @@ build_new_method_call (instance, name, args, basetype_path, flags)
int flags;
{
struct z_candidate *candidates = 0, *cand;
tree explicit_targs = NULL_TREE;
tree basetype, mem_args, fns, instance_ptr;
tree pretty_name;
tree user_args = args;
tree templates = NULL_TREE;
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
{
explicit_targs = TREE_OPERAND (name, 1);
name = TREE_OPERAND (name, 0);
}
/* If there is an extra argument for controlling virtual bases,
remove it for error reporting. */
if (flags & LOOKUP_HAS_IN_CHARGE)
@ -5536,12 +5568,12 @@ build_new_method_call (instance, name, args, basetype_path, flags)
/* A member template. */
templates = decl_tree_cons (NULL_TREE, t, templates);
candidates =
add_template_candidate (candidates, t,
add_template_candidate (candidates, t, explicit_targs,
this_arglist,
TREE_TYPE (name),
LOOKUP_NORMAL);
}
else
else if (explicit_targs == NULL_TREE)
candidates = add_function_candidate (candidates, t,
this_arglist, flags);
@ -5589,9 +5621,10 @@ build_new_method_call (instance, name, args, basetype_path, flags)
flags |= LOOKUP_NONVIRTUAL;
/* Pedantically, normal function declarations are never considered
to refer to template instantiations, but we won't implement that
until we implement full template instantiation syntax. */
if (templates && ! cand->template && ! DECL_INITIAL (cand->fn))
to refer to template instantiations, so we only do this with
-fguiding-decls. */
if (flag_guiding_decls && templates && ! cand->template
&& ! DECL_INITIAL (cand->fn))
add_maybe_template (cand->fn, templates);
return build_over_call

View File

@ -2079,6 +2079,53 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
obstack_free (current_obstack, baselink_vec);
}
/* Now, figure out what any member template specializations were
specializing. */
for (i = 0; i < TREE_VEC_LENGTH (method_vec); ++i)
{
tree fn;
for (fn = TREE_VEC_ELT (method_vec, i);
fn != NULL_TREE;
fn = DECL_CHAIN (fn))
if (DECL_TEMPLATE_SPECIALIZATION (fn))
{
tree f;
tree spec_args;
/* If there is a template, and t uses template parms, wer
are dealing with a specialization of a member
template in a template class, and we must grab the
template, rather than the function. */
if (DECL_TI_TEMPLATE (fn) && uses_template_parms (t))
f = DECL_TI_TEMPLATE (fn);
else
f = fn;
/* We want the specialization arguments, which will be the
innermost ones. */
if (DECL_TI_ARGS (f)
&& TREE_CODE (DECL_TI_ARGS (f)) == TREE_VEC)
spec_args
= TREE_VEC_ELT (DECL_TI_ARGS (f), 0);
else
spec_args = DECL_TI_ARGS (f);
check_explicit_specialization
(lookup_template_function (DECL_NAME (f), spec_args),
f, 0, 1);
/* Now, the assembler name will be correct for fn, so we
make its RTL. */
DECL_RTL (f) = 0;
make_decl_rtl (f, NULL_PTR, 1);
if (f != fn)
{
DECL_RTL (fn) = 0;
make_decl_rtl (fn, NULL_PTR, 1);
}
}
}
return method_vec;
}
@ -4877,6 +4924,8 @@ instantiate_type (lhstype, rhs, complain)
tree lhstype, rhs;
int complain;
{
tree explicit_targs = NULL_TREE;
if (TREE_CODE (lhstype) == UNKNOWN_TYPE)
{
if (complain)
@ -4991,6 +5040,13 @@ instantiate_type (lhstype, rhs, complain)
return rhs;
}
case TEMPLATE_ID_EXPR:
{
explicit_targs = TREE_OPERAND (rhs, 1);
rhs = TREE_OPERAND (rhs, 0);
}
/* fall through */
case TREE_LIST:
{
tree elem, baselink, name;
@ -5025,14 +5081,17 @@ instantiate_type (lhstype, rhs, complain)
if (globals > 0)
{
elem = get_first_fn (rhs);
while (elem)
if (! comptypes (lhstype, TREE_TYPE (elem), 1))
elem = DECL_CHAIN (elem);
else
{
mark_used (elem);
return elem;
}
/* If there are explicit_targs, only a template function
can match. */
if (explicit_targs == NULL_TREE)
while (elem)
if (! comptypes (lhstype, TREE_TYPE (elem), 1))
elem = DECL_CHAIN (elem);
else
{
mark_used (elem);
return elem;
}
/* No exact match found, look for a compatible template. */
{
@ -5046,7 +5105,8 @@ instantiate_type (lhstype, rhs, complain)
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);
TYPE_ARG_TYPES (lhstype), explicit_targs, &d,
1, 1);
if (i == 0)
{
if (save_elem)
@ -5068,38 +5128,47 @@ instantiate_type (lhstype, rhs, complain)
}
}
/* No match found, look for a compatible function. */
elem = get_first_fn (rhs);
while (elem && comp_target_types (lhstype,
TREE_TYPE (elem), 1) <= 0)
elem = DECL_CHAIN (elem);
if (elem)
/* If there are explicit_targs, only a template function
can match. */
if (explicit_targs == NULL_TREE)
{
tree save_elem = elem;
elem = DECL_CHAIN (elem);
/* No match found, look for a compatible function. */
elem = get_first_fn (rhs);
while (elem && comp_target_types (lhstype,
TREE_TYPE (elem), 0) <= 0)
TREE_TYPE (elem), 1) <= 0)
elem = DECL_CHAIN (elem);
if (elem)
{
if (complain)
tree save_elem = elem;
elem = DECL_CHAIN (elem);
while (elem
&& comp_target_types (lhstype,
TREE_TYPE (elem), 0) <= 0)
elem = DECL_CHAIN (elem);
if (elem)
{
cp_error ("cannot resolve overload to target type `%#T'",
lhstype);
cp_error_at (" ambiguity between `%#D'", save_elem);
cp_error_at (" and `%#D', at least", elem);
if (complain)
{
cp_error
("cannot resolve overload to target type `%#T'",
lhstype);
cp_error_at (" ambiguity between `%#D'",
save_elem);
cp_error_at (" and `%#D', at least", elem);
}
return error_mark_node;
}
return error_mark_node;
mark_used (save_elem);
return save_elem;
}
mark_used (save_elem);
return save_elem;
}
if (complain)
{
cp_error ("cannot resolve overload to target type `%#T'",
lhstype);
cp_error (" because no suitable overload of function `%D' exists",
TREE_PURPOSE (rhs));
cp_error
(" because no suitable overload of function `%D' exists",
TREE_PURPOSE (rhs));
}
return error_mark_node;
}

View File

@ -113,6 +113,14 @@ DEFTREECODE (USING_DECL, "using_decl", "d", 0)
/* An un-parsed default argument. Looks like an IDENTIFIER_NODE. */
DEFTREECODE (DEFAULT_ARG, "default_arg", "c", 2)
/* A template-id, like foo<int>. The first operand is the template.
The second is the list of explicitly specified arguments. The
template will be a FUNCTION_DECL, TEMPLATE_DECL, or a list of
overloaded functions and templates if the template-id refers to
a global template. If the template-id refers to a member template,
the template will will be an IDENTIFIER_NODE. */
DEFTREECODE (TEMPLATE_ID_EXPR, "template_id_expr", "e", 2)
/* A whole bunch of tree codes for the initial, superficial parsing of
templates. */
DEFTREECODE (LOOKUP_EXPR, "lookup_expr", "e", 2)

View File

@ -307,6 +307,14 @@ extern int flag_handle_signatures;
inline by default. */
extern int flag_default_inline;
/* The name-mangling scheme to use. Versions of gcc before 2.8 use
version 0. */
extern int name_mangling_version;
/* Nonzero means that guiding declarations are allowed. */
extern int flag_guiding_decls;
/* C++ language-specific tree codes. */
#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) SYM,
@ -2295,6 +2303,7 @@ extern void report_type_mismatch PROTO((struct candidate *, tree, char *));
extern char *build_overload_name PROTO((tree, int, int));
extern tree build_static_name PROTO((tree, tree));
extern tree build_decl_overload PROTO((tree, tree, int));
extern tree build_template_decl_overload PROTO((tree, tree, tree, tree, tree, int));
extern tree build_typename_overload PROTO((tree));
extern tree build_overload_with_type PROTO((tree, tree));
extern tree build_opfncall PROTO((enum tree_code, int, tree, tree, tree));
@ -2312,18 +2321,24 @@ 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 void begin_specialization PROTO((void));
extern void reset_specialization PROTO((void));
extern void end_specialization PROTO((void));
extern tree determine_explicit_specialization PROTO((tree, tree, tree *, int, int));
extern int check_explicit_specialization PROTO((tree, tree, int, int));
extern tree process_template_parm PROTO((tree, tree));
extern tree end_template_parm_list PROTO((tree));
extern void end_template_decl PROTO((void));
extern tree current_template_args PROTO((void));
extern void push_template_decl PROTO((tree));
extern tree lookup_template_class PROTO((tree, tree, tree));
extern tree lookup_template_function PROTO((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));
extern int fn_type_unification PROTO((tree, tree, tree, tree, tree, int));
extern int type_unification PROTO((tree, tree *, tree, tree, tree, int *, int, int));
struct tinst_level *tinst_for_decl PROTO((void));
extern void mark_decl_instantiated PROTO((tree, int));
extern int more_specialized PROTO((tree, tree));

View File

@ -157,9 +157,9 @@ static tree maybe_build_cleanup_1 PROTO((tree, tree));
static tree lookup_name_real PROTO((tree, int, int));
static void warn_extern_redeclared_static PROTO((tree, tree));
static void grok_reference_init PROTO((tree, tree, tree, tree *));
static tree grokfndecl PROTO((tree, tree, tree, int,
static tree grokfndecl PROTO((tree, tree, tree, tree, int,
enum overload_flags,
tree, tree, tree, int, int, int, int));
tree, tree, tree, int, int, int, int, int, int));
static tree grokvardecl PROTO((tree, tree, RID_BIT_TYPE *, int, int));
static tree lookup_tag PROTO((enum tree_code, tree,
struct binding_level *, int));
@ -2563,6 +2563,20 @@ duplicate_decls (newdecl, olddecl)
cp_error_at ("previous declaration as `%#D'", olddecl);
}
}
else if ((TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_TEMPLATE_SPECIALIZATION (olddecl)
&& (!DECL_TEMPLATE_SPECIALIZATION (newdecl)
|| (DECL_TI_TEMPLATE (newdecl)
!= DECL_TI_TEMPLATE (olddecl))))
|| (TREE_CODE (newdecl) == FUNCTION_DECL
&& DECL_TEMPLATE_SPECIALIZATION (newdecl)
&& (!DECL_TEMPLATE_SPECIALIZATION (olddecl)
|| (DECL_TI_TEMPLATE (olddecl) != DECL_TI_TEMPLATE
(newdecl)))))
/* It's OK to have a template specialization and a non-template
with the same type, or to have specializations of two
different templates with the same type. */
return 0;
else
{
char *errmsg = redeclaration_error_message (newdecl, olddecl);
@ -3030,7 +3044,9 @@ pushdecl (x)
char *file;
int line;
#endif
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
name = TREE_OPERAND (name, 0);
t = lookup_name_current_level (name);
if (t == error_mark_node)
{
@ -7173,14 +7189,16 @@ bad_specifiers (object, type, virtualp, quals, inlinep, friendp, raises)
not look, and -1 if we should not call `grokclassfn' at all. */
static tree
grokfndecl (ctype, type, declarator, virtualp, flags, quals,
raises, attrlist, check, publicp, inlinep, funcdef_flag)
grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
raises, attrlist, check, friendp, publicp, inlinep, funcdef_flag,
template_count)
tree ctype, type;
tree declarator;
tree orig_declarator;
int virtualp;
enum overload_flags flags;
tree quals, raises, attrlist;
int check, publicp, inlinep, funcdef_flag;
int check, friendp, publicp, inlinep, funcdef_flag, template_count;
{
tree cname, decl;
int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
@ -7255,6 +7273,11 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
}
/* Caller will do the rest of this. */
check_explicit_specialization (orig_declarator, decl,
template_count,
funcdef_flag ? 2 :
(friendp ? 3 : 0));
if (check < 0)
return decl;
@ -7272,6 +7295,7 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
DECL_CONSTRUCTOR_P (decl) = 1;
grokclassfn (ctype, declarator, decl, flags, quals);
if (check)
{
tmp = check_classfn (ctype, decl);
@ -7596,6 +7620,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
enum overload_flags flags = NO_SPECIAL;
tree quals = NULL_TREE;
tree raises = NULL_TREE;
int template_count = 0;
RIDBIT_RESET_ALL (specbits);
if (decl_context == FUNCDEF)
@ -7709,9 +7734,27 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
}
ctype = NULL_TREE;
break;
case TEMPLATE_ID_EXPR:
{
tree fns = TREE_OPERAND (decl, 0);
if (TREE_CODE (fns) == LOOKUP_EXPR)
fns = TREE_OPERAND (fns, 0);
if (TREE_CODE (fns) == IDENTIFIER_NODE)
dname = fns;
else if (really_overloaded_fn (fns))
dname = DECL_NAME (get_first_fn (fns));
else
dname = DECL_NAME (fns);
}
/* fall through */
case IDENTIFIER_NODE:
dname = decl;
if (TREE_CODE (decl) == IDENTIFIER_NODE)
dname = decl;
next = 0;
if (is_rid (dname))
@ -8407,7 +8450,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
Descend through it, creating more complex types, until we reach
the declared identifier (or NULL_TREE, in an absolute declarator). */
while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE)
while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE
&& TREE_CODE (declarator) != TEMPLATE_ID_EXPR)
{
/* Each level of DECLARATOR is either an ARRAY_REF (for ...[..]),
an INDIRECT_REF (for *...),
@ -8661,6 +8705,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
if (inner_decl && TREE_CODE (inner_decl) == SCOPE_REF)
inner_decl = TREE_OPERAND (inner_decl, 1);
if (inner_decl && TREE_CODE (inner_decl) == TEMPLATE_ID_EXPR)
inner_decl = dname;
/* Pick up type qualifiers which should be applied to `this'. */
quals = TREE_OPERAND (declarator, 2);
@ -8670,9 +8717,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
/* Say it's a definition only for the CALL_EXPR
closest to the identifier. */
funcdecl_p
= inner_decl && (TREE_CODE (inner_decl) == IDENTIFIER_NODE
|| TREE_CODE (inner_decl) == BIT_NOT_EXPR);
= inner_decl
&& (TREE_CODE (inner_decl) == IDENTIFIER_NODE
|| TREE_CODE (inner_decl) == TEMPLATE_ID_EXPR
|| TREE_CODE (inner_decl) == BIT_NOT_EXPR);
if (ctype == NULL_TREE
&& decl_context == FIELD
&& funcdecl_p
@ -8961,6 +9010,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
resolve to. The code here just needs to build
up appropriate member types. */
tree sname = TREE_OPERAND (declarator, 1);
tree t;
/* Destructors can have their visibilities changed as well. */
if (TREE_CODE (sname) == BIT_NOT_EXPR)
sname = TREE_OPERAND (sname, 0);
@ -9012,6 +9063,18 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
}
ctype = TREE_OPERAND (declarator, 0);
t = ctype;
while (t != NULL_TREE)
{
if (CLASSTYPE_TEMPLATE_INFO (t))
template_count += 1;
t = TYPE_MAIN_DECL (t);
if (DECL_LANG_SPECIFIC (t))
t = DECL_CLASS_CONTEXT (t);
else
t = NULL_TREE;
}
if (sname == NULL_TREE)
goto done_scoping;
@ -9430,10 +9493,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
/* Tell grokfndecl if it needs to set TREE_PUBLIC on the node. */
publicp = (! friendp || ! staticp);
decl = grokfndecl (ctype, type, declarator,
decl = grokfndecl (ctype, type,
TREE_CODE (declarator) != TEMPLATE_ID_EXPR
? declarator : dname,
declarator,
virtualp, flags, quals, raises, attrlist,
friendp ? -1 : 0, publicp, inlinep,
funcdef_flag);
friendp ? -1 : 0, friendp, publicp, inlinep,
funcdef_flag, template_count);
if (decl == NULL_TREE)
return NULL_TREE;
#if 0
@ -9451,9 +9517,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
members of other classes. */
/* All method decls are public, so tell grokfndecl to set
TREE_PUBLIC, also. */
decl = grokfndecl (ctype, type, declarator,
decl = grokfndecl (ctype, type, declarator, declarator,
virtualp, flags, quals, raises, attrlist,
friendp ? -1 : 0, 1, 0, funcdef_flag);
friendp ? -1 : 0, friendp, 1, 0, funcdef_flag,
template_count);
if (decl == NULL_TREE)
return NULL_TREE;
}
@ -9578,12 +9645,17 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
}
else if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE)
{
tree original_name = declarator;
tree original_name;
int publicp = 0;
if (! declarator)
return NULL_TREE;
if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
original_name = dname;
else
original_name = declarator;
if (RIDBIT_SETP (RID_AUTO, specbits))
error ("storage class `auto' invalid for function `%s'", name);
else if (RIDBIT_SETP (RID_REGISTER, specbits))
@ -9621,7 +9693,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
&& IDENTIFIER_POINTER (original_name)[1] == '_'
&& strncmp (IDENTIFIER_POINTER (original_name)+2, "builtin_", 8) == 0))
/* Plain overloading: will not be grok'd by grokclassfn. */
declarator = build_decl_overload (dname, TYPE_ARG_TYPES (type), 0);
if (name_mangling_version < 1
|| TREE_CODE (declarator) != TEMPLATE_ID_EXPR)
declarator = build_decl_overload (dname, TYPE_ARG_TYPES (type), 0);
}
else if (TREE_CODE (type) == FUNCTION_TYPE && staticp < 2)
type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep),
@ -9632,16 +9706,19 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
|| RIDBIT_SETP (RID_EXTERN, specbits)
|| !RIDBIT_SETP (RID_STATIC, specbits));
decl = grokfndecl (ctype, type, original_name,
decl = grokfndecl (ctype, type, original_name, declarator,
virtualp, flags, quals, raises, attrlist,
friendp ? 2 : 1,
publicp, inlinep, funcdef_flag);
friendp ? 2 : 1, friendp,
publicp, inlinep, funcdef_flag,
template_count);
if (decl == NULL_TREE)
return NULL_TREE;
if (ctype == NULL_TREE && DECL_LANGUAGE (decl) != lang_c)
if (ctype == NULL_TREE && DECL_LANGUAGE (decl) != lang_c
&& (!DECL_TEMPLATE_SPECIALIZATION (decl) ||
name_mangling_version < 1))
DECL_ASSEMBLER_NAME (decl) = current_namespace_id (declarator);
if (staticp == 1)
{
int illegal_static = 0;

View File

@ -406,6 +406,14 @@ int flag_weak = 1;
int max_tinst_depth = 17;
/* The name-mangling scheme to use. Must be 1 or greater to support
template functions with identical types, but different template
arguments. */
int name_mangling_version = 1;
/* Nonzero means that guiding declarations are allowed. */
int flag_guiding_decls;
/* Table of language-dependent -f options.
STRING is the option name. VARIABLE is the address of the variable.
ON_VALUE is the value to store in VARIABLE
@ -526,6 +534,17 @@ lang_decode_option (p)
flag_implicit_templates = 0;
found = 1;
}
else if (!strcmp (p, "guiding-decls"))
{
flag_guiding_decls = 1;
name_mangling_version = 0;
found = 1;
}
else if (!strcmp (p, "no-guiding-decls"))
{
flag_guiding_decls = 0;
found = 1;
}
else if (!strncmp (p, "template-depth-", 15))
{
char *endp = p + 15;
@ -542,6 +561,22 @@ lang_decode_option (p)
max_tinst_depth = atoi (p + 15);
template_depth_lose: ;
}
else if (!strncmp (p, "name-mangling-version-", 22))
{
char *endp = p + 22;
while (*endp)
{
if (*endp >= '0' && *endp <= '9')
endp++;
else
{
error ("Invalid option `%s'", p - 2);
goto mangling_version_lose;
}
}
name_mangling_version = atoi (p + 22);
mangling_version_lose:
}
else for (j = 0;
!found && j < sizeof (lang_f_options) / sizeof (lang_f_options[0]);
j++)
@ -1395,10 +1430,15 @@ check_classfn (ctype, function)
if (comptypes (TREE_TYPE (TREE_TYPE (function)),
TREE_TYPE (TREE_TYPE (fndecl)), 1)
&& compparms (p1, p2, 3))
&& compparms (p1, p2, 3)
&& (DECL_TEMPLATE_SPECIALIZATION (function)
== DECL_TEMPLATE_SPECIALIZATION (fndecl))
&& (!DECL_TEMPLATE_SPECIALIZATION (function)
|| (DECL_TI_TEMPLATE (function)
== DECL_TI_TEMPLATE (fndecl))))
return fndecl;
if (is_member_template (fndecl))
if (is_member_template (fndecl))
/* This function might be an instantiation
or specialization of fndecl. */
templates =
@ -3368,6 +3408,12 @@ build_expr_from_tree (t)
else
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)));
case INDIRECT_REF:
return build_x_indirect_ref
(build_expr_from_tree (TREE_OPERAND (t, 0)), "unary *");

View File

@ -924,6 +924,71 @@ dump_function_name (t)
}
else
dump_decl (name, 0);
if (DECL_TEMPLATE_SPECIALIZATION (t) || DECL_IMPLICIT_INSTANTIATION (t))
{
tree args = DECL_TEMPLATE_INFO (t)
? DECL_TI_ARGS (t) : NULL_TREE;
OB_PUTC ('<');
/* Be careful only to print things when we have them, so as not
to crash producing error messages. */
if (args)
{
if (TREE_CODE (args) == TREE_LIST)
{
tree arg;
int need_comma = 0;
for (arg = args; arg; arg = TREE_CHAIN (arg))
{
tree a = TREE_VALUE (arg);
if (need_comma)
OB_PUTS (", ");
if (a)
{
if (TREE_CODE_CLASS (TREE_CODE (a)) == 't')
dump_type (a, 0);
else
dump_expr (a, 0);
}
need_comma = 1;
}
}
else if (TREE_CODE (args) == TREE_VEC)
{
int i;
int need_comma = 0;
if (TREE_VEC_LENGTH (args) > 0
&& TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
args = TREE_VEC_ELT (args, 0);
for (i = 0; i < TREE_VEC_LENGTH (args); i++)
{
tree a = TREE_VEC_ELT (args, i);
if (need_comma)
OB_PUTS (", ");
if (a)
{
if (TREE_CODE_CLASS (TREE_CODE (a)) == 't')
dump_type (a, 0);
else
dump_expr (a, 0);
}
need_comma = 1;
}
}
}
OB_PUTC ('>');
}
}
static void

View File

@ -380,9 +380,11 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag)
if (funcdef_flag)
DECL_CLASS_CONTEXT (decl) = current_class_type;
/* We can call pushdecl here, because the TREE_CHAIN of this
FUNCTION_DECL is not needed for other purposes. */
decl = pushdecl (decl);
if (! DECL_USE_TEMPLATE (decl))
/* We can call pushdecl here, because the TREE_CHAIN of this
FUNCTION_DECL is not needed for other purposes. Don't do this
for a template instantiation. */
decl = pushdecl (decl);
make_decl_rtl (decl, NULL_PTR, 1);
add_friend (current_class_type, decl);

View File

@ -1669,12 +1669,23 @@ For example @code{Foo::\u0319::Bar} is encoded as
@subsection Templates
A template instantiation is encoded as the letter @samp{t},
A class template instantiation is encoded as the letter @samp{t},
followed by the encoding of the template name, followed
the number of template parameters, followed by encoding of the template
parameters. If a template parameter is a type, it is written
as a @samp{Z} followed by the encoding of the type.
A function template specialization (either an instantiation or an
explicit specialization) is encoded by an @samp{H} followed by the
encoding of the template parameters, as described above, followed by
an @samp{_}, the encoding of the argument types template function (not the
specialization), another @samp{_}, and the return type. (Like the
argument types, the return type is the return type of the function
template, not the specialization.) Template parameters in the argument
and return types are encoded by an @samp{X} for type parameters, or a
@samp{Y} for constant parameters, and an index indicating their position
in the template parameter list declaration.
@subsection Arrays
C++ array types are mangled by emitting @samp{A}, followed by
@ -1720,6 +1731,9 @@ Encodes the C++ and Java @code{float} types.
@item F
Used to indicate a function type.
@item H
Used to indicate a template function.
@item i
Encodes the C++ and Java @code{int} types.
@ -1775,6 +1789,12 @@ Encodes the C++ @code{wchar_t} type, and the Java @code{char} types.
@item x
Encodes the GNU C++ @code{long long} type, and the Java @code{long} type.
@item X
Encodes a template type parameter, when part of a function type.
@item Y
Encodes a template constant parameter, when part of a function type.
@item Z
Used for template type parameters.

View File

@ -1681,7 +1681,7 @@ build_member_call (type, name, parmlist)
tree type, name, parmlist;
{
tree t;
tree method_name = name;
tree method_name;
int dtor = 0;
int dont_use_this = 0;
tree basetype_path, decl;
@ -1690,6 +1690,11 @@ build_member_call (type, name, parmlist)
return build_x_function_call (do_scoped_id (name, 0), parmlist,
current_class_ref);
if (TREE_CODE (name) != TEMPLATE_ID_EXPR)
method_name = name;
else
method_name = TREE_OPERAND (name, 0);
if (TREE_CODE (method_name) == BIT_NOT_EXPR)
{
method_name = TREE_OPERAND (method_name, 0);
@ -1758,7 +1763,10 @@ build_member_call (type, name, parmlist)
|| method_name == constructor_name_full (type))
return build_functional_cast (type, parmlist);
if (t = lookup_fnfields (basetype_path, method_name, 0))
return build_method_call (decl, method_name, parmlist, basetype_path,
return build_method_call (decl,
TREE_CODE (name) == TEMPLATE_ID_EXPR
? name : method_name,
parmlist, basetype_path,
LOOKUP_NORMAL|LOOKUP_NONVIRTUAL);
if (TREE_CODE (name) == IDENTIFIER_NODE
&& ((t = lookup_field (TYPE_BINFO (type), name, 1, 0))))

View File

@ -48,6 +48,8 @@ Boston, MA 02111-1307, USA. */
"-fno-external-templates",
"-ffor-scope",
"-fno-for-scope",
"-fguiding-decls",
"-fno-guiding-decls",
"-fgnu-keywords",
"-fno-gnu-keywords",
"-fhandle-exceptions",
@ -64,6 +66,7 @@ Boston, MA 02111-1307, USA. */
"-fno-labels-ok",
"-fmemoize-lookups",
"-fno-memoize-lookups",
"-fname-mangling-version-",
"-fnonnull-objects",
"-fno-nonnull-objects",
"-foperator-names",

View File

@ -2729,6 +2729,15 @@ identifier_type (decl)
{
if (TREE_CODE (DECL_RESULT (decl)) == TYPE_DECL)
return PTYPENAME;
else if (looking_for_template)
return PFUNCNAME;
}
if (looking_for_template && really_overloaded_fn (decl))
{
tree t;
for (t = TREE_VALUE (decl); t != NULL_TREE; t = DECL_CHAIN (t))
if (DECL_FUNCTION_TEMPLATE_P (t))
return PFUNCNAME;
}
if (TREE_CODE (decl) == NAMESPACE_DECL)
return NSNAME;

View File

@ -71,6 +71,10 @@ static char *thunk_printable_name PROTO((tree));
static void do_build_assign_ref PROTO((tree));
static void do_build_copy_constructor PROTO((tree));
static tree largest_union_member PROTO((tree));
static tree build_decl_overload_real PROTO((tree, tree, tree, tree,
tree, int));
static void build_template_parm_names PROTO((tree, tree));
static void build_underscore_int PROTO((int));
# define OB_INIT() (scratch_firstobj ? (obstack_free (&scratch_obstack, scratch_firstobj), 0) : 0)
# define OB_PUTC(C) (obstack_1grow (&scratch_obstack, (C)))
@ -383,9 +387,16 @@ build_overload_nested_name (decl)
if (DECL_CONTEXT (decl))
{
tree context = DECL_CONTEXT (decl);
if (TREE_CODE_CLASS (TREE_CODE (context)) == 't')
context = TYPE_NAME (context);
build_overload_nested_name (context);
/* For a template type parameter, we want to output an 'Xn'
rather than 'T' or some such. */
if (TREE_CODE (context) == TEMPLATE_TYPE_PARM)
build_overload_name (context, 0, 0);
else
{
if (TREE_CODE_CLASS (TREE_CODE (context)) == 't')
context = TYPE_NAME (context);
build_overload_nested_name (context);
}
}
if (TREE_CODE (decl) == FUNCTION_DECL)
@ -406,6 +417,16 @@ build_overload_nested_name (decl)
build_overload_identifier (decl);
}
static void
build_underscore_int (int i)
{
if (i > 9)
OB_PUTC ('_');
icat (i);
if (i > 9)
OB_PUTS ('_');
}
/* Encoding for an INTEGER_CST value. */
static void
@ -416,11 +437,8 @@ build_overload_int (value, in_template)
if (TREE_CODE (value) == TEMPLATE_CONST_PARM)
{
OB_PUTC ('Y');
if (TEMPLATE_CONST_IDX (value) > 9)
OB_PUTC ('_');
icat (TEMPLATE_CONST_IDX (value));
if (TEMPLATE_CONST_IDX (value) > 9)
OB_PUTC ('_');
build_underscore_int (TEMPLATE_CONST_IDX (value));
build_underscore_int (TEMPLATE_CONST_LEVEL (value));
return;
}
else if (in_template
@ -633,6 +651,41 @@ build_overload_value (type, value, in_template)
}
}
/* Add encodings for the vector of template parameters in PARMLIST,
given the vector of arguments to be substituted in ARGLIST. */
void
build_template_parm_names (parmlist, arglist)
tree parmlist;
tree arglist;
{
int i, nparms;
nparms = TREE_VEC_LENGTH (parmlist);
icat (nparms);
for (i = 0; i < nparms; i++)
{
tree parm = TREE_VALUE (TREE_VEC_ELT (parmlist, i));
tree arg = TREE_VEC_ELT (arglist, i);
if (TREE_CODE (parm) == TYPE_DECL)
{
/* This parameter is a type. */
OB_PUTC ('Z');
build_overload_name (arg, 0, 0);
}
else
{
parm = tsubst (parm, arglist,
TREE_VEC_LENGTH (arglist), NULL_TREE);
/* It's a PARM_DECL. */
build_overload_name (TREE_TYPE (parm), 0, 0);
build_overload_value (parm, arg, uses_template_parms (arglist));
}
}
}
static void
build_overload_identifier (name)
tree name;
@ -643,36 +696,15 @@ build_overload_identifier (name)
&& PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (TREE_TYPE (name))))
{
tree template, parmlist, arglist, tname;
int i, nparms;
template = CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (name));
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));
OB_PUTID (tname);
icat (nparms);
for (i = 0; i < nparms; i++)
{
tree parm = TREE_VALUE (TREE_VEC_ELT (parmlist, i));
tree arg = TREE_VEC_ELT (arglist, i);
if (TREE_CODE (parm) == TYPE_DECL)
{
/* This parameter is a type. */
OB_PUTC ('Z');
build_overload_name (arg, 0, 0);
}
else
{
parm = tsubst (parm, arglist,
TREE_VEC_LENGTH (arglist), NULL_TREE);
/* It's a PARM_DECL. */
build_overload_name (TREE_TYPE (parm), 0, 0);
build_overload_value (parm, arg, uses_template_parms (arglist));
}
}
build_template_parm_names (parmlist, arglist);
}
else
{
@ -1012,22 +1044,18 @@ build_overload_name (parmtypes, begin, end)
case TEMPLATE_TYPE_PARM:
OB_PUTC ('X');
if (TEMPLATE_TYPE_IDX (parmtype) > 9)
OB_PUTC ('_');
icat (TEMPLATE_TYPE_IDX (parmtype));
if (TEMPLATE_TYPE_IDX (parmtype) > 9)
OB_PUTC ('_');
build_underscore_int (TEMPLATE_TYPE_IDX (parmtype));
build_underscore_int (TEMPLATE_TYPE_LEVEL (parmtype));
break;
case TYPENAME_TYPE:
/* We don't ever want this output, but it's inconvenient not to
be able to build the string. This should cause assembler
errors we'll notice. */
{
static int n;
sprintf (digit_buffer, " *%d", n++);
OB_PUTCP (digit_buffer);
}
/* When mangling the type of a function template whose
declaration looks like:
template <class T> void foo(typename T::U)
we have to mangle these. */
build_qualified_name (parmtype);
break;
default:
@ -1075,19 +1103,14 @@ build_static_name (context, name)
return get_identifier ((char *)obstack_base (&scratch_obstack));
}
/* Change the name of a function definition so that it may be
overloaded. NAME is the name of the function to overload,
PARMS is the parameter list (which determines what name the
final function obtains).
FOR_METHOD is 1 if this overload is being performed
for a method, rather than a function type. It is 2 if
this overload is being performed for a constructor. */
tree
build_decl_overload (dname, parms, for_method)
tree
build_decl_overload_real (dname, parms, ret_type, tparms, targs,
for_method)
tree dname;
tree parms;
tree ret_type;
tree tparms;
tree targs;
int for_method;
{
char *name = IDENTIFIER_POINTER (dname);
@ -1121,6 +1144,8 @@ build_decl_overload (dname, parms, for_method)
/* We can get away without doing this. */
OB_PUTC ('M');
#endif
if (tparms != NULL_TREE)
OB_PUTC ('H');
{
tree this_type = TREE_VALUE (parms);
@ -1133,12 +1158,18 @@ build_decl_overload (dname, parms, for_method)
}
}
else
OB_PUTC ('F');
OB_PUTC ((tparms != NULL_TREE) ? 'H' : 'F');
if (tparms)
{
build_template_parm_names (tparms, targs);
OB_PUTC ('_');
}
if (parms == NULL_TREE)
OB_PUTC2 ('e', '\0');
OB_PUTC ('e');
else if (parms == void_list_node)
OB_PUTC2 ('v', '\0');
OB_PUTC ('v');
else
{
ALLOCATE_TYPEVEC (parms);
@ -1151,14 +1182,23 @@ build_decl_overload (dname, parms, for_method)
TREE_USED (TREE_VALUE (parms)) = 1;
if (TREE_CHAIN (parms))
build_overload_name (TREE_CHAIN (parms), 0, 1);
build_overload_name (TREE_CHAIN (parms), 0, 0);
else
OB_PUTC2 ('e', '\0');
OB_PUTC ('e');
}
else
build_overload_name (parms, 0, 1);
build_overload_name (parms, 0, 0);
DEALLOCATE_TYPEVEC (parms);
}
if (ret_type != NULL_TREE)
{
/* Add the return type. */
OB_PUTC ('_');
build_overload_name (ret_type, 0, 0);
}
OB_FINISH ();
{
tree n = get_identifier (obstack_base (&scratch_obstack));
if (IDENTIFIER_OPNAME_P (dname))
@ -1167,6 +1207,43 @@ build_decl_overload (dname, parms, for_method)
}
}
/* Change the name of a function definition so that it may be
overloaded. NAME is the name of the function to overload,
PARMS is the parameter list (which determines what name the
final function obtains).
FOR_METHOD is 1 if this overload is being performed
for a method, rather than a function type. It is 2 if
this overload is being performed for a constructor. */
tree
build_decl_overload (dname, parms, for_method)
tree dname;
tree parms;
int for_method;
{
return build_decl_overload_real (dname, parms, NULL_TREE, NULL_TREE,
NULL_TREE, for_method);
}
/* Like build_decl_overload, but for template functions. */
tree
build_template_decl_overload (dname, parms, ret_type, tparms, targs,
for_method)
tree dname;
tree parms;
tree ret_type;
tree tparms;
tree targs;
int for_method;
{
return build_decl_overload_real (dname, parms, ret_type, tparms, targs,
for_method);
}
/* Build an overload name for the type expression TYPE. */
tree

File diff suppressed because it is too large Load Diff

View File

@ -2,89 +2,90 @@ typedef union {long itype; tree ttype; char *strtype; enum tree_code code; flagg
#define IDENTIFIER 258
#define TYPENAME 259
#define SELFNAME 260
#define SCSPEC 261
#define TYPESPEC 262
#define CV_QUALIFIER 263
#define CONSTANT 264
#define STRING 265
#define ELLIPSIS 266
#define SIZEOF 267
#define ENUM 268
#define IF 269
#define ELSE 270
#define WHILE 271
#define DO 272
#define FOR 273
#define SWITCH 274
#define CASE 275
#define DEFAULT 276
#define BREAK 277
#define CONTINUE 278
#define RETURN 279
#define GOTO 280
#define ASM_KEYWORD 281
#define GCC_ASM_KEYWORD 282
#define TYPEOF 283
#define ALIGNOF 284
#define SIGOF 285
#define ATTRIBUTE 286
#define EXTENSION 287
#define LABEL 288
#define REALPART 289
#define IMAGPART 290
#define AGGR 291
#define VISSPEC 292
#define DELETE 293
#define NEW 294
#define THIS 295
#define OPERATOR 296
#define CXX_TRUE 297
#define CXX_FALSE 298
#define NAMESPACE 299
#define TYPENAME_KEYWORD 300
#define USING 301
#define LEFT_RIGHT 302
#define TEMPLATE 303
#define TYPEID 304
#define DYNAMIC_CAST 305
#define STATIC_CAST 306
#define REINTERPRET_CAST 307
#define CONST_CAST 308
#define SCOPE 309
#define EMPTY 310
#define PTYPENAME 311
#define NSNAME 312
#define THROW 313
#define ASSIGN 314
#define OROR 315
#define ANDAND 316
#define MIN_MAX 317
#define EQCOMPARE 318
#define ARITHCOMPARE 319
#define LSHIFT 320
#define RSHIFT 321
#define POINTSAT_STAR 322
#define DOT_STAR 323
#define UNARY 324
#define PLUSPLUS 325
#define MINUSMINUS 326
#define HYPERUNARY 327
#define PAREN_STAR_PAREN 328
#define POINTSAT 329
#define TRY 330
#define CATCH 331
#define TYPENAME_ELLIPSIS 332
#define PRE_PARSED_FUNCTION_DECL 333
#define EXTERN_LANG_STRING 334
#define ALL 335
#define PRE_PARSED_CLASS_DECL 336
#define DEFARG 337
#define DEFARG_MARKER 338
#define TYPENAME_DEFN 339
#define IDENTIFIER_DEFN 340
#define PTYPENAME_DEFN 341
#define END_OF_LINE 342
#define END_OF_SAVED_INPUT 343
#define PFUNCNAME 261
#define SCSPEC 262
#define TYPESPEC 263
#define CV_QUALIFIER 264
#define CONSTANT 265
#define STRING 266
#define ELLIPSIS 267
#define SIZEOF 268
#define ENUM 269
#define IF 270
#define ELSE 271
#define WHILE 272
#define DO 273
#define FOR 274
#define SWITCH 275
#define CASE 276
#define DEFAULT 277
#define BREAK 278
#define CONTINUE 279
#define RETURN 280
#define GOTO 281
#define ASM_KEYWORD 282
#define GCC_ASM_KEYWORD 283
#define TYPEOF 284
#define ALIGNOF 285
#define SIGOF 286
#define ATTRIBUTE 287
#define EXTENSION 288
#define LABEL 289
#define REALPART 290
#define IMAGPART 291
#define AGGR 292
#define VISSPEC 293
#define DELETE 294
#define NEW 295
#define THIS 296
#define OPERATOR 297
#define CXX_TRUE 298
#define CXX_FALSE 299
#define NAMESPACE 300
#define TYPENAME_KEYWORD 301
#define USING 302
#define LEFT_RIGHT 303
#define TEMPLATE 304
#define TYPEID 305
#define DYNAMIC_CAST 306
#define STATIC_CAST 307
#define REINTERPRET_CAST 308
#define CONST_CAST 309
#define SCOPE 310
#define EMPTY 311
#define PTYPENAME 312
#define NSNAME 313
#define THROW 314
#define ASSIGN 315
#define OROR 316
#define ANDAND 317
#define MIN_MAX 318
#define EQCOMPARE 319
#define ARITHCOMPARE 320
#define LSHIFT 321
#define RSHIFT 322
#define POINTSAT_STAR 323
#define DOT_STAR 324
#define UNARY 325
#define PLUSPLUS 326
#define MINUSMINUS 327
#define HYPERUNARY 328
#define PAREN_STAR_PAREN 329
#define POINTSAT 330
#define TRY 331
#define CATCH 332
#define TYPENAME_ELLIPSIS 333
#define PRE_PARSED_FUNCTION_DECL 334
#define EXTERN_LANG_STRING 335
#define ALL 336
#define PRE_PARSED_CLASS_DECL 337
#define DEFARG 338
#define DEFARG_MARKER 339
#define TYPENAME_DEFN 340
#define IDENTIFIER_DEFN 341
#define PTYPENAME_DEFN 342
#define END_OF_LINE 343
#define END_OF_SAVED_INPUT 344
extern YYSTYPE yylval;

View File

@ -110,6 +110,9 @@ empty_parms ()
%token TYPENAME
%token SELFNAME
/* A template function. */
%token <ttype> PFUNCNAME
/* Reserved words that specify storage class.
yylval contains an IDENTIFIER_NODE which indicates which one. */
%token SCSPEC
@ -162,7 +165,7 @@ empty_parms ()
%nonassoc IF
%nonassoc ELSE
%left IDENTIFIER TYPENAME SELFNAME PTYPENAME SCSPEC TYPESPEC CV_QUALIFIER ENUM AGGR ELLIPSIS TYPEOF SIGOF OPERATOR NSNAME TYPENAME_KEYWORD
%left IDENTIFIER PFUNCNAME TYPENAME SELFNAME PTYPENAME SCSPEC TYPESPEC CV_QUALIFIER ENUM AGGR ELLIPSIS TYPEOF SIGOF OPERATOR NSNAME TYPENAME_KEYWORD
%left '{' ',' ';'
@ -193,6 +196,7 @@ empty_parms ()
%type <code> unop
%type <ttype> identifier IDENTIFIER TYPENAME CONSTANT expr nonnull_exprlist
%type <ttype> PFUNCNAME
%type <ttype> paren_expr_or_null nontrivial_exprlist SELFNAME
%type <ttype> expr_no_commas cast_expr unary_expr primary string STRING
%type <ttype> reserved_declspecs boolean.literal
@ -224,6 +228,7 @@ empty_parms ()
%type <ttype> fcast_or_absdcl regcast_or_absdcl
%type <ttype> expr_or_declarator complex_notype_declarator
%type <ttype> notype_unqualified_id unqualified_id qualified_id
%type <ttype> template_id object_template_id notype_template_declarator
%type <ttype> overqualified_id notype_qualified_id any_id
%type <ttype> complex_direct_notype_declarator functional_cast
%type <ttype> complex_parmlist parms_comma
@ -431,7 +436,8 @@ template_header:
template_parm_list '>'
{ $$ = end_template_parm_list ($4); }
| TEMPLATE '<' '>'
{ $$ = NULL_TREE; }
{ begin_specialization();
$$ = NULL_TREE; }
;
template_parm_list:
@ -483,10 +489,20 @@ template_parm:
template_def:
template_header
extdef
{ end_template_decl (); }
{
if ($1)
end_template_decl ();
else
end_specialization ();
}
| template_header
error %prec EMPTY
{ end_template_decl (); }
{
if ($1)
end_template_decl ();
else
end_specialization ();
}
;
datadef:
@ -701,8 +717,13 @@ fn.def2:
{ $$ = start_method (NULL_TREE, $$); goto rest_of_mdef; }
| template_header fn.def2
{
end_template_decl ();
if ($2 && DECL_TEMPLATE_INFO ($2))
if ($1)
end_template_decl ();
else
end_specialization ();
if ($2 && DECL_TEMPLATE_INFO ($2)
&& !DECL_TEMPLATE_SPECIALIZATION ($2))
{
$$ = DECL_TI_TEMPLATE ($2);
check_member_template ($$);
@ -1263,12 +1284,35 @@ expr_no_commas:
notype_unqualified_id:
'~' see_typename identifier
{ $$ = build_parse_node (BIT_NOT_EXPR, $3); }
| template_id
| operator_name
| IDENTIFIER
| PTYPENAME
| NSNAME %prec EMPTY
;
template_id:
PFUNCNAME '<' template_arg_list template_close_bracket
{ $$ = lookup_template_function ($1, $3); }
| PFUNCNAME '<' template_close_bracket
{ $$ = lookup_template_function ($1, NULL_TREE); }
| operator_name '<' template_arg_list template_close_bracket
{ $$ = lookup_template_function
(do_identifier ($1, 1), $3); }
| operator_name '<' template_close_bracket
{ $$ = lookup_template_function
(do_identifier ($1, 1), NULL_TREE); }
;
object_template_id:
TEMPLATE identifier '<' template_arg_list template_close_bracket
{ $$ = lookup_template_function ($2, $4); }
| TEMPLATE PFUNCNAME '<' template_arg_list template_close_bracket
{ $$ = lookup_template_function (DECL_NAME ($2), $4); }
| TEMPLATE operator_name '<' template_arg_list template_close_bracket
{ $$ = lookup_template_function (DECL_NAME ($2), $4); }
;
unqualified_id:
notype_unqualified_id
| TYPENAME
@ -1285,9 +1329,17 @@ expr_or_declarator:
{ $$ = $2; }
;
notype_template_declarator:
IDENTIFIER '<' template_arg_list template_close_bracket
{ $$ = lookup_template_function ($1, $3); }
| NSNAME '<' template_arg_list template_close_bracket
{ $$ = lookup_template_function ($1, $3); }
;
direct_notype_declarator:
complex_direct_notype_declarator
| notype_unqualified_id
| notype_template_declarator
| '(' expr_or_declarator ')'
{ $$ = finish_decl_parsing ($2); }
;
@ -1297,7 +1349,7 @@ primary:
{
if (TREE_CODE ($$) == BIT_NOT_EXPR)
$$ = build_x_unary_op (BIT_NOT_EXPR, TREE_OPERAND ($$, 0));
else
else if (TREE_CODE ($$) != TEMPLATE_ID_EXPR)
$$ = do_identifier ($$, 1);
}
| CONSTANT
@ -1500,6 +1552,20 @@ primary:
NULL_TREE, NULL_TREE);
else
$$ = build_member_call (OP0 ($$), OP1 ($$), NULL_TREE); }
| object object_template_id %prec UNARY
{
$$ = build_x_component_ref ($$, $2, NULL_TREE, 1);
}
| object object_template_id '(' nonnull_exprlist ')'
{
$$ = build_method_call ($1, $2, $4,
NULL_TREE, LOOKUP_NORMAL);
}
| object object_template_id LEFT_RIGHT
{
$$ = build_method_call ($1, $2, NULL_TREE,
NULL_TREE, LOOKUP_NORMAL);
}
| object unqualified_id %prec UNARY
{ $$ = build_x_component_ref ($$, $2, NULL_TREE, 1); }
| object overqualified_id %prec UNARY
@ -2191,7 +2257,9 @@ structsp:
{ $$.t = $2;
$$.new_type_flag = 0; }
/* C++ extensions, merged with C to avoid shift/reduce conflicts */
| class_head left_curly opt.component_decl_list '}' maybe_attribute
| class_head left_curly
{ reset_specialization(); }
opt.component_decl_list '}' maybe_attribute
{
int semi;
tree id;
@ -2214,7 +2282,7 @@ structsp:
;
else
{
$<ttype>$ = finish_struct ($1, $3, $5, semi);
$<ttype>$ = finish_struct ($1, $4, $6, semi);
if (semi) note_got_semicolon ($<ttype>$);
}
@ -2233,7 +2301,7 @@ structsp:
}
pending_inlines
{
$$.t = $<ttype>6;
$$.t = $<ttype>7;
$$.new_type_flag = 1;
if (current_class_type == NULL_TREE)
clear_inline_text_obstack ();
@ -2721,8 +2789,13 @@ component_decl_1:
{ $$ = do_class_using_decl ($1); }
| template_header component_decl_1
{
end_template_decl ();
if ($2 && DECL_TEMPLATE_INFO ($2))
if ($1)
end_template_decl ();
else
end_specialization ();
if ($2 && DECL_TEMPLATE_INFO ($2)
&& !DECL_TEMPLATE_SPECIALIZATION ($2))
{
$$ = DECL_TI_TEMPLATE ($2);
check_member_template ($$);
@ -3047,18 +3120,33 @@ complex_direct_notype_declarator:
TREE_COMPLEXITY ($$) = current_class_depth;
}
}
| nested_name_specifier notype_template_declarator
{ got_scope = NULL_TREE;
$$ = build_parse_node (SCOPE_REF, $1, $2);
if ($1 != current_class_type)
{
push_nested_class ($1, 3);
TREE_COMPLEXITY ($$) = current_class_depth;
}
}
;
qualified_id:
nested_name_specifier unqualified_id
{ got_scope = NULL_TREE;
$$ = build_parse_node (SCOPE_REF, $$, $2); }
| nested_name_specifier object_template_id
{ got_scope = NULL_TREE;
$$ = build_parse_node (SCOPE_REF, $1, $2); }
;
notype_qualified_id:
nested_name_specifier notype_unqualified_id
{ got_scope = NULL_TREE;
$$ = build_parse_node (SCOPE_REF, $$, $2); }
| nested_name_specifier object_template_id
{ got_scope = NULL_TREE;
$$ = build_parse_node (SCOPE_REF, $1, $2); }
;
overqualified_id:

View File

@ -63,6 +63,9 @@ static tree *maybe_template_tail = &maybe_templates;
int minimal_parse_mode;
static int processing_specialization;
static int template_header_count;
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
@ -78,6 +81,10 @@ 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, tree *));
static tree add_to_template_args PROTO((tree, tree));
static int type_unification_real PROTO((tree, tree *, tree, tree, int*,
int, int, int));
static int processing_explicit_specialization PROTO((int));
static void note_template_header PROTO((int));
/* Restore the template parameter context. */
@ -150,9 +157,10 @@ is_member_template (t)
certainly not a member template. */
return 0;
if (DECL_FUNCTION_MEMBER_P (t) ||
(TREE_CODE (t) == TEMPLATE_DECL &&
DECL_FUNCTION_MEMBER_P (DECL_TEMPLATE_RESULT (t))))
if ((DECL_FUNCTION_MEMBER_P (t)
&& !DECL_TEMPLATE_SPECIALIZATION (t))
|| (TREE_CODE (t) == TEMPLATE_DECL &&
DECL_FUNCTION_MEMBER_P (DECL_TEMPLATE_RESULT (t))))
{
tree tmpl = NULL_TREE;
@ -246,8 +254,391 @@ begin_template_parm_list ()
pushlevel (0);
declare_pseudo_global_level ();
++processing_template_decl;
note_template_header (0);
}
/* We've just seen template <>. */
void
begin_specialization ()
{
note_template_header (1);
}
/* Called at then end of processing a declaration preceeded by
template<>. */
void
end_specialization ()
{
reset_specialization ();
}
/* Any template <>'s that we have seen thus far are not referring to a
function specialization. */
void
reset_specialization ()
{
processing_specialization = 0;
template_header_count = 0;
}
/* We've just seen a template header. If SPECIALIZATION is non-zero,
it was of the form template <>. */
void
note_template_header (specialization)
int specialization;
{
processing_specialization = specialization;
template_header_count++;
}
/* Returns non-zero iff a declarator, in which the number of template
types that appeared was TEMPLATE_COUNT, is an explicit
specialization. */
int
processing_explicit_specialization(template_count)
int template_count;
{
/* A function declaration is an explicit specialization of a member
template if all of the following conditions hold:
o There was a template <...> preceeding the declaration.
o The last template <...> was in fact template <>.
o The number of template <...>'s preceeding the declaration, less
the number of template classes with arguments specified used to
qualify the function name, is 1.
For example:
template <> void S<int>::foo();
template <class T> template <> void S<T>::foo();
template <> struct S<int> { ... template <> void foo(); }
The first of these is not a specialization of S<int>::foo() (it
is instead a specialization of S<T>::foo), while the next two are
specializations of member template functions. */
return processing_specialization
&& template_header_count > template_count;
}
/* Returns the template function specialized by TEMPLATE_ID, or
NULL_TREE if there is none.
The TEMPLATE_ID is a TEMPLATE_ID_EXPR. The TYPE is
the type it has been declared to have. Return the TEMPLATE_DECL
that is being specialized, and put the specialization arguments in
*TARGS. If no appropriate specialization can be found, NULL_TREE is
returned, and *TARGS is assigned NULL_TREE. If complain is
non-zero, error messages are printed where appropriate. */
tree
determine_explicit_specialization (template_id, type, targs_out,
need_member_template,
complain)
tree template_id;
tree type;
tree* targs_out;
int need_member_template;
int complain;
{
int i;
int overloaded;
tree fns;
tree matching_fns = NULL_TREE;
tree name = NULL_TREE;
tree result;
tree fn;
my_friendly_assert (TREE_CODE (template_id) == TEMPLATE_ID_EXPR,
0);
fns = TREE_OPERAND (template_id, 0);
overloaded = fns != NULL_TREE && really_overloaded_fn (fns);
for (fn = (fns != NULL_TREE) ? get_first_fn (fns) : NULL_TREE;
fn != NULL_TREE;
fn = overloaded ? DECL_CHAIN (fn) : NULL_TREE)
{
int dummy;
tree targs;
if (name == NULL_TREE)
name = DECL_NAME (fn);
if (TREE_CODE (fn) != TEMPLATE_DECL
|| (need_member_template && !is_member_template (fn)))
continue;
if (list_length (TREE_OPERAND (template_id, 1)) > DECL_NTPARMS (fn))
continue;
targs = make_tree_vec (DECL_NTPARMS (fn));
/* We allow incomplete unification here, because we are going to
check all the functions. */
i = type_unification (DECL_INNERMOST_TEMPLATE_PARMS (fn),
&TREE_VEC_ELT (targs, 0),
type
? TYPE_ARG_TYPES (TREE_TYPE (fn)) : NULL_TREE,
type ? TYPE_ARG_TYPES (type) : NULL_TREE,
TREE_OPERAND (template_id, 1),
&dummy, 1, 1);
if (i == 0)
{
/* Unification was successful. See if the return types
match. */
if (type != NULL_TREE)
{
tree tmpl_return_type = tsubst (TREE_TYPE (TREE_TYPE (fn)),
targs,
DECL_NTPARMS (fn),
NULL_TREE);
if (tmpl_return_type != TREE_TYPE (type))
{
/* Always complain about this. With ambiguity, some
other context, might resolve things. But, a
non-matching return type will always be a
problem. */
cp_error ("Return type of explicit specialization of");
cp_error ("`%D' is `%T', but should be `%T'.",
fn, TREE_TYPE (type), tmpl_return_type);
*targs_out = NULL_TREE;
return NULL_TREE;
}
}
matching_fns = tree_cons (fn, targs, matching_fns);
}
}
if (matching_fns == NULL_TREE)
{
if (complain)
cp_error ("Specialization of `%s' does not match any template "
"declaration.", IDENTIFIER_POINTER (name));
*targs_out = NULL_TREE;
return NULL_TREE;
}
if (TREE_CHAIN (matching_fns) != NULL_TREE)
{
if (complain)
{
tree fn;
cp_error ("Ambiguous explicit specialization. Candidates are:");
for (fn = matching_fns; fn != NULL_TREE; fn = TREE_CHAIN (fn))
cp_error (" %D", TREE_PURPOSE (fn));
}
*targs_out = NULL_TREE;
return NULL_TREE;
}
/* We have one, and exactly one, match. */
*targs_out = TREE_VALUE (matching_fns);
return TREE_PURPOSE (matching_fns);
}
/* Check to see if the function just declared, as indicated in
DECLARATOR, and in DECL, is a specialization. Check that the
specialization is OK. If FLAGS == 1, we are being called by
finish_struct_methods. If FLAGS == 2, we are being called by
grokfndecl, and the function has a definition, or is a friend. If
FLAGS == 3, this is a friend declaration.
Returns 0 if the decl is not an explicit specialization or
instantiation, 1 if it is an explicit specialization, and 2 if it
is an explicit instantiation. */
int
check_explicit_specialization(declarator, decl, template_count,
flags)
tree declarator;
tree decl;
int template_count;
int flags;
{
int finish_member = flags == 1;
int have_def = flags == 2;
int is_friend = flags == 3;
if (processing_explicit_specialization (template_count)
|| finish_member
|| TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
{
tree tmpl = NULL_TREE;
tree dname = DECL_NAME (decl);
tree ctype = DECL_CLASS_CONTEXT (decl);
tree targs;
/* We've come across a declarator that looks like: U f<T1,
T2, ...>(A1, A2, ..). This is an explicit template
specialization. Check that:
o The explicitly specified parameters together with those
that can be deduced by template argument deduction
uniquely determine a particular specialization.
See [temp.expl.spec]. */
if (!finish_member
&& TREE_CODE (declarator) == TEMPLATE_ID_EXPR
&& !processing_explicit_specialization (template_count)
&& !is_friend)
{
if (!have_def)
/* This is not an explicit specialization. It must be
an explicit instantiation. */
return 2;
else if (pedantic)
pedwarn ("Explicit specialization not preceeded by "
"`template <>'");
}
if (TREE_CODE (declarator) != TEMPLATE_ID_EXPR)
{
tree fns;
my_friendly_assert (TREE_CODE (declarator) == IDENTIFIER_NODE,
0);
if (!ctype)
fns = IDENTIFIER_GLOBAL_VALUE (dname);
else
fns = dname;
declarator = lookup_template_function (fns, NULL_TREE);
}
if (TREE_CODE (TREE_OPERAND (declarator, 0)) == LOOKUP_EXPR)
{
/* A friend declaration. We can't do much, because we don't
know what this resolves to, yet. */
my_friendly_assert (is_friend != 0, 0);
SET_DECL_IMPLICIT_INSTANTIATION (decl);
return 1;
}
if (ctype
&& TREE_CODE (TREE_OPERAND (declarator, 0)) == IDENTIFIER_NODE)
{
tree fns;
if (TYPE_BEING_DEFINED (ctype) && !finish_member)
{
/* Since finish_struct_1 has not been called yet, we
can't call lookup_fnfields. We note that this
template is a specialization, and proceed, letting
finish_struct_methods fix this up later. */
SET_DECL_TEMPLATE_SPECIALIZATION (decl);
DECL_TEMPLATE_INFO (decl)
= perm_tree_cons (NULL_TREE,
TREE_OPERAND (declarator, 1),
NULL_TREE);
return 1;
}
fns = lookup_fnfields (TYPE_BINFO (ctype),
TREE_OPERAND (declarator, 0),
1);
if (fns == NULL_TREE)
{
cp_error ("No member template `%s' declared in `%T'",
IDENTIFIER_POINTER (TREE_OPERAND (declarator,
0)),
ctype);
return 1;
}
else
TREE_OPERAND (declarator, 0) = fns;
}
tmpl =
determine_explicit_specialization
(declarator, TREE_TYPE (decl), &targs,
TREE_CODE (decl) == TEMPLATE_DECL, 1);
if (tmpl)
{
/* Mangle the function name appropriately. */
if (name_mangling_version >= 1)
{
tree arg_types = TYPE_ARG_TYPES (TREE_TYPE (tmpl));
if (ctype
&& TREE_CODE (TREE_TYPE (tmpl)) == FUNCTION_TYPE)
arg_types =
hash_tree_chain (build_pointer_type (ctype),
arg_types);
DECL_ASSEMBLER_NAME (decl)
= build_template_decl_overload
(DECL_NAME (decl),
arg_types,
TREE_TYPE (TREE_TYPE (tmpl)),
DECL_INNERMOST_TEMPLATE_PARMS (tmpl),
targs, ctype != NULL_TREE);
}
if (is_friend && !have_def)
{
/* This is not really a declaration of a specialization.
It's just the name of an instantiation. But, it's not
a request for an instantiation, either. */
SET_DECL_IMPLICIT_INSTANTIATION (decl);
DECL_TEMPLATE_INFO (decl)
= perm_tree_cons (tmpl, targs, NULL_TREE);
return 1;
}
/* This function declaration is a template specialization.
Record that fact. */
SET_DECL_TEMPLATE_SPECIALIZATION (decl);
DECL_TEMPLATE_SPECIALIZATIONS (tmpl)
= perm_tree_cons (targs, decl,
DECL_TEMPLATE_SPECIALIZATIONS
(tmpl));
/* If DECL_TI_TEMPLATE (decl), the decl is an
instantiation of a specialization of a member template.
(In other words, there was a member template, in a
class template. That member template was specialized.
We then instantiated the class, so there is now an
instance of that specialization.)
According to the CD2,
14.7.3.13 [tmpl.expl.spec]
A specialization of a member function template or
member class template of a non-specialized class
template is itself a template.
So, we just leave the template info alone in this case.
*/
if (!(DECL_TEMPLATE_INFO (decl) && DECL_TI_TEMPLATE (decl)))
DECL_TEMPLATE_INFO (decl)
= perm_tree_cons (tmpl, targs, NULL_TREE);
return 1;
}
}
return 0;
}
/* Process information from new template parameter NEXT and append it to the
LIST being built. */
@ -358,6 +749,8 @@ end_template_parm_list (parms)
void
end_template_decl ()
{
reset_specialization ();
if (! processing_template_decl)
return;
@ -465,6 +858,15 @@ push_template_decl (decl)
DECL_CLASS_CONTEXT (tmpl) = DECL_CLASS_CONTEXT (decl);
DECL_STATIC_FUNCTION_P (tmpl) =
DECL_STATIC_FUNCTION_P (decl);
if (DECL_TEMPLATE_SPECIALIZATION (decl))
{
/* A specialization of a member template of a template
class. */
SET_DECL_TEMPLATE_SPECIALIZATION (tmpl);
DECL_TEMPLATE_INFO (tmpl) = DECL_TEMPLATE_INFO (decl);
DECL_TEMPLATE_INFO (decl) = NULL_TREE;
}
}
}
else
@ -749,6 +1151,9 @@ comp_template_args (oldargs, newargs)
{
int i;
if (TREE_VEC_LENGTH (oldargs) != TREE_VEC_LENGTH (newargs))
return 0;
for (i = 0; i < TREE_VEC_LENGTH (oldargs); ++i)
{
tree nt = TREE_VEC_ELT (newargs, i);
@ -895,6 +1300,35 @@ add_pending_template (d)
TI_PENDING_TEMPLATE_FLAG (ti) = 1;
}
/* Return a TEMPLATE_ID_EXPR corresponding to the indicated FNS (which
may be either a _DECL or an overloaded function or an
IDENTIFIER_NODE), and ARGLIST. */
tree
lookup_template_function (fns, arglist)
tree fns, arglist;
{
if (fns == NULL_TREE)
{
cp_error ("non-template used as template");
return error_mark_node;
}
if (arglist != NULL_TREE && !TREE_PERMANENT (arglist))
{
push_obstacks (&permanent_obstack, &permanent_obstack);
arglist = copy_list (arglist);
pop_obstacks ();
}
return build_min (TEMPLATE_ID_EXPR,
TREE_TYPE (fns)
? TREE_TYPE (fns) : unknown_type_node,
fns, arglist);
}
/* Given an IDENTIFIER_NODE (type TEMPLATE_DECL) and a chain of
parameters, find the desired type.
@ -1028,7 +1462,7 @@ lookup_template_class (d1, arglist, in_decl)
/* We need to set this again after CLASSTYPE_TEMPLATE_INFO is set up. */
DECL_ASSEMBLER_NAME (TYPE_MAIN_DECL (t)) = id;
if (! uses_template_parms (arglist))
/* if (! uses_template_parms (arglist)) */
DECL_ASSEMBLER_NAME (TYPE_MAIN_DECL (t))
= get_identifier (build_overload_name (t, 1, 1));
@ -1746,6 +2180,7 @@ tsubst (t, args, nargs, in_decl)
tree decl = DECL_TEMPLATE_RESULT (t);
tree new_decl;
tree parms;
tree spec;
int i;
/* We might already have an instance of this template. */
@ -1788,13 +2223,15 @@ tsubst (t, args, nargs, in_decl)
DECL_TEMPLATE_INSTANTIATIONS (t)
= perm_tree_cons (NULL_TREE, tmpl,
DECL_TEMPLATE_INSTANTIATIONS (t));
DECL_TEMPLATE_SPECIALIZATIONS (tmpl) = NULL_TREE;
return tmpl;
}
case FUNCTION_DECL:
{
tree r = NULL_TREE;
tree arg_types, ctx;
tree ctx;
int member;
@ -1857,12 +2294,6 @@ tsubst (t, args, nargs, in_decl)
DECL_NAME (r) = build_typename_overload (TREE_TYPE (type));
}
arg_types = TYPE_VALUES (type);
if (member && TREE_CODE (type) == FUNCTION_TYPE)
arg_types = hash_tree_chain
(build_pointer_type (DECL_CONTEXT (r)), arg_types);
if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (t)))
{
char *buf, *dbuf = build_overload_name (ctx, 1, 1);
@ -1874,9 +2305,72 @@ tsubst (t, args, nargs, in_decl)
strcat (buf, dbuf);
DECL_ASSEMBLER_NAME (r) = get_identifier (buf);
}
else
DECL_ASSEMBLER_NAME (r)
= build_decl_overload (DECL_NAME (r), arg_types, member);
else
{
/* Instantiations of template functions must be mangled
specially, in order to conform to 14.5.5.1
[temp.over.link]. We use in_decl below rather than
DECL_TI_TEMPLATE (r) because the latter is set to
NULL_TREE in instantiate_decl. */
tree tmpl;
tree arg_types;
if (DECL_TEMPLATE_INFO (r))
tmpl = DECL_TI_TEMPLATE (r);
else
tmpl = in_decl;
/* tmpl will be NULL if this is a specialization of a
member template of a template class. */
if (name_mangling_version < 1
|| tmpl == NULL_TREE
|| (member && !is_member_template (tmpl)
&& !DECL_TEMPLATE_INFO (tmpl)))
{
arg_types = TYPE_ARG_TYPES (type);
if (member && TREE_CODE (type) == FUNCTION_TYPE)
arg_types = hash_tree_chain
(build_pointer_type (DECL_CONTEXT (r)),
arg_types);
DECL_ASSEMBLER_NAME (r)
= build_decl_overload (DECL_NAME (r), arg_types,
member);
}
else
{
/* We pass the outermost template parameters to
build_template_decl_overload since the innermost
template parameters are still just template
parameters; there are no corresponding subsitution
arguments. */
tree tparms = DECL_TEMPLATE_PARMS (tmpl);
while (tparms && TREE_CHAIN (tparms) != NULL_TREE)
tparms = TREE_CHAIN (tparms);
my_friendly_assert (tparms != NULL_TREE
&& TREE_CODE (tparms) == TREE_LIST,
0);
tparms = TREE_VALUE (tparms);
arg_types = TYPE_ARG_TYPES (TREE_TYPE (tmpl));
if (member && TREE_CODE (type) == FUNCTION_TYPE)
arg_types = hash_tree_chain
(build_pointer_type (DECL_CONTEXT (r)),
arg_types);
DECL_ASSEMBLER_NAME (r)
= build_template_decl_overload
(DECL_NAME (r), arg_types,
TREE_TYPE (TREE_TYPE (tmpl)),
tparms,
TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC
? TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1) :
args,
member);
}
}
DECL_RTL (r) = 0;
make_decl_rtl (r, NULL_PTR, 1);
@ -2531,6 +3025,14 @@ tsubst_copy (t, args, nargs, in_decl)
return r;
}
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;
}
case TREE_LIST:
{
tree purpose, value, chain;
@ -2897,11 +3399,25 @@ instantiate_template (tmpl, targ_ptr)
struct obstack *old_fmp_obstack;
extern struct obstack *function_maybepermanent_obstack;
my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 283);
if (DECL_FUNCTION_TEMPLATE_P (tmpl))
{
tree specs;
/* Check to see if there is a matching specialization. */
for (specs = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
specs != NULL_TREE;
specs = TREE_CHAIN (specs))
if (comp_template_args (TREE_PURPOSE(specs),
targ_ptr))
return TREE_VALUE (specs);
}
push_obstacks (&permanent_obstack, &permanent_obstack);
old_fmp_obstack = function_maybepermanent_obstack;
function_maybepermanent_obstack = &permanent_obstack;
my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 283);
len = DECL_NTPARMS (tmpl);
i = len;
@ -2960,8 +3476,8 @@ overload_template_name (type)
operators. */
int
fn_type_unification (fn, targs, args, return_type, strict)
tree fn, targs, args, return_type;
fn_type_unification (fn, explicit_targs, targs, args, return_type, strict)
tree fn, explicit_targs, targs, args, return_type;
int strict;
{
int i, dummy = 0;
@ -2986,7 +3502,8 @@ fn_type_unification (fn, targs, args, return_type, strict)
&TREE_VEC_ELT (targs, 0),
fn_arg_types,
decl_arg_types,
&dummy, 0, strict);
explicit_targs,
&dummy, strict, 0);
return i;
}
@ -3016,25 +3533,54 @@ fn_type_unification (fn, targs, args, return_type, strict)
addresses, explicit instantiation, and more_specialized). */
int
type_unification (tparms, targs, parms, args, nsubsts, subr, strict)
type_unification (tparms, targs, parms, args, targs_in, nsubsts,
strict, allow_incomplete)
tree tparms, *targs, parms, args, targs_in;
int *nsubsts, strict, allow_incomplete;
{
int ntparms = TREE_VEC_LENGTH (tparms);
tree t;
int i;
int r;
bzero ((char *) targs, sizeof (tree) * ntparms);
/* Insert any explicit template arguments. They are encoded as the
operands of NOP_EXPRs so that unify can tell that they are
explicit arguments. */
for (i = 0, t = targs_in; t != NULL_TREE; t = TREE_CHAIN (t), ++i)
targs[i] = build1 (NOP_EXPR, NULL_TREE, TREE_VALUE (t));
r = type_unification_real (tparms, targs, parms, args, nsubsts, 0,
strict, allow_incomplete);
for (i = 0, t = targs_in; t != NULL_TREE; t = TREE_CHAIN (t), ++i)
if (TREE_CODE (targs[i]) == NOP_EXPR)
targs[i] = TREE_OPERAND (targs[i], 0);
return r;
}
int
type_unification_real (tparms, targs, parms, args, nsubsts, subr,
strict, allow_incomplete)
tree tparms, *targs, parms, args;
int *nsubsts, subr, strict;
int *nsubsts, subr, strict, allow_incomplete;
{
tree parm, arg;
int i;
int ntparms = TREE_VEC_LENGTH (tparms);
my_friendly_assert (TREE_CODE (tparms) == TREE_VEC, 289);
my_friendly_assert (TREE_CODE (parms) == TREE_LIST, 290);
my_friendly_assert (parms == NULL_TREE
|| TREE_CODE (parms) == TREE_LIST, 290);
/* ARGS could be NULL (via a call from parse.y to
build_x_function_call). */
if (args)
my_friendly_assert (TREE_CODE (args) == TREE_LIST, 291);
my_friendly_assert (ntparms > 0, 292);
if (!subr)
bzero ((char *) targs, sizeof (tree) * ntparms);
while (parms
&& parms != void_list_node
&& args
@ -3107,10 +3653,12 @@ type_unification (tparms, targs, parms, args, nsubsts, subr, strict)
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);
return
type_unification (DECL_INNERMOST_TEMPLATE_PARMS (arg),
targs,
TYPE_ARG_TYPES (TREE_TYPE (arg)),
parm, NULL_TREE, &nsubsts, strict,
allow_incomplete);
}
arg = TREE_TYPE (arg);
}
@ -3150,7 +3698,8 @@ type_unification (tparms, targs, parms, args, nsubsts, subr, strict)
for (i = 0; i < ntparms; i++)
if (!targs[i])
{
error ("incomplete type unification");
if (!allow_incomplete)
error ("incomplete type unification");
return 2;
}
return 0;
@ -3190,6 +3739,17 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts, strict)
case TEMPLATE_TYPE_PARM:
(*nsubsts)++;
idx = TEMPLATE_TYPE_IDX (parm);
/* Check for mixed types and values. */
if (TREE_CODE (TREE_VALUE (TREE_VEC_ELT (tparms, idx))) != TYPE_DECL)
return 1;
if (!strict && targs[idx] != NULL_TREE &&
TREE_CODE (targs[idx]) == NOP_EXPR)
/* An explicit template argument. Don't even try to match
here; the overload resolution code will manage check to
see whether the call is legal. */
return 0;
if (strict && (TYPE_READONLY (arg) < TYPE_READONLY (parm)
|| TYPE_VOLATILE (arg) < TYPE_VOLATILE (parm)))
return 1;
@ -3209,13 +3769,13 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts, strict)
}
#endif
/* Simple cases: Value already set, does match or doesn't. */
if (targs[idx] == arg)
if (targs[idx] == arg
|| (targs[idx]
&& TREE_CODE (targs[idx]) == NOP_EXPR
&& TREE_OPERAND (targs[idx], 0) == arg))
return 0;
else if (targs[idx])
return 1;
/* Check for mixed types and values. */
if (TREE_CODE (TREE_VALUE (TREE_VEC_ELT (tparms, idx))) != TYPE_DECL)
return 1;
targs[idx] = arg;
return 0;
case TEMPLATE_CONST_PARM:
@ -3363,8 +3923,9 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts, strict)
if (unify (tparms, targs, ntparms, TREE_TYPE (parm),
TREE_TYPE (arg), nsubsts, strict))
return 1;
return type_unification (tparms, targs, TYPE_ARG_TYPES (parm),
TYPE_ARG_TYPES (arg), nsubsts, 1, strict);
return type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm),
TYPE_ARG_TYPES (arg), nsubsts, 1,
strict, 0);
case OFFSET_TYPE:
if (TREE_CODE (arg) != OFFSET_TYPE)
@ -3470,7 +4031,7 @@ get_bindings (fn, decl)
tree targs = make_tree_vec (ntparms);
int i;
i = fn_type_unification (fn, targs,
i = fn_type_unification (fn, NULL_TREE, targs,
TYPE_ARG_TYPES (TREE_TYPE (decl)),
TREE_TYPE (TREE_TYPE (decl)),
1);
@ -3872,6 +4433,18 @@ instantiate_decl (d)
if (d_defined)
return d;
if (TREE_CODE (d) == FUNCTION_DECL)
{
tree specs;
/* Check to see if there is a matching specialization. */
for (specs = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
specs != NULL_TREE;
specs = TREE_CHAIN (specs))
if (comp_template_args (TREE_PURPOSE (specs), args))
return TREE_VALUE (specs);
}
/* This needs to happen before any tsubsting. */
if (! push_tinst_level (d))
return d;
@ -3950,9 +4523,16 @@ instantiate_decl (d)
popclass (1);
}
/* Convince duplicate_decls to use the DECL_ARGUMENTS from the new decl. */
if (TREE_CODE (d) == FUNCTION_DECL)
DECL_INITIAL (td) = error_mark_node;
{
/* Convince duplicate_decls to use the DECL_ARGUMENTS from the
new decl. */
DECL_INITIAL (td) = error_mark_node;
if (DECL_TEMPLATE_SPECIALIZATION (td) && !DECL_TEMPLATE_INFO (td))
/* Set up the information about what is being specialized. */
DECL_TEMPLATE_INFO (td) = DECL_TEMPLATE_INFO (d);
}
duplicate_decls (td, d);
if (TREE_CODE (d) == FUNCTION_DECL)
DECL_INITIAL (td) = 0;

View File

@ -316,6 +316,7 @@ yylex ()
if (got_scope)
tmp_token.yylval.ttype = trrr;
break;
case PFUNCNAME:
case IDENTIFIER:
lastiddecl = trrr;
break;
@ -377,6 +378,10 @@ yylex ()
if (spew_debug)
debug_yychar (yychar);
#endif
if (yychar == PFUNCNAME)
yylval.ttype = do_identifier (yylval.ttype, 1);
return yychar;
}

View File

@ -1262,6 +1262,9 @@ is_overloaded_fn (x)
if (TREE_CODE (x) == FUNCTION_DECL)
return 1;
if (TREE_CODE (x) == TEMPLATE_ID_EXPR)
return 1;
if (TREE_CODE (x) == TREE_LIST
&& (TREE_CODE (TREE_VALUE (x)) == FUNCTION_DECL
|| TREE_CODE (TREE_VALUE (x)) == TEMPLATE_DECL))
@ -1274,9 +1277,12 @@ int
really_overloaded_fn (x)
tree x;
{
if (TREE_CODE (x) == TEMPLATE_ID_EXPR)
return 1;
if (TREE_CODE (x) == TREE_LIST
&& (TREE_CODE (TREE_VALUE (x)) == FUNCTION_DECL
|| TREE_CODE (TREE_VALUE (x)) == TEMPLATE_DECL))
|| DECL_FUNCTION_TEMPLATE_P (TREE_VALUE (x))))
return 1;
return 0;
@ -1286,7 +1292,8 @@ tree
get_first_fn (from)
tree from;
{
if (TREE_CODE (from) == FUNCTION_DECL)
if (TREE_CODE (from) == FUNCTION_DECL
|| DECL_FUNCTION_TEMPLATE_P (from))
return from;
my_friendly_assert (TREE_CODE (from) == TREE_LIST, 9);

View File

@ -2375,7 +2375,7 @@ build_x_function_call (function, params, decl)
return build_method_call (decl, function, params,
NULL_TREE, LOOKUP_NORMAL);
}
else if (TREE_CODE (function) == TREE_LIST)
else if (really_overloaded_fn (function))
{
if (TREE_VALUE (function) == NULL_TREE)
{
@ -2643,7 +2643,8 @@ build_function_call_real (function, params, require_complete, flags)
if (!((TREE_CODE (fntype) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (fntype)) == FUNCTION_TYPE)
|| is_method))
|| is_method
|| TREE_CODE (function) == TEMPLATE_ID_EXPR))
{
cp_error ("`%E' cannot be used as a function", function);
return error_mark_node;
@ -4026,6 +4027,7 @@ build_x_unary_op (code, xarg)
/* & rec, on incomplete RECORD_TYPEs is the simple opr &, not an
error message. */
if (code == ADDR_EXPR
&& TREE_CODE (xarg) != TEMPLATE_ID_EXPR
&& ((IS_AGGR_TYPE_CODE (TREE_CODE (TREE_TYPE (xarg)))
&& TYPE_SIZE (TREE_TYPE (xarg)) == NULL_TREE)
|| (TREE_CODE (xarg) == OFFSET_REF)))
@ -4420,6 +4422,27 @@ build_unary_op (code, xarg, noconvert)
0);
return build1 (ADDR_EXPR, unknown_type_node, arg);
}
else if (TREE_CODE (arg) == TEMPLATE_ID_EXPR)
{
tree targs;
tree fn;
/* We don't require a match here; it's possible that the
context (like a cast to a particular type) will resolve
the particular choice of template. */
fn = determine_explicit_specialization (arg, NULL_TREE,
&targs,
0, 0);
if (fn)
{
fn = instantiate_template (fn, targs);
mark_addressable (fn);
return build_unary_op (ADDR_EXPR, fn, 0);
}
return build1 (ADDR_EXPR, unknown_type_node, arg);
}
/* Handle complex lvalues (when permitted)
by reduction to simpler cases. */
@ -4757,6 +4780,8 @@ mark_addressable (exp)
if (x == current_function_decl)
DECL_EXTERNAL (x) = 0;
}
if (DECL_TEMPLATE_INFO (x) && !DECL_TEMPLATE_SPECIALIZATION (x))
mark_used (x);
TREE_ADDRESSABLE (x) = 1;
TREE_USED (x) = 1;
TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;