diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 11:06:01 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 11:06:01 +0000 |
commit | 486754660bb926339aefcf012a3f848592babb8b (patch) | |
tree | ecdbc446c9876f4f120f701c243373cd3cb43db3 /lib/StaticAnalyzer/Core/Environment.cpp | |
parent | 55e6d896ad333f07bb3b1ba487df214fc268a4ab (diff) |
Notes
Diffstat (limited to 'lib/StaticAnalyzer/Core/Environment.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Core/Environment.cpp | 95 |
1 files changed, 62 insertions, 33 deletions
diff --git a/lib/StaticAnalyzer/Core/Environment.cpp b/lib/StaticAnalyzer/Core/Environment.cpp index c6acb9d1851ce..eccaee292c403 100644 --- a/lib/StaticAnalyzer/Core/Environment.cpp +++ b/lib/StaticAnalyzer/Core/Environment.cpp @@ -1,4 +1,4 @@ -//== Environment.cpp - Map from Stmt* to Locations/Values -------*- C++ -*--==// +//===- Environment.cpp - Map from Stmt* to Locations/Values ---------------===// // // The LLVM Compiler Infrastructure // @@ -11,12 +11,25 @@ // //===----------------------------------------------------------------------===// +#include "clang/StaticAnalyzer/Core/PathSensitive/Environment.h" +#include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" -#include "clang/AST/ExprObjC.h" +#include "clang/AST/PrettyPrinter.h" +#include "clang/AST/Stmt.h" #include "clang/Analysis/AnalysisDeclContext.h" -#include "clang/Analysis/CFG.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" +#include "llvm/ADT/ImmutableMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include <cassert> using namespace clang; using namespace ento; @@ -46,16 +59,16 @@ static const Expr *ignoreTransparentExprs(const Expr *E) { } static const Stmt *ignoreTransparentExprs(const Stmt *S) { - if (const Expr *E = dyn_cast<Expr>(S)) + if (const auto *E = dyn_cast<Expr>(S)) return ignoreTransparentExprs(E); return S; } EnvironmentEntry::EnvironmentEntry(const Stmt *S, const LocationContext *L) - : std::pair<const Stmt *, - const StackFrameContext *>(ignoreTransparentExprs(S), - L ? L->getCurrentStackFrame() - : nullptr) {} + : std::pair<const Stmt *, + const StackFrameContext *>(ignoreTransparentExprs(S), + L ? L->getStackFrame() + : nullptr) {} SVal Environment::lookupExpr(const EnvironmentEntry &E) const { const SVal* X = ExprBindings.lookup(E); @@ -95,7 +108,7 @@ SVal Environment::getSVal(const EnvironmentEntry &Entry, return svalBuilder.getConstantVal(cast<Expr>(S)).getValue(); case Stmt::ReturnStmtClass: { - const ReturnStmt *RS = cast<ReturnStmt>(S); + const auto *RS = cast<ReturnStmt>(S); if (const Expr *RE = RS->getRetValue()) return getSVal(EnvironmentEntry(RE, LCtx), svalBuilder); return UndefinedVal(); @@ -121,20 +134,25 @@ Environment EnvironmentManager::bindExpr(Environment Env, } namespace { + class MarkLiveCallback final : public SymbolVisitor { SymbolReaper &SymReaper; + public: MarkLiveCallback(SymbolReaper &symreaper) : SymReaper(symreaper) {} + bool VisitSymbol(SymbolRef sym) override { SymReaper.markLive(sym); return true; } + bool VisitMemRegion(const MemRegion *R) override { SymReaper.markLive(R); return true; } }; -} // end anonymous namespace + +} // namespace // removeDeadBindings: // - Remove subexpression bindings. @@ -147,7 +165,6 @@ Environment EnvironmentManager::removeDeadBindings(Environment Env, SymbolReaper &SymReaper, ProgramStateRef ST) { - // We construct a new Environment object entirely, as this is cheaper than // individually removing all the subexpression bindings (which will greatly // outnumber block-level expression bindings). @@ -156,14 +173,13 @@ EnvironmentManager::removeDeadBindings(Environment Env, MarkLiveCallback CB(SymReaper); ScanReachableSymbols RSScaner(ST, CB); - llvm::ImmutableMapRef<EnvironmentEntry,SVal> + llvm::ImmutableMapRef<EnvironmentEntry, SVal> EBMapRef(NewEnv.ExprBindings.getRootWithoutRetain(), F.getTreeFactory()); // Iterate over the block-expr bindings. for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) { - const EnvironmentEntry &BlkExpr = I.getKey(); const SVal &X = I.getData(); @@ -186,28 +202,41 @@ EnvironmentManager::removeDeadBindings(Environment Env, } void Environment::print(raw_ostream &Out, const char *NL, - const char *Sep) const { - bool isFirst = true; + const char *Sep, const LocationContext *WithLC) const { + if (ExprBindings.isEmpty()) + return; + + if (!WithLC) { + // Find the freshest location context. + llvm::SmallPtrSet<const LocationContext *, 16> FoundContexts; + for (auto I : *this) { + const LocationContext *LC = I.first.getLocationContext(); + if (FoundContexts.count(LC) == 0) { + // This context is fresher than all other contexts so far. + WithLC = LC; + for (const LocationContext *LCI = LC; LCI; LCI = LCI->getParent()) + FoundContexts.insert(LCI); + } + } + } - for (Environment::iterator I = begin(), E = end(); I != E; ++I) { - const EnvironmentEntry &En = I.getKey(); + assert(WithLC); - if (isFirst) { - Out << NL << NL - << "Expressions:" - << NL; - isFirst = false; - } else { - Out << NL; - } + LangOptions LO; // FIXME. + PrintingPolicy PP(LO); - const Stmt *S = En.getStmt(); - assert(S != nullptr && "Expected non-null Stmt"); + Out << NL << NL << "Expressions by stack frame:" << NL; + WithLC->dumpStack(Out, "", NL, Sep, [&](const LocationContext *LC) { + for (auto I : ExprBindings) { + if (I.first.getLocationContext() != LC) + continue; - Out << " (" << (const void*) En.getLocationContext() << ',' - << (const void*) S << ") "; - LangOptions LO; // FIXME. - S->printPretty(Out, nullptr, PrintingPolicy(LO)); - Out << " : " << I.getData(); - } + const Stmt *S = I.first.getStmt(); + assert(S != nullptr && "Expected non-null Stmt"); + + Out << "(" << (const void *)LC << ',' << (const void *)S << ") "; + S->printPretty(Out, nullptr, PP); + Out << " : " << I.second << NL; + } + }); } |