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