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