clang API Documentation
00001 //===--- BugReporter.h - Generate PathDiagnostics --------------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines BugReporter, a utility class for generating 00011 // PathDiagnostics for analyses based on ProgramState. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H 00016 #define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H 00017 00018 #include "clang/Basic/SourceLocation.h" 00019 #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" 00020 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h" 00021 #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" 00022 #include "clang/StaticAnalyzer/Core/CheckerManager.h" 00023 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 00024 #include "llvm/ADT/DenseSet.h" 00025 #include "llvm/ADT/FoldingSet.h" 00026 #include "llvm/ADT/ImmutableSet.h" 00027 #include "llvm/ADT/SmallSet.h" 00028 #include "llvm/ADT/ilist.h" 00029 #include "llvm/ADT/ilist_node.h" 00030 00031 namespace clang { 00032 00033 class ASTContext; 00034 class DiagnosticsEngine; 00035 class Stmt; 00036 class ParentMap; 00037 00038 namespace ento { 00039 00040 class PathDiagnostic; 00041 class ExplodedNode; 00042 class ExplodedGraph; 00043 class BugReport; 00044 class BugReporter; 00045 class BugReporterContext; 00046 class ExprEngine; 00047 class BugType; 00048 00049 //===----------------------------------------------------------------------===// 00050 // Interface for individual bug reports. 00051 //===----------------------------------------------------------------------===// 00052 00053 /// This class provides an interface through which checkers can create 00054 /// individual bug reports. 00055 class BugReport : public llvm::ilist_node<BugReport> { 00056 public: 00057 class NodeResolver { 00058 virtual void anchor(); 00059 public: 00060 virtual ~NodeResolver() {} 00061 virtual const ExplodedNode* 00062 getOriginalNode(const ExplodedNode *N) = 0; 00063 }; 00064 00065 typedef const SourceRange *ranges_iterator; 00066 typedef SmallVector<std::unique_ptr<BugReporterVisitor>, 8> VisitorList; 00067 typedef VisitorList::iterator visitor_iterator; 00068 typedef SmallVector<StringRef, 2> ExtraTextList; 00069 00070 protected: 00071 friend class BugReporter; 00072 friend class BugReportEquivClass; 00073 00074 BugType& BT; 00075 const Decl *DeclWithIssue; 00076 std::string ShortDescription; 00077 std::string Description; 00078 PathDiagnosticLocation Location; 00079 PathDiagnosticLocation UniqueingLocation; 00080 const Decl *UniqueingDecl; 00081 00082 const ExplodedNode *ErrorNode; 00083 SmallVector<SourceRange, 4> Ranges; 00084 ExtraTextList ExtraText; 00085 00086 typedef llvm::DenseSet<SymbolRef> Symbols; 00087 typedef llvm::DenseSet<const MemRegion *> Regions; 00088 00089 /// A (stack of) a set of symbols that are registered with this 00090 /// report as being "interesting", and thus used to help decide which 00091 /// diagnostics to include when constructing the final path diagnostic. 00092 /// The stack is largely used by BugReporter when generating PathDiagnostics 00093 /// for multiple PathDiagnosticConsumers. 00094 SmallVector<Symbols *, 2> interestingSymbols; 00095 00096 /// A (stack of) set of regions that are registered with this report as being 00097 /// "interesting", and thus used to help decide which diagnostics 00098 /// to include when constructing the final path diagnostic. 00099 /// The stack is largely used by BugReporter when generating PathDiagnostics 00100 /// for multiple PathDiagnosticConsumers. 00101 SmallVector<Regions *, 2> interestingRegions; 00102 00103 /// A set of location contexts that correspoind to call sites which should be 00104 /// considered "interesting". 00105 llvm::SmallSet<const LocationContext *, 2> InterestingLocationContexts; 00106 00107 /// A set of custom visitors which generate "event" diagnostics at 00108 /// interesting points in the path. 00109 VisitorList Callbacks; 00110 00111 /// Used for ensuring the visitors are only added once. 00112 llvm::FoldingSet<BugReporterVisitor> CallbacksSet; 00113 00114 /// Used for clients to tell if the report's configuration has changed 00115 /// since the last time they checked. 00116 unsigned ConfigurationChangeToken; 00117 00118 /// When set, this flag disables all callstack pruning from a diagnostic 00119 /// path. This is useful for some reports that want maximum fidelty 00120 /// when reporting an issue. 00121 bool DoNotPrunePath; 00122 00123 /// Used to track unique reasons why a bug report might be invalid. 00124 /// 00125 /// \sa markInvalid 00126 /// \sa removeInvalidation 00127 typedef std::pair<const void *, const void *> InvalidationRecord; 00128 00129 /// If non-empty, this bug report is likely a false positive and should not be 00130 /// shown to the user. 00131 /// 00132 /// \sa markInvalid 00133 /// \sa removeInvalidation 00134 llvm::SmallSet<InvalidationRecord, 4> Invalidations; 00135 00136 private: 00137 // Used internally by BugReporter. 00138 Symbols &getInterestingSymbols(); 00139 Regions &getInterestingRegions(); 00140 00141 void lazyInitializeInterestingSets(); 00142 void pushInterestingSymbolsAndRegions(); 00143 void popInterestingSymbolsAndRegions(); 00144 00145 public: 00146 BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode) 00147 : BT(bt), DeclWithIssue(nullptr), Description(desc), ErrorNode(errornode), 00148 ConfigurationChangeToken(0), DoNotPrunePath(false) {} 00149 00150 BugReport(BugType& bt, StringRef shortDesc, StringRef desc, 00151 const ExplodedNode *errornode) 00152 : BT(bt), DeclWithIssue(nullptr), ShortDescription(shortDesc), 00153 Description(desc), ErrorNode(errornode), ConfigurationChangeToken(0), 00154 DoNotPrunePath(false) {} 00155 00156 BugReport(BugType &bt, StringRef desc, PathDiagnosticLocation l) 00157 : BT(bt), DeclWithIssue(nullptr), Description(desc), Location(l), 00158 ErrorNode(nullptr), ConfigurationChangeToken(0), DoNotPrunePath(false) {} 00159 00160 /// \brief Create a BugReport with a custom uniqueing location. 00161 /// 00162 /// The reports that have the same report location, description, bug type, and 00163 /// ranges are uniqued - only one of the equivalent reports will be presented 00164 /// to the user. This method allows to rest the location which should be used 00165 /// for uniquing reports. For example, memory leaks checker, could set this to 00166 /// the allocation site, rather then the location where the bug is reported. 00167 BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode, 00168 PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique) 00169 : BT(bt), DeclWithIssue(nullptr), Description(desc), 00170 UniqueingLocation(LocationToUnique), 00171 UniqueingDecl(DeclToUnique), 00172 ErrorNode(errornode), ConfigurationChangeToken(0), 00173 DoNotPrunePath(false) {} 00174 00175 virtual ~BugReport(); 00176 00177 const BugType& getBugType() const { return BT; } 00178 BugType& getBugType() { return BT; } 00179 00180 const ExplodedNode *getErrorNode() const { return ErrorNode; } 00181 00182 StringRef getDescription() const { return Description; } 00183 00184 StringRef getShortDescription(bool UseFallback = true) const { 00185 if (ShortDescription.empty() && UseFallback) 00186 return Description; 00187 return ShortDescription; 00188 } 00189 00190 /// Indicates whether or not any path pruning should take place 00191 /// when generating a PathDiagnostic from this BugReport. 00192 bool shouldPrunePath() const { return !DoNotPrunePath; } 00193 00194 /// Disable all path pruning when generating a PathDiagnostic. 00195 void disablePathPruning() { DoNotPrunePath = true; } 00196 00197 void markInteresting(SymbolRef sym); 00198 void markInteresting(const MemRegion *R); 00199 void markInteresting(SVal V); 00200 void markInteresting(const LocationContext *LC); 00201 00202 bool isInteresting(SymbolRef sym); 00203 bool isInteresting(const MemRegion *R); 00204 bool isInteresting(SVal V); 00205 bool isInteresting(const LocationContext *LC); 00206 00207 unsigned getConfigurationChangeToken() const { 00208 return ConfigurationChangeToken; 00209 } 00210 00211 /// Returns whether or not this report should be considered valid. 00212 /// 00213 /// Invalid reports are those that have been classified as likely false 00214 /// positives after the fact. 00215 bool isValid() const { 00216 return Invalidations.empty(); 00217 } 00218 00219 /// Marks the current report as invalid, meaning that it is probably a false 00220 /// positive and should not be reported to the user. 00221 /// 00222 /// The \p Tag and \p Data arguments are intended to be opaque identifiers for 00223 /// this particular invalidation, where \p Tag represents the visitor 00224 /// responsible for invalidation, and \p Data represents the reason this 00225 /// visitor decided to invalidate the bug report. 00226 /// 00227 /// \sa removeInvalidation 00228 void markInvalid(const void *Tag, const void *Data) { 00229 Invalidations.insert(std::make_pair(Tag, Data)); 00230 } 00231 00232 /// Reverses the effects of a previous invalidation. 00233 /// 00234 /// \sa markInvalid 00235 void removeInvalidation(const void *Tag, const void *Data) { 00236 Invalidations.erase(std::make_pair(Tag, Data)); 00237 } 00238 00239 /// Return the canonical declaration, be it a method or class, where 00240 /// this issue semantically occurred. 00241 const Decl *getDeclWithIssue() const; 00242 00243 /// Specifically set the Decl where an issue occurred. This isn't necessary 00244 /// for BugReports that cover a path as it will be automatically inferred. 00245 void setDeclWithIssue(const Decl *declWithIssue) { 00246 DeclWithIssue = declWithIssue; 00247 } 00248 00249 /// \brief This allows for addition of meta data to the diagnostic. 00250 /// 00251 /// Currently, only the HTMLDiagnosticClient knows how to display it. 00252 void addExtraText(StringRef S) { 00253 ExtraText.push_back(S); 00254 } 00255 00256 virtual const ExtraTextList &getExtraText() { 00257 return ExtraText; 00258 } 00259 00260 /// \brief Return the "definitive" location of the reported bug. 00261 /// 00262 /// While a bug can span an entire path, usually there is a specific 00263 /// location that can be used to identify where the key issue occurred. 00264 /// This location is used by clients rendering diagnostics. 00265 virtual PathDiagnosticLocation getLocation(const SourceManager &SM) const; 00266 00267 /// \brief Get the location on which the report should be uniqued. 00268 PathDiagnosticLocation getUniqueingLocation() const { 00269 return UniqueingLocation; 00270 } 00271 00272 /// \brief Get the declaration containing the uniqueing location. 00273 const Decl *getUniqueingDecl() const { 00274 return UniqueingDecl; 00275 } 00276 00277 const Stmt *getStmt() const; 00278 00279 /// \brief Add a range to a bug report. 00280 /// 00281 /// Ranges are used to highlight regions of interest in the source code. 00282 /// They should be at the same source code line as the BugReport location. 00283 /// By default, the source range of the statement corresponding to the error 00284 /// node will be used; add a single invalid range to specify absence of 00285 /// ranges. 00286 void addRange(SourceRange R) { 00287 assert((R.isValid() || Ranges.empty()) && "Invalid range can only be used " 00288 "to specify that the report does not have a range."); 00289 Ranges.push_back(R); 00290 } 00291 00292 /// \brief Get the SourceRanges associated with the report. 00293 virtual std::pair<ranges_iterator, ranges_iterator> getRanges(); 00294 00295 /// \brief Add custom or predefined bug report visitors to this report. 00296 /// 00297 /// The visitors should be used when the default trace is not sufficient. 00298 /// For example, they allow constructing a more elaborate trace. 00299 /// \sa registerConditionVisitor(), registerTrackNullOrUndefValue(), 00300 /// registerFindLastStore(), registerNilReceiverVisitor(), and 00301 /// registerVarDeclsLastStore(). 00302 void addVisitor(std::unique_ptr<BugReporterVisitor> visitor); 00303 00304 /// Iterators through the custom diagnostic visitors. 00305 visitor_iterator visitor_begin() { return Callbacks.begin(); } 00306 visitor_iterator visitor_end() { return Callbacks.end(); } 00307 00308 /// Profile to identify equivalent bug reports for error report coalescing. 00309 /// Reports are uniqued to ensure that we do not emit multiple diagnostics 00310 /// for each bug. 00311 virtual void Profile(llvm::FoldingSetNodeID& hash) const; 00312 }; 00313 00314 } // end ento namespace 00315 } // end clang namespace 00316 00317 namespace llvm { 00318 template<> struct ilist_traits<clang::ento::BugReport> 00319 : public ilist_default_traits<clang::ento::BugReport> { 00320 clang::ento::BugReport *createSentinel() const { 00321 return static_cast<clang::ento::BugReport *>(&Sentinel); 00322 } 00323 void destroySentinel(clang::ento::BugReport *) const {} 00324 00325 clang::ento::BugReport *provideInitialHead() const { 00326 return createSentinel(); 00327 } 00328 clang::ento::BugReport *ensureHead(clang::ento::BugReport *) const { 00329 return createSentinel(); 00330 } 00331 private: 00332 mutable ilist_half_node<clang::ento::BugReport> Sentinel; 00333 }; 00334 } 00335 00336 namespace clang { 00337 namespace ento { 00338 00339 //===----------------------------------------------------------------------===// 00340 // BugTypes (collections of related reports). 00341 //===----------------------------------------------------------------------===// 00342 00343 class BugReportEquivClass : public llvm::FoldingSetNode { 00344 /// List of *owned* BugReport objects. 00345 llvm::ilist<BugReport> Reports; 00346 00347 friend class BugReporter; 00348 void AddReport(std::unique_ptr<BugReport> R) { 00349 Reports.push_back(R.release()); 00350 } 00351 00352 public: 00353 BugReportEquivClass(std::unique_ptr<BugReport> R) { AddReport(std::move(R)); } 00354 ~BugReportEquivClass(); 00355 00356 void Profile(llvm::FoldingSetNodeID& ID) const { 00357 assert(!Reports.empty()); 00358 Reports.front().Profile(ID); 00359 } 00360 00361 typedef llvm::ilist<BugReport>::iterator iterator; 00362 typedef llvm::ilist<BugReport>::const_iterator const_iterator; 00363 00364 iterator begin() { return Reports.begin(); } 00365 iterator end() { return Reports.end(); } 00366 00367 const_iterator begin() const { return Reports.begin(); } 00368 const_iterator end() const { return Reports.end(); } 00369 }; 00370 00371 //===----------------------------------------------------------------------===// 00372 // BugReporter and friends. 00373 //===----------------------------------------------------------------------===// 00374 00375 class BugReporterData { 00376 public: 00377 virtual ~BugReporterData(); 00378 virtual DiagnosticsEngine& getDiagnostic() = 0; 00379 virtual ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() = 0; 00380 virtual ASTContext &getASTContext() = 0; 00381 virtual SourceManager& getSourceManager() = 0; 00382 virtual AnalyzerOptions& getAnalyzerOptions() = 0; 00383 }; 00384 00385 /// BugReporter is a utility class for generating PathDiagnostics for analysis. 00386 /// It collects the BugReports and BugTypes and knows how to generate 00387 /// and flush the corresponding diagnostics. 00388 class BugReporter { 00389 public: 00390 enum Kind { BaseBRKind, GRBugReporterKind }; 00391 00392 private: 00393 typedef llvm::ImmutableSet<BugType*> BugTypesTy; 00394 BugTypesTy::Factory F; 00395 BugTypesTy BugTypes; 00396 00397 const Kind kind; 00398 BugReporterData& D; 00399 00400 /// Generate and flush the diagnostics for the given bug report. 00401 void FlushReport(BugReportEquivClass& EQ); 00402 00403 /// Generate and flush the diagnostics for the given bug report 00404 /// and PathDiagnosticConsumer. 00405 void FlushReport(BugReport *exampleReport, 00406 PathDiagnosticConsumer &PD, 00407 ArrayRef<BugReport*> BugReports); 00408 00409 /// The set of bug reports tracked by the BugReporter. 00410 llvm::FoldingSet<BugReportEquivClass> EQClasses; 00411 /// A vector of BugReports for tracking the allocated pointers and cleanup. 00412 std::vector<BugReportEquivClass *> EQClassesVector; 00413 00414 protected: 00415 BugReporter(BugReporterData& d, Kind k) : BugTypes(F.getEmptySet()), kind(k), 00416 D(d) {} 00417 00418 public: 00419 BugReporter(BugReporterData& d) : BugTypes(F.getEmptySet()), kind(BaseBRKind), 00420 D(d) {} 00421 virtual ~BugReporter(); 00422 00423 /// \brief Generate and flush diagnostics for all bug reports. 00424 void FlushReports(); 00425 00426 Kind getKind() const { return kind; } 00427 00428 DiagnosticsEngine& getDiagnostic() { 00429 return D.getDiagnostic(); 00430 } 00431 00432 ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() { 00433 return D.getPathDiagnosticConsumers(); 00434 } 00435 00436 /// \brief Iterator over the set of BugTypes tracked by the BugReporter. 00437 typedef BugTypesTy::iterator iterator; 00438 iterator begin() { return BugTypes.begin(); } 00439 iterator end() { return BugTypes.end(); } 00440 00441 /// \brief Iterator over the set of BugReports tracked by the BugReporter. 00442 typedef llvm::FoldingSet<BugReportEquivClass>::iterator EQClasses_iterator; 00443 EQClasses_iterator EQClasses_begin() { return EQClasses.begin(); } 00444 EQClasses_iterator EQClasses_end() { return EQClasses.end(); } 00445 00446 ASTContext &getContext() { return D.getASTContext(); } 00447 00448 SourceManager& getSourceManager() { return D.getSourceManager(); } 00449 00450 AnalyzerOptions& getAnalyzerOptions() { return D.getAnalyzerOptions(); } 00451 00452 virtual bool generatePathDiagnostic(PathDiagnostic& pathDiagnostic, 00453 PathDiagnosticConsumer &PC, 00454 ArrayRef<BugReport *> &bugReports) { 00455 return true; 00456 } 00457 00458 bool RemoveUnneededCalls(PathPieces &pieces, BugReport *R); 00459 00460 void Register(BugType *BT); 00461 00462 /// \brief Add the given report to the set of reports tracked by BugReporter. 00463 /// 00464 /// The reports are usually generated by the checkers. Further, they are 00465 /// folded based on the profile value, which is done to coalesce similar 00466 /// reports. 00467 void emitReport(BugReport *R); 00468 00469 void EmitBasicReport(const Decl *DeclWithIssue, const CheckerBase *Checker, 00470 StringRef BugName, StringRef BugCategory, 00471 StringRef BugStr, PathDiagnosticLocation Loc, 00472 ArrayRef<SourceRange> Ranges = None); 00473 00474 void EmitBasicReport(const Decl *DeclWithIssue, CheckName CheckName, 00475 StringRef BugName, StringRef BugCategory, 00476 StringRef BugStr, PathDiagnosticLocation Loc, 00477 ArrayRef<SourceRange> Ranges = None); 00478 00479 private: 00480 llvm::StringMap<BugType *> StrBugTypes; 00481 00482 /// \brief Returns a BugType that is associated with the given name and 00483 /// category. 00484 BugType *getBugTypeForName(CheckName CheckName, StringRef name, 00485 StringRef category); 00486 }; 00487 00488 // FIXME: Get rid of GRBugReporter. It's the wrong abstraction. 00489 class GRBugReporter : public BugReporter { 00490 ExprEngine& Eng; 00491 public: 00492 GRBugReporter(BugReporterData& d, ExprEngine& eng) 00493 : BugReporter(d, GRBugReporterKind), Eng(eng) {} 00494 00495 virtual ~GRBugReporter(); 00496 00497 /// getEngine - Return the analysis engine used to analyze a given 00498 /// function or method. 00499 ExprEngine &getEngine() { return Eng; } 00500 00501 /// getGraph - Get the exploded graph created by the analysis engine 00502 /// for the analyzed method or function. 00503 ExplodedGraph &getGraph(); 00504 00505 /// getStateManager - Return the state manager used by the analysis 00506 /// engine. 00507 ProgramStateManager &getStateManager(); 00508 00509 /// Generates a path corresponding to one of the given bug reports. 00510 /// 00511 /// Which report is used for path generation is not specified. The 00512 /// bug reporter will try to pick the shortest path, but this is not 00513 /// guaranteed. 00514 /// 00515 /// \return True if the report was valid and a path was generated, 00516 /// false if the reports should be considered invalid. 00517 bool generatePathDiagnostic(PathDiagnostic &PD, PathDiagnosticConsumer &PC, 00518 ArrayRef<BugReport*> &bugReports) override; 00519 00520 /// classof - Used by isa<>, cast<>, and dyn_cast<>. 00521 static bool classof(const BugReporter* R) { 00522 return R->getKind() == GRBugReporterKind; 00523 } 00524 }; 00525 00526 class BugReporterContext { 00527 virtual void anchor(); 00528 GRBugReporter &BR; 00529 public: 00530 BugReporterContext(GRBugReporter& br) : BR(br) {} 00531 00532 virtual ~BugReporterContext() {} 00533 00534 GRBugReporter& getBugReporter() { return BR; } 00535 00536 ExplodedGraph &getGraph() { return BR.getGraph(); } 00537 00538 ProgramStateManager& getStateManager() { 00539 return BR.getStateManager(); 00540 } 00541 00542 SValBuilder& getSValBuilder() { 00543 return getStateManager().getSValBuilder(); 00544 } 00545 00546 ASTContext &getASTContext() { 00547 return BR.getContext(); 00548 } 00549 00550 SourceManager& getSourceManager() { 00551 return BR.getSourceManager(); 00552 } 00553 00554 virtual BugReport::NodeResolver& getNodeResolver() = 0; 00555 }; 00556 00557 } // end GR namespace 00558 00559 } // end clang namespace 00560 00561 #endif