decl.c (compute_array_index_type): New function, split out from grokdeclarator.

* decl.c (compute_array_index_type): New function, split out from
	grokdeclarator.
	(create_array_type_for_decl): Likewise.
	(grokdeclarator): Use them.

	* semantics.c (expand_stmt): Don't suspend_momentary or
	resume_momentary.

From-SVN: r30504
This commit is contained in:
Mark Mitchell 1999-11-12 17:11:07 +00:00 committed by Mark Mitchell
parent d26f8097a3
commit 2848ad0fd6
3 changed files with 205 additions and 155 deletions

View File

@ -1,3 +1,13 @@
1999-11-12 Mark Mitchell <mark@codesourcery.com>
* decl.c (compute_array_index_type): New function, split out from
grokdeclarator.
(create_array_type_for_decl): Likewise.
(grokdeclarator): Use them.
* semantics.c (expand_stmt): Don't suspend_momentary or
resume_momentary.
Thu Nov 11 12:42:11 MST 1999 Diego Novillo <dnovillo@cygnus.com>
* init.c (init_init_processing): Header information for

View File

@ -175,6 +175,8 @@ static void destroy_local_static PROTO((tree));
static void destroy_local_var PROTO((tree));
static void finish_constructor_body PROTO((void));
static void finish_destructor_body PROTO((void));
static tree compute_array_index_type PROTO((tree, tree));
static tree create_array_type_for_decl PROTO((tree, tree, tree));
#if defined (DEBUG_CP_BINDING_LEVELS)
static void indent PROTO((void));
@ -8755,6 +8757,195 @@ check_static_variable_definition (decl, type)
return 0;
}
/* Given the SIZE (i.e., number of elements) in an array, compute an
appropriate index type for the array. If non-NULL, NAME is the
name of the thing being declared. */
static tree
compute_array_index_type (name, size)
tree name;
tree size;
{
tree itype;
/* The size might be the result of a cast. */
STRIP_TYPE_NOPS (size);
/* It might be a const variable or enumeration constant. */
if (TREE_READONLY_DECL_P (size))
size = decl_constant_value (size);
/* If this involves a template parameter, it will be a constant at
instantiation time, but we don't know what the value is yet.
Even if no template parameters are involved, we may an expression
that is not a constant; we don't even simplify `1 + 2' when
processing a template. */
if (processing_template_decl)
{
/* Resolve a qualified reference to an enumerator or static
const data member of ours. */
if (TREE_CODE (size) == SCOPE_REF
&& TREE_OPERAND (size, 0) == current_class_type)
{
tree t = lookup_field (current_class_type,
TREE_OPERAND (size, 1), 0, 0);
if (t)
size = t;
}
return build_index_type (build_min (MINUS_EXPR, sizetype,
size, integer_one_node));
}
/* The array bound must be an integer type. */
if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE
&& TREE_CODE (TREE_TYPE (size)) != ENUMERAL_TYPE
&& TREE_CODE (TREE_TYPE (size)) != BOOLEAN_TYPE)
{
cp_error ("size of array `%D' has non-integer type", name);
size = integer_one_node;
}
/* Normally, the array-bound will be a constant. */
if (TREE_CONSTANT (size))
{
/* Check to see if the array bound overflowed. Make that an
error, no matter how generous we're being. */
int old_flag_pedantic_errors = flag_pedantic_errors;
int old_pedantic = pedantic;
pedantic = flag_pedantic_errors = 1;
constant_expression_warning (size);
pedantic = old_pedantic;
flag_pedantic_errors = old_flag_pedantic_errors;
/* An array must have a positive number of elements. */
if (INT_CST_LT (size, integer_zero_node))
{
cp_error ("size of array `%D' is negative", name);
size = integer_one_node;
}
/* Except that an extension we allow zero-sized arrays. We
always allow them in system headers because glibc uses
them. */
else if (integer_zerop (size) && pedantic && !in_system_header)
cp_pedwarn ("ANSI C++ forbids zero-size array `%D'", name);
}
/* Compute the index of the largest element in the array. It is
one less than the number of elements in the array. */
itype
= fold (build_binary_op (MINUS_EXPR,
cp_convert (ssizetype, size),
cp_convert (ssizetype,
integer_one_node)));
/* Check for variable-sized arrays. We allow such things as an
extension, even though they are not allowed in ANSI/ISO C++. */
if (!TREE_CONSTANT (itype))
{
if (pedantic)
{
if (name)
cp_pedwarn ("ANSI C++ forbids variable-size array `%D'",
name);
else
cp_pedwarn ("ANSI C++ forbids variable-size array");
}
/* Create a variable-sized array index type. */
itype = variable_size (itype);
}
/* Make sure that there was no overflow when creating to a signed
index type. (For example, on a 32-bit machine, an array with
size 2^32 - 1 is too big.) */
else if (TREE_OVERFLOW (itype))
{
error ("overflow in array dimension");
TREE_OVERFLOW (itype) = 0;
}
/* Create and return the appropriate index type. */
return build_index_type (itype);
}
/* Returns an ARRAY_TYPE for an array with SIZE elements of the
indicated TYPE. If non-NULL, NAME is the NAME of the declaration
with this type. */
static tree
create_array_type_for_decl (name, type, size)
tree name;
tree type;
tree size;
{
tree itype = NULL_TREE;
const char* error_msg;
/* If things have already gone awry, bail now. */
if (type == error_mark_node || size == error_mark_node)
return error_mark_node;
/* Assume that everything will go OK. */
error_msg = NULL;
/* There are some types which cannot be array elements. */
switch (TREE_CODE (type))
{
case VOID_TYPE:
error_msg = "array of void";
break;
case FUNCTION_TYPE:
error_msg = "array of functions";
break;
case REFERENCE_TYPE:
error_msg = "array of references";
break;
case OFFSET_TYPE:
error_msg = "array of data members";
break;
case METHOD_TYPE:
error_msg = "array of function members";
break;
default:
break;
}
/* If something went wrong, issue an error-message and return. */
if (error_msg)
{
if (name)
cp_error ("declaration of `%D' as %s", name, error_msg);
else
cp_error ("creating %s", error_msg);
return error_mark_node;
}
/* [dcl.array]
The constant expressions that specify the bounds of the arrays
can be omitted only for the first member of the sequence. */
if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type))
{
cp_error ("declaration of `%D' as multidimensional array",
name);
cp_error ("must have bounds for all dimensions except the first");
return error_mark_node;
}
/* Figure out the index type for the array. */
if (size)
itype = compute_array_index_type (name, size);
return build_cplus_array_type (type, itype);
}
/* Given declspecs and a declarator,
determine the name and type of the object declared
and construct a ..._DECL node for it.
@ -9759,166 +9950,18 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
case ARRAY_REF:
{
register tree itype = NULL_TREE;
register tree size = TREE_OPERAND (declarator, 1);
/* The index is a signed object `sizetype' bits wide. */
tree index_type = signed_type (sizetype);
register tree size;
declarator = TREE_OPERAND (declarator, 0);
/* Check for some types that there cannot be arrays of. */
if (TREE_CODE (type) == VOID_TYPE)
{
cp_error ("declaration of `%D' as array of voids", dname);
type = error_mark_node;
}
if (TREE_CODE (type) == FUNCTION_TYPE)
{
cp_error ("declaration of `%D' as array of functions", dname);
type = error_mark_node;
}
/* ARM $8.4.3: Since you can't have a pointer to a reference,
you can't have arrays of references. If we allowed them,
then we'd be saying x[i] is valid for an array x, but
then you'd have to ask: what does `*(x + i)' mean? */
if (TREE_CODE (type) == REFERENCE_TYPE)
{
if (decl_context == TYPENAME)
cp_error ("cannot make arrays of references");
else
cp_error ("declaration of `%D' as array of references",
dname);
type = error_mark_node;
}
if (TREE_CODE (type) == OFFSET_TYPE)
{
cp_error ("declaration of `%D' as array of data members",
dname);
type = error_mark_node;
}
if (TREE_CODE (type) == METHOD_TYPE)
{
cp_error ("declaration of `%D' as array of function members",
dname);
type = error_mark_node;
}
if (size == error_mark_node)
type = error_mark_node;
else if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type))
{
/* [dcl.array]
the constant expressions that specify the bounds of
the arrays can be omitted only for the first member
of the sequence. */
cp_error ("declaration of `%D' as multidimensional array",
dname);
cp_error ("must have bounds for all dimensions except the first");
type = error_mark_node;
}
if (type == error_mark_node)
continue;
size = TREE_OPERAND (declarator, 1);
/* VC++ spells a zero-sized array with []. */
if (size == NULL_TREE && decl_context == FIELD && ! staticp
&& ! RIDBIT_SETP (RID_TYPEDEF, specbits))
size = integer_zero_node;
if (size)
{
/* Might be a cast. */
if (TREE_CODE (size) == NOP_EXPR
&& TREE_TYPE (size) == TREE_TYPE (TREE_OPERAND (size, 0)))
size = TREE_OPERAND (size, 0);
if (TREE_READONLY_DECL_P (size))
size = decl_constant_value (size);
declarator = TREE_OPERAND (declarator, 0);
/* If this involves a template parameter, it will be a
constant at instantiation time, but we don't know
what the value is yet. Even if no template
parameters are involved, we may an expression that
is not a constant; we don't even simplify `1 + 2'
when processing a template. */
if (processing_template_decl)
{
/* Resolve a qualified reference to an enumerator or
static const data member of ours. */
if (TREE_CODE (size) == SCOPE_REF
&& TREE_OPERAND (size, 0) == current_class_type)
{
tree t = lookup_field (current_class_type,
TREE_OPERAND (size, 1), 0, 0);
if (t)
size = t;
}
itype = build_index_type (build_min
(MINUS_EXPR, sizetype, size, integer_one_node));
goto dont_grok_size;
}
if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE
&& TREE_CODE (TREE_TYPE (size)) != ENUMERAL_TYPE
&& TREE_CODE (TREE_TYPE (size)) != BOOLEAN_TYPE)
{
cp_error ("size of array `%D' has non-integer type",
dname);
size = integer_one_node;
}
if (pedantic && !in_system_header && integer_zerop (size))
cp_pedwarn ("ANSI C++ forbids zero-size array `%D'", dname);
if (TREE_CONSTANT (size))
{
int old_flag_pedantic_errors = flag_pedantic_errors;
int old_pedantic = pedantic;
pedantic = flag_pedantic_errors = 1;
/* Always give overflow errors on array subscripts. */
constant_expression_warning (size);
pedantic = old_pedantic;
flag_pedantic_errors = old_flag_pedantic_errors;
if (INT_CST_LT (size, integer_zero_node))
{
cp_error ("size of array `%D' is negative", dname);
size = integer_one_node;
}
}
else
{
if (pedantic)
{
if (dname)
cp_pedwarn ("ANSI C++ forbids variable-size array `%D'",
dname);
else
cp_pedwarn ("ANSI C++ forbids variable-size array");
}
}
itype
= fold (build_binary_op (MINUS_EXPR,
cp_convert (index_type, size),
cp_convert (index_type,
integer_one_node)));
if (! TREE_CONSTANT (itype))
itype = variable_size (itype);
else if (TREE_OVERFLOW (itype))
{
error ("overflow in array dimension");
TREE_OVERFLOW (itype) = 0;
}
itype = build_index_type (itype);
}
dont_grok_size:
type = build_cplus_array_type (type, itype);
type = create_array_type_for_decl (dname, type, size);
ctype = NULL_TREE;
}
break;

View File

@ -2267,7 +2267,6 @@ expand_stmt (t)
case DECL_STMT:
{
tree decl;
int i = suspend_momentary ();
emit_line_note (input_filename, lineno);
decl = DECL_STMT_DECL (t);
@ -2290,8 +2289,6 @@ expand_stmt (t)
}
else if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
make_rtl_for_local_static (decl);
resume_momentary (i);
}
break;