Environment.cpp revision d4ce811ae08398e357c8ce3e707ba5f2aa0041a5
1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//== Environment.cpp - Map from Stmt* to Locations/Values -------*- C++ -*--==//
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//                     The LLVM Compiler Infrastructure
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// This file is distributed under the University of Illinois Open Source
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// License. See LICENSE.TXT for details.
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//===----------------------------------------------------------------------===//
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//  This file defined the Environment and EnvironmentManager classes.
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//===----------------------------------------------------------------------===//
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "clang/AST/ExprCXX.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "clang/AST/ExprObjC.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "clang/Analysis/AnalysisContext.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "clang/Analysis/CFG.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using namespace clang;
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using namespace ento;
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static const Expr *ignoreTransparentExprs(const Expr *E) {
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  E = E->IgnoreParens();
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  switch (E->getStmtClass()) {
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  case Stmt::OpaqueValueExprClass:
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    E = cast<OpaqueValueExpr>(E)->getSourceExpr();
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    break;
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  case Stmt::ExprWithCleanupsClass:
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    E = cast<ExprWithCleanups>(E)->getSubExpr();
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    break;
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  case Stmt::CXXBindTemporaryExprClass:
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    E = cast<CXXBindTemporaryExpr>(E)->getSubExpr();
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    break;
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  case Stmt::SubstNonTypeTemplateParmExprClass:
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    E = cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement();
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    break;
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  case Stmt::CXXDefaultArgExprClass:
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    E = cast<CXXDefaultArgExpr>(E)->getExpr();
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    break;
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  default:
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // This is the base case: we can't look through more than we already have.
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return E;
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return ignoreTransparentExprs(E);
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static const Stmt *ignoreTransparentExprs(const Stmt *S) {
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (const Expr *E = dyn_cast<Expr>(S))
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return ignoreTransparentExprs(E);
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return S;
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)EnvironmentEntry::EnvironmentEntry(const Stmt *S, const LocationContext *L)
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  : std::pair<const Stmt *,
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              const StackFrameContext *>(ignoreTransparentExprs(S),
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                         L ? L->getCurrentStackFrame() : 0) {}
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)SVal Environment::lookupExpr(const EnvironmentEntry &E) const {
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const SVal* X = ExprBindings.lookup(E);
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (X) {
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SVal V = *X;
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return V;
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return UnknownVal();
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)SVal Environment::getSVal(const EnvironmentEntry &Entry,
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          SValBuilder& svalBuilder) const {
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const Stmt *S = Entry.getStmt();
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const LocationContext *LCtx = Entry.getLocationContext();
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  switch (S->getStmtClass()) {
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  case Stmt::CXXBindTemporaryExprClass:
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  case Stmt::CXXDefaultArgExprClass:
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  case Stmt::ExprWithCleanupsClass:
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  case Stmt::GenericSelectionExprClass:
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  case Stmt::OpaqueValueExprClass:
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  case Stmt::ParenExprClass:
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  case Stmt::SubstNonTypeTemplateParmExprClass:
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    llvm_unreachable("Should have been handled by ignoreTransparentExprs");
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  case Stmt::AddrLabelExprClass:
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return svalBuilder.makeLoc(cast<AddrLabelExpr>(S));
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  case Stmt::CharacterLiteralClass: {
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const CharacterLiteral *C = cast<CharacterLiteral>(S);
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return svalBuilder.makeIntVal(C->getValue(), C->getType());
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  case Stmt::CXXBoolLiteralExprClass:
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return svalBuilder.makeBoolVal(cast<CXXBoolLiteralExpr>(S));
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  case Stmt::CXXScalarValueInitExprClass:
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  case Stmt::ImplicitValueInitExprClass: {
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    QualType Ty = cast<Expr>(S)->getType();
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return svalBuilder.makeZeroVal(Ty);
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  case Stmt::IntegerLiteralClass:
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return svalBuilder.makeIntVal(cast<IntegerLiteral>(S));
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  case Stmt::ObjCBoolLiteralExprClass:
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return svalBuilder.makeBoolVal(cast<ObjCBoolLiteralExpr>(S));
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // For special C0xx nullptr case, make a null pointer SVal.
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  case Stmt::CXXNullPtrLiteralExprClass:
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return svalBuilder.makeNull();
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  case Stmt::ObjCStringLiteralClass: {
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    MemRegionManager &MRMgr = svalBuilder.getRegionManager();
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ObjCStringLiteral *SL = cast<ObjCStringLiteral>(S);
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return svalBuilder.makeLoc(MRMgr.getObjCStringRegion(SL));
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  case Stmt::StringLiteralClass: {
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    MemRegionManager &MRMgr = svalBuilder.getRegionManager();
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const StringLiteral *SL = cast<StringLiteral>(S);
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return svalBuilder.makeLoc(MRMgr.getStringRegion(SL));
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  case Stmt::ReturnStmtClass: {
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ReturnStmt *RS = cast<ReturnStmt>(S);
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (const Expr *RE = RS->getRetValue())
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return getSVal(EnvironmentEntry(RE, LCtx), svalBuilder);
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return UndefinedVal();
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Handle all other Stmt* using a lookup.
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  default:
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    break;
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return lookupExpr(EnvironmentEntry(S, LCtx));
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Environment EnvironmentManager::bindExpr(Environment Env,
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                         const EnvironmentEntry &E,
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                         SVal V,
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                         bool Invalidate) {
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (V.isUnknown()) {
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (Invalidate)
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return Environment(F.remove(Env.ExprBindings, E));
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    else
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return Env;
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return Environment(F.add(Env.ExprBindings, E, V));
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)EnvironmentEntry EnvironmentEntry::makeLocation() const {
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EnvironmentEntry Result = *this;
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  reinterpret_cast<uintptr_t &>(Result.first) |= 0x1;
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return Result;
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Environment EnvironmentManager::bindExprAndLocation(Environment Env,
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                    const EnvironmentEntry &E,
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                    SVal location, SVal V) {
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return Environment(F.add(F.add(Env.ExprBindings, E.makeLocation(), location),
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           E, V));
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class MarkLiveCallback : public SymbolVisitor {
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SymbolReaper &SymReaper;
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)public:
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MarkLiveCallback(SymbolReaper &symreaper) : SymReaper(symreaper) {}
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool VisitSymbol(SymbolRef sym) {
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SymReaper.markLive(sym);
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return true;
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool VisitMemRegion(const MemRegion *R) {
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SymReaper.markLive(R);
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return true;
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // end anonymous namespace
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// In addition to mapping from EnvironmentEntry - > SVals in the Environment,
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// we also maintain a mapping from EnvironmentEntry -> SVals (locations)
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// that were used during a load and store.
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static inline bool IsLocation(const EnvironmentEntry &E) {
185  const Stmt *S = E.getStmt();
186  return (bool) (((uintptr_t) S) & 0x1);
187}
188
189// removeDeadBindings:
190//  - Remove subexpression bindings.
191//  - Remove dead block expression bindings.
192//  - Keep live block expression bindings:
193//   - Mark their reachable symbols live in SymbolReaper,
194//     see ScanReachableSymbols.
195//   - Mark the region in DRoots if the binding is a loc::MemRegionVal.
196Environment
197EnvironmentManager::removeDeadBindings(Environment Env,
198                                       SymbolReaper &SymReaper,
199                                       ProgramStateRef ST) {
200
201  // We construct a new Environment object entirely, as this is cheaper than
202  // individually removing all the subexpression bindings (which will greatly
203  // outnumber block-level expression bindings).
204  Environment NewEnv = getInitialEnvironment();
205
206  SmallVector<std::pair<EnvironmentEntry, SVal>, 10> deferredLocations;
207
208  MarkLiveCallback CB(SymReaper);
209  ScanReachableSymbols RSScaner(ST, CB);
210
211  llvm::ImmutableMapRef<EnvironmentEntry,SVal>
212    EBMapRef(NewEnv.ExprBindings.getRootWithoutRetain(),
213             F.getTreeFactory());
214
215  // Iterate over the block-expr bindings.
216  for (Environment::iterator I = Env.begin(), E = Env.end();
217       I != E; ++I) {
218
219    const EnvironmentEntry &BlkExpr = I.getKey();
220    // For recorded locations (used when evaluating loads and stores), we
221    // consider them live only when their associated normal expression is
222    // also live.
223    // NOTE: This assumes that loads/stores that evaluated to UnknownVal
224    // still have an entry in the map.
225    if (IsLocation(BlkExpr)) {
226      deferredLocations.push_back(std::make_pair(BlkExpr, I.getData()));
227      continue;
228    }
229    const SVal &X = I.getData();
230
231    if (SymReaper.isLive(BlkExpr.getStmt(), BlkExpr.getLocationContext())) {
232      // Copy the binding to the new map.
233      EBMapRef = EBMapRef.add(BlkExpr, X);
234
235      // If the block expr's value is a memory region, then mark that region.
236      if (isa<loc::MemRegionVal>(X)) {
237        const MemRegion *R = cast<loc::MemRegionVal>(X).getRegion();
238        SymReaper.markLive(R);
239      }
240
241      // Mark all symbols in the block expr's value live.
242      RSScaner.scan(X);
243      continue;
244    }
245  }
246
247  // Go through he deferred locations and add them to the new environment if
248  // the correspond Stmt* is in the map as well.
249  for (SmallVectorImpl<std::pair<EnvironmentEntry, SVal> >::iterator
250      I = deferredLocations.begin(), E = deferredLocations.end(); I != E; ++I) {
251    const EnvironmentEntry &En = I->first;
252    const Stmt *S = (Stmt*) (((uintptr_t) En.getStmt()) & (uintptr_t) ~0x1);
253    if (EBMapRef.lookup(EnvironmentEntry(S, En.getLocationContext())))
254      EBMapRef = EBMapRef.add(En, I->second);
255  }
256
257  NewEnv.ExprBindings = EBMapRef.asImmutableMap();
258  return NewEnv;
259}
260
261void Environment::print(raw_ostream &Out, const char *NL,
262                        const char *Sep) const {
263  printAux(Out, false, NL, Sep);
264  printAux(Out, true, NL, Sep);
265}
266
267void Environment::printAux(raw_ostream &Out, bool printLocations,
268                           const char *NL,
269                           const char *Sep) const{
270
271  bool isFirst = true;
272
273  for (Environment::iterator I = begin(), E = end(); I != E; ++I) {
274    const EnvironmentEntry &En = I.getKey();
275    if (IsLocation(En)) {
276      if (!printLocations)
277        continue;
278    }
279    else {
280      if (printLocations)
281        continue;
282    }
283
284    if (isFirst) {
285      Out << NL << NL
286          << (printLocations ? "Load/Store locations:" : "Expressions:")
287          << NL;
288      isFirst = false;
289    } else {
290      Out << NL;
291    }
292
293    const Stmt *S = En.getStmt();
294    if (printLocations) {
295      S = (Stmt*) (((uintptr_t) S) & ((uintptr_t) ~0x1));
296    }
297
298    Out << " (" << (const void*) En.getLocationContext() << ','
299      << (const void*) S << ") ";
300    LangOptions LO; // FIXME.
301    S->printPretty(Out, 0, PrintingPolicy(LO));
302    Out << " : " << I.getData();
303  }
304}
305