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