diff options
-rw-r--r-- | include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h | 8 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngineC.cpp | 3 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ProgramState.cpp | 65 | ||||
-rw-r--r-- | test/Analysis/inlining/InlineObjCInstanceMethod.m | 4 |
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. |