xref: /freebsd-src/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/SVals.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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