summaryrefslogtreecommitdiff
path: root/gcc/cp/pt.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/pt.c')
-rw-r--r--gcc/cp/pt.c140
1 files changed, 93 insertions, 47 deletions
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 6783b12dbf8..a64fe4cc5a6 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -99,12 +99,24 @@ finish_member_template_decl (template_parameters, decl)
tree decl;
{
if (template_parameters)
- end_template_decl();
+ end_template_decl ();
else
- end_specialization();
+ end_specialization ();
- if (decl && DECL_TEMPLATE_INFO (decl) &&
- !DECL_TEMPLATE_SPECIALIZATION (decl))
+ if (decl == NULL_TREE || decl == void_type_node)
+ return NULL_TREE;
+ else if (TREE_CODE (decl) == TREE_LIST)
+ {
+ decl = TREE_VALUE (decl);
+ if (IS_AGGR_TYPE (decl) && CLASSTYPE_TEMPLATE_INFO (decl))
+ {
+ tree tmpl = CLASSTYPE_TI_TEMPLATE (decl);
+ check_member_template (tmpl);
+ return tmpl;
+ }
+ }
+ else if (DECL_TEMPLATE_INFO (decl) &&
+ !DECL_TEMPLATE_SPECIALIZATION (decl))
{
check_member_template (DECL_TI_TEMPLATE (decl));
return DECL_TI_TEMPLATE (decl);
@@ -130,14 +142,14 @@ int
template_class_depth (type)
tree type;
{
- int depth = 0;
+ int depth;
- /* Note: this implementation will be broken when we have nested
- template classes. Presumably we will have to wrap this if
- statement a loop. */
- if (CLASSTYPE_TEMPLATE_INFO (type)
- && uses_template_parms (CLASSTYPE_TI_ARGS (type)))
- ++depth;
+ for (depth = 0; type && TREE_CODE (type) != FUNCTION_DECL;
+ type = TYPE_CONTEXT (type))
+ if (CLASSTYPE_TEMPLATE_INFO (type)
+ && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type))
+ && uses_template_parms (CLASSTYPE_TI_ARGS (type)))
+ ++depth;
return depth;
}
@@ -1047,18 +1059,19 @@ build_template_parm_index (index, level, orig_level, decl, type)
/* Return a TEMPLATE_PARM_INDEX, similar to INDEX, but whose
- TEMPLATE_PARM_LEVEL has been decreased by one. If such a
+ TEMPLATE_PARM_LEVEL has been decreased by LEVELS. If such a
TEMPLATE_PARM_INDEX already exists, it is returned; otherwise, a
new one is created. */
static tree
-reduce_template_parm_level (index, type)
+reduce_template_parm_level (index, type, levels)
tree index;
tree type;
+ int levels;
{
if (TEMPLATE_PARM_DESCENDANTS (index) == NULL_TREE
|| (TEMPLATE_PARM_LEVEL (TEMPLATE_PARM_DESCENDANTS (index))
- != TEMPLATE_PARM_LEVEL (index) - 1))
+ != TEMPLATE_PARM_LEVEL (index) - levels))
{
tree decl
= build_decl (TREE_CODE (TEMPLATE_PARM_DECL (index)),
@@ -1066,7 +1079,7 @@ reduce_template_parm_level (index, type)
type);
tree t
= build_template_parm_index (TEMPLATE_PARM_IDX (index),
- TEMPLATE_PARM_LEVEL (index) - 1,
+ TEMPLATE_PARM_LEVEL (index) - levels,
TEMPLATE_PARM_ORIG_LEVEL (index),
decl, type);
TEMPLATE_PARM_DESCENDANTS (index) = t;
@@ -1313,16 +1326,19 @@ push_template_decl (decl)
is assumed to be a member of the class. */
ctx = current_class_type;
- if ((! ctx
- || (TREE_CODE_CLASS (TREE_CODE (ctx)) == 't'
- && template_class_depth (ctx) == 0))
- /* At this point, we know that the DECL is not a member of some
- template class. However, a friend function declared in a
- template class is still not primary, since, in general it can
- depend on the template parameters of the enclosing class. */
- && !(is_friend
- && DECL_CLASS_CONTEXT (decl)
- && template_class_depth (DECL_CLASS_CONTEXT (decl)) > 0))
+ /* For determining whether this is a primary template or not, we're really
+ interested in the lexical context, not the true context. */
+ if (is_friend)
+ info = DECL_CLASS_CONTEXT (decl);
+ else
+ info = ctx;
+
+ if (info && TREE_CODE (info) == FUNCTION_DECL)
+ primary = 0;
+ else if (! info
+ || (TYPE_BEING_DEFINED (info) && template_header_count
+ && ! processing_specialization)
+ || (template_header_count > template_class_depth (info)))
primary = 1;
else
primary = 0;
@@ -2376,6 +2392,13 @@ lookup_template_class (d1, arglist, in_decl, context)
template = CLASSTYPE_TI_TEMPLATE (d1);
d1 = DECL_NAME (template);
}
+ else if (TREE_CODE (d1) == TEMPLATE_DECL
+ && TREE_CODE (DECL_RESULT (d1)) == TYPE_DECL)
+ {
+ template = d1;
+ d1 = DECL_NAME (template);
+ context = DECL_CONTEXT (template);
+ }
else
my_friendly_abort (272);
@@ -2928,6 +2951,13 @@ instantiate_class_template (type)
my_friendly_assert (TREE_CODE (template) == TEMPLATE_DECL, 279);
args = TI_ARGS (template_info);
+ if (DECL_TEMPLATE_INFO (template))
+ {
+ args = add_to_template_args (DECL_TI_ARGS (template), args);
+ while (DECL_TEMPLATE_INFO (template))
+ template = DECL_TI_TEMPLATE (template);
+ }
+
t = most_specialized_class
(DECL_TEMPLATE_SPECIALIZATIONS (template), args);
@@ -3391,6 +3421,7 @@ tsubst (t, args, in_decl)
{
int idx;
int level;
+ int levels;
tree r = NULL_TREE;
if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
@@ -3411,12 +3442,17 @@ tsubst (t, args, in_decl)
if (TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
{
- if (TREE_VEC_LENGTH (args) >= level - 1)
+ levels = TREE_VEC_LENGTH (args);
+ if (level <= levels)
arg = TREE_VEC_ELT
(TREE_VEC_ELT (args, level - 1), idx);
}
- else if (level == 1)
- arg = TREE_VEC_ELT (args, idx);
+ else
+ {
+ levels = 1;
+ if (level == 1)
+ arg = TREE_VEC_ELT (args, idx);
+ }
if (arg != NULL_TREE)
{
@@ -3470,14 +3506,14 @@ tsubst (t, args, in_decl)
r = copy_node (t);
TEMPLATE_TYPE_PARM_INDEX (r)
= reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
- r);
+ r, levels);
TYPE_STUB_DECL (r) = TYPE_NAME (r) = TEMPLATE_TYPE_DECL (r);
TYPE_MAIN_VARIANT (r) = r;
TYPE_POINTER_TO (r) = NULL_TREE;
break;
case TEMPLATE_PARM_INDEX:
- r = reduce_template_parm_level (t, TREE_TYPE (t));
+ r = reduce_template_parm_level (t, TREE_TYPE (t), levels);
break;
default:
@@ -3493,23 +3529,15 @@ tsubst (t, args, in_decl)
of a template class. */
tree tmpl;
tree decl = DECL_TEMPLATE_RESULT (t);
- tree new_decl;
tree parms;
tree* new_parms;
tree spec;
- if (TREE_CODE (decl) == TYPE_DECL)
- {
- if (TREE_CODE (TREE_TYPE (decl)) == TEMPLATE_TEMPLATE_PARM)
- /* There is no tsubst'ing to be done in a template template
- parameter. */
- return t;
-
- /* This must be a member template class. We don't handle
- this case yet. */
- sorry ("member template classes");
- return t;
- }
+ if (TREE_CODE (decl) == TYPE_DECL
+ && TREE_CODE (TREE_TYPE (decl)) == TEMPLATE_TEMPLATE_PARM)
+ /* There is no tsubst'ing to be done in a template template
+ parameter. */
+ return t;
/* We might already have an instance of this template. */
spec = retrieve_specialization (t, args);
@@ -3531,10 +3559,22 @@ tsubst (t, args, in_decl)
DECL_CLASS_CONTEXT (tmpl) = tsubst (DECL_CLASS_CONTEXT (t),
args, in_decl);
DECL_TEMPLATE_INFO (tmpl) = build_tree_list (t, args);
- new_decl = tsubst (decl, args, in_decl);
- DECL_RESULT (tmpl) = new_decl;
- DECL_TI_TEMPLATE (new_decl) = tmpl;
- TREE_TYPE (tmpl) = TREE_TYPE (new_decl);
+
+ if (TREE_CODE (decl) == TYPE_DECL)
+ {
+ tree new_type = tsubst (TREE_TYPE (t), args, in_decl);
+ TREE_TYPE (tmpl) = new_type;
+ CLASSTYPE_TI_TEMPLATE (new_type) = tmpl;
+ DECL_RESULT (tmpl) = TYPE_MAIN_DECL (new_type);
+ }
+ else
+ {
+ tree new_decl = tsubst (decl, args, in_decl);
+ DECL_RESULT (tmpl) = new_decl;
+ DECL_TI_TEMPLATE (new_decl) = tmpl;
+ TREE_TYPE (tmpl) = TREE_TYPE (new_decl);
+ }
+
DECL_TEMPLATE_INSTANTIATIONS (tmpl) = NULL_TREE;
SET_DECL_IMPLICIT_INSTANTIATION (tmpl);
@@ -3572,6 +3612,12 @@ tsubst (t, args, in_decl)
NULL_TREE);
}
+ if (PRIMARY_TEMPLATE_P (t))
+ TREE_TYPE (DECL_INNERMOST_TEMPLATE_PARMS (tmpl)) = tmpl;
+
+ if (TREE_CODE (decl) == TYPE_DECL)
+ return tmpl;
+
/* What should we do with the specializations of this member
template? Are they specializations of this new template,
or instantiations of the templates they previously were?