aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@yorick.cygnus.com>1998-02-27 12:15:17 +0000
committerJason Merrill <jason@gcc.gnu.org>1998-02-27 07:15:17 -0500
commit8d019cef1a2ecde418d34b58aece9b5a0be0586f (patch)
tree132ee51a4a24b5c03f0fa420891027b9210b7b84
parent5987a4f34ae693fa52d4f0c4adf136f6becb8984 (diff)
downloadgcc-8d019cef1a2ecde418d34b58aece9b5a0be0586f.zip
gcc-8d019cef1a2ecde418d34b58aece9b5a0be0586f.tar.gz
gcc-8d019cef1a2ecde418d34b58aece9b5a0be0586f.tar.bz2
Support partial specialization of member class templates.
* pt.c (get_class_bindings): Add outer_args parm. (most_specialized_class): Likewise. (instantiate_class_template): Pass it. (more_specialized_class): Likewise. (lookup_template_class): Get context from template if none was specified. (finish_member_template_decl): Don't do anything with a partial specialization. * decl2.c (check_member_template): Use IS_AGGR_TYPE instead of AGGREGATE_TYPE_P. * class.c (finish_struct): Member class templates have already been checked for name clashes. * decl.c (pushdecl_with_scope): Handle pushing at class level. From-SVN: r18285
-rw-r--r--gcc/cp/ChangeLog16
-rw-r--r--gcc/cp/class.c2
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/decl.c19
-rw-r--r--gcc/cp/decl2.c4
-rw-r--r--gcc/cp/pt.c51
6 files changed, 71 insertions, 23 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 319136f..136a71a 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,19 @@
+Fri Feb 27 11:17:50 1998 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (get_class_bindings): Add outer_args parm.
+ (most_specialized_class): Likewise.
+ (instantiate_class_template): Pass it.
+ (more_specialized_class): Likewise.
+ (lookup_template_class): Get context from template if none
+ was specified.
+ (finish_member_template_decl): Don't do anything with a
+ partial specialization.
+ * decl2.c (check_member_template): Use IS_AGGR_TYPE instead of
+ AGGREGATE_TYPE_P.
+ * class.c (finish_struct): Member class templates have already been
+ checked for name clashes.
+ * decl.c (pushdecl_with_scope): Handle pushing at class level.
+
Fri Feb 27 02:25:16 1998 Jason Merrill <jason@yorick.cygnus.com>
* pt.c (tsubst, TEMPLATE_DECL): Support member class templates.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 9868928..6d64e98 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -4375,6 +4375,8 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
/* Check for inconsistent use of this name in the class body.
Enums, types and static vars have already been checked. */
if (TREE_CODE (x) != TYPE_DECL && TREE_CODE (x) != USING_DECL
+ && ! (TREE_CODE (x) == TEMPLATE_DECL
+ && TREE_CODE (DECL_RESULT (x)) == TYPE_DECL)
&& TREE_CODE (x) != CONST_DECL && TREE_CODE (x) != VAR_DECL)
{
tree name = DECL_NAME (x);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 9f96b4a..eedf3e2 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -2458,7 +2458,7 @@ extern void end_tree PROTO((void));
extern void add_maybe_template PROTO((tree, tree));
extern void pop_tinst_level PROTO((void));
extern tree most_specialized PROTO((tree, tree, tree));
-extern tree most_specialized_class PROTO((tree, tree));
+extern tree most_specialized_class PROTO((tree, tree, tree));
extern int more_specialized_class PROTO((tree, tree));
extern void do_pushlevel PROTO((void));
extern int is_member_template PROTO((tree));
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 0002891..b61d44a 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -3503,13 +3503,24 @@ pushdecl_with_scope (x, level)
tree x;
struct binding_level *level;
{
- register struct binding_level *b = current_binding_level;
+ register struct binding_level *b;
tree function_decl = current_function_decl;
current_function_decl = NULL_TREE;
- current_binding_level = level;
- x = pushdecl (x);
- current_binding_level = b;
+ if (level->parm_flag == 2)
+ {
+ b = class_binding_level;
+ class_binding_level = level;
+ pushdecl_class_level (x);
+ class_binding_level = b;
+ }
+ else
+ {
+ b = current_binding_level;
+ current_binding_level = level;
+ x = pushdecl (x);
+ current_binding_level = b;
+ }
current_function_decl = function_decl;
return x;
}
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index cb786f9..fa39b9e 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -1386,8 +1386,8 @@ check_member_template (tmpl)
with member templates. */
DECL_IGNORED_P (tmpl) = 1;
}
- else if (TREE_CODE (decl) == TYPE_DECL &&
- AGGREGATE_TYPE_P (TREE_TYPE (decl)))
+ else if (TREE_CODE (decl) == TYPE_DECL
+ && IS_AGGR_TYPE (TREE_TYPE (decl)))
{
if (current_function_decl)
/* 14.5.2.2 [temp.mem]
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index fe66bf4..d5362aa 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -77,7 +77,7 @@ static char *mangle_class_name_for_template PROTO((char *, tree, tree, tree));
static tree tsubst_expr_values PROTO((tree, tree));
static int comp_template_args PROTO((tree, tree));
static int list_eq PROTO((tree, tree));
-static tree get_class_bindings PROTO((tree, tree, tree));
+static tree get_class_bindings PROTO((tree, tree, tree, tree));
static tree coerce_template_parms PROTO((tree, tree, tree, int, int, int));
static tree tsubst_enum PROTO((tree, tree, tree *));
static tree add_to_template_args PROTO((tree, tree));
@@ -109,12 +109,14 @@ finish_member_template_decl (template_parameters, decl)
{
/* Assume that the class is the only declspec. */
decl = TREE_VALUE (decl);
- if (IS_AGGR_TYPE (decl) && CLASSTYPE_TEMPLATE_INFO (decl))
+ if (IS_AGGR_TYPE (decl) && CLASSTYPE_TEMPLATE_INFO (decl)
+ && ! CLASSTYPE_TEMPLATE_SPECIALIZATION (decl))
{
tree tmpl = CLASSTYPE_TI_TEMPLATE (decl);
check_member_template (tmpl);
return tmpl;
}
+ return NULL_TREE;
}
else if (DECL_TEMPLATE_INFO (decl) &&
!DECL_TEMPLATE_SPECIALIZATION (decl))
@@ -2380,6 +2382,8 @@ lookup_template_class (d1, arglist, in_decl, context)
if (! template)
template = IDENTIFIER_CLASS_VALUE (d1);
}
+ if (template)
+ context = DECL_CONTEXT (template);
}
else if (TREE_CODE (d1) == TYPE_DECL && IS_AGGR_TYPE (TREE_TYPE (d1)))
{
@@ -2938,7 +2942,7 @@ instantiate_class_template (type)
tree type;
{
tree template, template_info, args, pattern, t, *field_chain;
- tree typedecl;
+ tree typedecl, outer_args;
if (type == error_mark_node)
return error_mark_node;
@@ -2954,14 +2958,15 @@ instantiate_class_template (type)
if (DECL_TEMPLATE_INFO (template))
{
- args = add_to_template_args (DECL_TI_ARGS (template), args);
+ outer_args = DECL_TI_ARGS (template);
while (DECL_TEMPLATE_INFO (template))
template = DECL_TI_TEMPLATE (template);
}
+ else
+ outer_args = NULL_TREE;
- /* FIXME deal with partial specializations of member templates. */
t = most_specialized_class
- (DECL_TEMPLATE_SPECIALIZATIONS (template), args);
+ (DECL_TEMPLATE_SPECIALIZATIONS (template), args, outer_args);
if (t == error_mark_node)
{
@@ -2969,7 +2974,8 @@ instantiate_class_template (type)
cp_error ("ambiguous class template instantiation for `%#T'", type);
for (t = DECL_TEMPLATE_SPECIALIZATIONS (template); t; t = TREE_CHAIN (t))
{
- if (get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), args))
+ if (get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t),
+ args, outer_args))
{
cp_error_at ("%s %+#T", str, TREE_TYPE (t));
str = " ";
@@ -2987,7 +2993,11 @@ instantiate_class_template (type)
return type;
if (t)
- args = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), args);
+ args = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t),
+ args, outer_args);
+
+ if (outer_args)
+ args = add_to_template_args (outer_args, args);
if (pedantic && uses_template_parms (args))
/* If there are still template parameters amongst the args, then
@@ -3617,7 +3627,7 @@ tsubst (t, args, in_decl)
if (PRIMARY_TEMPLATE_P (t))
TREE_TYPE (DECL_INNERMOST_TEMPLATE_PARMS (tmpl)) = tmpl;
- /* FIXME deal with partial specializations. */
+ /* We don't partially instantiate partial specializations. */
if (TREE_CODE (decl) == TYPE_DECL)
return tmpl;
@@ -5651,12 +5661,14 @@ more_specialized_class (pat1, pat2)
int winner = 0;
targs = get_class_bindings
- (TREE_VALUE (pat1), TREE_PURPOSE (pat1), TREE_PURPOSE (pat2));
+ (TREE_VALUE (pat1), TREE_PURPOSE (pat1),
+ TREE_PURPOSE (pat2), NULL_TREE);
if (targs)
--winner;
targs = get_class_bindings
- (TREE_VALUE (pat2), TREE_PURPOSE (pat2), TREE_PURPOSE (pat1));
+ (TREE_VALUE (pat2), TREE_PURPOSE (pat2),
+ TREE_PURPOSE (pat1), NULL_TREE);
if (targs)
++winner;
@@ -5718,12 +5730,18 @@ get_bindings (fn, decl, explicit_args)
}
static tree
-get_class_bindings (tparms, parms, args)
- tree tparms, parms, args;
+get_class_bindings (tparms, parms, args, outer_args)
+ tree tparms, parms, args, outer_args;
{
int i, dummy, ntparms = TREE_VEC_LENGTH (tparms);
tree vec = make_temp_vec (ntparms);
+ if (outer_args)
+ {
+ tparms = tsubst (tparms, outer_args, NULL_TREE);
+ parms = tsubst (parms, outer_args, NULL_TREE);
+ }
+
for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
{
switch (unify (tparms, &TREE_VEC_ELT (vec, 0), ntparms,
@@ -5803,15 +5821,16 @@ most_specialized (fns, decl, explicit_args)
SPECS that can produce an instantiation matching ARGS. */
tree
-most_specialized_class (specs, mainargs)
- tree specs, mainargs;
+most_specialized_class (specs, mainargs, outer_args)
+ tree specs, mainargs, outer_args;
{
tree list = NULL_TREE, t, args, champ;
int fate;
for (t = specs; t; t = TREE_CHAIN (t))
{
- args = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), mainargs);
+ args = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t),
+ mainargs, outer_args);
if (args)
{
list = decl_tree_cons (TREE_PURPOSE (t), TREE_VALUE (t), list);