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 17 using namespace clang; 18 using namespace ento; 19 20 QualType ObjCMessage::getType(ASTContext &ctx) const { 21 assert(isValid() && "This ObjCMessage is uninitialized!"); 22 if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE)) 23 return msgE->getType(); 24 const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE); 25 if (isPropertySetter()) 26 return ctx.VoidTy; 27 return propE->getType(); 28 } 29 30 Selector ObjCMessage::getSelector() const { 31 assert(isValid() && "This ObjCMessage is uninitialized!"); 32 if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE)) 33 return msgE->getSelector(); 34 const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE); 35 if (isPropertySetter()) 36 return propE->getSetterSelector(); 37 return propE->getGetterSelector(); 38 } 39 40 ObjCMethodFamily ObjCMessage::getMethodFamily() const { 41 assert(isValid() && "This ObjCMessage is uninitialized!"); 42 // Case 1. Explicit message send. 43 if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE)) 44 return msgE->getMethodFamily(); 45 46 const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE); 47 48 // Case 2. Reference to implicit property. 49 if (propE->isImplicitProperty()) { 50 if (isPropertySetter()) 51 return propE->getImplicitPropertySetter()->getMethodFamily(); 52 else 53 return propE->getImplicitPropertyGetter()->getMethodFamily(); 54 } 55 56 // Case 3. Reference to explicit property. 57 const ObjCPropertyDecl *prop = propE->getExplicitProperty(); 58 if (isPropertySetter()) { 59 if (prop->getSetterMethodDecl()) 60 return prop->getSetterMethodDecl()->getMethodFamily(); 61 return prop->getSetterName().getMethodFamily(); 62 } else { 63 if (prop->getGetterMethodDecl()) 64 return prop->getGetterMethodDecl()->getMethodFamily(); 65 return prop->getGetterName().getMethodFamily(); 66 } 67 } 68 69 const ObjCMethodDecl *ObjCMessage::getMethodDecl() const { 70 assert(isValid() && "This ObjCMessage is uninitialized!"); 71 if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE)) 72 return msgE->getMethodDecl(); 73 const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE); 74 if (propE->isImplicitProperty()) 75 return isPropertySetter() ? propE->getImplicitPropertySetter() 76 : propE->getImplicitPropertyGetter(); 77 return 0; 78 } 79 80 const ObjCInterfaceDecl *ObjCMessage::getReceiverInterface() const { 81 assert(isValid() && "This ObjCMessage is uninitialized!"); 82 if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE)) 83 return msgE->getReceiverInterface(); 84 const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE); 85 if (propE->isClassReceiver()) 86 return propE->getClassReceiver(); 87 QualType recT; 88 if (const Expr *recE = getInstanceReceiver()) 89 recT = recE->getType(); 90 else { 91 assert(propE->isSuperReceiver()); 92 recT = propE->getSuperReceiverType(); 93 } 94 if (const ObjCObjectPointerType *Ptr = recT->getAs<ObjCObjectPointerType>()) 95 return Ptr->getInterfaceDecl(); 96 return 0; 97 } 98 99 const Expr *ObjCMessage::getArgExpr(unsigned i) const { 100 assert(isValid() && "This ObjCMessage is uninitialized!"); 101 assert(i < getNumArgs() && "Invalid index for argument"); 102 if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE)) 103 return msgE->getArg(i); 104 assert(isPropertySetter()); 105 if (const BinaryOperator *bop = dyn_cast<BinaryOperator>(OriginE)) 106 if (bop->isAssignmentOp()) 107 return bop->getRHS(); 108 return 0; 109 } 110 111 QualType CallOrObjCMessage::getResultType(ASTContext &ctx) const { 112 QualType resultTy; 113 bool isLVal = false; 114 115 if (isObjCMessage()) { 116 isLVal = isa<ObjCMessageExpr>(Msg.getOriginExpr()) && 117 Msg.getOriginExpr()->isLValue(); 118 resultTy = Msg.getResultType(ctx); 119 } else if (const CXXConstructExpr *Ctor = 120 CallE.dyn_cast<const CXXConstructExpr *>()) { 121 resultTy = Ctor->getType(); 122 } else { 123 const CallExpr *FunctionCall = CallE.get<const CallExpr *>(); 124 125 isLVal = FunctionCall->isLValue(); 126 const Expr *Callee = FunctionCall->getCallee(); 127 if (const FunctionDecl *FD = State->getSVal(Callee).getAsFunctionDecl()) 128 resultTy = FD->getResultType(); 129 else 130 resultTy = FunctionCall->getType(); 131 } 132 133 if (isLVal) 134 resultTy = ctx.getPointerType(resultTy); 135 136 return resultTy; 137 } 138 139 SVal CallOrObjCMessage::getFunctionCallee() const { 140 assert(isFunctionCall()); 141 assert(!isCXXCall()); 142 const Expr *Fun = CallE.get<const CallExpr *>()->getCallee()->IgnoreParens(); 143 return State->getSVal(Fun); 144 } 145 146 SVal CallOrObjCMessage::getCXXCallee() const { 147 assert(isCXXCall()); 148 const CallExpr *ActualCall = CallE.get<const CallExpr *>(); 149 const Expr *callee = 150 cast<CXXMemberCallExpr>(ActualCall)->getImplicitObjectArgument(); 151 152 // FIXME: Will eventually need to cope with member pointers. This is 153 // a limitation in getImplicitObjectArgument(). 154 if (!callee) 155 return UnknownVal(); 156 157 return State->getSVal(callee); 158 } 159 160 SVal 161 CallOrObjCMessage::getInstanceMessageReceiver(const LocationContext *LC) const { 162 assert(isObjCMessage()); 163 return Msg.getInstanceReceiverSVal(State, LC); 164 } 165