aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Mitchell <mark@markmitchell.com>1998-09-05 20:14:21 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>1998-09-05 20:14:21 +0000
commit6c30752f0916390d06be4a7e46d8aea7407dd4c1 (patch)
treed1d0fafc75e4f76e3e8d41616158cdd0406ba16f
parent00dd3ccd9bb42709b6f97f6e94fcbbf4392d57d9 (diff)
downloadgcc-6c30752f0916390d06be4a7e46d8aea7407dd4c1.zip
gcc-6c30752f0916390d06be4a7e46d8aea7407dd4c1.tar.gz
gcc-6c30752f0916390d06be4a7e46d8aea7407dd4c1.tar.bz2
cp-tree.h (TI_PENDING_SPECIALIZATION_FLAG): Remove.
* cp-tree.h (TI_PENDING_SPECIALIZATION_FLAG): Remove. * class.c (finish_struct): Remove hackery to deal with explicit specializations in class scope. * decl.c (grokfndecl): Improve error-recovery. * decl2.c (grokfield): Likewise. * pt.c (check_specialization_scope): New function. (begin_specialization): Call it. (process_partial_specialization): New function, split out from push_template_decl. Check partial specializations more stringently. (push_template_decl): Call it. (check_explicit_specialization): Don't attempt to handle explicit specializations in class scope. (template_parm_data): Document. Add current_arg and arg_uses_template_parms. (mark_template_parm): Set it. (tsubst_arg_types): Remove unused variable. * semantics.c (begin_class_definition): Tweak. From-SVN: r22271
-rw-r--r--gcc/cp/ChangeLog21
-rw-r--r--gcc/cp/class.c36
-rw-r--r--gcc/cp/cp-tree.h6
-rw-r--r--gcc/cp/decl.c18
-rw-r--r--gcc/cp/decl2.c4
-rw-r--r--gcc/cp/pt.c347
-rw-r--r--gcc/cp/semantics.c2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/explicit12.C8
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/explicit13.C7
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/explicit35.C6
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/memclass7.C7
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/memtemp61.C3
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/memtemp62.C3
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/memtemp77.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/spec10.C13
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/spec11.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/spec12.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/spec13.C13
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/spec15.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/spec20.C11
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/spec21.C16
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/spec22.C15
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/spec6.C14
23 files changed, 373 insertions, 193 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 0beacd2..c092ea2 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,24 @@
+1998-09-05 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (TI_PENDING_SPECIALIZATION_FLAG): Remove.
+ * class.c (finish_struct): Remove hackery to deal with explicit
+ specializations in class scope.
+ * decl.c (grokfndecl): Improve error-recovery.
+ * decl2.c (grokfield): Likewise.
+ * pt.c (check_specialization_scope): New function.
+ (begin_specialization): Call it.
+ (process_partial_specialization): New function, split out from
+ push_template_decl. Check partial specializations more
+ stringently.
+ (push_template_decl): Call it.
+ (check_explicit_specialization): Don't attempt to handle explicit
+ specializations in class scope.
+ (template_parm_data): Document. Add current_arg and
+ arg_uses_template_parms.
+ (mark_template_parm): Set it.
+ (tsubst_arg_types): Remove unused variable.
+ * semantics.c (begin_class_definition): Tweak.
+
1998-09-04 Mark Mitchell <mark@markmitchell.com>
* inc/typeinfo (type_info::type_info(const char*)): Make
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index bcdf957..173c69a 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -4148,8 +4148,6 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
{
tree fields = NULL_TREE;
tree *tail = &TYPE_METHODS (t);
- tree specializations = NULL_TREE;
- tree *specialization_tail = &specializations;
tree name = TYPE_NAME (t);
tree x, last_x = NULL_TREE;
tree access;
@@ -4259,19 +4257,6 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
if (last_x)
TREE_CHAIN (last_x) = next_x;
- if (DECL_TEMPLATE_SPECIALIZATION (x))
- /* We don't enter the specialization into the class
- method vector since specializations don't affect
- overloading. Instead we keep track of the
- specializations, and process them after the method
- vector is complete. */
- {
- *specialization_tail = x;
- specialization_tail = &TREE_CHAIN (x);
- TREE_CHAIN (x) = NULL_TREE;
- continue;
- }
-
/* Link x onto end of TYPE_METHODS. */
*tail = x;
tail = &TREE_CHAIN (x);
@@ -4359,27 +4344,6 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
t = finish_struct_1 (t, warn_anon);
TYPE_BEING_DEFINED (t) = 0;
-
- /* Now, figure out which member templates we're specializing. */
- for (x = specializations; x != NULL_TREE; x = TREE_CHAIN (x))
- {
- int pending_specialization;
-
- pending_specialization
- = TI_PENDING_SPECIALIZATION_FLAG (DECL_TEMPLATE_INFO (x));
- check_explicit_specialization
- (lookup_template_function (DECL_NAME (x), DECL_TI_ARGS (x)),
- x, 0, 1 | (8 * pending_specialization));
- TI_PENDING_SPECIALIZATION_FLAG (DECL_TEMPLATE_INFO (x)) = 0;
-
- /* Now, the assembler name will be correct for fn, so we
- make its RTL. */
- DECL_RTL (x) = 0;
- make_decl_rtl (x, NULL_PTR, 1);
- DECL_RTL (DECL_TI_TEMPLATE (x)) = 0;
- make_decl_rtl (DECL_TI_TEMPLATE (x), NULL_PTR, 1);
- }
-
if (current_class_type)
popclass (0);
else
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 8bf6c5c..3c3a858 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -35,7 +35,6 @@ Boston, MA 02111-1307, USA. */
(TREE_MANGLED) (in IDENTIFIER_NODE) (commented-out).
1: IDENTIFIER_VIRTUAL_P.
TI_PENDING_TEMPLATE_FLAG.
- TI_PENDING_SPECIALIZATION_FLAG.
TEMPLATE_PARMS_FOR_INLINE.
DELETE_EXPR_USE_VEC (in DELETE_EXPR).
(TREE_CALLS_NEW) (in _EXPR or _REF) (commented-out).
@@ -1267,11 +1266,6 @@ struct lang_decl
#define TI_SPEC_INFO(NODE) (TREE_CHAIN (NODE))
#define TI_PENDING_TEMPLATE_FLAG(NODE) TREE_LANG_FLAG_1 (NODE)
-/* TI_PENDING_SPECIALIZATION_FLAG on a template-info node indicates
- that the template is a specialization of a member template, but
- that we don't yet know which one. */
-#define TI_PENDING_SPECIALIZATION_FLAG(NODE) TREE_LANG_FLAG_1 (NODE)
-
/* The TEMPLATE_DECL instantiated or specialized by NODE. This
TEMPLATE_DECL will be the immediate parent, not the most general
template. For example, in:
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 75538c4..42748ff 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -8016,6 +8016,8 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
template_count,
2 * (funcdef_flag != 0) +
4 * (friendp != 0));
+ if (decl == error_mark_node)
+ return error_mark_node;
if ((! TYPE_FOR_JAVA (ctype) || check_java_method (ctype, decl))
&& check)
@@ -8063,6 +8065,9 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
template_count,
2 * (funcdef_flag != 0) +
4 * (friendp != 0));
+ if (decl == error_mark_node)
+ return error_mark_node;
+
if (ctype != NULL_TREE
&& (! TYPE_FOR_JAVA (ctype) || check_java_method (ctype, decl))
&& check)
@@ -10392,10 +10397,15 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
if (decl && DECL_NAME (decl))
{
if (template_class_depth (current_class_type) == 0)
- decl
- = check_explicit_specialization
- (declarator, decl,
- template_count, 2 * (funcdef_flag != 0) + 4);
+ {
+ decl
+ = check_explicit_specialization
+ (declarator, decl,
+ template_count, 2 * (funcdef_flag != 0) + 4);
+ if (decl == error_mark_node)
+ return error_mark_node;
+ }
+
t = do_friend (ctype, declarator, decl,
last_function_parms, flags, quals,
funcdef_flag);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index c01bda2..be8689c 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -1606,8 +1606,8 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
init = NULL_TREE;
value = grokdeclarator (declarator, declspecs, FIELD, init != 0, NULL_TREE);
- if (! value)
- return value; /* friend or constructor went bad. */
+ if (! value || value == error_mark_node)
+ return NULL_TREE; /* friend or constructor went bad. */
/* Pass friendly classes back. */
if (TREE_CODE (value) == VOID_TYPE)
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index b27621b..04c9fd6 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -127,6 +127,8 @@ static int template_class_depth_real PROTO((tree, int));
static tree tsubst_aggr_type PROTO((tree, tree, tree, int));
static tree tsubst_decl PROTO((tree, tree, tree, tree));
static tree tsubst_arg_types PROTO((tree, tree, tree));
+static void check_specialization_scope PROTO((void));
+static tree process_partial_specialization PROTO((tree));
/* We use TREE_VECs to hold template arguments. If there is only one
level of template arguments, then the TREE_VEC contains the
@@ -575,12 +577,44 @@ begin_template_parm_list ()
note_template_header (0);
}
+/* This routine is called when a specialization is declared. If it is
+ illegal to declare a specialization here, an error is reported. */
+
+void
+check_specialization_scope ()
+{
+ tree scope = current_scope ();
+ /* [temp.expl.spec]
+
+ An explicit specialization shall be declared in the namespace of
+ which the template is a member, or, for member templates, in the
+ namespace of which the enclosing class or enclosing class
+ template is a member. An explicit specialization of a member
+ function, member class or static data member of a class template
+ shall be declared in the namespace of which the class template
+ is a member. */
+ if (scope && TREE_CODE (scope) != NAMESPACE_DECL)
+ cp_error ("explicit specialization in non-namespace scope `%D'",
+ scope);
+ /* [temp.expl.spec]
+
+ In an explicit specialization declaration for a member of a class
+ template or a member template that appears in namespace scope,
+ the member template and some of its enclosing class templates may
+ remain unspecialized, except that the declaration shall not
+ explicitly specialize a class member template if its enclosing
+ class templates are not explicitly specialized as well. */
+ if (current_template_parms)
+ cp_error ("enclosing class templates are not explicit specialized");
+}
+
/* We've just seen template <>. */
void
begin_specialization ()
{
note_template_header (1);
+ check_specialization_scope ();
}
/* Called at then end of processing a declaration preceeded by
@@ -1209,17 +1243,10 @@ check_explicit_specialization (declarator, decl, template_count, flags)
if (ctype != NULL_TREE && TYPE_BEING_DEFINED (ctype))
{
if (!explicit_instantiation)
- {
- /* 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 fix this up later. */
- tree ti = perm_tree_cons (NULL_TREE,
- TREE_OPERAND (declarator, 1),
- NULL_TREE);
- TI_PENDING_SPECIALIZATION_FLAG (ti) = 1;
- DECL_TEMPLATE_INFO (decl) = ti;
- }
+ /* A specialization in class scope. This is illegal,
+ but the error will already have been flagged by
+ check_specialization_scope. */
+ return error_mark_node;
else
/* It's not legal to write an explicit instantiation in
class scope, e.g.:
@@ -1759,8 +1786,23 @@ build_template_decl (decl, parms)
struct template_parm_data
{
+ /* The level of the template parameters we are currently
+ processing. */
int level;
+
+ /* The index of the specialization argument we are currently
+ processing. */
+ int current_arg;
+
+ /* An array whose size is the number of template parameters. The
+ elements are non-zero if the parameter has been used in any one
+ of the arguments processed so far. */
int* parms;
+
+ /* An array whose size is the number of template arguments. The
+ elements are non-zero if the argument makes use of template
+ parameters of this level. */
+ int* arg_uses_template_parms;
};
/* Subroutine of push_template_decl used to see if each template
@@ -1790,13 +1832,205 @@ mark_template_parm (t, data)
}
if (level == tpd->level)
- tpd->parms[idx] = 1;
+ {
+ tpd->parms[idx] = 1;
+ tpd->arg_uses_template_parms[tpd->current_arg] = 1;
+ }
/* Return zero so that for_each_template_parm will continue the
traversal of the tree; we want to mark *every* template parm. */
return 0;
}
+/* Process the partial specialization DECL. */
+
+tree
+process_partial_specialization (decl)
+ tree decl;
+{
+ tree type = TREE_TYPE (decl);
+ tree maintmpl = CLASSTYPE_TI_TEMPLATE (type);
+ tree specargs = CLASSTYPE_TI_ARGS (type);
+ tree inner_args = innermost_args (specargs);
+ tree inner_parms = INNERMOST_TEMPLATE_PARMS (current_template_parms);
+ tree main_inner_parms = DECL_INNERMOST_TEMPLATE_PARMS (maintmpl);
+ int nargs = TREE_VEC_LENGTH (inner_args);
+ int ntparms = TREE_VEC_LENGTH (inner_parms);
+ int i;
+ int did_error_intro = 0;
+ int issued_default_arg_message = 0;
+ struct template_parm_data tpd;
+ struct template_parm_data tpd2;
+
+ /* [temp.class.spec]
+
+ The template parameter list of a specialization shall not
+ contain default template argument values. */
+ for (i = 0; i < ntparms; ++i)
+ {
+ if (TREE_PURPOSE (TREE_VEC_ELT (inner_parms, i)))
+ {
+ if (!issued_default_arg_message)
+ {
+ cp_error ("default argument in partial specialization `%T'",
+ type);
+ issued_default_arg_message = 1;
+ }
+ TREE_PURPOSE (TREE_VEC_ELT (inner_parms, i)) = NULL_TREE;
+ }
+ }
+
+ /* We check that each of the template parameters given in the
+ partial specialization is used in the argument list to the
+ specialization. For example:
+
+ template <class T> struct S;
+ template <class T> struct S<T*>;
+
+ The second declaration is OK because `T*' uses the template
+ parameter T, whereas
+
+ template <class T> struct S<int>;
+
+ is no good. Even trickier is:
+
+ template <class T>
+ struct S1
+ {
+ template <class U>
+ struct S2;
+ template <class U>
+ struct S2<T>;
+ };
+
+ The S2<T> declaration is actually illegal; it is a
+ full-specialization. Of course,
+
+ template <class U>
+ struct S2<T (*)(U)>;
+
+ or some such would have been OK. */
+ tpd.level = TMPL_PARMS_DEPTH (current_template_parms);
+ tpd.parms = alloca (sizeof (int) * ntparms);
+ bzero (tpd.parms, sizeof (int) * nargs);
+
+ tpd.arg_uses_template_parms = alloca (sizeof (int) * nargs);
+ bzero (tpd.arg_uses_template_parms, sizeof (int) * nargs);
+ for (i = 0; i < nargs; ++i)
+ {
+ tpd.current_arg = i;
+ for_each_template_parm (TREE_VEC_ELT (inner_args, i),
+ &mark_template_parm,
+ &tpd);
+ }
+ for (i = 0; i < ntparms; ++i)
+ if (tpd.parms[i] == 0)
+ {
+ /* One of the template parms was not used in the
+ specialization. */
+ if (!did_error_intro)
+ {
+ cp_error ("template parameters not used in partial specialization:");
+ did_error_intro = 1;
+ }
+
+ cp_error (" `%D'",
+ TREE_VALUE (TREE_VEC_ELT (inner_parms, i)));
+ }
+
+ /* [temp.class.spec]
+
+ The argument list of the specialization shall not be identical to
+ the implicit argument list of the primary template. */
+ if (comp_template_args (inner_args,
+ innermost_args (CLASSTYPE_TI_ARGS (TREE_TYPE
+ (maintmpl)))))
+ cp_error ("partial specialization `%T' does not specialize any template arguments", type);
+
+ /* [temp.class.spec]
+
+ A partially specialized non-type argument expression shall not
+ involve template parameters of the partial specialization except
+ when the argument expression is a simple identifier.
+
+ The type of a template parameter corresponding to a specialized
+ non-type argument shall not be dependent on a parameter of the
+ specialization. */
+ my_friendly_assert (nargs == DECL_NTPARMS (maintmpl), 0);
+ tpd2.parms = 0;
+ for (i = 0; i < nargs; ++i)
+ {
+ tree arg = TREE_VEC_ELT (inner_args, i);
+ if (/* These first two lines are the `non-type' bit. */
+ TREE_CODE_CLASS (TREE_CODE (arg)) != 't'
+ && TREE_CODE (arg) != TEMPLATE_DECL
+ /* This next line is the `argument expression is not just a
+ simple identifier' condition and also the `specialized
+ non-type argument' bit. */
+ && TREE_CODE (arg) != TEMPLATE_PARM_INDEX)
+ {
+ if (tpd.arg_uses_template_parms[i])
+ cp_error ("template argument `%E' involves template parameter(s)", arg);
+ else
+ {
+ /* Look at the corresponding template parameter,
+ marking which template parameters its type depends
+ upon. */
+ tree type =
+ TREE_TYPE (TREE_VALUE (TREE_VEC_ELT (main_inner_parms,
+ i)));
+
+ if (!tpd2.parms)
+ {
+ /* We haven't yet initialized TPD2. Do so now. */
+ tpd2.arg_uses_template_parms
+ = (int*) alloca (sizeof (int) * nargs);
+ tpd2.parms = (int*) alloca (sizeof (int) * nargs);
+ tpd2.level =
+ TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (maintmpl));
+ }
+
+ /* Mark the template paramters. But this time, we're
+ looking for the template parameters of the main
+ template, not in the specialization. */
+ tpd2.current_arg = i;
+ tpd2.arg_uses_template_parms[i] = 0;
+ bzero (tpd.parms, sizeof (int) * nargs);
+ for_each_template_parm (type,
+ &mark_template_parm,
+ &tpd2);
+
+ if (tpd2.arg_uses_template_parms [i])
+ {
+ /* The type depended on some template parameters.
+ If they are fully specialized in the
+ specialization, that's OK. */
+ int j;
+ for (j = 0; j < nargs; ++j)
+ if (tpd2.parms[j] != 0
+ && tpd.arg_uses_template_parms [j])
+ {
+ cp_error ("type `%T' of template argument `%E' depends on template paramter(s)",
+ type,
+ arg);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (retrieve_specialization (maintmpl, specargs))
+ /* We've already got this specialization. */
+ return decl;
+
+ DECL_TEMPLATE_SPECIALIZATIONS (maintmpl) = CLASSTYPE_TI_SPEC_INFO (type)
+ = perm_tree_cons (inner_args, inner_parms,
+ DECL_TEMPLATE_SPECIALIZATIONS (maintmpl));
+ TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)) = type;
+ return decl;
+}
+
/* Creates a TEMPLATE_DECL for the indicated DECL using the template
parameters given by current_template_args, or reuses a
previously existing one, if appropriate. Returns the DECL, or an
@@ -1868,92 +2102,7 @@ push_template_decl_real (decl, is_friend)
if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl)
&& TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE
&& CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)))
- {
- tree type = TREE_TYPE (decl);
- tree maintmpl = CLASSTYPE_TI_TEMPLATE (type);
- tree specargs = CLASSTYPE_TI_ARGS (type);
-
- /* We check that each of the template parameters given in the
- partial specialization is used in the argument list to the
- specialization. For example:
-
- template <class T> struct S;
- template <class T> struct S<T*>;
-
- The second declaration is OK because `T*' uses the template
- parameter T, whereas
-
- template <class T> struct S<int>;
-
- is no good. Even trickier is:
-
- template <class T>
- struct S1
- {
- template <class U>
- struct S2;
- template <class U>
- struct S2<T>;
- };
-
- The S2<T> declaration is actually illegal; it is a
- full-specialization. Of course,
-
- template <class U>
- struct S2<T (*)(U)>;
-
- or some such would have been OK. */
- int i;
- struct template_parm_data tpd;
- int ntparms
- = TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS (current_template_parms));
- int did_error_intro = 0;
-
- tpd.level = TMPL_PARMS_DEPTH (current_template_parms);
- tpd.parms = alloca (sizeof (int) * ntparms);
- for (i = 0; i < ntparms; ++i)
- tpd.parms[i] = 0;
- for (i = 0; i < TREE_VEC_LENGTH (specargs); ++i)
- for_each_template_parm (TREE_VEC_ELT (specargs, i),
- &mark_template_parm,
- &tpd);
- for (i = 0; i < ntparms; ++i)
- if (tpd.parms[i] == 0)
- {
- /* One of the template parms was not used in the
- specialization. */
- if (!did_error_intro)
- {
- cp_error ("template parameters not used in partial specialization:");
- did_error_intro = 1;
- }
-
- cp_error (" `%D'",
- TREE_VALUE (TREE_VEC_ELT
- (TREE_VALUE (current_template_parms),
- i)));
- }
-
- /* [temp.class.spec]
-
- The argument list of the specialization shall not be
- identical to the implicit argument list of the primary
- template. */
- if (comp_template_args (specargs,
- CLASSTYPE_TI_ARGS (TREE_TYPE (maintmpl))))
- cp_error ("partial specialization `%T' does not specialize any template arguments", type);
-
- if (retrieve_specialization (maintmpl, specargs))
- /* We've already got this specialization. */
- return decl;
-
- DECL_TEMPLATE_SPECIALIZATIONS (maintmpl) = CLASSTYPE_TI_SPEC_INFO (type)
- = perm_tree_cons (innermost_args (specargs),
- INNERMOST_TEMPLATE_PARMS (current_template_parms),
- DECL_TEMPLATE_SPECIALIZATIONS (maintmpl));
- TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)) = type;
- return decl;
- }
+ return process_partial_specialization (decl);
args = current_template_args ();
@@ -5194,7 +5343,6 @@ tsubst_decl (t, args, type, in_decl)
return r;
}
-
/* Substitue into the ARG_TYPES of a function type. */
tree
@@ -5204,7 +5352,6 @@ tsubst_arg_types (arg_types, args, in_decl)
tree in_decl;
{
tree remaining_arg_types;
- tree result;
tree type;
if (!arg_types || arg_types == void_list_node)
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 89aca96..eee6616 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -1234,9 +1234,9 @@ begin_class_definition (t)
&& TREE_CODE (TYPE_CONTEXT (t)) != NAMESPACE_DECL
&& ! current_class_type)
push_template_decl (TYPE_STUB_DECL (t));
+ maybe_process_partial_specialization (t);
pushclass (t, 0);
TYPE_BEING_DEFINED (t) = 1;
- maybe_process_partial_specialization (t);
/* Reset the interface data, at the earliest possible
moment, as it might have been set via a class foo;
before. */
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/explicit12.C b/gcc/testsuite/g++.old-deja/g++.pt/explicit12.C
index 83ebcc1..0defb19 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/explicit12.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/explicit12.C
@@ -5,11 +5,13 @@ struct S
{
template <class T>
void foo(T t);
-
- template <>
- void foo<int>(int) {}
};
+
+template <>
+template <>
+void S<char*>::foo<int>(int) {}
+
int main()
{
S<char*> s;
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/explicit13.C b/gcc/testsuite/g++.old-deja/g++.pt/explicit13.C
index 73e0e19..fbb7901 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/explicit13.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/explicit13.C
@@ -7,13 +7,14 @@ struct S
template <class T>
void foo(T t);
- template <>
- void foo(int) { }
-
template <class T>
void bar(T t) { this->template foo<U>(3.74); }
};
+template <>
+template <>
+void S<int>::foo(int) { }
+
int main()
{
S<int> s;
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/explicit35.C b/gcc/testsuite/g++.old-deja/g++.pt/explicit35.C
index 9f71442..c928263 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/explicit35.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/explicit35.C
@@ -4,11 +4,11 @@ struct S
{
template <class T>
void foo(T t);
-
- template <>
- void foo<int>(int i) { }
};
+template <>
+void S::foo<int>(int i) { }
+
int main()
{
S s;
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/memclass7.C b/gcc/testsuite/g++.old-deja/g++.pt/memclass7.C
index 08166b0..1a5cabe 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/memclass7.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/memclass7.C
@@ -4,12 +4,13 @@ struct S
struct Y {
template <class T>
void foo(T t);
-
- template <>
- void foo<int>(int i) { }
};
};
+template <>
+template <>
+void S::Y<char>::foo<int>(int i) { }
+
int main()
{
S::Y<char> s;
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/memtemp61.C b/gcc/testsuite/g++.old-deja/g++.pt/memtemp61.C
index d67da39..1fdb055 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/memtemp61.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/memtemp61.C
@@ -4,9 +4,6 @@ struct S
{
template <class T>
void foo(T t);
-
- template <>
- void foo(int i);
};
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/memtemp62.C b/gcc/testsuite/g++.old-deja/g++.pt/memtemp62.C
index 2efd4d6..8cfadef 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/memtemp62.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/memtemp62.C
@@ -4,9 +4,6 @@ struct S
{
template <class T>
void foo(T t);
-
- template <>
- void foo(int i);
};
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/memtemp77.C b/gcc/testsuite/g++.old-deja/g++.pt/memtemp77.C
index e6f62cf..ca4cf20 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/memtemp77.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/memtemp77.C
@@ -7,9 +7,9 @@ struct S3
static char* h(U);
};
-template <class T>
template <>
-char* S3<T>::h(int) { return __PRETTY_FUNCTION__; }
+template <>
+char* S3<double>::h(int) { return __PRETTY_FUNCTION__; }
template <>
template <>
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec10.C b/gcc/testsuite/g++.old-deja/g++.pt/spec10.C
index 10947aa..5d53e2d 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/spec10.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/spec10.C
@@ -5,14 +5,15 @@ struct S
{
template <int i>
int f(int j) { abort(); return 0; }
-
- template <>
- int f<7>(int j) { return j + 7; }
-
- template <>
- int f<8>(int j) { return j + 8; }
};
+template <>
+template <>
+int S<double>::f<7>(int j) { return j + 7; }
+
+template <>
+template <>
+int S<double>::f<8>(int j) { return j + 8; }
int main()
{
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec11.C b/gcc/testsuite/g++.old-deja/g++.pt/spec11.C
index 4369f18..340b58e 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/spec11.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/spec11.C
@@ -7,9 +7,9 @@ struct S
int f(U u);
};
-template <class T>
template <>
-int S<T>::f(int i) { return 1; }
+template <>
+int S<char>::f(int i) { return 1; }
int main()
{
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec12.C b/gcc/testsuite/g++.old-deja/g++.pt/spec12.C
index 71676ff..d9c3965 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/spec12.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/spec12.C
@@ -8,9 +8,9 @@ struct S
};
-template <class T>
template <>
-int S<T>::f<int>(int i) { return 1; }
+template <>
+int S<char>::f<int>(int i) { return 1; }
int main()
{
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec13.C b/gcc/testsuite/g++.old-deja/g++.pt/spec13.C
index 8f94570..e5748f5 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/spec13.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/spec13.C
@@ -14,11 +14,11 @@ struct S1
template <class T>
void f(T* t);
-
- template <>
- void f(int* ip) {}
};
+template <>
+void S1::f(int* ip) {}
+
template <class U>
struct S2
{
@@ -27,11 +27,12 @@ struct S2
template <class T>
void f(T* t);
-
- template <>
- void f(int* ip) {}
};
+template <>
+template <>
+void S2<double>::f(int* ip) {}
+
int main()
{
int* ip;
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec15.C b/gcc/testsuite/g++.old-deja/g++.pt/spec15.C
index 0aec1433..2e97b04 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/spec15.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/spec15.C
@@ -28,9 +28,9 @@ struct S3
static int h(U);
};
-template <class T>
template <>
-int S3<T>::h(int) { return 0; }
+template <>
+int S3<double>::h(int) { return 0; }
template <>
template <>
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec20.C b/gcc/testsuite/g++.old-deja/g++.pt/spec20.C
new file mode 100644
index 0000000..497a32d
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.pt/spec20.C
@@ -0,0 +1,11 @@
+// Build don't link:
+
+template <class T>
+struct S {
+ template <class U> void f(U);
+ template <> void f<int>(int); // ERROR - specialization
+
+ template <class V> struct I {};
+ template <class V> struct I<V*> {};
+ template <> struct I<int>; // ERROR - specialization
+};
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec21.C b/gcc/testsuite/g++.old-deja/g++.pt/spec21.C
new file mode 100644
index 0000000..95e12d2
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.pt/spec21.C
@@ -0,0 +1,16 @@
+// Build don't link:
+
+template <class T> struct S {};
+template <class T = int> struct S<T*> {}; // ERROR - default argument
+
+template <int I, int J> struct A {};
+template <int I> struct A<I+5, I*2> {}; // ERROR - argument involves parameter
+
+template <class T, T t> struct C {};
+template <class T> struct C<T, 1>; // ERROR - type depends on parameter
+int i;
+template <class T> struct C<T*, &i>; // ERROR - type depends on parameter
+
+template< int X, int (*array_ptr)[X] > class B {};
+int array[5];
+template< int X > class B<X,&array> { }; // ERROR - type depends on parameter
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec22.C b/gcc/testsuite/g++.old-deja/g++.pt/spec22.C
new file mode 100644
index 0000000..88d55d3
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.pt/spec22.C
@@ -0,0 +1,15 @@
+// Build don't link:
+
+template <class T>
+struct S
+{
+ template <class U>
+ void f();
+};
+
+
+template <class T>
+template <> // ERROR - enclosing classes not specialized
+void S<T>::f<int> ()
+{
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec6.C b/gcc/testsuite/g++.old-deja/g++.pt/spec6.C
index b41ad9d..4ef8e65 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/spec6.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/spec6.C
@@ -4,21 +4,23 @@ struct S1
{
template <class T>
void f(T t1, T t2);
-
- template <>
- void f(int i1, int i2);
};
+
+template <>
+void S1::f(int i1, int i2);
+
template <class U>
struct S2
{
template <class T>
void f(T t1, T t2);
-
- template <>
- void f(int i1, int i2);
};
+template <>
+template <>
+void S2<char>::f(int i1, int i2);
+
void h()
{
S1 s1;