From a5acace6e3574d196f16fd9fb8a2233ee2de38a1 Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Thu, 30 May 2019 21:35:32 +0000 Subject: [PATCH] Fix constexpr __builtin_*_overflow issue when unsigned->signed operand. As reported here https://bugs.llvm.org/show_bug.cgi?id=42000, it was possible to get the constexpr version of __builtin_*_overflow to give the wrong answer. This was because when extending the operands to fit the largest type (so that the math could be done), the decision on whether to sign/zero extend the operands was based on the result signedness, not on the operands signedness. In the reported case, (unsigned char)255 - (int)100 needed to have each extended to the int in order to do the math. However, when extending the first operand to 'int', we incorrectly sign extended it instead of zero extending. Thus, the result didnt fit back into the unsigned char. The fix for this was simply to choose zero/sign extension based on the sign of the operand itself. Differential Revision: https://reviews.llvm.org/D62665 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@362157 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ExprConstant.cpp | 6 ++---- test/SemaCXX/builtins-overflow.cpp | 3 +++ 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index df9b3067b8..57d428282c 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -9454,10 +9454,8 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, if (IsSigned && !AllSigned) ++MaxBits; - LHS = APSInt(IsSigned ? LHS.sextOrSelf(MaxBits) : LHS.zextOrSelf(MaxBits), - !IsSigned); - RHS = APSInt(IsSigned ? RHS.sextOrSelf(MaxBits) : RHS.zextOrSelf(MaxBits), - !IsSigned); + LHS = APSInt(LHS.extOrTrunc(MaxBits), !IsSigned); + RHS = APSInt(RHS.extOrTrunc(MaxBits), !IsSigned); Result = APSInt(MaxBits, !IsSigned); } diff --git a/test/SemaCXX/builtins-overflow.cpp b/test/SemaCXX/builtins-overflow.cpp index 65733c0c15..c84b7da00b 100644 --- a/test/SemaCXX/builtins-overflow.cpp +++ b/test/SemaCXX/builtins-overflow.cpp @@ -2,6 +2,7 @@ // expected-no-diagnostics #include +#include int a() { const int x = 3; @@ -50,6 +51,7 @@ constexpr Result sub(LHS &&lhs, RHS &&rhs) { static_assert(sub(static_cast(0),static_cast(1)) == Result{true, UCHAR_MAX}); static_assert(sub(static_cast(0),static_cast(1)) == Result{false, -1}); static_assert(sub(static_cast(0),static_cast(1)) == Result{true, USHRT_MAX}); +static_assert(sub(static_cast(255),static_cast(100)) == Result{false, 155}); static_assert(sub(17,22) == Result{false, -5}); static_assert(sub(INT_MAX - 22, -23) == Result{true, INT_MIN}); @@ -91,3 +93,4 @@ constexpr Result smul(int lhs, int rhs) { static_assert(smul(17,22) == Result{false, 374}); static_assert(smul(INT_MAX / 22, 23) == Result{true, -2049870757}); static_assert(smul(INT_MIN / 22, -23) == Result{true, -2049870757}); + -- 2.40.0