1 //===- ObjCMessage.h - 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 #ifndef LLVM_CLANG_STATICANALYZER_PATHSENSITIVE_OBJCMESSAGE 16 #define LLVM_CLANG_STATICANALYZER_PATHSENSITIVE_OBJCMESSAGE 17 18 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" 19 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 20 #include "clang/AST/ExprObjC.h" 21 #include "clang/AST/ExprCXX.h" 22 #include "llvm/ADT/PointerUnion.h" 23 24 namespace clang { 25 namespace ento { 26 27 /// \brief Represents both explicit ObjC message expressions and implicit 28 /// messages that are sent for handling properties in dot syntax. 29 class ObjCMessage { 30 const Expr *MsgOrPropE; 31 const Expr *OriginE; 32 bool IsPropSetter; 33 SVal SetterArgV; 34 35 protected: 36 ObjCMessage(const Expr *E, const Expr *origE, bool isSetter, SVal setArgV) 37 : MsgOrPropE(E), OriginE(origE), 38 IsPropSetter(isSetter), SetterArgV(setArgV) { } 39 40 public: 41 ObjCMessage() : MsgOrPropE(0), OriginE(0) { } 42 43 ObjCMessage(const ObjCMessageExpr *E) 44 : MsgOrPropE(E), OriginE(E) { 45 assert(E && "should not be initialized with null expression"); 46 } 47 48 bool isValid() const { return MsgOrPropE != 0; } 49 bool isInvalid() const { return !isValid(); } 50 51 bool isMessageExpr() const { 52 return isValid() && isa<ObjCMessageExpr>(MsgOrPropE); 53 } 54 55 bool isPropertyGetter() const { 56 return isValid() && 57 isa<ObjCPropertyRefExpr>(MsgOrPropE) && !IsPropSetter; 58 } 59 60 bool isPropertySetter() const { 61 return isValid() && 62 isa<ObjCPropertyRefExpr>(MsgOrPropE) && IsPropSetter; 63 } 64 65 const Expr *getOriginExpr() const { return OriginE; } 66 67 QualType getType(ASTContext &ctx) const; 68 69 QualType getResultType(ASTContext &ctx) const { 70 assert(isValid() && "This ObjCMessage is uninitialized!"); 71 if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE)) 72 if (const ObjCMethodDecl *MD = msgE->getMethodDecl()) 73 return MD->getResultType(); 74 return getType(ctx); 75 } 76 77 ObjCMethodFamily getMethodFamily() const; 78 79 Selector getSelector() const; 80 81 const Expr *getInstanceReceiver() const { 82 assert(isValid() && "This ObjCMessage is uninitialized!"); 83 if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE)) 84 return msgE->getInstanceReceiver(); 85 const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE); 86 if (propE->isObjectReceiver()) 87 return propE->getBase(); 88 return 0; 89 } 90 91 SVal getInstanceReceiverSVal(const ProgramState *State, 92 const LocationContext *LC) const { 93 assert(isValid() && "This ObjCMessage is uninitialized!"); 94 if (!isInstanceMessage()) 95 return UndefinedVal(); 96 if (const Expr *Ex = getInstanceReceiver()) 97 return State->getSValAsScalarOrLoc(Ex); 98 99 // An instance message with no expression means we are sending to super. 100 // In this case the object reference is the same as 'self'. 101 const ImplicitParamDecl *SelfDecl = LC->getSelfDecl(); 102 assert(SelfDecl && "No message receiver Expr, but not in an ObjC method"); 103 return State->getSVal(State->getRegion(SelfDecl, LC)); 104 } 105 106 bool isInstanceMessage() const { 107 assert(isValid() && "This ObjCMessage is uninitialized!"); 108 if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE)) 109 return msgE->isInstanceMessage(); 110 const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE); 111 // FIXME: 'super' may be super class. 112 return propE->isObjectReceiver() || propE->isSuperReceiver(); 113 } 114 115 const ObjCMethodDecl *getMethodDecl() const; 116 117 const ObjCInterfaceDecl *getReceiverInterface() const; 118 119 SourceLocation getSuperLoc() const { 120 assert(isValid() && "This ObjCMessage is uninitialized!"); 121 if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE)) 122 return msgE->getSuperLoc(); 123 return cast<ObjCPropertyRefExpr>(MsgOrPropE)->getReceiverLocation(); 124 } 125 126 const Expr *getMsgOrPropExpr() const { 127 assert(isValid() && "This ObjCMessage is uninitialized!"); 128 return MsgOrPropE; 129 } 130 131 SourceRange getSourceRange() const { 132 assert(isValid() && "This ObjCMessage is uninitialized!"); 133 return MsgOrPropE->getSourceRange(); 134 } 135 136 unsigned getNumArgs() const { 137 assert(isValid() && "This ObjCMessage is uninitialized!"); 138 if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE)) 139 return msgE->getNumArgs(); 140 return isPropertySetter() ? 1 : 0; 141 } 142 143 SVal getArgSVal(unsigned i, const ProgramState *state) const { 144 assert(isValid() && "This ObjCMessage is uninitialized!"); 145 assert(i < getNumArgs() && "Invalid index for argument"); 146 if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE)) 147 return state->getSVal(msgE->getArg(i)); 148 assert(isPropertySetter()); 149 return SetterArgV; 150 } 151 152 QualType getArgType(unsigned i) const { 153 assert(isValid() && "This ObjCMessage is uninitialized!"); 154 assert(i < getNumArgs() && "Invalid index for argument"); 155 if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE)) 156 return msgE->getArg(i)->getType(); 157 assert(isPropertySetter()); 158 return cast<ObjCPropertyRefExpr>(MsgOrPropE)->getType(); 159 } 160 161 const Expr *getArgExpr(unsigned i) const; 162 163 SourceRange getArgSourceRange(unsigned i) const { 164 assert(isValid() && "This ObjCMessage is uninitialized!"); 165 assert(i < getNumArgs() && "Invalid index for argument"); 166 if (const Expr *argE = getArgExpr(i)) 167 return argE->getSourceRange(); 168 return OriginE->getSourceRange(); 169 } 170 171 SourceRange getReceiverSourceRange() const { 172 assert(isValid() && "This ObjCMessage is uninitialized!"); 173 if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE)) 174 return msgE->getReceiverRange(); 175 176 const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE); 177 if (propE->isObjectReceiver()) 178 return propE->getBase()->getSourceRange(); 179 180 // FIXME: This isn't a range. 181 return propE->getReceiverLocation(); 182 } 183 }; 184 185 class ObjCPropertyGetter : public ObjCMessage { 186 public: 187 ObjCPropertyGetter(const ObjCPropertyRefExpr *propE, const Expr *originE) 188 : ObjCMessage(propE, originE, false, SVal()) { 189 assert(propE && originE && 190 "should not be initialized with null expressions"); 191 } 192 }; 193 194 class ObjCPropertySetter : public ObjCMessage { 195 public: 196 ObjCPropertySetter(const ObjCPropertyRefExpr *propE, const Expr *storeE, 197 SVal argV) 198 : ObjCMessage(propE, storeE, true, argV) { 199 assert(propE && storeE &&"should not be initialized with null expressions"); 200 } 201 }; 202 203 /// \brief Common wrapper for a call expression, ObjC message, or C++ 204 /// constructor, mainly to provide a common interface for their arguments. 205 class CallOrObjCMessage { 206 llvm::PointerUnion<const CallExpr *, const CXXConstructExpr *> CallE; 207 ObjCMessage Msg; 208 const ProgramState *State; 209 public: 210 CallOrObjCMessage(const CallExpr *callE, const ProgramState *state) 211 : CallE(callE), State(state) {} 212 CallOrObjCMessage(const CXXConstructExpr *consE, const ProgramState *state) 213 : CallE(consE), State(state) {} 214 CallOrObjCMessage(const ObjCMessage &msg, const ProgramState *state) 215 : CallE((CallExpr *)0), Msg(msg), State(state) {} 216 217 QualType getResultType(ASTContext &ctx) const; 218 219 bool isFunctionCall() const { 220 return CallE && CallE.is<const CallExpr *>(); 221 } 222 223 bool isCXXConstructExpr() const { 224 return CallE && CallE.is<const CXXConstructExpr *>(); 225 } 226 227 bool isObjCMessage() const { 228 return !CallE; 229 } 230 231 bool isCXXCall() const { 232 const CallExpr *ActualCallE = CallE.dyn_cast<const CallExpr *>(); 233 return ActualCallE && isa<CXXMemberCallExpr>(ActualCallE); 234 } 235 236 const Expr *getOriginExpr() const { 237 if (!CallE) 238 return Msg.getOriginExpr(); 239 if (const CXXConstructExpr *Ctor = 240 CallE.dyn_cast<const CXXConstructExpr *>()) 241 return Ctor; 242 return CallE.get<const CallExpr *>(); 243 } 244 245 SVal getFunctionCallee() const; 246 SVal getCXXCallee() const; 247 SVal getInstanceMessageReceiver(const LocationContext *LC) const; 248 249 unsigned getNumArgs() const { 250 if (!CallE) 251 return Msg.getNumArgs(); 252 if (const CXXConstructExpr *Ctor = 253 CallE.dyn_cast<const CXXConstructExpr *>()) 254 return Ctor->getNumArgs(); 255 return CallE.get<const CallExpr *>()->getNumArgs(); 256 } 257 258 SVal getArgSVal(unsigned i) const { 259 assert(i < getNumArgs()); 260 if (!CallE) 261 return Msg.getArgSVal(i, State); 262 return State->getSVal(getArg(i)); 263 } 264 265 const Expr *getArg(unsigned i) const { 266 assert(i < getNumArgs()); 267 if (!CallE) 268 return Msg.getArgExpr(i); 269 if (const CXXConstructExpr *Ctor = 270 CallE.dyn_cast<const CXXConstructExpr *>()) 271 return Ctor->getArg(i); 272 return CallE.get<const CallExpr *>()->getArg(i); 273 } 274 275 SourceRange getArgSourceRange(unsigned i) const { 276 assert(i < getNumArgs()); 277 if (CallE) 278 return getArg(i)->getSourceRange(); 279 return Msg.getArgSourceRange(i); 280 } 281 282 SourceRange getReceiverSourceRange() const { 283 assert(isObjCMessage()); 284 return Msg.getReceiverSourceRange(); 285 } 286 }; 287 288 } 289 } 290 291 #endif 292