cp-tree.h (ICS_USER_FLAG): Remove comment about obsolete flag.

* cp-tree.h (ICS_USER_FLAG): Remove comment about obsolete flag.
	(DECL_MEMBER_TEMPLATE_P): New macro.
	(is_member_template): Remove.
	(class_method_index_for_fn): New function.
	* pt.c (build_over_call): Use DECL_MEMBER_TEMPLATE_P.
	* class.c (finish_struct_methods): Remove out-of-date comment.
	* decl.c (copy_fn_p): Use DECL_MBMER_TEMPLATE_P.
	* decl2.c (check_classfn): Use DECL_MEMBER_TEMPLATE_P and
	class_method_index_for_fn.
	* pt.c (is_member_template): Remove.
	(is_member_template_class): Likewise.
	(optimize_specialization_lookup_p): New function.
	(retrieve_specialization): Optimize lookups for members that are
	not member templates.
	(register_specialization): Adjust accordingly.
	(build_template_decl): Add member_template_p parameter.  Set
	DECL_MEMBER_TEMPLATE_P.
	(process_partial_specialization): Adjust call to
	retrieve_specialization.
	(push_template_decl_real): Determine whether the template is a
	member template.
	(lookup_template_class): Use retrieve_specialization.
	(tsubst_decl): Adjust call to retrieve_specialization.
	(tsubst_exception_specification): New function.
	(tsubst): Use it.
	(tsubst_copy): Use DECL_MEMBER_TEMPLATE_P.
	(instantiate_template): Adjust call to retrieve_specialization.
	(regenerate_decl_from_template): Do not actually generate a new
	DECL.
	(instantiate_decl): Adjust call to retrieve_specialization.
	(class_method_index_for_fn): New method.

From-SVN: r88697
This commit is contained in:
Mark Mitchell 2004-10-07 17:48:36 +00:00 committed by Mark Mitchell
parent d0e75c71c9
commit c7222c0224
8 changed files with 346 additions and 261 deletions

View File

@ -1,3 +1,37 @@
2004-10-07 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (ICS_USER_FLAG): Remove comment about obsolete flag.
(DECL_MEMBER_TEMPLATE_P): New macro.
(is_member_template): Remove.
(class_method_index_for_fn): New function.
* pt.c (build_over_call): Use DECL_MEMBER_TEMPLATE_P.
* class.c (finish_struct_methods): Remove out-of-date comment.
* decl.c (copy_fn_p): Use DECL_MBMER_TEMPLATE_P.
* decl2.c (check_classfn): Use DECL_MEMBER_TEMPLATE_P and
class_method_index_for_fn.
* pt.c (is_member_template): Remove.
(is_member_template_class): Likewise.
(optimize_specialization_lookup_p): New function.
(retrieve_specialization): Optimize lookups for members that are
not member templates.
(register_specialization): Adjust accordingly.
(build_template_decl): Add member_template_p parameter. Set
DECL_MEMBER_TEMPLATE_P.
(process_partial_specialization): Adjust call to
retrieve_specialization.
(push_template_decl_real): Determine whether the template is a
member template.
(lookup_template_class): Use retrieve_specialization.
(tsubst_decl): Adjust call to retrieve_specialization.
(tsubst_exception_specification): New function.
(tsubst): Use it.
(tsubst_copy): Use DECL_MEMBER_TEMPLATE_P.
(instantiate_template): Adjust call to retrieve_specialization.
(regenerate_decl_from_template): Do not actually generate a new
DECL.
(instantiate_decl): Adjust call to retrieve_specialization.
(class_method_index_for_fn): New method.
2004-10-07 Andrew Pinski <pinskia@physics.uc.edu>
* parser.c (cp_parser_asm_definition): Look passed the

View File

@ -4614,7 +4614,7 @@ build_over_call (struct z_candidate *cand, int flags)
primary template because `B<T>::g' and `B<int>::g' may have
different access. */
if (DECL_TEMPLATE_INFO (fn)
&& is_member_template (DECL_TI_TEMPLATE (fn)))
&& DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (fn)))
perform_or_defer_access_check (cand->access_path,
DECL_TI_TEMPLATE (fn));
else

View File

@ -1657,17 +1657,7 @@ resort_type_method_vec (void* obj,
}
}
/* Warn about duplicate methods in fn_fields. Also compact method
lists so that lookup can be made faster.
Data Structure: List of method lists. The outer list is a
TREE_LIST, whose TREE_PURPOSE field is the field name and the
TREE_VALUE is the DECL_CHAIN of the FUNCTION_DECLs. TREE_CHAIN
links the entire list of methods for TYPE_METHODS. Friends are
chained in the same way as member functions (? TREE_CHAIN or
DECL_CHAIN), but they live in the TREE_TYPE field of the outer
list. That allows them to be quickly deleted, and requires no
extra storage.
/* Warn about duplicate methods in fn_fields.
Sort methods that are not special (i.e., constructors, destructors,
and type conversion operators) so that we can find them faster in
@ -1686,11 +1676,9 @@ finish_struct_methods (tree t)
len = VEC_length (tree, method_vec);
/* First fill in entry 0 with the constructors, entry 1 with destructors,
and the next few with type conversion operators (if any). */
/* Clear DECL_IN_AGGR_P for all functions. */
for (fn_fields = TYPE_METHODS (t); fn_fields;
fn_fields = TREE_CHAIN (fn_fields))
/* Clear out this flag. */
DECL_IN_AGGR_P (fn_fields) = 0;
if (TYPE_HAS_DESTRUCTOR (t) && !CLASSTYPE_DESTRUCTORS (t))

View File

@ -39,7 +39,6 @@ struct diagnostic_context;
DELETE_EXPR_USE_GLOBAL (in DELETE_EXPR).
COMPOUND_EXPR_OVERLOADED (in COMPOUND_EXPR).
TREE_INDIRECT_USING (in NAMESPACE_DECL).
ICS_USER_FLAG (in _CONV)
CLEANUP_P (in TRY_BLOCK)
AGGR_INIT_VIA_CTOR_P (in AGGR_INIT_EXPR)
PTRMEM_OK_P (in ADDR_EXPR, OFFSET_REF)
@ -90,6 +89,7 @@ struct diagnostic_context;
DECL_MUTABLE_P (in FIELD_DECL)
1: C_TYPEDEF_EXPLICITLY_SIGNED (in TYPE_DECL).
DECL_TEMPLATE_INSTANTIATED (in a VAR_DECL or a FUNCTION_DECL)
DECL_MEMBER_TEMPLATE_P (in TEMPLATE_DECL)
2: DECL_THIS_EXTERN (in VAR_DECL or FUNCTION_DECL).
DECL_IMPLICIT_TYPEDEF_P (in a TYPE_DECL)
3: DECL_IN_AGGR_P.
@ -2177,6 +2177,11 @@ struct lang_decl GTY(())
#define INNERMOST_TEMPLATE_PARMS(NODE) TREE_VALUE (NODE)
/* Nonzero if NODE (a TEMPLATE_DECL) is a member template, in the
sense of [temp.mem]. */
#define DECL_MEMBER_TEMPLATE_P(NODE) \
(DECL_LANG_FLAG_1 (TEMPLATE_DECL_CHECK (NODE)))
/* Nonzero if the NODE corresponds to the template parameters for a
member template, whose inline definition is being processed after
the class definition is complete. */
@ -3930,7 +3935,6 @@ extern tree instantiate_decl (tree, int, int);
extern int push_tinst_level (tree);
extern void pop_tinst_level (void);
extern int more_specialized_class (tree, tree, tree);
extern int is_member_template (tree);
extern int comp_template_parms (tree, tree);
extern int template_class_depth (tree);
extern int is_specialization_of (tree, tree);
@ -3990,6 +3994,7 @@ extern int accessible_p (tree, tree);
extern tree lookup_field_1 (tree, tree, bool);
extern tree lookup_field (tree, tree, int, bool);
extern int lookup_fnfields_1 (tree, tree);
extern int class_method_index_for_fn (tree, tree);
extern tree lookup_fnfields (tree, tree, int);
extern tree lookup_member (tree, tree, int, bool);
extern int look_for_overrides (tree, tree);

View File

@ -8477,7 +8477,8 @@ copy_fn_p (tree d)
gcc_assert (DECL_FUNCTION_MEMBER_P (d));
if (DECL_TEMPLATE_INFO (d) && is_member_template (DECL_TI_TEMPLATE (d)))
if (DECL_TEMPLATE_INFO (d)
&& DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (d)))
/* Instantiations of template member functions are never copy
functions. Note that member functions of templated classes are
represented as template functions internally, and we must

View File

@ -596,7 +596,7 @@ check_classfn (tree ctype, tree function, tree template_parms)
if (DECL_USE_TEMPLATE (function)
&& !(TREE_CODE (function) == TEMPLATE_DECL
&& DECL_TEMPLATE_SPECIALIZATION (function))
&& is_member_template (DECL_TI_TEMPLATE (function)))
&& DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (function)))
/* Since this is a specialization of a member template,
we're not going to find the declaration in the class.
For example, in:
@ -622,11 +622,7 @@ check_classfn (tree ctype, tree function, tree template_parms)
/* OK, is this a definition of a member template? */
is_template = (template_parms != NULL_TREE);
ix = lookup_fnfields_1 (complete_type (ctype),
DECL_CONSTRUCTOR_P (function) ? ctor_identifier :
DECL_DESTRUCTOR_P (function) ? dtor_identifier :
DECL_NAME (function));
ix = class_method_index_for_fn (complete_type (ctype), function);
if (ix >= 0)
{
VEC(tree) *methods = CLASSTYPE_METHOD_VEC (ctype);

View File

@ -117,12 +117,9 @@ static int for_each_template_parm (tree, tree_fn_t, void*, htab_t);
static tree build_template_parm_index (int, int, int, tree, tree);
static int inline_needs_template_parms (tree);
static void push_inline_template_parms_recursive (tree, int);
static tree retrieve_specialization (tree, tree);
static tree retrieve_local_specialization (tree);
static tree register_specialization (tree, tree, tree);
static void register_local_specialization (tree, tree);
static tree reduce_template_parm_level (tree, tree, int);
static tree build_template_decl (tree, tree);
static int mark_template_parm (tree, void *);
static int template_parm_this_level_p (tree, void *);
static tree tsubst_friend_function (tree, tree);
@ -441,67 +438,6 @@ maybe_end_member_template_processing (void)
}
}
/* Returns nonzero iff T is a member template function. We must be
careful as in
template <class T> class C { void f(); }
Here, f is a template function, and a member, but not a member
template. This function does not concern itself with the origin of
T, only its present state. So if we have
template <class T> class C { template <class U> void f(U); }
then neither C<int>::f<char> nor C<T>::f<double> is considered
to be a member template. But, `template <class U> void
C<int>::f(U)' is considered a member template. */
int
is_member_template (tree t)
{
if (!DECL_FUNCTION_TEMPLATE_P (t))
/* Anything that isn't a function or a template function is
certainly not a member template. */
return 0;
/* A local class can't have member templates. */
if (decl_function_context (t))
return 0;
return (DECL_FUNCTION_MEMBER_P (DECL_TEMPLATE_RESULT (t))
/* If there are more levels of template parameters than
there are template classes surrounding the declaration,
then we have a member template. */
&& (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (t)) >
template_class_depth (DECL_CONTEXT (t))));
}
#if 0 /* UNUSED */
/* Returns nonzero iff T is a member template class. See
is_member_template for a description of what precisely constitutes
a member template. */
int
is_member_template_class (tree t)
{
if (!DECL_CLASS_TEMPLATE_P (t))
/* Anything that isn't a class template, is certainly not a member
template. */
return 0;
if (!DECL_CLASS_SCOPE_P (t))
/* Anything whose context isn't a class type is surely not a
member template. */
return 0;
/* If there are more levels of template parameters than there are
template classes surrounding the declaration, then we have a
member template. */
return (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (t)) >
template_class_depth (DECL_CONTEXT (t)));
}
#endif
/* Return a new template argument vector which contains all of ARGS,
but has as its innermost set of arguments the EXTRA_ARGS. */
@ -826,30 +762,122 @@ maybe_process_partial_specialization (tree type)
error ("explicit specialization of non-template %qT", type);
}
/* Returns onzero if we can optimize the retrieval of specializations
for TMPL, a TEMPLATE_DECL. In particular, for such a template, we
do not use DECL_TEMPLATE_SPECIALIZATIONS at all. */
static inline bool
optimize_specialization_lookup_p (tree tmpl)
{
return (DECL_FUNCTION_TEMPLATE_P (tmpl)
&& DECL_CLASS_SCOPE_P (tmpl)
/* DECL_CLASS_SCOPE_P holds of T::f even if T is a template
parameter. */
&& CLASS_TYPE_P (DECL_CONTEXT (tmpl))
&& !DECL_MEMBER_TEMPLATE_P (tmpl)
&& !DECL_CONV_FN_P (tmpl)
/* It is possible to have a template that is not a member
template and is not a member of a template class:
template <typename T>
struct S { friend A::f(); };
Here, the friend function is a template, but the context does
not have template information. The optimized lookup relies
on having ARGS be the template arguments for both the class
and the function template. */
&& !DECL_FRIEND_P (DECL_TEMPLATE_RESULT (tmpl)));
}
/* Retrieve the specialization (in the sense of [temp.spec] - a
specialization is either an instantiation or an explicit
specialization) of TMPL for the given template ARGS. If there is
no such specialization, return NULL_TREE. The ARGS are a vector of
arguments, or a vector of vectors of arguments, in the case of
templates with more than one level of parameters. */
templates with more than one level of parameters.
If TMPL is a type template and CLASS_SPECIALIZATIONS_P is true,
then we search for a partial specialization matching ARGS. This
parameter is ignored if TMPL is not a class template. */
static tree
retrieve_specialization (tree tmpl, tree args)
retrieve_specialization (tree tmpl, tree args,
bool class_specializations_p)
{
tree s;
gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL);
/* There should be as many levels of arguments as there are
levels of parameters. */
gcc_assert (TMPL_ARGS_DEPTH (args)
== TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)));
for (s = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
s != NULL_TREE;
s = TREE_CHAIN (s))
if (comp_template_args (TREE_PURPOSE (s), args))
return TREE_VALUE (s);
if (optimize_specialization_lookup_p (tmpl))
{
tree class_template;
tree class_specialization;
VEC(tree) *methods;
tree fns;
int idx;
/* The template arguments actually apply to the containing
class. Find the class specialization with those
arguments. */
class_template = CLASSTYPE_TI_TEMPLATE (DECL_CONTEXT (tmpl));
class_specialization
= retrieve_specialization (class_template, args,
/*class_specializations_p=*/false);
if (!class_specialization)
return NULL_TREE;
/* Now, find the appropriate entry in the CLASSTYPE_METHOD_VEC
for the specialization. */
idx = class_method_index_for_fn (class_specialization, tmpl);
if (idx == -1)
return NULL_TREE;
/* Iterate through the methods with the indicated name, looking
for the one that has an instance of TMPL. */
methods = CLASSTYPE_METHOD_VEC (class_specialization);
for (fns = VEC_index (tree, methods, idx); fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
if (DECL_TEMPLATE_INFO (fn) && DECL_TI_TEMPLATE (fn) == tmpl)
return fn;
}
return NULL_TREE;
}
else
{
tree *sp;
tree *head;
/* Class templates store their instantiations on the
DECL_TEMPLATE_INSTANTIATIONS list; other templates use the
DECL_TEMPLATE_SPECIALIZATIONS list. */
if (!class_specializations_p
&& TREE_CODE (DECL_TEMPLATE_RESULT (tmpl)) == TYPE_DECL)
sp = &DECL_TEMPLATE_INSTANTIATIONS (tmpl);
else
sp = &DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
head = sp;
/* Iterate through the list until we find a matching template. */
while (*sp != NULL_TREE)
{
tree spec = *sp;
if (comp_template_args (TREE_PURPOSE (spec), args))
{
/* Use the move-to-front heuristic to speed up future
searches. */
if (spec != *head)
{
*sp = TREE_CHAIN (*sp);
TREE_CHAIN (spec) = *head;
*head = spec;
}
return TREE_VALUE (spec);
}
sp = &TREE_CHAIN (spec);
}
}
return NULL_TREE;
}
@ -1035,7 +1063,7 @@ is_specialization_of_friend (tree decl, tree friend)
static tree
register_specialization (tree spec, tree tmpl, tree args)
{
tree s;
tree fn;
gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL);
@ -1059,73 +1087,67 @@ register_specialization (tree spec, tree tmpl, tree args)
gcc_assert (TMPL_ARGS_DEPTH (args)
== TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)));
for (s = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
s != NULL_TREE;
s = TREE_CHAIN (s))
fn = retrieve_specialization (tmpl, args,
/*class_specializations_p=*/false);
/* We can sometimes try to re-register a specialization that we've
already got. In particular, regenerate_decl_from_template calls
duplicate_decls which will update the specialization list. But,
we'll still get called again here anyhow. It's more convenient
to simply allow this than to try to prevent it. */
if (fn == spec)
return spec;
else if (fn && DECL_TEMPLATE_SPECIALIZATION (spec))
{
tree fn = TREE_VALUE (s);
/* We can sometimes try to re-register a specialization that we've
already got. In particular, regenerate_decl_from_template
calls duplicate_decls which will update the specialization
list. But, we'll still get called again here anyhow. It's
more convenient to simply allow this than to try to prevent it. */
if (fn == spec)
return spec;
else if (DECL_TEMPLATE_SPECIALIZATION (spec)
&& comp_template_args (TREE_PURPOSE (s), args))
if (DECL_TEMPLATE_INSTANTIATION (fn))
{
if (DECL_TEMPLATE_INSTANTIATION (fn))
if (TREE_USED (fn)
|| DECL_EXPLICIT_INSTANTIATION (fn))
{
if (TREE_USED (fn)
|| DECL_EXPLICIT_INSTANTIATION (fn))
{
error ("specialization of %qD after instantiation", fn);
return spec;
}
else
{
/* This situation should occur only if the first
specialization is an implicit instantiation, the
second is an explicit specialization, and the
implicit instantiation has not yet been used.
That situation can occur if we have implicitly
instantiated a member function and then
specialized it later.
We can also wind up here if a friend declaration
that looked like an instantiation turns out to be
a specialization:
template <class T> void foo(T);
class S { friend void foo<>(int) };
template <> void foo(int);
We transform the existing DECL in place so that
any pointers to it become pointers to the updated
declaration.
If there was a definition for the template, but
not for the specialization, we want this to look
as if there were no definition, and vice
versa. */
DECL_INITIAL (fn) = NULL_TREE;
duplicate_decls (spec, fn);
return fn;
}
error ("specialization of %qD after instantiation",
fn);
return spec;
}
else if (DECL_TEMPLATE_SPECIALIZATION (fn))
else
{
if (!duplicate_decls (spec, fn) && DECL_INITIAL (spec))
/* Dup decl failed, but this is a new definition. Set
the line number so any errors match this new
definition. */
DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (spec);
/* This situation should occur only if the first
specialization is an implicit instantiation, the
second is an explicit specialization, and the
implicit instantiation has not yet been used. That
situation can occur if we have implicitly
instantiated a member function and then specialized
it later.
We can also wind up here if a friend declaration that
looked like an instantiation turns out to be a
specialization:
template <class T> void foo(T);
class S { friend void foo<>(int) };
template <> void foo(int);
We transform the existing DECL in place so that any
pointers to it become pointers to the updated
declaration.
If there was a definition for the template, but not
for the specialization, we want this to look as if
there were no definition, and vice versa. */
DECL_INITIAL (fn) = NULL_TREE;
duplicate_decls (spec, fn);
return fn;
}
}
else if (DECL_TEMPLATE_SPECIALIZATION (fn))
{
if (!duplicate_decls (spec, fn) && DECL_INITIAL (spec))
/* Dup decl failed, but this is a new definition. Set the
line number so any errors match this new
definition. */
DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (spec);
return fn;
}
}
/* A specialization must be declared in the same namespace as the
@ -1134,8 +1156,9 @@ register_specialization (tree spec, tree tmpl, tree args)
&& !check_specialization_namespace (tmpl))
DECL_CONTEXT (spec) = decl_namespace_context (tmpl);
DECL_TEMPLATE_SPECIALIZATIONS (tmpl)
= tree_cons (args, spec, DECL_TEMPLATE_SPECIALIZATIONS (tmpl));
if (!optimize_specialization_lookup_p (tmpl))
DECL_TEMPLATE_SPECIALIZATIONS (tmpl)
= tree_cons (args, spec, DECL_TEMPLATE_SPECIALIZATIONS (tmpl));
return spec;
}
@ -2393,14 +2416,16 @@ current_template_args (void)
}
/* Return a TEMPLATE_DECL corresponding to DECL, using the indicated
template PARMS. Used by push_template_decl below. */
template PARMS. If MEMBER_TEMPLATE_P is true, the new template is
a mebmer template. Used by push_template_decl below. */
static tree
build_template_decl (tree decl, tree parms)
build_template_decl (tree decl, tree parms, bool member_template_p)
{
tree tmpl = build_lang_decl (TEMPLATE_DECL, DECL_NAME (decl), NULL_TREE);
DECL_TEMPLATE_PARMS (tmpl) = parms;
DECL_CONTEXT (tmpl) = DECL_CONTEXT (decl);
DECL_MEMBER_TEMPLATE_P (tmpl) = member_template_p;
if (DECL_LANG_SPECIFIC (decl))
{
DECL_STATIC_FUNCTION_P (tmpl) = DECL_STATIC_FUNCTION_P (decl);
@ -2636,7 +2661,8 @@ process_partial_specialization (tree decl)
}
}
if (retrieve_specialization (maintmpl, specargs))
if (retrieve_specialization (maintmpl, specargs,
/*class_specializations_p=*/true))
/* We've already got this specialization. */
return decl;
@ -2826,6 +2852,9 @@ push_template_decl_real (tree decl, int is_friend)
int primary;
int is_partial;
int new_template_p = 0;
/* True if the template is a member template, in the sense of
[temp.mem]. */
bool member_template_p = false;
if (decl == error_mark_node)
return decl;
@ -2862,6 +2891,8 @@ push_template_decl_real (tree decl, int is_friend)
if (primary)
{
if (DECL_CLASS_SCOPE_P (decl))
member_template_p = true;
if (current_lang_name == lang_name_c)
error ("template with C linkage");
else if (TREE_CODE (decl) == TYPE_DECL
@ -2941,7 +2972,8 @@ push_template_decl_real (tree decl, int is_friend)
}
else
{
tmpl = build_template_decl (decl, current_template_parms);
tmpl = build_template_decl (decl, current_template_parms,
member_template_p);
new_template_p = 1;
if (DECL_LANG_SPECIFIC (decl)
@ -2984,7 +3016,7 @@ push_template_decl_real (tree decl, int is_friend)
if (DECL_FUNCTION_TEMPLATE_P (tmpl)
&& DECL_TEMPLATE_INFO (decl) && DECL_TI_ARGS (decl)
&& DECL_TEMPLATE_SPECIALIZATION (decl)
&& is_member_template (tmpl))
&& DECL_MEMBER_TEMPLATE_P (tmpl))
{
tree new_tmpl;
@ -2996,7 +3028,8 @@ push_template_decl_real (tree decl, int is_friend)
args = DECL_TI_ARGS (decl);
new_tmpl
= build_template_decl (decl, current_template_parms);
= build_template_decl (decl, current_template_parms,
member_template_p);
DECL_TEMPLATE_RESULT (new_tmpl) = decl;
TREE_TYPE (new_tmpl) = TREE_TYPE (decl);
DECL_TI_TEMPLATE (decl) = new_tmpl;
@ -4342,7 +4375,6 @@ lookup_template_class (tree d1,
tree gen_tmpl;
tree type_decl;
tree found = NULL_TREE;
tree *tp;
int arg_depth;
int parm_depth;
int is_partial_instantiation;
@ -4466,22 +4498,11 @@ lookup_template_class (tree d1,
if (found)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, found);
for (tp = &DECL_TEMPLATE_INSTANTIATIONS (template);
*tp;
tp = &TREE_CHAIN (*tp))
if (comp_template_args (TREE_PURPOSE (*tp), arglist))
{
found = *tp;
/* Use the move-to-front heuristic to speed up future
searches. */
*tp = TREE_CHAIN (*tp);
TREE_CHAIN (found)
= DECL_TEMPLATE_INSTANTIATIONS (template);
DECL_TEMPLATE_INSTANTIATIONS (template) = found;
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, TREE_VALUE (found));
}
/* If we already have this specialization, return it. */
found = retrieve_specialization (template, arglist,
/*class_specializations_p=*/false);
if (found)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, found);
/* This type is a "partial instantiation" if any of the template
arguments still involve template parameters. Note that we set
@ -6069,7 +6090,8 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
changed. */
gcc_assert (full_args != tmpl_args);
spec = retrieve_specialization (t, full_args);
spec = retrieve_specialization (t, full_args,
/*class_specializations_p=*/true);
if (spec != NULL_TREE)
{
r = spec;
@ -6181,7 +6203,8 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
args, complain, in_decl);
/* Check to see if we already have this specialization. */
spec = retrieve_specialization (gen_tmpl, argvec);
spec = retrieve_specialization (gen_tmpl, argvec,
/*class_specializations_p=*/false);
if (spec)
{
@ -6467,7 +6490,8 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
tmpl = DECL_TI_TEMPLATE (t);
gen_tmpl = most_general_template (tmpl);
argvec = tsubst (DECL_TI_ARGS (t), args, complain, in_decl);
spec = retrieve_specialization (gen_tmpl, argvec);
spec = retrieve_specialization (gen_tmpl, argvec,
/*class_specializations_p=*/false);
}
else
spec = retrieve_local_specialization (t);
@ -6657,6 +6681,39 @@ tsubst_function_type (tree t,
return fntype;
}
/* FNTYPE is a FUNCTION_TYPE or METHOD_TYPE. Substitute the template
ARGS into that specification, and return the substituted
specification. If there is no specification, return NULL_TREE. */
static tree
tsubst_exception_specification (tree fntype,
tree args,
tsubst_flags_t complain,
tree in_decl)
{
tree specs;
tree new_specs;
specs = TYPE_RAISES_EXCEPTIONS (fntype);
new_specs = NULL_TREE;
if (specs)
{
if (! TREE_VALUE (specs))
new_specs = specs;
else
while (specs)
{
tree spec;
spec = tsubst (TREE_VALUE (specs), args, complain, in_decl);
if (spec == error_mark_node)
return spec;
new_specs = add_exception_specifier (new_specs, spec, complain);
specs = TREE_CHAIN (specs);
}
}
return new_specs;
}
/* Substitute into the PARMS of a call-declarator. */
static tree
@ -7089,32 +7146,16 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
case METHOD_TYPE:
{
tree fntype;
tree raises;
tree specs;
fntype = tsubst_function_type (t, args, complain, in_decl);
if (fntype == error_mark_node)
return error_mark_node;
/* Substitute the exception specification. */
raises = TYPE_RAISES_EXCEPTIONS (t);
if (raises)
{
tree list = NULL_TREE;
if (! TREE_VALUE (raises))
list = raises;
else
for (; raises != NULL_TREE; raises = TREE_CHAIN (raises))
{
tree spec = TREE_VALUE (raises);
spec = tsubst (spec, args, complain, in_decl);
if (spec == error_mark_node)
return spec;
list = add_exception_specifier (list, spec, complain);
}
fntype = build_exception_variant (fntype, list);
}
specs = tsubst_exception_specification (t, args, complain,
in_decl);
if (specs)
fntype = build_exception_variant (fntype, specs);
return fntype;
}
case ARRAY_TYPE:
@ -7537,7 +7578,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
if (DECL_TEMPLATE_TEMPLATE_PARM_P (t))
return tsubst (TREE_TYPE (DECL_TEMPLATE_RESULT (t)),
args, complain, in_decl);
else if (is_member_template (t))
else if (DECL_FUNCTION_TEMPLATE_P (t) && DECL_MEMBER_TEMPLATE_P (t))
return tsubst (t, args, complain, in_decl);
else if (DECL_CLASS_SCOPE_P (t)
&& uses_template_parms (DECL_CONTEXT (t)))
@ -8736,7 +8777,8 @@ instantiate_template (tree tmpl, tree targ_ptr, tsubst_flags_t complain)
}
/* Check to see if we already have this specialization. */
spec = retrieve_specialization (tmpl, targ_ptr);
spec = retrieve_specialization (tmpl, targ_ptr,
/*class_specializations_p=*/false);
if (spec != NULL_TREE)
return spec;
@ -8750,7 +8792,8 @@ instantiate_template (tree tmpl, tree targ_ptr, tsubst_flags_t complain)
targ_ptr);
/* Check to see if we already have this specialization. */
spec = retrieve_specialization (gen_tmpl, targ_ptr);
spec = retrieve_specialization (gen_tmpl, targ_ptr,
/*class_specializations_p=*/false);
if (spec != NULL_TREE)
return spec;
}
@ -10808,75 +10851,76 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
static void
regenerate_decl_from_template (tree decl, tree tmpl)
{
/* The most general version of TMPL. */
tree gen_tmpl;
/* The arguments used to instantiate DECL, from the most general
template. */
tree args;
tree code_pattern;
tree new_decl;
bool unregistered;
args = DECL_TI_ARGS (decl);
code_pattern = DECL_TEMPLATE_RESULT (tmpl);
/* Unregister the specialization so that when we tsubst we will not
just return DECL. We don't have to unregister DECL from TMPL
because if would only be registered there if it were a partial
instantiation of a specialization, which it isn't: it's a full
instantiation. */
gen_tmpl = most_general_template (tmpl);
unregistered = reregister_specialization (decl, gen_tmpl,
/*new_spec=*/NULL_TREE);
/* If the DECL was not unregistered then something peculiar is
happening: we created a specialization but did not call
register_specialization for it. */
gcc_assert (unregistered);
/* Make sure that we can see identifiers, and compute access
correctly. */
push_access_scope (decl);
/* Do the substitution to get the new declaration. */
new_decl = tsubst (code_pattern, args, tf_error, NULL_TREE);
if (TREE_CODE (decl) == VAR_DECL)
if (TREE_CODE (decl) == FUNCTION_DECL)
{
/* Set up DECL_INITIAL, since tsubst doesn't. */
if (!DECL_INITIALIZED_IN_CLASS_P (decl))
DECL_INITIAL (new_decl) =
tree decl_parm;
tree pattern_parm;
tree specs;
int args_depth;
int parms_depth;
args_depth = TMPL_ARGS_DEPTH (args);
parms_depth = TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl));
if (args_depth > parms_depth)
args = get_innermost_template_args (args, parms_depth);
specs = tsubst_exception_specification (TREE_TYPE (code_pattern),
args, tf_error, NULL_TREE);
if (specs)
TREE_TYPE (decl) = build_exception_variant (TREE_TYPE (decl),
specs);
/* Merge parameter declarations. */
decl_parm = skip_artificial_parms_for (decl,
DECL_ARGUMENTS (decl));
pattern_parm
= skip_artificial_parms_for (code_pattern,
DECL_ARGUMENTS (code_pattern));
while (decl_parm)
{
tree parm_type;
if (DECL_NAME (decl_parm) != DECL_NAME (pattern_parm))
DECL_NAME (decl_parm) = DECL_NAME (pattern_parm);
parm_type = tsubst (TREE_TYPE (pattern_parm), args, tf_error,
NULL_TREE);
if (!same_type_p (TREE_TYPE (decl_parm), parm_type))
TREE_TYPE (decl_parm) = parm_type;
decl_parm = TREE_CHAIN (decl_parm);
pattern_parm = TREE_CHAIN (pattern_parm);
}
/* Merge additional specifiers from the CODE_PATTERN. */
if (DECL_DECLARED_INLINE_P (code_pattern)
&& !DECL_DECLARED_INLINE_P (decl))
DECL_DECLARED_INLINE_P (decl) = 1;
if (DECL_INLINE (code_pattern) && !DECL_INLINE (decl))
DECL_INLINE (decl) = 1;
}
else if (TREE_CODE (decl) == VAR_DECL)
{
if (!DECL_INITIALIZED_IN_CLASS_P (decl)
&& DECL_INITIAL (code_pattern))
DECL_INITIAL (decl) =
tsubst_expr (DECL_INITIAL (code_pattern), args,
tf_error, DECL_TI_TEMPLATE (decl));
}
else if (TREE_CODE (decl) == FUNCTION_DECL)
{
/* Convince duplicate_decls to use the DECL_ARGUMENTS from the
new decl. */
DECL_INITIAL (new_decl) = error_mark_node;
/* And don't complain about a duplicate definition. */
DECL_INITIAL (decl) = NULL_TREE;
}
else
gcc_unreachable ();
pop_access_scope (decl);
/* The immediate parent of the new template is still whatever it was
before, even though tsubst sets DECL_TI_TEMPLATE up as the most
general template. We also reset the DECL_ASSEMBLER_NAME since
tsubst always calculates the name as if the function in question
were really a template instance, and sometimes, with friend
functions, this is not so. See tsubst_friend_function for
details. */
DECL_TI_TEMPLATE (new_decl) = DECL_TI_TEMPLATE (decl);
COPY_DECL_ASSEMBLER_NAME (decl, new_decl);
COPY_DECL_RTL (decl, new_decl);
DECL_USE_TEMPLATE (new_decl) = DECL_USE_TEMPLATE (decl);
/* Call duplicate decls to merge the old and new declarations. */
duplicate_decls (new_decl, decl);
/* Now, re-register the specialization. */
register_specialization (decl, gen_tmpl, args);
}
/* Return the TEMPLATE_DECL into which DECL_TI_ARGS(DECL) should be
@ -10994,7 +11038,8 @@ instantiate_decl (tree d, int defer_ok, int undefined_ok)
DECL_TEMPLATE_SPECIALIZATION. */
gen_tmpl = most_general_template (tmpl);
gen_args = DECL_TI_ARGS (d);
spec = retrieve_specialization (gen_tmpl, gen_args);
spec = retrieve_specialization (gen_tmpl, gen_args,
/*class_specializations_p=*/false);
if (spec != NULL_TREE && DECL_TEMPLATE_SPECIALIZATION (spec))
return spec;

View File

@ -1464,6 +1464,22 @@ lookup_fnfields_1 (tree type, tree name)
return -1;
}
/* Like lookup_fnfields_1, except that the name is extracted from
FUNCTION, which is a FUNCTION_DECL or a TEMPLATE_DECL. */
int
class_method_index_for_fn (tree class_type, tree function)
{
gcc_assert (TREE_CODE (function) == FUNCTION_DECL
|| DECL_FUNCTION_TEMPLATE_P (function));
return lookup_fnfields_1 (class_type,
DECL_CONSTRUCTOR_P (function) ? ctor_identifier :
DECL_DESTRUCTOR_P (function) ? dtor_identifier :
DECL_NAME (function));
}
/* DECL is the result of a qualified name lookup. QUALIFYING_SCOPE is
the class or namespace used to qualify the name. CONTEXT_CLASS is
the class corresponding to the object in which DECL will be used.