diff options
author | Anna Zaks <ganna@apple.com> | 2011-08-19 22:33:38 +0000 |
---|---|---|
committer | Anna Zaks <ganna@apple.com> | 2011-08-19 22:33:38 +0000 |
commit | 50bbc165b063155cc23c360deb7b865502e068e2 (patch) | |
tree | 26bd4515516fcefcc82b4593b9754c6b1ede5700 /include/clang | |
parent | e6452785f095db92887ad403299bfa616ce198e2 (diff) |
Static Analyzer Diagnostics: Kill the addVisitorCreator(callbackTy, void*) API in favor of addVisitor(BugReporterVisitor*).
1) Create a header file to expose the predefined visitors. And move the parent(BugReporterVisitor) there as well.
2) Remove the registerXXXVisitor functions - the Visitor constructors/getters can be used now to create the object. One exception is registerVarDeclsLastStore(), which registers more then one visitor, so make it static member of FindLastStoreBRVisitor.
3) Modify all the checkers to use the new API.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@138126 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/clang')
-rw-r--r-- | include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h | 51 | ||||
-rw-r--r-- | include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h | 166 |
2 files changed, 168 insertions, 49 deletions
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h index 421e305508..a8923be63f 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h @@ -16,6 +16,7 @@ #define LLVM_CLANG_GR_BUGREPORTER #include "clang/Basic/SourceLocation.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ImmutableList.h" @@ -48,24 +49,6 @@ class BugType; // Interface for individual bug reports. //===----------------------------------------------------------------------===// -class BugReporterVisitor : public llvm::FoldingSetNode { -public: - virtual ~BugReporterVisitor(); - - /// \brief Return a diagnostic piece which should be associated with the - /// given node. - /// - /// The last parameter can be used to register a new visitor with the given - /// BugReport while processing a node. - virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N, - const ExplodedNode *PrevN, - BugReporterContext &BRC, - BugReport &BR) = 0; - - virtual bool isOwnedByReporterContext() { return true; } - virtual void Profile(llvm::FoldingSetNodeID &ID) const = 0; -}; - /// This class provides an interface through which checkers can create /// individual bug reports. class BugReport : public BugReporterVisitor { @@ -77,14 +60,12 @@ public: getOriginalNode(const ExplodedNode *N) = 0; }; - typedef void (*VisitorCreator)(BugReport &BR, const void *data); typedef const SourceRange *ranges_iterator; typedef llvm::ImmutableList<BugReporterVisitor*>::iterator visitor_iterator; protected: friend class BugReporter; friend class BugReportEquivClass; - typedef SmallVector<std::pair<VisitorCreator, const void*>, 2> Creators; BugType& BT; std::string ShortDescription; @@ -178,11 +159,7 @@ public: /// \sa registerConditionVisitor(), registerTrackNullOrUndefValue(), /// registerFindLastStore(), registerNilReceiverVisitor(), and /// registerVarDeclsLastStore(). - void addVisitorCreator(VisitorCreator creator, const void *data) { - creator(*this, data); - } - - void addVisitor(BugReporterVisitor* visitor); + void addVisitor(BugReporterVisitor *visitor); /// Iterators through the custom diagnostic visitors. visitor_iterator visitor_begin() { return Callbacks.begin(); } @@ -445,30 +422,6 @@ public: virtual BugReport::NodeResolver& getNodeResolver() = 0; }; -//===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// - -namespace bugreporter { - -const Stmt *GetDerefExpr(const ExplodedNode *N); -const Stmt *GetDenomExpr(const ExplodedNode *N); -const Stmt *GetCalleeExpr(const ExplodedNode *N); -const Stmt *GetRetValExpr(const ExplodedNode *N); - -void registerConditionVisitor(BugReport &BR); - -void registerTrackNullOrUndefValue(BugReport &BR, const void *stmt); - -void registerFindLastStore(BugReport &BR, const void *memregion); - -void registerNilReceiverVisitor(BugReport &BR); - -void registerVarDeclsLastStore(BugReport &BR, const void *stmt); - -} // end namespace clang::bugreporter - -//===----------------------------------------------------------------------===// - } // end GR namespace } // end clang namespace diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h new file mode 100644 index 0000000000..4533616d99 --- /dev/null +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h @@ -0,0 +1,166 @@ +//===--- BugReporterVisitor.h - Generate PathDiagnostics -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares BugReporterVisitors, which are used to generate enhanced +// diagnostic traces. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_GR_BUGREPORTERVISITOR +#define LLVM_CLANG_GR_BUGREPORTERVISITOR + +#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" +#include "llvm/ADT/FoldingSet.h" + +namespace clang { + +namespace ento { + +class BugReport; +class BugReporterContext; +class ExplodedNode; +class MemRegion; +class PathDiagnosticPiece; + +class BugReporterVisitor : public llvm::FoldingSetNode { +public: + virtual ~BugReporterVisitor(); + + /// \brief Return a diagnostic piece which should be associated with the + /// given node. + /// + /// The last parameter can be used to register a new visitor with the given + /// BugReport while processing a node. + virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N, + const ExplodedNode *PrevN, + BugReporterContext &BRC, + BugReport &BR) = 0; + + virtual bool isOwnedByReporterContext() { return true; } + virtual void Profile(llvm::FoldingSetNodeID &ID) const = 0; +}; + +class FindLastStoreBRVisitor : public BugReporterVisitor { + const MemRegion *R; + SVal V; + bool satisfied; + const ExplodedNode *StoreSite; + +public: + /// \brief Convenience method to create a visitor given only the MemRegion. + /// Returns NULL if the visitor cannot be created. For example, when the + /// corresponding value is unknown. + static BugReporterVisitor *createVisitorObject(const ExplodedNode *N, + const MemRegion *R); + + /// Creates a visitor for every VarDecl inside a Stmt and registers it with + /// the BugReport. + static void registerStatementVarDecls(BugReport &BR, const Stmt *S); + + FindLastStoreBRVisitor(SVal v, const MemRegion *r) + : R(r), V(v), satisfied(false), StoreSite(0) { + assert (!V.isUnknown() && "Cannot track unknown value."); + + // TODO: Does it make sense to allow undef values here? + // (If not, also see UndefCapturedBlockVarChecker)? + } + + void Profile(llvm::FoldingSetNodeID &ID) const; + + PathDiagnosticPiece *VisitNode(const ExplodedNode *N, + const ExplodedNode *PrevN, + BugReporterContext &BRC, + BugReport &BR); +}; + +class TrackConstraintBRVisitor : public BugReporterVisitor { + DefinedSVal Constraint; + const bool Assumption; + bool isSatisfied; + +public: + TrackConstraintBRVisitor(DefinedSVal constraint, bool assumption) + : Constraint(constraint), Assumption(assumption), isSatisfied(false) {} + + void Profile(llvm::FoldingSetNodeID &ID) const; + + PathDiagnosticPiece *VisitNode(const ExplodedNode *N, + const ExplodedNode *PrevN, + BugReporterContext &BRC, + BugReport &BR); +}; + +class NilReceiverBRVisitor : public BugReporterVisitor { +public: + void Profile(llvm::FoldingSetNodeID &ID) const { + static int x = 0; + ID.AddPointer(&x); + } + + PathDiagnosticPiece *VisitNode(const ExplodedNode *N, + const ExplodedNode *PrevN, + BugReporterContext &BRC, + BugReport &BR); +}; + +/// Visitor that tries to report interesting diagnostics from conditions. +class ConditionBRVisitor : public BugReporterVisitor { +public: + void Profile(llvm::FoldingSetNodeID &ID) const { + static int x = 0; + ID.AddPointer(&x); + } + + virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N, + const ExplodedNode *Prev, + BugReporterContext &BRC, + BugReport &BR); + + PathDiagnosticPiece *VisitTerminator(const Stmt *Term, + const ProgramState *CurrentState, + const ProgramState *PrevState, + const CFGBlock *srcBlk, + const CFGBlock *dstBlk, + BugReporterContext &BRC); + + PathDiagnosticPiece *VisitTrueTest(const Expr *Cond, + bool tookTrue, + BugReporterContext &BRC); + + PathDiagnosticPiece *VisitTrueTest(const Expr *Cond, + const DeclRefExpr *DR, + const bool tookTrue, + BugReporterContext &BRC); + + PathDiagnosticPiece *VisitTrueTest(const Expr *Cond, + const BinaryOperator *BExpr, + const bool tookTrue, + BugReporterContext &BRC); + + bool patternMatch(const Expr *Ex, + llvm::raw_ostream &Out, + BugReporterContext &BRC); +}; + +namespace bugreporter { + +BugReporterVisitor *getTrackNullOrUndefValueVisitor(const ExplodedNode *N, + const Stmt *S); + +const Stmt *GetDerefExpr(const ExplodedNode *N); +const Stmt *GetDenomExpr(const ExplodedNode *N); +const Stmt *GetCalleeExpr(const ExplodedNode *N); +const Stmt *GetRetValExpr(const ExplodedNode *N); + +} // end namespace clang +} // end namespace ento +} // end namespace bugreporter + + +#endif //LLVM_CLANG_GR__BUGREPORTERVISITOR |