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