aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2004-09-28 02:56:11 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2004-09-28 02:56:11 +0000
commit455f19cb1cc13e726b806d792a8808f55aaa9a07 (patch)
tree36630ae2e63d9c79e59704bfce96a6e0b3b33f2c
parent081077002d07ddac4094b11b1edd5f8d1175bddd (diff)
downloadgcc-455f19cb1cc13e726b806d792a8808f55aaa9a07.zip
gcc-455f19cb1cc13e726b806d792a8808f55aaa9a07.tar.gz
gcc-455f19cb1cc13e726b806d792a8808f55aaa9a07.tar.bz2
re PR c++/17642 (internal compiler error: in invert_truthvalue, at fold-const.c:2997)
PR c++/17642 * stor-layout.c (layout_decl): Use fold_convert, not convert. (bit_from_pos): Likewise. (byte_from_pos): Likewise. (pos_from_bit): Likewise. (normalize_offset): Likewise. (place_field): Likewise. (finalize_type_size): Likewise. (layout_type): Likewise. * tree.c (build_index_type): Likewise. PR c++/17642 * cp-tree.h (fold_if_not_in_template): New function. * call.c (build_conditional_expr): Use fold_if_not_in_template. (build_cxx_call): Likewise. * cvt.c (convert_to_complex): Likewise. (ocp_convert): Likewise. (convert): Likewise. (convert_force): Likewise. * decl.c (compute_array_index_type): Clear processing_template_decl while folding array bounds. * pt.c (convert_nontype_argument): Clear processing_template_decl while processing non-type argument initialization. * tree.c (fold_if_not_in_template): New function. * typeck.c (build_class_member_access_expr): Use fold_if_not_in_template. (build_array_ref): Likewise. (build_binary_op): Likewise. Do not try to optimize computations when processing templates. (cp_pointer_int_sum): Use fold_if_not_in_template. (pointer_diff): Likewise. (build_unary_op): Likewise. (build_reinterpret_cast): Likewise. (get_delta_difference): Likewise. (expand_ptrmemfunc_cst): Likewise. (dubious_conversion_warnings): Likewise. * g++.dg/template/crash23.C: New test. From-SVN: r88217
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/cp/ChangeLog29
-rw-r--r--gcc/cp/call.c5
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/cvt.c23
-rw-r--r--gcc/cp/decl.c18
-rw-r--r--gcc/cp/pt.c8
-rw-r--r--gcc/cp/tree.c13
-rw-r--r--gcc/cp/typeck.c119
-rw-r--r--gcc/stor-layout.c51
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/template/crash23.C9
-rw-r--r--gcc/tree.c2
13 files changed, 205 insertions, 90 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f392069..d7fb97a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,16 @@
+2004-09-27 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/17642
+ * stor-layout.c (layout_decl): Use fold_convert, not convert.
+ (bit_from_pos): Likewise.
+ (byte_from_pos): Likewise.
+ (pos_from_bit): Likewise.
+ (normalize_offset): Likewise.
+ (place_field): Likewise.
+ (finalize_type_size): Likewise.
+ (layout_type): Likewise.
+ * tree.c (build_index_type): Likewise.
+
2004-09-27 Devang Patel <dpatel@apple.com>
* expr.c (expand_expr_real_1): Handle VEC_COND_EXPR.
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 6da00c4..561ac7a 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,32 @@
+2004-09-27 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/17642
+ * cp-tree.h (fold_if_not_in_template): New function.
+ * call.c (build_conditional_expr): Use fold_if_not_in_template.
+ (build_cxx_call): Likewise.
+ * cvt.c (convert_to_complex): Likewise.
+ (ocp_convert): Likewise.
+ (convert): Likewise.
+ (convert_force): Likewise.
+ * decl.c (compute_array_index_type): Clear
+ processing_template_decl while folding array bounds.
+ * pt.c (convert_nontype_argument): Clear
+ processing_template_decl while processing non-type argument
+ initialization.
+ * tree.c (fold_if_not_in_template): New function.
+ * typeck.c (build_class_member_access_expr): Use
+ fold_if_not_in_template.
+ (build_array_ref): Likewise.
+ (build_binary_op): Likewise. Do not try to optimize computations
+ when processing templates.
+ (cp_pointer_int_sum): Use fold_if_not_in_template.
+ (pointer_diff): Likewise.
+ (build_unary_op): Likewise.
+ (build_reinterpret_cast): Likewise.
+ (get_delta_difference): Likewise.
+ (expand_ptrmemfunc_cst): Likewise.
+ (dubious_conversion_warnings): Likewise.
+
2004-09-27 Matt Austern <austern@apple.com>
* cp/parser.c (struct cp_token): new one-bit field , implicit_extern_c
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index c5761ec..f61fa2a 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -3442,7 +3442,8 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3)
}
valid_operands:
- result = fold (build3 (COND_EXPR, result_type, arg1, arg2, arg3));
+ result = fold_if_not_in_template (build3 (COND_EXPR, result_type, arg1,
+ arg2, arg3));
/* We can't use result_type below, as fold might have returned a
throw_expr. */
@@ -4869,7 +4870,7 @@ build_cxx_call (tree fn, tree args)
/* Some built-in function calls will be evaluated at compile-time in
fold (). */
- fn = fold (fn);
+ fn = fold_if_not_in_template (fn);
if (VOID_TYPE_P (TREE_TYPE (fn)))
return fn;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 3c9ea57..0a2d970 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4207,6 +4207,7 @@ extern tree cp_add_pending_fn_decls (void*,tree);
extern int cp_is_overload_p (tree);
extern int cp_auto_var_in_fn_p (tree,tree);
extern void cp_update_decl_after_saving (tree, void *);
+extern tree fold_if_not_in_template (tree);
/* in typeck.c */
extern int string_conv_p (tree, tree, int);
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index d93351e..a5d42e4 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -643,7 +643,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
/* For complex data types, we need to perform componentwise
conversion. */
else if (TREE_CODE (type) == COMPLEX_TYPE)
- return fold (convert_to_complex (type, e));
+ return fold_if_not_in_template (convert_to_complex (type, e));
else if (TREE_CODE (e) == TARGET_EXPR)
{
/* Don't build a NOP_EXPR of class type. Instead, change the
@@ -659,7 +659,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
/* We shouldn't be treating objects of ADDRESSABLE type as
rvalues. */
gcc_assert (!TREE_ADDRESSABLE (type));
- return fold (build1 (NOP_EXPR, type, e));
+ return fold_if_not_in_template (build_nop (type, e));
}
}
@@ -696,10 +696,10 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
if (code == BOOLEAN_TYPE)
return cp_truthvalue_conversion (e);
- return fold (convert_to_integer (type, e));
+ return fold_if_not_in_template (convert_to_integer (type, e));
}
if (POINTER_TYPE_P (type) || TYPE_PTR_TO_MEMBER_P (type))
- return fold (cp_convert_to_pointer (type, e, false));
+ return fold_if_not_in_template (cp_convert_to_pointer (type, e, false));
if (code == VECTOR_TYPE)
{
tree in_vtype = TREE_TYPE (e);
@@ -713,7 +713,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
error ("`%#T' used where a `%T' was expected", in_vtype, type);
return error_mark_node;
}
- return fold (convert_to_vector (type, e));
+ return fold_if_not_in_template (convert_to_vector (type, e));
}
if (code == REAL_TYPE || code == COMPLEX_TYPE)
{
@@ -729,9 +729,9 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
TREE_TYPE (e));
}
if (code == REAL_TYPE)
- return fold (convert_to_real (type, e));
+ return fold_if_not_in_template (convert_to_real (type, e));
else if (code == COMPLEX_TYPE)
- return fold (convert_to_complex (type, e));
+ return fold_if_not_in_template (convert_to_complex (type, e));
}
/* New C++ semantics: since assignment is now based on
@@ -945,7 +945,7 @@ convert (tree type, tree expr)
if (POINTER_TYPE_P (type) && POINTER_TYPE_P (intype))
{
expr = decl_constant_value (expr);
- return fold (build1 (NOP_EXPR, type, expr));
+ return fold_if_not_in_template (build_nop (type, expr));
}
return ocp_convert (type, expr, CONV_OLD_CONVERT,
@@ -963,13 +963,14 @@ convert_force (tree type, tree expr, int convtype)
enum tree_code code = TREE_CODE (type);
if (code == REFERENCE_TYPE)
- return fold (convert_to_reference (type, e, CONV_C_CAST, LOOKUP_COMPLAIN,
- NULL_TREE));
+ return (fold_if_not_in_template
+ (convert_to_reference (type, e, CONV_C_CAST, LOOKUP_COMPLAIN,
+ NULL_TREE)));
else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE)
e = convert_from_reference (e);
if (code == POINTER_TYPE)
- return fold (convert_to_pointer_force (type, e));
+ return fold_if_not_in_template (convert_to_pointer_force (type, e));
/* From typeck.c convert_for_assignment */
if (((TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE && TREE_CODE (e) == ADDR_EXPR
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index d3a0c8d..fb1334f 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -6196,12 +6196,20 @@ compute_array_index_type (tree name, tree size)
itype = build_min (MINUS_EXPR, sizetype, size, integer_one_node);
else
{
+ HOST_WIDE_INT saved_processing_template_decl;
+
/* Compute the index of the largest element in the array. It is
- one less than the number of elements in the array. */
- itype
- = fold (cp_build_binary_op (MINUS_EXPR,
- cp_convert (ssizetype, size),
- cp_convert (ssizetype, integer_one_node)));
+ one less than the number of elements in the array. We save
+ and restore PROCESSING_TEMPLATE_DECL so that computations in
+ cp_build_binary_op will be appropriately folded. */
+ saved_processing_template_decl = processing_template_decl;
+ processing_template_decl = 0;
+ itype = cp_build_binary_op (MINUS_EXPR,
+ cp_convert (ssizetype, size),
+ cp_convert (ssizetype, integer_one_node));
+ itype = fold (itype);
+ processing_template_decl = saved_processing_template_decl;
+
if (!TREE_CONSTANT (itype))
/* A variable sized array. */
itype = variable_size (itype);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 3125c83..99c70b5 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -3381,6 +3381,8 @@ convert_nontype_argument (tree type, tree expr)
switch (TREE_CODE (type))
{
+ HOST_WIDE_INT saved_processing_template_decl;
+
case INTEGER_TYPE:
case BOOLEAN_TYPE:
case ENUMERAL_TYPE:
@@ -3398,8 +3400,12 @@ convert_nontype_argument (tree type, tree expr)
return error_mark_node;
/* It's safe to call digest_init in this case; we know we're
- just converting one integral constant expression to another. */
+ just converting one integral constant expression to another.
+ */
+ saved_processing_template_decl = processing_template_decl;
+ processing_template_decl = 0;
expr = digest_init (type, expr, (tree*) 0);
+ processing_template_decl = saved_processing_template_decl;
if (TREE_CODE (expr) != INTEGER_CST)
/* Curiously, some TREE_CONSTANT integral expressions do not
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index fc3516d..16bb39b 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -2331,6 +2331,19 @@ stabilize_init (tree init, tree *initp)
return true;
}
+/* Like "fold", but should be used whenever we might be processing the
+ body of a template. */
+
+tree
+fold_if_not_in_template (tree expr)
+{
+ /* In the body of a template, there is never any need to call
+ "fold". We will call fold later when actually instantiating the
+ template. Integral constant expressions in templates will be
+ evaluted via fold_non_dependent_expr, as necessary. */
+ return (processing_template_decl ? expr : fold (expr));
+}
+
#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
/* Complain that some language-specific thing hanging off a tree
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 164f7a3..8533773 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1768,8 +1768,9 @@ build_class_member_access_expr (tree object, tree member,
member_type = cp_build_qualified_type (member_type, type_quals);
}
- result = fold (build3 (COMPONENT_REF, member_type, object, member,
- NULL_TREE));
+ result = build3 (COMPONENT_REF, member_type, object, member,
+ NULL_TREE);
+ result = fold_if_not_in_template (result);
/* Mark the expression const or volatile, as appropriate. Even
though we've dealt with the type above, we still have to mark the
@@ -2272,7 +2273,7 @@ build_array_ref (tree array, tree idx)
|= (CP_TYPE_VOLATILE_P (type) | TREE_SIDE_EFFECTS (array));
TREE_THIS_VOLATILE (rval)
|= (CP_TYPE_VOLATILE_P (type) | TREE_THIS_VOLATILE (array));
- return require_complete_type (fold (rval));
+ return require_complete_type (fold_if_not_in_template (rval));
}
{
@@ -2762,6 +2763,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
convert it to this type. */
tree final_type = 0;
+ tree result;
+
/* Nonzero if this is an operation like MIN or MAX which can
safely be computed in short if both args are promoted shorts.
Also implies COMMON.
@@ -2782,6 +2785,9 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
/* Nonzero means set RESULT_TYPE to the common type of the args. */
int common = 0;
+ /* True if both operands have arithmetic type. */
+ bool arithmetic_types_p;
+
/* Apply default conversions. */
op0 = orig_op0;
op1 = orig_op1;
@@ -3169,14 +3175,31 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
break;
}
- if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE)
- &&
- (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE))
+ arithmetic_types_p =
+ ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE)
+ && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
+ || code1 == COMPLEX_TYPE));
+ /* Determine the RESULT_TYPE, if it is not already known. */
+ if (!result_type
+ && arithmetic_types_p
+ && (shorten || common || short_compare))
+ result_type = common_type (type0, type1);
+
+ if (!result_type)
{
- int none_complex = (code0 != COMPLEX_TYPE && code1 != COMPLEX_TYPE);
+ error ("invalid operands of types `%T' and `%T' to binary `%O'",
+ TREE_TYPE (orig_op0), TREE_TYPE (orig_op1), code);
+ return error_mark_node;
+ }
- if (shorten || common || short_compare)
- result_type = common_type (type0, type1);
+ /* If we're in a template, the only thing we need to know is the
+ RESULT_TYPE. */
+ if (processing_template_decl)
+ return build2 (resultcode, result_type, op0, op1);
+
+ if (arithmetic_types_p)
+ {
+ int none_complex = (code0 != COMPLEX_TYPE && code1 != COMPLEX_TYPE);
/* For certain operations (which identify themselves by shorten != 0)
if both args were extended from the same smaller type,
@@ -3419,19 +3442,11 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
}
}
- /* At this point, RESULT_TYPE must be nonzero to avoid an error message.
- If CONVERTED is zero, both args will be converted to type RESULT_TYPE.
+ /* If CONVERTED is zero, both args will be converted to type RESULT_TYPE.
Then the expression will be built.
It will be given type FINAL_TYPE if that is nonzero;
otherwise, it will be given type RESULT_TYPE. */
- if (!result_type)
- {
- error ("invalid operands of types `%T' and `%T' to binary `%O'",
- TREE_TYPE (orig_op0), TREE_TYPE (orig_op1), code);
- return error_mark_node;
- }
-
/* Issue warnings about peculiar, but valid, uses of NULL. */
if (/* It's reasonable to use pointer values as operands of &&
and ||, so NULL is no exception. */
@@ -3465,12 +3480,11 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
if (build_type == NULL_TREE)
build_type = result_type;
- {
- tree result = fold (build2 (resultcode, build_type, op0, op1));
- if (final_type != 0)
- result = cp_convert (final_type, result);
- return result;
- }
+ result = build2 (resultcode, build_type, op0, op1);
+ result = fold_if_not_in_template (result);
+ if (final_type != 0)
+ result = cp_convert (final_type, result);
+ return result;
}
/* Return a tree for the sum or difference (RESULTCODE says which)
@@ -3488,7 +3502,8 @@ cp_pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
pointer_int_sum() anyway. */
complete_type (TREE_TYPE (res_type));
- return pointer_int_sum (resultcode, ptrop, fold (intop));
+ return pointer_int_sum (resultcode, ptrop,
+ fold_if_not_in_template (intop));
}
/* Return a tree for the difference of pointers OP0 and OP1.
@@ -3532,7 +3547,7 @@ pointer_diff (tree op0, tree op1, tree ptrtype)
/* Do the division. */
result = build2 (EXACT_DIV_EXPR, restype, op0, cp_convert (restype, op1));
- return fold (result);
+ return fold_if_not_in_template (result);
}
/* Construct and perhaps optimize a tree representation
@@ -3782,7 +3797,10 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
if (TREE_CODE (arg) == COMPLEX_CST)
return TREE_REALPART (arg);
else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
- return fold (build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg));
+ {
+ arg = build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
+ return fold_if_not_in_template (arg);
+ }
else
return arg;
@@ -3790,7 +3808,10 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
if (TREE_CODE (arg) == COMPLEX_CST)
return TREE_IMAGPART (arg);
else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
- return fold (build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg));
+ {
+ arg = build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
+ return fold_if_not_in_template (arg);
+ }
else
return cp_convert (TREE_TYPE (arg), integer_zero_node);
@@ -4133,7 +4154,7 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
{
if (argtype == 0)
argtype = TREE_TYPE (arg);
- return fold (build1 (code, argtype, arg));
+ return fold_if_not_in_template (build1 (code, argtype, arg));
}
error ("%s", errstring);
@@ -4721,21 +4742,21 @@ build_reinterpret_cast (tree type, tree expr)
|| (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype)))
{
expr = decl_constant_value (expr);
- return fold (build1 (NOP_EXPR, type, expr));
+ return fold_if_not_in_template (build_nop (type, expr));
}
else if ((TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
|| (TYPE_PTROBV_P (type) && TYPE_PTROBV_P (intype)))
{
check_for_casting_away_constness (intype, type, "reinterpret_cast");
expr = decl_constant_value (expr);
- return fold (build1 (NOP_EXPR, type, expr));
+ return fold_if_not_in_template (build_nop (type, expr));
}
else if ((TYPE_PTRFN_P (type) && TYPE_PTROBV_P (intype))
|| (TYPE_PTRFN_P (intype) && TYPE_PTROBV_P (type)))
{
pedwarn ("ISO C++ forbids casting between pointer-to-function and pointer-to-object");
expr = decl_constant_value (expr);
- return fold (build1 (NOP_EXPR, type, expr));
+ return fold_if_not_in_template (build_nop (type, expr));
}
else
{
@@ -5382,7 +5403,8 @@ get_delta_difference (tree from, tree to, int force)
}
}
- return fold (convert_to_integer (ptrdiff_type_node, result));
+ return fold_if_not_in_template (convert_to_integer (ptrdiff_type_node,
+ result));
}
/* Return a constructor for the pointer-to-member-function TYPE using
@@ -5540,36 +5562,41 @@ expand_ptrmemfunc_cst (tree cst, tree *delta, tree *pfn)
fn; the call will do the opposite adjustment. */
tree orig_class = DECL_CONTEXT (fn);
tree binfo = binfo_or_else (orig_class, fn_class);
- *delta = fold (build2 (PLUS_EXPR, TREE_TYPE (*delta),
- *delta, BINFO_OFFSET (binfo)));
+ *delta = build2 (PLUS_EXPR, TREE_TYPE (*delta),
+ *delta, BINFO_OFFSET (binfo));
+ *delta = fold_if_not_in_template (*delta);
/* We set PFN to the vtable offset at which the function can be
found, plus one (unless ptrmemfunc_vbit_in_delta, in which
case delta is shifted left, and then incremented). */
*pfn = DECL_VINDEX (fn);
- *pfn = fold (build2 (MULT_EXPR, integer_type_node, *pfn,
- TYPE_SIZE_UNIT (vtable_entry_type)));
+ *pfn = build2 (MULT_EXPR, integer_type_node, *pfn,
+ TYPE_SIZE_UNIT (vtable_entry_type));
+ *pfn = fold_if_not_in_template (*pfn);
switch (TARGET_PTRMEMFUNC_VBIT_LOCATION)
{
case ptrmemfunc_vbit_in_pfn:
- *pfn = fold (build2 (PLUS_EXPR, integer_type_node, *pfn,
- integer_one_node));
+ *pfn = build2 (PLUS_EXPR, integer_type_node, *pfn,
+ integer_one_node);
+ *pfn = fold_if_not_in_template (*pfn);
break;
case ptrmemfunc_vbit_in_delta:
- *delta = fold (build2 (LSHIFT_EXPR, TREE_TYPE (*delta),
- *delta, integer_one_node));
- *delta = fold (build2 (PLUS_EXPR, TREE_TYPE (*delta),
- *delta, integer_one_node));
+ *delta = build2 (LSHIFT_EXPR, TREE_TYPE (*delta),
+ *delta, integer_one_node);
+ *delta = fold_if_not_in_template (*delta);
+ *delta = build2 (PLUS_EXPR, TREE_TYPE (*delta),
+ *delta, integer_one_node);
+ *delta = fold_if_not_in_template (*delta);
break;
default:
gcc_unreachable ();
}
- *pfn = fold (build1 (NOP_EXPR, TYPE_PTRMEMFUNC_FN_TYPE (type),
- *pfn));
+ *pfn = build_nop (TYPE_PTRMEMFUNC_FN_TYPE (type), *pfn);
+ *pfn = fold_if_not_in_template (*pfn);
}
}
@@ -5639,7 +5666,7 @@ dubious_conversion_warnings (tree type, tree expr,
overflow_warning (expr);
if (TREE_CONSTANT (expr))
- expr = fold (expr);
+ expr = fold_if_not_in_template (expr);
}
return expr;
}
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index 4ac9340..c86dd54 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -330,8 +330,8 @@ layout_decl (tree decl, unsigned int known_align)
}
else if (DECL_SIZE_UNIT (decl) == 0)
DECL_SIZE_UNIT (decl)
- = convert (sizetype, size_binop (CEIL_DIV_EXPR, DECL_SIZE (decl),
- bitsize_unit_node));
+ = fold_convert (sizetype, size_binop (CEIL_DIV_EXPR, DECL_SIZE (decl),
+ bitsize_unit_node));
if (code != FIELD_DECL)
/* For non-fields, update the alignment from the type. */
@@ -540,7 +540,8 @@ tree
bit_from_pos (tree offset, tree bitpos)
{
return size_binop (PLUS_EXPR, bitpos,
- size_binop (MULT_EXPR, convert (bitsizetype, offset),
+ size_binop (MULT_EXPR,
+ fold_convert (bitsizetype, offset),
bitsize_unit_node));
}
@@ -548,9 +549,9 @@ tree
byte_from_pos (tree offset, tree bitpos)
{
return size_binop (PLUS_EXPR, offset,
- convert (sizetype,
- size_binop (TRUNC_DIV_EXPR, bitpos,
- bitsize_unit_node)));
+ fold_convert (sizetype,
+ size_binop (TRUNC_DIV_EXPR, bitpos,
+ bitsize_unit_node)));
}
void
@@ -558,9 +559,9 @@ pos_from_bit (tree *poffset, tree *pbitpos, unsigned int off_align,
tree pos)
{
*poffset = size_binop (MULT_EXPR,
- convert (sizetype,
- size_binop (FLOOR_DIV_EXPR, pos,
- bitsize_int (off_align))),
+ fold_convert (sizetype,
+ size_binop (FLOOR_DIV_EXPR, pos,
+ bitsize_int (off_align))),
size_int (off_align / BITS_PER_UNIT));
*pbitpos = size_binop (FLOOR_MOD_EXPR, pos, bitsize_int (off_align));
}
@@ -580,7 +581,8 @@ normalize_offset (tree *poffset, tree *pbitpos, unsigned int off_align)
*poffset
= size_binop (PLUS_EXPR, *poffset,
- size_binop (MULT_EXPR, convert (sizetype, extra_aligns),
+ size_binop (MULT_EXPR,
+ fold_convert (sizetype, extra_aligns),
size_int (off_align / BITS_PER_UNIT)));
*pbitpos
@@ -869,9 +871,9 @@ place_field (record_layout_info rli, tree field)
/* First adjust OFFSET by the partial bits, then align. */
rli->offset
= size_binop (PLUS_EXPR, rli->offset,
- convert (sizetype,
- size_binop (CEIL_DIV_EXPR, rli->bitpos,
- bitsize_unit_node)));
+ fold_convert (sizetype,
+ size_binop (CEIL_DIV_EXPR, rli->bitpos,
+ bitsize_unit_node)));
rli->bitpos = bitsize_zero_node;
rli->offset = round_up (rli->offset, desired_align / BITS_PER_UNIT);
@@ -1147,9 +1149,9 @@ place_field (record_layout_info rli, tree field)
{
rli->offset
= size_binop (PLUS_EXPR, rli->offset,
- convert (sizetype,
- size_binop (CEIL_DIV_EXPR, rli->bitpos,
- bitsize_unit_node)));
+ fold_convert (sizetype,
+ size_binop (CEIL_DIV_EXPR, rli->bitpos,
+ bitsize_unit_node)));
rli->offset
= size_binop (PLUS_EXPR, rli->offset, DECL_SIZE_UNIT (field));
rli->bitpos = bitsize_zero_node;
@@ -1353,9 +1355,9 @@ finalize_type_size (tree type)
result will fit in sizetype. We will get more efficient code using
sizetype, so we force a conversion. */
TYPE_SIZE_UNIT (type)
- = convert (sizetype,
- size_binop (FLOOR_DIV_EXPR, TYPE_SIZE (type),
- bitsize_unit_node));
+ = fold_convert (sizetype,
+ size_binop (FLOOR_DIV_EXPR, TYPE_SIZE (type),
+ bitsize_unit_node));
if (TYPE_SIZE (type) != 0)
{
@@ -1638,10 +1640,10 @@ layout_type (tree type)
/* The initial subtraction should happen in the original type so
that (possible) negative values are handled appropriately. */
length = size_binop (PLUS_EXPR, size_one_node,
- convert (sizetype,
- fold (build2 (MINUS_EXPR,
- TREE_TYPE (lb),
- ub, lb))));
+ fold_convert (sizetype,
+ fold (build2 (MINUS_EXPR,
+ TREE_TYPE (lb),
+ ub, lb))));
/* Special handling for arrays of bits (for Chill). */
element_size = TYPE_SIZE (element);
@@ -1670,7 +1672,8 @@ layout_type (tree type)
length = size_binop (MAX_EXPR, length, size_zero_node);
TYPE_SIZE (type) = size_binop (MULT_EXPR, element_size,
- convert (bitsizetype, length));
+ fold_convert (bitsizetype,
+ length));
/* If we know the size of the element, calculate the total
size directly, rather than do some division thing below.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index eb4165c..2929381 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -10,6 +10,10 @@
2004-09-27 Mark Mitchell <mark@codesourcery.com>
+ * g++.dg/template/crash23.C: New test.
+
+2004-09-27 Mark Mitchell <mark@codesourcery.com>
+
PR c++/17585
* g++.dg/template/static8.C: New test.
diff --git a/gcc/testsuite/g++.dg/template/crash23.C b/gcc/testsuite/g++.dg/template/crash23.C
new file mode 100644
index 0000000..0c3eac1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/crash23.C
@@ -0,0 +1,9 @@
+// PR c++/17642
+
+template<int dim>
+int f(const int* const lsh, const int* const bbox, const int* const nghostzones, int d)
+{
+ for (int d=0; d<dim; ++d)
+ lsh[d] - (bbox[2*d+1] ? 0 : nghostzones[d]);
+}
+
diff --git a/gcc/tree.c b/gcc/tree.c
index 0237d07..c3912e9 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -4218,7 +4218,7 @@ build_index_type (tree maxval)
TREE_TYPE (itype) = sizetype;
TYPE_PRECISION (itype) = TYPE_PRECISION (sizetype);
TYPE_MIN_VALUE (itype) = size_zero_node;
- TYPE_MAX_VALUE (itype) = convert (sizetype, maxval);
+ TYPE_MAX_VALUE (itype) = fold_convert (sizetype, maxval);
TYPE_MODE (itype) = TYPE_MODE (sizetype);
TYPE_SIZE (itype) = TYPE_SIZE (sizetype);
TYPE_SIZE_UNIT (itype) = TYPE_SIZE_UNIT (sizetype);