https://github.com/ziqingluo-90 updated 
https://github.com/llvm/llvm-project/pull/139188

>From 95ac7cf69dbd683f70b123446115fe3893844526 Mon Sep 17 00:00:00 2001
From: Ziqing Luo <ziq...@udel.edu>
Date: Thu, 8 May 2025 17:48:41 -0700
Subject: [PATCH 1/2] [StaticAnalyzer] Handle __builtin_bit_cast

Previously, CSA did not handle __builtin_bit_cast correctly. It
evaluated the LvalueToRvalue conversion for the casting expression,
but did not actually convert the value of the expression to be of the
destination type.
This commit fixes the problem.

rdar://149987320
---
 clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 26 ++++++++++++++++++-
 clang/test/Analysis/builtin_bitcast.cpp       | 14 ++++++++--
 clang/test/Analysis/exercise-ps.c             |  2 +-
 3 files changed, 38 insertions(+), 4 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 3d0a69a515ab8..f2f640f459776 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -287,10 +287,34 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const 
Expr *Ex,
 
   if (CastE->getCastKind() == CK_LValueToRValue ||
       CastE->getCastKind() == CK_LValueToRValueBitCast) {
+    ExplodedNodeSet dstEvalLoad;
+
     for (ExplodedNode *subExprNode : dstPreStmt) {
       ProgramStateRef state = subExprNode->getState();
       const LocationContext *LCtx = subExprNode->getLocationContext();
-      evalLoad(Dst, CastE, CastE, subExprNode, state, state->getSVal(Ex, 
LCtx));
+      evalLoad(dstEvalLoad, CastE, CastE, subExprNode, state,
+               state->getSVal(Ex, LCtx));
+    }
+    if (CastE->getCastKind() == CK_LValueToRValue) {
+      Dst.insert(dstEvalLoad);
+      return;
+    }
+    assert(CastE->getCastKind() == CK_LValueToRValueBitCast &&
+           "unexpected cast kind");
+    // Need to simulate the actual cast operation:
+    StmtNodeBuilder Bldr(dstEvalLoad, Dst, *currBldrCtx);
+
+    for (ExplodedNode *Node : dstEvalLoad) {
+      ProgramStateRef state = Node->getState();
+      const LocationContext *LCtx = Node->getLocationContext();
+      // getAsRegion should always be successful since Ex is an lvalue:
+      SVal OrigV = state->getSVal(state->getSVal(Ex, LCtx).getAsRegion());
+      SVal CastedV =
+          svalBuilder.evalCast(svalBuilder.simplifySVal(state, OrigV),
+                               CastE->getType(), Ex->getType());
+
+      state = state->BindExpr(CastE, LCtx, CastedV);
+      Bldr.generateNode(CastE, Node, state);
     }
     return;
   }
diff --git a/clang/test/Analysis/builtin_bitcast.cpp 
b/clang/test/Analysis/builtin_bitcast.cpp
index 5a0d9e7189b8e..9309ca7785a92 100644
--- a/clang/test/Analysis/builtin_bitcast.cpp
+++ b/clang/test/Analysis/builtin_bitcast.cpp
@@ -39,7 +39,7 @@ struct A {
   }
 };
 void gh_69922(size_t p) {
-  // expected-warning-re@+1 {{(reg_${{[0-9]+}}<size_t p>) & 1U}}
+  // expected-warning@+1 {{Unknown}}
   clang_analyzer_dump(__builtin_bit_cast(A*, p & 1));
 
   __builtin_bit_cast(A*, p & 1)->set(2); // no-crash
@@ -49,5 +49,15 @@ void gh_69922(size_t p) {
   // store to the member variable `n`.
 
   clang_analyzer_dump(__builtin_bit_cast(A*, p & 1)->n); // Ideally, this 
should print "2".
-  // expected-warning-re@-1 {{(reg_${{[0-9]+}}<size_t p>) & 1U}}
+  // expected-warning@-1 {{Unknown}}
+}
+
+namespace {
+  typedef unsigned long uintptr_t;
+  
+  bool previously_crash(const void *& ptr) {
+    clang_analyzer_dump(__builtin_bit_cast(void*, static_cast<uintptr_t>(-1)));
+    // expected-warning-re@-1 {{{{[0-9]+}} (Loc)}}
+    return ptr == __builtin_bit_cast(void*, static_cast<uintptr_t>(-1));
+  }
 }
diff --git a/clang/test/Analysis/exercise-ps.c 
b/clang/test/Analysis/exercise-ps.c
index 50643d5b04687..21d97a364e190 100644
--- a/clang/test/Analysis/exercise-ps.c
+++ b/clang/test/Analysis/exercise-ps.c
@@ -41,7 +41,7 @@ void f4(char *array) {
 
   _Static_assert(sizeof(int) == 4, "Wrong triple for the test");
 
-  clang_analyzer_dump_int(__builtin_bit_cast(int, b)); // expected-warning 
{{lazyCompoundVal}}
+  clang_analyzer_dump_int(__builtin_bit_cast(int, b)); // expected-warning 
{{Unknown}}
   clang_analyzer_dump_int(array[__builtin_bit_cast(int, b)]); // 
expected-warning {{Unknown}}
 
   array[__builtin_bit_cast(int, b)] = 0x10; // no crash

>From 1d20c183135e20fad03a7598d5771540db44f0b2 Mon Sep 17 00:00:00 2001
From: Ziqing Luo <ziq...@udel.edu>
Date: Thu, 8 May 2025 18:31:21 -0700
Subject: [PATCH 2/2] For __builtin_bit_cast, we just need to evalLocation for
 the second argument instead of evalLoad.

---
 clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 26 +++++++++++--------
 1 file changed, 15 insertions(+), 11 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index f2f640f459776..e84fda8950e64 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -285,23 +285,27 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const 
Expr *Ex,
   ExplodedNodeSet dstPreStmt;
   getCheckerManager().runCheckersForPreStmt(dstPreStmt, Pred, CastE, *this);
 
-  if (CastE->getCastKind() == CK_LValueToRValue ||
-      CastE->getCastKind() == CK_LValueToRValueBitCast) {
+  if (CastE->getCastKind() == CK_LValueToRValue) {
+    for (ExplodedNode *subExprNode : dstPreStmt) {
+      ProgramStateRef state = subExprNode->getState();
+      const LocationContext *LCtx = subExprNode->getLocationContext();
+      evalLoad(Dst, CastE, CastE, subExprNode, state, state->getSVal(Ex, 
LCtx));
+    }
+    return;
+  }
+  if (CastE->getCastKind() == CK_LValueToRValueBitCast) {
+    // Handle `__builtin_bit_cast`:
     ExplodedNodeSet dstEvalLoad;
 
+    // Simulate the lvalue-to-rvalue conversion on `Ex`:
     for (ExplodedNode *subExprNode : dstPreStmt) {
       ProgramStateRef state = subExprNode->getState();
       const LocationContext *LCtx = subExprNode->getLocationContext();
-      evalLoad(dstEvalLoad, CastE, CastE, subExprNode, state,
-               state->getSVal(Ex, LCtx));
-    }
-    if (CastE->getCastKind() == CK_LValueToRValue) {
-      Dst.insert(dstEvalLoad);
-      return;
+      evalLocation(dstEvalLoad, CastE, Ex, subExprNode, state,
+                   state->getSVal(Ex, LCtx), true);
     }
-    assert(CastE->getCastKind() == CK_LValueToRValueBitCast &&
-           "unexpected cast kind");
-    // Need to simulate the actual cast operation:
+    // Simulate the operation that actually casts the original value to a new
+    // value of the destination type :
     StmtNodeBuilder Bldr(dstEvalLoad, Dst, *currBldrCtx);
 
     for (ExplodedNode *Node : dstEvalLoad) {

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

Reply via email to