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