10b57cec5SDimitry Andric //===- Store.cpp - Interface for maps from Locations to Values ------------===//
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 defined the types Store and StoreManager.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
140b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
150b57cec5SDimitry Andric #include "clang/AST/CXXInheritance.h"
160b57cec5SDimitry Andric #include "clang/AST/CharUnits.h"
170b57cec5SDimitry Andric #include "clang/AST/Decl.h"
180b57cec5SDimitry Andric #include "clang/AST/DeclCXX.h"
190b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h"
200b57cec5SDimitry Andric #include "clang/AST/Expr.h"
210b57cec5SDimitry Andric #include "clang/AST/Type.h"
220b57cec5SDimitry Andric #include "clang/Basic/LLVM.h"
230b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h"
240b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
250b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
260b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
270b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
280b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
290b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
300b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
310b57cec5SDimitry Andric #include "llvm/ADT/APSInt.h"
320b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
330b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
340b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
350b57cec5SDimitry Andric #include <cassert>
360b57cec5SDimitry Andric #include <cstdint>
37bdd1243dSDimitry Andric #include <optional>
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric using namespace clang;
400b57cec5SDimitry Andric using namespace ento;
410b57cec5SDimitry Andric 
StoreManager(ProgramStateManager & stateMgr)420b57cec5SDimitry Andric StoreManager::StoreManager(ProgramStateManager &stateMgr)
430b57cec5SDimitry Andric     : svalBuilder(stateMgr.getSValBuilder()), StateMgr(stateMgr),
440b57cec5SDimitry Andric       MRMgr(svalBuilder.getRegionManager()), Ctx(stateMgr.getContext()) {}
450b57cec5SDimitry Andric 
enterStackFrame(Store OldStore,const CallEvent & Call,const StackFrameContext * LCtx)460b57cec5SDimitry Andric StoreRef StoreManager::enterStackFrame(Store OldStore,
470b57cec5SDimitry Andric                                        const CallEvent &Call,
480b57cec5SDimitry Andric                                        const StackFrameContext *LCtx) {
490b57cec5SDimitry Andric   StoreRef Store = StoreRef(OldStore, *this);
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric   SmallVector<CallEvent::FrameBindingTy, 16> InitialBindings;
520b57cec5SDimitry Andric   Call.getInitialStackFrameContents(LCtx, InitialBindings);
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric   for (const auto &I : InitialBindings)
55a7dea167SDimitry Andric     Store = Bind(Store.getStore(), I.first.castAs<Loc>(), I.second);
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric   return Store;
580b57cec5SDimitry Andric }
590b57cec5SDimitry Andric 
MakeElementRegion(const SubRegion * Base,QualType EleTy,uint64_t index)600b57cec5SDimitry Andric const ElementRegion *StoreManager::MakeElementRegion(const SubRegion *Base,
610b57cec5SDimitry Andric                                                      QualType EleTy,
620b57cec5SDimitry Andric                                                      uint64_t index) {
630b57cec5SDimitry Andric   NonLoc idx = svalBuilder.makeArrayIndex(index);
640b57cec5SDimitry Andric   return MRMgr.getElementRegion(EleTy, idx, Base, svalBuilder.getContext());
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric 
GetElementZeroRegion(const SubRegion * R,QualType T)670b57cec5SDimitry Andric const ElementRegion *StoreManager::GetElementZeroRegion(const SubRegion *R,
680b57cec5SDimitry Andric                                                         QualType T) {
690b57cec5SDimitry Andric   NonLoc idx = svalBuilder.makeZeroArrayIndex();
700b57cec5SDimitry Andric   assert(!T.isNull());
710b57cec5SDimitry Andric   return MRMgr.getElementRegion(T, idx, R, Ctx);
720b57cec5SDimitry Andric }
730b57cec5SDimitry Andric 
castRegion(const MemRegion * R,QualType CastToTy)74bdd1243dSDimitry Andric std::optional<const MemRegion *> StoreManager::castRegion(const MemRegion *R,
75fe6060f1SDimitry Andric                                                           QualType CastToTy) {
760b57cec5SDimitry Andric   ASTContext &Ctx = StateMgr.getContext();
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric   // Handle casts to Objective-C objects.
790b57cec5SDimitry Andric   if (CastToTy->isObjCObjectPointerType())
800b57cec5SDimitry Andric     return R->StripCasts();
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric   if (CastToTy->isBlockPointerType()) {
830b57cec5SDimitry Andric     // FIXME: We may need different solutions, depending on the symbol
840b57cec5SDimitry Andric     // involved.  Blocks can be casted to/from 'id', as they can be treated
850b57cec5SDimitry Andric     // as Objective-C objects.  This could possibly be handled by enhancing
860b57cec5SDimitry Andric     // our reasoning of downcasts of symbolic objects.
87349cc55cSDimitry Andric     if (isa<CodeTextRegion, SymbolicRegion>(R))
880b57cec5SDimitry Andric       return R;
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric     // We don't know what to make of it.  Return a NULL region, which
910b57cec5SDimitry Andric     // will be interpreted as UnknownVal.
92bdd1243dSDimitry Andric     return std::nullopt;
930b57cec5SDimitry Andric   }
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric   // Now assume we are casting from pointer to pointer. Other cases should
960b57cec5SDimitry Andric   // already be handled.
970b57cec5SDimitry Andric   QualType PointeeTy = CastToTy->getPointeeType();
980b57cec5SDimitry Andric   QualType CanonPointeeTy = Ctx.getCanonicalType(PointeeTy);
99349cc55cSDimitry Andric   CanonPointeeTy = CanonPointeeTy.getLocalUnqualifiedType();
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric   // Handle casts to void*.  We just pass the region through.
102349cc55cSDimitry Andric   if (CanonPointeeTy == Ctx.VoidTy)
1030b57cec5SDimitry Andric     return R;
1040b57cec5SDimitry Andric 
105349cc55cSDimitry Andric   const auto IsSameRegionType = [&Ctx](const MemRegion *R, QualType OtherTy) {
1060b57cec5SDimitry Andric     if (const auto *TR = dyn_cast<TypedValueRegion>(R)) {
1070b57cec5SDimitry Andric       QualType ObjTy = Ctx.getCanonicalType(TR->getValueType());
108349cc55cSDimitry Andric       if (OtherTy == ObjTy.getLocalUnqualifiedType())
109349cc55cSDimitry Andric         return true;
1100b57cec5SDimitry Andric     }
111349cc55cSDimitry Andric     return false;
112349cc55cSDimitry Andric   };
113349cc55cSDimitry Andric 
114349cc55cSDimitry Andric   // Handle casts from compatible types.
115349cc55cSDimitry Andric   if (R->isBoundable() && IsSameRegionType(R, CanonPointeeTy))
116349cc55cSDimitry Andric     return R;
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric   // Process region cast according to the kind of the region being cast.
1190b57cec5SDimitry Andric   switch (R->getKind()) {
1200b57cec5SDimitry Andric     case MemRegion::CXXThisRegionKind:
1210b57cec5SDimitry Andric     case MemRegion::CodeSpaceRegionKind:
1220b57cec5SDimitry Andric     case MemRegion::StackLocalsSpaceRegionKind:
1230b57cec5SDimitry Andric     case MemRegion::StackArgumentsSpaceRegionKind:
1240b57cec5SDimitry Andric     case MemRegion::HeapSpaceRegionKind:
1250b57cec5SDimitry Andric     case MemRegion::UnknownSpaceRegionKind:
1260b57cec5SDimitry Andric     case MemRegion::StaticGlobalSpaceRegionKind:
1270b57cec5SDimitry Andric     case MemRegion::GlobalInternalSpaceRegionKind:
1280b57cec5SDimitry Andric     case MemRegion::GlobalSystemSpaceRegionKind:
1290b57cec5SDimitry Andric     case MemRegion::GlobalImmutableSpaceRegionKind: {
1300b57cec5SDimitry Andric       llvm_unreachable("Invalid region cast");
1310b57cec5SDimitry Andric     }
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric     case MemRegion::FunctionCodeRegionKind:
1340b57cec5SDimitry Andric     case MemRegion::BlockCodeRegionKind:
1350b57cec5SDimitry Andric     case MemRegion::BlockDataRegionKind:
1360b57cec5SDimitry Andric     case MemRegion::StringRegionKind:
1370b57cec5SDimitry Andric       // FIXME: Need to handle arbitrary downcasts.
1380b57cec5SDimitry Andric     case MemRegion::SymbolicRegionKind:
1390b57cec5SDimitry Andric     case MemRegion::AllocaRegionKind:
1400b57cec5SDimitry Andric     case MemRegion::CompoundLiteralRegionKind:
1410b57cec5SDimitry Andric     case MemRegion::FieldRegionKind:
1420b57cec5SDimitry Andric     case MemRegion::ObjCIvarRegionKind:
1430b57cec5SDimitry Andric     case MemRegion::ObjCStringRegionKind:
1445ffd83dbSDimitry Andric     case MemRegion::NonParamVarRegionKind:
1455ffd83dbSDimitry Andric     case MemRegion::ParamVarRegionKind:
1460b57cec5SDimitry Andric     case MemRegion::CXXTempObjectRegionKind:
14706c3fb27SDimitry Andric     case MemRegion::CXXLifetimeExtendedObjectRegionKind:
1480b57cec5SDimitry Andric     case MemRegion::CXXBaseObjectRegionKind:
1490b57cec5SDimitry Andric     case MemRegion::CXXDerivedObjectRegionKind:
1500b57cec5SDimitry Andric       return MakeElementRegion(cast<SubRegion>(R), PointeeTy);
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric     case MemRegion::ElementRegionKind: {
1530b57cec5SDimitry Andric       // If we are casting from an ElementRegion to another type, the
1540b57cec5SDimitry Andric       // algorithm is as follows:
1550b57cec5SDimitry Andric       //
1560b57cec5SDimitry Andric       // (1) Compute the "raw offset" of the ElementRegion from the
1570b57cec5SDimitry Andric       //     base region.  This is done by calling 'getAsRawOffset()'.
1580b57cec5SDimitry Andric       //
1590b57cec5SDimitry Andric       // (2a) If we get a 'RegionRawOffset' after calling
1600b57cec5SDimitry Andric       //      'getAsRawOffset()', determine if the absolute offset
1610b57cec5SDimitry Andric       //      can be exactly divided into chunks of the size of the
1620b57cec5SDimitry Andric       //      casted-pointee type.  If so, create a new ElementRegion with
1630b57cec5SDimitry Andric       //      the pointee-cast type as the new ElementType and the index
1640b57cec5SDimitry Andric       //      being the offset divded by the chunk size.  If not, create
1650b57cec5SDimitry Andric       //      a new ElementRegion at offset 0 off the raw offset region.
1660b57cec5SDimitry Andric       //
1670b57cec5SDimitry Andric       // (2b) If we don't a get a 'RegionRawOffset' after calling
1680b57cec5SDimitry Andric       //      'getAsRawOffset()', it means that we are at offset 0.
1690b57cec5SDimitry Andric       //
1700b57cec5SDimitry Andric       // FIXME: Handle symbolic raw offsets.
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric       const ElementRegion *elementR = cast<ElementRegion>(R);
1730b57cec5SDimitry Andric       const RegionRawOffset &rawOff = elementR->getAsArrayOffset();
1740b57cec5SDimitry Andric       const MemRegion *baseR = rawOff.getRegion();
1750b57cec5SDimitry Andric 
1760b57cec5SDimitry Andric       // If we cannot compute a raw offset, throw up our hands and return
1770b57cec5SDimitry Andric       // a NULL MemRegion*.
1780b57cec5SDimitry Andric       if (!baseR)
179bdd1243dSDimitry Andric         return std::nullopt;
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric       CharUnits off = rawOff.getOffset();
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric       if (off.isZero()) {
184349cc55cSDimitry Andric         // Edge case: we are at 0 bytes off the beginning of baseR. We check to
185349cc55cSDimitry Andric         // see if the type we are casting to is the same as the type of the base
1860b57cec5SDimitry Andric         // region. If so, just return the base region.
187349cc55cSDimitry Andric         if (IsSameRegionType(baseR, CanonPointeeTy))
1880b57cec5SDimitry Andric           return baseR;
1890b57cec5SDimitry Andric         // Otherwise, create a new ElementRegion at offset 0.
1900b57cec5SDimitry Andric         return MakeElementRegion(cast<SubRegion>(baseR), PointeeTy);
1910b57cec5SDimitry Andric       }
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric       // We have a non-zero offset from the base region.  We want to determine
1940b57cec5SDimitry Andric       // if the offset can be evenly divided by sizeof(PointeeTy).  If so,
1950b57cec5SDimitry Andric       // we create an ElementRegion whose index is that value.  Otherwise, we
1960b57cec5SDimitry Andric       // create two ElementRegions, one that reflects a raw offset and the other
1970b57cec5SDimitry Andric       // that reflects the cast.
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric       // Compute the index for the new ElementRegion.
2000b57cec5SDimitry Andric       int64_t newIndex = 0;
2010b57cec5SDimitry Andric       const MemRegion *newSuperR = nullptr;
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric       // We can only compute sizeof(PointeeTy) if it is a complete type.
2040b57cec5SDimitry Andric       if (!PointeeTy->isIncompleteType()) {
2050b57cec5SDimitry Andric         // Compute the size in **bytes**.
2060b57cec5SDimitry Andric         CharUnits pointeeTySize = Ctx.getTypeSizeInChars(PointeeTy);
2070b57cec5SDimitry Andric         if (!pointeeTySize.isZero()) {
2080b57cec5SDimitry Andric           // Is the offset a multiple of the size?  If so, we can layer the
2090b57cec5SDimitry Andric           // ElementRegion (with elementType == PointeeTy) directly on top of
2100b57cec5SDimitry Andric           // the base region.
2110b57cec5SDimitry Andric           if (off % pointeeTySize == 0) {
2120b57cec5SDimitry Andric             newIndex = off / pointeeTySize;
2130b57cec5SDimitry Andric             newSuperR = baseR;
2140b57cec5SDimitry Andric           }
2150b57cec5SDimitry Andric         }
2160b57cec5SDimitry Andric       }
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric       if (!newSuperR) {
2190b57cec5SDimitry Andric         // Create an intermediate ElementRegion to represent the raw byte.
2200b57cec5SDimitry Andric         // This will be the super region of the final ElementRegion.
2210b57cec5SDimitry Andric         newSuperR = MakeElementRegion(cast<SubRegion>(baseR), Ctx.CharTy,
2220b57cec5SDimitry Andric                                       off.getQuantity());
2230b57cec5SDimitry Andric       }
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric       return MakeElementRegion(cast<SubRegion>(newSuperR), PointeeTy, newIndex);
2260b57cec5SDimitry Andric     }
2270b57cec5SDimitry Andric   }
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric   llvm_unreachable("unreachable");
2300b57cec5SDimitry Andric }
2310b57cec5SDimitry Andric 
regionMatchesCXXRecordType(SVal V,QualType Ty)2320b57cec5SDimitry Andric static bool regionMatchesCXXRecordType(SVal V, QualType Ty) {
2330b57cec5SDimitry Andric   const MemRegion *MR = V.getAsRegion();
2340b57cec5SDimitry Andric   if (!MR)
2350b57cec5SDimitry Andric     return true;
2360b57cec5SDimitry Andric 
2370b57cec5SDimitry Andric   const auto *TVR = dyn_cast<TypedValueRegion>(MR);
2380b57cec5SDimitry Andric   if (!TVR)
2390b57cec5SDimitry Andric     return true;
2400b57cec5SDimitry Andric 
2410b57cec5SDimitry Andric   const CXXRecordDecl *RD = TVR->getValueType()->getAsCXXRecordDecl();
2420b57cec5SDimitry Andric   if (!RD)
2430b57cec5SDimitry Andric     return true;
2440b57cec5SDimitry Andric 
2450b57cec5SDimitry Andric   const CXXRecordDecl *Expected = Ty->getPointeeCXXRecordDecl();
2460b57cec5SDimitry Andric   if (!Expected)
2470b57cec5SDimitry Andric     Expected = Ty->getAsCXXRecordDecl();
2480b57cec5SDimitry Andric 
2490b57cec5SDimitry Andric   return Expected->getCanonicalDecl() == RD->getCanonicalDecl();
2500b57cec5SDimitry Andric }
2510b57cec5SDimitry Andric 
evalDerivedToBase(SVal Derived,const CastExpr * Cast)2520b57cec5SDimitry Andric SVal StoreManager::evalDerivedToBase(SVal Derived, const CastExpr *Cast) {
2535e801ac6SDimitry Andric   // Early return to avoid doing the wrong thing in the face of
2540b57cec5SDimitry Andric   // reinterpret_cast.
2550b57cec5SDimitry Andric   if (!regionMatchesCXXRecordType(Derived, Cast->getSubExpr()->getType()))
2560b57cec5SDimitry Andric     return UnknownVal();
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric   // Walk through the cast path to create nested CXXBaseRegions.
2590b57cec5SDimitry Andric   SVal Result = Derived;
26006c3fb27SDimitry Andric   for (const CXXBaseSpecifier *Base : Cast->path()) {
26106c3fb27SDimitry Andric     Result = evalDerivedToBase(Result, Base->getType(), Base->isVirtual());
2620b57cec5SDimitry Andric   }
2630b57cec5SDimitry Andric   return Result;
2640b57cec5SDimitry Andric }
2650b57cec5SDimitry Andric 
evalDerivedToBase(SVal Derived,const CXXBasePath & Path)2660b57cec5SDimitry Andric SVal StoreManager::evalDerivedToBase(SVal Derived, const CXXBasePath &Path) {
2670b57cec5SDimitry Andric   // Walk through the path to create nested CXXBaseRegions.
2680b57cec5SDimitry Andric   SVal Result = Derived;
2690b57cec5SDimitry Andric   for (const auto &I : Path)
2700b57cec5SDimitry Andric     Result = evalDerivedToBase(Result, I.Base->getType(),
2710b57cec5SDimitry Andric                                I.Base->isVirtual());
2720b57cec5SDimitry Andric   return Result;
2730b57cec5SDimitry Andric }
2740b57cec5SDimitry Andric 
evalDerivedToBase(SVal Derived,QualType BaseType,bool IsVirtual)2750b57cec5SDimitry Andric SVal StoreManager::evalDerivedToBase(SVal Derived, QualType BaseType,
2760b57cec5SDimitry Andric                                      bool IsVirtual) {
2770b57cec5SDimitry Andric   const MemRegion *DerivedReg = Derived.getAsRegion();
2780b57cec5SDimitry Andric   if (!DerivedReg)
2790b57cec5SDimitry Andric     return Derived;
2800b57cec5SDimitry Andric 
2810b57cec5SDimitry Andric   const CXXRecordDecl *BaseDecl = BaseType->getPointeeCXXRecordDecl();
2820b57cec5SDimitry Andric   if (!BaseDecl)
2830b57cec5SDimitry Andric     BaseDecl = BaseType->getAsCXXRecordDecl();
2840b57cec5SDimitry Andric   assert(BaseDecl && "not a C++ object?");
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric   if (const auto *AlreadyDerivedReg =
2870b57cec5SDimitry Andric           dyn_cast<CXXDerivedObjectRegion>(DerivedReg)) {
2880b57cec5SDimitry Andric     if (const auto *SR =
2890b57cec5SDimitry Andric             dyn_cast<SymbolicRegion>(AlreadyDerivedReg->getSuperRegion()))
2900b57cec5SDimitry Andric       if (SR->getSymbol()->getType()->getPointeeCXXRecordDecl() == BaseDecl)
2910b57cec5SDimitry Andric         return loc::MemRegionVal(SR);
2920b57cec5SDimitry Andric 
2930b57cec5SDimitry Andric     DerivedReg = AlreadyDerivedReg->getSuperRegion();
2940b57cec5SDimitry Andric   }
2950b57cec5SDimitry Andric 
2960b57cec5SDimitry Andric   const MemRegion *BaseReg = MRMgr.getCXXBaseObjectRegion(
2970b57cec5SDimitry Andric       BaseDecl, cast<SubRegion>(DerivedReg), IsVirtual);
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric   return loc::MemRegionVal(BaseReg);
3000b57cec5SDimitry Andric }
3010b57cec5SDimitry Andric 
3020b57cec5SDimitry Andric /// Returns the static type of the given region, if it represents a C++ class
3030b57cec5SDimitry Andric /// object.
3040b57cec5SDimitry Andric ///
3050b57cec5SDimitry Andric /// This handles both fully-typed regions, where the dynamic type is known, and
3060b57cec5SDimitry Andric /// symbolic regions, where the dynamic type is merely bounded (and even then,
3070b57cec5SDimitry Andric /// only ostensibly!), but does not take advantage of any dynamic type info.
getCXXRecordType(const MemRegion * MR)3080b57cec5SDimitry Andric static const CXXRecordDecl *getCXXRecordType(const MemRegion *MR) {
3090b57cec5SDimitry Andric   if (const auto *TVR = dyn_cast<TypedValueRegion>(MR))
3100b57cec5SDimitry Andric     return TVR->getValueType()->getAsCXXRecordDecl();
3110b57cec5SDimitry Andric   if (const auto *SR = dyn_cast<SymbolicRegion>(MR))
3120b57cec5SDimitry Andric     return SR->getSymbol()->getType()->getPointeeCXXRecordDecl();
3130b57cec5SDimitry Andric   return nullptr;
3140b57cec5SDimitry Andric }
3150b57cec5SDimitry Andric 
evalBaseToDerived(SVal Base,QualType TargetType)316bdd1243dSDimitry Andric std::optional<SVal> StoreManager::evalBaseToDerived(SVal Base,
317bdd1243dSDimitry Andric                                                     QualType TargetType) {
3180b57cec5SDimitry Andric   const MemRegion *MR = Base.getAsRegion();
3190b57cec5SDimitry Andric   if (!MR)
3200b57cec5SDimitry Andric     return UnknownVal();
3210b57cec5SDimitry Andric 
3220b57cec5SDimitry Andric   // Assume the derived class is a pointer or a reference to a CXX record.
3230b57cec5SDimitry Andric   TargetType = TargetType->getPointeeType();
3240b57cec5SDimitry Andric   assert(!TargetType.isNull());
3250b57cec5SDimitry Andric   const CXXRecordDecl *TargetClass = TargetType->getAsCXXRecordDecl();
3260b57cec5SDimitry Andric   if (!TargetClass && !TargetType->isVoidType())
3270b57cec5SDimitry Andric     return UnknownVal();
3280b57cec5SDimitry Andric 
3290b57cec5SDimitry Andric   // Drill down the CXXBaseObject chains, which represent upcasts (casts from
3300b57cec5SDimitry Andric   // derived to base).
3310b57cec5SDimitry Andric   while (const CXXRecordDecl *MRClass = getCXXRecordType(MR)) {
3320b57cec5SDimitry Andric     // If found the derived class, the cast succeeds.
3330b57cec5SDimitry Andric     if (MRClass == TargetClass)
3340b57cec5SDimitry Andric       return loc::MemRegionVal(MR);
3350b57cec5SDimitry Andric 
3360b57cec5SDimitry Andric     // We skip over incomplete types. They must be the result of an earlier
3370b57cec5SDimitry Andric     // reinterpret_cast, as one can only dynamic_cast between types in the same
3380b57cec5SDimitry Andric     // class hierarchy.
3390b57cec5SDimitry Andric     if (!TargetType->isVoidType() && MRClass->hasDefinition()) {
3400b57cec5SDimitry Andric       // Static upcasts are marked as DerivedToBase casts by Sema, so this will
3410b57cec5SDimitry Andric       // only happen when multiple or virtual inheritance is involved.
3420b57cec5SDimitry Andric       CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/true,
3430b57cec5SDimitry Andric                          /*DetectVirtual=*/false);
3440b57cec5SDimitry Andric       if (MRClass->isDerivedFrom(TargetClass, Paths))
3450b57cec5SDimitry Andric         return evalDerivedToBase(loc::MemRegionVal(MR), Paths.front());
3460b57cec5SDimitry Andric     }
3470b57cec5SDimitry Andric 
3480b57cec5SDimitry Andric     if (const auto *BaseR = dyn_cast<CXXBaseObjectRegion>(MR)) {
3490b57cec5SDimitry Andric       // Drill down the chain to get the derived classes.
3500b57cec5SDimitry Andric       MR = BaseR->getSuperRegion();
3510b57cec5SDimitry Andric       continue;
3520b57cec5SDimitry Andric     }
3530b57cec5SDimitry Andric 
3540b57cec5SDimitry Andric     // If this is a cast to void*, return the region.
3550b57cec5SDimitry Andric     if (TargetType->isVoidType())
3560b57cec5SDimitry Andric       return loc::MemRegionVal(MR);
3570b57cec5SDimitry Andric 
3580b57cec5SDimitry Andric     // Strange use of reinterpret_cast can give us paths we don't reason
3590b57cec5SDimitry Andric     // about well, by putting in ElementRegions where we'd expect
3600b57cec5SDimitry Andric     // CXXBaseObjectRegions. If it's a valid reinterpret_cast (i.e. if the
3610b57cec5SDimitry Andric     // derived class has a zero offset from the base class), then it's safe
3620b57cec5SDimitry Andric     // to strip the cast; if it's invalid, -Wreinterpret-base-class should
3630b57cec5SDimitry Andric     // catch it. In the interest of performance, the analyzer will silently
3640b57cec5SDimitry Andric     // do the wrong thing in the invalid case (because offsets for subregions
3650b57cec5SDimitry Andric     // will be wrong).
3660b57cec5SDimitry Andric     const MemRegion *Uncasted = MR->StripCasts(/*IncludeBaseCasts=*/false);
3670b57cec5SDimitry Andric     if (Uncasted == MR) {
3680b57cec5SDimitry Andric       // We reached the bottom of the hierarchy and did not find the derived
3690b57cec5SDimitry Andric       // class. We must be casting the base to derived, so the cast should
3700b57cec5SDimitry Andric       // fail.
3710b57cec5SDimitry Andric       break;
3720b57cec5SDimitry Andric     }
3730b57cec5SDimitry Andric 
3740b57cec5SDimitry Andric     MR = Uncasted;
3750b57cec5SDimitry Andric   }
3760b57cec5SDimitry Andric 
3770b57cec5SDimitry Andric   // If we're casting a symbolic base pointer to a derived class, use
3780b57cec5SDimitry Andric   // CXXDerivedObjectRegion to represent the cast. If it's a pointer to an
3790b57cec5SDimitry Andric   // unrelated type, it must be a weird reinterpret_cast and we have to
3800b57cec5SDimitry Andric   // be fine with ElementRegion. TODO: Should we instead make
3810b57cec5SDimitry Andric   // Derived{TargetClass, Element{SourceClass, SR}}?
3820b57cec5SDimitry Andric   if (const auto *SR = dyn_cast<SymbolicRegion>(MR)) {
3830b57cec5SDimitry Andric     QualType T = SR->getSymbol()->getType();
3840b57cec5SDimitry Andric     const CXXRecordDecl *SourceClass = T->getPointeeCXXRecordDecl();
3850b57cec5SDimitry Andric     if (TargetClass && SourceClass && TargetClass->isDerivedFrom(SourceClass))
3860b57cec5SDimitry Andric       return loc::MemRegionVal(
3870b57cec5SDimitry Andric           MRMgr.getCXXDerivedObjectRegion(TargetClass, SR));
3880b57cec5SDimitry Andric     return loc::MemRegionVal(GetElementZeroRegion(SR, TargetType));
3890b57cec5SDimitry Andric   }
3900b57cec5SDimitry Andric 
3910b57cec5SDimitry Andric   // We failed if the region we ended up with has perfect type info.
3920eae32dcSDimitry Andric   if (isa<TypedValueRegion>(MR))
393bdd1243dSDimitry Andric     return std::nullopt;
3940eae32dcSDimitry Andric 
3950b57cec5SDimitry Andric   return UnknownVal();
3960b57cec5SDimitry Andric }
3970b57cec5SDimitry Andric 
getLValueFieldOrIvar(const Decl * D,SVal Base)3980b57cec5SDimitry Andric SVal StoreManager::getLValueFieldOrIvar(const Decl *D, SVal Base) {
3990b57cec5SDimitry Andric   if (Base.isUnknownOrUndef())
4000b57cec5SDimitry Andric     return Base;
4010b57cec5SDimitry Andric 
4020b57cec5SDimitry Andric   Loc BaseL = Base.castAs<Loc>();
4030b57cec5SDimitry Andric   const SubRegion* BaseR = nullptr;
4040b57cec5SDimitry Andric 
4055f757f3fSDimitry Andric   switch (BaseL.getKind()) {
4060b57cec5SDimitry Andric   case loc::MemRegionValKind:
4070b57cec5SDimitry Andric     BaseR = cast<SubRegion>(BaseL.castAs<loc::MemRegionVal>().getRegion());
4080b57cec5SDimitry Andric     break;
4090b57cec5SDimitry Andric 
4100b57cec5SDimitry Andric   case loc::GotoLabelKind:
4110b57cec5SDimitry Andric     // These are anormal cases. Flag an undefined value.
4120b57cec5SDimitry Andric     return UndefinedVal();
4130b57cec5SDimitry Andric 
4140b57cec5SDimitry Andric   case loc::ConcreteIntKind:
4150b57cec5SDimitry Andric     // While these seem funny, this can happen through casts.
4160b57cec5SDimitry Andric     // FIXME: What we should return is the field offset, not base. For example,
4170b57cec5SDimitry Andric     //  add the field offset to the integer value.  That way things
4180b57cec5SDimitry Andric     //  like this work properly:  &(((struct foo *) 0xa)->f)
4190b57cec5SDimitry Andric     //  However, that's not easy to fix without reducing our abilities
4200b57cec5SDimitry Andric     //  to catch null pointer dereference. Eg., ((struct foo *)0x0)->f = 7
4210b57cec5SDimitry Andric     //  is a null dereference even though we're dereferencing offset of f
4220b57cec5SDimitry Andric     //  rather than null. Coming up with an approach that computes offsets
4230b57cec5SDimitry Andric     //  over null pointers properly while still being able to catch null
4240b57cec5SDimitry Andric     //  dereferences might be worth it.
4250b57cec5SDimitry Andric     return Base;
4260b57cec5SDimitry Andric 
4270b57cec5SDimitry Andric   default:
4280b57cec5SDimitry Andric     llvm_unreachable("Unhandled Base.");
4290b57cec5SDimitry Andric   }
4300b57cec5SDimitry Andric 
4310b57cec5SDimitry Andric   // NOTE: We must have this check first because ObjCIvarDecl is a subclass
4320b57cec5SDimitry Andric   // of FieldDecl.
4330b57cec5SDimitry Andric   if (const auto *ID = dyn_cast<ObjCIvarDecl>(D))
4340b57cec5SDimitry Andric     return loc::MemRegionVal(MRMgr.getObjCIvarRegion(ID, BaseR));
4350b57cec5SDimitry Andric 
4360b57cec5SDimitry Andric   return loc::MemRegionVal(MRMgr.getFieldRegion(cast<FieldDecl>(D), BaseR));
4370b57cec5SDimitry Andric }
4380b57cec5SDimitry Andric 
getLValueIvar(const ObjCIvarDecl * decl,SVal base)4390b57cec5SDimitry Andric SVal StoreManager::getLValueIvar(const ObjCIvarDecl *decl, SVal base) {
4400b57cec5SDimitry Andric   return getLValueFieldOrIvar(decl, base);
4410b57cec5SDimitry Andric }
4420b57cec5SDimitry Andric 
getLValueElement(QualType elementType,NonLoc Offset,SVal Base)4430b57cec5SDimitry Andric SVal StoreManager::getLValueElement(QualType elementType, NonLoc Offset,
4440b57cec5SDimitry Andric                                     SVal Base) {
445349cc55cSDimitry Andric 
446349cc55cSDimitry Andric   // Special case, if index is 0, return the same type as if
447349cc55cSDimitry Andric   // this was not an array dereference.
448349cc55cSDimitry Andric   if (Offset.isZeroConstant()) {
449349cc55cSDimitry Andric     QualType BT = Base.getType(this->Ctx);
450349cc55cSDimitry Andric     if (!BT.isNull() && !elementType.isNull()) {
451349cc55cSDimitry Andric       QualType PointeeTy = BT->getPointeeType();
452349cc55cSDimitry Andric       if (!PointeeTy.isNull() &&
453349cc55cSDimitry Andric           PointeeTy.getCanonicalType() == elementType.getCanonicalType())
454349cc55cSDimitry Andric         return Base;
455349cc55cSDimitry Andric     }
456349cc55cSDimitry Andric   }
457349cc55cSDimitry Andric 
4580b57cec5SDimitry Andric   // If the base is an unknown or undefined value, just return it back.
4590b57cec5SDimitry Andric   // FIXME: For absolute pointer addresses, we just return that value back as
4600b57cec5SDimitry Andric   //  well, although in reality we should return the offset added to that
4610b57cec5SDimitry Andric   //  value. See also the similar FIXME in getLValueFieldOrIvar().
46281ad6265SDimitry Andric   if (Base.isUnknownOrUndef() || isa<loc::ConcreteInt>(Base))
4630b57cec5SDimitry Andric     return Base;
4640b57cec5SDimitry Andric 
46581ad6265SDimitry Andric   if (isa<loc::GotoLabel>(Base))
4660b57cec5SDimitry Andric     return UnknownVal();
4670b57cec5SDimitry Andric 
4680b57cec5SDimitry Andric   const SubRegion *BaseRegion =
4690b57cec5SDimitry Andric       Base.castAs<loc::MemRegionVal>().getRegionAs<SubRegion>();
4700b57cec5SDimitry Andric 
4710b57cec5SDimitry Andric   // Pointer of any type can be cast and used as array base.
4720b57cec5SDimitry Andric   const auto *ElemR = dyn_cast<ElementRegion>(BaseRegion);
4730b57cec5SDimitry Andric 
4740b57cec5SDimitry Andric   // Convert the offset to the appropriate size and signedness.
4750b57cec5SDimitry Andric   Offset = svalBuilder.convertToArrayIndex(Offset).castAs<NonLoc>();
4760b57cec5SDimitry Andric 
4770b57cec5SDimitry Andric   if (!ElemR) {
4780b57cec5SDimitry Andric     // If the base region is not an ElementRegion, create one.
4790b57cec5SDimitry Andric     // This can happen in the following example:
4800b57cec5SDimitry Andric     //
4810b57cec5SDimitry Andric     //   char *p = __builtin_alloc(10);
4820b57cec5SDimitry Andric     //   p[1] = 8;
4830b57cec5SDimitry Andric     //
4840b57cec5SDimitry Andric     //  Observe that 'p' binds to an AllocaRegion.
4850b57cec5SDimitry Andric     return loc::MemRegionVal(MRMgr.getElementRegion(elementType, Offset,
4860b57cec5SDimitry Andric                                                     BaseRegion, Ctx));
4870b57cec5SDimitry Andric   }
4880b57cec5SDimitry Andric 
4890b57cec5SDimitry Andric   SVal BaseIdx = ElemR->getIndex();
4900b57cec5SDimitry Andric 
49181ad6265SDimitry Andric   if (!isa<nonloc::ConcreteInt>(BaseIdx))
4920b57cec5SDimitry Andric     return UnknownVal();
4930b57cec5SDimitry Andric 
4940b57cec5SDimitry Andric   const llvm::APSInt &BaseIdxI =
4950b57cec5SDimitry Andric       BaseIdx.castAs<nonloc::ConcreteInt>().getValue();
4960b57cec5SDimitry Andric 
4970b57cec5SDimitry Andric   // Only allow non-integer offsets if the base region has no offset itself.
4980b57cec5SDimitry Andric   // FIXME: This is a somewhat arbitrary restriction. We should be using
4990b57cec5SDimitry Andric   // SValBuilder here to add the two offsets without checking their types.
50081ad6265SDimitry Andric   if (!isa<nonloc::ConcreteInt>(Offset)) {
5010b57cec5SDimitry Andric     if (isa<ElementRegion>(BaseRegion->StripCasts()))
5020b57cec5SDimitry Andric       return UnknownVal();
5030b57cec5SDimitry Andric 
5040b57cec5SDimitry Andric     return loc::MemRegionVal(MRMgr.getElementRegion(
5050b57cec5SDimitry Andric         elementType, Offset, cast<SubRegion>(ElemR->getSuperRegion()), Ctx));
5060b57cec5SDimitry Andric   }
5070b57cec5SDimitry Andric 
5080b57cec5SDimitry Andric   const llvm::APSInt& OffI = Offset.castAs<nonloc::ConcreteInt>().getValue();
5090b57cec5SDimitry Andric   assert(BaseIdxI.isSigned());
5100b57cec5SDimitry Andric 
5110b57cec5SDimitry Andric   // Compute the new index.
5120b57cec5SDimitry Andric   nonloc::ConcreteInt NewIdx(svalBuilder.getBasicValueFactory().getValue(BaseIdxI +
5130b57cec5SDimitry Andric                                                                     OffI));
5140b57cec5SDimitry Andric 
5150b57cec5SDimitry Andric   // Construct the new ElementRegion.
5160b57cec5SDimitry Andric   const SubRegion *ArrayR = cast<SubRegion>(ElemR->getSuperRegion());
5170b57cec5SDimitry Andric   return loc::MemRegionVal(MRMgr.getElementRegion(elementType, NewIdx, ArrayR,
5180b57cec5SDimitry Andric                                                   Ctx));
5190b57cec5SDimitry Andric }
5200b57cec5SDimitry Andric 
5210b57cec5SDimitry Andric StoreManager::BindingsHandler::~BindingsHandler() = default;
5220b57cec5SDimitry Andric 
HandleBinding(StoreManager & SMgr,Store store,const MemRegion * R,SVal val)5230b57cec5SDimitry Andric bool StoreManager::FindUniqueBinding::HandleBinding(StoreManager& SMgr,
5240b57cec5SDimitry Andric                                                     Store store,
5250b57cec5SDimitry Andric                                                     const MemRegion* R,
5260b57cec5SDimitry Andric                                                     SVal val) {
5270b57cec5SDimitry Andric   SymbolRef SymV = val.getAsLocSymbol();
5280b57cec5SDimitry Andric   if (!SymV || SymV != Sym)
5290b57cec5SDimitry Andric     return true;
5300b57cec5SDimitry Andric 
5310b57cec5SDimitry Andric   if (Binding) {
5320b57cec5SDimitry Andric     First = false;
5330b57cec5SDimitry Andric     return false;
5340b57cec5SDimitry Andric   }
5350b57cec5SDimitry Andric   else
5360b57cec5SDimitry Andric     Binding = R;
5370b57cec5SDimitry Andric 
5380b57cec5SDimitry Andric   return true;
5390b57cec5SDimitry Andric }
540