Comments
Patch
@@ -6991,6 +6991,11 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t,
conversion. */
return fold (t);
r = fold_build1 (TREE_CODE (t), to, op);
+ /* Conversion of an out-of-range value has implementation-defined
+ behavior; the language considers it different from arithmetic
+ overflow, which is undefined. */
+ if (TREE_OVERFLOW_P (r) && !TREE_OVERFLOW_P (op))
+ TREE_OVERFLOW (r) = false;
}
break;
@@ -44,5 +44,4 @@ extern template struct A3<int, 510>;
// Use.
A3<int, 1111> a31;
-// FIXME should this be an error?
A3<char, 9999> a32; // { dg-warning "overflow" }
new file mode 100644
@@ -0,0 +1,8 @@
+// PR c++/47504
+// { dg-options -std=c++0x }
+
+char constexpr sub(char arg)
+{ return char(arg - char(1)); }
+
+int main()
+{ static char constexpr m = sub(-1); }
In this testcase, the fix for PR 25125 causes us to rewrite what starts as char(int(-1) - int(1)) to char((unsigned char)(-1) - (unsigned char)1) and thus char((unsigned char)254). 254 doesn't fit in char, so the result has TREE_OVERFLOW set even though the original expression was all signed and therefore shouldn't. One issue here is that the rewriting creates this situation where it didn't exist before, so I think the rewriting is wrong. But it's also the case that both C and C++ distinguish between arithmetic overflow (i.e. INT_MAX+1) which has undefined behavior, and conversion of a value that doesn't fit in the target type (i.e. char(254)), which has implementation-defined behavior. So we should allow the latter in constant expressions, even if it was wrong of the compiler to introduce it. Tested x86_64-pc-linux-gnu, applied to trunk. commit de85bc3224ebed6104076ea0e6218e202da1a64e Author: Jason Merrill <jason@redhat.com> Date: Thu Mar 17 15:33:40 2011 -0400 PR c++/47504 * semantics.c (cxx_eval_constant_expression) [NOP_EXPR]: Don't let the conversion set TREE_OVERFLOW.