+2004-09-21 Roger Sayle <roger@eyesopen.com>
+
+ PR c++/7503
+ * tree.c (lvalue_p_1): Disallow MIN_EXPR and MAX_EXPR as lvalues
+ if either operand has side-effects.
+ * typeck.c (rationalize_conditional_expr): Assert that neither
+ operand of MIN_EXPR or MAX_EXPR has side-effects.
+ (build_modify_expr): Add support for MIN_EXPR and MAX_EXPR.
+ Check that the "lhs" is a valid lvalue, i.e. that neither operand
+ of a MIN_EXPR or MAX_EXPR has a side-effect.
+
2004-09-21 Nathan Sidwell <nathan@codesourcery.com>
* cp-tree.h (struct lang_type_header): Remove
gcc_unreachable ();
case MAX_EXPR:
case MIN_EXPR:
+ /* Disallow <? and >? as lvalues if either argument side-effects. */
+ if (TREE_SIDE_EFFECTS (TREE_OPERAND (ref, 0))
+ || TREE_SIDE_EFFECTS (TREE_OPERAND (ref, 1)))
+ return clk_none;
op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
treat_class_rvalues_as_lvalues);
op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1),
are equal, so we know what conditional expression this used to be. */
if (TREE_CODE (t) == MIN_EXPR || TREE_CODE (t) == MAX_EXPR)
{
+ /* The following code is incorrect if either operand side-effects. */
+ gcc_assert (!TREE_SIDE_EFFECTS (TREE_OPERAND (t, 0))
+ && !TREE_SIDE_EFFECTS (TREE_OPERAND (t, 1)));
return
build_conditional_expr (build_x_binary_op ((TREE_CODE (t) == MIN_EXPR
? LE_EXPR : GE_EXPR),
return error_mark_node;
return build2 (COMPOUND_EXPR, lhstype, lhs, newrhs);
+ case MIN_EXPR:
+ case MAX_EXPR:
+ /* MIN_EXPR and MAX_EXPR are currently only permitted as lvalues,
+ when neither operand has side-effects. */
+ if (!lvalue_or_else (lhs, "assignment"))
+ return error_mark_node;
+
+ gcc_assert (!TREE_SIDE_EFFECTS (TREE_OPERAND (lhs, 0))
+ && !TREE_SIDE_EFFECTS (TREE_OPERAND (lhs, 1)));
+
+ lhs = build3 (COND_EXPR, TREE_TYPE (lhs),
+ build2 (TREE_CODE (lhs) == MIN_EXPR ? LE_EXPR : GE_EXPR,
+ boolean_type_node,
+ TREE_OPERAND (lhs, 0),
+ TREE_OPERAND (lhs, 1)),
+ TREE_OPERAND (lhs, 0),
+ TREE_OPERAND (lhs, 1));
+ /* Fall through. */
+
/* Handle (a ? b : c) used as an "lvalue". */
case COND_EXPR:
{
+2004-09-21 Roger Sayle <roger@eyesopen.com>
+
+ PR c++/7503
+ * g++.dg/opt/pr7503-1.C: New testcase for COND_EXPR lvalues.
+ * g++.dg/opt/pr7503-2.C: New testcase for <? and >? lvalues.
+ * g++.dg/opt/pr7503-3.C: New testcase for invalid <? lvalue errors.
+ * g++.dg/opt/pr7503-4.C: New testcase for <?= and >?= assignments.
+ * g++.dg/opt/pr7503-5.C: New testcase for side-effects with <?=.
+
2004-09-21 Bud Davis <bdavis9659@comcast.net>
PR fortran/17286
--- /dev/null
+// PR c++/7503
+// { dg-do run }
+// { dg-options "-O2" }
+
+extern "C" void abort();
+
+void test1a()
+{
+ int A = 4;
+ int B = 4;
+
+ (A > B ? A : B) = 1;
+ if (A != 4 || B != 1)
+ abort ();
+}
+
+void test1b()
+{
+ int A = 3;
+ int B = 5;
+
+ (A > B ? A : B) = 1;
+ if (A != 3 || B != 1)
+ abort ();
+}
+
+void test1c()
+{
+ int A = 5;
+ int B = 3;
+
+ (A > B ? A : B) = 1;
+ if (A != 1 || B != 3)
+ abort ();
+}
+
+void test2a()
+{
+ int A = 4;
+ int B = 4;
+
+ (A >= B ? A : B) = 1;
+ if (A != 1 || B != 4)
+ abort ();
+}
+
+void test2b()
+{
+ int A = 3;
+ int B = 5;
+
+ (A >= B ? A : B) = 1;
+ if (A != 3 || B != 1)
+ abort ();
+}
+
+void test2c()
+{
+ int A = 5;
+ int B = 3;
+
+ (A >= B ? A : B) = 1;
+ if (A != 1 || B != 3)
+ abort ();
+}
+
+void test3a()
+{
+ int A = 4;
+ int B = 4;
+
+ (A < B ? A : B) = 1;
+ if (A != 4 || B != 1)
+ abort ();
+}
+
+void test3b()
+{
+ int A = 3;
+ int B = 5;
+
+ (A < B ? A : B) = 1;
+ if (A != 1 || B != 5)
+ abort ();
+}
+
+void test3c()
+{
+ int A = 5;
+ int B = 3;
+
+ (A < B ? A : B) = 1;
+ if (A != 5 || B != 1)
+ abort ();
+}
+
+void test4a()
+{
+ int A = 4;
+ int B = 4;
+
+ (A <= B ? A : B) = 1;
+ if (A != 1 || B != 4)
+ abort ();
+}
+
+void test4b()
+{
+ int A = 3;
+ int B = 5;
+
+ (A <= B ? A : B) = 1;
+ if (A != 1 || B != 5)
+ abort ();
+}
+
+void test4c()
+{
+ int A = 5;
+ int B = 3;
+
+ (A <= B ? A : B) = 1;
+ if (A != 5 || B != 1)
+ abort ();
+}
+
+
+int main()
+{
+ test1a();
+ test1b();
+ test1c();
+
+ test2a();
+ test2b();
+ test2c();
+
+ test3a();
+ test3b();
+ test3c();
+
+ test4a();
+ test4b();
+ test4c();
+
+ return 0;
+}
+
--- /dev/null
+// PR c++/7503
+// { dg-do run }
+// { dg-options "-O2" }
+
+extern "C" void abort();
+
+void test1a()
+{
+ int A = 4;
+ int B = 4;
+
+ (A >? B) = 1;
+ if (A != 1 || B != 4)
+ abort ();
+}
+
+void test1b()
+{
+ int A = 3;
+ int B = 5;
+
+ (A >? B) = 1;
+ if (A != 3 || B != 1)
+ abort ();
+}
+
+void test1c()
+{
+ int A = 5;
+ int B = 3;
+
+ (A >? B) = 1;
+ if (A != 1 || B != 3)
+ abort ();
+}
+
+
+void test2a()
+{
+ int A = 4;
+ int B = 4;
+
+ (A <? B) = 1;
+ if (A != 1 || B != 4)
+ abort ();
+}
+
+void test2b()
+{
+ int A = 3;
+ int B = 5;
+
+ (A <? B) = 1;
+ if (A != 1 || B != 5)
+ abort ();
+}
+
+void test2c()
+{
+ int A = 5;
+ int B = 3;
+
+ (A <? B) = 1;
+ if (A != 5 || B != 1)
+ abort ();
+}
+
+
+int main()
+{
+ test1a();
+ test1b();
+ test1c();
+ test2a();
+ test2b();
+ test2c();
+ return 0;
+}
+
--- /dev/null
+// PR c++/7503
+// { dg-do compile }
+// { dg-options "-O2" }
+
+extern int A, B;
+
+void test1()
+{
+ (A++ <? B) = 0; // { dg-error "non-lvalue in assignment" }
+}
+
+void test2()
+{
+ (A <? B++) = 0; // { dg-error "non-lvalue in assignment" }
+}
+
+void test3()
+{
+ (A++ >? B) = 0; // { dg-error "non-lvalue in assignment" }
+}
+
+void test4()
+{
+ (A >? B++) = 0; // { dg-error "non-lvalue in assignment" }
+}
+
--- /dev/null
+// PR c++/7503
+// { dg-do run }
+// { dg-options "-O2" }
+
+extern "C" void abort();
+
+void test1a()
+{
+ int A = 4;
+ int B = 4;
+
+ A >?= B;
+ if (A != 4 || B != 4)
+ abort ();
+}
+
+void test1b()
+{
+ int A = 3;
+ int B = 5;
+
+ A >?= B;
+ if (A != 5 || B != 5)
+ abort ();
+}
+
+void test1c()
+{
+ int A = 5;
+ int B = 3;
+
+ A >?= B;
+ if (A != 5 || B != 3)
+ abort ();
+}
+
+
+void test2a()
+{
+ int A = 4;
+ int B = 4;
+
+ A <?= B;
+ if (A != 4 || B != 4)
+ abort ();
+}
+
+void test2b()
+{
+ int A = 3;
+ int B = 5;
+
+ A <?= B;
+ if (A != 3 || B != 5)
+ abort ();
+}
+
+void test2c()
+{
+ int A = 5;
+ int B = 3;
+
+ A <?= B;
+ if (A != 3 || B != 3)
+ abort ();
+}
+
+
+int main()
+{
+ test1a();
+ test1b();
+ test1c();
+
+ test2a();
+ test2b();
+ test2c();
+
+ return 0;
+}
+
--- /dev/null
+// PR c++/7503
+// { dg-do run }
+// { dg-options "-O2" }
+
+extern "C" void abort();
+
+void test1a()
+{
+ int A = 4;
+ int B = 4;
+
+ A >?= B++;
+ if (A != 4 || B != 5)
+ abort ();
+}
+
+void test1b()
+{
+ int A = 3;
+ int B = 5;
+
+ A >?= B++;
+ if (A != 5 || B != 6)
+ abort ();
+}
+
+void test1c()
+{
+ int A = 5;
+ int B = 3;
+
+ A >?= B++;
+ if (A != 5 || B != 4)
+ abort ();
+}
+
+
+void test2a()
+{
+ int A = 4;
+ int B = 4;
+
+ A <?= B++;
+ if (A != 4 || B != 5)
+ abort ();
+}
+
+void test2b()
+{
+ int A = 3;
+ int B = 5;
+
+ A <?= B++;
+ if (A != 3 || B != 6)
+ abort ();
+}
+
+void test2c()
+{
+ int A = 5;
+ int B = 3;
+
+ A <?= B++;
+ if (A != 3 || B != 4)
+ abort ();
+}
+
+
+int main()
+{
+ test1a();
+ test1b();
+ test1c();
+
+ test2a();
+ test2b();
+ test2c();
+
+ return 0;
+}
+