clang API Documentation
00001 //===- ObjCMessage.h - Wrapper for ObjC messages and dot syntax ---*- C++ -*--// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines ObjCMessage which serves as a common wrapper for ObjC 00011 // message expressions or implicit messages for loading/storing ObjC properties. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #ifndef LLVM_CLANG_STATICANALYZER_PATHSENSITIVE_OBJCMESSAGE 00016 #define LLVM_CLANG_STATICANALYZER_PATHSENSITIVE_OBJCMESSAGE 00017 00018 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" 00019 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 00020 #include "clang/AST/ExprObjC.h" 00021 #include "clang/AST/ExprCXX.h" 00022 #include "clang/Basic/SourceManager.h" 00023 #include "llvm/ADT/PointerUnion.h" 00024 #include "llvm/ADT/StringExtras.h" 00025 #include "llvm/Support/Compiler.h" 00026 00027 namespace clang { 00028 namespace ento { 00029 using llvm::StrInStrNoCase; 00030 00031 /// \brief Represents both explicit ObjC message expressions and implicit 00032 /// messages that are sent for handling properties in dot syntax. 00033 class ObjCMessage { 00034 const ObjCMessageExpr *Msg; 00035 const ObjCPropertyRefExpr *PE; 00036 const bool IsPropSetter; 00037 public: 00038 ObjCMessage() : Msg(0), PE(0), IsPropSetter(false) {} 00039 00040 ObjCMessage(const ObjCMessageExpr *E, const ObjCPropertyRefExpr *pe = 0, 00041 bool isSetter = false) 00042 : Msg(E), PE(pe), IsPropSetter(isSetter) { 00043 assert(E && "should not be initialized with null expression"); 00044 } 00045 00046 bool isValid() const { return Msg; } 00047 00048 bool isPureMessageExpr() const { return !PE; } 00049 00050 bool isPropertyGetter() const { return PE && !IsPropSetter; } 00051 00052 bool isPropertySetter() const { 00053 return IsPropSetter; 00054 } 00055 00056 const Expr *getMessageExpr() const { 00057 return Msg; 00058 } 00059 00060 QualType getType(ASTContext &ctx) const { 00061 return Msg->getType(); 00062 } 00063 00064 QualType getResultType(ASTContext &ctx) const { 00065 if (const ObjCMethodDecl *MD = Msg->getMethodDecl()) 00066 return MD->getResultType(); 00067 return getType(ctx); 00068 } 00069 00070 ObjCMethodFamily getMethodFamily() const { 00071 return Msg->getMethodFamily(); 00072 } 00073 00074 Selector getSelector() const { 00075 return Msg->getSelector(); 00076 } 00077 00078 const Expr *getInstanceReceiver() const { 00079 return Msg->getInstanceReceiver(); 00080 } 00081 00082 SVal getInstanceReceiverSVal(ProgramStateRef State, 00083 const LocationContext *LC) const { 00084 if (!isInstanceMessage()) 00085 return UndefinedVal(); 00086 if (const Expr *Ex = getInstanceReceiver()) 00087 return State->getSValAsScalarOrLoc(Ex, LC); 00088 00089 // An instance message with no expression means we are sending to super. 00090 // In this case the object reference is the same as 'self'. 00091 const ImplicitParamDecl *SelfDecl = LC->getSelfDecl(); 00092 assert(SelfDecl && "No message receiver Expr, but not in an ObjC method"); 00093 return State->getSVal(State->getRegion(SelfDecl, LC)); 00094 } 00095 00096 bool isInstanceMessage() const { 00097 return Msg->isInstanceMessage(); 00098 } 00099 00100 const ObjCMethodDecl *getMethodDecl() const { 00101 return Msg->getMethodDecl(); 00102 } 00103 00104 const ObjCInterfaceDecl *getReceiverInterface() const { 00105 return Msg->getReceiverInterface(); 00106 } 00107 00108 SourceLocation getSuperLoc() const { 00109 if (PE) 00110 return PE->getReceiverLocation(); 00111 return Msg->getSuperLoc(); 00112 } 00113 00114 SourceRange getSourceRange() const LLVM_READONLY { 00115 if (PE) 00116 return PE->getSourceRange(); 00117 return Msg->getSourceRange(); 00118 } 00119 00120 unsigned getNumArgs() const { 00121 return Msg->getNumArgs(); 00122 } 00123 00124 SVal getArgSVal(unsigned i, 00125 const LocationContext *LCtx, 00126 ProgramStateRef state) const { 00127 assert(i < getNumArgs() && "Invalid index for argument"); 00128 return state->getSVal(Msg->getArg(i), LCtx); 00129 } 00130 00131 QualType getArgType(unsigned i) const { 00132 assert(i < getNumArgs() && "Invalid index for argument"); 00133 return Msg->getArg(i)->getType(); 00134 } 00135 00136 const Expr *getArgExpr(unsigned i) const { 00137 assert(i < getNumArgs() && "Invalid index for argument"); 00138 return Msg->getArg(i); 00139 } 00140 00141 SourceRange getArgSourceRange(unsigned i) const { 00142 const Expr *argE = getArgExpr(i); 00143 return argE->getSourceRange(); 00144 } 00145 00146 SourceRange getReceiverSourceRange() const { 00147 if (PE) { 00148 if (PE->isObjectReceiver()) 00149 return PE->getBase()->getSourceRange(); 00150 } 00151 else { 00152 return Msg->getReceiverRange(); 00153 } 00154 00155 // FIXME: This isn't a range. 00156 return PE->getReceiverLocation(); 00157 } 00158 }; 00159 00160 /// \brief Common wrapper for a call expression, ObjC message, or C++ 00161 /// constructor, mainly to provide a common interface for their arguments. 00162 class CallOrObjCMessage { 00163 llvm::PointerUnion<const CallExpr *, const CXXConstructExpr *> CallE; 00164 ObjCMessage Msg; 00165 ProgramStateRef State; 00166 const LocationContext *LCtx; 00167 00168 bool isCallbackArg(unsigned Idx, const Type *T) const; 00169 00170 public: 00171 CallOrObjCMessage(const CallExpr *callE, ProgramStateRef state, 00172 const LocationContext *lctx) 00173 : CallE(callE), State(state), LCtx(lctx) {} 00174 CallOrObjCMessage(const CXXConstructExpr *consE, ProgramStateRef state, 00175 const LocationContext *lctx) 00176 : CallE(consE), State(state), LCtx(lctx) {} 00177 CallOrObjCMessage(const ObjCMessage &msg, ProgramStateRef state, 00178 const LocationContext *lctx) 00179 : CallE((CallExpr *)0), Msg(msg), State(state), LCtx(lctx) {} 00180 00181 QualType getResultType(ASTContext &ctx) const; 00182 00183 bool isFunctionCall() const { 00184 return CallE && CallE.is<const CallExpr *>(); 00185 } 00186 00187 bool isCXXConstructExpr() const { 00188 return CallE && CallE.is<const CXXConstructExpr *>(); 00189 } 00190 00191 bool isObjCMessage() const { 00192 return !CallE; 00193 } 00194 00195 bool isCXXCall() const { 00196 const CallExpr *ActualCallE = CallE.dyn_cast<const CallExpr *>(); 00197 return ActualCallE && isa<CXXMemberCallExpr>(ActualCallE); 00198 } 00199 00200 /// Check if the callee is declared in the system header. 00201 bool isInSystemHeader() const { 00202 if (const Decl *FD = getDecl()) { 00203 const SourceManager &SM = 00204 State->getStateManager().getContext().getSourceManager(); 00205 return SM.isInSystemHeader(FD->getLocation()); 00206 } 00207 return false; 00208 } 00209 00210 const Expr *getOriginExpr() const { 00211 if (!CallE) 00212 return Msg.getMessageExpr(); 00213 if (const CXXConstructExpr *Ctor = 00214 CallE.dyn_cast<const CXXConstructExpr *>()) 00215 return Ctor; 00216 return CallE.get<const CallExpr *>(); 00217 } 00218 00219 SVal getFunctionCallee() const; 00220 SVal getCXXCallee() const; 00221 SVal getInstanceMessageReceiver(const LocationContext *LC) const; 00222 00223 /// Get the declaration of the function or method. 00224 const Decl *getDecl() const; 00225 00226 unsigned getNumArgs() const { 00227 if (!CallE) 00228 return Msg.getNumArgs(); 00229 if (const CXXConstructExpr *Ctor = 00230 CallE.dyn_cast<const CXXConstructExpr *>()) 00231 return Ctor->getNumArgs(); 00232 return CallE.get<const CallExpr *>()->getNumArgs(); 00233 } 00234 00235 SVal getArgSVal(unsigned i) const { 00236 assert(i < getNumArgs()); 00237 if (!CallE) 00238 return Msg.getArgSVal(i, LCtx, State); 00239 return State->getSVal(getArg(i), LCtx); 00240 } 00241 00242 const Expr *getArg(unsigned i) const { 00243 assert(i < getNumArgs()); 00244 if (!CallE) 00245 return Msg.getArgExpr(i); 00246 if (const CXXConstructExpr *Ctor = 00247 CallE.dyn_cast<const CXXConstructExpr *>()) 00248 return Ctor->getArg(i); 00249 return CallE.get<const CallExpr *>()->getArg(i); 00250 } 00251 00252 SourceRange getArgSourceRange(unsigned i) const { 00253 assert(i < getNumArgs()); 00254 if (CallE) 00255 return getArg(i)->getSourceRange(); 00256 return Msg.getArgSourceRange(i); 00257 } 00258 00259 SourceRange getReceiverSourceRange() const { 00260 assert(isObjCMessage()); 00261 return Msg.getReceiverSourceRange(); 00262 } 00263 00264 /// \brief Check if one of the arguments might be a callback. 00265 bool hasNonZeroCallbackArg() const; 00266 00267 00268 /// \brief Check if the name corresponds to a CoreFoundation or CoreGraphics 00269 /// function that allows objects to escape. 00270 /// 00271 /// Many methods allow a tracked object to escape. For example: 00272 /// 00273 /// CFMutableDictionaryRef x = CFDictionaryCreateMutable(..., customDeallocator); 00274 /// CFDictionaryAddValue(y, key, x); 00275 /// 00276 /// We handle this and similar cases with the following heuristic. If the 00277 /// function name contains "InsertValue", "SetValue", "AddValue", 00278 /// "AppendValue", or "SetAttribute", then we assume that arguments may 00279 /// escape. 00280 // 00281 // TODO: To reduce false negatives here, we should track the container 00282 // allocation site and check if a proper deallocator was set there. 00283 static bool isCFCGAllowingEscape(StringRef FName); 00284 }; 00285 00286 } 00287 } 00288 00289 #endif