summaryrefslogtreecommitdiffstats
path: root/include/clang/StaticAnalyzer/Core/PathSensitive
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2013-04-08 18:45:10 +0000
committerdim <dim@FreeBSD.org>2013-04-08 18:45:10 +0000
commitc72c57c9e9b69944e3e009cd5e209634839581d3 (patch)
tree4fc2f184c499d106f29a386c452b49e5197bf63d /include/clang/StaticAnalyzer/Core/PathSensitive
parent5b20025c30d23d521e12c1f33ec8fa6b821952cd (diff)
downloadFreeBSD-src-c72c57c9e9b69944e3e009cd5e209634839581d3.zip
FreeBSD-src-c72c57c9e9b69944e3e009cd5e209634839581d3.tar.gz
Vendor import of clang trunk r178860:
http://llvm.org/svn/llvm-project/cfe/trunk@178860
Diffstat (limited to 'include/clang/StaticAnalyzer/Core/PathSensitive')
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h9
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h2
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h3
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h38
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h12
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h14
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h12
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h10
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h64
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h143
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h96
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h61
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h105
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h19
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h5
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h242
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/Store.h40
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h22
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h8
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h6
21 files changed, 593 insertions, 322 deletions
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h b/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h
index 27f3677..9502900 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h
@@ -81,9 +81,12 @@ public:
/// Tests whether a given value is losslessly representable using this type.
///
- /// Note that signedness conversions will be rejected, even with the same bit
- /// pattern. For example, -1s8 is not in range for 'unsigned char' (u8).
- RangeTestResultKind testInRange(const llvm::APSInt &Val) const LLVM_READONLY;
+ /// \param Val The value to test.
+ /// \param AllowMixedSign Whether or not to allow signedness conversions.
+ /// This determines whether -1s8 is considered in range
+ /// for 'unsigned char' (u8).
+ RangeTestResultKind testInRange(const llvm::APSInt &Val,
+ bool AllowMixedSign) const LLVM_READONLY;
bool operator==(const APSIntType &Other) const {
return BitWidth == Other.BitWidth && IsUnsigned == Other.IsUnsigned;
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
index 9038ae5..458c896 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
@@ -100,7 +100,7 @@ public:
}
bool shouldInlineCall() const {
- return options.IPAMode != None;
+ return options.getIPAMode() != IPAK_None;
}
CFG *getCFG(Decl const *D) {
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
index fb39354..1135b51 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
@@ -16,9 +16,10 @@
#ifndef LLVM_CLANG_GR_BASICVALUEFACTORY_H
#define LLVM_CLANG_GR_BASICVALUEFACTORY_H
+#include "clang/AST/ASTContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
namespace clang {
namespace ento {
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
index a6a91e2..f990b8d 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
@@ -16,11 +16,11 @@
#ifndef LLVM_CLANG_STATICANALYZER_PATHSENSITIVE_CALL
#define LLVM_CLANG_STATICANALYZER_PATHSENSITIVE_CALL
-#include "clang/Basic/SourceManager.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Basic/SourceManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "llvm/ADT/PointerIntPair.h"
@@ -162,11 +162,11 @@ protected:
}
- typedef SmallVectorImpl<const MemRegion *> RegionList;
+ typedef SmallVectorImpl<SVal> ValueList;
/// \brief Used to specify non-argument regions that will be invalidated as a
/// result of this call.
- virtual void getExtraInvalidatedRegions(RegionList &Regions) const {}
+ virtual void getExtraInvalidatedValues(ValueList &Values) const {}
public:
virtual ~CallEvent() {}
@@ -181,7 +181,7 @@ public:
}
/// \brief The state in which the call is being evaluated.
- ProgramStateRef getState() const {
+ const ProgramStateRef &getState() const {
return State;
}
@@ -228,6 +228,11 @@ public:
return false;
}
+ /// \brief Returns true if this is a call to a variadic function or method.
+ virtual bool isVariadic() const {
+ return false;
+ }
+
/// \brief Returns a source range for the entire call, suitable for
/// outputting in diagnostics.
virtual SourceRange getSourceRange() const {
@@ -331,7 +336,9 @@ public:
/// of some kind.
static bool isCallStmt(const Stmt *S);
- /// \brief Returns the result type of a function, method declaration.
+ /// \brief Returns the result type of a function or method declaration.
+ ///
+ /// This will return a null QualType if the result type cannot be determined.
static QualType getDeclaredResultType(const Decl *D);
// Iterator access to formal parameters and their types.
@@ -416,6 +423,10 @@ public:
return RuntimeDefinition();
}
+ virtual bool isVariadic() const {
+ return getDecl()->isVariadic();
+ }
+
virtual bool argumentsMayEscape() const;
virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
@@ -493,7 +504,7 @@ protected:
BlockCall(const BlockCall &Other) : SimpleCall(Other) {}
virtual void cloneTo(void *Dest) const { new (Dest) BlockCall(*this); }
- virtual void getExtraInvalidatedRegions(RegionList &Regions) const;
+ virtual void getExtraInvalidatedValues(ValueList &Values) const;
public:
/// \brief Returns the region associated with this instance of the block.
@@ -516,6 +527,10 @@ public:
return RuntimeDefinition(getBlockDecl());
}
+ virtual bool isVariadic() const {
+ return getBlockDecl()->isVariadic();
+ }
+
virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
BindingsTy &Bindings) const;
@@ -533,7 +548,7 @@ public:
/// it is written.
class CXXInstanceCall : public AnyFunctionCall {
protected:
- virtual void getExtraInvalidatedRegions(RegionList &Regions) const;
+ virtual void getExtraInvalidatedValues(ValueList &Values) const;
CXXInstanceCall(const CallExpr *CE, ProgramStateRef St,
const LocationContext *LCtx)
@@ -716,7 +731,7 @@ protected:
CXXConstructorCall(const CXXConstructorCall &Other) : AnyFunctionCall(Other){}
virtual void cloneTo(void *Dest) const { new (Dest) CXXConstructorCall(*this); }
- virtual void getExtraInvalidatedRegions(RegionList &Regions) const;
+ virtual void getExtraInvalidatedValues(ValueList &Values) const;
public:
virtual const CXXConstructExpr *getOriginExpr() const {
@@ -815,7 +830,7 @@ protected:
ObjCMethodCall(const ObjCMethodCall &Other) : CallEvent(Other) {}
virtual void cloneTo(void *Dest) const { new (Dest) ObjCMethodCall(*this); }
- virtual void getExtraInvalidatedRegions(RegionList &Regions) const;
+ virtual void getExtraInvalidatedValues(ValueList &Values) const;
/// Check if the selector may have multiple definitions (may have overrides).
virtual bool canBeOverridenInSubclass(ObjCInterfaceDecl *IDecl,
@@ -834,6 +849,9 @@ public:
virtual const Expr *getArgExpr(unsigned Index) const {
return getOriginExpr()->getArg(Index);
}
+ virtual bool isVariadic() const {
+ return getDecl()->isVariadic();
+ }
bool isInstanceMessage() const {
return getOriginExpr()->isInstanceMessage();
@@ -1024,7 +1042,7 @@ namespace llvm {
typedef const T *SimpleType;
static SimpleType
- getSimplifiedValue(const clang::ento::CallEventRef<T>& Val) {
+ getSimplifiedValue(clang::ento::CallEventRef<T> Val) {
return Val.getPtr();
}
};
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
index 4558cd9..cda1366 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
@@ -119,7 +119,7 @@ public:
/// the state of the program before the checker ran. Note, checkers should
/// not retain the node in their state since the nodes might get invalidated.
ExplodedNode *getPredecessor() { return Pred; }
- ProgramStateRef getState() const { return Pred->getState(); }
+ const ProgramStateRef &getState() const { return Pred->getState(); }
/// \brief Check if the checker changed the state of the execution; ex: added
/// a new transition or a bug report.
@@ -185,7 +185,7 @@ public:
/// example, for finding variables that the given symbol was assigned to.
static const MemRegion *getLocationRegionIfPostStore(const ExplodedNode *N) {
ProgramPoint L = N->getLocation();
- if (const PostStore *PSL = dyn_cast<PostStore>(&L))
+ if (Optional<PostStore> PSL = L.getAs<PostStore>())
return reinterpret_cast<const MemRegion*>(PSL->getLocationValue());
return 0;
}
@@ -303,14 +303,6 @@ private:
}
};
-/// \brief A helper class which wraps a boolean value set to false by default.
-struct DefaultBool {
- bool Val;
- DefaultBool() : Val(false) {}
- operator bool() const { return Val; }
- DefaultBool &operator=(bool b) { Val = b; return *this; }
-};
-
} // end GR namespace
} // end clang namespace
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
index 4a78849..1e76ea6 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
@@ -14,8 +14,8 @@
#ifndef LLVM_CLANG_GR_CONSTRAINT_MANAGER_H
#define LLVM_CLANG_GR_CONSTRAINT_MANAGER_H
-#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
#include "llvm/Support/SaveAndRestore.h"
namespace llvm {
@@ -28,7 +28,7 @@ namespace ento {
class SubEngine;
class ConditionTruthVal {
- llvm::Optional<bool> Val;
+ Optional<bool> Val;
public:
/// Construct a ConditionTruthVal indicating the constraint is constrained
/// to either true or false, depending on the boolean value provided.
@@ -78,9 +78,13 @@ public:
// If StTrue is infeasible, asserting the falseness of Cond is unnecessary
// because the existing constraints already establish this.
if (!StTrue) {
- // FIXME: This is fairly expensive and should be disabled even in
- // Release+Asserts builds.
+#ifndef __OPTIMIZE__
+ // This check is expensive and should be disabled even in Release+Asserts
+ // builds.
+ // FIXME: __OPTIMIZE__ is a GNU extension that Clang implements but MSVC
+ // does not. Is there a good equivalent there?
assert(assume(State, Cond, false) && "System is over constrained.");
+#endif
return ProgramStatePair((ProgramStateRef)NULL, State);
}
@@ -118,7 +122,7 @@ public:
/// Convenience method to query the state to see if a symbol is null or
/// not null, or if neither assumption can be made.
ConditionTruthVal isNull(ProgramStateRef State, SymbolRef Sym) {
- llvm::SaveAndRestore<bool> DisableNotify(NotifyAssumeClients, false);
+ SaveAndRestore<bool> DisableNotify(NotifyAssumeClients, false);
return checkNull(State, Sym);
}
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
index b668640..a2e211e 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
@@ -17,10 +17,10 @@
#include "clang/AST/Expr.h"
#include "clang/Analysis/AnalysisContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/WorkList.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h"
#include "llvm/ADT/OwningPtr.h"
namespace clang {
@@ -96,6 +96,10 @@ private:
void HandleBranch(const Stmt *Cond, const Stmt *Term, const CFGBlock *B,
ExplodedNode *Pred);
+ /// Handle conditional logic for running static initializers.
+ void HandleStaticInit(const DeclStmt *DS, const CFGBlock *B,
+ ExplodedNode *Pred);
+
private:
CoreEngine(const CoreEngine &) LLVM_DELETED_FUNCTION;
void operator=(const CoreEngine &) LLVM_DELETED_FUNCTION;
@@ -463,7 +467,7 @@ public:
bool operator!=(const iterator &X) const { return I != X.I; }
const LabelDecl *getLabel() const {
- return llvm::cast<LabelStmt>((*I)->getLabel())->getDecl();
+ return cast<LabelStmt>((*I)->getLabel())->getDecl();
}
const CFGBlock *getBlock() const {
@@ -510,7 +514,7 @@ public:
bool operator==(const iterator &X) const { return I == X.I; }
const CaseStmt *getCase() const {
- return llvm::cast<CaseStmt>((*I)->getLabel());
+ return cast<CaseStmt>((*I)->getLabel());
}
const CFGBlock *getBlock() const {
@@ -522,7 +526,7 @@ public:
iterator end() { return iterator(Src->succ_rend()); }
const SwitchStmt *getSwitch() const {
- return llvm::cast<SwitchStmt>(Src->getTerminator());
+ return cast<SwitchStmt>(Src->getTerminator());
}
ExplodedNode *generateCaseStmtNode(const iterator &I,
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h
index eb9bd85..f3a582d 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h
@@ -33,9 +33,6 @@ class SValBuilder;
/// other things.
class EnvironmentEntry : public std::pair<const Stmt*,
const StackFrameContext *> {
- friend class EnvironmentManager;
- EnvironmentEntry makeLocation() const;
-
public:
EnvironmentEntry(const Stmt *s, const LocationContext *L);
@@ -118,13 +115,6 @@ public:
/// Bind a symbolic value to the given environment entry.
Environment bindExpr(Environment Env, const EnvironmentEntry &E, SVal V,
bool Invalidate);
-
- /// Bind the location 'location' and value 'V' to the specified
- /// environment entry.
- Environment bindExprAndLocation(Environment Env,
- const EnvironmentEntry &E,
- SVal location,
- SVal V);
Environment removeDeadBindings(Environment Env,
SymbolReaper &SymReaper,
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
index b112e66..5211916 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
@@ -19,19 +19,19 @@
#ifndef LLVM_CLANG_GR_EXPLODEDGRAPH
#define LLVM_CLANG_GR_EXPLODEDGRAPH
-#include "clang/Analysis/ProgramPoint.h"
-#include "clang/Analysis/AnalysisContext.h"
#include "clang/AST/Decl.h"
-#include "llvm/ADT/SmallVector.h"
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/ProgramPoint.h"
+#include "clang/Analysis/Support/BumpVector.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/GraphTraits.h"
+#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Allocator.h"
-#include "llvm/ADT/OwningPtr.h"
-#include "llvm/ADT/GraphTraits.h"
-#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/Support/Casting.h"
-#include "clang/Analysis/Support/BumpVector.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include <vector>
namespace clang {
@@ -152,10 +152,12 @@ public:
return *getLocationContext()->getAnalysis<T>();
}
- ProgramStateRef getState() const { return State; }
+ const ProgramStateRef &getState() const { return State; }
template <typename T>
- const T* getLocationAs() const { return llvm::dyn_cast<T>(&Location); }
+ Optional<T> getLocationAs() const LLVM_LVALUE_FUNCTION {
+ return Location.getAs<T>();
+ }
static void Profile(llvm::FoldingSetNodeID &ID,
const ProgramPoint &Loc,
@@ -167,7 +169,8 @@ public:
}
void Profile(llvm::FoldingSetNodeID& ID) const {
- Profile(ID, getLocation(), getState(), isSink());
+ // We avoid copy constructors by not using accessors.
+ Profile(ID, Location, State, isSink());
}
/// addPredeccessor - Adds a predecessor to the current node, and
@@ -236,18 +239,8 @@ private:
void replacePredecessor(ExplodedNode *node) { Preds.replaceNode(node); }
};
-// FIXME: Is this class necessary?
-class InterExplodedGraphMap {
- virtual void anchor();
- llvm::DenseMap<const ExplodedNode*, ExplodedNode*> M;
- friend class ExplodedGraph;
-
-public:
- ExplodedNode *getMappedNode(const ExplodedNode *N) const;
-
- InterExplodedGraphMap() {}
- virtual ~InterExplodedGraphMap() {}
-};
+typedef llvm::DenseMap<const ExplodedNode *, const ExplodedNode *>
+ InterExplodedGraphMap;
class ExplodedGraph {
protected:
@@ -365,14 +358,19 @@ public:
typedef llvm::DenseMap<const ExplodedNode*, ExplodedNode*> NodeMap;
- std::pair<ExplodedGraph*, InterExplodedGraphMap*>
- Trim(const NodeTy* const* NBeg, const NodeTy* const* NEnd,
- llvm::DenseMap<const void*, const void*> *InverseMap = 0) const;
-
- ExplodedGraph* TrimInternal(const ExplodedNode* const * NBeg,
- const ExplodedNode* const * NEnd,
- InterExplodedGraphMap *M,
- llvm::DenseMap<const void*, const void*> *InverseMap) const;
+ /// Creates a trimmed version of the graph that only contains paths leading
+ /// to the given nodes.
+ ///
+ /// \param Nodes The nodes which must appear in the final graph. Presumably
+ /// these are end-of-path nodes (i.e. they have no successors).
+ /// \param[out] ForwardMap A optional map from nodes in this graph to nodes in
+ /// the returned graph.
+ /// \param[out] InverseMap An optional map from nodes in the returned graph to
+ /// nodes in this graph.
+ /// \returns The trimmed graph
+ ExplodedGraph *trim(ArrayRef<const NodeTy *> Nodes,
+ InterExplodedGraphMap *ForwardMap = 0,
+ InterExplodedGraphMap *InverseMap = 0) const;
/// Enable tracking of recently allocated nodes for potential reclamation
/// when calling reclaimRecentlyAllocatedNodes().
@@ -384,6 +382,10 @@ public:
/// was called.
void reclaimRecentlyAllocatedNodes();
+ /// \brief Returns true if nodes for the given expression kind are always
+ /// kept around.
+ static bool isInterestingLValueExpr(const Expr *Ex);
+
private:
bool shouldCollect(const ExplodedNode *node);
void collectNode(ExplodedNode *node);
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index 78b2542..33e4431 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -16,15 +16,15 @@
#ifndef LLVM_CLANG_GR_EXPRENGINE
#define LLVM_CLANG_GR_EXPRENGINE
+#include "clang/AST/Expr.h"
+#include "clang/AST/Type.h"
#include "clang/Analysis/DomainSpecific/ObjCNoReturn.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
-#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
-#include "clang/AST/Expr.h"
-#include "clang/AST/Type.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h"
namespace clang {
@@ -44,8 +44,19 @@ namespace ento {
class AnalysisManager;
class CallEvent;
class SimpleCall;
+class CXXConstructorCall;
class ExprEngine : public SubEngine {
+public:
+ /// The modes of inlining, which override the default analysis-wide settings.
+ enum InliningModes {
+ /// Follow the default settings for inlining callees.
+ Inline_Regular = 0,
+ /// Do minimal inlining of callees.
+ Inline_Minimal = 0x1
+ };
+
+private:
AnalysisManager &AMgr;
AnalysisDeclContextManager &AnalysisDeclContexts;
@@ -64,15 +75,6 @@ class ExprEngine : public SubEngine {
/// svalBuilder - SValBuilder object that creates SVals from expressions.
SValBuilder &svalBuilder;
- /// EntryNode - The immediate predecessor node.
- ExplodedNode *EntryNode;
-
- /// CleanedState - The state for EntryNode "cleaned" of all dead
- /// variables and symbols (as determined by a liveness analysis).
- ProgramStateRef CleanedState;
-
- /// currStmt - The current block-level statement.
- const Stmt *currStmt;
unsigned int currStmtIdx;
const NodeBuilderContext *currBldrCtx;
@@ -92,10 +94,14 @@ class ExprEngine : public SubEngine {
/// AnalysisConsumer. It can be null.
SetOfConstDecls *VisitedCallees;
+ /// The flag, which specifies the mode of inlining for the engine.
+ InliningModes HowToInline;
+
public:
ExprEngine(AnalysisManager &mgr, bool gcEnabled,
SetOfConstDecls *VisitedCalleesIn,
- FunctionSummariesTy *FS);
+ FunctionSummariesTy *FS,
+ InliningModes HowToInlineIn);
~ExprEngine();
@@ -140,11 +146,12 @@ public:
void enqueueEndOfPath(ExplodedNodeSet &S);
void GenerateCallExitNode(ExplodedNode *N);
- /// ViewGraph - Visualize the ExplodedGraph created by executing the
- /// simulation.
+ /// Visualize the ExplodedGraph created by executing the simulation.
void ViewGraph(bool trim = false);
- void ViewGraph(ExplodedNode** Beg, ExplodedNode** End);
+ /// Visualize a trimmed ExplodedGraph that only contains paths to the given
+ /// nodes.
+ void ViewGraph(ArrayRef<const ExplodedNode*> Nodes);
/// getInitialState - Return the initial state used for the root vertex
/// in the ExplodedGraph.
@@ -154,26 +161,33 @@ public:
const ExplodedGraph& getGraph() const { return G; }
/// \brief Run the analyzer's garbage collection - remove dead symbols and
- /// bindings.
+ /// bindings from the state.
///
- /// \param Node - The predecessor node, from which the processing should
- /// start.
- /// \param Out - The returned set of output nodes.
- /// \param ReferenceStmt - Run garbage collection using the symbols,
- /// which are live before the given statement.
- /// \param LC - The location context of the ReferenceStmt.
- /// \param DiagnosticStmt - the statement used to associate the diagnostic
- /// message, if any warnings should occur while removing the dead (leaks
- /// are usually reported here).
- /// \param K - In some cases it is possible to use PreStmt kind. (Do
- /// not use it unless you know what you are doing.)
- /// If the ReferenceStmt is NULL, everything is this and parent contexts is
- /// considered live.
- /// If the stack frame context is NULL, everything on stack is considered
- /// dead.
+ /// Checkers can participate in this process with two callbacks:
+ /// \c checkLiveSymbols and \c checkDeadSymbols. See the CheckerDocumentation
+ /// class for more information.
+ ///
+ /// \param Node The predecessor node, from which the processing should start.
+ /// \param Out The returned set of output nodes.
+ /// \param ReferenceStmt The statement which is about to be processed.
+ /// Everything needed for this statement should be considered live.
+ /// A null statement means that everything in child LocationContexts
+ /// is dead.
+ /// \param LC The location context of the \p ReferenceStmt. A null location
+ /// context means that we have reached the end of analysis and that
+ /// all statements and local variables should be considered dead.
+ /// \param DiagnosticStmt Used as a location for any warnings that should
+ /// occur while removing the dead (e.g. leaks). By default, the
+ /// \p ReferenceStmt is used.
+ /// \param K Denotes whether this is a pre- or post-statement purge. This
+ /// must only be ProgramPoint::PostStmtPurgeDeadSymbolsKind if an
+ /// entire location context is being cleared, in which case the
+ /// \p ReferenceStmt must either be a ReturnStmt or \c NULL. Otherwise,
+ /// it must be ProgramPoint::PreStmtPurgeDeadSymbolsKind (the default)
+ /// and \p ReferenceStmt must be valid (non-null).
void removeDead(ExplodedNode *Node, ExplodedNodeSet &Out,
- const Stmt *ReferenceStmt, const StackFrameContext *LC,
- const Stmt *DiagnosticStmt,
+ const Stmt *ReferenceStmt, const LocationContext *LC,
+ const Stmt *DiagnosticStmt = 0,
ProgramPoint::Kind K = ProgramPoint::PreStmtPurgeDeadSymbolsKind);
/// processCFGElement - Called by CoreEngine. Used to generate new successor
@@ -210,6 +224,15 @@ public:
const CFGBlock *DstT,
const CFGBlock *DstF);
+ /// Called by CoreEngine. Used to processing branching behavior
+ /// at static initalizers.
+ void processStaticInitializer(const DeclStmt *DS,
+ NodeBuilderContext& BuilderCtx,
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst,
+ const CFGBlock *DstT,
+ const CFGBlock *DstF);
+
/// processIndirectGoto - Called by CoreEngine. Used to generate successor
/// nodes by processing the 'effects' of a computed goto jump.
void processIndirectGoto(IndirectGotoNodeBuilder& builder);
@@ -218,8 +241,8 @@ public:
/// nodes by processing the 'effects' of a switch statement.
void processSwitch(SwitchNodeBuilder& builder);
- /// ProcessEndPath - Called by CoreEngine. Used to generate end-of-path
- /// nodes when the control reaches the end of a function.
+ /// Called by CoreEngine. Used to generate end-of-path
+ /// nodes when the control reaches the end of a function.
void processEndOfFunction(NodeBuilderContext& BC,
ExplodedNode *Pred);
@@ -250,7 +273,7 @@ public:
/// to the store. Used to update checkers that track region values.
ProgramStateRef
processRegionChanges(ProgramStateRef state,
- const StoreManager::InvalidatedSymbols *invalidated,
+ const InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
const CallEvent *Call);
@@ -416,11 +439,11 @@ public:
geteagerlyAssumeBinOpBifurcationTags();
SVal evalMinus(SVal X) {
- return X.isValid() ? svalBuilder.evalMinus(cast<NonLoc>(X)) : X;
+ return X.isValid() ? svalBuilder.evalMinus(X.castAs<NonLoc>()) : X;
}
SVal evalComplement(SVal X) {
- return X.isValid() ? svalBuilder.evalComplement(cast<NonLoc>(X)) : X;
+ return X.isValid() ? svalBuilder.evalComplement(X.castAs<NonLoc>()) : X;
}
public:
@@ -432,7 +455,8 @@ public:
SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op,
NonLoc L, SVal R, QualType T) {
- return R.isValid() ? svalBuilder.evalBinOpNN(state,op,L, cast<NonLoc>(R), T) : R;
+ return R.isValid() ? svalBuilder.evalBinOpNN(state, op, L,
+ R.castAs<NonLoc>(), T) : R;
}
SVal evalBinOp(ProgramStateRef ST, BinaryOperator::Opcode Op,
@@ -447,6 +471,20 @@ protected:
SVal location, SVal Val, bool atDeclInit = false,
const ProgramPoint *PP = 0);
+ /// Call PointerEscape callback when a value escapes as a result of bind.
+ ProgramStateRef processPointerEscapedOnBind(ProgramStateRef State,
+ SVal Loc, SVal Val);
+ /// Call PointerEscape callback when a value escapes as a result of
+ /// region invalidation.
+ /// \param[in] IsConst Specifies that the pointer is const.
+ ProgramStateRef notifyCheckersOfPointerEscape(
+ ProgramStateRef State,
+ const InvalidatedSymbols *Invalidated,
+ ArrayRef<const MemRegion *> ExplicitRegions,
+ ArrayRef<const MemRegion *> Regions,
+ const CallEvent *Call,
+ bool IsConst);
+
public:
// FIXME: 'tag' should be removed, and a LocationContext should be used
// instead.
@@ -506,7 +544,10 @@ private:
void examineStackFrames(const Decl *D, const LocationContext *LCtx,
bool &IsRecursive, unsigned &StackDepth);
- bool shouldInlineDecl(const Decl *D, ExplodedNode *Pred);
+ /// Checks our policies and decides weither the given call should be inlined.
+ bool shouldInlineCall(const CallEvent &Call, const Decl *D,
+ const ExplodedNode *Pred);
+
bool inlineCall(const CallEvent &Call, const Decl *D, NodeBuilder &Bldr,
ExplodedNode *Pred, ProgramStateRef State);
@@ -522,6 +563,22 @@ private:
ExplodedNode *Pred);
bool replayWithoutInlining(ExplodedNode *P, const LocationContext *CalleeLC);
+
+ /// Models a trivial copy or move constructor or trivial assignment operator
+ /// call with a simple bind.
+ void performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred,
+ const CallEvent &Call);
+
+ /// If the value of the given expression is a NonLoc, copy it into a new
+ /// temporary object region, and replace the value of the expression with
+ /// that.
+ ///
+ /// If \p ResultE is provided, the new region will be bound to this expression
+ /// instead of \p E.
+ ProgramStateRef createTemporaryRegionIfNeeded(ProgramStateRef State,
+ const LocationContext *LC,
+ const Expr *E,
+ const Expr *ResultE = 0);
};
/// Traits for storing the call processing policy inside GDM.
@@ -531,7 +588,7 @@ private:
struct ReplayWithoutInlining{};
template <>
struct ProgramStateTrait<ReplayWithoutInlining> :
- public ProgramStatePartialTrait<void*> {
+ public ProgramStatePartialTrait<const void*> {
static void *GDMIndex() { static int index = 0; return &index; }
};
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h b/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h
index cf4a692..169af93 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h
@@ -7,94 +7,126 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines a summary of a function gathered/used by static analyzes.
+// This file defines a summary of a function gathered/used by static analysis.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_GR_FUNCTIONSUMMARY_H
#define LLVM_CLANG_GR_FUNCTIONSUMMARY_H
-#include <deque>
-#include "clang/AST/Decl.h"
+#include "clang/Basic/LLVM.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallBitVector.h"
+#include <deque>
namespace clang {
+class Decl;
+
namespace ento {
typedef std::deque<Decl*> SetOfDecls;
typedef llvm::DenseSet<const Decl*> SetOfConstDecls;
class FunctionSummariesTy {
- struct FunctionSummary {
- /// True if this function has reached a max block count while inlined from
- /// at least one call site.
- bool MayReachMaxBlockCount;
+ class FunctionSummary {
+ public:
+ /// Marks the IDs of the basic blocks visited during the analyzes.
+ llvm::SmallBitVector VisitedBasicBlocks;
/// Total number of blocks in the function.
- unsigned TotalBasicBlocks;
+ unsigned TotalBasicBlocks : 30;
- /// Marks the IDs of the basic blocks visited during the analyzes.
- llvm::BitVector VisitedBasicBlocks;
+ /// True if this function has been checked against the rules for which
+ /// functions may be inlined.
+ unsigned InlineChecked : 1;
+
+ /// True if this function may be inlined.
+ unsigned MayInline : 1;
+
+ /// The number of times the function has been inlined.
+ unsigned TimesInlined : 32;
FunctionSummary() :
- MayReachMaxBlockCount(false),
TotalBasicBlocks(0),
- VisitedBasicBlocks(0) {}
+ InlineChecked(0),
+ TimesInlined(0) {}
};
- typedef llvm::DenseMap<const Decl*, FunctionSummary*> MapTy;
+ typedef llvm::DenseMap<const Decl *, FunctionSummary> MapTy;
MapTy Map;
public:
- ~FunctionSummariesTy();
-
MapTy::iterator findOrInsertSummary(const Decl *D) {
MapTy::iterator I = Map.find(D);
if (I != Map.end())
return I;
- FunctionSummary *DS = new FunctionSummary();
- I = Map.insert(std::pair<const Decl*, FunctionSummary*>(D, DS)).first;
+
+ typedef std::pair<const Decl *, FunctionSummary> KVPair;
+ I = Map.insert(KVPair(D, FunctionSummary())).first;
assert(I != Map.end());
return I;
}
- void markReachedMaxBlockCount(const Decl* D) {
+ void markMayInline(const Decl *D) {
MapTy::iterator I = findOrInsertSummary(D);
- I->second->MayReachMaxBlockCount = true;
+ I->second.InlineChecked = 1;
+ I->second.MayInline = 1;
}
- bool hasReachedMaxBlockCount(const Decl* D) {
- MapTy::const_iterator I = Map.find(D);
- if (I != Map.end())
- return I->second->MayReachMaxBlockCount;
- return false;
+ void markShouldNotInline(const Decl *D) {
+ MapTy::iterator I = findOrInsertSummary(D);
+ I->second.InlineChecked = 1;
+ I->second.MayInline = 0;
+ }
+
+ void markReachedMaxBlockCount(const Decl *D) {
+ markShouldNotInline(D);
+ }
+
+ Optional<bool> mayInline(const Decl *D) {
+ MapTy::const_iterator I = Map.find(D);
+ if (I != Map.end() && I->second.InlineChecked)
+ return I->second.MayInline;
+ return None;
}
void markVisitedBasicBlock(unsigned ID, const Decl* D, unsigned TotalIDs) {
MapTy::iterator I = findOrInsertSummary(D);
- llvm::BitVector &Blocks = I->second->VisitedBasicBlocks;
+ llvm::SmallBitVector &Blocks = I->second.VisitedBasicBlocks;
assert(ID < TotalIDs);
if (TotalIDs > Blocks.size()) {
Blocks.resize(TotalIDs);
- I->second->TotalBasicBlocks = TotalIDs;
+ I->second.TotalBasicBlocks = TotalIDs;
}
- Blocks[ID] = true;
+ Blocks.set(ID);
}
unsigned getNumVisitedBasicBlocks(const Decl* D) {
MapTy::const_iterator I = Map.find(D);
- if (I != Map.end())
- return I->second->VisitedBasicBlocks.count();
+ if (I != Map.end())
+ return I->second.VisitedBasicBlocks.count();
return 0;
}
+ unsigned getNumTimesInlined(const Decl* D) {
+ MapTy::const_iterator I = Map.find(D);
+ if (I != Map.end())
+ return I->second.TimesInlined;
+ return 0;
+ }
+
+ void bumpNumTimesInlined(const Decl* D) {
+ MapTy::iterator I = findOrInsertSummary(D);
+ I->second.TimesInlined++;
+ }
+
/// Get the percentage of the reachable blocks.
unsigned getPercentBlocksReachable(const Decl *D) {
MapTy::const_iterator I = Map.find(D);
if (I != Map.end())
- return ((I->second->VisitedBasicBlocks.count() * 100) /
- I->second->TotalBasicBlocks);
+ return ((I->second.VisitedBasicBlocks.count() * 100) /
+ I->second.TotalBasicBlocks);
return 0;
}
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
index 34fbc3c..af2f365 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
@@ -22,8 +22,8 @@
#include "clang/AST/ExprObjC.h"
#include "clang/Basic/LLVM.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
-#include "llvm/Support/ErrorHandling.h"
#include "llvm/ADT/FoldingSet.h"
+#include "llvm/Support/ErrorHandling.h"
#include <string>
namespace llvm {
@@ -642,26 +642,20 @@ public:
explicit referenced_vars_iterator(const MemRegion * const *r,
const MemRegion * const *originalR)
: R(r), OriginalR(originalR) {}
-
- operator const MemRegion * const *() const {
- return R;
- }
-
- const MemRegion *getCapturedRegion() const {
- return *R;
- }
- const MemRegion *getOriginalRegion() const {
- return *OriginalR;
- }
- const VarRegion* operator*() const {
+ const VarRegion *getCapturedRegion() const {
return cast<VarRegion>(*R);
}
-
+ const VarRegion *getOriginalRegion() const {
+ return cast<VarRegion>(*OriginalR);
+ }
+
bool operator==(const referenced_vars_iterator &I) const {
+ assert((R == 0) == (I.R == 0));
return I.R == R;
}
bool operator!=(const referenced_vars_iterator &I) const {
+ assert((R == 0) == (I.R == 0));
return I.R != R;
}
referenced_vars_iterator &operator++() {
@@ -670,6 +664,10 @@ public:
return *this;
}
};
+
+ /// Return the original region for a captured region, if
+ /// one exists.
+ const VarRegion *getOriginalRegion(const VarRegion *VR) const;
referenced_vars_iterator referenced_vars_begin() const;
referenced_vars_iterator referenced_vars_end() const;
@@ -686,6 +684,8 @@ public:
}
private:
void LazyInitializeReferencedVars();
+ std::pair<const VarRegion *, const VarRegion *>
+ getCaptureRegions(const VarDecl *VD);
};
/// SymbolicRegion - A special, "non-concrete" region. Unlike other region
@@ -952,6 +952,9 @@ public:
const ObjCIvarDecl *getDecl() const;
QualType getValueType() const;
+ bool canPrintPretty() const;
+ void printPretty(raw_ostream &os) const;
+
void dumpToStream(raw_ostream &os) const;
static bool classof(const MemRegion* R) {
@@ -993,8 +996,8 @@ class ElementRegion : public TypedValueRegion {
ElementRegion(QualType elementType, NonLoc Idx, const MemRegion* sReg)
: TypedValueRegion(sReg, ElementRegionKind),
ElementType(elementType), Index(Idx) {
- assert((!isa<nonloc::ConcreteInt>(&Idx) ||
- cast<nonloc::ConcreteInt>(&Idx)->getValue().isSigned()) &&
+ assert((!Idx.getAs<nonloc::ConcreteInt>() ||
+ Idx.castAs<nonloc::ConcreteInt>().getValue().isSigned()) &&
"The index must be signed");
}
@@ -1057,16 +1060,18 @@ public:
class CXXBaseObjectRegion : public TypedValueRegion {
friend class MemRegionManager;
- const CXXRecordDecl *decl;
+ llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> Data;
- CXXBaseObjectRegion(const CXXRecordDecl *d, const MemRegion *sReg)
- : TypedValueRegion(sReg, CXXBaseObjectRegionKind), decl(d) {}
+ CXXBaseObjectRegion(const CXXRecordDecl *RD, bool IsVirtual,
+ const MemRegion *SReg)
+ : TypedValueRegion(SReg, CXXBaseObjectRegionKind), Data(RD, IsVirtual) {}
- static void ProfileRegion(llvm::FoldingSetNodeID &ID,
- const CXXRecordDecl *decl, const MemRegion *sReg);
+ static void ProfileRegion(llvm::FoldingSetNodeID &ID, const CXXRecordDecl *RD,
+ bool IsVirtual, const MemRegion *SReg);
public:
- const CXXRecordDecl *getDecl() const { return decl; }
+ const CXXRecordDecl *getDecl() const { return Data.getPointer(); }
+ bool isVirtual() const { return Data.getInt(); }
QualType getValueType() const;
@@ -1216,15 +1221,21 @@ public:
const CXXTempObjectRegion *getCXXTempObjectRegion(Expr const *Ex,
LocationContext const *LC);
- const CXXBaseObjectRegion *getCXXBaseObjectRegion(const CXXRecordDecl *decl,
- const MemRegion *superRegion);
+ /// Create a CXXBaseObjectRegion with the given base class for region
+ /// \p Super.
+ ///
+ /// The type of \p Super is assumed be a class deriving from \p BaseClass.
+ const CXXBaseObjectRegion *
+ getCXXBaseObjectRegion(const CXXRecordDecl *BaseClass, const MemRegion *Super,
+ bool IsVirtual);
/// Create a CXXBaseObjectRegion with the same CXXRecordDecl but a different
/// super region.
const CXXBaseObjectRegion *
getCXXBaseObjectRegionWithSuper(const CXXBaseObjectRegion *baseReg,
const MemRegion *superRegion) {
- return getCXXBaseObjectRegion(baseReg->getDecl(), superRegion);
+ return getCXXBaseObjectRegion(baseReg->getDecl(), superRegion,
+ baseReg->isVirtual());
}
const FunctionTextRegion *getFunctionTextRegion(const NamedDecl *FD);
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
index 86c94de..6ea7211 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
@@ -18,13 +18,13 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/Environment.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h"
-#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableMap.h"
+#include "llvm/ADT/PointerIntPair.h"
namespace llvm {
class APSInt;
@@ -170,19 +170,30 @@ public:
// If no new state is feasible, NULL is returned.
//
+ /// Assumes that the value of \p cond is zero (if \p assumption is "false")
+ /// or non-zero (if \p assumption is "true").
+ ///
+ /// This returns a new state with the added constraint on \p cond.
+ /// If no new state is feasible, NULL is returned.
ProgramStateRef assume(DefinedOrUnknownSVal cond, bool assumption) const;
- /// This method assumes both "true" and "false" for 'cond', and
- /// returns both corresponding states. It's shorthand for doing
- /// 'assume' twice.
- std::pair<ProgramStateRef , ProgramStateRef >
+ /// Assumes both "true" and "false" for \p cond, and returns both
+ /// corresponding states (respectively).
+ ///
+ /// This is more efficient than calling assume() twice. Note that one (but not
+ /// both) of the returned states may be NULL.
+ std::pair<ProgramStateRef, ProgramStateRef>
assume(DefinedOrUnknownSVal cond) const;
ProgramStateRef assumeInBound(DefinedOrUnknownSVal idx,
DefinedOrUnknownSVal upperBound,
bool assumption,
QualType IndexType = QualType()) const;
-
+
+ /// \brief Check if the given SVal is constrained to zero or is a zero
+ /// constant.
+ ConditionTruthVal isNull(SVal V) const;
+
/// Utility method for getting regions.
const VarRegion* getRegion(const VarDecl *D, const LocationContext *LC) const;
@@ -203,12 +214,6 @@ public:
ProgramStateRef BindExpr(const Stmt *S, const LocationContext *LCtx,
SVal V, bool Invalidate = true) const;
- /// Create a new state by binding the value 'V' and location 'locaton' to the
- /// statement 'S' in the state's environment.
- ProgramStateRef bindExprAndLocation(const Stmt *S,
- const LocationContext *LCtx,
- SVal location, SVal V) const;
-
ProgramStateRef bindLoc(Loc location,
SVal V,
bool notifyChanges = true) const;
@@ -219,14 +224,38 @@ public:
ProgramStateRef killBinding(Loc LV) const;
- /// invalidateRegions - Returns the state with bindings for the given regions
- /// cleared from the store. The regions are provided as a continuous array
- /// from Begin to End. Optionally invalidates global regions as well.
- ProgramStateRef invalidateRegions(ArrayRef<const MemRegion *> Regions,
- const Expr *E, unsigned BlockCount,
- const LocationContext *LCtx,
- StoreManager::InvalidatedSymbols *IS = 0,
- const CallEvent *Call = 0) const;
+ /// \brief Returns the state with bindings for the given regions
+ /// cleared from the store.
+ ///
+ /// Optionally invalidates global regions as well.
+ ///
+ /// \param Regions the set of regions to be invalidated.
+ /// \param E the expression that caused the invalidation.
+ /// \param BlockCount The number of times the current basic block has been
+ // visited.
+ /// \param CausesPointerEscape the flag is set to true when
+ /// the invalidation entails escape of a symbol (representing a
+ /// pointer). For example, due to it being passed as an argument in a
+ /// call.
+ /// \param IS the set of invalidated symbols.
+ /// \param Call if non-null, the invalidated regions represent parameters to
+ /// the call and should be considered directly invalidated.
+ /// \param ConstRegions the set of regions whose contents are accessible,
+ /// even though the regions themselves should not be invalidated.
+ ProgramStateRef
+ invalidateRegions(ArrayRef<const MemRegion *> Regions, const Expr *E,
+ unsigned BlockCount, const LocationContext *LCtx,
+ bool CausesPointerEscape, InvalidatedSymbols *IS = 0,
+ const CallEvent *Call = 0,
+ ArrayRef<const MemRegion *> ConstRegions =
+ ArrayRef<const MemRegion *>()) const;
+
+ ProgramStateRef
+ invalidateRegions(ArrayRef<SVal> Regions, const Expr *E,
+ unsigned BlockCount, const LocationContext *LCtx,
+ bool CausesPointerEscape, InvalidatedSymbols *IS = 0,
+ const CallEvent *Call = 0,
+ ArrayRef<SVal> ConstRegions = ArrayRef<SVal>()) const;
/// enterStackFrame - Returns the state for entry to the given stack frame,
/// preserving the current state.
@@ -396,13 +425,17 @@ public:
private:
friend void ProgramStateRetain(const ProgramState *state);
friend void ProgramStateRelease(const ProgramState *state);
-
- ProgramStateRef
- invalidateRegionsImpl(ArrayRef<const MemRegion *> Regions,
+
+ /// \sa invalidateValues()
+ /// \sa invalidateRegions()
+ ProgramStateRef
+ invalidateRegionsImpl(ArrayRef<SVal> Values,
const Expr *E, unsigned BlockCount,
const LocationContext *LCtx,
- StoreManager::InvalidatedSymbols &IS,
- const CallEvent *Call) const;
+ bool ResultsInSymbolEscape,
+ InvalidatedSymbols &IS,
+ const CallEvent *Call,
+ ArrayRef<SVal> ConstValues) const;
};
//===----------------------------------------------------------------------===//
@@ -611,22 +644,24 @@ inline ProgramStateRef ProgramState::assume(DefinedOrUnknownSVal Cond,
bool Assumption) const {
if (Cond.isUnknown())
return this;
-
- return getStateManager().ConstraintMgr->assume(this, cast<DefinedSVal>(Cond),
- Assumption);
+
+ return getStateManager().ConstraintMgr
+ ->assume(this, Cond.castAs<DefinedSVal>(), Assumption);
}
inline std::pair<ProgramStateRef , ProgramStateRef >
ProgramState::assume(DefinedOrUnknownSVal Cond) const {
if (Cond.isUnknown())
return std::make_pair(this, this);
-
- return getStateManager().ConstraintMgr->assumeDual(this,
- cast<DefinedSVal>(Cond));
+
+ return getStateManager().ConstraintMgr
+ ->assumeDual(this, Cond.castAs<DefinedSVal>());
}
inline ProgramStateRef ProgramState::bindLoc(SVal LV, SVal V) const {
- return !isa<Loc>(LV) ? this : bindLoc(cast<Loc>(LV), V);
+ if (Optional<Loc> L = LV.getAs<Loc>())
+ return bindLoc(*L, V);
+ return this;
}
inline Loc ProgramState::getLValue(const VarDecl *VD,
@@ -660,7 +695,7 @@ inline SVal ProgramState::getLValue(const IndirectFieldDecl *D,
}
inline SVal ProgramState::getLValue(QualType ElementType, SVal Idx, SVal Base) const{
- if (NonLoc *N = dyn_cast<NonLoc>(&Idx))
+ if (Optional<NonLoc> N = Idx.getAs<NonLoc>())
return getStateManager().StoreMgr->getLValueElement(ElementType, *N, Base);
return UnknownVal();
}
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h
index ea2a852..eb52ae4 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h
@@ -18,6 +18,8 @@
#ifndef LLVM_CLANG_GR_PROGRAMSTATETRAIT_H
#define LLVM_CLANG_GR_PROGRAMSTATETRAIT_H
+#include "llvm/Support/DataTypes.h"
+
namespace llvm {
class BumpPtrAllocator;
template <typename K, typename D, typename I> class ImmutableMap;
@@ -165,7 +167,7 @@ namespace ento {
}
static inline void *MakeVoidPtr(data_type D) {
- return (void*) D.getInternalPointer();
+ return const_cast<llvm::ImmutableListImpl<T> *>(D.getInternalPointer());
}
static inline context_type MakeContext(void *p) {
@@ -221,7 +223,20 @@ namespace ento {
}
};
-} // end GR namespace
+ // Partial specialization for const void *.
+ template <> struct ProgramStatePartialTrait<const void *> {
+ typedef const void *data_type;
+
+ static inline data_type MakeData(void * const *p) {
+ return p ? *p : data_type();
+ }
+
+ static inline void *MakeVoidPtr(data_type d) {
+ return const_cast<void *>(d);
+ }
+ };
+
+} // end ento namespace
} // end clang namespace
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
index 5d72e73..f7e49a3 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
@@ -17,11 +17,10 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"
-#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
namespace clang {
@@ -124,7 +123,7 @@ public:
ProgramStateManager &getStateManager() { return StateMgr; }
QualType getConditionType() const {
- return getContext().IntTy;
+ return Context.getLangOpts().CPlusPlus ? Context.BoolTy : Context.IntTy;
}
QualType getArrayIndexType() const {
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
index c2134cf..1c5519e 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
@@ -16,8 +16,8 @@
#define LLVM_CLANG_GR_RVALUE_H
#include "clang/Basic/LLVM.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
#include "llvm/ADT/ImmutableList.h"
//==------------------------------------------------------------------------==//
@@ -33,7 +33,7 @@ class LazyCompoundValData;
class ProgramState;
class BasicValueFactory;
class MemRegion;
-class TypedRegion;
+class TypedValueRegion;
class MemRegionManager;
class ProgramStateManager;
class SValBuilder;
@@ -69,6 +69,29 @@ protected:
public:
explicit SVal() : Data(0), Kind(0) {}
+ /// \brief Convert to the specified SVal type, asserting that this SVal is of
+ /// the desired type.
+ template<typename T>
+ T castAs() const {
+ assert(T::isKind(*this));
+ T t;
+ SVal& sv = t;
+ sv = *this;
+ return t;
+ }
+
+ /// \brief Convert to the specified SVal type, returning None if this SVal is
+ /// not of the desired type.
+ template<typename T>
+ Optional<T> getAs() const {
+ if (!T::isKind(*this))
+ return None;
+ T t;
+ SVal& sv = t;
+ sv = *this;
+ return t;
+ }
+
/// BufferTy - A temporary buffer to hold a set of SVals.
typedef SmallVector<SVal,5> BufferTy;
@@ -161,29 +184,32 @@ class UndefinedVal : public SVal {
public:
UndefinedVal() : SVal(UndefinedKind) {}
- static inline bool classof(const SVal* V) {
- return V->getBaseKind() == UndefinedKind;
+private:
+ friend class SVal;
+ static bool isKind(const SVal& V) {
+ return V.getBaseKind() == UndefinedKind;
}
};
class DefinedOrUnknownSVal : public SVal {
private:
- // Do not implement. We want calling these methods to be a compiler
- // error since they are tautologically false.
- bool isUndef() const;
- bool isValid() const;
+ // We want calling these methods to be a compiler error since they are
+ // tautologically false.
+ bool isUndef() const LLVM_DELETED_FUNCTION;
+ bool isValid() const LLVM_DELETED_FUNCTION;
protected:
+ DefinedOrUnknownSVal() {}
explicit DefinedOrUnknownSVal(const void *d, bool isLoc, unsigned ValKind)
: SVal(d, isLoc, ValKind) {}
explicit DefinedOrUnknownSVal(BaseKind k, void *D = NULL)
: SVal(k, D) {}
-public:
- // Implement isa<T> support.
- static inline bool classof(const SVal *V) {
- return !V->isUndef();
+private:
+ friend class SVal;
+ static bool isKind(const SVal& V) {
+ return !V.isUndef();
}
};
@@ -191,61 +217,79 @@ class UnknownVal : public DefinedOrUnknownSVal {
public:
explicit UnknownVal() : DefinedOrUnknownSVal(UnknownKind) {}
- static inline bool classof(const SVal *V) {
- return V->getBaseKind() == UnknownKind;
+private:
+ friend class SVal;
+ static bool isKind(const SVal &V) {
+ return V.getBaseKind() == UnknownKind;
}
};
class DefinedSVal : public DefinedOrUnknownSVal {
private:
- // Do not implement. We want calling these methods to be a compiler
- // error since they are tautologically true/false.
- bool isUnknown() const;
- bool isUnknownOrUndef() const;
- bool isValid() const;
+ // We want calling these methods to be a compiler error since they are
+ // tautologically true/false.
+ bool isUnknown() const LLVM_DELETED_FUNCTION;
+ bool isUnknownOrUndef() const LLVM_DELETED_FUNCTION;
+ bool isValid() const LLVM_DELETED_FUNCTION;
protected:
+ DefinedSVal() {}
explicit DefinedSVal(const void *d, bool isLoc, unsigned ValKind)
: DefinedOrUnknownSVal(d, isLoc, ValKind) {}
-public:
- // Implement isa<T> support.
- static inline bool classof(const SVal *V) {
- return !V->isUnknownOrUndef();
+private:
+ friend class SVal;
+ static bool isKind(const SVal& V) {
+ return !V.isUnknownOrUndef();
+ }
+};
+
+
+/// \brief Represents an SVal that is guaranteed to not be UnknownVal.
+class KnownSVal : public SVal {
+ KnownSVal() {}
+ friend class SVal;
+ static bool isKind(const SVal &V) {
+ return !V.isUnknown();
}
+public:
+ KnownSVal(const DefinedSVal &V) : SVal(V) {}
+ KnownSVal(const UndefinedVal &V) : SVal(V) {}
};
class NonLoc : public DefinedSVal {
protected:
+ NonLoc() {}
explicit NonLoc(unsigned SubKind, const void *d)
: DefinedSVal(d, false, SubKind) {}
public:
void dumpToStream(raw_ostream &Out) const;
- // Implement isa<T> support.
- static inline bool classof(const SVal* V) {
- return V->getBaseKind() == NonLocKind;
+private:
+ friend class SVal;
+ static bool isKind(const SVal& V) {
+ return V.getBaseKind() == NonLocKind;
}
};
class Loc : public DefinedSVal {
protected:
+ Loc() {}
explicit Loc(unsigned SubKind, const void *D)
: DefinedSVal(const_cast<void*>(D), true, SubKind) {}
public:
void dumpToStream(raw_ostream &Out) const;
- Loc(const Loc& X) : DefinedSVal(X.Data, true, X.getSubKind()) {}
-
- // Implement isa<T> support.
- static inline bool classof(const SVal* V) {
- return V->getBaseKind() == LocKind;
- }
-
static inline bool isLocType(QualType T) {
return T->isAnyPointerType() || T->isBlockPointerType() ||
T->isReferenceType();
}
+
+private:
+ friend class SVal;
+ static bool isKind(const SVal& V) {
+ return V.getBaseKind() == LocKind;
+ }
};
//==------------------------------------------------------------------------==//
@@ -266,17 +310,20 @@ public:
return (const SymExpr*) Data;
}
- bool isExpression() {
+ bool isExpression() const {
return !isa<SymbolData>(getSymbol());
}
- static inline bool classof(const SVal* V) {
- return V->getBaseKind() == NonLocKind &&
- V->getSubKind() == SymbolValKind;
+private:
+ friend class SVal;
+ SymbolVal() {}
+ static bool isKind(const SVal& V) {
+ return V.getBaseKind() == NonLocKind &&
+ V.getSubKind() == SymbolValKind;
}
- static inline bool classof(const NonLoc* V) {
- return V->getSubKind() == SymbolValKind;
+ static bool isKind(const NonLoc& V) {
+ return V.getSubKind() == SymbolValKind;
}
};
@@ -297,38 +344,40 @@ public:
ConcreteInt evalMinus(SValBuilder &svalBuilder) const;
- // Implement isa<T> support.
- static inline bool classof(const SVal* V) {
- return V->getBaseKind() == NonLocKind &&
- V->getSubKind() == ConcreteIntKind;
+private:
+ friend class SVal;
+ ConcreteInt() {}
+ static bool isKind(const SVal& V) {
+ return V.getBaseKind() == NonLocKind &&
+ V.getSubKind() == ConcreteIntKind;
}
- static inline bool classof(const NonLoc* V) {
- return V->getSubKind() == ConcreteIntKind;
+ static bool isKind(const NonLoc& V) {
+ return V.getSubKind() == ConcreteIntKind;
}
};
class LocAsInteger : public NonLoc {
friend class ento::SValBuilder;
- explicit LocAsInteger(const std::pair<SVal, uintptr_t>& data) :
- NonLoc(LocAsIntegerKind, &data) {
- assert (isa<Loc>(data.first));
- }
+ explicit LocAsInteger(const std::pair<SVal, uintptr_t> &data)
+ : NonLoc(LocAsIntegerKind, &data) {
+ assert (data.first.getAs<Loc>());
+ }
public:
Loc getLoc() const {
const std::pair<SVal, uintptr_t> *D =
static_cast<const std::pair<SVal, uintptr_t> *>(Data);
- return cast<Loc>(D->first);
+ return D->first.castAs<Loc>();
}
- const Loc& getPersistentLoc() const {
+ Loc getPersistentLoc() const {
const std::pair<SVal, uintptr_t> *D =
static_cast<const std::pair<SVal, uintptr_t> *>(Data);
const SVal& V = D->first;
- return cast<Loc>(V);
+ return V.castAs<Loc>();
}
unsigned getNumBits() const {
@@ -337,14 +386,16 @@ public:
return D->second;
}
- // Implement isa<T> support.
- static inline bool classof(const SVal* V) {
- return V->getBaseKind() == NonLocKind &&
- V->getSubKind() == LocAsIntegerKind;
+private:
+ friend class SVal;
+ LocAsInteger() {}
+ static bool isKind(const SVal& V) {
+ return V.getBaseKind() == NonLocKind &&
+ V.getSubKind() == LocAsIntegerKind;
}
- static inline bool classof(const NonLoc* V) {
- return V->getSubKind() == LocAsIntegerKind;
+ static bool isKind(const NonLoc& V) {
+ return V.getSubKind() == LocAsIntegerKind;
}
};
@@ -362,12 +413,15 @@ public:
iterator begin() const;
iterator end() const;
- static bool classof(const SVal* V) {
- return V->getBaseKind() == NonLocKind && V->getSubKind() == CompoundValKind;
+private:
+ friend class SVal;
+ CompoundVal() {}
+ static bool isKind(const SVal& V) {
+ return V.getBaseKind() == NonLocKind && V.getSubKind() == CompoundValKind;
}
- static bool classof(const NonLoc* V) {
- return V->getSubKind() == CompoundValKind;
+ static bool isKind(const NonLoc& V) {
+ return V.getSubKind() == CompoundValKind;
}
};
@@ -381,14 +435,17 @@ public:
return static_cast<const LazyCompoundValData*>(Data);
}
const void *getStore() const;
- const TypedRegion *getRegion() const;
+ const TypedValueRegion *getRegion() const;
- static bool classof(const SVal *V) {
- return V->getBaseKind() == NonLocKind &&
- V->getSubKind() == LazyCompoundValKind;
+private:
+ friend class SVal;
+ LazyCompoundVal() {}
+ static bool isKind(const SVal& V) {
+ return V.getBaseKind() == NonLocKind &&
+ V.getSubKind() == LazyCompoundValKind;
}
- static bool classof(const NonLoc *V) {
- return V->getSubKind() == LazyCompoundValKind;
+ static bool isKind(const NonLoc& V) {
+ return V.getSubKind() == LazyCompoundValKind;
}
};
@@ -410,12 +467,15 @@ public:
return static_cast<const LabelDecl*>(Data);
}
- static inline bool classof(const SVal* V) {
- return V->getBaseKind() == LocKind && V->getSubKind() == GotoLabelKind;
+private:
+ friend class SVal;
+ GotoLabel() {}
+ static bool isKind(const SVal& V) {
+ return V.getBaseKind() == LocKind && V.getSubKind() == GotoLabelKind;
}
- static inline bool classof(const Loc* V) {
- return V->getSubKind() == GotoLabelKind;
+ static bool isKind(const Loc& V) {
+ return V.getSubKind() == GotoLabelKind;
}
};
@@ -434,7 +494,7 @@ public:
template <typename REGION>
const REGION* getRegionAs() const {
- return llvm::dyn_cast<REGION>(getRegion());
+ return dyn_cast<REGION>(getRegion());
}
inline bool operator==(const MemRegionVal& R) const {
@@ -445,14 +505,16 @@ public:
return getRegion() != R.getRegion();
}
- // Implement isa<T> support.
- static inline bool classof(const SVal* V) {
- return V->getBaseKind() == LocKind &&
- V->getSubKind() == MemRegionKind;
+private:
+ friend class SVal;
+ MemRegionVal() {}
+ static bool isKind(const SVal& V) {
+ return V.getBaseKind() == LocKind &&
+ V.getSubKind() == MemRegionKind;
}
- static inline bool classof(const Loc* V) {
- return V->getSubKind() == MemRegionKind;
+ static bool isKind(const Loc& V) {
+ return V.getSubKind() == MemRegionKind;
}
};
@@ -468,19 +530,22 @@ public:
SVal evalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op,
const ConcreteInt& R) const;
- // Implement isa<T> support.
- static inline bool classof(const SVal* V) {
- return V->getBaseKind() == LocKind &&
- V->getSubKind() == ConcreteIntKind;
+private:
+ friend class SVal;
+ ConcreteInt() {}
+ static bool isKind(const SVal& V) {
+ return V.getBaseKind() == LocKind &&
+ V.getSubKind() == ConcreteIntKind;
}
- static inline bool classof(const Loc* V) {
- return V->getSubKind() == ConcreteIntKind;
+ static bool isKind(const Loc& V) {
+ return V.getSubKind() == ConcreteIntKind;
}
};
} // end ento::loc namespace
-} // end GR namespace
+
+} // end ento namespace
} // end clang namespace
@@ -491,6 +556,11 @@ static inline raw_ostream &operator<<(raw_ostream &os,
return os;
}
+template <typename T> struct isPodLike;
+template <> struct isPodLike<clang::ento::SVal> {
+ static const bool value = true;
+};
+
} // end llvm namespace
#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
index 979546b..bbfd579 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
@@ -14,9 +14,9 @@
#ifndef LLVM_CLANG_GR_STORE_H
#define LLVM_CLANG_GR_STORE_H
-#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/Optional.h"
@@ -35,6 +35,8 @@ class ProgramState;
class ProgramStateManager;
class ScanReachableSymbols;
+typedef llvm::DenseSet<SymbolRef> InvalidatedSymbols;
+
class StoreManager {
protected:
SValBuilder &svalBuilder;
@@ -134,7 +136,8 @@ public:
SVal evalDerivedToBase(SVal Derived, const CXXBasePath &CastPath);
/// Evaluates a derived-to-base cast through a single level of derivation.
- SVal evalDerivedToBase(SVal Derived, QualType DerivedPtrType);
+ SVal evalDerivedToBase(SVal Derived, QualType DerivedPtrType,
+ bool IsVirtual);
/// \brief Evaluates C++ dynamic_cast cast.
/// The callback may result in the following 3 scenarios:
@@ -168,7 +171,6 @@ public:
/// associated with the object is recycled.
virtual void decrementReferenceCount(Store store) {}
- typedef llvm::DenseSet<SymbolRef> InvalidatedSymbols;
typedef SmallVector<const MemRegion *, 8> InvalidatedRegions;
/// invalidateRegions - Clears out the specified regions from the store,
@@ -176,26 +178,40 @@ public:
/// invalidate additional regions that may have changed based on accessing
/// the given regions. Optionally, invalidates non-static globals as well.
/// \param[in] store The initial store
- /// \param[in] Regions The regions to invalidate.
+ /// \param[in] Values The values to invalidate.
+ /// \param[in] ConstValues The values to invalidate; these are known to be
+ /// const, so only regions accesible from them should be invalidated.
/// \param[in] E The current statement being evaluated. Used to conjure
/// symbols to mark the values of invalidated regions.
/// \param[in] Count The current block count. Used to conjure
/// symbols to mark the values of invalidated regions.
- /// \param[in,out] IS A set to fill with any symbols that are no longer
- /// accessible. Pass \c NULL if this information will not be used.
/// \param[in] Call The call expression which will be used to determine which
/// globals should get invalidated.
+ /// \param[in,out] IS A set to fill with any symbols that are no longer
+ /// accessible. Pass \c NULL if this information will not be used.
+ /// \param[in,out] ConstIS A set to fill with any symbols corresponding to
+ /// the ConstValues.
+ /// \param[in,out] InvalidatedTopLevel A vector to fill with regions
+ //// explicitely being invalidated. Pass \c NULL if this
+ /// information will not be used.
+ /// \param[in,out] InvalidatedTopLevelConst A vector to fill with const
+ //// regions explicitely being invalidated. Pass \c NULL if this
+ /// information will not be used.
/// \param[in,out] Invalidated A vector to fill with any regions being
/// invalidated. This should include any regions explicitly invalidated
/// even if they do not currently have bindings. Pass \c NULL if this
/// information will not be used.
virtual StoreRef invalidateRegions(Store store,
- ArrayRef<const MemRegion *> Regions,
- const Expr *E, unsigned Count,
- const LocationContext *LCtx,
- InvalidatedSymbols &IS,
- const CallEvent *Call,
- InvalidatedRegions *Invalidated) = 0;
+ ArrayRef<SVal> Values,
+ ArrayRef<SVal> ConstValues,
+ const Expr *E, unsigned Count,
+ const LocationContext *LCtx,
+ const CallEvent *Call,
+ InvalidatedSymbols &IS,
+ InvalidatedSymbols &ConstIS,
+ InvalidatedRegions *InvalidatedTopLevel,
+ InvalidatedRegions *InvalidatedTopLevelConst,
+ InvalidatedRegions *Invalidated) = 0;
/// enterStackFrame - Let the StoreManager to do something when execution
/// engine is about to execute into a callee.
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
index 1e71077..d410063 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
@@ -72,6 +72,15 @@ public:
const CFGBlock *DstT,
const CFGBlock *DstF) = 0;
+ /// Called by CoreEngine. Used to processing branching behavior
+ /// at static initalizers.
+ virtual void processStaticInitializer(const DeclStmt *DS,
+ NodeBuilderContext& BuilderCtx,
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst,
+ const CFGBlock *DstT,
+ const CFGBlock *DstF) = 0;
+
/// Called by CoreEngine. Used to generate successor
/// nodes by processing the 'effects' of a computed goto jump.
virtual void processIndirectGoto(IndirectGotoNodeBuilder& builder) = 0;
@@ -104,7 +113,7 @@ public:
/// made to the store. Used to update checkers that track region values.
virtual ProgramStateRef
processRegionChanges(ProgramStateRef state,
- const StoreManager::InvalidatedSymbols *invalidated,
+ const InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
const CallEvent *Call) = 0;
@@ -116,6 +125,17 @@ public:
return processRegionChanges(state, 0, MR, MR, 0);
}
+ virtual ProgramStateRef
+ processPointerEscapedOnBind(ProgramStateRef State, SVal Loc, SVal Val) = 0;
+
+ virtual ProgramStateRef
+ notifyCheckersOfPointerEscape(ProgramStateRef State,
+ const InvalidatedSymbols *Invalidated,
+ ArrayRef<const MemRegion *> ExplicitRegions,
+ ArrayRef<const MemRegion *> Regions,
+ const CallEvent *Call,
+ bool IsConst = false) = 0;
+
/// printState - Called by ProgramStateManager to print checker-specific data.
virtual void printState(raw_ostream &Out, ProgramStateRef State,
const char *NL, const char *Sep) = 0;
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
index 873f773..56afca2 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
@@ -20,10 +20,10 @@
#include "clang/Analysis/AnalysisContext.h"
#include "clang/Basic/LLVM.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
-#include "llvm/Support/DataTypes.h"
-#include "llvm/ADT/FoldingSet.h"
-#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/Support/DataTypes.h"
namespace llvm {
class BumpPtrAllocator;
@@ -96,7 +96,7 @@ public:
};
typedef const SymExpr* SymbolRef;
-typedef llvm::SmallVector<SymbolRef, 2> SymbolRefSmallVectorTy;
+typedef SmallVector<SymbolRef, 2> SymbolRefSmallVectorTy;
typedef unsigned SymbolID;
/// \brief A symbol representing data which can be stored in a memory location
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h
index c274cea..4c58d4b 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h
@@ -14,7 +14,11 @@
#ifndef LLVM_CLANG_TAINTMANAGER_H
#define LLVM_CLANG_TAINTMANAGER_H
+#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h"
+#include "llvm/ADT/ImmutableMap.h"
namespace clang {
namespace ento {
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h b/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h
index 51aa753..d12a151 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h
@@ -16,7 +16,8 @@
#define LLVM_CLANG_GR_WORKLIST
#include "clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h"
-#include <cstddef>
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
+#include <cassert>
namespace clang {
@@ -24,9 +25,6 @@ class CFGBlock;
namespace ento {
-class ExplodedNode;
-class ExplodedNodeImpl;
-
class WorkListUnit {
ExplodedNode *node;
BlockCounter counter;
OpenPOWER on IntegriCloud