10b57cec5SDimitry Andric //===- CallEvent.cpp - Wrapper for all function and method calls ----------===// 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 /// \file This file defines CallEvent and its subclasses, which represent path- 100b57cec5SDimitry Andric /// sensitive instances of different kinds of function and method calls 110b57cec5SDimitry Andric /// (C, C++, and Objective-C). 120b57cec5SDimitry Andric // 130b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" 160b57cec5SDimitry Andric #include "clang/AST/ASTContext.h" 17480093f4SDimitry Andric #include "clang/AST/Attr.h" 180b57cec5SDimitry Andric #include "clang/AST/Decl.h" 190b57cec5SDimitry Andric #include "clang/AST/DeclBase.h" 200b57cec5SDimitry Andric #include "clang/AST/DeclCXX.h" 210b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h" 220b57cec5SDimitry Andric #include "clang/AST/Expr.h" 230b57cec5SDimitry Andric #include "clang/AST/ExprCXX.h" 240b57cec5SDimitry Andric #include "clang/AST/ExprObjC.h" 250b57cec5SDimitry Andric #include "clang/AST/ParentMap.h" 260b57cec5SDimitry Andric #include "clang/AST/Stmt.h" 270b57cec5SDimitry Andric #include "clang/AST/Type.h" 280b57cec5SDimitry Andric #include "clang/Analysis/AnalysisDeclContext.h" 290b57cec5SDimitry Andric #include "clang/Analysis/CFG.h" 300b57cec5SDimitry Andric #include "clang/Analysis/CFGStmtMap.h" 31a7dea167SDimitry Andric #include "clang/Analysis/PathDiagnostic.h" 320b57cec5SDimitry Andric #include "clang/Analysis/ProgramPoint.h" 330b57cec5SDimitry Andric #include "clang/Basic/IdentifierTable.h" 340b57cec5SDimitry Andric #include "clang/Basic/LLVM.h" 350b57cec5SDimitry Andric #include "clang/Basic/SourceLocation.h" 360b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h" 370b57cec5SDimitry Andric #include "clang/Basic/Specifiers.h" 38480093f4SDimitry Andric #include "clang/CrossTU/CrossTranslationUnit.h" 39349cc55cSDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h" 400b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 41a7dea167SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicType.h" 42480093f4SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h" 430b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" 440b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 450b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" 460b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h" 47480093f4SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" 480b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" 490b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 500b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 51fe6060f1SDimitry Andric #include "llvm/ADT/ImmutableList.h" 520b57cec5SDimitry Andric #include "llvm/ADT/PointerIntPair.h" 530b57cec5SDimitry Andric #include "llvm/ADT/SmallSet.h" 540b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 550b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h" 560b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 570b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 580b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 590b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 600b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 610b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 620b57cec5SDimitry Andric #include <cassert> 63bdd1243dSDimitry Andric #include <optional> 640b57cec5SDimitry Andric #include <utility> 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric #define DEBUG_TYPE "static-analyzer-call-event" 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric using namespace clang; 690b57cec5SDimitry Andric using namespace ento; 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric QualType CallEvent::getResultType() const { 720b57cec5SDimitry Andric ASTContext &Ctx = getState()->getStateManager().getContext(); 730b57cec5SDimitry Andric const Expr *E = getOriginExpr(); 740b57cec5SDimitry Andric if (!E) 750b57cec5SDimitry Andric return Ctx.VoidTy; 76349cc55cSDimitry Andric return Ctx.getReferenceQualifiedType(E); 770b57cec5SDimitry Andric } 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric static bool isCallback(QualType T) { 800b57cec5SDimitry Andric // If a parameter is a block or a callback, assume it can modify pointer. 810b57cec5SDimitry Andric if (T->isBlockPointerType() || 820b57cec5SDimitry Andric T->isFunctionPointerType() || 830b57cec5SDimitry Andric T->isObjCSelType()) 840b57cec5SDimitry Andric return true; 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric // Check if a callback is passed inside a struct (for both, struct passed by 870b57cec5SDimitry Andric // reference and by value). Dig just one level into the struct for now. 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric if (T->isAnyPointerType() || T->isReferenceType()) 900b57cec5SDimitry Andric T = T->getPointeeType(); 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric if (const RecordType *RT = T->getAsStructureType()) { 930b57cec5SDimitry Andric const RecordDecl *RD = RT->getDecl(); 940b57cec5SDimitry Andric for (const auto *I : RD->fields()) { 950b57cec5SDimitry Andric QualType FieldT = I->getType(); 960b57cec5SDimitry Andric if (FieldT->isBlockPointerType() || FieldT->isFunctionPointerType()) 970b57cec5SDimitry Andric return true; 980b57cec5SDimitry Andric } 990b57cec5SDimitry Andric } 1000b57cec5SDimitry Andric return false; 1010b57cec5SDimitry Andric } 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric static bool isVoidPointerToNonConst(QualType T) { 1040b57cec5SDimitry Andric if (const auto *PT = T->getAs<PointerType>()) { 1050b57cec5SDimitry Andric QualType PointeeTy = PT->getPointeeType(); 1060b57cec5SDimitry Andric if (PointeeTy.isConstQualified()) 1070b57cec5SDimitry Andric return false; 1080b57cec5SDimitry Andric return PointeeTy->isVoidType(); 1090b57cec5SDimitry Andric } else 1100b57cec5SDimitry Andric return false; 1110b57cec5SDimitry Andric } 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric bool CallEvent::hasNonNullArgumentsWithType(bool (*Condition)(QualType)) const { 1140b57cec5SDimitry Andric unsigned NumOfArgs = getNumArgs(); 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric // If calling using a function pointer, assume the function does not 1170b57cec5SDimitry Andric // satisfy the callback. 1180b57cec5SDimitry Andric // TODO: We could check the types of the arguments here. 1190b57cec5SDimitry Andric if (!getDecl()) 1200b57cec5SDimitry Andric return false; 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric unsigned Idx = 0; 1230b57cec5SDimitry Andric for (CallEvent::param_type_iterator I = param_type_begin(), 1240b57cec5SDimitry Andric E = param_type_end(); 1250b57cec5SDimitry Andric I != E && Idx < NumOfArgs; ++I, ++Idx) { 1260b57cec5SDimitry Andric // If the parameter is 0, it's harmless. 1270b57cec5SDimitry Andric if (getArgSVal(Idx).isZeroConstant()) 1280b57cec5SDimitry Andric continue; 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric if (Condition(*I)) 1310b57cec5SDimitry Andric return true; 1320b57cec5SDimitry Andric } 1330b57cec5SDimitry Andric return false; 1340b57cec5SDimitry Andric } 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric bool CallEvent::hasNonZeroCallbackArg() const { 1370b57cec5SDimitry Andric return hasNonNullArgumentsWithType(isCallback); 1380b57cec5SDimitry Andric } 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric bool CallEvent::hasVoidPointerToNonConstArg() const { 1410b57cec5SDimitry Andric return hasNonNullArgumentsWithType(isVoidPointerToNonConst); 1420b57cec5SDimitry Andric } 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric bool CallEvent::isGlobalCFunction(StringRef FunctionName) const { 1450b57cec5SDimitry Andric const auto *FD = dyn_cast_or_null<FunctionDecl>(getDecl()); 1460b57cec5SDimitry Andric if (!FD) 1470b57cec5SDimitry Andric return false; 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric return CheckerContext::isCLibraryFunction(FD, FunctionName); 1500b57cec5SDimitry Andric } 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric AnalysisDeclContext *CallEvent::getCalleeAnalysisDeclContext() const { 1530b57cec5SDimitry Andric const Decl *D = getDecl(); 1540b57cec5SDimitry Andric if (!D) 1550b57cec5SDimitry Andric return nullptr; 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric AnalysisDeclContext *ADC = 1580b57cec5SDimitry Andric LCtx->getAnalysisDeclContext()->getManager()->getContext(D); 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric return ADC; 1610b57cec5SDimitry Andric } 1620b57cec5SDimitry Andric 163a7dea167SDimitry Andric const StackFrameContext * 164a7dea167SDimitry Andric CallEvent::getCalleeStackFrame(unsigned BlockCount) const { 1650b57cec5SDimitry Andric AnalysisDeclContext *ADC = getCalleeAnalysisDeclContext(); 1660b57cec5SDimitry Andric if (!ADC) 1670b57cec5SDimitry Andric return nullptr; 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andric const Expr *E = getOriginExpr(); 1700b57cec5SDimitry Andric if (!E) 1710b57cec5SDimitry Andric return nullptr; 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric // Recover CFG block via reverse lookup. 1740b57cec5SDimitry Andric // TODO: If we were to keep CFG element information as part of the CallEvent 1750b57cec5SDimitry Andric // instead of doing this reverse lookup, we would be able to build the stack 1760b57cec5SDimitry Andric // frame for non-expression-based calls, and also we wouldn't need the reverse 1770b57cec5SDimitry Andric // lookup. 1780b57cec5SDimitry Andric CFGStmtMap *Map = LCtx->getAnalysisDeclContext()->getCFGStmtMap(); 1790b57cec5SDimitry Andric const CFGBlock *B = Map->getBlock(E); 1800b57cec5SDimitry Andric assert(B); 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric // Also recover CFG index by scanning the CFG block. 1830b57cec5SDimitry Andric unsigned Idx = 0, Sz = B->size(); 1840b57cec5SDimitry Andric for (; Idx < Sz; ++Idx) 1850b57cec5SDimitry Andric if (auto StmtElem = (*B)[Idx].getAs<CFGStmt>()) 1860b57cec5SDimitry Andric if (StmtElem->getStmt() == E) 1870b57cec5SDimitry Andric break; 1880b57cec5SDimitry Andric assert(Idx < Sz); 1890b57cec5SDimitry Andric 190a7dea167SDimitry Andric return ADC->getManager()->getStackFrame(ADC, LCtx, E, B, BlockCount, Idx); 1910b57cec5SDimitry Andric } 1920b57cec5SDimitry Andric 1935ffd83dbSDimitry Andric const ParamVarRegion 1945ffd83dbSDimitry Andric *CallEvent::getParameterLocation(unsigned Index, unsigned BlockCount) const { 195a7dea167SDimitry Andric const StackFrameContext *SFC = getCalleeStackFrame(BlockCount); 1960b57cec5SDimitry Andric // We cannot construct a VarRegion without a stack frame. 1970b57cec5SDimitry Andric if (!SFC) 1980b57cec5SDimitry Andric return nullptr; 1990b57cec5SDimitry Andric 2005ffd83dbSDimitry Andric const ParamVarRegion *PVR = 2015ffd83dbSDimitry Andric State->getStateManager().getRegionManager().getParamVarRegion( 2025ffd83dbSDimitry Andric getOriginExpr(), Index, SFC); 2035ffd83dbSDimitry Andric return PVR; 2040b57cec5SDimitry Andric } 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric /// Returns true if a type is a pointer-to-const or reference-to-const 2070b57cec5SDimitry Andric /// with no further indirection. 2080b57cec5SDimitry Andric static bool isPointerToConst(QualType Ty) { 2090b57cec5SDimitry Andric QualType PointeeTy = Ty->getPointeeType(); 2100b57cec5SDimitry Andric if (PointeeTy == QualType()) 2110b57cec5SDimitry Andric return false; 2120b57cec5SDimitry Andric if (!PointeeTy.isConstQualified()) 2130b57cec5SDimitry Andric return false; 2140b57cec5SDimitry Andric if (PointeeTy->isAnyPointerType()) 2150b57cec5SDimitry Andric return false; 2160b57cec5SDimitry Andric return true; 2170b57cec5SDimitry Andric } 2180b57cec5SDimitry Andric 2190b57cec5SDimitry Andric // Try to retrieve the function declaration and find the function parameter 2200b57cec5SDimitry Andric // types which are pointers/references to a non-pointer const. 2210b57cec5SDimitry Andric // We will not invalidate the corresponding argument regions. 2220b57cec5SDimitry Andric static void findPtrToConstParams(llvm::SmallSet<unsigned, 4> &PreserveArgs, 2230b57cec5SDimitry Andric const CallEvent &Call) { 2240b57cec5SDimitry Andric unsigned Idx = 0; 2250b57cec5SDimitry Andric for (CallEvent::param_type_iterator I = Call.param_type_begin(), 2260b57cec5SDimitry Andric E = Call.param_type_end(); 2270b57cec5SDimitry Andric I != E; ++I, ++Idx) { 2280b57cec5SDimitry Andric if (isPointerToConst(*I)) 2290b57cec5SDimitry Andric PreserveArgs.insert(Idx); 2300b57cec5SDimitry Andric } 2310b57cec5SDimitry Andric } 2320b57cec5SDimitry Andric 2330b57cec5SDimitry Andric ProgramStateRef CallEvent::invalidateRegions(unsigned BlockCount, 2340b57cec5SDimitry Andric ProgramStateRef Orig) const { 2350b57cec5SDimitry Andric ProgramStateRef Result = (Orig ? Orig : getState()); 2360b57cec5SDimitry Andric 2370b57cec5SDimitry Andric // Don't invalidate anything if the callee is marked pure/const. 2380b57cec5SDimitry Andric if (const Decl *callee = getDecl()) 2390b57cec5SDimitry Andric if (callee->hasAttr<PureAttr>() || callee->hasAttr<ConstAttr>()) 2400b57cec5SDimitry Andric return Result; 2410b57cec5SDimitry Andric 2420b57cec5SDimitry Andric SmallVector<SVal, 8> ValuesToInvalidate; 2430b57cec5SDimitry Andric RegionAndSymbolInvalidationTraits ETraits; 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andric getExtraInvalidatedValues(ValuesToInvalidate, &ETraits); 2460b57cec5SDimitry Andric 2470b57cec5SDimitry Andric // Indexes of arguments whose values will be preserved by the call. 2480b57cec5SDimitry Andric llvm::SmallSet<unsigned, 4> PreserveArgs; 2490b57cec5SDimitry Andric if (!argumentsMayEscape()) 2500b57cec5SDimitry Andric findPtrToConstParams(PreserveArgs, *this); 2510b57cec5SDimitry Andric 2520b57cec5SDimitry Andric for (unsigned Idx = 0, Count = getNumArgs(); Idx != Count; ++Idx) { 2530b57cec5SDimitry Andric // Mark this region for invalidation. We batch invalidate regions 2540b57cec5SDimitry Andric // below for efficiency. 2550b57cec5SDimitry Andric if (PreserveArgs.count(Idx)) 2560b57cec5SDimitry Andric if (const MemRegion *MR = getArgSVal(Idx).getAsRegion()) 2570b57cec5SDimitry Andric ETraits.setTrait(MR->getBaseRegion(), 2580b57cec5SDimitry Andric RegionAndSymbolInvalidationTraits::TK_PreserveContents); 2590b57cec5SDimitry Andric // TODO: Factor this out + handle the lower level const pointers. 2600b57cec5SDimitry Andric 2610b57cec5SDimitry Andric ValuesToInvalidate.push_back(getArgSVal(Idx)); 2620b57cec5SDimitry Andric 2630b57cec5SDimitry Andric // If a function accepts an object by argument (which would of course be a 2640b57cec5SDimitry Andric // temporary that isn't lifetime-extended), invalidate the object itself, 2650b57cec5SDimitry Andric // not only other objects reachable from it. This is necessary because the 2660b57cec5SDimitry Andric // destructor has access to the temporary object after the call. 2670b57cec5SDimitry Andric // TODO: Support placement arguments once we start 2680b57cec5SDimitry Andric // constructing them directly. 2690b57cec5SDimitry Andric // TODO: This is unnecessary when there's no destructor, but that's 2700b57cec5SDimitry Andric // currently hard to figure out. 2710b57cec5SDimitry Andric if (getKind() != CE_CXXAllocator) 2720b57cec5SDimitry Andric if (isArgumentConstructedDirectly(Idx)) 2730b57cec5SDimitry Andric if (auto AdjIdx = getAdjustedParameterIndex(Idx)) 2745ffd83dbSDimitry Andric if (const TypedValueRegion *TVR = 2755ffd83dbSDimitry Andric getParameterLocation(*AdjIdx, BlockCount)) 2765ffd83dbSDimitry Andric ValuesToInvalidate.push_back(loc::MemRegionVal(TVR)); 2770b57cec5SDimitry Andric } 2780b57cec5SDimitry Andric 2790b57cec5SDimitry Andric // Invalidate designated regions using the batch invalidation API. 2800b57cec5SDimitry Andric // NOTE: Even if RegionsToInvalidate is empty, we may still invalidate 2810b57cec5SDimitry Andric // global variables. 2820b57cec5SDimitry Andric return Result->invalidateRegions(ValuesToInvalidate, getOriginExpr(), 2830b57cec5SDimitry Andric BlockCount, getLocationContext(), 2840b57cec5SDimitry Andric /*CausedByPointerEscape*/ true, 2850b57cec5SDimitry Andric /*Symbols=*/nullptr, this, &ETraits); 2860b57cec5SDimitry Andric } 2870b57cec5SDimitry Andric 2880b57cec5SDimitry Andric ProgramPoint CallEvent::getProgramPoint(bool IsPreVisit, 2890b57cec5SDimitry Andric const ProgramPointTag *Tag) const { 29006c3fb27SDimitry Andric 2910b57cec5SDimitry Andric if (const Expr *E = getOriginExpr()) { 2920b57cec5SDimitry Andric if (IsPreVisit) 2930b57cec5SDimitry Andric return PreStmt(E, getLocationContext(), Tag); 2940b57cec5SDimitry Andric return PostStmt(E, getLocationContext(), Tag); 2950b57cec5SDimitry Andric } 2960b57cec5SDimitry Andric 2970b57cec5SDimitry Andric const Decl *D = getDecl(); 2980b57cec5SDimitry Andric assert(D && "Cannot get a program point without a statement or decl"); 29906c3fb27SDimitry Andric assert(ElemRef.getParent() && 30006c3fb27SDimitry Andric "Cannot get a program point without a CFGElementRef"); 3010b57cec5SDimitry Andric 3020b57cec5SDimitry Andric SourceLocation Loc = getSourceRange().getBegin(); 3030b57cec5SDimitry Andric if (IsPreVisit) 30406c3fb27SDimitry Andric return PreImplicitCall(D, Loc, getLocationContext(), ElemRef, Tag); 30506c3fb27SDimitry Andric return PostImplicitCall(D, Loc, getLocationContext(), ElemRef, Tag); 3060b57cec5SDimitry Andric } 3070b57cec5SDimitry Andric 3080b57cec5SDimitry Andric SVal CallEvent::getArgSVal(unsigned Index) const { 3090b57cec5SDimitry Andric const Expr *ArgE = getArgExpr(Index); 3100b57cec5SDimitry Andric if (!ArgE) 3110b57cec5SDimitry Andric return UnknownVal(); 3120b57cec5SDimitry Andric return getSVal(ArgE); 3130b57cec5SDimitry Andric } 3140b57cec5SDimitry Andric 3150b57cec5SDimitry Andric SourceRange CallEvent::getArgSourceRange(unsigned Index) const { 3160b57cec5SDimitry Andric const Expr *ArgE = getArgExpr(Index); 3170b57cec5SDimitry Andric if (!ArgE) 3180b57cec5SDimitry Andric return {}; 3190b57cec5SDimitry Andric return ArgE->getSourceRange(); 3200b57cec5SDimitry Andric } 3210b57cec5SDimitry Andric 3220b57cec5SDimitry Andric SVal CallEvent::getReturnValue() const { 3230b57cec5SDimitry Andric const Expr *E = getOriginExpr(); 3240b57cec5SDimitry Andric if (!E) 3250b57cec5SDimitry Andric return UndefinedVal(); 3260b57cec5SDimitry Andric return getSVal(E); 3270b57cec5SDimitry Andric } 3280b57cec5SDimitry Andric 3290b57cec5SDimitry Andric LLVM_DUMP_METHOD void CallEvent::dump() const { dump(llvm::errs()); } 3300b57cec5SDimitry Andric 3310b57cec5SDimitry Andric void CallEvent::dump(raw_ostream &Out) const { 3320b57cec5SDimitry Andric ASTContext &Ctx = getState()->getStateManager().getContext(); 3330b57cec5SDimitry Andric if (const Expr *E = getOriginExpr()) { 3340b57cec5SDimitry Andric E->printPretty(Out, nullptr, Ctx.getPrintingPolicy()); 3350b57cec5SDimitry Andric return; 3360b57cec5SDimitry Andric } 3370b57cec5SDimitry Andric 3380b57cec5SDimitry Andric if (const Decl *D = getDecl()) { 3390b57cec5SDimitry Andric Out << "Call to "; 3400b57cec5SDimitry Andric D->print(Out, Ctx.getPrintingPolicy()); 3410b57cec5SDimitry Andric return; 3420b57cec5SDimitry Andric } 3430b57cec5SDimitry Andric 3445ffd83dbSDimitry Andric Out << "Unknown call (type " << getKindAsString() << ")"; 3450b57cec5SDimitry Andric } 3460b57cec5SDimitry Andric 3470b57cec5SDimitry Andric bool CallEvent::isCallStmt(const Stmt *S) { 348349cc55cSDimitry Andric return isa<CallExpr, ObjCMessageExpr, CXXConstructExpr, CXXNewExpr>(S); 3490b57cec5SDimitry Andric } 3500b57cec5SDimitry Andric 3510b57cec5SDimitry Andric QualType CallEvent::getDeclaredResultType(const Decl *D) { 3520b57cec5SDimitry Andric assert(D); 3530b57cec5SDimitry Andric if (const auto *FD = dyn_cast<FunctionDecl>(D)) 3540b57cec5SDimitry Andric return FD->getReturnType(); 3550b57cec5SDimitry Andric if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) 3560b57cec5SDimitry Andric return MD->getReturnType(); 3570b57cec5SDimitry Andric if (const auto *BD = dyn_cast<BlockDecl>(D)) { 3580b57cec5SDimitry Andric // Blocks are difficult because the return type may not be stored in the 3590b57cec5SDimitry Andric // BlockDecl itself. The AST should probably be enhanced, but for now we 3600b57cec5SDimitry Andric // just do what we can. 3610b57cec5SDimitry Andric // If the block is declared without an explicit argument list, the 3620b57cec5SDimitry Andric // signature-as-written just includes the return type, not the entire 3630b57cec5SDimitry Andric // function type. 3640b57cec5SDimitry Andric // FIXME: All blocks should have signatures-as-written, even if the return 3650b57cec5SDimitry Andric // type is inferred. (That's signified with a dependent result type.) 3660b57cec5SDimitry Andric if (const TypeSourceInfo *TSI = BD->getSignatureAsWritten()) { 3670b57cec5SDimitry Andric QualType Ty = TSI->getType(); 3680b57cec5SDimitry Andric if (const FunctionType *FT = Ty->getAs<FunctionType>()) 3690b57cec5SDimitry Andric Ty = FT->getReturnType(); 3700b57cec5SDimitry Andric if (!Ty->isDependentType()) 3710b57cec5SDimitry Andric return Ty; 3720b57cec5SDimitry Andric } 3730b57cec5SDimitry Andric 3740b57cec5SDimitry Andric return {}; 3750b57cec5SDimitry Andric } 3760b57cec5SDimitry Andric 3770b57cec5SDimitry Andric llvm_unreachable("unknown callable kind"); 3780b57cec5SDimitry Andric } 3790b57cec5SDimitry Andric 3800b57cec5SDimitry Andric bool CallEvent::isVariadic(const Decl *D) { 3810b57cec5SDimitry Andric assert(D); 3820b57cec5SDimitry Andric 3830b57cec5SDimitry Andric if (const auto *FD = dyn_cast<FunctionDecl>(D)) 3840b57cec5SDimitry Andric return FD->isVariadic(); 3850b57cec5SDimitry Andric if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) 3860b57cec5SDimitry Andric return MD->isVariadic(); 3870b57cec5SDimitry Andric if (const auto *BD = dyn_cast<BlockDecl>(D)) 3880b57cec5SDimitry Andric return BD->isVariadic(); 3890b57cec5SDimitry Andric 3900b57cec5SDimitry Andric llvm_unreachable("unknown callable kind"); 3910b57cec5SDimitry Andric } 3920b57cec5SDimitry Andric 393fe6060f1SDimitry Andric static bool isTransparentUnion(QualType T) { 394fe6060f1SDimitry Andric const RecordType *UT = T->getAsUnionType(); 395fe6060f1SDimitry Andric return UT && UT->getDecl()->hasAttr<TransparentUnionAttr>(); 396fe6060f1SDimitry Andric } 397fe6060f1SDimitry Andric 398fe6060f1SDimitry Andric // In some cases, symbolic cases should be transformed before we associate 399fe6060f1SDimitry Andric // them with parameters. This function incapsulates such cases. 400fe6060f1SDimitry Andric static SVal processArgument(SVal Value, const Expr *ArgumentExpr, 401fe6060f1SDimitry Andric const ParmVarDecl *Parameter, SValBuilder &SVB) { 402fe6060f1SDimitry Andric QualType ParamType = Parameter->getType(); 403fe6060f1SDimitry Andric QualType ArgumentType = ArgumentExpr->getType(); 404fe6060f1SDimitry Andric 405fe6060f1SDimitry Andric // Transparent unions allow users to easily convert values of union field 406fe6060f1SDimitry Andric // types into union-typed objects. 407fe6060f1SDimitry Andric // 408fe6060f1SDimitry Andric // Also, more importantly, they allow users to define functions with different 409fe6060f1SDimitry Andric // different parameter types, substituting types matching transparent union 410fe6060f1SDimitry Andric // field types with the union type itself. 411fe6060f1SDimitry Andric // 412fe6060f1SDimitry Andric // Here, we check specifically for latter cases and prevent binding 413fe6060f1SDimitry Andric // field-typed values to union-typed regions. 414fe6060f1SDimitry Andric if (isTransparentUnion(ParamType) && 415fe6060f1SDimitry Andric // Let's check that we indeed trying to bind different types. 416fe6060f1SDimitry Andric !isTransparentUnion(ArgumentType)) { 417fe6060f1SDimitry Andric BasicValueFactory &BVF = SVB.getBasicValueFactory(); 418fe6060f1SDimitry Andric 419fe6060f1SDimitry Andric llvm::ImmutableList<SVal> CompoundSVals = BVF.getEmptySValList(); 420fe6060f1SDimitry Andric CompoundSVals = BVF.prependSVal(Value, CompoundSVals); 421fe6060f1SDimitry Andric 422fe6060f1SDimitry Andric // Wrap it with compound value. 423fe6060f1SDimitry Andric return SVB.makeCompoundVal(ParamType, CompoundSVals); 424fe6060f1SDimitry Andric } 425fe6060f1SDimitry Andric 426fe6060f1SDimitry Andric return Value; 427fe6060f1SDimitry Andric } 428fe6060f1SDimitry Andric 429bdd1243dSDimitry Andric /// Cast the argument value to the type of the parameter at the function 430bdd1243dSDimitry Andric /// declaration. 431bdd1243dSDimitry Andric /// Returns the argument value if it didn't need a cast. 432bdd1243dSDimitry Andric /// Or returns the cast argument if it needed a cast. 433bdd1243dSDimitry Andric /// Or returns 'Unknown' if it would need a cast but the callsite and the 434bdd1243dSDimitry Andric /// runtime definition don't match in terms of argument and parameter count. 435bdd1243dSDimitry Andric static SVal castArgToParamTypeIfNeeded(const CallEvent &Call, unsigned ArgIdx, 436bdd1243dSDimitry Andric SVal ArgVal, SValBuilder &SVB) { 437bdd1243dSDimitry Andric const FunctionDecl *RTDecl = 438bdd1243dSDimitry Andric Call.getRuntimeDefinition().getDecl()->getAsFunction(); 439bdd1243dSDimitry Andric const auto *CallExprDecl = dyn_cast_or_null<FunctionDecl>(Call.getDecl()); 440bdd1243dSDimitry Andric 441bdd1243dSDimitry Andric if (!RTDecl || !CallExprDecl) 442bdd1243dSDimitry Andric return ArgVal; 443bdd1243dSDimitry Andric 444bdd1243dSDimitry Andric // The function decl of the Call (in the AST) will not have any parameter 445bdd1243dSDimitry Andric // declarations, if it was 'only' declared without a prototype. However, the 446bdd1243dSDimitry Andric // engine will find the appropriate runtime definition - basically a 447bdd1243dSDimitry Andric // redeclaration, which has a function body (and a function prototype). 448bdd1243dSDimitry Andric if (CallExprDecl->hasPrototype() || !RTDecl->hasPrototype()) 449bdd1243dSDimitry Andric return ArgVal; 450bdd1243dSDimitry Andric 451bdd1243dSDimitry Andric // Only do this cast if the number arguments at the callsite matches with 452bdd1243dSDimitry Andric // the parameters at the runtime definition. 453bdd1243dSDimitry Andric if (Call.getNumArgs() != RTDecl->getNumParams()) 454bdd1243dSDimitry Andric return UnknownVal(); 455bdd1243dSDimitry Andric 456bdd1243dSDimitry Andric const Expr *ArgExpr = Call.getArgExpr(ArgIdx); 457bdd1243dSDimitry Andric const ParmVarDecl *Param = RTDecl->getParamDecl(ArgIdx); 458bdd1243dSDimitry Andric return SVB.evalCast(ArgVal, Param->getType(), ArgExpr->getType()); 459bdd1243dSDimitry Andric } 460bdd1243dSDimitry Andric 4610b57cec5SDimitry Andric static void addParameterValuesToBindings(const StackFrameContext *CalleeCtx, 4620b57cec5SDimitry Andric CallEvent::BindingsTy &Bindings, 4630b57cec5SDimitry Andric SValBuilder &SVB, 4640b57cec5SDimitry Andric const CallEvent &Call, 4650b57cec5SDimitry Andric ArrayRef<ParmVarDecl*> parameters) { 4660b57cec5SDimitry Andric MemRegionManager &MRMgr = SVB.getRegionManager(); 4670b57cec5SDimitry Andric 4680b57cec5SDimitry Andric // If the function has fewer parameters than the call has arguments, we simply 4690b57cec5SDimitry Andric // do not bind any values to them. 4700b57cec5SDimitry Andric unsigned NumArgs = Call.getNumArgs(); 4710b57cec5SDimitry Andric unsigned Idx = 0; 4720b57cec5SDimitry Andric ArrayRef<ParmVarDecl*>::iterator I = parameters.begin(), E = parameters.end(); 4730b57cec5SDimitry Andric for (; I != E && Idx < NumArgs; ++I, ++Idx) { 4745ffd83dbSDimitry Andric assert(*I && "Formal parameter has no decl?"); 4750b57cec5SDimitry Andric 4760b57cec5SDimitry Andric // TODO: Support allocator calls. 4770b57cec5SDimitry Andric if (Call.getKind() != CE_CXXAllocator) 478480093f4SDimitry Andric if (Call.isArgumentConstructedDirectly(Call.getASTArgumentIndex(Idx))) 4790b57cec5SDimitry Andric continue; 4800b57cec5SDimitry Andric 4810b57cec5SDimitry Andric // TODO: Allocators should receive the correct size and possibly alignment, 4820b57cec5SDimitry Andric // determined in compile-time but not represented as arg-expressions, 4830b57cec5SDimitry Andric // which makes getArgSVal() fail and return UnknownVal. 4840b57cec5SDimitry Andric SVal ArgVal = Call.getArgSVal(Idx); 485fe6060f1SDimitry Andric const Expr *ArgExpr = Call.getArgExpr(Idx); 486bdd1243dSDimitry Andric 487bdd1243dSDimitry Andric if (ArgVal.isUnknown()) 488bdd1243dSDimitry Andric continue; 489bdd1243dSDimitry Andric 490bdd1243dSDimitry Andric // Cast the argument value to match the type of the parameter in some 491bdd1243dSDimitry Andric // edge-cases. 492bdd1243dSDimitry Andric ArgVal = castArgToParamTypeIfNeeded(Call, Idx, ArgVal, SVB); 493bdd1243dSDimitry Andric 4945ffd83dbSDimitry Andric Loc ParamLoc = SVB.makeLoc( 4955ffd83dbSDimitry Andric MRMgr.getParamVarRegion(Call.getOriginExpr(), Idx, CalleeCtx)); 496fe6060f1SDimitry Andric Bindings.push_back( 497fe6060f1SDimitry Andric std::make_pair(ParamLoc, processArgument(ArgVal, ArgExpr, *I, SVB))); 4980b57cec5SDimitry Andric } 4990b57cec5SDimitry Andric 5000b57cec5SDimitry Andric // FIXME: Variadic arguments are not handled at all right now. 5010b57cec5SDimitry Andric } 5020b57cec5SDimitry Andric 5035ffd83dbSDimitry Andric const ConstructionContext *CallEvent::getConstructionContext() const { 5045ffd83dbSDimitry Andric const StackFrameContext *StackFrame = getCalleeStackFrame(0); 5055ffd83dbSDimitry Andric if (!StackFrame) 5065ffd83dbSDimitry Andric return nullptr; 5075ffd83dbSDimitry Andric 5085ffd83dbSDimitry Andric const CFGElement Element = StackFrame->getCallSiteCFGElement(); 5095ffd83dbSDimitry Andric if (const auto Ctor = Element.getAs<CFGConstructor>()) { 5105ffd83dbSDimitry Andric return Ctor->getConstructionContext(); 5115ffd83dbSDimitry Andric } 5125ffd83dbSDimitry Andric 5135ffd83dbSDimitry Andric if (const auto RecCall = Element.getAs<CFGCXXRecordTypedCall>()) { 5145ffd83dbSDimitry Andric return RecCall->getConstructionContext(); 5155ffd83dbSDimitry Andric } 5165ffd83dbSDimitry Andric 5175ffd83dbSDimitry Andric return nullptr; 5185ffd83dbSDimitry Andric } 5195ffd83dbSDimitry Andric 5205f757f3fSDimitry Andric const CallEventRef<> CallEvent::getCaller() const { 5215f757f3fSDimitry Andric const auto *CallLocationContext = this->getLocationContext(); 5225f757f3fSDimitry Andric if (!CallLocationContext || CallLocationContext->inTopFrame()) 5235f757f3fSDimitry Andric return nullptr; 5245f757f3fSDimitry Andric 5255f757f3fSDimitry Andric const auto *CallStackFrameContext = CallLocationContext->getStackFrame(); 5265f757f3fSDimitry Andric if (!CallStackFrameContext) 5275f757f3fSDimitry Andric return nullptr; 5285f757f3fSDimitry Andric 5295f757f3fSDimitry Andric CallEventManager &CEMgr = State->getStateManager().getCallEventManager(); 5305f757f3fSDimitry Andric return CEMgr.getCaller(CallStackFrameContext, State); 5315f757f3fSDimitry Andric } 5325f757f3fSDimitry Andric 5335f757f3fSDimitry Andric bool CallEvent::isCalledFromSystemHeader() const { 5345f757f3fSDimitry Andric if (const CallEventRef<> Caller = getCaller()) 5355f757f3fSDimitry Andric return Caller->isInSystemHeader(); 5365f757f3fSDimitry Andric 5375f757f3fSDimitry Andric return false; 5385f757f3fSDimitry Andric } 5395f757f3fSDimitry Andric 540bdd1243dSDimitry Andric std::optional<SVal> CallEvent::getReturnValueUnderConstruction() const { 5415ffd83dbSDimitry Andric const auto *CC = getConstructionContext(); 5425ffd83dbSDimitry Andric if (!CC) 543bdd1243dSDimitry Andric return std::nullopt; 5445ffd83dbSDimitry Andric 5455ffd83dbSDimitry Andric EvalCallOptions CallOpts; 5465ffd83dbSDimitry Andric ExprEngine &Engine = getState()->getStateManager().getOwningEngine(); 547bdd1243dSDimitry Andric SVal RetVal = Engine.computeObjectUnderConstruction( 548bdd1243dSDimitry Andric getOriginExpr(), getState(), &Engine.getBuilderContext(), 5495ffd83dbSDimitry Andric getLocationContext(), CC, CallOpts); 5505ffd83dbSDimitry Andric return RetVal; 5515ffd83dbSDimitry Andric } 5525ffd83dbSDimitry Andric 5530b57cec5SDimitry Andric ArrayRef<ParmVarDecl*> AnyFunctionCall::parameters() const { 5540b57cec5SDimitry Andric const FunctionDecl *D = getDecl(); 5550b57cec5SDimitry Andric if (!D) 556bdd1243dSDimitry Andric return std::nullopt; 5570b57cec5SDimitry Andric return D->parameters(); 5580b57cec5SDimitry Andric } 5590b57cec5SDimitry Andric 5600b57cec5SDimitry Andric RuntimeDefinition AnyFunctionCall::getRuntimeDefinition() const { 5610b57cec5SDimitry Andric const FunctionDecl *FD = getDecl(); 5620b57cec5SDimitry Andric if (!FD) 5630b57cec5SDimitry Andric return {}; 5640b57cec5SDimitry Andric 5650b57cec5SDimitry Andric // Note that the AnalysisDeclContext will have the FunctionDecl with 5660b57cec5SDimitry Andric // the definition (if one exists). 5670b57cec5SDimitry Andric AnalysisDeclContext *AD = 5680b57cec5SDimitry Andric getLocationContext()->getAnalysisDeclContext()-> 5690b57cec5SDimitry Andric getManager()->getContext(FD); 5700b57cec5SDimitry Andric bool IsAutosynthesized; 5710b57cec5SDimitry Andric Stmt* Body = AD->getBody(IsAutosynthesized); 5720b57cec5SDimitry Andric LLVM_DEBUG({ 5730b57cec5SDimitry Andric if (IsAutosynthesized) 5740b57cec5SDimitry Andric llvm::dbgs() << "Using autosynthesized body for " << FD->getName() 5750b57cec5SDimitry Andric << "\n"; 5760b57cec5SDimitry Andric }); 5770b57cec5SDimitry Andric 5785ffd83dbSDimitry Andric ExprEngine &Engine = getState()->getStateManager().getOwningEngine(); 57981ad6265SDimitry Andric cross_tu::CrossTranslationUnitContext &CTUCtx = 58081ad6265SDimitry Andric *Engine.getCrossTranslationUnitContext(); 58181ad6265SDimitry Andric 5820b57cec5SDimitry Andric AnalyzerOptions &Opts = Engine.getAnalysisManager().options; 5830b57cec5SDimitry Andric 58481ad6265SDimitry Andric if (Body) { 58581ad6265SDimitry Andric const Decl* Decl = AD->getDecl(); 58681ad6265SDimitry Andric if (Opts.IsNaiveCTUEnabled && CTUCtx.isImportedAsNew(Decl)) { 58781ad6265SDimitry Andric // A newly created definition, but we had error(s) during the import. 58881ad6265SDimitry Andric if (CTUCtx.hasError(Decl)) 58981ad6265SDimitry Andric return {}; 59081ad6265SDimitry Andric return RuntimeDefinition(Decl, /*Foreign=*/true); 59181ad6265SDimitry Andric } 59281ad6265SDimitry Andric return RuntimeDefinition(Decl, /*Foreign=*/false); 59381ad6265SDimitry Andric } 59481ad6265SDimitry Andric 5950b57cec5SDimitry Andric // Try to get CTU definition only if CTUDir is provided. 5960b57cec5SDimitry Andric if (!Opts.IsNaiveCTUEnabled) 5970b57cec5SDimitry Andric return {}; 5980b57cec5SDimitry Andric 5990b57cec5SDimitry Andric llvm::Expected<const FunctionDecl *> CTUDeclOrError = 6000b57cec5SDimitry Andric CTUCtx.getCrossTUDefinition(FD, Opts.CTUDir, Opts.CTUIndexName, 6010b57cec5SDimitry Andric Opts.DisplayCTUProgress); 6020b57cec5SDimitry Andric 6030b57cec5SDimitry Andric if (!CTUDeclOrError) { 6040b57cec5SDimitry Andric handleAllErrors(CTUDeclOrError.takeError(), 6050b57cec5SDimitry Andric [&](const cross_tu::IndexError &IE) { 6060b57cec5SDimitry Andric CTUCtx.emitCrossTUDiagnostics(IE); 6070b57cec5SDimitry Andric }); 6080b57cec5SDimitry Andric return {}; 6090b57cec5SDimitry Andric } 6100b57cec5SDimitry Andric 61181ad6265SDimitry Andric return RuntimeDefinition(*CTUDeclOrError, /*Foreign=*/true); 6120b57cec5SDimitry Andric } 6130b57cec5SDimitry Andric 6140b57cec5SDimitry Andric void AnyFunctionCall::getInitialStackFrameContents( 6150b57cec5SDimitry Andric const StackFrameContext *CalleeCtx, 6160b57cec5SDimitry Andric BindingsTy &Bindings) const { 6170b57cec5SDimitry Andric const auto *D = cast<FunctionDecl>(CalleeCtx->getDecl()); 6180b57cec5SDimitry Andric SValBuilder &SVB = getState()->getStateManager().getSValBuilder(); 6190b57cec5SDimitry Andric addParameterValuesToBindings(CalleeCtx, Bindings, SVB, *this, 6200b57cec5SDimitry Andric D->parameters()); 6210b57cec5SDimitry Andric } 6220b57cec5SDimitry Andric 6230b57cec5SDimitry Andric bool AnyFunctionCall::argumentsMayEscape() const { 6240b57cec5SDimitry Andric if (CallEvent::argumentsMayEscape() || hasVoidPointerToNonConstArg()) 6250b57cec5SDimitry Andric return true; 6260b57cec5SDimitry Andric 6270b57cec5SDimitry Andric const FunctionDecl *D = getDecl(); 6280b57cec5SDimitry Andric if (!D) 6290b57cec5SDimitry Andric return true; 6300b57cec5SDimitry Andric 6310b57cec5SDimitry Andric const IdentifierInfo *II = D->getIdentifier(); 6320b57cec5SDimitry Andric if (!II) 6330b57cec5SDimitry Andric return false; 6340b57cec5SDimitry Andric 6350b57cec5SDimitry Andric // This set of "escaping" APIs is 6360b57cec5SDimitry Andric 6370b57cec5SDimitry Andric // - 'int pthread_setspecific(ptheread_key k, const void *)' stores a 6380b57cec5SDimitry Andric // value into thread local storage. The value can later be retrieved with 6390b57cec5SDimitry Andric // 'void *ptheread_getspecific(pthread_key)'. So even thought the 6400b57cec5SDimitry Andric // parameter is 'const void *', the region escapes through the call. 6410b57cec5SDimitry Andric if (II->isStr("pthread_setspecific")) 6420b57cec5SDimitry Andric return true; 6430b57cec5SDimitry Andric 6440b57cec5SDimitry Andric // - xpc_connection_set_context stores a value which can be retrieved later 6450b57cec5SDimitry Andric // with xpc_connection_get_context. 6460b57cec5SDimitry Andric if (II->isStr("xpc_connection_set_context")) 6470b57cec5SDimitry Andric return true; 6480b57cec5SDimitry Andric 6490b57cec5SDimitry Andric // - funopen - sets a buffer for future IO calls. 6500b57cec5SDimitry Andric if (II->isStr("funopen")) 6510b57cec5SDimitry Andric return true; 6520b57cec5SDimitry Andric 6530b57cec5SDimitry Andric // - __cxa_demangle - can reallocate memory and can return the pointer to 6540b57cec5SDimitry Andric // the input buffer. 6550b57cec5SDimitry Andric if (II->isStr("__cxa_demangle")) 6560b57cec5SDimitry Andric return true; 6570b57cec5SDimitry Andric 6580b57cec5SDimitry Andric StringRef FName = II->getName(); 6590b57cec5SDimitry Andric 6600b57cec5SDimitry Andric // - CoreFoundation functions that end with "NoCopy" can free a passed-in 6610b57cec5SDimitry Andric // buffer even if it is const. 6625f757f3fSDimitry Andric if (FName.ends_with("NoCopy")) 6630b57cec5SDimitry Andric return true; 6640b57cec5SDimitry Andric 6650b57cec5SDimitry Andric // - NSXXInsertXX, for example NSMapInsertIfAbsent, since they can 6660b57cec5SDimitry Andric // be deallocated by NSMapRemove. 6675f757f3fSDimitry Andric if (FName.starts_with("NS") && FName.contains("Insert")) 6680b57cec5SDimitry Andric return true; 6690b57cec5SDimitry Andric 6700b57cec5SDimitry Andric // - Many CF containers allow objects to escape through custom 6710b57cec5SDimitry Andric // allocators/deallocators upon container construction. (PR12101) 6725f757f3fSDimitry Andric if (FName.starts_with("CF") || FName.starts_with("CG")) { 6730b57cec5SDimitry Andric return StrInStrNoCase(FName, "InsertValue") != StringRef::npos || 6740b57cec5SDimitry Andric StrInStrNoCase(FName, "AddValue") != StringRef::npos || 6750b57cec5SDimitry Andric StrInStrNoCase(FName, "SetValue") != StringRef::npos || 6760b57cec5SDimitry Andric StrInStrNoCase(FName, "WithData") != StringRef::npos || 6770b57cec5SDimitry Andric StrInStrNoCase(FName, "AppendValue") != StringRef::npos || 6780b57cec5SDimitry Andric StrInStrNoCase(FName, "SetAttribute") != StringRef::npos; 6790b57cec5SDimitry Andric } 6800b57cec5SDimitry Andric 6810b57cec5SDimitry Andric return false; 6820b57cec5SDimitry Andric } 6830b57cec5SDimitry Andric 6840b57cec5SDimitry Andric const FunctionDecl *SimpleFunctionCall::getDecl() const { 6850b57cec5SDimitry Andric const FunctionDecl *D = getOriginExpr()->getDirectCallee(); 6860b57cec5SDimitry Andric if (D) 6870b57cec5SDimitry Andric return D; 6880b57cec5SDimitry Andric 6890b57cec5SDimitry Andric return getSVal(getOriginExpr()->getCallee()).getAsFunctionDecl(); 6900b57cec5SDimitry Andric } 6910b57cec5SDimitry Andric 6920b57cec5SDimitry Andric const FunctionDecl *CXXInstanceCall::getDecl() const { 6930b57cec5SDimitry Andric const auto *CE = cast_or_null<CallExpr>(getOriginExpr()); 6940b57cec5SDimitry Andric if (!CE) 6950b57cec5SDimitry Andric return AnyFunctionCall::getDecl(); 6960b57cec5SDimitry Andric 6970b57cec5SDimitry Andric const FunctionDecl *D = CE->getDirectCallee(); 6980b57cec5SDimitry Andric if (D) 6990b57cec5SDimitry Andric return D; 7000b57cec5SDimitry Andric 7010b57cec5SDimitry Andric return getSVal(CE->getCallee()).getAsFunctionDecl(); 7020b57cec5SDimitry Andric } 7030b57cec5SDimitry Andric 7040b57cec5SDimitry Andric void CXXInstanceCall::getExtraInvalidatedValues( 7050b57cec5SDimitry Andric ValueList &Values, RegionAndSymbolInvalidationTraits *ETraits) const { 7060b57cec5SDimitry Andric SVal ThisVal = getCXXThisVal(); 7070b57cec5SDimitry Andric Values.push_back(ThisVal); 7080b57cec5SDimitry Andric 7090b57cec5SDimitry Andric // Don't invalidate if the method is const and there are no mutable fields. 7100b57cec5SDimitry Andric if (const auto *D = cast_or_null<CXXMethodDecl>(getDecl())) { 7110b57cec5SDimitry Andric if (!D->isConst()) 7120b57cec5SDimitry Andric return; 7130b57cec5SDimitry Andric // Get the record decl for the class of 'This'. D->getParent() may return a 7140b57cec5SDimitry Andric // base class decl, rather than the class of the instance which needs to be 7150b57cec5SDimitry Andric // checked for mutable fields. 7160b57cec5SDimitry Andric // TODO: We might as well look at the dynamic type of the object. 717e8d8bef9SDimitry Andric const Expr *Ex = getCXXThisExpr()->IgnoreParenBaseCasts(); 7180b57cec5SDimitry Andric QualType T = Ex->getType(); 7190b57cec5SDimitry Andric if (T->isPointerType()) // Arrow or implicit-this syntax? 7200b57cec5SDimitry Andric T = T->getPointeeType(); 7210b57cec5SDimitry Andric const CXXRecordDecl *ParentRecord = T->getAsCXXRecordDecl(); 7220b57cec5SDimitry Andric assert(ParentRecord); 7230b57cec5SDimitry Andric if (ParentRecord->hasMutableFields()) 7240b57cec5SDimitry Andric return; 7250b57cec5SDimitry Andric // Preserve CXXThis. 7260b57cec5SDimitry Andric const MemRegion *ThisRegion = ThisVal.getAsRegion(); 7270b57cec5SDimitry Andric if (!ThisRegion) 7280b57cec5SDimitry Andric return; 7290b57cec5SDimitry Andric 7300b57cec5SDimitry Andric ETraits->setTrait(ThisRegion->getBaseRegion(), 7310b57cec5SDimitry Andric RegionAndSymbolInvalidationTraits::TK_PreserveContents); 7320b57cec5SDimitry Andric } 7330b57cec5SDimitry Andric } 7340b57cec5SDimitry Andric 7350b57cec5SDimitry Andric SVal CXXInstanceCall::getCXXThisVal() const { 7360b57cec5SDimitry Andric const Expr *Base = getCXXThisExpr(); 7370b57cec5SDimitry Andric // FIXME: This doesn't handle an overloaded ->* operator. 7385f757f3fSDimitry Andric SVal ThisVal = Base ? getSVal(Base) : UnknownVal(); 7390b57cec5SDimitry Andric 7405f757f3fSDimitry Andric if (isa<NonLoc>(ThisVal)) { 7415f757f3fSDimitry Andric SValBuilder &SVB = getState()->getStateManager().getSValBuilder(); 7425f757f3fSDimitry Andric QualType OriginalTy = ThisVal.getType(SVB.getContext()); 7435f757f3fSDimitry Andric return SVB.evalCast(ThisVal, Base->getType(), OriginalTy); 7445f757f3fSDimitry Andric } 7455f757f3fSDimitry Andric 74681ad6265SDimitry Andric assert(ThisVal.isUnknownOrUndef() || isa<Loc>(ThisVal)); 7470b57cec5SDimitry Andric return ThisVal; 7480b57cec5SDimitry Andric } 7490b57cec5SDimitry Andric 7500b57cec5SDimitry Andric RuntimeDefinition CXXInstanceCall::getRuntimeDefinition() const { 7510b57cec5SDimitry Andric // Do we have a decl at all? 7520b57cec5SDimitry Andric const Decl *D = getDecl(); 7530b57cec5SDimitry Andric if (!D) 7540b57cec5SDimitry Andric return {}; 7550b57cec5SDimitry Andric 7560b57cec5SDimitry Andric // If the method is non-virtual, we know we can inline it. 7570b57cec5SDimitry Andric const auto *MD = cast<CXXMethodDecl>(D); 7580b57cec5SDimitry Andric if (!MD->isVirtual()) 7590b57cec5SDimitry Andric return AnyFunctionCall::getRuntimeDefinition(); 7600b57cec5SDimitry Andric 7610b57cec5SDimitry Andric // Do we know the implicit 'this' object being called? 7620b57cec5SDimitry Andric const MemRegion *R = getCXXThisVal().getAsRegion(); 7630b57cec5SDimitry Andric if (!R) 7640b57cec5SDimitry Andric return {}; 7650b57cec5SDimitry Andric 7660b57cec5SDimitry Andric // Do we know anything about the type of 'this'? 7670b57cec5SDimitry Andric DynamicTypeInfo DynType = getDynamicTypeInfo(getState(), R); 7680b57cec5SDimitry Andric if (!DynType.isValid()) 7690b57cec5SDimitry Andric return {}; 7700b57cec5SDimitry Andric 7710b57cec5SDimitry Andric // Is the type a C++ class? (This is mostly a defensive check.) 7720b57cec5SDimitry Andric QualType RegionType = DynType.getType()->getPointeeType(); 7730b57cec5SDimitry Andric assert(!RegionType.isNull() && "DynamicTypeInfo should always be a pointer."); 7740b57cec5SDimitry Andric 7750b57cec5SDimitry Andric const CXXRecordDecl *RD = RegionType->getAsCXXRecordDecl(); 7760b57cec5SDimitry Andric if (!RD || !RD->hasDefinition()) 7770b57cec5SDimitry Andric return {}; 7780b57cec5SDimitry Andric 7790b57cec5SDimitry Andric // Find the decl for this method in that class. 7800b57cec5SDimitry Andric const CXXMethodDecl *Result = MD->getCorrespondingMethodInClass(RD, true); 7810b57cec5SDimitry Andric if (!Result) { 7820b57cec5SDimitry Andric // We might not even get the original statically-resolved method due to 7830b57cec5SDimitry Andric // some particularly nasty casting (e.g. casts to sister classes). 7840b57cec5SDimitry Andric // However, we should at least be able to search up and down our own class 7850b57cec5SDimitry Andric // hierarchy, and some real bugs have been caught by checking this. 7860b57cec5SDimitry Andric assert(!RD->isDerivedFrom(MD->getParent()) && "Couldn't find known method"); 7870b57cec5SDimitry Andric 7880b57cec5SDimitry Andric // FIXME: This is checking that our DynamicTypeInfo is at least as good as 7890b57cec5SDimitry Andric // the static type. However, because we currently don't update 7900b57cec5SDimitry Andric // DynamicTypeInfo when an object is cast, we can't actually be sure the 7910b57cec5SDimitry Andric // DynamicTypeInfo is up to date. This assert should be re-enabled once 7925f757f3fSDimitry Andric // this is fixed. 7935f757f3fSDimitry Andric // 7940b57cec5SDimitry Andric // assert(!MD->getParent()->isDerivedFrom(RD) && "Bad DynamicTypeInfo"); 7950b57cec5SDimitry Andric 7960b57cec5SDimitry Andric return {}; 7970b57cec5SDimitry Andric } 7980b57cec5SDimitry Andric 7990b57cec5SDimitry Andric // Does the decl that we found have an implementation? 8000b57cec5SDimitry Andric const FunctionDecl *Definition; 8010b57cec5SDimitry Andric if (!Result->hasBody(Definition)) { 8020b57cec5SDimitry Andric if (!DynType.canBeASubClass()) 8030b57cec5SDimitry Andric return AnyFunctionCall::getRuntimeDefinition(); 8040b57cec5SDimitry Andric return {}; 8050b57cec5SDimitry Andric } 8060b57cec5SDimitry Andric 8070b57cec5SDimitry Andric // We found a definition. If we're not sure that this devirtualization is 8080b57cec5SDimitry Andric // actually what will happen at runtime, make sure to provide the region so 8090b57cec5SDimitry Andric // that ExprEngine can decide what to do with it. 8100b57cec5SDimitry Andric if (DynType.canBeASubClass()) 8110b57cec5SDimitry Andric return RuntimeDefinition(Definition, R->StripCasts()); 8120b57cec5SDimitry Andric return RuntimeDefinition(Definition, /*DispatchRegion=*/nullptr); 8130b57cec5SDimitry Andric } 8140b57cec5SDimitry Andric 8150b57cec5SDimitry Andric void CXXInstanceCall::getInitialStackFrameContents( 8160b57cec5SDimitry Andric const StackFrameContext *CalleeCtx, 8170b57cec5SDimitry Andric BindingsTy &Bindings) const { 8180b57cec5SDimitry Andric AnyFunctionCall::getInitialStackFrameContents(CalleeCtx, Bindings); 8190b57cec5SDimitry Andric 8200b57cec5SDimitry Andric // Handle the binding of 'this' in the new stack frame. 8210b57cec5SDimitry Andric SVal ThisVal = getCXXThisVal(); 8220b57cec5SDimitry Andric if (!ThisVal.isUnknown()) { 8230b57cec5SDimitry Andric ProgramStateManager &StateMgr = getState()->getStateManager(); 8240b57cec5SDimitry Andric SValBuilder &SVB = StateMgr.getSValBuilder(); 8250b57cec5SDimitry Andric 8260b57cec5SDimitry Andric const auto *MD = cast<CXXMethodDecl>(CalleeCtx->getDecl()); 8270b57cec5SDimitry Andric Loc ThisLoc = SVB.getCXXThis(MD, CalleeCtx); 8280b57cec5SDimitry Andric 8290b57cec5SDimitry Andric // If we devirtualized to a different member function, we need to make sure 8300b57cec5SDimitry Andric // we have the proper layering of CXXBaseObjectRegions. 8310b57cec5SDimitry Andric if (MD->getCanonicalDecl() != getDecl()->getCanonicalDecl()) { 8320b57cec5SDimitry Andric ASTContext &Ctx = SVB.getContext(); 8330b57cec5SDimitry Andric const CXXRecordDecl *Class = MD->getParent(); 8340b57cec5SDimitry Andric QualType Ty = Ctx.getPointerType(Ctx.getRecordType(Class)); 8350b57cec5SDimitry Andric 8360b57cec5SDimitry Andric // FIXME: CallEvent maybe shouldn't be directly accessing StoreManager. 837bdd1243dSDimitry Andric std::optional<SVal> V = 8380eae32dcSDimitry Andric StateMgr.getStoreManager().evalBaseToDerived(ThisVal, Ty); 83981ad6265SDimitry Andric if (!V) { 8400b57cec5SDimitry Andric // We might have suffered some sort of placement new earlier, so 8410b57cec5SDimitry Andric // we're constructing in a completely unexpected storage. 8420b57cec5SDimitry Andric // Fall back to a generic pointer cast for this-value. 8430b57cec5SDimitry Andric const CXXMethodDecl *StaticMD = cast<CXXMethodDecl>(getDecl()); 8440b57cec5SDimitry Andric const CXXRecordDecl *StaticClass = StaticMD->getParent(); 8450b57cec5SDimitry Andric QualType StaticTy = Ctx.getPointerType(Ctx.getRecordType(StaticClass)); 8460b57cec5SDimitry Andric ThisVal = SVB.evalCast(ThisVal, Ty, StaticTy); 8470eae32dcSDimitry Andric } else 8480eae32dcSDimitry Andric ThisVal = *V; 8490b57cec5SDimitry Andric } 8500b57cec5SDimitry Andric 8510b57cec5SDimitry Andric if (!ThisVal.isUnknown()) 8520b57cec5SDimitry Andric Bindings.push_back(std::make_pair(ThisLoc, ThisVal)); 8530b57cec5SDimitry Andric } 8540b57cec5SDimitry Andric } 8550b57cec5SDimitry Andric 8560b57cec5SDimitry Andric const Expr *CXXMemberCall::getCXXThisExpr() const { 8570b57cec5SDimitry Andric return getOriginExpr()->getImplicitObjectArgument(); 8580b57cec5SDimitry Andric } 8590b57cec5SDimitry Andric 8600b57cec5SDimitry Andric RuntimeDefinition CXXMemberCall::getRuntimeDefinition() const { 8610b57cec5SDimitry Andric // C++11 [expr.call]p1: ...If the selected function is non-virtual, or if the 8620b57cec5SDimitry Andric // id-expression in the class member access expression is a qualified-id, 8630b57cec5SDimitry Andric // that function is called. Otherwise, its final overrider in the dynamic type 8640b57cec5SDimitry Andric // of the object expression is called. 8650b57cec5SDimitry Andric if (const auto *ME = dyn_cast<MemberExpr>(getOriginExpr()->getCallee())) 8660b57cec5SDimitry Andric if (ME->hasQualifier()) 8670b57cec5SDimitry Andric return AnyFunctionCall::getRuntimeDefinition(); 8680b57cec5SDimitry Andric 8690b57cec5SDimitry Andric return CXXInstanceCall::getRuntimeDefinition(); 8700b57cec5SDimitry Andric } 8710b57cec5SDimitry Andric 8720b57cec5SDimitry Andric const Expr *CXXMemberOperatorCall::getCXXThisExpr() const { 8730b57cec5SDimitry Andric return getOriginExpr()->getArg(0); 8740b57cec5SDimitry Andric } 8750b57cec5SDimitry Andric 8760b57cec5SDimitry Andric const BlockDataRegion *BlockCall::getBlockRegion() const { 8770b57cec5SDimitry Andric const Expr *Callee = getOriginExpr()->getCallee(); 8780b57cec5SDimitry Andric const MemRegion *DataReg = getSVal(Callee).getAsRegion(); 8790b57cec5SDimitry Andric 8800b57cec5SDimitry Andric return dyn_cast_or_null<BlockDataRegion>(DataReg); 8810b57cec5SDimitry Andric } 8820b57cec5SDimitry Andric 8830b57cec5SDimitry Andric ArrayRef<ParmVarDecl*> BlockCall::parameters() const { 8840b57cec5SDimitry Andric const BlockDecl *D = getDecl(); 8850b57cec5SDimitry Andric if (!D) 886bdd1243dSDimitry Andric return std::nullopt; 8870b57cec5SDimitry Andric return D->parameters(); 8880b57cec5SDimitry Andric } 8890b57cec5SDimitry Andric 8900b57cec5SDimitry Andric void BlockCall::getExtraInvalidatedValues(ValueList &Values, 8910b57cec5SDimitry Andric RegionAndSymbolInvalidationTraits *ETraits) const { 8920b57cec5SDimitry Andric // FIXME: This also needs to invalidate captured globals. 8930b57cec5SDimitry Andric if (const MemRegion *R = getBlockRegion()) 8940b57cec5SDimitry Andric Values.push_back(loc::MemRegionVal(R)); 8950b57cec5SDimitry Andric } 8960b57cec5SDimitry Andric 8970b57cec5SDimitry Andric void BlockCall::getInitialStackFrameContents(const StackFrameContext *CalleeCtx, 8980b57cec5SDimitry Andric BindingsTy &Bindings) const { 8990b57cec5SDimitry Andric SValBuilder &SVB = getState()->getStateManager().getSValBuilder(); 9000b57cec5SDimitry Andric ArrayRef<ParmVarDecl*> Params; 9010b57cec5SDimitry Andric if (isConversionFromLambda()) { 9020b57cec5SDimitry Andric auto *LambdaOperatorDecl = cast<CXXMethodDecl>(CalleeCtx->getDecl()); 9030b57cec5SDimitry Andric Params = LambdaOperatorDecl->parameters(); 9040b57cec5SDimitry Andric 9050b57cec5SDimitry Andric // For blocks converted from a C++ lambda, the callee declaration is the 9060b57cec5SDimitry Andric // operator() method on the lambda so we bind "this" to 9070b57cec5SDimitry Andric // the lambda captured by the block. 9080b57cec5SDimitry Andric const VarRegion *CapturedLambdaRegion = getRegionStoringCapturedLambda(); 9090b57cec5SDimitry Andric SVal ThisVal = loc::MemRegionVal(CapturedLambdaRegion); 9100b57cec5SDimitry Andric Loc ThisLoc = SVB.getCXXThis(LambdaOperatorDecl, CalleeCtx); 9110b57cec5SDimitry Andric Bindings.push_back(std::make_pair(ThisLoc, ThisVal)); 9120b57cec5SDimitry Andric } else { 9130b57cec5SDimitry Andric Params = cast<BlockDecl>(CalleeCtx->getDecl())->parameters(); 9140b57cec5SDimitry Andric } 9150b57cec5SDimitry Andric 9160b57cec5SDimitry Andric addParameterValuesToBindings(CalleeCtx, Bindings, SVB, *this, 9170b57cec5SDimitry Andric Params); 9180b57cec5SDimitry Andric } 9190b57cec5SDimitry Andric 9205ffd83dbSDimitry Andric SVal AnyCXXConstructorCall::getCXXThisVal() const { 9210b57cec5SDimitry Andric if (Data) 9220b57cec5SDimitry Andric return loc::MemRegionVal(static_cast<const MemRegion *>(Data)); 9230b57cec5SDimitry Andric return UnknownVal(); 9240b57cec5SDimitry Andric } 9250b57cec5SDimitry Andric 9265ffd83dbSDimitry Andric void AnyCXXConstructorCall::getExtraInvalidatedValues(ValueList &Values, 9270b57cec5SDimitry Andric RegionAndSymbolInvalidationTraits *ETraits) const { 9285ffd83dbSDimitry Andric SVal V = getCXXThisVal(); 9295ffd83dbSDimitry Andric if (SymbolRef Sym = V.getAsSymbol(true)) 9300b57cec5SDimitry Andric ETraits->setTrait(Sym, 9310b57cec5SDimitry Andric RegionAndSymbolInvalidationTraits::TK_SuppressEscape); 9325ffd83dbSDimitry Andric Values.push_back(V); 9330b57cec5SDimitry Andric } 9340b57cec5SDimitry Andric 9355ffd83dbSDimitry Andric void AnyCXXConstructorCall::getInitialStackFrameContents( 9360b57cec5SDimitry Andric const StackFrameContext *CalleeCtx, 9370b57cec5SDimitry Andric BindingsTy &Bindings) const { 9380b57cec5SDimitry Andric AnyFunctionCall::getInitialStackFrameContents(CalleeCtx, Bindings); 9390b57cec5SDimitry Andric 9400b57cec5SDimitry Andric SVal ThisVal = getCXXThisVal(); 9410b57cec5SDimitry Andric if (!ThisVal.isUnknown()) { 9420b57cec5SDimitry Andric SValBuilder &SVB = getState()->getStateManager().getSValBuilder(); 9430b57cec5SDimitry Andric const auto *MD = cast<CXXMethodDecl>(CalleeCtx->getDecl()); 9440b57cec5SDimitry Andric Loc ThisLoc = SVB.getCXXThis(MD, CalleeCtx); 9450b57cec5SDimitry Andric Bindings.push_back(std::make_pair(ThisLoc, ThisVal)); 9460b57cec5SDimitry Andric } 9470b57cec5SDimitry Andric } 9480b57cec5SDimitry Andric 9495ffd83dbSDimitry Andric const StackFrameContext * 9505ffd83dbSDimitry Andric CXXInheritedConstructorCall::getInheritingStackFrame() const { 9515ffd83dbSDimitry Andric const StackFrameContext *SFC = getLocationContext()->getStackFrame(); 9525ffd83dbSDimitry Andric while (isa<CXXInheritedCtorInitExpr>(SFC->getCallSite())) 9535ffd83dbSDimitry Andric SFC = SFC->getParent()->getStackFrame(); 9545ffd83dbSDimitry Andric return SFC; 9555ffd83dbSDimitry Andric } 9565ffd83dbSDimitry Andric 9570b57cec5SDimitry Andric SVal CXXDestructorCall::getCXXThisVal() const { 9580b57cec5SDimitry Andric if (Data) 9590b57cec5SDimitry Andric return loc::MemRegionVal(DtorDataTy::getFromOpaqueValue(Data).getPointer()); 9600b57cec5SDimitry Andric return UnknownVal(); 9610b57cec5SDimitry Andric } 9620b57cec5SDimitry Andric 9630b57cec5SDimitry Andric RuntimeDefinition CXXDestructorCall::getRuntimeDefinition() const { 9640b57cec5SDimitry Andric // Base destructors are always called non-virtually. 9650b57cec5SDimitry Andric // Skip CXXInstanceCall's devirtualization logic in this case. 9660b57cec5SDimitry Andric if (isBaseDestructor()) 9670b57cec5SDimitry Andric return AnyFunctionCall::getRuntimeDefinition(); 9680b57cec5SDimitry Andric 9690b57cec5SDimitry Andric return CXXInstanceCall::getRuntimeDefinition(); 9700b57cec5SDimitry Andric } 9710b57cec5SDimitry Andric 9720b57cec5SDimitry Andric ArrayRef<ParmVarDecl*> ObjCMethodCall::parameters() const { 9730b57cec5SDimitry Andric const ObjCMethodDecl *D = getDecl(); 9740b57cec5SDimitry Andric if (!D) 975bdd1243dSDimitry Andric return std::nullopt; 9760b57cec5SDimitry Andric return D->parameters(); 9770b57cec5SDimitry Andric } 9780b57cec5SDimitry Andric 9790b57cec5SDimitry Andric void ObjCMethodCall::getExtraInvalidatedValues( 9800b57cec5SDimitry Andric ValueList &Values, RegionAndSymbolInvalidationTraits *ETraits) const { 9810b57cec5SDimitry Andric 9820b57cec5SDimitry Andric // If the method call is a setter for property known to be backed by 9830b57cec5SDimitry Andric // an instance variable, don't invalidate the entire receiver, just 9840b57cec5SDimitry Andric // the storage for that instance variable. 9850b57cec5SDimitry Andric if (const ObjCPropertyDecl *PropDecl = getAccessedProperty()) { 9860b57cec5SDimitry Andric if (const ObjCIvarDecl *PropIvar = PropDecl->getPropertyIvarDecl()) { 9870b57cec5SDimitry Andric SVal IvarLVal = getState()->getLValue(PropIvar, getReceiverSVal()); 9880b57cec5SDimitry Andric if (const MemRegion *IvarRegion = IvarLVal.getAsRegion()) { 9890b57cec5SDimitry Andric ETraits->setTrait( 9900b57cec5SDimitry Andric IvarRegion, 9910b57cec5SDimitry Andric RegionAndSymbolInvalidationTraits::TK_DoNotInvalidateSuperRegion); 9920b57cec5SDimitry Andric ETraits->setTrait( 9930b57cec5SDimitry Andric IvarRegion, 9940b57cec5SDimitry Andric RegionAndSymbolInvalidationTraits::TK_SuppressEscape); 9950b57cec5SDimitry Andric Values.push_back(IvarLVal); 9960b57cec5SDimitry Andric } 9970b57cec5SDimitry Andric return; 9980b57cec5SDimitry Andric } 9990b57cec5SDimitry Andric } 10000b57cec5SDimitry Andric 10010b57cec5SDimitry Andric Values.push_back(getReceiverSVal()); 10020b57cec5SDimitry Andric } 10030b57cec5SDimitry Andric 10040b57cec5SDimitry Andric SVal ObjCMethodCall::getReceiverSVal() const { 10050b57cec5SDimitry Andric // FIXME: Is this the best way to handle class receivers? 10060b57cec5SDimitry Andric if (!isInstanceMessage()) 10070b57cec5SDimitry Andric return UnknownVal(); 10080b57cec5SDimitry Andric 10090b57cec5SDimitry Andric if (const Expr *RecE = getOriginExpr()->getInstanceReceiver()) 10100b57cec5SDimitry Andric return getSVal(RecE); 10110b57cec5SDimitry Andric 10120b57cec5SDimitry Andric // An instance message with no expression means we are sending to super. 10130b57cec5SDimitry Andric // In this case the object reference is the same as 'self'. 10140b57cec5SDimitry Andric assert(getOriginExpr()->getReceiverKind() == ObjCMessageExpr::SuperInstance); 10155ffd83dbSDimitry Andric SVal SelfVal = getState()->getSelfSVal(getLocationContext()); 10160b57cec5SDimitry Andric assert(SelfVal.isValid() && "Calling super but not in ObjC method"); 10170b57cec5SDimitry Andric return SelfVal; 10180b57cec5SDimitry Andric } 10190b57cec5SDimitry Andric 10200b57cec5SDimitry Andric bool ObjCMethodCall::isReceiverSelfOrSuper() const { 10210b57cec5SDimitry Andric if (getOriginExpr()->getReceiverKind() == ObjCMessageExpr::SuperInstance || 10220b57cec5SDimitry Andric getOriginExpr()->getReceiverKind() == ObjCMessageExpr::SuperClass) 10230b57cec5SDimitry Andric return true; 10240b57cec5SDimitry Andric 10250b57cec5SDimitry Andric if (!isInstanceMessage()) 10260b57cec5SDimitry Andric return false; 10270b57cec5SDimitry Andric 10280b57cec5SDimitry Andric SVal RecVal = getSVal(getOriginExpr()->getInstanceReceiver()); 10295ffd83dbSDimitry Andric SVal SelfVal = getState()->getSelfSVal(getLocationContext()); 10300b57cec5SDimitry Andric 10315ffd83dbSDimitry Andric return (RecVal == SelfVal); 10320b57cec5SDimitry Andric } 10330b57cec5SDimitry Andric 10340b57cec5SDimitry Andric SourceRange ObjCMethodCall::getSourceRange() const { 10350b57cec5SDimitry Andric switch (getMessageKind()) { 10360b57cec5SDimitry Andric case OCM_Message: 10370b57cec5SDimitry Andric return getOriginExpr()->getSourceRange(); 10380b57cec5SDimitry Andric case OCM_PropertyAccess: 10390b57cec5SDimitry Andric case OCM_Subscript: 10400b57cec5SDimitry Andric return getContainingPseudoObjectExpr()->getSourceRange(); 10410b57cec5SDimitry Andric } 10420b57cec5SDimitry Andric llvm_unreachable("unknown message kind"); 10430b57cec5SDimitry Andric } 10440b57cec5SDimitry Andric 10450b57cec5SDimitry Andric using ObjCMessageDataTy = llvm::PointerIntPair<const PseudoObjectExpr *, 2>; 10460b57cec5SDimitry Andric 10470b57cec5SDimitry Andric const PseudoObjectExpr *ObjCMethodCall::getContainingPseudoObjectExpr() const { 10480b57cec5SDimitry Andric assert(Data && "Lazy lookup not yet performed."); 10490b57cec5SDimitry Andric assert(getMessageKind() != OCM_Message && "Explicit message send."); 10500b57cec5SDimitry Andric return ObjCMessageDataTy::getFromOpaqueValue(Data).getPointer(); 10510b57cec5SDimitry Andric } 10520b57cec5SDimitry Andric 10530b57cec5SDimitry Andric static const Expr * 10540b57cec5SDimitry Andric getSyntacticFromForPseudoObjectExpr(const PseudoObjectExpr *POE) { 1055349cc55cSDimitry Andric const Expr *Syntactic = POE->getSyntacticForm()->IgnoreParens(); 10560b57cec5SDimitry Andric 10570b57cec5SDimitry Andric // This handles the funny case of assigning to the result of a getter. 10580b57cec5SDimitry Andric // This can happen if the getter returns a non-const reference. 10590b57cec5SDimitry Andric if (const auto *BO = dyn_cast<BinaryOperator>(Syntactic)) 1060349cc55cSDimitry Andric Syntactic = BO->getLHS()->IgnoreParens(); 10610b57cec5SDimitry Andric 10620b57cec5SDimitry Andric return Syntactic; 10630b57cec5SDimitry Andric } 10640b57cec5SDimitry Andric 10650b57cec5SDimitry Andric ObjCMessageKind ObjCMethodCall::getMessageKind() const { 10660b57cec5SDimitry Andric if (!Data) { 10670b57cec5SDimitry Andric // Find the parent, ignoring implicit casts. 1068a7dea167SDimitry Andric const ParentMap &PM = getLocationContext()->getParentMap(); 10690b57cec5SDimitry Andric const Stmt *S = PM.getParentIgnoreParenCasts(getOriginExpr()); 10700b57cec5SDimitry Andric 10710b57cec5SDimitry Andric // Check if parent is a PseudoObjectExpr. 10720b57cec5SDimitry Andric if (const auto *POE = dyn_cast_or_null<PseudoObjectExpr>(S)) { 10730b57cec5SDimitry Andric const Expr *Syntactic = getSyntacticFromForPseudoObjectExpr(POE); 10740b57cec5SDimitry Andric 10750b57cec5SDimitry Andric ObjCMessageKind K; 10760b57cec5SDimitry Andric switch (Syntactic->getStmtClass()) { 10770b57cec5SDimitry Andric case Stmt::ObjCPropertyRefExprClass: 10780b57cec5SDimitry Andric K = OCM_PropertyAccess; 10790b57cec5SDimitry Andric break; 10800b57cec5SDimitry Andric case Stmt::ObjCSubscriptRefExprClass: 10810b57cec5SDimitry Andric K = OCM_Subscript; 10820b57cec5SDimitry Andric break; 10830b57cec5SDimitry Andric default: 10840b57cec5SDimitry Andric // FIXME: Can this ever happen? 10850b57cec5SDimitry Andric K = OCM_Message; 10860b57cec5SDimitry Andric break; 10870b57cec5SDimitry Andric } 10880b57cec5SDimitry Andric 10890b57cec5SDimitry Andric if (K != OCM_Message) { 10900b57cec5SDimitry Andric const_cast<ObjCMethodCall *>(this)->Data 10910b57cec5SDimitry Andric = ObjCMessageDataTy(POE, K).getOpaqueValue(); 10920b57cec5SDimitry Andric assert(getMessageKind() == K); 10930b57cec5SDimitry Andric return K; 10940b57cec5SDimitry Andric } 10950b57cec5SDimitry Andric } 10960b57cec5SDimitry Andric 10970b57cec5SDimitry Andric const_cast<ObjCMethodCall *>(this)->Data 10980b57cec5SDimitry Andric = ObjCMessageDataTy(nullptr, 1).getOpaqueValue(); 10990b57cec5SDimitry Andric assert(getMessageKind() == OCM_Message); 11000b57cec5SDimitry Andric return OCM_Message; 11010b57cec5SDimitry Andric } 11020b57cec5SDimitry Andric 11030b57cec5SDimitry Andric ObjCMessageDataTy Info = ObjCMessageDataTy::getFromOpaqueValue(Data); 11040b57cec5SDimitry Andric if (!Info.getPointer()) 11050b57cec5SDimitry Andric return OCM_Message; 11060b57cec5SDimitry Andric return static_cast<ObjCMessageKind>(Info.getInt()); 11070b57cec5SDimitry Andric } 11080b57cec5SDimitry Andric 11090b57cec5SDimitry Andric const ObjCPropertyDecl *ObjCMethodCall::getAccessedProperty() const { 11100b57cec5SDimitry Andric // Look for properties accessed with property syntax (foo.bar = ...) 11110b57cec5SDimitry Andric if (getMessageKind() == OCM_PropertyAccess) { 11120b57cec5SDimitry Andric const PseudoObjectExpr *POE = getContainingPseudoObjectExpr(); 11130b57cec5SDimitry Andric assert(POE && "Property access without PseudoObjectExpr?"); 11140b57cec5SDimitry Andric 11150b57cec5SDimitry Andric const Expr *Syntactic = getSyntacticFromForPseudoObjectExpr(POE); 11160b57cec5SDimitry Andric auto *RefExpr = cast<ObjCPropertyRefExpr>(Syntactic); 11170b57cec5SDimitry Andric 11180b57cec5SDimitry Andric if (RefExpr->isExplicitProperty()) 11190b57cec5SDimitry Andric return RefExpr->getExplicitProperty(); 11200b57cec5SDimitry Andric } 11210b57cec5SDimitry Andric 11220b57cec5SDimitry Andric // Look for properties accessed with method syntax ([foo setBar:...]). 11230b57cec5SDimitry Andric const ObjCMethodDecl *MD = getDecl(); 11240b57cec5SDimitry Andric if (!MD || !MD->isPropertyAccessor()) 11250b57cec5SDimitry Andric return nullptr; 11260b57cec5SDimitry Andric 11270b57cec5SDimitry Andric // Note: This is potentially quite slow. 11280b57cec5SDimitry Andric return MD->findPropertyDecl(); 11290b57cec5SDimitry Andric } 11300b57cec5SDimitry Andric 11310b57cec5SDimitry Andric bool ObjCMethodCall::canBeOverridenInSubclass(ObjCInterfaceDecl *IDecl, 11320b57cec5SDimitry Andric Selector Sel) const { 11330b57cec5SDimitry Andric assert(IDecl); 11340b57cec5SDimitry Andric AnalysisManager &AMgr = 11350b57cec5SDimitry Andric getState()->getStateManager().getOwningEngine().getAnalysisManager(); 11360b57cec5SDimitry Andric // If the class interface is declared inside the main file, assume it is not 11370b57cec5SDimitry Andric // subcassed. 11380b57cec5SDimitry Andric // TODO: It could actually be subclassed if the subclass is private as well. 11390b57cec5SDimitry Andric // This is probably very rare. 11400b57cec5SDimitry Andric SourceLocation InterfLoc = IDecl->getEndOfDefinitionLoc(); 11410b57cec5SDimitry Andric if (InterfLoc.isValid() && AMgr.isInCodeFile(InterfLoc)) 11420b57cec5SDimitry Andric return false; 11430b57cec5SDimitry Andric 11440b57cec5SDimitry Andric // Assume that property accessors are not overridden. 11450b57cec5SDimitry Andric if (getMessageKind() == OCM_PropertyAccess) 11460b57cec5SDimitry Andric return false; 11470b57cec5SDimitry Andric 11480b57cec5SDimitry Andric // We assume that if the method is public (declared outside of main file) or 11490b57cec5SDimitry Andric // has a parent which publicly declares the method, the method could be 11500b57cec5SDimitry Andric // overridden in a subclass. 11510b57cec5SDimitry Andric 11520b57cec5SDimitry Andric // Find the first declaration in the class hierarchy that declares 11530b57cec5SDimitry Andric // the selector. 11540b57cec5SDimitry Andric ObjCMethodDecl *D = nullptr; 11550b57cec5SDimitry Andric while (true) { 11560b57cec5SDimitry Andric D = IDecl->lookupMethod(Sel, true); 11570b57cec5SDimitry Andric 11580b57cec5SDimitry Andric // Cannot find a public definition. 11590b57cec5SDimitry Andric if (!D) 11600b57cec5SDimitry Andric return false; 11610b57cec5SDimitry Andric 11620b57cec5SDimitry Andric // If outside the main file, 11630b57cec5SDimitry Andric if (D->getLocation().isValid() && !AMgr.isInCodeFile(D->getLocation())) 11640b57cec5SDimitry Andric return true; 11650b57cec5SDimitry Andric 11660b57cec5SDimitry Andric if (D->isOverriding()) { 11670b57cec5SDimitry Andric // Search in the superclass on the next iteration. 11680b57cec5SDimitry Andric IDecl = D->getClassInterface(); 11690b57cec5SDimitry Andric if (!IDecl) 11700b57cec5SDimitry Andric return false; 11710b57cec5SDimitry Andric 11720b57cec5SDimitry Andric IDecl = IDecl->getSuperClass(); 11730b57cec5SDimitry Andric if (!IDecl) 11740b57cec5SDimitry Andric return false; 11750b57cec5SDimitry Andric 11760b57cec5SDimitry Andric continue; 11770b57cec5SDimitry Andric } 11780b57cec5SDimitry Andric 11790b57cec5SDimitry Andric return false; 11800b57cec5SDimitry Andric }; 11810b57cec5SDimitry Andric 11820b57cec5SDimitry Andric llvm_unreachable("The while loop should always terminate."); 11830b57cec5SDimitry Andric } 11840b57cec5SDimitry Andric 11850b57cec5SDimitry Andric static const ObjCMethodDecl *findDefiningRedecl(const ObjCMethodDecl *MD) { 11860b57cec5SDimitry Andric if (!MD) 11870b57cec5SDimitry Andric return MD; 11880b57cec5SDimitry Andric 11890b57cec5SDimitry Andric // Find the redeclaration that defines the method. 11900b57cec5SDimitry Andric if (!MD->hasBody()) { 1191bdd1243dSDimitry Andric for (auto *I : MD->redecls()) 11920b57cec5SDimitry Andric if (I->hasBody()) 11930b57cec5SDimitry Andric MD = cast<ObjCMethodDecl>(I); 11940b57cec5SDimitry Andric } 11950b57cec5SDimitry Andric return MD; 11960b57cec5SDimitry Andric } 11970b57cec5SDimitry Andric 11985ffd83dbSDimitry Andric struct PrivateMethodKey { 11995ffd83dbSDimitry Andric const ObjCInterfaceDecl *Interface; 12005ffd83dbSDimitry Andric Selector LookupSelector; 12015ffd83dbSDimitry Andric bool IsClassMethod; 12025ffd83dbSDimitry Andric }; 12030b57cec5SDimitry Andric 12045ffd83dbSDimitry Andric namespace llvm { 12055ffd83dbSDimitry Andric template <> struct DenseMapInfo<PrivateMethodKey> { 12065ffd83dbSDimitry Andric using InterfaceInfo = DenseMapInfo<const ObjCInterfaceDecl *>; 12075ffd83dbSDimitry Andric using SelectorInfo = DenseMapInfo<Selector>; 12080b57cec5SDimitry Andric 12095ffd83dbSDimitry Andric static inline PrivateMethodKey getEmptyKey() { 12105ffd83dbSDimitry Andric return {InterfaceInfo::getEmptyKey(), SelectorInfo::getEmptyKey(), false}; 12110b57cec5SDimitry Andric } 12120b57cec5SDimitry Andric 12135ffd83dbSDimitry Andric static inline PrivateMethodKey getTombstoneKey() { 12145ffd83dbSDimitry Andric return {InterfaceInfo::getTombstoneKey(), SelectorInfo::getTombstoneKey(), 12155ffd83dbSDimitry Andric true}; 12160b57cec5SDimitry Andric } 12170b57cec5SDimitry Andric 12185ffd83dbSDimitry Andric static unsigned getHashValue(const PrivateMethodKey &Key) { 12195ffd83dbSDimitry Andric return llvm::hash_combine( 12205ffd83dbSDimitry Andric llvm::hash_code(InterfaceInfo::getHashValue(Key.Interface)), 12215ffd83dbSDimitry Andric llvm::hash_code(SelectorInfo::getHashValue(Key.LookupSelector)), 12225ffd83dbSDimitry Andric Key.IsClassMethod); 12230b57cec5SDimitry Andric } 12240b57cec5SDimitry Andric 12255ffd83dbSDimitry Andric static bool isEqual(const PrivateMethodKey &LHS, 12265ffd83dbSDimitry Andric const PrivateMethodKey &RHS) { 12275ffd83dbSDimitry Andric return InterfaceInfo::isEqual(LHS.Interface, RHS.Interface) && 12285ffd83dbSDimitry Andric SelectorInfo::isEqual(LHS.LookupSelector, RHS.LookupSelector) && 12295ffd83dbSDimitry Andric LHS.IsClassMethod == RHS.IsClassMethod; 12300b57cec5SDimitry Andric } 12315ffd83dbSDimitry Andric }; 12325ffd83dbSDimitry Andric } // end namespace llvm 12330b57cec5SDimitry Andric 12345ffd83dbSDimitry Andric static const ObjCMethodDecl * 12355ffd83dbSDimitry Andric lookupRuntimeDefinition(const ObjCInterfaceDecl *Interface, 12365ffd83dbSDimitry Andric Selector LookupSelector, bool InstanceMethod) { 12370b57cec5SDimitry Andric // Repeatedly calling lookupPrivateMethod() is expensive, especially 12380b57cec5SDimitry Andric // when in many cases it returns null. We cache the results so 12390b57cec5SDimitry Andric // that repeated queries on the same ObjCIntefaceDecl and Selector 12400b57cec5SDimitry Andric // don't incur the same cost. On some test cases, we can see the 12410b57cec5SDimitry Andric // same query being issued thousands of times. 12420b57cec5SDimitry Andric // 12430b57cec5SDimitry Andric // NOTE: This cache is essentially a "global" variable, but it 12440b57cec5SDimitry Andric // only gets lazily created when we get here. The value of the 12450b57cec5SDimitry Andric // cache probably comes from it being global across ExprEngines, 12460b57cec5SDimitry Andric // where the same queries may get issued. If we are worried about 12470b57cec5SDimitry Andric // concurrency, or possibly loading/unloading ASTs, etc., we may 12480b57cec5SDimitry Andric // need to revisit this someday. In terms of memory, this table 12490b57cec5SDimitry Andric // stays around until clang quits, which also may be bad if we 12500b57cec5SDimitry Andric // need to release memory. 12510b57cec5SDimitry Andric using PrivateMethodCache = 1252bdd1243dSDimitry Andric llvm::DenseMap<PrivateMethodKey, std::optional<const ObjCMethodDecl *>>; 12530b57cec5SDimitry Andric 12540b57cec5SDimitry Andric static PrivateMethodCache PMC; 1255bdd1243dSDimitry Andric std::optional<const ObjCMethodDecl *> &Val = 12565ffd83dbSDimitry Andric PMC[{Interface, LookupSelector, InstanceMethod}]; 12570b57cec5SDimitry Andric 12580b57cec5SDimitry Andric // Query lookupPrivateMethod() if the cache does not hit. 125981ad6265SDimitry Andric if (!Val) { 12605ffd83dbSDimitry Andric Val = Interface->lookupPrivateMethod(LookupSelector, InstanceMethod); 12610b57cec5SDimitry Andric 12625ffd83dbSDimitry Andric if (!*Val) { 12635ffd83dbSDimitry Andric // Query 'lookupMethod' as a backup. 12645ffd83dbSDimitry Andric Val = Interface->lookupMethod(LookupSelector, InstanceMethod); 12650b57cec5SDimitry Andric } 12660b57cec5SDimitry Andric } 12670b57cec5SDimitry Andric 126881ad6265SDimitry Andric return *Val; 12695ffd83dbSDimitry Andric } 12705ffd83dbSDimitry Andric 12715ffd83dbSDimitry Andric RuntimeDefinition ObjCMethodCall::getRuntimeDefinition() const { 12725ffd83dbSDimitry Andric const ObjCMessageExpr *E = getOriginExpr(); 12735ffd83dbSDimitry Andric assert(E); 12745ffd83dbSDimitry Andric Selector Sel = E->getSelector(); 12755ffd83dbSDimitry Andric 12765ffd83dbSDimitry Andric if (E->isInstanceMessage()) { 12775ffd83dbSDimitry Andric // Find the receiver type. 12785ffd83dbSDimitry Andric const ObjCObjectType *ReceiverT = nullptr; 12795ffd83dbSDimitry Andric bool CanBeSubClassed = false; 12805ffd83dbSDimitry Andric bool LookingForInstanceMethod = true; 12815ffd83dbSDimitry Andric QualType SupersType = E->getSuperType(); 12825ffd83dbSDimitry Andric const MemRegion *Receiver = nullptr; 12835ffd83dbSDimitry Andric 12845ffd83dbSDimitry Andric if (!SupersType.isNull()) { 12855ffd83dbSDimitry Andric // The receiver is guaranteed to be 'super' in this case. 12865ffd83dbSDimitry Andric // Super always means the type of immediate predecessor to the method 12875ffd83dbSDimitry Andric // where the call occurs. 12885ffd83dbSDimitry Andric ReceiverT = cast<ObjCObjectPointerType>(SupersType)->getObjectType(); 12895ffd83dbSDimitry Andric } else { 12905ffd83dbSDimitry Andric Receiver = getReceiverSVal().getAsRegion(); 12915ffd83dbSDimitry Andric if (!Receiver) 12925ffd83dbSDimitry Andric return {}; 12935ffd83dbSDimitry Andric 12945ffd83dbSDimitry Andric DynamicTypeInfo DTI = getDynamicTypeInfo(getState(), Receiver); 12955ffd83dbSDimitry Andric if (!DTI.isValid()) { 12965ffd83dbSDimitry Andric assert(isa<AllocaRegion>(Receiver) && 12975ffd83dbSDimitry Andric "Unhandled untyped region class!"); 12985ffd83dbSDimitry Andric return {}; 12995ffd83dbSDimitry Andric } 13005ffd83dbSDimitry Andric 13015ffd83dbSDimitry Andric QualType DynType = DTI.getType(); 13025ffd83dbSDimitry Andric CanBeSubClassed = DTI.canBeASubClass(); 13035ffd83dbSDimitry Andric 13045ffd83dbSDimitry Andric const auto *ReceiverDynT = 13055ffd83dbSDimitry Andric dyn_cast<ObjCObjectPointerType>(DynType.getCanonicalType()); 13065ffd83dbSDimitry Andric 13075ffd83dbSDimitry Andric if (ReceiverDynT) { 13085ffd83dbSDimitry Andric ReceiverT = ReceiverDynT->getObjectType(); 13095ffd83dbSDimitry Andric 13105ffd83dbSDimitry Andric // It can be actually class methods called with Class object as a 13115ffd83dbSDimitry Andric // receiver. This type of messages is treated by the compiler as 13125ffd83dbSDimitry Andric // instance (not class). 13135ffd83dbSDimitry Andric if (ReceiverT->isObjCClass()) { 13145ffd83dbSDimitry Andric 13155ffd83dbSDimitry Andric SVal SelfVal = getState()->getSelfSVal(getLocationContext()); 13165ffd83dbSDimitry Andric // For [self classMethod], return compiler visible declaration. 13175ffd83dbSDimitry Andric if (Receiver == SelfVal.getAsRegion()) { 13185ffd83dbSDimitry Andric return RuntimeDefinition(findDefiningRedecl(E->getMethodDecl())); 13195ffd83dbSDimitry Andric } 13205ffd83dbSDimitry Andric 13215ffd83dbSDimitry Andric // Otherwise, let's check if we know something about the type 13225ffd83dbSDimitry Andric // inside of this class object. 13235ffd83dbSDimitry Andric if (SymbolRef ReceiverSym = getReceiverSVal().getAsSymbol()) { 13245ffd83dbSDimitry Andric DynamicTypeInfo DTI = 13255ffd83dbSDimitry Andric getClassObjectDynamicTypeInfo(getState(), ReceiverSym); 13265ffd83dbSDimitry Andric if (DTI.isValid()) { 13275ffd83dbSDimitry Andric // Let's use this type for lookup. 13285ffd83dbSDimitry Andric ReceiverT = 13295ffd83dbSDimitry Andric cast<ObjCObjectType>(DTI.getType().getCanonicalType()); 13305ffd83dbSDimitry Andric 13315ffd83dbSDimitry Andric CanBeSubClassed = DTI.canBeASubClass(); 13325ffd83dbSDimitry Andric // And it should be a class method instead. 13335ffd83dbSDimitry Andric LookingForInstanceMethod = false; 13345ffd83dbSDimitry Andric } 13355ffd83dbSDimitry Andric } 13365ffd83dbSDimitry Andric } 13375ffd83dbSDimitry Andric 13385ffd83dbSDimitry Andric if (CanBeSubClassed) 13395ffd83dbSDimitry Andric if (ObjCInterfaceDecl *IDecl = ReceiverT->getInterface()) 13405ffd83dbSDimitry Andric // Even if `DynamicTypeInfo` told us that it can be 13415ffd83dbSDimitry Andric // not necessarily this type, but its descendants, we still want 13425ffd83dbSDimitry Andric // to check again if this selector can be actually overridden. 13435ffd83dbSDimitry Andric CanBeSubClassed = canBeOverridenInSubclass(IDecl, Sel); 13445ffd83dbSDimitry Andric } 13455ffd83dbSDimitry Andric } 13465ffd83dbSDimitry Andric 13475ffd83dbSDimitry Andric // Lookup the instance method implementation. 13485ffd83dbSDimitry Andric if (ReceiverT) 13495ffd83dbSDimitry Andric if (ObjCInterfaceDecl *IDecl = ReceiverT->getInterface()) { 13505ffd83dbSDimitry Andric const ObjCMethodDecl *MD = 13515ffd83dbSDimitry Andric lookupRuntimeDefinition(IDecl, Sel, LookingForInstanceMethod); 13525ffd83dbSDimitry Andric 1353480093f4SDimitry Andric if (MD && !MD->hasBody()) 1354480093f4SDimitry Andric MD = MD->getCanonicalDecl(); 13555ffd83dbSDimitry Andric 13560b57cec5SDimitry Andric if (CanBeSubClassed) 13570b57cec5SDimitry Andric return RuntimeDefinition(MD, Receiver); 13580b57cec5SDimitry Andric else 13590b57cec5SDimitry Andric return RuntimeDefinition(MD, nullptr); 13600b57cec5SDimitry Andric } 13610b57cec5SDimitry Andric } else { 13620b57cec5SDimitry Andric // This is a class method. 13630b57cec5SDimitry Andric // If we have type info for the receiver class, we are calling via 13640b57cec5SDimitry Andric // class name. 13650b57cec5SDimitry Andric if (ObjCInterfaceDecl *IDecl = E->getReceiverInterface()) { 13660b57cec5SDimitry Andric // Find/Return the method implementation. 13670b57cec5SDimitry Andric return RuntimeDefinition(IDecl->lookupPrivateClassMethod(Sel)); 13680b57cec5SDimitry Andric } 13690b57cec5SDimitry Andric } 13700b57cec5SDimitry Andric 13710b57cec5SDimitry Andric return {}; 13720b57cec5SDimitry Andric } 13730b57cec5SDimitry Andric 13740b57cec5SDimitry Andric bool ObjCMethodCall::argumentsMayEscape() const { 13750b57cec5SDimitry Andric if (isInSystemHeader() && !isInstanceMessage()) { 13760b57cec5SDimitry Andric Selector Sel = getSelector(); 13770b57cec5SDimitry Andric if (Sel.getNumArgs() == 1 && 13780b57cec5SDimitry Andric Sel.getIdentifierInfoForSlot(0)->isStr("valueWithPointer")) 13790b57cec5SDimitry Andric return true; 13800b57cec5SDimitry Andric } 13810b57cec5SDimitry Andric 13820b57cec5SDimitry Andric return CallEvent::argumentsMayEscape(); 13830b57cec5SDimitry Andric } 13840b57cec5SDimitry Andric 13850b57cec5SDimitry Andric void ObjCMethodCall::getInitialStackFrameContents( 13860b57cec5SDimitry Andric const StackFrameContext *CalleeCtx, 13870b57cec5SDimitry Andric BindingsTy &Bindings) const { 13880b57cec5SDimitry Andric const auto *D = cast<ObjCMethodDecl>(CalleeCtx->getDecl()); 13890b57cec5SDimitry Andric SValBuilder &SVB = getState()->getStateManager().getSValBuilder(); 13900b57cec5SDimitry Andric addParameterValuesToBindings(CalleeCtx, Bindings, SVB, *this, 13910b57cec5SDimitry Andric D->parameters()); 13920b57cec5SDimitry Andric 13930b57cec5SDimitry Andric SVal SelfVal = getReceiverSVal(); 13940b57cec5SDimitry Andric if (!SelfVal.isUnknown()) { 13950b57cec5SDimitry Andric const VarDecl *SelfD = CalleeCtx->getAnalysisDeclContext()->getSelfDecl(); 13960b57cec5SDimitry Andric MemRegionManager &MRMgr = SVB.getRegionManager(); 13970b57cec5SDimitry Andric Loc SelfLoc = SVB.makeLoc(MRMgr.getVarRegion(SelfD, CalleeCtx)); 13980b57cec5SDimitry Andric Bindings.push_back(std::make_pair(SelfLoc, SelfVal)); 13990b57cec5SDimitry Andric } 14000b57cec5SDimitry Andric } 14010b57cec5SDimitry Andric 14020b57cec5SDimitry Andric CallEventRef<> 14030b57cec5SDimitry Andric CallEventManager::getSimpleCall(const CallExpr *CE, ProgramStateRef State, 140406c3fb27SDimitry Andric const LocationContext *LCtx, 140506c3fb27SDimitry Andric CFGBlock::ConstCFGElementRef ElemRef) { 14060b57cec5SDimitry Andric if (const auto *MCE = dyn_cast<CXXMemberCallExpr>(CE)) 140706c3fb27SDimitry Andric return create<CXXMemberCall>(MCE, State, LCtx, ElemRef); 14080b57cec5SDimitry Andric 14090b57cec5SDimitry Andric if (const auto *OpCE = dyn_cast<CXXOperatorCallExpr>(CE)) { 14100b57cec5SDimitry Andric const FunctionDecl *DirectCallee = OpCE->getDirectCallee(); 1411*0fca6ea1SDimitry Andric if (const auto *MD = dyn_cast<CXXMethodDecl>(DirectCallee)) { 1412439352acSDimitry Andric if (MD->isImplicitObjectMemberFunction()) 141306c3fb27SDimitry Andric return create<CXXMemberOperatorCall>(OpCE, State, LCtx, ElemRef); 1414*0fca6ea1SDimitry Andric if (MD->isStatic()) 1415*0fca6ea1SDimitry Andric return create<CXXStaticOperatorCall>(OpCE, State, LCtx, ElemRef); 1416*0fca6ea1SDimitry Andric } 14170b57cec5SDimitry Andric 14180b57cec5SDimitry Andric } else if (CE->getCallee()->getType()->isBlockPointerType()) { 141906c3fb27SDimitry Andric return create<BlockCall>(CE, State, LCtx, ElemRef); 14200b57cec5SDimitry Andric } 14210b57cec5SDimitry Andric 14220b57cec5SDimitry Andric // Otherwise, it's a normal function call, static member function call, or 14230b57cec5SDimitry Andric // something we can't reason about. 142406c3fb27SDimitry Andric return create<SimpleFunctionCall>(CE, State, LCtx, ElemRef); 14250b57cec5SDimitry Andric } 14260b57cec5SDimitry Andric 14270b57cec5SDimitry Andric CallEventRef<> 14280b57cec5SDimitry Andric CallEventManager::getCaller(const StackFrameContext *CalleeCtx, 14290b57cec5SDimitry Andric ProgramStateRef State) { 14300b57cec5SDimitry Andric const LocationContext *ParentCtx = CalleeCtx->getParent(); 14310b57cec5SDimitry Andric const LocationContext *CallerCtx = ParentCtx->getStackFrame(); 143206c3fb27SDimitry Andric CFGBlock::ConstCFGElementRef ElemRef = {CalleeCtx->getCallSiteBlock(), 143306c3fb27SDimitry Andric CalleeCtx->getIndex()}; 14340b57cec5SDimitry Andric assert(CallerCtx && "This should not be used for top-level stack frames"); 14350b57cec5SDimitry Andric 14360b57cec5SDimitry Andric const Stmt *CallSite = CalleeCtx->getCallSite(); 14370b57cec5SDimitry Andric 14380b57cec5SDimitry Andric if (CallSite) { 143906c3fb27SDimitry Andric if (CallEventRef<> Out = getCall(CallSite, State, CallerCtx, ElemRef)) 14400b57cec5SDimitry Andric return Out; 14410b57cec5SDimitry Andric 14420b57cec5SDimitry Andric SValBuilder &SVB = State->getStateManager().getSValBuilder(); 14430b57cec5SDimitry Andric const auto *Ctor = cast<CXXMethodDecl>(CalleeCtx->getDecl()); 14440b57cec5SDimitry Andric Loc ThisPtr = SVB.getCXXThis(Ctor, CalleeCtx); 14450b57cec5SDimitry Andric SVal ThisVal = State->getSVal(ThisPtr); 14460b57cec5SDimitry Andric 14475ffd83dbSDimitry Andric if (const auto *CE = dyn_cast<CXXConstructExpr>(CallSite)) 144806c3fb27SDimitry Andric return getCXXConstructorCall(CE, ThisVal.getAsRegion(), State, CallerCtx, 144906c3fb27SDimitry Andric ElemRef); 14505ffd83dbSDimitry Andric else if (const auto *CIE = dyn_cast<CXXInheritedCtorInitExpr>(CallSite)) 14515ffd83dbSDimitry Andric return getCXXInheritedConstructorCall(CIE, ThisVal.getAsRegion(), State, 145206c3fb27SDimitry Andric CallerCtx, ElemRef); 14535ffd83dbSDimitry Andric else { 14545ffd83dbSDimitry Andric // All other cases are handled by getCall. 14555ffd83dbSDimitry Andric llvm_unreachable("This is not an inlineable statement"); 14565ffd83dbSDimitry Andric } 14570b57cec5SDimitry Andric } 14580b57cec5SDimitry Andric 14590b57cec5SDimitry Andric // Fall back to the CFG. The only thing we haven't handled yet is 14600b57cec5SDimitry Andric // destructors, though this could change in the future. 14610b57cec5SDimitry Andric const CFGBlock *B = CalleeCtx->getCallSiteBlock(); 14620b57cec5SDimitry Andric CFGElement E = (*B)[CalleeCtx->getIndex()]; 14630b57cec5SDimitry Andric assert((E.getAs<CFGImplicitDtor>() || E.getAs<CFGTemporaryDtor>()) && 14640b57cec5SDimitry Andric "All other CFG elements should have exprs"); 14650b57cec5SDimitry Andric 14660b57cec5SDimitry Andric SValBuilder &SVB = State->getStateManager().getSValBuilder(); 14670b57cec5SDimitry Andric const auto *Dtor = cast<CXXDestructorDecl>(CalleeCtx->getDecl()); 14680b57cec5SDimitry Andric Loc ThisPtr = SVB.getCXXThis(Dtor, CalleeCtx); 14690b57cec5SDimitry Andric SVal ThisVal = State->getSVal(ThisPtr); 14700b57cec5SDimitry Andric 14710b57cec5SDimitry Andric const Stmt *Trigger; 1472bdd1243dSDimitry Andric if (std::optional<CFGAutomaticObjDtor> AutoDtor = 1473bdd1243dSDimitry Andric E.getAs<CFGAutomaticObjDtor>()) 14740b57cec5SDimitry Andric Trigger = AutoDtor->getTriggerStmt(); 1475bdd1243dSDimitry Andric else if (std::optional<CFGDeleteDtor> DeleteDtor = E.getAs<CFGDeleteDtor>()) 14760b57cec5SDimitry Andric Trigger = DeleteDtor->getDeleteExpr(); 14770b57cec5SDimitry Andric else 14780b57cec5SDimitry Andric Trigger = Dtor->getBody(); 14790b57cec5SDimitry Andric 14800b57cec5SDimitry Andric return getCXXDestructorCall(Dtor, Trigger, ThisVal.getAsRegion(), 148181ad6265SDimitry Andric E.getAs<CFGBaseDtor>().has_value(), State, 148206c3fb27SDimitry Andric CallerCtx, ElemRef); 14830b57cec5SDimitry Andric } 14840b57cec5SDimitry Andric 14850b57cec5SDimitry Andric CallEventRef<> CallEventManager::getCall(const Stmt *S, ProgramStateRef State, 148606c3fb27SDimitry Andric const LocationContext *LC, 148706c3fb27SDimitry Andric CFGBlock::ConstCFGElementRef ElemRef) { 14880b57cec5SDimitry Andric if (const auto *CE = dyn_cast<CallExpr>(S)) { 148906c3fb27SDimitry Andric return getSimpleCall(CE, State, LC, ElemRef); 14900b57cec5SDimitry Andric } else if (const auto *NE = dyn_cast<CXXNewExpr>(S)) { 149106c3fb27SDimitry Andric return getCXXAllocatorCall(NE, State, LC, ElemRef); 149281ad6265SDimitry Andric } else if (const auto *DE = dyn_cast<CXXDeleteExpr>(S)) { 149306c3fb27SDimitry Andric return getCXXDeallocatorCall(DE, State, LC, ElemRef); 14940b57cec5SDimitry Andric } else if (const auto *ME = dyn_cast<ObjCMessageExpr>(S)) { 149506c3fb27SDimitry Andric return getObjCMethodCall(ME, State, LC, ElemRef); 14960b57cec5SDimitry Andric } else { 14970b57cec5SDimitry Andric return nullptr; 14980b57cec5SDimitry Andric } 14990b57cec5SDimitry Andric } 1500