Commit ae58fa02 by Mark Mitchell Committed by Mark Mitchell

typeck.c (require_complete_type): Use complete_type_or_else.

	* typeck.c (require_complete_type): Use complete_type_or_else.
	(complete_type_or_else): Always return NULL_TREE on failure, as
	documented.
	* pt.c (tsubst_aggr_type): Prototype.
	(tsubst_decl): New function, split out from tsubst.  Set
	input_filename and lineno as appropriate.
	(pop_tinst_level): Restore the file and line number saved in
	push_tinst_level.
	(instantiate_class_template): Set input_filename and lineno as
	appropriate.
	(tsubst): Move _DECL processing to tsubst_decl.  Make sure the
	context for a TYPENAME_TYPE is complete.
	* decl2.c (grokbitfield): Issue errors on bitfields declared with
	function type.
	(do_dtors): As in do_ctors, pretend to be a member of the same
	class as a static data member while generating a call to its
	destructor.

From-SVN: r21627
parent 52363387
1998-08-07 Mark Mitchell <mark@markmitchell.com> 1998-08-07 Mark Mitchell <mark@markmitchell.com>
* cvt.c (cp_convert_to_pointer): Handle a NULL pointer * typeck.c (require_complete_type): Use complete_type_or_else.
(complete_type_or_else): Always return NULL_TREE on failure, as
documented.
* pt.c (tsubst_aggr_type): Prototype.
(tsubst_decl): New function, split out from tsubst. Set
input_filename and lineno as appropriate.
(pop_tinst_level): Restore the file and line number saved in
push_tinst_level.
(instantiate_class_template): Set input_filename and lineno as
appropriate.
(tsubst): Move _DECL processing to tsubst_decl. Make sure the
context for a TYPENAME_TYPE is complete.
* decl2.c (grokbitfield): Issue errors on bitfields declared with
function type.
(do_dtors): As in do_ctors, pretend to be a member of the same
class as a static data member while generating a call to its
destructor.
* cvt.c (cp_convert_to_pointer): Handle NULL pointer
conversions, even in complex virtual base class hierarchies. conversions, even in complex virtual base class hierarchies.
1998-08-06 Mark Mitchell <mark@markmitchell.com> 1998-08-06 Mark Mitchell <mark@markmitchell.com>
......
...@@ -1845,6 +1845,17 @@ grokbitfield (declarator, declspecs, width) ...@@ -1845,6 +1845,17 @@ grokbitfield (declarator, declspecs, width)
return NULL_TREE; return NULL_TREE;
} }
/* Usually, finish_struct_1 catches bitifields with invalid types.
But, in the case of bitfields with function type, we confuse
ourselves into thinking they are member functions, so we must
check here. */
if (TREE_CODE (value) == FUNCTION_DECL)
{
cp_error ("cannot declare bitfield `%D' with funcion type",
DECL_NAME (value));
return NULL_TREE;
}
if (IS_SIGNATURE (current_class_type)) if (IS_SIGNATURE (current_class_type))
{ {
error ("field declaration not allowed in signature"); error ("field declaration not allowed in signature");
...@@ -3001,6 +3012,25 @@ do_dtors () ...@@ -3001,6 +3012,25 @@ do_dtors ()
if (! current_function_decl) if (! current_function_decl)
start_objects ('D'); start_objects ('D');
/* Because of:
[class.access.spec]
Access control for implicit calls to the constructors,
the conversion functions, or the destructor called to
create and destroy a static data member is per- formed as
if these calls appeared in the scope of the member's
class.
we must convince enforce_access to let us access the
DECL. */
if (member_p (decl))
{
DECL_CLASS_CONTEXT (current_function_decl)
= DECL_CONTEXT (decl);
DECL_STATIC_FUNCTION_P (current_function_decl) = 1;
}
temp = build_cleanup (decl); temp = build_cleanup (decl);
if (protect) if (protect)
...@@ -3015,6 +3045,11 @@ do_dtors () ...@@ -3015,6 +3045,11 @@ do_dtors ()
if (protect) if (protect)
expand_end_cond (); expand_end_cond ();
/* Now that we're done with DECL we don't need to pretend to
be a member of its class any longer. */
DECL_CLASS_CONTEXT (current_function_decl) = NULL_TREE;
DECL_STATIC_FUNCTION_P (current_function_decl) = 0;
} }
} }
......
...@@ -122,6 +122,8 @@ static tree most_specialized_class PROTO((tree, tree)); ...@@ -122,6 +122,8 @@ static tree most_specialized_class PROTO((tree, tree));
static tree most_general_template PROTO((tree)); static tree most_general_template PROTO((tree));
static void set_mangled_name_for_template_decl PROTO((tree)); static void set_mangled_name_for_template_decl PROTO((tree));
static int template_class_depth_real PROTO((tree, int)); 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));
/* We use TREE_VECs to hold template arguments. If there is only one /* We use TREE_VECs to hold template arguments. If there is only one
level of template arguments, then the TREE_VEC contains the level of template arguments, then the TREE_VEC contains the
...@@ -3779,6 +3781,11 @@ pop_tinst_level () ...@@ -3779,6 +3781,11 @@ pop_tinst_level ()
{ {
struct tinst_level *old = current_tinst_level; struct tinst_level *old = current_tinst_level;
/* Restore the filename and line number stashed away when we started
this instantiation. */
lineno = old->line;
input_filename = old->file;
current_tinst_level = old->next; current_tinst_level = old->next;
old->next = free_tinst_level; old->next = free_tinst_level;
free_tinst_level = old; free_tinst_level = old;
...@@ -4291,7 +4298,15 @@ instantiate_class_template (type) ...@@ -4291,7 +4298,15 @@ instantiate_class_template (type)
for (t = TYPE_FIELDS (pattern); t; t = TREE_CHAIN (t)) for (t = TYPE_FIELDS (pattern); t; t = TREE_CHAIN (t))
if (TREE_CODE (t) != CONST_DECL) if (TREE_CODE (t) != CONST_DECL)
{ {
tree r = tsubst (t, args, NULL_TREE); tree r;
/* The the file and line for this declaration, to assist in
error message reporting. Since we called push_tinst_level
above, we don't need to restore these. */
lineno = DECL_SOURCE_LINE (t);
input_filename = DECL_SOURCE_FILE (t);
r = tsubst (t, args, NULL_TREE);
if (TREE_CODE (r) == VAR_DECL) if (TREE_CODE (r) == VAR_DECL)
{ {
pending_statics = perm_tree_cons (NULL_TREE, r, pending_statics); pending_statics = perm_tree_cons (NULL_TREE, r, pending_statics);
...@@ -4619,204 +4634,34 @@ tsubst_aggr_type (t, args, in_decl, entering_scope) ...@@ -4619,204 +4634,34 @@ tsubst_aggr_type (t, args, in_decl, entering_scope)
} }
} }
/* Take the tree structure T and replace template parameters used therein /* Substitute the ARGS into the T, which is a _DECL. TYPE is the
with the argument vector ARGS. IN_DECL is an associated decl for (already computed) substitution of ARGS into TREE_TYPE (T), if
diagnostics. appropriate. Return the result of the substitution. IN_DECL is as
for tsubst. */
tsubst is used for dealing with types, decls and the like; for
expressions, use tsubst_expr or tsubst_copy. */
tree tree
tsubst (t, args, in_decl) tsubst_decl (t, args, type, in_decl)
tree t, args; tree t;
tree args;
tree type;
tree in_decl; tree in_decl;
{ {
tree type; int saved_lineno;
char* saved_filename;
if (t == NULL_TREE || t == error_mark_node
|| t == integer_type_node
|| t == void_type_node
|| t == char_type_node
|| TREE_CODE (t) == NAMESPACE_DECL)
return t;
if (TREE_CODE (t) == IDENTIFIER_NODE)
type = IDENTIFIER_TYPE_VALUE (t);
else
type = TREE_TYPE (t);
if (type == unknown_type_node)
my_friendly_abort (42);
if (type && TREE_CODE (t) != FUNCTION_DECL
&& TREE_CODE (t) != TYPENAME_TYPE
&& TREE_CODE (t) != TEMPLATE_DECL
&& TREE_CODE (t) != IDENTIFIER_NODE)
type = tsubst (type, args, in_decl);
switch (TREE_CODE (t))
{
case RECORD_TYPE:
case UNION_TYPE:
case ENUMERAL_TYPE:
return tsubst_aggr_type (t, args, in_decl, /*entering_scope=*/0);
case ERROR_MARK:
case IDENTIFIER_NODE:
case OP_IDENTIFIER:
case VOID_TYPE:
case REAL_TYPE:
case COMPLEX_TYPE:
case BOOLEAN_TYPE:
case INTEGER_CST:
case REAL_CST:
case STRING_CST:
case NAMESPACE_DECL:
return t;
case INTEGER_TYPE:
if (t == integer_type_node)
return t;
if (TREE_CODE (TYPE_MIN_VALUE (t)) == INTEGER_CST
&& TREE_CODE (TYPE_MAX_VALUE (t)) == INTEGER_CST)
return t;
{
tree max = TREE_OPERAND (TYPE_MAX_VALUE (t), 0);
max = tsubst_expr (max, args, in_decl);
if (processing_template_decl)
{
tree itype = make_node (INTEGER_TYPE);
TYPE_MIN_VALUE (itype) = size_zero_node;
TYPE_MAX_VALUE (itype) = build_min (MINUS_EXPR, sizetype, max,
integer_one_node);
return itype;
}
max = fold (build_binary_op (MINUS_EXPR, max, integer_one_node, 1));
return build_index_2_type (size_zero_node, max);
}
case TEMPLATE_TYPE_PARM:
case TEMPLATE_TEMPLATE_PARM:
case TEMPLATE_PARM_INDEX:
{
int idx;
int level;
int levels;
tree r = NULL_TREE;
if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
|| TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
{
idx = TEMPLATE_TYPE_IDX (t);
level = TEMPLATE_TYPE_LEVEL (t);
}
else
{
idx = TEMPLATE_PARM_IDX (t);
level = TEMPLATE_PARM_LEVEL (t);
}
if (TREE_VEC_LENGTH (args) > 0)
{
tree arg = NULL_TREE;
levels = TMPL_ARGS_DEPTH (args);
if (level <= levels)
arg = TMPL_ARG (args, level, idx);
if (arg != NULL_TREE)
{
if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
{
my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (arg))
== 't', 0);
return cp_build_type_variant
(arg, TYPE_READONLY (arg) || TYPE_READONLY (t),
TYPE_VOLATILE (arg) || TYPE_VOLATILE (t));
}
else if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
{
if (CLASSTYPE_TEMPLATE_INFO (t))
{
/* We are processing a type constructed from
a template template parameter */
tree argvec = tsubst (CLASSTYPE_TI_ARGS (t),
args, in_decl);
tree r; tree r;
/* We can get a TEMPLATE_TEMPLATE_PARM here when /* Set the filename and linenumber to improve error-reporting. */
we are resolving nested-types in the signature of saved_lineno = lineno;
a member function templates. saved_filename = input_filename;
Otherwise ARG is a TEMPLATE_DECL and is the real lineno = DECL_SOURCE_LINE (t);
template to be instantiated. */ input_filename = DECL_SOURCE_FILE (t);
if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
arg = TYPE_NAME (arg);
r = lookup_template_class (DECL_NAME (arg),
argvec, in_decl,
DECL_CONTEXT (arg),
/*entering_scope=*/0);
return cp_build_type_variant (r, TYPE_READONLY (t),
TYPE_VOLATILE (t));
}
else
/* We are processing a template argument list. */
return arg;
}
else
return arg;
}
}
if (level == 1)
/* This can happen during the attempted tsubst'ing in
unify. This means that we don't yet have any information
about the template parameter in question. */
return t;
/* If we get here, we must have been looking at a parm for a
more deeply nested template. Make a new version of this
template parameter, but with a lower level. */
switch (TREE_CODE (t)) switch (TREE_CODE (t))
{ {
case TEMPLATE_TYPE_PARM:
case TEMPLATE_TEMPLATE_PARM:
r = copy_node (t);
TEMPLATE_TYPE_PARM_INDEX (r)
= reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
r, levels);
TYPE_STUB_DECL (r) = TYPE_NAME (r) = TEMPLATE_TYPE_DECL (r);
TYPE_MAIN_VARIANT (r) = r;
TYPE_POINTER_TO (r) = NULL_TREE;
TYPE_REFERENCE_TO (r) = NULL_TREE;
if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM
&& CLASSTYPE_TEMPLATE_INFO (t))
{
tree argvec = tsubst (CLASSTYPE_TI_ARGS (t), args, in_decl);
CLASSTYPE_TEMPLATE_INFO (r)
= perm_tree_cons (TYPE_NAME (t), argvec, NULL_TREE);
}
break;
case TEMPLATE_PARM_INDEX:
r = reduce_template_parm_level (t, type, levels);
break;
default:
my_friendly_abort (0);
}
return r;
}
case TEMPLATE_DECL: case TEMPLATE_DECL:
{ {
/* We can get here when processing a member template function /* We can get here when processing a member template function
of a template class. */ of a template class. */
tree tmpl;
tree decl = DECL_TEMPLATE_RESULT (t); tree decl = DECL_TEMPLATE_RESULT (t);
tree parms; tree parms;
tree* new_parms; tree* new_parms;
...@@ -4841,7 +4686,10 @@ tsubst (t, args, in_decl) ...@@ -4841,7 +4686,10 @@ tsubst (t, args, in_decl)
spec = retrieve_specialization (t, full_args); spec = retrieve_specialization (t, full_args);
if (spec != NULL_TREE) if (spec != NULL_TREE)
return spec; {
r = spec;
break;
}
} }
/* Make a new template decl. It will be similar to the /* Make a new template decl. It will be similar to the
...@@ -4849,60 +4697,60 @@ tsubst (t, args, in_decl) ...@@ -4849,60 +4697,60 @@ tsubst (t, args, in_decl)
We also create a new function declaration, which is just We also create a new function declaration, which is just
like the old one, but points to this new template, rather like the old one, but points to this new template, rather
than the old one. */ than the old one. */
tmpl = copy_node (t); r = copy_node (t);
copy_lang_decl (tmpl); copy_lang_decl (r);
my_friendly_assert (DECL_LANG_SPECIFIC (tmpl) != 0, 0); my_friendly_assert (DECL_LANG_SPECIFIC (r) != 0, 0);
TREE_CHAIN (tmpl) = NULL_TREE; TREE_CHAIN (r) = NULL_TREE;
if (is_template_template_parm) if (is_template_template_parm)
{ {
tree new_decl = tsubst (decl, args, in_decl); tree new_decl = tsubst (decl, args, in_decl);
DECL_RESULT (tmpl) = new_decl; DECL_RESULT (r) = new_decl;
TREE_TYPE (tmpl) = TREE_TYPE (new_decl); TREE_TYPE (r) = TREE_TYPE (new_decl);
return tmpl; break;
} }
DECL_CONTEXT (tmpl) DECL_CONTEXT (r)
= tsubst_aggr_type (DECL_CONTEXT (t), args, in_decl, = tsubst_aggr_type (DECL_CONTEXT (t), args, in_decl,
/*entering_scope=*/1); /*entering_scope=*/1);
DECL_CLASS_CONTEXT (tmpl) DECL_CLASS_CONTEXT (r)
= tsubst_aggr_type (DECL_CLASS_CONTEXT (t), args, in_decl, = tsubst_aggr_type (DECL_CLASS_CONTEXT (t), args, in_decl,
/*entering_scope=*/1); /*entering_scope=*/1);
DECL_TEMPLATE_INFO (tmpl) = build_tree_list (t, args); DECL_TEMPLATE_INFO (r) = build_tree_list (t, args);
if (TREE_CODE (decl) == TYPE_DECL) if (TREE_CODE (decl) == TYPE_DECL)
{ {
tree new_type = tsubst (TREE_TYPE (t), args, in_decl); tree new_type = tsubst (TREE_TYPE (t), args, in_decl);
TREE_TYPE (tmpl) = new_type; TREE_TYPE (r) = new_type;
CLASSTYPE_TI_TEMPLATE (new_type) = tmpl; CLASSTYPE_TI_TEMPLATE (new_type) = r;
DECL_RESULT (tmpl) = TYPE_MAIN_DECL (new_type); DECL_RESULT (r) = TYPE_MAIN_DECL (new_type);
DECL_TI_ARGS (tmpl) = CLASSTYPE_TI_ARGS (new_type); DECL_TI_ARGS (r) = CLASSTYPE_TI_ARGS (new_type);
} }
else else
{ {
tree new_decl = tsubst (decl, args, in_decl); tree new_decl = tsubst (decl, args, in_decl);
DECL_RESULT (tmpl) = new_decl; DECL_RESULT (r) = new_decl;
DECL_TI_TEMPLATE (new_decl) = tmpl; DECL_TI_TEMPLATE (new_decl) = r;
TREE_TYPE (tmpl) = TREE_TYPE (new_decl); TREE_TYPE (r) = TREE_TYPE (new_decl);
DECL_TI_ARGS (tmpl) = DECL_TI_ARGS (new_decl); DECL_TI_ARGS (r) = DECL_TI_ARGS (new_decl);
} }
SET_DECL_IMPLICIT_INSTANTIATION (tmpl); SET_DECL_IMPLICIT_INSTANTIATION (r);
DECL_TEMPLATE_INSTANTIATIONS (tmpl) = NULL_TREE; DECL_TEMPLATE_INSTANTIATIONS (r) = NULL_TREE;
DECL_TEMPLATE_SPECIALIZATIONS (tmpl) = NULL_TREE; DECL_TEMPLATE_SPECIALIZATIONS (r) = NULL_TREE;
/* The template parameters for this new template are all the /* The template parameters for this new template are all the
template parameters for the old template, except the template parameters for the old template, except the
outermost level of parameters. */ outermost level of parameters. */
DECL_TEMPLATE_PARMS (tmpl) DECL_TEMPLATE_PARMS (r)
= tsubst_template_parms (DECL_TEMPLATE_PARMS (t), args); = tsubst_template_parms (DECL_TEMPLATE_PARMS (t), args);
if (PRIMARY_TEMPLATE_P (t)) if (PRIMARY_TEMPLATE_P (t))
DECL_PRIMARY_TEMPLATE (tmpl) = tmpl; DECL_PRIMARY_TEMPLATE (r) = r;
/* We don't partially instantiate partial specializations. */ /* We don't partially instantiate partial specializations. */
if (TREE_CODE (decl) == TYPE_DECL) if (TREE_CODE (decl) == TYPE_DECL)
return tmpl; break;
for (spec = DECL_TEMPLATE_SPECIALIZATIONS (t); for (spec = DECL_TEMPLATE_SPECIALIZATIONS (t);
spec != NULL_TREE; spec != NULL_TREE;
...@@ -4953,20 +4801,19 @@ tsubst (t, args, in_decl) ...@@ -4953,20 +4801,19 @@ tsubst (t, args, in_decl)
new_fn = tsubst (DECL_RESULT (most_general_template (fn)), new_fn = tsubst (DECL_RESULT (most_general_template (fn)),
spec_args, in_decl); spec_args, in_decl);
DECL_TI_TEMPLATE (new_fn) = fn; DECL_TI_TEMPLATE (new_fn) = fn;
register_specialization (new_fn, tmpl, register_specialization (new_fn, r,
innermost_args (spec_args)); innermost_args (spec_args));
} }
/* Record this partial instantiation. */ /* Record this partial instantiation. */
register_specialization (tmpl, t, register_specialization (r, t,
DECL_TI_ARGS (DECL_RESULT (tmpl))); DECL_TI_ARGS (DECL_RESULT (r)));
return tmpl;
} }
break;
case FUNCTION_DECL: case FUNCTION_DECL:
{ {
tree r = NULL_TREE;
tree ctx; tree ctx;
tree argvec; tree argvec;
tree gen_tmpl; tree gen_tmpl;
...@@ -4988,7 +4835,10 @@ tsubst (t, args, in_decl) ...@@ -4988,7 +4835,10 @@ tsubst (t, args, in_decl)
/* Check to see if we already have this specialization. */ /* Check to see if we already have this specialization. */
spec = retrieve_specialization (gen_tmpl, argvec); spec = retrieve_specialization (gen_tmpl, argvec);
if (spec) if (spec)
return spec; {
r = spec;
break;
}
} }
else else
{ {
...@@ -5113,13 +4963,12 @@ tsubst (t, args, in_decl) ...@@ -5113,13 +4963,12 @@ tsubst (t, args, in_decl)
== NULL_TREE)) == NULL_TREE))
SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r), r); SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r), r);
} }
return r;
} }
break;
case PARM_DECL: case PARM_DECL:
{ {
tree r = copy_node (t); r = copy_node (t);
TREE_TYPE (r) = type; TREE_TYPE (r) = type;
if (TREE_CODE (DECL_INITIAL (r)) != TEMPLATE_PARM_INDEX) if (TREE_CODE (DECL_INITIAL (r)) != TEMPLATE_PARM_INDEX)
DECL_INITIAL (r) = TREE_TYPE (r); DECL_INITIAL (r) = TREE_TYPE (r);
...@@ -5135,12 +4984,12 @@ tsubst (t, args, in_decl) ...@@ -5135,12 +4984,12 @@ tsubst (t, args, in_decl)
#endif #endif
if (TREE_CHAIN (t)) if (TREE_CHAIN (t))
TREE_CHAIN (r) = tsubst (TREE_CHAIN (t), args, TREE_CHAIN (t)); TREE_CHAIN (r) = tsubst (TREE_CHAIN (t), args, TREE_CHAIN (t));
return r;
} }
break;
case FIELD_DECL: case FIELD_DECL:
{ {
tree r = copy_node (t); r = copy_node (t);
TREE_TYPE (r) = type; TREE_TYPE (r) = type;
copy_lang_decl (r); copy_lang_decl (r);
#if 0 #if 0
...@@ -5150,21 +4999,20 @@ tsubst (t, args, in_decl) ...@@ -5150,21 +4999,20 @@ tsubst (t, args, in_decl)
TREE_CHAIN (r) = NULL_TREE; TREE_CHAIN (r) = NULL_TREE;
if (TREE_CODE (type) == VOID_TYPE) if (TREE_CODE (type) == VOID_TYPE)
cp_error_at ("instantiation of `%D' as type void", r); cp_error_at ("instantiation of `%D' as type void", r);
return r;
} }
break;
case USING_DECL: case USING_DECL:
{ {
tree r = copy_node (t); r = copy_node (t);
DECL_INITIAL (r) DECL_INITIAL (r)
= tsubst_copy (DECL_INITIAL (t), args, in_decl); = tsubst_copy (DECL_INITIAL (t), args, in_decl);
TREE_CHAIN (r) = NULL_TREE; TREE_CHAIN (r) = NULL_TREE;
return r;
} }
break;
case VAR_DECL: case VAR_DECL:
{ {
tree r;
tree argvec; tree argvec;
tree gen_tmpl; tree gen_tmpl;
tree spec; tree spec;
...@@ -5183,7 +5031,10 @@ tsubst (t, args, in_decl) ...@@ -5183,7 +5031,10 @@ tsubst (t, args, in_decl)
spec = retrieve_specialization (gen_tmpl, argvec); spec = retrieve_specialization (gen_tmpl, argvec);
if (spec) if (spec)
return spec; {
r = spec;
break;
}
r = copy_node (t); r = copy_node (t);
TREE_TYPE (r) = type; TREE_TYPE (r) = type;
...@@ -5207,18 +5058,225 @@ tsubst (t, args, in_decl) ...@@ -5207,18 +5058,225 @@ tsubst (t, args, in_decl)
TREE_CHAIN (r) = NULL_TREE; TREE_CHAIN (r) = NULL_TREE;
if (TREE_CODE (type) == VOID_TYPE) if (TREE_CODE (type) == VOID_TYPE)
cp_error_at ("instantiation of `%D' as type void", r); cp_error_at ("instantiation of `%D' as type void", r);
return r;
} }
break;
case TYPE_DECL: case TYPE_DECL:
if (t == TYPE_NAME (TREE_TYPE (t))) if (t == TYPE_NAME (TREE_TYPE (t)))
return TYPE_NAME (type); r = TYPE_NAME (type);
else
{ {
tree r = copy_node (t); r = copy_node (t);
TREE_TYPE (r) = type; TREE_TYPE (r) = type;
DECL_CONTEXT (r) = current_class_type; DECL_CONTEXT (r) = current_class_type;
TREE_CHAIN (r) = NULL_TREE; TREE_CHAIN (r) = NULL_TREE;
}
break;
default:
my_friendly_abort (0);
}
/* Restore the file and line information. */
lineno = saved_lineno;
input_filename = saved_filename;
return r;
}
/* Take the tree structure T and replace template parameters used therein
with the argument vector ARGS. IN_DECL is an associated decl for
diagnostics.
tsubst is used for dealing with types, decls and the like; for
expressions, use tsubst_expr or tsubst_copy. */
tree
tsubst (t, args, in_decl)
tree t, args;
tree in_decl;
{
tree type;
if (t == NULL_TREE || t == error_mark_node
|| t == integer_type_node
|| t == void_type_node
|| t == char_type_node
|| TREE_CODE (t) == NAMESPACE_DECL)
return t;
if (TREE_CODE (t) == IDENTIFIER_NODE)
type = IDENTIFIER_TYPE_VALUE (t);
else
type = TREE_TYPE (t);
if (type == unknown_type_node)
my_friendly_abort (42);
if (type && TREE_CODE (t) != FUNCTION_DECL
&& TREE_CODE (t) != TYPENAME_TYPE
&& TREE_CODE (t) != TEMPLATE_DECL
&& TREE_CODE (t) != IDENTIFIER_NODE)
type = tsubst (type, args, in_decl);
if (TREE_CODE_CLASS (TREE_CODE (t)) == 'd')
return tsubst_decl (t, args, type, in_decl);
switch (TREE_CODE (t))
{
case RECORD_TYPE:
case UNION_TYPE:
case ENUMERAL_TYPE:
return tsubst_aggr_type (t, args, in_decl, /*entering_scope=*/0);
case ERROR_MARK:
case IDENTIFIER_NODE:
case OP_IDENTIFIER:
case VOID_TYPE:
case REAL_TYPE:
case COMPLEX_TYPE:
case BOOLEAN_TYPE:
case INTEGER_CST:
case REAL_CST:
case STRING_CST:
return t;
case INTEGER_TYPE:
if (t == integer_type_node)
return t;
if (TREE_CODE (TYPE_MIN_VALUE (t)) == INTEGER_CST
&& TREE_CODE (TYPE_MAX_VALUE (t)) == INTEGER_CST)
return t;
{
tree max = TREE_OPERAND (TYPE_MAX_VALUE (t), 0);
max = tsubst_expr (max, args, in_decl);
if (processing_template_decl)
{
tree itype = make_node (INTEGER_TYPE);
TYPE_MIN_VALUE (itype) = size_zero_node;
TYPE_MAX_VALUE (itype) = build_min (MINUS_EXPR, sizetype, max,
integer_one_node);
return itype;
}
max = fold (build_binary_op (MINUS_EXPR, max, integer_one_node, 1));
return build_index_2_type (size_zero_node, max);
}
case TEMPLATE_TYPE_PARM:
case TEMPLATE_TEMPLATE_PARM:
case TEMPLATE_PARM_INDEX:
{
int idx;
int level;
int levels;
tree r = NULL_TREE;
if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
|| TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
{
idx = TEMPLATE_TYPE_IDX (t);
level = TEMPLATE_TYPE_LEVEL (t);
}
else
{
idx = TEMPLATE_PARM_IDX (t);
level = TEMPLATE_PARM_LEVEL (t);
}
if (TREE_VEC_LENGTH (args) > 0)
{
tree arg = NULL_TREE;
levels = TMPL_ARGS_DEPTH (args);
if (level <= levels)
arg = TMPL_ARG (args, level, idx);
if (arg != NULL_TREE)
{
if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
{
my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (arg))
== 't', 0);
return cp_build_type_variant
(arg, TYPE_READONLY (arg) || TYPE_READONLY (t),
TYPE_VOLATILE (arg) || TYPE_VOLATILE (t));
}
else if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
{
if (CLASSTYPE_TEMPLATE_INFO (t))
{
/* We are processing a type constructed from
a template template parameter */
tree argvec = tsubst (CLASSTYPE_TI_ARGS (t),
args, in_decl);
tree r;
/* We can get a TEMPLATE_TEMPLATE_PARM here when
we are resolving nested-types in the signature of
a member function templates.
Otherwise ARG is a TEMPLATE_DECL and is the real
template to be instantiated. */
if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
arg = TYPE_NAME (arg);
r = lookup_template_class (DECL_NAME (arg),
argvec, in_decl,
DECL_CONTEXT (arg),
/*entering_scope=*/0);
return cp_build_type_variant (r, TYPE_READONLY (t),
TYPE_VOLATILE (t));
}
else
/* We are processing a template argument list. */
return arg;
}
else
return arg;
}
}
if (level == 1)
/* This can happen during the attempted tsubst'ing in
unify. This means that we don't yet have any information
about the template parameter in question. */
return t;
/* If we get here, we must have been looking at a parm for a
more deeply nested template. Make a new version of this
template parameter, but with a lower level. */
switch (TREE_CODE (t))
{
case TEMPLATE_TYPE_PARM:
case TEMPLATE_TEMPLATE_PARM:
r = copy_node (t);
TEMPLATE_TYPE_PARM_INDEX (r)
= reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
r, levels);
TYPE_STUB_DECL (r) = TYPE_NAME (r) = TEMPLATE_TYPE_DECL (r);
TYPE_MAIN_VARIANT (r) = r;
TYPE_POINTER_TO (r) = NULL_TREE;
TYPE_REFERENCE_TO (r) = NULL_TREE;
if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM
&& CLASSTYPE_TEMPLATE_INFO (t))
{
tree argvec = tsubst (CLASSTYPE_TI_ARGS (t), args, in_decl);
CLASSTYPE_TEMPLATE_INFO (r)
= perm_tree_cons (TYPE_NAME (t), argvec, NULL_TREE);
}
break;
case TEMPLATE_PARM_INDEX:
r = reduce_template_parm_level (t, type, levels);
break;
default:
my_friendly_abort (0);
}
return r; return r;
} }
...@@ -5439,6 +5497,19 @@ tsubst (t, args, in_decl) ...@@ -5439,6 +5497,19 @@ tsubst (t, args, in_decl)
tree ctx = tsubst_aggr_type (TYPE_CONTEXT (t), args, in_decl, tree ctx = tsubst_aggr_type (TYPE_CONTEXT (t), args, in_decl,
/*entering_scope=*/1); /*entering_scope=*/1);
tree f = tsubst_copy (TYPENAME_TYPE_FULLNAME (t), args, in_decl); tree f = tsubst_copy (TYPENAME_TYPE_FULLNAME (t), args, in_decl);
/* Normally, make_typename_type does not require that the CTX
have complete type in order to allow things like:
template <class T> struct S { typename S<T>::X Y; };
But, such constructs have already been resolved by this
point, so here CTX really should have complete type, unless
it's a partial instantiation. */
if (!uses_template_parms (ctx)
&& !complete_type_or_else (ctx))
return error_mark_node;
f = make_typename_type (ctx, f); f = make_typename_type (ctx, f);
return cp_build_type_variant return cp_build_type_variant
(f, TYPE_READONLY (f) || TYPE_READONLY (t), (f, TYPE_READONLY (f) || TYPE_READONLY (t),
......
...@@ -80,7 +80,9 @@ target_type (type) ...@@ -80,7 +80,9 @@ target_type (type)
} }
/* Do `exp = require_complete_type (exp);' to make sure exp /* Do `exp = require_complete_type (exp);' to make sure exp
does not have an incomplete type. (That includes void types.) */ does not have an incomplete type. (That includes void types.)
Returns the error_mark_node if the VALUE does not have
complete type when this function returns. */
tree tree
require_complete_type (value) require_complete_type (value)
...@@ -120,13 +122,10 @@ require_complete_type (value) ...@@ -120,13 +122,10 @@ require_complete_type (value)
return require_complete_type (value); return require_complete_type (value);
} }
if (TYPE_SIZE (complete_type (type))) if (complete_type_or_else (type))
return value; return value;
else else
{
incomplete_type_error (value, type);
return error_mark_node; return error_mark_node;
}
} }
/* Try to complete TYPE, if it is incomplete. For example, if TYPE is /* Try to complete TYPE, if it is incomplete. For example, if TYPE is
...@@ -170,7 +169,10 @@ complete_type_or_else (type) ...@@ -170,7 +169,10 @@ complete_type_or_else (type)
tree type; tree type;
{ {
type = complete_type (type); type = complete_type (type);
if (type != error_mark_node && !TYPE_SIZE (type)) if (type == error_mark_node)
/* We already issued an error. */
return NULL_TREE;
else if (!TYPE_SIZE (type))
{ {
incomplete_type_error (NULL_TREE, type); incomplete_type_error (NULL_TREE, type);
return NULL_TREE; return NULL_TREE;
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
typedef void (func_type) (); typedef void (func_type) ();
struct s { struct s {
func_type f:32; // ERROR - XFAIL *-*-* func_type f:32; // ERROR - bitified with function type
}; };
int main () { return 0; } int main () { return 0; }
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
const int ArraySize = 12; const int ArraySize = 12;
template <class Type> template <class Type>
class Array { class Array { // ERROR - .struct Array_RC redecl.*
friend class Array_RC; friend class Array_RC;
public: public:
Array(const Type *ar, int sz) { init(ar,sz); } Array(const Type *ar, int sz) { init(ar,sz); }
...@@ -97,7 +97,7 @@ try_array( Array_RC<Type> &rc ) ...@@ -97,7 +97,7 @@ try_array( Array_RC<Type> &rc )
main() main()
{ {
static int ia[10] = { 12, 7, 14, 9, 128, 17, 6, 3, 27, 5 }; static int ia[10] = { 12, 7, 14, 9, 128, 17, 6, 3, 27, 5 };
Array_RC<int> iA(ia, 10);// ERROR - .struct Array_RC redecl.* Array_RC<int> iA(ia, 10);// ERROR - instantiated from here
cout << "template Array_RC class" << endl; cout << "template Array_RC class" << endl;
try_array(iA); try_array(iA);
......
// Build don't link:
class K {
public:
friend class C;
private:
static K qwe;
K();
~K();
};
K K::qwe;
...@@ -2,9 +2,9 @@ ...@@ -2,9 +2,9 @@
template <class T = int> // ERROR - original definition template <class T = int> // ERROR - original definition
struct S struct S
{ { // ERROR - redefinition of default arg
template <class U = int> template <class U = int>
friend class S; friend class S;
}; };
template struct S<int>; // ERROR - redefinition of default arg template struct S<int>; // ERROR - instantiated from here
// Build don't link: // Build don't link:
template <class A> class B { template <class A> class B { // ERROR - candidates
A a; A a;
public: public:
B(A&aa); // ERROR - B(A&aa); // ERROR - near match
~B(); ~B();
}; };
static B<int> b_int (3); // ERROR - static B<int> b_int (3); // ERROR - no matching function
// Build don't link:
template < class T > class A
{
public:
typedef typename T::myT anotherT; // ERROR - undefined type
anotherT t; // ERROR - undefined type
A(anotherT _t) { // ERROR - undefined type
t=_t;
}
anotherT getT() {
return t;
}
};
class B : public A< B >
{
public:
typedef int myT;
};
int main() {
B b;
}
...@@ -17,7 +17,7 @@ inline istream& operator>>(istream& is, Empty& ) { return is;} ...@@ -17,7 +17,7 @@ inline istream& operator>>(istream& is, Empty& ) { return is;}
template<class VertexType, class EdgeType> template<class VertexType, class EdgeType>
class Graph class Graph
{ { // ERROR - candidates
public: public:
// public type interface // public type interface
typedef map<int, EdgeType > Successor; typedef map<int, EdgeType > Successor;
......
template<class T> template<class T>
struct A { struct A {
typedef T* iterator; typedef T* iterator; // ERROR - pointer to reference
public: public:
A(){} A(){}
}; };
void f() void f()
{ {
A<int&> a; // ERROR - pointer to reference A<int&> a; // ERROR - instantiated from here
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment