https://github.com/ziqingluo-90 created https://github.com/llvm/llvm-project/pull/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 >From 99931f58846f361e409445d06fdfca4f5e7d3bb3 Mon Sep 17 00:00:00 2001 From: Ziqing Luo <ziq...@udel.edu> Date: Thu, 5 Jun 2025 12:28:12 +0800 Subject: [PATCH] [clang][CFG] Fix assertion failure in checkIncorrectLogicOperator `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 --- clang/lib/Analysis/CFG.cpp | 22 ++++++++++++++++++++++ clang/test/Sema/warn-unreachable_crash.cpp | 8 ++++++++ 2 files changed, 30 insertions(+) create mode 100644 clang/test/Sema/warn-unreachable_crash.cpp diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index 7f37a8b18d46e..c9610cc2888ad 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -1261,6 +1261,28 @@ class CFGBuilder { 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. + int8_t Order = Context->getFloatingTypeOrder(NumExpr1->getType(), + NumExpr2->getType()); + bool convertLoseInfo = false; + + if (Order > 0) { + // type rank L1 > L2: + if (L2.convert(L1.getSemantics(), llvm::APFloat::rmNearestTiesToEven, + &convertLoseInfo)) + return {}; + } else if (Order < 0) + // type rank L1 < L2: + if (L1.convert(L2.getSemantics(), llvm::APFloat::rmNearestTiesToEven, + &convertLoseInfo)) + return {}; + if (convertLoseInfo) + return {}; // If the conversion loses info, bail + llvm::APFloat MidValue = L1; MidValue.add(L2, llvm::APFloat::rmNearestTiesToEven); MidValue.divide(llvm::APFloat(MidValue.getSemantics(), "2.0"), diff --git a/clang/test/Sema/warn-unreachable_crash.cpp b/clang/test/Sema/warn-unreachable_crash.cpp new file mode 100644 index 0000000000000..7b23f30c6a214 --- /dev/null +++ b/clang/test/Sema/warn-unreachable_crash.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -verify -Wunreachable-code %s + +static void test(__fp16& x) { + if (x != 0 || x != 1.0) { // expected-note{{}} + x = 0.9; + } else + x = 0.8; // expected-warning{{code will never be executed}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits