DeclObjC.h revision 60fbca0b027ff5a6579f16cb6e3abab826e0d967
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/// ObjcInterfaceDecl - Represents an ObjC class declaration. For example:
32///
33///   // MostPrimitive declares no super class (not particularly useful).
34///   @interface MostPrimitive
35///     // no instance variables or methods.
36///   @end
37///
38///   // NSResponder inherits from NSObject & implements NSCoding (a protocol).
39///   @interface NSResponder : NSObject <NSCoding>
40///   { // instance variables are represented by ObjcIvarDecl.
41///     id nextResponder; // nextResponder instance variable.
42///   }
43///   - (NSResponder *)nextResponder; // return a pointer to NSResponder.
44///   - (void)mouseMoved:(NSEvent *)theEvent; // return void, takes a pointer
45///   @end                                    // to an NSEvent.
46///
47///   Unlike C/C++, forward class declarations are accomplished with @class.
48///   Unlike C/C++, @class allows for a list of classes to be forward declared.
49///   Unlike C++, ObjC is a single-rooted class model. In Cocoa, classes
50///   typically inherit from NSObject (an exception is NSProxy).
51///
52class ObjcInterfaceDecl : public TypeDecl {
53
54  /// Class's super class.
55  ObjcInterfaceDecl *SuperClass;
56
57  /// Protocols referenced in interface header declaration
58  ObjcProtocolDecl **ReferencedProtocols;  // Null if none
59  int NumReferencedProtocols;  // -1 if none
60
61  /// Ivars/NumIvars - This is a new[]'d array of pointers to Decls.
62  ObjcIvarDecl **Ivars;   // Null if not defined.
63  int NumIvars;   // -1 if not defined.
64
65  /// instance methods
66  ObjcMethodDecl **InstanceMethods;  // Null if not defined
67  int NumInstanceMethods;  // -1 if not defined
68
69  /// class methods
70  ObjcMethodDecl **ClassMethods;  // Null if not defined
71  int NumClassMethods;  // -1 if not defined
72
73  /// List of categories defined for this class.
74  ObjcCategoryDecl *CategoryList;
75
76  /// class properties
77  ObjcPropertyDecl **PropertyDecl;  // Null if no property
78  int NumPropertyDecl;  // -1 if no property
79
80  bool ForwardDecl:1; // declared with @class.
81  bool InternalInterface:1; // true - no @interface for @implementation
82
83  SourceLocation EndLoc; // marks the '>', '}', or identifier.
84  SourceLocation AtEndLoc; // marks the end of the entire interface.
85public:
86  ObjcInterfaceDecl(SourceLocation atLoc, unsigned numRefProtos,
87                    IdentifierInfo *Id, bool FD = false,
88                    bool isInternal = false)
89    : TypeDecl(ObjcInterface, atLoc, Id, 0), SuperClass(0),
90      ReferencedProtocols(0), NumReferencedProtocols(-1), Ivars(0),
91      NumIvars(-1),
92      InstanceMethods(0), NumInstanceMethods(-1),
93      ClassMethods(0), NumClassMethods(-1),
94      CategoryList(0), PropertyDecl(0), NumPropertyDecl(-1),
95      ForwardDecl(FD), InternalInterface(isInternal) {
96        AllocIntfRefProtocols(numRefProtos);
97      }
98
99  // This is necessary when converting a forward declaration to a definition.
100  void AllocIntfRefProtocols(unsigned numRefProtos) {
101    if (numRefProtos) {
102      ReferencedProtocols = new ObjcProtocolDecl*[numRefProtos];
103      memset(ReferencedProtocols, '\0',
104             numRefProtos*sizeof(ObjcProtocolDecl*));
105      NumReferencedProtocols = numRefProtos;
106    }
107  }
108
109  ObjcProtocolDecl **getReferencedProtocols() const {
110    return ReferencedProtocols;
111  }
112  int getNumIntfRefProtocols() const { return NumReferencedProtocols; }
113
114  ObjcIvarDecl **getIntfDeclIvars() const { return Ivars; }
115  int getIntfDeclNumIvars() const { return NumIvars; }
116
117  ObjcMethodDecl** getInstanceMethods() const { return InstanceMethods; }
118  int getNumInstanceMethods() const { return NumInstanceMethods; }
119
120  ObjcMethodDecl** getClassMethods() const { return ClassMethods; }
121  int getNumClassMethods() const { return NumClassMethods; }
122
123  void addInstanceVariablesToClass(ObjcIvarDecl **ivars, unsigned numIvars,
124                                   SourceLocation RBracLoc);
125
126  void addMethods(ObjcMethodDecl **insMethods, unsigned numInsMembers,
127                  ObjcMethodDecl **clsMethods, unsigned numClsMembers,
128                  SourceLocation AtEnd);
129
130  bool isForwardDecl() const { return ForwardDecl; }
131  void setForwardDecl(bool val) { ForwardDecl = val; }
132
133  void setIntfRefProtocols(int idx, ObjcProtocolDecl *OID) {
134    assert((idx < NumReferencedProtocols) && "index out of range");
135    ReferencedProtocols[idx] = OID;
136  }
137
138  ObjcInterfaceDecl *getSuperClass() const { return SuperClass; }
139  void setSuperClass(ObjcInterfaceDecl * superCls) { SuperClass = superCls; }
140
141  ObjcCategoryDecl* getCategoryList() const { return CategoryList; }
142  void setCategoryList(ObjcCategoryDecl *category) {
143         CategoryList = category;
144  }
145  ObjcMethodDecl *lookupInstanceMethod(Selector &Sel);
146  ObjcMethodDecl *lookupClassMethod(Selector &Sel);
147
148  // Location information, modeled after the Stmt API.
149  SourceLocation getLocStart() const { return getLocation(); } // '@'interface
150  SourceLocation getLocEnd() const { return EndLoc; }
151  void setLocEnd(SourceLocation LE) { EndLoc = LE; };
152
153  // We also need to record the @end location.
154  SourceLocation getAtEndLoc() const { return AtEndLoc; }
155
156  const int getNumPropertyDecl() const { return NumPropertyDecl; }
157  int getNumPropertyDecl() { return NumPropertyDecl; }
158  void setNumPropertyDecl(int num) { NumPropertyDecl = num; }
159
160  ObjcPropertyDecl **const getPropertyDecl() const { return PropertyDecl; }
161  ObjcPropertyDecl **getPropertyDecl() { return PropertyDecl; }
162  void setPropertyDecls(ObjcPropertyDecl **properties) {
163    PropertyDecl = properties;
164  }
165
166  /// ImplicitInterfaceDecl - check that this is an implicitely declared
167  /// ObjcInterfaceDecl node. This is for legacy objective-c @implementation
168  /// declaration without an @interface declaration.
169  bool ImplicitInterfaceDecl() const { return InternalInterface; }
170
171  static bool classof(const Decl *D) { return D->getKind() == ObjcInterface; }
172  static bool classof(const ObjcInterfaceDecl *D) { return true; }
173};
174
175/// ObjcIvarDecl - Represents an ObjC instance variable. In general, ObjC
176/// instance variables are identical to C. The only exception is Objective-C
177/// supports C++ style access control. For example:
178///
179///   @interface IvarExample : NSObject
180///   {
181///     id defaultToPrivate; // same as C++.
182///   @public:
183///     id canBePublic; // same as C++.
184///   @protected:
185///     id canBeProtected; // same as C++.
186///   @package:
187///     id canBePackage; // framework visibility (not available in C++).
188///   }
189///
190class ObjcIvarDecl : public FieldDecl {
191public:
192  ObjcIvarDecl(SourceLocation L, IdentifierInfo *Id, QualType T)
193    : FieldDecl(ObjcIvar, L, Id, T) {}
194
195  enum AccessControl {
196    None, Private, Protected, Public, Package
197  };
198  void setAccessControl(AccessControl ac) { DeclAccess = ac; }
199  AccessControl getAccessControl() const { return DeclAccess; }
200
201  // Implement isa/cast/dyncast/etc.
202  static bool classof(const Decl *D) { return D->getKind() == ObjcIvar; }
203  static bool classof(const ObjcIvarDecl *D) { return true; }
204private:
205  AccessControl DeclAccess : 3;
206};
207
208/// ObjcMethodDecl - Represents an instance or class method declaration.
209/// ObjC methods can be declared within 4 contexts: class interfaces,
210/// categories, protocols, and class implementations. While C++ member
211/// functions leverage C syntax, Objective-C method syntax is modeled after
212/// Smalltalk (using colons to specify argument types/expressions).
213/// Here are some brief examples:
214///
215/// Setter/getter instance methods:
216/// - (void)setMenu:(NSMenu *)menu;
217/// - (NSMenu *)menu;
218///
219/// Instance method that takes 2 NSView arguments:
220/// - (void)replaceSubview:(NSView *)oldView with:(NSView *)newView;
221///
222/// Getter class method:
223/// + (NSMenu *)defaultMenu;
224///
225/// A selector represents a unique name for a method. The selector names for
226/// the above methods are setMenu:, menu, replaceSubview:with:, and defaultMenu.
227///
228class ObjcMethodDecl : public Decl {
229public:
230  enum ImplementationControl { None, Required, Optional };
231private:
232  /// Bitfields must be first fields in this class so they pack with those
233  /// declared in class Decl.
234  /// instance (true) or class (false) method.
235  bool IsInstance : 1;
236  /// @required/@optional
237  ImplementationControl DeclImplementation : 2;
238
239  /// in, inout, etc.
240  ObjcDeclQualifier objcDeclQualifier : 6;
241
242  // @interface decl this Method belongs to.
243  ObjcInterfaceDecl *ClassInterface;
244
245  // A unigue name for this method.
246  Selector SelName;
247
248  // Type of this method.
249  QualType MethodDeclType;
250  /// ParamInfo - new[]'d array of pointers to VarDecls for the formal
251  /// parameters of this Method.  This is null if there are no formals.
252  ParmVarDecl **ParamInfo;
253  int NumMethodParams;  // -1 if no parameters
254
255  /// List of attributes for this method declaration.
256  AttributeList *MethodAttrs;
257
258  Stmt *Body;  // Null if a prototype.
259
260  SourceLocation EndLoc; // the location of the ';' or '{'.
261public:
262  ObjcMethodDecl(SourceLocation beginLoc, SourceLocation endLoc,
263                 Selector SelInfo, QualType T,
264                 ObjcInterfaceDecl *interfaceDecl,
265                 ParmVarDecl **paramInfo = 0, int numParams=-1,
266                 AttributeList *M = 0, bool isInstance = true,
267                 ImplementationControl impControl = None,
268                 Decl *PrevDecl = 0)
269    : Decl(ObjcMethod, beginLoc),
270      IsInstance(isInstance), DeclImplementation(impControl),
271      objcDeclQualifier(OBJC_TQ_None),
272      ClassInterface(interfaceDecl),
273      SelName(SelInfo), MethodDeclType(T),
274      ParamInfo(paramInfo), NumMethodParams(numParams),
275      MethodAttrs(M), EndLoc(endLoc) {}
276  virtual ~ObjcMethodDecl();
277
278  ObjcDeclQualifier getObjcDeclQualifier() const { return objcDeclQualifier; }
279  void setObjcDeclQualifier(ObjcDeclQualifier QV) { objcDeclQualifier = QV; }
280
281  // Location information, modeled after the Stmt API.
282  SourceLocation getLocStart() const { return getLocation(); }
283  SourceLocation getLocEnd() const { return EndLoc; }
284
285  ObjcInterfaceDecl *const getClassInterface() const { return ClassInterface; }
286
287  Selector getSelector() const { return SelName; }
288  QualType getResultType() const { return MethodDeclType; }
289
290  int getNumParams() const { return NumMethodParams; }
291  ParmVarDecl *getParamDecl(int i) const {
292    assert(i < getNumParams() && "Illegal param #");
293    return ParamInfo[i];
294  }
295  void setMethodParams(ParmVarDecl **NewParamInfo, unsigned NumParams);
296
297  AttributeList *getMethodAttrs() const {return MethodAttrs;}
298  bool isInstance() const { return IsInstance; }
299  // Related to protocols declared in  @protocol
300  void setDeclImplementation(ImplementationControl ic)
301         { DeclImplementation = ic; }
302  ImplementationControl  getImplementationControl() const
303                           { return DeclImplementation; }
304
305  Stmt *const getBody() const { return Body; }
306  void setBody(Stmt *B) { Body = B; }
307
308  // Implement isa/cast/dyncast/etc.
309  static bool classof(const Decl *D) { return D->getKind() == ObjcMethod; }
310  static bool classof(const ObjcMethodDecl *D) { return true; }
311};
312
313/// ObjcProtocolDecl - Represents a protocol declaration. ObjC protocols
314/// declare a pure abstract type (i.e no instance variables are permitted).
315/// Protocols orginally drew inspiration from C++ pure virtual functions (a C++
316/// feature with nice semantics and lousy syntax:-). Here is an example:
317///
318/// @protocol NSDraggingInfo
319/// - (NSWindow *)draggingDestinationWindow;
320/// - (NSImage *)draggedImage;
321/// @end
322///
323/// @interface ImplementsNSDraggingInfo : NSObject <NSDraggingInfo>
324/// @end
325///
326/// Objc protocols inspired Java interfaces. Unlike Java, ObjC classes and
327/// protocols are in distinct namespaces. For example, Cocoa defines both
328/// an NSObject protocol and class (which isn't allowed in Java). As a result,
329/// protocols are referenced using angle brackets as follows:
330///
331/// id <NSDraggingInfo> anyObjectThatImplementsNSDraggingInfo;
332///
333class ObjcProtocolDecl : public NamedDecl {
334  /// referenced protocols
335  ObjcProtocolDecl **ReferencedProtocols;  // Null if none
336  int NumReferencedProtocols;  // -1 if none
337
338  /// protocol instance methods
339  ObjcMethodDecl **InstanceMethods;  // Null if not defined
340  int NumInstanceMethods;  // -1 if not defined
341
342  /// protocol class methods
343  ObjcMethodDecl **ClassMethods;  // Null if not defined
344  int NumClassMethods;  // -1 if not defined
345
346  bool isForwardProtoDecl; // declared with @protocol.
347
348  SourceLocation EndLoc; // marks the '>' or identifier.
349  SourceLocation AtEndLoc; // marks the end of the entire interface.
350public:
351  ObjcProtocolDecl(SourceLocation L, unsigned numRefProtos,
352                   IdentifierInfo *Id, bool FD = false)
353    : NamedDecl(ObjcProtocol, L, Id),
354      ReferencedProtocols(0), NumReferencedProtocols(-1),
355      InstanceMethods(0), NumInstanceMethods(-1),
356      ClassMethods(0), NumClassMethods(-1),
357      isForwardProtoDecl(FD) {
358        AllocReferencedProtocols(numRefProtos);
359      }
360  void AllocReferencedProtocols(unsigned numRefProtos) {
361    if (numRefProtos) {
362      ReferencedProtocols = new ObjcProtocolDecl*[numRefProtos];
363      memset(ReferencedProtocols, '\0',
364             numRefProtos*sizeof(ObjcProtocolDecl*));
365      NumReferencedProtocols = numRefProtos;
366    }
367  }
368  void addMethods(ObjcMethodDecl **insMethods, unsigned numInsMembers,
369                  ObjcMethodDecl **clsMethods, unsigned numClsMembers,
370                  SourceLocation AtEndLoc);
371
372  void setReferencedProtocols(int idx, ObjcProtocolDecl *OID) {
373    assert((idx < NumReferencedProtocols) && "index out of range");
374    ReferencedProtocols[idx] = OID;
375  }
376
377  ObjcProtocolDecl** getReferencedProtocols() const {
378    return ReferencedProtocols;
379  }
380  int getNumReferencedProtocols() const { return NumReferencedProtocols; }
381
382  ObjcMethodDecl** getInstanceMethods() const { return InstanceMethods; }
383  int getNumInstanceMethods() const { return NumInstanceMethods; }
384
385  ObjcMethodDecl** getClassMethods() const { return ClassMethods; }
386  int getNumClassMethods() const { return NumClassMethods; }
387
388  bool isForwardDecl() const { return isForwardProtoDecl; }
389  void setForwardDecl(bool val) { isForwardProtoDecl = val; }
390
391  // Location information, modeled after the Stmt API.
392  SourceLocation getLocStart() const { return getLocation(); } // '@'protocol
393  SourceLocation getLocEnd() const { return EndLoc; }
394  void setLocEnd(SourceLocation LE) { EndLoc = LE; };
395
396  // We also need to record the @end location.
397  SourceLocation getAtEndLoc() const { return AtEndLoc; }
398
399  static bool classof(const Decl *D) { return D->getKind() == ObjcProtocol; }
400  static bool classof(const ObjcProtocolDecl *D) { return true; }
401};
402
403/// ObjcClassDecl - Specifies a list of forward class declarations. For example:
404///
405/// @class NSCursor, NSImage, NSPasteboard, NSWindow;
406///
407class ObjcClassDecl : public Decl {
408  ObjcInterfaceDecl **ForwardDecls;
409  unsigned NumForwardDecls;
410public:
411  ObjcClassDecl(SourceLocation L, ObjcInterfaceDecl **Elts, unsigned nElts)
412    : Decl(ObjcClass, L) {
413    if (nElts) {
414      ForwardDecls = new ObjcInterfaceDecl*[nElts];
415      memcpy(ForwardDecls, Elts, nElts*sizeof(ObjcInterfaceDecl*));
416    } else {
417      ForwardDecls = 0;
418    }
419    NumForwardDecls = nElts;
420  }
421  void setInterfaceDecl(unsigned idx, ObjcInterfaceDecl *OID) {
422    assert(idx < NumForwardDecls && "index out of range");
423    ForwardDecls[idx] = OID;
424  }
425  ObjcInterfaceDecl** getForwardDecls() const { return ForwardDecls; }
426  int getNumForwardDecls() const { return NumForwardDecls; }
427
428  static bool classof(const Decl *D) { return D->getKind() == ObjcClass; }
429  static bool classof(const ObjcClassDecl *D) { return true; }
430};
431
432/// ObjcForwardProtocolDecl - Specifies a list of forward protocol declarations.
433/// For example:
434///
435/// @protocol NSTextInput, NSChangeSpelling, NSDraggingInfo;
436///
437class ObjcForwardProtocolDecl : public Decl {
438  ObjcProtocolDecl **ReferencedProtocols;
439  unsigned NumReferencedProtocols;
440public:
441  ObjcForwardProtocolDecl(SourceLocation L,
442                          ObjcProtocolDecl **Elts, unsigned nElts)
443  : Decl(ObjcForwardProtocol, L) {
444    NumReferencedProtocols = nElts;
445    if (nElts) {
446      ReferencedProtocols = new ObjcProtocolDecl*[nElts];
447      memcpy(ReferencedProtocols, Elts, nElts*sizeof(ObjcProtocolDecl*));
448    } else {
449      ReferencedProtocols = 0;
450    }
451  }
452  void setForwardProtocolDecl(unsigned idx, ObjcProtocolDecl *OID) {
453    assert(idx < NumReferencedProtocols && "index out of range");
454    ReferencedProtocols[idx] = OID;
455  }
456
457  unsigned getNumForwardDecls() const { return NumReferencedProtocols; }
458
459  ObjcProtocolDecl *getForwardProtocolDecl(unsigned idx) {
460    assert(idx < NumReferencedProtocols && "index out of range");
461    return ReferencedProtocols[idx];
462  }
463  const ObjcProtocolDecl *getForwardProtocolDecl(unsigned idx) const {
464    assert(idx < NumReferencedProtocols && "index out of range");
465    return ReferencedProtocols[idx];
466  }
467
468  static bool classof(const Decl *D) {
469    return D->getKind() == ObjcForwardProtocol;
470  }
471  static bool classof(const ObjcForwardProtocolDecl *D) { return true; }
472};
473
474/// ObjcCategoryDecl - Represents a category declaration. A category allows
475/// you to add methods to an existing class (without subclassing or modifying
476/// the original class interface or implementation:-). Categories don't allow
477/// you to add instance data. The following example adds "myMethod" to all
478/// NSView's within a process:
479///
480/// @interface NSView (MyViewMethods)
481/// - myMethod;
482/// @end
483///
484/// Cateogries also allow you to split the implementation of a class across
485/// several files (a feature more naturally supported in C++).
486///
487/// Categories were originally inspired by dynamic languages such as Common
488/// Lisp and Smalltalk. More traditional class-based languages (C++, Java)
489/// don't support this level of dynamism, which is both powerful and dangerous.
490///
491class ObjcCategoryDecl : public NamedDecl {
492  /// Interface belonging to this category
493  ObjcInterfaceDecl *ClassInterface;
494
495  /// referenced protocols in this category
496  ObjcProtocolDecl **ReferencedProtocols;  // Null if none
497  int NumReferencedProtocols;  // -1 if none
498
499  /// category instance methods
500  ObjcMethodDecl **InstanceMethods;  // Null if not defined
501  int NumInstanceMethods;  // -1 if not defined
502
503  /// category class methods
504  ObjcMethodDecl **ClassMethods;  // Null if not defined
505  int NumClassMethods;  // -1 if not defined
506
507  /// Next category belonging to this class
508  ObjcCategoryDecl *NextClassCategory;
509
510  SourceLocation EndLoc; // marks the '>' or identifier.
511  SourceLocation AtEndLoc; // marks the end of the entire interface.
512public:
513  ObjcCategoryDecl(SourceLocation L, unsigned numRefProtocol,IdentifierInfo *Id)
514    : NamedDecl(ObjcCategory, L, Id),
515      ClassInterface(0), ReferencedProtocols(0), NumReferencedProtocols(-1),
516      InstanceMethods(0), NumInstanceMethods(-1),
517      ClassMethods(0), NumClassMethods(-1),
518      NextClassCategory(0) {
519        if (numRefProtocol) {
520          ReferencedProtocols = new ObjcProtocolDecl*[numRefProtocol];
521          memset(ReferencedProtocols, '\0',
522                 numRefProtocol*sizeof(ObjcProtocolDecl*));
523          NumReferencedProtocols = numRefProtocol;
524        }
525      }
526
527  ObjcInterfaceDecl *getClassInterface() const { return ClassInterface; }
528  void setClassInterface(ObjcInterfaceDecl *IDecl) { ClassInterface = IDecl; }
529
530  void setCatReferencedProtocols(int idx, ObjcProtocolDecl *OID) {
531    assert((idx < NumReferencedProtocols) && "index out of range");
532    ReferencedProtocols[idx] = OID;
533  }
534
535  ObjcProtocolDecl **getReferencedProtocols() const {
536    return ReferencedProtocols;
537  }
538  int getNumReferencedProtocols() const { return NumReferencedProtocols; }
539
540  ObjcMethodDecl **getInstanceMethods() const { return InstanceMethods; }
541  int getNumInstanceMethods() const { return NumInstanceMethods; }
542
543  ObjcMethodDecl **getClassMethods() const { return ClassMethods; }
544  int getNumClassMethods() const { return NumClassMethods; }
545
546  void addMethods(ObjcMethodDecl **insMethods, unsigned numInsMembers,
547                  ObjcMethodDecl **clsMethods, unsigned numClsMembers,
548                  SourceLocation AtEndLoc);
549
550  ObjcCategoryDecl *getNextClassCategory() const { return NextClassCategory; }
551  void insertNextClassCategory() {
552    NextClassCategory = ClassInterface->getCategoryList();
553    ClassInterface->setCategoryList(this);
554  }
555  // Location information, modeled after the Stmt API.
556  SourceLocation getLocStart() const { return getLocation(); } // '@'interface
557  SourceLocation getLocEnd() const { return EndLoc; }
558  void setLocEnd(SourceLocation LE) { EndLoc = LE; };
559
560  // We also need to record the @end location.
561  SourceLocation getAtEndLoc() const { return AtEndLoc; }
562
563  static bool classof(const Decl *D) { return D->getKind() == ObjcCategory; }
564  static bool classof(const ObjcCategoryDecl *D) { return true; }
565};
566
567/// ObjcCategoryImplDecl - An object of this class encapsulates a category
568/// @implementation declaration.
569class ObjcCategoryImplDecl : public NamedDecl {
570  /// Class interface for this category implementation
571  ObjcInterfaceDecl *ClassInterface;
572
573  /// category instance methods being implemented
574  ObjcMethodDecl **InstanceMethods; // Null if category is not implementing any
575  int NumInstanceMethods;           // -1 if category is not implementing any
576
577  /// category class methods being implemented
578  ObjcMethodDecl **ClassMethods; // Null if category is not implementing any
579  int NumClassMethods;  // -1 if category is not implementing any
580
581  public:
582    ObjcCategoryImplDecl(SourceLocation L, IdentifierInfo *Id,
583                         ObjcInterfaceDecl *classInterface)
584    : NamedDecl(ObjcCategoryImpl, L, Id),
585    ClassInterface(classInterface),
586    InstanceMethods(0), NumInstanceMethods(-1),
587    ClassMethods(0), NumClassMethods(-1) {}
588
589    ObjcInterfaceDecl *getClassInterface() const {
590      return ClassInterface;
591    }
592
593  ObjcMethodDecl **getInstanceMethods() const { return InstanceMethods; }
594  int getNumInstanceMethods() const { return NumInstanceMethods; }
595
596  ObjcMethodDecl **getClassMethods() const { return ClassMethods; }
597  int getNumClassMethods() const { return NumClassMethods; }
598
599  void addMethods(ObjcMethodDecl **insMethods, unsigned numInsMembers,
600                  ObjcMethodDecl **clsMethods, unsigned numClsMembers,
601                  SourceLocation AtEndLoc);
602
603  static bool classof(const Decl *D) { return D->getKind() == ObjcCategoryImpl;}
604  static bool classof(const ObjcCategoryImplDecl *D) { return true; }
605};
606
607/// ObjcImplementationDecl - Represents a class definition - this is where
608/// method definitions are specified. For example:
609///
610/// @implementation MyClass
611/// - (void)myMethod { /* do something */ }
612/// @end
613///
614/// Typically, instance variables are specified in the class interface,
615/// *not* in the implemenentation. Nevertheless (for legacy reasons), we
616/// allow instance variables to be specified in the implementation. When
617/// specified, they need to be *identical* to the interface. Now that we
618/// have support for non-fragile ivars in ObjC 2.0, we can consider removing
619/// the legacy semantics and allow developers to move private ivar declarations
620/// from the class interface to the class implementation (but I digress:-)
621///
622class ObjcImplementationDecl : public NamedDecl {
623  /// Class interface for this category implementation
624  ObjcInterfaceDecl *ClassInterface;
625
626  /// Implementation Class's super class.
627  ObjcInterfaceDecl *SuperClass;
628
629  /// Optional Ivars/NumIvars - This is a new[]'d array of pointers to Decls.
630  ObjcIvarDecl **Ivars;   // Null if not specified
631  int NumIvars;   // -1 if not defined.
632
633  /// implemented instance methods
634  ObjcMethodDecl **InstanceMethods;  // Null if not defined
635  int NumInstanceMethods;  // -1 if not defined
636
637  /// implemented class methods
638  ObjcMethodDecl **ClassMethods;  // Null if not defined
639  int NumClassMethods;  // -1 if not defined
640
641public:
642  ObjcImplementationDecl(SourceLocation L, IdentifierInfo *Id,
643                         ObjcInterfaceDecl *classInterface,
644                         ObjcInterfaceDecl *superDecl)
645    : NamedDecl(ObjcImplementation, L, Id),
646      ClassInterface(classInterface),
647      SuperClass(superDecl),
648      Ivars(0), NumIvars(-1),
649      InstanceMethods(0), NumInstanceMethods(-1),
650      ClassMethods(0), NumClassMethods(-1) {}
651
652  void ObjcAddInstanceVariablesToClassImpl(ObjcIvarDecl **ivars,
653                                           unsigned numIvars);
654
655  void addMethods(ObjcMethodDecl **insMethods, unsigned numInsMembers,
656                  ObjcMethodDecl **clsMethods, unsigned numClsMembers,
657                  SourceLocation AtEndLoc);
658
659  ObjcInterfaceDecl *getClassInterface() const { return ClassInterface; }
660  ObjcInterfaceDecl *getSuperClass() const { return SuperClass; }
661
662  void setSuperClass(ObjcInterfaceDecl * superCls)
663         { SuperClass = superCls; }
664
665  ObjcMethodDecl **getInstanceMethods() const { return InstanceMethods; }
666  int getNumInstanceMethods() const { return NumInstanceMethods; }
667
668  ObjcMethodDecl **getClassMethods() const { return ClassMethods; }
669  int getNumClassMethods() const { return NumClassMethods; }
670
671  ObjcIvarDecl **getImplDeclIVars() const { return Ivars; }
672  int getImplDeclNumIvars() const { return NumIvars; }
673
674  static bool classof(const Decl *D) {
675    return D->getKind() == ObjcImplementation;
676  }
677  static bool classof(const ObjcImplementationDecl *D) { return true; }
678};
679
680/// ObjcCompatibleAliasDecl - Represents alias of a class. This alias is
681/// declared as @compatibility_alias alias class.
682class ObjcCompatibleAliasDecl : public ScopedDecl {
683  /// Class that this is an alias of.
684  ObjcInterfaceDecl *AliasedClass;
685
686public:
687  ObjcCompatibleAliasDecl(SourceLocation L, IdentifierInfo *Id,
688                         ObjcInterfaceDecl* aliasedClass)
689  : ScopedDecl(CompatibleAlias, L, Id, 0),
690  AliasedClass(aliasedClass) {}
691
692  ObjcInterfaceDecl *getClassInterface() const { return AliasedClass; }
693
694  static bool classof(const Decl *D) {
695    return D->getKind() == CompatibleAlias;
696  }
697  static bool classof(const ObjcCompatibleAliasDecl *D) { return true; }
698
699};
700
701class ObjcPropertyDecl : public Decl {
702public:
703  enum PropertyAttributeKind { OBJC_PR_noattr = 0x0,
704                       OBJC_PR_readonly = 0x01,
705                       OBJC_PR_getter = 0x02,
706                       OBJC_PR_assign = 0x04,
707                       OBJC_PR_readwrite = 0x08,
708                       OBJC_PR_retain = 0x10,
709                       OBJC_PR_copy = 0x20,
710                       OBJC_PR_nonatomic = 0x40,
711                       OBJC_PR_setter = 0x80 };
712private:
713  // List of property name declarations
714  // FIXME: Property is not an ivar.
715  ObjcIvarDecl **PropertyDecls;
716  int NumPropertyDecls;
717
718  PropertyAttributeKind PropertyAttributes : 8;
719
720  IdentifierInfo *GetterName;    // getter name of NULL if no getter
721  IdentifierInfo *SetterName;    // setter name of NULL if no setter
722
723public:
724  ObjcPropertyDecl(SourceLocation L)
725  : Decl(PropertyDecl, L),
726  PropertyDecls(0), NumPropertyDecls(-1), PropertyAttributes(OBJC_PR_noattr),
727  GetterName(0), SetterName(0) {}
728
729  ObjcIvarDecl **const getPropertyDecls() const { return PropertyDecls; }
730  void setPropertyDecls(ObjcIvarDecl **property) { PropertyDecls = property; }
731
732  const int getNumPropertyDecls() const { return NumPropertyDecls; }
733  void setNumPropertyDecls(int num) { NumPropertyDecls = num; }
734
735  const PropertyAttributeKind getPropertyAttributes() const
736    { return PropertyAttributes; }
737  void setPropertyAttributes(PropertyAttributeKind PRVal) {
738    PropertyAttributes =
739    (PropertyAttributeKind) (PropertyAttributes | PRVal);
740  }
741
742  const IdentifierInfo *getGetterName() const { return GetterName; }
743  IdentifierInfo *getGetterName() { return GetterName; }
744  void setGetterName(IdentifierInfo *Id) { GetterName = Id; }
745
746  const IdentifierInfo *getSetterName() const { return SetterName; }
747  IdentifierInfo *getSetterName() { return SetterName; }
748  void setSetterName(IdentifierInfo *Id) { SetterName = Id; }
749
750  static bool classof(const Decl *D) {
751    return D->getKind() == PropertyDecl;
752  }
753  static bool classof(const ObjcPropertyDecl *D) { return true; }
754};
755
756}  // end namespace clang
757#endif
758