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),
57d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose                                         L ? L->getCurrentStackFrame() : 0) {}
58d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose
595eca482fe895ea57bc82410222e6426c09e63284Ted KremenekSVal Environment::lookupExpr(const EnvironmentEntry &E) const {
60465846324f412055dd1ce270d757bfeead0811dcTed Kremenek  const SVal* X = ExprBindings.lookup(E);
61465846324f412055dd1ce270d757bfeead0811dcTed Kremenek  if (X) {
62465846324f412055dd1ce270d757bfeead0811dcTed Kremenek    SVal V = *X;
63465846324f412055dd1ce270d757bfeead0811dcTed Kremenek    return V;
64465846324f412055dd1ce270d757bfeead0811dcTed Kremenek  }
65465846324f412055dd1ce270d757bfeead0811dcTed Kremenek  return UnknownVal();
66465846324f412055dd1ce270d757bfeead0811dcTed Kremenek}
67465846324f412055dd1ce270d757bfeead0811dcTed Kremenek
685eca482fe895ea57bc82410222e6426c09e63284Ted KremenekSVal Environment::getSVal(const EnvironmentEntry &Entry,
69e5a934d3c840872d58724383a83443ed38f1d831Jordan Rose                          SValBuilder& svalBuilder) const {
70d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  const Stmt *S = Entry.getStmt();
715eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek  const LocationContext *LCtx = Entry.getLocationContext();
72d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose
73d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  switch (S->getStmtClass()) {
74d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  case Stmt::CXXBindTemporaryExprClass:
75d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  case Stmt::ExprWithCleanupsClass:
76d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  case Stmt::GenericSelectionExprClass:
77d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  case Stmt::OpaqueValueExprClass:
78d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  case Stmt::ParenExprClass:
79d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  case Stmt::SubstNonTypeTemplateParmExprClass:
80d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose    llvm_unreachable("Should have been handled by ignoreTransparentExprs");
81d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose
82d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  case Stmt::AddrLabelExprClass:
83e2b1246a24e8babf2f58c93713fba16b8edb8e2dJordan Rose  case Stmt::CharacterLiteralClass:
84d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  case Stmt::CXXBoolLiteralExprClass:
85d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  case Stmt::CXXScalarValueInitExprClass:
86e2b1246a24e8babf2f58c93713fba16b8edb8e2dJordan Rose  case Stmt::ImplicitValueInitExprClass:
87d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  case Stmt::IntegerLiteralClass:
88d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  case Stmt::ObjCBoolLiteralExprClass:
89d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  case Stmt::CXXNullPtrLiteralExprClass:
90e2b1246a24e8babf2f58c93713fba16b8edb8e2dJordan Rose  case Stmt::ObjCStringLiteralClass:
91e2b1246a24e8babf2f58c93713fba16b8edb8e2dJordan Rose  case Stmt::StringLiteralClass:
92e2b1246a24e8babf2f58c93713fba16b8edb8e2dJordan Rose    // Known constants; defer to SValBuilder.
93e2b1246a24e8babf2f58c93713fba16b8edb8e2dJordan Rose    return svalBuilder.getConstantVal(cast<Expr>(S)).getValue();
94d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose
95d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  case Stmt::ReturnStmtClass: {
96d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose    const ReturnStmt *RS = cast<ReturnStmt>(S);
97d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose    if (const Expr *RE = RS->getRetValue())
98d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose      return getSVal(EnvironmentEntry(RE, LCtx), svalBuilder);
99d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose    return UndefinedVal();
100d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  }
101d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose
102d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  // Handle all other Stmt* using a lookup.
103d4ce811ae08398e357c8ce3e707ba5f2aa0041a5Jordan Rose  default:
104e2b1246a24e8babf2f58c93713fba16b8edb8e2dJordan Rose    return lookupExpr(EnvironmentEntry(S, LCtx));
105d72ee907f76000446c706471e93d1f299104f9a7Ted Kremenek  }
106d72ee907f76000446c706471e93d1f299104f9a7Ted Kremenek}
1078133a26c166be89fb4f0a339db1e2fe923c51a70Ted Kremenek
1085eca482fe895ea57bc82410222e6426c09e63284Ted KremenekEnvironment EnvironmentManager::bindExpr(Environment Env,
1095eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek                                         const EnvironmentEntry &E,
1105eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek                                         SVal V,
1115eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek                                         bool Invalidate) {
1121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  if (V.isUnknown()) {
113d72ee907f76000446c706471e93d1f299104f9a7Ted Kremenek    if (Invalidate)
1145eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek      return Environment(F.remove(Env.ExprBindings, E));
115d72ee907f76000446c706471e93d1f299104f9a7Ted Kremenek    else
116d72ee907f76000446c706471e93d1f299104f9a7Ted Kremenek      return Env;
117d72ee907f76000446c706471e93d1f299104f9a7Ted Kremenek  }
1185eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek  return Environment(F.add(Env.ExprBindings, E, V));
119d72ee907f76000446c706471e93d1f299104f9a7Ted Kremenek}
120df9cdf8fce5bb43b335994f946f7c8e3a3bca7faTed Kremenek
1215216ad7e095873f19e535ad1efba91973f05d8e8Ted Kremeneknamespace {
122ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass MarkLiveCallback : public SymbolVisitor {
1235216ad7e095873f19e535ad1efba91973f05d8e8Ted Kremenek  SymbolReaper &SymReaper;
1245216ad7e095873f19e535ad1efba91973f05d8e8Ted Kremenekpublic:
1251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  MarkLiveCallback(SymbolReaper &symreaper) : SymReaper(symreaper) {}
1267f9b1d963d4b7e2faff7305733e3453130b402feTed Kremenek  bool VisitSymbol(SymbolRef sym) {
1277f9b1d963d4b7e2faff7305733e3453130b402feTed Kremenek    SymReaper.markLive(sym);
1287f9b1d963d4b7e2faff7305733e3453130b402feTed Kremenek    return true;
1297f9b1d963d4b7e2faff7305733e3453130b402feTed Kremenek  }
1307f9b1d963d4b7e2faff7305733e3453130b402feTed Kremenek  bool VisitMemRegion(const MemRegion *R) {
1317f9b1d963d4b7e2faff7305733e3453130b402feTed Kremenek    SymReaper.markLive(R);
1327f9b1d963d4b7e2faff7305733e3453130b402feTed Kremenek    return true;
1337f9b1d963d4b7e2faff7305733e3453130b402feTed Kremenek  }
1345216ad7e095873f19e535ad1efba91973f05d8e8Ted Kremenek};
1355216ad7e095873f19e535ad1efba91973f05d8e8Ted Kremenek} // end anonymous namespace
1365216ad7e095873f19e535ad1efba91973f05d8e8Ted Kremenek
137db0594bfc013131f88429add4eb653c285fa94fbTed Kremenek// removeDeadBindings:
1389d8d0fc04d69bfae2478eb17df5e0335648a82c5Zhongxing Xu//  - Remove subexpression bindings.
1399d8d0fc04d69bfae2478eb17df5e0335648a82c5Zhongxing Xu//  - Remove dead block expression bindings.
1409d8d0fc04d69bfae2478eb17df5e0335648a82c5Zhongxing Xu//  - Keep live block expression bindings:
1411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump//   - Mark their reachable symbols live in SymbolReaper,
1429d8d0fc04d69bfae2478eb17df5e0335648a82c5Zhongxing Xu//     see ScanReachableSymbols.
1439d8d0fc04d69bfae2478eb17df5e0335648a82c5Zhongxing Xu//   - Mark the region in DRoots if the binding is a loc::MemRegionVal.
1441eb4433ac451dc16f4133a88af2d002ac26c58efMike StumpEnvironment
145db0594bfc013131f88429add4eb653c285fa94fbTed KremenekEnvironmentManager::removeDeadBindings(Environment Env,
1460fb0bc4067d6c9d7c0e655300ef309b05d3adfc9Ted Kremenek                                       SymbolReaper &SymReaper,
1478bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek                                       ProgramStateRef ST) {
1481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1490fb0bc4067d6c9d7c0e655300ef309b05d3adfc9Ted Kremenek  // We construct a new Environment object entirely, as this is cheaper than
1500fb0bc4067d6c9d7c0e655300ef309b05d3adfc9Ted Kremenek  // individually removing all the subexpression bindings (which will greatly
1510fb0bc4067d6c9d7c0e655300ef309b05d3adfc9Ted Kremenek  // outnumber block-level expression bindings).
152c179a7fbb294fe3ff6cf5479f6239a10f39628c7Zhongxing Xu  Environment NewEnv = getInitialEnvironment();
1531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1545f625712f622f6e57de17b6f7eec242956b993eeAnna Zaks  MarkLiveCallback CB(SymReaper);
1555f625712f622f6e57de17b6f7eec242956b993eeAnna Zaks  ScanReachableSymbols RSScaner(ST, CB);
1565f625712f622f6e57de17b6f7eec242956b993eeAnna Zaks
1575eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek  llvm::ImmutableMapRef<EnvironmentEntry,SVal>
1581e705d57f27f6f899882440cbd5b0fbf520e2fe4Anna Zaks    EBMapRef(NewEnv.ExprBindings.getRootWithoutRetain(),
1591e705d57f27f6f899882440cbd5b0fbf520e2fe4Anna Zaks             F.getTreeFactory());
1601e705d57f27f6f899882440cbd5b0fbf520e2fe4Anna Zaks
161df9cdf8fce5bb43b335994f946f7c8e3a3bca7faTed Kremenek  // Iterate over the block-expr bindings.
1621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  for (Environment::iterator I = Env.begin(), E = Env.end();
163df9cdf8fce5bb43b335994f946f7c8e3a3bca7faTed Kremenek       I != E; ++I) {
1641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1655eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek    const EnvironmentEntry &BlkExpr = I.getKey();
1667b73b92870aa6271ac3d0a91eca83f6dde68c904Zhongxing Xu    const SVal &X = I.getData();
1677b73b92870aa6271ac3d0a91eca83f6dde68c904Zhongxing Xu
1685eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek    if (SymReaper.isLive(BlkExpr.getStmt(), BlkExpr.getLocationContext())) {
1690fb0bc4067d6c9d7c0e655300ef309b05d3adfc9Ted Kremenek      // Copy the binding to the new map.
1701e705d57f27f6f899882440cbd5b0fbf520e2fe4Anna Zaks      EBMapRef = EBMapRef.add(BlkExpr, X);
1711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1729e24049bef26b6289cce9ac9b483c5cbb096e3aeTed Kremenek      // If the block expr's value is a memory region, then mark that region.
173dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie      if (Optional<loc::MemRegionVal> R = X.getAs<loc::MemRegionVal>())
1745251abea41b446c26e3239c8dd6c7edea6fc335dDavid Blaikie        SymReaper.markLive(R->getRegion());
1759e24049bef26b6289cce9ac9b483c5cbb096e3aeTed Kremenek
1765216ad7e095873f19e535ad1efba91973f05d8e8Ted Kremenek      // Mark all symbols in the block expr's value live.
1775f625712f622f6e57de17b6f7eec242956b993eeAnna Zaks      RSScaner.scan(X);
1780fb0bc4067d6c9d7c0e655300ef309b05d3adfc9Ted Kremenek      continue;
17984c484545c5906ba55143e212b4a5275ab55889fJordan Rose    } else {
18084c484545c5906ba55143e212b4a5275ab55889fJordan Rose      SymExpr::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end();
18184c484545c5906ba55143e212b4a5275ab55889fJordan Rose      for (; SI != SE; ++SI)
18284c484545c5906ba55143e212b4a5275ab55889fJordan Rose        SymReaper.maybeDead(*SI);
183df9cdf8fce5bb43b335994f946f7c8e3a3bca7faTed Kremenek    }
184df9cdf8fce5bb43b335994f946f7c8e3a3bca7faTed Kremenek  }
185df9cdf8fce5bb43b335994f946f7c8e3a3bca7faTed Kremenek
1861e705d57f27f6f899882440cbd5b0fbf520e2fe4Anna Zaks  NewEnv.ExprBindings = EBMapRef.asImmutableMap();
1870fb0bc4067d6c9d7c0e655300ef309b05d3adfc9Ted Kremenek  return NewEnv;
188df9cdf8fce5bb43b335994f946f7c8e3a3bca7faTed Kremenek}
1895eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek
1905eca482fe895ea57bc82410222e6426c09e63284Ted Kremenekvoid Environment::print(raw_ostream &Out, const char *NL,
1915eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek                        const char *Sep) const {
1925eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek  bool isFirst = true;
1935eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek
1945eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek  for (Environment::iterator I = begin(), E = end(); I != E; ++I) {
1955eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek    const EnvironmentEntry &En = I.getKey();
1965eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek
1975eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek    if (isFirst) {
1985eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek      Out << NL << NL
1997affe151f5689b2d3547b8947c4099532c78a021Jordan Rose          << "Expressions:"
2005eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek          << NL;
2015eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek      isFirst = false;
2025eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek    } else {
2035eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek      Out << NL;
2045eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek    }
2055eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek
2065eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek    const Stmt *S = En.getStmt();
2075eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek
20831ba6135375433b617a8587ea6cc836a014ebd86Roman Divacky    Out << " (" << (const void*) En.getLocationContext() << ','
20931ba6135375433b617a8587ea6cc836a014ebd86Roman Divacky      << (const void*) S << ") ";
2105eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek    LangOptions LO; // FIXME.
2115eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek    S->printPretty(Out, 0, PrintingPolicy(LO));
2125eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek    Out << " : " << I.getData();
2135eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek  }
2145eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek}
215