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