diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2011-05-02 19:39:53 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2011-05-02 19:39:53 +0000 |
commit | 01af97d3b23bded2b2b21af19bbc6e4cce49e5b3 (patch) | |
tree | 64a10f4c4154739d4a8191d7e1b52ce497f4ebd6 /include/clang/Analysis | |
parent | c3b054d250cdca485c71845089c316e10610ebad (diff) |
Diffstat (limited to 'include/clang/Analysis')
-rw-r--r-- | include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h | 4 | ||||
-rw-r--r-- | include/clang/Analysis/Analyses/UninitializedValues.h | 82 | ||||
-rw-r--r-- | include/clang/Analysis/Analyses/UninitializedValuesV2.h | 40 | ||||
-rw-r--r-- | include/clang/Analysis/AnalysisContext.h | 60 | ||||
-rw-r--r-- | include/clang/Analysis/AnalysisDiagnostic.h | 3 | ||||
-rw-r--r-- | include/clang/Analysis/CFG.h | 120 | ||||
-rw-r--r-- | include/clang/Analysis/DomainSpecific/CocoaConventions.h | 2 | ||||
-rw-r--r-- | include/clang/Analysis/FlowSensitive/DataflowSolver.h | 8 | ||||
-rw-r--r-- | include/clang/Analysis/ProgramPoint.h | 13 | ||||
-rw-r--r-- | include/clang/Analysis/Visitors/CFGStmtVisitor.h | 5 |
10 files changed, 140 insertions, 197 deletions
diff --git a/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h b/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h index 72f644aaf0287..a61d9e47881d9 100644 --- a/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h +++ b/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h @@ -29,13 +29,13 @@ class CFGBlock; // tend to have a common destination, so we lazily do a predecessor search // from the destination node and cache the results to prevent work // duplication. -class CFGReachabilityAnalysis { +class CFGReverseBlockReachabilityAnalysis { typedef llvm::BitVector ReachableSet; typedef llvm::DenseMap<unsigned, ReachableSet> ReachableMap; ReachableSet analyzed; ReachableMap reachable; public: - CFGReachabilityAnalysis(const CFG &cfg); + CFGReverseBlockReachabilityAnalysis(const CFG &cfg); /// Returns true if the block 'Dst' can be reached from block 'Src'. bool isReachable(const CFGBlock *Src, const CFGBlock *Dst); diff --git a/include/clang/Analysis/Analyses/UninitializedValues.h b/include/clang/Analysis/Analyses/UninitializedValues.h index cd771acb06a5d..b966f3a90ffff 100644 --- a/include/clang/Analysis/Analyses/UninitializedValues.h +++ b/include/clang/Analysis/Analyses/UninitializedValues.h @@ -1,4 +1,4 @@ -//===- UninitializedValues.h - unintialized values analysis ----*- C++ --*-===// +//= UninitializedValues.h - Finding uses of uninitialized values --*- C++ -*-==// // // The LLVM Compiler Infrastructure // @@ -7,71 +7,35 @@ // //===----------------------------------------------------------------------===// // -// This file provides the interface for the Unintialized Values analysis, -// a flow-sensitive analysis that detects when variable values are unintialized. +// This file defines APIs for invoking and reported uninitialized values +// warnings. // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_UNITVALS_H -#define LLVM_CLANG_UNITVALS_H - -#include "clang/Analysis/Support/BlkExprDeclBitVector.h" -#include "clang/Analysis/FlowSensitive/DataflowValues.h" +#ifndef LLVM_CLANG_UNINIT_VALS_H +#define LLVM_CLANG_UNINIT_VALS_H namespace clang { - class BlockVarDecl; - class Expr; - class DeclRefExpr; - class VarDecl; - -/// UninitializedValues_ValueTypes - Utility class to wrap type declarations -/// for dataflow values and dataflow analysis state for the -/// Unitialized Values analysis. -class UninitializedValues_ValueTypes { -public: - - struct ObserverTy; - - struct AnalysisDataTy : public StmtDeclBitVector_Types::AnalysisDataTy { - AnalysisDataTy() : Observer(NULL), FullUninitTaint(true) {} - virtual ~AnalysisDataTy() {} - - ObserverTy* Observer; - bool FullUninitTaint; - }; - - typedef StmtDeclBitVector_Types::ValTy ValTy; - - //===--------------------------------------------------------------------===// - // ObserverTy - Observer for querying DeclRefExprs that use an uninitalized - // value. - //===--------------------------------------------------------------------===// - - struct ObserverTy { - virtual ~ObserverTy(); - virtual void ObserveDeclRefExpr(ValTy& Val, AnalysisDataTy& AD, - DeclRefExpr* DR, VarDecl* VD) = 0; - }; -}; - -/// UninitializedValues - Objects of this class encapsulate dataflow analysis -/// information regarding what variable declarations in a function are -/// potentially unintialized. -class UninitializedValues : - public DataflowValues<UninitializedValues_ValueTypes> { +class AnalysisContext; +class CFG; +class DeclContext; +class Expr; +class VarDecl; + +class UninitVariablesHandler { public: - typedef UninitializedValues_ValueTypes::ObserverTy ObserverTy; - - UninitializedValues(CFG &cfg) { getAnalysisData().setCFG(cfg); } - - /// IntializeValues - Create initial dataflow values and meta data for - /// a given CFG. This is intended to be called by the dataflow solver. - void InitializeValues(const CFG& cfg); + UninitVariablesHandler() {} + virtual ~UninitVariablesHandler(); + + virtual void handleUseOfUninitVariable(const Expr *ex, + const VarDecl *vd, + bool isAlwaysUninit) {} }; + +void runUninitializedVariablesAnalysis(const DeclContext &dc, const CFG &cfg, + AnalysisContext &ac, + UninitVariablesHandler &handler); - -void CheckUninitializedValues(CFG& cfg, ASTContext& Ctx, Diagnostic& Diags, - bool FullUninitTaint=false); -} // end namespace clang +} #endif diff --git a/include/clang/Analysis/Analyses/UninitializedValuesV2.h b/include/clang/Analysis/Analyses/UninitializedValuesV2.h deleted file mode 100644 index c1fe040793e12..0000000000000 --- a/include/clang/Analysis/Analyses/UninitializedValuesV2.h +++ /dev/null @@ -1,40 +0,0 @@ -//= UninitializedValuesV2.h - Finding uses of uninitialized values --*- C++ -*-= -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines APIs for invoking and reported uninitialized values -// warnings. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_UNINIT_VALS_H -#define LLVM_CLANG_UNINIT_VALS_H - -namespace clang { - -class AnalysisContext; -class CFG; -class DeclContext; -class Expr; -class VarDecl; - -class UninitVariablesHandler { -public: - UninitVariablesHandler() {} - virtual ~UninitVariablesHandler(); - - virtual void handleUseOfUninitVariable(const Expr *ex, - const VarDecl *vd) {} -}; - -void runUninitializedVariablesAnalysis(const DeclContext &dc, const CFG &cfg, - AnalysisContext &ac, - UninitVariablesHandler &handler); - -} -#endif diff --git a/include/clang/Analysis/AnalysisContext.h b/include/clang/Analysis/AnalysisContext.h index 851451457881c..66c12a5384d4c 100644 --- a/include/clang/Analysis/AnalysisContext.h +++ b/include/clang/Analysis/AnalysisContext.h @@ -17,6 +17,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" +#include "clang/Analysis/CFG.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/PointerUnion.h" @@ -27,9 +28,7 @@ namespace clang { class Decl; class Stmt; -class CFG; -class CFGBlock; -class CFGReachabilityAnalysis; +class CFGReverseBlockReachabilityAnalysis; class CFGStmtMap; class LiveVariables; class ParentMap; @@ -48,33 +47,32 @@ class AnalysisContext { // TranslationUnit is NULL if we don't have multiple translation units. idx::TranslationUnit *TU; - // AnalysisContext owns the following data. - CFG *cfg, *completeCFG; - CFGStmtMap *cfgStmtMap; + llvm::OwningPtr<CFG> cfg, completeCFG; + llvm::OwningPtr<CFGStmtMap> cfgStmtMap; + + CFG::BuildOptions cfgBuildOptions; + CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs; + bool builtCFG, builtCompleteCFG; - LiveVariables *liveness; - LiveVariables *relaxedLiveness; - ParentMap *PM; - PseudoConstantAnalysis *PCA; - CFGReachabilityAnalysis *CFA; - llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars; + const bool useUnoptimizedCFG; + + llvm::OwningPtr<LiveVariables> liveness; + llvm::OwningPtr<LiveVariables> relaxedLiveness; + llvm::OwningPtr<ParentMap> PM; + llvm::OwningPtr<PseudoConstantAnalysis> PCA; + llvm::OwningPtr<CFGReverseBlockReachabilityAnalysis> CFA; + llvm::BumpPtrAllocator A; - bool UseUnoptimizedCFG; - bool AddEHEdges; - bool AddImplicitDtors; - bool AddInitializers; + + // FIXME: remove. + llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars; + public: AnalysisContext(const Decl *d, idx::TranslationUnit *tu, bool useUnoptimizedCFG = false, bool addehedges = false, bool addImplicitDtors = false, - bool addInitializers = false) - : D(d), TU(tu), cfg(0), completeCFG(0), cfgStmtMap(0), - builtCFG(false), builtCompleteCFG(false), - liveness(0), relaxedLiveness(0), PM(0), PCA(0), CFA(0), - ReferencedBlockVars(0), UseUnoptimizedCFG(useUnoptimizedCFG), - AddEHEdges(addehedges), AddImplicitDtors(addImplicitDtors), - AddInitializers(addInitializers) {} + bool addInitializers = false); ~AnalysisContext(); @@ -87,18 +85,22 @@ public: /// callExprs. If this is false, then try/catch statements and blocks /// reachable from them can appear to be dead in the CFG, analysis passes must /// cope with that. - bool getAddEHEdges() const { return AddEHEdges; } - - bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; } - bool getAddImplicitDtors() const { return AddImplicitDtors; } - bool getAddInitializers() const { return AddInitializers; } + bool getAddEHEdges() const { return cfgBuildOptions.AddEHEdges; } + bool getUseUnoptimizedCFG() const { + return cfgBuildOptions.PruneTriviallyFalseEdges; + } + bool getAddImplicitDtors() const { return cfgBuildOptions.AddImplicitDtors; } + bool getAddInitializers() const { return cfgBuildOptions.AddInitializers; } + void registerForcedBlockExpression(const Stmt *stmt); + const CFGBlock *getBlockForRegisteredExpression(const Stmt *stmt); + Stmt *getBody(); CFG *getCFG(); CFGStmtMap *getCFGStmtMap(); - CFGReachabilityAnalysis *getCFGReachablityAnalysis(); + CFGReverseBlockReachabilityAnalysis *getCFGReachablityAnalysis(); /// Return a version of the CFG without any edges pruned. CFG *getUnoptimizedCFG(); diff --git a/include/clang/Analysis/AnalysisDiagnostic.h b/include/clang/Analysis/AnalysisDiagnostic.h index 295d0a2133d36..dbf4e4c9aefeb 100644 --- a/include/clang/Analysis/AnalysisDiagnostic.h +++ b/include/clang/Analysis/AnalysisDiagnostic.h @@ -15,7 +15,8 @@ namespace clang { namespace diag { enum { -#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM, +#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ + SFINAE,ACCESS,CATEGORY,BRIEF,FULL) ENUM, #define ANALYSISSTART #include "clang/Basic/DiagnosticAnalysisKinds.inc" #undef DIAG diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h index b337d74495c9b..ca46459afd9a8 100644 --- a/include/clang/Analysis/CFG.h +++ b/include/clang/Analysis/CFG.h @@ -19,6 +19,8 @@ #include "llvm/ADT/GraphTraits.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Casting.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/DenseMap.h" #include "clang/Analysis/Support/BumpVector.h" #include "clang/Basic/SourceLocation.h" #include <cassert> @@ -29,6 +31,7 @@ namespace llvm { } namespace clang { + class CXXDestructorDecl; class Decl; class Stmt; class Expr; @@ -47,45 +50,45 @@ class CFGElement { public: enum Kind { // main kind + Invalid, Statement, Initializer, - ImplicitDtor, // dtor kind AutomaticObjectDtor, BaseDtor, MemberDtor, TemporaryDtor, - DTOR_BEGIN = AutomaticObjectDtor + DTOR_BEGIN = AutomaticObjectDtor, + DTOR_END = TemporaryDtor }; protected: - // The int bits are used to mark the main kind. + // The int bits are used to mark the kind. llvm::PointerIntPair<void *, 2> Data1; - // The int bits are used to mark the dtor kind. llvm::PointerIntPair<void *, 2> Data2; - CFGElement(void *Ptr, unsigned Int) : Data1(Ptr, Int) {} - CFGElement(void *Ptr1, unsigned Int1, void *Ptr2, unsigned Int2) - : Data1(Ptr1, Int1), Data2(Ptr2, Int2) {} + CFGElement(Kind kind, const void *Ptr1, const void *Ptr2 = 0) + : Data1(const_cast<void*>(Ptr1), ((unsigned) kind) & 0x3), + Data2(const_cast<void*>(Ptr2), (((unsigned) kind) >> 2) & 0x3) {} public: CFGElement() {} - Kind getKind() const { return static_cast<Kind>(Data1.getInt()); } - - Kind getDtorKind() const { - assert(getKind() == ImplicitDtor); - return static_cast<Kind>(Data2.getInt() + DTOR_BEGIN); + Kind getKind() const { + unsigned x = Data2.getInt(); + x <<= 2; + x |= Data1.getInt(); + return (Kind) x; } - - bool isValid() const { return Data1.getPointer(); } + + bool isValid() const { return getKind() != Invalid; } operator bool() const { return isValid(); } - - template<class ElemTy> ElemTy getAs() const { + + template<class ElemTy> const ElemTy *getAs() const { if (llvm::isa<ElemTy>(this)) - return *static_cast<const ElemTy*>(this); - return ElemTy(); + return static_cast<const ElemTy*>(this); + return 0; } static bool classof(const CFGElement *E) { return true; } @@ -93,13 +96,10 @@ public: class CFGStmt : public CFGElement { public: - CFGStmt() {} - CFGStmt(Stmt *S) : CFGElement(S, 0) {} + CFGStmt(Stmt *S) : CFGElement(Statement, S) {} Stmt *getStmt() const { return static_cast<Stmt *>(Data1.getPointer()); } - operator Stmt*() const { return getStmt(); } - static bool classof(const CFGElement *E) { return E->getKind() == Statement; } @@ -109,14 +109,12 @@ public: /// constructor's initialization list. class CFGInitializer : public CFGElement { public: - CFGInitializer() {} - CFGInitializer(CXXCtorInitializer* I) - : CFGElement(I, Initializer) {} + CFGInitializer(CXXCtorInitializer *initializer) + : CFGElement(Initializer, initializer) {} CXXCtorInitializer* getInitializer() const { return static_cast<CXXCtorInitializer*>(Data1.getPointer()); } - operator CXXCtorInitializer*() const { return getInitializer(); } static bool classof(const CFGElement *E) { return E->getKind() == Initializer; @@ -127,14 +125,18 @@ public: /// by compiler on various occasions. class CFGImplicitDtor : public CFGElement { protected: - CFGImplicitDtor(unsigned K, void* P, void* S) - : CFGElement(P, ImplicitDtor, S, K - DTOR_BEGIN) {} + CFGImplicitDtor(Kind kind, const void *data1, const void *data2 = 0) + : CFGElement(kind, data1, data2) { + assert(kind >= DTOR_BEGIN && kind <= DTOR_END); + } public: - CFGImplicitDtor() {} + const CXXDestructorDecl *getDestructorDecl(ASTContext &astContext) const; + bool isNoReturn(ASTContext &astContext) const; static bool classof(const CFGElement *E) { - return E->getKind() == ImplicitDtor; + Kind kind = E->getKind(); + return kind >= DTOR_BEGIN && kind <= DTOR_END; } }; @@ -143,22 +145,20 @@ public: /// of leaving its local scope. class CFGAutomaticObjDtor: public CFGImplicitDtor { public: - CFGAutomaticObjDtor() {} - CFGAutomaticObjDtor(VarDecl* VD, Stmt* S) - : CFGImplicitDtor(AutomaticObjectDtor, VD, S) {} + CFGAutomaticObjDtor(const VarDecl *var, const Stmt *stmt) + : CFGImplicitDtor(AutomaticObjectDtor, var, stmt) {} - VarDecl* getVarDecl() const { + const VarDecl *getVarDecl() const { return static_cast<VarDecl*>(Data1.getPointer()); } // Get statement end of which triggered the destructor call. - Stmt* getTriggerStmt() const { + const Stmt *getTriggerStmt() const { return static_cast<Stmt*>(Data2.getPointer()); } - static bool classof(const CFGElement *E) { - return E->getKind() == ImplicitDtor && - E->getDtorKind() == AutomaticObjectDtor; + static bool classof(const CFGElement *elem) { + return elem->getKind() == AutomaticObjectDtor; } }; @@ -166,16 +166,15 @@ public: /// base object in destructor. class CFGBaseDtor : public CFGImplicitDtor { public: - CFGBaseDtor() {} - CFGBaseDtor(const CXXBaseSpecifier *BS) - : CFGImplicitDtor(BaseDtor, const_cast<CXXBaseSpecifier*>(BS), NULL) {} + CFGBaseDtor(const CXXBaseSpecifier *base) + : CFGImplicitDtor(BaseDtor, base) {} const CXXBaseSpecifier *getBaseSpecifier() const { return static_cast<const CXXBaseSpecifier*>(Data1.getPointer()); } static bool classof(const CFGElement *E) { - return E->getKind() == ImplicitDtor && E->getDtorKind() == BaseDtor; + return E->getKind() == BaseDtor; } }; @@ -183,16 +182,15 @@ public: /// member object in destructor. class CFGMemberDtor : public CFGImplicitDtor { public: - CFGMemberDtor() {} - CFGMemberDtor(FieldDecl *FD) - : CFGImplicitDtor(MemberDtor, FD, NULL) {} + CFGMemberDtor(const FieldDecl *field) + : CFGImplicitDtor(MemberDtor, field, 0) {} - FieldDecl *getFieldDecl() const { - return static_cast<FieldDecl*>(Data1.getPointer()); + const FieldDecl *getFieldDecl() const { + return static_cast<const FieldDecl*>(Data1.getPointer()); } static bool classof(const CFGElement *E) { - return E->getKind() == ImplicitDtor && E->getDtorKind() == MemberDtor; + return E->getKind() == MemberDtor; } }; @@ -200,16 +198,15 @@ public: /// at the end of full expression for temporary object. class CFGTemporaryDtor : public CFGImplicitDtor { public: - CFGTemporaryDtor() {} - CFGTemporaryDtor(CXXBindTemporaryExpr *E) - : CFGImplicitDtor(TemporaryDtor, E, NULL) {} + CFGTemporaryDtor(CXXBindTemporaryExpr *expr) + : CFGImplicitDtor(TemporaryDtor, expr, 0) {} - CXXBindTemporaryExpr *getBindTemporaryExpr() const { - return static_cast<CXXBindTemporaryExpr *>(Data1.getPointer()); + const CXXBindTemporaryExpr *getBindTemporaryExpr() const { + return static_cast<const CXXBindTemporaryExpr *>(Data1.getPointer()); } static bool classof(const CFGElement *E) { - return E->getKind() == ImplicitDtor && E->getDtorKind() == TemporaryDtor; + return E->getKind() == TemporaryDtor; } }; @@ -267,6 +264,8 @@ public: /// ? operator LHS expression; RHS expression /// &&, || expression that uses result of && or ||, RHS /// +/// But note that any of that may be NULL in case of optimized-out edges. +/// class CFGBlock { class ElementList { typedef BumpVector<CFGElement> ImplTy; @@ -471,8 +470,6 @@ public: const Stmt *getLoopTarget() const { return LoopTarget; } - bool hasBinaryBranchTerminator() const; - Stmt* getLabel() { return Label; } const Stmt* getLabel() const { return Label; } @@ -537,13 +534,16 @@ public: class BuildOptions { public: + typedef llvm::DenseMap<const Stmt *, const CFGBlock*> ForcedBlkExprs; + ForcedBlkExprs **forcedBlkExprs; + bool PruneTriviallyFalseEdges:1; bool AddEHEdges:1; bool AddInitializers:1; bool AddImplicitDtors:1; BuildOptions() - : PruneTriviallyFalseEdges(true) + : forcedBlkExprs(0), PruneTriviallyFalseEdges(true) , AddEHEdges(false) , AddInitializers(false) , AddImplicitDtors(false) {} @@ -552,7 +552,7 @@ public: /// buildCFG - Builds a CFG from an AST. The responsibility to free the /// constructed CFG belongs to the caller. static CFG* buildCFG(const Decl *D, Stmt* AST, ASTContext *C, - BuildOptions BO = BuildOptions()); + const BuildOptions &BO); /// createBlock - Create a new block in the CFG. The CFG owns the block; /// the caller should not directly free it. @@ -607,8 +607,8 @@ public: for (const_iterator I=begin(), E=end(); I != E; ++I) for (CFGBlock::const_iterator BI=(*I)->begin(), BE=(*I)->end(); BI != BE; ++BI) { - if (CFGStmt S = BI->getAs<CFGStmt>()) - O(S); + if (const CFGStmt *stmt = BI->getAs<CFGStmt>()) + O(stmt->getStmt()); } } diff --git a/include/clang/Analysis/DomainSpecific/CocoaConventions.h b/include/clang/Analysis/DomainSpecific/CocoaConventions.h index 7e6e3815400c1..18e81fed79f8b 100644 --- a/include/clang/Analysis/DomainSpecific/CocoaConventions.h +++ b/include/clang/Analysis/DomainSpecific/CocoaConventions.h @@ -22,7 +22,7 @@ namespace cocoa { enum NamingConvention { NoConvention, CreateRule, InitRule }; - NamingConvention deriveNamingConvention(Selector S, bool ignorePrefix = true); + NamingConvention deriveNamingConvention(Selector S); static inline bool followsFundamentalRule(Selector S) { return deriveNamingConvention(S) == CreateRule; diff --git a/include/clang/Analysis/FlowSensitive/DataflowSolver.h b/include/clang/Analysis/FlowSensitive/DataflowSolver.h index d75d333db6b6d..9561b964b5f8f 100644 --- a/include/clang/Analysis/FlowSensitive/DataflowSolver.h +++ b/include/clang/Analysis/FlowSensitive/DataflowSolver.h @@ -277,8 +277,8 @@ private: for (StmtItr I=ItrTraits::StmtBegin(B), E=ItrTraits::StmtEnd(B); I!=E;++I) { CFGElement El = *I; - if (CFGStmt S = El.getAs<CFGStmt>()) - ProcessStmt(S, recordStmtValues, AnalysisDirTag()); + if (const CFGStmt *S = El.getAs<CFGStmt>()) + ProcessStmt(S->getStmt(), recordStmtValues, AnalysisDirTag()); } TF.VisitTerminator(const_cast<CFGBlock*>(B)); @@ -293,8 +293,8 @@ private: for (StmtItr I=ItrTraits::StmtBegin(B), E=ItrTraits::StmtEnd(B); I!=E;++I) { CFGElement El = *I; - if (CFGStmt S = El.getAs<CFGStmt>()) - ProcessStmt(S, recordStmtValues, AnalysisDirTag()); + if (const CFGStmt *S = El.getAs<CFGStmt>()) + ProcessStmt(S->getStmt(), recordStmtValues, AnalysisDirTag()); } } diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h index 54cfc3dc0db6a..07b4dea987ded 100644 --- a/include/clang/Analysis/ProgramPoint.h +++ b/include/clang/Analysis/ProgramPoint.h @@ -43,6 +43,7 @@ public: PostStoreKind, PostPurgeDeadSymbolsKind, PostStmtCustomKind, + PostConditionKind, PostLValueKind, PostInitializerKind, CallEnterKind, @@ -221,7 +222,17 @@ public: } }; - +// PostCondition represents the post program point of a branch condition. +class PostCondition : public PostStmt { +public: + PostCondition(const Stmt* S, const LocationContext *L, const void *tag = 0) + : PostStmt(S, PostConditionKind, L, tag) {} + + static bool classof(const ProgramPoint* Location) { + return Location->getKind() == PostConditionKind; + } +}; + class LocationCheck : public StmtPoint { protected: LocationCheck(const Stmt *S, const LocationContext *L, diff --git a/include/clang/Analysis/Visitors/CFGStmtVisitor.h b/include/clang/Analysis/Visitors/CFGStmtVisitor.h index d197e69babde1..7fb4ab3ebad97 100644 --- a/include/clang/Analysis/Visitors/CFGStmtVisitor.h +++ b/include/clang/Analysis/Visitors/CFGStmtVisitor.h @@ -82,6 +82,7 @@ public: DISPATCH_CASE(ConditionalOperator) DISPATCH_CASE(BinaryConditionalOperator) DISPATCH_CASE(ObjCForCollectionStmt) + DISPATCH_CASE(CXXForRangeStmt) case Stmt::BinaryOperatorClass: { BinaryOperator* B = cast<BinaryOperator>(S); @@ -109,6 +110,10 @@ public: return static_cast<ImplClass*>(this)->BlockStmt_VisitStmt(S); } + RetTy BlockStmt_VisitCXXForRangeStmt(CXXForRangeStmt* S) { + return static_cast<ImplClass*>(this)->BlockStmt_VisitStmt(S); + } + RetTy BlockStmt_VisitImplicitControlFlowExpr(Expr* E) { return static_cast<ImplClass*>(this)->BlockStmt_VisitExpr(E); } |