[clang][CFG] Fix assertion failure in checkIncorrectLogicOperator (#142897)
`checkIncorrectLogicOperator` checks if an expression, for example `x != 0 || x != 1.0`, is always true or false by comparing the two literals `0` and `1.0`. But in case `x` is a 16-bit float, the two literals have distinct types---16-bit float and double, respectively. Directly comparing `APValue`s extracted from the two literals results in an assertion failure because of their distinct types. This commit fixes the issue by doing a conversion from the "smaller" one to the "bigger" one. The two literals must be compatible because both of them are comparing with `x`. rdar://152456316
This commit is contained in:
parent
9a894ae794
commit
b9d41328c6
@ -1261,6 +1261,28 @@ private:
|
||||
L2Result.Val.getKind() == APValue::Float) {
|
||||
llvm::APFloat L1 = L1Result.Val.getFloat();
|
||||
llvm::APFloat L2 = L2Result.Val.getFloat();
|
||||
// Note that L1 and L2 do not necessarily have the same type. For example
|
||||
// `x != 0 || x != 1.0`, if `x` is a float16, the two literals `0` and
|
||||
// `1.0` are float16 and double respectively. In this case, we should do
|
||||
// a conversion before comparing L1 and L2. Their types must be
|
||||
// compatible since they are comparing with the same DRE.
|
||||
int Order = Context->getFloatingTypeSemanticOrder(NumExpr1->getType(),
|
||||
NumExpr2->getType());
|
||||
bool Ignored = false;
|
||||
|
||||
if (Order > 0) {
|
||||
// type rank L1 > L2:
|
||||
if (llvm::APFloat::opOK !=
|
||||
L2.convert(L1.getSemantics(), llvm::APFloat::rmNearestTiesToEven,
|
||||
&Ignored))
|
||||
return {};
|
||||
} else if (Order < 0)
|
||||
// type rank L1 < L2:
|
||||
if (llvm::APFloat::opOK !=
|
||||
L1.convert(L2.getSemantics(), llvm::APFloat::rmNearestTiesToEven,
|
||||
&Ignored))
|
||||
return {};
|
||||
|
||||
llvm::APFloat MidValue = L1;
|
||||
MidValue.add(L2, llvm::APFloat::rmNearestTiesToEven);
|
||||
MidValue.divide(llvm::APFloat(MidValue.getSemantics(), "2.0"),
|
||||
|
16
clang/test/Sema/warn-unreachable_crash.cpp
Normal file
16
clang/test/Sema/warn-unreachable_crash.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
// RUN: %clang_cc1 -verify -Wunreachable-code %s
|
||||
|
||||
// Previously this test will crash
|
||||
static void test(__fp16& x) {
|
||||
if (x != 0 || x != 1.0) { // expected-note{{}} no-crash
|
||||
x = 0.9;
|
||||
} else
|
||||
x = 0.8; // expected-warning{{code will never be executed}}
|
||||
}
|
||||
|
||||
static void test2(__fp16& x) {
|
||||
if (x != 1 && x == 1.0) { // expected-note{{}} no-crash
|
||||
x = 0.9; // expected-warning{{code will never be executed}}
|
||||
} else
|
||||
x = 0.8;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user