pushtag contains special code to call pushdecl_with_scope on the
TEMPLATE_DECL for S2. */
- pushlevel (0);
- declare_pseudo_global_level ();
+ begin_scope (sk_template_parms);
++processing_template_decl;
++processing_template_parmlist;
note_template_header (0);
void
begin_specialization ()
{
+ begin_scope (sk_template_spec);
note_template_header (1);
check_specialization_scope ();
}
void
end_specialization ()
{
+ finish_scope ();
reset_specialization ();
}
int specialization = 0;
int explicit_instantiation = 0;
int member_specialization = 0;
-
tree ctype = DECL_CLASS_CONTEXT (decl);
tree dname = DECL_NAME (decl);
+ tmpl_spec_kind tsk;
- if (processing_specialization)
- {
- /* The last template header was of the form template <>. */
-
- if (template_header_count > template_count)
- {
- /* There were more template headers than qualifying template
- classes. */
- if (template_header_count - template_count > 1)
- /* There shouldn't be that many template parameter lists.
- There can be at most one parameter list for every
- qualifying class, plus one for the function itself. */
- cp_error ("too many template parameter lists in declaration of `%D'", decl);
+ tsk = current_tmpl_spec_kind (template_count);
- SET_DECL_TEMPLATE_SPECIALIZATION (decl);
- if (ctype)
- member_specialization = 1;
- else
- specialization = 1;
- }
- else if (template_header_count == template_count)
+ switch (tsk)
+ {
+ case tsk_none:
+ if (processing_specialization)
{
- /* The counts are equal. So, this might be a
- specialization, but it is not a specialization of a
- member template. It might be something like
-
- template <class T> struct S {
- void f(int i);
- };
- template <>
- void S<int>::f(int i) {} */
specialization = 1;
SET_DECL_TEMPLATE_SPECIALIZATION (decl);
}
- else
+ else if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
{
- /* This cannot be an explicit specialization. There are not
- enough headers for all of the qualifying classes. For
- example, we might have:
-
- template <>
- void S<int>::T<char>::f();
+ if (is_friend)
+ /* This could be something like:
- But, we're missing another template <>. */
- cp_error("too few template parameter lists in declaration of `%D'", decl);
- return decl;
- }
- }
- else if (processing_explicit_instantiation)
- {
- if (template_header_count)
- cp_error ("template parameter list used in explicit instantiation");
-
+ template <class T> void f(T);
+ class S { friend void f<>(int); } */
+ specialization = 1;
+ else
+ {
+ /* This case handles bogus declarations like template <>
+ template <class T> void f<int>(); */
+
+ cp_error ("template-id `%D' in declaration of primary template",
+ declarator);
+ return decl;
+ }
+ }
+ break;
+
+ case tsk_invalid_member_spec:
+ /* The error has already been reported in
+ check_specialization_scope. */
+ return error_mark_node;
+
+ case tsk_invalid_expl_inst:
+ cp_error ("template parameter list used in explicit instantiation");
+
+ /* Fall through. */
+
+ case tsk_expl_inst:
if (have_def)
cp_error ("definition provided for explicit instantiation");
-
+
explicit_instantiation = 1;
- }
- else if (ctype != NULL_TREE
- && !TYPE_BEING_DEFINED (ctype)
- && CLASSTYPE_TEMPLATE_INSTANTIATION (ctype)
- && !is_friend)
- {
- /* This case catches outdated code that looks like this:
-
- template <class T> struct S { void f(); };
- void S<int>::f() {} // Missing template <>
+ break;
- We disable this check when the type is being defined to
- avoid complaining about default compiler-generated
- constructors, destructors, and assignment operators.
- Since the type is an instantiation, not a specialization,
- these are the only functions that can be defined before
- the class is complete. */
+ case tsk_excessive_parms:
+ cp_error ("too many template parameter lists in declaration of `%D'",
+ decl);
+ return error_mark_node;
- /* If they said
- template <class T> void S<int>::f() {}
- that's bogus. */
+ /* Fall through. */
+ case tsk_expl_spec:
+ SET_DECL_TEMPLATE_SPECIALIZATION (decl);
+ if (ctype)
+ member_specialization = 1;
+ else
+ specialization = 1;
+ break;
+
+ case tsk_insufficient_parms:
if (template_header_count)
{
- cp_error ("template parameters specified in specialization");
+ cp_error("too few template parameter lists in declaration of `%D'",
+ decl);
return decl;
}
+ else if (ctype != NULL_TREE
+ && !TYPE_BEING_DEFINED (ctype)
+ && CLASSTYPE_TEMPLATE_INSTANTIATION (ctype)
+ && !is_friend)
+ {
+ /* For backwards compatibility, we accept:
- if (pedantic)
- cp_pedwarn
- ("explicit specialization not preceded by `template <>'");
- specialization = 1;
- SET_DECL_TEMPLATE_SPECIALIZATION (decl);
- }
- else if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
- {
- if (is_friend)
- /* This could be something like:
+ template <class T> struct S { void f(); };
+ void S<int>::f() {} // Missing template <>
- template <class T> void f(T);
- class S { friend void f<>(int); } */
- specialization = 1;
- else
+ That used to be legal C++. */
+ if (pedantic)
+ cp_pedwarn
+ ("explicit specialization not preceded by `template <>'");
+ specialization = 1;
+ SET_DECL_TEMPLATE_SPECIALIZATION (decl);
+ }
+ break;
+
+ case tsk_template:
+ if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
{
/* This case handles bogus declarations like template <>
template <class T> void f<int>(); */
declarator);
return decl;
}
+
+ if (ctype && CLASSTYPE_TEMPLATE_INSTANTIATION (ctype))
+ /* This is a specialization of a member template, without
+ specialization the containing class. Something like:
+
+ template <class T> struct S {
+ template <class U> void f (U);
+ };
+ template <> template <class U> void S<int>::f(U) {}
+
+ That's a specialization -- but of the entire template. */
+ specialization = 1;
+ break;
+
+ default:
+ my_friendly_abort (20000309);
}
if (specialization || member_specialization)
targs = new_targs;
}
- decl = instantiate_template (tmpl, targs);
- return decl;
+ return instantiate_template (tmpl, targs);
}
-
+
+ /* If this is both a template specialization, then it's a
+ specialization of a member template of a template class.
+ In that case we want to return the TEMPLATE_DECL, not the
+ specialization of it. */
+ if (tsk == tsk_template)
+ {
+ SET_DECL_TEMPLATE_SPECIALIZATION (tmpl);
+ return tmpl;
+ }
+
/* If we though that the DECL was a member function, but it
turns out to be specializing a static member function,
make DECL a static member function as well. */
we do not mangle S<int>::f() here. That's because it's
just an ordinary member function and doesn't need special
treatment. We do this here so that the ordinary,
- non-template, name-mangling algorith will not be used
+ non-template, name-mangling algorithm will not be used
later. */
if ((is_member_template (tmpl) || ctype == NULL_TREE)
&& name_mangling_version >= 1)
return;
/* This matches the pushlevel in begin_template_parm_list. */
- poplevel (0, 0, 0);
+ finish_scope ();
--processing_template_decl;
current_template_parms = TREE_CHAIN (current_template_parms);
- (void) get_pending_sizes (); /* Why? */
}
/* Given a template argument vector containing the template PARMS.
DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
/* See if this is a primary template. */
- primary = pseudo_global_level_p ();
+ primary = template_parm_scope_p ();
if (primary)
{
tree a, t, current, parms;
int i;
- if (CLASSTYPE_TEMPLATE_INSTANTIATION (ctx))
- cp_error ("must specialize `%#T' before defining member `%#D'",
- ctx, decl);
if (TREE_CODE (decl) == TYPE_DECL)
{
if ((IS_AGGR_TYPE_CODE (TREE_CODE (TREE_TYPE (decl)))
template <class T> struct S {
template <class U> friend void f();
};
- template <class U> friend void f() {}
+ template <class U> void f() {}
template S<int>;
template void f<double>();
if (spec != NULL_TREE)
return spec;
- if (DECL_TEMPLATE_INFO (tmpl))
+ if (DECL_TEMPLATE_INFO (tmpl) && !DECL_TEMPLATE_SPECIALIZATION (tmpl))
{
/* The TMPL is a partial instantiation. To get a full set of
arguments we must add the arguments used to perform the
tree decl;
{
while (DECL_TEMPLATE_INFO (decl)
+ && !(TREE_CODE (decl) == TEMPLATE_DECL
+ && DECL_TEMPLATE_SPECIALIZATION (decl))
/* The DECL_TI_TEMPLATE can be a LOOKUP_EXPR or
IDENTIFIER_NODE in some cases. (See cp-tree.h for
details.) */