Commit 2b110bfc by Jason Merrill Committed by Jason Merrill

Use hash tables for template specialization lookup.

	* pt.c (struct spec_entry): New type.
	(decl_specializations, type_specializations): New hash tables.
	(register_specialization, retrieve_specialization): Use them.
	(reregister_specialization, lookup_template_class): Use them.
	(eq_specializations, hash_tmpl_and_args, hash_specialization): New.
	(iterative_hash_template_arg): New.
	(init_template_processing): New
	(process_partial_specialization): Don't look to see if we already
	have this partial specialization.
	(maybe_process_partial_specialization): Handle reassigning
	full specializations when we get an explicit specialization
	of the partial instantiation.
	(tsubst_friend_function): Adjust specialization reassignment code.
	(instantiate_template): Only do one lookup.
	(instantiate_decl): Don't do any lookup.
	* cp-tree.h: Declare init_template_processing.
	* decl.c (duplicate_decls): Pass args to reregister_specialization.

From-SVN: r149188
parent 74c9e852
2009-07-02 Jason Merrill <jason@redhat.com>
Use hash tables for template specialization lookup.
* pt.c (struct spec_entry): New type.
(decl_specializations, type_specializations): New hash tables.
(register_specialization, retrieve_specialization): Use them.
(reregister_specialization, lookup_template_class): Use them.
(eq_specializations, hash_tmpl_and_args, hash_specialization): New.
(iterative_hash_template_arg): New.
(init_template_processing): New
(process_partial_specialization): Don't look to see if we already
have this partial specialization.
(maybe_process_partial_specialization): Handle reassigning
full specializations when we get an explicit specialization
of the partial instantiation.
(tsubst_friend_function): Adjust specialization reassignment code.
(instantiate_template): Only do one lookup.
(instantiate_decl): Don't do any lookup.
* cp-tree.h: Declare init_template_processing.
* decl.c (duplicate_decls): Pass args to reregister_specialization.
2009-07-01 Jason Merrill <jason@redhat.com>
* cp-tree.h (DECL_CLASS_TEMPLATE_P): Use DECL_IMPLICIT_TYPEDEF_P.
......
......@@ -3072,15 +3072,18 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
TREE_VEC_LENGTH (DECL_INNERMOST_TEMPLATE_PARMS (NODE))
/* For function, method, class-data templates. */
#define DECL_TEMPLATE_RESULT(NODE) DECL_RESULT_FLD (NODE)
/* For a static member variable template, the
DECL_TEMPLATE_INSTANTIATIONS list contains the explicitly and
implicitly generated instantiations of the variable. There are no
partial instantiations of static member variables, so all of these
will be full instantiations.
/* For a function template at namespace scope, DECL_TEMPLATE_INSTANTIATIONS
lists all instantiations and specializations of the function so that
tsubst_friend_function can reassign them to another template if we find
that the namespace-scope template is really a partial instantiation of a
friend template.
For a class template the DECL_TEMPLATE_INSTANTIATIONS lists holds
all instantiations and specializations of the class type, including
partial instantiations and partial specializations.
partial instantiations and partial specializations, so that if we
explicitly specialize a partial instantiation we can walk the list
in maybe_process_partial_specialization and reassign them or complain
as appropriate.
In both cases, the TREE_PURPOSE of each node contains the arguments
used; the TREE_VALUE contains the generated variable. The template
......@@ -3096,29 +3099,9 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
DECL_TEMPLATE_INSTANTIATIONS list for `template <class T> template
<class U> struct S1<T>::S2'.
This list is not used for function templates. */
This list is not used for other templates. */
#define DECL_TEMPLATE_INSTANTIATIONS(NODE) DECL_VINDEX (NODE)
/* For a function template, the DECL_TEMPLATE_SPECIALIZATIONS lists
contains all instantiations and specializations of the function,
including partial instantiations. For a partial instantiation
which is a specialization, this list holds only full
specializations of the template that are instantiations of the
partial instantiation. For example, given:
template <class T> struct S {
template <class U> void f(U);
template <> void f(T);
};
the `S<int>::f<int>(int)' function will appear on the
DECL_TEMPLATE_SPECIALIZATIONS list for both `template <class T>
template <class U> void S<T>::f(U)' and `template <class T> void
S<int>::f(T)'. In the latter case, however, it will have only the
innermost set of arguments (T, in this case). The DECL_TI_TEMPLATE
for the function declaration will point at the specialization, not
the fully general template.
For a class template, this list contains the partial
/* For a class template, this list contains the partial
specializations of this template. (Full specializations are not
recorded on this list.) The TREE_PURPOSE holds the arguments used
in the partial specialization (e.g., for `template <class T> struct
......@@ -3128,7 +3111,7 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
example above.) The TREE_TYPE is the _TYPE node for the partial
specialization.
This list is not used for static variable templates. */
This list is not used for other templates. */
#define DECL_TEMPLATE_SPECIALIZATIONS(NODE) DECL_SIZE (NODE)
/* Nonzero for a DECL which is actually a template parameter. Keep
......@@ -4619,6 +4602,7 @@ extern tree fold_non_dependent_expr (tree);
extern bool explicit_class_specialization_p (tree);
extern struct tinst_level *outermost_tinst_level(void);
extern bool parameter_of_template_p (tree, tree);
extern void init_template_processing (void);
/* in repo.c */
extern void init_repo (void);
......
......@@ -1109,7 +1109,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
unsigned olddecl_uid = DECL_UID (olddecl);
int olddecl_friend = 0, types_match = 0, hidden_friend = 0;
int new_defines_function = 0;
tree new_template;
tree new_template_info;
if (newdecl == olddecl)
return olddecl;
......@@ -1855,7 +1855,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
if (! DECL_EXTERNAL (olddecl))
DECL_EXTERNAL (newdecl) = 0;
new_template = NULL_TREE;
new_template_info = NULL_TREE;
if (DECL_LANG_SPECIFIC (newdecl) && DECL_LANG_SPECIFIC (olddecl))
{
bool new_redefines_gnu_inline = false;
......@@ -1899,7 +1899,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
DECL_REPO_AVAILABLE_P (newdecl) = DECL_REPO_AVAILABLE_P (olddecl);
if (DECL_TEMPLATE_INFO (newdecl))
new_template = DECL_TI_TEMPLATE (newdecl);
new_template_info = DECL_TEMPLATE_INFO (newdecl);
DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
DECL_INITIALIZED_IN_CLASS_P (newdecl)
|= DECL_INITIALIZED_IN_CLASS_P (olddecl);
......@@ -2097,7 +2097,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
memcpy ((char *) olddecl + sizeof (struct tree_decl_common),
(char *) newdecl + sizeof (struct tree_decl_common),
sizeof (struct tree_function_decl) - sizeof (struct tree_decl_common));
if (new_template)
if (new_template_info)
/* If newdecl is a template instantiation, it is possible that
the following sequence of events has occurred:
......@@ -2120,7 +2120,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
instantiations so that if we try to do the instantiation
again we won't get the clobbered declaration. */
reregister_specialization (newdecl,
new_template,
new_template_info,
olddecl);
}
else
......@@ -3459,6 +3459,7 @@ cxx_init_decl_processing (void)
/* Perform other language dependent initializations. */
init_class_processing ();
init_rtti_processing ();
init_template_processing ();
if (flag_exceptions)
init_exception_processing ();
......
2009-07-02 Jason Merrill <jason@redhat.com>
* g++.dg/template/spec8.C: Fix.
2009-07-02 Michael Matz <matz@suse.de>
PR fortran/32131
......
......@@ -5,7 +5,12 @@
template<class T1> struct A
{
template<class T2> struct B {};
template<class T2> struct C {};
};
template <> template <> struct A<int>::B<int> {};
template <> template <class U> struct A<int>::B {}; // { dg-error "specialization" }
template <> template <> struct A<int>::B<int>;
template <> template <class U> struct A<int>::B {};
A<int>::B<int> ab; // { dg-error "incomplete" }
A<int>::C<char> ac;
template <> template <class U> struct A<int>::C {}; // { dg-error "specialization" }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment