pt.c (tsubst, [...]): Support member class templates.

* pt.c (tsubst, TEMPLATE_DECL): Support member class templates.
	(tsubst, *_PARM): Support multiple levels of template classes.
	(instantiate_class_template): Look up the pattern from the
	original template.
	(lookup_template_class): Handle getting a template for d1.
	(push_template_decl): Correct setting of 'primary'.
	(reduce_template_parm_level): Add 'levels' parm.
	(finish_member_template_decl): Support member class templates.
	(template_class_depth): Handle multiple levels.
	* parse.y (component_decl_1, fn.def2): Remove member template case.
	(component_decl): Add member template cases.
	* decl2.c (check_member_template): We now handle member template
	classes.
	* decl.c (pushtag): Handle member templates.
	* method.c (do_inline_function_hair): Don't touch
	IDENTIFIER_GLOBAL_VALUE.
	* init.c (build_offset_ref): If name isn't an identifier, just
	return it.
	* spew.c (yylex): Handle PTYPENAME like TYPENAME.
	* typeck.c (get_delta_difference): Do adjust for conversions to
	and from virtual base.

From-SVN: r18280
This commit is contained in:
Jason Merrill 1998-02-27 02:27:38 +00:00 committed by Jason Merrill
parent a7b4c0acc8
commit 93cdc044ea
11 changed files with 3472 additions and 3400 deletions

View File

@ -1,3 +1,28 @@
Fri Feb 27 02:25:16 1998 Jason Merrill <jason@yorick.cygnus.com>
* pt.c (tsubst, TEMPLATE_DECL): Support member class templates.
(tsubst, *_PARM): Support multiple levels of template classes.
(instantiate_class_template): Look up the pattern from the
original template.
(lookup_template_class): Handle getting a template for d1.
(push_template_decl): Correct setting of 'primary'.
(reduce_template_parm_level): Add 'levels' parm.
(finish_member_template_decl): Support member class templates.
(template_class_depth): Handle multiple levels.
* parse.y (component_decl_1, fn.def2): Remove member template case.
(component_decl): Add member template cases.
* decl2.c (check_member_template): We now handle member template
classes.
* decl.c (pushtag): Handle member templates.
* method.c (do_inline_function_hair): Don't touch
IDENTIFIER_GLOBAL_VALUE.
* init.c (build_offset_ref): If name isn't an identifier, just
return it.
* spew.c (yylex): Handle PTYPENAME like TYPENAME.
* typeck.c (get_delta_difference): Do adjust for conversions to
and from virtual base.
Wed Feb 25 09:51:29 1998 Jason Merrill <jason@yorick.cygnus.com>
* typeck.c (get_delta_difference): Give hard error for conversion

View File

@ -1439,12 +1439,9 @@ extern int flag_new_for_scope;
(TREE_CODE (NODE) == TEMPLATE_DECL \
&& TREE_CODE (DECL_TEMPLATE_RESULT (NODE)) == FUNCTION_DECL)
/* A `primary' template is one which depends on no tbemplate parameters
except those specified in its parameter list. So, a template
member of a non-template class is primary, and every global
function template is primary, but a member function of a template
class is not primary, neither is a member template of a template
class. */
/* A `primary' template is one that has its own template header. A
member function of a class template is a template, but not primary.
A member template is primary. */
#define PRIMARY_TEMPLATE_P(NODE) \
(TREE_TYPE (DECL_INNERMOST_TEMPLATE_PARMS (NODE)) == (NODE))

View File

@ -2179,47 +2179,43 @@ pushtag (name, type, globalize)
/* Do C++ gratuitous typedefing. */
if (IDENTIFIER_TYPE_VALUE (name) != type)
{
register tree d;
int newdecl = 0;
if (b->parm_flag != 2
|| TYPE_SIZE (current_class_type) != NULL_TREE)
{
d = lookup_nested_type (type, c_decl);
register tree d = NULL_TREE;
int newdecl = 0, in_class = 0;
if (d == NULL_TREE)
{
newdecl = 1;
d = build_decl (TYPE_DECL, name, type);
SET_DECL_ARTIFICIAL (d);
set_identifier_type_value_with_scope (name, type, b);
}
else
d = TYPE_MAIN_DECL (d);
TYPE_NAME (type) = d;
DECL_CONTEXT (d) = context;
if (! globalize && processing_template_decl && IS_AGGR_TYPE (type))
d = push_template_decl (d);
if (b->parm_flag == 2)
d = pushdecl_class_level (d);
else
d = pushdecl_with_scope (d, b);
}
if ((b->pseudo_global && b->level_chain->parm_flag == 2)
|| b->parm_flag == 2)
in_class = 1;
else
d = lookup_nested_type (type, c_decl);
if (d == NULL_TREE)
{
/* Make nested declarations go into class-level scope. */
newdecl = 1;
d = build_decl (TYPE_DECL, name, type);
SET_DECL_ARTIFICIAL (d);
TYPE_NAME (type) = d;
DECL_CONTEXT (d) = context;
if (! globalize && processing_template_decl && IS_AGGR_TYPE (type))
d = push_template_decl (d);
d = pushdecl_class_level (d);
if (! in_class)
set_identifier_type_value_with_scope (name, type, b);
}
else
d = TYPE_MAIN_DECL (d);
TYPE_NAME (type) = d;
DECL_CONTEXT (d) = context;
if (! globalize && processing_template_decl
&& IS_AGGR_TYPE (type))
{
d = push_template_decl (d);
if (b->pseudo_global && b->level_chain->parm_flag == 2)
pushdecl_with_scope (CLASSTYPE_TI_TEMPLATE (type),
b->level_chain);
}
if (b->parm_flag == 2)
d = pushdecl_class_level (d);
else
d = pushdecl_with_scope (d, b);
if (newdecl)
{
if (ANON_AGGRNAME_P (name))

View File

@ -1395,9 +1395,6 @@ check_member_template (tmpl)
A local class shall not have member templates. */
cp_error ("declaration of of member template `%#D' in local class",
decl);
/* We don't handle member template classes yet. */
sorry ("member templates classes");
}
else
cp_error ("template declaration of `%#D'", decl);

View File

@ -1836,6 +1836,9 @@ build_offset_ref (type, name)
tree basebinfo = NULL_TREE;
int dtor = 0;
if (TREE_CODE (name) != IDENTIFIER_NODE)
return name;
if (type == std_node)
return do_scoped_id (name, 0);

View File

@ -151,11 +151,6 @@ do_inline_function_hair (type, friend_list)
DECL_CONTEXT (args) = method;
args = TREE_CHAIN (args);
}
/* Allow this decl to be seen in global scope. Don't do this for
local class methods, though. */
if (! current_function_decl)
IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (method)) = method;
}
method = TREE_CHAIN (method);
}
@ -174,10 +169,6 @@ do_inline_function_hair (type, friend_list)
DECL_CONTEXT (args) = fndecl;
args = TREE_CHAIN (args);
}
/* Allow this decl to be seen in global scope */
if (! current_function_decl)
IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (fndecl)) = fndecl;
}
friend_list = TREE_CHAIN (friend_list);

File diff suppressed because it is too large Load Diff

View File

@ -769,8 +769,6 @@ fn.def2:
$$ = start_method (specs, $2); goto rest_of_mdef; }
| constructor_declarator
{ $$ = start_method (NULL_TREE, $$); goto rest_of_mdef; }
| template_header fn.def2
{ $$ = finish_member_template_decl ($1, $2); }
;
return_id:
@ -2760,6 +2758,14 @@ component_decl:
| extension component_decl
{ $$ = $2;
pedantic = $<itype>1; }
| template_header component_decl
{ $$ = finish_member_template_decl ($1, $2); }
| template_header typed_declspecs ';'
{
shadow_tag ($2.t);
note_list_got_semicolon ($2.t);
$$ = finish_member_template_decl ($1, $2.t);
}
;
component_decl_1:
@ -2799,8 +2805,6 @@ component_decl_1:
build_tree_list ($3, NULL_TREE)); }
| using_decl
{ $$ = do_class_using_decl ($1); }
| template_header component_decl_1
{ $$ = finish_member_template_decl ($1, $2); }
/* The case of exactly one component is handled directly by component_decl. */
/* ??? Huh? ^^^ */

View File

@ -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?

View File

@ -313,6 +313,7 @@ yylex ()
case TYPENAME:
case SELFNAME:
case NSNAME:
case PTYPENAME:
lastiddecl = trrr;
if (got_scope)
tmp_token.yylval.ttype = trrr;
@ -320,7 +321,6 @@ yylex ()
case PFUNCNAME:
case IDENTIFIER:
case PTYPENAME:
lastiddecl = trrr;
break;

View File

@ -6304,8 +6304,16 @@ get_delta_difference (from, to, force)
return delta;
}
binfo = get_binfo (to, from, 1);
if (binfo == 0 || binfo == error_mark_node || TREE_VIA_VIRTUAL (binfo))
if (binfo == 0 || binfo == error_mark_node)
return delta;
if (TREE_VIA_VIRTUAL (binfo))
{
binfo = binfo_member (BINFO_TYPE (binfo),
CLASSTYPE_VBASECLASSES (from));
cp_warning ("pointer to member cast to virtual base `%T'",
BINFO_TYPE (binfo));
warning (" will only work if you are very careful");
}
delta = BINFO_OFFSET (binfo);
delta = cp_convert (ptrdiff_type_node, delta);
@ -6325,7 +6333,6 @@ get_delta_difference (from, to, force)
else
cp_error ("pointer to member conversion from virtual base `%T'",
BINFO_TYPE (binfo));
return delta;
}
return BINFO_OFFSET (binfo);