diff options
Diffstat (limited to 'include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h')
-rw-r--r-- | include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h | 231 |
1 files changed, 167 insertions, 64 deletions
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h index 6d53c097d29f..406be3cc4bd4 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h @@ -16,6 +16,7 @@ #include "clang/Basic/Diagnostic.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/PointerUnion.h" #include <deque> #include <iterator> #include <string> @@ -23,42 +24,55 @@ namespace clang { +class AnalysisContext; +class BinaryOperator; +class CompoundStmt; class Decl; +class LocationContext; +class MemberExpr; +class ParentMap; +class ProgramPoint; class SourceManager; class Stmt; namespace ento { +class ExplodedNode; + //===----------------------------------------------------------------------===// // High-level interface for handlers of path-sensitive diagnostics. //===----------------------------------------------------------------------===// class PathDiagnostic; -class PathDiagnosticClient : public DiagnosticClient { +class PathDiagnosticConsumer { public: - PathDiagnosticClient() {} + PathDiagnosticConsumer() {} - virtual ~PathDiagnosticClient() {} + virtual ~PathDiagnosticConsumer() {} virtual void - FlushDiagnostics(llvm::SmallVectorImpl<std::string> *FilesMade = 0) = 0; + FlushDiagnostics(SmallVectorImpl<std::string> *FilesMade = 0) = 0; - void FlushDiagnostics(llvm::SmallVectorImpl<std::string> &FilesMade) { + void FlushDiagnostics(SmallVectorImpl<std::string> &FilesMade) { FlushDiagnostics(&FilesMade); } - virtual llvm::StringRef getName() const = 0; + virtual StringRef getName() const = 0; - virtual void HandleDiagnostic(Diagnostic::Level DiagLevel, - const DiagnosticInfo &Info); - virtual void HandlePathDiagnostic(const PathDiagnostic* D) = 0; + void HandlePathDiagnostic(const PathDiagnostic* D); enum PathGenerationScheme { Minimal, Extensive }; virtual PathGenerationScheme getGenerationScheme() const { return Minimal; } virtual bool supportsLogicalOpControlFlow() const { return false; } virtual bool supportsAllBlockEdges() const { return false; } virtual bool useVerboseDescription() const { return true; } + +protected: + /// The actual logic for handling path diagnostics, as implemented + /// by subclasses of PathDiagnosticConsumer. + virtual void HandlePathDiagnosticImpl(const PathDiagnostic* D) = 0; + }; //===----------------------------------------------------------------------===// @@ -67,60 +81,143 @@ public: class PathDiagnosticRange : public SourceRange { public: - const bool isPoint; + bool isPoint; PathDiagnosticRange(const SourceRange &R, bool isP = false) : SourceRange(R), isPoint(isP) {} + + PathDiagnosticRange() : isPoint(false) {} }; +typedef llvm::PointerUnion<const LocationContext*, AnalysisContext*> + LocationOrAnalysisContext; + class PathDiagnosticLocation { private: enum Kind { RangeK, SingleLocK, StmtK, DeclK } K; - SourceRange R; const Stmt *S; const Decl *D; const SourceManager *SM; + FullSourceLoc Loc; + PathDiagnosticRange Range; + + PathDiagnosticLocation(SourceLocation L, const SourceManager &sm, + Kind kind) + : K(kind), S(0), D(0), SM(&sm), + Loc(genLocation(L)), Range(genRange()) { + assert(Loc.isValid()); + assert(Range.isValid()); + } + + FullSourceLoc + genLocation(SourceLocation L = SourceLocation(), + LocationOrAnalysisContext LAC = (AnalysisContext*)0) const; + + PathDiagnosticRange + genRange(LocationOrAnalysisContext LAC = (AnalysisContext*)0) const; + public: + /// Create an invalid location. PathDiagnosticLocation() : K(SingleLocK), S(0), D(0), SM(0) {} - PathDiagnosticLocation(FullSourceLoc L) - : K(SingleLocK), R(L, L), S(0), D(0), SM(&L.getManager()) {} + /// Create a location corresponding to the given statement. + PathDiagnosticLocation(const Stmt *s, + const SourceManager &sm, + LocationOrAnalysisContext lac) + : K(StmtK), S(s), D(0), SM(&sm), + Loc(genLocation(SourceLocation(), lac)), + Range(genRange(lac)) { + assert(Loc.isValid()); + assert(Range.isValid()); + } - PathDiagnosticLocation(const Stmt *s, const SourceManager &sm) - : K(StmtK), S(s), D(0), SM(&sm) {} + /// Create a location corresponding to the given declaration. + PathDiagnosticLocation(const Decl *d, const SourceManager &sm) + : K(DeclK), S(0), D(d), SM(&sm), + Loc(genLocation()), Range(genRange()) { + assert(Loc.isValid()); + assert(Range.isValid()); + } - PathDiagnosticLocation(SourceRange r, const SourceManager &sm) - : K(RangeK), R(r), S(0), D(0), SM(&sm) {} + /// Create a location corresponding to the given declaration. + static PathDiagnosticLocation create(const Decl *D, + const SourceManager &SM) { + return PathDiagnosticLocation(D, SM); + } - PathDiagnosticLocation(const Decl *d, const SourceManager &sm) - : K(DeclK), S(0), D(d), SM(&sm) {} + /// Create a location for the beginning of the declaration. + static PathDiagnosticLocation createBegin(const Decl *D, + const SourceManager &SM); + + /// Create a location for the beginning of the statement. + static PathDiagnosticLocation createBegin(const Stmt *S, + const SourceManager &SM, + const LocationOrAnalysisContext LAC); + + /// Create the location for the operator of the binary expression. + /// Assumes the statement has a valid location. + static PathDiagnosticLocation createOperatorLoc(const BinaryOperator *BO, + const SourceManager &SM); + + /// For member expressions, return the location of the '.' or '->'. + /// Assumes the statement has a valid location. + static PathDiagnosticLocation createMemberLoc(const MemberExpr *ME, + const SourceManager &SM); + + /// Create a location for the beginning of the compound statement. + /// Assumes the statement has a valid location. + static PathDiagnosticLocation createBeginBrace(const CompoundStmt *CS, + const SourceManager &SM); + + /// Create a location for the end of the compound statement. + /// Assumes the statement has a valid location. + static PathDiagnosticLocation createEndBrace(const CompoundStmt *CS, + const SourceManager &SM); + + /// Create a location for the beginning of the enclosing declaration body. + /// Defaults to the beginning of the first statement in the declaration body. + static PathDiagnosticLocation createDeclBegin(const LocationContext *LC, + const SourceManager &SM); + + /// Constructs a location for the end of the enclosing declaration body. + /// Defaults to the end of brace. + static PathDiagnosticLocation createDeclEnd(const LocationContext *LC, + const SourceManager &SM); + + /// Create a location corresponding to the given valid ExplodedNode. + static PathDiagnosticLocation create(const ProgramPoint& P, + const SourceManager &SMng); + + /// Create a location corresponding to the next valid ExplodedNode as end + /// of path location. + static PathDiagnosticLocation createEndOfPath(const ExplodedNode* N, + const SourceManager &SM); + + /// Convert the given location into a single kind location. + static PathDiagnosticLocation createSingleLocation( + const PathDiagnosticLocation &PDL); bool operator==(const PathDiagnosticLocation &X) const { - return K == X.K && R == X.R && S == X.S && D == X.D; + return K == X.K && Loc == X.Loc && Range == X.Range; } bool operator!=(const PathDiagnosticLocation &X) const { - return K != X.K || R != X.R || S != X.S || D != X.D;; - } - - PathDiagnosticLocation& operator=(const PathDiagnosticLocation &X) { - K = X.K; - R = X.R; - S = X.S; - D = X.D; - SM = X.SM; - return *this; + return !(*this == X); } bool isValid() const { return SM != 0; } - const SourceManager& getSourceManager() const { assert(isValid());return *SM;} + FullSourceLoc asLocation() const { + return Loc; + } + + PathDiagnosticRange asRange() const { + return Range; + } - FullSourceLoc asLocation() const; - PathDiagnosticRange asRange() const; const Stmt *asStmt() const { assert(isValid()); return S; } const Decl *asDecl() const { assert(isValid()); return D; } @@ -181,7 +278,7 @@ private: PathDiagnosticPiece& operator=(const PathDiagnosticPiece &P); protected: - PathDiagnosticPiece(llvm::StringRef s, Kind k, DisplayHint hint = Below); + PathDiagnosticPiece(StringRef s, Kind k, DisplayHint hint = Below); PathDiagnosticPiece(Kind k, DisplayHint hint = Below); @@ -191,7 +288,7 @@ public: const std::string& getString() const { return str; } /// getDisplayHint - Return a hint indicating where the diagnostic should - /// be displayed by the PathDiagnosticClient. + /// be displayed by the PathDiagnosticConsumer. DisplayHint getDisplayHint() const { return Hint; } virtual PathDiagnosticLocation getLocation() const = 0; @@ -199,9 +296,15 @@ public: Kind getKind() const { return kind; } - void addRange(SourceRange R) { ranges.push_back(R); } + void addRange(SourceRange R) { + if (!R.isValid()) + return; + ranges.push_back(R); + } void addRange(SourceLocation B, SourceLocation E) { + if (!B.isValid() || !E.isValid()) + return; ranges.push_back(SourceRange(B,E)); } @@ -230,7 +333,7 @@ public: : &FixItHints[0] + FixItHints.size(); } - static inline bool classof(const PathDiagnosticPiece* P) { + static inline bool classof(const PathDiagnosticPiece *P) { return true; } @@ -242,11 +345,11 @@ private: PathDiagnosticLocation Pos; public: PathDiagnosticSpotPiece(const PathDiagnosticLocation &pos, - llvm::StringRef s, + StringRef s, PathDiagnosticPiece::Kind k, bool addPosRange = true) : PathDiagnosticPiece(s, k), Pos(pos) { - assert(Pos.asLocation().isValid() && + assert(Pos.isValid() && Pos.asLocation().isValid() && "PathDiagnosticSpotPiece's must have a valid location."); if (addPosRange && Pos.hasRange()) addRange(Pos.asRange()); } @@ -261,12 +364,12 @@ class PathDiagnosticEventPiece : public PathDiagnosticSpotPiece { public: PathDiagnosticEventPiece(const PathDiagnosticLocation &pos, - llvm::StringRef s, bool addPosRange = true) + StringRef s, bool addPosRange = true) : PathDiagnosticSpotPiece(pos, s, Event, addPosRange) {} ~PathDiagnosticEventPiece(); - static inline bool classof(const PathDiagnosticPiece* P) { + static inline bool classof(const PathDiagnosticPiece *P) { return P->getKind() == Event; } }; @@ -276,7 +379,7 @@ class PathDiagnosticControlFlowPiece : public PathDiagnosticPiece { public: PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos, const PathDiagnosticLocation &endPos, - llvm::StringRef s) + StringRef s) : PathDiagnosticPiece(s, ControlFlow) { LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos)); } @@ -320,7 +423,7 @@ public: const_iterator begin() const { return LPairs.begin(); } const_iterator end() const { return LPairs.end(); } - static inline bool classof(const PathDiagnosticPiece* P) { + static inline bool classof(const PathDiagnosticPiece *P) { return P->getKind() == ControlFlow; } @@ -337,7 +440,7 @@ public: bool containsEvent() const; - void push_back(PathDiagnosticPiece* P) { SubPieces.push_back(P); } + void push_back(PathDiagnosticPiece *P) { SubPieces.push_back(P); } typedef std::vector<PathDiagnosticPiece*>::iterator iterator; iterator begin() { return SubPieces.begin(); } @@ -352,7 +455,7 @@ public: const_iterator begin() const { return SubPieces.begin(); } const_iterator end() const { return SubPieces.end(); } - static inline bool classof(const PathDiagnosticPiece* P) { + static inline bool classof(const PathDiagnosticPiece *P) { return P->getKind() == Macro; } @@ -373,42 +476,42 @@ class PathDiagnostic : public llvm::FoldingSetNode { public: PathDiagnostic(); - PathDiagnostic(llvm::StringRef bugtype, llvm::StringRef desc, - llvm::StringRef category); + PathDiagnostic(StringRef bugtype, StringRef desc, + StringRef category); ~PathDiagnostic(); - llvm::StringRef getDescription() const { return Desc; } - llvm::StringRef getBugType() const { return BugType; } - llvm::StringRef getCategory() const { return Category; } + StringRef getDescription() const { return Desc; } + StringRef getBugType() const { return BugType; } + StringRef getCategory() const { return Category; } typedef std::deque<std::string>::const_iterator meta_iterator; meta_iterator meta_begin() const { return OtherDesc.begin(); } meta_iterator meta_end() const { return OtherDesc.end(); } - void addMeta(llvm::StringRef s) { OtherDesc.push_back(s); } + void addMeta(StringRef s) { OtherDesc.push_back(s); } PathDiagnosticLocation getLocation() const { assert(Size > 0 && "getLocation() requires a non-empty PathDiagnostic."); return rbegin()->getLocation(); } - void push_front(PathDiagnosticPiece* piece) { + void push_front(PathDiagnosticPiece *piece) { assert(piece); path.push_front(piece); ++Size; } - void push_back(PathDiagnosticPiece* piece) { + void push_back(PathDiagnosticPiece *piece) { assert(piece); path.push_back(piece); ++Size; } - PathDiagnosticPiece* back() { + PathDiagnosticPiece *back() { return path.back(); } - const PathDiagnosticPiece* back() const { + const PathDiagnosticPiece *back() const { return path.back(); } @@ -433,14 +536,14 @@ public: public: iterator(const ImplTy& i) : I(i) {} - bool operator==(const iterator& X) const { return I == X.I; } - bool operator!=(const iterator& X) const { return I != X.I; } + bool operator==(const iterator &X) const { return I == X.I; } + bool operator!=(const iterator &X) const { return I != X.I; } PathDiagnosticPiece& operator*() const { return **I; } - PathDiagnosticPiece* operator->() const { return *I; } + PathDiagnosticPiece *operator->() const { return *I; } - iterator& operator++() { ++I; return *this; } - iterator& operator--() { --I; return *this; } + iterator &operator++() { ++I; return *this; } + iterator &operator--() { --I; return *this; } }; class const_iterator { @@ -459,14 +562,14 @@ public: public: const_iterator(const ImplTy& i) : I(i) {} - bool operator==(const const_iterator& X) const { return I == X.I; } - bool operator!=(const const_iterator& X) const { return I != X.I; } + bool operator==(const const_iterator &X) const { return I == X.I; } + bool operator!=(const const_iterator &X) const { return I != X.I; } reference operator*() const { return **I; } pointer operator->() const { return *I; } - const_iterator& operator++() { ++I; return *this; } - const_iterator& operator--() { --I; return *this; } + const_iterator &operator++() { ++I; return *this; } + const_iterator &operator--() { --I; return *this; } }; typedef std::reverse_iterator<iterator> reverse_iterator; |