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"
18226890Sdim#include "clang/AST/SelectorLocationsKind.h"
19193326Sed#include "llvm/ADT/STLExtras.h"
20235633Sdim#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 {
36245431Sdim  ObjCListBase(const ObjCListBase &) LLVM_DELETED_FUNCTION;
37245431Sdim  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
88235633Sdim  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
126245431Sdim  /// True if this method is the getter or setter for an explicit property.
127245431Sdim  unsigned IsPropertyAccessor : 1;
128235633Sdim
129212904Sdim  // Method has a definition.
130221345Sdim  unsigned IsDefined : 1;
131198092Srdivacky
132226890Sdim  /// \brief Method redeclaration in the same interface.
133226890Sdim  unsigned IsRedeclaration : 1;
134226890Sdim
135226890Sdim  /// \brief Is redeclared in the same interface.
136226890Sdim  mutable unsigned HasRedeclaration : 1;
137226890Sdim
138193326Sed  // NOTE: VC++ treats enums as signed, avoid using ImplementationControl enum
139245431Sdim  /// \@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;
148235633Sdim
149226890Sdim  /// \brief Whether the locations of the selector identifiers are in a
150226890Sdim  /// "standard" position, a enum SelectorLocationsKind.
151226890Sdim  unsigned SelLocsKind : 2;
152207619Srdivacky
153245431Sdim  /// \brief Whether this method overrides any other in the class hierarchy.
154245431Sdim  ///
155245431Sdim  /// A method is said to override any method in the class's
156245431Sdim  /// base classes, its protocols, or its categories' protocols, that has
157245431Sdim  /// the same selector and is of the same kind (class or instance).
158245431Sdim  /// A method in an implementation is not considered as overriding the same
159245431Sdim  /// method in the interface or its categories.
160245431Sdim  unsigned IsOverriding : 1;
161245431Sdim
162252723Sdim  /// \brief Indicates if the method was a definition but its body was skipped.
163252723Sdim  unsigned HasSkippedBody : 1;
164252723Sdim
165204962Srdivacky  // Result type of this method.
166193326Sed  QualType MethodDeclType;
167235633Sdim
168204962Srdivacky  // Type source information for the result type.
169204962Srdivacky  TypeSourceInfo *ResultTInfo;
170204962Srdivacky
171226890Sdim  /// \brief Array of ParmVarDecls for the formal parameters of this method
172226890Sdim  /// and optionally followed by selector locations.
173226890Sdim  void *ParamsAndSelLocs;
174226890Sdim  unsigned NumParams;
175198092Srdivacky
176193326Sed  /// List of attributes for this method declaration.
177245431Sdim  SourceLocation DeclEndLoc; // the location of the ';' or '{'.
178198092Srdivacky
179193326Sed  // The following are only used for method definitions, null otherwise.
180245431Sdim  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
189226890Sdim  SelectorLocationsKind getSelLocsKind() const {
190226890Sdim    return (SelectorLocationsKind)SelLocsKind;
191226890Sdim  }
192226890Sdim  bool hasStandardSelLocs() const {
193226890Sdim    return getSelLocsKind() != SelLoc_NonStandard;
194226890Sdim  }
195226890Sdim
196226890Sdim  /// \brief Get a pointer to the stored selector identifiers locations array.
197226890Sdim  /// No locations will be stored if HasStandardSelLocs is true.
198226890Sdim  SourceLocation *getStoredSelLocs() {
199226890Sdim    return reinterpret_cast<SourceLocation*>(getParams() + NumParams);
200226890Sdim  }
201226890Sdim  const SourceLocation *getStoredSelLocs() const {
202226890Sdim    return reinterpret_cast<const SourceLocation*>(getParams() + NumParams);
203226890Sdim  }
204226890Sdim
205226890Sdim  /// \brief Get a pointer to the stored selector identifiers locations array.
206226890Sdim  /// No locations will be stored if HasStandardSelLocs is true.
207226890Sdim  ParmVarDecl **getParams() {
208226890Sdim    return reinterpret_cast<ParmVarDecl **>(ParamsAndSelLocs);
209226890Sdim  }
210226890Sdim  const ParmVarDecl *const *getParams() const {
211226890Sdim    return reinterpret_cast<const ParmVarDecl *const *>(ParamsAndSelLocs);
212226890Sdim  }
213226890Sdim
214226890Sdim  /// \brief Get the number of stored selector identifiers locations.
215226890Sdim  /// No locations will be stored if HasStandardSelLocs is true.
216226890Sdim  unsigned getNumStoredSelLocs() const {
217226890Sdim    if (hasStandardSelLocs())
218226890Sdim      return 0;
219226890Sdim    return getNumSelectorLocs();
220226890Sdim  }
221226890Sdim
222226890Sdim  void setParamsAndSelLocs(ASTContext &C,
223226890Sdim                           ArrayRef<ParmVarDecl*> Params,
224226890Sdim                           ArrayRef<SourceLocation> SelLocs);
225226890Sdim
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,
232245431Sdim                 bool isPropertyAccessor = false,
233226890Sdim                 bool isImplicitlyDeclared = false,
234212904Sdim                 bool isDefined = false,
235207619Srdivacky                 ImplementationControl impControl = None,
236226890Sdim                 bool HasRelatedResultType = false)
237193326Sed  : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo),
238221345Sdim    DeclContext(ObjCMethod), Family(InvalidObjCMethodFamily),
239193326Sed    IsInstance(isInstance), IsVariadic(isVariadic),
240245431Sdim    IsPropertyAccessor(isPropertyAccessor),
241226890Sdim    IsDefined(isDefined), IsRedeclaration(0), HasRedeclaration(0),
242193326Sed    DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None),
243226890Sdim    RelatedResultType(HasRelatedResultType),
244252723Sdim    SelLocsKind(SelLoc_StandardNoSpace), IsOverriding(0), HasSkippedBody(0),
245223017Sdim    MethodDeclType(T), ResultTInfo(ResultTInfo),
246226890Sdim    ParamsAndSelLocs(0), NumParams(0),
247245431Sdim    DeclEndLoc(endLoc), Body(), SelfDecl(0), CmdDecl(0) {
248226890Sdim    setImplicit(isImplicitlyDeclared);
249226890Sdim  }
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,
259226890Sdim                                SourceLocation endLoc,
260226890Sdim                                Selector SelInfo,
261235633Sdim                                QualType T,
262204962Srdivacky                                TypeSourceInfo *ResultTInfo,
263204962Srdivacky                                DeclContext *contextDecl,
264193326Sed                                bool isInstance = true,
265193326Sed                                bool isVariadic = false,
266245431Sdim                                bool isPropertyAccessor = false,
267226890Sdim                                bool isImplicitlyDeclared = false,
268212904Sdim                                bool isDefined = false,
269207619Srdivacky                                ImplementationControl impControl = None,
270226890Sdim                                bool HasRelatedResultType = false);
271198092Srdivacky
272235633Sdim  static ObjCMethodDecl *CreateDeserialized(ASTContext &C, unsigned ID);
273235633Sdim
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; }
287235633Sdim
288223017Sdim  /// \brief Note whether this method has a related result type.
289223017Sdim  void SetRelatedResultType(bool RRT = true) { RelatedResultType = RRT; }
290226890Sdim
291226890Sdim  /// \brief True if this is a method redeclaration in the same interface.
292226890Sdim  bool isRedeclaration() const { return IsRedeclaration; }
293226890Sdim  void setAsRedeclaration(const ObjCMethodDecl *PrevMethod);
294235633Sdim
295245431Sdim  /// \brief Returns the location where the declarator ends. It will be
296245431Sdim  /// the location of ';' for a method declaration and the location of '{'
297245431Sdim  /// for a method definition.
298245431Sdim  SourceLocation getDeclaratorEndLoc() const { return DeclEndLoc; }
299245431Sdim
300193326Sed  // Location information, modeled after the Stmt API.
301235633Sdim  SourceLocation getLocStart() const LLVM_READONLY { return getLocation(); }
302245431Sdim  SourceLocation getLocEnd() const LLVM_READONLY;
303235633Sdim  virtual SourceRange getSourceRange() const LLVM_READONLY {
304245431Sdim    return SourceRange(getLocation(), getLocEnd());
305193326Sed  }
306198092Srdivacky
307235633Sdim  SourceLocation getSelectorStartLoc() const {
308235633Sdim    if (isImplicit())
309235633Sdim      return getLocStart();
310235633Sdim    return getSelectorLoc(0);
311235633Sdim  }
312226890Sdim  SourceLocation getSelectorLoc(unsigned Index) const {
313226890Sdim    assert(Index < getNumSelectorLocs() && "Index out of range!");
314226890Sdim    if (hasStandardSelLocs())
315226890Sdim      return getStandardSelectorLoc(Index, getSelector(),
316226890Sdim                                   getSelLocsKind() == SelLoc_StandardWithSpace,
317226890Sdim                      llvm::makeArrayRef(const_cast<ParmVarDecl**>(getParams()),
318226890Sdim                                         NumParams),
319245431Sdim                                   DeclEndLoc);
320226890Sdim    return getStoredSelLocs()[Index];
321226890Sdim  }
322226890Sdim
323226890Sdim  void getSelectorLocs(SmallVectorImpl<SourceLocation> &SelLocs) const;
324226890Sdim
325226890Sdim  unsigned getNumSelectorLocs() const {
326226890Sdim    if (isImplicit())
327226890Sdim      return 0;
328226890Sdim    Selector Sel = getSelector();
329226890Sdim    if (Sel.isUnarySelector())
330226890Sdim      return 1;
331226890Sdim    return Sel.getNumArgs();
332226890Sdim  }
333226890Sdim
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
344235633Sdim  /// \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  }
349235633Sdim
350204962Srdivacky  TypeSourceInfo *getResultTypeSourceInfo() const { return ResultTInfo; }
351204962Srdivacky  void setResultTypeSourceInfo(TypeSourceInfo *TInfo) { ResultTInfo = TInfo; }
352204962Srdivacky
353193326Sed  // Iterator access to formal parameters.
354226890Sdim  unsigned param_size() const { return NumParams; }
355226890Sdim  typedef const ParmVarDecl *const *param_const_iterator;
356226890Sdim  typedef ParmVarDecl *const *param_iterator;
357226890Sdim  param_const_iterator param_begin() const { return getParams(); }
358226890Sdim  param_const_iterator param_end() const { return getParams() + NumParams; }
359226890Sdim  param_iterator param_begin() { return getParams(); }
360226890Sdim  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.
363235633Sdim  param_const_iterator sel_param_end() const {
364235633Sdim    return param_begin() + getSelector().getNumArgs();
365207619Srdivacky  }
366193326Sed
367226890Sdim  /// \brief Sets the method's parameters and selector source locations.
368245431Sdim  /// If the method is implicit (not coming from source) \p SelLocs is
369226890Sdim  /// ignored.
370226890Sdim  void setMethodParams(ASTContext &C,
371226890Sdim                       ArrayRef<ParmVarDecl*> Params,
372226890Sdim                       ArrayRef<SourceLocation> SelLocs =
373226890Sdim                           ArrayRef<SourceLocation>());
374193326Sed
375193326Sed  // Iterator access to parameter types.
376193326Sed  typedef std::const_mem_fun_t<QualType, ParmVarDecl> deref_fun;
377226890Sdim  typedef llvm::mapped_iterator<param_const_iterator, deref_fun>
378226890Sdim      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
408245431Sdim  bool isPropertyAccessor() const { return IsPropertyAccessor; }
409245431Sdim  void setPropertyAccessor(bool isAccessor) { IsPropertyAccessor = isAccessor; }
410235633Sdim
411212904Sdim  bool isDefined() const { return IsDefined; }
412212904Sdim  void setDefined(bool isDefined) { IsDefined = isDefined; }
413198092Srdivacky
414245431Sdim  /// \brief Whether this method overrides any other in the class hierarchy.
415245431Sdim  ///
416245431Sdim  /// A method is said to override any method in the class's
417245431Sdim  /// base classes, its protocols, or its categories' protocols, that has
418245431Sdim  /// the same selector and is of the same kind (class or instance).
419245431Sdim  /// A method in an implementation is not considered as overriding the same
420245431Sdim  /// method in the interface or its categories.
421245431Sdim  bool isOverriding() const { return IsOverriding; }
422245431Sdim  void setOverriding(bool isOverriding) { IsOverriding = isOverriding; }
423245431Sdim
424245431Sdim  /// \brief Return overridden methods for the given \p Method.
425245431Sdim  ///
426245431Sdim  /// An ObjC method is considered to override any method in the class's
427245431Sdim  /// base classes (and base's categories), its protocols, or its categories'
428245431Sdim  /// protocols, that has
429245431Sdim  /// the same selector and is of the same kind (class or instance).
430245431Sdim  /// A method in an implementation is not considered as overriding the same
431245431Sdim  /// method in the interface or its categories.
432245431Sdim  void getOverriddenMethods(
433245431Sdim                     SmallVectorImpl<const ObjCMethodDecl *> &Overridden) const;
434245431Sdim
435252723Sdim  /// \brief True if the method was a definition but its body was skipped.
436252723Sdim  bool hasSkippedBody() const { return HasSkippedBody; }
437252723Sdim  void setHasSkippedBody(bool Skipped = true) { HasSkippedBody = Skipped; }
438252723Sdim
439245431Sdim  /// \brief Returns the property associated with this method's selector.
440245431Sdim  ///
441245431Sdim  /// Note that even if this particular method is not marked as a property
442245431Sdim  /// accessor, it is still possible for it to match a property declared in a
443245431Sdim  /// superclass. Pass \c false if you only want to check the current class.
444245431Sdim  const ObjCPropertyDecl *findPropertyDecl(bool CheckOverrides = true) const;
445245431Sdim
446245431Sdim  // 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
454245431Sdim  /// \brief Determine whether this method has a body.
455263509Sdim  virtual bool hasBody() const { return Body.isValid(); }
456245431Sdim
457245431Sdim  /// \brief Retrieve the body of this method, if it has one.
458245431Sdim  virtual Stmt *getBody() const;
459245431Sdim
460245431Sdim  void setLazyBody(uint64_t Offset) { Body = Offset; }
461245431Sdim
462245431Sdim  CompoundStmt *getCompoundBody() { return (CompoundStmt*)getBody(); }
463193326Sed  void setBody(Stmt *B) { Body = B; }
464193326Sed
465198092Srdivacky  /// \brief Returns whether this specific method is a definition.
466263509Sdim  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  }
477226890Sdim
478226890Sdim  friend class ASTDeclReader;
479226890Sdim  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 {
487235633Sdim  virtual void anchor();
488235633Sdim
489226890Sdim  SourceLocation AtStart;
490226890Sdim
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
496226890Sdim  ObjCContainerDecl(Kind DK, DeclContext *DC,
497226890Sdim                    IdentifierInfo *Id, SourceLocation nameLoc,
498226890Sdim                    SourceLocation atStartLoc)
499226890Sdim    : 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.
540252723Sdim  ObjCMethodDecl *getMethod(Selector Sel, bool isInstance,
541252723Sdim                            bool AllowHidden = false) const;
542252723Sdim  ObjCMethodDecl *getInstanceMethod(Selector Sel,
543252723Sdim                                    bool AllowHidden = false) const {
544252723Sdim    return getMethod(Sel, true/*isInstance*/, AllowHidden);
545198092Srdivacky  }
546252723Sdim  ObjCMethodDecl *getClassMethod(Selector Sel, bool AllowHidden = false) const {
547252723Sdim    return getMethod(Sel, false/*isInstance*/, AllowHidden);
548198092Srdivacky  }
549252723Sdim  bool HasUserDeclaredSetterMethod(const ObjCPropertyDecl *P) const;
550195341Sed  ObjCIvarDecl *getIvarDecl(IdentifierInfo *Id) const;
551193326Sed
552195341Sed  ObjCPropertyDecl *FindPropertyDeclaration(IdentifierInfo *PropertyId) const;
553193326Sed
554245431Sdim  typedef llvm::DenseMap<IdentifierInfo*, ObjCPropertyDecl*> PropertyMap;
555252723Sdim
556263509Sdim  typedef llvm::DenseMap<const ObjCProtocolDecl *, ObjCPropertyDecl*>
557263509Sdim            ProtocolPropertyMap;
558263509Sdim
559252723Sdim  typedef llvm::SmallVector<ObjCPropertyDecl*, 8> PropertyDeclOrder;
560252723Sdim
561245431Sdim  /// This routine collects list of properties to be implemented in the class.
562245431Sdim  /// This includes, class's and its conforming protocols' properties.
563245431Sdim  /// Note, the superclass's properties are not included in the list.
564252723Sdim  virtual void collectPropertiesToImplement(PropertyMap &PM,
565252723Sdim                                            PropertyDeclOrder &PO) const {}
566245431Sdim
567226890Sdim  SourceLocation getAtStartLoc() const { return AtStart; }
568226890Sdim  void setAtStartLoc(SourceLocation Loc) { AtStart = Loc; }
569226890Sdim
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
578235633Sdim  virtual SourceRange getSourceRange() const LLVM_READONLY {
579226890Sdim    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
597245431Sdim/// \brief Represents an ObjC class declaration.
598193326Sed///
599245431Sdim/// For example:
600245431Sdim///
601245431Sdim/// \code
602193326Sed///   // MostPrimitive declares no super class (not particularly useful).
603245431Sdim///   \@interface MostPrimitive
604193326Sed///     // no instance variables or methods.
605245431Sdim///   \@end
606193326Sed///
607198092Srdivacky///   // NSResponder inherits from NSObject & implements NSCoding (a protocol).
608245431Sdim///   \@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
614245431Sdim///   \@end                                    // to an NSEvent.
615245431Sdim/// \endcode
616193326Sed///
617245431Sdim///   Unlike C/C++, forward class declarations are accomplished with \@class.
618245431Sdim///   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///
622235633Sdimclass ObjCInterfaceDecl : public ObjCContainerDecl
623235633Sdim                        , public Redeclarable<ObjCInterfaceDecl> {
624235633Sdim  virtual void anchor();
625235633Sdim
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;
630235633Sdim
631235633Sdim  struct DefinitionData {
632235633Sdim    /// \brief The definition of this class, for quick access from any
633235633Sdim    /// declaration.
634235633Sdim    ObjCInterfaceDecl *Definition;
635235633Sdim
636235633Sdim    /// Class's super class.
637235633Sdim    ObjCInterfaceDecl *SuperClass;
638198092Srdivacky
639245431Sdim    /// Protocols referenced in the \@interface  declaration
640235633Sdim    ObjCProtocolList ReferencedProtocols;
641198092Srdivacky
642245431Sdim    /// Protocols reference in both the \@interface and class extensions.
643235633Sdim    ObjCList<ObjCProtocolDecl> AllReferencedProtocols;
644198092Srdivacky
645235633Sdim    /// \brief List of categories and class extensions defined for this class.
646235633Sdim    ///
647235633Sdim    /// Categories are stored as a linked list in the AST, since the categories
648235633Sdim    /// and class extensions come long after the initial interface declaration,
649235633Sdim    /// and we avoid dynamically-resized arrays in the AST wherever possible.
650235633Sdim    ObjCCategoryDecl *CategoryList;
651198092Srdivacky
652235633Sdim    /// IvarList - List of all ivars defined by this class; including class
653235633Sdim    /// extensions and implementation. This list is built lazily.
654235633Sdim    ObjCIvarDecl *IvarList;
655193326Sed
656235633Sdim    /// \brief Indicates that the contents of this Objective-C class will be
657235633Sdim    /// completed by the external AST source when required.
658235633Sdim    mutable bool ExternallyCompleted : 1;
659235633Sdim
660252723Sdim    /// \brief Indicates that the ivar cache does not yet include ivars
661252723Sdim    /// declared in the implementation.
662252723Sdim    mutable bool IvarListMissingImplementation : 1;
663252723Sdim
664235633Sdim    /// \brief The location of the superclass, if any.
665235633Sdim    SourceLocation SuperClassLoc;
666235633Sdim
667235633Sdim    /// \brief The location of the last location in this declaration, before
668235633Sdim    /// the properties/methods. For example, this will be the '>', '}', or
669235633Sdim    /// identifier,
670235633Sdim    SourceLocation EndLoc;
671235633Sdim
672235633Sdim    DefinitionData() : Definition(), SuperClass(), CategoryList(), IvarList(),
673252723Sdim                       ExternallyCompleted(),
674252723Sdim                       IvarListMissingImplementation(true) { }
675235633Sdim  };
676235633Sdim
677193326Sed  ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
678235633Sdim                    SourceLocation CLoc, ObjCInterfaceDecl *PrevDecl,
679235633Sdim                    bool isInternal);
680198092Srdivacky
681218893Sdim  void LoadExternalDefinition() const;
682235633Sdim
683235633Sdim  /// \brief Contains a pointer to the data associated with this class,
684235633Sdim  /// which will be NULL if this class has not yet been defined.
685252723Sdim  ///
686252723Sdim  /// The bit indicates when we don't need to check for out-of-date
687252723Sdim  /// declarations. It will be set unless modules are enabled.
688252723Sdim  llvm::PointerIntPair<DefinitionData *, 1, bool> Data;
689235633Sdim
690235633Sdim  DefinitionData &data() const {
691252723Sdim    assert(Data.getPointer() && "Declaration has no definition!");
692252723Sdim    return *Data.getPointer();
693235633Sdim  }
694235633Sdim
695235633Sdim  /// \brief Allocate the definition data for this class.
696235633Sdim  void allocateDefinitionData();
697235633Sdim
698235633Sdim  typedef Redeclarable<ObjCInterfaceDecl> redeclarable_base;
699235633Sdim  virtual ObjCInterfaceDecl *getNextRedeclaration() {
700252723Sdim    return RedeclLink.getNext();
701235633Sdim  }
702235633Sdim  virtual ObjCInterfaceDecl *getPreviousDeclImpl() {
703235633Sdim    return getPreviousDecl();
704235633Sdim  }
705235633Sdim  virtual ObjCInterfaceDecl *getMostRecentDeclImpl() {
706235633Sdim    return getMostRecentDecl();
707235633Sdim  }
708235633Sdim
709193326Sedpublic:
710235633Sdim  static ObjCInterfaceDecl *Create(const ASTContext &C, DeclContext *DC,
711193326Sed                                   SourceLocation atLoc,
712198092Srdivacky                                   IdentifierInfo *Id,
713235633Sdim                                   ObjCInterfaceDecl *PrevDecl,
714193326Sed                                   SourceLocation ClassLoc = SourceLocation(),
715193326Sed                                   bool isInternal = false);
716235633Sdim
717235633Sdim  static ObjCInterfaceDecl *CreateDeserialized(ASTContext &C, unsigned ID);
718235633Sdim
719235633Sdim  virtual SourceRange getSourceRange() const LLVM_READONLY {
720235633Sdim    if (isThisDeclarationADefinition())
721235633Sdim      return ObjCContainerDecl::getSourceRange();
722235633Sdim
723235633Sdim    return SourceRange(getAtStartLoc(), getLocation());
724235633Sdim  }
725235633Sdim
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();
730235633Sdim
731202879Srdivacky  const ObjCProtocolList &getReferencedProtocols() const {
732235633Sdim    assert(hasDefinition() && "Caller did not check for forward reference!");
733235633Sdim    if (data().ExternallyCompleted)
734218893Sdim      LoadExternalDefinition();
735235633Sdim
736235633Sdim    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;
753235633Sdim
754212904Sdim  protocol_iterator protocol_begin() const {
755235633Sdim    // FIXME: Should make sure no callers ever do this.
756235633Sdim    if (!hasDefinition())
757235633Sdim      return protocol_iterator();
758235633Sdim
759235633Sdim    if (data().ExternallyCompleted)
760218893Sdim      LoadExternalDefinition();
761218893Sdim
762235633Sdim    return data().ReferencedProtocols.begin();
763212904Sdim  }
764212904Sdim  protocol_iterator protocol_end() const {
765235633Sdim    // FIXME: Should make sure no callers ever do this.
766235633Sdim    if (!hasDefinition())
767235633Sdim      return protocol_iterator();
768235633Sdim
769235633Sdim    if (data().ExternallyCompleted)
770218893Sdim      LoadExternalDefinition();
771218893Sdim
772235633Sdim    return data().ReferencedProtocols.end();
773212904Sdim  }
774212904Sdim
775202879Srdivacky  typedef ObjCProtocolList::loc_iterator protocol_loc_iterator;
776212904Sdim
777235633Sdim  protocol_loc_iterator protocol_loc_begin() const {
778235633Sdim    // FIXME: Should make sure no callers ever do this.
779235633Sdim    if (!hasDefinition())
780235633Sdim      return protocol_loc_iterator();
781235633Sdim
782235633Sdim    if (data().ExternallyCompleted)
783218893Sdim      LoadExternalDefinition();
784218893Sdim
785235633Sdim    return data().ReferencedProtocols.loc_begin();
786202879Srdivacky  }
787212904Sdim
788235633Sdim  protocol_loc_iterator protocol_loc_end() const {
789235633Sdim    // FIXME: Should make sure no callers ever do this.
790235633Sdim    if (!hasDefinition())
791235633Sdim      return protocol_loc_iterator();
792235633Sdim
793235633Sdim    if (data().ExternallyCompleted)
794218893Sdim      LoadExternalDefinition();
795218893Sdim
796235633Sdim    return data().ReferencedProtocols.loc_end();
797202879Srdivacky  }
798235633Sdim
799212904Sdim  typedef ObjCList<ObjCProtocolDecl>::iterator all_protocol_iterator;
800235633Sdim
801212904Sdim  all_protocol_iterator all_referenced_protocol_begin() const {
802235633Sdim    // FIXME: Should make sure no callers ever do this.
803235633Sdim    if (!hasDefinition())
804235633Sdim      return all_protocol_iterator();
805235633Sdim
806235633Sdim    if (data().ExternallyCompleted)
807218893Sdim      LoadExternalDefinition();
808218893Sdim
809235633Sdim    return data().AllReferencedProtocols.empty()
810235633Sdim             ? protocol_begin()
811235633Sdim             : data().AllReferencedProtocols.begin();
812212904Sdim  }
813212904Sdim  all_protocol_iterator all_referenced_protocol_end() const {
814235633Sdim    // FIXME: Should make sure no callers ever do this.
815235633Sdim    if (!hasDefinition())
816235633Sdim      return all_protocol_iterator();
817235633Sdim
818235633Sdim    if (data().ExternallyCompleted)
819218893Sdim      LoadExternalDefinition();
820218893Sdim
821235633Sdim    return data().AllReferencedProtocols.empty()
822235633Sdim             ? protocol_end()
823235633Sdim             : data().AllReferencedProtocols.end();
824212904Sdim  }
825193326Sed
826204643Srdivacky  typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator;
827212904Sdim
828235633Sdim  ivar_iterator ivar_begin() const {
829235633Sdim    if (const ObjCInterfaceDecl *Def = getDefinition())
830235633Sdim      return ivar_iterator(Def->decls_begin());
831235633Sdim
832235633Sdim    // FIXME: Should make sure no callers ever do this.
833235633Sdim    return ivar_iterator();
834235633Sdim  }
835235633Sdim  ivar_iterator ivar_end() const {
836235633Sdim    if (const ObjCInterfaceDecl *Def = getDefinition())
837235633Sdim      return ivar_iterator(Def->decls_end());
838212904Sdim
839235633Sdim    // FIXME: Should make sure no callers ever do this.
840235633Sdim    return ivar_iterator();
841235633Sdim  }
842235633Sdim
843204643Srdivacky  unsigned ivar_size() const {
844204643Srdivacky    return std::distance(ivar_begin(), ivar_end());
845204643Srdivacky  }
846235633Sdim
847204643Srdivacky  bool ivar_empty() const { return ivar_begin() == ivar_end(); }
848235633Sdim
849226890Sdim  ObjCIvarDecl *all_declared_ivar_begin();
850226890Sdim  const ObjCIvarDecl *all_declared_ivar_begin() const {
851226890Sdim    // Even though this modifies IvarList, it's conceptually const:
852226890Sdim    // the ivar chain is essentially a cached property of ObjCInterfaceDecl.
853226890Sdim    return const_cast<ObjCInterfaceDecl *>(this)->all_declared_ivar_begin();
854226890Sdim  }
855235633Sdim  void setIvarList(ObjCIvarDecl *ivar) { data().IvarList = ivar; }
856235633Sdim
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) {
861235633Sdim    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.
866235633Sdim  void mergeClassExtensionProtocolList(ObjCProtocolDecl *const* List,
867202879Srdivacky                                       unsigned Num,
868202879Srdivacky                                       ASTContext &C);
869198092Srdivacky
870235633Sdim  /// \brief Determine whether this particular declaration of this class is
871235633Sdim  /// actually also a definition.
872235633Sdim  bool isThisDeclarationADefinition() const {
873252723Sdim    return getDefinition() == this;
874235633Sdim  }
875235633Sdim
876235633Sdim  /// \brief Determine whether this class has been defined.
877252723Sdim  bool hasDefinition() const {
878252723Sdim    // If the name of this class is out-of-date, bring it up-to-date, which
879252723Sdim    // might bring in a definition.
880252723Sdim    // Note: a null value indicates that we don't have a definition and that
881252723Sdim    // modules are enabled.
882252723Sdim    if (!Data.getOpaqueValue()) {
883252723Sdim      if (IdentifierInfo *II = getIdentifier()) {
884252723Sdim        if (II->isOutOfDate()) {
885252723Sdim          updateOutOfDate(*II);
886252723Sdim        }
887252723Sdim      }
888252723Sdim    }
889252723Sdim
890252723Sdim    return Data.getPointer();
891252723Sdim  }
892235633Sdim
893235633Sdim  /// \brief Retrieve the definition of this class, or NULL if this class
894245431Sdim  /// has been forward-declared (with \@class) but not yet defined (with
895245431Sdim  /// \@interface).
896235633Sdim  ObjCInterfaceDecl *getDefinition() {
897252723Sdim    return hasDefinition()? Data.getPointer()->Definition : 0;
898235633Sdim  }
899198092Srdivacky
900235633Sdim  /// \brief Retrieve the definition of this class, or NULL if this class
901245431Sdim  /// has been forward-declared (with \@class) but not yet defined (with
902245431Sdim  /// \@interface).
903235633Sdim  const ObjCInterfaceDecl *getDefinition() const {
904252723Sdim    return hasDefinition()? Data.getPointer()->Definition : 0;
905235633Sdim  }
906235633Sdim
907235633Sdim  /// \brief Starts the definition of this Objective-C class, taking it from
908245431Sdim  /// a forward declaration (\@class) to a definition (\@interface).
909235633Sdim  void startDefinition();
910235633Sdim
911235633Sdim  ObjCInterfaceDecl *getSuperClass() const {
912235633Sdim    // FIXME: Should make sure no callers ever do this.
913235633Sdim    if (!hasDefinition())
914235633Sdim      return 0;
915235633Sdim
916235633Sdim    if (data().ExternallyCompleted)
917218893Sdim      LoadExternalDefinition();
918218893Sdim
919235633Sdim    return data().SuperClass;
920218893Sdim  }
921198092Srdivacky
922235633Sdim  void setSuperClass(ObjCInterfaceDecl * superCls) {
923235633Sdim    data().SuperClass =
924235633Sdim      (superCls && superCls->hasDefinition()) ? superCls->getDefinition()
925235633Sdim                                              : superCls;
926235633Sdim  }
927235633Sdim
928252723Sdim  /// \brief Iterator that walks over the list of categories, filtering out
929252723Sdim  /// those that do not meet specific criteria.
930252723Sdim  ///
931252723Sdim  /// This class template is used for the various permutations of category
932252723Sdim  /// and extension iterators.
933252723Sdim  template<bool (*Filter)(ObjCCategoryDecl *)>
934252723Sdim  class filtered_category_iterator {
935252723Sdim    ObjCCategoryDecl *Current;
936252723Sdim
937252723Sdim    void findAcceptableCategory();
938252723Sdim
939252723Sdim  public:
940252723Sdim    typedef ObjCCategoryDecl *      value_type;
941252723Sdim    typedef value_type              reference;
942252723Sdim    typedef value_type              pointer;
943252723Sdim    typedef std::ptrdiff_t          difference_type;
944252723Sdim    typedef std::input_iterator_tag iterator_category;
945252723Sdim
946252723Sdim    filtered_category_iterator() : Current(0) { }
947252723Sdim    explicit filtered_category_iterator(ObjCCategoryDecl *Current)
948252723Sdim      : Current(Current)
949252723Sdim    {
950252723Sdim      findAcceptableCategory();
951252723Sdim    }
952252723Sdim
953252723Sdim    reference operator*() const { return Current; }
954252723Sdim    pointer operator->() const { return Current; }
955252723Sdim
956252723Sdim    filtered_category_iterator &operator++();
957252723Sdim
958252723Sdim    filtered_category_iterator operator++(int) {
959252723Sdim      filtered_category_iterator Tmp = *this;
960252723Sdim      ++(*this);
961252723Sdim      return Tmp;
962252723Sdim    }
963252723Sdim
964252723Sdim    friend bool operator==(filtered_category_iterator X,
965252723Sdim                           filtered_category_iterator Y) {
966252723Sdim      return X.Current == Y.Current;
967252723Sdim    }
968252723Sdim
969252723Sdim    friend bool operator!=(filtered_category_iterator X,
970252723Sdim                           filtered_category_iterator Y) {
971252723Sdim      return X.Current != Y.Current;
972252723Sdim    }
973252723Sdim  };
974252723Sdim
975252723Sdimprivate:
976252723Sdim  /// \brief Test whether the given category is visible.
977252723Sdim  ///
978252723Sdim  /// Used in the \c visible_categories_iterator.
979252723Sdim  static bool isVisibleCategory(ObjCCategoryDecl *Cat);
980252723Sdim
981252723Sdimpublic:
982252723Sdim  /// \brief Iterator that walks over the list of categories and extensions
983252723Sdim  /// that are visible, i.e., not hidden in a non-imported submodule.
984252723Sdim  typedef filtered_category_iterator<isVisibleCategory>
985252723Sdim    visible_categories_iterator;
986252723Sdim
987252723Sdim  /// \brief Retrieve an iterator to the beginning of the visible-categories
988252723Sdim  /// list.
989252723Sdim  visible_categories_iterator visible_categories_begin() const {
990252723Sdim    return visible_categories_iterator(getCategoryListRaw());
991252723Sdim  }
992252723Sdim
993252723Sdim  /// \brief Retrieve an iterator to the end of the visible-categories list.
994252723Sdim  visible_categories_iterator visible_categories_end() const {
995252723Sdim    return visible_categories_iterator();
996252723Sdim  }
997252723Sdim
998252723Sdim  /// \brief Determine whether the visible-categories list is empty.
999252723Sdim  bool visible_categories_empty() const {
1000252723Sdim    return visible_categories_begin() == visible_categories_end();
1001252723Sdim  }
1002252723Sdim
1003252723Sdimprivate:
1004252723Sdim  /// \brief Test whether the given category... is a category.
1005252723Sdim  ///
1006252723Sdim  /// Used in the \c known_categories_iterator.
1007252723Sdim  static bool isKnownCategory(ObjCCategoryDecl *) { return true; }
1008252723Sdim
1009252723Sdimpublic:
1010252723Sdim  /// \brief Iterator that walks over all of the known categories and
1011252723Sdim  /// extensions, including those that are hidden.
1012252723Sdim  typedef filtered_category_iterator<isKnownCategory> known_categories_iterator;
1013252723Sdim
1014252723Sdim  /// \brief Retrieve an iterator to the beginning of the known-categories
1015252723Sdim  /// list.
1016252723Sdim  known_categories_iterator known_categories_begin() const {
1017252723Sdim    return known_categories_iterator(getCategoryListRaw());
1018252723Sdim  }
1019252723Sdim
1020252723Sdim  /// \brief Retrieve an iterator to the end of the known-categories list.
1021252723Sdim  known_categories_iterator known_categories_end() const {
1022252723Sdim    return known_categories_iterator();
1023252723Sdim  }
1024252723Sdim
1025252723Sdim  /// \brief Determine whether the known-categories list is empty.
1026252723Sdim  bool known_categories_empty() const {
1027252723Sdim    return known_categories_begin() == known_categories_end();
1028252723Sdim  }
1029252723Sdim
1030252723Sdimprivate:
1031252723Sdim  /// \brief Test whether the given category is a visible extension.
1032252723Sdim  ///
1033252723Sdim  /// Used in the \c visible_extensions_iterator.
1034252723Sdim  static bool isVisibleExtension(ObjCCategoryDecl *Cat);
1035252723Sdim
1036252723Sdimpublic:
1037252723Sdim  /// \brief Iterator that walks over all of the visible extensions, skipping
1038252723Sdim  /// any that are known but hidden.
1039252723Sdim  typedef filtered_category_iterator<isVisibleExtension>
1040252723Sdim    visible_extensions_iterator;
1041252723Sdim
1042252723Sdim  /// \brief Retrieve an iterator to the beginning of the visible-extensions
1043252723Sdim  /// list.
1044252723Sdim  visible_extensions_iterator visible_extensions_begin() const {
1045252723Sdim    return visible_extensions_iterator(getCategoryListRaw());
1046252723Sdim  }
1047252723Sdim
1048252723Sdim  /// \brief Retrieve an iterator to the end of the visible-extensions list.
1049252723Sdim  visible_extensions_iterator visible_extensions_end() const {
1050252723Sdim    return visible_extensions_iterator();
1051252723Sdim  }
1052252723Sdim
1053252723Sdim  /// \brief Determine whether the visible-extensions list is empty.
1054252723Sdim  bool visible_extensions_empty() const {
1055252723Sdim    return visible_extensions_begin() == visible_extensions_end();
1056252723Sdim  }
1057252723Sdim
1058252723Sdimprivate:
1059252723Sdim  /// \brief Test whether the given category is an extension.
1060252723Sdim  ///
1061252723Sdim  /// Used in the \c known_extensions_iterator.
1062252723Sdim  static bool isKnownExtension(ObjCCategoryDecl *Cat);
1063252723Sdim
1064252723Sdimpublic:
1065252723Sdim  /// \brief Iterator that walks over all of the known extensions.
1066252723Sdim  typedef filtered_category_iterator<isKnownExtension>
1067252723Sdim    known_extensions_iterator;
1068252723Sdim
1069252723Sdim  /// \brief Retrieve an iterator to the beginning of the known-extensions
1070252723Sdim  /// list.
1071252723Sdim  known_extensions_iterator known_extensions_begin() const {
1072252723Sdim    return known_extensions_iterator(getCategoryListRaw());
1073252723Sdim  }
1074252723Sdim
1075252723Sdim  /// \brief Retrieve an iterator to the end of the known-extensions list.
1076252723Sdim  known_extensions_iterator known_extensions_end() const {
1077252723Sdim    return known_extensions_iterator();
1078252723Sdim  }
1079252723Sdim
1080252723Sdim  /// \brief Determine whether the known-extensions list is empty.
1081252723Sdim  bool known_extensions_empty() const {
1082252723Sdim    return known_extensions_begin() == known_extensions_end();
1083252723Sdim  }
1084252723Sdim
1085252723Sdim  /// \brief Retrieve the raw pointer to the start of the category/extension
1086252723Sdim  /// list.
1087252723Sdim  ObjCCategoryDecl* getCategoryListRaw() const {
1088235633Sdim    // FIXME: Should make sure no callers ever do this.
1089235633Sdim    if (!hasDefinition())
1090235633Sdim      return 0;
1091235633Sdim
1092235633Sdim    if (data().ExternallyCompleted)
1093218893Sdim      LoadExternalDefinition();
1094218893Sdim
1095235633Sdim    return data().CategoryList;
1096218893Sdim  }
1097235633Sdim
1098252723Sdim  /// \brief Set the raw pointer to the start of the category/extension
1099252723Sdim  /// list.
1100252723Sdim  void setCategoryListRaw(ObjCCategoryDecl *category) {
1101235633Sdim    data().CategoryList = category;
1102193326Sed  }
1103235633Sdim
1104205219Srdivacky  ObjCPropertyDecl
1105205219Srdivacky    *FindPropertyVisibleInPrimaryClass(IdentifierInfo *PropertyId) const;
1106205219Srdivacky
1107252723Sdim  virtual void collectPropertiesToImplement(PropertyMap &PM,
1108252723Sdim                                            PropertyDeclOrder &PO) const;
1109245431Sdim
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) {
1115235633Sdim      if (declaresSameEntity(this, I))
1116193326Sed        return true;
1117235633Sdim
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.
1125252723Sdim  bool isArcWeakrefUnavailable() const;
1126224145Sdim
1127235633Sdim  /// isObjCRequiresPropertyDefs - Checks that a class or one of its super
1128245431Sdim  /// classes must not be auto-synthesized. Returns class decl. if it must not
1129245431Sdim  /// be; 0, otherwise.
1130252723Sdim  const ObjCInterfaceDecl *isObjCRequiresPropertyDefs() const;
1131235633Sdim
1132195341Sed  ObjCIvarDecl *lookupInstanceVariable(IdentifierInfo *IVarName,
1133193326Sed                                       ObjCInterfaceDecl *&ClassDeclared);
1134195341Sed  ObjCIvarDecl *lookupInstanceVariable(IdentifierInfo *IVarName) {
1135193326Sed    ObjCInterfaceDecl *ClassDeclared;
1136195341Sed    return lookupInstanceVariable(IVarName, ClassDeclared);
1137193326Sed  }
1138193326Sed
1139263509Sdim  ObjCProtocolDecl *lookupNestedProtocol(IdentifierInfo *Name);
1140263509Sdim
1141193326Sed  // Lookup a method. First, we search locally. If a method isn't
1142193326Sed  // found, we search referenced protocols and class categories.
1143235633Sdim  ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance,
1144252723Sdim                               bool shallowCategoryLookup= false,
1145252723Sdim                               const ObjCCategoryDecl *C= 0) const;
1146235633Sdim  ObjCMethodDecl *lookupInstanceMethod(Selector Sel,
1147235633Sdim                            bool shallowCategoryLookup = false) const {
1148235633Sdim    return lookupMethod(Sel, true/*isInstance*/, shallowCategoryLookup);
1149198092Srdivacky  }
1150235633Sdim  ObjCMethodDecl *lookupClassMethod(Selector Sel,
1151235633Sdim                     bool shallowCategoryLookup = false) const {
1152235633Sdim    return lookupMethod(Sel, false/*isInstance*/, shallowCategoryLookup);
1153198092Srdivacky  }
1154193326Sed  ObjCInterfaceDecl *lookupInheritedClass(const IdentifierInfo *ICName);
1155235633Sdim
1156245431Sdim  /// \brief Lookup a method in the classes implementation hierarchy.
1157245431Sdim  ObjCMethodDecl *lookupPrivateMethod(const Selector &Sel,
1158245431Sdim                                      bool Instance=true) const;
1159193326Sed
1160245431Sdim  ObjCMethodDecl *lookupPrivateClassMethod(const Selector &Sel) {
1161245431Sdim    return lookupPrivateMethod(Sel, false);
1162245431Sdim  }
1163245431Sdim
1164252723Sdim  /// \brief Lookup a setter or getter in the class hierarchy,
1165252723Sdim  /// including in all categories except for category passed
1166252723Sdim  /// as argument.
1167252723Sdim  ObjCMethodDecl *lookupPropertyAccessor(const Selector Sel,
1168252723Sdim                                         const ObjCCategoryDecl *Cat) const {
1169252723Sdim    return lookupMethod(Sel, true/*isInstance*/,
1170252723Sdim                        false/*shallowCategoryLookup*/, Cat);
1171252723Sdim  }
1172252723Sdim
1173235633Sdim  SourceLocation getEndOfDefinitionLoc() const {
1174235633Sdim    if (!hasDefinition())
1175235633Sdim      return getLocation();
1176235633Sdim
1177235633Sdim    return data().EndLoc;
1178235633Sdim  }
1179235633Sdim
1180235633Sdim  void setEndOfDefinitionLoc(SourceLocation LE) { data().EndLoc = LE; }
1181198092Srdivacky
1182235633Sdim  void setSuperClassLoc(SourceLocation Loc) { data().SuperClassLoc = Loc; }
1183235633Sdim  SourceLocation getSuperClassLoc() const { return data().SuperClassLoc; }
1184198092Srdivacky
1185193326Sed  /// isImplicitInterfaceDecl - check that this is an implicitly declared
1186245431Sdim  /// ObjCInterfaceDecl node. This is for legacy objective-c \@implementation
1187245431Sdim  /// declaration without an \@interface declaration.
1188235633Sdim  bool isImplicitInterfaceDecl() const {
1189252723Sdim    return hasDefinition() ? data().Definition->isImplicit() : isImplicit();
1190235633Sdim  }
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
1199235633Sdim  typedef redeclarable_base::redecl_iterator redecl_iterator;
1200235633Sdim  using redeclarable_base::redecls_begin;
1201235633Sdim  using redeclarable_base::redecls_end;
1202235633Sdim  using redeclarable_base::getPreviousDecl;
1203235633Sdim  using redeclarable_base::getMostRecentDecl;
1204263509Sdim  using redeclarable_base::isFirstDecl;
1205235633Sdim
1206235633Sdim  /// Retrieves the canonical declaration of this Objective-C class.
1207263509Sdim  ObjCInterfaceDecl *getCanonicalDecl() { return getFirstDecl(); }
1208263509Sdim  const ObjCInterfaceDecl *getCanonicalDecl() const { return getFirstDecl(); }
1209235633Sdim
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
1217235633Sdim  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///
1226245431Sdim///   \@interface IvarExample : NSObject
1227193326Sed///   {
1228193326Sed///     id defaultToProtected;
1229245431Sdim///   \@public:
1230193326Sed///     id canBePublic; // same as C++.
1231245431Sdim///   \@protected:
1232193326Sed///     id canBeProtected; // same as C++.
1233245431Sdim///   \@package:
1234193326Sed///     id canBePackage; // framework visibility (not available in C++).
1235193326Sed///   }
1236193326Sed///
1237193326Sedclass ObjCIvarDecl : public FieldDecl {
1238235633Sdim  virtual void anchor();
1239235633Sdim
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,
1249263509Sdim               bool synthesized,
1250263509Sdim               bool backingIvarReferencedInAccessor)
1251221345Sdim    : FieldDecl(ObjCIvar, DC, StartLoc, IdLoc, Id, T, TInfo, BW,
1252245431Sdim                /*Mutable=*/false, /*HasInit=*/ICIS_NoInit),
1253263509Sdim      NextIvar(0), DeclAccess(ac), Synthesized(synthesized),
1254263509Sdim      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,
1262263509Sdim                              bool synthesized=false,
1263263509Sdim                              bool backingIvarReferencedInAccessor=false);
1264198092Srdivacky
1265235633Sdim  static ObjCIvarDecl *CreateDeserialized(ASTContext &C, unsigned ID);
1266235633Sdim
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;
1272235633Sdim
1273212904Sdim  ObjCIvarDecl *getNextIvar() { return NextIvar; }
1274226890Sdim  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
1285263509Sdim  void setBackingIvarReferencedInAccessor(bool val) {
1286263509Sdim    BackingIvarReferencedInAccessor = val;
1287263509Sdim  }
1288263509Sdim  bool getBackingIvarReferencedInAccessor() const {
1289263509Sdim    return BackingIvarReferencedInAccessor;
1290263509Sdim  }
1291263509Sdim
1292212904Sdim  void setSynthesize(bool synth) { Synthesized = synth; }
1293212904Sdim  bool getSynthesize() const { return Synthesized; }
1294235633Sdim
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:
1299235633Sdim  /// NextIvar - Next Ivar in the list of ivars declared in class; class's
1300212904Sdim  /// extensions and class's implementation
1301212904Sdim  ObjCIvarDecl *NextIvar;
1302235633Sdim
1303193326Sed  // NOTE: VC++ treats enums as signed, avoid using the AccessControl enum
1304193326Sed  unsigned DeclAccess : 3;
1305212904Sdim  unsigned Synthesized : 1;
1306263509Sdim  unsigned BackingIvarReferencedInAccessor : 1;
1307193326Sed};
1308193326Sed
1309198092Srdivacky
1310245431Sdim/// \brief Represents a field declaration created by an \@defs(...).
1311193326Sedclass ObjCAtDefsFieldDecl : public FieldDecl {
1312235633Sdim  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 ?
1318245431Sdim                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
1326235633Sdim  static ObjCAtDefsFieldDecl *CreateDeserialized(ASTContext &C, unsigned ID);
1327235633Sdim
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
1333245431Sdim/// \brief Represents an Objective-C protocol declaration.
1334193326Sed///
1335245431Sdim/// Objective-C protocols declare a pure abstract type (i.e., no instance
1336245431Sdim/// variables are permitted).  Protocols originally drew inspiration from
1337245431Sdim/// C++ pure virtual functions (a C++ feature with nice semantics and lousy
1338245431Sdim/// syntax:-). Here is an example:
1339245431Sdim///
1340245431Sdim/// \code
1341245431Sdim/// \@protocol NSDraggingInfo <refproto1, refproto2>
1342193326Sed/// - (NSWindow *)draggingDestinationWindow;
1343193326Sed/// - (NSImage *)draggedImage;
1344245431Sdim/// \@end
1345245431Sdim/// \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///
1351245431Sdim/// \code
1352245431Sdim/// \@interface ImplementsNSDraggingInfo : NSObject \<NSDraggingInfo>
1353245431Sdim/// \@end
1354245431Sdim/// \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///
1361245431Sdim/// id \<NSDraggingInfo> anyObjectThatImplementsNSDraggingInfo;
1362193326Sed///
1363235633Sdimclass ObjCProtocolDecl : public ObjCContainerDecl,
1364235633Sdim                         public Redeclarable<ObjCProtocolDecl> {
1365235633Sdim  virtual void anchor();
1366198092Srdivacky
1367235633Sdim  struct DefinitionData {
1368235633Sdim    // \brief The declaration that defines this protocol.
1369235633Sdim    ObjCProtocolDecl *Definition;
1370198092Srdivacky
1371235633Sdim    /// \brief Referenced protocols
1372235633Sdim    ObjCProtocolList ReferencedProtocols;
1373235633Sdim  };
1374198092Srdivacky
1375252723Sdim  /// \brief Contains a pointer to the data associated with this class,
1376252723Sdim  /// which will be NULL if this class has not yet been defined.
1377252723Sdim  ///
1378252723Sdim  /// The bit indicates when we don't need to check for out-of-date
1379252723Sdim  /// declarations. It will be set unless modules are enabled.
1380252723Sdim  llvm::PointerIntPair<DefinitionData *, 1, bool> Data;
1381252723Sdim
1382235633Sdim  DefinitionData &data() const {
1383252723Sdim    assert(Data.getPointer() && "Objective-C protocol has no definition!");
1384252723Sdim    return *Data.getPointer();
1385235633Sdim  }
1386235633Sdim
1387226890Sdim  ObjCProtocolDecl(DeclContext *DC, IdentifierInfo *Id,
1388235633Sdim                   SourceLocation nameLoc, SourceLocation atStartLoc,
1389235633Sdim                   ObjCProtocolDecl *PrevDecl);
1390235633Sdim
1391235633Sdim  void allocateDefinitionData();
1392235633Sdim
1393235633Sdim  typedef Redeclarable<ObjCProtocolDecl> redeclarable_base;
1394235633Sdim  virtual ObjCProtocolDecl *getNextRedeclaration() {
1395235633Sdim    return RedeclLink.getNext();
1396193326Sed  }
1397235633Sdim  virtual ObjCProtocolDecl *getPreviousDeclImpl() {
1398235633Sdim    return getPreviousDecl();
1399235633Sdim  }
1400235633Sdim  virtual ObjCProtocolDecl *getMostRecentDeclImpl() {
1401235633Sdim    return getMostRecentDecl();
1402235633Sdim  }
1403252723Sdim
1404193326Sedpublic:
1405198092Srdivacky  static ObjCProtocolDecl *Create(ASTContext &C, DeclContext *DC,
1406226890Sdim                                  IdentifierInfo *Id,
1407226890Sdim                                  SourceLocation nameLoc,
1408235633Sdim                                  SourceLocation atStartLoc,
1409235633Sdim                                  ObjCProtocolDecl *PrevDecl);
1410193326Sed
1411235633Sdim  static ObjCProtocolDecl *CreateDeserialized(ASTContext &C, unsigned ID);
1412235633Sdim
1413202879Srdivacky  const ObjCProtocolList &getReferencedProtocols() const {
1414235633Sdim    assert(hasDefinition() && "No definition available!");
1415235633Sdim    return data().ReferencedProtocols;
1416193326Sed  }
1417202879Srdivacky  typedef ObjCProtocolList::iterator protocol_iterator;
1418235633Sdim  protocol_iterator protocol_begin() const {
1419235633Sdim    if (!hasDefinition())
1420235633Sdim      return protocol_iterator();
1421235633Sdim
1422235633Sdim    return data().ReferencedProtocols.begin();
1423235633Sdim  }
1424235633Sdim  protocol_iterator protocol_end() const {
1425235633Sdim    if (!hasDefinition())
1426235633Sdim      return protocol_iterator();
1427235633Sdim
1428235633Sdim    return data().ReferencedProtocols.end();
1429235633Sdim  }
1430202879Srdivacky  typedef ObjCProtocolList::loc_iterator protocol_loc_iterator;
1431235633Sdim  protocol_loc_iterator protocol_loc_begin() const {
1432235633Sdim    if (!hasDefinition())
1433235633Sdim      return protocol_loc_iterator();
1434235633Sdim
1435235633Sdim    return data().ReferencedProtocols.loc_begin();
1436202879Srdivacky  }
1437235633Sdim  protocol_loc_iterator protocol_loc_end() const {
1438235633Sdim    if (!hasDefinition())
1439235633Sdim      return protocol_loc_iterator();
1440235633Sdim
1441235633Sdim    return data().ReferencedProtocols.loc_end();
1442202879Srdivacky  }
1443235633Sdim  unsigned protocol_size() const {
1444235633Sdim    if (!hasDefinition())
1445235633Sdim      return 0;
1446235633Sdim
1447235633Sdim    return data().ReferencedProtocols.size();
1448235633Sdim  }
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) {
1454252723Sdim    assert(hasDefinition() && "Protocol is not defined");
1455235633Sdim    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
1470235633Sdim  /// \brief Determine whether this protocol has a definition.
1471252723Sdim  bool hasDefinition() const {
1472252723Sdim    // If the name of this protocol is out-of-date, bring it up-to-date, which
1473252723Sdim    // might bring in a definition.
1474252723Sdim    // Note: a null value indicates that we don't have a definition and that
1475252723Sdim    // modules are enabled.
1476252723Sdim    if (!Data.getOpaqueValue()) {
1477252723Sdim      if (IdentifierInfo *II = getIdentifier()) {
1478252723Sdim        if (II->isOutOfDate()) {
1479252723Sdim          updateOutOfDate(*II);
1480252723Sdim        }
1481252723Sdim      }
1482252723Sdim    }
1483198092Srdivacky
1484252723Sdim    return Data.getPointer();
1485252723Sdim  }
1486252723Sdim
1487235633Sdim  /// \brief Retrieve the definition of this protocol, if any.
1488235633Sdim  ObjCProtocolDecl *getDefinition() {
1489252723Sdim    return hasDefinition()? Data.getPointer()->Definition : 0;
1490235633Sdim  }
1491198092Srdivacky
1492235633Sdim  /// \brief Retrieve the definition of this protocol, if any.
1493235633Sdim  const ObjCProtocolDecl *getDefinition() const {
1494252723Sdim    return hasDefinition()? Data.getPointer()->Definition : 0;
1495235633Sdim  }
1496198092Srdivacky
1497235633Sdim  /// \brief Determine whether this particular declaration is also the
1498235633Sdim  /// definition.
1499235633Sdim  bool isThisDeclarationADefinition() const {
1500235633Sdim    return getDefinition() == this;
1501235633Sdim  }
1502199482Srdivacky
1503235633Sdim  /// \brief Starts the definition of this Objective-C protocol.
1504235633Sdim  void startDefinition();
1505198092Srdivacky
1506235633Sdim  virtual SourceRange getSourceRange() const LLVM_READONLY {
1507235633Sdim    if (isThisDeclarationADefinition())
1508235633Sdim      return ObjCContainerDecl::getSourceRange();
1509235633Sdim
1510235633Sdim    return SourceRange(getAtStartLoc(), getLocation());
1511202879Srdivacky  }
1512235633Sdim
1513235633Sdim  typedef redeclarable_base::redecl_iterator redecl_iterator;
1514235633Sdim  using redeclarable_base::redecls_begin;
1515235633Sdim  using redeclarable_base::redecls_end;
1516235633Sdim  using redeclarable_base::getPreviousDecl;
1517235633Sdim  using redeclarable_base::getMostRecentDecl;
1518263509Sdim  using redeclarable_base::isFirstDecl;
1519202879Srdivacky
1520235633Sdim  /// Retrieves the canonical declaration of this Objective-C protocol.
1521263509Sdim  ObjCProtocolDecl *getCanonicalDecl() { return getFirstDecl(); }
1522263509Sdim  const ObjCProtocolDecl *getCanonicalDecl() const { return getFirstDecl(); }
1523202879Srdivacky
1524252723Sdim  virtual void collectPropertiesToImplement(PropertyMap &PM,
1525252723Sdim                                            PropertyDeclOrder &PO) const;
1526263509Sdim
1527263509Sdimvoid collectInheritedProtocolProperties(const ObjCPropertyDecl *Property,
1528263509Sdim                                        ProtocolPropertyMap &PM) const;
1529245431Sdim
1530235633Sdim  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
1531235633Sdim  static bool classofKind(Kind K) { return K == ObjCProtocol; }
1532193326Sed
1533235633Sdim  friend class ASTReader;
1534235633Sdim  friend class ASTDeclReader;
1535235633Sdim  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///
1544245431Sdim/// \@interface NSView (MyViewMethods)
1545193326Sed/// - myMethod;
1546245431Sdim/// \@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 {
1556235633Sdim  virtual void anchor();
1557235633Sdim
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
1571235633Sdim  /// class extension may have private ivars.
1572235633Sdim  SourceLocation IvarLBraceLoc;
1573235633Sdim  SourceLocation IvarRBraceLoc;
1574235633Sdim
1575235633Sdim  ObjCCategoryDecl(DeclContext *DC, SourceLocation AtLoc,
1576202879Srdivacky                   SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc,
1577235633Sdim                   IdentifierInfo *Id, ObjCInterfaceDecl *IDecl,
1578235633Sdim                   SourceLocation IvarLBraceLoc=SourceLocation(),
1579235633Sdim                   SourceLocation IvarRBraceLoc=SourceLocation())
1580226890Sdim    : ObjCContainerDecl(ObjCCategory, DC, Id, ClassNameLoc, AtLoc),
1581245431Sdim      ClassInterface(IDecl), NextClassCategory(0),
1582235633Sdim      CategoryNameLoc(CategoryNameLoc),
1583235633Sdim      IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc) {
1584193326Sed  }
1585252723Sdim
1586193326Sedpublic:
1587198092Srdivacky
1588193326Sed  static ObjCCategoryDecl *Create(ASTContext &C, DeclContext *DC,
1589235633Sdim                                  SourceLocation AtLoc,
1590202879Srdivacky                                  SourceLocation ClassNameLoc,
1591202879Srdivacky                                  SourceLocation CategoryNameLoc,
1592226890Sdim                                  IdentifierInfo *Id,
1593235633Sdim                                  ObjCInterfaceDecl *IDecl,
1594235633Sdim                                  SourceLocation IvarLBraceLoc=SourceLocation(),
1595235633Sdim                                  SourceLocation IvarRBraceLoc=SourceLocation());
1596235633Sdim  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;
1620235633Sdim  protocol_loc_iterator protocol_loc_begin() const {
1621235633Sdim    return ReferencedProtocols.loc_begin();
1622202879Srdivacky  }
1623235633Sdim  protocol_loc_iterator protocol_loc_end() const {
1624235633Sdim    return ReferencedProtocols.loc_end();
1625202879Srdivacky  }
1626198092Srdivacky
1627193326Sed  ObjCCategoryDecl *getNextClassCategory() const { return NextClassCategory; }
1628198092Srdivacky
1629252723Sdim  /// \brief Retrieve the pointer to the next stored category (or extension),
1630252723Sdim  /// which may be hidden.
1631252723Sdim  ObjCCategoryDecl *getNextClassCategoryRaw() const {
1632252723Sdim    return NextClassCategory;
1633252723Sdim  }
1634252723Sdim
1635203955Srdivacky  bool IsClassExtension() const { return getIdentifier() == 0; }
1636235633Sdim
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; }
1653235633Sdim
1654235633Sdim  void setIvarLBraceLoc(SourceLocation Loc) { IvarLBraceLoc = Loc; }
1655235633Sdim  SourceLocation getIvarLBraceLoc() const { return IvarLBraceLoc; }
1656235633Sdim  void setIvarRBraceLoc(SourceLocation Loc) { IvarRBraceLoc = Loc; }
1657235633Sdim  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; }
1661226890Sdim
1662226890Sdim  friend class ASTDeclReader;
1663226890Sdim  friend class ASTDeclWriter;
1664193326Sed};
1665193326Sed
1666198092Srdivackyclass ObjCImplDecl : public ObjCContainerDecl {
1667235633Sdim  virtual void anchor();
1668235633Sdim
1669198893Srdivacky  /// Class interface for this class/category implementation
1670193326Sed  ObjCInterfaceDecl *ClassInterface;
1671198092Srdivacky
1672193326Sedprotected:
1673226890Sdim  ObjCImplDecl(Kind DK, DeclContext *DC,
1674226890Sdim               ObjCInterfaceDecl *classInterface,
1675226890Sdim               SourceLocation nameLoc, SourceLocation atStartLoc)
1676226890Sdim    : ObjCContainerDecl(DK, DC,
1677226890Sdim                        classInterface? classInterface->getIdentifier() : 0,
1678226890Sdim                        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
1718245431Sdim/// \@implementation declaration. If a category class has declaration of a
1719198092Srdivacky/// property, its implementation must be specified in the category's
1720245431Sdim/// \@implementation declaration. Example:
1721245431Sdim/// \@interface I \@end
1722245431Sdim/// \@interface I(CATEGORY)
1723245431Sdim///    \@property int p1, d1;
1724245431Sdim/// \@end
1725245431Sdim/// \@implementation I(CATEGORY)
1726245431Sdim///  \@dynamic p1,d1;
1727245431Sdim/// \@end
1728193326Sed///
1729193326Sed/// ObjCCategoryImplDecl
1730193326Sedclass ObjCCategoryImplDecl : public ObjCImplDecl {
1731235633Sdim  virtual void anchor();
1732235633Sdim
1733193326Sed  // Category name
1734193326Sed  IdentifierInfo *Id;
1735193326Sed
1736235633Sdim  // Category name location
1737235633Sdim  SourceLocation CategoryNameLoc;
1738235633Sdim
1739226890Sdim  ObjCCategoryImplDecl(DeclContext *DC, IdentifierInfo *Id,
1740226890Sdim                       ObjCInterfaceDecl *classInterface,
1741235633Sdim                       SourceLocation nameLoc, SourceLocation atStartLoc,
1742235633Sdim                       SourceLocation CategoryNameLoc)
1743226890Sdim    : ObjCImplDecl(ObjCCategoryImpl, DC, classInterface, nameLoc, atStartLoc),
1744235633Sdim      Id(Id), CategoryNameLoc(CategoryNameLoc) {}
1745193326Sedpublic:
1746193326Sed  static ObjCCategoryImplDecl *Create(ASTContext &C, DeclContext *DC,
1747226890Sdim                                      IdentifierInfo *Id,
1748226890Sdim                                      ObjCInterfaceDecl *classInterface,
1749226890Sdim                                      SourceLocation nameLoc,
1750235633Sdim                                      SourceLocation atStartLoc,
1751235633Sdim                                      SourceLocation CategoryNameLoc);
1752235633Sdim  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:
1758235633Sdim  /// ((NamedDecl *)SomeCategoryImplDecl)->getIdentifier()
1759235633Sdim  /// returns the class interface name, whereas
1760235633Sdim  /// ((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
1769235633Sdim  SourceLocation getCategoryNameLoc() const { return CategoryNameLoc; }
1770235633Sdim
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.
1776226890Sdim  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;}
1789235633Sdim
1790235633Sdim  friend class ASTDeclReader;
1791235633Sdim  friend class ASTDeclWriter;
1792193326Sed};
1793193326Sed
1794235633Sdimraw_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
1800245431Sdim/// \@implementation MyClass
1801193326Sed/// - (void)myMethod { /* do something */ }
1802245431Sdim/// \@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 {
1811235633Sdim  virtual void anchor();
1812193326Sed  /// Implementation Class's super class.
1813193326Sed  ObjCInterfaceDecl *SuperClass;
1814252723Sdim  SourceLocation SuperLoc;
1815252723Sdim
1816245431Sdim  /// \@implementation may have private ivars.
1817235633Sdim  SourceLocation IvarLBraceLoc;
1818235633Sdim  SourceLocation IvarRBraceLoc;
1819235633Sdim
1820207619Srdivacky  /// Support for ivar initialization.
1821207619Srdivacky  /// IvarInitializers - The arguments used to initialize the ivars
1822218893Sdim  CXXCtorInitializer **IvarInitializers;
1823207619Srdivacky  unsigned NumIvarInitializers;
1824224145Sdim
1825245431Sdim  /// Do the ivars of this class require initialization other than
1826245431Sdim  /// zero-initialization?
1827245431Sdim  bool HasNonZeroConstructors : 1;
1828235633Sdim
1829245431Sdim  /// Do the ivars of this class require non-trivial destruction?
1830245431Sdim  bool HasDestructors : 1;
1831235633Sdim
1832226890Sdim  ObjCImplementationDecl(DeclContext *DC,
1833193326Sed                         ObjCInterfaceDecl *classInterface,
1834226890Sdim                         ObjCInterfaceDecl *superDecl,
1835235633Sdim                         SourceLocation nameLoc, SourceLocation atStartLoc,
1836252723Sdim                         SourceLocation superLoc = SourceLocation(),
1837235633Sdim                         SourceLocation IvarLBraceLoc=SourceLocation(),
1838235633Sdim                         SourceLocation IvarRBraceLoc=SourceLocation())
1839226890Sdim    : ObjCImplDecl(ObjCImplementation, DC, classInterface, nameLoc, atStartLoc),
1840252723Sdim       SuperClass(superDecl), SuperLoc(superLoc), IvarLBraceLoc(IvarLBraceLoc),
1841235633Sdim       IvarRBraceLoc(IvarRBraceLoc),
1842235633Sdim       IvarInitializers(0), NumIvarInitializers(0),
1843245431Sdim       HasNonZeroConstructors(false), HasDestructors(false) {}
1844198092Srdivackypublic:
1845198092Srdivacky  static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC,
1846193326Sed                                        ObjCInterfaceDecl *classInterface,
1847226890Sdim                                        ObjCInterfaceDecl *superDecl,
1848226890Sdim                                        SourceLocation nameLoc,
1849235633Sdim                                        SourceLocation atStartLoc,
1850252723Sdim                                     SourceLocation superLoc = SourceLocation(),
1851235633Sdim                                        SourceLocation IvarLBraceLoc=SourceLocation(),
1852235633Sdim                                        SourceLocation IvarRBraceLoc=SourceLocation());
1853235633Sdim
1854235633Sdim  static ObjCImplementationDecl *CreateDeserialized(ASTContext &C, unsigned ID);
1855235633Sdim
1856207619Srdivacky  /// init_iterator - Iterates through the ivar initializer list.
1857218893Sdim  typedef CXXCtorInitializer **init_iterator;
1858235633Sdim
1859207619Srdivacky  /// init_const_iterator - Iterates through the ivar initializer list.
1860218893Sdim  typedef CXXCtorInitializer * const * init_const_iterator;
1861235633Sdim
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; }
1866235633Sdim
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  }
1879235633Sdim
1880207619Srdivacky  void setNumIvarInitializers(unsigned numNumIvarInitializers) {
1881207619Srdivacky    NumIvarInitializers = numNumIvarInitializers;
1882207619Srdivacky  }
1883235633Sdim
1884207619Srdivacky  void setIvarInitializers(ASTContext &C,
1885218893Sdim                           CXXCtorInitializer ** initializers,
1886207619Srdivacky                           unsigned numInitializers);
1887224145Sdim
1888245431Sdim  /// Do any of the ivars of this class (not counting its base classes)
1889245431Sdim  /// require construction other than zero-initialization?
1890245431Sdim  bool hasNonZeroConstructors() const { return HasNonZeroConstructors; }
1891245431Sdim  void setHasNonZeroConstructors(bool val) { HasNonZeroConstructors = val; }
1892235633Sdim
1893245431Sdim  /// Do any of the ivars of this class (not counting its base classes)
1894245431Sdim  /// require non-trivial destruction?
1895245431Sdim  bool hasDestructors() const { return HasDestructors; }
1896245431Sdim  void setHasDestructors(bool val) { HasDestructors = val; }
1897235633Sdim
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.
1909226890Sdim  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; }
1923252723Sdim  SourceLocation getSuperClassLoc() const { return SuperLoc; }
1924198092Srdivacky
1925193326Sed  void setSuperClass(ObjCInterfaceDecl * superCls) { SuperClass = superCls; }
1926198092Srdivacky
1927235633Sdim  void setIvarLBraceLoc(SourceLocation Loc) { IvarLBraceLoc = Loc; }
1928235633Sdim  SourceLocation getIvarLBraceLoc() const { return IvarLBraceLoc; }
1929235633Sdim  void setIvarRBraceLoc(SourceLocation Loc) { IvarRBraceLoc = Loc; }
1930235633Sdim  SourceLocation getIvarRBraceLoc() const { return IvarRBraceLoc; }
1931235633Sdim
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
1953235633Sdimraw_ostream &operator<<(raw_ostream &OS, const ObjCImplementationDecl &ID);
1954207619Srdivacky
1955198092Srdivacky/// ObjCCompatibleAliasDecl - Represents alias of a class. This alias is
1956245431Sdim/// declared as \@compatibility_alias alias class.
1957193326Sedclass ObjCCompatibleAliasDecl : public NamedDecl {
1958235633Sdim  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
1970235633Sdim  static ObjCCompatibleAliasDecl *CreateDeserialized(ASTContext &C,
1971235633Sdim                                                     unsigned ID);
1972235633Sdim
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
1982245431Sdim/// \brief Represents one property declaration in an Objective-C interface.
1983245431Sdim///
1984193326Sed/// For example:
1985245431Sdim/// \code{.mm}
1986245431Sdim/// \@property (assign, readwrite) int MyProperty;
1987245431Sdim/// \endcode
1988193326Sedclass ObjCPropertyDecl : public NamedDecl {
1989235633Sdim  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
2013226890Sdim  enum SetterKind { Assign, Retain, Copy, Weak };
2014193326Sed  enum PropertyControl { None, Required, Optional };
2015193326Sedprivate:
2016245431Sdim  SourceLocation AtLoc;   // location of \@property
2017235633Sdim  SourceLocation LParenLoc; // location of '(' starting attribute list or null.
2018210299Sed  TypeSourceInfo *DeclType;
2019224145Sdim  unsigned PropertyAttributes : NumPropertyAttrsBits;
2020224145Sdim  unsigned PropertyAttributesAsWritten : NumPropertyAttrsBits;
2021245431Sdim  // \@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,
2032235633Sdim                   SourceLocation AtLocation,  SourceLocation LParenLocation,
2033235633Sdim                   TypeSourceInfo *T)
2034235633Sdim    : NamedDecl(ObjCProperty, DC, L, Id), AtLoc(AtLocation),
2035235633Sdim      LParenLoc(LParenLocation), DeclType(T),
2036235633Sdim      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,
2046235633Sdim                                  SourceLocation LParenLocation,
2047210299Sed                                  TypeSourceInfo *T,
2048193326Sed                                  PropertyControl propControl = None);
2049235633Sdim
2050235633Sdim  static ObjCPropertyDecl *CreateDeserialized(ASTContext &C, unsigned ID);
2051235633Sdim
2052202879Srdivacky  SourceLocation getAtLoc() const { return AtLoc; }
2053202879Srdivacky  void setAtLoc(SourceLocation L) { AtLoc = L; }
2054202879Srdivacky
2055235633Sdim  SourceLocation getLParenLoc() const { return LParenLoc; }
2056235633Sdim  void setLParenLoc(SourceLocation L) { LParenLoc = L; }
2057235633Sdim
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  }
2078235633Sdim
2079210299Sed  void setPropertyAttributesAsWritten(PropertyAttributeKind PRVal) {
2080210299Sed    PropertyAttributesAsWritten = PRVal;
2081210299Sed  }
2082235633Sdim
2083252723Sdim 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
2095226890Sdim  /// isAtomic - Return true if the property is atomic.
2096226890Sdim  bool isAtomic() const {
2097226890Sdim    return (PropertyAttributes & OBJC_PR_atomic);
2098226890Sdim  }
2099226890Sdim
2100226890Sdim  /// isRetaining - Return true if the property retains its value.
2101226890Sdim  bool isRetaining() const {
2102226890Sdim    return (PropertyAttributes &
2103226890Sdim            (OBJC_PR_retain | OBJC_PR_strong | OBJC_PR_copy));
2104226890Sdim  }
2105226890Sdim
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 {
2110226890Sdim    if (PropertyAttributes & OBJC_PR_strong)
2111226890Sdim      return getType()->isBlockPointerType() ? Copy : Retain;
2112226890Sdim    if (PropertyAttributes & OBJC_PR_retain)
2113193326Sed      return Retain;
2114193326Sed    if (PropertyAttributes & OBJC_PR_copy)
2115193326Sed      return Copy;
2116226890Sdim    if (PropertyAttributes & OBJC_PR_weak)
2117226890Sdim      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
2133245431Sdim  // 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
2148235633Sdim  virtual SourceRange getSourceRange() const LLVM_READONLY {
2149218893Sdim    return SourceRange(AtLoc, getLocation());
2150218893Sdim  }
2151245431Sdim
2152245431Sdim  /// Get the default name of the synthesized ivar.
2153245431Sdim  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:
2165245431Sdim/// \@synthesize prop1 = ivar1;
2166193326Sed///
2167193326Sedclass ObjCPropertyImplDecl : public Decl {
2168193326Sedpublic:
2169193326Sed  enum Kind {
2170193326Sed    Synthesize,
2171193326Sed    Dynamic
2172193326Sed  };
2173193326Sedprivate:
2174245431Sdim  SourceLocation AtLoc;   // location of \@synthesize or \@dynamic
2175235633Sdim
2176245431Sdim  /// \brief For \@synthesize, the location of the ivar, if it was written in
2177218893Sdim  /// the source code.
2178218893Sdim  ///
2179218893Sdim  /// \code
2180245431Sdim  /// \@synthesize int a = b
2181218893Sdim  /// \endcode
2182218893Sdim  SourceLocation IvarLoc;
2183235633Sdim
2184193326Sed  /// Property declaration being implemented
2185193326Sed  ObjCPropertyDecl *PropertyDecl;
2186193326Sed
2187245431Sdim  /// Null for \@dynamic. Required for \@synthesize.
2188193326Sed  ObjCIvarDecl *PropertyIvarDecl;
2189235633Sdim
2190245431Sdim  /// Null for \@dynamic. Non-null if property must be copy-constructed in
2191245431Sdim  /// getter.
2192208600Srdivacky  Expr *GetterCXXConstructor;
2193235633Sdim
2194245431Sdim  /// 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),
2204235633Sdim      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
2217235633Sdim  static ObjCPropertyImplDecl *CreateDeserialized(ASTContext &C, unsigned ID);
2218218893Sdim
2219235633Sdim  virtual SourceRange getSourceRange() const LLVM_READONLY;
2220235633Sdim
2221235633Sdim  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; }
2237235633Sdim
2238218893Sdim  void setPropertyIvarDecl(ObjCIvarDecl *Ivar,
2239235633Sdim                           SourceLocation IvarLoc) {
2240235633Sdim    PropertyIvarDecl = Ivar;
2241218893Sdim    this->IvarLoc = IvarLoc;
2242218893Sdim  }
2243235633Sdim
2244245431Sdim  /// \brief For \@synthesize, returns true if an ivar name was explicitly
2245245431Sdim  /// specified.
2246245431Sdim  ///
2247245431Sdim  /// \code
2248245431Sdim  /// \@synthesize int a = b; // true
2249245431Sdim  /// \@synthesize int a; // false
2250245431Sdim  /// \endcode
2251245431Sdim  bool isIvarNameSpecified() const {
2252245431Sdim    return IvarLoc.isValid() && IvarLoc != getLocation();
2253245431Sdim  }
2254245431Sdim
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  }
2268235633Sdim
2269203955Srdivacky  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
2270203955Srdivacky  static bool classofKind(Decl::Kind K) { return K == ObjCPropertyImpl; }
2271235633Sdim
2272218893Sdim  friend class ASTDeclReader;
2273193326Sed};
2274193326Sed
2275252723Sdimtemplate<bool (*Filter)(ObjCCategoryDecl *)>
2276252723Sdimvoid
2277252723SdimObjCInterfaceDecl::filtered_category_iterator<Filter>::
2278252723SdimfindAcceptableCategory() {
2279252723Sdim  while (Current && !Filter(Current))
2280252723Sdim    Current = Current->getNextClassCategoryRaw();
2281252723Sdim}
2282252723Sdim
2283252723Sdimtemplate<bool (*Filter)(ObjCCategoryDecl *)>
2284252723Sdiminline ObjCInterfaceDecl::filtered_category_iterator<Filter> &
2285252723SdimObjCInterfaceDecl::filtered_category_iterator<Filter>::operator++() {
2286252723Sdim  Current = Current->getNextClassCategoryRaw();
2287252723Sdim  findAcceptableCategory();
2288252723Sdim  return *this;
2289252723Sdim}
2290252723Sdim
2291252723Sdiminline bool ObjCInterfaceDecl::isVisibleCategory(ObjCCategoryDecl *Cat) {
2292252723Sdim  return !Cat->isHidden();
2293252723Sdim}
2294252723Sdim
2295252723Sdiminline bool ObjCInterfaceDecl::isVisibleExtension(ObjCCategoryDecl *Cat) {
2296252723Sdim  return Cat->IsClassExtension() && !Cat->isHidden();
2297252723Sdim}
2298252723Sdim
2299252723Sdiminline bool ObjCInterfaceDecl::isKnownExtension(ObjCCategoryDecl *Cat) {
2300252723Sdim  return Cat->IsClassExtension();
2301252723Sdim}
2302252723Sdim
2303193326Sed}  // end namespace clang
2304193326Sed#endif
2305