15bc81eb9SEugene Zelenko //===- CallEvent.cpp - Wrapper for all function and method calls ----------===//
24f7df9beSJordan Rose //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
64f7df9beSJordan Rose //
74f7df9beSJordan Rose //===----------------------------------------------------------------------===//
84f7df9beSJordan Rose //
94f7df9beSJordan Rose /// \file This file defines CallEvent and its subclasses, which represent path-
104f7df9beSJordan Rose /// sensitive instances of different kinds of function and method calls
114f7df9beSJordan Rose /// (C, C++, and Objective-C).
124f7df9beSJordan Rose //
134f7df9beSJordan Rose //===----------------------------------------------------------------------===//
144f7df9beSJordan Rose
154f7df9beSJordan Rose #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
165bc81eb9SEugene Zelenko #include "clang/AST/ASTContext.h"
1760573ae6SReid Kleckner #include "clang/AST/Attr.h"
185bc81eb9SEugene Zelenko #include "clang/AST/Decl.h"
195bc81eb9SEugene Zelenko #include "clang/AST/DeclBase.h"
205bc81eb9SEugene Zelenko #include "clang/AST/DeclCXX.h"
215bc81eb9SEugene Zelenko #include "clang/AST/DeclObjC.h"
225bc81eb9SEugene Zelenko #include "clang/AST/Expr.h"
235bc81eb9SEugene Zelenko #include "clang/AST/ExprCXX.h"
245bc81eb9SEugene Zelenko #include "clang/AST/ExprObjC.h"
254f7df9beSJordan Rose #include "clang/AST/ParentMap.h"
265bc81eb9SEugene Zelenko #include "clang/AST/Stmt.h"
275bc81eb9SEugene Zelenko #include "clang/AST/Type.h"
285bc81eb9SEugene Zelenko #include "clang/Analysis/AnalysisDeclContext.h"
295bc81eb9SEugene Zelenko #include "clang/Analysis/CFG.h"
30b21b4796SArtem Dergachev #include "clang/Analysis/CFGStmtMap.h"
31f0bb45faSArtem Dergachev #include "clang/Analysis/PathDiagnostic.h"
323a02247dSChandler Carruth #include "clang/Analysis/ProgramPoint.h"
335bc81eb9SEugene Zelenko #include "clang/Basic/IdentifierTable.h"
345bc81eb9SEugene Zelenko #include "clang/Basic/LLVM.h"
355bc81eb9SEugene Zelenko #include "clang/Basic/SourceLocation.h"
365bc81eb9SEugene Zelenko #include "clang/Basic/SourceManager.h"
375bc81eb9SEugene Zelenko #include "clang/Basic/Specifiers.h"
3860573ae6SReid Kleckner #include "clang/CrossTU/CrossTranslationUnit.h"
390b9d3a6eSBalazs Benics #include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
403a02247dSChandler Carruth #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
41e4bf456fSCsaba Dabis #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicType.h"
4260573ae6SReid Kleckner #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h"
435bc81eb9SEugene Zelenko #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
445bc81eb9SEugene Zelenko #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
455bc81eb9SEugene Zelenko #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
465bc81eb9SEugene Zelenko #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
4760573ae6SReid Kleckner #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
485bc81eb9SEugene Zelenko #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
495bc81eb9SEugene Zelenko #include "llvm/ADT/ArrayRef.h"
505bc81eb9SEugene Zelenko #include "llvm/ADT/DenseMap.h"
51d6461571SValeriy Savchenko #include "llvm/ADT/ImmutableList.h"
525bc81eb9SEugene Zelenko #include "llvm/ADT/None.h"
535bc81eb9SEugene Zelenko #include "llvm/ADT/Optional.h"
545bc81eb9SEugene Zelenko #include "llvm/ADT/PointerIntPair.h"
554f7df9beSJordan Rose #include "llvm/ADT/SmallSet.h"
565bc81eb9SEugene Zelenko #include "llvm/ADT/SmallVector.h"
574f7df9beSJordan Rose #include "llvm/ADT/StringExtras.h"
585bc81eb9SEugene Zelenko #include "llvm/ADT/StringRef.h"
595bc81eb9SEugene Zelenko #include "llvm/Support/Casting.h"
605bc81eb9SEugene Zelenko #include "llvm/Support/Compiler.h"
61504e2360SGeorge Karpenkov #include "llvm/Support/Debug.h"
625bc81eb9SEugene Zelenko #include "llvm/Support/ErrorHandling.h"
635bc81eb9SEugene Zelenko #include "llvm/Support/raw_ostream.h"
645bc81eb9SEugene Zelenko #include <cassert>
655bc81eb9SEugene Zelenko #include <utility>
66504e2360SGeorge Karpenkov
67504e2360SGeorge Karpenkov #define DEBUG_TYPE "static-analyzer-call-event"
684f7df9beSJordan Rose
694f7df9beSJordan Rose using namespace clang;
704f7df9beSJordan Rose using namespace ento;
714f7df9beSJordan Rose
getResultType() const724f7df9beSJordan Rose QualType CallEvent::getResultType() const {
732da56438SJordan Rose ASTContext &Ctx = getState()->getStateManager().getContext();
74405fdfc3SGeorge Karpenkov const Expr *E = getOriginExpr();
75405fdfc3SGeorge Karpenkov if (!E)
76405fdfc3SGeorge Karpenkov return Ctx.VoidTy;
770c7cd4a8SMatheus Izvekov return Ctx.getReferenceQualifiedType(E);
784f7df9beSJordan Rose }
794f7df9beSJordan Rose
isCallback(QualType T)80fe1eca51SAnna Zaks static bool isCallback(QualType T) {
814f7df9beSJordan Rose // If a parameter is a block or a callback, assume it can modify pointer.
824f7df9beSJordan Rose if (T->isBlockPointerType() ||
834f7df9beSJordan Rose T->isFunctionPointerType() ||
844f7df9beSJordan Rose T->isObjCSelType())
854f7df9beSJordan Rose return true;
864f7df9beSJordan Rose
874f7df9beSJordan Rose // Check if a callback is passed inside a struct (for both, struct passed by
884f7df9beSJordan Rose // reference and by value). Dig just one level into the struct for now.
894f7df9beSJordan Rose
90d1a08b6eSJordan Rose if (T->isAnyPointerType() || T->isReferenceType())
914f7df9beSJordan Rose T = T->getPointeeType();
924f7df9beSJordan Rose
934f7df9beSJordan Rose if (const RecordType *RT = T->getAsStructureType()) {
944f7df9beSJordan Rose const RecordDecl *RD = RT->getDecl();
95e8a8baefSAaron Ballman for (const auto *I : RD->fields()) {
964f7df9beSJordan Rose QualType FieldT = I->getType();
974f7df9beSJordan Rose if (FieldT->isBlockPointerType() || FieldT->isFunctionPointerType())
984f7df9beSJordan Rose return true;
994f7df9beSJordan Rose }
1004f7df9beSJordan Rose }
1014f7df9beSJordan Rose return false;
1024f7df9beSJordan Rose }
1034f7df9beSJordan Rose
isVoidPointerToNonConst(QualType T)104fe1eca51SAnna Zaks static bool isVoidPointerToNonConst(QualType T) {
1055bc81eb9SEugene Zelenko if (const auto *PT = T->getAs<PointerType>()) {
106fe1eca51SAnna Zaks QualType PointeeTy = PT->getPointeeType();
107fe1eca51SAnna Zaks if (PointeeTy.isConstQualified())
108fe1eca51SAnna Zaks return false;
109fe1eca51SAnna Zaks return PointeeTy->isVoidType();
110fe1eca51SAnna Zaks } else
111fe1eca51SAnna Zaks return false;
112fe1eca51SAnna Zaks }
113fe1eca51SAnna Zaks
hasNonNullArgumentsWithType(bool (* Condition)(QualType)) const114fe1eca51SAnna Zaks bool CallEvent::hasNonNullArgumentsWithType(bool (*Condition)(QualType)) const {
1154f7df9beSJordan Rose unsigned NumOfArgs = getNumArgs();
1164f7df9beSJordan Rose
1174f7df9beSJordan Rose // If calling using a function pointer, assume the function does not
118fe1eca51SAnna Zaks // satisfy the callback.
119fe1eca51SAnna Zaks // TODO: We could check the types of the arguments here.
1204f7df9beSJordan Rose if (!getDecl())
1214f7df9beSJordan Rose return false;
1224f7df9beSJordan Rose
1234f7df9beSJordan Rose unsigned Idx = 0;
1244f7df9beSJordan Rose for (CallEvent::param_type_iterator I = param_type_begin(),
1254f7df9beSJordan Rose E = param_type_end();
1264f7df9beSJordan Rose I != E && Idx < NumOfArgs; ++I, ++Idx) {
127fe1eca51SAnna Zaks // If the parameter is 0, it's harmless.
128fe1eca51SAnna Zaks if (getArgSVal(Idx).isZeroConstant())
129fe1eca51SAnna Zaks continue;
130fe1eca51SAnna Zaks
131fe1eca51SAnna Zaks if (Condition(*I))
1324f7df9beSJordan Rose return true;
1334f7df9beSJordan Rose }
1344f7df9beSJordan Rose return false;
1354f7df9beSJordan Rose }
1364f7df9beSJordan Rose
hasNonZeroCallbackArg() const137fe1eca51SAnna Zaks bool CallEvent::hasNonZeroCallbackArg() const {
138fe1eca51SAnna Zaks return hasNonNullArgumentsWithType(isCallback);
139fe1eca51SAnna Zaks }
140fe1eca51SAnna Zaks
hasVoidPointerToNonConstArg() const141fe1eca51SAnna Zaks bool CallEvent::hasVoidPointerToNonConstArg() const {
142fe1eca51SAnna Zaks return hasNonNullArgumentsWithType(isVoidPointerToNonConst);
143fe1eca51SAnna Zaks }
144fe1eca51SAnna Zaks
isGlobalCFunction(StringRef FunctionName) const145829c3831SJordan Rose bool CallEvent::isGlobalCFunction(StringRef FunctionName) const {
1465bc81eb9SEugene Zelenko const auto *FD = dyn_cast_or_null<FunctionDecl>(getDecl());
147829c3831SJordan Rose if (!FD)
148829c3831SJordan Rose return false;
149829c3831SJordan Rose
150829c3831SJordan Rose return CheckerContext::isCLibraryFunction(FD, FunctionName);
151829c3831SJordan Rose }
152829c3831SJordan Rose
getCalleeAnalysisDeclContext() const153b21b4796SArtem Dergachev AnalysisDeclContext *CallEvent::getCalleeAnalysisDeclContext() const {
154b21b4796SArtem Dergachev const Decl *D = getDecl();
155b21b4796SArtem Dergachev if (!D)
156b21b4796SArtem Dergachev return nullptr;
157b21b4796SArtem Dergachev
1583ccf14ebSArtem Dergachev AnalysisDeclContext *ADC =
1593ccf14ebSArtem Dergachev LCtx->getAnalysisDeclContext()->getManager()->getContext(D);
1603ccf14ebSArtem Dergachev
1613ccf14ebSArtem Dergachev return ADC;
162b21b4796SArtem Dergachev }
163b21b4796SArtem Dergachev
1647740c6d6SCsaba Dabis const StackFrameContext *
getCalleeStackFrame(unsigned BlockCount) const1657740c6d6SCsaba Dabis CallEvent::getCalleeStackFrame(unsigned BlockCount) const {
166b21b4796SArtem Dergachev AnalysisDeclContext *ADC = getCalleeAnalysisDeclContext();
167b21b4796SArtem Dergachev if (!ADC)
168b21b4796SArtem Dergachev return nullptr;
169b21b4796SArtem Dergachev
170b21b4796SArtem Dergachev const Expr *E = getOriginExpr();
171b21b4796SArtem Dergachev if (!E)
172b21b4796SArtem Dergachev return nullptr;
173b21b4796SArtem Dergachev
174b21b4796SArtem Dergachev // Recover CFG block via reverse lookup.
175b21b4796SArtem Dergachev // TODO: If we were to keep CFG element information as part of the CallEvent
176b21b4796SArtem Dergachev // instead of doing this reverse lookup, we would be able to build the stack
177b21b4796SArtem Dergachev // frame for non-expression-based calls, and also we wouldn't need the reverse
178b21b4796SArtem Dergachev // lookup.
179b21b4796SArtem Dergachev CFGStmtMap *Map = LCtx->getAnalysisDeclContext()->getCFGStmtMap();
180b21b4796SArtem Dergachev const CFGBlock *B = Map->getBlock(E);
181b21b4796SArtem Dergachev assert(B);
182b21b4796SArtem Dergachev
183b21b4796SArtem Dergachev // Also recover CFG index by scanning the CFG block.
184b21b4796SArtem Dergachev unsigned Idx = 0, Sz = B->size();
185b21b4796SArtem Dergachev for (; Idx < Sz; ++Idx)
186b21b4796SArtem Dergachev if (auto StmtElem = (*B)[Idx].getAs<CFGStmt>())
187b21b4796SArtem Dergachev if (StmtElem->getStmt() == E)
188b21b4796SArtem Dergachev break;
189b21b4796SArtem Dergachev assert(Idx < Sz);
190b21b4796SArtem Dergachev
1917740c6d6SCsaba Dabis return ADC->getManager()->getStackFrame(ADC, LCtx, E, B, BlockCount, Idx);
192b21b4796SArtem Dergachev }
193b21b4796SArtem Dergachev
19498db1f99SAdam Balogh const ParamVarRegion
getParameterLocation(unsigned Index,unsigned BlockCount) const19598db1f99SAdam Balogh *CallEvent::getParameterLocation(unsigned Index, unsigned BlockCount) const {
1967740c6d6SCsaba Dabis const StackFrameContext *SFC = getCalleeStackFrame(BlockCount);
197b21b4796SArtem Dergachev // We cannot construct a VarRegion without a stack frame.
198b21b4796SArtem Dergachev if (!SFC)
199b21b4796SArtem Dergachev return nullptr;
200b21b4796SArtem Dergachev
20198db1f99SAdam Balogh const ParamVarRegion *PVR =
20298db1f99SAdam Balogh State->getStateManager().getRegionManager().getParamVarRegion(
20398db1f99SAdam Balogh getOriginExpr(), Index, SFC);
20498db1f99SAdam Balogh return PVR;
205b21b4796SArtem Dergachev }
206b21b4796SArtem Dergachev
2079fc8faf9SAdrian Prantl /// Returns true if a type is a pointer-to-const or reference-to-const
2084f7df9beSJordan Rose /// with no further indirection.
isPointerToConst(QualType Ty)2094f7df9beSJordan Rose static bool isPointerToConst(QualType Ty) {
2104f7df9beSJordan Rose QualType PointeeTy = Ty->getPointeeType();
2114f7df9beSJordan Rose if (PointeeTy == QualType())
2124f7df9beSJordan Rose return false;
2134f7df9beSJordan Rose if (!PointeeTy.isConstQualified())
2144f7df9beSJordan Rose return false;
2154f7df9beSJordan Rose if (PointeeTy->isAnyPointerType())
2164f7df9beSJordan Rose return false;
2174f7df9beSJordan Rose return true;
2184f7df9beSJordan Rose }
2194f7df9beSJordan Rose
2204f7df9beSJordan Rose // Try to retrieve the function declaration and find the function parameter
2214f7df9beSJordan Rose // types which are pointers/references to a non-pointer const.
2224f7df9beSJordan Rose // We will not invalidate the corresponding argument regions.
findPtrToConstParams(llvm::SmallSet<unsigned,4> & PreserveArgs,const CallEvent & Call)2235413aaa7SJordan Rose static void findPtrToConstParams(llvm::SmallSet<unsigned, 4> &PreserveArgs,
2244f7df9beSJordan Rose const CallEvent &Call) {
2254f7df9beSJordan Rose unsigned Idx = 0;
2264f7df9beSJordan Rose for (CallEvent::param_type_iterator I = Call.param_type_begin(),
2274f7df9beSJordan Rose E = Call.param_type_end();
2284f7df9beSJordan Rose I != E; ++I, ++Idx) {
2294f7df9beSJordan Rose if (isPointerToConst(*I))
2304f7df9beSJordan Rose PreserveArgs.insert(Idx);
2314f7df9beSJordan Rose }
2324f7df9beSJordan Rose }
2334f7df9beSJordan Rose
invalidateRegions(unsigned BlockCount,ProgramStateRef Orig) const2344f7df9beSJordan Rose ProgramStateRef CallEvent::invalidateRegions(unsigned BlockCount,
2354f7df9beSJordan Rose ProgramStateRef Orig) const {
2364f7df9beSJordan Rose ProgramStateRef Result = (Orig ? Orig : getState());
2374f7df9beSJordan Rose
2382741654bSJordan Rose // Don't invalidate anything if the callee is marked pure/const.
2392741654bSJordan Rose if (const Decl *callee = getDecl())
2402741654bSJordan Rose if (callee->hasAttr<PureAttr>() || callee->hasAttr<ConstAttr>())
2412741654bSJordan Rose return Result;
2422741654bSJordan Rose
24360bf5f45SAnna Zaks SmallVector<SVal, 8> ValuesToInvalidate;
244424ad95fSAnton Yartsev RegionAndSymbolInvalidationTraits ETraits;
24560bf5f45SAnna Zaks
2464f770deeSDevin Coughlin getExtraInvalidatedValues(ValuesToInvalidate, &ETraits);
2474f7df9beSJordan Rose
2484f7df9beSJordan Rose // Indexes of arguments whose values will be preserved by the call.
2495413aaa7SJordan Rose llvm::SmallSet<unsigned, 4> PreserveArgs;
2504f7df9beSJordan Rose if (!argumentsMayEscape())
2514f7df9beSJordan Rose findPtrToConstParams(PreserveArgs, *this);
2524f7df9beSJordan Rose
2534f7df9beSJordan Rose for (unsigned Idx = 0, Count = getNumArgs(); Idx != Count; ++Idx) {
2544f7df9beSJordan Rose // Mark this region for invalidation. We batch invalidate regions
2554f7df9beSJordan Rose // below for efficiency.
2565413aaa7SJordan Rose if (PreserveArgs.count(Idx))
2573d90e7e8SArtem Dergachev if (const MemRegion *MR = getArgSVal(Idx).getAsRegion())
2583d90e7e8SArtem Dergachev ETraits.setTrait(MR->getBaseRegion(),
259424ad95fSAnton Yartsev RegionAndSymbolInvalidationTraits::TK_PreserveContents);
2603d90e7e8SArtem Dergachev // TODO: Factor this out + handle the lower level const pointers.
261424ad95fSAnton Yartsev
26260bf5f45SAnna Zaks ValuesToInvalidate.push_back(getArgSVal(Idx));
2633ccf14ebSArtem Dergachev
2643ccf14ebSArtem Dergachev // If a function accepts an object by argument (which would of course be a
2653ccf14ebSArtem Dergachev // temporary that isn't lifetime-extended), invalidate the object itself,
2663ccf14ebSArtem Dergachev // not only other objects reachable from it. This is necessary because the
2673ccf14ebSArtem Dergachev // destructor has access to the temporary object after the call.
2683ccf14ebSArtem Dergachev // TODO: Support placement arguments once we start
2693ccf14ebSArtem Dergachev // constructing them directly.
2703ccf14ebSArtem Dergachev // TODO: This is unnecessary when there's no destructor, but that's
2713ccf14ebSArtem Dergachev // currently hard to figure out.
2723ccf14ebSArtem Dergachev if (getKind() != CE_CXXAllocator)
2733ccf14ebSArtem Dergachev if (isArgumentConstructedDirectly(Idx))
2743ccf14ebSArtem Dergachev if (auto AdjIdx = getAdjustedParameterIndex(Idx))
27598db1f99SAdam Balogh if (const TypedValueRegion *TVR =
27698db1f99SAdam Balogh getParameterLocation(*AdjIdx, BlockCount))
27798db1f99SAdam Balogh ValuesToInvalidate.push_back(loc::MemRegionVal(TVR));
2784f7df9beSJordan Rose }
2794f7df9beSJordan Rose
2804f7df9beSJordan Rose // Invalidate designated regions using the batch invalidation API.
2814f7df9beSJordan Rose // NOTE: Even if RegionsToInvalidate is empty, we may still invalidate
2824f7df9beSJordan Rose // global variables.
28360bf5f45SAnna Zaks return Result->invalidateRegions(ValuesToInvalidate, getOriginExpr(),
2844f7df9beSJordan Rose BlockCount, getLocationContext(),
2859747febbSAnna Zaks /*CausedByPointerEscape*/ true,
2860dbb783cSCraig Topper /*Symbols=*/nullptr, this, &ETraits);
2874f7df9beSJordan Rose }
2884f7df9beSJordan Rose
getProgramPoint(bool IsPreVisit,const ProgramPointTag * Tag) const2894f7df9beSJordan Rose ProgramPoint CallEvent::getProgramPoint(bool IsPreVisit,
2904f7df9beSJordan Rose const ProgramPointTag *Tag) const {
2914f7df9beSJordan Rose if (const Expr *E = getOriginExpr()) {
2924f7df9beSJordan Rose if (IsPreVisit)
2934f7df9beSJordan Rose return PreStmt(E, getLocationContext(), Tag);
2944f7df9beSJordan Rose return PostStmt(E, getLocationContext(), Tag);
2954f7df9beSJordan Rose }
2964f7df9beSJordan Rose
2974f7df9beSJordan Rose const Decl *D = getDecl();
2984f7df9beSJordan Rose assert(D && "Cannot get a program point without a statement or decl");
2994f7df9beSJordan Rose
3004f7df9beSJordan Rose SourceLocation Loc = getSourceRange().getBegin();
3014f7df9beSJordan Rose if (IsPreVisit)
3024f7df9beSJordan Rose return PreImplicitCall(D, Loc, getLocationContext(), Tag);
3034f7df9beSJordan Rose return PostImplicitCall(D, Loc, getLocationContext(), Tag);
3044f7df9beSJordan Rose }
3054f7df9beSJordan Rose
getArgSVal(unsigned Index) const30672ce8e2dSJordan Rose SVal CallEvent::getArgSVal(unsigned Index) const {
30772ce8e2dSJordan Rose const Expr *ArgE = getArgExpr(Index);
30872ce8e2dSJordan Rose if (!ArgE)
30972ce8e2dSJordan Rose return UnknownVal();
31072ce8e2dSJordan Rose return getSVal(ArgE);
31172ce8e2dSJordan Rose }
31272ce8e2dSJordan Rose
getArgSourceRange(unsigned Index) const31372ce8e2dSJordan Rose SourceRange CallEvent::getArgSourceRange(unsigned Index) const {
31472ce8e2dSJordan Rose const Expr *ArgE = getArgExpr(Index);
31572ce8e2dSJordan Rose if (!ArgE)
3165bc81eb9SEugene Zelenko return {};
31772ce8e2dSJordan Rose return ArgE->getSourceRange();
31872ce8e2dSJordan Rose }
31972ce8e2dSJordan Rose
getReturnValue() const320829c3831SJordan Rose SVal CallEvent::getReturnValue() const {
321829c3831SJordan Rose const Expr *E = getOriginExpr();
322829c3831SJordan Rose if (!E)
323829c3831SJordan Rose return UndefinedVal();
324829c3831SJordan Rose return getSVal(E);
325829c3831SJordan Rose }
326829c3831SJordan Rose
dump() const327ef6b007dSAlp Toker LLVM_DUMP_METHOD void CallEvent::dump() const { dump(llvm::errs()); }
3289299d8c2SBenjamin Kramer
dump(raw_ostream & Out) const32972ce8e2dSJordan Rose void CallEvent::dump(raw_ostream &Out) const {
33072ce8e2dSJordan Rose ASTContext &Ctx = getState()->getStateManager().getContext();
33172ce8e2dSJordan Rose if (const Expr *E = getOriginExpr()) {
3320dbb783cSCraig Topper E->printPretty(Out, nullptr, Ctx.getPrintingPolicy());
33372ce8e2dSJordan Rose return;
33472ce8e2dSJordan Rose }
33572ce8e2dSJordan Rose
33672ce8e2dSJordan Rose if (const Decl *D = getDecl()) {
33772ce8e2dSJordan Rose Out << "Call to ";
33872ce8e2dSJordan Rose D->print(Out, Ctx.getPrintingPolicy());
33972ce8e2dSJordan Rose return;
34072ce8e2dSJordan Rose }
34172ce8e2dSJordan Rose
342023c4d40SKirstóf Umann Out << "Unknown call (type " << getKindAsString() << ")";
34372ce8e2dSJordan Rose }
34472ce8e2dSJordan Rose
isCallStmt(const Stmt * S)345e537cc05SJordan Rose bool CallEvent::isCallStmt(const Stmt *S) {
34616be17adSBalazs Benics return isa<CallExpr, ObjCMessageExpr, CXXConstructExpr, CXXNewExpr>(S);
3474f7df9beSJordan Rose }
3484f7df9beSJordan Rose
getDeclaredResultType(const Decl * D)3495d2964e7SAnna Zaks QualType CallEvent::getDeclaredResultType(const Decl *D) {
3505d2964e7SAnna Zaks assert(D);
3515bc81eb9SEugene Zelenko if (const auto *FD = dyn_cast<FunctionDecl>(D))
352314cc81bSAlp Toker return FD->getReturnType();
3535bc81eb9SEugene Zelenko if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
354314cc81bSAlp Toker return MD->getReturnType();
3555bc81eb9SEugene Zelenko if (const auto *BD = dyn_cast<BlockDecl>(D)) {
356add14263SJordan Rose // Blocks are difficult because the return type may not be stored in the
357add14263SJordan Rose // BlockDecl itself. The AST should probably be enhanced, but for now we
358add14263SJordan Rose // just do what we can.
359278d9de3SJordan Rose // If the block is declared without an explicit argument list, the
360278d9de3SJordan Rose // signature-as-written just includes the return type, not the entire
361278d9de3SJordan Rose // function type.
3621bfe9c78SJordan Rose // FIXME: All blocks should have signatures-as-written, even if the return
363278d9de3SJordan Rose // type is inferred. (That's signified with a dependent result type.)
3641bfe9c78SJordan Rose if (const TypeSourceInfo *TSI = BD->getSignatureAsWritten()) {
365278d9de3SJordan Rose QualType Ty = TSI->getType();
366278d9de3SJordan Rose if (const FunctionType *FT = Ty->getAs<FunctionType>())
367314cc81bSAlp Toker Ty = FT->getReturnType();
368278d9de3SJordan Rose if (!Ty->isDependentType())
369278d9de3SJordan Rose return Ty;
3701bfe9c78SJordan Rose }
371add14263SJordan Rose
3725bc81eb9SEugene Zelenko return {};
373add14263SJordan Rose }
374add14263SJordan Rose
3753553bb38SJordan Rose llvm_unreachable("unknown callable kind");
3763553bb38SJordan Rose }
3773553bb38SJordan Rose
isVariadic(const Decl * D)3783553bb38SJordan Rose bool CallEvent::isVariadic(const Decl *D) {
3793553bb38SJordan Rose assert(D);
3803553bb38SJordan Rose
3815bc81eb9SEugene Zelenko if (const auto *FD = dyn_cast<FunctionDecl>(D))
3823553bb38SJordan Rose return FD->isVariadic();
3835bc81eb9SEugene Zelenko if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
3843553bb38SJordan Rose return MD->isVariadic();
3855bc81eb9SEugene Zelenko if (const auto *BD = dyn_cast<BlockDecl>(D))
3863553bb38SJordan Rose return BD->isVariadic();
3873553bb38SJordan Rose
3883553bb38SJordan Rose llvm_unreachable("unknown callable kind");
3895d2964e7SAnna Zaks }
3905d2964e7SAnna Zaks
isTransparentUnion(QualType T)391d6461571SValeriy Savchenko static bool isTransparentUnion(QualType T) {
392d6461571SValeriy Savchenko const RecordType *UT = T->getAsUnionType();
393d6461571SValeriy Savchenko return UT && UT->getDecl()->hasAttr<TransparentUnionAttr>();
394d6461571SValeriy Savchenko }
395d6461571SValeriy Savchenko
396d6461571SValeriy Savchenko // In some cases, symbolic cases should be transformed before we associate
397d6461571SValeriy Savchenko // them with parameters. This function incapsulates such cases.
processArgument(SVal Value,const Expr * ArgumentExpr,const ParmVarDecl * Parameter,SValBuilder & SVB)398d6461571SValeriy Savchenko static SVal processArgument(SVal Value, const Expr *ArgumentExpr,
399d6461571SValeriy Savchenko const ParmVarDecl *Parameter, SValBuilder &SVB) {
400d6461571SValeriy Savchenko QualType ParamType = Parameter->getType();
401d6461571SValeriy Savchenko QualType ArgumentType = ArgumentExpr->getType();
402d6461571SValeriy Savchenko
403d6461571SValeriy Savchenko // Transparent unions allow users to easily convert values of union field
404d6461571SValeriy Savchenko // types into union-typed objects.
405d6461571SValeriy Savchenko //
406d6461571SValeriy Savchenko // Also, more importantly, they allow users to define functions with different
407d6461571SValeriy Savchenko // different parameter types, substituting types matching transparent union
408d6461571SValeriy Savchenko // field types with the union type itself.
409d6461571SValeriy Savchenko //
410d6461571SValeriy Savchenko // Here, we check specifically for latter cases and prevent binding
411d6461571SValeriy Savchenko // field-typed values to union-typed regions.
412d6461571SValeriy Savchenko if (isTransparentUnion(ParamType) &&
413d6461571SValeriy Savchenko // Let's check that we indeed trying to bind different types.
414d6461571SValeriy Savchenko !isTransparentUnion(ArgumentType)) {
415d6461571SValeriy Savchenko BasicValueFactory &BVF = SVB.getBasicValueFactory();
416d6461571SValeriy Savchenko
417d6461571SValeriy Savchenko llvm::ImmutableList<SVal> CompoundSVals = BVF.getEmptySValList();
418d6461571SValeriy Savchenko CompoundSVals = BVF.prependSVal(Value, CompoundSVals);
419d6461571SValeriy Savchenko
420d6461571SValeriy Savchenko // Wrap it with compound value.
421d6461571SValeriy Savchenko return SVB.makeCompoundVal(ParamType, CompoundSVals);
422d6461571SValeriy Savchenko }
423d6461571SValeriy Savchenko
424d6461571SValeriy Savchenko return Value;
425d6461571SValeriy Savchenko }
426d6461571SValeriy Savchenko
addParameterValuesToBindings(const StackFrameContext * CalleeCtx,CallEvent::BindingsTy & Bindings,SValBuilder & SVB,const CallEvent & Call,ArrayRef<ParmVarDecl * > parameters)42742e8d649SJordan Rose static void addParameterValuesToBindings(const StackFrameContext *CalleeCtx,
42842e8d649SJordan Rose CallEvent::BindingsTy &Bindings,
42942e8d649SJordan Rose SValBuilder &SVB,
43042e8d649SJordan Rose const CallEvent &Call,
4312ff16004STed Kremenek ArrayRef<ParmVarDecl*> parameters) {
43242e8d649SJordan Rose MemRegionManager &MRMgr = SVB.getRegionManager();
4334f7df9beSJordan Rose
434963f91b3SPavel Labath // If the function has fewer parameters than the call has arguments, we simply
435963f91b3SPavel Labath // do not bind any values to them.
436963f91b3SPavel Labath unsigned NumArgs = Call.getNumArgs();
43742e8d649SJordan Rose unsigned Idx = 0;
4382ff16004STed Kremenek ArrayRef<ParmVarDecl*>::iterator I = parameters.begin(), E = parameters.end();
439963f91b3SPavel Labath for (; I != E && Idx < NumArgs; ++I, ++Idx) {
4400cd4d47cSKadir Cetinkaya assert(*I && "Formal parameter has no decl?");
4414f7df9beSJordan Rose
442fcf107d4SArtem Dergachev // TODO: Support allocator calls.
4433ccf14ebSArtem Dergachev if (Call.getKind() != CE_CXXAllocator)
444be86fdb8SArtem Dergachev if (Call.isArgumentConstructedDirectly(Call.getASTArgumentIndex(Idx)))
4453ccf14ebSArtem Dergachev continue;
4463ccf14ebSArtem Dergachev
447fcf107d4SArtem Dergachev // TODO: Allocators should receive the correct size and possibly alignment,
448fcf107d4SArtem Dergachev // determined in compile-time but not represented as arg-expressions,
449fcf107d4SArtem Dergachev // which makes getArgSVal() fail and return UnknownVal.
45042e8d649SJordan Rose SVal ArgVal = Call.getArgSVal(Idx);
451d6461571SValeriy Savchenko const Expr *ArgExpr = Call.getArgExpr(Idx);
45242e8d649SJordan Rose if (!ArgVal.isUnknown()) {
45398db1f99SAdam Balogh Loc ParamLoc = SVB.makeLoc(
45498db1f99SAdam Balogh MRMgr.getParamVarRegion(Call.getOriginExpr(), Idx, CalleeCtx));
455d6461571SValeriy Savchenko Bindings.push_back(
456d6461571SValeriy Savchenko std::make_pair(ParamLoc, processArgument(ArgVal, ArgExpr, *I, SVB)));
45742e8d649SJordan Rose }
4584f7df9beSJordan Rose }
4594f7df9beSJordan Rose
46042e8d649SJordan Rose // FIXME: Variadic arguments are not handled at all right now.
46142e8d649SJordan Rose }
46242e8d649SJordan Rose
getConstructionContext() const463813734daSAdam Balogh const ConstructionContext *CallEvent::getConstructionContext() const {
464813734daSAdam Balogh const StackFrameContext *StackFrame = getCalleeStackFrame(0);
465813734daSAdam Balogh if (!StackFrame)
466813734daSAdam Balogh return nullptr;
467813734daSAdam Balogh
468813734daSAdam Balogh const CFGElement Element = StackFrame->getCallSiteCFGElement();
469813734daSAdam Balogh if (const auto Ctor = Element.getAs<CFGConstructor>()) {
470813734daSAdam Balogh return Ctor->getConstructionContext();
471813734daSAdam Balogh }
472813734daSAdam Balogh
473813734daSAdam Balogh if (const auto RecCall = Element.getAs<CFGCXXRecordTypedCall>()) {
474813734daSAdam Balogh return RecCall->getConstructionContext();
475813734daSAdam Balogh }
476813734daSAdam Balogh
477813734daSAdam Balogh return nullptr;
478813734daSAdam Balogh }
479813734daSAdam Balogh
480813734daSAdam Balogh Optional<SVal>
getReturnValueUnderConstruction() const481813734daSAdam Balogh CallEvent::getReturnValueUnderConstruction() const {
482813734daSAdam Balogh const auto *CC = getConstructionContext();
483813734daSAdam Balogh if (!CC)
484813734daSAdam Balogh return None;
485813734daSAdam Balogh
48637c1bf21SNithin Vadukkumchery Rajendrakumar EvalCallOptions CallOpts;
487813734daSAdam Balogh ExprEngine &Engine = getState()->getStateManager().getOwningEngine();
488813734daSAdam Balogh SVal RetVal =
489813734daSAdam Balogh Engine.computeObjectUnderConstruction(getOriginExpr(), getState(),
490813734daSAdam Balogh getLocationContext(), CC, CallOpts);
491813734daSAdam Balogh return RetVal;
492813734daSAdam Balogh }
493813734daSAdam Balogh
parameters() const4942ff16004STed Kremenek ArrayRef<ParmVarDecl*> AnyFunctionCall::parameters() const {
49542e8d649SJordan Rose const FunctionDecl *D = getDecl();
4964f7df9beSJordan Rose if (!D)
49700bbdcf9SCraig Topper return None;
4982ff16004STed Kremenek return D->parameters();
49942e8d649SJordan Rose }
50042e8d649SJordan Rose
getRuntimeDefinition() const5017b9cf1c4SGeorge Karpenkov RuntimeDefinition AnyFunctionCall::getRuntimeDefinition() const {
5027b9cf1c4SGeorge Karpenkov const FunctionDecl *FD = getDecl();
503ca7923abSGabor Horvath if (!FD)
504ca7923abSGabor Horvath return {};
505ca7923abSGabor Horvath
5067b9cf1c4SGeorge Karpenkov // Note that the AnalysisDeclContext will have the FunctionDecl with
5077b9cf1c4SGeorge Karpenkov // the definition (if one exists).
5087b9cf1c4SGeorge Karpenkov AnalysisDeclContext *AD =
5097b9cf1c4SGeorge Karpenkov getLocationContext()->getAnalysisDeclContext()->
5107b9cf1c4SGeorge Karpenkov getManager()->getContext(FD);
511504e2360SGeorge Karpenkov bool IsAutosynthesized;
512504e2360SGeorge Karpenkov Stmt* Body = AD->getBody(IsAutosynthesized);
5133538b39eSNicola Zaghen LLVM_DEBUG({
514504e2360SGeorge Karpenkov if (IsAutosynthesized)
515504e2360SGeorge Karpenkov llvm::dbgs() << "Using autosynthesized body for " << FD->getName()
516504e2360SGeorge Karpenkov << "\n";
517504e2360SGeorge Karpenkov });
5187b9cf1c4SGeorge Karpenkov
519d70ec366SAdam Balogh ExprEngine &Engine = getState()->getStateManager().getOwningEngine();
52056b9b97cSGabor Marton cross_tu::CrossTranslationUnitContext &CTUCtx =
52156b9b97cSGabor Marton *Engine.getCrossTranslationUnitContext();
52256b9b97cSGabor Marton
52321aa8db6SGabor Horvath AnalyzerOptions &Opts = Engine.getAnalysisManager().options;
5248b9b3bd0SIlya Biryukov
52556b9b97cSGabor Marton if (Body) {
52656b9b97cSGabor Marton const Decl* Decl = AD->getDecl();
52756b9b97cSGabor Marton if (Opts.IsNaiveCTUEnabled && CTUCtx.isImportedAsNew(Decl)) {
52856b9b97cSGabor Marton // A newly created definition, but we had error(s) during the import.
52956b9b97cSGabor Marton if (CTUCtx.hasError(Decl))
53056b9b97cSGabor Marton return {};
53156b9b97cSGabor Marton return RuntimeDefinition(Decl, /*Foreign=*/true);
53256b9b97cSGabor Marton }
53356b9b97cSGabor Marton return RuntimeDefinition(Decl, /*Foreign=*/false);
53456b9b97cSGabor Marton }
53556b9b97cSGabor Marton
5368b9b3bd0SIlya Biryukov // Try to get CTU definition only if CTUDir is provided.
537549f9cd4SKristof Umann if (!Opts.IsNaiveCTUEnabled)
538ca7923abSGabor Horvath return {};
5398b9b3bd0SIlya Biryukov
5408b9b3bd0SIlya Biryukov llvm::Expected<const FunctionDecl *> CTUDeclOrError =
5419419eb42SGabor Marton CTUCtx.getCrossTUDefinition(FD, Opts.CTUDir, Opts.CTUIndexName,
5429419eb42SGabor Marton Opts.DisplayCTUProgress);
5438b9b3bd0SIlya Biryukov
5448b9b3bd0SIlya Biryukov if (!CTUDeclOrError) {
5458b9b3bd0SIlya Biryukov handleAllErrors(CTUDeclOrError.takeError(),
5468b9b3bd0SIlya Biryukov [&](const cross_tu::IndexError &IE) {
5478b9b3bd0SIlya Biryukov CTUCtx.emitCrossTUDiagnostics(IE);
5488b9b3bd0SIlya Biryukov });
5495bc81eb9SEugene Zelenko return {};
5507b9cf1c4SGeorge Karpenkov }
5517b9cf1c4SGeorge Karpenkov
55256b9b97cSGabor Marton return RuntimeDefinition(*CTUDeclOrError, /*Foreign=*/true);
5538b9b3bd0SIlya Biryukov }
5548b9b3bd0SIlya Biryukov
getInitialStackFrameContents(const StackFrameContext * CalleeCtx,BindingsTy & Bindings) const55542e8d649SJordan Rose void AnyFunctionCall::getInitialStackFrameContents(
55642e8d649SJordan Rose const StackFrameContext *CalleeCtx,
55742e8d649SJordan Rose BindingsTy &Bindings) const {
5585bc81eb9SEugene Zelenko const auto *D = cast<FunctionDecl>(CalleeCtx->getDecl());
55942e8d649SJordan Rose SValBuilder &SVB = getState()->getStateManager().getSValBuilder();
56042e8d649SJordan Rose addParameterValuesToBindings(CalleeCtx, Bindings, SVB, *this,
5612ff16004STed Kremenek D->parameters());
5624f7df9beSJordan Rose }
5634f7df9beSJordan Rose
argumentsMayEscape() const5644f7df9beSJordan Rose bool AnyFunctionCall::argumentsMayEscape() const {
565fe1eca51SAnna Zaks if (CallEvent::argumentsMayEscape() || hasVoidPointerToNonConstArg())
5664f7df9beSJordan Rose return true;
5674f7df9beSJordan Rose
5684f7df9beSJordan Rose const FunctionDecl *D = getDecl();
5694f7df9beSJordan Rose if (!D)
5704f7df9beSJordan Rose return true;
5714f7df9beSJordan Rose
5724f7df9beSJordan Rose const IdentifierInfo *II = D->getIdentifier();
5734f7df9beSJordan Rose if (!II)
5747bd0674dSAnna Zaks return false;
5754f7df9beSJordan Rose
5764f7df9beSJordan Rose // This set of "escaping" APIs is
5774f7df9beSJordan Rose
5784f7df9beSJordan Rose // - 'int pthread_setspecific(ptheread_key k, const void *)' stores a
5794f7df9beSJordan Rose // value into thread local storage. The value can later be retrieved with
5804f7df9beSJordan Rose // 'void *ptheread_getspecific(pthread_key)'. So even thought the
5814f7df9beSJordan Rose // parameter is 'const void *', the region escapes through the call.
5824f7df9beSJordan Rose if (II->isStr("pthread_setspecific"))
5834f7df9beSJordan Rose return true;
5844f7df9beSJordan Rose
5854f7df9beSJordan Rose // - xpc_connection_set_context stores a value which can be retrieved later
5864f7df9beSJordan Rose // with xpc_connection_get_context.
5874f7df9beSJordan Rose if (II->isStr("xpc_connection_set_context"))
5884f7df9beSJordan Rose return true;
5894f7df9beSJordan Rose
5904f7df9beSJordan Rose // - funopen - sets a buffer for future IO calls.
5914f7df9beSJordan Rose if (II->isStr("funopen"))
5924f7df9beSJordan Rose return true;
5934f7df9beSJordan Rose
59444cdeb1dSAnna Zaks // - __cxa_demangle - can reallocate memory and can return the pointer to
59544cdeb1dSAnna Zaks // the input buffer.
59644cdeb1dSAnna Zaks if (II->isStr("__cxa_demangle"))
59744cdeb1dSAnna Zaks return true;
59844cdeb1dSAnna Zaks
5994f7df9beSJordan Rose StringRef FName = II->getName();
6004f7df9beSJordan Rose
6014f7df9beSJordan Rose // - CoreFoundation functions that end with "NoCopy" can free a passed-in
6024f7df9beSJordan Rose // buffer even if it is const.
6034f7df9beSJordan Rose if (FName.endswith("NoCopy"))
6044f7df9beSJordan Rose return true;
6054f7df9beSJordan Rose
6064f7df9beSJordan Rose // - NSXXInsertXX, for example NSMapInsertIfAbsent, since they can
6074f7df9beSJordan Rose // be deallocated by NSMapRemove.
6080abb5d29SKazu Hirata if (FName.startswith("NS") && FName.contains("Insert"))
6094f7df9beSJordan Rose return true;
6104f7df9beSJordan Rose
6114f7df9beSJordan Rose // - Many CF containers allow objects to escape through custom
6124f7df9beSJordan Rose // allocators/deallocators upon container construction. (PR12101)
6134f7df9beSJordan Rose if (FName.startswith("CF") || FName.startswith("CG")) {
6144f7df9beSJordan Rose return StrInStrNoCase(FName, "InsertValue") != StringRef::npos ||
6154f7df9beSJordan Rose StrInStrNoCase(FName, "AddValue") != StringRef::npos ||
6164f7df9beSJordan Rose StrInStrNoCase(FName, "SetValue") != StringRef::npos ||
6174f7df9beSJordan Rose StrInStrNoCase(FName, "WithData") != StringRef::npos ||
6184f7df9beSJordan Rose StrInStrNoCase(FName, "AppendValue") != StringRef::npos ||
6194f7df9beSJordan Rose StrInStrNoCase(FName, "SetAttribute") != StringRef::npos;
6204f7df9beSJordan Rose }
6214f7df9beSJordan Rose
6224f7df9beSJordan Rose return false;
6234f7df9beSJordan Rose }
6244f7df9beSJordan Rose
getDecl() const6252a833ca5SJordan Rose const FunctionDecl *SimpleFunctionCall::getDecl() const {
6264f7df9beSJordan Rose const FunctionDecl *D = getOriginExpr()->getDirectCallee();
6274f7df9beSJordan Rose if (D)
6284f7df9beSJordan Rose return D;
6294f7df9beSJordan Rose
6304f7df9beSJordan Rose return getSVal(getOriginExpr()->getCallee()).getAsFunctionDecl();
6314f7df9beSJordan Rose }
6324f7df9beSJordan Rose
getDecl() const633ce6c99a5SJordan Rose const FunctionDecl *CXXInstanceCall::getDecl() const {
6345bc81eb9SEugene Zelenko const auto *CE = cast_or_null<CallExpr>(getOriginExpr());
635ce6c99a5SJordan Rose if (!CE)
636ce6c99a5SJordan Rose return AnyFunctionCall::getDecl();
637ce6c99a5SJordan Rose
638ce6c99a5SJordan Rose const FunctionDecl *D = CE->getDirectCallee();
639ce6c99a5SJordan Rose if (D)
640ce6c99a5SJordan Rose return D;
641ce6c99a5SJordan Rose
642ce6c99a5SJordan Rose return getSVal(CE->getCallee()).getAsFunctionDecl();
643ce6c99a5SJordan Rose }
644ce6c99a5SJordan Rose
getExtraInvalidatedValues(ValueList & Values,RegionAndSymbolInvalidationTraits * ETraits) const64500e780e1SSean Eveson void CXXInstanceCall::getExtraInvalidatedValues(
64600e780e1SSean Eveson ValueList &Values, RegionAndSymbolInvalidationTraits *ETraits) const {
6474f770deeSDevin Coughlin SVal ThisVal = getCXXThisVal();
6484f770deeSDevin Coughlin Values.push_back(ThisVal);
6494f770deeSDevin Coughlin
6503f072ef8SSean Eveson // Don't invalidate if the method is const and there are no mutable fields.
6515bc81eb9SEugene Zelenko if (const auto *D = cast_or_null<CXXMethodDecl>(getDecl())) {
6524f770deeSDevin Coughlin if (!D->isConst())
6534f770deeSDevin Coughlin return;
6544f770deeSDevin Coughlin // Get the record decl for the class of 'This'. D->getParent() may return a
6554f770deeSDevin Coughlin // base class decl, rather than the class of the instance which needs to be
6564f770deeSDevin Coughlin // checked for mutable fields.
657f74ef4b1SArtem Dergachev // TODO: We might as well look at the dynamic type of the object.
6581a7a2cd7SEduardo Caldas const Expr *Ex = getCXXThisExpr()->IgnoreParenBaseCasts();
659f74ef4b1SArtem Dergachev QualType T = Ex->getType();
660f74ef4b1SArtem Dergachev if (T->isPointerType()) // Arrow or implicit-this syntax?
661f74ef4b1SArtem Dergachev T = T->getPointeeType();
662f74ef4b1SArtem Dergachev const CXXRecordDecl *ParentRecord = T->getAsCXXRecordDecl();
663f74ef4b1SArtem Dergachev assert(ParentRecord);
664f74ef4b1SArtem Dergachev if (ParentRecord->hasMutableFields())
6654f770deeSDevin Coughlin return;
6664f770deeSDevin Coughlin // Preserve CXXThis.
6674f770deeSDevin Coughlin const MemRegion *ThisRegion = ThisVal.getAsRegion();
6689c76869bSDevin Coughlin if (!ThisRegion)
6699c76869bSDevin Coughlin return;
6709c76869bSDevin Coughlin
6714f770deeSDevin Coughlin ETraits->setTrait(ThisRegion->getBaseRegion(),
6724f770deeSDevin Coughlin RegionAndSymbolInvalidationTraits::TK_PreserveContents);
6734f770deeSDevin Coughlin }
6744f7df9beSJordan Rose }
6754f7df9beSJordan Rose
getCXXThisVal() const676fcdda361SJordan Rose SVal CXXInstanceCall::getCXXThisVal() const {
677fcdda361SJordan Rose const Expr *Base = getCXXThisExpr();
678fcdda361SJordan Rose // FIXME: This doesn't handle an overloaded ->* operator.
679fcdda361SJordan Rose if (!Base)
680fcdda361SJordan Rose return UnknownVal();
681fcdda361SJordan Rose
682fcdda361SJordan Rose SVal ThisVal = getSVal(Base);
68396ccb690SBalazs Benics assert(ThisVal.isUnknownOrUndef() || isa<Loc>(ThisVal));
684fcdda361SJordan Rose return ThisVal;
685fcdda361SJordan Rose }
686fcdda361SJordan Rose
getRuntimeDefinition() const687089c5510STed Kremenek RuntimeDefinition CXXInstanceCall::getRuntimeDefinition() const {
6880f6d63beSJordan Rose // Do we have a decl at all?
68951bcb226SJordan Rose const Decl *D = getDecl();
6904f7df9beSJordan Rose if (!D)
6915bc81eb9SEugene Zelenko return {};
6924f7df9beSJordan Rose
6930f6d63beSJordan Rose // If the method is non-virtual, we know we can inline it.
6945bc81eb9SEugene Zelenko const auto *MD = cast<CXXMethodDecl>(D);
6954f7df9beSJordan Rose if (!MD->isVirtual())
696089c5510STed Kremenek return AnyFunctionCall::getRuntimeDefinition();
6974f7df9beSJordan Rose
6980f6d63beSJordan Rose // Do we know the implicit 'this' object being called?
6990f6d63beSJordan Rose const MemRegion *R = getCXXThisVal().getAsRegion();
7000f6d63beSJordan Rose if (!R)
7015bc81eb9SEugene Zelenko return {};
7020f6d63beSJordan Rose
7030f6d63beSJordan Rose // Do we know anything about the type of 'this'?
7044df9d812SGabor Horvath DynamicTypeInfo DynType = getDynamicTypeInfo(getState(), R);
7050f6d63beSJordan Rose if (!DynType.isValid())
7065bc81eb9SEugene Zelenko return {};
7070f6d63beSJordan Rose
7080f6d63beSJordan Rose // Is the type a C++ class? (This is mostly a defensive check.)
7090f6d63beSJordan Rose QualType RegionType = DynType.getType()->getPointeeType();
710d1a08b6eSJordan Rose assert(!RegionType.isNull() && "DynamicTypeInfo should always be a pointer.");
711d1a08b6eSJordan Rose
7120f6d63beSJordan Rose const CXXRecordDecl *RD = RegionType->getAsCXXRecordDecl();
71399107208SJordan Rose if (!RD || !RD->hasDefinition())
7145bc81eb9SEugene Zelenko return {};
7150f6d63beSJordan Rose
71699c6c2b4SJordan Rose // Find the decl for this method in that class.
71799c6c2b4SJordan Rose const CXXMethodDecl *Result = MD->getCorrespondingMethodInClass(RD, true);
71881456d9fSJordan Rose if (!Result) {
71981456d9fSJordan Rose // We might not even get the original statically-resolved method due to
72081456d9fSJordan Rose // some particularly nasty casting (e.g. casts to sister classes).
72181456d9fSJordan Rose // However, we should at least be able to search up and down our own class
72281456d9fSJordan Rose // hierarchy, and some real bugs have been caught by checking this.
72381456d9fSJordan Rose assert(!RD->isDerivedFrom(MD->getParent()) && "Couldn't find known method");
724d44977efSJordan Rose
725d44977efSJordan Rose // FIXME: This is checking that our DynamicTypeInfo is at least as good as
726d44977efSJordan Rose // the static type. However, because we currently don't update
727d44977efSJordan Rose // DynamicTypeInfo when an object is cast, we can't actually be sure the
728d44977efSJordan Rose // DynamicTypeInfo is up to date. This assert should be re-enabled once
729d44977efSJordan Rose // this is fixed. <rdar://problem/12287087>
730d44977efSJordan Rose //assert(!MD->getParent()->isDerivedFrom(RD) && "Bad DynamicTypeInfo");
731d44977efSJordan Rose
7325bc81eb9SEugene Zelenko return {};
73381456d9fSJordan Rose }
7340f6d63beSJordan Rose
7350f6d63beSJordan Rose // Does the decl that we found have an implementation?
7360f6d63beSJordan Rose const FunctionDecl *Definition;
737e712295fSGabor Marton if (!Result->hasBody(Definition)) {
738e712295fSGabor Marton if (!DynType.canBeASubClass())
739e712295fSGabor Marton return AnyFunctionCall::getRuntimeDefinition();
7405bc81eb9SEugene Zelenko return {};
741e712295fSGabor Marton }
7420f6d63beSJordan Rose
7430f6d63beSJordan Rose // We found a definition. If we're not sure that this devirtualization is
7440f6d63beSJordan Rose // actually what will happen at runtime, make sure to provide the region so
7450f6d63beSJordan Rose // that ExprEngine can decide what to do with it.
7460f6d63beSJordan Rose if (DynType.canBeASubClass())
7470f6d63beSJordan Rose return RuntimeDefinition(Definition, R->StripCasts());
7480dbb783cSCraig Topper return RuntimeDefinition(Definition, /*DispatchRegion=*/nullptr);
7494f7df9beSJordan Rose }
7504f7df9beSJordan Rose
getInitialStackFrameContents(const StackFrameContext * CalleeCtx,BindingsTy & Bindings) const75142e8d649SJordan Rose void CXXInstanceCall::getInitialStackFrameContents(
75242e8d649SJordan Rose const StackFrameContext *CalleeCtx,
75342e8d649SJordan Rose BindingsTy &Bindings) const {
75442e8d649SJordan Rose AnyFunctionCall::getInitialStackFrameContents(CalleeCtx, Bindings);
75542e8d649SJordan Rose
75602e5309bSJordan Rose // Handle the binding of 'this' in the new stack frame.
75742e8d649SJordan Rose SVal ThisVal = getCXXThisVal();
75842e8d649SJordan Rose if (!ThisVal.isUnknown()) {
75902e5309bSJordan Rose ProgramStateManager &StateMgr = getState()->getStateManager();
76002e5309bSJordan Rose SValBuilder &SVB = StateMgr.getSValBuilder();
76102e5309bSJordan Rose
7625bc81eb9SEugene Zelenko const auto *MD = cast<CXXMethodDecl>(CalleeCtx->getDecl());
76342e8d649SJordan Rose Loc ThisLoc = SVB.getCXXThis(MD, CalleeCtx);
76402e5309bSJordan Rose
76531c3fa9cSJordan Rose // If we devirtualized to a different member function, we need to make sure
76631c3fa9cSJordan Rose // we have the proper layering of CXXBaseObjectRegions.
76731c3fa9cSJordan Rose if (MD->getCanonicalDecl() != getDecl()->getCanonicalDecl()) {
768710f6b12SJordan Rose ASTContext &Ctx = SVB.getContext();
76902e5309bSJordan Rose const CXXRecordDecl *Class = MD->getParent();
770710f6b12SJordan Rose QualType Ty = Ctx.getPointerType(Ctx.getRecordType(Class));
77102e5309bSJordan Rose
772710f6b12SJordan Rose // FIXME: CallEvent maybe shouldn't be directly accessing StoreManager.
773da8bd972SDenys Petrov Optional<SVal> V =
774da8bd972SDenys Petrov StateMgr.getStoreManager().evalBaseToDerived(ThisVal, Ty);
775452db157SKazu Hirata if (!V) {
776f01831ebSArtem Dergachev // We might have suffered some sort of placement new earlier, so
777f01831ebSArtem Dergachev // we're constructing in a completely unexpected storage.
778f01831ebSArtem Dergachev // Fall back to a generic pointer cast for this-value.
779f01831ebSArtem Dergachev const CXXMethodDecl *StaticMD = cast<CXXMethodDecl>(getDecl());
780f01831ebSArtem Dergachev const CXXRecordDecl *StaticClass = StaticMD->getParent();
781f01831ebSArtem Dergachev QualType StaticTy = Ctx.getPointerType(Ctx.getRecordType(StaticClass));
782f01831ebSArtem Dergachev ThisVal = SVB.evalCast(ThisVal, Ty, StaticTy);
783da8bd972SDenys Petrov } else
784da8bd972SDenys Petrov ThisVal = *V;
78502e5309bSJordan Rose }
78602e5309bSJordan Rose
78731c3fa9cSJordan Rose if (!ThisVal.isUnknown())
78842e8d649SJordan Rose Bindings.push_back(std::make_pair(ThisLoc, ThisVal));
78942e8d649SJordan Rose }
79042e8d649SJordan Rose }
79142e8d649SJordan Rose
getCXXThisExpr() const79292e1449bSJordan Rose const Expr *CXXMemberCall::getCXXThisExpr() const {
79392e1449bSJordan Rose return getOriginExpr()->getImplicitObjectArgument();
7944f7df9beSJordan Rose }
7954f7df9beSJordan Rose
getRuntimeDefinition() const796089c5510STed Kremenek RuntimeDefinition CXXMemberCall::getRuntimeDefinition() const {
79712f669e3SJordan Rose // C++11 [expr.call]p1: ...If the selected function is non-virtual, or if the
79812f669e3SJordan Rose // id-expression in the class member access expression is a qualified-id,
79912f669e3SJordan Rose // that function is called. Otherwise, its final overrider in the dynamic type
80012f669e3SJordan Rose // of the object expression is called.
8015bc81eb9SEugene Zelenko if (const auto *ME = dyn_cast<MemberExpr>(getOriginExpr()->getCallee()))
80212f669e3SJordan Rose if (ME->hasQualifier())
803089c5510STed Kremenek return AnyFunctionCall::getRuntimeDefinition();
80412f669e3SJordan Rose
805089c5510STed Kremenek return CXXInstanceCall::getRuntimeDefinition();
80612f669e3SJordan Rose }
80712f669e3SJordan Rose
getCXXThisExpr() const80892e1449bSJordan Rose const Expr *CXXMemberOperatorCall::getCXXThisExpr() const {
80992e1449bSJordan Rose return getOriginExpr()->getArg(0);
8104f7df9beSJordan Rose }
8114f7df9beSJordan Rose
getBlockRegion() const8124f7df9beSJordan Rose const BlockDataRegion *BlockCall::getBlockRegion() const {
8134f7df9beSJordan Rose const Expr *Callee = getOriginExpr()->getCallee();
8144f7df9beSJordan Rose const MemRegion *DataReg = getSVal(Callee).getAsRegion();
8154f7df9beSJordan Rose
8164f7df9beSJordan Rose return dyn_cast_or_null<BlockDataRegion>(DataReg);
8174f7df9beSJordan Rose }
8184f7df9beSJordan Rose
parameters() const8192ff16004STed Kremenek ArrayRef<ParmVarDecl*> BlockCall::parameters() const {
8202a833ca5SJordan Rose const BlockDecl *D = getDecl();
8214f7df9beSJordan Rose if (!D)
82246f34624SArtem Dergachev return None;
8232ff16004STed Kremenek return D->parameters();
8244f7df9beSJordan Rose }
8254f7df9beSJordan Rose
getExtraInvalidatedValues(ValueList & Values,RegionAndSymbolInvalidationTraits * ETraits) const8264f770deeSDevin Coughlin void BlockCall::getExtraInvalidatedValues(ValueList &Values,
8274f770deeSDevin Coughlin RegionAndSymbolInvalidationTraits *ETraits) const {
8284f7df9beSJordan Rose // FIXME: This also needs to invalidate captured globals.
8294f7df9beSJordan Rose if (const MemRegion *R = getBlockRegion())
83060bf5f45SAnna Zaks Values.push_back(loc::MemRegionVal(R));
8314f7df9beSJordan Rose }
8324f7df9beSJordan Rose
getInitialStackFrameContents(const StackFrameContext * CalleeCtx,BindingsTy & Bindings) const83342e8d649SJordan Rose void BlockCall::getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
83442e8d649SJordan Rose BindingsTy &Bindings) const {
83542e8d649SJordan Rose SValBuilder &SVB = getState()->getStateManager().getSValBuilder();
836ebeed880SDevin Coughlin ArrayRef<ParmVarDecl*> Params;
837ebeed880SDevin Coughlin if (isConversionFromLambda()) {
838ebeed880SDevin Coughlin auto *LambdaOperatorDecl = cast<CXXMethodDecl>(CalleeCtx->getDecl());
839ebeed880SDevin Coughlin Params = LambdaOperatorDecl->parameters();
840ebeed880SDevin Coughlin
841ebeed880SDevin Coughlin // For blocks converted from a C++ lambda, the callee declaration is the
8425690454bSSanjay Patel // operator() method on the lambda so we bind "this" to
843ebeed880SDevin Coughlin // the lambda captured by the block.
844ebeed880SDevin Coughlin const VarRegion *CapturedLambdaRegion = getRegionStoringCapturedLambda();
845ebeed880SDevin Coughlin SVal ThisVal = loc::MemRegionVal(CapturedLambdaRegion);
846ebeed880SDevin Coughlin Loc ThisLoc = SVB.getCXXThis(LambdaOperatorDecl, CalleeCtx);
847ebeed880SDevin Coughlin Bindings.push_back(std::make_pair(ThisLoc, ThisVal));
848ebeed880SDevin Coughlin } else {
849ebeed880SDevin Coughlin Params = cast<BlockDecl>(CalleeCtx->getDecl())->parameters();
850ebeed880SDevin Coughlin }
851ebeed880SDevin Coughlin
85242e8d649SJordan Rose addParameterValuesToBindings(CalleeCtx, Bindings, SVB, *this,
853ebeed880SDevin Coughlin Params);
85442e8d649SJordan Rose }
85542e8d649SJordan Rose
getCXXThisVal() const856a82ffe9dSArtem Dergachev SVal AnyCXXConstructorCall::getCXXThisVal() const {
8574f7df9beSJordan Rose if (Data)
8584f7df9beSJordan Rose return loc::MemRegionVal(static_cast<const MemRegion *>(Data));
8594f7df9beSJordan Rose return UnknownVal();
8604f7df9beSJordan Rose }
8614f7df9beSJordan Rose
getExtraInvalidatedValues(ValueList & Values,RegionAndSymbolInvalidationTraits * ETraits) const862a82ffe9dSArtem Dergachev void AnyCXXConstructorCall::getExtraInvalidatedValues(ValueList &Values,
8634f770deeSDevin Coughlin RegionAndSymbolInvalidationTraits *ETraits) const {
864a82ffe9dSArtem Dergachev SVal V = getCXXThisVal();
865a82ffe9dSArtem Dergachev if (SymbolRef Sym = V.getAsSymbol(true))
8660c79eab0SArtem Dergachev ETraits->setTrait(Sym,
8670c79eab0SArtem Dergachev RegionAndSymbolInvalidationTraits::TK_SuppressEscape);
868a82ffe9dSArtem Dergachev Values.push_back(V);
8694f7df9beSJordan Rose }
8704f7df9beSJordan Rose
getInitialStackFrameContents(const StackFrameContext * CalleeCtx,BindingsTy & Bindings) const871a82ffe9dSArtem Dergachev void AnyCXXConstructorCall::getInitialStackFrameContents(
87242e8d649SJordan Rose const StackFrameContext *CalleeCtx,
87342e8d649SJordan Rose BindingsTy &Bindings) const {
87442e8d649SJordan Rose AnyFunctionCall::getInitialStackFrameContents(CalleeCtx, Bindings);
87542e8d649SJordan Rose
87642e8d649SJordan Rose SVal ThisVal = getCXXThisVal();
87742e8d649SJordan Rose if (!ThisVal.isUnknown()) {
87842e8d649SJordan Rose SValBuilder &SVB = getState()->getStateManager().getSValBuilder();
8795bc81eb9SEugene Zelenko const auto *MD = cast<CXXMethodDecl>(CalleeCtx->getDecl());
88042e8d649SJordan Rose Loc ThisLoc = SVB.getCXXThis(MD, CalleeCtx);
88142e8d649SJordan Rose Bindings.push_back(std::make_pair(ThisLoc, ThisVal));
88242e8d649SJordan Rose }
88342e8d649SJordan Rose }
88442e8d649SJordan Rose
885a82ffe9dSArtem Dergachev const StackFrameContext *
getInheritingStackFrame() const886a82ffe9dSArtem Dergachev CXXInheritedConstructorCall::getInheritingStackFrame() const {
887a82ffe9dSArtem Dergachev const StackFrameContext *SFC = getLocationContext()->getStackFrame();
888a82ffe9dSArtem Dergachev while (isa<CXXInheritedCtorInitExpr>(SFC->getCallSite()))
889a82ffe9dSArtem Dergachev SFC = SFC->getParent()->getStackFrame();
890a82ffe9dSArtem Dergachev return SFC;
891a82ffe9dSArtem Dergachev }
892a82ffe9dSArtem Dergachev
getCXXThisVal() const8934f7df9beSJordan Rose SVal CXXDestructorCall::getCXXThisVal() const {
8944f7df9beSJordan Rose if (Data)
8952bc9674bSJordan Rose return loc::MemRegionVal(DtorDataTy::getFromOpaqueValue(Data).getPointer());
8964f7df9beSJordan Rose return UnknownVal();
8974f7df9beSJordan Rose }
8984f7df9beSJordan Rose
getRuntimeDefinition() const899089c5510STed Kremenek RuntimeDefinition CXXDestructorCall::getRuntimeDefinition() const {
9002bc9674bSJordan Rose // Base destructors are always called non-virtually.
9012bc9674bSJordan Rose // Skip CXXInstanceCall's devirtualization logic in this case.
9022bc9674bSJordan Rose if (isBaseDestructor())
903089c5510STed Kremenek return AnyFunctionCall::getRuntimeDefinition();
9042bc9674bSJordan Rose
905089c5510STed Kremenek return CXXInstanceCall::getRuntimeDefinition();
9062bc9674bSJordan Rose }
9072bc9674bSJordan Rose
parameters() const9082ff16004STed Kremenek ArrayRef<ParmVarDecl*> ObjCMethodCall::parameters() const {
90942e8d649SJordan Rose const ObjCMethodDecl *D = getDecl();
9104f7df9beSJordan Rose if (!D)
9115fc8fc2dSCraig Topper return None;
9122ff16004STed Kremenek return D->parameters();
9134f7df9beSJordan Rose }
9144f7df9beSJordan Rose
getExtraInvalidatedValues(ValueList & Values,RegionAndSymbolInvalidationTraits * ETraits) const915069a1073SDevin Coughlin void ObjCMethodCall::getExtraInvalidatedValues(
916069a1073SDevin Coughlin ValueList &Values, RegionAndSymbolInvalidationTraits *ETraits) const {
917069a1073SDevin Coughlin
918069a1073SDevin Coughlin // If the method call is a setter for property known to be backed by
919069a1073SDevin Coughlin // an instance variable, don't invalidate the entire receiver, just
920069a1073SDevin Coughlin // the storage for that instance variable.
921069a1073SDevin Coughlin if (const ObjCPropertyDecl *PropDecl = getAccessedProperty()) {
922069a1073SDevin Coughlin if (const ObjCIvarDecl *PropIvar = PropDecl->getPropertyIvarDecl()) {
923069a1073SDevin Coughlin SVal IvarLVal = getState()->getLValue(PropIvar, getReceiverSVal());
9245f24c12dSAlexander Shaposhnikov if (const MemRegion *IvarRegion = IvarLVal.getAsRegion()) {
925069a1073SDevin Coughlin ETraits->setTrait(
926069a1073SDevin Coughlin IvarRegion,
927069a1073SDevin Coughlin RegionAndSymbolInvalidationTraits::TK_DoNotInvalidateSuperRegion);
9285f24c12dSAlexander Shaposhnikov ETraits->setTrait(
9295f24c12dSAlexander Shaposhnikov IvarRegion,
930069a1073SDevin Coughlin RegionAndSymbolInvalidationTraits::TK_SuppressEscape);
931069a1073SDevin Coughlin Values.push_back(IvarLVal);
9325f24c12dSAlexander Shaposhnikov }
933069a1073SDevin Coughlin return;
934069a1073SDevin Coughlin }
935069a1073SDevin Coughlin }
936069a1073SDevin Coughlin
93760bf5f45SAnna Zaks Values.push_back(getReceiverSVal());
9384f7df9beSJordan Rose }
9394f7df9beSJordan Rose
getReceiverSVal() const9404f7df9beSJordan Rose SVal ObjCMethodCall::getReceiverSVal() const {
9414f7df9beSJordan Rose // FIXME: Is this the best way to handle class receivers?
9424f7df9beSJordan Rose if (!isInstanceMessage())
9434f7df9beSJordan Rose return UnknownVal();
9444f7df9beSJordan Rose
945472dbcf1SAnna Zaks if (const Expr *RecE = getOriginExpr()->getInstanceReceiver())
946472dbcf1SAnna Zaks return getSVal(RecE);
9474f7df9beSJordan Rose
9484f7df9beSJordan Rose // An instance message with no expression means we are sending to super.
9494f7df9beSJordan Rose // In this case the object reference is the same as 'self'.
9503d5d3d3eSAnna Zaks assert(getOriginExpr()->getReceiverKind() == ObjCMessageExpr::SuperInstance);
951239c53b7SValeriy Savchenko SVal SelfVal = getState()->getSelfSVal(getLocationContext());
9523d5d3d3eSAnna Zaks assert(SelfVal.isValid() && "Calling super but not in ObjC method");
9533d5d3d3eSAnna Zaks return SelfVal;
9543d5d3d3eSAnna Zaks }
9553d5d3d3eSAnna Zaks
isReceiverSelfOrSuper() const9563d5d3d3eSAnna Zaks bool ObjCMethodCall::isReceiverSelfOrSuper() const {
9573d5d3d3eSAnna Zaks if (getOriginExpr()->getReceiverKind() == ObjCMessageExpr::SuperInstance ||
9583d5d3d3eSAnna Zaks getOriginExpr()->getReceiverKind() == ObjCMessageExpr::SuperClass)
9593d5d3d3eSAnna Zaks return true;
9603d5d3d3eSAnna Zaks
9613d5d3d3eSAnna Zaks if (!isInstanceMessage())
9623d5d3d3eSAnna Zaks return false;
9633d5d3d3eSAnna Zaks
9643d5d3d3eSAnna Zaks SVal RecVal = getSVal(getOriginExpr()->getInstanceReceiver());
965239c53b7SValeriy Savchenko SVal SelfVal = getState()->getSelfSVal(getLocationContext());
9663d5d3d3eSAnna Zaks
967239c53b7SValeriy Savchenko return (RecVal == SelfVal);
9684f7df9beSJordan Rose }
9694f7df9beSJordan Rose
getSourceRange() const9704f7df9beSJordan Rose SourceRange ObjCMethodCall::getSourceRange() const {
9714f7df9beSJordan Rose switch (getMessageKind()) {
9724f7df9beSJordan Rose case OCM_Message:
9734f7df9beSJordan Rose return getOriginExpr()->getSourceRange();
9744f7df9beSJordan Rose case OCM_PropertyAccess:
9754f7df9beSJordan Rose case OCM_Subscript:
9764f7df9beSJordan Rose return getContainingPseudoObjectExpr()->getSourceRange();
9774f7df9beSJordan Rose }
9784f7df9beSJordan Rose llvm_unreachable("unknown message kind");
9794f7df9beSJordan Rose }
9804f7df9beSJordan Rose
9815bc81eb9SEugene Zelenko using ObjCMessageDataTy = llvm::PointerIntPair<const PseudoObjectExpr *, 2>;
9824f7df9beSJordan Rose
getContainingPseudoObjectExpr() const9834f7df9beSJordan Rose const PseudoObjectExpr *ObjCMethodCall::getContainingPseudoObjectExpr() const {
9840dbb783cSCraig Topper assert(Data && "Lazy lookup not yet performed.");
9854f7df9beSJordan Rose assert(getMessageKind() != OCM_Message && "Explicit message send.");
9864f7df9beSJordan Rose return ObjCMessageDataTy::getFromOpaqueValue(Data).getPointer();
9874f7df9beSJordan Rose }
9884f7df9beSJordan Rose
989069a1073SDevin Coughlin static const Expr *
getSyntacticFromForPseudoObjectExpr(const PseudoObjectExpr * POE)990069a1073SDevin Coughlin getSyntacticFromForPseudoObjectExpr(const PseudoObjectExpr *POE) {
99112cbc8cbSArtem Dergachev const Expr *Syntactic = POE->getSyntacticForm()->IgnoreParens();
992069a1073SDevin Coughlin
993069a1073SDevin Coughlin // This handles the funny case of assigning to the result of a getter.
994069a1073SDevin Coughlin // This can happen if the getter returns a non-const reference.
9955bc81eb9SEugene Zelenko if (const auto *BO = dyn_cast<BinaryOperator>(Syntactic))
99612cbc8cbSArtem Dergachev Syntactic = BO->getLHS()->IgnoreParens();
997069a1073SDevin Coughlin
998069a1073SDevin Coughlin return Syntactic;
999069a1073SDevin Coughlin }
1000069a1073SDevin Coughlin
getMessageKind() const10014f7df9beSJordan Rose ObjCMessageKind ObjCMethodCall::getMessageKind() const {
10020dbb783cSCraig Topper if (!Data) {
1003226a56faSAnna Zaks // Find the parent, ignoring implicit casts.
1004fc76d855SKristof Umann const ParentMap &PM = getLocationContext()->getParentMap();
10055770c038SJordan Rose const Stmt *S = PM.getParentIgnoreParenCasts(getOriginExpr());
1006226a56faSAnna Zaks
1007226a56faSAnna Zaks // Check if parent is a PseudoObjectExpr.
10085bc81eb9SEugene Zelenko if (const auto *POE = dyn_cast_or_null<PseudoObjectExpr>(S)) {
1009069a1073SDevin Coughlin const Expr *Syntactic = getSyntacticFromForPseudoObjectExpr(POE);
10104f7df9beSJordan Rose
10114f7df9beSJordan Rose ObjCMessageKind K;
10124f7df9beSJordan Rose switch (Syntactic->getStmtClass()) {
10134f7df9beSJordan Rose case Stmt::ObjCPropertyRefExprClass:
10144f7df9beSJordan Rose K = OCM_PropertyAccess;
10154f7df9beSJordan Rose break;
10164f7df9beSJordan Rose case Stmt::ObjCSubscriptRefExprClass:
10174f7df9beSJordan Rose K = OCM_Subscript;
10184f7df9beSJordan Rose break;
10194f7df9beSJordan Rose default:
10204f7df9beSJordan Rose // FIXME: Can this ever happen?
10214f7df9beSJordan Rose K = OCM_Message;
10224f7df9beSJordan Rose break;
10234f7df9beSJordan Rose }
10244f7df9beSJordan Rose
10254f7df9beSJordan Rose if (K != OCM_Message) {
10264f7df9beSJordan Rose const_cast<ObjCMethodCall *>(this)->Data
10274f7df9beSJordan Rose = ObjCMessageDataTy(POE, K).getOpaqueValue();
10284f7df9beSJordan Rose assert(getMessageKind() == K);
10294f7df9beSJordan Rose return K;
10304f7df9beSJordan Rose }
10314f7df9beSJordan Rose }
10324f7df9beSJordan Rose
10334f7df9beSJordan Rose const_cast<ObjCMethodCall *>(this)->Data
10340dbb783cSCraig Topper = ObjCMessageDataTy(nullptr, 1).getOpaqueValue();
10354f7df9beSJordan Rose assert(getMessageKind() == OCM_Message);
10364f7df9beSJordan Rose return OCM_Message;
10374f7df9beSJordan Rose }
10384f7df9beSJordan Rose
10394f7df9beSJordan Rose ObjCMessageDataTy Info = ObjCMessageDataTy::getFromOpaqueValue(Data);
10404f7df9beSJordan Rose if (!Info.getPointer())
10414f7df9beSJordan Rose return OCM_Message;
10424f7df9beSJordan Rose return static_cast<ObjCMessageKind>(Info.getInt());
10434f7df9beSJordan Rose }
10444f7df9beSJordan Rose
getAccessedProperty() const1045069a1073SDevin Coughlin const ObjCPropertyDecl *ObjCMethodCall::getAccessedProperty() const {
1046069a1073SDevin Coughlin // Look for properties accessed with property syntax (foo.bar = ...)
1047069a1073SDevin Coughlin if (getMessageKind() == OCM_PropertyAccess) {
1048069a1073SDevin Coughlin const PseudoObjectExpr *POE = getContainingPseudoObjectExpr();
1049069a1073SDevin Coughlin assert(POE && "Property access without PseudoObjectExpr?");
1050069a1073SDevin Coughlin
1051069a1073SDevin Coughlin const Expr *Syntactic = getSyntacticFromForPseudoObjectExpr(POE);
1052069a1073SDevin Coughlin auto *RefExpr = cast<ObjCPropertyRefExpr>(Syntactic);
1053069a1073SDevin Coughlin
1054069a1073SDevin Coughlin if (RefExpr->isExplicitProperty())
1055069a1073SDevin Coughlin return RefExpr->getExplicitProperty();
1056069a1073SDevin Coughlin }
1057069a1073SDevin Coughlin
1058069a1073SDevin Coughlin // Look for properties accessed with method syntax ([foo setBar:...]).
1059069a1073SDevin Coughlin const ObjCMethodDecl *MD = getDecl();
1060069a1073SDevin Coughlin if (!MD || !MD->isPropertyAccessor())
1061069a1073SDevin Coughlin return nullptr;
1062069a1073SDevin Coughlin
1063069a1073SDevin Coughlin // Note: This is potentially quite slow.
1064069a1073SDevin Coughlin return MD->findPropertyDecl();
1065069a1073SDevin Coughlin }
1066920af014SAnna Zaks
canBeOverridenInSubclass(ObjCInterfaceDecl * IDecl,Selector Sel) const1067920af014SAnna Zaks bool ObjCMethodCall::canBeOverridenInSubclass(ObjCInterfaceDecl *IDecl,
1068920af014SAnna Zaks Selector Sel) const {
1069920af014SAnna Zaks assert(IDecl);
1070516837f2SArtem Dergachev AnalysisManager &AMgr =
107121aa8db6SGabor Horvath getState()->getStateManager().getOwningEngine().getAnalysisManager();
1072920af014SAnna Zaks // If the class interface is declared inside the main file, assume it is not
1073920af014SAnna Zaks // subcassed.
1074920af014SAnna Zaks // TODO: It could actually be subclassed if the subclass is private as well.
1075920af014SAnna Zaks // This is probably very rare.
1076920af014SAnna Zaks SourceLocation InterfLoc = IDecl->getEndOfDefinitionLoc();
1077516837f2SArtem Dergachev if (InterfLoc.isValid() && AMgr.isInCodeFile(InterfLoc))
1078920af014SAnna Zaks return false;
1079920af014SAnna Zaks
10806ddb6b1aSAnna Zaks // Assume that property accessors are not overridden.
10816ddb6b1aSAnna Zaks if (getMessageKind() == OCM_PropertyAccess)
10826ddb6b1aSAnna Zaks return false;
1083920af014SAnna Zaks
1084920af014SAnna Zaks // We assume that if the method is public (declared outside of main file) or
1085920af014SAnna Zaks // has a parent which publicly declares the method, the method could be
1086920af014SAnna Zaks // overridden in a subclass.
1087920af014SAnna Zaks
1088920af014SAnna Zaks // Find the first declaration in the class hierarchy that declares
1089920af014SAnna Zaks // the selector.
10900dbb783cSCraig Topper ObjCMethodDecl *D = nullptr;
1091920af014SAnna Zaks while (true) {
1092920af014SAnna Zaks D = IDecl->lookupMethod(Sel, true);
1093920af014SAnna Zaks
1094920af014SAnna Zaks // Cannot find a public definition.
1095920af014SAnna Zaks if (!D)
1096920af014SAnna Zaks return false;
1097920af014SAnna Zaks
1098920af014SAnna Zaks // If outside the main file,
1099516837f2SArtem Dergachev if (D->getLocation().isValid() && !AMgr.isInCodeFile(D->getLocation()))
1100920af014SAnna Zaks return true;
1101920af014SAnna Zaks
1102920af014SAnna Zaks if (D->isOverriding()) {
1103920af014SAnna Zaks // Search in the superclass on the next iteration.
1104920af014SAnna Zaks IDecl = D->getClassInterface();
1105920af014SAnna Zaks if (!IDecl)
1106920af014SAnna Zaks return false;
1107920af014SAnna Zaks
1108920af014SAnna Zaks IDecl = IDecl->getSuperClass();
1109920af014SAnna Zaks if (!IDecl)
1110920af014SAnna Zaks return false;
1111920af014SAnna Zaks
1112920af014SAnna Zaks continue;
1113920af014SAnna Zaks }
1114920af014SAnna Zaks
1115920af014SAnna Zaks return false;
1116920af014SAnna Zaks };
1117920af014SAnna Zaks
1118920af014SAnna Zaks llvm_unreachable("The while loop should always terminate.");
1119920af014SAnna Zaks }
1120920af014SAnna Zaks
findDefiningRedecl(const ObjCMethodDecl * MD)1121dcfc1914SAnna Zaks static const ObjCMethodDecl *findDefiningRedecl(const ObjCMethodDecl *MD) {
1122dcfc1914SAnna Zaks if (!MD)
1123dcfc1914SAnna Zaks return MD;
1124dcfc1914SAnna Zaks
1125dcfc1914SAnna Zaks // Find the redeclaration that defines the method.
1126dcfc1914SAnna Zaks if (!MD->hasBody()) {
1127dcfc1914SAnna Zaks for (auto I : MD->redecls())
1128dcfc1914SAnna Zaks if (I->hasBody())
1129dcfc1914SAnna Zaks MD = cast<ObjCMethodDecl>(I);
1130dcfc1914SAnna Zaks }
1131dcfc1914SAnna Zaks return MD;
1132dcfc1914SAnna Zaks }
1133dcfc1914SAnna Zaks
1134239c53b7SValeriy Savchenko struct PrivateMethodKey {
1135239c53b7SValeriy Savchenko const ObjCInterfaceDecl *Interface;
1136239c53b7SValeriy Savchenko Selector LookupSelector;
1137239c53b7SValeriy Savchenko bool IsClassMethod;
1138239c53b7SValeriy Savchenko };
1139dcfc1914SAnna Zaks
114023f4edf1SValeriy Savchenko namespace llvm {
114123f4edf1SValeriy Savchenko template <> struct DenseMapInfo<PrivateMethodKey> {
1142239c53b7SValeriy Savchenko using InterfaceInfo = DenseMapInfo<const ObjCInterfaceDecl *>;
1143239c53b7SValeriy Savchenko using SelectorInfo = DenseMapInfo<Selector>;
1144dcfc1914SAnna Zaks
getEmptyKeyllvm::DenseMapInfo1145239c53b7SValeriy Savchenko static inline PrivateMethodKey getEmptyKey() {
1146239c53b7SValeriy Savchenko return {InterfaceInfo::getEmptyKey(), SelectorInfo::getEmptyKey(), false};
1147dcfc1914SAnna Zaks }
1148dcfc1914SAnna Zaks
getTombstoneKeyllvm::DenseMapInfo1149239c53b7SValeriy Savchenko static inline PrivateMethodKey getTombstoneKey() {
1150239c53b7SValeriy Savchenko return {InterfaceInfo::getTombstoneKey(), SelectorInfo::getTombstoneKey(),
1151239c53b7SValeriy Savchenko true};
115211150c00SArtem Dergachev }
115311150c00SArtem Dergachev
getHashValuellvm::DenseMapInfo1154239c53b7SValeriy Savchenko static unsigned getHashValue(const PrivateMethodKey &Key) {
1155239c53b7SValeriy Savchenko return llvm::hash_combine(
1156239c53b7SValeriy Savchenko llvm::hash_code(InterfaceInfo::getHashValue(Key.Interface)),
1157239c53b7SValeriy Savchenko llvm::hash_code(SelectorInfo::getHashValue(Key.LookupSelector)),
1158239c53b7SValeriy Savchenko Key.IsClassMethod);
11594f7df9beSJordan Rose }
11604f7df9beSJordan Rose
isEqualllvm::DenseMapInfo1161239c53b7SValeriy Savchenko static bool isEqual(const PrivateMethodKey &LHS,
1162239c53b7SValeriy Savchenko const PrivateMethodKey &RHS) {
1163239c53b7SValeriy Savchenko return InterfaceInfo::isEqual(LHS.Interface, RHS.Interface) &&
1164239c53b7SValeriy Savchenko SelectorInfo::isEqual(LHS.LookupSelector, RHS.LookupSelector) &&
1165239c53b7SValeriy Savchenko LHS.IsClassMethod == RHS.IsClassMethod;
1166dcfc1914SAnna Zaks }
1167239c53b7SValeriy Savchenko };
116823f4edf1SValeriy Savchenko } // end namespace llvm
1169dcfc1914SAnna Zaks
1170350dadaaSBenjamin Kramer static const ObjCMethodDecl *
lookupRuntimeDefinition(const ObjCInterfaceDecl * Interface,Selector LookupSelector,bool InstanceMethod)1171239c53b7SValeriy Savchenko lookupRuntimeDefinition(const ObjCInterfaceDecl *Interface,
1172239c53b7SValeriy Savchenko Selector LookupSelector, bool InstanceMethod) {
1173245e45afSTed Kremenek // Repeatedly calling lookupPrivateMethod() is expensive, especially
1174245e45afSTed Kremenek // when in many cases it returns null. We cache the results so
1175245e45afSTed Kremenek // that repeated queries on the same ObjCIntefaceDecl and Selector
1176245e45afSTed Kremenek // don't incur the same cost. On some test cases, we can see the
1177245e45afSTed Kremenek // same query being issued thousands of times.
1178245e45afSTed Kremenek //
1179245e45afSTed Kremenek // NOTE: This cache is essentially a "global" variable, but it
1180245e45afSTed Kremenek // only gets lazily created when we get here. The value of the
1181245e45afSTed Kremenek // cache probably comes from it being global across ExprEngines,
1182245e45afSTed Kremenek // where the same queries may get issued. If we are worried about
1183245e45afSTed Kremenek // concurrency, or possibly loading/unloading ASTs, etc., we may
1184245e45afSTed Kremenek // need to revisit this someday. In terms of memory, this table
1185245e45afSTed Kremenek // stays around until clang quits, which also may be bad if we
1186245e45afSTed Kremenek // need to release memory.
11875bc81eb9SEugene Zelenko using PrivateMethodCache =
11885bc81eb9SEugene Zelenko llvm::DenseMap<PrivateMethodKey, Optional<const ObjCMethodDecl *>>;
1189245e45afSTed Kremenek
1190245e45afSTed Kremenek static PrivateMethodCache PMC;
1191239c53b7SValeriy Savchenko Optional<const ObjCMethodDecl *> &Val =
1192239c53b7SValeriy Savchenko PMC[{Interface, LookupSelector, InstanceMethod}];
1193245e45afSTed Kremenek
1194245e45afSTed Kremenek // Query lookupPrivateMethod() if the cache does not hit.
1195452db157SKazu Hirata if (!Val) {
1196239c53b7SValeriy Savchenko Val = Interface->lookupPrivateMethod(LookupSelector, InstanceMethod);
1197245e45afSTed Kremenek
1198239c53b7SValeriy Savchenko if (!*Val) {
1199239c53b7SValeriy Savchenko // Query 'lookupMethod' as a backup.
1200239c53b7SValeriy Savchenko Val = Interface->lookupMethod(LookupSelector, InstanceMethod);
12011a866cd5SJordan Rose }
1202c239dd13SDevin Coughlin }
12031a866cd5SJordan Rose
1204*ca4af13eSKazu Hirata return *Val;
1205239c53b7SValeriy Savchenko }
1206239c53b7SValeriy Savchenko
getRuntimeDefinition() const1207239c53b7SValeriy Savchenko RuntimeDefinition ObjCMethodCall::getRuntimeDefinition() const {
1208239c53b7SValeriy Savchenko const ObjCMessageExpr *E = getOriginExpr();
1209239c53b7SValeriy Savchenko assert(E);
1210239c53b7SValeriy Savchenko Selector Sel = E->getSelector();
1211239c53b7SValeriy Savchenko
1212239c53b7SValeriy Savchenko if (E->isInstanceMessage()) {
1213239c53b7SValeriy Savchenko // Find the receiver type.
1214239c53b7SValeriy Savchenko const ObjCObjectType *ReceiverT = nullptr;
1215239c53b7SValeriy Savchenko bool CanBeSubClassed = false;
1216239c53b7SValeriy Savchenko bool LookingForInstanceMethod = true;
1217239c53b7SValeriy Savchenko QualType SupersType = E->getSuperType();
1218239c53b7SValeriy Savchenko const MemRegion *Receiver = nullptr;
1219239c53b7SValeriy Savchenko
1220239c53b7SValeriy Savchenko if (!SupersType.isNull()) {
1221239c53b7SValeriy Savchenko // The receiver is guaranteed to be 'super' in this case.
1222239c53b7SValeriy Savchenko // Super always means the type of immediate predecessor to the method
1223239c53b7SValeriy Savchenko // where the call occurs.
1224239c53b7SValeriy Savchenko ReceiverT = cast<ObjCObjectPointerType>(SupersType)->getObjectType();
1225239c53b7SValeriy Savchenko } else {
1226239c53b7SValeriy Savchenko Receiver = getReceiverSVal().getAsRegion();
1227239c53b7SValeriy Savchenko if (!Receiver)
1228239c53b7SValeriy Savchenko return {};
1229239c53b7SValeriy Savchenko
1230239c53b7SValeriy Savchenko DynamicTypeInfo DTI = getDynamicTypeInfo(getState(), Receiver);
1231239c53b7SValeriy Savchenko if (!DTI.isValid()) {
1232239c53b7SValeriy Savchenko assert(isa<AllocaRegion>(Receiver) &&
1233239c53b7SValeriy Savchenko "Unhandled untyped region class!");
1234239c53b7SValeriy Savchenko return {};
1235239c53b7SValeriy Savchenko }
1236239c53b7SValeriy Savchenko
1237239c53b7SValeriy Savchenko QualType DynType = DTI.getType();
1238239c53b7SValeriy Savchenko CanBeSubClassed = DTI.canBeASubClass();
1239239c53b7SValeriy Savchenko
1240239c53b7SValeriy Savchenko const auto *ReceiverDynT =
1241239c53b7SValeriy Savchenko dyn_cast<ObjCObjectPointerType>(DynType.getCanonicalType());
1242239c53b7SValeriy Savchenko
1243239c53b7SValeriy Savchenko if (ReceiverDynT) {
1244239c53b7SValeriy Savchenko ReceiverT = ReceiverDynT->getObjectType();
1245239c53b7SValeriy Savchenko
1246239c53b7SValeriy Savchenko // It can be actually class methods called with Class object as a
1247239c53b7SValeriy Savchenko // receiver. This type of messages is treated by the compiler as
1248239c53b7SValeriy Savchenko // instance (not class).
1249239c53b7SValeriy Savchenko if (ReceiverT->isObjCClass()) {
1250239c53b7SValeriy Savchenko
1251239c53b7SValeriy Savchenko SVal SelfVal = getState()->getSelfSVal(getLocationContext());
1252239c53b7SValeriy Savchenko // For [self classMethod], return compiler visible declaration.
1253239c53b7SValeriy Savchenko if (Receiver == SelfVal.getAsRegion()) {
1254239c53b7SValeriy Savchenko return RuntimeDefinition(findDefiningRedecl(E->getMethodDecl()));
1255239c53b7SValeriy Savchenko }
1256239c53b7SValeriy Savchenko
1257239c53b7SValeriy Savchenko // Otherwise, let's check if we know something about the type
1258239c53b7SValeriy Savchenko // inside of this class object.
1259239c53b7SValeriy Savchenko if (SymbolRef ReceiverSym = getReceiverSVal().getAsSymbol()) {
1260239c53b7SValeriy Savchenko DynamicTypeInfo DTI =
1261239c53b7SValeriy Savchenko getClassObjectDynamicTypeInfo(getState(), ReceiverSym);
1262239c53b7SValeriy Savchenko if (DTI.isValid()) {
1263239c53b7SValeriy Savchenko // Let's use this type for lookup.
1264239c53b7SValeriy Savchenko ReceiverT =
1265239c53b7SValeriy Savchenko cast<ObjCObjectType>(DTI.getType().getCanonicalType());
1266239c53b7SValeriy Savchenko
1267239c53b7SValeriy Savchenko CanBeSubClassed = DTI.canBeASubClass();
1268239c53b7SValeriy Savchenko // And it should be a class method instead.
1269239c53b7SValeriy Savchenko LookingForInstanceMethod = false;
1270239c53b7SValeriy Savchenko }
1271239c53b7SValeriy Savchenko }
1272239c53b7SValeriy Savchenko }
1273239c53b7SValeriy Savchenko
1274239c53b7SValeriy Savchenko if (CanBeSubClassed)
1275239c53b7SValeriy Savchenko if (ObjCInterfaceDecl *IDecl = ReceiverT->getInterface())
1276239c53b7SValeriy Savchenko // Even if `DynamicTypeInfo` told us that it can be
1277239c53b7SValeriy Savchenko // not necessarily this type, but its descendants, we still want
1278239c53b7SValeriy Savchenko // to check again if this selector can be actually overridden.
1279239c53b7SValeriy Savchenko CanBeSubClassed = canBeOverridenInSubclass(IDecl, Sel);
1280239c53b7SValeriy Savchenko }
1281239c53b7SValeriy Savchenko }
1282239c53b7SValeriy Savchenko
1283239c53b7SValeriy Savchenko // Lookup the instance method implementation.
1284239c53b7SValeriy Savchenko if (ReceiverT)
1285239c53b7SValeriy Savchenko if (ObjCInterfaceDecl *IDecl = ReceiverT->getInterface()) {
1286239c53b7SValeriy Savchenko const ObjCMethodDecl *MD =
1287239c53b7SValeriy Savchenko lookupRuntimeDefinition(IDecl, Sel, LookingForInstanceMethod);
1288239c53b7SValeriy Savchenko
12890b58b80eSArtem Dergachev if (MD && !MD->hasBody())
12900b58b80eSArtem Dergachev MD = MD->getCanonicalDecl();
1291239c53b7SValeriy Savchenko
129275f49a9cSAnna Zaks if (CanBeSubClassed)
129375f49a9cSAnna Zaks return RuntimeDefinition(MD, Receiver);
1294920af014SAnna Zaks else
12950dbb783cSCraig Topper return RuntimeDefinition(MD, nullptr);
1296920af014SAnna Zaks }
129763282aefSAnna Zaks } else {
129863282aefSAnna Zaks // This is a class method.
129963282aefSAnna Zaks // If we have type info for the receiver class, we are calling via
130063282aefSAnna Zaks // class name.
130163282aefSAnna Zaks if (ObjCInterfaceDecl *IDecl = E->getReceiverInterface()) {
130263282aefSAnna Zaks // Find/Return the method implementation.
130385383182SAnna Zaks return RuntimeDefinition(IDecl->lookupPrivateClassMethod(Sel));
13044f7df9beSJordan Rose }
130563282aefSAnna Zaks }
130663282aefSAnna Zaks
13075bc81eb9SEugene Zelenko return {};
13084f7df9beSJordan Rose }
13094f7df9beSJordan Rose
argumentsMayEscape() const1310514f9354SJordan Rose bool ObjCMethodCall::argumentsMayEscape() const {
1311514f9354SJordan Rose if (isInSystemHeader() && !isInstanceMessage()) {
1312514f9354SJordan Rose Selector Sel = getSelector();
1313514f9354SJordan Rose if (Sel.getNumArgs() == 1 &&
1314514f9354SJordan Rose Sel.getIdentifierInfoForSlot(0)->isStr("valueWithPointer"))
1315514f9354SJordan Rose return true;
1316514f9354SJordan Rose }
1317514f9354SJordan Rose
1318514f9354SJordan Rose return CallEvent::argumentsMayEscape();
1319514f9354SJordan Rose }
1320514f9354SJordan Rose
getInitialStackFrameContents(const StackFrameContext * CalleeCtx,BindingsTy & Bindings) const132142e8d649SJordan Rose void ObjCMethodCall::getInitialStackFrameContents(
132242e8d649SJordan Rose const StackFrameContext *CalleeCtx,
132342e8d649SJordan Rose BindingsTy &Bindings) const {
13245bc81eb9SEugene Zelenko const auto *D = cast<ObjCMethodDecl>(CalleeCtx->getDecl());
132542e8d649SJordan Rose SValBuilder &SVB = getState()->getStateManager().getSValBuilder();
132642e8d649SJordan Rose addParameterValuesToBindings(CalleeCtx, Bindings, SVB, *this,
13272ff16004STed Kremenek D->parameters());
132842e8d649SJordan Rose
132942e8d649SJordan Rose SVal SelfVal = getReceiverSVal();
133042e8d649SJordan Rose if (!SelfVal.isUnknown()) {
133142e8d649SJordan Rose const VarDecl *SelfD = CalleeCtx->getAnalysisDeclContext()->getSelfDecl();
133242e8d649SJordan Rose MemRegionManager &MRMgr = SVB.getRegionManager();
133342e8d649SJordan Rose Loc SelfLoc = SVB.makeLoc(MRMgr.getVarRegion(SelfD, CalleeCtx));
133442e8d649SJordan Rose Bindings.push_back(std::make_pair(SelfLoc, SelfVal));
133542e8d649SJordan Rose }
133642e8d649SJordan Rose }
133742e8d649SJordan Rose
1338ce6c99a5SJordan Rose CallEventRef<>
getSimpleCall(const CallExpr * CE,ProgramStateRef State,const LocationContext * LCtx)1339fcd016e5SJordan Rose CallEventManager::getSimpleCall(const CallExpr *CE, ProgramStateRef State,
1340fcd016e5SJordan Rose const LocationContext *LCtx) {
13415bc81eb9SEugene Zelenko if (const auto *MCE = dyn_cast<CXXMemberCallExpr>(CE))
1342fcd016e5SJordan Rose return create<CXXMemberCall>(MCE, State, LCtx);
1343fcd016e5SJordan Rose
13445bc81eb9SEugene Zelenko if (const auto *OpCE = dyn_cast<CXXOperatorCallExpr>(CE)) {
1345fcd016e5SJordan Rose const FunctionDecl *DirectCallee = OpCE->getDirectCallee();
13465bc81eb9SEugene Zelenko if (const auto *MD = dyn_cast<CXXMethodDecl>(DirectCallee))
1347fcd016e5SJordan Rose if (MD->isInstance())
1348fcd016e5SJordan Rose return create<CXXMemberOperatorCall>(OpCE, State, LCtx);
1349fcd016e5SJordan Rose
1350fcd016e5SJordan Rose } else if (CE->getCallee()->getType()->isBlockPointerType()) {
1351fcd016e5SJordan Rose return create<BlockCall>(CE, State, LCtx);
1352fcd016e5SJordan Rose }
1353fcd016e5SJordan Rose
1354fcd016e5SJordan Rose // Otherwise, it's a normal function call, static member function call, or
1355fcd016e5SJordan Rose // something we can't reason about.
13562a833ca5SJordan Rose return create<SimpleFunctionCall>(CE, State, LCtx);
1357fcd016e5SJordan Rose }
1358c2d249ceSJordan Rose
1359c2d249ceSJordan Rose CallEventRef<>
getCaller(const StackFrameContext * CalleeCtx,ProgramStateRef State)1360c2d249ceSJordan Rose CallEventManager::getCaller(const StackFrameContext *CalleeCtx,
1361c2d249ceSJordan Rose ProgramStateRef State) {
1362c2d249ceSJordan Rose const LocationContext *ParentCtx = CalleeCtx->getParent();
1363dd18b11bSGeorge Karpenkov const LocationContext *CallerCtx = ParentCtx->getStackFrame();
1364c2d249ceSJordan Rose assert(CallerCtx && "This should not be used for top-level stack frames");
1365c2d249ceSJordan Rose
1366c2d249ceSJordan Rose const Stmt *CallSite = CalleeCtx->getCallSite();
1367c2d249ceSJordan Rose
1368c2d249ceSJordan Rose if (CallSite) {
13699f3a279fSGeorge Karpenkov if (CallEventRef<> Out = getCall(CallSite, State, CallerCtx))
13709f3a279fSGeorge Karpenkov return Out;
1371c2d249ceSJordan Rose
1372c2d249ceSJordan Rose SValBuilder &SVB = State->getStateManager().getSValBuilder();
13735bc81eb9SEugene Zelenko const auto *Ctor = cast<CXXMethodDecl>(CalleeCtx->getDecl());
1374c2d249ceSJordan Rose Loc ThisPtr = SVB.getCXXThis(Ctor, CalleeCtx);
1375c2d249ceSJordan Rose SVal ThisVal = State->getSVal(ThisPtr);
1376c2d249ceSJordan Rose
1377a82ffe9dSArtem Dergachev if (const auto *CE = dyn_cast<CXXConstructExpr>(CallSite))
1378a82ffe9dSArtem Dergachev return getCXXConstructorCall(CE, ThisVal.getAsRegion(), State, CallerCtx);
1379a82ffe9dSArtem Dergachev else if (const auto *CIE = dyn_cast<CXXInheritedCtorInitExpr>(CallSite))
1380a82ffe9dSArtem Dergachev return getCXXInheritedConstructorCall(CIE, ThisVal.getAsRegion(), State,
1381a82ffe9dSArtem Dergachev CallerCtx);
1382a82ffe9dSArtem Dergachev else {
1383a82ffe9dSArtem Dergachev // All other cases are handled by getCall.
1384a82ffe9dSArtem Dergachev llvm_unreachable("This is not an inlineable statement");
1385a82ffe9dSArtem Dergachev }
1386c2d249ceSJordan Rose }
1387c2d249ceSJordan Rose
1388c2d249ceSJordan Rose // Fall back to the CFG. The only thing we haven't handled yet is
1389c2d249ceSJordan Rose // destructors, though this could change in the future.
1390c2d249ceSJordan Rose const CFGBlock *B = CalleeCtx->getCallSiteBlock();
1391c2d249ceSJordan Rose CFGElement E = (*B)[CalleeCtx->getIndex()];
1392f884cd42SAaron Ballman assert((E.getAs<CFGImplicitDtor>() || E.getAs<CFGTemporaryDtor>()) &&
13932a01f5d4SDavid Blaikie "All other CFG elements should have exprs");
1394c2d249ceSJordan Rose
1395c2d249ceSJordan Rose SValBuilder &SVB = State->getStateManager().getSValBuilder();
13965bc81eb9SEugene Zelenko const auto *Dtor = cast<CXXDestructorDecl>(CalleeCtx->getDecl());
1397c2d249ceSJordan Rose Loc ThisPtr = SVB.getCXXThis(Dtor, CalleeCtx);
1398c2d249ceSJordan Rose SVal ThisVal = State->getSVal(ThisPtr);
1399c2d249ceSJordan Rose
1400c2d249ceSJordan Rose const Stmt *Trigger;
140100be69abSDavid Blaikie if (Optional<CFGAutomaticObjDtor> AutoDtor = E.getAs<CFGAutomaticObjDtor>())
140200be69abSDavid Blaikie Trigger = AutoDtor->getTriggerStmt();
14031ccc43d5SJordan Rose else if (Optional<CFGDeleteDtor> DeleteDtor = E.getAs<CFGDeleteDtor>())
140400f70bd9SGeorge Burgess IV Trigger = DeleteDtor->getDeleteExpr();
1405c2d249ceSJordan Rose else
1406c2d249ceSJordan Rose Trigger = Dtor->getBody();
1407c2d249ceSJordan Rose
1408c2d249ceSJordan Rose return getCXXDestructorCall(Dtor, Trigger, ThisVal.getAsRegion(),
14090916d96dSKazu Hirata E.getAs<CFGBaseDtor>().has_value(), State,
141000be69abSDavid Blaikie CallerCtx);
1411c2d249ceSJordan Rose }
14129f3a279fSGeorge Karpenkov
getCall(const Stmt * S,ProgramStateRef State,const LocationContext * LC)14139f3a279fSGeorge Karpenkov CallEventRef<> CallEventManager::getCall(const Stmt *S, ProgramStateRef State,
14149f3a279fSGeorge Karpenkov const LocationContext *LC) {
14159f3a279fSGeorge Karpenkov if (const auto *CE = dyn_cast<CallExpr>(S)) {
14169f3a279fSGeorge Karpenkov return getSimpleCall(CE, State, LC);
14179f3a279fSGeorge Karpenkov } else if (const auto *NE = dyn_cast<CXXNewExpr>(S)) {
14189f3a279fSGeorge Karpenkov return getCXXAllocatorCall(NE, State, LC);
14191ec1cdcfSFred Tingaud } else if (const auto *DE = dyn_cast<CXXDeleteExpr>(S)) {
14201ec1cdcfSFred Tingaud return getCXXDeallocatorCall(DE, State, LC);
14219f3a279fSGeorge Karpenkov } else if (const auto *ME = dyn_cast<ObjCMessageExpr>(S)) {
14229f3a279fSGeorge Karpenkov return getObjCMethodCall(ME, State, LC);
14239f3a279fSGeorge Karpenkov } else {
14249f3a279fSGeorge Karpenkov return nullptr;
14259f3a279fSGeorge Karpenkov }
14269f3a279fSGeorge Karpenkov }
1427