DeclObjC.h revision cffe36686142e06ce67fd4f0469ecc58e1286bdf
1//===--- DeclObjC.h - Classes for representing declarations -----*- 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 DeclObjC interface and subclasses. 11// 12//===----------------------------------------------------------------------===// 13 14#ifndef LLVM_CLANG_AST_DECLOBJC_H 15#define LLVM_CLANG_AST_DECLOBJC_H 16 17#include "clang/AST/Decl.h" 18#include "clang/Basic/IdentifierTable.h" 19 20namespace clang { 21class Expr; 22class Stmt; 23class FunctionDecl; 24class AttributeList; 25class ObjCIvarDecl; 26class ObjCMethodDecl; 27class ObjCProtocolDecl; 28class ObjCCategoryDecl; 29class ObjCPropertyDecl; 30 31/// ObjCMethodDecl - Represents an instance or class method declaration. 32/// ObjC methods can be declared within 4 contexts: class interfaces, 33/// categories, protocols, and class implementations. While C++ member 34/// functions leverage C syntax, Objective-C method syntax is modeled after 35/// Smalltalk (using colons to specify argument types/expressions). 36/// Here are some brief examples: 37/// 38/// Setter/getter instance methods: 39/// - (void)setMenu:(NSMenu *)menu; 40/// - (NSMenu *)menu; 41/// 42/// Instance method that takes 2 NSView arguments: 43/// - (void)replaceSubview:(NSView *)oldView with:(NSView *)newView; 44/// 45/// Getter class method: 46/// + (NSMenu *)defaultMenu; 47/// 48/// A selector represents a unique name for a method. The selector names for 49/// the above methods are setMenu:, menu, replaceSubview:with:, and defaultMenu. 50/// 51class ObjCMethodDecl : public Decl { 52public: 53 enum ImplementationControl { None, Required, Optional }; 54private: 55 /// Bitfields must be first fields in this class so they pack with those 56 /// declared in class Decl. 57 /// instance (true) or class (false) method. 58 bool IsInstance : 1; 59 bool IsVariadic : 1; 60 61 // NOTE: VC++ treats enums as signed, avoid using ImplementationControl enum 62 /// @required/@optional 63 unsigned DeclImplementation : 2; 64 65 // NOTE: VC++ treats enums as signed, avoid using the ObjCDeclQualifier enum 66 /// in, inout, etc. 67 unsigned objcDeclQualifier : 6; 68 69 // Context this method is declared in. 70 NamedDecl *MethodContext; 71 72 // A unigue name for this method. 73 Selector SelName; 74 75 // Type of this method. 76 QualType MethodDeclType; 77 /// ParamInfo - new[]'d array of pointers to VarDecls for the formal 78 /// parameters of this Method. This is null if there are no formals. 79 ParmVarDecl **ParamInfo; 80 unsigned NumMethodParams; 81 82 /// List of attributes for this method declaration. 83 AttributeList *MethodAttrs; 84 85 SourceLocation EndLoc; // the location of the ';' or '{'. 86 87 // The following are only used for method definitions, null otherwise. 88 // FIXME: space savings opportunity, consider a sub-class. 89 Stmt *Body; 90 ParmVarDecl *SelfDecl; 91 92 ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc, 93 Selector SelInfo, QualType T, 94 Decl *contextDecl, 95 AttributeList *M = 0, bool isInstance = true, 96 bool isVariadic = false, 97 ImplementationControl impControl = None) 98 : Decl(ObjCMethod, beginLoc), 99 IsInstance(isInstance), IsVariadic(isVariadic), 100 DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None), 101 MethodContext(static_cast<NamedDecl*>(contextDecl)), 102 SelName(SelInfo), MethodDeclType(T), 103 ParamInfo(0), NumMethodParams(0), 104 MethodAttrs(M), EndLoc(endLoc), Body(0), SelfDecl(0) {} 105 virtual ~ObjCMethodDecl(); 106public: 107 108 static ObjCMethodDecl *Create(ASTContext &C, SourceLocation beginLoc, 109 SourceLocation endLoc, Selector SelInfo, 110 QualType T, Decl *contextDecl, 111 AttributeList *M = 0, bool isInstance = true, 112 bool isVariadic = false, 113 ImplementationControl impControl = None); 114 115 ObjCDeclQualifier getObjCDeclQualifier() const { 116 return ObjCDeclQualifier(objcDeclQualifier); 117 } 118 void setObjCDeclQualifier(ObjCDeclQualifier QV) { objcDeclQualifier = QV; } 119 120 // Location information, modeled after the Stmt API. 121 SourceLocation getLocStart() const { return getLocation(); } 122 SourceLocation getLocEnd() const { return EndLoc; } 123 124 NamedDecl *getMethodContext() const { return MethodContext; } 125 126 ObjCInterfaceDecl *const getClassInterface() const; 127 128 Selector getSelector() const { return SelName; } 129 unsigned getSynthesizedMethodSize() const; 130 QualType getResultType() const { return MethodDeclType; } 131 132 // Iterator access to formal parameters. 133 unsigned param_size() const { return NumMethodParams; } 134 typedef ParmVarDecl **param_iterator; 135 typedef ParmVarDecl * const *param_const_iterator; 136 param_iterator param_begin() { return ParamInfo; } 137 param_iterator param_end() { return ParamInfo+param_size(); } 138 param_const_iterator param_begin() const { return ParamInfo; } 139 param_const_iterator param_end() const { return ParamInfo+param_size(); } 140 141 unsigned getNumParams() const { return NumMethodParams; } 142 ParmVarDecl *getParamDecl(unsigned i) const { 143 assert(i < getNumParams() && "Illegal param #"); 144 return ParamInfo[i]; 145 } 146 void setParamDecl(int i, ParmVarDecl *pDecl) { 147 ParamInfo[i] = pDecl; 148 } 149 void setMethodParams(ParmVarDecl **NewParamInfo, unsigned NumParams); 150 151 AttributeList *getMethodAttrs() const {return MethodAttrs;} 152 bool isInstance() const { return IsInstance; } 153 bool isVariadic() const { return IsVariadic; } 154 155 // Related to protocols declared in @protocol 156 void setDeclImplementation(ImplementationControl ic) { 157 DeclImplementation = ic; 158 } 159 ImplementationControl getImplementationControl() const { 160 return ImplementationControl(DeclImplementation); 161 } 162 Stmt *const getBody() const { return Body; } 163 void setBody(Stmt *B) { Body = B; } 164 165 ParmVarDecl *const getSelfDecl() const { return SelfDecl; } 166 void setSelfDecl(ParmVarDecl *PVD) { SelfDecl = PVD; } 167 168 // Implement isa/cast/dyncast/etc. 169 static bool classof(const Decl *D) { return D->getKind() == ObjCMethod; } 170 static bool classof(const ObjCMethodDecl *D) { return true; } 171}; 172 173/// ObjCInterfaceDecl - Represents an ObjC class declaration. For example: 174/// 175/// // MostPrimitive declares no super class (not particularly useful). 176/// @interface MostPrimitive 177/// // no instance variables or methods. 178/// @end 179/// 180/// // NSResponder inherits from NSObject & implements NSCoding (a protocol). 181/// @interface NSResponder : NSObject <NSCoding> 182/// { // instance variables are represented by ObjCIvarDecl. 183/// id nextResponder; // nextResponder instance variable. 184/// } 185/// - (NSResponder *)nextResponder; // return a pointer to NSResponder. 186/// - (void)mouseMoved:(NSEvent *)theEvent; // return void, takes a pointer 187/// @end // to an NSEvent. 188/// 189/// Unlike C/C++, forward class declarations are accomplished with @class. 190/// Unlike C/C++, @class allows for a list of classes to be forward declared. 191/// Unlike C++, ObjC is a single-rooted class model. In Cocoa, classes 192/// typically inherit from NSObject (an exception is NSProxy). 193/// 194class ObjCInterfaceDecl : public TypeDecl { 195 196 /// Class's super class. 197 ObjCInterfaceDecl *SuperClass; 198 199 /// Protocols referenced in interface header declaration 200 ObjCProtocolDecl **ReferencedProtocols; // Null if none 201 unsigned NumReferencedProtocols; // 0 if none 202 203 /// Ivars/NumIvars - This is a new[]'d array of pointers to Decls. 204 ObjCIvarDecl **Ivars; // Null if not defined. 205 unsigned NumIvars; // 0 if none. 206 207 /// instance methods 208 ObjCMethodDecl **InstanceMethods; // Null if not defined 209 int NumInstanceMethods; // -1 if not defined 210 211 /// class methods 212 ObjCMethodDecl **ClassMethods; // Null if not defined 213 unsigned NumClassMethods; // 0 if none 214 215 /// List of categories defined for this class. 216 ObjCCategoryDecl *CategoryList; 217 218 /// class properties 219 ObjCPropertyDecl **PropertyDecl; // Null if no property 220 unsigned NumPropertyDecl; // 0 if none. 221 222 bool ForwardDecl:1; // declared with @class. 223 bool InternalInterface:1; // true - no @interface for @implementation 224 225 SourceLocation EndLoc; // marks the '>', '}', or identifier. 226 SourceLocation AtEndLoc; // marks the end of the entire interface. 227 228 ObjCInterfaceDecl(SourceLocation atLoc, unsigned numRefProtos, 229 IdentifierInfo *Id, bool FD, bool isInternal) 230 : TypeDecl(ObjCInterface, atLoc, Id, 0), SuperClass(0), 231 ReferencedProtocols(0), NumReferencedProtocols(0), Ivars(0), 232 NumIvars(0), 233 InstanceMethods(0), NumInstanceMethods(-1), 234 ClassMethods(0), NumClassMethods(0), 235 CategoryList(0), PropertyDecl(0), NumPropertyDecl(-1), 236 ForwardDecl(FD), InternalInterface(isInternal) { 237 AllocIntfRefProtocols(numRefProtos); 238 } 239public: 240 241 static ObjCInterfaceDecl *Create(ASTContext &C, SourceLocation atLoc, 242 unsigned numRefProtos, IdentifierInfo *Id, 243 bool ForwardDecl = false, 244 bool isInternal = false); 245 246 // This is necessary when converting a forward declaration to a definition. 247 void AllocIntfRefProtocols(unsigned numRefProtos) { 248 if (numRefProtos) { 249 ReferencedProtocols = new ObjCProtocolDecl*[numRefProtos]; 250 memset(ReferencedProtocols, '\0', 251 numRefProtos*sizeof(ObjCProtocolDecl*)); 252 NumReferencedProtocols = numRefProtos; 253 } 254 } 255 256 ObjCProtocolDecl **getReferencedProtocols() const { 257 return ReferencedProtocols; 258 } 259 unsigned getNumIntfRefProtocols() const { return NumReferencedProtocols; } 260 261 typedef ObjCIvarDecl * const *ivar_iterator; 262 ivar_iterator ivar_begin() const { return Ivars; } 263 ivar_iterator ivar_end() const { return Ivars + ivar_size();} 264 unsigned ivar_size() const { return NumIvars; } 265 266 int getNumInstanceMethods() const { return NumInstanceMethods; } 267 unsigned getNumClassMethods() const { return NumClassMethods; } 268 269 typedef ObjCMethodDecl * const * instmeth_iterator; 270 instmeth_iterator instmeth_begin() const { return InstanceMethods; } 271 instmeth_iterator instmeth_end() const { 272 return InstanceMethods+(NumInstanceMethods == -1 ? 0 : NumInstanceMethods); 273 } 274 275 typedef ObjCMethodDecl * const * classmeth_iterator; 276 classmeth_iterator classmeth_begin() const { return ClassMethods; } 277 classmeth_iterator classmeth_end() const { 278 return ClassMethods+NumClassMethods; 279 } 280 281 void addInstanceVariablesToClass(ObjCIvarDecl **ivars, unsigned numIvars, 282 SourceLocation RBracLoc); 283 284 void addMethods(ObjCMethodDecl **insMethods, unsigned numInsMembers, 285 ObjCMethodDecl **clsMethods, unsigned numClsMembers, 286 SourceLocation AtEnd); 287 288 void addProperties(ObjCPropertyDecl **Properties, unsigned NumProperties); 289 290 291 bool isForwardDecl() const { return ForwardDecl; } 292 void setForwardDecl(bool val) { ForwardDecl = val; } 293 294 void setIntfRefProtocols(unsigned idx, ObjCProtocolDecl *OID) { 295 assert((idx < NumReferencedProtocols) && "index out of range"); 296 ReferencedProtocols[idx] = OID; 297 } 298 299 ObjCInterfaceDecl *getSuperClass() const { return SuperClass; } 300 void setSuperClass(ObjCInterfaceDecl * superCls) { SuperClass = superCls; } 301 302 ObjCCategoryDecl* getCategoryList() const { return CategoryList; } 303 void setCategoryList(ObjCCategoryDecl *category) { 304 CategoryList = category; 305 } 306 ObjCIvarDecl *lookupInstanceVariable(IdentifierInfo *ivarName, 307 ObjCInterfaceDecl *&clsDeclared); 308 309 // Get the local instance method declared in this interface. 310 ObjCMethodDecl *getInstanceMethod(Selector &Sel) { 311 for (instmeth_iterator I = instmeth_begin(), E = instmeth_end(); 312 I != E; ++I) { 313 if ((*I)->getSelector() == Sel) 314 return *I; 315 } 316 return 0; 317 } 318 // Get the local class method declared in this interface. 319 ObjCMethodDecl *getClassMethod(Selector &Sel) { 320 for (classmeth_iterator I = classmeth_begin(), E = classmeth_end(); 321 I != E; ++I) { 322 if ((*I)->getSelector() == Sel) 323 return *I; 324 } 325 return 0; 326 } 327 // Lookup a method. First, we search locally. If a method isn't 328 // found, we search referenced protocols and class categories. 329 ObjCMethodDecl *lookupInstanceMethod(Selector Sel); 330 ObjCMethodDecl *lookupClassMethod(Selector Sel); 331 332 // Location information, modeled after the Stmt API. 333 SourceLocation getLocStart() const { return getLocation(); } // '@'interface 334 SourceLocation getLocEnd() const { return EndLoc; } 335 void setLocEnd(SourceLocation LE) { EndLoc = LE; }; 336 337 // We also need to record the @end location. 338 SourceLocation getAtEndLoc() const { return AtEndLoc; } 339 340 int getNumPropertyDecl() const { return NumPropertyDecl; } 341 342 ObjCPropertyDecl * const * getPropertyDecl() const { return PropertyDecl; } 343 ObjCPropertyDecl **getPropertyDecl() { return PropertyDecl; } 344 345 /// ImplicitInterfaceDecl - check that this is an implicitely declared 346 /// ObjCInterfaceDecl node. This is for legacy objective-c @implementation 347 /// declaration without an @interface declaration. 348 bool ImplicitInterfaceDecl() const { return InternalInterface; } 349 350 static bool classof(const Decl *D) { return D->getKind() == ObjCInterface; } 351 static bool classof(const ObjCInterfaceDecl *D) { return true; } 352}; 353 354/// ObjCIvarDecl - Represents an ObjC instance variable. In general, ObjC 355/// instance variables are identical to C. The only exception is Objective-C 356/// supports C++ style access control. For example: 357/// 358/// @interface IvarExample : NSObject 359/// { 360/// id defaultToPrivate; // same as C++. 361/// @public: 362/// id canBePublic; // same as C++. 363/// @protected: 364/// id canBeProtected; // same as C++. 365/// @package: 366/// id canBePackage; // framework visibility (not available in C++). 367/// } 368/// 369class ObjCIvarDecl : public FieldDecl { 370 ObjCIvarDecl(SourceLocation L, IdentifierInfo *Id, QualType T) 371 : FieldDecl(ObjCIvar, L, Id, T) {} 372public: 373 static ObjCIvarDecl *Create(ASTContext &C, SourceLocation L, 374 IdentifierInfo *Id, QualType T); 375 376 enum AccessControl { 377 None, Private, Protected, Public, Package 378 }; 379 void setAccessControl(AccessControl ac) { DeclAccess = ac; } 380 AccessControl getAccessControl() const { return AccessControl(DeclAccess); } 381 382 // Implement isa/cast/dyncast/etc. 383 static bool classof(const Decl *D) { return D->getKind() == ObjCIvar; } 384 static bool classof(const ObjCIvarDecl *D) { return true; } 385private: 386 // NOTE: VC++ treats enums as signed, avoid using the AccessControl enum 387 unsigned DeclAccess : 3; 388}; 389 390 391/// ObjCProtocolDecl - Represents a protocol declaration. ObjC protocols 392/// declare a pure abstract type (i.e no instance variables are permitted). 393/// Protocols orginally drew inspiration from C++ pure virtual functions (a C++ 394/// feature with nice semantics and lousy syntax:-). Here is an example: 395/// 396/// @protocol NSDraggingInfo 397/// - (NSWindow *)draggingDestinationWindow; 398/// - (NSImage *)draggedImage; 399/// @end 400/// 401/// @interface ImplementsNSDraggingInfo : NSObject <NSDraggingInfo> 402/// @end 403/// 404/// ObjC protocols inspired Java interfaces. Unlike Java, ObjC classes and 405/// protocols are in distinct namespaces. For example, Cocoa defines both 406/// an NSObject protocol and class (which isn't allowed in Java). As a result, 407/// protocols are referenced using angle brackets as follows: 408/// 409/// id <NSDraggingInfo> anyObjectThatImplementsNSDraggingInfo; 410/// 411class ObjCProtocolDecl : public NamedDecl { 412 /// referenced protocols 413 ObjCProtocolDecl **ReferencedProtocols; // Null if none 414 unsigned NumReferencedProtocols; // 0 if none 415 416 /// protocol instance methods 417 ObjCMethodDecl **InstanceMethods; // Null if not defined 418 unsigned NumInstanceMethods; // 0 if none 419 420 /// protocol class methods 421 ObjCMethodDecl **ClassMethods; // Null if not defined 422 unsigned NumClassMethods; // 0 if none 423 424 bool isForwardProtoDecl; // declared with @protocol. 425 426 SourceLocation EndLoc; // marks the '>' or identifier. 427 SourceLocation AtEndLoc; // marks the end of the entire interface. 428 429 ObjCProtocolDecl(SourceLocation L, unsigned numRefProtos, IdentifierInfo *Id) 430 : NamedDecl(ObjCProtocol, L, Id), 431 ReferencedProtocols(0), NumReferencedProtocols(0), 432 InstanceMethods(0), NumInstanceMethods(0), 433 ClassMethods(0), NumClassMethods(0), 434 isForwardProtoDecl(true) { 435 AllocReferencedProtocols(numRefProtos); 436 } 437public: 438 static ObjCProtocolDecl *Create(ASTContext &C, SourceLocation L, 439 unsigned numRefProtos, IdentifierInfo *Id); 440 441 void AllocReferencedProtocols(unsigned numRefProtos) { 442 if (numRefProtos) { 443 ReferencedProtocols = new ObjCProtocolDecl*[numRefProtos]; 444 memset(ReferencedProtocols, '\0', 445 numRefProtos*sizeof(ObjCProtocolDecl*)); 446 NumReferencedProtocols = numRefProtos; 447 } 448 } 449 void addMethods(ObjCMethodDecl **insMethods, unsigned numInsMembers, 450 ObjCMethodDecl **clsMethods, unsigned numClsMembers, 451 SourceLocation AtEndLoc); 452 453 void setReferencedProtocols(unsigned idx, ObjCProtocolDecl *OID) { 454 assert((idx < NumReferencedProtocols) && "index out of range"); 455 ReferencedProtocols[idx] = OID; 456 } 457 458 ObjCProtocolDecl** getReferencedProtocols() const { 459 return ReferencedProtocols; 460 } 461 unsigned getNumReferencedProtocols() const { return NumReferencedProtocols; } 462 unsigned getNumInstanceMethods() const { return NumInstanceMethods; } 463 unsigned getNumClassMethods() const { return NumClassMethods; } 464 465 typedef ObjCMethodDecl * const * instmeth_iterator; 466 instmeth_iterator instmeth_begin() const { return InstanceMethods; } 467 instmeth_iterator instmeth_end() const { 468 return InstanceMethods+NumInstanceMethods; 469 } 470 471 typedef ObjCMethodDecl * const * classmeth_iterator; 472 classmeth_iterator classmeth_begin() const { return ClassMethods; } 473 classmeth_iterator classmeth_end() const { 474 return ClassMethods+NumClassMethods; 475 } 476 477 // Get the local instance method declared in this interface. 478 ObjCMethodDecl *getInstanceMethod(Selector Sel) { 479 for (instmeth_iterator I = instmeth_begin(), E = instmeth_end(); 480 I != E; ++I) { 481 if ((*I)->getSelector() == Sel) 482 return *I; 483 } 484 return 0; 485 } 486 // Get the local class method declared in this interface. 487 ObjCMethodDecl *getClassMethod(Selector Sel) { 488 for (classmeth_iterator I = classmeth_begin(), E = classmeth_end(); 489 I != E; ++I) { 490 if ((*I)->getSelector() == Sel) 491 return *I; 492 } 493 return 0; 494 } 495 496 // Lookup a method. First, we search locally. If a method isn't 497 // found, we search referenced protocols and class categories. 498 ObjCMethodDecl *lookupInstanceMethod(Selector Sel); 499 ObjCMethodDecl *lookupClassMethod(Selector Sel); 500 501 bool isForwardDecl() const { return isForwardProtoDecl; } 502 void setForwardDecl(bool val) { isForwardProtoDecl = val; } 503 504 // Location information, modeled after the Stmt API. 505 SourceLocation getLocStart() const { return getLocation(); } // '@'protocol 506 SourceLocation getLocEnd() const { return EndLoc; } 507 void setLocEnd(SourceLocation LE) { EndLoc = LE; }; 508 509 // We also need to record the @end location. 510 SourceLocation getAtEndLoc() const { return AtEndLoc; } 511 512 static bool classof(const Decl *D) { return D->getKind() == ObjCProtocol; } 513 static bool classof(const ObjCProtocolDecl *D) { return true; } 514}; 515 516/// ObjCClassDecl - Specifies a list of forward class declarations. For example: 517/// 518/// @class NSCursor, NSImage, NSPasteboard, NSWindow; 519/// 520class ObjCClassDecl : public Decl { 521 ObjCInterfaceDecl **ForwardDecls; 522 unsigned NumForwardDecls; 523 524 ObjCClassDecl(SourceLocation L, ObjCInterfaceDecl **Elts, unsigned nElts) 525 : Decl(ObjCClass, L) { 526 if (nElts) { 527 ForwardDecls = new ObjCInterfaceDecl*[nElts]; 528 memcpy(ForwardDecls, Elts, nElts*sizeof(ObjCInterfaceDecl*)); 529 } else { 530 ForwardDecls = 0; 531 } 532 NumForwardDecls = nElts; 533 } 534public: 535 static ObjCClassDecl *Create(ASTContext &C, SourceLocation L, 536 ObjCInterfaceDecl **Elts, unsigned nElts); 537 538 void setInterfaceDecl(unsigned idx, ObjCInterfaceDecl *OID) { 539 assert(idx < NumForwardDecls && "index out of range"); 540 ForwardDecls[idx] = OID; 541 } 542 ObjCInterfaceDecl** getForwardDecls() const { return ForwardDecls; } 543 int getNumForwardDecls() const { return NumForwardDecls; } 544 545 static bool classof(const Decl *D) { return D->getKind() == ObjCClass; } 546 static bool classof(const ObjCClassDecl *D) { return true; } 547}; 548 549/// ObjCForwardProtocolDecl - Specifies a list of forward protocol declarations. 550/// For example: 551/// 552/// @protocol NSTextInput, NSChangeSpelling, NSDraggingInfo; 553/// 554class ObjCForwardProtocolDecl : public Decl { 555 ObjCProtocolDecl **ReferencedProtocols; 556 unsigned NumReferencedProtocols; 557 558 ObjCForwardProtocolDecl(SourceLocation L, 559 ObjCProtocolDecl **Elts, unsigned nElts) 560 : Decl(ObjCForwardProtocol, L) { 561 NumReferencedProtocols = nElts; 562 if (nElts) { 563 ReferencedProtocols = new ObjCProtocolDecl*[nElts]; 564 memcpy(ReferencedProtocols, Elts, nElts*sizeof(ObjCProtocolDecl*)); 565 } else { 566 ReferencedProtocols = 0; 567 } 568 } 569public: 570 static ObjCForwardProtocolDecl *Create(ASTContext &C, SourceLocation L, 571 ObjCProtocolDecl **Elts, unsigned Num); 572 573 574 void setForwardProtocolDecl(unsigned idx, ObjCProtocolDecl *OID) { 575 assert(idx < NumReferencedProtocols && "index out of range"); 576 ReferencedProtocols[idx] = OID; 577 } 578 579 unsigned getNumForwardDecls() const { return NumReferencedProtocols; } 580 581 ObjCProtocolDecl *getForwardProtocolDecl(unsigned idx) { 582 assert(idx < NumReferencedProtocols && "index out of range"); 583 return ReferencedProtocols[idx]; 584 } 585 const ObjCProtocolDecl *getForwardProtocolDecl(unsigned idx) const { 586 assert(idx < NumReferencedProtocols && "index out of range"); 587 return ReferencedProtocols[idx]; 588 } 589 590 static bool classof(const Decl *D) { 591 return D->getKind() == ObjCForwardProtocol; 592 } 593 static bool classof(const ObjCForwardProtocolDecl *D) { return true; } 594}; 595 596/// ObjCCategoryDecl - Represents a category declaration. A category allows 597/// you to add methods to an existing class (without subclassing or modifying 598/// the original class interface or implementation:-). Categories don't allow 599/// you to add instance data. The following example adds "myMethod" to all 600/// NSView's within a process: 601/// 602/// @interface NSView (MyViewMethods) 603/// - myMethod; 604/// @end 605/// 606/// Cateogries also allow you to split the implementation of a class across 607/// several files (a feature more naturally supported in C++). 608/// 609/// Categories were originally inspired by dynamic languages such as Common 610/// Lisp and Smalltalk. More traditional class-based languages (C++, Java) 611/// don't support this level of dynamism, which is both powerful and dangerous. 612/// 613class ObjCCategoryDecl : public NamedDecl { 614 /// Interface belonging to this category 615 ObjCInterfaceDecl *ClassInterface; 616 617 /// referenced protocols in this category. 618 ObjCProtocolDecl **ReferencedProtocols; // Null if none 619 unsigned NumReferencedProtocols; // 0 if none 620 621 /// category instance methods 622 ObjCMethodDecl **InstanceMethods; // Null if not defined 623 unsigned NumInstanceMethods; // 0 if none 624 625 /// category class methods 626 ObjCMethodDecl **ClassMethods; // Null if not defined 627 unsigned NumClassMethods; // 0 if not defined 628 629 /// Next category belonging to this class 630 ObjCCategoryDecl *NextClassCategory; 631 632 SourceLocation EndLoc; // marks the '>' or identifier. 633 SourceLocation AtEndLoc; // marks the end of the entire interface. 634 635 ObjCCategoryDecl(SourceLocation L, IdentifierInfo *Id) 636 : NamedDecl(ObjCCategory, L, Id), 637 ClassInterface(0), ReferencedProtocols(0), NumReferencedProtocols(0), 638 InstanceMethods(0), NumInstanceMethods(0), 639 ClassMethods(0), NumClassMethods(0), 640 NextClassCategory(0) { 641 } 642public: 643 644 static ObjCCategoryDecl *Create(ASTContext &C, SourceLocation L, 645 IdentifierInfo *Id); 646 647 ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; } 648 void setClassInterface(ObjCInterfaceDecl *IDecl) { ClassInterface = IDecl; } 649 650 void setReferencedProtocolList(ObjCProtocolDecl **List, unsigned NumRPs); 651 652 void setCatReferencedProtocols(unsigned idx, ObjCProtocolDecl *OID) { 653 assert((idx < NumReferencedProtocols) && "index out of range"); 654 ReferencedProtocols[idx] = OID; 655 } 656 657 ObjCProtocolDecl **getReferencedProtocols() const { 658 return ReferencedProtocols; 659 } 660 unsigned getNumReferencedProtocols() const { return NumReferencedProtocols; } 661 unsigned getNumInstanceMethods() const { return NumInstanceMethods; } 662 unsigned getNumClassMethods() const { return NumClassMethods; } 663 664 typedef ObjCMethodDecl * const * instmeth_iterator; 665 instmeth_iterator instmeth_begin() const { return InstanceMethods; } 666 instmeth_iterator instmeth_end() const { 667 return InstanceMethods+NumInstanceMethods; 668 } 669 670 typedef ObjCMethodDecl * const * classmeth_iterator; 671 classmeth_iterator classmeth_begin() const { return ClassMethods; } 672 classmeth_iterator classmeth_end() const { 673 return ClassMethods+NumClassMethods; 674 } 675 676 // Get the local instance method declared in this interface. 677 ObjCMethodDecl *getInstanceMethod(Selector Sel) { 678 for (instmeth_iterator I = instmeth_begin(), E = instmeth_end(); 679 I != E; ++I) { 680 if ((*I)->getSelector() == Sel) 681 return *I; 682 } 683 return 0; 684 } 685 // Get the local class method declared in this interface. 686 ObjCMethodDecl *getClassMethod(Selector Sel) { 687 for (classmeth_iterator I = classmeth_begin(), E = classmeth_end(); 688 I != E; ++I) { 689 if ((*I)->getSelector() == Sel) 690 return *I; 691 } 692 return 0; 693 } 694 695 void addMethods(ObjCMethodDecl **insMethods, unsigned numInsMembers, 696 ObjCMethodDecl **clsMethods, unsigned numClsMembers, 697 SourceLocation AtEndLoc); 698 699 ObjCCategoryDecl *getNextClassCategory() const { return NextClassCategory; } 700 void insertNextClassCategory() { 701 NextClassCategory = ClassInterface->getCategoryList(); 702 ClassInterface->setCategoryList(this); 703 } 704 // Location information, modeled after the Stmt API. 705 SourceLocation getLocStart() const { return getLocation(); } // '@'interface 706 SourceLocation getLocEnd() const { return EndLoc; } 707 void setLocEnd(SourceLocation LE) { EndLoc = LE; }; 708 709 // We also need to record the @end location. 710 SourceLocation getAtEndLoc() const { return AtEndLoc; } 711 712 static bool classof(const Decl *D) { return D->getKind() == ObjCCategory; } 713 static bool classof(const ObjCCategoryDecl *D) { return true; } 714}; 715 716/// ObjCCategoryImplDecl - An object of this class encapsulates a category 717/// @implementation declaration. 718class ObjCCategoryImplDecl : public NamedDecl { 719 /// Class interface for this category implementation 720 ObjCInterfaceDecl *ClassInterface; 721 722 /// implemented instance methods 723 llvm::SmallVector<ObjCMethodDecl*, 32> InstanceMethods; 724 725 /// implemented class methods 726 llvm::SmallVector<ObjCMethodDecl*, 32> ClassMethods; 727 728 SourceLocation EndLoc; 729 730 ObjCCategoryImplDecl(SourceLocation L, IdentifierInfo *Id, 731 ObjCInterfaceDecl *classInterface) 732 : NamedDecl(ObjCCategoryImpl, L, Id), ClassInterface(classInterface) {} 733public: 734 static ObjCCategoryImplDecl *Create(ASTContext &C, SourceLocation L, 735 IdentifierInfo *Id, 736 ObjCInterfaceDecl *classInterface); 737 738 ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; } 739 740 unsigned getNumInstanceMethods() const { return InstanceMethods.size(); } 741 unsigned getNumClassMethods() const { return ClassMethods.size(); } 742 743 void addInstanceMethod(ObjCMethodDecl *method) { 744 InstanceMethods.push_back(method); 745 } 746 void addClassMethod(ObjCMethodDecl *method) { 747 ClassMethods.push_back(method); 748 } 749 // Get the instance method definition for this implementation. 750 ObjCMethodDecl *getInstanceMethod(Selector Sel); 751 752 // Get the class method definition for this implementation. 753 ObjCMethodDecl *getClassMethod(Selector Sel); 754 755 typedef llvm::SmallVector<ObjCMethodDecl*, 32>::const_iterator 756 instmeth_iterator; 757 instmeth_iterator instmeth_begin() const { return InstanceMethods.begin(); } 758 instmeth_iterator instmeth_end() const { return InstanceMethods.end(); } 759 760 typedef llvm::SmallVector<ObjCMethodDecl*, 32>::const_iterator 761 classmeth_iterator; 762 classmeth_iterator classmeth_begin() const { return ClassMethods.begin(); } 763 classmeth_iterator classmeth_end() const { return ClassMethods.end(); } 764 765 766 // Location information, modeled after the Stmt API. 767 SourceLocation getLocStart() const { return getLocation(); } 768 SourceLocation getLocEnd() const { return EndLoc; } 769 void setLocEnd(SourceLocation LE) { EndLoc = LE; }; 770 771 static bool classof(const Decl *D) { return D->getKind() == ObjCCategoryImpl;} 772 static bool classof(const ObjCCategoryImplDecl *D) { return true; } 773}; 774 775/// ObjCImplementationDecl - Represents a class definition - this is where 776/// method definitions are specified. For example: 777/// 778/// @implementation MyClass 779/// - (void)myMethod { /* do something */ } 780/// @end 781/// 782/// Typically, instance variables are specified in the class interface, 783/// *not* in the implemenentation. Nevertheless (for legacy reasons), we 784/// allow instance variables to be specified in the implementation. When 785/// specified, they need to be *identical* to the interface. Now that we 786/// have support for non-fragile ivars in ObjC 2.0, we can consider removing 787/// the legacy semantics and allow developers to move private ivar declarations 788/// from the class interface to the class implementation (but I digress:-) 789/// 790class ObjCImplementationDecl : public NamedDecl { 791 /// Class interface for this category implementation 792 ObjCInterfaceDecl *ClassInterface; 793 794 /// Implementation Class's super class. 795 ObjCInterfaceDecl *SuperClass; 796 797 /// Optional Ivars/NumIvars - This is a new[]'d array of pointers to Decls. 798 ObjCIvarDecl **Ivars; // Null if not specified 799 unsigned NumIvars; // 0 if none. 800 801 /// implemented instance methods 802 llvm::SmallVector<ObjCMethodDecl*, 32> InstanceMethods; 803 804 /// implemented class methods 805 llvm::SmallVector<ObjCMethodDecl*, 32> ClassMethods; 806 807 SourceLocation EndLoc; 808 809 ObjCImplementationDecl(SourceLocation L, IdentifierInfo *Id, 810 ObjCInterfaceDecl *classInterface, 811 ObjCInterfaceDecl *superDecl) 812 : NamedDecl(ObjCImplementation, L, Id), 813 ClassInterface(classInterface), SuperClass(superDecl), 814 Ivars(0), NumIvars(0) {} 815public: 816 static ObjCImplementationDecl *Create(ASTContext &C, SourceLocation L, 817 IdentifierInfo *Id, 818 ObjCInterfaceDecl *classInterface, 819 ObjCInterfaceDecl *superDecl); 820 821 822 void ObjCAddInstanceVariablesToClassImpl(ObjCIvarDecl **ivars, 823 unsigned numIvars); 824 825 void addInstanceMethod(ObjCMethodDecl *method) { 826 InstanceMethods.push_back(method); 827 } 828 void addClassMethod(ObjCMethodDecl *method) { 829 ClassMethods.push_back(method); 830 } 831 // Location information, modeled after the Stmt API. 832 SourceLocation getLocStart() const { return getLocation(); } 833 SourceLocation getLocEnd() const { return EndLoc; } 834 void setLocEnd(SourceLocation LE) { EndLoc = LE; }; 835 836 ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; } 837 ObjCInterfaceDecl *getSuperClass() const { return SuperClass; } 838 839 void setSuperClass(ObjCInterfaceDecl * superCls) { SuperClass = superCls; } 840 841 int getNumInstanceMethods() const { return InstanceMethods.size(); } 842 unsigned getNumClassMethods() const { return ClassMethods.size(); } 843 844 typedef llvm::SmallVector<ObjCMethodDecl*, 32>::const_iterator 845 instmeth_iterator; 846 instmeth_iterator instmeth_begin() const { return InstanceMethods.begin(); } 847 instmeth_iterator instmeth_end() const { return InstanceMethods.end(); } 848 849 typedef llvm::SmallVector<ObjCMethodDecl*, 32>::const_iterator 850 classmeth_iterator; 851 classmeth_iterator classmeth_begin() const { return ClassMethods.begin(); } 852 classmeth_iterator classmeth_end() const { return ClassMethods.end(); } 853 854 // Get the instance method definition for this implementation. 855 ObjCMethodDecl *getInstanceMethod(Selector Sel); 856 857 // Get the class method definition for this implementation. 858 ObjCMethodDecl *getClassMethod(Selector Sel); 859 860 typedef ObjCIvarDecl * const *ivar_iterator; 861 ivar_iterator ivar_begin() const { return Ivars; } 862 ivar_iterator ivar_end() const { return Ivars+NumIvars; } 863 unsigned ivar_size() const { return NumIvars; } 864 bool ivar_empty() const { return NumIvars == 0; } 865 866 static bool classof(const Decl *D) { 867 return D->getKind() == ObjCImplementation; 868 } 869 static bool classof(const ObjCImplementationDecl *D) { return true; } 870}; 871 872/// ObjCCompatibleAliasDecl - Represents alias of a class. This alias is 873/// declared as @compatibility_alias alias class. 874class ObjCCompatibleAliasDecl : public ScopedDecl { 875 /// Class that this is an alias of. 876 ObjCInterfaceDecl *AliasedClass; 877 878 ObjCCompatibleAliasDecl(SourceLocation L, IdentifierInfo *Id, 879 ObjCInterfaceDecl* aliasedClass) 880 : ScopedDecl(CompatibleAlias, L, Id, 0), AliasedClass(aliasedClass) {} 881public: 882 static ObjCCompatibleAliasDecl *Create(ASTContext &C, SourceLocation L, 883 IdentifierInfo *Id, 884 ObjCInterfaceDecl* aliasedClass); 885 886 const ObjCInterfaceDecl *getClassInterface() const { return AliasedClass; } 887 ObjCInterfaceDecl *getClassInterface() { return AliasedClass; } 888 889 static bool classof(const Decl *D) { 890 return D->getKind() == CompatibleAlias; 891 } 892 static bool classof(const ObjCCompatibleAliasDecl *D) { return true; } 893 894}; 895 896class ObjCPropertyDecl : public Decl { 897public: 898 enum PropertyAttributeKind { OBJC_PR_noattr = 0x0, 899 OBJC_PR_readonly = 0x01, 900 OBJC_PR_getter = 0x02, 901 OBJC_PR_assign = 0x04, 902 OBJC_PR_readwrite = 0x08, 903 OBJC_PR_retain = 0x10, 904 OBJC_PR_copy = 0x20, 905 OBJC_PR_nonatomic = 0x40, 906 OBJC_PR_setter = 0x80 }; 907private: 908 // List of property name declarations 909 // FIXME: Property is not an ivar. 910 ObjCIvarDecl **PropertyDecls; 911 int NumPropertyDecls; 912 913 // NOTE: VC++ treats enums as signed, avoid using PropertyAttributeKind enum 914 unsigned PropertyAttributes : 8; 915 916 IdentifierInfo *GetterName; // getter name of NULL if no getter 917 IdentifierInfo *SetterName; // setter name of NULL if no setter 918 919 ObjCPropertyDecl(SourceLocation L) 920 : Decl(PropertyDecl, L), PropertyDecls(0), NumPropertyDecls(-1), 921 PropertyAttributes(OBJC_PR_noattr), GetterName(0), SetterName(0) {} 922public: 923 static ObjCPropertyDecl *Create(ASTContext &C, SourceLocation L); 924 925 ObjCIvarDecl **const getPropertyDecls() const { return PropertyDecls; } 926 void setPropertyDecls(ObjCIvarDecl **property) { PropertyDecls = property; } 927 928 const int getNumPropertyDecls() const { return NumPropertyDecls; } 929 void setNumPropertyDecls(int num) { NumPropertyDecls = num; } 930 931 const PropertyAttributeKind getPropertyAttributes() const 932 { return PropertyAttributeKind(PropertyAttributes); } 933 void setPropertyAttributes(PropertyAttributeKind PRVal) { 934 PropertyAttributes = 935 (PropertyAttributeKind) (PropertyAttributes | PRVal); 936 } 937 938 const IdentifierInfo *getGetterName() const { return GetterName; } 939 IdentifierInfo *getGetterName() { return GetterName; } 940 void setGetterName(IdentifierInfo *Id) { GetterName = Id; } 941 942 const IdentifierInfo *getSetterName() const { return SetterName; } 943 IdentifierInfo *getSetterName() { return SetterName; } 944 void setSetterName(IdentifierInfo *Id) { SetterName = Id; } 945 946 static bool classof(const Decl *D) { 947 return D->getKind() == PropertyDecl; 948 } 949 static bool classof(const ObjCPropertyDecl *D) { return true; } 950}; 951 952} // end namespace clang 953#endif 954