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