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