aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2004-11-10 17:01:00 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2004-11-10 17:01:00 +0000
commitd746e87d41548db18c07a1e400f3e446c71f27b4 (patch)
tree29af1a5a411111dc12fe0ef9a57841e7e1ebc56d /gcc/cp
parent8393a290d26dfaa9d5ff3e7981a3b8a984645cc2 (diff)
downloadgcc-d746e87d41548db18c07a1e400f3e446c71f27b4.zip
gcc-d746e87d41548db18c07a1e400f3e446c71f27b4.tar.gz
gcc-d746e87d41548db18c07a1e400f3e446c71f27b4.tar.bz2
re PR c++/18369 (Segfault on braced new)
PR c++/18369 * init.c (build_new_1): Handle parenthesized type-ids that name an array type. Tidy. PR c++/18369 * g++.dg/init/new12.C: New test. From-SVN: r90394
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/init.c134
2 files changed, 81 insertions, 59 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 8ac1df2..a3d6aba 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2004-11-09 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/18369
+ * init.c (build_new_1): Handle parenthesized type-ids that name an
+ array type. Tidy.
+
2004-11-09 Joseph S. Myers <joseph@codesourcery.com>
* call.c, class.c, decl.c, decl2.c, error.c, mangle.c, parser.c,
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 48297b9..9d00d4b 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -1718,15 +1718,29 @@ static tree
build_new_1 (tree exp)
{
tree placement, init;
- tree true_type, size, rval;
+ tree size, rval;
+ /* True iff this is a call to "operator new[]" instead of just
+ "operator new". */
+ bool array_p = false;
+ /* True iff ARRAY_P is true and the bound of the array type is
+ not necessarily a compile time constant. For example, VLA_P is
+ true for "new int[f()]". */
+ bool vla_p = false;
+ /* The type being allocated. If ARRAY_P is true, this will be an
+ ARRAY_TYPE. */
+ tree full_type;
+ /* If ARRAY_P is true, the element type of the array. This is an
+ never ARRAY_TYPE; for something like "new int[3][4]", the
+ ELT_TYPE is "int". If ARRAY_P is false, this is the same type as
+ FULL_TYPE. */
+ tree elt_type;
/* The type of the new-expression. (This type is always a pointer
type.) */
tree pointer_type;
- /* The type pointed to by POINTER_TYPE. */
+ /* The type pointed to by POINTER_TYPE. This type may be different
+ from ELT_TYPE for a multi-dimensional array; ELT_TYPE is never an
+ ARRAY_TYPE, but TYPE may be an ARRAY_TYPE. */
tree type;
- /* The type being allocated. For "new T[...]" this will be an
- ARRAY_TYPE. */
- tree full_type;
/* A pointer type pointing to to the FULL_TYPE. */
tree full_pointer_type;
tree outer_nelts = NULL_TREE;
@@ -1737,8 +1751,6 @@ build_new_1 (tree exp)
tree alloc_node;
tree alloc_fn;
tree cookie_expr, init_expr;
- int has_array = 0;
- enum tree_code code;
int nothrow, check_new;
/* Nonzero if the user wrote `::new' rather than just `new'. */
int globally_qualified_p;
@@ -1771,76 +1783,80 @@ build_new_1 (tree exp)
{
tree index;
- has_array = 1;
outer_nelts = nelts;
+ array_p = true;
/* ??? The middle-end will error on us for building a VLA outside a
function context. Methinks that's not it's purvey. So we'll do
our own VLA layout later. */
-
+ vla_p = true;
full_type = build_cplus_array_type (type, NULL_TREE);
-
index = convert (sizetype, nelts);
index = size_binop (MINUS_EXPR, index, size_one_node);
TYPE_DOMAIN (full_type) = build_index_type (index);
}
else
- full_type = type;
-
- true_type = type;
-
- code = has_array ? VEC_NEW_EXPR : NEW_EXPR;
+ {
+ full_type = type;
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ array_p = true;
+ nelts = array_type_nelts_top (type);
+ outer_nelts = nelts;
+ type = TREE_TYPE (type);
+ }
+ }
/* If our base type is an array, then make sure we know how many elements
it has. */
- while (TREE_CODE (true_type) == ARRAY_TYPE)
- {
- tree this_nelts = array_type_nelts_top (true_type);
- nelts = cp_build_binary_op (MULT_EXPR, nelts, this_nelts);
- true_type = TREE_TYPE (true_type);
- }
+ for (elt_type = type;
+ TREE_CODE (elt_type) == ARRAY_TYPE;
+ elt_type = TREE_TYPE (elt_type))
+ nelts = cp_build_binary_op (MULT_EXPR, nelts,
+ array_type_nelts_top (elt_type));
- if (!complete_type_or_else (true_type, exp))
+ if (!complete_type_or_else (elt_type, exp))
return error_mark_node;
- if (TREE_CODE (true_type) == VOID_TYPE)
+ if (TREE_CODE (elt_type) == VOID_TYPE)
{
error ("invalid type %<void%> for new");
return error_mark_node;
}
- if (abstract_virtuals_error (NULL_TREE, true_type))
+ if (abstract_virtuals_error (NULL_TREE, elt_type))
return error_mark_node;
- is_initialized = (TYPE_NEEDS_CONSTRUCTING (type) || init);
- if (CP_TYPE_CONST_P (true_type) && !is_initialized)
+ is_initialized = (TYPE_NEEDS_CONSTRUCTING (elt_type) || init);
+ if (CP_TYPE_CONST_P (elt_type) && !is_initialized)
{
- error ("uninitialized const in %<new%> of %q#T", true_type);
+ error ("uninitialized const in %<new%> of %q#T", elt_type);
return error_mark_node;
}
- size = size_in_bytes (true_type);
- if (has_array)
+ size = size_in_bytes (elt_type);
+ if (array_p)
{
- tree n, bitsize;
-
- /* Do our own VLA layout. Setting TYPE_SIZE/_UNIT is necessary in
- order for the <INIT_EXPR <*foo> <CONSTRUCTOR ...>> to be valid. */
-
- n = convert (sizetype, nelts);
- size = size_binop (MULT_EXPR, size, n);
- TYPE_SIZE_UNIT (full_type) = size;
-
- n = convert (bitsizetype, nelts);
- bitsize = size_binop (MULT_EXPR, TYPE_SIZE (true_type), n);
- TYPE_SIZE (full_type) = bitsize;
+ size = size_binop (MULT_EXPR, size, convert (sizetype, nelts));
+ if (vla_p)
+ {
+ tree n, bitsize;
+
+ /* Do our own VLA layout. Setting TYPE_SIZE/_UNIT is
+ necessary in order for the <INIT_EXPR <*foo> <CONSTRUCTOR
+ ...>> to be valid. */
+ TYPE_SIZE_UNIT (full_type) = size;
+ n = convert (bitsizetype, nelts);
+ bitsize = size_binop (MULT_EXPR, TYPE_SIZE (elt_type), n);
+ TYPE_SIZE (full_type) = bitsize;
+ }
}
/* Allocate the object. */
- if (! placement && TYPE_FOR_JAVA (true_type))
+ if (! placement && TYPE_FOR_JAVA (elt_type))
{
tree class_addr, alloc_decl;
- tree class_decl = build_java_class_ref (true_type);
+ tree class_decl = build_java_class_ref (elt_type);
static const char alloc_name[] = "_Jv_AllocObject";
use_java_new = 1;
@@ -1867,32 +1883,32 @@ build_new_1 (tree exp)
tree fnname;
tree fns;
- fnname = ansi_opname (code);
+ fnname = ansi_opname (array_p ? VEC_NEW_EXPR : NEW_EXPR);
if (!globally_qualified_p
- && CLASS_TYPE_P (true_type)
- && (has_array
- ? TYPE_HAS_ARRAY_NEW_OPERATOR (true_type)
- : TYPE_HAS_NEW_OPERATOR (true_type)))
+ && CLASS_TYPE_P (elt_type)
+ && (array_p
+ ? TYPE_HAS_ARRAY_NEW_OPERATOR (elt_type)
+ : TYPE_HAS_NEW_OPERATOR (elt_type)))
{
/* Use a class-specific operator new. */
/* If a cookie is required, add some extra space. */
- if (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type))
+ if (array_p && TYPE_VEC_NEW_USES_COOKIE (elt_type))
{
- cookie_size = targetm.cxx.get_cookie_size (true_type);
+ cookie_size = targetm.cxx.get_cookie_size (elt_type);
size = size_binop (PLUS_EXPR, size, cookie_size);
}
/* Create the argument list. */
args = tree_cons (NULL_TREE, size, placement);
/* Do name-lookup to find the appropriate operator. */
- fns = lookup_fnfields (true_type, fnname, /*protect=*/2);
+ fns = lookup_fnfields (elt_type, fnname, /*protect=*/2);
if (TREE_CODE (fns) == TREE_LIST)
{
error ("request for member %qD is ambiguous", fnname);
print_candidates (fns);
return error_mark_node;
}
- alloc_call = build_new_method_call (build_dummy_object (true_type),
+ alloc_call = build_new_method_call (build_dummy_object (elt_type),
fns, args,
/*conversion_path=*/NULL_TREE,
LOOKUP_NORMAL);
@@ -1901,8 +1917,8 @@ build_new_1 (tree exp)
{
/* Use a global operator new. */
/* See if a cookie might be required. */
- if (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type))
- cookie_size = targetm.cxx.get_cookie_size (true_type);
+ if (array_p && TYPE_VEC_NEW_USES_COOKIE (elt_type))
+ cookie_size = targetm.cxx.get_cookie_size (elt_type);
else
cookie_size = NULL_TREE;
@@ -1995,7 +2011,7 @@ build_new_1 (tree exp)
cookie_ptr, size_in_bytes (sizetype));
cookie = build_indirect_ref (cookie_ptr, NULL);
cookie = build2 (MODIFY_EXPR, sizetype, cookie,
- size_in_bytes(true_type));
+ size_in_bytes(elt_type));
cookie_expr = build2 (COMPOUND_EXPR, TREE_TYPE (cookie_expr),
cookie, cookie_expr);
}
@@ -2020,10 +2036,10 @@ build_new_1 (tree exp)
if (init == void_zero_node)
init = build_default_init (full_type, nelts);
- else if (init && has_array)
+ else if (init && array_p)
pedwarn ("ISO C++ forbids initialization in array new");
- if (has_array)
+ if (array_p)
{
init_expr
= build_vec_init (init_expr,
@@ -2040,7 +2056,7 @@ build_new_1 (tree exp)
{
init_expr = build_special_member_call (init_expr,
complete_ctor_identifier,
- init, true_type,
+ init, elt_type,
LOOKUP_NORMAL);
stable = stabilize_init (init_expr, &init_preeval_expr);
}
@@ -2073,7 +2089,7 @@ build_new_1 (tree exp)
freed. */
if (flag_exceptions && ! use_java_new)
{
- enum tree_code dcode = has_array ? VEC_DELETE_EXPR : DELETE_EXPR;
+ enum tree_code dcode = array_p ? VEC_DELETE_EXPR : DELETE_EXPR;
tree cleanup;
/* The Standard is unclear here, but the right thing to do