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> 2009-07-01 Jason Merrill <jason@redhat.com>
* cp-tree.h (DECL_CLASS_TEMPLATE_P): Use DECL_IMPLICIT_TYPEDEF_P. * 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) ...@@ -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)) TREE_VEC_LENGTH (DECL_INNERMOST_TEMPLATE_PARMS (NODE))
/* For function, method, class-data templates. */ /* For function, method, class-data templates. */
#define DECL_TEMPLATE_RESULT(NODE) DECL_RESULT_FLD (NODE) #define DECL_TEMPLATE_RESULT(NODE) DECL_RESULT_FLD (NODE)
/* For a static member variable template, the /* For a function template at namespace scope, DECL_TEMPLATE_INSTANTIATIONS
DECL_TEMPLATE_INSTANTIATIONS list contains the explicitly and lists all instantiations and specializations of the function so that
implicitly generated instantiations of the variable. There are no tsubst_friend_function can reassign them to another template if we find
partial instantiations of static member variables, so all of these that the namespace-scope template is really a partial instantiation of a
will be full instantiations. friend template.
For a class template the DECL_TEMPLATE_INSTANTIATIONS lists holds For a class template the DECL_TEMPLATE_INSTANTIATIONS lists holds
all instantiations and specializations of the class type, including 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 In both cases, the TREE_PURPOSE of each node contains the arguments
used; the TREE_VALUE contains the generated variable. The template 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) ...@@ -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 DECL_TEMPLATE_INSTANTIATIONS list for `template <class T> template
<class U> struct S1<T>::S2'. <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) #define DECL_TEMPLATE_INSTANTIATIONS(NODE) DECL_VINDEX (NODE)
/* For a function template, the DECL_TEMPLATE_SPECIALIZATIONS lists /* For a class template, this list contains the partial
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
specializations of this template. (Full specializations are not specializations of this template. (Full specializations are not
recorded on this list.) The TREE_PURPOSE holds the arguments used recorded on this list.) The TREE_PURPOSE holds the arguments used
in the partial specialization (e.g., for `template <class T> struct 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) ...@@ -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 example above.) The TREE_TYPE is the _TYPE node for the partial
specialization. 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) #define DECL_TEMPLATE_SPECIALIZATIONS(NODE) DECL_SIZE (NODE)
/* Nonzero for a DECL which is actually a template parameter. Keep /* Nonzero for a DECL which is actually a template parameter. Keep
...@@ -4619,6 +4602,7 @@ extern tree fold_non_dependent_expr (tree); ...@@ -4619,6 +4602,7 @@ extern tree fold_non_dependent_expr (tree);
extern bool explicit_class_specialization_p (tree); extern bool explicit_class_specialization_p (tree);
extern struct tinst_level *outermost_tinst_level(void); extern struct tinst_level *outermost_tinst_level(void);
extern bool parameter_of_template_p (tree, tree); extern bool parameter_of_template_p (tree, tree);
extern void init_template_processing (void);
/* in repo.c */ /* in repo.c */
extern void init_repo (void); extern void init_repo (void);
......
...@@ -1109,7 +1109,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) ...@@ -1109,7 +1109,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
unsigned olddecl_uid = DECL_UID (olddecl); unsigned olddecl_uid = DECL_UID (olddecl);
int olddecl_friend = 0, types_match = 0, hidden_friend = 0; int olddecl_friend = 0, types_match = 0, hidden_friend = 0;
int new_defines_function = 0; int new_defines_function = 0;
tree new_template; tree new_template_info;
if (newdecl == olddecl) if (newdecl == olddecl)
return olddecl; return olddecl;
...@@ -1855,7 +1855,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) ...@@ -1855,7 +1855,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
if (! DECL_EXTERNAL (olddecl)) if (! DECL_EXTERNAL (olddecl))
DECL_EXTERNAL (newdecl) = 0; DECL_EXTERNAL (newdecl) = 0;
new_template = NULL_TREE; new_template_info = NULL_TREE;
if (DECL_LANG_SPECIFIC (newdecl) && DECL_LANG_SPECIFIC (olddecl)) if (DECL_LANG_SPECIFIC (newdecl) && DECL_LANG_SPECIFIC (olddecl))
{ {
bool new_redefines_gnu_inline = false; bool new_redefines_gnu_inline = false;
...@@ -1899,7 +1899,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) ...@@ -1899,7 +1899,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl); DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
DECL_REPO_AVAILABLE_P (newdecl) = DECL_REPO_AVAILABLE_P (olddecl); DECL_REPO_AVAILABLE_P (newdecl) = DECL_REPO_AVAILABLE_P (olddecl);
if (DECL_TEMPLATE_INFO (newdecl)) 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_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
DECL_INITIALIZED_IN_CLASS_P (newdecl) DECL_INITIALIZED_IN_CLASS_P (newdecl)
|= DECL_INITIALIZED_IN_CLASS_P (olddecl); |= DECL_INITIALIZED_IN_CLASS_P (olddecl);
...@@ -2097,7 +2097,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) ...@@ -2097,7 +2097,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
memcpy ((char *) olddecl + sizeof (struct tree_decl_common), memcpy ((char *) olddecl + sizeof (struct tree_decl_common),
(char *) newdecl + sizeof (struct tree_decl_common), (char *) newdecl + sizeof (struct tree_decl_common),
sizeof (struct tree_function_decl) - 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 /* If newdecl is a template instantiation, it is possible that
the following sequence of events has occurred: the following sequence of events has occurred:
...@@ -2120,7 +2120,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) ...@@ -2120,7 +2120,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
instantiations so that if we try to do the instantiation instantiations so that if we try to do the instantiation
again we won't get the clobbered declaration. */ again we won't get the clobbered declaration. */
reregister_specialization (newdecl, reregister_specialization (newdecl,
new_template, new_template_info,
olddecl); olddecl);
} }
else else
...@@ -3459,6 +3459,7 @@ cxx_init_decl_processing (void) ...@@ -3459,6 +3459,7 @@ cxx_init_decl_processing (void)
/* Perform other language dependent initializations. */ /* Perform other language dependent initializations. */
init_class_processing (); init_class_processing ();
init_rtti_processing (); init_rtti_processing ();
init_template_processing ();
if (flag_exceptions) if (flag_exceptions)
init_exception_processing (); 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> 2009-07-02 Michael Matz <matz@suse.de>
PR fortran/32131 PR fortran/32131
......
...@@ -5,7 +5,12 @@ ...@@ -5,7 +5,12 @@
template<class T1> struct A template<class T1> struct A
{ {
template<class T2> struct B {}; template<class T2> struct B {};
template<class T2> struct C {};
}; };
template <> template <> struct A<int>::B<int> {}; template <> template <> struct A<int>::B<int>;
template <> template <class U> struct A<int>::B {}; // { dg-error "specialization" } 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