mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-13 11:21:18 +08:00
[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:
parent
e741306e3c
commit
386b8a85a6
120
gcc/cp/ChangeLog
120
gcc/cp/ChangeLog
@ -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
|
||||
|
29
gcc/cp/NEWS
29
gcc/cp/NEWS
@ -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.
|
||||
|
103
gcc/cp/call.c
103
gcc/cp/call.c
@ -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
|
||||
|
125
gcc/cp/class.c
125
gcc/cp/class.c
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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));
|
||||
|
123
gcc/cp/decl.c
123
gcc/cp/decl.c
@ -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;
|
||||
|
@ -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 *");
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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))))
|
||||
|
@ -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",
|
||||
|
@ -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;
|
||||
|
197
gcc/cp/method.c
197
gcc/cp/method.c
@ -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
|
||||
|
9093
gcc/cp/parse.c
9093
gcc/cp/parse.c
File diff suppressed because it is too large
Load Diff
167
gcc/cp/parse.h
167
gcc/cp/parse.h
@ -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;
|
||||
|
112
gcc/cp/parse.y
112
gcc/cp/parse.y
@ -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:
|
||||
|
656
gcc/cp/pt.c
656
gcc/cp/pt.c
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user