1193326Sed//===--- DeclObjC.h - Classes for representing declarations -----*- C++ -*-===//
2193326Sed//
3193326Sed//                     The LLVM Compiler Infrastructure
4193326Sed//
5193326Sed// This file is distributed under the University of Illinois Open Source
6193326Sed// License. See LICENSE.TXT for details.
7193326Sed//
8193326Sed//===----------------------------------------------------------------------===//
9193326Sed//
10193326Sed//  This file defines the DeclObjC interface and subclasses.
11193326Sed//
12193326Sed//===----------------------------------------------------------------------===//
13193326Sed
14193326Sed#ifndef LLVM_CLANG_AST_DECLOBJC_H
15193326Sed#define LLVM_CLANG_AST_DECLOBJC_H
16193326Sed
17193326Sed#include "clang/AST/Decl.h"
18226633Sdim#include "clang/AST/SelectorLocationsKind.h"
19193326Sed#include "llvm/ADT/STLExtras.h"
20234353Sdim#include "llvm/Support/Compiler.h"
21193326Sed
22193326Sednamespace clang {
23193326Sedclass Expr;
24193326Sedclass Stmt;
25193326Sedclass FunctionDecl;
26193326Sedclass RecordDecl;
27193326Sedclass ObjCIvarDecl;
28193326Sedclass ObjCMethodDecl;
29193326Sedclass ObjCProtocolDecl;
30193326Sedclass ObjCCategoryDecl;
31193326Sedclass ObjCPropertyDecl;
32193326Sedclass ObjCPropertyImplDecl;
33218893Sdimclass CXXCtorInitializer;
34193326Sed
35193326Sedclass ObjCListBase {
36243830Sdim  ObjCListBase(const ObjCListBase &) LLVM_DELETED_FUNCTION;
37243830Sdim  void operator=(const ObjCListBase &) LLVM_DELETED_FUNCTION;
38193326Sedprotected:
39193326Sed  /// List is an array of pointers to objects that are not owned by this object.
40193326Sed  void **List;
41193326Sed  unsigned NumElts;
42193326Sed
43193326Sedpublic:
44193326Sed  ObjCListBase() : List(0), NumElts(0) {}
45193326Sed  unsigned size() const { return NumElts; }
46193326Sed  bool empty() const { return NumElts == 0; }
47198092Srdivacky
48193326Sedprotected:
49193326Sed  void set(void *const* InList, unsigned Elts, ASTContext &Ctx);
50193326Sed};
51198092Srdivacky
52198092Srdivacky
53193326Sed/// ObjCList - This is a simple template class used to hold various lists of
54193326Sed/// decls etc, which is heavily used by the ObjC front-end.  This only use case
55193326Sed/// this supports is setting the list all at once and then reading elements out
56193326Sed/// of it.
57193326Sedtemplate <typename T>
58193326Sedclass ObjCList : public ObjCListBase {
59193326Sedpublic:
60193326Sed  void set(T* const* InList, unsigned Elts, ASTContext &Ctx) {
61193326Sed    ObjCListBase::set(reinterpret_cast<void*const*>(InList), Elts, Ctx);
62193326Sed  }
63198092Srdivacky
64193326Sed  typedef T* const * iterator;
65193326Sed  iterator begin() const { return (iterator)List; }
66193326Sed  iterator end() const { return (iterator)List+NumElts; }
67198092Srdivacky
68193326Sed  T* operator[](unsigned Idx) const {
69193326Sed    assert(Idx < NumElts && "Invalid access");
70193326Sed    return (T*)List[Idx];
71193326Sed  }
72193326Sed};
73193326Sed
74202879Srdivacky/// \brief A list of Objective-C protocols, along with the source
75202879Srdivacky/// locations at which they were referenced.
76202879Srdivackyclass ObjCProtocolList : public ObjCList<ObjCProtocolDecl> {
77202879Srdivacky  SourceLocation *Locations;
78193326Sed
79202879Srdivacky  using ObjCList<ObjCProtocolDecl>::set;
80198092Srdivacky
81202879Srdivackypublic:
82202879Srdivacky  ObjCProtocolList() : ObjCList<ObjCProtocolDecl>(), Locations(0) { }
83202879Srdivacky
84202879Srdivacky  typedef const SourceLocation *loc_iterator;
85202879Srdivacky  loc_iterator loc_begin() const { return Locations; }
86202879Srdivacky  loc_iterator loc_end() const { return Locations + size(); }
87202879Srdivacky
88234353Sdim  void set(ObjCProtocolDecl* const* InList, unsigned Elts,
89202879Srdivacky           const SourceLocation *Locs, ASTContext &Ctx);
90202879Srdivacky};
91202879Srdivacky
92202879Srdivacky
93193326Sed/// ObjCMethodDecl - Represents an instance or class method declaration.
94193326Sed/// ObjC methods can be declared within 4 contexts: class interfaces,
95193326Sed/// categories, protocols, and class implementations. While C++ member
96198092Srdivacky/// functions leverage C syntax, Objective-C method syntax is modeled after
97198092Srdivacky/// Smalltalk (using colons to specify argument types/expressions).
98193326Sed/// Here are some brief examples:
99193326Sed///
100193326Sed/// Setter/getter instance methods:
101193326Sed/// - (void)setMenu:(NSMenu *)menu;
102198092Srdivacky/// - (NSMenu *)menu;
103198092Srdivacky///
104193326Sed/// Instance method that takes 2 NSView arguments:
105193326Sed/// - (void)replaceSubview:(NSView *)oldView with:(NSView *)newView;
106193326Sed///
107193326Sed/// Getter class method:
108193326Sed/// + (NSMenu *)defaultMenu;
109193326Sed///
110193326Sed/// A selector represents a unique name for a method. The selector names for
111193326Sed/// the above methods are setMenu:, menu, replaceSubview:with:, and defaultMenu.
112193326Sed///
113193326Sedclass ObjCMethodDecl : public NamedDecl, public DeclContext {
114193326Sedpublic:
115193326Sed  enum ImplementationControl { None, Required, Optional };
116193326Sedprivate:
117221345Sdim  // The conventional meaning of this method; an ObjCMethodFamily.
118221345Sdim  // This is not serialized; instead, it is computed on demand and
119221345Sdim  // cached.
120221345Sdim  mutable unsigned Family : ObjCMethodFamilyBitWidth;
121221345Sdim
122193326Sed  /// instance (true) or class (false) method.
123221345Sdim  unsigned IsInstance : 1;
124221345Sdim  unsigned IsVariadic : 1;
125198092Srdivacky
126243830Sdim  /// True if this method is the getter or setter for an explicit property.
127243830Sdim  unsigned IsPropertyAccessor : 1;
128234353Sdim
129212904Sdim  // Method has a definition.
130221345Sdim  unsigned IsDefined : 1;
131198092Srdivacky
132226633Sdim  /// \brief Method redeclaration in the same interface.
133226633Sdim  unsigned IsRedeclaration : 1;
134226633Sdim
135226633Sdim  /// \brief Is redeclared in the same interface.
136226633Sdim  mutable unsigned HasRedeclaration : 1;
137226633Sdim
138193326Sed  // NOTE: VC++ treats enums as signed, avoid using ImplementationControl enum
139239462Sdim  /// \@required/\@optional
140193326Sed  unsigned DeclImplementation : 2;
141198092Srdivacky
142193326Sed  // NOTE: VC++ treats enums as signed, avoid using the ObjCDeclQualifier enum
143193326Sed  /// in, inout, etc.
144193326Sed  unsigned objcDeclQualifier : 6;
145198092Srdivacky
146223017Sdim  /// \brief Indicates whether this method has a related result type.
147223017Sdim  unsigned RelatedResultType : 1;
148234353Sdim
149226633Sdim  /// \brief Whether the locations of the selector identifiers are in a
150226633Sdim  /// "standard" position, a enum SelectorLocationsKind.
151226633Sdim  unsigned SelLocsKind : 2;
152207619Srdivacky
153239462Sdim  /// \brief Whether this method overrides any other in the class hierarchy.
154239462Sdim  ///
155239462Sdim  /// A method is said to override any method in the class's
156239462Sdim  /// base classes, its protocols, or its categories' protocols, that has
157239462Sdim  /// the same selector and is of the same kind (class or instance).
158239462Sdim  /// A method in an implementation is not considered as overriding the same
159239462Sdim  /// method in the interface or its categories.
160239462Sdim  unsigned IsOverriding : 1;
161239462Sdim
162249423Sdim  /// \brief Indicates if the method was a definition but its body was skipped.
163249423Sdim  unsigned HasSkippedBody : 1;
164249423Sdim
165204962Srdivacky  // Result type of this method.
166193326Sed  QualType MethodDeclType;
167234353Sdim
168204962Srdivacky  // Type source information for the result type.
169204962Srdivacky  TypeSourceInfo *ResultTInfo;
170204962Srdivacky
171226633Sdim  /// \brief Array of ParmVarDecls for the formal parameters of this method
172226633Sdim  /// and optionally followed by selector locations.
173226633Sdim  void *ParamsAndSelLocs;
174226633Sdim  unsigned NumParams;
175198092Srdivacky
176193326Sed  /// List of attributes for this method declaration.
177239462Sdim  SourceLocation DeclEndLoc; // the location of the ';' or '{'.
178198092Srdivacky
179193326Sed  // The following are only used for method definitions, null otherwise.
180243830Sdim  LazyDeclStmtPtr Body;
181193326Sed
182193326Sed  /// SelfDecl - Decl for the implicit self parameter. This is lazily
183193326Sed  /// constructed by createImplicitParams.
184193326Sed  ImplicitParamDecl *SelfDecl;
185193326Sed  /// CmdDecl - Decl for the implicit _cmd parameter. This is lazily
186193326Sed  /// constructed by createImplicitParams.
187193326Sed  ImplicitParamDecl *CmdDecl;
188198092Srdivacky
189226633Sdim  SelectorLocationsKind getSelLocsKind() const {
190226633Sdim    return (SelectorLocationsKind)SelLocsKind;
191226633Sdim  }
192226633Sdim  bool hasStandardSelLocs() const {
193226633Sdim    return getSelLocsKind() != SelLoc_NonStandard;
194226633Sdim  }
195226633Sdim
196226633Sdim  /// \brief Get a pointer to the stored selector identifiers locations array.
197226633Sdim  /// No locations will be stored if HasStandardSelLocs is true.
198226633Sdim  SourceLocation *getStoredSelLocs() {
199226633Sdim    return reinterpret_cast<SourceLocation*>(getParams() + NumParams);
200226633Sdim  }
201226633Sdim  const SourceLocation *getStoredSelLocs() const {
202226633Sdim    return reinterpret_cast<const SourceLocation*>(getParams() + NumParams);
203226633Sdim  }
204226633Sdim
205226633Sdim  /// \brief Get a pointer to the stored selector identifiers locations array.
206226633Sdim  /// No locations will be stored if HasStandardSelLocs is true.
207226633Sdim  ParmVarDecl **getParams() {
208226633Sdim    return reinterpret_cast<ParmVarDecl **>(ParamsAndSelLocs);
209226633Sdim  }
210226633Sdim  const ParmVarDecl *const *getParams() const {
211226633Sdim    return reinterpret_cast<const ParmVarDecl *const *>(ParamsAndSelLocs);
212226633Sdim  }
213226633Sdim
214226633Sdim  /// \brief Get the number of stored selector identifiers locations.
215226633Sdim  /// No locations will be stored if HasStandardSelLocs is true.
216226633Sdim  unsigned getNumStoredSelLocs() const {
217226633Sdim    if (hasStandardSelLocs())
218226633Sdim      return 0;
219226633Sdim    return getNumSelectorLocs();
220226633Sdim  }
221226633Sdim
222226633Sdim  void setParamsAndSelLocs(ASTContext &C,
223226633Sdim                           ArrayRef<ParmVarDecl*> Params,
224226633Sdim                           ArrayRef<SourceLocation> SelLocs);
225226633Sdim
226193326Sed  ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc,
227193326Sed                 Selector SelInfo, QualType T,
228204962Srdivacky                 TypeSourceInfo *ResultTInfo,
229193326Sed                 DeclContext *contextDecl,
230193326Sed                 bool isInstance = true,
231193326Sed                 bool isVariadic = false,
232243830Sdim                 bool isPropertyAccessor = false,
233226633Sdim                 bool isImplicitlyDeclared = false,
234212904Sdim                 bool isDefined = false,
235207619Srdivacky                 ImplementationControl impControl = None,
236226633Sdim                 bool HasRelatedResultType = false)
237193326Sed  : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo),
238221345Sdim    DeclContext(ObjCMethod), Family(InvalidObjCMethodFamily),
239193326Sed    IsInstance(isInstance), IsVariadic(isVariadic),
240243830Sdim    IsPropertyAccessor(isPropertyAccessor),
241226633Sdim    IsDefined(isDefined), IsRedeclaration(0), HasRedeclaration(0),
242193326Sed    DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None),
243226633Sdim    RelatedResultType(HasRelatedResultType),
244249423Sdim    SelLocsKind(SelLoc_StandardNoSpace), IsOverriding(0), HasSkippedBody(0),
245223017Sdim    MethodDeclType(T), ResultTInfo(ResultTInfo),
246226633Sdim    ParamsAndSelLocs(0), NumParams(0),
247243830Sdim    DeclEndLoc(endLoc), Body(), SelfDecl(0), CmdDecl(0) {
248226633Sdim    setImplicit(isImplicitlyDeclared);
249226633Sdim  }
250193326Sed
251198092Srdivacky  /// \brief A definition will return its interface declaration.
252198092Srdivacky  /// An interface declaration will return its definition.
253198092Srdivacky  /// Otherwise it will return itself.
254198092Srdivacky  virtual ObjCMethodDecl *getNextRedeclaration();
255198092Srdivacky
256193326Sedpublic:
257193326Sed  static ObjCMethodDecl *Create(ASTContext &C,
258198092Srdivacky                                SourceLocation beginLoc,
259226633Sdim                                SourceLocation endLoc,
260226633Sdim                                Selector SelInfo,
261234353Sdim                                QualType T,
262204962Srdivacky                                TypeSourceInfo *ResultTInfo,
263204962Srdivacky                                DeclContext *contextDecl,
264193326Sed                                bool isInstance = true,
265193326Sed                                bool isVariadic = false,
266243830Sdim                                bool isPropertyAccessor = false,
267226633Sdim                                bool isImplicitlyDeclared = false,
268212904Sdim                                bool isDefined = false,
269207619Srdivacky                                ImplementationControl impControl = None,
270226633Sdim                                bool HasRelatedResultType = false);
271198092Srdivacky
272234353Sdim  static ObjCMethodDecl *CreateDeserialized(ASTContext &C, unsigned ID);
273234353Sdim
274198092Srdivacky  virtual ObjCMethodDecl *getCanonicalDecl();
275203955Srdivacky  const ObjCMethodDecl *getCanonicalDecl() const {
276203955Srdivacky    return const_cast<ObjCMethodDecl*>(this)->getCanonicalDecl();
277203955Srdivacky  }
278198092Srdivacky
279193326Sed  ObjCDeclQualifier getObjCDeclQualifier() const {
280193326Sed    return ObjCDeclQualifier(objcDeclQualifier);
281193326Sed  }
282193326Sed  void setObjCDeclQualifier(ObjCDeclQualifier QV) { objcDeclQualifier = QV; }
283198092Srdivacky
284223017Sdim  /// \brief Determine whether this method has a result type that is related
285223017Sdim  /// to the message receiver's type.
286223017Sdim  bool hasRelatedResultType() const { return RelatedResultType; }
287234353Sdim
288223017Sdim  /// \brief Note whether this method has a related result type.
289223017Sdim  void SetRelatedResultType(bool RRT = true) { RelatedResultType = RRT; }
290226633Sdim
291226633Sdim  /// \brief True if this is a method redeclaration in the same interface.
292226633Sdim  bool isRedeclaration() const { return IsRedeclaration; }
293226633Sdim  void setAsRedeclaration(const ObjCMethodDecl *PrevMethod);
294234353Sdim
295239462Sdim  /// \brief Returns the location where the declarator ends. It will be
296239462Sdim  /// the location of ';' for a method declaration and the location of '{'
297239462Sdim  /// for a method definition.
298239462Sdim  SourceLocation getDeclaratorEndLoc() const { return DeclEndLoc; }
299239462Sdim
300193326Sed  // Location information, modeled after the Stmt API.
301234353Sdim  SourceLocation getLocStart() const LLVM_READONLY { return getLocation(); }
302239462Sdim  SourceLocation getLocEnd() const LLVM_READONLY;
303234353Sdim  virtual SourceRange getSourceRange() const LLVM_READONLY {
304239462Sdim    return SourceRange(getLocation(), getLocEnd());
305193326Sed  }
306198092Srdivacky
307234353Sdim  SourceLocation getSelectorStartLoc() const {
308234353Sdim    if (isImplicit())
309234353Sdim      return getLocStart();
310234353Sdim    return getSelectorLoc(0);
311234353Sdim  }
312226633Sdim  SourceLocation getSelectorLoc(unsigned Index) const {
313226633Sdim    assert(Index < getNumSelectorLocs() && "Index out of range!");
314226633Sdim    if (hasStandardSelLocs())
315226633Sdim      return getStandardSelectorLoc(Index, getSelector(),
316226633Sdim                                   getSelLocsKind() == SelLoc_StandardWithSpace,
317226633Sdim                      llvm::makeArrayRef(const_cast<ParmVarDecl**>(getParams()),
318226633Sdim                                         NumParams),
319239462Sdim                                   DeclEndLoc);
320226633Sdim    return getStoredSelLocs()[Index];
321226633Sdim  }
322226633Sdim
323226633Sdim  void getSelectorLocs(SmallVectorImpl<SourceLocation> &SelLocs) const;
324226633Sdim
325226633Sdim  unsigned getNumSelectorLocs() const {
326226633Sdim    if (isImplicit())
327226633Sdim      return 0;
328226633Sdim    Selector Sel = getSelector();
329226633Sdim    if (Sel.isUnarySelector())
330226633Sdim      return 1;
331226633Sdim    return Sel.getNumArgs();
332226633Sdim  }
333226633Sdim
334193326Sed  ObjCInterfaceDecl *getClassInterface();
335193326Sed  const ObjCInterfaceDecl *getClassInterface() const {
336193326Sed    return const_cast<ObjCMethodDecl*>(this)->getClassInterface();
337193326Sed  }
338198092Srdivacky
339193326Sed  Selector getSelector() const { return getDeclName().getObjCSelector(); }
340198092Srdivacky
341193326Sed  QualType getResultType() const { return MethodDeclType; }
342193326Sed  void setResultType(QualType T) { MethodDeclType = T; }
343198092Srdivacky
344234353Sdim  /// \brief Determine the type of an expression that sends a message to this
345210299Sed  /// function.
346210299Sed  QualType getSendResultType() const {
347210299Sed    return getResultType().getNonLValueExprType(getASTContext());
348210299Sed  }
349234353Sdim
350204962Srdivacky  TypeSourceInfo *getResultTypeSourceInfo() const { return ResultTInfo; }
351204962Srdivacky  void setResultTypeSourceInfo(TypeSourceInfo *TInfo) { ResultTInfo = TInfo; }
352204962Srdivacky
353193326Sed  // Iterator access to formal parameters.
354226633Sdim  unsigned param_size() const { return NumParams; }
355226633Sdim  typedef const ParmVarDecl *const *param_const_iterator;
356226633Sdim  typedef ParmVarDecl *const *param_iterator;
357226633Sdim  param_const_iterator param_begin() const { return getParams(); }
358226633Sdim  param_const_iterator param_end() const { return getParams() + NumParams; }
359226633Sdim  param_iterator param_begin() { return getParams(); }
360226633Sdim  param_iterator param_end() { return getParams() + NumParams; }
361207619Srdivacky  // This method returns and of the parameters which are part of the selector
362207619Srdivacky  // name mangling requirements.
363234353Sdim  param_const_iterator sel_param_end() const {
364234353Sdim    return param_begin() + getSelector().getNumArgs();
365207619Srdivacky  }
366193326Sed
367226633Sdim  /// \brief Sets the method's parameters and selector source locations.
368243830Sdim  /// If the method is implicit (not coming from source) \p SelLocs is
369226633Sdim  /// ignored.
370226633Sdim  void setMethodParams(ASTContext &C,
371226633Sdim                       ArrayRef<ParmVarDecl*> Params,
372226633Sdim                       ArrayRef<SourceLocation> SelLocs =
373226633Sdim                           ArrayRef<SourceLocation>());
374193326Sed
375193326Sed  // Iterator access to parameter types.
376193326Sed  typedef std::const_mem_fun_t<QualType, ParmVarDecl> deref_fun;
377226633Sdim  typedef llvm::mapped_iterator<param_const_iterator, deref_fun>
378226633Sdim      arg_type_iterator;
379193326Sed
380193326Sed  arg_type_iterator arg_type_begin() const {
381193326Sed    return llvm::map_iterator(param_begin(), deref_fun(&ParmVarDecl::getType));
382193326Sed  }
383193326Sed  arg_type_iterator arg_type_end() const {
384193326Sed    return llvm::map_iterator(param_end(), deref_fun(&ParmVarDecl::getType));
385193326Sed  }
386198092Srdivacky
387193326Sed  /// createImplicitParams - Used to lazily create the self and cmd
388193326Sed  /// implict parameters. This must be called prior to using getSelfDecl()
389193326Sed  /// or getCmdDecl(). The call is ignored if the implicit paramters
390193326Sed  /// have already been created.
391193326Sed  void createImplicitParams(ASTContext &Context, const ObjCInterfaceDecl *ID);
392193326Sed
393193326Sed  ImplicitParamDecl * getSelfDecl() const { return SelfDecl; }
394193326Sed  void setSelfDecl(ImplicitParamDecl *SD) { SelfDecl = SD; }
395193326Sed  ImplicitParamDecl * getCmdDecl() const { return CmdDecl; }
396193326Sed  void setCmdDecl(ImplicitParamDecl *CD) { CmdDecl = CD; }
397198092Srdivacky
398221345Sdim  /// Determines the family of this method.
399221345Sdim  ObjCMethodFamily getMethodFamily() const;
400221345Sdim
401193326Sed  bool isInstanceMethod() const { return IsInstance; }
402193326Sed  void setInstanceMethod(bool isInst) { IsInstance = isInst; }
403193326Sed  bool isVariadic() const { return IsVariadic; }
404193326Sed  void setVariadic(bool isVar) { IsVariadic = isVar; }
405198092Srdivacky
406193326Sed  bool isClassMethod() const { return !IsInstance; }
407193326Sed
408243830Sdim  bool isPropertyAccessor() const { return IsPropertyAccessor; }
409243830Sdim  void setPropertyAccessor(bool isAccessor) { IsPropertyAccessor = isAccessor; }
410234353Sdim
411212904Sdim  bool isDefined() const { return IsDefined; }
412212904Sdim  void setDefined(bool isDefined) { IsDefined = isDefined; }
413198092Srdivacky
414239462Sdim  /// \brief Whether this method overrides any other in the class hierarchy.
415239462Sdim  ///
416239462Sdim  /// A method is said to override any method in the class's
417239462Sdim  /// base classes, its protocols, or its categories' protocols, that has
418239462Sdim  /// the same selector and is of the same kind (class or instance).
419239462Sdim  /// A method in an implementation is not considered as overriding the same
420239462Sdim  /// method in the interface or its categories.
421239462Sdim  bool isOverriding() const { return IsOverriding; }
422239462Sdim  void setOverriding(bool isOverriding) { IsOverriding = isOverriding; }
423243830Sdim
424243830Sdim  /// \brief Return overridden methods for the given \p Method.
425243830Sdim  ///
426243830Sdim  /// An ObjC method is considered to override any method in the class's
427243830Sdim  /// base classes (and base's categories), its protocols, or its categories'
428243830Sdim  /// protocols, that has
429243830Sdim  /// the same selector and is of the same kind (class or instance).
430243830Sdim  /// A method in an implementation is not considered as overriding the same
431243830Sdim  /// method in the interface or its categories.
432243830Sdim  void getOverriddenMethods(
433243830Sdim                     SmallVectorImpl<const ObjCMethodDecl *> &Overridden) const;
434243830Sdim
435249423Sdim  /// \brief True if the method was a definition but its body was skipped.
436249423Sdim  bool hasSkippedBody() const { return HasSkippedBody; }
437249423Sdim  void setHasSkippedBody(bool Skipped = true) { HasSkippedBody = Skipped; }
438249423Sdim
439243830Sdim  /// \brief Returns the property associated with this method's selector.
440243830Sdim  ///
441243830Sdim  /// Note that even if this particular method is not marked as a property
442243830Sdim  /// accessor, it is still possible for it to match a property declared in a
443243830Sdim  /// superclass. Pass \c false if you only want to check the current class.
444243830Sdim  const ObjCPropertyDecl *findPropertyDecl(bool CheckOverrides = true) const;
445243830Sdim
446239462Sdim  // Related to protocols declared in  \@protocol
447198092Srdivacky  void setDeclImplementation(ImplementationControl ic) {
448198092Srdivacky    DeclImplementation = ic;
449193326Sed  }
450198092Srdivacky  ImplementationControl getImplementationControl() const {
451198092Srdivacky    return ImplementationControl(DeclImplementation);
452193326Sed  }
453193326Sed
454243830Sdim  /// \brief Determine whether this method has a body.
455263508Sdim  virtual bool hasBody() const { return Body.isValid(); }
456243830Sdim
457243830Sdim  /// \brief Retrieve the body of this method, if it has one.
458243830Sdim  virtual Stmt *getBody() const;
459243830Sdim
460243830Sdim  void setLazyBody(uint64_t Offset) { Body = Offset; }
461243830Sdim
462243830Sdim  CompoundStmt *getCompoundBody() { return (CompoundStmt*)getBody(); }
463193326Sed  void setBody(Stmt *B) { Body = B; }
464193326Sed
465198092Srdivacky  /// \brief Returns whether this specific method is a definition.
466263508Sdim  bool isThisDeclarationADefinition() const { return hasBody(); }
467198092Srdivacky
468193326Sed  // Implement isa/cast/dyncast/etc.
469203955Srdivacky  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
470203955Srdivacky  static bool classofKind(Kind K) { return K == ObjCMethod; }
471193326Sed  static DeclContext *castToDeclContext(const ObjCMethodDecl *D) {
472193326Sed    return static_cast<DeclContext *>(const_cast<ObjCMethodDecl*>(D));
473193326Sed  }
474193326Sed  static ObjCMethodDecl *castFromDeclContext(const DeclContext *DC) {
475193326Sed    return static_cast<ObjCMethodDecl *>(const_cast<DeclContext*>(DC));
476193326Sed  }
477226633Sdim
478226633Sdim  friend class ASTDeclReader;
479226633Sdim  friend class ASTDeclWriter;
480193326Sed};
481193326Sed
482193326Sed/// ObjCContainerDecl - Represents a container for method declarations.
483198092Srdivacky/// Current sub-classes are ObjCInterfaceDecl, ObjCCategoryDecl,
484198092Srdivacky/// ObjCProtocolDecl, and ObjCImplDecl.
485193326Sed///
486193326Sedclass ObjCContainerDecl : public NamedDecl, public DeclContext {
487234353Sdim  virtual void anchor();
488234353Sdim
489226633Sdim  SourceLocation AtStart;
490226633Sdim
491202379Srdivacky  // These two locations in the range mark the end of the method container.
492202379Srdivacky  // The first points to the '@' token, and the second to the 'end' token.
493202379Srdivacky  SourceRange AtEnd;
494193326Sedpublic:
495193326Sed
496226633Sdim  ObjCContainerDecl(Kind DK, DeclContext *DC,
497226633Sdim                    IdentifierInfo *Id, SourceLocation nameLoc,
498226633Sdim                    SourceLocation atStartLoc)
499226633Sdim    : NamedDecl(DK, DC, nameLoc, Id), DeclContext(DK), AtStart(atStartLoc) {}
500193326Sed
501193326Sed  // Iterator access to properties.
502193326Sed  typedef specific_decl_iterator<ObjCPropertyDecl> prop_iterator;
503198092Srdivacky  prop_iterator prop_begin() const {
504195341Sed    return prop_iterator(decls_begin());
505193326Sed  }
506198092Srdivacky  prop_iterator prop_end() const {
507195341Sed    return prop_iterator(decls_end());
508193326Sed  }
509198092Srdivacky
510193326Sed  // Iterator access to instance/class methods.
511193326Sed  typedef specific_decl_iterator<ObjCMethodDecl> method_iterator;
512198092Srdivacky  method_iterator meth_begin() const {
513195341Sed    return method_iterator(decls_begin());
514193326Sed  }
515198092Srdivacky  method_iterator meth_end() const {
516195341Sed    return method_iterator(decls_end());
517193326Sed  }
518193326Sed
519198092Srdivacky  typedef filtered_decl_iterator<ObjCMethodDecl,
520198092Srdivacky                                 &ObjCMethodDecl::isInstanceMethod>
521193326Sed    instmeth_iterator;
522195341Sed  instmeth_iterator instmeth_begin() const {
523195341Sed    return instmeth_iterator(decls_begin());
524193326Sed  }
525195341Sed  instmeth_iterator instmeth_end() const {
526195341Sed    return instmeth_iterator(decls_end());
527193326Sed  }
528193326Sed
529198092Srdivacky  typedef filtered_decl_iterator<ObjCMethodDecl,
530198092Srdivacky                                 &ObjCMethodDecl::isClassMethod>
531193326Sed    classmeth_iterator;
532195341Sed  classmeth_iterator classmeth_begin() const {
533195341Sed    return classmeth_iterator(decls_begin());
534193326Sed  }
535195341Sed  classmeth_iterator classmeth_end() const {
536195341Sed    return classmeth_iterator(decls_end());
537193326Sed  }
538193326Sed
539193326Sed  // Get the local instance/class method declared in this interface.
540249423Sdim  ObjCMethodDecl *getMethod(Selector Sel, bool isInstance,
541249423Sdim                            bool AllowHidden = false) const;
542249423Sdim  ObjCMethodDecl *getInstanceMethod(Selector Sel,
543249423Sdim                                    bool AllowHidden = false) const {
544249423Sdim    return getMethod(Sel, true/*isInstance*/, AllowHidden);
545198092Srdivacky  }
546249423Sdim  ObjCMethodDecl *getClassMethod(Selector Sel, bool AllowHidden = false) const {
547249423Sdim    return getMethod(Sel, false/*isInstance*/, AllowHidden);
548198092Srdivacky  }
549249423Sdim  bool HasUserDeclaredSetterMethod(const ObjCPropertyDecl *P) const;
550195341Sed  ObjCIvarDecl *getIvarDecl(IdentifierInfo *Id) const;
551193326Sed
552195341Sed  ObjCPropertyDecl *FindPropertyDeclaration(IdentifierInfo *PropertyId) const;
553193326Sed
554243830Sdim  typedef llvm::DenseMap<IdentifierInfo*, ObjCPropertyDecl*> PropertyMap;
555249423Sdim
556263508Sdim  typedef llvm::DenseMap<const ObjCProtocolDecl *, ObjCPropertyDecl*>
557263508Sdim            ProtocolPropertyMap;
558263508Sdim
559249423Sdim  typedef llvm::SmallVector<ObjCPropertyDecl*, 8> PropertyDeclOrder;
560249423Sdim
561243830Sdim  /// This routine collects list of properties to be implemented in the class.
562243830Sdim  /// This includes, class's and its conforming protocols' properties.
563243830Sdim  /// Note, the superclass's properties are not included in the list.
564249423Sdim  virtual void collectPropertiesToImplement(PropertyMap &PM,
565249423Sdim                                            PropertyDeclOrder &PO) const {}
566243830Sdim
567226633Sdim  SourceLocation getAtStartLoc() const { return AtStart; }
568226633Sdim  void setAtStartLoc(SourceLocation Loc) { AtStart = Loc; }
569226633Sdim
570193326Sed  // Marks the end of the container.
571202379Srdivacky  SourceRange getAtEndRange() const {
572202379Srdivacky    return AtEnd;
573202379Srdivacky  }
574202379Srdivacky  void setAtEndRange(SourceRange atEnd) {
575202379Srdivacky    AtEnd = atEnd;
576202379Srdivacky  }
577198092Srdivacky
578234353Sdim  virtual SourceRange getSourceRange() const LLVM_READONLY {
579226633Sdim    return SourceRange(AtStart, getAtEndRange().getEnd());
580198092Srdivacky  }
581198092Srdivacky
582193326Sed  // Implement isa/cast/dyncast/etc.
583203955Srdivacky  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
584203955Srdivacky  static bool classofKind(Kind K) {
585210299Sed    return K >= firstObjCContainer &&
586210299Sed           K <= lastObjCContainer;
587193326Sed  }
588193326Sed
589193326Sed  static DeclContext *castToDeclContext(const ObjCContainerDecl *D) {
590193326Sed    return static_cast<DeclContext *>(const_cast<ObjCContainerDecl*>(D));
591193326Sed  }
592193326Sed  static ObjCContainerDecl *castFromDeclContext(const DeclContext *DC) {
593193326Sed    return static_cast<ObjCContainerDecl *>(const_cast<DeclContext*>(DC));
594193326Sed  }
595193326Sed};
596193326Sed
597239462Sdim/// \brief Represents an ObjC class declaration.
598193326Sed///
599239462Sdim/// For example:
600239462Sdim///
601239462Sdim/// \code
602193326Sed///   // MostPrimitive declares no super class (not particularly useful).
603239462Sdim///   \@interface MostPrimitive
604193326Sed///     // no instance variables or methods.
605239462Sdim///   \@end
606193326Sed///
607198092Srdivacky///   // NSResponder inherits from NSObject & implements NSCoding (a protocol).
608239462Sdim///   \@interface NSResponder : NSObject \<NSCoding>
609193326Sed///   { // instance variables are represented by ObjCIvarDecl.
610193326Sed///     id nextResponder; // nextResponder instance variable.
611193326Sed///   }
612193326Sed///   - (NSResponder *)nextResponder; // return a pointer to NSResponder.
613193326Sed///   - (void)mouseMoved:(NSEvent *)theEvent; // return void, takes a pointer
614239462Sdim///   \@end                                    // to an NSEvent.
615239462Sdim/// \endcode
616193326Sed///
617239462Sdim///   Unlike C/C++, forward class declarations are accomplished with \@class.
618239462Sdim///   Unlike C/C++, \@class allows for a list of classes to be forward declared.
619193326Sed///   Unlike C++, ObjC is a single-rooted class model. In Cocoa, classes
620193326Sed///   typically inherit from NSObject (an exception is NSProxy).
621193326Sed///
622234353Sdimclass ObjCInterfaceDecl : public ObjCContainerDecl
623234353Sdim                        , public Redeclarable<ObjCInterfaceDecl> {
624234353Sdim  virtual void anchor();
625234353Sdim
626193326Sed  /// TypeForDecl - This indicates the Type object that represents this
627193326Sed  /// TypeDecl.  It is a cache maintained by ASTContext::getObjCInterfaceType
628218893Sdim  mutable const Type *TypeForDecl;
629193326Sed  friend class ASTContext;
630234353Sdim
631234353Sdim  struct DefinitionData {
632234353Sdim    /// \brief The definition of this class, for quick access from any
633234353Sdim    /// declaration.
634234353Sdim    ObjCInterfaceDecl *Definition;
635234353Sdim
636234353Sdim    /// Class's super class.
637234353Sdim    ObjCInterfaceDecl *SuperClass;
638198092Srdivacky
639239462Sdim    /// Protocols referenced in the \@interface  declaration
640234353Sdim    ObjCProtocolList ReferencedProtocols;
641198092Srdivacky
642239462Sdim    /// Protocols reference in both the \@interface and class extensions.
643234353Sdim    ObjCList<ObjCProtocolDecl> AllReferencedProtocols;
644198092Srdivacky
645234353Sdim    /// \brief List of categories and class extensions defined for this class.
646234353Sdim    ///
647234353Sdim    /// Categories are stored as a linked list in the AST, since the categories
648234353Sdim    /// and class extensions come long after the initial interface declaration,
649234353Sdim    /// and we avoid dynamically-resized arrays in the AST wherever possible.
650234353Sdim    ObjCCategoryDecl *CategoryList;
651198092Srdivacky
652234353Sdim    /// IvarList - List of all ivars defined by this class; including class
653234353Sdim    /// extensions and implementation. This list is built lazily.
654234353Sdim    ObjCIvarDecl *IvarList;
655193326Sed
656234353Sdim    /// \brief Indicates that the contents of this Objective-C class will be
657234353Sdim    /// completed by the external AST source when required.
658234353Sdim    mutable bool ExternallyCompleted : 1;
659234353Sdim
660249423Sdim    /// \brief Indicates that the ivar cache does not yet include ivars
661249423Sdim    /// declared in the implementation.
662249423Sdim    mutable bool IvarListMissingImplementation : 1;
663249423Sdim
664234353Sdim    /// \brief The location of the superclass, if any.
665234353Sdim    SourceLocation SuperClassLoc;
666234353Sdim
667234353Sdim    /// \brief The location of the last location in this declaration, before
668234353Sdim    /// the properties/methods. For example, this will be the '>', '}', or
669234353Sdim    /// identifier,
670234353Sdim    SourceLocation EndLoc;
671234353Sdim
672234353Sdim    DefinitionData() : Definition(), SuperClass(), CategoryList(), IvarList(),
673249423Sdim                       ExternallyCompleted(),
674249423Sdim                       IvarListMissingImplementation(true) { }
675234353Sdim  };
676234353Sdim
677193326Sed  ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
678234353Sdim                    SourceLocation CLoc, ObjCInterfaceDecl *PrevDecl,
679234353Sdim                    bool isInternal);
680198092Srdivacky
681218893Sdim  void LoadExternalDefinition() const;
682234353Sdim
683234353Sdim  /// \brief Contains a pointer to the data associated with this class,
684234353Sdim  /// which will be NULL if this class has not yet been defined.
685249423Sdim  ///
686249423Sdim  /// The bit indicates when we don't need to check for out-of-date
687249423Sdim  /// declarations. It will be set unless modules are enabled.
688249423Sdim  llvm::PointerIntPair<DefinitionData *, 1, bool> Data;
689234353Sdim
690234353Sdim  DefinitionData &data() const {
691249423Sdim    assert(Data.getPointer() && "Declaration has no definition!");
692249423Sdim    return *Data.getPointer();
693234353Sdim  }
694234353Sdim
695234353Sdim  /// \brief Allocate the definition data for this class.
696234353Sdim  void allocateDefinitionData();
697234353Sdim
698234353Sdim  typedef Redeclarable<ObjCInterfaceDecl> redeclarable_base;
699234353Sdim  virtual ObjCInterfaceDecl *getNextRedeclaration() {
700249423Sdim    return RedeclLink.getNext();
701234353Sdim  }
702234353Sdim  virtual ObjCInterfaceDecl *getPreviousDeclImpl() {
703234353Sdim    return getPreviousDecl();
704234353Sdim  }
705234353Sdim  virtual ObjCInterfaceDecl *getMostRecentDeclImpl() {
706234353Sdim    return getMostRecentDecl();
707234353Sdim  }
708234353Sdim
709193326Sedpublic:
710234353Sdim  static ObjCInterfaceDecl *Create(const ASTContext &C, DeclContext *DC,
711193326Sed                                   SourceLocation atLoc,
712198092Srdivacky                                   IdentifierInfo *Id,
713234353Sdim                                   ObjCInterfaceDecl *PrevDecl,
714193326Sed                                   SourceLocation ClassLoc = SourceLocation(),
715193326Sed                                   bool isInternal = false);
716234353Sdim
717234353Sdim  static ObjCInterfaceDecl *CreateDeserialized(ASTContext &C, unsigned ID);
718234353Sdim
719234353Sdim  virtual SourceRange getSourceRange() const LLVM_READONLY {
720234353Sdim    if (isThisDeclarationADefinition())
721234353Sdim      return ObjCContainerDecl::getSourceRange();
722234353Sdim
723234353Sdim    return SourceRange(getAtStartLoc(), getLocation());
724234353Sdim  }
725234353Sdim
726218893Sdim  /// \brief Indicate that this Objective-C class is complete, but that
727218893Sdim  /// the external AST source will be responsible for filling in its contents
728218893Sdim  /// when a complete class is required.
729218893Sdim  void setExternallyCompleted();
730234353Sdim
731202879Srdivacky  const ObjCProtocolList &getReferencedProtocols() const {
732234353Sdim    assert(hasDefinition() && "Caller did not check for forward reference!");
733234353Sdim    if (data().ExternallyCompleted)
734218893Sdim      LoadExternalDefinition();
735234353Sdim
736234353Sdim    return data().ReferencedProtocols;
737193326Sed  }
738198092Srdivacky
739198092Srdivacky  ObjCImplementationDecl *getImplementation() const;
740198092Srdivacky  void setImplementation(ObjCImplementationDecl *ImplD);
741198092Srdivacky
742193326Sed  ObjCCategoryDecl *FindCategoryDeclaration(IdentifierInfo *CategoryId) const;
743193326Sed
744198092Srdivacky  // Get the local instance/class method declared in a category.
745198092Srdivacky  ObjCMethodDecl *getCategoryInstanceMethod(Selector Sel) const;
746198092Srdivacky  ObjCMethodDecl *getCategoryClassMethod(Selector Sel) const;
747198092Srdivacky  ObjCMethodDecl *getCategoryMethod(Selector Sel, bool isInstance) const {
748198092Srdivacky    return isInstance ? getInstanceMethod(Sel)
749198092Srdivacky                      : getClassMethod(Sel);
750198092Srdivacky  }
751198092Srdivacky
752202879Srdivacky  typedef ObjCProtocolList::iterator protocol_iterator;
753234353Sdim
754212904Sdim  protocol_iterator protocol_begin() const {
755234353Sdim    // FIXME: Should make sure no callers ever do this.
756234353Sdim    if (!hasDefinition())
757234353Sdim      return protocol_iterator();
758234353Sdim
759234353Sdim    if (data().ExternallyCompleted)
760218893Sdim      LoadExternalDefinition();
761218893Sdim
762234353Sdim    return data().ReferencedProtocols.begin();
763212904Sdim  }
764212904Sdim  protocol_iterator protocol_end() const {
765234353Sdim    // FIXME: Should make sure no callers ever do this.
766234353Sdim    if (!hasDefinition())
767234353Sdim      return protocol_iterator();
768234353Sdim
769234353Sdim    if (data().ExternallyCompleted)
770218893Sdim      LoadExternalDefinition();
771218893Sdim
772234353Sdim    return data().ReferencedProtocols.end();
773212904Sdim  }
774212904Sdim
775202879Srdivacky  typedef ObjCProtocolList::loc_iterator protocol_loc_iterator;
776212904Sdim
777234353Sdim  protocol_loc_iterator protocol_loc_begin() const {
778234353Sdim    // FIXME: Should make sure no callers ever do this.
779234353Sdim    if (!hasDefinition())
780234353Sdim      return protocol_loc_iterator();
781234353Sdim
782234353Sdim    if (data().ExternallyCompleted)
783218893Sdim      LoadExternalDefinition();
784218893Sdim
785234353Sdim    return data().ReferencedProtocols.loc_begin();
786202879Srdivacky  }
787212904Sdim
788234353Sdim  protocol_loc_iterator protocol_loc_end() const {
789234353Sdim    // FIXME: Should make sure no callers ever do this.
790234353Sdim    if (!hasDefinition())
791234353Sdim      return protocol_loc_iterator();
792234353Sdim
793234353Sdim    if (data().ExternallyCompleted)
794218893Sdim      LoadExternalDefinition();
795218893Sdim
796234353Sdim    return data().ReferencedProtocols.loc_end();
797202879Srdivacky  }
798234353Sdim
799212904Sdim  typedef ObjCList<ObjCProtocolDecl>::iterator all_protocol_iterator;
800234353Sdim
801212904Sdim  all_protocol_iterator all_referenced_protocol_begin() const {
802234353Sdim    // FIXME: Should make sure no callers ever do this.
803234353Sdim    if (!hasDefinition())
804234353Sdim      return all_protocol_iterator();
805234353Sdim
806234353Sdim    if (data().ExternallyCompleted)
807218893Sdim      LoadExternalDefinition();
808218893Sdim
809234353Sdim    return data().AllReferencedProtocols.empty()
810234353Sdim             ? protocol_begin()
811234353Sdim             : data().AllReferencedProtocols.begin();
812212904Sdim  }
813212904Sdim  all_protocol_iterator all_referenced_protocol_end() const {
814234353Sdim    // FIXME: Should make sure no callers ever do this.
815234353Sdim    if (!hasDefinition())
816234353Sdim      return all_protocol_iterator();
817234353Sdim
818234353Sdim    if (data().ExternallyCompleted)
819218893Sdim      LoadExternalDefinition();
820218893Sdim
821234353Sdim    return data().AllReferencedProtocols.empty()
822234353Sdim             ? protocol_end()
823234353Sdim             : data().AllReferencedProtocols.end();
824212904Sdim  }
825193326Sed
826204643Srdivacky  typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator;
827212904Sdim
828234353Sdim  ivar_iterator ivar_begin() const {
829234353Sdim    if (const ObjCInterfaceDecl *Def = getDefinition())
830234353Sdim      return ivar_iterator(Def->decls_begin());
831234353Sdim
832234353Sdim    // FIXME: Should make sure no callers ever do this.
833234353Sdim    return ivar_iterator();
834234353Sdim  }
835234353Sdim  ivar_iterator ivar_end() const {
836234353Sdim    if (const ObjCInterfaceDecl *Def = getDefinition())
837234353Sdim      return ivar_iterator(Def->decls_end());
838212904Sdim
839234353Sdim    // FIXME: Should make sure no callers ever do this.
840234353Sdim    return ivar_iterator();
841234353Sdim  }
842234353Sdim
843204643Srdivacky  unsigned ivar_size() const {
844204643Srdivacky    return std::distance(ivar_begin(), ivar_end());
845204643Srdivacky  }
846234353Sdim
847204643Srdivacky  bool ivar_empty() const { return ivar_begin() == ivar_end(); }
848234353Sdim
849226633Sdim  ObjCIvarDecl *all_declared_ivar_begin();
850226633Sdim  const ObjCIvarDecl *all_declared_ivar_begin() const {
851226633Sdim    // Even though this modifies IvarList, it's conceptually const:
852226633Sdim    // the ivar chain is essentially a cached property of ObjCInterfaceDecl.
853226633Sdim    return const_cast<ObjCInterfaceDecl *>(this)->all_declared_ivar_begin();
854226633Sdim  }
855234353Sdim  void setIvarList(ObjCIvarDecl *ivar) { data().IvarList = ivar; }
856234353Sdim
857193326Sed  /// setProtocolList - Set the list of protocols that this interface
858193326Sed  /// implements.
859193326Sed  void setProtocolList(ObjCProtocolDecl *const* List, unsigned Num,
860202879Srdivacky                       const SourceLocation *Locs, ASTContext &C) {
861234353Sdim    data().ReferencedProtocols.set(List, Num, Locs, C);
862193326Sed  }
863198092Srdivacky
864198092Srdivacky  /// mergeClassExtensionProtocolList - Merge class extension's protocol list
865198092Srdivacky  /// into the protocol list for this class.
866234353Sdim  void mergeClassExtensionProtocolList(ObjCProtocolDecl *const* List,
867202879Srdivacky                                       unsigned Num,
868202879Srdivacky                                       ASTContext &C);
869198092Srdivacky
870234353Sdim  /// \brief Determine whether this particular declaration of this class is
871234353Sdim  /// actually also a definition.
872234353Sdim  bool isThisDeclarationADefinition() const {
873249423Sdim    return getDefinition() == this;
874234353Sdim  }
875234353Sdim
876234353Sdim  /// \brief Determine whether this class has been defined.
877249423Sdim  bool hasDefinition() const {
878249423Sdim    // If the name of this class is out-of-date, bring it up-to-date, which
879249423Sdim    // might bring in a definition.
880249423Sdim    // Note: a null value indicates that we don't have a definition and that
881249423Sdim    // modules are enabled.
882249423Sdim    if (!Data.getOpaqueValue()) {
883249423Sdim      if (IdentifierInfo *II = getIdentifier()) {
884249423Sdim        if (II->isOutOfDate()) {
885249423Sdim          updateOutOfDate(*II);
886249423Sdim        }
887249423Sdim      }
888249423Sdim    }
889249423Sdim
890249423Sdim    return Data.getPointer();
891249423Sdim  }
892234353Sdim
893234353Sdim  /// \brief Retrieve the definition of this class, or NULL if this class
894239462Sdim  /// has been forward-declared (with \@class) but not yet defined (with
895239462Sdim  /// \@interface).
896234353Sdim  ObjCInterfaceDecl *getDefinition() {
897249423Sdim    return hasDefinition()? Data.getPointer()->Definition : 0;
898234353Sdim  }
899198092Srdivacky
900234353Sdim  /// \brief Retrieve the definition of this class, or NULL if this class
901239462Sdim  /// has been forward-declared (with \@class) but not yet defined (with
902239462Sdim  /// \@interface).
903234353Sdim  const ObjCInterfaceDecl *getDefinition() const {
904249423Sdim    return hasDefinition()? Data.getPointer()->Definition : 0;
905234353Sdim  }
906234353Sdim
907234353Sdim  /// \brief Starts the definition of this Objective-C class, taking it from
908239462Sdim  /// a forward declaration (\@class) to a definition (\@interface).
909234353Sdim  void startDefinition();
910234353Sdim
911234353Sdim  ObjCInterfaceDecl *getSuperClass() const {
912234353Sdim    // FIXME: Should make sure no callers ever do this.
913234353Sdim    if (!hasDefinition())
914234353Sdim      return 0;
915234353Sdim
916234353Sdim    if (data().ExternallyCompleted)
917218893Sdim      LoadExternalDefinition();
918218893Sdim
919234353Sdim    return data().SuperClass;
920218893Sdim  }
921198092Srdivacky
922234353Sdim  void setSuperClass(ObjCInterfaceDecl * superCls) {
923234353Sdim    data().SuperClass =
924234353Sdim      (superCls && superCls->hasDefinition()) ? superCls->getDefinition()
925234353Sdim                                              : superCls;
926234353Sdim  }
927234353Sdim
928249423Sdim  /// \brief Iterator that walks over the list of categories, filtering out
929249423Sdim  /// those that do not meet specific criteria.
930249423Sdim  ///
931249423Sdim  /// This class template is used for the various permutations of category
932249423Sdim  /// and extension iterators.
933249423Sdim  template<bool (*Filter)(ObjCCategoryDecl *)>
934249423Sdim  class filtered_category_iterator {
935249423Sdim    ObjCCategoryDecl *Current;
936249423Sdim
937249423Sdim    void findAcceptableCategory();
938249423Sdim
939249423Sdim  public:
940249423Sdim    typedef ObjCCategoryDecl *      value_type;
941249423Sdim    typedef value_type              reference;
942249423Sdim    typedef value_type              pointer;
943249423Sdim    typedef std::ptrdiff_t          difference_type;
944249423Sdim    typedef std::input_iterator_tag iterator_category;
945249423Sdim
946249423Sdim    filtered_category_iterator() : Current(0) { }
947249423Sdim    explicit filtered_category_iterator(ObjCCategoryDecl *Current)
948249423Sdim      : Current(Current)
949249423Sdim    {
950249423Sdim      findAcceptableCategory();
951249423Sdim    }
952249423Sdim
953249423Sdim    reference operator*() const { return Current; }
954249423Sdim    pointer operator->() const { return Current; }
955249423Sdim
956249423Sdim    filtered_category_iterator &operator++();
957249423Sdim
958249423Sdim    filtered_category_iterator operator++(int) {
959249423Sdim      filtered_category_iterator Tmp = *this;
960249423Sdim      ++(*this);
961249423Sdim      return Tmp;
962249423Sdim    }
963249423Sdim
964249423Sdim    friend bool operator==(filtered_category_iterator X,
965249423Sdim                           filtered_category_iterator Y) {
966249423Sdim      return X.Current == Y.Current;
967249423Sdim    }
968249423Sdim
969249423Sdim    friend bool operator!=(filtered_category_iterator X,
970249423Sdim                           filtered_category_iterator Y) {
971249423Sdim      return X.Current != Y.Current;
972249423Sdim    }
973249423Sdim  };
974249423Sdim
975249423Sdimprivate:
976249423Sdim  /// \brief Test whether the given category is visible.
977249423Sdim  ///
978249423Sdim  /// Used in the \c visible_categories_iterator.
979249423Sdim  static bool isVisibleCategory(ObjCCategoryDecl *Cat);
980249423Sdim
981249423Sdimpublic:
982249423Sdim  /// \brief Iterator that walks over the list of categories and extensions
983249423Sdim  /// that are visible, i.e., not hidden in a non-imported submodule.
984249423Sdim  typedef filtered_category_iterator<isVisibleCategory>
985249423Sdim    visible_categories_iterator;
986249423Sdim
987249423Sdim  /// \brief Retrieve an iterator to the beginning of the visible-categories
988249423Sdim  /// list.
989249423Sdim  visible_categories_iterator visible_categories_begin() const {
990249423Sdim    return visible_categories_iterator(getCategoryListRaw());
991249423Sdim  }
992249423Sdim
993249423Sdim  /// \brief Retrieve an iterator to the end of the visible-categories list.
994249423Sdim  visible_categories_iterator visible_categories_end() const {
995249423Sdim    return visible_categories_iterator();
996249423Sdim  }
997249423Sdim
998249423Sdim  /// \brief Determine whether the visible-categories list is empty.
999249423Sdim  bool visible_categories_empty() const {
1000249423Sdim    return visible_categories_begin() == visible_categories_end();
1001249423Sdim  }
1002249423Sdim
1003249423Sdimprivate:
1004249423Sdim  /// \brief Test whether the given category... is a category.
1005249423Sdim  ///
1006249423Sdim  /// Used in the \c known_categories_iterator.
1007249423Sdim  static bool isKnownCategory(ObjCCategoryDecl *) { return true; }
1008249423Sdim
1009249423Sdimpublic:
1010249423Sdim  /// \brief Iterator that walks over all of the known categories and
1011249423Sdim  /// extensions, including those that are hidden.
1012249423Sdim  typedef filtered_category_iterator<isKnownCategory> known_categories_iterator;
1013249423Sdim
1014249423Sdim  /// \brief Retrieve an iterator to the beginning of the known-categories
1015249423Sdim  /// list.
1016249423Sdim  known_categories_iterator known_categories_begin() const {
1017249423Sdim    return known_categories_iterator(getCategoryListRaw());
1018249423Sdim  }
1019249423Sdim
1020249423Sdim  /// \brief Retrieve an iterator to the end of the known-categories list.
1021249423Sdim  known_categories_iterator known_categories_end() const {
1022249423Sdim    return known_categories_iterator();
1023249423Sdim  }
1024249423Sdim
1025249423Sdim  /// \brief Determine whether the known-categories list is empty.
1026249423Sdim  bool known_categories_empty() const {
1027249423Sdim    return known_categories_begin() == known_categories_end();
1028249423Sdim  }
1029249423Sdim
1030249423Sdimprivate:
1031249423Sdim  /// \brief Test whether the given category is a visible extension.
1032249423Sdim  ///
1033249423Sdim  /// Used in the \c visible_extensions_iterator.
1034249423Sdim  static bool isVisibleExtension(ObjCCategoryDecl *Cat);
1035249423Sdim
1036249423Sdimpublic:
1037249423Sdim  /// \brief Iterator that walks over all of the visible extensions, skipping
1038249423Sdim  /// any that are known but hidden.
1039249423Sdim  typedef filtered_category_iterator<isVisibleExtension>
1040249423Sdim    visible_extensions_iterator;
1041249423Sdim
1042249423Sdim  /// \brief Retrieve an iterator to the beginning of the visible-extensions
1043249423Sdim  /// list.
1044249423Sdim  visible_extensions_iterator visible_extensions_begin() const {
1045249423Sdim    return visible_extensions_iterator(getCategoryListRaw());
1046249423Sdim  }
1047249423Sdim
1048249423Sdim  /// \brief Retrieve an iterator to the end of the visible-extensions list.
1049249423Sdim  visible_extensions_iterator visible_extensions_end() const {
1050249423Sdim    return visible_extensions_iterator();
1051249423Sdim  }
1052249423Sdim
1053249423Sdim  /// \brief Determine whether the visible-extensions list is empty.
1054249423Sdim  bool visible_extensions_empty() const {
1055249423Sdim    return visible_extensions_begin() == visible_extensions_end();
1056249423Sdim  }
1057249423Sdim
1058249423Sdimprivate:
1059249423Sdim  /// \brief Test whether the given category is an extension.
1060249423Sdim  ///
1061249423Sdim  /// Used in the \c known_extensions_iterator.
1062249423Sdim  static bool isKnownExtension(ObjCCategoryDecl *Cat);
1063249423Sdim
1064249423Sdimpublic:
1065249423Sdim  /// \brief Iterator that walks over all of the known extensions.
1066249423Sdim  typedef filtered_category_iterator<isKnownExtension>
1067249423Sdim    known_extensions_iterator;
1068249423Sdim
1069249423Sdim  /// \brief Retrieve an iterator to the beginning of the known-extensions
1070249423Sdim  /// list.
1071249423Sdim  known_extensions_iterator known_extensions_begin() const {
1072249423Sdim    return known_extensions_iterator(getCategoryListRaw());
1073249423Sdim  }
1074249423Sdim
1075249423Sdim  /// \brief Retrieve an iterator to the end of the known-extensions list.
1076249423Sdim  known_extensions_iterator known_extensions_end() const {
1077249423Sdim    return known_extensions_iterator();
1078249423Sdim  }
1079249423Sdim
1080249423Sdim  /// \brief Determine whether the known-extensions list is empty.
1081249423Sdim  bool known_extensions_empty() const {
1082249423Sdim    return known_extensions_begin() == known_extensions_end();
1083249423Sdim  }
1084249423Sdim
1085249423Sdim  /// \brief Retrieve the raw pointer to the start of the category/extension
1086249423Sdim  /// list.
1087249423Sdim  ObjCCategoryDecl* getCategoryListRaw() const {
1088234353Sdim    // FIXME: Should make sure no callers ever do this.
1089234353Sdim    if (!hasDefinition())
1090234353Sdim      return 0;
1091234353Sdim
1092234353Sdim    if (data().ExternallyCompleted)
1093218893Sdim      LoadExternalDefinition();
1094218893Sdim
1095234353Sdim    return data().CategoryList;
1096218893Sdim  }
1097234353Sdim
1098249423Sdim  /// \brief Set the raw pointer to the start of the category/extension
1099249423Sdim  /// list.
1100249423Sdim  void setCategoryListRaw(ObjCCategoryDecl *category) {
1101234353Sdim    data().CategoryList = category;
1102193326Sed  }
1103234353Sdim
1104205219Srdivacky  ObjCPropertyDecl
1105205219Srdivacky    *FindPropertyVisibleInPrimaryClass(IdentifierInfo *PropertyId) const;
1106205219Srdivacky
1107249423Sdim  virtual void collectPropertiesToImplement(PropertyMap &PM,
1108249423Sdim                                            PropertyDeclOrder &PO) const;
1109243830Sdim
1110193326Sed  /// isSuperClassOf - Return true if this class is the specified class or is a
1111193326Sed  /// super class of the specified interface class.
1112193326Sed  bool isSuperClassOf(const ObjCInterfaceDecl *I) const {
1113193326Sed    // If RHS is derived from LHS it is OK; else it is not OK.
1114193326Sed    while (I != NULL) {
1115234353Sdim      if (declaresSameEntity(this, I))
1116193326Sed        return true;
1117234353Sdim
1118193326Sed      I = I->getSuperClass();
1119193326Sed    }
1120193326Sed    return false;
1121193326Sed  }
1122198092Srdivacky
1123224145Sdim  /// isArcWeakrefUnavailable - Checks for a class or one of its super classes
1124224145Sdim  /// to be incompatible with __weak references. Returns true if it is.
1125249423Sdim  bool isArcWeakrefUnavailable() const;
1126224145Sdim
1127234353Sdim  /// isObjCRequiresPropertyDefs - Checks that a class or one of its super
1128239462Sdim  /// classes must not be auto-synthesized. Returns class decl. if it must not
1129239462Sdim  /// be; 0, otherwise.
1130249423Sdim  const ObjCInterfaceDecl *isObjCRequiresPropertyDefs() const;
1131234353Sdim
1132195341Sed  ObjCIvarDecl *lookupInstanceVariable(IdentifierInfo *IVarName,
1133193326Sed                                       ObjCInterfaceDecl *&ClassDeclared);
1134195341Sed  ObjCIvarDecl *lookupInstanceVariable(IdentifierInfo *IVarName) {
1135193326Sed    ObjCInterfaceDecl *ClassDeclared;
1136195341Sed    return lookupInstanceVariable(IVarName, ClassDeclared);
1137193326Sed  }
1138193326Sed
1139263508Sdim  ObjCProtocolDecl *lookupNestedProtocol(IdentifierInfo *Name);
1140263508Sdim
1141193326Sed  // Lookup a method. First, we search locally. If a method isn't
1142193326Sed  // found, we search referenced protocols and class categories.
1143234353Sdim  ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance,
1144251662Sdim                               bool shallowCategoryLookup= false,
1145251662Sdim                               const ObjCCategoryDecl *C= 0) const;
1146234353Sdim  ObjCMethodDecl *lookupInstanceMethod(Selector Sel,
1147234353Sdim                            bool shallowCategoryLookup = false) const {
1148234353Sdim    return lookupMethod(Sel, true/*isInstance*/, shallowCategoryLookup);
1149198092Srdivacky  }
1150234353Sdim  ObjCMethodDecl *lookupClassMethod(Selector Sel,
1151234353Sdim                     bool shallowCategoryLookup = false) const {
1152234353Sdim    return lookupMethod(Sel, false/*isInstance*/, shallowCategoryLookup);
1153198092Srdivacky  }
1154193326Sed  ObjCInterfaceDecl *lookupInheritedClass(const IdentifierInfo *ICName);
1155234353Sdim
1156239462Sdim  /// \brief Lookup a method in the classes implementation hierarchy.
1157239462Sdim  ObjCMethodDecl *lookupPrivateMethod(const Selector &Sel,
1158239462Sdim                                      bool Instance=true) const;
1159193326Sed
1160239462Sdim  ObjCMethodDecl *lookupPrivateClassMethod(const Selector &Sel) {
1161239462Sdim    return lookupPrivateMethod(Sel, false);
1162239462Sdim  }
1163239462Sdim
1164251662Sdim  /// \brief Lookup a setter or getter in the class hierarchy,
1165251662Sdim  /// including in all categories except for category passed
1166251662Sdim  /// as argument.
1167251662Sdim  ObjCMethodDecl *lookupPropertyAccessor(const Selector Sel,
1168251662Sdim                                         const ObjCCategoryDecl *Cat) const {
1169251662Sdim    return lookupMethod(Sel, true/*isInstance*/,
1170251662Sdim                        false/*shallowCategoryLookup*/, Cat);
1171251662Sdim  }
1172251662Sdim
1173234353Sdim  SourceLocation getEndOfDefinitionLoc() const {
1174234353Sdim    if (!hasDefinition())
1175234353Sdim      return getLocation();
1176234353Sdim
1177234353Sdim    return data().EndLoc;
1178234353Sdim  }
1179234353Sdim
1180234353Sdim  void setEndOfDefinitionLoc(SourceLocation LE) { data().EndLoc = LE; }
1181198092Srdivacky
1182234353Sdim  void setSuperClassLoc(SourceLocation Loc) { data().SuperClassLoc = Loc; }
1183234353Sdim  SourceLocation getSuperClassLoc() const { return data().SuperClassLoc; }
1184198092Srdivacky
1185193326Sed  /// isImplicitInterfaceDecl - check that this is an implicitly declared
1186239462Sdim  /// ObjCInterfaceDecl node. This is for legacy objective-c \@implementation
1187239462Sdim  /// declaration without an \@interface declaration.
1188234353Sdim  bool isImplicitInterfaceDecl() const {
1189249423Sdim    return hasDefinition() ? data().Definition->isImplicit() : isImplicit();
1190234353Sdim  }
1191198092Srdivacky
1192198092Srdivacky  /// ClassImplementsProtocol - Checks that 'lProto' protocol
1193198092Srdivacky  /// has been implemented in IDecl class, its super class or categories (if
1194198092Srdivacky  /// lookupCategory is true).
1195198092Srdivacky  bool ClassImplementsProtocol(ObjCProtocolDecl *lProto,
1196198092Srdivacky                               bool lookupCategory,
1197198092Srdivacky                               bool RHSIsQualifiedID = false);
1198198092Srdivacky
1199234353Sdim  typedef redeclarable_base::redecl_iterator redecl_iterator;
1200234353Sdim  using redeclarable_base::redecls_begin;
1201234353Sdim  using redeclarable_base::redecls_end;
1202234353Sdim  using redeclarable_base::getPreviousDecl;
1203234353Sdim  using redeclarable_base::getMostRecentDecl;
1204263508Sdim  using redeclarable_base::isFirstDecl;
1205234353Sdim
1206234353Sdim  /// Retrieves the canonical declaration of this Objective-C class.
1207263508Sdim  ObjCInterfaceDecl *getCanonicalDecl() { return getFirstDecl(); }
1208263508Sdim  const ObjCInterfaceDecl *getCanonicalDecl() const { return getFirstDecl(); }
1209234353Sdim
1210193326Sed  // Low-level accessor
1211218893Sdim  const Type *getTypeForDecl() const { return TypeForDecl; }
1212218893Sdim  void setTypeForDecl(const Type *TD) const { TypeForDecl = TD; }
1213193326Sed
1214203955Srdivacky  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
1215203955Srdivacky  static bool classofKind(Kind K) { return K == ObjCInterface; }
1216212904Sdim
1217234353Sdim  friend class ASTReader;
1218212904Sdim  friend class ASTDeclReader;
1219212904Sdim  friend class ASTDeclWriter;
1220193326Sed};
1221193326Sed
1222193326Sed/// ObjCIvarDecl - Represents an ObjC instance variable. In general, ObjC
1223193326Sed/// instance variables are identical to C. The only exception is Objective-C
1224193326Sed/// supports C++ style access control. For example:
1225193326Sed///
1226239462Sdim///   \@interface IvarExample : NSObject
1227193326Sed///   {
1228193326Sed///     id defaultToProtected;
1229239462Sdim///   \@public:
1230193326Sed///     id canBePublic; // same as C++.
1231239462Sdim///   \@protected:
1232193326Sed///     id canBeProtected; // same as C++.
1233239462Sdim///   \@package:
1234193326Sed///     id canBePackage; // framework visibility (not available in C++).
1235193326Sed///   }
1236193326Sed///
1237193326Sedclass ObjCIvarDecl : public FieldDecl {
1238234353Sdim  virtual void anchor();
1239234353Sdim
1240193326Sedpublic:
1241193326Sed  enum AccessControl {
1242193326Sed    None, Private, Protected, Public, Package
1243193326Sed  };
1244198092Srdivacky
1245193326Sedprivate:
1246221345Sdim  ObjCIvarDecl(ObjCContainerDecl *DC, SourceLocation StartLoc,
1247221345Sdim               SourceLocation IdLoc, IdentifierInfo *Id,
1248212904Sdim               QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW,
1249263508Sdim               bool synthesized,
1250263508Sdim               bool backingIvarReferencedInAccessor)
1251221345Sdim    : FieldDecl(ObjCIvar, DC, StartLoc, IdLoc, Id, T, TInfo, BW,
1252239462Sdim                /*Mutable=*/false, /*HasInit=*/ICIS_NoInit),
1253263508Sdim      NextIvar(0), DeclAccess(ac), Synthesized(synthesized),
1254263508Sdim      BackingIvarReferencedInAccessor(backingIvarReferencedInAccessor) {}
1255198092Srdivacky
1256193326Sedpublic:
1257206125Srdivacky  static ObjCIvarDecl *Create(ASTContext &C, ObjCContainerDecl *DC,
1258221345Sdim                              SourceLocation StartLoc, SourceLocation IdLoc,
1259221345Sdim                              IdentifierInfo *Id, QualType T,
1260200583Srdivacky                              TypeSourceInfo *TInfo,
1261212904Sdim                              AccessControl ac, Expr *BW = NULL,
1262263508Sdim                              bool synthesized=false,
1263263508Sdim                              bool backingIvarReferencedInAccessor=false);
1264198092Srdivacky
1265234353Sdim  static ObjCIvarDecl *CreateDeserialized(ASTContext &C, unsigned ID);
1266234353Sdim
1267206125Srdivacky  /// \brief Return the class interface that this ivar is logically contained
1268206125Srdivacky  /// in; this is either the interface where the ivar was declared, or the
1269206125Srdivacky  /// interface the ivar is conceptually a part of in the case of synthesized
1270206125Srdivacky  /// ivars.
1271206125Srdivacky  const ObjCInterfaceDecl *getContainingInterface() const;
1272234353Sdim
1273212904Sdim  ObjCIvarDecl *getNextIvar() { return NextIvar; }
1274226633Sdim  const ObjCIvarDecl *getNextIvar() const { return NextIvar; }
1275212904Sdim  void setNextIvar(ObjCIvarDecl *ivar) { NextIvar = ivar; }
1276206125Srdivacky
1277193326Sed  void setAccessControl(AccessControl ac) { DeclAccess = ac; }
1278193326Sed
1279193326Sed  AccessControl getAccessControl() const { return AccessControl(DeclAccess); }
1280193326Sed
1281193326Sed  AccessControl getCanonicalAccessControl() const {
1282193326Sed    return DeclAccess == None ? Protected : AccessControl(DeclAccess);
1283193326Sed  }
1284198092Srdivacky
1285263508Sdim  void setBackingIvarReferencedInAccessor(bool val) {
1286263508Sdim    BackingIvarReferencedInAccessor = val;
1287263508Sdim  }
1288263508Sdim  bool getBackingIvarReferencedInAccessor() const {
1289263508Sdim    return BackingIvarReferencedInAccessor;
1290263508Sdim  }
1291263508Sdim
1292212904Sdim  void setSynthesize(bool synth) { Synthesized = synth; }
1293212904Sdim  bool getSynthesize() const { return Synthesized; }
1294234353Sdim
1295193326Sed  // Implement isa/cast/dyncast/etc.
1296203955Srdivacky  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
1297203955Srdivacky  static bool classofKind(Kind K) { return K == ObjCIvar; }
1298193326Sedprivate:
1299234353Sdim  /// NextIvar - Next Ivar in the list of ivars declared in class; class's
1300212904Sdim  /// extensions and class's implementation
1301212904Sdim  ObjCIvarDecl *NextIvar;
1302234353Sdim
1303193326Sed  // NOTE: VC++ treats enums as signed, avoid using the AccessControl enum
1304193326Sed  unsigned DeclAccess : 3;
1305212904Sdim  unsigned Synthesized : 1;
1306263508Sdim  unsigned BackingIvarReferencedInAccessor : 1;
1307193326Sed};
1308193326Sed
1309198092Srdivacky
1310239462Sdim/// \brief Represents a field declaration created by an \@defs(...).
1311193326Sedclass ObjCAtDefsFieldDecl : public FieldDecl {
1312234353Sdim  virtual void anchor();
1313221345Sdim  ObjCAtDefsFieldDecl(DeclContext *DC, SourceLocation StartLoc,
1314221345Sdim                      SourceLocation IdLoc, IdentifierInfo *Id,
1315193326Sed                      QualType T, Expr *BW)
1316221345Sdim    : FieldDecl(ObjCAtDefsField, DC, StartLoc, IdLoc, Id, T,
1317200583Srdivacky                /*TInfo=*/0, // FIXME: Do ObjCAtDefs have declarators ?
1318239462Sdim                BW, /*Mutable=*/false, /*HasInit=*/ICIS_NoInit) {}
1319198092Srdivacky
1320193326Sedpublic:
1321193326Sed  static ObjCAtDefsFieldDecl *Create(ASTContext &C, DeclContext *DC,
1322221345Sdim                                     SourceLocation StartLoc,
1323221345Sdim                                     SourceLocation IdLoc, IdentifierInfo *Id,
1324221345Sdim                                     QualType T, Expr *BW);
1325198092Srdivacky
1326234353Sdim  static ObjCAtDefsFieldDecl *CreateDeserialized(ASTContext &C, unsigned ID);
1327234353Sdim
1328193326Sed  // Implement isa/cast/dyncast/etc.
1329203955Srdivacky  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
1330203955Srdivacky  static bool classofKind(Kind K) { return K == ObjCAtDefsField; }
1331193326Sed};
1332193326Sed
1333239462Sdim/// \brief Represents an Objective-C protocol declaration.
1334193326Sed///
1335239462Sdim/// Objective-C protocols declare a pure abstract type (i.e., no instance
1336239462Sdim/// variables are permitted).  Protocols originally drew inspiration from
1337239462Sdim/// C++ pure virtual functions (a C++ feature with nice semantics and lousy
1338239462Sdim/// syntax:-). Here is an example:
1339239462Sdim///
1340239462Sdim/// \code
1341239462Sdim/// \@protocol NSDraggingInfo <refproto1, refproto2>
1342193326Sed/// - (NSWindow *)draggingDestinationWindow;
1343193326Sed/// - (NSImage *)draggedImage;
1344239462Sdim/// \@end
1345239462Sdim/// \endcode
1346193326Sed///
1347193326Sed/// This says that NSDraggingInfo requires two methods and requires everything
1348193326Sed/// that the two "referenced protocols" 'refproto1' and 'refproto2' require as
1349193326Sed/// well.
1350193326Sed///
1351239462Sdim/// \code
1352239462Sdim/// \@interface ImplementsNSDraggingInfo : NSObject \<NSDraggingInfo>
1353239462Sdim/// \@end
1354239462Sdim/// \endcode
1355193326Sed///
1356193326Sed/// ObjC protocols inspired Java interfaces. Unlike Java, ObjC classes and
1357193326Sed/// protocols are in distinct namespaces. For example, Cocoa defines both
1358198092Srdivacky/// an NSObject protocol and class (which isn't allowed in Java). As a result,
1359193326Sed/// protocols are referenced using angle brackets as follows:
1360193326Sed///
1361239462Sdim/// id \<NSDraggingInfo> anyObjectThatImplementsNSDraggingInfo;
1362193326Sed///
1363234353Sdimclass ObjCProtocolDecl : public ObjCContainerDecl,
1364234353Sdim                         public Redeclarable<ObjCProtocolDecl> {
1365234353Sdim  virtual void anchor();
1366198092Srdivacky
1367234353Sdim  struct DefinitionData {
1368234353Sdim    // \brief The declaration that defines this protocol.
1369234353Sdim    ObjCProtocolDecl *Definition;
1370198092Srdivacky
1371234353Sdim    /// \brief Referenced protocols
1372234353Sdim    ObjCProtocolList ReferencedProtocols;
1373234353Sdim  };
1374198092Srdivacky
1375249423Sdim  /// \brief Contains a pointer to the data associated with this class,
1376249423Sdim  /// which will be NULL if this class has not yet been defined.
1377249423Sdim  ///
1378249423Sdim  /// The bit indicates when we don't need to check for out-of-date
1379249423Sdim  /// declarations. It will be set unless modules are enabled.
1380249423Sdim  llvm::PointerIntPair<DefinitionData *, 1, bool> Data;
1381249423Sdim
1382234353Sdim  DefinitionData &data() const {
1383249423Sdim    assert(Data.getPointer() && "Objective-C protocol has no definition!");
1384249423Sdim    return *Data.getPointer();
1385234353Sdim  }
1386234353Sdim
1387226633Sdim  ObjCProtocolDecl(DeclContext *DC, IdentifierInfo *Id,
1388234353Sdim                   SourceLocation nameLoc, SourceLocation atStartLoc,
1389234353Sdim                   ObjCProtocolDecl *PrevDecl);
1390234353Sdim
1391234353Sdim  void allocateDefinitionData();
1392234353Sdim
1393234353Sdim  typedef Redeclarable<ObjCProtocolDecl> redeclarable_base;
1394234353Sdim  virtual ObjCProtocolDecl *getNextRedeclaration() {
1395234353Sdim    return RedeclLink.getNext();
1396193326Sed  }
1397234353Sdim  virtual ObjCProtocolDecl *getPreviousDeclImpl() {
1398234353Sdim    return getPreviousDecl();
1399234353Sdim  }
1400234353Sdim  virtual ObjCProtocolDecl *getMostRecentDeclImpl() {
1401234353Sdim    return getMostRecentDecl();
1402234353Sdim  }
1403249423Sdim
1404193326Sedpublic:
1405198092Srdivacky  static ObjCProtocolDecl *Create(ASTContext &C, DeclContext *DC,
1406226633Sdim                                  IdentifierInfo *Id,
1407226633Sdim                                  SourceLocation nameLoc,
1408234353Sdim                                  SourceLocation atStartLoc,
1409234353Sdim                                  ObjCProtocolDecl *PrevDecl);
1410193326Sed
1411234353Sdim  static ObjCProtocolDecl *CreateDeserialized(ASTContext &C, unsigned ID);
1412234353Sdim
1413202879Srdivacky  const ObjCProtocolList &getReferencedProtocols() const {
1414234353Sdim    assert(hasDefinition() && "No definition available!");
1415234353Sdim    return data().ReferencedProtocols;
1416193326Sed  }
1417202879Srdivacky  typedef ObjCProtocolList::iterator protocol_iterator;
1418234353Sdim  protocol_iterator protocol_begin() const {
1419234353Sdim    if (!hasDefinition())
1420234353Sdim      return protocol_iterator();
1421234353Sdim
1422234353Sdim    return data().ReferencedProtocols.begin();
1423234353Sdim  }
1424234353Sdim  protocol_iterator protocol_end() const {
1425234353Sdim    if (!hasDefinition())
1426234353Sdim      return protocol_iterator();
1427234353Sdim
1428234353Sdim    return data().ReferencedProtocols.end();
1429234353Sdim  }
1430202879Srdivacky  typedef ObjCProtocolList::loc_iterator protocol_loc_iterator;
1431234353Sdim  protocol_loc_iterator protocol_loc_begin() const {
1432234353Sdim    if (!hasDefinition())
1433234353Sdim      return protocol_loc_iterator();
1434234353Sdim
1435234353Sdim    return data().ReferencedProtocols.loc_begin();
1436202879Srdivacky  }
1437234353Sdim  protocol_loc_iterator protocol_loc_end() const {
1438234353Sdim    if (!hasDefinition())
1439234353Sdim      return protocol_loc_iterator();
1440234353Sdim
1441234353Sdim    return data().ReferencedProtocols.loc_end();
1442202879Srdivacky  }
1443234353Sdim  unsigned protocol_size() const {
1444234353Sdim    if (!hasDefinition())
1445234353Sdim      return 0;
1446234353Sdim
1447234353Sdim    return data().ReferencedProtocols.size();
1448234353Sdim  }
1449198092Srdivacky
1450193326Sed  /// setProtocolList - Set the list of protocols that this interface
1451193326Sed  /// implements.
1452193326Sed  void setProtocolList(ObjCProtocolDecl *const*List, unsigned Num,
1453202879Srdivacky                       const SourceLocation *Locs, ASTContext &C) {
1454249423Sdim    assert(hasDefinition() && "Protocol is not defined");
1455234353Sdim    data().ReferencedProtocols.set(List, Num, Locs, C);
1456193326Sed  }
1457198092Srdivacky
1458193326Sed  ObjCProtocolDecl *lookupProtocolNamed(IdentifierInfo *PName);
1459198092Srdivacky
1460193326Sed  // Lookup a method. First, we search locally. If a method isn't
1461193326Sed  // found, we search referenced protocols and class categories.
1462198092Srdivacky  ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance) const;
1463198092Srdivacky  ObjCMethodDecl *lookupInstanceMethod(Selector Sel) const {
1464198092Srdivacky    return lookupMethod(Sel, true/*isInstance*/);
1465198092Srdivacky  }
1466198092Srdivacky  ObjCMethodDecl *lookupClassMethod(Selector Sel) const {
1467198092Srdivacky    return lookupMethod(Sel, false/*isInstance*/);
1468198092Srdivacky  }
1469193326Sed
1470234353Sdim  /// \brief Determine whether this protocol has a definition.
1471249423Sdim  bool hasDefinition() const {
1472249423Sdim    // If the name of this protocol is out-of-date, bring it up-to-date, which
1473249423Sdim    // might bring in a definition.
1474249423Sdim    // Note: a null value indicates that we don't have a definition and that
1475249423Sdim    // modules are enabled.
1476249423Sdim    if (!Data.getOpaqueValue()) {
1477249423Sdim      if (IdentifierInfo *II = getIdentifier()) {
1478249423Sdim        if (II->isOutOfDate()) {
1479249423Sdim          updateOutOfDate(*II);
1480249423Sdim        }
1481249423Sdim      }
1482249423Sdim    }
1483198092Srdivacky
1484249423Sdim    return Data.getPointer();
1485249423Sdim  }
1486249423Sdim
1487234353Sdim  /// \brief Retrieve the definition of this protocol, if any.
1488234353Sdim  ObjCProtocolDecl *getDefinition() {
1489249423Sdim    return hasDefinition()? Data.getPointer()->Definition : 0;
1490234353Sdim  }
1491198092Srdivacky
1492234353Sdim  /// \brief Retrieve the definition of this protocol, if any.
1493234353Sdim  const ObjCProtocolDecl *getDefinition() const {
1494249423Sdim    return hasDefinition()? Data.getPointer()->Definition : 0;
1495234353Sdim  }
1496198092Srdivacky
1497234353Sdim  /// \brief Determine whether this particular declaration is also the
1498234353Sdim  /// definition.
1499234353Sdim  bool isThisDeclarationADefinition() const {
1500234353Sdim    return getDefinition() == this;
1501234353Sdim  }
1502199482Srdivacky
1503234353Sdim  /// \brief Starts the definition of this Objective-C protocol.
1504234353Sdim  void startDefinition();
1505198092Srdivacky
1506234353Sdim  virtual SourceRange getSourceRange() const LLVM_READONLY {
1507234353Sdim    if (isThisDeclarationADefinition())
1508234353Sdim      return ObjCContainerDecl::getSourceRange();
1509234353Sdim
1510234353Sdim    return SourceRange(getAtStartLoc(), getLocation());
1511202879Srdivacky  }
1512234353Sdim
1513234353Sdim  typedef redeclarable_base::redecl_iterator redecl_iterator;
1514234353Sdim  using redeclarable_base::redecls_begin;
1515234353Sdim  using redeclarable_base::redecls_end;
1516234353Sdim  using redeclarable_base::getPreviousDecl;
1517234353Sdim  using redeclarable_base::getMostRecentDecl;
1518263508Sdim  using redeclarable_base::isFirstDecl;
1519202879Srdivacky
1520234353Sdim  /// Retrieves the canonical declaration of this Objective-C protocol.
1521263508Sdim  ObjCProtocolDecl *getCanonicalDecl() { return getFirstDecl(); }
1522263508Sdim  const ObjCProtocolDecl *getCanonicalDecl() const { return getFirstDecl(); }
1523202879Srdivacky
1524249423Sdim  virtual void collectPropertiesToImplement(PropertyMap &PM,
1525249423Sdim                                            PropertyDeclOrder &PO) const;
1526263508Sdim
1527263508Sdimvoid collectInheritedProtocolProperties(const ObjCPropertyDecl *Property,
1528263508Sdim                                        ProtocolPropertyMap &PM) const;
1529243830Sdim
1530234353Sdim  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
1531234353Sdim  static bool classofKind(Kind K) { return K == ObjCProtocol; }
1532193326Sed
1533234353Sdim  friend class ASTReader;
1534234353Sdim  friend class ASTDeclReader;
1535234353Sdim  friend class ASTDeclWriter;
1536193326Sed};
1537193326Sed
1538193326Sed/// ObjCCategoryDecl - Represents a category declaration. A category allows
1539193326Sed/// you to add methods to an existing class (without subclassing or modifying
1540198092Srdivacky/// the original class interface or implementation:-). Categories don't allow
1541193326Sed/// you to add instance data. The following example adds "myMethod" to all
1542193326Sed/// NSView's within a process:
1543193326Sed///
1544239462Sdim/// \@interface NSView (MyViewMethods)
1545193326Sed/// - myMethod;
1546239462Sdim/// \@end
1547193326Sed///
1548199512Srdivacky/// Categories also allow you to split the implementation of a class across
1549193326Sed/// several files (a feature more naturally supported in C++).
1550193326Sed///
1551193326Sed/// Categories were originally inspired by dynamic languages such as Common
1552198092Srdivacky/// Lisp and Smalltalk.  More traditional class-based languages (C++, Java)
1553193326Sed/// don't support this level of dynamism, which is both powerful and dangerous.
1554193326Sed///
1555193326Sedclass ObjCCategoryDecl : public ObjCContainerDecl {
1556234353Sdim  virtual void anchor();
1557234353Sdim
1558193326Sed  /// Interface belonging to this category
1559193326Sed  ObjCInterfaceDecl *ClassInterface;
1560198092Srdivacky
1561193326Sed  /// referenced protocols in this category.
1562202879Srdivacky  ObjCProtocolList ReferencedProtocols;
1563198092Srdivacky
1564193326Sed  /// Next category belonging to this class.
1565193326Sed  /// FIXME: this should not be a singly-linked list.  Move storage elsewhere.
1566193326Sed  ObjCCategoryDecl *NextClassCategory;
1567198092Srdivacky
1568202879Srdivacky  /// \brief The location of the category name in this declaration.
1569202879Srdivacky  SourceLocation CategoryNameLoc;
1570202879Srdivacky
1571234353Sdim  /// class extension may have private ivars.
1572234353Sdim  SourceLocation IvarLBraceLoc;
1573234353Sdim  SourceLocation IvarRBraceLoc;
1574234353Sdim
1575234353Sdim  ObjCCategoryDecl(DeclContext *DC, SourceLocation AtLoc,
1576202879Srdivacky                   SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc,
1577234353Sdim                   IdentifierInfo *Id, ObjCInterfaceDecl *IDecl,
1578234353Sdim                   SourceLocation IvarLBraceLoc=SourceLocation(),
1579234353Sdim                   SourceLocation IvarRBraceLoc=SourceLocation())
1580226633Sdim    : ObjCContainerDecl(ObjCCategory, DC, Id, ClassNameLoc, AtLoc),
1581239462Sdim      ClassInterface(IDecl), NextClassCategory(0),
1582234353Sdim      CategoryNameLoc(CategoryNameLoc),
1583234353Sdim      IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc) {
1584193326Sed  }
1585249423Sdim
1586193326Sedpublic:
1587198092Srdivacky
1588193326Sed  static ObjCCategoryDecl *Create(ASTContext &C, DeclContext *DC,
1589234353Sdim                                  SourceLocation AtLoc,
1590202879Srdivacky                                  SourceLocation ClassNameLoc,
1591202879Srdivacky                                  SourceLocation CategoryNameLoc,
1592226633Sdim                                  IdentifierInfo *Id,
1593234353Sdim                                  ObjCInterfaceDecl *IDecl,
1594234353Sdim                                  SourceLocation IvarLBraceLoc=SourceLocation(),
1595234353Sdim                                  SourceLocation IvarRBraceLoc=SourceLocation());
1596234353Sdim  static ObjCCategoryDecl *CreateDeserialized(ASTContext &C, unsigned ID);
1597198092Srdivacky
1598193326Sed  ObjCInterfaceDecl *getClassInterface() { return ClassInterface; }
1599193326Sed  const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; }
1600198092Srdivacky
1601198092Srdivacky  ObjCCategoryImplDecl *getImplementation() const;
1602198092Srdivacky  void setImplementation(ObjCCategoryImplDecl *ImplD);
1603198092Srdivacky
1604193326Sed  /// setProtocolList - Set the list of protocols that this interface
1605193326Sed  /// implements.
1606193326Sed  void setProtocolList(ObjCProtocolDecl *const*List, unsigned Num,
1607202879Srdivacky                       const SourceLocation *Locs, ASTContext &C) {
1608202879Srdivacky    ReferencedProtocols.set(List, Num, Locs, C);
1609193326Sed  }
1610198092Srdivacky
1611202879Srdivacky  const ObjCProtocolList &getReferencedProtocols() const {
1612193326Sed    return ReferencedProtocols;
1613193326Sed  }
1614198092Srdivacky
1615202879Srdivacky  typedef ObjCProtocolList::iterator protocol_iterator;
1616193326Sed  protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();}
1617193326Sed  protocol_iterator protocol_end() const { return ReferencedProtocols.end(); }
1618193326Sed  unsigned protocol_size() const { return ReferencedProtocols.size(); }
1619202879Srdivacky  typedef ObjCProtocolList::loc_iterator protocol_loc_iterator;
1620234353Sdim  protocol_loc_iterator protocol_loc_begin() const {
1621234353Sdim    return ReferencedProtocols.loc_begin();
1622202879Srdivacky  }
1623234353Sdim  protocol_loc_iterator protocol_loc_end() const {
1624234353Sdim    return ReferencedProtocols.loc_end();
1625202879Srdivacky  }
1626198092Srdivacky
1627193326Sed  ObjCCategoryDecl *getNextClassCategory() const { return NextClassCategory; }
1628198092Srdivacky
1629249423Sdim  /// \brief Retrieve the pointer to the next stored category (or extension),
1630249423Sdim  /// which may be hidden.
1631249423Sdim  ObjCCategoryDecl *getNextClassCategoryRaw() const {
1632249423Sdim    return NextClassCategory;
1633249423Sdim  }
1634249423Sdim
1635203955Srdivacky  bool IsClassExtension() const { return getIdentifier() == 0; }
1636234353Sdim
1637204643Srdivacky  typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator;
1638204643Srdivacky  ivar_iterator ivar_begin() const {
1639204643Srdivacky    return ivar_iterator(decls_begin());
1640204643Srdivacky  }
1641204643Srdivacky  ivar_iterator ivar_end() const {
1642204643Srdivacky    return ivar_iterator(decls_end());
1643204643Srdivacky  }
1644204643Srdivacky  unsigned ivar_size() const {
1645204643Srdivacky    return std::distance(ivar_begin(), ivar_end());
1646204643Srdivacky  }
1647204643Srdivacky  bool ivar_empty() const {
1648204643Srdivacky    return ivar_begin() == ivar_end();
1649204643Srdivacky  }
1650202879Srdivacky
1651202879Srdivacky  SourceLocation getCategoryNameLoc() const { return CategoryNameLoc; }
1652202879Srdivacky  void setCategoryNameLoc(SourceLocation Loc) { CategoryNameLoc = Loc; }
1653234353Sdim
1654234353Sdim  void setIvarLBraceLoc(SourceLocation Loc) { IvarLBraceLoc = Loc; }
1655234353Sdim  SourceLocation getIvarLBraceLoc() const { return IvarLBraceLoc; }
1656234353Sdim  void setIvarRBraceLoc(SourceLocation Loc) { IvarRBraceLoc = Loc; }
1657234353Sdim  SourceLocation getIvarRBraceLoc() const { return IvarRBraceLoc; }
1658202879Srdivacky
1659203955Srdivacky  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
1660203955Srdivacky  static bool classofKind(Kind K) { return K == ObjCCategory; }
1661226633Sdim
1662226633Sdim  friend class ASTDeclReader;
1663226633Sdim  friend class ASTDeclWriter;
1664193326Sed};
1665193326Sed
1666198092Srdivackyclass ObjCImplDecl : public ObjCContainerDecl {
1667234353Sdim  virtual void anchor();
1668234353Sdim
1669198893Srdivacky  /// Class interface for this class/category implementation
1670193326Sed  ObjCInterfaceDecl *ClassInterface;
1671198092Srdivacky
1672193326Sedprotected:
1673226633Sdim  ObjCImplDecl(Kind DK, DeclContext *DC,
1674226633Sdim               ObjCInterfaceDecl *classInterface,
1675226633Sdim               SourceLocation nameLoc, SourceLocation atStartLoc)
1676226633Sdim    : ObjCContainerDecl(DK, DC,
1677226633Sdim                        classInterface? classInterface->getIdentifier() : 0,
1678226633Sdim                        nameLoc, atStartLoc),
1679198092Srdivacky      ClassInterface(classInterface) {}
1680198092Srdivacky
1681193326Sedpublic:
1682193326Sed  const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; }
1683193326Sed  ObjCInterfaceDecl *getClassInterface() { return ClassInterface; }
1684198092Srdivacky  void setClassInterface(ObjCInterfaceDecl *IFace);
1685193326Sed
1686198092Srdivacky  void addInstanceMethod(ObjCMethodDecl *method) {
1687193326Sed    // FIXME: Context should be set correctly before we get here.
1688193326Sed    method->setLexicalDeclContext(this);
1689198092Srdivacky    addDecl(method);
1690193326Sed  }
1691198092Srdivacky  void addClassMethod(ObjCMethodDecl *method) {
1692193326Sed    // FIXME: Context should be set correctly before we get here.
1693193326Sed    method->setLexicalDeclContext(this);
1694198092Srdivacky    addDecl(method);
1695193326Sed  }
1696198092Srdivacky
1697195341Sed  void addPropertyImplementation(ObjCPropertyImplDecl *property);
1698198092Srdivacky
1699195341Sed  ObjCPropertyImplDecl *FindPropertyImplDecl(IdentifierInfo *propertyId) const;
1700195341Sed  ObjCPropertyImplDecl *FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const;
1701193326Sed
1702193326Sed  // Iterator access to properties.
1703193326Sed  typedef specific_decl_iterator<ObjCPropertyImplDecl> propimpl_iterator;
1704198092Srdivacky  propimpl_iterator propimpl_begin() const {
1705195341Sed    return propimpl_iterator(decls_begin());
1706193326Sed  }
1707198092Srdivacky  propimpl_iterator propimpl_end() const {
1708195341Sed    return propimpl_iterator(decls_end());
1709193326Sed  }
1710193326Sed
1711203955Srdivacky  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
1712203955Srdivacky  static bool classofKind(Kind K) {
1713210299Sed    return K >= firstObjCImpl && K <= lastObjCImpl;
1714193326Sed  }
1715198092Srdivacky};
1716193326Sed
1717198092Srdivacky/// ObjCCategoryImplDecl - An object of this class encapsulates a category
1718239462Sdim/// \@implementation declaration. If a category class has declaration of a
1719198092Srdivacky/// property, its implementation must be specified in the category's
1720239462Sdim/// \@implementation declaration. Example:
1721239462Sdim/// \@interface I \@end
1722239462Sdim/// \@interface I(CATEGORY)
1723239462Sdim///    \@property int p1, d1;
1724239462Sdim/// \@end
1725239462Sdim/// \@implementation I(CATEGORY)
1726239462Sdim///  \@dynamic p1,d1;
1727239462Sdim/// \@end
1728193326Sed///
1729193326Sed/// ObjCCategoryImplDecl
1730193326Sedclass ObjCCategoryImplDecl : public ObjCImplDecl {
1731234353Sdim  virtual void anchor();
1732234353Sdim
1733193326Sed  // Category name
1734193326Sed  IdentifierInfo *Id;
1735193326Sed
1736234353Sdim  // Category name location
1737234353Sdim  SourceLocation CategoryNameLoc;
1738234353Sdim
1739226633Sdim  ObjCCategoryImplDecl(DeclContext *DC, IdentifierInfo *Id,
1740226633Sdim                       ObjCInterfaceDecl *classInterface,
1741234353Sdim                       SourceLocation nameLoc, SourceLocation atStartLoc,
1742234353Sdim                       SourceLocation CategoryNameLoc)
1743226633Sdim    : ObjCImplDecl(ObjCCategoryImpl, DC, classInterface, nameLoc, atStartLoc),
1744234353Sdim      Id(Id), CategoryNameLoc(CategoryNameLoc) {}
1745193326Sedpublic:
1746193326Sed  static ObjCCategoryImplDecl *Create(ASTContext &C, DeclContext *DC,
1747226633Sdim                                      IdentifierInfo *Id,
1748226633Sdim                                      ObjCInterfaceDecl *classInterface,
1749226633Sdim                                      SourceLocation nameLoc,
1750234353Sdim                                      SourceLocation atStartLoc,
1751234353Sdim                                      SourceLocation CategoryNameLoc);
1752234353Sdim  static ObjCCategoryImplDecl *CreateDeserialized(ASTContext &C, unsigned ID);
1753198092Srdivacky
1754198893Srdivacky  /// getIdentifier - Get the identifier that names the category
1755193326Sed  /// interface associated with this implementation.
1756198893Srdivacky  /// FIXME: This is a bad API, we are overriding the NamedDecl::getIdentifier()
1757198893Srdivacky  /// to mean something different. For example:
1758234353Sdim  /// ((NamedDecl *)SomeCategoryImplDecl)->getIdentifier()
1759234353Sdim  /// returns the class interface name, whereas
1760234353Sdim  /// ((ObjCCategoryImplDecl *)SomeCategoryImplDecl)->getIdentifier()
1761198893Srdivacky  /// returns the category name.
1762198092Srdivacky  IdentifierInfo *getIdentifier() const {
1763198092Srdivacky    return Id;
1764193326Sed  }
1765193326Sed  void setIdentifier(IdentifierInfo *II) { Id = II; }
1766193326Sed
1767198893Srdivacky  ObjCCategoryDecl *getCategoryDecl() const;
1768198092Srdivacky
1769234353Sdim  SourceLocation getCategoryNameLoc() const { return CategoryNameLoc; }
1770234353Sdim
1771198398Srdivacky  /// getName - Get the name of identifier for the class interface associated
1772198398Srdivacky  /// with this implementation as a StringRef.
1773198398Srdivacky  //
1774198398Srdivacky  // FIXME: This is a bad API, we are overriding the NamedDecl::getName, to mean
1775198398Srdivacky  // something different.
1776226633Sdim  StringRef getName() const {
1777198398Srdivacky    return Id ? Id->getNameStart() : "";
1778198398Srdivacky  }
1779198398Srdivacky
1780193326Sed  /// @brief Get the name of the class associated with this interface.
1781198398Srdivacky  //
1782198398Srdivacky  // FIXME: Deprecated, move clients to getName().
1783193326Sed  std::string getNameAsString() const {
1784198398Srdivacky    return getName();
1785193326Sed  }
1786198092Srdivacky
1787203955Srdivacky  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
1788203955Srdivacky  static bool classofKind(Kind K) { return K == ObjCCategoryImpl;}
1789234353Sdim
1790234353Sdim  friend class ASTDeclReader;
1791234353Sdim  friend class ASTDeclWriter;
1792193326Sed};
1793193326Sed
1794234353Sdimraw_ostream &operator<<(raw_ostream &OS, const ObjCCategoryImplDecl &CID);
1795207619Srdivacky
1796193326Sed/// ObjCImplementationDecl - Represents a class definition - this is where
1797193326Sed/// method definitions are specified. For example:
1798193326Sed///
1799193326Sed/// @code
1800239462Sdim/// \@implementation MyClass
1801193326Sed/// - (void)myMethod { /* do something */ }
1802239462Sdim/// \@end
1803193326Sed/// @endcode
1804193326Sed///
1805198092Srdivacky/// Typically, instance variables are specified in the class interface,
1806193326Sed/// *not* in the implementation. Nevertheless (for legacy reasons), we
1807193326Sed/// allow instance variables to be specified in the implementation.  When
1808193326Sed/// specified, they need to be *identical* to the interface.
1809193326Sed///
1810198092Srdivackyclass ObjCImplementationDecl : public ObjCImplDecl {
1811234353Sdim  virtual void anchor();
1812193326Sed  /// Implementation Class's super class.
1813193326Sed  ObjCInterfaceDecl *SuperClass;
1814251662Sdim  SourceLocation SuperLoc;
1815251662Sdim
1816239462Sdim  /// \@implementation may have private ivars.
1817234353Sdim  SourceLocation IvarLBraceLoc;
1818234353Sdim  SourceLocation IvarRBraceLoc;
1819234353Sdim
1820207619Srdivacky  /// Support for ivar initialization.
1821207619Srdivacky  /// IvarInitializers - The arguments used to initialize the ivars
1822218893Sdim  CXXCtorInitializer **IvarInitializers;
1823207619Srdivacky  unsigned NumIvarInitializers;
1824224145Sdim
1825243830Sdim  /// Do the ivars of this class require initialization other than
1826243830Sdim  /// zero-initialization?
1827243830Sdim  bool HasNonZeroConstructors : 1;
1828234353Sdim
1829243830Sdim  /// Do the ivars of this class require non-trivial destruction?
1830243830Sdim  bool HasDestructors : 1;
1831243830Sdim
1832226633Sdim  ObjCImplementationDecl(DeclContext *DC,
1833193326Sed                         ObjCInterfaceDecl *classInterface,
1834226633Sdim                         ObjCInterfaceDecl *superDecl,
1835234353Sdim                         SourceLocation nameLoc, SourceLocation atStartLoc,
1836251662Sdim                         SourceLocation superLoc = SourceLocation(),
1837234353Sdim                         SourceLocation IvarLBraceLoc=SourceLocation(),
1838234353Sdim                         SourceLocation IvarRBraceLoc=SourceLocation())
1839226633Sdim    : ObjCImplDecl(ObjCImplementation, DC, classInterface, nameLoc, atStartLoc),
1840251662Sdim       SuperClass(superDecl), SuperLoc(superLoc), IvarLBraceLoc(IvarLBraceLoc),
1841234353Sdim       IvarRBraceLoc(IvarRBraceLoc),
1842234353Sdim       IvarInitializers(0), NumIvarInitializers(0),
1843243830Sdim       HasNonZeroConstructors(false), HasDestructors(false) {}
1844198092Srdivackypublic:
1845198092Srdivacky  static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC,
1846193326Sed                                        ObjCInterfaceDecl *classInterface,
1847226633Sdim                                        ObjCInterfaceDecl *superDecl,
1848226633Sdim                                        SourceLocation nameLoc,
1849234353Sdim                                        SourceLocation atStartLoc,
1850251662Sdim                                     SourceLocation superLoc = SourceLocation(),
1851234353Sdim                                        SourceLocation IvarLBraceLoc=SourceLocation(),
1852234353Sdim                                        SourceLocation IvarRBraceLoc=SourceLocation());
1853234353Sdim
1854234353Sdim  static ObjCImplementationDecl *CreateDeserialized(ASTContext &C, unsigned ID);
1855234353Sdim
1856207619Srdivacky  /// init_iterator - Iterates through the ivar initializer list.
1857218893Sdim  typedef CXXCtorInitializer **init_iterator;
1858234353Sdim
1859207619Srdivacky  /// init_const_iterator - Iterates through the ivar initializer list.
1860218893Sdim  typedef CXXCtorInitializer * const * init_const_iterator;
1861234353Sdim
1862207619Srdivacky  /// init_begin() - Retrieve an iterator to the first initializer.
1863207619Srdivacky  init_iterator       init_begin()       { return IvarInitializers; }
1864207619Srdivacky  /// begin() - Retrieve an iterator to the first initializer.
1865207619Srdivacky  init_const_iterator init_begin() const { return IvarInitializers; }
1866234353Sdim
1867207619Srdivacky  /// init_end() - Retrieve an iterator past the last initializer.
1868207619Srdivacky  init_iterator       init_end()       {
1869207619Srdivacky    return IvarInitializers + NumIvarInitializers;
1870207619Srdivacky  }
1871207619Srdivacky  /// end() - Retrieve an iterator past the last initializer.
1872207619Srdivacky  init_const_iterator init_end() const {
1873207619Srdivacky    return IvarInitializers + NumIvarInitializers;
1874207619Srdivacky  }
1875207619Srdivacky  /// getNumArgs - Number of ivars which must be initialized.
1876207619Srdivacky  unsigned getNumIvarInitializers() const {
1877207619Srdivacky    return NumIvarInitializers;
1878207619Srdivacky  }
1879234353Sdim
1880207619Srdivacky  void setNumIvarInitializers(unsigned numNumIvarInitializers) {
1881207619Srdivacky    NumIvarInitializers = numNumIvarInitializers;
1882207619Srdivacky  }
1883234353Sdim
1884207619Srdivacky  void setIvarInitializers(ASTContext &C,
1885218893Sdim                           CXXCtorInitializer ** initializers,
1886207619Srdivacky                           unsigned numInitializers);
1887224145Sdim
1888243830Sdim  /// Do any of the ivars of this class (not counting its base classes)
1889243830Sdim  /// require construction other than zero-initialization?
1890243830Sdim  bool hasNonZeroConstructors() const { return HasNonZeroConstructors; }
1891243830Sdim  void setHasNonZeroConstructors(bool val) { HasNonZeroConstructors = val; }
1892234353Sdim
1893243830Sdim  /// Do any of the ivars of this class (not counting its base classes)
1894243830Sdim  /// require non-trivial destruction?
1895243830Sdim  bool hasDestructors() const { return HasDestructors; }
1896243830Sdim  void setHasDestructors(bool val) { HasDestructors = val; }
1897243830Sdim
1898193326Sed  /// getIdentifier - Get the identifier that names the class
1899193326Sed  /// interface associated with this implementation.
1900198092Srdivacky  IdentifierInfo *getIdentifier() const {
1901198092Srdivacky    return getClassInterface()->getIdentifier();
1902193326Sed  }
1903193326Sed
1904198398Srdivacky  /// getName - Get the name of identifier for the class interface associated
1905198398Srdivacky  /// with this implementation as a StringRef.
1906198398Srdivacky  //
1907198398Srdivacky  // FIXME: This is a bad API, we are overriding the NamedDecl::getName, to mean
1908198398Srdivacky  // something different.
1909226633Sdim  StringRef getName() const {
1910198398Srdivacky    assert(getIdentifier() && "Name is not a simple identifier");
1911198398Srdivacky    return getIdentifier()->getName();
1912198398Srdivacky  }
1913198398Srdivacky
1914193326Sed  /// @brief Get the name of the class associated with this interface.
1915198398Srdivacky  //
1916198398Srdivacky  // FIXME: Move to StringRef API.
1917193326Sed  std::string getNameAsString() const {
1918198398Srdivacky    return getName();
1919193326Sed  }
1920193326Sed
1921193326Sed  const ObjCInterfaceDecl *getSuperClass() const { return SuperClass; }
1922193326Sed  ObjCInterfaceDecl *getSuperClass() { return SuperClass; }
1923251662Sdim  SourceLocation getSuperClassLoc() const { return SuperLoc; }
1924198092Srdivacky
1925193326Sed  void setSuperClass(ObjCInterfaceDecl * superCls) { SuperClass = superCls; }
1926198092Srdivacky
1927234353Sdim  void setIvarLBraceLoc(SourceLocation Loc) { IvarLBraceLoc = Loc; }
1928234353Sdim  SourceLocation getIvarLBraceLoc() const { return IvarLBraceLoc; }
1929234353Sdim  void setIvarRBraceLoc(SourceLocation Loc) { IvarRBraceLoc = Loc; }
1930234353Sdim  SourceLocation getIvarRBraceLoc() const { return IvarRBraceLoc; }
1931234353Sdim
1932193326Sed  typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator;
1933198092Srdivacky  ivar_iterator ivar_begin() const {
1934198092Srdivacky    return ivar_iterator(decls_begin());
1935193326Sed  }
1936198092Srdivacky  ivar_iterator ivar_end() const {
1937195341Sed    return ivar_iterator(decls_end());
1938193326Sed  }
1939198092Srdivacky  unsigned ivar_size() const {
1940195341Sed    return std::distance(ivar_begin(), ivar_end());
1941193326Sed  }
1942198092Srdivacky  bool ivar_empty() const {
1943195341Sed    return ivar_begin() == ivar_end();
1944193326Sed  }
1945198092Srdivacky
1946203955Srdivacky  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
1947203955Srdivacky  static bool classofKind(Kind K) { return K == ObjCImplementation; }
1948212904Sdim
1949212904Sdim  friend class ASTDeclReader;
1950212904Sdim  friend class ASTDeclWriter;
1951193326Sed};
1952193326Sed
1953234353Sdimraw_ostream &operator<<(raw_ostream &OS, const ObjCImplementationDecl &ID);
1954207619Srdivacky
1955198092Srdivacky/// ObjCCompatibleAliasDecl - Represents alias of a class. This alias is
1956239462Sdim/// declared as \@compatibility_alias alias class.
1957193326Sedclass ObjCCompatibleAliasDecl : public NamedDecl {
1958234353Sdim  virtual void anchor();
1959193326Sed  /// Class that this is an alias of.
1960193326Sed  ObjCInterfaceDecl *AliasedClass;
1961198092Srdivacky
1962193326Sed  ObjCCompatibleAliasDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
1963193326Sed                          ObjCInterfaceDecl* aliasedClass)
1964193326Sed    : NamedDecl(ObjCCompatibleAlias, DC, L, Id), AliasedClass(aliasedClass) {}
1965193326Sedpublic:
1966193326Sed  static ObjCCompatibleAliasDecl *Create(ASTContext &C, DeclContext *DC,
1967193326Sed                                         SourceLocation L, IdentifierInfo *Id,
1968193326Sed                                         ObjCInterfaceDecl* aliasedClass);
1969193326Sed
1970234353Sdim  static ObjCCompatibleAliasDecl *CreateDeserialized(ASTContext &C,
1971234353Sdim                                                     unsigned ID);
1972234353Sdim
1973193326Sed  const ObjCInterfaceDecl *getClassInterface() const { return AliasedClass; }
1974193326Sed  ObjCInterfaceDecl *getClassInterface() { return AliasedClass; }
1975193326Sed  void setClassInterface(ObjCInterfaceDecl *D) { AliasedClass = D; }
1976198092Srdivacky
1977203955Srdivacky  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
1978203955Srdivacky  static bool classofKind(Kind K) { return K == ObjCCompatibleAlias; }
1979198092Srdivacky
1980193326Sed};
1981193326Sed
1982239462Sdim/// \brief Represents one property declaration in an Objective-C interface.
1983239462Sdim///
1984193326Sed/// For example:
1985239462Sdim/// \code{.mm}
1986239462Sdim/// \@property (assign, readwrite) int MyProperty;
1987239462Sdim/// \endcode
1988193326Sedclass ObjCPropertyDecl : public NamedDecl {
1989234353Sdim  virtual void anchor();
1990193326Sedpublic:
1991193326Sed  enum PropertyAttributeKind {
1992198092Srdivacky    OBJC_PR_noattr    = 0x00,
1993198092Srdivacky    OBJC_PR_readonly  = 0x01,
1994193326Sed    OBJC_PR_getter    = 0x02,
1995198092Srdivacky    OBJC_PR_assign    = 0x04,
1996198092Srdivacky    OBJC_PR_readwrite = 0x08,
1997193326Sed    OBJC_PR_retain    = 0x10,
1998198092Srdivacky    OBJC_PR_copy      = 0x20,
1999193326Sed    OBJC_PR_nonatomic = 0x40,
2000218893Sdim    OBJC_PR_setter    = 0x80,
2001224145Sdim    OBJC_PR_atomic    = 0x100,
2002224145Sdim    OBJC_PR_weak      = 0x200,
2003224145Sdim    OBJC_PR_strong    = 0x400,
2004224145Sdim    OBJC_PR_unsafe_unretained = 0x800
2005224145Sdim    // Adding a property should change NumPropertyAttrsBits
2006193326Sed  };
2007193326Sed
2008224145Sdim  enum {
2009224145Sdim    /// \brief Number of bits fitting all the property attributes.
2010224145Sdim    NumPropertyAttrsBits = 12
2011224145Sdim  };
2012224145Sdim
2013226633Sdim  enum SetterKind { Assign, Retain, Copy, Weak };
2014193326Sed  enum PropertyControl { None, Required, Optional };
2015193326Sedprivate:
2016239462Sdim  SourceLocation AtLoc;   // location of \@property
2017234353Sdim  SourceLocation LParenLoc; // location of '(' starting attribute list or null.
2018210299Sed  TypeSourceInfo *DeclType;
2019224145Sdim  unsigned PropertyAttributes : NumPropertyAttrsBits;
2020224145Sdim  unsigned PropertyAttributesAsWritten : NumPropertyAttrsBits;
2021239462Sdim  // \@required/\@optional
2022193326Sed  unsigned PropertyImplementation : 2;
2023198092Srdivacky
2024193326Sed  Selector GetterName;    // getter name of NULL if no getter
2025193326Sed  Selector SetterName;    // setter name of NULL if no setter
2026198092Srdivacky
2027193326Sed  ObjCMethodDecl *GetterMethodDecl; // Declaration of getter instance method
2028193326Sed  ObjCMethodDecl *SetterMethodDecl; // Declaration of setter instance method
2029193326Sed  ObjCIvarDecl *PropertyIvarDecl;   // Synthesize ivar for this property
2030193326Sed
2031198092Srdivacky  ObjCPropertyDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
2032234353Sdim                   SourceLocation AtLocation,  SourceLocation LParenLocation,
2033234353Sdim                   TypeSourceInfo *T)
2034234353Sdim    : NamedDecl(ObjCProperty, DC, L, Id), AtLoc(AtLocation),
2035234353Sdim      LParenLoc(LParenLocation), DeclType(T),
2036234353Sdim      PropertyAttributes(OBJC_PR_noattr),
2037210299Sed      PropertyAttributesAsWritten(OBJC_PR_noattr),
2038210299Sed      PropertyImplementation(None),
2039198092Srdivacky      GetterName(Selector()),
2040193326Sed      SetterName(Selector()),
2041193326Sed      GetterMethodDecl(0), SetterMethodDecl(0) , PropertyIvarDecl(0) {}
2042193326Sedpublic:
2043198092Srdivacky  static ObjCPropertyDecl *Create(ASTContext &C, DeclContext *DC,
2044198092Srdivacky                                  SourceLocation L,
2045202879Srdivacky                                  IdentifierInfo *Id, SourceLocation AtLocation,
2046234353Sdim                                  SourceLocation LParenLocation,
2047210299Sed                                  TypeSourceInfo *T,
2048193326Sed                                  PropertyControl propControl = None);
2049234353Sdim
2050234353Sdim  static ObjCPropertyDecl *CreateDeserialized(ASTContext &C, unsigned ID);
2051234353Sdim
2052202879Srdivacky  SourceLocation getAtLoc() const { return AtLoc; }
2053202879Srdivacky  void setAtLoc(SourceLocation L) { AtLoc = L; }
2054202879Srdivacky
2055234353Sdim  SourceLocation getLParenLoc() const { return LParenLoc; }
2056234353Sdim  void setLParenLoc(SourceLocation L) { LParenLoc = L; }
2057234353Sdim
2058210299Sed  TypeSourceInfo *getTypeSourceInfo() const { return DeclType; }
2059210299Sed  QualType getType() const { return DeclType->getType(); }
2060210299Sed  void setType(TypeSourceInfo *T) { DeclType = T; }
2061193326Sed
2062193326Sed  PropertyAttributeKind getPropertyAttributes() const {
2063193326Sed    return PropertyAttributeKind(PropertyAttributes);
2064193326Sed  }
2065198092Srdivacky  void setPropertyAttributes(PropertyAttributeKind PRVal) {
2066193326Sed    PropertyAttributes |= PRVal;
2067193326Sed  }
2068193326Sed
2069210299Sed  PropertyAttributeKind getPropertyAttributesAsWritten() const {
2070210299Sed    return PropertyAttributeKind(PropertyAttributesAsWritten);
2071210299Sed  }
2072224145Sdim
2073224145Sdim  bool hasWrittenStorageAttribute() const {
2074224145Sdim    return PropertyAttributesAsWritten & (OBJC_PR_assign | OBJC_PR_copy |
2075224145Sdim        OBJC_PR_unsafe_unretained | OBJC_PR_retain | OBJC_PR_strong |
2076224145Sdim        OBJC_PR_weak);
2077224145Sdim  }
2078234353Sdim
2079210299Sed  void setPropertyAttributesAsWritten(PropertyAttributeKind PRVal) {
2080210299Sed    PropertyAttributesAsWritten = PRVal;
2081210299Sed  }
2082234353Sdim
2083249423Sdim void makeitReadWriteAttribute() {
2084193326Sed    PropertyAttributes &= ~OBJC_PR_readonly;
2085193326Sed    PropertyAttributes |= OBJC_PR_readwrite;
2086198092Srdivacky }
2087193326Sed
2088193326Sed  // Helper methods for accessing attributes.
2089193326Sed
2090193326Sed  /// isReadOnly - Return true iff the property has a setter.
2091193326Sed  bool isReadOnly() const {
2092193326Sed    return (PropertyAttributes & OBJC_PR_readonly);
2093193326Sed  }
2094193326Sed
2095226633Sdim  /// isAtomic - Return true if the property is atomic.
2096226633Sdim  bool isAtomic() const {
2097226633Sdim    return (PropertyAttributes & OBJC_PR_atomic);
2098226633Sdim  }
2099226633Sdim
2100226633Sdim  /// isRetaining - Return true if the property retains its value.
2101226633Sdim  bool isRetaining() const {
2102226633Sdim    return (PropertyAttributes &
2103226633Sdim            (OBJC_PR_retain | OBJC_PR_strong | OBJC_PR_copy));
2104226633Sdim  }
2105226633Sdim
2106193326Sed  /// getSetterKind - Return the method used for doing assignment in
2107193326Sed  /// the property setter. This is only valid if the property has been
2108193326Sed  /// defined to have a setter.
2109193326Sed  SetterKind getSetterKind() const {
2110226633Sdim    if (PropertyAttributes & OBJC_PR_strong)
2111226633Sdim      return getType()->isBlockPointerType() ? Copy : Retain;
2112226633Sdim    if (PropertyAttributes & OBJC_PR_retain)
2113193326Sed      return Retain;
2114193326Sed    if (PropertyAttributes & OBJC_PR_copy)
2115193326Sed      return Copy;
2116226633Sdim    if (PropertyAttributes & OBJC_PR_weak)
2117226633Sdim      return Weak;
2118193326Sed    return Assign;
2119193326Sed  }
2120193326Sed
2121193326Sed  Selector getGetterName() const { return GetterName; }
2122193326Sed  void setGetterName(Selector Sel) { GetterName = Sel; }
2123198092Srdivacky
2124193326Sed  Selector getSetterName() const { return SetterName; }
2125193326Sed  void setSetterName(Selector Sel) { SetterName = Sel; }
2126198092Srdivacky
2127193326Sed  ObjCMethodDecl *getGetterMethodDecl() const { return GetterMethodDecl; }
2128193326Sed  void setGetterMethodDecl(ObjCMethodDecl *gDecl) { GetterMethodDecl = gDecl; }
2129193326Sed
2130193326Sed  ObjCMethodDecl *getSetterMethodDecl() const { return SetterMethodDecl; }
2131193326Sed  void setSetterMethodDecl(ObjCMethodDecl *gDecl) { SetterMethodDecl = gDecl; }
2132198092Srdivacky
2133239462Sdim  // Related to \@optional/\@required declared in \@protocol
2134193326Sed  void setPropertyImplementation(PropertyControl pc) {
2135193326Sed    PropertyImplementation = pc;
2136193326Sed  }
2137193326Sed  PropertyControl getPropertyImplementation() const {
2138193326Sed    return PropertyControl(PropertyImplementation);
2139198092Srdivacky  }
2140198092Srdivacky
2141193326Sed  void setPropertyIvarDecl(ObjCIvarDecl *Ivar) {
2142193326Sed    PropertyIvarDecl = Ivar;
2143193326Sed  }
2144193326Sed  ObjCIvarDecl *getPropertyIvarDecl() const {
2145193326Sed    return PropertyIvarDecl;
2146193326Sed  }
2147198092Srdivacky
2148234353Sdim  virtual SourceRange getSourceRange() const LLVM_READONLY {
2149218893Sdim    return SourceRange(AtLoc, getLocation());
2150218893Sdim  }
2151243830Sdim
2152243830Sdim  /// Get the default name of the synthesized ivar.
2153243830Sdim  IdentifierInfo *getDefaultSynthIvarName(ASTContext &Ctx) const;
2154218893Sdim
2155205219Srdivacky  /// Lookup a property by name in the specified DeclContext.
2156205219Srdivacky  static ObjCPropertyDecl *findPropertyDecl(const DeclContext *DC,
2157205219Srdivacky                                            IdentifierInfo *propertyID);
2158205219Srdivacky
2159203955Srdivacky  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
2160203955Srdivacky  static bool classofKind(Kind K) { return K == ObjCProperty; }
2161193326Sed};
2162193326Sed
2163198092Srdivacky/// ObjCPropertyImplDecl - Represents implementation declaration of a property
2164193326Sed/// in a class or category implementation block. For example:
2165239462Sdim/// \@synthesize prop1 = ivar1;
2166193326Sed///
2167193326Sedclass ObjCPropertyImplDecl : public Decl {
2168193326Sedpublic:
2169193326Sed  enum Kind {
2170193326Sed    Synthesize,
2171193326Sed    Dynamic
2172193326Sed  };
2173193326Sedprivate:
2174239462Sdim  SourceLocation AtLoc;   // location of \@synthesize or \@dynamic
2175234353Sdim
2176239462Sdim  /// \brief For \@synthesize, the location of the ivar, if it was written in
2177218893Sdim  /// the source code.
2178218893Sdim  ///
2179218893Sdim  /// \code
2180239462Sdim  /// \@synthesize int a = b
2181218893Sdim  /// \endcode
2182218893Sdim  SourceLocation IvarLoc;
2183234353Sdim
2184193326Sed  /// Property declaration being implemented
2185193326Sed  ObjCPropertyDecl *PropertyDecl;
2186193326Sed
2187239462Sdim  /// Null for \@dynamic. Required for \@synthesize.
2188193326Sed  ObjCIvarDecl *PropertyIvarDecl;
2189234353Sdim
2190239462Sdim  /// Null for \@dynamic. Non-null if property must be copy-constructed in
2191239462Sdim  /// getter.
2192208600Srdivacky  Expr *GetterCXXConstructor;
2193234353Sdim
2194239462Sdim  /// Null for \@dynamic. Non-null if property has assignment operator to call
2195208600Srdivacky  /// in Setter synthesis.
2196208600Srdivacky  Expr *SetterCXXAssignment;
2197193326Sed
2198193326Sed  ObjCPropertyImplDecl(DeclContext *DC, SourceLocation atLoc, SourceLocation L,
2199198092Srdivacky                       ObjCPropertyDecl *property,
2200198092Srdivacky                       Kind PK,
2201218893Sdim                       ObjCIvarDecl *ivarDecl,
2202218893Sdim                       SourceLocation ivarLoc)
2203198092Srdivacky    : Decl(ObjCPropertyImpl, DC, L), AtLoc(atLoc),
2204234353Sdim      IvarLoc(ivarLoc), PropertyDecl(property), PropertyIvarDecl(ivarDecl),
2205208600Srdivacky      GetterCXXConstructor(0), SetterCXXAssignment(0) {
2206193326Sed    assert (PK == Dynamic || PropertyIvarDecl);
2207193326Sed  }
2208198092Srdivacky
2209193326Sedpublic:
2210193326Sed  static ObjCPropertyImplDecl *Create(ASTContext &C, DeclContext *DC,
2211198092Srdivacky                                      SourceLocation atLoc, SourceLocation L,
2212198092Srdivacky                                      ObjCPropertyDecl *property,
2213198092Srdivacky                                      Kind PK,
2214218893Sdim                                      ObjCIvarDecl *ivarDecl,
2215218893Sdim                                      SourceLocation ivarLoc);
2216193326Sed
2217234353Sdim  static ObjCPropertyImplDecl *CreateDeserialized(ASTContext &C, unsigned ID);
2218218893Sdim
2219234353Sdim  virtual SourceRange getSourceRange() const LLVM_READONLY;
2220234353Sdim
2221234353Sdim  SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; }
2222193326Sed  void setAtLoc(SourceLocation Loc) { AtLoc = Loc; }
2223193326Sed
2224193326Sed  ObjCPropertyDecl *getPropertyDecl() const {
2225193326Sed    return PropertyDecl;
2226193326Sed  }
2227193326Sed  void setPropertyDecl(ObjCPropertyDecl *Prop) { PropertyDecl = Prop; }
2228193326Sed
2229193326Sed  Kind getPropertyImplementation() const {
2230193326Sed    return PropertyIvarDecl ? Synthesize : Dynamic;
2231193326Sed  }
2232198092Srdivacky
2233193326Sed  ObjCIvarDecl *getPropertyIvarDecl() const {
2234193326Sed    return PropertyIvarDecl;
2235193326Sed  }
2236218893Sdim  SourceLocation getPropertyIvarDeclLoc() const { return IvarLoc; }
2237234353Sdim
2238218893Sdim  void setPropertyIvarDecl(ObjCIvarDecl *Ivar,
2239234353Sdim                           SourceLocation IvarLoc) {
2240234353Sdim    PropertyIvarDecl = Ivar;
2241218893Sdim    this->IvarLoc = IvarLoc;
2242218893Sdim  }
2243234353Sdim
2244239462Sdim  /// \brief For \@synthesize, returns true if an ivar name was explicitly
2245239462Sdim  /// specified.
2246239462Sdim  ///
2247239462Sdim  /// \code
2248239462Sdim  /// \@synthesize int a = b; // true
2249239462Sdim  /// \@synthesize int a; // false
2250239462Sdim  /// \endcode
2251239462Sdim  bool isIvarNameSpecified() const {
2252239462Sdim    return IvarLoc.isValid() && IvarLoc != getLocation();
2253239462Sdim  }
2254239462Sdim
2255208600Srdivacky  Expr *getGetterCXXConstructor() const {
2256208600Srdivacky    return GetterCXXConstructor;
2257208600Srdivacky  }
2258208600Srdivacky  void setGetterCXXConstructor(Expr *getterCXXConstructor) {
2259208600Srdivacky    GetterCXXConstructor = getterCXXConstructor;
2260208600Srdivacky  }
2261193326Sed
2262208600Srdivacky  Expr *getSetterCXXAssignment() const {
2263208600Srdivacky    return SetterCXXAssignment;
2264208600Srdivacky  }
2265208600Srdivacky  void setSetterCXXAssignment(Expr *setterCXXAssignment) {
2266208600Srdivacky    SetterCXXAssignment = setterCXXAssignment;
2267208600Srdivacky  }
2268234353Sdim
2269203955Srdivacky  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
2270203955Srdivacky  static bool classofKind(Decl::Kind K) { return K == ObjCPropertyImpl; }
2271234353Sdim
2272218893Sdim  friend class ASTDeclReader;
2273193326Sed};
2274193326Sed
2275249423Sdimtemplate<bool (*Filter)(ObjCCategoryDecl *)>
2276249423Sdimvoid
2277249423SdimObjCInterfaceDecl::filtered_category_iterator<Filter>::
2278249423SdimfindAcceptableCategory() {
2279249423Sdim  while (Current && !Filter(Current))
2280249423Sdim    Current = Current->getNextClassCategoryRaw();
2281249423Sdim}
2282249423Sdim
2283249423Sdimtemplate<bool (*Filter)(ObjCCategoryDecl *)>
2284249423Sdiminline ObjCInterfaceDecl::filtered_category_iterator<Filter> &
2285249423SdimObjCInterfaceDecl::filtered_category_iterator<Filter>::operator++() {
2286249423Sdim  Current = Current->getNextClassCategoryRaw();
2287249423Sdim  findAcceptableCategory();
2288249423Sdim  return *this;
2289249423Sdim}
2290249423Sdim
2291249423Sdiminline bool ObjCInterfaceDecl::isVisibleCategory(ObjCCategoryDecl *Cat) {
2292249423Sdim  return !Cat->isHidden();
2293249423Sdim}
2294249423Sdim
2295249423Sdiminline bool ObjCInterfaceDecl::isVisibleExtension(ObjCCategoryDecl *Cat) {
2296249423Sdim  return Cat->IsClassExtension() && !Cat->isHidden();
2297249423Sdim}
2298249423Sdim
2299249423Sdiminline bool ObjCInterfaceDecl::isKnownExtension(ObjCCategoryDecl *Cat) {
2300249423Sdim  return Cat->IsClassExtension();
2301249423Sdim}
2302249423Sdim
2303193326Sed}  // end namespace clang
2304193326Sed#endif
2305