[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