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>
* 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.
1998-08-06 Mark Mitchell <mark@markmitchell.com>
......
......@@ -1845,6 +1845,17 @@ grokbitfield (declarator, declspecs, width)
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))
{
error ("field declaration not allowed in signature");
......@@ -3001,6 +3012,25 @@ do_dtors ()
if (! current_function_decl)
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);
if (protect)
......@@ -3015,6 +3045,11 @@ do_dtors ()
if (protect)
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));
static tree most_general_template PROTO((tree));
static void set_mangled_name_for_template_decl PROTO((tree));
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
level of template arguments, then the TREE_VEC contains the
......@@ -3779,6 +3781,11 @@ pop_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;
old->next = free_tinst_level;
free_tinst_level = old;
......@@ -4291,7 +4298,15 @@ instantiate_class_template (type)
for (t = TYPE_FIELDS (pattern); t; t = TREE_CHAIN (t))
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)
{
pending_statics = perm_tree_cons (NULL_TREE, r, pending_statics);
......@@ -4619,204 +4634,34 @@ tsubst_aggr_type (t, args, in_decl, entering_scope)
}
}
/* 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. */
/* Substitute the ARGS into the T, which is a _DECL. TYPE is the
(already computed) substitution of ARGS into TREE_TYPE (T), if
appropriate. Return the result of the substitution. IN_DECL is as
for tsubst. */
tree
tsubst (t, args, in_decl)
tree t, args;
tsubst_decl (t, args, type, in_decl)
tree t;
tree args;
tree type;
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);
int saved_lineno;
char* saved_filename;
tree r;
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);
/* Set the filename and linenumber to improve error-reporting. */
saved_lineno = lineno;
saved_filename = input_filename;
lineno = DECL_SOURCE_LINE (t);
input_filename = DECL_SOURCE_FILE (t);
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;
/* 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;
}
case TEMPLATE_DECL:
{
/* We can get here when processing a member template function
of a template class. */
tree tmpl;
tree decl = DECL_TEMPLATE_RESULT (t);
tree parms;
tree* new_parms;
......@@ -4841,7 +4686,10 @@ tsubst (t, args, in_decl)
spec = retrieve_specialization (t, full_args);
if (spec != NULL_TREE)
return spec;
{
r = spec;
break;
}
}
/* Make a new template decl. It will be similar to the
......@@ -4849,60 +4697,60 @@ tsubst (t, args, in_decl)
We also create a new function declaration, which is just
like the old one, but points to this new template, rather
than the old one. */
tmpl = copy_node (t);
copy_lang_decl (tmpl);
my_friendly_assert (DECL_LANG_SPECIFIC (tmpl) != 0, 0);
TREE_CHAIN (tmpl) = NULL_TREE;
r = copy_node (t);
copy_lang_decl (r);
my_friendly_assert (DECL_LANG_SPECIFIC (r) != 0, 0);
TREE_CHAIN (r) = NULL_TREE;
if (is_template_template_parm)
{
tree new_decl = tsubst (decl, args, in_decl);
DECL_RESULT (tmpl) = new_decl;
TREE_TYPE (tmpl) = TREE_TYPE (new_decl);
return tmpl;
DECL_RESULT (r) = new_decl;
TREE_TYPE (r) = TREE_TYPE (new_decl);
break;
}
DECL_CONTEXT (tmpl)
DECL_CONTEXT (r)
= tsubst_aggr_type (DECL_CONTEXT (t), args, in_decl,
/*entering_scope=*/1);
DECL_CLASS_CONTEXT (tmpl)
DECL_CLASS_CONTEXT (r)
= tsubst_aggr_type (DECL_CLASS_CONTEXT (t), args, in_decl,
/*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)
{
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);
DECL_TI_ARGS (tmpl) = CLASSTYPE_TI_ARGS (new_type);
TREE_TYPE (r) = new_type;
CLASSTYPE_TI_TEMPLATE (new_type) = r;
DECL_RESULT (r) = TYPE_MAIN_DECL (new_type);
DECL_TI_ARGS (r) = CLASSTYPE_TI_ARGS (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_TI_ARGS (tmpl) = DECL_TI_ARGS (new_decl);
DECL_RESULT (r) = new_decl;
DECL_TI_TEMPLATE (new_decl) = r;
TREE_TYPE (r) = TREE_TYPE (new_decl);
DECL_TI_ARGS (r) = DECL_TI_ARGS (new_decl);
}
SET_DECL_IMPLICIT_INSTANTIATION (tmpl);
DECL_TEMPLATE_INSTANTIATIONS (tmpl) = NULL_TREE;
DECL_TEMPLATE_SPECIALIZATIONS (tmpl) = NULL_TREE;
SET_DECL_IMPLICIT_INSTANTIATION (r);
DECL_TEMPLATE_INSTANTIATIONS (r) = NULL_TREE;
DECL_TEMPLATE_SPECIALIZATIONS (r) = NULL_TREE;
/* The template parameters for this new template are all the
template parameters for the old template, except the
outermost level of parameters. */
DECL_TEMPLATE_PARMS (tmpl)
DECL_TEMPLATE_PARMS (r)
= tsubst_template_parms (DECL_TEMPLATE_PARMS (t), args);
if (PRIMARY_TEMPLATE_P (t))
DECL_PRIMARY_TEMPLATE (tmpl) = tmpl;
DECL_PRIMARY_TEMPLATE (r) = r;
/* We don't partially instantiate partial specializations. */
if (TREE_CODE (decl) == TYPE_DECL)
return tmpl;
break;
for (spec = DECL_TEMPLATE_SPECIALIZATIONS (t);
spec != NULL_TREE;
......@@ -4953,20 +4801,19 @@ tsubst (t, args, in_decl)
new_fn = tsubst (DECL_RESULT (most_general_template (fn)),
spec_args, in_decl);
DECL_TI_TEMPLATE (new_fn) = fn;
register_specialization (new_fn, tmpl,
register_specialization (new_fn, r,
innermost_args (spec_args));
}
/* Record this partial instantiation. */
register_specialization (tmpl, t,
DECL_TI_ARGS (DECL_RESULT (tmpl)));
register_specialization (r, t,
DECL_TI_ARGS (DECL_RESULT (r)));
return tmpl;
}
break;
case FUNCTION_DECL:
{
tree r = NULL_TREE;
tree ctx;
tree argvec;
tree gen_tmpl;
......@@ -4988,7 +4835,10 @@ tsubst (t, args, in_decl)
/* Check to see if we already have this specialization. */
spec = retrieve_specialization (gen_tmpl, argvec);
if (spec)
return spec;
{
r = spec;
break;
}
}
else
{
......@@ -5113,13 +4963,12 @@ tsubst (t, args, in_decl)
== NULL_TREE))
SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r), r);
}
return r;
}
break;
case PARM_DECL:
{
tree r = copy_node (t);
r = copy_node (t);
TREE_TYPE (r) = type;
if (TREE_CODE (DECL_INITIAL (r)) != TEMPLATE_PARM_INDEX)
DECL_INITIAL (r) = TREE_TYPE (r);
......@@ -5135,12 +4984,12 @@ tsubst (t, args, in_decl)
#endif
if (TREE_CHAIN (t))
TREE_CHAIN (r) = tsubst (TREE_CHAIN (t), args, TREE_CHAIN (t));
return r;
}
break;
case FIELD_DECL:
{
tree r = copy_node (t);
r = copy_node (t);
TREE_TYPE (r) = type;
copy_lang_decl (r);
#if 0
......@@ -5150,21 +4999,20 @@ tsubst (t, args, in_decl)
TREE_CHAIN (r) = NULL_TREE;
if (TREE_CODE (type) == VOID_TYPE)
cp_error_at ("instantiation of `%D' as type void", r);
return r;
}
break;
case USING_DECL:
{
tree r = copy_node (t);
r = copy_node (t);
DECL_INITIAL (r)
= tsubst_copy (DECL_INITIAL (t), args, in_decl);
TREE_CHAIN (r) = NULL_TREE;
return r;
}
break;
case VAR_DECL:
{
tree r;
tree argvec;
tree gen_tmpl;
tree spec;
......@@ -5183,7 +5031,10 @@ tsubst (t, args, in_decl)
spec = retrieve_specialization (gen_tmpl, argvec);
if (spec)
return spec;
{
r = spec;
break;
}
r = copy_node (t);
TREE_TYPE (r) = type;
......@@ -5207,20 +5058,227 @@ tsubst (t, args, in_decl)
TREE_CHAIN (r) = NULL_TREE;
if (TREE_CODE (type) == VOID_TYPE)
cp_error_at ("instantiation of `%D' as type void", r);
return r;
}
break;
case TYPE_DECL:
if (t == TYPE_NAME (TREE_TYPE (t)))
return TYPE_NAME (type);
r = TYPE_NAME (type);
else
{
r = copy_node (t);
TREE_TYPE (r) = type;
DECL_CONTEXT (r) = current_class_type;
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 r = copy_node (t);
TREE_TYPE (r) = type;
DECL_CONTEXT (r) = current_class_type;
TREE_CHAIN (r) = NULL_TREE;
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;
}
}
case TREE_LIST:
{
......@@ -5439,6 +5497,19 @@ tsubst (t, args, in_decl)
tree ctx = tsubst_aggr_type (TYPE_CONTEXT (t), args, in_decl,
/*entering_scope=*/1);
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);
return cp_build_type_variant
(f, TYPE_READONLY (f) || TYPE_READONLY (t),
......
......@@ -80,7 +80,9 @@ target_type (type)
}
/* 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
require_complete_type (value)
......@@ -120,13 +122,10 @@ require_complete_type (value)
return require_complete_type (value);
}
if (TYPE_SIZE (complete_type (type)))
if (complete_type_or_else (type))
return value;
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
......@@ -170,7 +169,10 @@ complete_type_or_else (type)
tree 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);
return NULL_TREE;
......
......@@ -9,7 +9,7 @@
typedef void (func_type) ();
struct s {
func_type f:32; // ERROR - XFAIL *-*-*
func_type f:32; // ERROR - bitified with function type
};
int main () { return 0; }
......@@ -14,7 +14,7 @@
const int ArraySize = 12;
template <class Type>
class Array {
class Array { // ERROR - .struct Array_RC redecl.*
friend class Array_RC;
public:
Array(const Type *ar, int sz) { init(ar,sz); }
......@@ -97,7 +97,7 @@ try_array( Array_RC<Type> &rc )
main()
{
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;
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 @@
template <class T = int> // ERROR - original definition
struct S
{
{ // ERROR - redefinition of default arg
template <class U = int>
friend class S;
};
template struct S<int>; // ERROR - redefinition of default arg
template struct S<int>; // ERROR - instantiated from here
// Build don't link:
template <class A> class B {
A a;
template <class A> class B { // ERROR - candidates
A a;
public:
B(A&aa); // ERROR -
B(A&aa); // ERROR - near match
~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;}
template<class VertexType, class EdgeType>
class Graph
{
{ // ERROR - candidates
public:
// public type interface
typedef map<int, EdgeType > Successor;
......
template<class T>
struct A {
typedef T* iterator;
typedef T* iterator; // ERROR - pointer to reference
public:
A(){}
};
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