diff options
Diffstat (limited to 'lib/Analysis')
-rw-r--r-- | lib/Analysis/BasicStore.cpp | 104 | ||||
-rw-r--r-- | lib/Analysis/BugReporter.cpp | 7 | ||||
-rw-r--r-- | lib/Analysis/CFRefCount.cpp | 57 | ||||
-rw-r--r-- | lib/Analysis/CheckDeadStores.cpp | 4 | ||||
-rw-r--r-- | lib/Analysis/CheckObjCDealloc.cpp | 14 | ||||
-rw-r--r-- | lib/Analysis/CheckObjCInstMethSignature.cpp | 8 | ||||
-rw-r--r-- | lib/Analysis/CheckObjCUnusedIVars.cpp | 15 | ||||
-rw-r--r-- | lib/Analysis/Environment.cpp | 15 | ||||
-rw-r--r-- | lib/Analysis/GRExprEngine.cpp | 15 | ||||
-rw-r--r-- | lib/Analysis/GRExprEngineInternalChecks.cpp | 2 | ||||
-rw-r--r-- | lib/Analysis/GRState.cpp | 6 | ||||
-rw-r--r-- | lib/Analysis/LiveVariables.cpp | 3 | ||||
-rw-r--r-- | lib/Analysis/MemRegion.cpp | 46 | ||||
-rw-r--r-- | lib/Analysis/RegionStore.cpp | 135 | ||||
-rw-r--r-- | lib/Analysis/SVals.cpp | 7 | ||||
-rw-r--r-- | lib/Analysis/Store.cpp | 6 |
16 files changed, 263 insertions, 181 deletions
diff --git a/lib/Analysis/BasicStore.cpp b/lib/Analysis/BasicStore.cpp index 8fbce528fa9a6..19d641ee9753a 100644 --- a/lib/Analysis/BasicStore.cpp +++ b/lib/Analysis/BasicStore.cpp @@ -198,7 +198,7 @@ SVal BasicStoreManager::getLValueElement(const GRState *state, return Base; Loc BaseL = cast<Loc>(Base); - const TypedRegion* BaseR = 0; + const MemRegion* BaseR = 0; switch(BaseL.getSubKind()) { case loc::GotoLabelKind: @@ -216,17 +216,11 @@ SVal BasicStoreManager::getLValueElement(const GRState *state, return Base; } - - if (const TypedRegion *TR = dyn_cast<TypedRegion>(R)) { - BaseR = TR; + if (isa<TypedRegion>(R) || isa<SymbolicRegion>(R)) { + BaseR = R; break; } - if (const SymbolicRegion* SR = dyn_cast<SymbolicRegion>(R)) { - SymbolRef Sym = SR->getSymbol(); - BaseR = MRMgr.getTypedViewRegion(Sym->getType(getContext()), SR); - } - break; } @@ -242,9 +236,10 @@ SVal BasicStoreManager::getLValueElement(const GRState *state, return Base; } - if (BaseR) + if (BaseR) { return ValMgr.makeLoc(MRMgr.getElementRegion(elementType, UnknownVal(), BaseR, getContext())); + } else return UnknownVal(); } @@ -319,54 +314,50 @@ SVal BasicStoreManager::Retrieve(const GRState *state, Loc loc, QualType T) { } Store BasicStoreManager::BindInternal(Store store, Loc loc, SVal V) { - switch (loc.getSubKind()) { - case loc::MemRegionKind: { - const MemRegion* R = cast<loc::MemRegionVal>(loc).getRegion(); - ASTContext &C = StateMgr.getContext(); + if (isa<loc::ConcreteInt>(loc)) + return store; + + const MemRegion* R = cast<loc::MemRegionVal>(loc).getRegion(); + ASTContext &C = StateMgr.getContext(); - // Special case: handle store of pointer values (Loc) to pointers via - // a cast to intXX_t*, void*, etc. This is needed to handle - // OSCompareAndSwap32Barrier/OSCompareAndSwap64Barrier. - if (isa<Loc>(V) || isa<nonloc::LocAsInteger>(V)) - if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) { - // FIXME: Should check for index 0. - QualType T = ER->getLocationType(C); + // Special case: handle store of pointer values (Loc) to pointers via + // a cast to intXX_t*, void*, etc. This is needed to handle + // OSCompareAndSwap32Barrier/OSCompareAndSwap64Barrier. + if (isa<Loc>(V) || isa<nonloc::LocAsInteger>(V)) + if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) { + // FIXME: Should check for index 0. + QualType T = ER->getLocationType(C); - if (isHigherOrderRawPtr(T, C)) - R = ER->getSuperRegion(); - } + if (isHigherOrderRawPtr(T, C)) + R = ER->getSuperRegion(); + } - if (!(isa<VarRegion>(R) || isa<ObjCIvarRegion>(R))) - return store; + if (!(isa<VarRegion>(R) || isa<ObjCIvarRegion>(R))) + return store; - // We only track bindings to self.ivar. - if (const ObjCIvarRegion *IVR = dyn_cast<ObjCIvarRegion>(R)) - if (IVR->getSuperRegion() != SelfRegion) - return store; + // We only track bindings to self.ivar. + if (const ObjCIvarRegion *IVR = dyn_cast<ObjCIvarRegion>(R)) + if (IVR->getSuperRegion() != SelfRegion) + return store; - if (nonloc::LocAsInteger *X = dyn_cast<nonloc::LocAsInteger>(&V)) { - // Only convert 'V' to a location iff the underlying region type - // is a location as well. - // FIXME: We are allowing a store of an arbitrary location to - // a pointer. We may wish to flag a type error here if the types - // are incompatible. This may also cause lots of breakage - // elsewhere. Food for thought. - if (const TypedRegion *TyR = dyn_cast<TypedRegion>(R)) { - if (TyR->isBoundable() && - Loc::IsLocType(TyR->getValueType(C))) - V = X->getLoc(); - } - } - - BindingsTy B = GetBindings(store); - return V.isUnknown() - ? VBFactory.Remove(B, R).getRoot() - : VBFactory.Add(B, R, V).getRoot(); + if (nonloc::LocAsInteger *X = dyn_cast<nonloc::LocAsInteger>(&V)) { + // Only convert 'V' to a location iff the underlying region type + // is a location as well. + // FIXME: We are allowing a store of an arbitrary location to + // a pointer. We may wish to flag a type error here if the types + // are incompatible. This may also cause lots of breakage + // elsewhere. Food for thought. + if (const TypedRegion *TyR = dyn_cast<TypedRegion>(R)) { + if (TyR->isBoundable() && + Loc::IsLocType(TyR->getValueType(C))) + V = X->getLoc(); } - default: - assert ("SetSVal for given Loc type not yet implemented."); - return store; } + + BindingsTy B = GetBindings(store); + return V.isUnknown() + ? VBFactory.Remove(B, R).getRoot() + : VBFactory.Add(B, R, V).getRoot(); } Store BasicStoreManager::Remove(Store store, Loc loc) { @@ -521,7 +512,7 @@ Store BasicStoreManager::getInitialStore() { // Scan the method for ivar references. While this requires an // entire AST scan, the cost should not be high in practice. - St = scanForIvars(MD->getBody(getContext()), PD, St); + St = scanForIvars(MD->getBody(), PD, St); } } } @@ -537,10 +528,9 @@ Store BasicStoreManager::getInitialStore() { // Initialize globals and parameters to symbolic values. // Initialize local variables to undefined. const MemRegion *R = ValMgr.getRegionManager().getVarRegion(VD); - SVal X = (VD->hasGlobalStorage() || isa<ParmVarDecl>(VD) || - isa<ImplicitParamDecl>(VD)) - ? ValMgr.getRegionValueSymbolVal(R) - : UndefinedVal(); + SVal X = R->hasGlobalsOrParametersStorage() + ? ValMgr.getRegionValueSymbolVal(R) + : UndefinedVal(); St = BindInternal(St, ValMgr.makeLoc(R), X); } @@ -594,7 +584,7 @@ Store BasicStoreManager::BindDeclInternal(Store store, const VarDecl* VD, } else { // Process local scalar variables. QualType T = VD->getType(); - if (Loc::IsLocType(T) || T->isIntegerType()) { + if (ValMgr.getSymbolManager().canSymbolicate(T)) { SVal V = InitVal ? *InitVal : UndefinedVal(); store = BindInternal(store, getLoc(VD), V); } diff --git a/lib/Analysis/BugReporter.cpp b/lib/Analysis/BugReporter.cpp index 38ea458a65994..3db96ca9eacba 100644 --- a/lib/Analysis/BugReporter.cpp +++ b/lib/Analysis/BugReporter.cpp @@ -146,7 +146,7 @@ public: ParentMap& getParentMap() { if (PM.get() == 0) - PM.reset(new ParentMap(getCodeDecl().getBody(getASTContext()))); + PM.reset(new ParentMap(getCodeDecl().getBody())); return *PM.get(); } @@ -182,8 +182,7 @@ PathDiagnosticBuilder::ExecutionContinues(const ExplodedNode<GRState>* N) { if (Stmt *S = GetNextStmt(N)) return PathDiagnosticLocation(S, getSourceManager()); - return FullSourceLoc(getCodeDecl().getBodyRBrace(getASTContext()), - getSourceManager()); + return FullSourceLoc(getCodeDecl().getBodyRBrace(), getSourceManager()); } PathDiagnosticLocation @@ -893,7 +892,7 @@ public: // statement (if it doesn't already exist). // FIXME: Should handle CXXTryStmt if analyser starts supporting C++. if (const CompoundStmt *CS = - PDB.getCodeDecl().getCompoundBody(PDB.getASTContext())) + PDB.getCodeDecl().getCompoundBody()) if (!CS->body_empty()) { SourceLocation Loc = (*CS->body_begin())->getLocStart(); rawAddEdge(PathDiagnosticLocation(Loc, PDB.getSourceManager())); diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp index f4a28e0c19fd2..3cca482633caf 100644 --- a/lib/Analysis/CFRefCount.cpp +++ b/lib/Analysis/CFRefCount.cpp @@ -156,13 +156,13 @@ static bool followsFundamentalRule(Selector S) { } static const ObjCMethodDecl* -ResolveToInterfaceMethodDecl(const ObjCMethodDecl *MD, ASTContext &Context) { +ResolveToInterfaceMethodDecl(const ObjCMethodDecl *MD) { ObjCInterfaceDecl *ID = const_cast<ObjCInterfaceDecl*>(MD->getClassInterface()); return MD->isInstanceMethod() - ? ID->lookupInstanceMethod(Context, MD->getSelector()) - : ID->lookupClassMethod(Context, MD->getSelector()); + ? ID->lookupInstanceMethod(MD->getSelector()) + : ID->lookupClassMethod(MD->getSelector()); } namespace { @@ -827,8 +827,7 @@ public: QualType ResultTy = MD->getResultType(); // Resolve the method decl last. - if (const ObjCMethodDecl *InterfaceMD = - ResolveToInterfaceMethodDecl(MD, Ctx)) + if (const ObjCMethodDecl *InterfaceMD = ResolveToInterfaceMethodDecl(MD)) MD = InterfaceMD; if (MD->isInstanceMethod()) @@ -1248,15 +1247,15 @@ RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ, // Determine if there is a special return effect for this method. if (isTrackedObjCObjectType(RetTy)) { - if (FD->getAttr<NSReturnsRetainedAttr>(Ctx)) { + if (FD->getAttr<NSReturnsRetainedAttr>()) { Summ.setRetEffect(ObjCAllocRetE); } - else if (FD->getAttr<CFReturnsRetainedAttr>(Ctx)) { + else if (FD->getAttr<CFReturnsRetainedAttr>()) { Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true)); } } else if (RetTy->getAsPointerType()) { - if (FD->getAttr<CFReturnsRetainedAttr>(Ctx)) { + if (FD->getAttr<CFReturnsRetainedAttr>()) { Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true)); } } @@ -1270,10 +1269,10 @@ RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ, // Determine if there is a special return effect for this method. if (isTrackedObjCObjectType(MD->getResultType())) { - if (MD->getAttr<NSReturnsRetainedAttr>(Ctx)) { + if (MD->getAttr<NSReturnsRetainedAttr>()) { Summ.setRetEffect(ObjCAllocRetE); } - else if (MD->getAttr<CFReturnsRetainedAttr>(Ctx)) { + else if (MD->getAttr<CFReturnsRetainedAttr>()) { Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true)); } } @@ -2632,7 +2631,7 @@ CFRefLeakReport::getEndPath(BugReporterContext& BRC, if (!L.isValid()) { const Decl &D = BRC.getCodeDecl(); - L = PathDiagnosticLocation(D.getBodyRBrace(BRC.getASTContext()), SMgr); + L = PathDiagnosticLocation(D.getBodyRBrace(), SMgr); } std::string sbuf; @@ -2796,7 +2795,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst, // to identify conjured symbols by an expression pair: the enclosing // expression (the context) and the expression itself. This should // disambiguate conjured symbols. - + unsigned Count = Builder.getCurrentBlockCount(); const TypedRegion* R = dyn_cast<TypedRegion>(MR->getRegion()); if (R) { @@ -2833,7 +2832,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst, if (R->isBoundable()) { // Set the value of the variable to be a conjured symbol. - unsigned Count = Builder.getCurrentBlockCount(); + QualType T = R->getValueType(Ctx); if (Loc::IsLocType(T) || (T->isIntegerType() && T->isScalarType())){ @@ -2857,20 +2856,31 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst, state->getStateManager().getRegionManager(); // Iterate through the fields and construct new symbols. - for (RecordDecl::field_iterator FI=RD->field_begin(Ctx), - FE=RD->field_end(Ctx); FI!=FE; ++FI) { + for (RecordDecl::field_iterator FI=RD->field_begin(), + FE=RD->field_end(); FI!=FE; ++FI) { // For now just handle scalar fields. FieldDecl *FD = *FI; QualType FT = FD->getType(); - + const FieldRegion* FR = MRMgr.getFieldRegion(FD, R); + if (Loc::IsLocType(FT) || (FT->isIntegerType() && FT->isScalarType())) { - const FieldRegion* FR = MRMgr.getFieldRegion(FD, R); - SVal V = ValMgr.getConjuredSymbolVal(*I, FT, Count); state = state->bindLoc(ValMgr.makeLoc(FR), V); - } + } + else if (FT->isStructureType()) { + // set the default value of the struct field to conjured + // symbol. Note that the type of the symbol is irrelavant. + // We cannot use the type of the struct otherwise ValMgr won't + // give us the conjured symbol. + StoreManager& StoreMgr = + Eng.getStateManager().getStoreManager(); + SVal V = ValMgr.getConjuredSymbolVal(*I, + Eng.getContext().IntTy, + Count); + state = StoreMgr.setDefaultValue(state, FR, V); + } } } else if (const ArrayType *AT = Ctx.getAsArrayType(T)) { // Set the default value of the array to conjured symbol. @@ -2884,6 +2894,15 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst, } } } + else if (isa<AllocaRegion>(MR->getRegion())) { + // Invalidate the alloca region by setting its default value to + // conjured symbol. The type of the symbol is irrelavant. + SVal V = ValMgr.getConjuredSymbolVal(*I, Eng.getContext().IntTy, + Count); + StoreManager& StoreMgr = + Eng.getStateManager().getStoreManager(); + state = StoreMgr.setDefaultValue(state, MR->getRegion(), V); + } else state = state->bindLoc(*MR, UnknownVal()); } diff --git a/lib/Analysis/CheckDeadStores.cpp b/lib/Analysis/CheckDeadStores.cpp index 0f61a5ee916a1..69433d6396a5b 100644 --- a/lib/Analysis/CheckDeadStores.cpp +++ b/lib/Analysis/CheckDeadStores.cpp @@ -85,7 +85,7 @@ public: const LiveVariables::AnalysisDataTy& AD, const LiveVariables::ValTy& Live) { - if (VD->hasLocalStorage() && !Live(VD, AD) && !VD->getAttr<UnusedAttr>(Ctx)) + if (VD->hasLocalStorage() && !Live(VD, AD) && !VD->getAttr<UnusedAttr>()) Report(VD, dsk, Ex->getSourceRange().getBegin(), Val->getSourceRange()); } @@ -190,7 +190,7 @@ public: // A dead initialization is a variable that is dead after it // is initialized. We don't flag warnings for those variables // marked 'unused'. - if (!Live(V, AD) && V->getAttr<UnusedAttr>(Ctx) == 0) { + if (!Live(V, AD) && V->getAttr<UnusedAttr>() == 0) { // Special case: check for initializations with constants. // // e.g. : int x = 0; diff --git a/lib/Analysis/CheckObjCDealloc.cpp b/lib/Analysis/CheckObjCDealloc.cpp index 2ba7d868e90b2..a14ae265128b9 100644 --- a/lib/Analysis/CheckObjCDealloc.cpp +++ b/lib/Analysis/CheckObjCDealloc.cpp @@ -109,7 +109,7 @@ void clang::CheckObjCDealloc(ObjCImplementationDecl* D, QualType T = ID->getType(); if (!Ctx.isObjCObjectPointerType(T) || - ID->getAttr<IBOutletAttr>(Ctx)) // Skip IBOutlets. + ID->getAttr<IBOutletAttr>()) // Skip IBOutlets. continue; containsPointerIvar = true; @@ -147,8 +147,8 @@ void clang::CheckObjCDealloc(ObjCImplementationDecl* D, ObjCMethodDecl* MD = 0; // Scan the instance methods for "dealloc". - for (ObjCImplementationDecl::instmeth_iterator I = D->instmeth_begin(Ctx), - E = D->instmeth_end(Ctx); I!=E; ++I) { + for (ObjCImplementationDecl::instmeth_iterator I = D->instmeth_begin(), + E = D->instmeth_end(); I!=E; ++I) { if ((*I)->getSelector() == S) { MD = *I; @@ -172,7 +172,7 @@ void clang::CheckObjCDealloc(ObjCImplementationDecl* D, } // dealloc found. Scan for missing [super dealloc]. - if (MD->getBody(Ctx) && !scan_dealloc(MD->getBody(Ctx), S)) { + if (MD->getBody() && !scan_dealloc(MD->getBody(), S)) { const char* name = LOpts.getGCMode() == LangOptions::NonGC ? "missing [super dealloc]" @@ -198,8 +198,8 @@ void clang::CheckObjCDealloc(ObjCImplementationDecl* D, // Scan for missing and extra releases of ivars used by implementations // of synthesized properties - for (ObjCImplementationDecl::propimpl_iterator I = D->propimpl_begin(Ctx), - E = D->propimpl_end(Ctx); I!=E; ++I) { + for (ObjCImplementationDecl::propimpl_iterator I = D->propimpl_begin(), + E = D->propimpl_end(); I!=E; ++I) { // We can only check the synthesized properties if((*I)->getPropertyImplementation() != ObjCPropertyImplDecl::Synthesize) @@ -223,7 +223,7 @@ void clang::CheckObjCDealloc(ObjCImplementationDecl* D, // ivar must be released if and only if the kind of setter was not 'assign' bool requiresRelease = PD->getSetterKind() != ObjCPropertyDecl::Assign; - if(scan_ivar_release(MD->getBody(Ctx), ID, PD, RS, SelfII, Ctx) + if(scan_ivar_release(MD->getBody(), ID, PD, RS, SelfII, Ctx) != requiresRelease) { const char *name; const char* category = "Memory (Core Foundation/Objective-C)"; diff --git a/lib/Analysis/CheckObjCInstMethSignature.cpp b/lib/Analysis/CheckObjCInstMethSignature.cpp index 9fec7c1dc1115..28814867bd589 100644 --- a/lib/Analysis/CheckObjCInstMethSignature.cpp +++ b/lib/Analysis/CheckObjCInstMethSignature.cpp @@ -86,8 +86,8 @@ void clang::CheckObjCInstMethSignature(ObjCImplementationDecl* ID, MapTy IMeths; unsigned NumMethods = 0; - for (ObjCImplementationDecl::instmeth_iterator I=ID->instmeth_begin(Ctx), - E=ID->instmeth_end(Ctx); I!=E; ++I) { + for (ObjCImplementationDecl::instmeth_iterator I=ID->instmeth_begin(), + E=ID->instmeth_end(); I!=E; ++I) { ObjCMethodDecl* M = *I; IMeths[M->getSelector()] = M; @@ -97,8 +97,8 @@ void clang::CheckObjCInstMethSignature(ObjCImplementationDecl* ID, // Now recurse the class hierarchy chain looking for methods with the // same signatures. while (C && NumMethods) { - for (ObjCInterfaceDecl::instmeth_iterator I=C->instmeth_begin(Ctx), - E=C->instmeth_end(Ctx); I!=E; ++I) { + for (ObjCInterfaceDecl::instmeth_iterator I=C->instmeth_begin(), + E=C->instmeth_end(); I!=E; ++I) { ObjCMethodDecl* M = *I; Selector S = M->getSelector(); diff --git a/lib/Analysis/CheckObjCUnusedIVars.cpp b/lib/Analysis/CheckObjCUnusedIVars.cpp index 21dc658dfa1a5..0063c40482a0e 100644 --- a/lib/Analysis/CheckObjCUnusedIVars.cpp +++ b/lib/Analysis/CheckObjCUnusedIVars.cpp @@ -59,9 +59,6 @@ void clang::CheckObjCUnusedIvar(ObjCImplementationDecl* D, BugReporter& BR) { ObjCInterfaceDecl* ID = D->getClassInterface(); IvarUsageMap M; - - ASTContext &Ctx = BR.getContext(); - // Iterate over the ivars. for (ObjCInterfaceDecl::ivar_iterator I=ID->ivar_begin(), E=ID->ivar_end(); I!=E; ++I) { @@ -73,7 +70,7 @@ void clang::CheckObjCUnusedIvar(ObjCImplementationDecl* D, BugReporter& BR) { continue; // Skip IB Outlets. - if (ID->getAttr<IBOutletAttr>(Ctx)) + if (ID->getAttr<IBOutletAttr>()) continue; M[ID] = Unused; @@ -83,14 +80,14 @@ void clang::CheckObjCUnusedIvar(ObjCImplementationDecl* D, BugReporter& BR) { return; // Now scan the methods for accesses. - for (ObjCImplementationDecl::instmeth_iterator I = D->instmeth_begin(Ctx), - E = D->instmeth_end(Ctx); I!=E; ++I) - Scan(M, (*I)->getBody(Ctx)); + for (ObjCImplementationDecl::instmeth_iterator I = D->instmeth_begin(), + E = D->instmeth_end(); I!=E; ++I) + Scan(M, (*I)->getBody()); // Scan for @synthesized property methods that act as setters/getters // to an ivar. - for (ObjCImplementationDecl::propimpl_iterator I = D->propimpl_begin(Ctx), - E = D->propimpl_end(Ctx); I!=E; ++I) + for (ObjCImplementationDecl::propimpl_iterator I = D->propimpl_begin(), + E = D->propimpl_end(); I!=E; ++I) Scan(M, *I); // Find ivars that are unused. diff --git a/lib/Analysis/Environment.cpp b/lib/Analysis/Environment.cpp index 2b751df830c2f..3f8f14dcb0b4e 100644 --- a/lib/Analysis/Environment.cpp +++ b/lib/Analysis/Environment.cpp @@ -143,8 +143,19 @@ EnvironmentManager::RemoveDeadBindings(Environment Env, Stmt* Loc, SVal X = I.getData(); // If the block expr's value is a memory region, then mark that region. - if (isa<loc::MemRegionVal>(X)) - DRoots.push_back(cast<loc::MemRegionVal>(X).getRegion()); + if (isa<loc::MemRegionVal>(X)) { + const MemRegion* R = cast<loc::MemRegionVal>(X).getRegion(); + DRoots.push_back(R); + // Mark the super region of the RX as live. + // e.g.: int x; char *y = (char*) &x; if (*y) ... + // 'y' => element region. 'x' is its super region. + // We only add one level super region for now. + + // FIXME: maybe multiple level of super regions should be added. + if (const SubRegion *SR = dyn_cast<SubRegion>(R)) { + DRoots.push_back(SR->getSuperRegion()); + } + } // Mark all symbols in the block expr's value live. MarkLiveCallback cb(SymReaper); diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index 8b4f5c8f11c10..d9117f5930e61 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -1437,8 +1437,8 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, NodeTy* Pred, SaveAndRestore<bool> OldSink(Builder->BuildSinks); const FunctionDecl* FD = L.getAsFunctionDecl(); if (FD) { - if (FD->getAttr<NoReturnAttr>(getContext()) || - FD->getAttr<AnalyzerNoReturnAttr>(getContext())) + if (FD->getAttr<NoReturnAttr>() || + FD->getAttr<AnalyzerNoReturnAttr>()) Builder->BuildSinks = true; else { // HACK: Some functions are not marked noreturn, and don't return. @@ -3154,7 +3154,8 @@ struct VISIBILITY_HIDDEN DOTGraphTraits<GRExprEngine::NodeTy*> : SourceLocation SLoc = S->getLocStart(); Out << S->getStmtClassName() << ' ' << (void*) S << ' '; - S->printPretty(Out); + LangOptions LO; // FIXME. + S->printPretty(Out, 0, PrintingPolicy(LO)); if (SLoc.isFileID()) { Out << "\\lline=" @@ -3208,7 +3209,8 @@ struct VISIBILITY_HIDDEN DOTGraphTraits<GRExprEngine::NodeTy*> : SourceLocation SLoc = T->getLocStart(); Out << "\\|Terminator: "; - E.getSrc()->printTerminator(Out); + LangOptions LO; // FIXME. + E.getSrc()->printTerminator(Out, LO); if (SLoc.isFileID()) { Out << "\\lline=" @@ -3223,11 +3225,12 @@ struct VISIBILITY_HIDDEN DOTGraphTraits<GRExprEngine::NodeTy*> : if (Label) { if (CaseStmt* C = dyn_cast<CaseStmt>(Label)) { Out << "\\lcase "; - C->getLHS()->printPretty(Out); + LangOptions LO; // FIXME. + C->getLHS()->printPretty(Out, 0, PrintingPolicy(LO)); if (Stmt* RHS = C->getRHS()) { Out << " .. "; - RHS->printPretty(Out); + RHS->printPretty(Out, 0, PrintingPolicy(LO)); } Out << ":"; diff --git a/lib/Analysis/GRExprEngineInternalChecks.cpp b/lib/Analysis/GRExprEngineInternalChecks.cpp index 76d26dd9f02af..a2ce79a2f390d 100644 --- a/lib/Analysis/GRExprEngineInternalChecks.cpp +++ b/lib/Analysis/GRExprEngineInternalChecks.cpp @@ -566,7 +566,7 @@ public: if (!FD) return false; - const NonNullAttr* Att = FD->getAttr<NonNullAttr>(BR.getContext()); + const NonNullAttr* Att = FD->getAttr<NonNullAttr>(); if (!Att) return false; diff --git a/lib/Analysis/GRState.cpp b/lib/Analysis/GRState.cpp index 493edc37bacbb..54c0afbff33ee 100644 --- a/lib/Analysis/GRState.cpp +++ b/lib/Analysis/GRState.cpp @@ -166,7 +166,8 @@ void GRState::print(llvm::raw_ostream& Out, const char* nl, else { Out << nl; } Out << " (" << (void*) I.getKey() << ") "; - I.getKey()->printPretty(Out); + LangOptions LO; // FIXME. + I.getKey()->printPretty(Out, 0, PrintingPolicy(LO)); Out << " : "; I.getData().print(Out); } @@ -183,7 +184,8 @@ void GRState::print(llvm::raw_ostream& Out, const char* nl, else { Out << nl; } Out << " (" << (void*) I.getKey() << ") "; - I.getKey()->printPretty(Out); + LangOptions LO; // FIXME. + I.getKey()->printPretty(Out, 0, PrintingPolicy(LO)); Out << " : "; I.getData().print(Out); } diff --git a/lib/Analysis/LiveVariables.cpp b/lib/Analysis/LiveVariables.cpp index b0eb37b065244..aead7f43ad8f6 100644 --- a/lib/Analysis/LiveVariables.cpp +++ b/lib/Analysis/LiveVariables.cpp @@ -135,9 +135,10 @@ void TransferFuncs::Visit(Stmt *S) { StmtVisitor<TransferFuncs,void>::Visit(S); } - else + else { // For block-level expressions, mark that they are live. LiveState(S,AD) = Alive; + } } void TransferFuncs::VisitTerminator(CFGBlock* B) { diff --git a/lib/Analysis/MemRegion.cpp b/lib/Analysis/MemRegion.cpp index c8e027579a309..45305403585a8 100644 --- a/lib/Analysis/MemRegion.cpp +++ b/lib/Analysis/MemRegion.cpp @@ -143,6 +143,10 @@ void CodeTextRegion::Profile(llvm::FoldingSetNodeID& ID) const { // Region pretty-printing. //===----------------------------------------------------------------------===// +void MemRegion::printStdErr() const { + print(llvm::errs()); +} + std::string MemRegion::getString() const { std::string s; llvm::raw_string_ostream os(s); @@ -184,7 +188,8 @@ void FieldRegion::print(llvm::raw_ostream& os) const { } void StringRegion::print(llvm::raw_ostream& os) const { - Str->printPretty(os); + LangOptions LO; // FIXME. + Str->printPretty(os, 0, PrintingPolicy(LO)); } void SymbolicRegion::print(llvm::raw_ostream& os) const { @@ -218,6 +223,10 @@ MemSpaceRegion* MemRegionManager::getStackRegion() { return LazyAllocate(stack); } +MemSpaceRegion* MemRegionManager::getStackArgumentsRegion() { + return LazyAllocate(stackArguments); +} + MemSpaceRegion* MemRegionManager::getGlobalsRegion() { return LazyAllocate(globals); } @@ -327,8 +336,10 @@ const MemSpaceRegion *MemRegion::getMemorySpace() const { } bool MemRegion::hasStackStorage() const { - if (const MemSpaceRegion *MS = getMemorySpace()) - return MS == getMemRegionManager()->getStackRegion(); + if (const MemSpaceRegion *MS = getMemorySpace()) { + MemRegionManager *Mgr = getMemRegionManager(); + return MS == Mgr->getStackRegion() || MS == Mgr->getStackArgumentsRegion(); + } return false; } @@ -343,10 +354,35 @@ bool MemRegion::hasHeapStorage() const { bool MemRegion::hasHeapOrStackStorage() const { if (const MemSpaceRegion *MS = getMemorySpace()) { MemRegionManager *Mgr = getMemRegionManager(); - return MS == Mgr->getHeapRegion() || MS == Mgr->getStackRegion(); + return MS == Mgr->getHeapRegion() + || MS == Mgr->getStackRegion() + || MS == Mgr->getStackArgumentsRegion(); } return false; -} +} + +bool MemRegion::hasGlobalsStorage() const { + if (const MemSpaceRegion *MS = getMemorySpace()) + return MS == getMemRegionManager()->getGlobalsRegion(); + + return false; +} + +bool MemRegion::hasParametersStorage() const { + if (const MemSpaceRegion *MS = getMemorySpace()) + return MS == getMemRegionManager()->getStackArgumentsRegion(); + + return false; +} + +bool MemRegion::hasGlobalsOrParametersStorage() const { + if (const MemSpaceRegion *MS = getMemorySpace()) { + MemRegionManager *Mgr = getMemRegionManager(); + return MS == Mgr->getGlobalsRegion() + || MS == Mgr->getStackArgumentsRegion(); + } + return false; +} //===----------------------------------------------------------------------===// // View handling. diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp index d45048de1a42f..23e8b738b601f 100644 --- a/lib/Analysis/RegionStore.cpp +++ b/lib/Analysis/RegionStore.cpp @@ -347,9 +347,6 @@ public: // FIXME: Remove. ASTContext& getContext() { return StateMgr.getContext(); } - - // FIXME: Use ValueManager? - SymbolManager& getSymbolManager() { return StateMgr.getSymbolManager(); } }; } // end anonymous namespace @@ -822,12 +819,6 @@ SVal RegionStoreManager::Retrieve(const GRState *state, Loc L, QualType T) { const TypedRegion *R = cast<TypedRegion>(MR); assert(R && "bad region"); - if (const FieldRegion* FR = dyn_cast<FieldRegion>(R)) - return RetrieveField(state, FR); - - if (const ElementRegion* ER = dyn_cast<ElementRegion>(R)) - return RetrieveElement(state, ER); - // FIXME: We should eventually handle funny addressing. e.g.: // // int x = ...; @@ -848,6 +839,12 @@ SVal RegionStoreManager::Retrieve(const GRState *state, Loc L, QualType T) { // FIXME: handle Vector types. if (RTy->isVectorType()) return UnknownVal(); + + if (const FieldRegion* FR = dyn_cast<FieldRegion>(R)) + return RetrieveField(state, FR); + + if (const ElementRegion* ER = dyn_cast<ElementRegion>(R)) + return RetrieveElement(state, ER); RegionBindingsTy B = GetRegionBindings(state->getStore()); RegionBindingsTy::data_type* V = B.lookup(R); @@ -882,14 +879,8 @@ SVal RegionStoreManager::Retrieve(const GRState *state, Loc L, QualType T) { if (VD == SelfDecl) return loc::MemRegionVal(getSelfRegion(0)); - if (isa<ParmVarDecl>(VD) || isa<ImplicitParamDecl>(VD) || - VD->hasGlobalStorage()) { - QualType VTy = VD->getType(); - if (Loc::IsLocType(VTy) || VTy->isIntegerType()) - return ValMgr.getRegionValueSymbolVal(VR); - else - return UnknownVal(); - } + if (VR->hasGlobalsOrParametersStorage()) + return ValMgr.getRegionValueSymbolValOrUnknown(VR, VD->getType()); } if (R->hasHeapOrStackStorage()) { @@ -907,23 +898,21 @@ SVal RegionStoreManager::Retrieve(const GRState *state, Loc L, QualType T) { RTy = T->getAsPointerType()->getPointeeType(); } - // All other integer values are symbolic. - if (Loc::IsLocType(RTy) || RTy->isIntegerType()) - return ValMgr.getRegionValueSymbolVal(R, RTy); - else - return UnknownVal(); + // All other values are symbolic. + return ValMgr.getRegionValueSymbolValOrUnknown(R, RTy); } SVal RegionStoreManager::RetrieveElement(const GRState* state, const ElementRegion* R) { // Check if the region has a binding. RegionBindingsTy B = GetRegionBindings(state->getStore()); - const SVal* V = B.lookup(R); - if (V) + if (const SVal* V = B.lookup(R)) return *V; + const MemRegion* superR = R->getSuperRegion(); + // Check if the region is an element region of a string literal. - if (const StringRegion *StrR=dyn_cast<StringRegion>(R->getSuperRegion())) { + if (const StringRegion *StrR=dyn_cast<StringRegion>(superR)) { const StringLiteral *Str = StrR->getStringLiteral(); SVal Idx = R->getIndex(); if (nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(&Idx)) { @@ -937,18 +926,38 @@ SVal RegionStoreManager::RetrieveElement(const GRState* state, } } - const MemRegion* SuperR = R->getSuperRegion(); - const SVal* D = state->get<RegionDefaultValue>(SuperR); - - if (D) { + // Check if the super region has a default value. + if (const SVal *D = state->get<RegionDefaultValue>(superR)) { if (D->hasConjuredSymbol()) return ValMgr.getRegionValueSymbolVal(R); else return *D; } - if (R->hasHeapOrStackStorage()) + // Check if the super region has a binding. + if (B.lookup(superR)) { + // We do not extract the bit value from super region for now. + return UnknownVal(); + } + + if (R->hasHeapStorage()) { + // FIXME: If the region has heap storage and we know nothing special + // about its bindings, should we instead return UnknownVal? Seems like + // we should only return UndefinedVal in the cases where we know the value + // will be undefined. return UndefinedVal(); + } + + if (R->hasStackStorage() && !R->hasParametersStorage()) { + // Currently we don't reason specially about Clang-style vectors. Check + // if superR is a vector and if so return Unknown. + if (const TypedRegion *typedSuperR = dyn_cast<TypedRegion>(superR)) { + if (typedSuperR->getValueType(getContext())->isVectorType()) + return UnknownVal(); + } + + return UndefinedVal(); + } QualType Ty = R->getValueType(getContext()); @@ -957,10 +966,7 @@ SVal RegionStoreManager::RetrieveElement(const GRState* state, if (const QualType *p = state->get<RegionCasts>(R)) Ty = (*p)->getAsPointerType()->getPointeeType(); - if (Loc::IsLocType(Ty) || Ty->isIntegerType()) - return ValMgr.getRegionValueSymbolVal(R, Ty); - else - return UnknownVal(); + return ValMgr.getRegionValueSymbolValOrUnknown(R, Ty); } SVal RegionStoreManager::RetrieveField(const GRState* state, @@ -969,13 +975,11 @@ SVal RegionStoreManager::RetrieveField(const GRState* state, // Check if the region has a binding. RegionBindingsTy B = GetRegionBindings(state->getStore()); - const SVal* V = B.lookup(R); - if (V) + if (const SVal* V = B.lookup(R)) return *V; - const MemRegion* SuperR = R->getSuperRegion(); - const SVal* D = state->get<RegionDefaultValue>(SuperR); - if (D) { + const MemRegion* superR = R->getSuperRegion(); + if (const SVal* D = state->get<RegionDefaultValue>(superR)) { if (D->hasConjuredSymbol()) return ValMgr.getRegionValueSymbolVal(R); @@ -988,7 +992,11 @@ SVal RegionStoreManager::RetrieveField(const GRState* state, assert(0 && "Unknown default value"); } - if (R->hasHeapOrStackStorage()) + // FIXME: Is this correct? Should it be UnknownVal? + if (R->hasHeapStorage()) + return UndefinedVal(); + + if (R->hasStackStorage() && !R->hasParametersStorage()) return UndefinedVal(); // If the region is already cast to another type, use that type to create the @@ -998,11 +1006,8 @@ SVal RegionStoreManager::RetrieveField(const GRState* state, Ty = tmp->getAsPointerType()->getPointeeType(); } - // All other integer values are symbolic. - if (Loc::IsLocType(Ty) || Ty->isIntegerType()) - return ValMgr.getRegionValueSymbolVal(R, Ty); - else - return UnknownVal(); + // All other values are symbolic. + return ValMgr.getRegionValueSymbolValOrUnknown(R, Ty); } SVal RegionStoreManager::RetrieveStruct(const GRState *state, @@ -1018,8 +1023,7 @@ SVal RegionStoreManager::RetrieveStruct(const GRState *state, // FIXME: We shouldn't use a std::vector. If RecordDecl doesn't have a // reverse iterator, we should implement one. - std::vector<FieldDecl *> Fields(RD->field_begin(getContext()), - RD->field_end(getContext())); + std::vector<FieldDecl *> Fields(RD->field_begin(), RD->field_end()); for (std::vector<FieldDecl *>::reverse_iterator Field = Fields.rbegin(), FieldEnd = Fields.rend(); @@ -1074,6 +1078,9 @@ Store RegionStoreManager::Remove(Store store, Loc L) { } const GRState *RegionStoreManager::Bind(const GRState *state, Loc L, SVal V) { + if (isa<loc::ConcreteInt>(L)) + return state; + // If we get here, the location should be a region. const MemRegion* R = cast<loc::MemRegionVal>(L).getRegion(); @@ -1204,8 +1211,7 @@ RegionStoreManager::BindStruct(const GRState *state, const TypedRegion* R, RecordDecl::field_iterator FI, FE; - for (FI = RD->field_begin(getContext()), FE = RD->field_end(getContext()); - FI != FE; ++FI, ++VI) { + for (FI = RD->field_begin(), FE = RD->field_end(); FI != FE; ++FI, ++VI) { if (VI == VE) break; @@ -1357,8 +1363,9 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState *state, Stmt* Loc, IntermediateRoots.pop_back(); if (const VarRegion* VR = dyn_cast<VarRegion>(R)) { - if (SymReaper.isLive(Loc, VR->getDecl())) + if (SymReaper.isLive(Loc, VR->getDecl())) { RegionRoots.push_back(VR); // This is a live "root". + } } else if (const SymbolicRegion* SR = dyn_cast<SymbolicRegion>(R)) { if (SymReaper.isLive(SR->getSymbol())) @@ -1366,19 +1373,19 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState *state, Stmt* Loc, } else { // Get the super region for R. - const MemRegion* SuperR = cast<SubRegion>(R)->getSuperRegion(); + const MemRegion* superR = cast<SubRegion>(R)->getSuperRegion(); // Get the current set of subregions for SuperR. - const SubRegionsTy* SRptr = SubRegMap.lookup(SuperR); + const SubRegionsTy* SRptr = SubRegMap.lookup(superR); SubRegionsTy SRs = SRptr ? *SRptr : SubRegF.GetEmptySet(); // Add R to the subregions of SuperR. - SubRegMap = SubRegMapF.Add(SubRegMap, SuperR, SubRegF.Add(SRs, R)); + SubRegMap = SubRegMapF.Add(SubRegMap, superR, SubRegF.Add(SRs, R)); // Super region may be VarRegion or subregion of another VarRegion. Add it // to the work list. - if (isa<SubRegion>(SuperR)) - IntermediateRoots.push_back(SuperR); + if (isa<SubRegion>(superR)) + IntermediateRoots.push_back(superR); } } @@ -1409,9 +1416,19 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState *state, Stmt* Loc, SVal X = *Xptr; UpdateLiveSymbols(X, SymReaper); // Update the set of live symbols. - // If X is a region, then add it the RegionRoots. - if (loc::MemRegionVal* RegionX = dyn_cast<loc::MemRegionVal>(&X)) - RegionRoots.push_back(RegionX->getRegion()); + // If X is a region, then add it to the RegionRoots. + if (const MemRegion *RX = X.getAsRegion()) { + RegionRoots.push_back(RX); + + // Mark the super region of the RX as live. + // e.g.: int x; char *y = (char*) &x; if (*y) ... + // 'y' => element region. 'x' is its super region. + // We only add one level super region for now. + // FIXME: maybe multiple level of super regions should be added. + if (const SubRegion *SR = dyn_cast<SubRegion>(RX)) { + RegionRoots.push_back(SR->getSuperRegion()); + } + } } // Get the subregions of R. These are RegionRoots as well since they @@ -1422,6 +1439,7 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState *state, Stmt* Loc, for (SubRegionsTy::iterator I=SR.begin(), E=SR.end(); I!=E; ++I) RegionRoots.push_back(*I); + } // We have now scanned the store, marking reachable regions and symbols @@ -1429,7 +1447,6 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState *state, Stmt* Loc, // as well as update DSymbols with the set symbols that are now dead. for (RegionBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) { const MemRegion* R = I.getKey(); - // If this region live? Is so, none of its symbols are dead. if (Marked.count(R)) continue; diff --git a/lib/Analysis/SVals.cpp b/lib/Analysis/SVals.cpp index 7d1850d730957..d711ce0a225e3 100644 --- a/lib/Analysis/SVals.cpp +++ b/lib/Analysis/SVals.cpp @@ -114,6 +114,13 @@ const SymExpr *SVal::getAsSymbolicExpression() const { return getAsSymbol(); } +const MemRegion *SVal::getAsRegion() const { + if (const loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(this)) + return X->getRegion(); + + return 0; +} + bool SVal::symbol_iterator::operator==(const symbol_iterator &X) const { return itr == X.itr; } diff --git a/lib/Analysis/Store.cpp b/lib/Analysis/Store.cpp index 5aa756e14be37..cb099862f0551 100644 --- a/lib/Analysis/Store.cpp +++ b/lib/Analysis/Store.cpp @@ -88,10 +88,10 @@ StoreManager::CastRegion(const GRState* state, const MemRegion* R, // If the super region is an element region, strip it away. // FIXME: Is this the right thing to do in all cases? - const TypedRegion *Base = isa<ElementRegion>(TR) ? - cast<TypedRegion>(TR->getSuperRegion()) : TR; + const MemRegion *Base = isa<ElementRegion>(TR) ? TR->getSuperRegion() + : TR; ElementRegion* ER = MRMgr.getElementRegion(Pointee, Idx, Base, - StateMgr.getContext()); + StateMgr.getContext()); return CastResult(state, ER); } } |