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