Skip to content

Commit b9d4132

Browse files
authored
[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
1 parent 9a894ae commit b9d4132

File tree

2 files changed

+38
-0
lines changed

2 files changed

+38
-0
lines changed

clang/lib/Analysis/CFG.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1261,6 +1261,28 @@ class CFGBuilder {
12611261
L2Result.Val.getKind() == APValue::Float) {
12621262
llvm::APFloat L1 = L1Result.Val.getFloat();
12631263
llvm::APFloat L2 = L2Result.Val.getFloat();
1264+
// Note that L1 and L2 do not necessarily have the same type. For example
1265+
// `x != 0 || x != 1.0`, if `x` is a float16, the two literals `0` and
1266+
// `1.0` are float16 and double respectively. In this case, we should do
1267+
// a conversion before comparing L1 and L2. Their types must be
1268+
// compatible since they are comparing with the same DRE.
1269+
int Order = Context->getFloatingTypeSemanticOrder(NumExpr1->getType(),
1270+
NumExpr2->getType());
1271+
bool Ignored = false;
1272+
1273+
if (Order > 0) {
1274+
// type rank L1 > L2:
1275+
if (llvm::APFloat::opOK !=
1276+
L2.convert(L1.getSemantics(), llvm::APFloat::rmNearestTiesToEven,
1277+
&Ignored))
1278+
return {};
1279+
} else if (Order < 0)
1280+
// type rank L1 < L2:
1281+
if (llvm::APFloat::opOK !=
1282+
L1.convert(L2.getSemantics(), llvm::APFloat::rmNearestTiesToEven,
1283+
&Ignored))
1284+
return {};
1285+
12641286
llvm::APFloat MidValue = L1;
12651287
MidValue.add(L2, llvm::APFloat::rmNearestTiesToEven);
12661288
MidValue.divide(llvm::APFloat(MidValue.getSemantics(), "2.0"),
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// RUN: %clang_cc1 -verify -Wunreachable-code %s
2+
3+
// Previously this test will crash
4+
static void test(__fp16& x) {
5+
if (x != 0 || x != 1.0) { // expected-note{{}} no-crash
6+
x = 0.9;
7+
} else
8+
x = 0.8; // expected-warning{{code will never be executed}}
9+
}
10+
11+
static void test2(__fp16& x) {
12+
if (x != 1 && x == 1.0) { // expected-note{{}} no-crash
13+
x = 0.9; // expected-warning{{code will never be executed}}
14+
} else
15+
x = 0.8;
16+
}

0 commit comments

Comments
 (0)