14f7df9beSJordan Rose //===- Calls.cpp - Wrapper for all function and method calls ------*- C++ -*--//
24f7df9beSJordan Rose //
34f7df9beSJordan Rose //                     The LLVM Compiler Infrastructure
44f7df9beSJordan Rose //
54f7df9beSJordan Rose // This file is distributed under the University of Illinois Open Source
64f7df9beSJordan Rose // License. See LICENSE.TXT for details.
74f7df9beSJordan Rose //
84f7df9beSJordan Rose //===----------------------------------------------------------------------===//
94f7df9beSJordan Rose //
104f7df9beSJordan Rose /// \file This file defines CallEvent and its subclasses, which represent path-
114f7df9beSJordan Rose /// sensitive instances of different kinds of function and method calls
124f7df9beSJordan Rose /// (C, C++, and Objective-C).
134f7df9beSJordan Rose //
144f7df9beSJordan Rose //===----------------------------------------------------------------------===//
154f7df9beSJordan Rose 
164f7df9beSJordan Rose #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
174f7df9beSJordan Rose #include "clang/Analysis/ProgramPoint.h"
184f7df9beSJordan Rose #include "clang/AST/ParentMap.h"
194f7df9beSJordan Rose #include "llvm/ADT/SmallSet.h"
204f7df9beSJordan Rose #include "llvm/ADT/StringExtras.h"
214f7df9beSJordan Rose 
224f7df9beSJordan Rose using namespace clang;
234f7df9beSJordan Rose using namespace ento;
244f7df9beSJordan Rose 
254f7df9beSJordan Rose QualType CallEvent::getResultType() const {
264f7df9beSJordan Rose   QualType ResultTy = getDeclaredResultType();
274f7df9beSJordan Rose 
284f7df9beSJordan Rose   if (ResultTy.isNull())
294f7df9beSJordan Rose     ResultTy = getOriginExpr()->getType();
304f7df9beSJordan Rose 
314f7df9beSJordan Rose   return ResultTy;
324f7df9beSJordan Rose }
334f7df9beSJordan Rose 
344f7df9beSJordan Rose static bool isCallbackArg(SVal V, QualType T) {
354f7df9beSJordan Rose   // If the parameter is 0, it's harmless.
364f7df9beSJordan Rose   if (V.isZeroConstant())
374f7df9beSJordan Rose     return false;
384f7df9beSJordan Rose 
394f7df9beSJordan Rose   // If a parameter is a block or a callback, assume it can modify pointer.
404f7df9beSJordan Rose   if (T->isBlockPointerType() ||
414f7df9beSJordan Rose       T->isFunctionPointerType() ||
424f7df9beSJordan Rose       T->isObjCSelType())
434f7df9beSJordan Rose     return true;
444f7df9beSJordan Rose 
454f7df9beSJordan Rose   // Check if a callback is passed inside a struct (for both, struct passed by
464f7df9beSJordan Rose   // reference and by value). Dig just one level into the struct for now.
474f7df9beSJordan Rose 
484f7df9beSJordan Rose   if (isa<PointerType>(T) || isa<ReferenceType>(T))
494f7df9beSJordan Rose     T = T->getPointeeType();
504f7df9beSJordan Rose 
514f7df9beSJordan Rose   if (const RecordType *RT = T->getAsStructureType()) {
524f7df9beSJordan Rose     const RecordDecl *RD = RT->getDecl();
534f7df9beSJordan Rose     for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
544f7df9beSJordan Rose          I != E; ++I) {
554f7df9beSJordan Rose       QualType FieldT = I->getType();
564f7df9beSJordan Rose       if (FieldT->isBlockPointerType() || FieldT->isFunctionPointerType())
574f7df9beSJordan Rose         return true;
584f7df9beSJordan Rose     }
594f7df9beSJordan Rose   }
604f7df9beSJordan Rose 
614f7df9beSJordan Rose   return false;
624f7df9beSJordan Rose }
634f7df9beSJordan Rose 
644f7df9beSJordan Rose bool CallEvent::hasNonZeroCallbackArg() const {
654f7df9beSJordan Rose   unsigned NumOfArgs = getNumArgs();
664f7df9beSJordan Rose 
674f7df9beSJordan Rose   // If calling using a function pointer, assume the function does not
684f7df9beSJordan Rose   // have a callback. TODO: We could check the types of the arguments here.
694f7df9beSJordan Rose   if (!getDecl())
704f7df9beSJordan Rose     return false;
714f7df9beSJordan Rose 
724f7df9beSJordan Rose   unsigned Idx = 0;
734f7df9beSJordan Rose   for (CallEvent::param_type_iterator I = param_type_begin(),
744f7df9beSJordan Rose                                        E = param_type_end();
754f7df9beSJordan Rose        I != E && Idx < NumOfArgs; ++I, ++Idx) {
764f7df9beSJordan Rose     if (NumOfArgs <= Idx)
774f7df9beSJordan Rose       break;
784f7df9beSJordan Rose 
794f7df9beSJordan Rose     if (isCallbackArg(getArgSVal(Idx), *I))
804f7df9beSJordan Rose       return true;
814f7df9beSJordan Rose   }
824f7df9beSJordan Rose 
834f7df9beSJordan Rose   return false;
844f7df9beSJordan Rose }
854f7df9beSJordan Rose 
864f7df9beSJordan Rose /// \brief Returns true if a type is a pointer-to-const or reference-to-const
874f7df9beSJordan Rose /// with no further indirection.
884f7df9beSJordan Rose static bool isPointerToConst(QualType Ty) {
894f7df9beSJordan Rose   QualType PointeeTy = Ty->getPointeeType();
904f7df9beSJordan Rose   if (PointeeTy == QualType())
914f7df9beSJordan Rose     return false;
924f7df9beSJordan Rose   if (!PointeeTy.isConstQualified())
934f7df9beSJordan Rose     return false;
944f7df9beSJordan Rose   if (PointeeTy->isAnyPointerType())
954f7df9beSJordan Rose     return false;
964f7df9beSJordan Rose   return true;
974f7df9beSJordan Rose }
984f7df9beSJordan Rose 
994f7df9beSJordan Rose // Try to retrieve the function declaration and find the function parameter
1004f7df9beSJordan Rose // types which are pointers/references to a non-pointer const.
1014f7df9beSJordan Rose // We will not invalidate the corresponding argument regions.
1024f7df9beSJordan Rose static void findPtrToConstParams(llvm::SmallSet<unsigned, 1> &PreserveArgs,
1034f7df9beSJordan Rose                                  const CallEvent &Call) {
1044f7df9beSJordan Rose   unsigned Idx = 0;
1054f7df9beSJordan Rose   for (CallEvent::param_type_iterator I = Call.param_type_begin(),
1064f7df9beSJordan Rose                                       E = Call.param_type_end();
1074f7df9beSJordan Rose        I != E; ++I, ++Idx) {
1084f7df9beSJordan Rose     if (isPointerToConst(*I))
1094f7df9beSJordan Rose       PreserveArgs.insert(Idx);
1104f7df9beSJordan Rose   }
1114f7df9beSJordan Rose }
1124f7df9beSJordan Rose 
1134f7df9beSJordan Rose ProgramStateRef CallEvent::invalidateRegions(unsigned BlockCount,
1144f7df9beSJordan Rose                                               ProgramStateRef Orig) const {
1154f7df9beSJordan Rose   ProgramStateRef Result = (Orig ? Orig : getState());
1164f7df9beSJordan Rose 
1174f7df9beSJordan Rose   SmallVector<const MemRegion *, 8> RegionsToInvalidate;
1184f7df9beSJordan Rose   getExtraInvalidatedRegions(RegionsToInvalidate);
1194f7df9beSJordan Rose 
1204f7df9beSJordan Rose   // Indexes of arguments whose values will be preserved by the call.
1214f7df9beSJordan Rose   llvm::SmallSet<unsigned, 1> PreserveArgs;
1224f7df9beSJordan Rose   if (!argumentsMayEscape())
1234f7df9beSJordan Rose     findPtrToConstParams(PreserveArgs, *this);
1244f7df9beSJordan Rose 
1254f7df9beSJordan Rose   for (unsigned Idx = 0, Count = getNumArgs(); Idx != Count; ++Idx) {
1264f7df9beSJordan Rose     if (PreserveArgs.count(Idx))
1274f7df9beSJordan Rose       continue;
1284f7df9beSJordan Rose 
1294f7df9beSJordan Rose     SVal V = getArgSVal(Idx);
1304f7df9beSJordan Rose 
1314f7df9beSJordan Rose     // If we are passing a location wrapped as an integer, unwrap it and
1324f7df9beSJordan Rose     // invalidate the values referred by the location.
1334f7df9beSJordan Rose     if (nonloc::LocAsInteger *Wrapped = dyn_cast<nonloc::LocAsInteger>(&V))
1344f7df9beSJordan Rose       V = Wrapped->getLoc();
1354f7df9beSJordan Rose     else if (!isa<Loc>(V))
1364f7df9beSJordan Rose       continue;
1374f7df9beSJordan Rose 
1384f7df9beSJordan Rose     if (const MemRegion *R = V.getAsRegion()) {
1394f7df9beSJordan Rose       // Invalidate the value of the variable passed by reference.
1404f7df9beSJordan Rose 
1414f7df9beSJordan Rose       // Are we dealing with an ElementRegion?  If the element type is
1424f7df9beSJordan Rose       // a basic integer type (e.g., char, int) and the underlying region
1434f7df9beSJordan Rose       // is a variable region then strip off the ElementRegion.
1444f7df9beSJordan Rose       // FIXME: We really need to think about this for the general case
1454f7df9beSJordan Rose       //   as sometimes we are reasoning about arrays and other times
1464f7df9beSJordan Rose       //   about (char*), etc., is just a form of passing raw bytes.
1474f7df9beSJordan Rose       //   e.g., void *p = alloca(); foo((char*)p);
1484f7df9beSJordan Rose       if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
1494f7df9beSJordan Rose         // Checking for 'integral type' is probably too promiscuous, but
1504f7df9beSJordan Rose         // we'll leave it in for now until we have a systematic way of
1514f7df9beSJordan Rose         // handling all of these cases.  Eventually we need to come up
1524f7df9beSJordan Rose         // with an interface to StoreManager so that this logic can be
1534f7df9beSJordan Rose         // appropriately delegated to the respective StoreManagers while
1544f7df9beSJordan Rose         // still allowing us to do checker-specific logic (e.g.,
1554f7df9beSJordan Rose         // invalidating reference counts), probably via callbacks.
1564f7df9beSJordan Rose         if (ER->getElementType()->isIntegralOrEnumerationType()) {
1574f7df9beSJordan Rose           const MemRegion *superReg = ER->getSuperRegion();
1584f7df9beSJordan Rose           if (isa<VarRegion>(superReg) || isa<FieldRegion>(superReg) ||
1594f7df9beSJordan Rose               isa<ObjCIvarRegion>(superReg))
1604f7df9beSJordan Rose             R = cast<TypedRegion>(superReg);
1614f7df9beSJordan Rose         }
1624f7df9beSJordan Rose         // FIXME: What about layers of ElementRegions?
1634f7df9beSJordan Rose       }
1644f7df9beSJordan Rose 
1654f7df9beSJordan Rose       // Mark this region for invalidation.  We batch invalidate regions
1664f7df9beSJordan Rose       // below for efficiency.
1674f7df9beSJordan Rose       RegionsToInvalidate.push_back(R);
1684f7df9beSJordan Rose     }
1694f7df9beSJordan Rose   }
1704f7df9beSJordan Rose 
1714f7df9beSJordan Rose   // Invalidate designated regions using the batch invalidation API.
1724f7df9beSJordan Rose   // NOTE: Even if RegionsToInvalidate is empty, we may still invalidate
1734f7df9beSJordan Rose   //  global variables.
1744f7df9beSJordan Rose   return Result->invalidateRegions(RegionsToInvalidate, getOriginExpr(),
1754f7df9beSJordan Rose                                    BlockCount, getLocationContext(),
1764f7df9beSJordan Rose                                    /*Symbols=*/0, this);
1774f7df9beSJordan Rose }
1784f7df9beSJordan Rose 
1794f7df9beSJordan Rose ProgramPoint CallEvent::getProgramPoint(bool IsPreVisit,
1804f7df9beSJordan Rose                                         const ProgramPointTag *Tag) const {
1814f7df9beSJordan Rose   if (const Expr *E = getOriginExpr()) {
1824f7df9beSJordan Rose     if (IsPreVisit)
1834f7df9beSJordan Rose       return PreStmt(E, getLocationContext(), Tag);
1844f7df9beSJordan Rose     return PostStmt(E, getLocationContext(), Tag);
1854f7df9beSJordan Rose   }
1864f7df9beSJordan Rose 
1874f7df9beSJordan Rose   const Decl *D = getDecl();
1884f7df9beSJordan Rose   assert(D && "Cannot get a program point without a statement or decl");
1894f7df9beSJordan Rose 
1904f7df9beSJordan Rose   SourceLocation Loc = getSourceRange().getBegin();
1914f7df9beSJordan Rose   if (IsPreVisit)
1924f7df9beSJordan Rose     return PreImplicitCall(D, Loc, getLocationContext(), Tag);
1934f7df9beSJordan Rose   return PostImplicitCall(D, Loc, getLocationContext(), Tag);
1944f7df9beSJordan Rose }
1954f7df9beSJordan Rose 
19672ce8e2dSJordan Rose SVal CallEvent::getArgSVal(unsigned Index) const {
19772ce8e2dSJordan Rose   const Expr *ArgE = getArgExpr(Index);
19872ce8e2dSJordan Rose   if (!ArgE)
19972ce8e2dSJordan Rose     return UnknownVal();
20072ce8e2dSJordan Rose   return getSVal(ArgE);
20172ce8e2dSJordan Rose }
20272ce8e2dSJordan Rose 
20372ce8e2dSJordan Rose SourceRange CallEvent::getArgSourceRange(unsigned Index) const {
20472ce8e2dSJordan Rose   const Expr *ArgE = getArgExpr(Index);
20572ce8e2dSJordan Rose   if (!ArgE)
20672ce8e2dSJordan Rose     return SourceRange();
20772ce8e2dSJordan Rose   return ArgE->getSourceRange();
20872ce8e2dSJordan Rose }
20972ce8e2dSJordan Rose 
21072ce8e2dSJordan Rose void CallEvent::dump(raw_ostream &Out) const {
21172ce8e2dSJordan Rose   ASTContext &Ctx = getState()->getStateManager().getContext();
21272ce8e2dSJordan Rose   if (const Expr *E = getOriginExpr()) {
21372ce8e2dSJordan Rose     E->printPretty(Out, Ctx, 0, Ctx.getPrintingPolicy());
21472ce8e2dSJordan Rose     Out << "\n";
21572ce8e2dSJordan Rose     return;
21672ce8e2dSJordan Rose   }
21772ce8e2dSJordan Rose 
21872ce8e2dSJordan Rose   if (const Decl *D = getDecl()) {
21972ce8e2dSJordan Rose     Out << "Call to ";
22072ce8e2dSJordan Rose     D->print(Out, Ctx.getPrintingPolicy());
22172ce8e2dSJordan Rose     return;
22272ce8e2dSJordan Rose   }
22372ce8e2dSJordan Rose 
22472ce8e2dSJordan Rose   // FIXME: a string representation of the kind would be nice.
22572ce8e2dSJordan Rose   Out << "Unknown call (type " << getKind() << ")";
22672ce8e2dSJordan Rose }
22772ce8e2dSJordan Rose 
2284f7df9beSJordan Rose 
2294f7df9beSJordan Rose bool CallEvent::mayBeInlined(const Stmt *S) {
23072ce8e2dSJordan Rose   // FIXME: Kill this.
23172ce8e2dSJordan Rose   return isa<CallExpr>(S) || isa<ObjCMessageExpr>(S)
23272ce8e2dSJordan Rose                           || isa<CXXConstructExpr>(S);
2334f7df9beSJordan Rose }
2344f7df9beSJordan Rose 
2354f7df9beSJordan Rose 
2364f7df9beSJordan Rose CallEvent::param_iterator
2374f7df9beSJordan Rose AnyFunctionCall::param_begin(bool UseDefinitionParams) const {
2384f7df9beSJordan Rose   const Decl *D = UseDefinitionParams ? getRuntimeDefinition()
2394f7df9beSJordan Rose                                       : getDecl();
2404f7df9beSJordan Rose   if (!D)
2414f7df9beSJordan Rose     return 0;
2424f7df9beSJordan Rose 
2434f7df9beSJordan Rose   return cast<FunctionDecl>(D)->param_begin();
2444f7df9beSJordan Rose }
2454f7df9beSJordan Rose 
2464f7df9beSJordan Rose CallEvent::param_iterator
2474f7df9beSJordan Rose AnyFunctionCall::param_end(bool UseDefinitionParams) const {
2484f7df9beSJordan Rose   const Decl *D = UseDefinitionParams ? getRuntimeDefinition()
2494f7df9beSJordan Rose                                       : getDecl();
2504f7df9beSJordan Rose   if (!D)
2514f7df9beSJordan Rose     return 0;
2524f7df9beSJordan Rose 
2534f7df9beSJordan Rose   return cast<FunctionDecl>(D)->param_end();
2544f7df9beSJordan Rose }
2554f7df9beSJordan Rose 
2564f7df9beSJordan Rose QualType AnyFunctionCall::getDeclaredResultType() const {
2574f7df9beSJordan Rose   const FunctionDecl *D = getDecl();
2584f7df9beSJordan Rose   if (!D)
2594f7df9beSJordan Rose     return QualType();
2604f7df9beSJordan Rose 
2614f7df9beSJordan Rose   return D->getResultType();
2624f7df9beSJordan Rose }
2634f7df9beSJordan Rose 
2644f7df9beSJordan Rose bool AnyFunctionCall::argumentsMayEscape() const {
2654f7df9beSJordan Rose   if (hasNonZeroCallbackArg())
2664f7df9beSJordan Rose     return true;
2674f7df9beSJordan Rose 
2684f7df9beSJordan Rose   const FunctionDecl *D = getDecl();
2694f7df9beSJordan Rose   if (!D)
2704f7df9beSJordan Rose     return true;
2714f7df9beSJordan Rose 
2724f7df9beSJordan Rose   const IdentifierInfo *II = D->getIdentifier();
2734f7df9beSJordan Rose   if (!II)
2744f7df9beSJordan Rose     return true;
2754f7df9beSJordan Rose 
2764f7df9beSJordan Rose   // This set of "escaping" APIs is
2774f7df9beSJordan Rose 
2784f7df9beSJordan Rose   // - 'int pthread_setspecific(ptheread_key k, const void *)' stores a
2794f7df9beSJordan Rose   //   value into thread local storage. The value can later be retrieved with
2804f7df9beSJordan Rose   //   'void *ptheread_getspecific(pthread_key)'. So even thought the
2814f7df9beSJordan Rose   //   parameter is 'const void *', the region escapes through the call.
2824f7df9beSJordan Rose   if (II->isStr("pthread_setspecific"))
2834f7df9beSJordan Rose     return true;
2844f7df9beSJordan Rose 
2854f7df9beSJordan Rose   // - xpc_connection_set_context stores a value which can be retrieved later
2864f7df9beSJordan Rose   //   with xpc_connection_get_context.
2874f7df9beSJordan Rose   if (II->isStr("xpc_connection_set_context"))
2884f7df9beSJordan Rose     return true;
2894f7df9beSJordan Rose 
2904f7df9beSJordan Rose   // - funopen - sets a buffer for future IO calls.
2914f7df9beSJordan Rose   if (II->isStr("funopen"))
2924f7df9beSJordan Rose     return true;
2934f7df9beSJordan Rose 
2944f7df9beSJordan Rose   StringRef FName = II->getName();
2954f7df9beSJordan Rose 
2964f7df9beSJordan Rose   // - CoreFoundation functions that end with "NoCopy" can free a passed-in
2974f7df9beSJordan Rose   //   buffer even if it is const.
2984f7df9beSJordan Rose   if (FName.endswith("NoCopy"))
2994f7df9beSJordan Rose     return true;
3004f7df9beSJordan Rose 
3014f7df9beSJordan Rose   // - NSXXInsertXX, for example NSMapInsertIfAbsent, since they can
3024f7df9beSJordan Rose   //   be deallocated by NSMapRemove.
3034f7df9beSJordan Rose   if (FName.startswith("NS") && (FName.find("Insert") != StringRef::npos))
3044f7df9beSJordan Rose     return true;
3054f7df9beSJordan Rose 
3064f7df9beSJordan Rose   // - Many CF containers allow objects to escape through custom
3074f7df9beSJordan Rose   //   allocators/deallocators upon container construction. (PR12101)
3084f7df9beSJordan Rose   if (FName.startswith("CF") || FName.startswith("CG")) {
3094f7df9beSJordan Rose     return StrInStrNoCase(FName, "InsertValue")  != StringRef::npos ||
3104f7df9beSJordan Rose            StrInStrNoCase(FName, "AddValue")     != StringRef::npos ||
3114f7df9beSJordan Rose            StrInStrNoCase(FName, "SetValue")     != StringRef::npos ||
3124f7df9beSJordan Rose            StrInStrNoCase(FName, "WithData")     != StringRef::npos ||
3134f7df9beSJordan Rose            StrInStrNoCase(FName, "AppendValue")  != StringRef::npos ||
3144f7df9beSJordan Rose            StrInStrNoCase(FName, "SetAttribute") != StringRef::npos;
3154f7df9beSJordan Rose   }
3164f7df9beSJordan Rose 
3174f7df9beSJordan Rose   return false;
3184f7df9beSJordan Rose }
3194f7df9beSJordan Rose 
3204f7df9beSJordan Rose 
3214f7df9beSJordan Rose const FunctionDecl *SimpleCall::getDecl() const {
3224f7df9beSJordan Rose   const FunctionDecl *D = getOriginExpr()->getDirectCallee();
3234f7df9beSJordan Rose   if (D)
3244f7df9beSJordan Rose     return D;
3254f7df9beSJordan Rose 
3264f7df9beSJordan Rose   return getSVal(getOriginExpr()->getCallee()).getAsFunctionDecl();
3274f7df9beSJordan Rose }
3284f7df9beSJordan Rose 
3294f7df9beSJordan Rose 
3304f7df9beSJordan Rose void CXXInstanceCall::getExtraInvalidatedRegions(RegionList &Regions) const {
3314f7df9beSJordan Rose   if (const MemRegion *R = getCXXThisVal().getAsRegion())
3324f7df9beSJordan Rose     Regions.push_back(R);
3334f7df9beSJordan Rose }
3344f7df9beSJordan Rose 
3354f7df9beSJordan Rose static const CXXMethodDecl *devirtualize(const CXXMethodDecl *MD, SVal ThisVal){
3364f7df9beSJordan Rose   const MemRegion *R = ThisVal.getAsRegion();
3374f7df9beSJordan Rose   if (!R)
3384f7df9beSJordan Rose     return 0;
3394f7df9beSJordan Rose 
3404f7df9beSJordan Rose   const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R->StripCasts());
3414f7df9beSJordan Rose   if (!TR)
3424f7df9beSJordan Rose     return 0;
3434f7df9beSJordan Rose 
3444f7df9beSJordan Rose   const CXXRecordDecl *RD = TR->getValueType()->getAsCXXRecordDecl();
3454f7df9beSJordan Rose   if (!RD)
3464f7df9beSJordan Rose     return 0;
3474f7df9beSJordan Rose 
3484f7df9beSJordan Rose   const CXXMethodDecl *Result = MD->getCorrespondingMethodInClass(RD);
3494f7df9beSJordan Rose   const FunctionDecl *Definition;
3504f7df9beSJordan Rose   if (!Result->hasBody(Definition))
3514f7df9beSJordan Rose     return 0;
3524f7df9beSJordan Rose 
3534f7df9beSJordan Rose   return cast<CXXMethodDecl>(Definition);
3544f7df9beSJordan Rose }
3554f7df9beSJordan Rose 
3564f7df9beSJordan Rose 
3574f7df9beSJordan Rose const Decl *CXXInstanceCall::getRuntimeDefinition() const {
3584f7df9beSJordan Rose   const Decl *D = SimpleCall::getRuntimeDefinition();
3594f7df9beSJordan Rose   if (!D)
3604f7df9beSJordan Rose     return 0;
3614f7df9beSJordan Rose 
3624f7df9beSJordan Rose   const CXXMethodDecl *MD = cast<CXXMethodDecl>(D);
3634f7df9beSJordan Rose   if (!MD->isVirtual())
3644f7df9beSJordan Rose     return MD;
3654f7df9beSJordan Rose 
3664f7df9beSJordan Rose   // If the method is virtual, see if we can find the actual implementation
3674f7df9beSJordan Rose   // based on context-sensitivity.
3684f7df9beSJordan Rose   if (const CXXMethodDecl *Devirtualized = devirtualize(MD, getCXXThisVal()))
3694f7df9beSJordan Rose     return Devirtualized;
3704f7df9beSJordan Rose 
3714f7df9beSJordan Rose   return 0;
3724f7df9beSJordan Rose }
3734f7df9beSJordan Rose 
3744f7df9beSJordan Rose 
3754f7df9beSJordan Rose SVal CXXMemberCall::getCXXThisVal() const {
3764f7df9beSJordan Rose   const Expr *Base = getOriginExpr()->getImplicitObjectArgument();
3774f7df9beSJordan Rose 
3784f7df9beSJordan Rose   // FIXME: Will eventually need to cope with member pointers.  This is
3794f7df9beSJordan Rose   // a limitation in getImplicitObjectArgument().
3804f7df9beSJordan Rose   if (!Base)
3814f7df9beSJordan Rose     return UnknownVal();
3824f7df9beSJordan Rose 
3834f7df9beSJordan Rose   return getSVal(Base);
3844f7df9beSJordan Rose }
3854f7df9beSJordan Rose 
3864f7df9beSJordan Rose 
3874f7df9beSJordan Rose SVal CXXMemberOperatorCall::getCXXThisVal() const {
3884f7df9beSJordan Rose   const Expr *Base = getOriginExpr()->getArg(0);
3894f7df9beSJordan Rose   return getSVal(Base);
3904f7df9beSJordan Rose }
3914f7df9beSJordan Rose 
3924f7df9beSJordan Rose 
3934f7df9beSJordan Rose const BlockDataRegion *BlockCall::getBlockRegion() const {
3944f7df9beSJordan Rose   const Expr *Callee = getOriginExpr()->getCallee();
3954f7df9beSJordan Rose   const MemRegion *DataReg = getSVal(Callee).getAsRegion();
3964f7df9beSJordan Rose 
3974f7df9beSJordan Rose   return dyn_cast_or_null<BlockDataRegion>(DataReg);
3984f7df9beSJordan Rose }
3994f7df9beSJordan Rose 
4004f7df9beSJordan Rose CallEvent::param_iterator
4014f7df9beSJordan Rose BlockCall::param_begin(bool UseDefinitionParams) const {
4024f7df9beSJordan Rose   // Blocks don't have distinct declarations and definitions.
4034f7df9beSJordan Rose   (void)UseDefinitionParams;
4044f7df9beSJordan Rose 
4054f7df9beSJordan Rose   const BlockDecl *D = getBlockDecl();
4064f7df9beSJordan Rose   if (!D)
4074f7df9beSJordan Rose     return 0;
4084f7df9beSJordan Rose   return D->param_begin();
4094f7df9beSJordan Rose }
4104f7df9beSJordan Rose 
4114f7df9beSJordan Rose CallEvent::param_iterator
4124f7df9beSJordan Rose BlockCall::param_end(bool UseDefinitionParams) const {
4134f7df9beSJordan Rose   // Blocks don't have distinct declarations and definitions.
4144f7df9beSJordan Rose   (void)UseDefinitionParams;
4154f7df9beSJordan Rose 
4164f7df9beSJordan Rose   const BlockDecl *D = getBlockDecl();
4174f7df9beSJordan Rose   if (!D)
4184f7df9beSJordan Rose     return 0;
4194f7df9beSJordan Rose   return D->param_end();
4204f7df9beSJordan Rose }
4214f7df9beSJordan Rose 
4224f7df9beSJordan Rose void BlockCall::getExtraInvalidatedRegions(RegionList &Regions) const {
4234f7df9beSJordan Rose   // FIXME: This also needs to invalidate captured globals.
4244f7df9beSJordan Rose   if (const MemRegion *R = getBlockRegion())
4254f7df9beSJordan Rose     Regions.push_back(R);
4264f7df9beSJordan Rose }
4274f7df9beSJordan Rose 
4284f7df9beSJordan Rose QualType BlockCall::getDeclaredResultType() const {
4294f7df9beSJordan Rose   const BlockDataRegion *BR = getBlockRegion();
4304f7df9beSJordan Rose   if (!BR)
4314f7df9beSJordan Rose     return QualType();
4324f7df9beSJordan Rose   QualType BlockTy = BR->getCodeRegion()->getLocationType();
4334f7df9beSJordan Rose   return cast<FunctionType>(BlockTy->getPointeeType())->getResultType();
4344f7df9beSJordan Rose }
4354f7df9beSJordan Rose 
4364f7df9beSJordan Rose 
4374f7df9beSJordan Rose SVal CXXConstructorCall::getCXXThisVal() const {
4384f7df9beSJordan Rose   if (Data)
4394f7df9beSJordan Rose     return loc::MemRegionVal(static_cast<const MemRegion *>(Data));
4404f7df9beSJordan Rose   return UnknownVal();
4414f7df9beSJordan Rose }
4424f7df9beSJordan Rose 
4434f7df9beSJordan Rose void CXXConstructorCall::getExtraInvalidatedRegions(RegionList &Regions) const {
4444f7df9beSJordan Rose   if (Data)
4454f7df9beSJordan Rose     Regions.push_back(static_cast<const MemRegion *>(Data));
4464f7df9beSJordan Rose }
4474f7df9beSJordan Rose 
4484f7df9beSJordan Rose 
4494f7df9beSJordan Rose SVal CXXDestructorCall::getCXXThisVal() const {
4504f7df9beSJordan Rose   if (Data)
4514f7df9beSJordan Rose     return loc::MemRegionVal(static_cast<const MemRegion *>(Data));
4524f7df9beSJordan Rose   return UnknownVal();
4534f7df9beSJordan Rose }
4544f7df9beSJordan Rose 
4554f7df9beSJordan Rose void CXXDestructorCall::getExtraInvalidatedRegions(RegionList &Regions) const {
4564f7df9beSJordan Rose   if (Data)
4574f7df9beSJordan Rose     Regions.push_back(static_cast<const MemRegion *>(Data));
4584f7df9beSJordan Rose }
4594f7df9beSJordan Rose 
4604f7df9beSJordan Rose const Decl *CXXDestructorCall::getRuntimeDefinition() const {
4614f7df9beSJordan Rose   const Decl *D = AnyFunctionCall::getRuntimeDefinition();
4624f7df9beSJordan Rose   if (!D)
4634f7df9beSJordan Rose     return 0;
4644f7df9beSJordan Rose 
4654f7df9beSJordan Rose   const CXXMethodDecl *MD = cast<CXXMethodDecl>(D);
4664f7df9beSJordan Rose   if (!MD->isVirtual())
4674f7df9beSJordan Rose     return MD;
4684f7df9beSJordan Rose 
4694f7df9beSJordan Rose   // If the method is virtual, see if we can find the actual implementation
4704f7df9beSJordan Rose   // based on context-sensitivity.
4714f7df9beSJordan Rose   if (const CXXMethodDecl *Devirtualized = devirtualize(MD, getCXXThisVal()))
4724f7df9beSJordan Rose     return Devirtualized;
4734f7df9beSJordan Rose 
4744f7df9beSJordan Rose   return 0;
4754f7df9beSJordan Rose }
4764f7df9beSJordan Rose 
4774f7df9beSJordan Rose 
4784f7df9beSJordan Rose CallEvent::param_iterator
4794f7df9beSJordan Rose ObjCMethodCall::param_begin(bool UseDefinitionParams) const {
4804f7df9beSJordan Rose   const Decl *D = UseDefinitionParams ? getRuntimeDefinition()
4814f7df9beSJordan Rose                                       : getDecl();
4824f7df9beSJordan Rose   if (!D)
4834f7df9beSJordan Rose     return 0;
4844f7df9beSJordan Rose 
4854f7df9beSJordan Rose   return cast<ObjCMethodDecl>(D)->param_begin();
4864f7df9beSJordan Rose }
4874f7df9beSJordan Rose 
4884f7df9beSJordan Rose CallEvent::param_iterator
4894f7df9beSJordan Rose ObjCMethodCall::param_end(bool UseDefinitionParams) const {
4904f7df9beSJordan Rose   const Decl *D = UseDefinitionParams ? getRuntimeDefinition()
4914f7df9beSJordan Rose                                       : getDecl();
4924f7df9beSJordan Rose   if (!D)
4934f7df9beSJordan Rose     return 0;
4944f7df9beSJordan Rose 
4954f7df9beSJordan Rose   return cast<ObjCMethodDecl>(D)->param_end();
4964f7df9beSJordan Rose }
4974f7df9beSJordan Rose 
4984f7df9beSJordan Rose void
4994f7df9beSJordan Rose ObjCMethodCall::getExtraInvalidatedRegions(RegionList &Regions) const {
5004f7df9beSJordan Rose   if (const MemRegion *R = getReceiverSVal().getAsRegion())
5014f7df9beSJordan Rose     Regions.push_back(R);
5024f7df9beSJordan Rose }
5034f7df9beSJordan Rose 
5044f7df9beSJordan Rose QualType ObjCMethodCall::getDeclaredResultType() const {
5054f7df9beSJordan Rose   const ObjCMethodDecl *D = getDecl();
5064f7df9beSJordan Rose   if (!D)
5074f7df9beSJordan Rose     return QualType();
5084f7df9beSJordan Rose 
5094f7df9beSJordan Rose   return D->getResultType();
5104f7df9beSJordan Rose }
5114f7df9beSJordan Rose 
5124f7df9beSJordan Rose SVal ObjCMethodCall::getReceiverSVal() const {
5134f7df9beSJordan Rose   // FIXME: Is this the best way to handle class receivers?
5144f7df9beSJordan Rose   if (!isInstanceMessage())
5154f7df9beSJordan Rose     return UnknownVal();
5164f7df9beSJordan Rose 
5174f7df9beSJordan Rose   if (const Expr *Base = getOriginExpr()->getInstanceReceiver())
5184f7df9beSJordan Rose     return getSVal(Base);
5194f7df9beSJordan Rose 
5204f7df9beSJordan Rose   // An instance message with no expression means we are sending to super.
5214f7df9beSJordan Rose   // In this case the object reference is the same as 'self'.
5224f7df9beSJordan Rose   const LocationContext *LCtx = getLocationContext();
5234f7df9beSJordan Rose   const ImplicitParamDecl *SelfDecl = LCtx->getSelfDecl();
5244f7df9beSJordan Rose   assert(SelfDecl && "No message receiver Expr, but not in an ObjC method");
5254f7df9beSJordan Rose   return getState()->getSVal(getState()->getRegion(SelfDecl, LCtx));
5264f7df9beSJordan Rose }
5274f7df9beSJordan Rose 
5284f7df9beSJordan Rose SourceRange ObjCMethodCall::getSourceRange() const {
5294f7df9beSJordan Rose   switch (getMessageKind()) {
5304f7df9beSJordan Rose   case OCM_Message:
5314f7df9beSJordan Rose     return getOriginExpr()->getSourceRange();
5324f7df9beSJordan Rose   case OCM_PropertyAccess:
5334f7df9beSJordan Rose   case OCM_Subscript:
5344f7df9beSJordan Rose     return getContainingPseudoObjectExpr()->getSourceRange();
5354f7df9beSJordan Rose   }
5364f7df9beSJordan Rose   llvm_unreachable("unknown message kind");
5374f7df9beSJordan Rose }
5384f7df9beSJordan Rose 
5394f7df9beSJordan Rose typedef llvm::PointerIntPair<const PseudoObjectExpr *, 2> ObjCMessageDataTy;
5404f7df9beSJordan Rose 
5414f7df9beSJordan Rose const PseudoObjectExpr *ObjCMethodCall::getContainingPseudoObjectExpr() const {
5424f7df9beSJordan Rose   assert(Data != 0 && "Lazy lookup not yet performed.");
5434f7df9beSJordan Rose   assert(getMessageKind() != OCM_Message && "Explicit message send.");
5444f7df9beSJordan Rose   return ObjCMessageDataTy::getFromOpaqueValue(Data).getPointer();
5454f7df9beSJordan Rose }
5464f7df9beSJordan Rose 
5474f7df9beSJordan Rose ObjCMessageKind ObjCMethodCall::getMessageKind() const {
5484f7df9beSJordan Rose   if (Data == 0) {
5494f7df9beSJordan Rose     ParentMap &PM = getLocationContext()->getParentMap();
5504f7df9beSJordan Rose     const Stmt *S = PM.getParent(getOriginExpr());
5514f7df9beSJordan Rose     if (const PseudoObjectExpr *POE = dyn_cast_or_null<PseudoObjectExpr>(S)) {
5524f7df9beSJordan Rose       const Expr *Syntactic = POE->getSyntacticForm();
5534f7df9beSJordan Rose 
5544f7df9beSJordan Rose       // This handles the funny case of assigning to the result of a getter.
5554f7df9beSJordan Rose       // This can happen if the getter returns a non-const reference.
5564f7df9beSJordan Rose       if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(Syntactic))
5574f7df9beSJordan Rose         Syntactic = BO->getLHS();
5584f7df9beSJordan Rose 
5594f7df9beSJordan Rose       ObjCMessageKind K;
5604f7df9beSJordan Rose       switch (Syntactic->getStmtClass()) {
5614f7df9beSJordan Rose       case Stmt::ObjCPropertyRefExprClass:
5624f7df9beSJordan Rose         K = OCM_PropertyAccess;
5634f7df9beSJordan Rose         break;
5644f7df9beSJordan Rose       case Stmt::ObjCSubscriptRefExprClass:
5654f7df9beSJordan Rose         K = OCM_Subscript;
5664f7df9beSJordan Rose         break;
5674f7df9beSJordan Rose       default:
5684f7df9beSJordan Rose         // FIXME: Can this ever happen?
5694f7df9beSJordan Rose         K = OCM_Message;
5704f7df9beSJordan Rose         break;
5714f7df9beSJordan Rose       }
5724f7df9beSJordan Rose 
5734f7df9beSJordan Rose       if (K != OCM_Message) {
5744f7df9beSJordan Rose         const_cast<ObjCMethodCall *>(this)->Data
5754f7df9beSJordan Rose           = ObjCMessageDataTy(POE, K).getOpaqueValue();
5764f7df9beSJordan Rose         assert(getMessageKind() == K);
5774f7df9beSJordan Rose         return K;
5784f7df9beSJordan Rose       }
5794f7df9beSJordan Rose     }
5804f7df9beSJordan Rose 
5814f7df9beSJordan Rose     const_cast<ObjCMethodCall *>(this)->Data
5824f7df9beSJordan Rose       = ObjCMessageDataTy(0, 1).getOpaqueValue();
5834f7df9beSJordan Rose     assert(getMessageKind() == OCM_Message);
5844f7df9beSJordan Rose     return OCM_Message;
5854f7df9beSJordan Rose   }
5864f7df9beSJordan Rose 
5874f7df9beSJordan Rose   ObjCMessageDataTy Info = ObjCMessageDataTy::getFromOpaqueValue(Data);
5884f7df9beSJordan Rose   if (!Info.getPointer())
5894f7df9beSJordan Rose     return OCM_Message;
5904f7df9beSJordan Rose   return static_cast<ObjCMessageKind>(Info.getInt());
5914f7df9beSJordan Rose }
5924f7df9beSJordan Rose 
59363282aefSAnna Zaks const Decl *ObjCMethodCall::getRuntimeDefinition() const {
59463282aefSAnna Zaks   const ObjCMessageExpr *E = getOriginExpr();
59563282aefSAnna Zaks   assert(E);
596*5808eb80SAnna Zaks   Selector Sel = E->getSelector();
5974f7df9beSJordan Rose 
59863282aefSAnna Zaks   if (E->isInstanceMessage()) {
599*5808eb80SAnna Zaks 
600*5808eb80SAnna Zaks     // Find the the receiver type.
601*5808eb80SAnna Zaks     const ObjCObjectPointerType *ReceiverT = 0;
602*5808eb80SAnna Zaks     QualType SupersType = E->getSuperType();
603*5808eb80SAnna Zaks     if (!SupersType.isNull()) {
604*5808eb80SAnna Zaks       ReceiverT = cast<ObjCObjectPointerType>(SupersType.getTypePtr());
605*5808eb80SAnna Zaks     } else {
60663282aefSAnna Zaks       const MemRegion *Receiver = getReceiverSVal().getAsRegion();
60763282aefSAnna Zaks       DynamicTypeInfo TI = getState()->getDynamicTypeInfo(Receiver);
608*5808eb80SAnna Zaks       ReceiverT = dyn_cast<ObjCObjectPointerType>(TI.getType().getTypePtr());
6094f7df9beSJordan Rose     }
6104f7df9beSJordan Rose 
611*5808eb80SAnna Zaks     // Lookup the method implementation.
612*5808eb80SAnna Zaks     if (ReceiverT)
613*5808eb80SAnna Zaks       if (ObjCInterfaceDecl *IDecl = ReceiverT->getInterfaceDecl())
614*5808eb80SAnna Zaks         return IDecl->lookupPrivateMethod(Sel);
615*5808eb80SAnna Zaks 
61663282aefSAnna Zaks   } else {
61763282aefSAnna Zaks     // This is a class method.
61863282aefSAnna Zaks     // If we have type info for the receiver class, we are calling via
61963282aefSAnna Zaks     // class name.
62063282aefSAnna Zaks     if (ObjCInterfaceDecl *IDecl = E->getReceiverInterface()) {
62163282aefSAnna Zaks       // Find/Return the method implementation.
62263282aefSAnna Zaks       return IDecl->lookupPrivateClassMethod(Sel);
6234f7df9beSJordan Rose     }
62463282aefSAnna Zaks   }
62563282aefSAnna Zaks 
62663282aefSAnna Zaks   return 0;
6274f7df9beSJordan Rose }
6284f7df9beSJordan Rose 
629fcd016e5SJordan Rose 
630fcd016e5SJordan Rose CallEventRef<SimpleCall>
631fcd016e5SJordan Rose CallEventManager::getSimpleCall(const CallExpr *CE, ProgramStateRef State,
632fcd016e5SJordan Rose                                 const LocationContext *LCtx) {
633fcd016e5SJordan Rose   if (const CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(CE))
634fcd016e5SJordan Rose     return create<CXXMemberCall>(MCE, State, LCtx);
635fcd016e5SJordan Rose 
636fcd016e5SJordan Rose   if (const CXXOperatorCallExpr *OpCE = dyn_cast<CXXOperatorCallExpr>(CE)) {
637fcd016e5SJordan Rose     const FunctionDecl *DirectCallee = OpCE->getDirectCallee();
638fcd016e5SJordan Rose     if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DirectCallee))
639fcd016e5SJordan Rose       if (MD->isInstance())
640fcd016e5SJordan Rose         return create<CXXMemberOperatorCall>(OpCE, State, LCtx);
641fcd016e5SJordan Rose 
642fcd016e5SJordan Rose   } else if (CE->getCallee()->getType()->isBlockPointerType()) {
643fcd016e5SJordan Rose     return create<BlockCall>(CE, State, LCtx);
644fcd016e5SJordan Rose   }
645fcd016e5SJordan Rose 
646fcd016e5SJordan Rose   // Otherwise, it's a normal function call, static member function call, or
647fcd016e5SJordan Rose   // something we can't reason about.
648fcd016e5SJordan Rose   return create<FunctionCall>(CE, State, LCtx);
649fcd016e5SJordan Rose }
650c2d249ceSJordan Rose 
651c2d249ceSJordan Rose 
652c2d249ceSJordan Rose CallEventRef<>
653c2d249ceSJordan Rose CallEventManager::getCaller(const StackFrameContext *CalleeCtx,
654c2d249ceSJordan Rose                             ProgramStateRef State) {
655c2d249ceSJordan Rose   const LocationContext *ParentCtx = CalleeCtx->getParent();
656c2d249ceSJordan Rose   const LocationContext *CallerCtx = ParentCtx->getCurrentStackFrame();
657c2d249ceSJordan Rose   assert(CallerCtx && "This should not be used for top-level stack frames");
658c2d249ceSJordan Rose 
659c2d249ceSJordan Rose   const Stmt *CallSite = CalleeCtx->getCallSite();
660c2d249ceSJordan Rose 
661c2d249ceSJordan Rose   if (CallSite) {
662c2d249ceSJordan Rose     if (const CallExpr *CE = dyn_cast<CallExpr>(CallSite))
663c2d249ceSJordan Rose       return getSimpleCall(CE, State, CallerCtx);
664c2d249ceSJordan Rose 
665c2d249ceSJordan Rose     switch (CallSite->getStmtClass()) {
666c2d249ceSJordan Rose     case Stmt::CXXConstructExprClass: {
667c2d249ceSJordan Rose       SValBuilder &SVB = State->getStateManager().getSValBuilder();
668c2d249ceSJordan Rose       const CXXMethodDecl *Ctor = cast<CXXMethodDecl>(CalleeCtx->getDecl());
669c2d249ceSJordan Rose       Loc ThisPtr = SVB.getCXXThis(Ctor, CalleeCtx);
670c2d249ceSJordan Rose       SVal ThisVal = State->getSVal(ThisPtr);
671c2d249ceSJordan Rose 
672c2d249ceSJordan Rose       return getCXXConstructorCall(cast<CXXConstructExpr>(CallSite),
673c2d249ceSJordan Rose                                    ThisVal.getAsRegion(), State, CallerCtx);
674c2d249ceSJordan Rose     }
675c2d249ceSJordan Rose     case Stmt::CXXNewExprClass:
676c2d249ceSJordan Rose       return getCXXAllocatorCall(cast<CXXNewExpr>(CallSite), State, CallerCtx);
677c2d249ceSJordan Rose     case Stmt::ObjCMessageExprClass:
678c2d249ceSJordan Rose       return getObjCMethodCall(cast<ObjCMessageExpr>(CallSite),
679c2d249ceSJordan Rose                                State, CallerCtx);
680c2d249ceSJordan Rose     default:
681c2d249ceSJordan Rose       llvm_unreachable("This is not an inlineable statement.");
682c2d249ceSJordan Rose     }
683c2d249ceSJordan Rose   }
684c2d249ceSJordan Rose 
685c2d249ceSJordan Rose   // Fall back to the CFG. The only thing we haven't handled yet is
686c2d249ceSJordan Rose   // destructors, though this could change in the future.
687c2d249ceSJordan Rose   const CFGBlock *B = CalleeCtx->getCallSiteBlock();
688c2d249ceSJordan Rose   CFGElement E = (*B)[CalleeCtx->getIndex()];
689c2d249ceSJordan Rose   assert(isa<CFGImplicitDtor>(E) && "All other CFG elements should have exprs");
690c2d249ceSJordan Rose   assert(!isa<CFGTemporaryDtor>(E) && "We don't handle temporaries yet");
691c2d249ceSJordan Rose 
692c2d249ceSJordan Rose   SValBuilder &SVB = State->getStateManager().getSValBuilder();
693c2d249ceSJordan Rose   const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CalleeCtx->getDecl());
694c2d249ceSJordan Rose   Loc ThisPtr = SVB.getCXXThis(Dtor, CalleeCtx);
695c2d249ceSJordan Rose   SVal ThisVal = State->getSVal(ThisPtr);
696c2d249ceSJordan Rose 
697c2d249ceSJordan Rose   const Stmt *Trigger;
698c2d249ceSJordan Rose   if (const CFGAutomaticObjDtor *AutoDtor = dyn_cast<CFGAutomaticObjDtor>(&E))
699c2d249ceSJordan Rose     Trigger = AutoDtor->getTriggerStmt();
700c2d249ceSJordan Rose   else
701c2d249ceSJordan Rose     Trigger = Dtor->getBody();
702c2d249ceSJordan Rose 
703c2d249ceSJordan Rose   return getCXXDestructorCall(Dtor, Trigger, ThisVal.getAsRegion(),
704c2d249ceSJordan Rose                               State, CallerCtx);
705c2d249ceSJordan Rose }
706c2d249ceSJordan Rose 
707