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