]> granicus.if.org Git - clang/blobdiff - include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
Header guard canonicalization, clang part.
[clang] / include / clang / StaticAnalyzer / Core / BugReporter / BugReporter.h
index 48393a379b39e227a6d2890a3b44fae527c0413f..3e1745e840d1d464e241d46b2e9b642055f3f942 100644 (file)
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_GR_BUGREPORTER
-#define LLVM_CLANG_GR_BUGREPORTER
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H
+#define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H
 
 #include "clang/Basic/SourceLocation.h"
+#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/ImmutableSet.h"
+#include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/ilist.h"
 #include "llvm/ADT/ilist_node.h"
-#include "llvm/ADT/ImmutableSet.h"
-#include "llvm/ADT/DenseSet.h"
 
 namespace clang {
 
@@ -74,6 +77,8 @@ protected:
   std::string Description;
   PathDiagnosticLocation Location;
   PathDiagnosticLocation UniqueingLocation;
+  const Decl *UniqueingDecl;
+  
   const ExplodedNode *ErrorNode;
   SmallVector<SourceRange, 4> Ranges;
   ExtraTextList ExtraText;
@@ -86,14 +91,18 @@ protected:
   /// diagnostics to include when constructing the final path diagnostic.
   /// The stack is largely used by BugReporter when generating PathDiagnostics
   /// for multiple PathDiagnosticConsumers.
-  llvm::SmallVector<Symbols *, 2> interestingSymbols;
+  SmallVector<Symbols *, 2> interestingSymbols;
 
   /// A (stack of) set of regions that are registered with this report as being
   /// "interesting", and thus used to help decide which diagnostics
   /// to include when constructing the final path diagnostic.
   /// The stack is largely used by BugReporter when generating PathDiagnostics
   /// for multiple PathDiagnosticConsumers.
-  llvm::SmallVector<Regions *, 2> interestingRegions;
+  SmallVector<Regions *, 2> interestingRegions;
+
+  /// A set of location contexts that correspoind to call sites which should be
+  /// considered "interesting".
+  llvm::SmallSet<const LocationContext *, 2> InterestingLocationContexts;
 
   /// A set of custom visitors which generate "event" diagnostics at
   /// interesting points in the path.
@@ -111,6 +120,19 @@ protected:
   /// when reporting an issue.
   bool DoNotPrunePath;
 
+  /// Used to track unique reasons why a bug report might be invalid.
+  ///
+  /// \sa markInvalid
+  /// \sa removeInvalidation
+  typedef std::pair<const void *, const void *> InvalidationRecord;
+
+  /// If non-empty, this bug report is likely a false positive and should not be
+  /// shown to the user.
+  ///
+  /// \sa markInvalid
+  /// \sa removeInvalidation
+  llvm::SmallSet<InvalidationRecord, 4> Invalidations;
+
 private:
   // Used internally by BugReporter.
   Symbols &getInterestingSymbols();
@@ -122,19 +144,18 @@ private:
 
 public:
   BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode)
-    : BT(bt), DeclWithIssue(0), Description(desc), ErrorNode(errornode),
+    : BT(bt), DeclWithIssue(nullptr), Description(desc), ErrorNode(errornode),
       ConfigurationChangeToken(0), DoNotPrunePath(false) {}
 
   BugReport(BugType& bt, StringRef shortDesc, StringRef desc,
             const ExplodedNode *errornode)
-    : BT(bt), DeclWithIssue(0), ShortDescription(shortDesc), Description(desc),
-      ErrorNode(errornode), ConfigurationChangeToken(0),
+    : BT(bt), DeclWithIssue(nullptr), ShortDescription(shortDesc),
+      Description(desc), ErrorNode(errornode), ConfigurationChangeToken(0),
       DoNotPrunePath(false) {}
 
-  BugReport(BugType& bt, StringRef desc, PathDiagnosticLocation l)
-    : BT(bt), DeclWithIssue(0), Description(desc), Location(l), ErrorNode(0),
-      ConfigurationChangeToken(0),
-      DoNotPrunePath(false) {}
+  BugReport(BugType &bt, StringRef desc, PathDiagnosticLocation l)
+    : BT(bt), DeclWithIssue(nullptr), Description(desc), Location(l),
+      ErrorNode(nullptr), ConfigurationChangeToken(0), DoNotPrunePath(false) {}
 
   /// \brief Create a BugReport with a custom uniqueing location.
   ///
@@ -144,10 +165,12 @@ public:
   /// for uniquing reports. For example, memory leaks checker, could set this to
   /// the allocation site, rather then the location where the bug is reported.
   BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode,
-            PathDiagnosticLocation LocationToUnique)
-    : BT(bt), DeclWithIssue(0), Description(desc),
+            PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique)
+    : BT(bt), DeclWithIssue(nullptr), Description(desc),
       UniqueingLocation(LocationToUnique),
-      ErrorNode(errornode), ConfigurationChangeToken(0) {}
+      UniqueingDecl(DeclToUnique),
+      ErrorNode(errornode), ConfigurationChangeToken(0),
+      DoNotPrunePath(false) {}
 
   virtual ~BugReport();
 
@@ -158,8 +181,10 @@ public:
 
   const StringRef getDescription() const { return Description; }
 
-  const StringRef getShortDescription() const {
-    return ShortDescription.empty() ? Description : ShortDescription;
+  const StringRef getShortDescription(bool UseFallback = true) const {
+    if (ShortDescription.empty() && UseFallback)
+      return Description;
+    return ShortDescription;
   }
 
   /// Indicates whether or not any path pruning should take place
@@ -172,14 +197,44 @@ public:
   void markInteresting(SymbolRef sym);
   void markInteresting(const MemRegion *R);
   void markInteresting(SVal V);
+  void markInteresting(const LocationContext *LC);
   
   bool isInteresting(SymbolRef sym);
   bool isInteresting(const MemRegion *R);
   bool isInteresting(SVal V);
+  bool isInteresting(const LocationContext *LC);
 
   unsigned getConfigurationChangeToken() const {
     return ConfigurationChangeToken;
   }
+
+  /// Returns whether or not this report should be considered valid.
+  ///
+  /// Invalid reports are those that have been classified as likely false
+  /// positives after the fact.
+  bool isValid() const {
+    return Invalidations.empty();
+  }
+
+  /// Marks the current report as invalid, meaning that it is probably a false
+  /// positive and should not be reported to the user.
+  ///
+  /// The \p Tag and \p Data arguments are intended to be opaque identifiers for
+  /// this particular invalidation, where \p Tag represents the visitor
+  /// responsible for invalidation, and \p Data represents the reason this
+  /// visitor decided to invalidate the bug report.
+  ///
+  /// \sa removeInvalidation
+  void markInvalid(const void *Tag, const void *Data) {
+    Invalidations.insert(std::make_pair(Tag, Data));
+  }
+
+  /// Reverses the effects of a previous invalidation.
+  ///
+  /// \sa markInvalid
+  void removeInvalidation(const void *Tag, const void *Data) {
+    Invalidations.erase(std::make_pair(Tag, Data));
+  }
   
   /// Return the canonical declaration, be it a method or class, where
   /// this issue semantically occurred.
@@ -209,6 +264,16 @@ public:
   ///  This location is used by clients rendering diagnostics.
   virtual PathDiagnosticLocation getLocation(const SourceManager &SM) const;
 
+  /// \brief Get the location on which the report should be uniqued.
+  PathDiagnosticLocation getUniqueingLocation() const {
+    return UniqueingLocation;
+  }
+  
+  /// \brief Get the declaration containing the uniqueing location.
+  const Decl *getUniqueingDecl() const {
+    return UniqueingDecl;
+  }
+
   const Stmt *getStmt() const;
 
   /// \brief Add a range to a bug report.
@@ -311,6 +376,7 @@ public:
   virtual ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() = 0;
   virtual ASTContext &getASTContext() = 0;
   virtual SourceManager& getSourceManager() = 0;
+  virtual AnalyzerOptions& getAnalyzerOptions() = 0;
 };
 
 /// BugReporter is a utility class for generating PathDiagnostics for analysis.
@@ -378,9 +444,15 @@ public:
 
   SourceManager& getSourceManager() { return D.getSourceManager(); }
 
-  virtual void GeneratePathDiagnostic(PathDiagnostic& pathDiagnostic,
+  AnalyzerOptions& getAnalyzerOptions() { return D.getAnalyzerOptions(); }
+
+  virtual bool generatePathDiagnostic(PathDiagnostic& pathDiagnostic,
                                       PathDiagnosticConsumer &PC,
-                                      ArrayRef<BugReport *> &bugReports) {}
+                                      ArrayRef<BugReport *> &bugReports) {
+    return true;
+  }
+
+  bool RemoveUnneededCalls(PathPieces &pieces, BugReport *R);
 
   void Register(BugType *BT);
 
@@ -389,34 +461,25 @@ public:
   /// The reports are usually generated by the checkers. Further, they are
   /// folded based on the profile value, which is done to coalesce similar
   /// reports.
-  void EmitReport(BugReport *R);
+  void emitReport(BugReport *R);
 
-  void EmitBasicReport(const Decl *DeclWithIssue,
+  void EmitBasicReport(const Decl *DeclWithIssue, const CheckerBase *Checker,
                        StringRef BugName, StringRef BugCategory,
                        StringRef BugStr, PathDiagnosticLocation Loc,
-                       SourceRange* RangeBeg, unsigned NumRanges);
+                       ArrayRef<SourceRange> Ranges = None);
 
-  void EmitBasicReport(const Decl *DeclWithIssue,
+  void EmitBasicReport(const Decl *DeclWithIssue, CheckName CheckName,
                        StringRef BugName, StringRef BugCategory,
-                       StringRef BugStr, PathDiagnosticLocation Loc) {
-    EmitBasicReport(DeclWithIssue, BugName, BugCategory, BugStr, Loc, 0, 0);
-  }
-
-  void EmitBasicReport(const Decl *DeclWithIssue,
-                       StringRef BugName, StringRef Category,
                        StringRef BugStr, PathDiagnosticLocation Loc,
-                       SourceRange R) {
-    EmitBasicReport(DeclWithIssue, BugName, Category, BugStr, Loc, &R, 1);
-  }
-
-  static bool classof(const BugReporter* R) { return true; }
+                       ArrayRef<SourceRange> Ranges = None);
 
 private:
   llvm::StringMap<BugType *> StrBugTypes;
 
   /// \brief Returns a BugType that is associated with the given name and
   /// category.
-  BugType *getBugTypeForName(StringRef name, StringRef category);
+  BugType *getBugTypeForName(CheckName CheckName, StringRef name,
+                             StringRef category);
 };
 
 // FIXME: Get rid of GRBugReporter.  It's the wrong abstraction.
@@ -440,9 +503,16 @@ public:
   ///  engine.
   ProgramStateManager &getStateManager();
 
-  virtual void GeneratePathDiagnostic(PathDiagnostic &pathDiagnostic,
-                                      PathDiagnosticConsumer &PC,
-                                      ArrayRef<BugReport*> &bugReports);
+  /// Generates a path corresponding to one of the given bug reports.
+  ///
+  /// Which report is used for path generation is not specified. The
+  /// bug reporter will try to pick the shortest path, but this is not
+  /// guaranteed.
+  ///
+  /// \return True if the report was valid and a path was generated,
+  ///         false if the reports should be considered invalid.
+  bool generatePathDiagnostic(PathDiagnostic &PD, PathDiagnosticConsumer &PC,
+                              ArrayRef<BugReport*> &bugReports) override;
 
   /// classof - Used by isa<>, cast<>, and dyn_cast<>.
   static bool classof(const BugReporter* R) {