[clang] eadd54f - [analyzer] Decouple NoteTag from its Factory
Valeriy Savchenko via cfe-commits
cfe-commits at lists.llvm.org
Tue Jun 15 01:59:02 PDT 2021
Author: Valeriy Savchenko
Date: 2021-06-15T11:58:13+03:00
New Revision: eadd54f2741f9dc7307512382a7c8fb49aa840d0
URL: https://github.com/llvm/llvm-project/commit/eadd54f2741f9dc7307512382a7c8fb49aa840d0
DIFF: https://github.com/llvm/llvm-project/commit/eadd54f2741f9dc7307512382a7c8fb49aa840d0.diff
LOG: [analyzer] Decouple NoteTag from its Factory
This allows us to create other types of tags that carry useful
bits of information alongside.
Differential Revision: https://reviews.llvm.org/D104135
Added:
Modified:
clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
index 0b12ff7075780..99cd24a52f2df 100644
--- a/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
+++ b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
@@ -725,14 +725,43 @@ class BugReporterContext {
}
};
+/// The tag that carries some information with it.
+///
+/// It can be valuable to produce tags with some bits of information and later
+/// reuse them for a better diagnostic.
+///
+/// Please make sure that derived class' constuctor is private and that the user
+/// can only create objects using DataTag::Factory. This also means that
+/// DataTag::Factory should be friend for every derived class.
+class DataTag : public ProgramPointTag {
+public:
+ StringRef getTagDescription() const override { return "Data Tag"; }
+
+ // Manage memory for DataTag objects.
+ class Factory {
+ std::vector<std::unique_ptr<DataTag>> Tags;
+
+ public:
+ template <class DataTagType, class... Args>
+ const DataTagType *make(Args &&... ConstructorArgs) {
+ // We cannot use std::make_unique because we cannot access the private
+ // constructor from inside it.
+ Tags.emplace_back(
+ new DataTagType(std::forward<Args>(ConstructorArgs)...));
+ return static_cast<DataTagType *>(Tags.back().get());
+ }
+ };
+
+protected:
+ DataTag(void *TagKind) : ProgramPointTag(TagKind) {}
+};
/// The tag upon which the TagVisitor reacts. Add these in order to display
/// additional PathDiagnosticEventPieces along the path.
-class NoteTag : public ProgramPointTag {
+class NoteTag : public DataTag {
public:
- using Callback =
- std::function<std::string(BugReporterContext &,
- PathSensitiveBugReport &)>;
+ using Callback = std::function<std::string(BugReporterContext &,
+ PathSensitiveBugReport &)>;
private:
static int Kind;
@@ -741,7 +770,7 @@ class NoteTag : public ProgramPointTag {
const bool IsPrunable;
NoteTag(Callback &&Cb, bool IsPrunable)
- : ProgramPointTag(&Kind), Cb(std::move(Cb)), IsPrunable(IsPrunable) {}
+ : DataTag(&Kind), Cb(std::move(Cb)), IsPrunable(IsPrunable) {}
public:
static bool classof(const ProgramPointTag *T) {
@@ -766,20 +795,7 @@ class NoteTag : public ProgramPointTag {
bool isPrunable() const { return IsPrunable; }
- // Manage memory for NoteTag objects.
- class Factory {
- std::vector<std::unique_ptr<NoteTag>> Tags;
-
- public:
- const NoteTag *makeNoteTag(Callback &&Cb, bool IsPrunable = false) {
- // We cannot use std::make_unique because we cannot access the private
- // constructor from inside it.
- std::unique_ptr<NoteTag> T(new NoteTag(std::move(Cb), IsPrunable));
- Tags.push_back(std::move(T));
- return Tags.back().get();
- }
- };
-
+ friend class Factory;
friend class TagVisitor;
};
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
index 54572bd81f20f..a383012dc3516 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
@@ -255,7 +255,7 @@ class CheckerContext {
/// to omit the note from the report if it would make the displayed
/// bug path significantly shorter.
const NoteTag *getNoteTag(NoteTag::Callback &&Cb, bool IsPrunable = false) {
- return Eng.getNoteTags().makeNoteTag(std::move(Cb), IsPrunable);
+ return Eng.getDataTags().make<NoteTag>(std::move(Cb), IsPrunable);
}
/// A shorthand version of getNoteTag that doesn't require you to accept
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
index 2aca2c99ef4fd..9898b9b42f4b2 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
@@ -96,9 +96,10 @@ class CoreEngine {
/// (This data is owned by AnalysisConsumer.)
FunctionSummariesTy *FunctionSummaries;
- /// Add path note tags along the path when we see that something interesting
- /// is happening. This field is the allocator for such tags.
- NoteTag::Factory NoteTags;
+ /// Add path tags with some useful data along the path when we see that
+ /// something interesting is happening. This field is the allocator for such
+ /// tags.
+ DataTag::Factory DataTags;
void generateNode(const ProgramPoint &Loc,
ProgramStateRef State,
@@ -200,7 +201,7 @@ class CoreEngine {
/// Enqueue a single node created as a result of statement processing.
void enqueueStmtNode(ExplodedNode *N, const CFGBlock *Block, unsigned Idx);
- NoteTag::Factory &getNoteTags() { return NoteTags; }
+ DataTag::Factory &getDataTags() { return DataTags; }
};
// TODO: Turn into a class.
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index 582a56cbee1ee..cef7dda172f3e 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -428,8 +428,7 @@ class ExprEngine {
SymbolManager &getSymbolManager() { return SymMgr; }
MemRegionManager &getRegionManager() { return MRMgr; }
- NoteTag::Factory &getNoteTags() { return Engine.getNoteTags(); }
-
+ DataTag::Factory &getDataTags() { return Engine.getDataTags(); }
// Functions for external checking of whether we have unfinished work
bool wasBlocksExhausted() const { return Engine.wasBlocksExhausted(); }
diff --git a/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp b/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
index ae45ae5aa02f3..bc939d2528002 100644
--- a/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
@@ -219,13 +219,14 @@ void CoreEngine::HandleBlockEdge(const BlockEdge &L, ExplodedNode *Pred) {
// and we're taking the path that skips virtual base constructors.
if (L.getSrc()->getTerminator().isVirtualBaseBranch() &&
L.getDst() == *L.getSrc()->succ_begin()) {
- ProgramPoint P = L.withTag(getNoteTags().makeNoteTag(
+ ProgramPoint P = L.withTag(getDataTags().make<NoteTag>(
[](BugReporterContext &, PathSensitiveBugReport &) -> std::string {
// TODO: Just call out the name of the most derived class
// when we know it.
return "Virtual base initialization skipped because "
"it has already been handled by the most derived class";
- }, /*IsPrunable=*/true));
+ },
+ /*IsPrunable=*/true));
// Perform the transition.
ExplodedNodeSet Dst;
NodeBuilder Bldr(Pred, Dst, BuilderCtx);
More information about the cfe-commits
mailing list