Skip to content

Commit 95ac7cf

Browse files
committed
[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
1 parent 611d81b commit 95ac7cf

File tree

3 files changed

+38
-4
lines changed

3 files changed

+38
-4
lines changed

clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,10 +287,34 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
287287

288288
if (CastE->getCastKind() == CK_LValueToRValue ||
289289
CastE->getCastKind() == CK_LValueToRValueBitCast) {
290+
ExplodedNodeSet dstEvalLoad;
291+
290292
for (ExplodedNode *subExprNode : dstPreStmt) {
291293
ProgramStateRef state = subExprNode->getState();
292294
const LocationContext *LCtx = subExprNode->getLocationContext();
293-
evalLoad(Dst, CastE, CastE, subExprNode, state, state->getSVal(Ex, LCtx));
295+
evalLoad(dstEvalLoad, CastE, CastE, subExprNode, state,
296+
state->getSVal(Ex, LCtx));
297+
}
298+
if (CastE->getCastKind() == CK_LValueToRValue) {
299+
Dst.insert(dstEvalLoad);
300+
return;
301+
}
302+
assert(CastE->getCastKind() == CK_LValueToRValueBitCast &&
303+
"unexpected cast kind");
304+
// Need to simulate the actual cast operation:
305+
StmtNodeBuilder Bldr(dstEvalLoad, Dst, *currBldrCtx);
306+
307+
for (ExplodedNode *Node : dstEvalLoad) {
308+
ProgramStateRef state = Node->getState();
309+
const LocationContext *LCtx = Node->getLocationContext();
310+
// getAsRegion should always be successful since Ex is an lvalue:
311+
SVal OrigV = state->getSVal(state->getSVal(Ex, LCtx).getAsRegion());
312+
SVal CastedV =
313+
svalBuilder.evalCast(svalBuilder.simplifySVal(state, OrigV),
314+
CastE->getType(), Ex->getType());
315+
316+
state = state->BindExpr(CastE, LCtx, CastedV);
317+
Bldr.generateNode(CastE, Node, state);
294318
}
295319
return;
296320
}

clang/test/Analysis/builtin_bitcast.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ struct A {
3939
}
4040
};
4141
void gh_69922(size_t p) {
42-
// expected-warning-re@+1 {{(reg_${{[0-9]+}}<size_t p>) & 1U}}
42+
// expected-warning@+1 {{Unknown}}
4343
clang_analyzer_dump(__builtin_bit_cast(A*, p & 1));
4444

4545
__builtin_bit_cast(A*, p & 1)->set(2); // no-crash
@@ -49,5 +49,15 @@ void gh_69922(size_t p) {
4949
// store to the member variable `n`.
5050

5151
clang_analyzer_dump(__builtin_bit_cast(A*, p & 1)->n); // Ideally, this should print "2".
52-
// expected-warning-re@-1 {{(reg_${{[0-9]+}}<size_t p>) & 1U}}
52+
// expected-warning@-1 {{Unknown}}
53+
}
54+
55+
namespace {
56+
typedef unsigned long uintptr_t;
57+
58+
bool previously_crash(const void *& ptr) {
59+
clang_analyzer_dump(__builtin_bit_cast(void*, static_cast<uintptr_t>(-1)));
60+
// expected-warning-re@-1 {{{{[0-9]+}} (Loc)}}
61+
return ptr == __builtin_bit_cast(void*, static_cast<uintptr_t>(-1));
62+
}
5363
}

clang/test/Analysis/exercise-ps.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ void f4(char *array) {
4141

4242
_Static_assert(sizeof(int) == 4, "Wrong triple for the test");
4343

44-
clang_analyzer_dump_int(__builtin_bit_cast(int, b)); // expected-warning {{lazyCompoundVal}}
44+
clang_analyzer_dump_int(__builtin_bit_cast(int, b)); // expected-warning {{Unknown}}
4545
clang_analyzer_dump_int(array[__builtin_bit_cast(int, b)]); // expected-warning {{Unknown}}
4646

4747
array[__builtin_bit_cast(int, b)] = 0x10; // no crash

0 commit comments

Comments
 (0)