summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Analysis/CFRefCount.cpp18
-rw-r--r--clang/lib/Analysis/GRExprEngine.cpp122
-rw-r--r--clang/lib/Analysis/GRState.cpp154
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:
OpenPOWER on IntegriCloud