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