[PATCH] Fix PR c++/4401 (take 2)
Jakub Jelinek
jakub@redhat.com
Wed Feb 20 11:27:00 GMT 2002
On Wed, Feb 20, 2002 at 03:56:13PM +0000, Jason Merrill wrote:
> > They have different warnings (e.g. the C version doesn't
> > warn about arithmetic on METHOD_TYPE or OFFSET_TYPE).
>
> Then copy that code over from the C++ version. There's no reason a
> function in c-common can't handle those types.
>
> > It might be possible to merge the rest of the functions into some helper
> > function in c-common.c, but after deleting the redundant part with fold
> > the functions minus the warnings part don't look long enough to justify
> > this IMHO.
>
> The reason to do this is to avoid bugs like this one; it looks like someone
> already fixed it in the C frontend. If the code had been shared with C++,
> it would have been fixed there for free. Even if the extra code in the if
> doesn't actually fix this bug, reducing code duplication is always
> worthwhile.
Ok, here is the rewritten patch, bootstrapped and regression tested on
i386-redhat-linux.
Ok to commit?
2002-02-20 Jakub Jelinek <jakub@redhat.com>
* c-common.c (pointer_int_sum): Moved from...
* c-typeck.c (pointer_int_sum): ...here.
* c-common.h (pointer_int_sum): Add prototype.
* typeck.c (cp_pointer_int_sum): Renamed from
pointer_int_sum, call pointer_int_sum.
* g++.dg/opt/ptrintsum1.C: New test.
--- gcc/cp/typeck.c.jj Sat Feb 16 22:48:21 2002
+++ gcc/cp/typeck.c Wed Feb 20 17:12:46 2002
@@ -45,7 +45,7 @@ Boston, MA 02111-1307, USA. */
static tree convert_for_assignment PARAMS ((tree, tree, const char *, tree,
int));
-static tree pointer_int_sum PARAMS ((enum tree_code, tree, tree));
+static tree cp_pointer_int_sum PARAMS ((enum tree_code, tree, tree));
static tree rationalize_conditional_expr PARAMS ((enum tree_code, tree));
static int comp_target_parms PARAMS ((tree, tree));
static int comp_ptr_ttypes_real PARAMS ((tree, tree, int));
@@ -3452,9 +3452,9 @@ build_binary_op (code, orig_op0, orig_op
case PLUS_EXPR:
/* Handle the pointer + int case. */
if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
- return pointer_int_sum (PLUS_EXPR, op0, op1);
+ return cp_pointer_int_sum (PLUS_EXPR, op0, op1);
else if (code1 == POINTER_TYPE && code0 == INTEGER_TYPE)
- return pointer_int_sum (PLUS_EXPR, op1, op0);
+ return cp_pointer_int_sum (PLUS_EXPR, op1, op0);
else
common = 1;
break;
@@ -3467,7 +3467,7 @@ build_binary_op (code, orig_op0, orig_op
return pointer_diff (op0, op1, common_type (type0, type1));
/* Handle pointer minus int. Just like pointer plus int. */
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
- return pointer_int_sum (MINUS_EXPR, op0, op1);
+ return cp_pointer_int_sum (MINUS_EXPR, op0, op1);
else
common = 1;
break;
@@ -4072,94 +4072,14 @@ build_binary_op (code, orig_op0, orig_op
of pointer PTROP and integer INTOP. */
static tree
-pointer_int_sum (resultcode, ptrop, intop)
+cp_pointer_int_sum (resultcode, ptrop, intop)
enum tree_code resultcode;
register tree ptrop, intop;
{
- tree size_exp;
-
- register tree result;
- register tree folded = fold (intop);
-
- /* The result is a pointer of the same type that is being added. */
-
- register tree result_type = TREE_TYPE (ptrop);
-
- if (!complete_type_or_else (result_type, ptrop))
+ if (!complete_type_or_else (TREE_TYPE (ptrop), ptrop))
return error_mark_node;
- if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)
- {
- if (pedantic || warn_pointer_arith)
- pedwarn ("ISO C++ forbids using pointer of type `void *' in pointer arithmetic");
- size_exp = integer_one_node;
- }
- else if (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE)
- {
- if (pedantic || warn_pointer_arith)
- pedwarn ("ISO C++ forbids using a pointer-to-function in pointer arithmetic");
- size_exp = integer_one_node;
- }
- else if (TREE_CODE (TREE_TYPE (result_type)) == METHOD_TYPE)
- {
- if (pedantic || warn_pointer_arith)
- pedwarn ("ISO C++ forbids using a pointer to member function in pointer arithmetic");
- size_exp = integer_one_node;
- }
- else if (TREE_CODE (TREE_TYPE (result_type)) == OFFSET_TYPE)
- {
- if (pedantic || warn_pointer_arith)
- pedwarn ("ISO C++ forbids using pointer to a member in pointer arithmetic");
- size_exp = integer_one_node;
- }
- else
- size_exp = size_in_bytes (complete_type (TREE_TYPE (result_type)));
-
- /* Needed to make OOPS V2R3 work. */
- intop = folded;
- if (integer_zerop (intop))
- return ptrop;
-
- /* If what we are about to multiply by the size of the elements
- contains a constant term, apply distributive law
- and multiply that constant term separately.
- This helps produce common subexpressions. */
-
- if ((TREE_CODE (intop) == PLUS_EXPR || TREE_CODE (intop) == MINUS_EXPR)
- && ! TREE_CONSTANT (intop)
- && TREE_CONSTANT (TREE_OPERAND (intop, 1))
- && TREE_CONSTANT (size_exp))
- {
- enum tree_code subcode = resultcode;
- if (TREE_CODE (intop) == MINUS_EXPR)
- subcode = (subcode == PLUS_EXPR ? MINUS_EXPR : PLUS_EXPR);
- ptrop = cp_build_binary_op (subcode, ptrop, TREE_OPERAND (intop, 1));
- intop = TREE_OPERAND (intop, 0);
- }
-
- /* Convert the integer argument to a type the same size as sizetype
- so the multiply won't overflow spuriously. */
-
- if (TYPE_PRECISION (TREE_TYPE (intop)) != TYPE_PRECISION (sizetype))
- intop = cp_convert (type_for_size (TYPE_PRECISION (sizetype), 0), intop);
-
- /* Replace the integer argument with a suitable product by the object size.
- Do this multiplication as signed, then convert to the appropriate
- pointer type (actually unsigned integral). */
-
- intop = cp_convert (result_type,
- cp_build_binary_op (MULT_EXPR, intop,
- cp_convert (TREE_TYPE (intop),
- size_exp)));
-
- /* Create the sum or difference. */
-
- result = build (resultcode, result_type, ptrop, intop);
-
- folded = fold (result);
- if (folded == result)
- TREE_CONSTANT (folded) = TREE_CONSTANT (ptrop) & TREE_CONSTANT (intop);
- return folded;
+ return pointer_int_sum (resultcode, ptrop, fold (intop));
}
/* Return a tree for the difference of pointers OP0 and OP1.
--- gcc/c-common.c.jj Tue Feb 19 11:13:09 2002
+++ gcc/c-common.c Wed Feb 20 17:15:21 2002
@@ -1982,6 +1982,107 @@ shorten_compare (op0_ptr, op1_ptr, resty
return 0;
}
+/* Return a tree for the sum or difference (RESULTCODE says which)
+ of pointer PTROP and integer INTOP. */
+
+tree
+pointer_int_sum (resultcode, ptrop, intop)
+ enum tree_code resultcode;
+ tree ptrop, intop;
+{
+ tree size_exp;
+
+ tree result;
+ tree folded;
+
+ /* The result is a pointer of the same type that is being added. */
+
+ tree result_type = TREE_TYPE (ptrop);
+
+ if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)
+ {
+ if (pedantic || warn_pointer_arith)
+ pedwarn ("pointer of type `void *' used in arithmetic");
+ size_exp = integer_one_node;
+ }
+ else if (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE)
+ {
+ if (pedantic || warn_pointer_arith)
+ pedwarn ("pointer to a function used in arithmetic");
+ size_exp = integer_one_node;
+ }
+ else if (TREE_CODE (TREE_TYPE (result_type)) == METHOD_TYPE)
+ {
+ if (pedantic || warn_pointer_arith)
+ pedwarn ("pointer to member function used in arithmetic");
+ size_exp = integer_one_node;
+ }
+ else if (TREE_CODE (TREE_TYPE (result_type)) == OFFSET_TYPE)
+ {
+ if (pedantic || warn_pointer_arith)
+ pedwarn ("pointer to a member used in arithmetic");
+ size_exp = integer_one_node;
+ }
+ else
+ size_exp = size_in_bytes (TREE_TYPE (result_type));
+
+ /* If what we are about to multiply by the size of the elements
+ contains a constant term, apply distributive law
+ and multiply that constant term separately.
+ This helps produce common subexpressions. */
+
+ if ((TREE_CODE (intop) == PLUS_EXPR || TREE_CODE (intop) == MINUS_EXPR)
+ && ! TREE_CONSTANT (intop)
+ && TREE_CONSTANT (TREE_OPERAND (intop, 1))
+ && TREE_CONSTANT (size_exp)
+ /* If the constant comes from pointer subtraction,
+ skip this optimization--it would cause an error. */
+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (intop, 0))) == INTEGER_TYPE
+ /* If the constant is unsigned, and smaller than the pointer size,
+ then we must skip this optimization. This is because it could cause
+ an overflow error if the constant is negative but INTOP is not. */
+ && (! TREE_UNSIGNED (TREE_TYPE (intop))
+ || (TYPE_PRECISION (TREE_TYPE (intop))
+ == TYPE_PRECISION (TREE_TYPE (ptrop)))))
+ {
+ enum tree_code subcode = resultcode;
+ tree int_type = TREE_TYPE (intop);
+ if (TREE_CODE (intop) == MINUS_EXPR)
+ subcode = (subcode == PLUS_EXPR ? MINUS_EXPR : PLUS_EXPR);
+ /* Convert both subexpression types to the type of intop,
+ because weird cases involving pointer arithmetic
+ can result in a sum or difference with different type args. */
+ ptrop = build_binary_op (subcode, ptrop,
+ convert (int_type, TREE_OPERAND (intop, 1)), 1);
+ intop = convert (int_type, TREE_OPERAND (intop, 0));
+ }
+
+ /* Convert the integer argument to a type the same size as sizetype
+ so the multiply won't overflow spuriously. */
+
+ if (TYPE_PRECISION (TREE_TYPE (intop)) != TYPE_PRECISION (sizetype)
+ || TREE_UNSIGNED (TREE_TYPE (intop)) != TREE_UNSIGNED (sizetype))
+ intop = convert (type_for_size (TYPE_PRECISION (sizetype),
+ TREE_UNSIGNED (sizetype)), intop);
+
+ /* Replace the integer argument with a suitable product by the object size.
+ Do this multiplication as signed, then convert to the appropriate
+ pointer type (actually unsigned integral). */
+
+ intop = convert (result_type,
+ build_binary_op (MULT_EXPR, intop,
+ convert (TREE_TYPE (intop), size_exp), 1));
+
+ /* Create the sum or difference. */
+
+ result = build (resultcode, result_type, ptrop, intop);
+
+ folded = fold (result);
+ if (folded == result)
+ TREE_CONSTANT (folded) = TREE_CONSTANT (ptrop) & TREE_CONSTANT (intop);
+ return folded;
+}
+
/* Prepare expr to be an argument of a TRUTH_NOT_EXPR,
or validate its data type for an `if' or `while' statement or ?..: exp.
--- gcc/c-typeck.c.jj Sat Feb 16 22:48:00 2002
+++ gcc/c-typeck.c Wed Feb 20 16:53:35 2002
@@ -58,7 +58,6 @@ static tree decl_constant_value_for_brok
static tree default_function_array_conversion PARAMS ((tree));
static tree lookup_field PARAMS ((tree, tree));
static tree convert_arguments PARAMS ((tree, tree, tree, tree));
-static tree pointer_int_sum PARAMS ((enum tree_code, tree, tree));
static tree pointer_diff PARAMS ((tree, tree));
static tree unary_complex_lvalue PARAMS ((enum tree_code, tree, int));
static void pedantic_lvalue_warning PARAMS ((enum tree_code));
@@ -2637,95 +2636,6 @@ build_binary_op (code, orig_op0, orig_op
}
}
-/* Return a tree for the sum or difference (RESULTCODE says which)
- of pointer PTROP and integer INTOP. */
-
-static tree
-pointer_int_sum (resultcode, ptrop, intop)
- enum tree_code resultcode;
- tree ptrop, intop;
-{
- tree size_exp;
-
- tree result;
- tree folded;
-
- /* The result is a pointer of the same type that is being added. */
-
- tree result_type = TREE_TYPE (ptrop);
-
- if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)
- {
- if (pedantic || warn_pointer_arith)
- pedwarn ("pointer of type `void *' used in arithmetic");
- size_exp = integer_one_node;
- }
- else if (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE)
- {
- if (pedantic || warn_pointer_arith)
- pedwarn ("pointer to a function used in arithmetic");
- size_exp = integer_one_node;
- }
- else
- size_exp = c_size_in_bytes (TREE_TYPE (result_type));
-
- /* If what we are about to multiply by the size of the elements
- contains a constant term, apply distributive law
- and multiply that constant term separately.
- This helps produce common subexpressions. */
-
- if ((TREE_CODE (intop) == PLUS_EXPR || TREE_CODE (intop) == MINUS_EXPR)
- && ! TREE_CONSTANT (intop)
- && TREE_CONSTANT (TREE_OPERAND (intop, 1))
- && TREE_CONSTANT (size_exp)
- /* If the constant comes from pointer subtraction,
- skip this optimization--it would cause an error. */
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (intop, 0))) == INTEGER_TYPE
- /* If the constant is unsigned, and smaller than the pointer size,
- then we must skip this optimization. This is because it could cause
- an overflow error if the constant is negative but INTOP is not. */
- && (! TREE_UNSIGNED (TREE_TYPE (intop))
- || (TYPE_PRECISION (TREE_TYPE (intop))
- == TYPE_PRECISION (TREE_TYPE (ptrop)))))
- {
- enum tree_code subcode = resultcode;
- tree int_type = TREE_TYPE (intop);
- if (TREE_CODE (intop) == MINUS_EXPR)
- subcode = (subcode == PLUS_EXPR ? MINUS_EXPR : PLUS_EXPR);
- /* Convert both subexpression types to the type of intop,
- because weird cases involving pointer arithmetic
- can result in a sum or difference with different type args. */
- ptrop = build_binary_op (subcode, ptrop,
- convert (int_type, TREE_OPERAND (intop, 1)), 1);
- intop = convert (int_type, TREE_OPERAND (intop, 0));
- }
-
- /* Convert the integer argument to a type the same size as sizetype
- so the multiply won't overflow spuriously. */
-
- if (TYPE_PRECISION (TREE_TYPE (intop)) != TYPE_PRECISION (sizetype)
- || TREE_UNSIGNED (TREE_TYPE (intop)) != TREE_UNSIGNED (sizetype))
- intop = convert (type_for_size (TYPE_PRECISION (sizetype),
- TREE_UNSIGNED (sizetype)), intop);
-
- /* Replace the integer argument with a suitable product by the object size.
- Do this multiplication as signed, then convert to the appropriate
- pointer type (actually unsigned integral). */
-
- intop = convert (result_type,
- build_binary_op (MULT_EXPR, intop,
- convert (TREE_TYPE (intop), size_exp), 1));
-
- /* Create the sum or difference. */
-
- result = build (resultcode, result_type, ptrop, intop);
-
- folded = fold (result);
- if (folded == result)
- TREE_CONSTANT (folded) = TREE_CONSTANT (ptrop) & TREE_CONSTANT (intop);
- return folded;
-}
-
/* Return a tree for the difference of pointers OP0 and OP1.
The resulting tree has type int. */
--- gcc/c-common.h.jj Mon Feb 4 15:25:53 2002
+++ gcc/c-common.h Wed Feb 20 17:16:23 2002
@@ -538,6 +538,7 @@ extern char *get_directive_line PARAMS
and, if so, perhaps change them both back to their original type. */
extern tree shorten_compare PARAMS ((tree *, tree *, tree *, enum tree_code *));
+extern tree pointer_int_sum PARAMS ((enum tree_code, tree, tree));
extern unsigned int min_precision PARAMS ((tree, int));
/* Add qualifiers to a type, in the fashion for C. */
--- gcc/testsuite/g++.dg/opt/ptrintsum1.C.jj Wed Feb 20 13:32:15 2002
+++ gcc/testsuite/g++.dg/opt/ptrintsum1.C Wed Feb 20 13:32:12 2002
@@ -0,0 +1,29 @@
+// PR c++/4401
+// This testcase was miscompiled on 64-bit platforms, resulting to
+// operating on a[0x100000000] instead of a[0].
+// { dg-do run }
+// { dg-options "-O2" }
+
+char *a;
+char b[] = "AAAA";
+
+extern "C" void abort (void);
+extern "C" void exit (int);
+
+void foo (void)
+{
+ unsigned int i, j;
+
+ i = 2;
+ j = 3;
+ a[i + 1 - j] += i;
+}
+
+int main (void)
+{
+ a = b;
+ foo ();
+ if (b[0] != 'A' + 2)
+ abort ();
+ exit (0);
+}
Jakub
More information about the Gcc-patches
mailing list