10b57cec5SDimitry Andric //===-- SVals.cpp - Abstract RValues for Path-Sens. Value Tracking --------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file defines SVal, Loc, and NonLoc, classes that represent 100b57cec5SDimitry Andric // abstract r-values for use with path-sensitive value tracking. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" 15fe6060f1SDimitry Andric #include "clang/AST/ASTContext.h" 160b57cec5SDimitry Andric #include "clang/AST/Decl.h" 170b57cec5SDimitry Andric #include "clang/AST/DeclCXX.h" 180b57cec5SDimitry Andric #include "clang/AST/Expr.h" 190b57cec5SDimitry Andric #include "clang/AST/Type.h" 200b57cec5SDimitry Andric #include "clang/Basic/JsonSupport.h" 210b57cec5SDimitry Andric #include "clang/Basic/LLVM.h" 220b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h" 230b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" 240b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h" 25fe6060f1SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h" 260b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h" 270b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" 280b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 290b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 300b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 310b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 320b57cec5SDimitry Andric #include <cassert> 33bdd1243dSDimitry Andric #include <optional> 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric using namespace clang; 360b57cec5SDimitry Andric using namespace ento; 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 390b57cec5SDimitry Andric // Symbol iteration within an SVal. 400b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 430b57cec5SDimitry Andric // Utility methods. 440b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric const FunctionDecl *SVal::getAsFunctionDecl() const { 47bdd1243dSDimitry Andric if (std::optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>()) { 480b57cec5SDimitry Andric const MemRegion* R = X->getRegion(); 490b57cec5SDimitry Andric if (const FunctionCodeRegion *CTR = R->getAs<FunctionCodeRegion>()) 500b57cec5SDimitry Andric if (const auto *FD = dyn_cast<FunctionDecl>(CTR->getDecl())) 510b57cec5SDimitry Andric return FD; 520b57cec5SDimitry Andric } 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric if (auto X = getAs<nonloc::PointerToMember>()) { 550b57cec5SDimitry Andric if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(X->getDecl())) 560b57cec5SDimitry Andric return MD; 570b57cec5SDimitry Andric } 580b57cec5SDimitry Andric return nullptr; 590b57cec5SDimitry Andric } 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric /// If this SVal is a location (subclasses Loc) and wraps a symbol, 620b57cec5SDimitry Andric /// return that SymbolRef. Otherwise return 0. 630b57cec5SDimitry Andric /// 640b57cec5SDimitry Andric /// Implicit casts (ex: void* -> char*) can turn Symbolic region into Element 650b57cec5SDimitry Andric /// region. If that is the case, gets the underlining region. 660b57cec5SDimitry Andric /// When IncludeBaseRegions is set to true and the SubRegion is non-symbolic, 670b57cec5SDimitry Andric /// the first symbolic parent region is returned. 680b57cec5SDimitry Andric SymbolRef SVal::getAsLocSymbol(bool IncludeBaseRegions) const { 690b57cec5SDimitry Andric // FIXME: should we consider SymbolRef wrapped in CodeTextRegion? 70e8d8bef9SDimitry Andric if (const MemRegion *R = getAsRegion()) 71e8d8bef9SDimitry Andric if (const SymbolicRegion *SymR = 72e8d8bef9SDimitry Andric IncludeBaseRegions ? R->getSymbolicBase() 73e8d8bef9SDimitry Andric : dyn_cast<SymbolicRegion>(R->StripCasts())) 740b57cec5SDimitry Andric return SymR->getSymbol(); 75e8d8bef9SDimitry Andric 760b57cec5SDimitry Andric return nullptr; 770b57cec5SDimitry Andric } 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric /// Get the symbol in the SVal or its base region. 800b57cec5SDimitry Andric SymbolRef SVal::getLocSymbolInBase() const { 81bdd1243dSDimitry Andric std::optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>(); 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric if (!X) 840b57cec5SDimitry Andric return nullptr; 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric const MemRegion *R = X->getRegion(); 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric while (const auto *SR = dyn_cast<SubRegion>(R)) { 890b57cec5SDimitry Andric if (const auto *SymR = dyn_cast<SymbolicRegion>(SR)) 900b57cec5SDimitry Andric return SymR->getSymbol(); 910b57cec5SDimitry Andric else 920b57cec5SDimitry Andric R = SR->getSuperRegion(); 930b57cec5SDimitry Andric } 940b57cec5SDimitry Andric 950b57cec5SDimitry Andric return nullptr; 960b57cec5SDimitry Andric } 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric /// If this SVal wraps a symbol return that SymbolRef. 990b57cec5SDimitry Andric /// Otherwise, return 0. 1000b57cec5SDimitry Andric /// 1010b57cec5SDimitry Andric /// Casts are ignored during lookup. 1020b57cec5SDimitry Andric /// \param IncludeBaseRegions The boolean that controls whether the search 1030b57cec5SDimitry Andric /// should continue to the base regions if the region is not symbolic. 1040b57cec5SDimitry Andric SymbolRef SVal::getAsSymbol(bool IncludeBaseRegions) const { 1050b57cec5SDimitry Andric // FIXME: should we consider SymbolRef wrapped in CodeTextRegion? 106bdd1243dSDimitry Andric if (std::optional<nonloc::SymbolVal> X = getAs<nonloc::SymbolVal>()) 1070b57cec5SDimitry Andric return X->getSymbol(); 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric return getAsLocSymbol(IncludeBaseRegions); 1100b57cec5SDimitry Andric } 1110b57cec5SDimitry Andric 112fcaf7f86SDimitry Andric const llvm::APSInt *SVal::getAsInteger() const { 113fcaf7f86SDimitry Andric if (auto CI = getAs<nonloc::ConcreteInt>()) 114fcaf7f86SDimitry Andric return &CI->getValue(); 115fcaf7f86SDimitry Andric if (auto CI = getAs<loc::ConcreteInt>()) 116fcaf7f86SDimitry Andric return &CI->getValue(); 117fcaf7f86SDimitry Andric return nullptr; 118fcaf7f86SDimitry Andric } 119fcaf7f86SDimitry Andric 1200b57cec5SDimitry Andric const MemRegion *SVal::getAsRegion() const { 121bdd1243dSDimitry Andric if (std::optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>()) 1220b57cec5SDimitry Andric return X->getRegion(); 1230b57cec5SDimitry Andric 124bdd1243dSDimitry Andric if (std::optional<nonloc::LocAsInteger> X = getAs<nonloc::LocAsInteger>()) 1250b57cec5SDimitry Andric return X->getLoc().getAsRegion(); 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric return nullptr; 1280b57cec5SDimitry Andric } 1290b57cec5SDimitry Andric 130fe6060f1SDimitry Andric namespace { 131fe6060f1SDimitry Andric class TypeRetrievingVisitor 132fe6060f1SDimitry Andric : public FullSValVisitor<TypeRetrievingVisitor, QualType> { 133fe6060f1SDimitry Andric private: 134fe6060f1SDimitry Andric const ASTContext &Context; 135fe6060f1SDimitry Andric 136fe6060f1SDimitry Andric public: 137fe6060f1SDimitry Andric TypeRetrievingVisitor(const ASTContext &Context) : Context(Context) {} 138fe6060f1SDimitry Andric 1395f757f3fSDimitry Andric QualType VisitMemRegionVal(loc::MemRegionVal MRV) { 140fe6060f1SDimitry Andric return Visit(MRV.getRegion()); 141fe6060f1SDimitry Andric } 1425f757f3fSDimitry Andric QualType VisitGotoLabel(loc::GotoLabel GL) { 143fe6060f1SDimitry Andric return QualType{Context.VoidPtrTy}; 144fe6060f1SDimitry Andric } 145fe6060f1SDimitry Andric template <class ConcreteInt> QualType VisitConcreteInt(ConcreteInt CI) { 146fe6060f1SDimitry Andric const llvm::APSInt &Value = CI.getValue(); 147fcaf7f86SDimitry Andric if (1 == Value.getBitWidth()) 148fcaf7f86SDimitry Andric return Context.BoolTy; 149fe6060f1SDimitry Andric return Context.getIntTypeForBitwidth(Value.getBitWidth(), Value.isSigned()); 150fe6060f1SDimitry Andric } 1515f757f3fSDimitry Andric QualType VisitLocAsInteger(nonloc::LocAsInteger LI) { 152fe6060f1SDimitry Andric QualType NestedType = Visit(LI.getLoc()); 153fe6060f1SDimitry Andric if (NestedType.isNull()) 154fe6060f1SDimitry Andric return NestedType; 155fe6060f1SDimitry Andric 156fe6060f1SDimitry Andric return Context.getIntTypeForBitwidth(LI.getNumBits(), 157fe6060f1SDimitry Andric NestedType->isSignedIntegerType()); 158fe6060f1SDimitry Andric } 1595f757f3fSDimitry Andric QualType VisitCompoundVal(nonloc::CompoundVal CV) { 160fe6060f1SDimitry Andric return CV.getValue()->getType(); 161fe6060f1SDimitry Andric } 1625f757f3fSDimitry Andric QualType VisitLazyCompoundVal(nonloc::LazyCompoundVal LCV) { 163fe6060f1SDimitry Andric return LCV.getRegion()->getValueType(); 164fe6060f1SDimitry Andric } 1655f757f3fSDimitry Andric QualType VisitSymbolVal(nonloc::SymbolVal SV) { 166fe6060f1SDimitry Andric return Visit(SV.getSymbol()); 167fe6060f1SDimitry Andric } 168fe6060f1SDimitry Andric QualType VisitSymbolicRegion(const SymbolicRegion *SR) { 169fe6060f1SDimitry Andric return Visit(SR->getSymbol()); 170fe6060f1SDimitry Andric } 17106c3fb27SDimitry Andric QualType VisitAllocaRegion(const AllocaRegion *) { 17206c3fb27SDimitry Andric return QualType{Context.VoidPtrTy}; 17306c3fb27SDimitry Andric } 174fe6060f1SDimitry Andric QualType VisitTypedRegion(const TypedRegion *TR) { 175fe6060f1SDimitry Andric return TR->getLocationType(); 176fe6060f1SDimitry Andric } 177fe6060f1SDimitry Andric QualType VisitSymExpr(const SymExpr *SE) { return SE->getType(); } 178fe6060f1SDimitry Andric }; 179fe6060f1SDimitry Andric } // end anonymous namespace 180fe6060f1SDimitry Andric 181fe6060f1SDimitry Andric QualType SVal::getType(const ASTContext &Context) const { 182fe6060f1SDimitry Andric TypeRetrievingVisitor TRV{Context}; 183fe6060f1SDimitry Andric return TRV.Visit(*this); 184fe6060f1SDimitry Andric } 185fe6060f1SDimitry Andric 1860b57cec5SDimitry Andric const MemRegion *loc::MemRegionVal::stripCasts(bool StripBaseCasts) const { 18781ad6265SDimitry Andric return getRegion()->StripCasts(StripBaseCasts); 1880b57cec5SDimitry Andric } 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric const void *nonloc::LazyCompoundVal::getStore() const { 1910b57cec5SDimitry Andric return static_cast<const LazyCompoundValData*>(Data)->getStore(); 1920b57cec5SDimitry Andric } 1930b57cec5SDimitry Andric 1940b57cec5SDimitry Andric const TypedValueRegion *nonloc::LazyCompoundVal::getRegion() const { 1950b57cec5SDimitry Andric return static_cast<const LazyCompoundValData*>(Data)->getRegion(); 1960b57cec5SDimitry Andric } 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric bool nonloc::PointerToMember::isNullMemberPointer() const { 1990b57cec5SDimitry Andric return getPTMData().isNull(); 2000b57cec5SDimitry Andric } 2010b57cec5SDimitry Andric 202e8d8bef9SDimitry Andric const NamedDecl *nonloc::PointerToMember::getDecl() const { 2030b57cec5SDimitry Andric const auto PTMD = this->getPTMData(); 2040b57cec5SDimitry Andric if (PTMD.isNull()) 2050b57cec5SDimitry Andric return nullptr; 2060b57cec5SDimitry Andric 207e8d8bef9SDimitry Andric const NamedDecl *ND = nullptr; 208e8d8bef9SDimitry Andric if (PTMD.is<const NamedDecl *>()) 209e8d8bef9SDimitry Andric ND = PTMD.get<const NamedDecl *>(); 2100b57cec5SDimitry Andric else 211e8d8bef9SDimitry Andric ND = PTMD.get<const PointerToMemberData *>()->getDeclaratorDecl(); 2120b57cec5SDimitry Andric 213e8d8bef9SDimitry Andric return ND; 2140b57cec5SDimitry Andric } 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 2170b57cec5SDimitry Andric // Other Iterators. 2180b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 2190b57cec5SDimitry Andric 2200b57cec5SDimitry Andric nonloc::CompoundVal::iterator nonloc::CompoundVal::begin() const { 2210b57cec5SDimitry Andric return getValue()->begin(); 2220b57cec5SDimitry Andric } 2230b57cec5SDimitry Andric 2240b57cec5SDimitry Andric nonloc::CompoundVal::iterator nonloc::CompoundVal::end() const { 2250b57cec5SDimitry Andric return getValue()->end(); 2260b57cec5SDimitry Andric } 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric nonloc::PointerToMember::iterator nonloc::PointerToMember::begin() const { 2290b57cec5SDimitry Andric const PTMDataType PTMD = getPTMData(); 230e8d8bef9SDimitry Andric if (PTMD.is<const NamedDecl *>()) 2310b57cec5SDimitry Andric return {}; 2320b57cec5SDimitry Andric return PTMD.get<const PointerToMemberData *>()->begin(); 2330b57cec5SDimitry Andric } 2340b57cec5SDimitry Andric 2350b57cec5SDimitry Andric nonloc::PointerToMember::iterator nonloc::PointerToMember::end() const { 2360b57cec5SDimitry Andric const PTMDataType PTMD = getPTMData(); 237e8d8bef9SDimitry Andric if (PTMD.is<const NamedDecl *>()) 2380b57cec5SDimitry Andric return {}; 2390b57cec5SDimitry Andric return PTMD.get<const PointerToMemberData *>()->end(); 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric 2420b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 2430b57cec5SDimitry Andric // Useful predicates. 2440b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 2450b57cec5SDimitry Andric 2460b57cec5SDimitry Andric bool SVal::isConstant() const { 2470b57cec5SDimitry Andric return getAs<nonloc::ConcreteInt>() || getAs<loc::ConcreteInt>(); 2480b57cec5SDimitry Andric } 2490b57cec5SDimitry Andric 2500b57cec5SDimitry Andric bool SVal::isConstant(int I) const { 251bdd1243dSDimitry Andric if (std::optional<loc::ConcreteInt> LV = getAs<loc::ConcreteInt>()) 2520b57cec5SDimitry Andric return LV->getValue() == I; 253bdd1243dSDimitry Andric if (std::optional<nonloc::ConcreteInt> NV = getAs<nonloc::ConcreteInt>()) 2540b57cec5SDimitry Andric return NV->getValue() == I; 2550b57cec5SDimitry Andric return false; 2560b57cec5SDimitry Andric } 2570b57cec5SDimitry Andric 2580b57cec5SDimitry Andric bool SVal::isZeroConstant() const { 2590b57cec5SDimitry Andric return isConstant(0); 2600b57cec5SDimitry Andric } 2610b57cec5SDimitry Andric 2620b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 2630b57cec5SDimitry Andric // Pretty-Printing. 2640b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 2650b57cec5SDimitry Andric 2660b57cec5SDimitry Andric LLVM_DUMP_METHOD void SVal::dump() const { dumpToStream(llvm::errs()); } 2670b57cec5SDimitry Andric 2680b57cec5SDimitry Andric void SVal::printJson(raw_ostream &Out, bool AddQuotes) const { 2690b57cec5SDimitry Andric std::string Buf; 2700b57cec5SDimitry Andric llvm::raw_string_ostream TempOut(Buf); 2710b57cec5SDimitry Andric 2720b57cec5SDimitry Andric dumpToStream(TempOut); 2730b57cec5SDimitry Andric 274*0fca6ea1SDimitry Andric Out << JsonFormat(Buf, AddQuotes); 2750b57cec5SDimitry Andric } 2760b57cec5SDimitry Andric 2770b57cec5SDimitry Andric void SVal::dumpToStream(raw_ostream &os) const { 2785f757f3fSDimitry Andric if (isUndef()) { 2790b57cec5SDimitry Andric os << "Undefined"; 2805f757f3fSDimitry Andric return; 2810b57cec5SDimitry Andric } 2825f757f3fSDimitry Andric if (isUnknown()) { 2835f757f3fSDimitry Andric os << "Unknown"; 2845f757f3fSDimitry Andric return; 2855f757f3fSDimitry Andric } 2865f757f3fSDimitry Andric if (NonLoc::classof(*this)) { 2875f757f3fSDimitry Andric castAs<NonLoc>().dumpToStream(os); 2885f757f3fSDimitry Andric return; 2895f757f3fSDimitry Andric } 2905f757f3fSDimitry Andric if (Loc::classof(*this)) { 2915f757f3fSDimitry Andric castAs<Loc>().dumpToStream(os); 2925f757f3fSDimitry Andric return; 2935f757f3fSDimitry Andric } 2945f757f3fSDimitry Andric llvm_unreachable("Unhandled SVal kind!"); 2950b57cec5SDimitry Andric } 2960b57cec5SDimitry Andric 2970b57cec5SDimitry Andric void NonLoc::dumpToStream(raw_ostream &os) const { 2985f757f3fSDimitry Andric switch (getKind()) { 2990b57cec5SDimitry Andric case nonloc::ConcreteIntKind: { 3000b57cec5SDimitry Andric const auto &Value = castAs<nonloc::ConcreteInt>().getValue(); 3015f757f3fSDimitry Andric os << Value << ' ' << (Value.isSigned() ? 'S' : 'U') << Value.getBitWidth() 3025f757f3fSDimitry Andric << 'b'; 3030b57cec5SDimitry Andric break; 3040b57cec5SDimitry Andric } 3050b57cec5SDimitry Andric case nonloc::SymbolValKind: 3060b57cec5SDimitry Andric os << castAs<nonloc::SymbolVal>().getSymbol(); 3070b57cec5SDimitry Andric break; 3080b57cec5SDimitry Andric 3090b57cec5SDimitry Andric case nonloc::LocAsIntegerKind: { 3100b57cec5SDimitry Andric const nonloc::LocAsInteger& C = castAs<nonloc::LocAsInteger>(); 3110b57cec5SDimitry Andric os << C.getLoc() << " [as " << C.getNumBits() << " bit integer]"; 3120b57cec5SDimitry Andric break; 3130b57cec5SDimitry Andric } 3140b57cec5SDimitry Andric case nonloc::CompoundValKind: { 3150b57cec5SDimitry Andric const nonloc::CompoundVal& C = castAs<nonloc::CompoundVal>(); 3160b57cec5SDimitry Andric os << "compoundVal{"; 3170b57cec5SDimitry Andric bool first = true; 3180b57cec5SDimitry Andric for (const auto &I : C) { 3190b57cec5SDimitry Andric if (first) { 3200b57cec5SDimitry Andric os << ' '; first = false; 3210b57cec5SDimitry Andric } 3220b57cec5SDimitry Andric else 3230b57cec5SDimitry Andric os << ", "; 3240b57cec5SDimitry Andric 3250b57cec5SDimitry Andric I.dumpToStream(os); 3260b57cec5SDimitry Andric } 3270b57cec5SDimitry Andric os << "}"; 3280b57cec5SDimitry Andric break; 3290b57cec5SDimitry Andric } 3300b57cec5SDimitry Andric case nonloc::LazyCompoundValKind: { 3310b57cec5SDimitry Andric const nonloc::LazyCompoundVal &C = castAs<nonloc::LazyCompoundVal>(); 3320b57cec5SDimitry Andric os << "lazyCompoundVal{" << const_cast<void *>(C.getStore()) 3330b57cec5SDimitry Andric << ',' << C.getRegion() 3340b57cec5SDimitry Andric << '}'; 3350b57cec5SDimitry Andric break; 3360b57cec5SDimitry Andric } 3370b57cec5SDimitry Andric case nonloc::PointerToMemberKind: { 3380b57cec5SDimitry Andric os << "pointerToMember{"; 3390b57cec5SDimitry Andric const nonloc::PointerToMember &CastRes = 3400b57cec5SDimitry Andric castAs<nonloc::PointerToMember>(); 3410b57cec5SDimitry Andric if (CastRes.getDecl()) 3420b57cec5SDimitry Andric os << "|" << CastRes.getDecl()->getQualifiedNameAsString() << "|"; 3430b57cec5SDimitry Andric bool first = true; 3440b57cec5SDimitry Andric for (const auto &I : CastRes) { 3450b57cec5SDimitry Andric if (first) { 3460b57cec5SDimitry Andric os << ' '; first = false; 3470b57cec5SDimitry Andric } 3480b57cec5SDimitry Andric else 3490b57cec5SDimitry Andric os << ", "; 3500b57cec5SDimitry Andric 35181ad6265SDimitry Andric os << I->getType(); 3520b57cec5SDimitry Andric } 3530b57cec5SDimitry Andric 3540b57cec5SDimitry Andric os << '}'; 3550b57cec5SDimitry Andric break; 3560b57cec5SDimitry Andric } 3570b57cec5SDimitry Andric default: 3580b57cec5SDimitry Andric assert(false && "Pretty-printed not implemented for this NonLoc."); 3590b57cec5SDimitry Andric break; 3600b57cec5SDimitry Andric } 3610b57cec5SDimitry Andric } 3620b57cec5SDimitry Andric 3630b57cec5SDimitry Andric void Loc::dumpToStream(raw_ostream &os) const { 3645f757f3fSDimitry Andric switch (getKind()) { 3650b57cec5SDimitry Andric case loc::ConcreteIntKind: 3660b57cec5SDimitry Andric os << castAs<loc::ConcreteInt>().getValue().getZExtValue() << " (Loc)"; 3670b57cec5SDimitry Andric break; 3680b57cec5SDimitry Andric case loc::GotoLabelKind: 3690b57cec5SDimitry Andric os << "&&" << castAs<loc::GotoLabel>().getLabel()->getName(); 3700b57cec5SDimitry Andric break; 3710b57cec5SDimitry Andric case loc::MemRegionValKind: 3720b57cec5SDimitry Andric os << '&' << castAs<loc::MemRegionVal>().getRegion()->getString(); 3730b57cec5SDimitry Andric break; 3740b57cec5SDimitry Andric default: 3750b57cec5SDimitry Andric llvm_unreachable("Pretty-printing not implemented for this Loc."); 3760b57cec5SDimitry Andric } 3770b57cec5SDimitry Andric } 378