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