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