1 //===- ObjCMessage.cpp - Wrapper for ObjC messages and dot syntax -*- C++ -*--// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines ObjCMessage which serves as a common wrapper for ObjC 11 // message expressions or implicit messages for loading/storing ObjC properties. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h" 16 #include "clang/AST/DeclCXX.h" 17 18 using namespace clang; 19 using namespace ento; 20 getResultType(ASTContext & ctx) const21QualType CallOrObjCMessage::getResultType(ASTContext &ctx) const { 22 QualType resultTy; 23 bool isLVal = false; 24 25 if (isObjCMessage()) { 26 resultTy = Msg.getResultType(ctx); 27 } else if (const CXXConstructExpr *Ctor = 28 CallE.dyn_cast<const CXXConstructExpr *>()) { 29 resultTy = Ctor->getType(); 30 } else { 31 const CallExpr *FunctionCall = CallE.get<const CallExpr *>(); 32 33 isLVal = FunctionCall->isLValue(); 34 const Expr *Callee = FunctionCall->getCallee(); 35 if (const FunctionDecl *FD = State->getSVal(Callee, LCtx).getAsFunctionDecl()) 36 resultTy = FD->getResultType(); 37 else 38 resultTy = FunctionCall->getType(); 39 } 40 41 if (isLVal) 42 resultTy = ctx.getPointerType(resultTy); 43 44 return resultTy; 45 } 46 getFunctionCallee() const47SVal CallOrObjCMessage::getFunctionCallee() const { 48 assert(isFunctionCall()); 49 assert(!isCXXCall()); 50 const Expr *Fun = CallE.get<const CallExpr *>()->getCallee()->IgnoreParens(); 51 return State->getSVal(Fun, LCtx); 52 } 53 getCXXCallee() const54SVal CallOrObjCMessage::getCXXCallee() const { 55 assert(isCXXCall()); 56 const CallExpr *ActualCall = CallE.get<const CallExpr *>(); 57 const Expr *callee = 58 cast<CXXMemberCallExpr>(ActualCall)->getImplicitObjectArgument(); 59 60 // FIXME: Will eventually need to cope with member pointers. This is 61 // a limitation in getImplicitObjectArgument(). 62 if (!callee) 63 return UnknownVal(); 64 65 return State->getSVal(callee, LCtx); 66 } 67 68 SVal getInstanceMessageReceiver(const LocationContext * LC) const69CallOrObjCMessage::getInstanceMessageReceiver(const LocationContext *LC) const { 70 assert(isObjCMessage()); 71 return Msg.getInstanceReceiverSVal(State, LC); 72 } 73 getDecl() const74const Decl *CallOrObjCMessage::getDecl() const { 75 if (isCXXCall()) { 76 const CXXMemberCallExpr *CE = 77 cast<CXXMemberCallExpr>(CallE.dyn_cast<const CallExpr *>()); 78 assert(CE); 79 return CE->getMethodDecl(); 80 } else if (isObjCMessage()) { 81 return Msg.getMethodDecl(); 82 } else if (isFunctionCall()) { 83 // In case of a C style call, use the path sensitive information to find 84 // the function declaration. 85 SVal CalleeVal = getFunctionCallee(); 86 return CalleeVal.getAsFunctionDecl(); 87 } 88 return 0; 89 } 90 91