DeclObjC.h revision 8cf0bb3c2a798ce3acacaac2d3178648cd4c65c6
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;
30class ObjCPropertyImplDecl;
31
32
33/// ObjCList - This is a simple template class used to hold various lists of
34/// decls etc, which is heavily used by the ObjC front-end.  This only use case
35/// this supports is setting the list all at once and then reading elements out
36/// of it.
37template <typename T>
38class ObjCList {
39  /// List is a new[]'d array of pointers to objects that are not owned by this
40  /// list.
41  T **List;
42  unsigned NumElts;
43
44  void operator=(const ObjCList &); // DO NOT IMPLEMENT
45  ObjCList(const ObjCList&);        // DO NOT IMPLEMENT
46public:
47  ObjCList() : List(0), NumElts(0) {}
48  ~ObjCList() {
49    delete[] List;
50  }
51
52  void set(T* const* InList, unsigned Elts) {
53    assert(List == 0 && "Elements already set!");
54    List = new T*[Elts];
55    NumElts = Elts;
56    memcpy(List, InList, sizeof(T*)*Elts);
57  }
58
59  typedef T* const * iterator;
60  iterator begin() const { return List; }
61  iterator end() const { return List+NumElts; }
62
63  unsigned size() const { return NumElts; }
64  bool empty() const { return NumElts == 0; }
65
66  T* operator[](unsigned idx) const {
67    assert(idx < NumElts && "Invalid access");
68    return List[idx];
69  }
70};
71
72
73
74/// ObjCMethodDecl - Represents an instance or class method declaration.
75/// ObjC methods can be declared within 4 contexts: class interfaces,
76/// categories, protocols, and class implementations. While C++ member
77/// functions leverage C syntax, Objective-C method syntax is modeled after
78/// Smalltalk (using colons to specify argument types/expressions).
79/// Here are some brief examples:
80///
81/// Setter/getter instance methods:
82/// - (void)setMenu:(NSMenu *)menu;
83/// - (NSMenu *)menu;
84///
85/// Instance method that takes 2 NSView arguments:
86/// - (void)replaceSubview:(NSView *)oldView with:(NSView *)newView;
87///
88/// Getter class method:
89/// + (NSMenu *)defaultMenu;
90///
91/// A selector represents a unique name for a method. The selector names for
92/// the above methods are setMenu:, menu, replaceSubview:with:, and defaultMenu.
93///
94class ObjCMethodDecl : public NamedDecl, public DeclContext {
95public:
96  enum ImplementationControl { None, Required, Optional };
97private:
98  /// Bitfields must be first fields in this class so they pack with those
99  /// declared in class Decl.
100  /// instance (true) or class (false) method.
101  bool IsInstance : 1;
102  bool IsVariadic : 1;
103
104  // Synthesized declaration method for a property setter/getter
105  bool IsSynthesized : 1;
106
107  // NOTE: VC++ treats enums as signed, avoid using ImplementationControl enum
108  /// @required/@optional
109  unsigned DeclImplementation : 2;
110
111  // NOTE: VC++ treats enums as signed, avoid using the ObjCDeclQualifier enum
112  /// in, inout, etc.
113  unsigned objcDeclQualifier : 6;
114
115  // Context this method is declared in.
116  NamedDecl *MethodContext;
117
118  // Type of this method.
119  QualType MethodDeclType;
120  /// ParamInfo - new[]'d array of pointers to VarDecls for the formal
121  /// parameters of this Method.  This is null if there are no formals.
122  ParmVarDecl **ParamInfo;
123  unsigned NumMethodParams;
124
125  /// List of attributes for this method declaration.
126  SourceLocation EndLoc; // the location of the ';' or '{'.
127
128  // The following are only used for method definitions, null otherwise.
129  // FIXME: space savings opportunity, consider a sub-class.
130  Stmt *Body;
131
132  /// SelfDecl - Decl for the implicit self parameter. This is lazily
133  /// constructed by createImplicitParams.
134  ImplicitParamDecl *SelfDecl;
135  /// CmdDecl - Decl for the implicit _cmd parameter. This is lazily
136  /// constructed by createImplicitParams.
137  ImplicitParamDecl *CmdDecl;
138
139  ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc,
140                 Selector SelInfo, QualType T,
141                 Decl *contextDecl,
142                 bool isInstance = true,
143                 bool isVariadic = false,
144                 bool isSynthesized = false,
145                 ImplementationControl impControl = None)
146  : NamedDecl(ObjCMethod, beginLoc, SelInfo),
147    DeclContext(ObjCMethod),
148    IsInstance(isInstance), IsVariadic(isVariadic),
149    IsSynthesized(isSynthesized),
150    DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None),
151    MethodContext(static_cast<NamedDecl*>(contextDecl)),
152    MethodDeclType(T),
153    ParamInfo(0), NumMethodParams(0),
154    EndLoc(endLoc), Body(0), SelfDecl(0), CmdDecl(0) {}
155
156  virtual ~ObjCMethodDecl();
157
158public:
159
160  /// Destroy - Call destructors and release memory.
161  virtual void Destroy(ASTContext& C);
162
163  static ObjCMethodDecl *Create(ASTContext &C,
164                                SourceLocation beginLoc,
165                                SourceLocation endLoc, Selector SelInfo,
166                                QualType T, Decl *contextDecl,
167                                bool isInstance = true,
168                                bool isVariadic = false,
169                                bool isSynthesized = false,
170                                ImplementationControl impControl = None);
171
172  ObjCDeclQualifier getObjCDeclQualifier() const {
173    return ObjCDeclQualifier(objcDeclQualifier);
174  }
175  void setObjCDeclQualifier(ObjCDeclQualifier QV) { objcDeclQualifier = QV; }
176
177  // Location information, modeled after the Stmt API.
178  SourceLocation getLocStart() const { return getLocation(); }
179  SourceLocation getLocEnd() const { return EndLoc; }
180  SourceRange getSourceRange() const {
181    return SourceRange(getLocation(), EndLoc);
182  }
183
184  NamedDecl *getMethodContext() const { return MethodContext; }
185
186  ObjCInterfaceDecl *getClassInterface();
187  const ObjCInterfaceDecl *getClassInterface() const {
188    return const_cast<ObjCMethodDecl*>(this)->getClassInterface();
189  }
190
191  Selector getSelector() const { return getDeclName().getObjCSelector(); }
192  unsigned getSynthesizedMethodSize() const;
193  QualType getResultType() const { return MethodDeclType; }
194
195  // Iterator access to formal parameters.
196  unsigned param_size() const { return NumMethodParams; }
197  typedef ParmVarDecl **param_iterator;
198  typedef ParmVarDecl * const *param_const_iterator;
199  param_iterator param_begin() { return ParamInfo; }
200  param_iterator param_end() { return ParamInfo+param_size(); }
201  param_const_iterator param_begin() const { return ParamInfo; }
202  param_const_iterator param_end() const { return ParamInfo+param_size(); }
203
204  unsigned getNumParams() const { return NumMethodParams; }
205  ParmVarDecl *getParamDecl(unsigned i) const {
206    assert(i < getNumParams() && "Illegal param #");
207    return ParamInfo[i];
208  }
209  void setParamDecl(int i, ParmVarDecl *pDecl) {
210    ParamInfo[i] = pDecl;
211  }
212  void setMethodParams(ParmVarDecl **NewParamInfo, unsigned NumParams);
213
214  /// createImplicitParams - Used to lazily create the self and cmd
215  /// implict parameters. This must be called prior to using getSelfDecl()
216  /// or getCmdDecl(). The call is ignored if the implicit paramters
217  /// have already been created.
218  void createImplicitParams(ASTContext &Context);
219
220  ImplicitParamDecl * getSelfDecl() const { return SelfDecl; }
221  ImplicitParamDecl * getCmdDecl() const { return CmdDecl; }
222
223  bool isInstance() const { return IsInstance; }
224  bool isVariadic() const { return IsVariadic; }
225
226  bool isSynthesized() const { return IsSynthesized; }
227
228  // Related to protocols declared in  @protocol
229  void setDeclImplementation(ImplementationControl ic) {
230    DeclImplementation = ic;
231  }
232  ImplementationControl getImplementationControl() const {
233    return ImplementationControl(DeclImplementation);
234  }
235
236  virtual Stmt *getBody() const { return Body; }
237  void setBody(Stmt *B) { Body = B; }
238
239  // Implement isa/cast/dyncast/etc.
240  static bool classof(const Decl *D) { return D->getKind() == ObjCMethod; }
241  static bool classof(const ObjCMethodDecl *D) { return true; }
242  static DeclContext *castToDeclContext(const ObjCMethodDecl *D) {
243    return static_cast<DeclContext *>(const_cast<ObjCMethodDecl*>(D));
244  }
245  static ObjCMethodDecl *castFromDeclContext(const DeclContext *DC) {
246    return static_cast<ObjCMethodDecl *>(const_cast<DeclContext*>(DC));
247  }
248};
249
250/// ObjCInterfaceDecl - Represents an ObjC class declaration. For example:
251///
252///   // MostPrimitive declares no super class (not particularly useful).
253///   @interface MostPrimitive
254///     // no instance variables or methods.
255///   @end
256///
257///   // NSResponder inherits from NSObject & implements NSCoding (a protocol).
258///   @interface NSResponder : NSObject <NSCoding>
259///   { // instance variables are represented by ObjCIvarDecl.
260///     id nextResponder; // nextResponder instance variable.
261///   }
262///   - (NSResponder *)nextResponder; // return a pointer to NSResponder.
263///   - (void)mouseMoved:(NSEvent *)theEvent; // return void, takes a pointer
264///   @end                                    // to an NSEvent.
265///
266///   Unlike C/C++, forward class declarations are accomplished with @class.
267///   Unlike C/C++, @class allows for a list of classes to be forward declared.
268///   Unlike C++, ObjC is a single-rooted class model. In Cocoa, classes
269///   typically inherit from NSObject (an exception is NSProxy).
270///
271class ObjCInterfaceDecl : public NamedDecl, public DeclContext {
272  /// TypeForDecl - This indicates the Type object that represents this
273  /// TypeDecl.  It is a cache maintained by ASTContext::getObjCInterfaceType
274  Type *TypeForDecl;
275  friend class ASTContext;
276
277  /// Class's super class.
278  ObjCInterfaceDecl *SuperClass;
279
280  /// Protocols referenced in interface header declaration
281  ObjCList<ObjCProtocolDecl> ReferencedProtocols;
282
283  /// Ivars/NumIvars - This is a new[]'d array of pointers to Decls.
284  ObjCIvarDecl **Ivars;   // Null if not defined.
285  unsigned NumIvars;      // 0 if none.
286
287  /// instance methods
288  ObjCMethodDecl **InstanceMethods;  // Null if not defined
289  unsigned NumInstanceMethods;  // 0 if none.
290
291  /// class methods
292  ObjCMethodDecl **ClassMethods;  // Null if not defined
293  unsigned NumClassMethods;  // 0 if none
294
295  /// List of categories defined for this class.
296  ObjCCategoryDecl *CategoryList;
297
298  /// class properties
299  ObjCPropertyDecl **PropertyDecl;  // Null if no property
300  unsigned NumPropertyDecl;  // 0 if none.
301
302  bool ForwardDecl:1; // declared with @class.
303  bool InternalInterface:1; // true - no @interface for @implementation
304
305  SourceLocation ClassLoc; // location of the class identifier.
306  SourceLocation SuperClassLoc; // location of the super class identifier.
307  SourceLocation EndLoc; // marks the '>', '}', or identifier.
308  SourceLocation AtEndLoc; // marks the end of the entire interface.
309
310  ObjCInterfaceDecl(SourceLocation atLoc, IdentifierInfo *Id,
311                    SourceLocation CLoc, bool FD, bool isInternal)
312    : NamedDecl(ObjCInterface, atLoc, Id), DeclContext(ObjCInterface),
313      TypeForDecl(0), SuperClass(0),
314      Ivars(0), NumIvars(0),
315      InstanceMethods(0), NumInstanceMethods(0),
316      ClassMethods(0), NumClassMethods(0),
317      CategoryList(0), PropertyDecl(0), NumPropertyDecl(0),
318      ForwardDecl(FD), InternalInterface(isInternal),
319      ClassLoc(CLoc) {
320      }
321
322  virtual ~ObjCInterfaceDecl();
323
324public:
325
326  /// Destroy - Call destructors and release memory.
327  virtual void Destroy(ASTContext& C);
328
329  static ObjCInterfaceDecl *Create(ASTContext &C,
330                                   SourceLocation atLoc,
331                                   IdentifierInfo *Id,
332                                   SourceLocation ClassLoc = SourceLocation(),
333                                   bool ForwardDecl = false,
334                                   bool isInternal = false);
335  const ObjCList<ObjCProtocolDecl> &getReferencedProtocols() const {
336    return ReferencedProtocols;
337  }
338
339  ObjCPropertyDecl *FindPropertyDeclaration(IdentifierInfo *PropertyId) const;
340  ObjCCategoryDecl *FindCategoryDeclaration(IdentifierInfo *CategoryId) const;
341  ObjCIvarDecl *FindIvarDeclaration(IdentifierInfo *IvarId) const;
342  bool isPropertyReadonly(ObjCPropertyDecl *PropertyDecl) const;
343
344  typedef ObjCList<ObjCProtocolDecl>::iterator protocol_iterator;
345  protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();}
346  protocol_iterator protocol_end() const { return ReferencedProtocols.end(); }
347
348  typedef ObjCIvarDecl * const *ivar_iterator;
349  ivar_iterator ivar_begin() const { return Ivars; }
350  ivar_iterator ivar_end() const { return Ivars + ivar_size();}
351  unsigned ivar_size() const { return NumIvars; }
352  bool ivar_empty() const { return NumIvars == 0; }
353
354  unsigned getNumInstanceMethods() const { return NumInstanceMethods; }
355  unsigned getNumClassMethods() const { return NumClassMethods; }
356
357  typedef ObjCMethodDecl * const * instmeth_iterator;
358  instmeth_iterator instmeth_begin() const { return InstanceMethods; }
359  instmeth_iterator instmeth_end() const {
360    return InstanceMethods+NumInstanceMethods;
361  }
362
363  typedef ObjCMethodDecl * const * classmeth_iterator;
364  classmeth_iterator classmeth_begin() const { return ClassMethods; }
365  classmeth_iterator classmeth_end() const {
366    return ClassMethods+NumClassMethods;
367  }
368
369  /// addReferencedProtocols - Set the list of protocols that this interface
370  /// implements.
371  void addReferencedProtocols(ObjCProtocolDecl *const*List, unsigned NumRPs) {
372    ReferencedProtocols.set(List, NumRPs);
373  }
374
375  void addInstanceVariablesToClass(ObjCIvarDecl **ivars, unsigned numIvars,
376                                   SourceLocation RBracLoc);
377
378  void addMethods(ObjCMethodDecl **insMethods, unsigned numInsMembers,
379                  ObjCMethodDecl **clsMethods, unsigned numClsMembers,
380                  SourceLocation AtEnd);
381
382  void addProperties(ObjCPropertyDecl **Properties, unsigned NumProperties);
383
384  void mergeProperties(ObjCPropertyDecl **Properties, unsigned NumProperties);
385
386  void addPropertyMethods(ASTContext &Context,
387                          ObjCPropertyDecl* Property,
388                          llvm::SmallVector<ObjCMethodDecl*, 32> &insMethods);
389
390  typedef ObjCPropertyDecl * const * classprop_iterator;
391  classprop_iterator classprop_begin() const { return PropertyDecl; }
392  classprop_iterator classprop_end() const {
393    return PropertyDecl+NumPropertyDecl;
394  }
395
396  bool isForwardDecl() const { return ForwardDecl; }
397  void setForwardDecl(bool val) { ForwardDecl = val; }
398
399  ObjCInterfaceDecl *getSuperClass() const { return SuperClass; }
400  void setSuperClass(ObjCInterfaceDecl * superCls) { SuperClass = superCls; }
401
402  ObjCCategoryDecl* getCategoryList() const { return CategoryList; }
403  void setCategoryList(ObjCCategoryDecl *category) {
404    CategoryList = category;
405  }
406
407  /// isSuperClassOf - Return true if this class is the specified class or is a
408  /// super class of the specified interface class.
409  bool isSuperClassOf(const ObjCInterfaceDecl *I) const {
410    // If RHS is derived from LHS it is OK; else it is not OK.
411    while (I != NULL) {
412      if (this == I)
413        return true;
414      I = I->getSuperClass();
415    }
416    return false;
417  }
418
419  ObjCIvarDecl *lookupInstanceVariable(IdentifierInfo *IVarName,
420                                       ObjCInterfaceDecl *&ClassDeclared);
421  ObjCIvarDecl *lookupInstanceVariable(IdentifierInfo *IVarName) {
422    ObjCInterfaceDecl *ClassDeclared;
423    return lookupInstanceVariable(IVarName, ClassDeclared);
424  }
425
426
427  // Get the local instance method declared in this interface.
428  ObjCMethodDecl *getInstanceMethod(Selector Sel) const {
429    for (instmeth_iterator I = instmeth_begin(), E = instmeth_end();
430         I != E; ++I) {
431      if ((*I)->getSelector() == Sel)
432        return *I;
433    }
434    return 0;
435  }
436  // Get the local class method declared in this interface.
437  ObjCMethodDecl *getClassMethod(Selector Sel) const {
438    for (classmeth_iterator I = classmeth_begin(), E = classmeth_end();
439         I != E; ++I) {
440      if ((*I)->getSelector() == Sel)
441        return *I;
442    }
443    return 0;
444  }
445  // Lookup a method. First, we search locally. If a method isn't
446  // found, we search referenced protocols and class categories.
447  ObjCMethodDecl *lookupInstanceMethod(Selector Sel);
448  ObjCMethodDecl *lookupClassMethod(Selector Sel);
449
450  // Location information, modeled after the Stmt API.
451  SourceLocation getLocStart() const { return getLocation(); } // '@'interface
452  SourceLocation getLocEnd() const { return EndLoc; }
453  void setLocEnd(SourceLocation LE) { EndLoc = LE; };
454
455  SourceLocation getClassLoc() const { return ClassLoc; }
456  void setSuperClassLoc(SourceLocation Loc) { SuperClassLoc = Loc; }
457  SourceLocation getSuperClassLoc() const { return SuperClassLoc; }
458
459  // We also need to record the @end location.
460  SourceLocation getAtEndLoc() const { return AtEndLoc; }
461
462  unsigned getNumPropertyDecl() const { return NumPropertyDecl; }
463
464  ObjCPropertyDecl * const * getPropertyDecl() const { return PropertyDecl; }
465  ObjCPropertyDecl **getPropertyDecl() { return PropertyDecl; }
466
467  /// ImplicitInterfaceDecl - check that this is an implicitely declared
468  /// ObjCInterfaceDecl node. This is for legacy objective-c @implementation
469  /// declaration without an @interface declaration.
470  bool ImplicitInterfaceDecl() const { return InternalInterface; }
471
472  static bool classof(const Decl *D) { return D->getKind() == ObjCInterface; }
473  static bool classof(const ObjCInterfaceDecl *D) { return true; }
474  static DeclContext *castToDeclContext(const ObjCInterfaceDecl *D) {
475    return static_cast<DeclContext *>(const_cast<ObjCInterfaceDecl*>(D));
476  }
477  static ObjCInterfaceDecl *castFromDeclContext(const DeclContext *DC) {
478    return static_cast<ObjCInterfaceDecl *>(const_cast<DeclContext*>(DC));
479  }
480};
481
482/// ObjCIvarDecl - Represents an ObjC instance variable. In general, ObjC
483/// instance variables are identical to C. The only exception is Objective-C
484/// supports C++ style access control. For example:
485///
486///   @interface IvarExample : NSObject
487///   {
488///     id defaultToProtected;
489///   @public:
490///     id canBePublic; // same as C++.
491///   @protected:
492///     id canBeProtected; // same as C++.
493///   @package:
494///     id canBePackage; // framework visibility (not available in C++).
495///   }
496///
497class ObjCIvarDecl : public FieldDecl {
498public:
499  enum AccessControl {
500    None, Private, Protected, Public, Package
501  };
502
503private:
504  ObjCIvarDecl(SourceLocation L, IdentifierInfo *Id, QualType T,
505               AccessControl ac, Expr *BW)
506    : FieldDecl(ObjCIvar, L, Id, T, BW), DeclAccess(ac) {}
507
508public:
509  static ObjCIvarDecl *Create(ASTContext &C, SourceLocation L,
510                              IdentifierInfo *Id, QualType T,
511                              AccessControl ac, Expr *BW = NULL);
512
513  void setAccessControl(AccessControl ac) { DeclAccess = ac; }
514
515  AccessControl getAccessControl() const { return AccessControl(DeclAccess); }
516
517  AccessControl getCanonicalAccessControl() const {
518    return DeclAccess == None ? Protected : AccessControl(DeclAccess);
519  }
520
521  // Implement isa/cast/dyncast/etc.
522  static bool classof(const Decl *D) { return D->getKind() == ObjCIvar; }
523  static bool classof(const ObjCIvarDecl *D) { return true; }
524private:
525  // NOTE: VC++ treats enums as signed, avoid using the AccessControl enum
526  unsigned DeclAccess : 3;
527};
528
529
530/// ObjCAtDefsFieldDecl - Represents a field declaration created by an
531///  @defs(...).
532class ObjCAtDefsFieldDecl : public FieldDecl {
533private:
534  ObjCAtDefsFieldDecl(SourceLocation L, IdentifierInfo *Id,
535                      QualType T, Expr *BW)
536  : FieldDecl(ObjCAtDefsField, L, Id, T, BW) {}
537
538public:
539  static ObjCAtDefsFieldDecl *Create(ASTContext &C, SourceLocation L,
540                                     IdentifierInfo *Id, QualType T,
541                                     Expr *BW);
542
543  virtual void Destroy(ASTContext& C);
544
545  // Implement isa/cast/dyncast/etc.
546  static bool classof(const Decl *D) { return D->getKind() == ObjCAtDefsField; }
547  static bool classof(const ObjCAtDefsFieldDecl *D) { return true; }
548};
549
550/// ObjCProtocolDecl - Represents a protocol declaration. ObjC protocols
551/// declare a pure abstract type (i.e no instance variables are permitted).
552/// Protocols orginally drew inspiration from C++ pure virtual functions (a C++
553/// feature with nice semantics and lousy syntax:-). Here is an example:
554///
555/// @protocol NSDraggingInfo <refproto1, refproto2>
556/// - (NSWindow *)draggingDestinationWindow;
557/// - (NSImage *)draggedImage;
558/// @end
559///
560/// This says that NSDraggingInfo requires two methods and requires everything
561/// that the two "referenced protocols" 'refproto1' and 'refproto2' require as
562/// well.
563///
564/// @interface ImplementsNSDraggingInfo : NSObject <NSDraggingInfo>
565/// @end
566///
567/// ObjC protocols inspired Java interfaces. Unlike Java, ObjC classes and
568/// protocols are in distinct namespaces. For example, Cocoa defines both
569/// an NSObject protocol and class (which isn't allowed in Java). As a result,
570/// protocols are referenced using angle brackets as follows:
571///
572/// id <NSDraggingInfo> anyObjectThatImplementsNSDraggingInfo;
573///
574class ObjCProtocolDecl : public NamedDecl {
575  /// Referenced protocols
576  ObjCList<ObjCProtocolDecl> ReferencedProtocols;
577
578  /// protocol instance methods
579  ObjCMethodDecl **InstanceMethods;  // Null if not defined
580  unsigned NumInstanceMethods;  // 0 if none
581
582  /// protocol class methods
583  ObjCMethodDecl **ClassMethods;  // Null if not defined
584  unsigned NumClassMethods;  // 0 if none
585
586  /// protocol properties
587  ObjCPropertyDecl **PropertyDecl;  // Null if no property
588  unsigned NumPropertyDecl;  // 0 if none
589
590  bool isForwardProtoDecl; // declared with @protocol.
591
592  SourceLocation EndLoc; // marks the '>' or identifier.
593  SourceLocation AtEndLoc; // marks the end of the entire interface.
594
595  ObjCProtocolDecl(SourceLocation L, IdentifierInfo *Id)
596    : NamedDecl(ObjCProtocol, L, Id),
597      InstanceMethods(0), NumInstanceMethods(0),
598      ClassMethods(0), NumClassMethods(0),
599      PropertyDecl(0), NumPropertyDecl(0),
600      isForwardProtoDecl(true) {
601  }
602
603  virtual ~ObjCProtocolDecl();
604
605public:
606
607  /// Destroy - Call destructors and release memory.
608  virtual void Destroy(ASTContext& C);
609
610  static ObjCProtocolDecl *Create(ASTContext &C, SourceLocation L,
611                                  IdentifierInfo *Id);
612
613  void addMethods(ObjCMethodDecl **insMethods, unsigned numInsMembers,
614                  ObjCMethodDecl **clsMethods, unsigned numClsMembers,
615                  SourceLocation AtEndLoc);
616
617  const ObjCList<ObjCProtocolDecl> &getReferencedProtocols() const {
618    return ReferencedProtocols;
619  }
620  typedef ObjCList<ObjCProtocolDecl>::iterator protocol_iterator;
621  protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();}
622  protocol_iterator protocol_end() const { return ReferencedProtocols.end(); }
623
624  /// addReferencedProtocols - Set the list of protocols that this interface
625  /// implements.
626  void addReferencedProtocols(ObjCProtocolDecl *const*List, unsigned NumRPs) {
627    ReferencedProtocols.set(List, NumRPs);
628  }
629
630  unsigned getNumInstanceMethods() const { return NumInstanceMethods; }
631  unsigned getNumClassMethods() const { return NumClassMethods; }
632
633  ObjCPropertyDecl *FindPropertyDeclaration(IdentifierInfo *PropertyId) const;
634
635  unsigned getNumPropertyDecl() const { return NumPropertyDecl; }
636
637  ObjCPropertyDecl * const * getPropertyDecl() const { return PropertyDecl; }
638  ObjCPropertyDecl **getPropertyDecl() { return PropertyDecl; }
639
640  void addProperties(ObjCPropertyDecl **Properties, unsigned NumProperties);
641
642  void addPropertyMethods(ASTContext &Context,
643                          ObjCPropertyDecl* Property,
644                          llvm::SmallVector<ObjCMethodDecl*, 32> &insMethods);
645
646  typedef ObjCPropertyDecl * const * classprop_iterator;
647  classprop_iterator classprop_begin() const { return PropertyDecl; }
648  classprop_iterator classprop_end() const {
649    return PropertyDecl+NumPropertyDecl;
650  }
651
652  typedef ObjCMethodDecl * const * instmeth_iterator;
653  instmeth_iterator instmeth_begin() const { return InstanceMethods; }
654  instmeth_iterator instmeth_end() const {
655    return InstanceMethods+NumInstanceMethods;
656  }
657
658  typedef ObjCMethodDecl * const * classmeth_iterator;
659  classmeth_iterator classmeth_begin() const { return ClassMethods; }
660  classmeth_iterator classmeth_end() const {
661    return ClassMethods+NumClassMethods;
662  }
663
664  // Get the local instance method declared in this interface.
665  ObjCMethodDecl *getInstanceMethod(Selector Sel) const {
666    for (instmeth_iterator I = instmeth_begin(), E = instmeth_end();
667         I != E; ++I) {
668      if ((*I)->getSelector() == Sel)
669        return *I;
670    }
671    return 0;
672  }
673  // Get the local class method declared in this interface.
674  ObjCMethodDecl *getClassMethod(Selector Sel) const {
675    for (classmeth_iterator I = classmeth_begin(), E = classmeth_end();
676         I != E; ++I) {
677      if ((*I)->getSelector() == Sel)
678        return *I;
679    }
680    return 0;
681  }
682
683  // Lookup a method. First, we search locally. If a method isn't
684  // found, we search referenced protocols and class categories.
685  ObjCMethodDecl *lookupInstanceMethod(Selector Sel);
686  ObjCMethodDecl *lookupClassMethod(Selector Sel);
687
688  bool isForwardDecl() const { return isForwardProtoDecl; }
689  void setForwardDecl(bool val) { isForwardProtoDecl = val; }
690
691  // Location information, modeled after the Stmt API.
692  SourceLocation getLocStart() const { return getLocation(); } // '@'protocol
693  SourceLocation getLocEnd() const { return EndLoc; }
694  void setLocEnd(SourceLocation LE) { EndLoc = LE; };
695
696  // We also need to record the @end location.
697  SourceLocation getAtEndLoc() const { return AtEndLoc; }
698
699  static bool classof(const Decl *D) { return D->getKind() == ObjCProtocol; }
700  static bool classof(const ObjCProtocolDecl *D) { return true; }
701};
702
703/// ObjCClassDecl - Specifies a list of forward class declarations. For example:
704///
705/// @class NSCursor, NSImage, NSPasteboard, NSWindow;
706///
707class ObjCClassDecl : public Decl {
708  ObjCInterfaceDecl **ForwardDecls;
709  unsigned NumForwardDecls;
710
711  ObjCClassDecl(SourceLocation L, ObjCInterfaceDecl **Elts, unsigned nElts)
712    : Decl(ObjCClass, L) {
713    if (nElts) {
714      ForwardDecls = new ObjCInterfaceDecl*[nElts];
715      memcpy(ForwardDecls, Elts, nElts*sizeof(ObjCInterfaceDecl*));
716    } else {
717      ForwardDecls = 0;
718    }
719    NumForwardDecls = nElts;
720  }
721
722  virtual ~ObjCClassDecl();
723
724public:
725
726  /// Destroy - Call destructors and release memory.
727  virtual void Destroy(ASTContext& C);
728
729  static ObjCClassDecl *Create(ASTContext &C, SourceLocation L,
730                               ObjCInterfaceDecl **Elts, unsigned nElts);
731
732  void setInterfaceDecl(unsigned idx, ObjCInterfaceDecl *OID) {
733    assert(idx < NumForwardDecls && "index out of range");
734    ForwardDecls[idx] = OID;
735  }
736  ObjCInterfaceDecl** getForwardDecls() const { return ForwardDecls; }
737  int getNumForwardDecls() const { return NumForwardDecls; }
738
739  typedef ObjCInterfaceDecl * const * iterator;
740  iterator begin() const { return ForwardDecls; }
741  iterator end() const { return ForwardDecls+NumForwardDecls; }
742
743  static bool classof(const Decl *D) { return D->getKind() == ObjCClass; }
744  static bool classof(const ObjCClassDecl *D) { return true; }
745};
746
747/// ObjCForwardProtocolDecl - Specifies a list of forward protocol declarations.
748/// For example:
749///
750/// @protocol NSTextInput, NSChangeSpelling, NSDraggingInfo;
751///
752class ObjCForwardProtocolDecl : public Decl {
753  ObjCProtocolDecl **ReferencedProtocols;
754  unsigned NumReferencedProtocols;
755
756  ObjCForwardProtocolDecl(SourceLocation L,
757                          ObjCProtocolDecl **Elts, unsigned nElts)
758  : Decl(ObjCForwardProtocol, L) {
759    NumReferencedProtocols = nElts;
760    if (nElts) {
761      ReferencedProtocols = new ObjCProtocolDecl*[nElts];
762      memcpy(ReferencedProtocols, Elts, nElts*sizeof(ObjCProtocolDecl*));
763    } else {
764      ReferencedProtocols = 0;
765    }
766  }
767
768  virtual ~ObjCForwardProtocolDecl();
769
770public:
771  static ObjCForwardProtocolDecl *Create(ASTContext &C, SourceLocation L,
772                                         ObjCProtocolDecl **Elts, unsigned Num);
773
774
775  void setForwardProtocolDecl(unsigned idx, ObjCProtocolDecl *OID) {
776    assert(idx < NumReferencedProtocols && "index out of range");
777    ReferencedProtocols[idx] = OID;
778  }
779
780  unsigned getNumForwardDecls() const { return NumReferencedProtocols; }
781
782  ObjCProtocolDecl *getForwardProtocolDecl(unsigned idx) {
783    assert(idx < NumReferencedProtocols && "index out of range");
784    return ReferencedProtocols[idx];
785  }
786  const ObjCProtocolDecl *getForwardProtocolDecl(unsigned idx) const {
787    assert(idx < NumReferencedProtocols && "index out of range");
788    return ReferencedProtocols[idx];
789  }
790
791  typedef ObjCProtocolDecl * const * iterator;
792  iterator begin() const { return ReferencedProtocols; }
793  iterator end() const { return ReferencedProtocols+NumReferencedProtocols; }
794
795  static bool classof(const Decl *D) {
796    return D->getKind() == ObjCForwardProtocol;
797  }
798  static bool classof(const ObjCForwardProtocolDecl *D) { return true; }
799};
800
801/// ObjCCategoryDecl - Represents a category declaration. A category allows
802/// you to add methods to an existing class (without subclassing or modifying
803/// the original class interface or implementation:-). Categories don't allow
804/// you to add instance data. The following example adds "myMethod" to all
805/// NSView's within a process:
806///
807/// @interface NSView (MyViewMethods)
808/// - myMethod;
809/// @end
810///
811/// Cateogries also allow you to split the implementation of a class across
812/// several files (a feature more naturally supported in C++).
813///
814/// Categories were originally inspired by dynamic languages such as Common
815/// Lisp and Smalltalk.  More traditional class-based languages (C++, Java)
816/// don't support this level of dynamism, which is both powerful and dangerous.
817///
818class ObjCCategoryDecl : public NamedDecl {
819  /// Interface belonging to this category
820  ObjCInterfaceDecl *ClassInterface;
821
822  /// referenced protocols in this category.
823  ObjCList<ObjCProtocolDecl> ReferencedProtocols;
824
825  /// category instance methods
826  ObjCMethodDecl **InstanceMethods;  // Null if not defined
827  unsigned NumInstanceMethods;  // 0 if none
828
829  /// category class methods
830  ObjCMethodDecl **ClassMethods;  // Null if not defined
831  unsigned NumClassMethods;  // 0 if not defined
832
833  /// Next category belonging to this class
834  ObjCCategoryDecl *NextClassCategory;
835
836  /// category properties
837  ObjCPropertyDecl **PropertyDecl;  // Null if no property
838  unsigned NumPropertyDecl;  // 0 if none
839
840  SourceLocation EndLoc; // marks the '>' or identifier.
841  SourceLocation AtEndLoc; // marks the end of the entire interface.
842
843  ObjCCategoryDecl(SourceLocation L, IdentifierInfo *Id)
844    : NamedDecl(ObjCCategory, L, Id),
845      ClassInterface(0),
846      InstanceMethods(0), NumInstanceMethods(0),
847      ClassMethods(0), NumClassMethods(0),
848      NextClassCategory(0), PropertyDecl(0),  NumPropertyDecl(0) {
849  }
850public:
851
852  static ObjCCategoryDecl *Create(ASTContext &C,
853                                  SourceLocation L, IdentifierInfo *Id);
854
855  ObjCInterfaceDecl *getClassInterface() { return ClassInterface; }
856  const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; }
857  void setClassInterface(ObjCInterfaceDecl *IDecl) { ClassInterface = IDecl; }
858
859  /// addReferencedProtocols - Set the list of protocols that this interface
860  /// implements.
861  void addReferencedProtocols(ObjCProtocolDecl *const*List, unsigned NumRPs) {
862    ReferencedProtocols.set(List, NumRPs);
863  }
864
865  const ObjCList<ObjCProtocolDecl> &getReferencedProtocols() const {
866    return ReferencedProtocols;
867  }
868
869  typedef ObjCProtocolDecl * const * protocol_iterator;
870  protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();}
871  protocol_iterator protocol_end() const { return ReferencedProtocols.end(); }
872
873
874  unsigned getNumInstanceMethods() const { return NumInstanceMethods; }
875  unsigned getNumClassMethods() const { return NumClassMethods; }
876
877  unsigned getNumPropertyDecl() const { return NumPropertyDecl; }
878
879  ObjCPropertyDecl * const * getPropertyDecl() const { return PropertyDecl; }
880
881  void addProperties(ObjCPropertyDecl **Properties, unsigned NumProperties);
882
883  void addPropertyMethods(ASTContext &Context,
884                          ObjCPropertyDecl* Property,
885                          llvm::SmallVector<ObjCMethodDecl*, 32> &insMethods);
886
887  ObjCPropertyDecl *FindPropertyDeclaration(IdentifierInfo *PropertyId) const;
888
889  typedef ObjCPropertyDecl * const * classprop_iterator;
890  classprop_iterator classprop_begin() const { return PropertyDecl; }
891  classprop_iterator classprop_end() const {
892    return PropertyDecl+NumPropertyDecl;
893  }
894
895  typedef ObjCMethodDecl * const * instmeth_iterator;
896  instmeth_iterator instmeth_begin() const { return InstanceMethods; }
897  instmeth_iterator instmeth_end() const {
898    return InstanceMethods+NumInstanceMethods;
899  }
900
901  typedef ObjCMethodDecl * const * classmeth_iterator;
902  classmeth_iterator classmeth_begin() const { return ClassMethods; }
903  classmeth_iterator classmeth_end() const {
904    return ClassMethods+NumClassMethods;
905  }
906
907  // Get the local instance method declared in this interface.
908  ObjCMethodDecl *getInstanceMethod(Selector Sel) const {
909    for (instmeth_iterator I = instmeth_begin(), E = instmeth_end();
910         I != E; ++I) {
911      if ((*I)->getSelector() == Sel)
912        return *I;
913    }
914    return 0;
915  }
916  // Get the local class method declared in this interface.
917  ObjCMethodDecl *getClassMethod(Selector Sel) const {
918    for (classmeth_iterator I = classmeth_begin(), E = classmeth_end();
919         I != E; ++I) {
920      if ((*I)->getSelector() == Sel)
921        return *I;
922    }
923    return 0;
924  }
925
926  void addMethods(ObjCMethodDecl **insMethods, unsigned numInsMembers,
927                  ObjCMethodDecl **clsMethods, unsigned numClsMembers,
928                  SourceLocation AtEndLoc);
929
930  ObjCCategoryDecl *getNextClassCategory() const { return NextClassCategory; }
931  void insertNextClassCategory() {
932    NextClassCategory = ClassInterface->getCategoryList();
933    ClassInterface->setCategoryList(this);
934  }
935  // Location information, modeled after the Stmt API.
936  SourceLocation getLocStart() const { return getLocation(); } // '@'interface
937  SourceLocation getLocEnd() const { return EndLoc; }
938  void setLocEnd(SourceLocation LE) { EndLoc = LE; };
939
940  // We also need to record the @end location.
941  SourceLocation getAtEndLoc() const { return AtEndLoc; }
942
943  static bool classof(const Decl *D) { return D->getKind() == ObjCCategory; }
944  static bool classof(const ObjCCategoryDecl *D) { return true; }
945};
946
947/// ObjCCategoryImplDecl - An object of this class encapsulates a category
948/// @implementation declaration. If a category class has declaration of a
949/// property, its implementation must be specified in the category's
950/// @implementation declaration. Example:
951/// @interface I @end
952/// @interface I(CATEGORY)
953///    @property int p1, d1;
954/// @end
955/// @implementation I(CATEGORY)
956///  @dynamic p1,d1;
957/// @end
958///
959class ObjCCategoryImplDecl : public NamedDecl {
960  /// Class interface for this category implementation
961  ObjCInterfaceDecl *ClassInterface;
962
963  /// implemented instance methods
964  llvm::SmallVector<ObjCMethodDecl*, 32> InstanceMethods;
965
966  /// implemented class methods
967  llvm::SmallVector<ObjCMethodDecl*, 32> ClassMethods;
968
969  /// Property Implementations in this category
970  llvm::SmallVector<ObjCPropertyImplDecl*, 8> PropertyImplementations;
971
972  SourceLocation EndLoc;
973
974  ObjCCategoryImplDecl(SourceLocation L, IdentifierInfo *Id,
975                       ObjCInterfaceDecl *classInterface)
976    : NamedDecl(ObjCCategoryImpl, L, Id), ClassInterface(classInterface) {}
977public:
978  static ObjCCategoryImplDecl *Create(ASTContext &C,
979                                      SourceLocation L, IdentifierInfo *Id,
980                                      ObjCInterfaceDecl *classInterface);
981
982  const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; }
983  ObjCInterfaceDecl *getClassInterface() { return ClassInterface; }
984
985  unsigned getNumInstanceMethods() const { return InstanceMethods.size(); }
986  unsigned getNumClassMethods() const { return ClassMethods.size(); }
987
988  void addInstanceMethod(ObjCMethodDecl *method) {
989    InstanceMethods.push_back(method);
990  }
991  void addClassMethod(ObjCMethodDecl *method) {
992    ClassMethods.push_back(method);
993  }
994  // Get the instance method definition for this implementation.
995  ObjCMethodDecl *getInstanceMethod(Selector Sel) const;
996
997  // Get the class method definition for this implementation.
998  ObjCMethodDecl *getClassMethod(Selector Sel) const;
999
1000  void addPropertyImplementation(ObjCPropertyImplDecl *property) {
1001    PropertyImplementations.push_back(property);
1002  }
1003
1004  unsigned getNumPropertyImplementations() const
1005  { return PropertyImplementations.size(); }
1006
1007
1008  typedef llvm::SmallVector<ObjCPropertyImplDecl*, 8>::const_iterator
1009    propimpl_iterator;
1010  propimpl_iterator propimpl_begin() const {
1011    return PropertyImplementations.begin();
1012  }
1013  propimpl_iterator propimpl_end() const {
1014    return PropertyImplementations.end();
1015  }
1016
1017  typedef llvm::SmallVector<ObjCMethodDecl*, 32>::const_iterator
1018    instmeth_iterator;
1019  instmeth_iterator instmeth_begin() const { return InstanceMethods.begin(); }
1020  instmeth_iterator instmeth_end() const { return InstanceMethods.end(); }
1021
1022  typedef llvm::SmallVector<ObjCMethodDecl*, 32>::const_iterator
1023    classmeth_iterator;
1024  classmeth_iterator classmeth_begin() const { return ClassMethods.begin(); }
1025  classmeth_iterator classmeth_end() const { return ClassMethods.end(); }
1026
1027
1028  // Location information, modeled after the Stmt API.
1029  SourceLocation getLocStart() const { return getLocation(); }
1030  SourceLocation getLocEnd() const { return EndLoc; }
1031  void setLocEnd(SourceLocation LE) { EndLoc = LE; };
1032
1033  static bool classof(const Decl *D) { return D->getKind() == ObjCCategoryImpl;}
1034  static bool classof(const ObjCCategoryImplDecl *D) { return true; }
1035};
1036
1037/// ObjCImplementationDecl - Represents a class definition - this is where
1038/// method definitions are specified. For example:
1039///
1040/// @implementation MyClass
1041/// - (void)myMethod { /* do something */ }
1042/// @end
1043///
1044/// Typically, instance variables are specified in the class interface,
1045/// *not* in the implemenentation. Nevertheless (for legacy reasons), we
1046/// allow instance variables to be specified in the implementation. When
1047/// specified, they need to be *identical* to the interface. Now that we
1048/// have support for non-fragile ivars in ObjC 2.0, we can consider removing
1049/// the legacy semantics and allow developers to move private ivar declarations
1050/// from the class interface to the class implementation (but I digress:-)
1051///
1052class ObjCImplementationDecl : public NamedDecl {
1053  /// Class interface for this implementation
1054  ObjCInterfaceDecl *ClassInterface;
1055
1056  /// Implementation Class's super class.
1057  ObjCInterfaceDecl *SuperClass;
1058
1059  /// Optional Ivars/NumIvars - This is a new[]'d array of pointers to Decls.
1060  ObjCIvarDecl **Ivars;   // Null if not specified
1061  unsigned NumIvars;      // 0 if none.
1062
1063  /// implemented instance methods
1064  llvm::SmallVector<ObjCMethodDecl*, 32> InstanceMethods;
1065
1066  /// implemented class methods
1067  llvm::SmallVector<ObjCMethodDecl*, 32> ClassMethods;
1068
1069  /// Propertys' being implemented
1070  llvm::SmallVector<ObjCPropertyImplDecl*, 8> PropertyImplementations;
1071
1072  SourceLocation EndLoc;
1073
1074  ObjCImplementationDecl(SourceLocation L, IdentifierInfo *Id,
1075                         ObjCInterfaceDecl *classInterface,
1076                         ObjCInterfaceDecl *superDecl)
1077    : NamedDecl(ObjCImplementation, L, Id),
1078      ClassInterface(classInterface), SuperClass(superDecl),
1079      Ivars(0), NumIvars(0) {}
1080public:
1081  static ObjCImplementationDecl *Create(ASTContext &C,
1082                                        SourceLocation L, IdentifierInfo *Id,
1083                                        ObjCInterfaceDecl *classInterface,
1084                                        ObjCInterfaceDecl *superDecl);
1085
1086
1087  void ObjCAddInstanceVariablesToClassImpl(ObjCIvarDecl **ivars,
1088                                           unsigned numIvars);
1089
1090  void addInstanceMethod(ObjCMethodDecl *method) {
1091    InstanceMethods.push_back(method);
1092  }
1093  void addClassMethod(ObjCMethodDecl *method) {
1094    ClassMethods.push_back(method);
1095  }
1096
1097  void addPropertyImplementation(ObjCPropertyImplDecl *property) {
1098    PropertyImplementations.push_back(property);
1099  }
1100  typedef llvm::SmallVector<ObjCPropertyImplDecl*, 8>::const_iterator
1101  propimpl_iterator;
1102  propimpl_iterator propimpl_begin() const {
1103    return PropertyImplementations.begin();
1104  }
1105  propimpl_iterator propimpl_end() const {
1106    return PropertyImplementations.end();
1107  }
1108
1109  // Location information, modeled after the Stmt API.
1110  SourceLocation getLocStart() const { return getLocation(); }
1111  SourceLocation getLocEnd() const { return EndLoc; }
1112  void setLocEnd(SourceLocation LE) { EndLoc = LE; };
1113
1114  const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; }
1115  ObjCInterfaceDecl *getClassInterface() { return ClassInterface; }
1116  const ObjCInterfaceDecl *getSuperClass() const { return SuperClass; }
1117  ObjCInterfaceDecl *getSuperClass() { return SuperClass; }
1118
1119  void setSuperClass(ObjCInterfaceDecl * superCls) { SuperClass = superCls; }
1120
1121  unsigned getNumInstanceMethods() const { return InstanceMethods.size(); }
1122  unsigned getNumClassMethods() const { return ClassMethods.size(); }
1123
1124  unsigned getNumPropertyImplementations() const
1125    { return PropertyImplementations.size(); }
1126
1127  typedef llvm::SmallVector<ObjCMethodDecl*, 32>::const_iterator
1128       instmeth_iterator;
1129  instmeth_iterator instmeth_begin() const { return InstanceMethods.begin(); }
1130  instmeth_iterator instmeth_end() const { return InstanceMethods.end(); }
1131
1132  typedef llvm::SmallVector<ObjCMethodDecl*, 32>::const_iterator
1133    classmeth_iterator;
1134  classmeth_iterator classmeth_begin() const { return ClassMethods.begin(); }
1135  classmeth_iterator classmeth_end() const { return ClassMethods.end(); }
1136
1137  // Get the instance method definition for this implementation.
1138  ObjCMethodDecl *getInstanceMethod(Selector Sel) const;
1139
1140  // Get the class method definition for this implementation.
1141  ObjCMethodDecl *getClassMethod(Selector Sel) const;
1142
1143  typedef ObjCIvarDecl * const *ivar_iterator;
1144  ivar_iterator ivar_begin() const { return Ivars; }
1145  ivar_iterator ivar_end() const { return Ivars+NumIvars; }
1146  unsigned ivar_size() const { return NumIvars; }
1147  bool ivar_empty() const { return NumIvars == 0; }
1148
1149  static bool classof(const Decl *D) {
1150    return D->getKind() == ObjCImplementation;
1151  }
1152  static bool classof(const ObjCImplementationDecl *D) { return true; }
1153};
1154
1155/// ObjCCompatibleAliasDecl - Represents alias of a class. This alias is
1156/// declared as @compatibility_alias alias class.
1157class ObjCCompatibleAliasDecl : public NamedDecl {
1158  /// Class that this is an alias of.
1159  ObjCInterfaceDecl *AliasedClass;
1160
1161  ObjCCompatibleAliasDecl(SourceLocation L, IdentifierInfo *Id,
1162                          ObjCInterfaceDecl* aliasedClass)
1163    : NamedDecl(ObjCCompatibleAlias, L, Id), AliasedClass(aliasedClass) {}
1164public:
1165  static ObjCCompatibleAliasDecl *Create(ASTContext &C,
1166                                         SourceLocation L, IdentifierInfo *Id,
1167                                         ObjCInterfaceDecl* aliasedClass);
1168
1169  const ObjCInterfaceDecl *getClassInterface() const { return AliasedClass; }
1170  ObjCInterfaceDecl *getClassInterface() { return AliasedClass; }
1171
1172  static bool classof(const Decl *D) {
1173    return D->getKind() == ObjCCompatibleAlias;
1174  }
1175  static bool classof(const ObjCCompatibleAliasDecl *D) { return true; }
1176
1177};
1178
1179/// ObjCPropertyDecl - Represents one property declaration in an interface.
1180/// For example:
1181/// @property (assign, readwrite) int MyProperty;
1182///
1183class ObjCPropertyDecl : public NamedDecl {
1184public:
1185  enum PropertyAttributeKind {
1186    OBJC_PR_noattr    = 0x00,
1187    OBJC_PR_readonly  = 0x01,
1188    OBJC_PR_getter    = 0x02,
1189    OBJC_PR_assign    = 0x04,
1190    OBJC_PR_readwrite = 0x08,
1191    OBJC_PR_retain    = 0x10,
1192    OBJC_PR_copy      = 0x20,
1193    OBJC_PR_nonatomic = 0x40,
1194    OBJC_PR_setter    = 0x80
1195  };
1196
1197  enum SetterKind { Assign, Retain, Copy };
1198  enum PropertyControl { None, Required, Optional };
1199private:
1200  QualType DeclType;
1201  unsigned PropertyAttributes : 8;
1202
1203  // @required/@optional
1204  unsigned PropertyImplementation : 2;
1205
1206  Selector GetterName;    // getter name of NULL if no getter
1207  Selector SetterName;    // setter name of NULL if no setter
1208
1209  ObjCMethodDecl *GetterMethodDecl; // Declaration of getter instance method
1210  ObjCMethodDecl *SetterMethodDecl; // Declaration of setter instance method
1211
1212  ObjCPropertyDecl(SourceLocation L, IdentifierInfo *Id, QualType T)
1213    : NamedDecl(ObjCProperty, L, Id), DeclType(T),
1214      PropertyAttributes(OBJC_PR_noattr), PropertyImplementation(None),
1215      GetterName(Selector()),
1216      SetterName(Selector()),
1217      GetterMethodDecl(0), SetterMethodDecl(0) {}
1218public:
1219  static ObjCPropertyDecl *Create(ASTContext &C, SourceLocation L,
1220                                  IdentifierInfo *Id, QualType T,
1221                                  PropertyControl propControl = None);
1222  QualType getType() const { return DeclType; }
1223
1224  PropertyAttributeKind getPropertyAttributes() const {
1225    return PropertyAttributeKind(PropertyAttributes);
1226  }
1227  void setPropertyAttributes(PropertyAttributeKind PRVal) {
1228    PropertyAttributes |= PRVal;
1229  }
1230
1231 void makeitReadWriteAttribute(void) {
1232    PropertyAttributes &= ~OBJC_PR_readonly;
1233    PropertyAttributes |= OBJC_PR_readwrite;
1234 }
1235
1236  // Helper methods for accessing attributes.
1237
1238  /// isReadOnly - Return true iff the property has a setter.
1239  bool isReadOnly() const {
1240    return (PropertyAttributes & OBJC_PR_readonly);
1241  }
1242
1243  /// getSetterKind - Return the method used for doing assignment in
1244  /// the property setter. This is only valid if the property has been
1245  /// defined to have a setter.
1246  SetterKind getSetterKind() const {
1247    if (PropertyAttributes & OBJC_PR_retain)
1248      return Retain;
1249    if (PropertyAttributes & OBJC_PR_copy)
1250      return Copy;
1251    return Assign;
1252  }
1253
1254  Selector getGetterName() const { return GetterName; }
1255  void setGetterName(Selector Sel) { GetterName = Sel; }
1256
1257  Selector getSetterName() const { return SetterName; }
1258  void setSetterName(Selector Sel) { SetterName = Sel; }
1259
1260  ObjCMethodDecl *getGetterMethodDecl() const { return GetterMethodDecl; }
1261  void setGetterMethodDecl(ObjCMethodDecl *gDecl) { GetterMethodDecl = gDecl; }
1262
1263  ObjCMethodDecl *getSetterMethodDecl() const { return SetterMethodDecl; }
1264  void setSetterMethodDecl(ObjCMethodDecl *gDecl) { SetterMethodDecl = gDecl; }
1265
1266  // Related to @optional/@required declared in @protocol
1267  void setPropertyImplementation(PropertyControl pc) {
1268    PropertyImplementation = pc;
1269  }
1270  PropertyControl getPropertyImplementation() const {
1271    return PropertyControl(PropertyImplementation);
1272  }
1273
1274  static bool classof(const Decl *D) {
1275    return D->getKind() == ObjCProperty;
1276  }
1277  static bool classof(const ObjCPropertyDecl *D) { return true; }
1278};
1279
1280/// ObjCPropertyImplDecl - Represents implementation declaration of a property
1281/// in a class or category implementation block. For example:
1282/// @synthesize prop1 = ivar1;
1283///
1284class ObjCPropertyImplDecl : public Decl {
1285public:
1286  enum Kind {
1287    Synthesize,
1288    Dynamic
1289  };
1290private:
1291  SourceLocation AtLoc;   // location of @synthesize or @dynamic
1292  /// Property declaration being implemented
1293  ObjCPropertyDecl *PropertyDecl;
1294
1295  /// Null for @dynamic. Required for @synthesize.
1296  ObjCIvarDecl *PropertyIvarDecl;
1297
1298  ObjCPropertyImplDecl(SourceLocation atLoc, SourceLocation L,
1299                       ObjCPropertyDecl *property,
1300                       Kind PK,
1301                       ObjCIvarDecl *ivarDecl)
1302    : Decl(ObjCPropertyImpl, L), AtLoc(atLoc), PropertyDecl(property),
1303      PropertyIvarDecl(ivarDecl) {
1304    assert (PK == Dynamic || PropertyIvarDecl);
1305  }
1306
1307public:
1308  static ObjCPropertyImplDecl *Create(ASTContext &C, SourceLocation atLoc,
1309                                      SourceLocation L,
1310                                      ObjCPropertyDecl *property,
1311                                      Kind PK,
1312                                      ObjCIvarDecl *ivarDecl);
1313
1314  ObjCPropertyDecl *getPropertyDecl() const {
1315    return PropertyDecl;
1316  }
1317
1318  Kind getPropertyImplementation() const {
1319    return PropertyIvarDecl ? Synthesize : Dynamic;
1320  }
1321
1322  ObjCIvarDecl *getPropertyIvarDecl() const {
1323    return PropertyIvarDecl;
1324  }
1325
1326  static bool classof(const Decl *D) {
1327    return D->getKind() == ObjCPropertyImpl;
1328  }
1329  static bool classof(const ObjCPropertyImplDecl *D) { return true; }
1330};
1331
1332}  // end namespace clang
1333#endif
1334