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