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