vsavchenko created this revision.
vsavchenko added reviewers: NoQ, xazax.hun, martong, steakhal, Szelethus, 
manas, RedDocMD.
Herald added subscribers: ASDenysPetrov, dkrupp, donat.nagy, mikhail.ramalho, 
a.sidorin, rnkovacs, szepet, baloghadamsoftware.
vsavchenko requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This allows us to create other types of tags that carry useful
bits of information alongside.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D104135

Files:
  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

Index: clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
+++ clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
@@ -219,13 +219,14 @@
   // 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);
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -428,8 +428,7 @@
   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(); }
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
@@ -96,9 +96,10 @@
   /// (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 @@
   /// 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.
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
@@ -255,7 +255,7 @@
   ///        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
Index: clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
+++ clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
@@ -725,14 +725,43 @@
   }
 };
 
+/// 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 @@
   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 @@
 
   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;
 };
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to