ExprObjC.h revision e66f4e3e3ae9d7d11b0c302211066fad69228aba
1//===--- ExprObjC.h - Classes for representing ObjC expressions -*- 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 the ExprObjC interface and subclasses. 11// 12//===----------------------------------------------------------------------===// 13 14#ifndef LLVM_CLANG_AST_EXPROBJC_H 15#define LLVM_CLANG_AST_EXPROBJC_H 16 17#include "clang/AST/Expr.h" 18#include "clang/Basic/IdentifierTable.h" 19 20namespace clang { 21 class IdentifierInfo; 22 class ASTContext; 23 class ObjCMethodDecl; 24 class ObjCPropertyDecl; 25 26/// ObjCStringLiteral, used for Objective-C string literals 27/// i.e. @"foo". 28class ObjCStringLiteral : public Expr { 29 StringLiteral *String; 30 SourceLocation AtLoc; 31public: 32 ObjCStringLiteral(StringLiteral *SL, QualType T, SourceLocation L) 33 : Expr(ObjCStringLiteralClass, T), String(SL), AtLoc(L) {} 34 35 StringLiteral* getString() { return String; } 36 37 const StringLiteral* getString() const { return String; } 38 39 SourceLocation getAtLoc() const { return AtLoc; } 40 41 virtual SourceRange getSourceRange() const { 42 return SourceRange(AtLoc, String->getLocEnd()); 43 } 44 45 static bool classof(const Stmt *T) { 46 return T->getStmtClass() == ObjCStringLiteralClass; 47 } 48 static bool classof(const ObjCStringLiteral *) { return true; } 49 50 // Iterators 51 virtual child_iterator child_begin(); 52 virtual child_iterator child_end(); 53 54 virtual void EmitImpl(llvm::Serializer& S) const; 55 static ObjCStringLiteral* CreateImpl(llvm::Deserializer& D, ASTContext& C); 56}; 57 58/// ObjCEncodeExpr, used for @encode in Objective-C. 59class ObjCEncodeExpr : public Expr { 60 QualType EncType; 61 SourceLocation AtLoc, RParenLoc; 62public: 63 ObjCEncodeExpr(QualType T, QualType ET, 64 SourceLocation at, SourceLocation rp) 65 : Expr(ObjCEncodeExprClass, T), EncType(ET), AtLoc(at), RParenLoc(rp) {} 66 67 SourceLocation getAtLoc() const { return AtLoc; } 68 SourceLocation getRParenLoc() const { return RParenLoc; } 69 70 virtual SourceRange getSourceRange() const { 71 return SourceRange(AtLoc, RParenLoc); 72 } 73 74 QualType getEncodedType() const { return EncType; } 75 76 static bool classof(const Stmt *T) { 77 return T->getStmtClass() == ObjCEncodeExprClass; 78 } 79 static bool classof(const ObjCEncodeExpr *) { return true; } 80 81 // Iterators 82 virtual child_iterator child_begin(); 83 virtual child_iterator child_end(); 84 85 virtual void EmitImpl(llvm::Serializer& S) const; 86 static ObjCEncodeExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C); 87}; 88 89/// ObjCSelectorExpr used for @selector in Objective-C. 90class ObjCSelectorExpr : public Expr { 91 Selector SelName; 92 SourceLocation AtLoc, RParenLoc; 93public: 94 ObjCSelectorExpr(QualType T, Selector selInfo, 95 SourceLocation at, SourceLocation rp) 96 : Expr(ObjCSelectorExprClass, T), SelName(selInfo), 97 AtLoc(at), RParenLoc(rp) {} 98 99 Selector getSelector() const { return SelName; } 100 101 SourceLocation getAtLoc() const { return AtLoc; } 102 SourceLocation getRParenLoc() const { return RParenLoc; } 103 104 virtual SourceRange getSourceRange() const { 105 return SourceRange(AtLoc, RParenLoc); 106 } 107 108 /// getNumArgs - Return the number of actual arguments to this call. 109 unsigned getNumArgs() const { return SelName.getNumArgs(); } 110 111 static bool classof(const Stmt *T) { 112 return T->getStmtClass() == ObjCSelectorExprClass; 113 } 114 static bool classof(const ObjCSelectorExpr *) { return true; } 115 116 // Iterators 117 virtual child_iterator child_begin(); 118 virtual child_iterator child_end(); 119 120 virtual void EmitImpl(llvm::Serializer& S) const; 121 static ObjCSelectorExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C); 122}; 123 124/// ObjCProtocolExpr used for protocol in Objective-C. 125class ObjCProtocolExpr : public Expr { 126 ObjCProtocolDecl *Protocol; 127 SourceLocation AtLoc, RParenLoc; 128public: 129 ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol, 130 SourceLocation at, SourceLocation rp) 131 : Expr(ObjCProtocolExprClass, T), Protocol(protocol), 132 AtLoc(at), RParenLoc(rp) {} 133 134 ObjCProtocolDecl *getProtocol() const { return Protocol; } 135 136 SourceLocation getAtLoc() const { return AtLoc; } 137 SourceLocation getRParenLoc() const { return RParenLoc; } 138 139 virtual SourceRange getSourceRange() const { 140 return SourceRange(AtLoc, RParenLoc); 141 } 142 143 static bool classof(const Stmt *T) { 144 return T->getStmtClass() == ObjCProtocolExprClass; 145 } 146 static bool classof(const ObjCProtocolExpr *) { return true; } 147 148 // Iterators 149 virtual child_iterator child_begin(); 150 virtual child_iterator child_end(); 151}; 152 153/// ObjCIvarRefExpr - A reference to an ObjC instance variable. 154class ObjCIvarRefExpr : public Expr { 155 class ObjCIvarDecl *D; 156 SourceLocation Loc; 157 Stmt *Base; 158 bool IsArrow:1; // True if this is "X->F", false if this is "X.F". 159 bool IsFreeIvar:1; // True if ivar reference has no base (self assumed). 160 161public: 162 ObjCIvarRefExpr(ObjCIvarDecl *d, QualType t, SourceLocation l, Expr *base=0, 163 bool arrow = false, bool freeIvar = false) : 164 Expr(ObjCIvarRefExprClass, t), D(d), Loc(l), Base(base), IsArrow(arrow), 165 IsFreeIvar(freeIvar) {} 166 167 ObjCIvarDecl *getDecl() { return D; } 168 const ObjCIvarDecl *getDecl() const { return D; } 169 virtual SourceRange getSourceRange() const { 170 return isFreeIvar() ? SourceRange(Loc) 171 : SourceRange(getBase()->getLocStart(), Loc); 172 } 173 const Expr *getBase() const { return cast<Expr>(Base); } 174 Expr *getBase() { return cast<Expr>(Base); } 175 void setBase(Expr * base) { Base = base; } 176 bool isArrow() const { return IsArrow; } 177 bool isFreeIvar() const { return IsFreeIvar; } 178 179 SourceLocation getLocation() const { return Loc; } 180 181 static bool classof(const Stmt *T) { 182 return T->getStmtClass() == ObjCIvarRefExprClass; 183 } 184 static bool classof(const ObjCIvarRefExpr *) { return true; } 185 186 // Iterators 187 virtual child_iterator child_begin(); 188 virtual child_iterator child_end(); 189 190 virtual void EmitImpl(llvm::Serializer& S) const; 191 static ObjCIvarRefExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C); 192}; 193 194/// ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC 195/// property. Note that dot-syntax can also be used to access 196/// "implicit" properties (i.e. methods following the property naming 197/// convention). Additionally, sema is not yet smart enough to know if 198/// a property reference is to a getter or a setter, so the expr must 199/// have access to both methods. 200/// 201// FIXME: Consider splitting these into separate Expr classes. 202class ObjCPropertyRefExpr : public Expr { 203public: 204 enum Kind { 205 PropertyRef, // This expressions references a declared property. 206 MethodRef // This expressions references methods. 207 }; 208 209private: 210 // A dot-syntax reference via methods must always have a getter. We 211 // avoid storing the kind explicitly by relying on this invariant 212 // and assuming this is a MethodRef iff Getter is non-null. Setter 213 // can be null in situations which access a read-only property. 214 union { 215 ObjCPropertyDecl *AsProperty; 216 struct { 217 ObjCMethodDecl *Setter; 218 ObjCMethodDecl *Getter; 219 } AsMethod; 220 } Referent; 221 SourceLocation Loc; 222 Stmt *Base; 223 224public: 225 ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t, 226 SourceLocation l, Expr *base) 227 : Expr(ObjCPropertyRefExprClass, t), Loc(l), Base(base) { 228 Referent.AsMethod.Getter = Referent.AsMethod.Setter = NULL; 229 Referent.AsProperty = PD; 230 } 231 ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter, 232 QualType t, 233 SourceLocation l, Expr *base) 234 : Expr(ObjCPropertyRefExprClass, t), Loc(l), Base(base) { 235 Referent.AsMethod.Getter = Getter; 236 Referent.AsMethod.Setter = Setter; 237 } 238 239 Kind getKind() const { 240 return Referent.AsMethod.Getter ? MethodRef : PropertyRef; 241 } 242 243 ObjCPropertyDecl *getProperty() const { 244 assert(getKind() == PropertyRef && 245 "Cannot get property from an ObjCPropertyRefExpr using methods"); 246 return Referent.AsProperty; 247 } 248 ObjCMethodDecl *getGetterMethod() const { 249 assert(getKind() == MethodRef && 250 "Cannot get method from an ObjCPropertyRefExpr using a property"); 251 return Referent.AsMethod.Getter; 252 } 253 ObjCMethodDecl *getSetterMethod() const { 254 assert(getKind() == MethodRef && 255 "Cannot get method from an ObjCPropertyRefExpr using a property"); 256 return Referent.AsMethod.Setter; 257 } 258 259 virtual SourceRange getSourceRange() const { 260 return SourceRange(getBase()->getLocStart(), Loc); 261 } 262 const Expr *getBase() const { return cast<Expr>(Base); } 263 Expr *getBase() { return cast<Expr>(Base); } 264 void setBase(Expr * base) { Base = base; } 265 266 SourceLocation getLocation() const { return Loc; } 267 268 static bool classof(const Stmt *T) { 269 return T->getStmtClass() == ObjCPropertyRefExprClass; 270 } 271 static bool classof(const ObjCPropertyRefExpr *) { return true; } 272 273 // Iterators 274 virtual child_iterator child_begin(); 275 virtual child_iterator child_end(); 276 277 virtual void EmitImpl(llvm::Serializer& S) const; 278 static ObjCPropertyRefExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C); 279}; 280 281class ObjCMessageExpr : public Expr { 282 // SubExprs - The receiver and arguments of the message expression. 283 Stmt **SubExprs; 284 285 // NumArgs - The number of arguments (not including the receiver) to the 286 // message expression. 287 unsigned NumArgs; 288 289 // A unigue name for this message. 290 Selector SelName; 291 292 // A method prototype for this message (optional). 293 // FIXME: Since method decls contain the selector, and most messages have a 294 // prototype, consider devising a scheme for unifying SelName/MethodProto. 295 ObjCMethodDecl *MethodProto; 296 297 SourceLocation LBracloc, RBracloc; 298 299 // Constants for indexing into SubExprs. 300 enum { RECEIVER=0, ARGS_START=1 }; 301 302 // Bit-swizziling flags. 303 enum { IsInstMeth=0, IsClsMethDeclUnknown, IsClsMethDeclKnown, Flags=0x3 }; 304 unsigned getFlag() const { return (uintptr_t) SubExprs[RECEIVER] & Flags; } 305 306 // constructor used during deserialization 307 ObjCMessageExpr(Selector selInfo, QualType retType, 308 SourceLocation LBrac, SourceLocation RBrac, 309 Stmt **subexprs, unsigned nargs) 310 : Expr(ObjCMessageExprClass, retType), SubExprs(subexprs), 311 NumArgs(nargs), SelName(selInfo), MethodProto(NULL), 312 LBracloc(LBrac), RBracloc(RBrac) {} 313 314public: 315 /// This constructor is used to represent class messages where the 316 /// ObjCInterfaceDecl* of the receiver is not known. 317 ObjCMessageExpr(IdentifierInfo *clsName, Selector selInfo, 318 QualType retType, ObjCMethodDecl *methDecl, 319 SourceLocation LBrac, SourceLocation RBrac, 320 Expr **ArgExprs, unsigned NumArgs); 321 322 /// This constructor is used to represent class messages where the 323 /// ObjCInterfaceDecl* of the receiver is known. 324 // FIXME: clsName should be typed to ObjCInterfaceType 325 ObjCMessageExpr(ObjCInterfaceDecl *cls, Selector selInfo, 326 QualType retType, ObjCMethodDecl *methDecl, 327 SourceLocation LBrac, SourceLocation RBrac, 328 Expr **ArgExprs, unsigned NumArgs); 329 330 // constructor for instance messages. 331 ObjCMessageExpr(Expr *receiver, Selector selInfo, 332 QualType retType, ObjCMethodDecl *methDecl, 333 SourceLocation LBrac, SourceLocation RBrac, 334 Expr **ArgExprs, unsigned NumArgs); 335 336 ~ObjCMessageExpr() { 337 delete [] SubExprs; 338 } 339 340 /// getReceiver - Returns the receiver of the message expression. 341 /// This can be NULL if the message is for class methods. For 342 /// class methods, use getClassName. 343 /// FIXME: need to handle/detect 'super' usage within a class method. 344 Expr *getReceiver() { 345 uintptr_t x = (uintptr_t) SubExprs[RECEIVER]; 346 return (x & Flags) == IsInstMeth ? (Expr*) x : 0; 347 } 348 const Expr *getReceiver() const { 349 return const_cast<ObjCMessageExpr*>(this)->getReceiver(); 350 } 351 352 Selector getSelector() const { return SelName; } 353 354 const ObjCMethodDecl *getMethodDecl() const { return MethodProto; } 355 ObjCMethodDecl *getMethodDecl() { return MethodProto; } 356 357 typedef std::pair<ObjCInterfaceDecl*, IdentifierInfo*> ClassInfo; 358 359 /// getClassInfo - For class methods, this returns both the ObjCInterfaceDecl* 360 /// and IdentifierInfo* of the invoked class. Both can be NULL if this 361 /// is an instance message, and the ObjCInterfaceDecl* can be NULL if none 362 /// was available when this ObjCMessageExpr object was constructed. 363 ClassInfo getClassInfo() const; 364 365 /// getClassName - For class methods, this returns the invoked class, 366 /// and returns NULL otherwise. For instance methods, use getReceiver. 367 IdentifierInfo *getClassName() const { 368 return getClassInfo().second; 369 } 370 371 372 /// getNumArgs - Return the number of actual arguments to this call. 373 unsigned getNumArgs() const { return NumArgs; } 374 375 /// getArg - Return the specified argument. 376 Expr *getArg(unsigned Arg) { 377 assert(Arg < NumArgs && "Arg access out of range!"); 378 return cast<Expr>(SubExprs[Arg+ARGS_START]); 379 } 380 const Expr *getArg(unsigned Arg) const { 381 assert(Arg < NumArgs && "Arg access out of range!"); 382 return cast<Expr>(SubExprs[Arg+ARGS_START]); 383 } 384 /// setArg - Set the specified argument. 385 void setArg(unsigned Arg, Expr *ArgExpr) { 386 assert(Arg < NumArgs && "Arg access out of range!"); 387 SubExprs[Arg+ARGS_START] = ArgExpr; 388 } 389 390 virtual SourceRange getSourceRange() const { 391 return SourceRange(LBracloc, RBracloc); 392 } 393 394 static bool classof(const Stmt *T) { 395 return T->getStmtClass() == ObjCMessageExprClass; 396 } 397 static bool classof(const ObjCMessageExpr *) { return true; } 398 399 // Iterators 400 virtual child_iterator child_begin(); 401 virtual child_iterator child_end(); 402 403 typedef ExprIterator arg_iterator; 404 typedef ConstExprIterator const_arg_iterator; 405 406 arg_iterator arg_begin() { return &SubExprs[ARGS_START]; } 407 arg_iterator arg_end() { return &SubExprs[ARGS_START] + NumArgs; } 408 const_arg_iterator arg_begin() const { return &SubExprs[ARGS_START]; } 409 const_arg_iterator arg_end() const { return &SubExprs[ARGS_START] + NumArgs; } 410 411 // Serialization. 412 virtual void EmitImpl(llvm::Serializer& S) const; 413 static ObjCMessageExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C); 414}; 415 416} // end namespace clang 417 418#endif 419