mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-13 19:24:21 +00:00
[clang][Interp] Check floating results for NaNs
Differential Revision: https://reviews.llvm.org/D156506
This commit is contained in:
parent
53602e6193
commit
4b5fe9c42d
@ -495,13 +495,25 @@ bool CheckPotentialReinterpretCast(InterpState &S, CodePtr OpPC,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CheckFloatResult(InterpState &S, CodePtr OpPC, APFloat::opStatus Status) {
|
||||
bool CheckFloatResult(InterpState &S, CodePtr OpPC, const Floating &Result,
|
||||
APFloat::opStatus Status) {
|
||||
const SourceInfo &E = S.Current->getSource(OpPC);
|
||||
|
||||
// [expr.pre]p4:
|
||||
// If during the evaluation of an expression, the result is not
|
||||
// mathematically defined [...], the behavior is undefined.
|
||||
// FIXME: C++ rules require us to not conform to IEEE 754 here.
|
||||
if (Result.isNan()) {
|
||||
S.CCEDiag(E, diag::note_constexpr_float_arithmetic)
|
||||
<< /*NaN=*/true << S.Current->getRange(OpPC);
|
||||
return S.noteUndefinedBehavior();
|
||||
}
|
||||
|
||||
// In a constant context, assume that any dynamic rounding mode or FP
|
||||
// exception state matches the default floating-point environment.
|
||||
if (S.inConstantContext())
|
||||
return true;
|
||||
|
||||
const SourceInfo &E = S.Current->getSource(OpPC);
|
||||
FPOptions FPO = E.asExpr()->getFPFeaturesInEffect(S.Ctx.getLangOpts());
|
||||
|
||||
if ((Status & APFloat::opInexact) &&
|
||||
|
@ -172,7 +172,8 @@ bool CheckDivRem(InterpState &S, CodePtr OpPC, const T &LHS, const T &RHS) {
|
||||
|
||||
/// Checks if the result of a floating-point operation is valid
|
||||
/// in the current context.
|
||||
bool CheckFloatResult(InterpState &S, CodePtr OpPC, APFloat::opStatus Status);
|
||||
bool CheckFloatResult(InterpState &S, CodePtr OpPC, const Floating &Result,
|
||||
APFloat::opStatus Status);
|
||||
|
||||
/// Interpreter entry point.
|
||||
bool Interpret(InterpState &S, APValue &Result);
|
||||
@ -304,7 +305,7 @@ inline bool Addf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
|
||||
Floating Result;
|
||||
auto Status = Floating::add(LHS, RHS, RM, &Result);
|
||||
S.Stk.push<Floating>(Result);
|
||||
return CheckFloatResult(S, OpPC, Status);
|
||||
return CheckFloatResult(S, OpPC, Result, Status);
|
||||
}
|
||||
|
||||
template <PrimType Name, class T = typename PrimConv<Name>::T>
|
||||
@ -322,7 +323,7 @@ inline bool Subf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
|
||||
Floating Result;
|
||||
auto Status = Floating::sub(LHS, RHS, RM, &Result);
|
||||
S.Stk.push<Floating>(Result);
|
||||
return CheckFloatResult(S, OpPC, Status);
|
||||
return CheckFloatResult(S, OpPC, Result, Status);
|
||||
}
|
||||
|
||||
template <PrimType Name, class T = typename PrimConv<Name>::T>
|
||||
@ -340,7 +341,7 @@ inline bool Mulf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
|
||||
Floating Result;
|
||||
auto Status = Floating::mul(LHS, RHS, RM, &Result);
|
||||
S.Stk.push<Floating>(Result);
|
||||
return CheckFloatResult(S, OpPC, Status);
|
||||
return CheckFloatResult(S, OpPC, Result, Status);
|
||||
}
|
||||
/// 1) Pops the RHS from the stack.
|
||||
/// 2) Pops the LHS from the stack.
|
||||
@ -443,7 +444,7 @@ inline bool Divf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
|
||||
Floating Result;
|
||||
auto Status = Floating::div(LHS, RHS, RM, &Result);
|
||||
S.Stk.push<Floating>(Result);
|
||||
return CheckFloatResult(S, OpPC, Status);
|
||||
return CheckFloatResult(S, OpPC, Result, Status);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -622,7 +623,7 @@ bool IncDecFloatHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
|
||||
|
||||
Ptr.deref<Floating>() = Result;
|
||||
|
||||
return CheckFloatResult(S, OpPC, Status);
|
||||
return CheckFloatResult(S, OpPC, Result, Status);
|
||||
}
|
||||
|
||||
inline bool Incf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
|
||||
@ -1525,7 +1526,7 @@ bool CastIntegralFloating(InterpState &S, CodePtr OpPC,
|
||||
auto Status = Floating::fromIntegral(FromAP, *Sem, RM, Result);
|
||||
S.Stk.push<Floating>(Result);
|
||||
|
||||
return CheckFloatResult(S, OpPC, Status);
|
||||
return CheckFloatResult(S, OpPC, Result, Status);
|
||||
}
|
||||
|
||||
template <PrimType Name, class T = typename PrimConv<Name>::T>
|
||||
@ -1550,7 +1551,7 @@ bool CastFloatingIntegral(InterpState &S, CodePtr OpPC) {
|
||||
}
|
||||
|
||||
S.Stk.push<T>(T(Result));
|
||||
return CheckFloatResult(S, OpPC, Status);
|
||||
return CheckFloatResult(S, OpPC, F, Status);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -202,3 +202,18 @@ namespace Compare {
|
||||
static_assert(!(inf < nan), "");
|
||||
static_assert(!(inf > nan), "");
|
||||
}
|
||||
|
||||
namespace nan {
|
||||
constexpr double nan = __builtin_nan("");
|
||||
static_assert(nan);
|
||||
|
||||
constexpr double D1 = 1 + nan; // ref-error {{must be initialized by a constant expression}} \
|
||||
// ref-note {{produces a NaN}} \
|
||||
// expected-error {{must be initialized by a constant expression}} \
|
||||
// expected-note {{produces a NaN}}
|
||||
|
||||
constexpr double D2 = __builtin_inf() / __builtin_inf(); // ref-error {{must be initialized by a constant expression}} \
|
||||
// ref-note {{produces a NaN}} \
|
||||
// expected-error {{must be initialized by a constant expression}} \
|
||||
// expected-note {{produces a NaN}}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user