diff options
Diffstat (limited to 'include/clang/StaticAnalyzer/Core')
9 files changed, 92 insertions, 18 deletions
diff --git a/include/clang/StaticAnalyzer/Core/Checker.h b/include/clang/StaticAnalyzer/Core/Checker.h index 8c2ffc6..eb38bd8 100644 --- a/include/clang/StaticAnalyzer/Core/Checker.h +++ b/include/clang/StaticAnalyzer/Core/Checker.h @@ -63,6 +63,24 @@ public: } }; +class EndOfTranslationUnit { + template <typename CHECKER> + static void _checkEndOfTranslationUnit(void *checker, + const TranslationUnitDecl *TU, + AnalysisManager& mgr, + BugReporter &BR) { + ((const CHECKER *)checker)->checkEndOfTranslationUnit(TU, mgr, BR); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr){ + mgr._registerForEndOfTranslationUnit( + CheckerManager::CheckEndOfTranslationUnit(checker, + _checkEndOfTranslationUnit<CHECKER>)); + } +}; + template <typename STMT> class PreStmt { template <typename CHECKER> @@ -240,9 +258,11 @@ public: class RegionChanges { template <typename CHECKER> static const GRState *_checkRegionChanges(void *checker, const GRState *state, + const StoreManager::InvalidatedSymbols *invalidated, const MemRegion * const *Begin, const MemRegion * const *End) { - return ((const CHECKER *)checker)->checkRegionChanges(state, Begin, End); + return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated, + Begin, End); } template <typename CHECKER> static bool _wantsRegionChangeUpdate(void *checker, const GRState *state) { diff --git a/include/clang/StaticAnalyzer/Core/CheckerManager.h b/include/clang/StaticAnalyzer/Core/CheckerManager.h index 92ec038..45d38fb 100644 --- a/include/clang/StaticAnalyzer/Core/CheckerManager.h +++ b/include/clang/StaticAnalyzer/Core/CheckerManager.h @@ -18,6 +18,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" #include <vector> namespace clang { @@ -49,6 +50,18 @@ public: template <typename T> class CheckerFn; +template <typename RET, typename P1, typename P2, typename P3, typename P4> +class CheckerFn<RET(P1, P2, P3, P4)> { + typedef RET (*Func)(void *, P1, P2, P3, P4); + Func Fn; +public: + void *Checker; + CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { } + RET operator()(P1 p1, P2 p2, P3 p3, P4 p4) const { + return Fn(Checker, p1, p2, p3, p4); + } +}; + template <typename RET, typename P1, typename P2, typename P3> class CheckerFn<RET(P1, P2, P3)> { typedef RET (*Func)(void *, P1, P2, P3); @@ -224,9 +237,11 @@ public: bool wantsRegionChangeUpdate(const GRState *state); /// \brief Run checkers for region changes. - const GRState *runCheckersForRegionChanges(const GRState *state, - const MemRegion * const *Begin, - const MemRegion * const *End); + const GRState * + runCheckersForRegionChanges(const GRState *state, + const StoreManager::InvalidatedSymbols *invalidated, + const MemRegion * const *Begin, + const MemRegion * const *End); /// \brief Run checkers for handling assumptions on symbolic values. const GRState *runCheckersForEvalAssume(const GRState *state, @@ -237,6 +252,11 @@ public: const ExplodedNodeSet &Src, const CallExpr *CE, ExprEngine &Eng, GraphExpander *defaultEval = 0); + + /// \brief Run checkers for the entire Translation Unit. + void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl* TU, + AnalysisManager &mgr, + BugReporter &BR); //===----------------------------------------------------------------------===// // Internal registration functions for AST traversing. @@ -283,6 +303,7 @@ public: typedef CheckerFn<void (const GRState *,SymbolReaper &)> CheckLiveSymbolsFunc; typedef CheckerFn<const GRState * (const GRState *, + const StoreManager::InvalidatedSymbols *symbols, const MemRegion * const *begin, const MemRegion * const *end)> CheckRegionChangesFunc; @@ -296,6 +317,10 @@ public: typedef CheckerFn<bool (const CallExpr *, CheckerContext &)> EvalCallFunc; + typedef CheckerFn<void (const TranslationUnitDecl *, + AnalysisManager&, BugReporter &)> + CheckEndOfTranslationUnit; + typedef bool (*HandlesStmtFunc)(const Stmt *D); void _registerForPreStmt(CheckStmtFunc checkfn, HandlesStmtFunc isForStmtFn); @@ -326,6 +351,8 @@ public: void _registerForEvalCall(EvalCallFunc checkfn); + void _registerForEndOfTranslationUnit(CheckEndOfTranslationUnit checkfn); + //===----------------------------------------------------------------------===// // Internal registration functions for events. //===----------------------------------------------------------------------===// @@ -446,6 +473,8 @@ private: std::vector<EvalCallFunc> EvalCallCheckers; + std::vector<CheckEndOfTranslationUnit> EndOfTranslationUnitCheckers; + struct EventInfo { llvm::SmallVector<CheckEventFunc, 4> Checkers; bool HasDispatcher; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h index 65fbfcc..69495be 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h @@ -108,7 +108,8 @@ public: const llvm::APSInt &Convert(QualType T, const llvm::APSInt &From) { assert(T->isIntegerType() || Loc::isLocType(T)); unsigned bitwidth = Ctx.getTypeSize(T); - bool isUnsigned = T->isUnsignedIntegerType() || Loc::isLocType(T); + bool isUnsigned + = T->isUnsignedIntegerOrEnumerationType() || Loc::isLocType(T); if (isUnsigned == From.isUnsigned() && bitwidth == From.getBitWidth()) return From; @@ -131,13 +132,15 @@ public: inline const llvm::APSInt& getMaxValue(QualType T) { assert(T->isIntegerType() || Loc::isLocType(T)); - bool isUnsigned = T->isUnsignedIntegerType() || Loc::isLocType(T); + bool isUnsigned + = T->isUnsignedIntegerOrEnumerationType() || Loc::isLocType(T); return getValue(llvm::APSInt::getMaxValue(Ctx.getTypeSize(T), isUnsigned)); } inline const llvm::APSInt& getMinValue(QualType T) { assert(T->isIntegerType() || Loc::isLocType(T)); - bool isUnsigned = T->isUnsignedIntegerType() || Loc::isLocType(T); + bool isUnsigned + = T->isUnsignedIntegerOrEnumerationType() || Loc::isLocType(T); return getValue(llvm::APSInt::getMinValue(Ctx.getTypeSize(T), isUnsigned)); } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 8cd743f..d24036c 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -21,6 +21,7 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h" #include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h" #include "clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" #include "clang/AST/Type.h" #include "clang/AST/ExprObjC.h" @@ -188,9 +189,11 @@ public: /// processRegionChanges - Called by GRStateManager whenever a change is made /// to the store. Used to update checkers that track region values. - const GRState* processRegionChanges(const GRState *state, - const MemRegion * const *Begin, - const MemRegion * const *End); + const GRState * + processRegionChanges(const GRState *state, + const StoreManager::InvalidatedSymbols *invalidated, + const MemRegion * const *Begin, + const MemRegion * const *End); virtual GRStateManager& getStateManager() { return StateMgr; } @@ -458,6 +461,13 @@ private: const void *tag, bool isLoad); bool InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE, ExplodedNode *Pred); + + +public: + /// Returns true if calling the specific function or method would possibly + /// cause global variables to be invalidated. + bool doesInvalidateGlobals(const CallOrObjCMessage &callOrMessage) const; + }; } // end ento namespace diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/GRState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/GRState.h index a957c89..0d61d0e 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/GRState.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/GRState.h @@ -368,6 +368,12 @@ private: assert(refCount > 0); --refCount; } + + const GRState *invalidateRegionsImpl(const MemRegion * const *Begin, + const MemRegion * const *End, + const Expr *E, unsigned BlockCount, + StoreManager::InvalidatedSymbols &IS, + bool invalidateGlobals) const; }; class GRStateSet { diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h index 6d8fc89..734024c 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h @@ -187,6 +187,7 @@ public: return CallE && isa<CXXMemberCallExpr>(CallE); } + SVal getFunctionCallee() const; SVal getCXXCallee() const; unsigned getNumArgs() const { diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h index 0f9e56a..65eabea 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h @@ -172,7 +172,7 @@ public: nonloc::ConcreteInt makeIntVal(const IntegerLiteral* integer) { return nonloc::ConcreteInt( BasicVals.getValue(integer->getValue(), - integer->getType()->isUnsignedIntegerType())); + integer->getType()->isUnsignedIntegerOrEnumerationType())); } nonloc::ConcreteInt makeBoolVal(const CXXBoolLiteralExpr *boolean) { diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h index 21c6ae7..cdbdf64 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h @@ -188,7 +188,7 @@ public: const MemRegion * const *Begin, const MemRegion * const *End, const Expr *E, unsigned Count, - InvalidatedSymbols *IS, + InvalidatedSymbols &IS, bool invalidateGlobals, InvalidatedRegions *Regions) = 0; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h index 3d6f9fa..1f6ea3d 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h @@ -15,6 +15,7 @@ #include "clang/Analysis/ProgramPoint.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" namespace clang { @@ -95,13 +96,17 @@ public: /// processRegionChanges - Called by GRStateManager whenever a change is made /// to the store. Used to update checkers that track region values. - virtual const GRState* processRegionChanges(const GRState* state, - const MemRegion* const *Begin, - const MemRegion* const *End) = 0; + virtual const GRState * + processRegionChanges(const GRState *state, + const StoreManager::InvalidatedSymbols *invalidated, + const MemRegion* const *Begin, + const MemRegion* const *End) = 0; - inline const GRState* processRegionChange(const GRState* state, - const MemRegion* MR) { - return processRegionChanges(state, &MR, &MR+1); + + inline const GRState * + processRegionChange(const GRState* state, + const MemRegion* MR) { + return processRegionChanges(state, 0, &MR, &MR+1); } /// Called by CoreEngine when the analysis worklist is either empty or the |