]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR middle-end/19650 (miscompiling of array acess of (int)(a==2))
authorDale Johannesen <dalej@gcc.gnu.org>
Mon, 31 Jan 2005 18:00:52 +0000 (18:00 +0000)
committerDale Johannesen <dalej@gcc.gnu.org>
Mon, 31 Jan 2005 18:00:52 +0000 (18:00 +0000)
2005-01-31  Roger Sayle  <roger@eyesopen.com>
    Dale Johannesen  <dalej@apple.com>

PR middle-end/19650
* fold-const.c (fold_binary_op_with_conditional_arg):
Make types match original operands, before STRIP_NOPS.

From-SVN: r94485

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/opt/pr19650.C [new file with mode: 0644]

index 2a39cfd1727a9eae72f88943014b08ed3d22dd73..132be3f9e6805a186bfcaad75db9b746967affa0 100644 (file)
@@ -1,3 +1,10 @@
+2005-01-31  Roger Sayle  <roger@eyesopen.com>
+           Dale Johannesen  <dalej@apple.com>
+
+       PR middle-end/19650
+       * fold-const.c (fold_binary_op_with_conditional_arg):
+       Make types match original operands, before STRIP_NOPS.
+
 2005-01-31  Alan Modra  <amodra@bigpond.net.au>
 
        * config/rs6000/linux-unwind.h (struct gcc_vregs): New.
index 5d6e713ff53119468885d99926f21cc165b8f546..13c57e0ba6aea8a3be4e336fba0f93f9fae697c9 100644 (file)
@@ -121,8 +121,8 @@ static tree optimize_minmax_comparison (tree);
 static tree extract_muldiv (tree, tree, enum tree_code, tree);
 static tree extract_muldiv_1 (tree, tree, enum tree_code, tree);
 static int multiple_of_p (tree, tree, tree);
-static tree fold_binary_op_with_conditional_arg (enum tree_code, tree, tree,
-                                                tree, int);
+static tree fold_binary_op_with_conditional_arg (tree, enum tree_code, 
+                                                tree, tree, int);
 static bool fold_real_zero_addition_p (tree, tree, int);
 static tree fold_mathfn_compare (enum built_in_function, enum tree_code,
                                 tree, tree, tree);
@@ -5435,9 +5435,14 @@ extract_array_ref (tree expr, tree *base, tree *offset)
    possible.  */
 
 static tree
-fold_binary_op_with_conditional_arg (enum tree_code code, tree type,
-                                    tree cond, tree arg, int cond_first_p)
+fold_binary_op_with_conditional_arg (tree t, enum tree_code code, tree cond,
+                                    tree arg, int cond_first_p)
 {
+  const tree type = TREE_TYPE (t);
+  tree cond_type = cond_first_p ? TREE_TYPE (TREE_OPERAND (t, 0)) 
+                               : TREE_TYPE (TREE_OPERAND (t, 1));
+  tree arg_type = cond_first_p ? TREE_TYPE (TREE_OPERAND (t, 1)) 
+                              : TREE_TYPE (TREE_OPERAND (t, 0));
   tree test, true_value, false_value;
   tree lhs = NULL_TREE;
   tree rhs = NULL_TREE;
@@ -5469,12 +5474,19 @@ fold_binary_op_with_conditional_arg (enum tree_code code, tree type,
       false_value = constant_boolean_node (false, testtype);
     }
 
+  arg = fold_convert (arg_type, arg);
   if (lhs == 0)
-    lhs = fold (cond_first_p ? build2 (code, type, true_value, arg)
+    {
+      true_value = fold_convert (cond_type, true_value);
+      lhs = fold (cond_first_p ? build2 (code, type, true_value, arg)
                             : build2 (code, type, arg, true_value));
+    }
   if (rhs == 0)
-    rhs = fold (cond_first_p ? build2 (code, type, false_value, arg)
+    {
+      false_value = fold_convert (cond_type, false_value);
+      rhs = fold (cond_first_p ? build2 (code, type, false_value, arg)
                             : build2 (code, type, arg, false_value));
+    }
 
   test = fold (build3 (COND_EXPR, type, test, lhs, rhs));
   return fold_convert (type, test);
@@ -6516,7 +6528,7 @@ fold (tree expr)
 
       if (TREE_CODE (arg0) == COND_EXPR || COMPARISON_CLASS_P (arg0))
        {
-         tem = fold_binary_op_with_conditional_arg (code, type, arg0, arg1,
+         tem = fold_binary_op_with_conditional_arg (t, code, arg0, arg1, 
                                                     /*cond_first_p=*/1);
          if (tem != NULL_TREE)
            return tem;
@@ -6524,8 +6536,8 @@ fold (tree expr)
 
       if (TREE_CODE (arg1) == COND_EXPR || COMPARISON_CLASS_P (arg1))
        {
-         tem = fold_binary_op_with_conditional_arg (code, type, arg1, arg0,
-                                                    /*cond_first_p=*/0);
+         tem = fold_binary_op_with_conditional_arg (t, code, arg1, arg0, 
+                                                    /*cond_first_p=*/0);
          if (tem != NULL_TREE)
            return tem;
        }
index 648c97b6a01047b2848ce6ef77d1fc5e5cf50837..cc1f201465d5badc0949896d4747aba11404980c 100644 (file)
@@ -1,3 +1,7 @@
+2005-01-31  Dale Johannesen  <dalej@apple.com>
+
+       * g++.dg/opt/pr19650.C:  New test.
+
 2005-01-31  Richard Henderson  <rth@redhat.com>
 
        * gcc.c-torture/execute/ieee/copysign1.c: Special case sizeof
diff --git a/gcc/testsuite/g++.dg/opt/pr19650.C b/gcc/testsuite/g++.dg/opt/pr19650.C
new file mode 100644 (file)
index 0000000..3a8d4b8
--- /dev/null
@@ -0,0 +1,71 @@
+// { dg-options "-O1" }
+// { dg-do "run" }
+// Tests the fold bug described in PR 19650.
+#include <stdio.h>
+#include <stdlib.h>
+#define test(a) ((a) ? 1 : 0)
+
+typedef int (*arg_cmp_func)();
+
+class Item_func 
+{
+public:
+    enum Functype { UNKNOWN_FUNC, EQ_FUNC, EQUAL_FUNC };
+    virtual enum Functype functype() const { return UNKNOWN_FUNC; }
+};
+
+class Item_bool_func2 : public Item_func
+{
+public:
+    virtual enum Functype functype() const { return EQUAL_FUNC; }
+};
+
+class Arg_comparator 
+{
+public:
+    Item_bool_func2 *owner;
+    arg_cmp_func func;
+    static arg_cmp_func comparator_matrix[4][2];
+
+    int Arg_comparator::set_compare_func(Item_bool_func2 *item, int type)
+    {
+        owner = item;
+
+        /****************** problematic line is here ************************/
+
+        func = comparator_matrix[type][test(owner->functype() == Item_func::EQUAL_FUNC)];
+        return 0;
+    }
+};
+
+int compare_string() { return 0; }
+int compare_e_string() { return 0; }
+int compare_real() { return 0; }
+int compare_e_real() { return 0; }
+int compare_int_signed() { return 0; }
+int compare_e_int() { return 0; }
+int compare_row() { return 0; }
+int compare_e_row() { return 0; }
+
+arg_cmp_func Arg_comparator::comparator_matrix[4][2] =
+    {{&compare_string,     &compare_e_string},
+     {&compare_real,       &compare_e_real},
+     {&compare_int_signed, &compare_e_int},
+     {&compare_row,        &compare_e_row}};
+
+void myfunc (const char*p, arg_cmp_func f1, arg_cmp_func f2) __attribute__((noinline));
+void myfunc (const char*p, arg_cmp_func f1, arg_cmp_func f2)
+{
+    if (f1!=f2)
+      abort ();
+}
+
+int main()
+{
+    Arg_comparator cmp;
+    Item_bool_func2 equal_func;
+
+    cmp.set_compare_func(&equal_func, 0);
+    myfunc("cmp.func is %p (expected %p)\n", cmp.func, &compare_e_string);
+}
+