-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[analyzer] Add previous CFG block to BlockEntrance ProgramPoints #140861
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[analyzer] Add previous CFG block to BlockEntrance ProgramPoints #140861
Conversation
This helps to gain contextual information about how we entered a CFG block. The `noexprcrash.c` test probably changed due to the fact that now BlockEntrance ProgramPoint Profile also hashes the pointer of the previous CFG block. I didn't investigate. CPP-6483
|
/cc @necto |
|
@llvm/pr-subscribers-clang-analysis @llvm/pr-subscribers-clang-static-analyzer-1 Author: Balázs Benics (balazs-benics-sonarsource) ChangesThis helps to gain contextual information about how we entered a CFG block. The CPP-6483 Full diff: https://github.com/llvm/llvm-project/pull/140861.diff 3 Files Affected:
diff --git a/clang/include/clang/Analysis/ProgramPoint.h b/clang/include/clang/Analysis/ProgramPoint.h
index c40aa3d8ffb72..096ad48a42984 100644
--- a/clang/include/clang/Analysis/ProgramPoint.h
+++ b/clang/include/clang/Analysis/ProgramPoint.h
@@ -224,10 +224,14 @@ class ProgramPoint {
class BlockEntrance : public ProgramPoint {
public:
- BlockEntrance(const CFGBlock *B, const LocationContext *L,
- const ProgramPointTag *tag = nullptr)
- : ProgramPoint(B, BlockEntranceKind, L, tag) {
- assert(B && "BlockEntrance requires non-null block");
+ BlockEntrance(const CFGBlock *PrevBlock, const CFGBlock *CurrBlock,
+ const LocationContext *L, const ProgramPointTag *Tag = nullptr)
+ : ProgramPoint(CurrBlock, PrevBlock, BlockEntranceKind, L, Tag) {
+ assert(CurrBlock && "BlockEntrance requires non-null block");
+ }
+
+ const CFGBlock *getPreviousBlock() const {
+ return reinterpret_cast<const CFGBlock *>(getData2());
}
const CFGBlock *getBlock() const {
@@ -760,13 +764,15 @@ template <> struct DenseMapInfo<clang::ProgramPoint> {
static inline clang::ProgramPoint getEmptyKey() {
uintptr_t x =
reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getEmptyKey()) & ~0x7;
- return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), nullptr);
+ return clang::BlockEntrance(nullptr, reinterpret_cast<clang::CFGBlock *>(x),
+ nullptr);
}
static inline clang::ProgramPoint getTombstoneKey() {
uintptr_t x =
reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getTombstoneKey()) & ~0x7;
- return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), nullptr);
+ return clang::BlockEntrance(nullptr, reinterpret_cast<clang::CFGBlock *>(x),
+ nullptr);
}
static unsigned getHashValue(const clang::ProgramPoint &Loc) {
diff --git a/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp b/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
index 8cc086a12ad70..bedb11f8b94a5 100644
--- a/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
@@ -315,7 +315,7 @@ void CoreEngine::HandleBlockEdge(const BlockEdge &L, ExplodedNode *Pred) {
// Call into the ExprEngine to process entering the CFGBlock.
ExplodedNodeSet dstNodes;
- BlockEntrance BE(Blk, Pred->getLocationContext());
+ BlockEntrance BE(L.getSrc(), L.getDst(), Pred->getLocationContext());
NodeBuilderWithSinks nodeBuilder(Pred, dstNodes, BuilderCtx, BE);
ExprEng.processCFGBlockEntrance(L, nodeBuilder, Pred);
diff --git a/clang/test/Analysis/exploration_order/noexprcrash.c b/clang/test/Analysis/exploration_order/noexprcrash.c
index 75c2f0e6798a3..427c669783374 100644
--- a/clang/test/Analysis/exploration_order/noexprcrash.c
+++ b/clang/test/Analysis/exploration_order/noexprcrash.c
@@ -1,17 +1,18 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify -analyzer-config exploration_strategy=unexplored_first %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify -analyzer-config exploration_strategy=dfs %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify=common,ufirst -analyzer-config exploration_strategy=unexplored_first %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify=common,dfs -analyzer-config exploration_strategy=dfs %s
extern void clang_analyzer_eval(int);
typedef struct { char a; } b;
int c(b* input) {
- int x = (input->a ?: input) ? 1 : 0; // expected-warning{{pointer/integer type mismatch}}
+ int x = (input->a ?: input) ? 1 : 0; // common-warning{{pointer/integer type mismatch}}
if (input->a) {
// FIXME: The value should actually be "TRUE",
// but is incorrect due to a bug.
- clang_analyzer_eval(x); // expected-warning{{FALSE}}
+ // dfs-warning@+1 {{FALSE}} ufirst-warning@+1 {{TRUE}}
+ clang_analyzer_eval(x);
} else {
- clang_analyzer_eval(x); // expected-warning{{TRUE}}
+ clang_analyzer_eval(x); // common-warning{{TRUE}}
}
return x;
}
|
NagyDonat
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, straightforward simple extension.
This helps to gain contextual information about how we entered a CFG block.
The
noexprcrash.ctest probably changed due to the fact that now BlockEntrance ProgramPoint Profile also hashes the pointer of the previous CFG block. I didn't investigate.CPP-6483