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