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