aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h8
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineC.cpp3
-rw-r--r--lib/StaticAnalyzer/Core/ProgramState.cpp65
-rw-r--r--test/Analysis/inlining/InlineObjCInstanceMethod.m4
4 files changed, 75 insertions, 5 deletions
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
index 4e92873860..9d82ec6983 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
@@ -66,6 +66,12 @@ public:
DynamicTypeInfo() : T(QualType()) {}
DynamicTypeInfo(QualType WithType) : T(WithType) {}
QualType getType() {return T;}
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ T.Profile(ID);
+ }
+ bool operator==(const DynamicTypeInfo &X) const {
+ return T == X.T;
+ }
};
/// \class ProgramState
@@ -327,6 +333,8 @@ public:
/// Get dynamic type information for a region.
DynamicTypeInfo getDynamicTypeInfo(const MemRegion *Reg) const;
+ /// Add dynamic type information to the region and return the new state.
+ ProgramStateRef addDynamicTypeInfo(const MemRegion *Reg, QualType NewTy)const;
//==---------------------------------------------------------------------==//
// Accessing the Generic Data Map (GDM).
diff --git a/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 7ec151ef6d..740dec5ec4 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -308,6 +308,9 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
const LocationContext *LCtx = Pred->getLocationContext();
SVal V = state->getSVal(Ex, LCtx);
V = svalBuilder.evalCast(V, T, ExTy);
+ if (const MemRegion *R = V.getAsRegion()) {
+ state = state->addDynamicTypeInfo(R, T);
+ }
state = state->BindExpr(CastE, LCtx, V);
Bldr.generateNode(CastE, Pred, state);
continue;
diff --git a/lib/StaticAnalyzer/Core/ProgramState.cpp b/lib/StaticAnalyzer/Core/ProgramState.cpp
index 20f1e226b8..5730bc985a 100644
--- a/lib/StaticAnalyzer/Core/ProgramState.cpp
+++ b/lib/StaticAnalyzer/Core/ProgramState.cpp
@@ -732,11 +732,70 @@ bool ProgramState::isTainted(SymbolRef Sym, TaintTagType Kind) const {
return Tainted;
}
+/// The GDM component containing the dynamic type info. This is a map from a
+/// symbol to it's most likely type.
+namespace clang {
+namespace ento {
+struct DynamicTypeMap {};
+typedef llvm::ImmutableMap<SymbolRef, DynamicTypeInfo> DynamicTypeMapImpl;
+template<> struct ProgramStateTrait<DynamicTypeMap>
+ : public ProgramStatePartialTrait<DynamicTypeMapImpl> {
+ static void *GDMIndex() { static int index; return &index; }
+};
+}}
+
DynamicTypeInfo ProgramState::getDynamicTypeInfo(const MemRegion *Reg) const {
if (const TypedRegion *TR = dyn_cast<TypedRegion>(Reg))
return DynamicTypeInfo(TR->getLocationType());
- if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(Reg))
- return DynamicTypeInfo(SR->getSymbol()
- ->getType(getStateManager().getContext()));
+
+ if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(Reg)) {
+ SymbolRef Sym = SR->getSymbol();
+ // Lookup the dynamic type in the GDM.
+ const DynamicTypeInfo *GDMType = get<DynamicTypeMap>(Sym);
+ if (GDMType)
+ return *GDMType;
+
+ // Else, lookup the type at point of symbol creation.
+ return DynamicTypeInfo(Sym->getType(getStateManager().getContext()));
+ }
return DynamicTypeInfo();
}
+
+ProgramStateRef ProgramState::addDynamicTypeInfo(const MemRegion *Reg,
+ QualType NewTy) const {
+ if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(Reg)) {
+ SymbolRef Sym = SR->getSymbol();
+ // TODO: Instead of resetting the type info, check the old type info and
+ // merge and pick the most precise type.
+ ProgramStateRef NewState = set<DynamicTypeMap>(Sym, DynamicTypeInfo(NewTy));
+ assert(NewState);
+ return NewState;
+ }
+ return this;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/Analysis/inlining/InlineObjCInstanceMethod.m b/test/Analysis/inlining/InlineObjCInstanceMethod.m
index 8d8f28d923..651d7c5b5a 100644
--- a/test/Analysis/inlining/InlineObjCInstanceMethod.m
+++ b/test/Analysis/inlining/InlineObjCInstanceMethod.m
@@ -20,10 +20,10 @@
return 5/y; // expected-warning {{Division by zero}}
}
-// Method is called on inited object.
+// Get the dynamic type info from a cast (from id to MyClass*).
+ (int)testAllocInit {
MyClass *a = [[self alloc] init];
- return 5/[a getInt]; // todo
+ return 5/[a getInt]; // expected-warning {{Division by zero}}
}
// Method is called on inited object.