aboutsummaryrefslogtreecommitdiff
path: root/include/clang
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang')
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h9
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h66
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h6
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h28
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h39
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h2
6 files changed, 104 insertions, 46 deletions
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
index 3a51182172..875df3a4ec 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
@@ -16,6 +16,7 @@
#define LLVM_CLANG_GR_COREENGINE
#include "clang/AST/Expr.h"
+#include "clang/Analysis/AnalysisContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/WorkList.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h"
@@ -469,6 +470,10 @@ public:
const Expr *getTarget() const { return E; }
const ProgramState *getState() const { return Pred->State; }
+
+ const LocationContext *getLocationContext() const {
+ return Pred->getLocationContext();
+ }
};
class SwitchNodeBuilder {
@@ -518,6 +523,10 @@ public:
const Expr *getCondition() const { return Condition; }
const ProgramState *getState() const { return Pred->State; }
+
+ const LocationContext *getLocationContext() const {
+ return Pred->getLocationContext();
+ }
};
class CallEnterNodeBuilder {
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h
index 2463e23f5f..c58da3ea52 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_GR_ENVIRONMENT_H
#define LLVM_CLANG_GR_ENVIRONMENT_H
+#include "clang/Analysis/AnalysisContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "llvm/ADT/ImmutableMap.h"
@@ -26,15 +27,39 @@ namespace ento {
class EnvironmentManager;
class SValBuilder;
-/// Environment - An immutable map from Stmts to their current
-/// symbolic values (SVals).
-///
+/// An entry in the environment consists of a Stmt and an LocationContext.
+/// This allows the environment to manage context-sensitive bindings,
+/// which is essentially for modeling recursive function analysis, among
+/// other things.
+class EnvironmentEntry : public std::pair<const Stmt*,
+ const StackFrameContext *> {
+public:
+ EnvironmentEntry(const Stmt *s, const LocationContext *L)
+ : std::pair<const Stmt*,
+ const StackFrameContext*>(s, L ? L->getCurrentStackFrame():0) {}
+
+ const Stmt *getStmt() const { return first; }
+ const LocationContext *getLocationContext() const { return second; }
+
+ /// Profile an EnvironmentEntry for inclusion in a FoldingSet.
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ const EnvironmentEntry &E) {
+ ID.AddPointer(E.getStmt());
+ ID.AddPointer(E.getLocationContext());
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ Profile(ID, *this);
+ }
+};
+
+/// An immutable map from EnvironemntEntries to SVals.
class Environment {
private:
friend class EnvironmentManager;
// Type definitions.
- typedef llvm::ImmutableMap<const Stmt*,SVal> BindingsTy;
+ typedef llvm::ImmutableMap<EnvironmentEntry, SVal> BindingsTy;
// Data.
BindingsTy ExprBindings;
@@ -42,18 +67,18 @@ private:
Environment(BindingsTy eb)
: ExprBindings(eb) {}
- SVal lookupExpr(const Stmt *E) const;
+ SVal lookupExpr(const EnvironmentEntry &E) const;
public:
typedef BindingsTy::iterator iterator;
iterator begin() const { return ExprBindings.begin(); }
iterator end() const { return ExprBindings.end(); }
-
- /// getSVal - Fetches the current binding of the expression in the
- /// Environment.
- SVal getSVal(const Stmt *Ex, SValBuilder& svalBuilder,
- bool useOnlyDirectBindings = false) const;
+ /// Fetches the current binding of the expression in the
+ /// Environment.
+ SVal getSVal(const EnvironmentEntry &E,
+ SValBuilder &svalBuilder,
+ bool useOnlyDirectBindings = false) const;
/// Profile - Profile the contents of an Environment object for use
/// in a FoldingSet.
@@ -70,6 +95,12 @@ public:
bool operator==(const Environment& RHS) const {
return ExprBindings == RHS.ExprBindings;
}
+
+ void print(raw_ostream &Out, const char *NL, const char *Sep) const;
+
+private:
+ void printAux(raw_ostream &Out, bool printLocations,
+ const char *NL, const char *Sep) const;
};
class EnvironmentManager {
@@ -85,17 +116,20 @@ public:
return Environment(F.getEmptyMap());
}
- /// Bind the value 'V' to the statement 'S'.
- Environment bindExpr(Environment Env, const Stmt *S, SVal V,
+ /// 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 statement 'S'. This
- /// is used when simulating loads/stores.
- Environment bindExprAndLocation(Environment Env, const Stmt *S, SVal location,
+ /// 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, const ProgramState *ST);
+ SymbolReaper &SymReaper,
+ const ProgramState *state);
};
} // end GR namespace
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index 3877cb88b4..f6d49985cc 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -433,8 +433,10 @@ protected:
const CallOrObjCMessage &Call,
const LocationContext *LC);
- const ProgramState *MarkBranch(const ProgramState *St, const Stmt *Terminator,
- bool branchTaken);
+ const ProgramState *MarkBranch(const ProgramState *state,
+ const Stmt *Terminator,
+ const LocationContext *LCtx,
+ bool branchTaken);
/// evalBind - Handle the semantics of binding a value to a specific location.
/// This method is used by evalStore, VisitDeclStmt, and others.
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h
index 500f587e85..bcaf2591cf 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h
@@ -95,7 +95,7 @@ public:
if (!isInstanceMessage())
return UndefinedVal();
if (const Expr *Ex = getInstanceReceiver())
- return State->getSValAsScalarOrLoc(Ex);
+ return State->getSValAsScalarOrLoc(Ex, LC);
// An instance message with no expression means we are sending to super.
// In this case the object reference is the same as 'self'.
@@ -141,11 +141,13 @@ public:
return isPropertySetter() ? 1 : 0;
}
- SVal getArgSVal(unsigned i, const ProgramState *state) const {
+ SVal getArgSVal(unsigned i,
+ const LocationContext *LCtx,
+ const ProgramState *state) const {
assert(isValid() && "This ObjCMessage is uninitialized!");
assert(i < getNumArgs() && "Invalid index for argument");
if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
- return state->getSVal(msgE->getArg(i));
+ return state->getSVal(msgE->getArg(i), LCtx);
assert(isPropertySetter());
return SetterArgV;
}
@@ -207,13 +209,17 @@ class CallOrObjCMessage {
llvm::PointerUnion<const CallExpr *, const CXXConstructExpr *> CallE;
ObjCMessage Msg;
const ProgramState *State;
+ const LocationContext *LCtx;
public:
- CallOrObjCMessage(const CallExpr *callE, const ProgramState *state)
- : CallE(callE), State(state) {}
- CallOrObjCMessage(const CXXConstructExpr *consE, const ProgramState *state)
- : CallE(consE), State(state) {}
- CallOrObjCMessage(const ObjCMessage &msg, const ProgramState *state)
- : CallE((CallExpr *)0), Msg(msg), State(state) {}
+ CallOrObjCMessage(const CallExpr *callE, const ProgramState *state,
+ const LocationContext *lctx)
+ : CallE(callE), State(state), LCtx(lctx) {}
+ CallOrObjCMessage(const CXXConstructExpr *consE, const ProgramState *state,
+ const LocationContext *lctx)
+ : CallE(consE), State(state), LCtx(lctx) {}
+ CallOrObjCMessage(const ObjCMessage &msg, const ProgramState *state,
+ const LocationContext *lctx)
+ : CallE((CallExpr *)0), Msg(msg), State(state), LCtx(lctx) {}
QualType getResultType(ASTContext &ctx) const;
@@ -272,8 +278,8 @@ public:
SVal getArgSVal(unsigned i) const {
assert(i < getNumArgs());
if (!CallE)
- return Msg.getArgSVal(i, State);
- return State->getSVal(getArg(i));
+ return Msg.getArgSVal(i, LCtx, State);
+ return State->getSVal(getArg(i), LCtx);
}
const Expr *getArg(unsigned i) const {
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
index e9d6d6ec96..c3396d4eb1 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
@@ -196,12 +196,14 @@ public:
/// Create a new state by binding the value 'V' to the statement 'S' in the
/// state's environment.
- const ProgramState *BindExpr(const Stmt *S, SVal V, bool Invalidate = true) const;
+ const ProgramState *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.
- const ProgramState *bindExprAndLocation(const Stmt *S, SVal location, SVal V)
- const;
+ const ProgramState *bindExprAndLocation(const Stmt *S,
+ const LocationContext *LCtx,
+ SVal location, SVal V) const;
const ProgramState *bindDecl(const VarRegion *VR, SVal V) const;
@@ -248,9 +250,10 @@ public:
const llvm::APSInt *getSymVal(SymbolRef sym) const;
/// Returns the SVal bound to the statement 'S' in the state's environment.
- SVal getSVal(const Stmt *S, bool useOnlyDirectBindings = false) const;
+ SVal getSVal(const Stmt *S, const LocationContext *LCtx,
+ bool useOnlyDirectBindings = false) const;
- SVal getSValAsScalarOrLoc(const Stmt *Ex) const;
+ SVal getSValAsScalarOrLoc(const Stmt *Ex, const LocationContext *LCtx) const;
SVal getSVal(Loc LV, QualType T = QualType()) const;
@@ -290,7 +293,7 @@ public:
const MemRegion * const *end) const;
/// Create a new state in which the statement is marked as tainted.
- const ProgramState* addTaint(const Stmt *S,
+ const ProgramState* addTaint(const Stmt *S, const LocationContext *LCtx,
TaintTagType Kind = TaintTagGeneric) const;
/// Create a new state in which the symbol is marked as tainted.
@@ -302,7 +305,8 @@ public:
TaintTagType Kind = TaintTagGeneric) const;
/// Check if the statement is tainted in the current state.
- bool isTainted(const Stmt *S, TaintTagType Kind = TaintTagGeneric) const;
+ bool isTainted(const Stmt *S, const LocationContext *LCtx,
+ TaintTagType Kind = TaintTagGeneric) const;
bool isTainted(SVal V, TaintTagType Kind = TaintTagGeneric) const;
bool isTainted(const SymExpr* Sym, TaintTagType Kind = TaintTagGeneric) const;
bool isTainted(const MemRegion *Reg, TaintTagType Kind=TaintTagGeneric) const;
@@ -361,12 +365,10 @@ public:
}
// Pretty-printing.
- void print(raw_ostream &Out, CFG *C, const char *nl = "\n",
+ void print(raw_ostream &Out, const char *nl = "\n",
const char *sep = "") const;
- void dump(CFG &C) const;
-
- void printDOT(raw_ostream &Out, CFG &C) const;
+ void printDOT(raw_ostream &Out) const;
void dump() const;
@@ -647,7 +649,8 @@ public:
//===----------------------------------------------------------------------===//
inline const VarRegion* ProgramState::getRegion(const VarDecl *D,
- const LocationContext *LC) const {
+ const LocationContext *LC) const
+{
return getStateManager().getRegionManager().getVarRegion(D, LC);
}
@@ -705,16 +708,20 @@ inline const llvm::APSInt *ProgramState::getSymVal(SymbolRef sym) const {
return getStateManager().getSymVal(this, sym);
}
-inline SVal ProgramState::getSVal(const Stmt *Ex, bool useOnlyDirectBindings) const{
- return Env.getSVal(Ex, *getStateManager().svalBuilder,
+inline SVal ProgramState::getSVal(const Stmt *Ex, const LocationContext *LCtx,
+ bool useOnlyDirectBindings) const{
+ return Env.getSVal(EnvironmentEntry(Ex, LCtx),
+ *getStateManager().svalBuilder,
useOnlyDirectBindings);
}
-inline SVal ProgramState::getSValAsScalarOrLoc(const Stmt *S) const {
+inline SVal
+ProgramState::getSValAsScalarOrLoc(const Stmt *S,
+ const LocationContext *LCtx) const {
if (const Expr *Ex = dyn_cast<Expr>(S)) {
QualType T = Ex->getType();
if (Ex->isLValue() || Loc::isLocType(T) || T->isIntegerType())
- return getSVal(S);
+ return getSVal(S, LCtx);
}
return UnknownVal();
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
index 32381e7dec..3690b11eef 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
@@ -577,7 +577,7 @@ public:
bool isLive(SymbolRef sym);
bool isLiveRegion(const MemRegion *region);
- bool isLive(const Stmt *ExprVal) const;
+ bool isLive(const Stmt *ExprVal, const LocationContext *LCtx) const;
bool isLive(const VarRegion *VR, bool includeStoreBindings = false) const;
/// \brief Unconditionally marks a symbol as live.