1d4931632946fe86fc2b09496f2b62443440a7da4Ted Kremenek//== Environment.cpp - Map from Stmt* to Locations/Values -------*- C++ -*--==//
28133a26c166be89fb4f0a339db1e2fe923c51a70Ted Kremenek//
38133a26c166be89fb4f0a339db1e2fe923c51a70Ted Kremenek//                     The LLVM Compiler Infrastructure
48133a26c166be89fb4f0a339db1e2fe923c51a70Ted Kremenek//
58133a26c166be89fb4f0a339db1e2fe923c51a70Ted Kremenek// This file is distributed under the University of Illinois Open Source
68133a26c166be89fb4f0a339db1e2fe923c51a70Ted Kremenek// License. See LICENSE.TXT for details.
78133a26c166be89fb4f0a339db1e2fe923c51a70Ted Kremenek//
88133a26c166be89fb4f0a339db1e2fe923c51a70Ted Kremenek//===----------------------------------------------------------------------===//
98133a26c166be89fb4f0a339db1e2fe923c51a70Ted Kremenek//
108133a26c166be89fb4f0a339db1e2fe923c51a70Ted Kremenek//  This file defined the Environment and EnvironmentManager classes.
118133a26c166be89fb4f0a339db1e2fe923c51a70Ted Kremenek//
128133a26c166be89fb4f0a339db1e2fe923c51a70Ted Kremenek//===----------------------------------------------------------------------===//
135e2d2c2ee3cf410643e0f9a5701708e51409d973Benjamin Kramer
14c35fb7d67d515659ad2325b4f6ec97c9fe64fb63Benjamin Kramer#include "clang/AST/ExprCXX.h"
15f8b5aae41e46f94fe90ed5f1ee98f36f0aa59dc9Ted Kremenek#include "clang/AST/ExprObjC.h"
165e2d2c2ee3cf410643e0f9a5701708e51409d973Benjamin Kramer#include "clang/Analysis/AnalysisContext.h"
175e2d2c2ee3cf410643e0f9a5701708e51409d973Benjamin Kramer#include "clang/Analysis/CFG.h"
1818c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
19a93d0f280693b8418bc88cf7a8c93325f7fcf4c6Benjamin Kramer#include "llvm/Support/raw_ostream.h"
208133a26c166be89fb4f0a339db1e2fe923c51a70Ted Kremenek
218133a26c166be89fb4f0a339db1e2fe923c51a70Ted Kremenekusing namespace clang;
229ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento;
238133a26c166be89fb4f0a339db1e2fe923c51a70Ted Kremenek
24d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rosestatic const Expr *ignoreTransparentExprs(const Expr *E) {
25d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  E = E->IgnoreParens();
26d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose
27d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  switch (E->getStmtClass()) {
28d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  case Stmt::OpaqueValueExprClass:
29d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose    E = cast<OpaqueValueExpr>(E)->getSourceExpr();
30d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose    break;
31d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  case Stmt::ExprWithCleanupsClass:
32d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose    E = cast<ExprWithCleanups>(E)->getSubExpr();
33d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose    break;
34d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  case Stmt::CXXBindTemporaryExprClass:
35d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose    E = cast<CXXBindTemporaryExpr>(E)->getSubExpr();
36d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose    break;
37d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  case Stmt::SubstNonTypeTemplateParmExprClass:
38d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose    E = cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement();
39d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose    break;
40d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  default:
41d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose    // This is the base case: we can't look through more than we already have.
42d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose    return E;
43d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  }
44d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose
45d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  return ignoreTransparentExprs(E);
46d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose}
47d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose
48d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rosestatic const Stmt *ignoreTransparentExprs(const Stmt *S) {
49d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  if (const Expr *E = dyn_cast<Expr>(S))
50d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose    return ignoreTransparentExprs(E);
51d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  return S;
52d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose}
53d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose
54d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan RoseEnvironmentEntry::EnvironmentEntry(const Stmt *S, const LocationContext *L)
55d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  : std::pair<const Stmt *,
56d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose              const StackFrameContext *>(ignoreTransparentExprs(S),
576bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                         L ? L->getCurrentStackFrame()
586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                           : nullptr) {}
59d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose
605eca482fe895ea57bc82410222e6426c09e63284Ted KremenekSVal Environment::lookupExpr(const EnvironmentEntry &E) const {
61465846324f412055dd1ce270d757bfeead0811dcTed Kremenek  const SVal* X = ExprBindings.lookup(E);
62465846324f412055dd1ce270d757bfeead0811dcTed Kremenek  if (X) {
63465846324f412055dd1ce270d757bfeead0811dcTed Kremenek    SVal V = *X;
64465846324f412055dd1ce270d757bfeead0811dcTed Kremenek    return V;
65465846324f412055dd1ce270d757bfeead0811dcTed Kremenek  }
66465846324f412055dd1ce270d757bfeead0811dcTed Kremenek  return UnknownVal();
67465846324f412055dd1ce270d757bfeead0811dcTed Kremenek}
68465846324f412055dd1ce270d757bfeead0811dcTed Kremenek
695eca482fe895ea57bc82410222e6426c09e63284Ted KremenekSVal Environment::getSVal(const EnvironmentEntry &Entry,
70e5a934d3c840872d58724383a83443ed38f1d831Jordan Rose                          SValBuilder& svalBuilder) const {
71d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  const Stmt *S = Entry.getStmt();
725eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek  const LocationContext *LCtx = Entry.getLocationContext();
73d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose
74d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  switch (S->getStmtClass()) {
75d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  case Stmt::CXXBindTemporaryExprClass:
76d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  case Stmt::ExprWithCleanupsClass:
77d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  case Stmt::GenericSelectionExprClass:
78d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  case Stmt::OpaqueValueExprClass:
79d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  case Stmt::ParenExprClass:
80d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  case Stmt::SubstNonTypeTemplateParmExprClass:
81d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose    llvm_unreachable("Should have been handled by ignoreTransparentExprs");
82d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose
83d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  case Stmt::AddrLabelExprClass:
84e2b1246a24e8babf2f58c93713fba16b8edb8e2dJordan Rose  case Stmt::CharacterLiteralClass:
85d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  case Stmt::CXXBoolLiteralExprClass:
86d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  case Stmt::CXXScalarValueInitExprClass:
87e2b1246a24e8babf2f58c93713fba16b8edb8e2dJordan Rose  case Stmt::ImplicitValueInitExprClass:
88d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  case Stmt::IntegerLiteralClass:
89d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  case Stmt::ObjCBoolLiteralExprClass:
90d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  case Stmt::CXXNullPtrLiteralExprClass:
91e2b1246a24e8babf2f58c93713fba16b8edb8e2dJordan Rose  case Stmt::ObjCStringLiteralClass:
92e2b1246a24e8babf2f58c93713fba16b8edb8e2dJordan Rose  case Stmt::StringLiteralClass:
93e2b1246a24e8babf2f58c93713fba16b8edb8e2dJordan Rose    // Known constants; defer to SValBuilder.
94e2b1246a24e8babf2f58c93713fba16b8edb8e2dJordan Rose    return svalBuilder.getConstantVal(cast<Expr>(S)).getValue();
95d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose
96d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  case Stmt::ReturnStmtClass: {
97d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose    const ReturnStmt *RS = cast<ReturnStmt>(S);
98d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose    if (const Expr *RE = RS->getRetValue())
99d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose      return getSVal(EnvironmentEntry(RE, LCtx), svalBuilder);
100d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose    return UndefinedVal();
101d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  }
102d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose
103d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  // Handle all other Stmt* using a lookup.
104d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  default:
105e2b1246a24e8babf2f58c93713fba16b8edb8e2dJordan Rose    return lookupExpr(EnvironmentEntry(S, LCtx));
106d72ee907f76000446c706471e93d1f299104f9a7Ted Kremenek  }
107d72ee907f76000446c706471e93d1f299104f9a7Ted Kremenek}
1088133a26c166be89fb4f0a339db1e2fe923c51a70Ted Kremenek
1095eca482fe895ea57bc82410222e6426c09e63284Ted KremenekEnvironment EnvironmentManager::bindExpr(Environment Env,
1105eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek                                         const EnvironmentEntry &E,
1115eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek                                         SVal V,
1125eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek                                         bool Invalidate) {
1131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  if (V.isUnknown()) {
114d72ee907f76000446c706471e93d1f299104f9a7Ted Kremenek    if (Invalidate)
1155eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek      return Environment(F.remove(Env.ExprBindings, E));
116d72ee907f76000446c706471e93d1f299104f9a7Ted Kremenek    else
117d72ee907f76000446c706471e93d1f299104f9a7Ted Kremenek      return Env;
118d72ee907f76000446c706471e93d1f299104f9a7Ted Kremenek  }
1195eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek  return Environment(F.add(Env.ExprBindings, E, V));
120d72ee907f76000446c706471e93d1f299104f9a7Ted Kremenek}
121df9cdf8fce5bb43b335994f946f7c8e3a3bca7faTed Kremenek
1225216ad7e095873f19e535ad1efba91973f05d8e8Ted Kremeneknamespace {
123ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass MarkLiveCallback : public SymbolVisitor {
1245216ad7e095873f19e535ad1efba91973f05d8e8Ted Kremenek  SymbolReaper &SymReaper;
1255216ad7e095873f19e535ad1efba91973f05d8e8Ted Kremenekpublic:
1261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  MarkLiveCallback(SymbolReaper &symreaper) : SymReaper(symreaper) {}
127651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool VisitSymbol(SymbolRef sym) override {
1287f9b1d963d4b7e2faff7305733e3453130b402feTed Kremenek    SymReaper.markLive(sym);
1297f9b1d963d4b7e2faff7305733e3453130b402feTed Kremenek    return true;
1307f9b1d963d4b7e2faff7305733e3453130b402feTed Kremenek  }
131651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool VisitMemRegion(const MemRegion *R) override {
1327f9b1d963d4b7e2faff7305733e3453130b402feTed Kremenek    SymReaper.markLive(R);
1337f9b1d963d4b7e2faff7305733e3453130b402feTed Kremenek    return true;
1347f9b1d963d4b7e2faff7305733e3453130b402feTed Kremenek  }
1355216ad7e095873f19e535ad1efba91973f05d8e8Ted Kremenek};
1365216ad7e095873f19e535ad1efba91973f05d8e8Ted Kremenek} // end anonymous namespace
1375216ad7e095873f19e535ad1efba91973f05d8e8Ted Kremenek
138db0594bfc013131f88429add4eb653c285fa94fbTed Kremenek// removeDeadBindings:
1399d8d0fc04d69bfae2478eb17df5e0335648a82c5Zhongxing Xu//  - Remove subexpression bindings.
1409d8d0fc04d69bfae2478eb17df5e0335648a82c5Zhongxing Xu//  - Remove dead block expression bindings.
1419d8d0fc04d69bfae2478eb17df5e0335648a82c5Zhongxing Xu//  - Keep live block expression bindings:
1421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump//   - Mark their reachable symbols live in SymbolReaper,
1439d8d0fc04d69bfae2478eb17df5e0335648a82c5Zhongxing Xu//     see ScanReachableSymbols.
1449d8d0fc04d69bfae2478eb17df5e0335648a82c5Zhongxing Xu//   - Mark the region in DRoots if the binding is a loc::MemRegionVal.
1451eb4433ac451dc16f4133a88af2d002ac26c58efMike StumpEnvironment
146db0594bfc013131f88429add4eb653c285fa94fbTed KremenekEnvironmentManager::removeDeadBindings(Environment Env,
1470fb0bc4067d6c9d7c0e655300ef309b05d3adfc9Ted Kremenek                                       SymbolReaper &SymReaper,
1488bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek                                       ProgramStateRef ST) {
1491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1500fb0bc4067d6c9d7c0e655300ef309b05d3adfc9Ted Kremenek  // We construct a new Environment object entirely, as this is cheaper than
1510fb0bc4067d6c9d7c0e655300ef309b05d3adfc9Ted Kremenek  // individually removing all the subexpression bindings (which will greatly
1520fb0bc4067d6c9d7c0e655300ef309b05d3adfc9Ted Kremenek  // outnumber block-level expression bindings).
153c179a7fbb294fe3ff6cf5479f6239a10f39628c7Zhongxing Xu  Environment NewEnv = getInitialEnvironment();
1541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1555f625712f622f6e57de17b6f7eec242956b993eeAnna Zaks  MarkLiveCallback CB(SymReaper);
1565f625712f622f6e57de17b6f7eec242956b993eeAnna Zaks  ScanReachableSymbols RSScaner(ST, CB);
1575f625712f622f6e57de17b6f7eec242956b993eeAnna Zaks
1585eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek  llvm::ImmutableMapRef<EnvironmentEntry,SVal>
1591e705d57f27f6f899882440cbd5b0fbf520e2fe4Anna Zaks    EBMapRef(NewEnv.ExprBindings.getRootWithoutRetain(),
1601e705d57f27f6f899882440cbd5b0fbf520e2fe4Anna Zaks             F.getTreeFactory());
1611e705d57f27f6f899882440cbd5b0fbf520e2fe4Anna Zaks
162df9cdf8fce5bb43b335994f946f7c8e3a3bca7faTed Kremenek  // Iterate over the block-expr bindings.
1631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  for (Environment::iterator I = Env.begin(), E = Env.end();
164df9cdf8fce5bb43b335994f946f7c8e3a3bca7faTed Kremenek       I != E; ++I) {
1651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1665eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek    const EnvironmentEntry &BlkExpr = I.getKey();
1677b73b92870aa6271ac3d0a91eca83f6dde68c904Zhongxing Xu    const SVal &X = I.getData();
1687b73b92870aa6271ac3d0a91eca83f6dde68c904Zhongxing Xu
1695eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek    if (SymReaper.isLive(BlkExpr.getStmt(), BlkExpr.getLocationContext())) {
1700fb0bc4067d6c9d7c0e655300ef309b05d3adfc9Ted Kremenek      // Copy the binding to the new map.
1711e705d57f27f6f899882440cbd5b0fbf520e2fe4Anna Zaks      EBMapRef = EBMapRef.add(BlkExpr, X);
1721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1739e24049bef26b6289cce9ac9b483c5cbb096e3aeTed Kremenek      // If the block expr's value is a memory region, then mark that region.
174dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie      if (Optional<loc::MemRegionVal> R = X.getAs<loc::MemRegionVal>())
1755251abea41b446c26e3239c8dd6c7edea6fc335dDavid Blaikie        SymReaper.markLive(R->getRegion());
1769e24049bef26b6289cce9ac9b483c5cbb096e3aeTed Kremenek
1775216ad7e095873f19e535ad1efba91973f05d8e8Ted Kremenek      // Mark all symbols in the block expr's value live.
1785f625712f622f6e57de17b6f7eec242956b993eeAnna Zaks      RSScaner.scan(X);
1790fb0bc4067d6c9d7c0e655300ef309b05d3adfc9Ted Kremenek      continue;
18084c484545c5906ba55143e212b4a5275ab55889fJordan Rose    } else {
18184c484545c5906ba55143e212b4a5275ab55889fJordan Rose      SymExpr::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end();
18284c484545c5906ba55143e212b4a5275ab55889fJordan Rose      for (; SI != SE; ++SI)
18384c484545c5906ba55143e212b4a5275ab55889fJordan Rose        SymReaper.maybeDead(*SI);
184df9cdf8fce5bb43b335994f946f7c8e3a3bca7faTed Kremenek    }
185df9cdf8fce5bb43b335994f946f7c8e3a3bca7faTed Kremenek  }
186df9cdf8fce5bb43b335994f946f7c8e3a3bca7faTed Kremenek
1871e705d57f27f6f899882440cbd5b0fbf520e2fe4Anna Zaks  NewEnv.ExprBindings = EBMapRef.asImmutableMap();
1880fb0bc4067d6c9d7c0e655300ef309b05d3adfc9Ted Kremenek  return NewEnv;
189df9cdf8fce5bb43b335994f946f7c8e3a3bca7faTed Kremenek}
1905eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek
1915eca482fe895ea57bc82410222e6426c09e63284Ted Kremenekvoid Environment::print(raw_ostream &Out, const char *NL,
1925eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek                        const char *Sep) const {
1935eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek  bool isFirst = true;
1945eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek
1955eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek  for (Environment::iterator I = begin(), E = end(); I != E; ++I) {
1965eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek    const EnvironmentEntry &En = I.getKey();
1975eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek
1985eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek    if (isFirst) {
1995eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek      Out << NL << NL
2007affe151f5689b2d3547b8947c4099532c78a021Jordan Rose          << "Expressions:"
2015eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek          << NL;
2025eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek      isFirst = false;
2035eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek    } else {
2045eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek      Out << NL;
2055eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek    }
2065eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek
2075eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek    const Stmt *S = En.getStmt();
208ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    assert(S != nullptr && "Expected non-null Stmt");
209ef8225444452a1486bd721f3285301fe84643b00Stephen Hines
21031ba6135375433b617a8587ea6cc836a014ebd86Roman Divacky    Out << " (" << (const void*) En.getLocationContext() << ','
21131ba6135375433b617a8587ea6cc836a014ebd86Roman Divacky      << (const void*) S << ") ";
2125eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek    LangOptions LO; // FIXME.
2136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    S->printPretty(Out, nullptr, PrintingPolicy(LO));
2145eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek    Out << " : " << I.getData();
2155eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek  }
2165eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek}
217