Author: Ziqing Luo
Date: 2025-06-10T11:54:01+08:00
New Revision: b9d41328c6c60c622fe5737f449e568f1ee4ec8f

URL: 
https://github.com/llvm/llvm-project/commit/b9d41328c6c60c622fe5737f449e568f1ee4ec8f
DIFF: 
https://github.com/llvm/llvm-project/commit/b9d41328c6c60c622fe5737f449e568f1ee4ec8f.diff

LOG: [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

Added: 
    clang/test/Sema/warn-unreachable_crash.cpp

Modified: 
    clang/lib/Analysis/CFG.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp
index 7f37a8b18d46e..cf7595952be27 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.
+      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"),

diff  --git a/clang/test/Sema/warn-unreachable_crash.cpp 
b/clang/test/Sema/warn-unreachable_crash.cpp
new file mode 100644
index 0000000000000..628abcc83f810
--- /dev/null
+++ b/clang/test/Sema/warn-unreachable_crash.cpp
@@ -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;
+}


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to