diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Analysis/CFRefCount.cpp | 18 | ||||
-rw-r--r-- | clang/lib/Analysis/GRExprEngine.cpp | 122 | ||||
-rw-r--r-- | clang/lib/Analysis/GRState.cpp | 154 |
3 files changed, 132 insertions, 162 deletions
diff --git a/clang/lib/Analysis/CFRefCount.cpp b/clang/lib/Analysis/CFRefCount.cpp index 9a769988a10..2fdd0290e1d 100644 --- a/clang/lib/Analysis/CFRefCount.cpp +++ b/clang/lib/Analysis/CFRefCount.cpp @@ -1264,7 +1264,6 @@ private: UseAfterReleasesTy UseAfterReleases; ReleasesNotOwnedTy ReleasesNotOwned; LeaksTy Leaks; - BindingsPrinter Printer; RefBindings Update(RefBindings B, SymbolID sym, RefVal V, ArgEffect E, RefVal::Kind& hasErr); @@ -1301,8 +1300,8 @@ public: virtual void RegisterChecks(GRExprEngine& Eng); - virtual void getStatePrinters(std::vector<GRState::Printer*>& Printers) { - Printers.push_back(&Printer); + virtual void RegisterPrinters(std::vector<GRState::Printer*>& Printers) { + Printers.push_back(new BindingsPrinter()); } bool isGCEnabled() const { return Summaries.isGCEnabled(); } @@ -1598,7 +1597,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst, ? cast<RVal>(lval::SymbolVal(Sym)) : cast<RVal>(nonlval::SymbolVal(Sym)); - state = state.SetRVal(Ex, X, Eng.getCFG().isBlkExpr(Ex), false); + state = state.SetRVal(Ex, X, false); } break; @@ -1608,14 +1607,14 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst, assert (arg_end >= arg_beg); assert (idx < (unsigned) (arg_end - arg_beg)); RVal V = state.GetRVal(*(arg_beg+idx)); - state = state.SetRVal(Ex, V, Eng.getCFG().isBlkExpr(Ex), false); + state = state.SetRVal(Ex, V, false); break; } case RetEffect::ReceiverAlias: { assert (Receiver); RVal V = state.GetRVal(Receiver); - state = state.SetRVal(Ex, V, Eng.getCFG().isBlkExpr(Ex), false); + state = state.SetRVal(Ex, V, false); break; } @@ -1626,15 +1625,13 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst, QualType RetT = GetReturnType(Ex, Eng.getContext()); state = state.set<RefBindings>(Sym, RefVal::makeOwned(RetT), RefBFactory); - state = state.SetRVal(Ex, lval::SymbolVal(Sym), - Eng.getCFG().isBlkExpr(Ex), false); + state = state.SetRVal(Ex, lval::SymbolVal(Sym), false); #if 0 RefBindings B = GetRefBindings(StImpl); SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeOwned(RetT))); #endif - // FIXME: Add a flag to the checker where allocations are allowed to fail. if (RE.getKind() == RetEffect::OwnedAllocatedSymbol) state = state.AddNE(Sym, Eng.getBasicVals().getZeroWithPtrWidth()); @@ -1648,8 +1645,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst, QualType RetT = GetReturnType(Ex, Eng.getContext()); state = state.set<RefBindings>(Sym, RefVal::makeNotOwned(RetT), RefBFactory); - state = state.SetRVal(Ex, lval::SymbolVal(Sym), - Eng.getCFG().isBlkExpr(Ex), false); + state = state.SetRVal(Ex, lval::SymbolVal(Sym), false); break; } } diff --git a/clang/lib/Analysis/GRExprEngine.cpp b/clang/lib/Analysis/GRExprEngine.cpp index f4ffcb12e01..896f473df8a 100644 --- a/clang/lib/Analysis/GRExprEngine.cpp +++ b/clang/lib/Analysis/GRExprEngine.cpp @@ -177,7 +177,8 @@ void GRExprEngine::EmitWarnings(BugReporterData& BRData) { void GRExprEngine::setTransferFunctions(GRTransferFuncs* tf) { StateMgr.TF = tf; - getTF().RegisterChecks(*this); + tf->RegisterChecks(*this); + tf->RegisterPrinters(getStateManager().Printers); } void GRExprEngine::AddCheck(GRSimpleAPICheck* A, Stmt::StmtClass C) { @@ -2266,109 +2267,12 @@ void GRExprEngine::EvalBinOp(GRStateSet& OStates, const GRState* St, #ifndef NDEBUG static GRExprEngine* GraphPrintCheckerState; static SourceManager* GraphPrintSourceManager; -static GRState::Printer **GraphStatePrinterBeg, **GraphStatePrinterEnd; namespace llvm { template<> struct VISIBILITY_HIDDEN DOTGraphTraits<GRExprEngine::NodeTy*> : public DefaultDOTGraphTraits { - static void PrintVarBindings(std::ostream& Out, GRState* St) { - - Out << "Variables:\\l"; - - bool isFirst = true; - - for (GRState::vb_iterator I=St->vb_begin(), E=St->vb_end(); I!=E;++I) { - - if (isFirst) - isFirst = false; - else - Out << "\\l"; - - Out << ' ' << I.getKey()->getName() << " : "; - I.getData().print(Out); - } - - } - - - static void PrintSubExprBindings(std::ostream& Out, GRState* St){ - - bool isFirst = true; - - for (GRState::seb_iterator I=St->seb_begin(), E=St->seb_end();I!=E;++I) { - - if (isFirst) { - Out << "\\l\\lSub-Expressions:\\l"; - isFirst = false; - } - else - Out << "\\l"; - - Out << " (" << (void*) I.getKey() << ") "; - I.getKey()->printPretty(Out); - Out << " : "; - I.getData().print(Out); - } - } - - static void PrintBlkExprBindings(std::ostream& Out, GRState* St){ - - bool isFirst = true; - - for (GRState::beb_iterator I=St->beb_begin(), E=St->beb_end(); I!=E;++I){ - if (isFirst) { - Out << "\\l\\lBlock-level Expressions:\\l"; - isFirst = false; - } - else - Out << "\\l"; - - Out << " (" << (void*) I.getKey() << ") "; - I.getKey()->printPretty(Out); - Out << " : "; - I.getData().print(Out); - } - } - - static void PrintEQ(std::ostream& Out, GRState* St) { - GRState::ConstEqTy CE = St->ConstEq; - - if (CE.isEmpty()) - return; - - Out << "\\l\\|'==' constraints:"; - - for (GRState::ConstEqTy::iterator I=CE.begin(), E=CE.end(); I!=E;++I) - Out << "\\l $" << I.getKey() << " : " << I.getData()->toString(); - } - - static void PrintNE(std::ostream& Out, GRState* St) { - GRState::ConstNotEqTy NE = St->ConstNotEq; - - if (NE.isEmpty()) - return; - - Out << "\\l\\|'!=' constraints:"; - - for (GRState::ConstNotEqTy::iterator I=NE.begin(), EI=NE.end(); - I != EI; ++I){ - - Out << "\\l $" << I.getKey() << " : "; - bool isFirst = true; - - GRState::IntSetTy::iterator J=I.getData().begin(), - EJ=I.getData().end(); - for ( ; J != EJ; ++J) { - if (isFirst) isFirst = false; - else Out << ", "; - - Out << (*J)->toString(); - } - } - } - static std::string getNodeAttributes(const GRExprEngine::NodeTy* N, void*) { if (GraphPrintCheckerState->isImplicitNullDeref(N) || @@ -2509,7 +2413,8 @@ struct VISIBILITY_HIDDEN DOTGraphTraits<GRExprEngine::NodeTy*> : Out << "\\|StateID: " << (void*) N->getState() << "\\|"; - N->getState()->printDOT(Out, GraphStatePrinterBeg, GraphStatePrinterEnd); + GRStateRef state(N->getState(), GraphPrintCheckerState->getStateManager()); + state.printDOT(Out); Out << "\\l"; return Out.str(); @@ -2575,19 +2480,10 @@ void GRExprEngine::ViewGraph(bool trim) { GraphPrintCheckerState = this; GraphPrintSourceManager = &getContext().getSourceManager(); - // Get the state printers. - std::vector<GRState::Printer*> Printers; - getTF().getStatePrinters(Printers); - GraphStatePrinterBeg = Printers.empty() ? 0 : &Printers[0]; - GraphStatePrinterEnd = Printers.empty() ? 0 : &Printers[0]+Printers.size(); - - llvm::ViewGraph(*G.roots_begin(), "GRExprEngine"); GraphPrintCheckerState = NULL; GraphPrintSourceManager = NULL; - GraphStatePrinterBeg = NULL; - GraphStatePrinterEnd = NULL; } #endif } @@ -2596,13 +2492,7 @@ void GRExprEngine::ViewGraph(NodeTy** Beg, NodeTy** End) { #ifndef NDEBUG GraphPrintCheckerState = this; GraphPrintSourceManager = &getContext().getSourceManager(); - - // Get the state printers. - std::vector<GRState::Printer*> Printers; - getTF().getStatePrinters(Printers); - GraphStatePrinterBeg = Printers.empty() ? 0 : &Printers[0]; - GraphStatePrinterEnd = Printers.empty() ? 0 : &Printers[0]+Printers.size(); - + GRExprEngine::GraphTy* TrimmedG = G.Trim(Beg, End); if (!TrimmedG) @@ -2614,7 +2504,5 @@ void GRExprEngine::ViewGraph(NodeTy** Beg, NodeTy** End) { GraphPrintCheckerState = NULL; GraphPrintSourceManager = NULL; - GraphStatePrinterBeg = NULL; - GraphStatePrinterEnd = NULL; #endif } diff --git a/clang/lib/Analysis/GRState.cpp b/clang/lib/Analysis/GRState.cpp index b9458038043..5522600d849 100644 --- a/clang/lib/Analysis/GRState.cpp +++ b/clang/lib/Analysis/GRState.cpp @@ -17,10 +17,71 @@ using namespace clang; +GRStateManager::~GRStateManager() { + for (std::vector<GRState::Printer*>::iterator I=Printers.begin(), + E=Printers.end(); I!=E; ++I) + delete *I; + + for (GDMContextsTy::iterator I=GDMContexts.begin(), E=GDMContexts.end(); + I!=E; ++I) + I->second.second(I->second.first); +} + +//===----------------------------------------------------------------------===// +// Basic symbolic analysis. This will eventually be refactored into a +// separate component. +//===----------------------------------------------------------------------===// + +typedef llvm::ImmutableMap<SymbolID,GRState::IntSetTy> ConstNotEqTy; + +static int ConstNotEqTyIndex = 0; + +namespace clang { + template<> struct GRStateTrait<ConstNotEqTy> { + typedef ConstNotEqTy data_type; + typedef ConstNotEqTy::Factory& context_type; + typedef SymbolID key_type; + typedef GRState::IntSetTy value_type; + typedef const GRState::IntSetTy* lookup_type; + + static data_type MakeData(void* const* p) { + return p ? ConstNotEqTy((ConstNotEqTy::TreeTy*) *p) : ConstNotEqTy(0); + } + static void* MakeVoidPtr(ConstNotEqTy B) { + return B.getRoot(); + } + static void* GDMIndex() { + return &ConstNotEqTyIndex; + } + static lookup_type Lookup(ConstNotEqTy B, SymbolID K) { + return B.lookup(K); + } + static data_type Set(data_type B, key_type K, value_type E,context_type F){ + return F.Add(B, K, E); + } + + static data_type Remove(ConstNotEqTy B, SymbolID K, context_type F) { + return F.Remove(B, K); + } + + static context_type MakeContext(void* p) { + return *((ConstNotEqTy::Factory*) p); + } + + static void* CreateContext(llvm::BumpPtrAllocator& Alloc) { + return new ConstNotEqTy::Factory(Alloc); + } + + static void DeleteContext(void* Ctx) { + delete (ConstNotEqTy::Factory*) Ctx; + } + }; +} + bool GRState::isNotEqual(SymbolID sym, const llvm::APSInt& V) const { // Retrieve the NE-set associated with the given symbol. - const ConstNotEqTy::data_type* T = ConstNotEq.lookup(sym); + const ConstNotEqTy::data_type* T = get<ConstNotEqTy>(sym); // See if V is present in the NE-set. return T ? T->contains(&V) : false; @@ -42,8 +103,8 @@ const llvm::APSInt* GRState::getSymVal(SymbolID sym) const { const GRState* GRStateManager::RemoveDeadBindings(const GRState* St, Stmt* Loc, - const LiveVariables& Liveness, - DeadSymbolsTy& DSymbols) { + const LiveVariables& Liveness, + DeadSymbolsTy& DSymbols) { // This code essentially performs a "mark-and-sweep" of the VariableBindings. // The roots are any Block-level exprs and Decls that our liveness algorithm @@ -97,7 +158,9 @@ GRStateManager::RemoveDeadBindings(const GRState* St, Stmt* Loc, LSymbols, DSymbols); // Remove the dead symbols from the symbol tracker. - for (GRState::ce_iterator I = St->ce_begin(), E=St->ce_end(); I!=E; ++I) { + // FIXME: Refactor into something else that manages symbol values. + for (GRState::ConstEqTy::iterator I = St->ConstEq.begin(), + E=St->ConstEq.end(); I!=E; ++I) { SymbolID sym = I.getKey(); @@ -107,17 +170,19 @@ GRStateManager::RemoveDeadBindings(const GRState* St, Stmt* Loc, } } - for (GRState::cne_iterator I = St->cne_begin(), E=St->cne_end(); I!=E;++I){ - - SymbolID sym = I.getKey(); - + GRStateRef state(getPersistentState(NewSt), *this); + ConstNotEqTy CNE = state.get<ConstNotEqTy>(); + ConstNotEqTy::Factory& CNEFactory = state.get_context<ConstNotEqTy>(); + + for (ConstNotEqTy::iterator I = CNE.begin(), E = CNE.end(); I != E; ++I) { + SymbolID sym = I.getKey(); if (!LSymbols.count(sym)) { DSymbols.insert(sym); - NewSt.ConstNotEq = CNEFactory.Remove(NewSt.ConstNotEq, sym); + CNE = CNEFactory.Remove(CNE, sym); } } - return getPersistentState(NewSt); + return state.set<ConstNotEqTy>(CNE); } const GRState* GRStateManager::SetRVal(const GRState* St, LVal LV, @@ -148,21 +213,19 @@ const GRState* GRStateManager::Unbind(const GRState* St, LVal LV) { const GRState* GRStateManager::AddNE(const GRState* St, SymbolID sym, - const llvm::APSInt& V) { + const llvm::APSInt& V) { + + GRStateRef state(St, *this); // First, retrieve the NE-set associated with the given symbol. - GRState::ConstNotEqTy::data_type* T = St->ConstNotEq.lookup(sym); + ConstNotEqTy::data_type* T = state.get<ConstNotEqTy>(sym); GRState::IntSetTy S = T ? *T : ISetFactory.GetEmptySet(); // Now add V to the NE set. S = ISetFactory.Add(S, &V); // Create a new state with the old binding replaced. - GRState NewSt = *St; - NewSt.ConstNotEq = CNEFactory.Add(NewSt.ConstNotEq, sym, S); - - // Get the persistent copy. - return getPersistentState(NewSt); + return state.set<ConstNotEqTy>(sym, S); } const GRState* GRStateManager::AddEQ(const GRState* St, SymbolID sym, @@ -179,7 +242,7 @@ const GRState* GRStateManager::AddEQ(const GRState* St, SymbolID sym, const GRState* GRStateManager::getInitialState() { GRState StateImpl(EnvMgr.getInitialEnvironment(), StMgr->getInitialStore(), - GDMFactory.GetEmptyMap(), CNEFactory.GetEmptyMap(), + GDMFactory.GetEmptyMap(), CEFactory.GetEmptyMap()); return getPersistentState(StateImpl); @@ -200,14 +263,10 @@ const GRState* GRStateManager::getPersistentState(GRState& State) { return I; } -void GRState::printDOT(std::ostream& Out, - Printer** Beg, Printer** End) const { - print(Out, Beg, End, "\\l", "\\|"); -} -void GRState::printStdErr(Printer** Beg, Printer** End) const { - print(*llvm::cerr, Beg, End); -} +//===----------------------------------------------------------------------===// +// State pretty-printing. +//===----------------------------------------------------------------------===// void GRState::print(std::ostream& Out, Printer** Beg, Printer** End, const char* nl, const char* sep) const { @@ -279,14 +338,14 @@ void GRState::print(std::ostream& Out, Printer** Beg, Printer** End, // Print != constraints. // FIXME: Make just another printer do this. - - if (!ConstNotEq.isEmpty()) { + + ConstNotEqTy CNE = get<ConstNotEqTy>(); + + if (!CNE.isEmpty()) { Out << nl << sep << "'!=' constraints:"; - for (ConstNotEqTy::iterator I = ConstNotEq.begin(), - EI = ConstNotEq.end(); I != EI; ++I) { - + for (ConstNotEqTy::iterator I = CNE.begin(), EI = CNE.end(); I!=EI; ++I) { Out << nl << " $" << I.getKey() << " : "; isFirst = true; @@ -305,6 +364,20 @@ void GRState::print(std::ostream& Out, Printer** Beg, Printer** End, for ( ; Beg != End ; ++Beg) (*Beg)->Print(Out, this, nl, sep); } +void GRStateRef::printDOT(std::ostream& Out) const { + print(Out, "\\l", "\\|"); +} + +void GRStateRef::printStdErr() const { + print(*llvm::cerr); +} + +void GRStateRef::print(std::ostream& Out, const char* nl, const char* sep)const{ + GRState::Printer **beg = Mgr->Printers.empty() ? 0 : &Mgr->Printers[0]; + GRState::Printer **end = !beg ? 0 : beg + Mgr->Printers.size(); + St->print(Out, beg, end, nl, sep); +} + //===----------------------------------------------------------------------===// // Generic Data Map. //===----------------------------------------------------------------------===// @@ -313,6 +386,20 @@ void* const* GRState::FindGDM(void* K) const { return GDM.lookup(K); } +void* +GRStateManager::FindGDMContext(void* K, + void* (*CreateContext)(llvm::BumpPtrAllocator&), + void (*DeleteContext)(void*)) { + + std::pair<void*, void (*)(void*)>& p = GDMContexts[K]; + if (!p.first) { + p.first = CreateContext(Alloc); + p.second = DeleteContext; + } + + return p.first; +} + const GRState* GRStateManager::addGDM(const GRState* St, void* Key, void* Data){ GRState::GenericDataMap M1 = St->getGDM(); GRState::GenericDataMap M2 = GDMFactory.Add(M1, Key, Data); @@ -330,7 +417,8 @@ const GRState* GRStateManager::addGDM(const GRState* St, void* Key, void* Data){ //===----------------------------------------------------------------------===// bool GRStateManager::isEqual(const GRState* state, Expr* Ex, - const llvm::APSInt& Y) { + const llvm::APSInt& Y) { + RVal V = GetRVal(state, Ex); if (lval::ConcreteInt* X = dyn_cast<lval::ConcreteInt>(&V)) @@ -348,8 +436,7 @@ bool GRStateManager::isEqual(const GRState* state, Expr* Ex, return false; } -bool GRStateManager::isEqual(const GRState* state, Expr* Ex, - uint64_t x) { +bool GRStateManager::isEqual(const GRState* state, Expr* Ex, uint64_t x) { return isEqual(state, Ex, BasicVals.getValue(x, Ex->getType())); } @@ -382,7 +469,6 @@ const GRState* GRStateManager::AssumeAux(const GRState* St, LVal Cond, return AssumeSymEQ(St, cast<lval::SymbolVal>(Cond).getSymbol(), BasicVals.getZeroWithPtrWidth(), isFeasible); - case lval::DeclValKind: case lval::FuncValKind: case lval::GotoLabelKind: |