summaryrefslogtreecommitdiff
path: root/include/clang/Analysis
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2011-05-02 19:39:53 +0000
committerDimitry Andric <dim@FreeBSD.org>2011-05-02 19:39:53 +0000
commit01af97d3b23bded2b2b21af19bbc6e4cce49e5b3 (patch)
tree64a10f4c4154739d4a8191d7e1b52ce497f4ebd6 /include/clang/Analysis
parentc3b054d250cdca485c71845089c316e10610ebad (diff)
Diffstat (limited to 'include/clang/Analysis')
-rw-r--r--include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h4
-rw-r--r--include/clang/Analysis/Analyses/UninitializedValues.h82
-rw-r--r--include/clang/Analysis/Analyses/UninitializedValuesV2.h40
-rw-r--r--include/clang/Analysis/AnalysisContext.h60
-rw-r--r--include/clang/Analysis/AnalysisDiagnostic.h3
-rw-r--r--include/clang/Analysis/CFG.h120
-rw-r--r--include/clang/Analysis/DomainSpecific/CocoaConventions.h2
-rw-r--r--include/clang/Analysis/FlowSensitive/DataflowSolver.h8
-rw-r--r--include/clang/Analysis/ProgramPoint.h13
-rw-r--r--include/clang/Analysis/Visitors/CFGStmtVisitor.h5
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);
}