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