ExprObjC.h revision d17c24ff8597fe0dee4210639d225bc4f7c5ac04
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 virtual void EmitImpl(llvm::Serializer& S) const; 153 static ObjCProtocolExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C); 154}; 155 156/// ObjCIvarRefExpr - A reference to an ObjC instance variable. 157class ObjCIvarRefExpr : public Expr { 158 class ObjCIvarDecl *D; 159 SourceLocation Loc; 160 Stmt *Base; 161 bool IsArrow:1; // True if this is "X->F", false if this is "X.F". 162 bool IsFreeIvar:1; // True if ivar reference has no base (self assumed). 163 164public: 165 ObjCIvarRefExpr(ObjCIvarDecl *d, QualType t, SourceLocation l, Expr *base=0, 166 bool arrow = false, bool freeIvar = false) : 167 Expr(ObjCIvarRefExprClass, t), D(d), Loc(l), Base(base), IsArrow(arrow), 168 IsFreeIvar(freeIvar) {} 169 170 ObjCIvarDecl *getDecl() { return D; } 171 const ObjCIvarDecl *getDecl() const { return D; } 172 virtual SourceRange getSourceRange() const { 173 return isFreeIvar() ? SourceRange(Loc) 174 : SourceRange(getBase()->getLocStart(), Loc); 175 } 176 const Expr *getBase() const { return cast<Expr>(Base); } 177 Expr *getBase() { return cast<Expr>(Base); } 178 void setBase(Expr * base) { Base = base; } 179 bool isArrow() const { return IsArrow; } 180 bool isFreeIvar() const { return IsFreeIvar; } 181 182 SourceLocation getLocation() const { return Loc; } 183 184 static bool classof(const Stmt *T) { 185 return T->getStmtClass() == ObjCIvarRefExprClass; 186 } 187 static bool classof(const ObjCIvarRefExpr *) { return true; } 188 189 // Iterators 190 virtual child_iterator child_begin(); 191 virtual child_iterator child_end(); 192 193 virtual void EmitImpl(llvm::Serializer& S) const; 194 static ObjCIvarRefExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C); 195}; 196 197/// ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC 198/// property. Note that dot-syntax can also be used to access 199/// "implicit" properties (i.e. methods following the property naming 200/// convention). Additionally, sema is not yet smart enough to know if 201/// a property reference is to a getter or a setter, so the expr must 202/// have access to both methods. 203/// 204// FIXME: Consider splitting these into separate Expr classes. 205class ObjCPropertyRefExpr : public Expr { 206public: 207 enum Kind { 208 PropertyRef, // This expressions references a declared property. 209 MethodRef // This expressions references methods. 210 }; 211 212private: 213 // A dot-syntax reference via methods must always have a getter. We 214 // avoid storing the kind explicitly by relying on this invariant 215 // and assuming this is a MethodRef iff Getter is non-null. Setter 216 // can be null in situations which access a read-only property. 217 union { 218 ObjCPropertyDecl *AsProperty; 219 struct { 220 ObjCMethodDecl *Setter; 221 ObjCMethodDecl *Getter; 222 } AsMethod; 223 } Referent; 224 SourceLocation Loc; 225 Stmt *Base; 226 227public: 228 ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t, 229 SourceLocation l, Expr *base) 230 : Expr(ObjCPropertyRefExprClass, t), Loc(l), Base(base) { 231 Referent.AsMethod.Getter = Referent.AsMethod.Setter = NULL; 232 Referent.AsProperty = PD; 233 } 234 ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter, 235 QualType t, 236 SourceLocation l, Expr *base) 237 : Expr(ObjCPropertyRefExprClass, t), Loc(l), Base(base) { 238 Referent.AsMethod.Getter = Getter; 239 Referent.AsMethod.Setter = Setter; 240 } 241 242 Kind getKind() const { 243 return Referent.AsMethod.Getter ? MethodRef : PropertyRef; 244 } 245 246 ObjCPropertyDecl *getProperty() const { 247 assert(getKind() == PropertyRef && 248 "Cannot get property from an ObjCPropertyRefExpr using methods"); 249 return Referent.AsProperty; 250 } 251 ObjCMethodDecl *getGetterMethod() const { 252 assert(getKind() == MethodRef && 253 "Cannot get method from an ObjCPropertyRefExpr using a property"); 254 return Referent.AsMethod.Getter; 255 } 256 ObjCMethodDecl *getSetterMethod() const { 257 assert(getKind() == MethodRef && 258 "Cannot get method from an ObjCPropertyRefExpr using a property"); 259 return Referent.AsMethod.Setter; 260 } 261 262 virtual SourceRange getSourceRange() const { 263 return SourceRange(getBase()->getLocStart(), Loc); 264 } 265 const Expr *getBase() const { return cast<Expr>(Base); } 266 Expr *getBase() { return cast<Expr>(Base); } 267 void setBase(Expr * base) { Base = base; } 268 269 SourceLocation getLocation() const { return Loc; } 270 271 static bool classof(const Stmt *T) { 272 return T->getStmtClass() == ObjCPropertyRefExprClass; 273 } 274 static bool classof(const ObjCPropertyRefExpr *) { return true; } 275 276 // Iterators 277 virtual child_iterator child_begin(); 278 virtual child_iterator child_end(); 279 280 virtual void EmitImpl(llvm::Serializer& S) const; 281 static ObjCPropertyRefExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C); 282}; 283 284class ObjCMessageExpr : public Expr { 285 // SubExprs - The receiver and arguments of the message expression. 286 Stmt **SubExprs; 287 288 // NumArgs - The number of arguments (not including the receiver) to the 289 // message expression. 290 unsigned NumArgs; 291 292 // A unigue name for this message. 293 Selector SelName; 294 295 // A method prototype for this message (optional). 296 // FIXME: Since method decls contain the selector, and most messages have a 297 // prototype, consider devising a scheme for unifying SelName/MethodProto. 298 ObjCMethodDecl *MethodProto; 299 300 SourceLocation LBracloc, RBracloc; 301 302 // Constants for indexing into SubExprs. 303 enum { RECEIVER=0, ARGS_START=1 }; 304 305 // Bit-swizziling flags. 306 enum { IsInstMeth=0, IsClsMethDeclUnknown, IsClsMethDeclKnown, Flags=0x3 }; 307 unsigned getFlag() const { return (uintptr_t) SubExprs[RECEIVER] & Flags; } 308 309 // constructor used during deserialization 310 ObjCMessageExpr(Selector selInfo, QualType retType, 311 SourceLocation LBrac, SourceLocation RBrac, 312 Stmt **subexprs, unsigned nargs) 313 : Expr(ObjCMessageExprClass, retType), SubExprs(subexprs), 314 NumArgs(nargs), SelName(selInfo), MethodProto(NULL), 315 LBracloc(LBrac), RBracloc(RBrac) {} 316 317public: 318 /// This constructor is used to represent class messages where the 319 /// ObjCInterfaceDecl* of the receiver is not known. 320 ObjCMessageExpr(IdentifierInfo *clsName, Selector selInfo, 321 QualType retType, ObjCMethodDecl *methDecl, 322 SourceLocation LBrac, SourceLocation RBrac, 323 Expr **ArgExprs, unsigned NumArgs); 324 325 /// This constructor is used to represent class messages where the 326 /// ObjCInterfaceDecl* of the receiver is known. 327 // FIXME: clsName should be typed to ObjCInterfaceType 328 ObjCMessageExpr(ObjCInterfaceDecl *cls, Selector selInfo, 329 QualType retType, ObjCMethodDecl *methDecl, 330 SourceLocation LBrac, SourceLocation RBrac, 331 Expr **ArgExprs, unsigned NumArgs); 332 333 // constructor for instance messages. 334 ObjCMessageExpr(Expr *receiver, Selector selInfo, 335 QualType retType, ObjCMethodDecl *methDecl, 336 SourceLocation LBrac, SourceLocation RBrac, 337 Expr **ArgExprs, unsigned NumArgs); 338 339 ~ObjCMessageExpr() { 340 delete [] SubExprs; 341 } 342 343 /// getReceiver - Returns the receiver of the message expression. 344 /// This can be NULL if the message is for class methods. For 345 /// class methods, use getClassName. 346 /// FIXME: need to handle/detect 'super' usage within a class method. 347 Expr *getReceiver() { 348 uintptr_t x = (uintptr_t) SubExprs[RECEIVER]; 349 return (x & Flags) == IsInstMeth ? (Expr*) x : 0; 350 } 351 const Expr *getReceiver() const { 352 return const_cast<ObjCMessageExpr*>(this)->getReceiver(); 353 } 354 355 Selector getSelector() const { return SelName; } 356 357 const ObjCMethodDecl *getMethodDecl() const { return MethodProto; } 358 ObjCMethodDecl *getMethodDecl() { return MethodProto; } 359 360 typedef std::pair<ObjCInterfaceDecl*, IdentifierInfo*> ClassInfo; 361 362 /// getClassInfo - For class methods, this returns both the ObjCInterfaceDecl* 363 /// and IdentifierInfo* of the invoked class. Both can be NULL if this 364 /// is an instance message, and the ObjCInterfaceDecl* can be NULL if none 365 /// was available when this ObjCMessageExpr object was constructed. 366 ClassInfo getClassInfo() const; 367 368 /// getClassName - For class methods, this returns the invoked class, 369 /// and returns NULL otherwise. For instance methods, use getReceiver. 370 IdentifierInfo *getClassName() const { 371 return getClassInfo().second; 372 } 373 374 375 /// getNumArgs - Return the number of actual arguments to this call. 376 unsigned getNumArgs() const { return NumArgs; } 377 378 /// getArg - Return the specified argument. 379 Expr *getArg(unsigned Arg) { 380 assert(Arg < NumArgs && "Arg access out of range!"); 381 return cast<Expr>(SubExprs[Arg+ARGS_START]); 382 } 383 const Expr *getArg(unsigned Arg) const { 384 assert(Arg < NumArgs && "Arg access out of range!"); 385 return cast<Expr>(SubExprs[Arg+ARGS_START]); 386 } 387 /// setArg - Set the specified argument. 388 void setArg(unsigned Arg, Expr *ArgExpr) { 389 assert(Arg < NumArgs && "Arg access out of range!"); 390 SubExprs[Arg+ARGS_START] = ArgExpr; 391 } 392 393 virtual SourceRange getSourceRange() const { 394 return SourceRange(LBracloc, RBracloc); 395 } 396 397 static bool classof(const Stmt *T) { 398 return T->getStmtClass() == ObjCMessageExprClass; 399 } 400 static bool classof(const ObjCMessageExpr *) { return true; } 401 402 // Iterators 403 virtual child_iterator child_begin(); 404 virtual child_iterator child_end(); 405 406 typedef ExprIterator arg_iterator; 407 typedef ConstExprIterator const_arg_iterator; 408 409 arg_iterator arg_begin() { return &SubExprs[ARGS_START]; } 410 arg_iterator arg_end() { return &SubExprs[ARGS_START] + NumArgs; } 411 const_arg_iterator arg_begin() const { return &SubExprs[ARGS_START]; } 412 const_arg_iterator arg_end() const { return &SubExprs[ARGS_START] + NumArgs; } 413 414 // Serialization. 415 virtual void EmitImpl(llvm::Serializer& S) const; 416 static ObjCMessageExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C); 417}; 418 419} // end namespace clang 420 421#endif 422