xref: /openbsd-src/gnu/llvm/clang/include/clang/AST/DeclObjC.h (revision 12c855180aad702bbcca06e0398d774beeafb155)
1e5dd7070Spatrick //===- DeclObjC.h - Classes for representing declarations -------*- C++ -*-===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick //
9e5dd7070Spatrick //  This file defines the DeclObjC interface and subclasses.
10e5dd7070Spatrick //
11e5dd7070Spatrick //===----------------------------------------------------------------------===//
12e5dd7070Spatrick 
13e5dd7070Spatrick #ifndef LLVM_CLANG_AST_DECLOBJC_H
14e5dd7070Spatrick #define LLVM_CLANG_AST_DECLOBJC_H
15e5dd7070Spatrick 
16e5dd7070Spatrick #include "clang/AST/Decl.h"
17e5dd7070Spatrick #include "clang/AST/DeclBase.h"
18ec727ea7Spatrick #include "clang/AST/DeclObjCCommon.h"
19e5dd7070Spatrick #include "clang/AST/ExternalASTSource.h"
20e5dd7070Spatrick #include "clang/AST/Redeclarable.h"
21e5dd7070Spatrick #include "clang/AST/SelectorLocationsKind.h"
22e5dd7070Spatrick #include "clang/AST/Type.h"
23e5dd7070Spatrick #include "clang/Basic/IdentifierTable.h"
24e5dd7070Spatrick #include "clang/Basic/LLVM.h"
25e5dd7070Spatrick #include "clang/Basic/SourceLocation.h"
26e5dd7070Spatrick #include "clang/Basic/Specifiers.h"
27e5dd7070Spatrick #include "llvm/ADT/ArrayRef.h"
28e5dd7070Spatrick #include "llvm/ADT/DenseSet.h"
29*12c85518Srobert #include "llvm/ADT/MapVector.h"
30e5dd7070Spatrick #include "llvm/ADT/PointerIntPair.h"
31e5dd7070Spatrick #include "llvm/ADT/STLExtras.h"
32e5dd7070Spatrick #include "llvm/ADT/StringRef.h"
33e5dd7070Spatrick #include "llvm/ADT/iterator_range.h"
34e5dd7070Spatrick #include "llvm/Support/Compiler.h"
35e5dd7070Spatrick #include "llvm/Support/TrailingObjects.h"
36e5dd7070Spatrick #include <cassert>
37e5dd7070Spatrick #include <cstddef>
38e5dd7070Spatrick #include <cstdint>
39e5dd7070Spatrick #include <iterator>
40e5dd7070Spatrick #include <string>
41e5dd7070Spatrick #include <utility>
42e5dd7070Spatrick 
43e5dd7070Spatrick namespace clang {
44e5dd7070Spatrick 
45e5dd7070Spatrick class ASTContext;
46e5dd7070Spatrick class CompoundStmt;
47e5dd7070Spatrick class CXXCtorInitializer;
48e5dd7070Spatrick class Expr;
49e5dd7070Spatrick class ObjCCategoryDecl;
50e5dd7070Spatrick class ObjCCategoryImplDecl;
51e5dd7070Spatrick class ObjCImplementationDecl;
52e5dd7070Spatrick class ObjCInterfaceDecl;
53e5dd7070Spatrick class ObjCIvarDecl;
54e5dd7070Spatrick class ObjCPropertyDecl;
55e5dd7070Spatrick class ObjCPropertyImplDecl;
56e5dd7070Spatrick class ObjCProtocolDecl;
57e5dd7070Spatrick class Stmt;
58e5dd7070Spatrick 
59e5dd7070Spatrick class ObjCListBase {
60e5dd7070Spatrick protected:
61e5dd7070Spatrick   /// List is an array of pointers to objects that are not owned by this object.
62e5dd7070Spatrick   void **List = nullptr;
63e5dd7070Spatrick   unsigned NumElts = 0;
64e5dd7070Spatrick 
65e5dd7070Spatrick public:
66e5dd7070Spatrick   ObjCListBase() = default;
67e5dd7070Spatrick   ObjCListBase(const ObjCListBase &) = delete;
68e5dd7070Spatrick   ObjCListBase &operator=(const ObjCListBase &) = delete;
69e5dd7070Spatrick 
size()70e5dd7070Spatrick   unsigned size() const { return NumElts; }
empty()71e5dd7070Spatrick   bool empty() const { return NumElts == 0; }
72e5dd7070Spatrick 
73e5dd7070Spatrick protected:
74e5dd7070Spatrick   void set(void *const* InList, unsigned Elts, ASTContext &Ctx);
75e5dd7070Spatrick };
76e5dd7070Spatrick 
77e5dd7070Spatrick /// ObjCList - This is a simple template class used to hold various lists of
78e5dd7070Spatrick /// decls etc, which is heavily used by the ObjC front-end.  This only use case
79e5dd7070Spatrick /// this supports is setting the list all at once and then reading elements out
80e5dd7070Spatrick /// of it.
81e5dd7070Spatrick template <typename T>
82e5dd7070Spatrick class ObjCList : public ObjCListBase {
83e5dd7070Spatrick public:
set(T * const * InList,unsigned Elts,ASTContext & Ctx)84e5dd7070Spatrick   void set(T* const* InList, unsigned Elts, ASTContext &Ctx) {
85e5dd7070Spatrick     ObjCListBase::set(reinterpret_cast<void*const*>(InList), Elts, Ctx);
86e5dd7070Spatrick   }
87e5dd7070Spatrick 
88e5dd7070Spatrick   using iterator = T* const *;
89e5dd7070Spatrick 
begin()90e5dd7070Spatrick   iterator begin() const { return (iterator)List; }
end()91e5dd7070Spatrick   iterator end() const { return (iterator)List+NumElts; }
92e5dd7070Spatrick 
93e5dd7070Spatrick   T* operator[](unsigned Idx) const {
94e5dd7070Spatrick     assert(Idx < NumElts && "Invalid access");
95e5dd7070Spatrick     return (T*)List[Idx];
96e5dd7070Spatrick   }
97e5dd7070Spatrick };
98e5dd7070Spatrick 
99e5dd7070Spatrick /// A list of Objective-C protocols, along with the source
100e5dd7070Spatrick /// locations at which they were referenced.
101e5dd7070Spatrick class ObjCProtocolList : public ObjCList<ObjCProtocolDecl> {
102e5dd7070Spatrick   SourceLocation *Locations = nullptr;
103e5dd7070Spatrick 
104e5dd7070Spatrick   using ObjCList<ObjCProtocolDecl>::set;
105e5dd7070Spatrick 
106e5dd7070Spatrick public:
107e5dd7070Spatrick   ObjCProtocolList() = default;
108e5dd7070Spatrick 
109e5dd7070Spatrick   using loc_iterator = const SourceLocation *;
110e5dd7070Spatrick 
loc_begin()111e5dd7070Spatrick   loc_iterator loc_begin() const { return Locations; }
loc_end()112e5dd7070Spatrick   loc_iterator loc_end() const { return Locations + size(); }
113e5dd7070Spatrick 
114e5dd7070Spatrick   void set(ObjCProtocolDecl* const* InList, unsigned Elts,
115e5dd7070Spatrick            const SourceLocation *Locs, ASTContext &Ctx);
116e5dd7070Spatrick };
117e5dd7070Spatrick 
118e5dd7070Spatrick /// ObjCMethodDecl - Represents an instance or class method declaration.
119e5dd7070Spatrick /// ObjC methods can be declared within 4 contexts: class interfaces,
120e5dd7070Spatrick /// categories, protocols, and class implementations. While C++ member
121e5dd7070Spatrick /// functions leverage C syntax, Objective-C method syntax is modeled after
122e5dd7070Spatrick /// Smalltalk (using colons to specify argument types/expressions).
123e5dd7070Spatrick /// Here are some brief examples:
124e5dd7070Spatrick ///
125e5dd7070Spatrick /// Setter/getter instance methods:
126e5dd7070Spatrick /// - (void)setMenu:(NSMenu *)menu;
127e5dd7070Spatrick /// - (NSMenu *)menu;
128e5dd7070Spatrick ///
129e5dd7070Spatrick /// Instance method that takes 2 NSView arguments:
130e5dd7070Spatrick /// - (void)replaceSubview:(NSView *)oldView with:(NSView *)newView;
131e5dd7070Spatrick ///
132e5dd7070Spatrick /// Getter class method:
133e5dd7070Spatrick /// + (NSMenu *)defaultMenu;
134e5dd7070Spatrick ///
135e5dd7070Spatrick /// A selector represents a unique name for a method. The selector names for
136e5dd7070Spatrick /// the above methods are setMenu:, menu, replaceSubview:with:, and defaultMenu.
137e5dd7070Spatrick ///
138e5dd7070Spatrick class ObjCMethodDecl : public NamedDecl, public DeclContext {
139e5dd7070Spatrick   // This class stores some data in DeclContext::ObjCMethodDeclBits
140e5dd7070Spatrick   // to save some space. Use the provided accessors to access it.
141e5dd7070Spatrick 
142e5dd7070Spatrick public:
143e5dd7070Spatrick   enum ImplementationControl { None, Required, Optional };
144e5dd7070Spatrick 
145e5dd7070Spatrick private:
146e5dd7070Spatrick   /// Return type of this method.
147e5dd7070Spatrick   QualType MethodDeclType;
148e5dd7070Spatrick 
149e5dd7070Spatrick   /// Type source information for the return type.
150e5dd7070Spatrick   TypeSourceInfo *ReturnTInfo;
151e5dd7070Spatrick 
152e5dd7070Spatrick   /// Array of ParmVarDecls for the formal parameters of this method
153e5dd7070Spatrick   /// and optionally followed by selector locations.
154e5dd7070Spatrick   void *ParamsAndSelLocs = nullptr;
155e5dd7070Spatrick   unsigned NumParams = 0;
156e5dd7070Spatrick 
157e5dd7070Spatrick   /// List of attributes for this method declaration.
158e5dd7070Spatrick   SourceLocation DeclEndLoc; // the location of the ';' or '{'.
159e5dd7070Spatrick 
160e5dd7070Spatrick   /// The following are only used for method definitions, null otherwise.
161e5dd7070Spatrick   LazyDeclStmtPtr Body;
162e5dd7070Spatrick 
163e5dd7070Spatrick   /// SelfDecl - Decl for the implicit self parameter. This is lazily
164e5dd7070Spatrick   /// constructed by createImplicitParams.
165e5dd7070Spatrick   ImplicitParamDecl *SelfDecl = nullptr;
166e5dd7070Spatrick 
167e5dd7070Spatrick   /// CmdDecl - Decl for the implicit _cmd parameter. This is lazily
168e5dd7070Spatrick   /// constructed by createImplicitParams.
169e5dd7070Spatrick   ImplicitParamDecl *CmdDecl = nullptr;
170e5dd7070Spatrick 
171e5dd7070Spatrick   ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc,
172e5dd7070Spatrick                  Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo,
173e5dd7070Spatrick                  DeclContext *contextDecl, bool isInstance = true,
174e5dd7070Spatrick                  bool isVariadic = false, bool isPropertyAccessor = false,
175e5dd7070Spatrick                  bool isSynthesizedAccessorStub = false,
176e5dd7070Spatrick                  bool isImplicitlyDeclared = false, bool isDefined = false,
177e5dd7070Spatrick                  ImplementationControl impControl = None,
178e5dd7070Spatrick                  bool HasRelatedResultType = false);
179e5dd7070Spatrick 
getSelLocsKind()180e5dd7070Spatrick   SelectorLocationsKind getSelLocsKind() const {
181e5dd7070Spatrick     return static_cast<SelectorLocationsKind>(ObjCMethodDeclBits.SelLocsKind);
182e5dd7070Spatrick   }
183e5dd7070Spatrick 
setSelLocsKind(SelectorLocationsKind Kind)184e5dd7070Spatrick   void setSelLocsKind(SelectorLocationsKind Kind) {
185e5dd7070Spatrick     ObjCMethodDeclBits.SelLocsKind = Kind;
186e5dd7070Spatrick   }
187e5dd7070Spatrick 
hasStandardSelLocs()188e5dd7070Spatrick   bool hasStandardSelLocs() const {
189e5dd7070Spatrick     return getSelLocsKind() != SelLoc_NonStandard;
190e5dd7070Spatrick   }
191e5dd7070Spatrick 
192e5dd7070Spatrick   /// Get a pointer to the stored selector identifiers locations array.
193e5dd7070Spatrick   /// No locations will be stored if HasStandardSelLocs is true.
getStoredSelLocs()194e5dd7070Spatrick   SourceLocation *getStoredSelLocs() {
195e5dd7070Spatrick     return reinterpret_cast<SourceLocation *>(getParams() + NumParams);
196e5dd7070Spatrick   }
getStoredSelLocs()197e5dd7070Spatrick   const SourceLocation *getStoredSelLocs() const {
198e5dd7070Spatrick     return reinterpret_cast<const SourceLocation *>(getParams() + NumParams);
199e5dd7070Spatrick   }
200e5dd7070Spatrick 
201e5dd7070Spatrick   /// Get a pointer to the stored selector identifiers locations array.
202e5dd7070Spatrick   /// No locations will be stored if HasStandardSelLocs is true.
getParams()203e5dd7070Spatrick   ParmVarDecl **getParams() {
204e5dd7070Spatrick     return reinterpret_cast<ParmVarDecl **>(ParamsAndSelLocs);
205e5dd7070Spatrick   }
getParams()206e5dd7070Spatrick   const ParmVarDecl *const *getParams() const {
207e5dd7070Spatrick     return reinterpret_cast<const ParmVarDecl *const *>(ParamsAndSelLocs);
208e5dd7070Spatrick   }
209e5dd7070Spatrick 
210e5dd7070Spatrick   /// Get the number of stored selector identifiers locations.
211e5dd7070Spatrick   /// No locations will be stored if HasStandardSelLocs is true.
getNumStoredSelLocs()212e5dd7070Spatrick   unsigned getNumStoredSelLocs() const {
213e5dd7070Spatrick     if (hasStandardSelLocs())
214e5dd7070Spatrick       return 0;
215e5dd7070Spatrick     return getNumSelectorLocs();
216e5dd7070Spatrick   }
217e5dd7070Spatrick 
218e5dd7070Spatrick   void setParamsAndSelLocs(ASTContext &C,
219e5dd7070Spatrick                            ArrayRef<ParmVarDecl*> Params,
220e5dd7070Spatrick                            ArrayRef<SourceLocation> SelLocs);
221e5dd7070Spatrick 
222e5dd7070Spatrick   /// A definition will return its interface declaration.
223e5dd7070Spatrick   /// An interface declaration will return its definition.
224e5dd7070Spatrick   /// Otherwise it will return itself.
225e5dd7070Spatrick   ObjCMethodDecl *getNextRedeclarationImpl() override;
226e5dd7070Spatrick 
227e5dd7070Spatrick public:
228e5dd7070Spatrick   friend class ASTDeclReader;
229e5dd7070Spatrick   friend class ASTDeclWriter;
230e5dd7070Spatrick 
231e5dd7070Spatrick   static ObjCMethodDecl *
232e5dd7070Spatrick   Create(ASTContext &C, SourceLocation beginLoc, SourceLocation endLoc,
233e5dd7070Spatrick          Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo,
234e5dd7070Spatrick          DeclContext *contextDecl, bool isInstance = true,
235e5dd7070Spatrick          bool isVariadic = false, bool isPropertyAccessor = false,
236e5dd7070Spatrick          bool isSynthesizedAccessorStub = false,
237e5dd7070Spatrick          bool isImplicitlyDeclared = false, bool isDefined = false,
238e5dd7070Spatrick          ImplementationControl impControl = None,
239e5dd7070Spatrick          bool HasRelatedResultType = false);
240e5dd7070Spatrick 
241e5dd7070Spatrick   static ObjCMethodDecl *CreateDeserialized(ASTContext &C, unsigned ID);
242e5dd7070Spatrick 
243e5dd7070Spatrick   ObjCMethodDecl *getCanonicalDecl() override;
getCanonicalDecl()244e5dd7070Spatrick   const ObjCMethodDecl *getCanonicalDecl() const {
245e5dd7070Spatrick     return const_cast<ObjCMethodDecl*>(this)->getCanonicalDecl();
246e5dd7070Spatrick   }
247e5dd7070Spatrick 
getObjCDeclQualifier()248e5dd7070Spatrick   ObjCDeclQualifier getObjCDeclQualifier() const {
249e5dd7070Spatrick     return static_cast<ObjCDeclQualifier>(ObjCMethodDeclBits.objcDeclQualifier);
250e5dd7070Spatrick   }
251e5dd7070Spatrick 
setObjCDeclQualifier(ObjCDeclQualifier QV)252e5dd7070Spatrick   void setObjCDeclQualifier(ObjCDeclQualifier QV) {
253e5dd7070Spatrick     ObjCMethodDeclBits.objcDeclQualifier = QV;
254e5dd7070Spatrick   }
255e5dd7070Spatrick 
256e5dd7070Spatrick   /// Determine whether this method has a result type that is related
257e5dd7070Spatrick   /// to the message receiver's type.
hasRelatedResultType()258e5dd7070Spatrick   bool hasRelatedResultType() const {
259e5dd7070Spatrick     return ObjCMethodDeclBits.RelatedResultType;
260e5dd7070Spatrick   }
261e5dd7070Spatrick 
262e5dd7070Spatrick   /// Note whether this method has a related result type.
263e5dd7070Spatrick   void setRelatedResultType(bool RRT = true) {
264e5dd7070Spatrick     ObjCMethodDeclBits.RelatedResultType = RRT;
265e5dd7070Spatrick   }
266e5dd7070Spatrick 
267e5dd7070Spatrick   /// True if this is a method redeclaration in the same interface.
isRedeclaration()268e5dd7070Spatrick   bool isRedeclaration() const { return ObjCMethodDeclBits.IsRedeclaration; }
setIsRedeclaration(bool RD)269e5dd7070Spatrick   void setIsRedeclaration(bool RD) { ObjCMethodDeclBits.IsRedeclaration = RD; }
270e5dd7070Spatrick   void setAsRedeclaration(const ObjCMethodDecl *PrevMethod);
271e5dd7070Spatrick 
272e5dd7070Spatrick   /// True if redeclared in the same interface.
hasRedeclaration()273e5dd7070Spatrick   bool hasRedeclaration() const { return ObjCMethodDeclBits.HasRedeclaration; }
setHasRedeclaration(bool HRD)274e5dd7070Spatrick   void setHasRedeclaration(bool HRD) const {
275e5dd7070Spatrick     ObjCMethodDeclBits.HasRedeclaration = HRD;
276e5dd7070Spatrick   }
277e5dd7070Spatrick 
278e5dd7070Spatrick   /// Returns the location where the declarator ends. It will be
279e5dd7070Spatrick   /// the location of ';' for a method declaration and the location of '{'
280e5dd7070Spatrick   /// for a method definition.
getDeclaratorEndLoc()281e5dd7070Spatrick   SourceLocation getDeclaratorEndLoc() const { return DeclEndLoc; }
282e5dd7070Spatrick 
283e5dd7070Spatrick   // Location information, modeled after the Stmt API.
getBeginLoc()284e5dd7070Spatrick   SourceLocation getBeginLoc() const LLVM_READONLY { return getLocation(); }
285e5dd7070Spatrick   SourceLocation getEndLoc() const LLVM_READONLY;
getSourceRange()286e5dd7070Spatrick   SourceRange getSourceRange() const override LLVM_READONLY {
287e5dd7070Spatrick     return SourceRange(getLocation(), getEndLoc());
288e5dd7070Spatrick   }
289e5dd7070Spatrick 
getSelectorStartLoc()290e5dd7070Spatrick   SourceLocation getSelectorStartLoc() const {
291e5dd7070Spatrick     if (isImplicit())
292e5dd7070Spatrick       return getBeginLoc();
293e5dd7070Spatrick     return getSelectorLoc(0);
294e5dd7070Spatrick   }
295e5dd7070Spatrick 
getSelectorLoc(unsigned Index)296e5dd7070Spatrick   SourceLocation getSelectorLoc(unsigned Index) const {
297e5dd7070Spatrick     assert(Index < getNumSelectorLocs() && "Index out of range!");
298e5dd7070Spatrick     if (hasStandardSelLocs())
299e5dd7070Spatrick       return getStandardSelectorLoc(Index, getSelector(),
300e5dd7070Spatrick                                    getSelLocsKind() == SelLoc_StandardWithSpace,
301e5dd7070Spatrick                                     parameters(),
302e5dd7070Spatrick                                    DeclEndLoc);
303e5dd7070Spatrick     return getStoredSelLocs()[Index];
304e5dd7070Spatrick   }
305e5dd7070Spatrick 
306e5dd7070Spatrick   void getSelectorLocs(SmallVectorImpl<SourceLocation> &SelLocs) const;
307e5dd7070Spatrick 
getNumSelectorLocs()308e5dd7070Spatrick   unsigned getNumSelectorLocs() const {
309e5dd7070Spatrick     if (isImplicit())
310e5dd7070Spatrick       return 0;
311e5dd7070Spatrick     Selector Sel = getSelector();
312e5dd7070Spatrick     if (Sel.isUnarySelector())
313e5dd7070Spatrick       return 1;
314e5dd7070Spatrick     return Sel.getNumArgs();
315e5dd7070Spatrick   }
316e5dd7070Spatrick 
317e5dd7070Spatrick   ObjCInterfaceDecl *getClassInterface();
getClassInterface()318e5dd7070Spatrick   const ObjCInterfaceDecl *getClassInterface() const {
319e5dd7070Spatrick     return const_cast<ObjCMethodDecl*>(this)->getClassInterface();
320e5dd7070Spatrick   }
321e5dd7070Spatrick 
322a9ac8606Spatrick   /// If this method is declared or implemented in a category, return
323a9ac8606Spatrick   /// that category.
324a9ac8606Spatrick   ObjCCategoryDecl *getCategory();
getCategory()325a9ac8606Spatrick   const ObjCCategoryDecl *getCategory() const {
326a9ac8606Spatrick     return const_cast<ObjCMethodDecl*>(this)->getCategory();
327a9ac8606Spatrick   }
328a9ac8606Spatrick 
getSelector()329e5dd7070Spatrick   Selector getSelector() const { return getDeclName().getObjCSelector(); }
330e5dd7070Spatrick 
getReturnType()331e5dd7070Spatrick   QualType getReturnType() const { return MethodDeclType; }
setReturnType(QualType T)332e5dd7070Spatrick   void setReturnType(QualType T) { MethodDeclType = T; }
333e5dd7070Spatrick   SourceRange getReturnTypeSourceRange() const;
334e5dd7070Spatrick 
335e5dd7070Spatrick   /// Determine the type of an expression that sends a message to this
336e5dd7070Spatrick   /// function. This replaces the type parameters with the types they would
337e5dd7070Spatrick   /// get if the receiver was parameterless (e.g. it may replace the type
338e5dd7070Spatrick   /// parameter with 'id').
339e5dd7070Spatrick   QualType getSendResultType() const;
340e5dd7070Spatrick 
341e5dd7070Spatrick   /// Determine the type of an expression that sends a message to this
342e5dd7070Spatrick   /// function with the given receiver type.
343e5dd7070Spatrick   QualType getSendResultType(QualType receiverType) const;
344e5dd7070Spatrick 
getReturnTypeSourceInfo()345e5dd7070Spatrick   TypeSourceInfo *getReturnTypeSourceInfo() const { return ReturnTInfo; }
setReturnTypeSourceInfo(TypeSourceInfo * TInfo)346e5dd7070Spatrick   void setReturnTypeSourceInfo(TypeSourceInfo *TInfo) { ReturnTInfo = TInfo; }
347e5dd7070Spatrick 
348e5dd7070Spatrick   // Iterator access to formal parameters.
param_size()349e5dd7070Spatrick   unsigned param_size() const { return NumParams; }
350e5dd7070Spatrick 
351e5dd7070Spatrick   using param_const_iterator = const ParmVarDecl *const *;
352e5dd7070Spatrick   using param_iterator = ParmVarDecl *const *;
353e5dd7070Spatrick   using param_range = llvm::iterator_range<param_iterator>;
354e5dd7070Spatrick   using param_const_range = llvm::iterator_range<param_const_iterator>;
355e5dd7070Spatrick 
param_begin()356e5dd7070Spatrick   param_const_iterator param_begin() const {
357e5dd7070Spatrick     return param_const_iterator(getParams());
358e5dd7070Spatrick   }
359e5dd7070Spatrick 
param_end()360e5dd7070Spatrick   param_const_iterator param_end() const {
361e5dd7070Spatrick     return param_const_iterator(getParams() + NumParams);
362e5dd7070Spatrick   }
363e5dd7070Spatrick 
param_begin()364e5dd7070Spatrick   param_iterator param_begin() { return param_iterator(getParams()); }
param_end()365e5dd7070Spatrick   param_iterator param_end() { return param_iterator(getParams() + NumParams); }
366e5dd7070Spatrick 
367e5dd7070Spatrick   // This method returns and of the parameters which are part of the selector
368e5dd7070Spatrick   // name mangling requirements.
sel_param_end()369e5dd7070Spatrick   param_const_iterator sel_param_end() const {
370e5dd7070Spatrick     return param_begin() + getSelector().getNumArgs();
371e5dd7070Spatrick   }
372e5dd7070Spatrick 
373e5dd7070Spatrick   // ArrayRef access to formal parameters.  This should eventually
374e5dd7070Spatrick   // replace the iterator interface above.
parameters()375e5dd7070Spatrick   ArrayRef<ParmVarDecl*> parameters() const {
376*12c85518Srobert     return llvm::ArrayRef(const_cast<ParmVarDecl **>(getParams()), NumParams);
377e5dd7070Spatrick   }
378e5dd7070Spatrick 
getParamDecl(unsigned Idx)379e5dd7070Spatrick   ParmVarDecl *getParamDecl(unsigned Idx) {
380e5dd7070Spatrick     assert(Idx < NumParams && "Index out of bounds!");
381e5dd7070Spatrick     return getParams()[Idx];
382e5dd7070Spatrick   }
getParamDecl(unsigned Idx)383e5dd7070Spatrick   const ParmVarDecl *getParamDecl(unsigned Idx) const {
384e5dd7070Spatrick     return const_cast<ObjCMethodDecl *>(this)->getParamDecl(Idx);
385e5dd7070Spatrick   }
386e5dd7070Spatrick 
387e5dd7070Spatrick   /// Sets the method's parameters and selector source locations.
388e5dd7070Spatrick   /// If the method is implicit (not coming from source) \p SelLocs is
389e5dd7070Spatrick   /// ignored.
390*12c85518Srobert   void setMethodParams(ASTContext &C, ArrayRef<ParmVarDecl *> Params,
391*12c85518Srobert                        ArrayRef<SourceLocation> SelLocs = std::nullopt);
392e5dd7070Spatrick 
393e5dd7070Spatrick   // Iterator access to parameter types.
394e5dd7070Spatrick   struct GetTypeFn {
operatorGetTypeFn395e5dd7070Spatrick     QualType operator()(const ParmVarDecl *PD) const { return PD->getType(); }
396e5dd7070Spatrick   };
397e5dd7070Spatrick 
398e5dd7070Spatrick   using param_type_iterator =
399e5dd7070Spatrick       llvm::mapped_iterator<param_const_iterator, GetTypeFn>;
400e5dd7070Spatrick 
param_type_begin()401e5dd7070Spatrick   param_type_iterator param_type_begin() const {
402e5dd7070Spatrick     return llvm::map_iterator(param_begin(), GetTypeFn());
403e5dd7070Spatrick   }
404e5dd7070Spatrick 
param_type_end()405e5dd7070Spatrick   param_type_iterator param_type_end() const {
406e5dd7070Spatrick     return llvm::map_iterator(param_end(), GetTypeFn());
407e5dd7070Spatrick   }
408e5dd7070Spatrick 
409e5dd7070Spatrick   /// createImplicitParams - Used to lazily create the self and cmd
410ec727ea7Spatrick   /// implicit parameters. This must be called prior to using getSelfDecl()
411e5dd7070Spatrick   /// or getCmdDecl(). The call is ignored if the implicit parameters
412e5dd7070Spatrick   /// have already been created.
413e5dd7070Spatrick   void createImplicitParams(ASTContext &Context, const ObjCInterfaceDecl *ID);
414e5dd7070Spatrick 
415e5dd7070Spatrick   /// \return the type for \c self and set \arg selfIsPseudoStrong and
416e5dd7070Spatrick   /// \arg selfIsConsumed accordingly.
417e5dd7070Spatrick   QualType getSelfType(ASTContext &Context, const ObjCInterfaceDecl *OID,
418e5dd7070Spatrick                        bool &selfIsPseudoStrong, bool &selfIsConsumed) const;
419e5dd7070Spatrick 
getSelfDecl()420e5dd7070Spatrick   ImplicitParamDecl * getSelfDecl() const { return SelfDecl; }
setSelfDecl(ImplicitParamDecl * SD)421e5dd7070Spatrick   void setSelfDecl(ImplicitParamDecl *SD) { SelfDecl = SD; }
getCmdDecl()422e5dd7070Spatrick   ImplicitParamDecl * getCmdDecl() const { return CmdDecl; }
setCmdDecl(ImplicitParamDecl * CD)423e5dd7070Spatrick   void setCmdDecl(ImplicitParamDecl *CD) { CmdDecl = CD; }
424e5dd7070Spatrick 
425e5dd7070Spatrick   /// Determines the family of this method.
426e5dd7070Spatrick   ObjCMethodFamily getMethodFamily() const;
427e5dd7070Spatrick 
isInstanceMethod()428e5dd7070Spatrick   bool isInstanceMethod() const { return ObjCMethodDeclBits.IsInstance; }
setInstanceMethod(bool isInst)429e5dd7070Spatrick   void setInstanceMethod(bool isInst) {
430e5dd7070Spatrick     ObjCMethodDeclBits.IsInstance = isInst;
431e5dd7070Spatrick   }
432e5dd7070Spatrick 
isVariadic()433e5dd7070Spatrick   bool isVariadic() const { return ObjCMethodDeclBits.IsVariadic; }
setVariadic(bool isVar)434e5dd7070Spatrick   void setVariadic(bool isVar) { ObjCMethodDeclBits.IsVariadic = isVar; }
435e5dd7070Spatrick 
isClassMethod()436e5dd7070Spatrick   bool isClassMethod() const { return !isInstanceMethod(); }
437e5dd7070Spatrick 
isPropertyAccessor()438e5dd7070Spatrick   bool isPropertyAccessor() const {
439e5dd7070Spatrick     return ObjCMethodDeclBits.IsPropertyAccessor;
440e5dd7070Spatrick   }
441e5dd7070Spatrick 
setPropertyAccessor(bool isAccessor)442e5dd7070Spatrick   void setPropertyAccessor(bool isAccessor) {
443e5dd7070Spatrick     ObjCMethodDeclBits.IsPropertyAccessor = isAccessor;
444e5dd7070Spatrick   }
445e5dd7070Spatrick 
isSynthesizedAccessorStub()446e5dd7070Spatrick   bool isSynthesizedAccessorStub() const {
447e5dd7070Spatrick     return ObjCMethodDeclBits.IsSynthesizedAccessorStub;
448e5dd7070Spatrick   }
449e5dd7070Spatrick 
setSynthesizedAccessorStub(bool isSynthesizedAccessorStub)450e5dd7070Spatrick   void setSynthesizedAccessorStub(bool isSynthesizedAccessorStub) {
451e5dd7070Spatrick     ObjCMethodDeclBits.IsSynthesizedAccessorStub = isSynthesizedAccessorStub;
452e5dd7070Spatrick   }
453e5dd7070Spatrick 
isDefined()454e5dd7070Spatrick   bool isDefined() const { return ObjCMethodDeclBits.IsDefined; }
setDefined(bool isDefined)455e5dd7070Spatrick   void setDefined(bool isDefined) { ObjCMethodDeclBits.IsDefined = isDefined; }
456e5dd7070Spatrick 
457e5dd7070Spatrick   /// Whether this method overrides any other in the class hierarchy.
458e5dd7070Spatrick   ///
459e5dd7070Spatrick   /// A method is said to override any method in the class's
460e5dd7070Spatrick   /// base classes, its protocols, or its categories' protocols, that has
461e5dd7070Spatrick   /// the same selector and is of the same kind (class or instance).
462e5dd7070Spatrick   /// A method in an implementation is not considered as overriding the same
463e5dd7070Spatrick   /// method in the interface or its categories.
isOverriding()464e5dd7070Spatrick   bool isOverriding() const { return ObjCMethodDeclBits.IsOverriding; }
setOverriding(bool IsOver)465e5dd7070Spatrick   void setOverriding(bool IsOver) { ObjCMethodDeclBits.IsOverriding = IsOver; }
466e5dd7070Spatrick 
467e5dd7070Spatrick   /// Return overridden methods for the given \p Method.
468e5dd7070Spatrick   ///
469e5dd7070Spatrick   /// An ObjC method is considered to override any method in the class's
470e5dd7070Spatrick   /// base classes (and base's categories), its protocols, or its categories'
471e5dd7070Spatrick   /// protocols, that has
472e5dd7070Spatrick   /// the same selector and is of the same kind (class or instance).
473e5dd7070Spatrick   /// A method in an implementation is not considered as overriding the same
474e5dd7070Spatrick   /// method in the interface or its categories.
475e5dd7070Spatrick   void getOverriddenMethods(
476e5dd7070Spatrick                      SmallVectorImpl<const ObjCMethodDecl *> &Overridden) const;
477e5dd7070Spatrick 
478e5dd7070Spatrick   /// True if the method was a definition but its body was skipped.
hasSkippedBody()479e5dd7070Spatrick   bool hasSkippedBody() const { return ObjCMethodDeclBits.HasSkippedBody; }
480e5dd7070Spatrick   void setHasSkippedBody(bool Skipped = true) {
481e5dd7070Spatrick     ObjCMethodDeclBits.HasSkippedBody = Skipped;
482e5dd7070Spatrick   }
483e5dd7070Spatrick 
484e5dd7070Spatrick   /// True if the method is tagged as objc_direct
485e5dd7070Spatrick   bool isDirectMethod() const;
486e5dd7070Spatrick 
487*12c85518Srobert   /// True if the method has a parameter that's destroyed in the callee.
488*12c85518Srobert   bool hasParamDestroyedInCallee() const;
489*12c85518Srobert 
490e5dd7070Spatrick   /// Returns the property associated with this method's selector.
491e5dd7070Spatrick   ///
492e5dd7070Spatrick   /// Note that even if this particular method is not marked as a property
493e5dd7070Spatrick   /// accessor, it is still possible for it to match a property declared in a
494e5dd7070Spatrick   /// superclass. Pass \c false if you only want to check the current class.
495e5dd7070Spatrick   const ObjCPropertyDecl *findPropertyDecl(bool CheckOverrides = true) const;
496e5dd7070Spatrick 
497e5dd7070Spatrick   // Related to protocols declared in  \@protocol
setDeclImplementation(ImplementationControl ic)498e5dd7070Spatrick   void setDeclImplementation(ImplementationControl ic) {
499e5dd7070Spatrick     ObjCMethodDeclBits.DeclImplementation = ic;
500e5dd7070Spatrick   }
501e5dd7070Spatrick 
getImplementationControl()502e5dd7070Spatrick   ImplementationControl getImplementationControl() const {
503e5dd7070Spatrick     return ImplementationControl(ObjCMethodDeclBits.DeclImplementation);
504e5dd7070Spatrick   }
505e5dd7070Spatrick 
isOptional()506e5dd7070Spatrick   bool isOptional() const {
507e5dd7070Spatrick     return getImplementationControl() == Optional;
508e5dd7070Spatrick   }
509e5dd7070Spatrick 
510e5dd7070Spatrick   /// Returns true if this specific method declaration is marked with the
511e5dd7070Spatrick   /// designated initializer attribute.
512e5dd7070Spatrick   bool isThisDeclarationADesignatedInitializer() const;
513e5dd7070Spatrick 
514e5dd7070Spatrick   /// Returns true if the method selector resolves to a designated initializer
515e5dd7070Spatrick   /// in the class's interface.
516e5dd7070Spatrick   ///
517e5dd7070Spatrick   /// \param InitMethod if non-null and the function returns true, it receives
518e5dd7070Spatrick   /// the method declaration that was marked with the designated initializer
519e5dd7070Spatrick   /// attribute.
520e5dd7070Spatrick   bool isDesignatedInitializerForTheInterface(
521e5dd7070Spatrick       const ObjCMethodDecl **InitMethod = nullptr) const;
522e5dd7070Spatrick 
523e5dd7070Spatrick   /// Determine whether this method has a body.
hasBody()524e5dd7070Spatrick   bool hasBody() const override { return Body.isValid(); }
525e5dd7070Spatrick 
526e5dd7070Spatrick   /// Retrieve the body of this method, if it has one.
527e5dd7070Spatrick   Stmt *getBody() const override;
528e5dd7070Spatrick 
setLazyBody(uint64_t Offset)529e5dd7070Spatrick   void setLazyBody(uint64_t Offset) { Body = Offset; }
530e5dd7070Spatrick 
getCompoundBody()531e5dd7070Spatrick   CompoundStmt *getCompoundBody() { return (CompoundStmt*)getBody(); }
setBody(Stmt * B)532e5dd7070Spatrick   void setBody(Stmt *B) { Body = B; }
533e5dd7070Spatrick 
534e5dd7070Spatrick   /// Returns whether this specific method is a definition.
isThisDeclarationADefinition()535e5dd7070Spatrick   bool isThisDeclarationADefinition() const { return hasBody(); }
536e5dd7070Spatrick 
537e5dd7070Spatrick   /// Is this method defined in the NSObject base class?
538e5dd7070Spatrick   bool definedInNSObject(const ASTContext &) const;
539e5dd7070Spatrick 
540e5dd7070Spatrick   // Implement isa/cast/dyncast/etc.
classof(const Decl * D)541e5dd7070Spatrick   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
classofKind(Kind K)542e5dd7070Spatrick   static bool classofKind(Kind K) { return K == ObjCMethod; }
543e5dd7070Spatrick 
castToDeclContext(const ObjCMethodDecl * D)544e5dd7070Spatrick   static DeclContext *castToDeclContext(const ObjCMethodDecl *D) {
545e5dd7070Spatrick     return static_cast<DeclContext *>(const_cast<ObjCMethodDecl*>(D));
546e5dd7070Spatrick   }
547e5dd7070Spatrick 
castFromDeclContext(const DeclContext * DC)548e5dd7070Spatrick   static ObjCMethodDecl *castFromDeclContext(const DeclContext *DC) {
549e5dd7070Spatrick     return static_cast<ObjCMethodDecl *>(const_cast<DeclContext*>(DC));
550e5dd7070Spatrick   }
551e5dd7070Spatrick };
552e5dd7070Spatrick 
553e5dd7070Spatrick /// Describes the variance of a given generic parameter.
554e5dd7070Spatrick enum class ObjCTypeParamVariance : uint8_t {
555e5dd7070Spatrick   /// The parameter is invariant: must match exactly.
556e5dd7070Spatrick   Invariant,
557e5dd7070Spatrick 
558e5dd7070Spatrick   /// The parameter is covariant, e.g., X<T> is a subtype of X<U> when
559e5dd7070Spatrick   /// the type parameter is covariant and T is a subtype of U.
560e5dd7070Spatrick   Covariant,
561e5dd7070Spatrick 
562e5dd7070Spatrick   /// The parameter is contravariant, e.g., X<T> is a subtype of X<U>
563e5dd7070Spatrick   /// when the type parameter is covariant and U is a subtype of T.
564e5dd7070Spatrick   Contravariant,
565e5dd7070Spatrick };
566e5dd7070Spatrick 
567e5dd7070Spatrick /// Represents the declaration of an Objective-C type parameter.
568e5dd7070Spatrick ///
569e5dd7070Spatrick /// \code
570e5dd7070Spatrick /// @interface NSDictionary<Key : id<NSCopying>, Value>
571e5dd7070Spatrick /// @end
572e5dd7070Spatrick /// \endcode
573e5dd7070Spatrick ///
574e5dd7070Spatrick /// In the example above, both \c Key and \c Value are represented by
575e5dd7070Spatrick /// \c ObjCTypeParamDecl. \c Key has an explicit bound of \c id<NSCopying>,
576e5dd7070Spatrick /// while \c Value gets an implicit bound of \c id.
577e5dd7070Spatrick ///
578e5dd7070Spatrick /// Objective-C type parameters are typedef-names in the grammar,
579e5dd7070Spatrick class ObjCTypeParamDecl : public TypedefNameDecl {
580e5dd7070Spatrick   /// Index of this type parameter in the type parameter list.
581e5dd7070Spatrick   unsigned Index : 14;
582e5dd7070Spatrick 
583e5dd7070Spatrick   /// The variance of the type parameter.
584e5dd7070Spatrick   unsigned Variance : 2;
585e5dd7070Spatrick 
586e5dd7070Spatrick   /// The location of the variance, if any.
587e5dd7070Spatrick   SourceLocation VarianceLoc;
588e5dd7070Spatrick 
589e5dd7070Spatrick   /// The location of the ':', which will be valid when the bound was
590e5dd7070Spatrick   /// explicitly specified.
591e5dd7070Spatrick   SourceLocation ColonLoc;
592e5dd7070Spatrick 
ObjCTypeParamDecl(ASTContext & ctx,DeclContext * dc,ObjCTypeParamVariance variance,SourceLocation varianceLoc,unsigned index,SourceLocation nameLoc,IdentifierInfo * name,SourceLocation colonLoc,TypeSourceInfo * boundInfo)593e5dd7070Spatrick   ObjCTypeParamDecl(ASTContext &ctx, DeclContext *dc,
594e5dd7070Spatrick                     ObjCTypeParamVariance variance, SourceLocation varianceLoc,
595e5dd7070Spatrick                     unsigned index,
596e5dd7070Spatrick                     SourceLocation nameLoc, IdentifierInfo *name,
597e5dd7070Spatrick                     SourceLocation colonLoc, TypeSourceInfo *boundInfo)
598e5dd7070Spatrick       : TypedefNameDecl(ObjCTypeParam, ctx, dc, nameLoc, nameLoc, name,
599e5dd7070Spatrick                         boundInfo),
600e5dd7070Spatrick         Index(index), Variance(static_cast<unsigned>(variance)),
601e5dd7070Spatrick         VarianceLoc(varianceLoc), ColonLoc(colonLoc) {}
602e5dd7070Spatrick 
603e5dd7070Spatrick   void anchor() override;
604e5dd7070Spatrick 
605e5dd7070Spatrick public:
606e5dd7070Spatrick   friend class ASTDeclReader;
607e5dd7070Spatrick   friend class ASTDeclWriter;
608e5dd7070Spatrick 
609e5dd7070Spatrick   static ObjCTypeParamDecl *Create(ASTContext &ctx, DeclContext *dc,
610e5dd7070Spatrick                                    ObjCTypeParamVariance variance,
611e5dd7070Spatrick                                    SourceLocation varianceLoc,
612e5dd7070Spatrick                                    unsigned index,
613e5dd7070Spatrick                                    SourceLocation nameLoc,
614e5dd7070Spatrick                                    IdentifierInfo *name,
615e5dd7070Spatrick                                    SourceLocation colonLoc,
616e5dd7070Spatrick                                    TypeSourceInfo *boundInfo);
617e5dd7070Spatrick   static ObjCTypeParamDecl *CreateDeserialized(ASTContext &ctx, unsigned ID);
618e5dd7070Spatrick 
619e5dd7070Spatrick   SourceRange getSourceRange() const override LLVM_READONLY;
620e5dd7070Spatrick 
621e5dd7070Spatrick   /// Determine the variance of this type parameter.
getVariance()622e5dd7070Spatrick   ObjCTypeParamVariance getVariance() const {
623e5dd7070Spatrick     return static_cast<ObjCTypeParamVariance>(Variance);
624e5dd7070Spatrick   }
625e5dd7070Spatrick 
626e5dd7070Spatrick   /// Set the variance of this type parameter.
setVariance(ObjCTypeParamVariance variance)627e5dd7070Spatrick   void setVariance(ObjCTypeParamVariance variance) {
628e5dd7070Spatrick     Variance = static_cast<unsigned>(variance);
629e5dd7070Spatrick   }
630e5dd7070Spatrick 
631e5dd7070Spatrick   /// Retrieve the location of the variance keyword.
getVarianceLoc()632e5dd7070Spatrick   SourceLocation getVarianceLoc() const { return VarianceLoc; }
633e5dd7070Spatrick 
634e5dd7070Spatrick   /// Retrieve the index into its type parameter list.
getIndex()635e5dd7070Spatrick   unsigned getIndex() const { return Index; }
636e5dd7070Spatrick 
637e5dd7070Spatrick   /// Whether this type parameter has an explicitly-written type bound, e.g.,
638e5dd7070Spatrick   /// "T : NSView".
hasExplicitBound()639e5dd7070Spatrick   bool hasExplicitBound() const { return ColonLoc.isValid(); }
640e5dd7070Spatrick 
641e5dd7070Spatrick   /// Retrieve the location of the ':' separating the type parameter name
642e5dd7070Spatrick   /// from the explicitly-specified bound.
getColonLoc()643e5dd7070Spatrick   SourceLocation getColonLoc() const { return ColonLoc; }
644e5dd7070Spatrick 
645e5dd7070Spatrick   // Implement isa/cast/dyncast/etc.
classof(const Decl * D)646e5dd7070Spatrick   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
classofKind(Kind K)647e5dd7070Spatrick   static bool classofKind(Kind K) { return K == ObjCTypeParam; }
648e5dd7070Spatrick };
649e5dd7070Spatrick 
650e5dd7070Spatrick /// Stores a list of Objective-C type parameters for a parameterized class
651e5dd7070Spatrick /// or a category/extension thereof.
652e5dd7070Spatrick ///
653e5dd7070Spatrick /// \code
654e5dd7070Spatrick /// @interface NSArray<T> // stores the <T>
655e5dd7070Spatrick /// @end
656e5dd7070Spatrick /// \endcode
657e5dd7070Spatrick class ObjCTypeParamList final
658e5dd7070Spatrick     : private llvm::TrailingObjects<ObjCTypeParamList, ObjCTypeParamDecl *> {
659e5dd7070Spatrick   /// Location of the left and right angle brackets.
660a9ac8606Spatrick   SourceRange Brackets;
661e5dd7070Spatrick   /// The number of parameters in the list, which are tail-allocated.
662e5dd7070Spatrick   unsigned NumParams;
663e5dd7070Spatrick 
664e5dd7070Spatrick   ObjCTypeParamList(SourceLocation lAngleLoc,
665e5dd7070Spatrick                     ArrayRef<ObjCTypeParamDecl *> typeParams,
666e5dd7070Spatrick                     SourceLocation rAngleLoc);
667e5dd7070Spatrick 
668e5dd7070Spatrick public:
669e5dd7070Spatrick   friend TrailingObjects;
670e5dd7070Spatrick 
671e5dd7070Spatrick   /// Create a new Objective-C type parameter list.
672e5dd7070Spatrick   static ObjCTypeParamList *create(ASTContext &ctx,
673e5dd7070Spatrick                                    SourceLocation lAngleLoc,
674e5dd7070Spatrick                                    ArrayRef<ObjCTypeParamDecl *> typeParams,
675e5dd7070Spatrick                                    SourceLocation rAngleLoc);
676e5dd7070Spatrick 
677e5dd7070Spatrick   /// Iterate through the type parameters in the list.
678e5dd7070Spatrick   using iterator = ObjCTypeParamDecl **;
679e5dd7070Spatrick 
begin()680e5dd7070Spatrick   iterator begin() { return getTrailingObjects<ObjCTypeParamDecl *>(); }
681e5dd7070Spatrick 
end()682e5dd7070Spatrick   iterator end() { return begin() + size(); }
683e5dd7070Spatrick 
684e5dd7070Spatrick   /// Determine the number of type parameters in this list.
size()685e5dd7070Spatrick   unsigned size() const { return NumParams; }
686e5dd7070Spatrick 
687e5dd7070Spatrick   // Iterate through the type parameters in the list.
688e5dd7070Spatrick   using const_iterator = ObjCTypeParamDecl * const *;
689e5dd7070Spatrick 
begin()690e5dd7070Spatrick   const_iterator begin() const {
691e5dd7070Spatrick     return getTrailingObjects<ObjCTypeParamDecl *>();
692e5dd7070Spatrick   }
693e5dd7070Spatrick 
end()694e5dd7070Spatrick   const_iterator end() const {
695e5dd7070Spatrick     return begin() + size();
696e5dd7070Spatrick   }
697e5dd7070Spatrick 
front()698e5dd7070Spatrick   ObjCTypeParamDecl *front() const {
699e5dd7070Spatrick     assert(size() > 0 && "empty Objective-C type parameter list");
700e5dd7070Spatrick     return *begin();
701e5dd7070Spatrick   }
702e5dd7070Spatrick 
back()703e5dd7070Spatrick   ObjCTypeParamDecl *back() const {
704e5dd7070Spatrick     assert(size() > 0 && "empty Objective-C type parameter list");
705e5dd7070Spatrick     return *(end() - 1);
706e5dd7070Spatrick   }
707e5dd7070Spatrick 
getLAngleLoc()708a9ac8606Spatrick   SourceLocation getLAngleLoc() const { return Brackets.getBegin(); }
getRAngleLoc()709a9ac8606Spatrick   SourceLocation getRAngleLoc() const { return Brackets.getEnd(); }
getSourceRange()710a9ac8606Spatrick   SourceRange getSourceRange() const { return Brackets; }
711e5dd7070Spatrick 
712e5dd7070Spatrick   /// Gather the default set of type arguments to be substituted for
713e5dd7070Spatrick   /// these type parameters when dealing with an unspecialized type.
714e5dd7070Spatrick   void gatherDefaultTypeArgs(SmallVectorImpl<QualType> &typeArgs) const;
715e5dd7070Spatrick };
716e5dd7070Spatrick 
717e5dd7070Spatrick enum class ObjCPropertyQueryKind : uint8_t {
718e5dd7070Spatrick   OBJC_PR_query_unknown = 0x00,
719e5dd7070Spatrick   OBJC_PR_query_instance,
720e5dd7070Spatrick   OBJC_PR_query_class
721e5dd7070Spatrick };
722e5dd7070Spatrick 
723e5dd7070Spatrick /// Represents one property declaration in an Objective-C interface.
724e5dd7070Spatrick ///
725e5dd7070Spatrick /// For example:
726e5dd7070Spatrick /// \code{.mm}
727e5dd7070Spatrick /// \@property (assign, readwrite) int MyProperty;
728e5dd7070Spatrick /// \endcode
729e5dd7070Spatrick class ObjCPropertyDecl : public NamedDecl {
730e5dd7070Spatrick   void anchor() override;
731e5dd7070Spatrick 
732e5dd7070Spatrick public:
733e5dd7070Spatrick   enum SetterKind { Assign, Retain, Copy, Weak };
734e5dd7070Spatrick   enum PropertyControl { None, Required, Optional };
735e5dd7070Spatrick 
736e5dd7070Spatrick private:
737e5dd7070Spatrick   // location of \@property
738e5dd7070Spatrick   SourceLocation AtLoc;
739e5dd7070Spatrick 
740e5dd7070Spatrick   // location of '(' starting attribute list or null.
741e5dd7070Spatrick   SourceLocation LParenLoc;
742e5dd7070Spatrick 
743e5dd7070Spatrick   QualType DeclType;
744e5dd7070Spatrick   TypeSourceInfo *DeclTypeSourceInfo;
745ec727ea7Spatrick   unsigned PropertyAttributes : NumObjCPropertyAttrsBits;
746ec727ea7Spatrick   unsigned PropertyAttributesAsWritten : NumObjCPropertyAttrsBits;
747e5dd7070Spatrick 
748e5dd7070Spatrick   // \@required/\@optional
749e5dd7070Spatrick   unsigned PropertyImplementation : 2;
750e5dd7070Spatrick 
751e5dd7070Spatrick   // getter name of NULL if no getter
752e5dd7070Spatrick   Selector GetterName;
753e5dd7070Spatrick 
754e5dd7070Spatrick   // setter name of NULL if no setter
755e5dd7070Spatrick   Selector SetterName;
756e5dd7070Spatrick 
757e5dd7070Spatrick   // location of the getter attribute's value
758e5dd7070Spatrick   SourceLocation GetterNameLoc;
759e5dd7070Spatrick 
760e5dd7070Spatrick   // location of the setter attribute's value
761e5dd7070Spatrick   SourceLocation SetterNameLoc;
762e5dd7070Spatrick 
763e5dd7070Spatrick   // Declaration of getter instance method
764e5dd7070Spatrick   ObjCMethodDecl *GetterMethodDecl = nullptr;
765e5dd7070Spatrick 
766e5dd7070Spatrick   // Declaration of setter instance method
767e5dd7070Spatrick   ObjCMethodDecl *SetterMethodDecl = nullptr;
768e5dd7070Spatrick 
769e5dd7070Spatrick   // Synthesize ivar for this property
770e5dd7070Spatrick   ObjCIvarDecl *PropertyIvarDecl = nullptr;
771e5dd7070Spatrick 
ObjCPropertyDecl(DeclContext * DC,SourceLocation L,IdentifierInfo * Id,SourceLocation AtLocation,SourceLocation LParenLocation,QualType T,TypeSourceInfo * TSI,PropertyControl propControl)772e5dd7070Spatrick   ObjCPropertyDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
773e5dd7070Spatrick                    SourceLocation AtLocation, SourceLocation LParenLocation,
774ec727ea7Spatrick                    QualType T, TypeSourceInfo *TSI, PropertyControl propControl)
775e5dd7070Spatrick       : NamedDecl(ObjCProperty, DC, L, Id), AtLoc(AtLocation),
776e5dd7070Spatrick         LParenLoc(LParenLocation), DeclType(T), DeclTypeSourceInfo(TSI),
777ec727ea7Spatrick         PropertyAttributes(ObjCPropertyAttribute::kind_noattr),
778ec727ea7Spatrick         PropertyAttributesAsWritten(ObjCPropertyAttribute::kind_noattr),
779*12c85518Srobert         PropertyImplementation(propControl) {}
780e5dd7070Spatrick 
781e5dd7070Spatrick public:
782*12c85518Srobert   static ObjCPropertyDecl *
783*12c85518Srobert   Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
784*12c85518Srobert          SourceLocation AtLocation, SourceLocation LParenLocation, QualType T,
785*12c85518Srobert          TypeSourceInfo *TSI, PropertyControl propControl = None);
786e5dd7070Spatrick 
787e5dd7070Spatrick   static ObjCPropertyDecl *CreateDeserialized(ASTContext &C, unsigned ID);
788e5dd7070Spatrick 
getAtLoc()789e5dd7070Spatrick   SourceLocation getAtLoc() const { return AtLoc; }
setAtLoc(SourceLocation L)790e5dd7070Spatrick   void setAtLoc(SourceLocation L) { AtLoc = L; }
791e5dd7070Spatrick 
getLParenLoc()792e5dd7070Spatrick   SourceLocation getLParenLoc() const { return LParenLoc; }
setLParenLoc(SourceLocation L)793e5dd7070Spatrick   void setLParenLoc(SourceLocation L) { LParenLoc = L; }
794e5dd7070Spatrick 
getTypeSourceInfo()795e5dd7070Spatrick   TypeSourceInfo *getTypeSourceInfo() const { return DeclTypeSourceInfo; }
796e5dd7070Spatrick 
getType()797e5dd7070Spatrick   QualType getType() const { return DeclType; }
798e5dd7070Spatrick 
setType(QualType T,TypeSourceInfo * TSI)799e5dd7070Spatrick   void setType(QualType T, TypeSourceInfo *TSI) {
800e5dd7070Spatrick     DeclType = T;
801e5dd7070Spatrick     DeclTypeSourceInfo = TSI;
802e5dd7070Spatrick   }
803e5dd7070Spatrick 
804e5dd7070Spatrick   /// Retrieve the type when this property is used with a specific base object
805e5dd7070Spatrick   /// type.
806e5dd7070Spatrick   QualType getUsageType(QualType objectType) const;
807e5dd7070Spatrick 
getPropertyAttributes()808ec727ea7Spatrick   ObjCPropertyAttribute::Kind getPropertyAttributes() const {
809ec727ea7Spatrick     return ObjCPropertyAttribute::Kind(PropertyAttributes);
810e5dd7070Spatrick   }
811e5dd7070Spatrick 
setPropertyAttributes(ObjCPropertyAttribute::Kind PRVal)812ec727ea7Spatrick   void setPropertyAttributes(ObjCPropertyAttribute::Kind PRVal) {
813e5dd7070Spatrick     PropertyAttributes |= PRVal;
814e5dd7070Spatrick   }
815e5dd7070Spatrick 
overwritePropertyAttributes(unsigned PRVal)816e5dd7070Spatrick   void overwritePropertyAttributes(unsigned PRVal) {
817e5dd7070Spatrick     PropertyAttributes = PRVal;
818e5dd7070Spatrick   }
819e5dd7070Spatrick 
getPropertyAttributesAsWritten()820ec727ea7Spatrick   ObjCPropertyAttribute::Kind getPropertyAttributesAsWritten() const {
821ec727ea7Spatrick     return ObjCPropertyAttribute::Kind(PropertyAttributesAsWritten);
822e5dd7070Spatrick   }
823e5dd7070Spatrick 
setPropertyAttributesAsWritten(ObjCPropertyAttribute::Kind PRVal)824ec727ea7Spatrick   void setPropertyAttributesAsWritten(ObjCPropertyAttribute::Kind PRVal) {
825e5dd7070Spatrick     PropertyAttributesAsWritten = PRVal;
826e5dd7070Spatrick   }
827e5dd7070Spatrick 
828e5dd7070Spatrick   // Helper methods for accessing attributes.
829e5dd7070Spatrick 
830e5dd7070Spatrick   /// isReadOnly - Return true iff the property has a setter.
isReadOnly()831e5dd7070Spatrick   bool isReadOnly() const {
832ec727ea7Spatrick     return (PropertyAttributes & ObjCPropertyAttribute::kind_readonly);
833e5dd7070Spatrick   }
834e5dd7070Spatrick 
835e5dd7070Spatrick   /// isAtomic - Return true if the property is atomic.
isAtomic()836e5dd7070Spatrick   bool isAtomic() const {
837ec727ea7Spatrick     return (PropertyAttributes & ObjCPropertyAttribute::kind_atomic);
838e5dd7070Spatrick   }
839e5dd7070Spatrick 
840e5dd7070Spatrick   /// isRetaining - Return true if the property retains its value.
isRetaining()841e5dd7070Spatrick   bool isRetaining() const {
842ec727ea7Spatrick     return (PropertyAttributes & (ObjCPropertyAttribute::kind_retain |
843ec727ea7Spatrick                                   ObjCPropertyAttribute::kind_strong |
844ec727ea7Spatrick                                   ObjCPropertyAttribute::kind_copy));
845e5dd7070Spatrick   }
846e5dd7070Spatrick 
isInstanceProperty()847e5dd7070Spatrick   bool isInstanceProperty() const { return !isClassProperty(); }
isClassProperty()848ec727ea7Spatrick   bool isClassProperty() const {
849ec727ea7Spatrick     return PropertyAttributes & ObjCPropertyAttribute::kind_class;
850ec727ea7Spatrick   }
851a9ac8606Spatrick   bool isDirectProperty() const;
852e5dd7070Spatrick 
getQueryKind()853e5dd7070Spatrick   ObjCPropertyQueryKind getQueryKind() const {
854e5dd7070Spatrick     return isClassProperty() ? ObjCPropertyQueryKind::OBJC_PR_query_class :
855e5dd7070Spatrick                                ObjCPropertyQueryKind::OBJC_PR_query_instance;
856e5dd7070Spatrick   }
857e5dd7070Spatrick 
getQueryKind(bool isClassProperty)858e5dd7070Spatrick   static ObjCPropertyQueryKind getQueryKind(bool isClassProperty) {
859e5dd7070Spatrick     return isClassProperty ? ObjCPropertyQueryKind::OBJC_PR_query_class :
860e5dd7070Spatrick                              ObjCPropertyQueryKind::OBJC_PR_query_instance;
861e5dd7070Spatrick   }
862e5dd7070Spatrick 
863e5dd7070Spatrick   /// getSetterKind - Return the method used for doing assignment in
864e5dd7070Spatrick   /// the property setter. This is only valid if the property has been
865e5dd7070Spatrick   /// defined to have a setter.
getSetterKind()866e5dd7070Spatrick   SetterKind getSetterKind() const {
867ec727ea7Spatrick     if (PropertyAttributes & ObjCPropertyAttribute::kind_strong)
868e5dd7070Spatrick       return getType()->isBlockPointerType() ? Copy : Retain;
869ec727ea7Spatrick     if (PropertyAttributes & ObjCPropertyAttribute::kind_retain)
870e5dd7070Spatrick       return Retain;
871ec727ea7Spatrick     if (PropertyAttributes & ObjCPropertyAttribute::kind_copy)
872e5dd7070Spatrick       return Copy;
873ec727ea7Spatrick     if (PropertyAttributes & ObjCPropertyAttribute::kind_weak)
874e5dd7070Spatrick       return Weak;
875e5dd7070Spatrick     return Assign;
876e5dd7070Spatrick   }
877e5dd7070Spatrick 
getGetterName()878e5dd7070Spatrick   Selector getGetterName() const { return GetterName; }
getGetterNameLoc()879e5dd7070Spatrick   SourceLocation getGetterNameLoc() const { return GetterNameLoc; }
880e5dd7070Spatrick 
881e5dd7070Spatrick   void setGetterName(Selector Sel, SourceLocation Loc = SourceLocation()) {
882e5dd7070Spatrick     GetterName = Sel;
883e5dd7070Spatrick     GetterNameLoc = Loc;
884e5dd7070Spatrick   }
885e5dd7070Spatrick 
getSetterName()886e5dd7070Spatrick   Selector getSetterName() const { return SetterName; }
getSetterNameLoc()887e5dd7070Spatrick   SourceLocation getSetterNameLoc() const { return SetterNameLoc; }
888e5dd7070Spatrick 
889e5dd7070Spatrick   void setSetterName(Selector Sel, SourceLocation Loc = SourceLocation()) {
890e5dd7070Spatrick     SetterName = Sel;
891e5dd7070Spatrick     SetterNameLoc = Loc;
892e5dd7070Spatrick   }
893e5dd7070Spatrick 
getGetterMethodDecl()894e5dd7070Spatrick   ObjCMethodDecl *getGetterMethodDecl() const { return GetterMethodDecl; }
setGetterMethodDecl(ObjCMethodDecl * gDecl)895e5dd7070Spatrick   void setGetterMethodDecl(ObjCMethodDecl *gDecl) { GetterMethodDecl = gDecl; }
896e5dd7070Spatrick 
getSetterMethodDecl()897e5dd7070Spatrick   ObjCMethodDecl *getSetterMethodDecl() const { return SetterMethodDecl; }
setSetterMethodDecl(ObjCMethodDecl * gDecl)898e5dd7070Spatrick   void setSetterMethodDecl(ObjCMethodDecl *gDecl) { SetterMethodDecl = gDecl; }
899e5dd7070Spatrick 
900e5dd7070Spatrick   // Related to \@optional/\@required declared in \@protocol
setPropertyImplementation(PropertyControl pc)901e5dd7070Spatrick   void setPropertyImplementation(PropertyControl pc) {
902e5dd7070Spatrick     PropertyImplementation = pc;
903e5dd7070Spatrick   }
904e5dd7070Spatrick 
getPropertyImplementation()905e5dd7070Spatrick   PropertyControl getPropertyImplementation() const {
906e5dd7070Spatrick     return PropertyControl(PropertyImplementation);
907e5dd7070Spatrick   }
908e5dd7070Spatrick 
isOptional()909e5dd7070Spatrick   bool isOptional() const {
910e5dd7070Spatrick     return getPropertyImplementation() == PropertyControl::Optional;
911e5dd7070Spatrick   }
912e5dd7070Spatrick 
setPropertyIvarDecl(ObjCIvarDecl * Ivar)913e5dd7070Spatrick   void setPropertyIvarDecl(ObjCIvarDecl *Ivar) {
914e5dd7070Spatrick     PropertyIvarDecl = Ivar;
915e5dd7070Spatrick   }
916e5dd7070Spatrick 
getPropertyIvarDecl()917e5dd7070Spatrick   ObjCIvarDecl *getPropertyIvarDecl() const {
918e5dd7070Spatrick     return PropertyIvarDecl;
919e5dd7070Spatrick   }
920e5dd7070Spatrick 
getSourceRange()921e5dd7070Spatrick   SourceRange getSourceRange() const override LLVM_READONLY {
922e5dd7070Spatrick     return SourceRange(AtLoc, getLocation());
923e5dd7070Spatrick   }
924e5dd7070Spatrick 
925e5dd7070Spatrick   /// Get the default name of the synthesized ivar.
926e5dd7070Spatrick   IdentifierInfo *getDefaultSynthIvarName(ASTContext &Ctx) const;
927e5dd7070Spatrick 
928e5dd7070Spatrick   /// Lookup a property by name in the specified DeclContext.
929e5dd7070Spatrick   static ObjCPropertyDecl *findPropertyDecl(const DeclContext *DC,
930e5dd7070Spatrick                                             const IdentifierInfo *propertyID,
931e5dd7070Spatrick                                             ObjCPropertyQueryKind queryKind);
932e5dd7070Spatrick 
classof(const Decl * D)933e5dd7070Spatrick   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
classofKind(Kind K)934e5dd7070Spatrick   static bool classofKind(Kind K) { return K == ObjCProperty; }
935e5dd7070Spatrick };
936e5dd7070Spatrick 
937e5dd7070Spatrick /// ObjCContainerDecl - Represents a container for method declarations.
938e5dd7070Spatrick /// Current sub-classes are ObjCInterfaceDecl, ObjCCategoryDecl,
939e5dd7070Spatrick /// ObjCProtocolDecl, and ObjCImplDecl.
940e5dd7070Spatrick ///
941e5dd7070Spatrick class ObjCContainerDecl : public NamedDecl, public DeclContext {
942e5dd7070Spatrick   // This class stores some data in DeclContext::ObjCContainerDeclBits
943e5dd7070Spatrick   // to save some space. Use the provided accessors to access it.
944e5dd7070Spatrick 
945e5dd7070Spatrick   // These two locations in the range mark the end of the method container.
946e5dd7070Spatrick   // The first points to the '@' token, and the second to the 'end' token.
947e5dd7070Spatrick   SourceRange AtEnd;
948e5dd7070Spatrick 
949e5dd7070Spatrick   void anchor() override;
950e5dd7070Spatrick 
951e5dd7070Spatrick public:
952e5dd7070Spatrick   ObjCContainerDecl(Kind DK, DeclContext *DC, IdentifierInfo *Id,
953e5dd7070Spatrick                     SourceLocation nameLoc, SourceLocation atStartLoc);
954e5dd7070Spatrick 
955e5dd7070Spatrick   // Iterator access to instance/class properties.
956e5dd7070Spatrick   using prop_iterator = specific_decl_iterator<ObjCPropertyDecl>;
957e5dd7070Spatrick   using prop_range =
958e5dd7070Spatrick       llvm::iterator_range<specific_decl_iterator<ObjCPropertyDecl>>;
959e5dd7070Spatrick 
properties()960e5dd7070Spatrick   prop_range properties() const { return prop_range(prop_begin(), prop_end()); }
961e5dd7070Spatrick 
prop_begin()962e5dd7070Spatrick   prop_iterator prop_begin() const {
963e5dd7070Spatrick     return prop_iterator(decls_begin());
964e5dd7070Spatrick   }
965e5dd7070Spatrick 
prop_end()966e5dd7070Spatrick   prop_iterator prop_end() const {
967e5dd7070Spatrick     return prop_iterator(decls_end());
968e5dd7070Spatrick   }
969e5dd7070Spatrick 
970e5dd7070Spatrick   using instprop_iterator =
971e5dd7070Spatrick       filtered_decl_iterator<ObjCPropertyDecl,
972e5dd7070Spatrick                              &ObjCPropertyDecl::isInstanceProperty>;
973e5dd7070Spatrick   using instprop_range = llvm::iterator_range<instprop_iterator>;
974e5dd7070Spatrick 
instance_properties()975e5dd7070Spatrick   instprop_range instance_properties() const {
976e5dd7070Spatrick     return instprop_range(instprop_begin(), instprop_end());
977e5dd7070Spatrick   }
978e5dd7070Spatrick 
instprop_begin()979e5dd7070Spatrick   instprop_iterator instprop_begin() const {
980e5dd7070Spatrick     return instprop_iterator(decls_begin());
981e5dd7070Spatrick   }
982e5dd7070Spatrick 
instprop_end()983e5dd7070Spatrick   instprop_iterator instprop_end() const {
984e5dd7070Spatrick     return instprop_iterator(decls_end());
985e5dd7070Spatrick   }
986e5dd7070Spatrick 
987e5dd7070Spatrick   using classprop_iterator =
988e5dd7070Spatrick       filtered_decl_iterator<ObjCPropertyDecl,
989e5dd7070Spatrick                              &ObjCPropertyDecl::isClassProperty>;
990e5dd7070Spatrick   using classprop_range = llvm::iterator_range<classprop_iterator>;
991e5dd7070Spatrick 
class_properties()992e5dd7070Spatrick   classprop_range class_properties() const {
993e5dd7070Spatrick     return classprop_range(classprop_begin(), classprop_end());
994e5dd7070Spatrick   }
995e5dd7070Spatrick 
classprop_begin()996e5dd7070Spatrick   classprop_iterator classprop_begin() const {
997e5dd7070Spatrick     return classprop_iterator(decls_begin());
998e5dd7070Spatrick   }
999e5dd7070Spatrick 
classprop_end()1000e5dd7070Spatrick   classprop_iterator classprop_end() const {
1001e5dd7070Spatrick     return classprop_iterator(decls_end());
1002e5dd7070Spatrick   }
1003e5dd7070Spatrick 
1004e5dd7070Spatrick   // Iterator access to instance/class methods.
1005e5dd7070Spatrick   using method_iterator = specific_decl_iterator<ObjCMethodDecl>;
1006e5dd7070Spatrick   using method_range =
1007e5dd7070Spatrick       llvm::iterator_range<specific_decl_iterator<ObjCMethodDecl>>;
1008e5dd7070Spatrick 
methods()1009e5dd7070Spatrick   method_range methods() const {
1010e5dd7070Spatrick     return method_range(meth_begin(), meth_end());
1011e5dd7070Spatrick   }
1012e5dd7070Spatrick 
meth_begin()1013e5dd7070Spatrick   method_iterator meth_begin() const {
1014e5dd7070Spatrick     return method_iterator(decls_begin());
1015e5dd7070Spatrick   }
1016e5dd7070Spatrick 
meth_end()1017e5dd7070Spatrick   method_iterator meth_end() const {
1018e5dd7070Spatrick     return method_iterator(decls_end());
1019e5dd7070Spatrick   }
1020e5dd7070Spatrick 
1021e5dd7070Spatrick   using instmeth_iterator =
1022e5dd7070Spatrick       filtered_decl_iterator<ObjCMethodDecl,
1023e5dd7070Spatrick                              &ObjCMethodDecl::isInstanceMethod>;
1024e5dd7070Spatrick   using instmeth_range = llvm::iterator_range<instmeth_iterator>;
1025e5dd7070Spatrick 
instance_methods()1026e5dd7070Spatrick   instmeth_range instance_methods() const {
1027e5dd7070Spatrick     return instmeth_range(instmeth_begin(), instmeth_end());
1028e5dd7070Spatrick   }
1029e5dd7070Spatrick 
instmeth_begin()1030e5dd7070Spatrick   instmeth_iterator instmeth_begin() const {
1031e5dd7070Spatrick     return instmeth_iterator(decls_begin());
1032e5dd7070Spatrick   }
1033e5dd7070Spatrick 
instmeth_end()1034e5dd7070Spatrick   instmeth_iterator instmeth_end() const {
1035e5dd7070Spatrick     return instmeth_iterator(decls_end());
1036e5dd7070Spatrick   }
1037e5dd7070Spatrick 
1038e5dd7070Spatrick   using classmeth_iterator =
1039e5dd7070Spatrick       filtered_decl_iterator<ObjCMethodDecl,
1040e5dd7070Spatrick                              &ObjCMethodDecl::isClassMethod>;
1041e5dd7070Spatrick   using classmeth_range = llvm::iterator_range<classmeth_iterator>;
1042e5dd7070Spatrick 
class_methods()1043e5dd7070Spatrick   classmeth_range class_methods() const {
1044e5dd7070Spatrick     return classmeth_range(classmeth_begin(), classmeth_end());
1045e5dd7070Spatrick   }
1046e5dd7070Spatrick 
classmeth_begin()1047e5dd7070Spatrick   classmeth_iterator classmeth_begin() const {
1048e5dd7070Spatrick     return classmeth_iterator(decls_begin());
1049e5dd7070Spatrick   }
1050e5dd7070Spatrick 
classmeth_end()1051e5dd7070Spatrick   classmeth_iterator classmeth_end() const {
1052e5dd7070Spatrick     return classmeth_iterator(decls_end());
1053e5dd7070Spatrick   }
1054e5dd7070Spatrick 
1055e5dd7070Spatrick   // Get the local instance/class method declared in this interface.
1056e5dd7070Spatrick   ObjCMethodDecl *getMethod(Selector Sel, bool isInstance,
1057e5dd7070Spatrick                             bool AllowHidden = false) const;
1058e5dd7070Spatrick 
1059e5dd7070Spatrick   ObjCMethodDecl *getInstanceMethod(Selector Sel,
1060e5dd7070Spatrick                                     bool AllowHidden = false) const {
1061e5dd7070Spatrick     return getMethod(Sel, true/*isInstance*/, AllowHidden);
1062e5dd7070Spatrick   }
1063e5dd7070Spatrick 
1064e5dd7070Spatrick   ObjCMethodDecl *getClassMethod(Selector Sel, bool AllowHidden = false) const {
1065e5dd7070Spatrick     return getMethod(Sel, false/*isInstance*/, AllowHidden);
1066e5dd7070Spatrick   }
1067e5dd7070Spatrick 
1068e5dd7070Spatrick   bool HasUserDeclaredSetterMethod(const ObjCPropertyDecl *P) const;
1069e5dd7070Spatrick   ObjCIvarDecl *getIvarDecl(IdentifierInfo *Id) const;
1070e5dd7070Spatrick 
1071*12c85518Srobert   ObjCPropertyDecl *getProperty(const IdentifierInfo *Id,
1072*12c85518Srobert                                 bool IsInstance) const;
1073*12c85518Srobert 
1074e5dd7070Spatrick   ObjCPropertyDecl *
1075e5dd7070Spatrick   FindPropertyDeclaration(const IdentifierInfo *PropertyId,
1076e5dd7070Spatrick                           ObjCPropertyQueryKind QueryKind) const;
1077e5dd7070Spatrick 
1078e5dd7070Spatrick   using PropertyMap =
1079*12c85518Srobert       llvm::MapVector<std::pair<IdentifierInfo *, unsigned /*isClassProperty*/>,
1080e5dd7070Spatrick                       ObjCPropertyDecl *>;
1081e5dd7070Spatrick   using ProtocolPropertySet = llvm::SmallDenseSet<const ObjCProtocolDecl *, 8>;
1082e5dd7070Spatrick   using PropertyDeclOrder = llvm::SmallVector<ObjCPropertyDecl *, 8>;
1083e5dd7070Spatrick 
1084e5dd7070Spatrick   /// This routine collects list of properties to be implemented in the class.
1085e5dd7070Spatrick   /// This includes, class's and its conforming protocols' properties.
1086e5dd7070Spatrick   /// Note, the superclass's properties are not included in the list.
collectPropertiesToImplement(PropertyMap & PM)1087*12c85518Srobert   virtual void collectPropertiesToImplement(PropertyMap &PM) const {}
1088e5dd7070Spatrick 
getAtStartLoc()1089e5dd7070Spatrick   SourceLocation getAtStartLoc() const { return ObjCContainerDeclBits.AtStart; }
1090e5dd7070Spatrick 
setAtStartLoc(SourceLocation Loc)1091e5dd7070Spatrick   void setAtStartLoc(SourceLocation Loc) {
1092e5dd7070Spatrick     ObjCContainerDeclBits.AtStart = Loc;
1093e5dd7070Spatrick   }
1094e5dd7070Spatrick 
1095e5dd7070Spatrick   // Marks the end of the container.
getAtEndRange()1096e5dd7070Spatrick   SourceRange getAtEndRange() const { return AtEnd; }
1097e5dd7070Spatrick 
setAtEndRange(SourceRange atEnd)1098e5dd7070Spatrick   void setAtEndRange(SourceRange atEnd) { AtEnd = atEnd; }
1099e5dd7070Spatrick 
getSourceRange()1100e5dd7070Spatrick   SourceRange getSourceRange() const override LLVM_READONLY {
1101e5dd7070Spatrick     return SourceRange(getAtStartLoc(), getAtEndRange().getEnd());
1102e5dd7070Spatrick   }
1103e5dd7070Spatrick 
1104e5dd7070Spatrick   // Implement isa/cast/dyncast/etc.
classof(const Decl * D)1105e5dd7070Spatrick   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
1106e5dd7070Spatrick 
classofKind(Kind K)1107e5dd7070Spatrick   static bool classofKind(Kind K) {
1108e5dd7070Spatrick     return K >= firstObjCContainer &&
1109e5dd7070Spatrick            K <= lastObjCContainer;
1110e5dd7070Spatrick   }
1111e5dd7070Spatrick 
castToDeclContext(const ObjCContainerDecl * D)1112e5dd7070Spatrick   static DeclContext *castToDeclContext(const ObjCContainerDecl *D) {
1113e5dd7070Spatrick     return static_cast<DeclContext *>(const_cast<ObjCContainerDecl*>(D));
1114e5dd7070Spatrick   }
1115e5dd7070Spatrick 
castFromDeclContext(const DeclContext * DC)1116e5dd7070Spatrick   static ObjCContainerDecl *castFromDeclContext(const DeclContext *DC) {
1117e5dd7070Spatrick     return static_cast<ObjCContainerDecl *>(const_cast<DeclContext*>(DC));
1118e5dd7070Spatrick   }
1119e5dd7070Spatrick };
1120e5dd7070Spatrick 
1121e5dd7070Spatrick /// Represents an ObjC class declaration.
1122e5dd7070Spatrick ///
1123e5dd7070Spatrick /// For example:
1124e5dd7070Spatrick ///
1125e5dd7070Spatrick /// \code
1126e5dd7070Spatrick ///   // MostPrimitive declares no super class (not particularly useful).
1127e5dd7070Spatrick ///   \@interface MostPrimitive
1128e5dd7070Spatrick ///     // no instance variables or methods.
1129e5dd7070Spatrick ///   \@end
1130e5dd7070Spatrick ///
1131e5dd7070Spatrick ///   // NSResponder inherits from NSObject & implements NSCoding (a protocol).
1132e5dd7070Spatrick ///   \@interface NSResponder : NSObject \<NSCoding>
1133e5dd7070Spatrick ///   { // instance variables are represented by ObjCIvarDecl.
1134e5dd7070Spatrick ///     id nextResponder; // nextResponder instance variable.
1135e5dd7070Spatrick ///   }
1136e5dd7070Spatrick ///   - (NSResponder *)nextResponder; // return a pointer to NSResponder.
1137e5dd7070Spatrick ///   - (void)mouseMoved:(NSEvent *)theEvent; // return void, takes a pointer
1138e5dd7070Spatrick ///   \@end                                    // to an NSEvent.
1139e5dd7070Spatrick /// \endcode
1140e5dd7070Spatrick ///
1141e5dd7070Spatrick ///   Unlike C/C++, forward class declarations are accomplished with \@class.
1142e5dd7070Spatrick ///   Unlike C/C++, \@class allows for a list of classes to be forward declared.
1143e5dd7070Spatrick ///   Unlike C++, ObjC is a single-rooted class model. In Cocoa, classes
1144e5dd7070Spatrick ///   typically inherit from NSObject (an exception is NSProxy).
1145e5dd7070Spatrick ///
1146e5dd7070Spatrick class ObjCInterfaceDecl : public ObjCContainerDecl
1147e5dd7070Spatrick                         , public Redeclarable<ObjCInterfaceDecl> {
1148e5dd7070Spatrick   friend class ASTContext;
1149*12c85518Srobert   friend class ODRDiagsEmitter;
1150e5dd7070Spatrick 
1151e5dd7070Spatrick   /// TypeForDecl - This indicates the Type object that represents this
1152e5dd7070Spatrick   /// TypeDecl.  It is a cache maintained by ASTContext::getObjCInterfaceType
1153e5dd7070Spatrick   mutable const Type *TypeForDecl = nullptr;
1154e5dd7070Spatrick 
1155e5dd7070Spatrick   struct DefinitionData {
1156e5dd7070Spatrick     /// The definition of this class, for quick access from any
1157e5dd7070Spatrick     /// declaration.
1158e5dd7070Spatrick     ObjCInterfaceDecl *Definition = nullptr;
1159e5dd7070Spatrick 
1160e5dd7070Spatrick     /// When non-null, this is always an ObjCObjectType.
1161e5dd7070Spatrick     TypeSourceInfo *SuperClassTInfo = nullptr;
1162e5dd7070Spatrick 
1163e5dd7070Spatrick     /// Protocols referenced in the \@interface  declaration
1164e5dd7070Spatrick     ObjCProtocolList ReferencedProtocols;
1165e5dd7070Spatrick 
1166e5dd7070Spatrick     /// Protocols reference in both the \@interface and class extensions.
1167e5dd7070Spatrick     ObjCList<ObjCProtocolDecl> AllReferencedProtocols;
1168e5dd7070Spatrick 
1169e5dd7070Spatrick     /// List of categories and class extensions defined for this class.
1170e5dd7070Spatrick     ///
1171e5dd7070Spatrick     /// Categories are stored as a linked list in the AST, since the categories
1172e5dd7070Spatrick     /// and class extensions come long after the initial interface declaration,
1173e5dd7070Spatrick     /// and we avoid dynamically-resized arrays in the AST wherever possible.
1174e5dd7070Spatrick     ObjCCategoryDecl *CategoryList = nullptr;
1175e5dd7070Spatrick 
1176e5dd7070Spatrick     /// IvarList - List of all ivars defined by this class; including class
1177e5dd7070Spatrick     /// extensions and implementation. This list is built lazily.
1178e5dd7070Spatrick     ObjCIvarDecl *IvarList = nullptr;
1179e5dd7070Spatrick 
1180e5dd7070Spatrick     /// Indicates that the contents of this Objective-C class will be
1181e5dd7070Spatrick     /// completed by the external AST source when required.
1182e5dd7070Spatrick     mutable unsigned ExternallyCompleted : 1;
1183e5dd7070Spatrick 
1184e5dd7070Spatrick     /// Indicates that the ivar cache does not yet include ivars
1185e5dd7070Spatrick     /// declared in the implementation.
1186e5dd7070Spatrick     mutable unsigned IvarListMissingImplementation : 1;
1187e5dd7070Spatrick 
1188e5dd7070Spatrick     /// Indicates that this interface decl contains at least one initializer
1189e5dd7070Spatrick     /// marked with the 'objc_designated_initializer' attribute.
1190e5dd7070Spatrick     unsigned HasDesignatedInitializers : 1;
1191e5dd7070Spatrick 
1192e5dd7070Spatrick     enum InheritedDesignatedInitializersState {
1193e5dd7070Spatrick       /// We didn't calculate whether the designated initializers should be
1194e5dd7070Spatrick       /// inherited or not.
1195e5dd7070Spatrick       IDI_Unknown = 0,
1196e5dd7070Spatrick 
1197e5dd7070Spatrick       /// Designated initializers are inherited for the super class.
1198e5dd7070Spatrick       IDI_Inherited = 1,
1199e5dd7070Spatrick 
1200e5dd7070Spatrick       /// The class does not inherit designated initializers.
1201e5dd7070Spatrick       IDI_NotInherited = 2
1202e5dd7070Spatrick     };
1203e5dd7070Spatrick 
1204e5dd7070Spatrick     /// One of the \c InheritedDesignatedInitializersState enumeratos.
1205e5dd7070Spatrick     mutable unsigned InheritedDesignatedInitializers : 2;
1206e5dd7070Spatrick 
1207*12c85518Srobert     /// Tracks whether a ODR hash has been computed for this interface.
1208*12c85518Srobert     unsigned HasODRHash : 1;
1209*12c85518Srobert 
1210*12c85518Srobert     /// A hash of parts of the class to help in ODR checking.
1211*12c85518Srobert     unsigned ODRHash = 0;
1212*12c85518Srobert 
1213e5dd7070Spatrick     /// The location of the last location in this declaration, before
1214e5dd7070Spatrick     /// the properties/methods. For example, this will be the '>', '}', or
1215e5dd7070Spatrick     /// identifier,
1216e5dd7070Spatrick     SourceLocation EndLoc;
1217e5dd7070Spatrick 
DefinitionDataDefinitionData1218e5dd7070Spatrick     DefinitionData()
1219e5dd7070Spatrick         : ExternallyCompleted(false), IvarListMissingImplementation(true),
1220e5dd7070Spatrick           HasDesignatedInitializers(false),
1221*12c85518Srobert           InheritedDesignatedInitializers(IDI_Unknown), HasODRHash(false) {}
1222e5dd7070Spatrick   };
1223e5dd7070Spatrick 
1224e5dd7070Spatrick   /// The type parameters associated with this class, if any.
1225e5dd7070Spatrick   ObjCTypeParamList *TypeParamList = nullptr;
1226e5dd7070Spatrick 
1227e5dd7070Spatrick   /// Contains a pointer to the data associated with this class,
1228e5dd7070Spatrick   /// which will be NULL if this class has not yet been defined.
1229e5dd7070Spatrick   ///
1230e5dd7070Spatrick   /// The bit indicates when we don't need to check for out-of-date
1231e5dd7070Spatrick   /// declarations. It will be set unless modules are enabled.
1232e5dd7070Spatrick   llvm::PointerIntPair<DefinitionData *, 1, bool> Data;
1233e5dd7070Spatrick 
1234e5dd7070Spatrick   ObjCInterfaceDecl(const ASTContext &C, DeclContext *DC, SourceLocation AtLoc,
1235e5dd7070Spatrick                     IdentifierInfo *Id, ObjCTypeParamList *typeParamList,
1236e5dd7070Spatrick                     SourceLocation CLoc, ObjCInterfaceDecl *PrevDecl,
1237e5dd7070Spatrick                     bool IsInternal);
1238e5dd7070Spatrick 
1239e5dd7070Spatrick   void anchor() override;
1240e5dd7070Spatrick 
1241e5dd7070Spatrick   void LoadExternalDefinition() const;
1242e5dd7070Spatrick 
data()1243e5dd7070Spatrick   DefinitionData &data() const {
1244e5dd7070Spatrick     assert(Data.getPointer() && "Declaration has no definition!");
1245e5dd7070Spatrick     return *Data.getPointer();
1246e5dd7070Spatrick   }
1247e5dd7070Spatrick 
1248e5dd7070Spatrick   /// Allocate the definition data for this class.
1249e5dd7070Spatrick   void allocateDefinitionData();
1250e5dd7070Spatrick 
1251e5dd7070Spatrick   using redeclarable_base = Redeclarable<ObjCInterfaceDecl>;
1252e5dd7070Spatrick 
getNextRedeclarationImpl()1253e5dd7070Spatrick   ObjCInterfaceDecl *getNextRedeclarationImpl() override {
1254e5dd7070Spatrick     return getNextRedeclaration();
1255e5dd7070Spatrick   }
1256e5dd7070Spatrick 
getPreviousDeclImpl()1257e5dd7070Spatrick   ObjCInterfaceDecl *getPreviousDeclImpl() override {
1258e5dd7070Spatrick     return getPreviousDecl();
1259e5dd7070Spatrick   }
1260e5dd7070Spatrick 
getMostRecentDeclImpl()1261e5dd7070Spatrick   ObjCInterfaceDecl *getMostRecentDeclImpl() override {
1262e5dd7070Spatrick     return getMostRecentDecl();
1263e5dd7070Spatrick   }
1264e5dd7070Spatrick 
1265e5dd7070Spatrick public:
1266e5dd7070Spatrick   static ObjCInterfaceDecl *Create(const ASTContext &C, DeclContext *DC,
1267e5dd7070Spatrick                                    SourceLocation atLoc,
1268e5dd7070Spatrick                                    IdentifierInfo *Id,
1269e5dd7070Spatrick                                    ObjCTypeParamList *typeParamList,
1270e5dd7070Spatrick                                    ObjCInterfaceDecl *PrevDecl,
1271e5dd7070Spatrick                                    SourceLocation ClassLoc = SourceLocation(),
1272e5dd7070Spatrick                                    bool isInternal = false);
1273e5dd7070Spatrick 
1274e5dd7070Spatrick   static ObjCInterfaceDecl *CreateDeserialized(const ASTContext &C, unsigned ID);
1275e5dd7070Spatrick 
1276e5dd7070Spatrick   /// Retrieve the type parameters of this class.
1277e5dd7070Spatrick   ///
1278e5dd7070Spatrick   /// This function looks for a type parameter list for the given
1279e5dd7070Spatrick   /// class; if the class has been declared (with \c \@class) but not
1280e5dd7070Spatrick   /// defined (with \c \@interface), it will search for a declaration that
1281e5dd7070Spatrick   /// has type parameters, skipping any declarations that do not.
1282e5dd7070Spatrick   ObjCTypeParamList *getTypeParamList() const;
1283e5dd7070Spatrick 
1284e5dd7070Spatrick   /// Set the type parameters of this class.
1285e5dd7070Spatrick   ///
1286e5dd7070Spatrick   /// This function is used by the AST importer, which must import the type
1287e5dd7070Spatrick   /// parameters after creating their DeclContext to avoid loops.
1288e5dd7070Spatrick   void setTypeParamList(ObjCTypeParamList *TPL);
1289e5dd7070Spatrick 
1290e5dd7070Spatrick   /// Retrieve the type parameters written on this particular declaration of
1291e5dd7070Spatrick   /// the class.
getTypeParamListAsWritten()1292e5dd7070Spatrick   ObjCTypeParamList *getTypeParamListAsWritten() const {
1293e5dd7070Spatrick     return TypeParamList;
1294e5dd7070Spatrick   }
1295e5dd7070Spatrick 
getSourceRange()1296e5dd7070Spatrick   SourceRange getSourceRange() const override LLVM_READONLY {
1297e5dd7070Spatrick     if (isThisDeclarationADefinition())
1298e5dd7070Spatrick       return ObjCContainerDecl::getSourceRange();
1299e5dd7070Spatrick 
1300e5dd7070Spatrick     return SourceRange(getAtStartLoc(), getLocation());
1301e5dd7070Spatrick   }
1302e5dd7070Spatrick 
1303e5dd7070Spatrick   /// Indicate that this Objective-C class is complete, but that
1304e5dd7070Spatrick   /// the external AST source will be responsible for filling in its contents
1305e5dd7070Spatrick   /// when a complete class is required.
1306e5dd7070Spatrick   void setExternallyCompleted();
1307e5dd7070Spatrick 
1308e5dd7070Spatrick   /// Indicate that this interface decl contains at least one initializer
1309e5dd7070Spatrick   /// marked with the 'objc_designated_initializer' attribute.
1310e5dd7070Spatrick   void setHasDesignatedInitializers();
1311e5dd7070Spatrick 
1312e5dd7070Spatrick   /// Returns true if this interface decl contains at least one initializer
1313e5dd7070Spatrick   /// marked with the 'objc_designated_initializer' attribute.
1314e5dd7070Spatrick   bool hasDesignatedInitializers() const;
1315e5dd7070Spatrick 
1316e5dd7070Spatrick   /// Returns true if this interface decl declares a designated initializer
1317e5dd7070Spatrick   /// or it inherites one from its super class.
declaresOrInheritsDesignatedInitializers()1318e5dd7070Spatrick   bool declaresOrInheritsDesignatedInitializers() const {
1319e5dd7070Spatrick     return hasDesignatedInitializers() || inheritsDesignatedInitializers();
1320e5dd7070Spatrick   }
1321e5dd7070Spatrick 
getReferencedProtocols()1322e5dd7070Spatrick   const ObjCProtocolList &getReferencedProtocols() const {
1323e5dd7070Spatrick     assert(hasDefinition() && "Caller did not check for forward reference!");
1324e5dd7070Spatrick     if (data().ExternallyCompleted)
1325e5dd7070Spatrick       LoadExternalDefinition();
1326e5dd7070Spatrick 
1327e5dd7070Spatrick     return data().ReferencedProtocols;
1328e5dd7070Spatrick   }
1329e5dd7070Spatrick 
1330e5dd7070Spatrick   ObjCImplementationDecl *getImplementation() const;
1331e5dd7070Spatrick   void setImplementation(ObjCImplementationDecl *ImplD);
1332e5dd7070Spatrick 
1333e5dd7070Spatrick   ObjCCategoryDecl *FindCategoryDeclaration(IdentifierInfo *CategoryId) const;
1334e5dd7070Spatrick 
1335e5dd7070Spatrick   // Get the local instance/class method declared in a category.
1336e5dd7070Spatrick   ObjCMethodDecl *getCategoryInstanceMethod(Selector Sel) const;
1337e5dd7070Spatrick   ObjCMethodDecl *getCategoryClassMethod(Selector Sel) const;
1338e5dd7070Spatrick 
getCategoryMethod(Selector Sel,bool isInstance)1339e5dd7070Spatrick   ObjCMethodDecl *getCategoryMethod(Selector Sel, bool isInstance) const {
1340e5dd7070Spatrick     return isInstance ? getCategoryInstanceMethod(Sel)
1341e5dd7070Spatrick                       : getCategoryClassMethod(Sel);
1342e5dd7070Spatrick   }
1343e5dd7070Spatrick 
1344e5dd7070Spatrick   using protocol_iterator = ObjCProtocolList::iterator;
1345e5dd7070Spatrick   using protocol_range = llvm::iterator_range<protocol_iterator>;
1346e5dd7070Spatrick 
protocols()1347e5dd7070Spatrick   protocol_range protocols() const {
1348e5dd7070Spatrick     return protocol_range(protocol_begin(), protocol_end());
1349e5dd7070Spatrick   }
1350e5dd7070Spatrick 
protocol_begin()1351e5dd7070Spatrick   protocol_iterator protocol_begin() const {
1352e5dd7070Spatrick     // FIXME: Should make sure no callers ever do this.
1353e5dd7070Spatrick     if (!hasDefinition())
1354e5dd7070Spatrick       return protocol_iterator();
1355e5dd7070Spatrick 
1356e5dd7070Spatrick     if (data().ExternallyCompleted)
1357e5dd7070Spatrick       LoadExternalDefinition();
1358e5dd7070Spatrick 
1359e5dd7070Spatrick     return data().ReferencedProtocols.begin();
1360e5dd7070Spatrick   }
1361e5dd7070Spatrick 
protocol_end()1362e5dd7070Spatrick   protocol_iterator protocol_end() const {
1363e5dd7070Spatrick     // FIXME: Should make sure no callers ever do this.
1364e5dd7070Spatrick     if (!hasDefinition())
1365e5dd7070Spatrick       return protocol_iterator();
1366e5dd7070Spatrick 
1367e5dd7070Spatrick     if (data().ExternallyCompleted)
1368e5dd7070Spatrick       LoadExternalDefinition();
1369e5dd7070Spatrick 
1370e5dd7070Spatrick     return data().ReferencedProtocols.end();
1371e5dd7070Spatrick   }
1372e5dd7070Spatrick 
1373e5dd7070Spatrick   using protocol_loc_iterator = ObjCProtocolList::loc_iterator;
1374e5dd7070Spatrick   using protocol_loc_range = llvm::iterator_range<protocol_loc_iterator>;
1375e5dd7070Spatrick 
protocol_locs()1376e5dd7070Spatrick   protocol_loc_range protocol_locs() const {
1377e5dd7070Spatrick     return protocol_loc_range(protocol_loc_begin(), protocol_loc_end());
1378e5dd7070Spatrick   }
1379e5dd7070Spatrick 
protocol_loc_begin()1380e5dd7070Spatrick   protocol_loc_iterator protocol_loc_begin() const {
1381e5dd7070Spatrick     // FIXME: Should make sure no callers ever do this.
1382e5dd7070Spatrick     if (!hasDefinition())
1383e5dd7070Spatrick       return protocol_loc_iterator();
1384e5dd7070Spatrick 
1385e5dd7070Spatrick     if (data().ExternallyCompleted)
1386e5dd7070Spatrick       LoadExternalDefinition();
1387e5dd7070Spatrick 
1388e5dd7070Spatrick     return data().ReferencedProtocols.loc_begin();
1389e5dd7070Spatrick   }
1390e5dd7070Spatrick 
protocol_loc_end()1391e5dd7070Spatrick   protocol_loc_iterator protocol_loc_end() const {
1392e5dd7070Spatrick     // FIXME: Should make sure no callers ever do this.
1393e5dd7070Spatrick     if (!hasDefinition())
1394e5dd7070Spatrick       return protocol_loc_iterator();
1395e5dd7070Spatrick 
1396e5dd7070Spatrick     if (data().ExternallyCompleted)
1397e5dd7070Spatrick       LoadExternalDefinition();
1398e5dd7070Spatrick 
1399e5dd7070Spatrick     return data().ReferencedProtocols.loc_end();
1400e5dd7070Spatrick   }
1401e5dd7070Spatrick 
1402e5dd7070Spatrick   using all_protocol_iterator = ObjCList<ObjCProtocolDecl>::iterator;
1403e5dd7070Spatrick   using all_protocol_range = llvm::iterator_range<all_protocol_iterator>;
1404e5dd7070Spatrick 
all_referenced_protocols()1405e5dd7070Spatrick   all_protocol_range all_referenced_protocols() const {
1406e5dd7070Spatrick     return all_protocol_range(all_referenced_protocol_begin(),
1407e5dd7070Spatrick                               all_referenced_protocol_end());
1408e5dd7070Spatrick   }
1409e5dd7070Spatrick 
all_referenced_protocol_begin()1410e5dd7070Spatrick   all_protocol_iterator all_referenced_protocol_begin() const {
1411e5dd7070Spatrick     // FIXME: Should make sure no callers ever do this.
1412e5dd7070Spatrick     if (!hasDefinition())
1413e5dd7070Spatrick       return all_protocol_iterator();
1414e5dd7070Spatrick 
1415e5dd7070Spatrick     if (data().ExternallyCompleted)
1416e5dd7070Spatrick       LoadExternalDefinition();
1417e5dd7070Spatrick 
1418e5dd7070Spatrick     return data().AllReferencedProtocols.empty()
1419e5dd7070Spatrick              ? protocol_begin()
1420e5dd7070Spatrick              : data().AllReferencedProtocols.begin();
1421e5dd7070Spatrick   }
1422e5dd7070Spatrick 
all_referenced_protocol_end()1423e5dd7070Spatrick   all_protocol_iterator all_referenced_protocol_end() const {
1424e5dd7070Spatrick     // FIXME: Should make sure no callers ever do this.
1425e5dd7070Spatrick     if (!hasDefinition())
1426e5dd7070Spatrick       return all_protocol_iterator();
1427e5dd7070Spatrick 
1428e5dd7070Spatrick     if (data().ExternallyCompleted)
1429e5dd7070Spatrick       LoadExternalDefinition();
1430e5dd7070Spatrick 
1431e5dd7070Spatrick     return data().AllReferencedProtocols.empty()
1432e5dd7070Spatrick              ? protocol_end()
1433e5dd7070Spatrick              : data().AllReferencedProtocols.end();
1434e5dd7070Spatrick   }
1435e5dd7070Spatrick 
1436e5dd7070Spatrick   using ivar_iterator = specific_decl_iterator<ObjCIvarDecl>;
1437e5dd7070Spatrick   using ivar_range = llvm::iterator_range<specific_decl_iterator<ObjCIvarDecl>>;
1438e5dd7070Spatrick 
ivars()1439e5dd7070Spatrick   ivar_range ivars() const { return ivar_range(ivar_begin(), ivar_end()); }
1440e5dd7070Spatrick 
ivar_begin()1441e5dd7070Spatrick   ivar_iterator ivar_begin() const {
1442e5dd7070Spatrick     if (const ObjCInterfaceDecl *Def = getDefinition())
1443e5dd7070Spatrick       return ivar_iterator(Def->decls_begin());
1444e5dd7070Spatrick 
1445e5dd7070Spatrick     // FIXME: Should make sure no callers ever do this.
1446e5dd7070Spatrick     return ivar_iterator();
1447e5dd7070Spatrick   }
1448e5dd7070Spatrick 
ivar_end()1449e5dd7070Spatrick   ivar_iterator ivar_end() const {
1450e5dd7070Spatrick     if (const ObjCInterfaceDecl *Def = getDefinition())
1451e5dd7070Spatrick       return ivar_iterator(Def->decls_end());
1452e5dd7070Spatrick 
1453e5dd7070Spatrick     // FIXME: Should make sure no callers ever do this.
1454e5dd7070Spatrick     return ivar_iterator();
1455e5dd7070Spatrick   }
1456e5dd7070Spatrick 
ivar_size()1457e5dd7070Spatrick   unsigned ivar_size() const {
1458e5dd7070Spatrick     return std::distance(ivar_begin(), ivar_end());
1459e5dd7070Spatrick   }
1460e5dd7070Spatrick 
ivar_empty()1461e5dd7070Spatrick   bool ivar_empty() const { return ivar_begin() == ivar_end(); }
1462e5dd7070Spatrick 
1463e5dd7070Spatrick   ObjCIvarDecl *all_declared_ivar_begin();
all_declared_ivar_begin()1464e5dd7070Spatrick   const ObjCIvarDecl *all_declared_ivar_begin() const {
1465e5dd7070Spatrick     // Even though this modifies IvarList, it's conceptually const:
1466e5dd7070Spatrick     // the ivar chain is essentially a cached property of ObjCInterfaceDecl.
1467e5dd7070Spatrick     return const_cast<ObjCInterfaceDecl *>(this)->all_declared_ivar_begin();
1468e5dd7070Spatrick   }
setIvarList(ObjCIvarDecl * ivar)1469e5dd7070Spatrick   void setIvarList(ObjCIvarDecl *ivar) { data().IvarList = ivar; }
1470e5dd7070Spatrick 
1471e5dd7070Spatrick   /// setProtocolList - Set the list of protocols that this interface
1472e5dd7070Spatrick   /// implements.
setProtocolList(ObjCProtocolDecl * const * List,unsigned Num,const SourceLocation * Locs,ASTContext & C)1473e5dd7070Spatrick   void setProtocolList(ObjCProtocolDecl *const* List, unsigned Num,
1474e5dd7070Spatrick                        const SourceLocation *Locs, ASTContext &C) {
1475e5dd7070Spatrick     data().ReferencedProtocols.set(List, Num, Locs, C);
1476e5dd7070Spatrick   }
1477e5dd7070Spatrick 
1478e5dd7070Spatrick   /// mergeClassExtensionProtocolList - Merge class extension's protocol list
1479e5dd7070Spatrick   /// into the protocol list for this class.
1480e5dd7070Spatrick   void mergeClassExtensionProtocolList(ObjCProtocolDecl *const* List,
1481e5dd7070Spatrick                                        unsigned Num,
1482e5dd7070Spatrick                                        ASTContext &C);
1483e5dd7070Spatrick 
1484e5dd7070Spatrick   /// Produce a name to be used for class's metadata. It comes either via
1485e5dd7070Spatrick   /// objc_runtime_name attribute or class name.
1486e5dd7070Spatrick   StringRef getObjCRuntimeNameAsString() const;
1487e5dd7070Spatrick 
1488e5dd7070Spatrick   /// Returns the designated initializers for the interface.
1489e5dd7070Spatrick   ///
1490e5dd7070Spatrick   /// If this declaration does not have methods marked as designated
1491e5dd7070Spatrick   /// initializers then the interface inherits the designated initializers of
1492e5dd7070Spatrick   /// its super class.
1493e5dd7070Spatrick   void getDesignatedInitializers(
1494e5dd7070Spatrick                   llvm::SmallVectorImpl<const ObjCMethodDecl *> &Methods) const;
1495e5dd7070Spatrick 
1496e5dd7070Spatrick   /// Returns true if the given selector is a designated initializer for the
1497e5dd7070Spatrick   /// interface.
1498e5dd7070Spatrick   ///
1499e5dd7070Spatrick   /// If this declaration does not have methods marked as designated
1500e5dd7070Spatrick   /// initializers then the interface inherits the designated initializers of
1501e5dd7070Spatrick   /// its super class.
1502e5dd7070Spatrick   ///
1503e5dd7070Spatrick   /// \param InitMethod if non-null and the function returns true, it receives
1504e5dd7070Spatrick   /// the method that was marked as a designated initializer.
1505e5dd7070Spatrick   bool
1506e5dd7070Spatrick   isDesignatedInitializer(Selector Sel,
1507e5dd7070Spatrick                           const ObjCMethodDecl **InitMethod = nullptr) const;
1508e5dd7070Spatrick 
1509e5dd7070Spatrick   /// Determine whether this particular declaration of this class is
1510e5dd7070Spatrick   /// actually also a definition.
isThisDeclarationADefinition()1511e5dd7070Spatrick   bool isThisDeclarationADefinition() const {
1512e5dd7070Spatrick     return getDefinition() == this;
1513e5dd7070Spatrick   }
1514e5dd7070Spatrick 
1515e5dd7070Spatrick   /// Determine whether this class has been defined.
hasDefinition()1516e5dd7070Spatrick   bool hasDefinition() const {
1517e5dd7070Spatrick     // If the name of this class is out-of-date, bring it up-to-date, which
1518e5dd7070Spatrick     // might bring in a definition.
1519e5dd7070Spatrick     // Note: a null value indicates that we don't have a definition and that
1520e5dd7070Spatrick     // modules are enabled.
1521e5dd7070Spatrick     if (!Data.getOpaqueValue())
1522e5dd7070Spatrick       getMostRecentDecl();
1523e5dd7070Spatrick 
1524e5dd7070Spatrick     return Data.getPointer();
1525e5dd7070Spatrick   }
1526e5dd7070Spatrick 
1527e5dd7070Spatrick   /// Retrieve the definition of this class, or NULL if this class
1528e5dd7070Spatrick   /// has been forward-declared (with \@class) but not yet defined (with
1529e5dd7070Spatrick   /// \@interface).
getDefinition()1530e5dd7070Spatrick   ObjCInterfaceDecl *getDefinition() {
1531e5dd7070Spatrick     return hasDefinition()? Data.getPointer()->Definition : nullptr;
1532e5dd7070Spatrick   }
1533e5dd7070Spatrick 
1534e5dd7070Spatrick   /// Retrieve the definition of this class, or NULL if this class
1535e5dd7070Spatrick   /// has been forward-declared (with \@class) but not yet defined (with
1536e5dd7070Spatrick   /// \@interface).
getDefinition()1537e5dd7070Spatrick   const ObjCInterfaceDecl *getDefinition() const {
1538e5dd7070Spatrick     return hasDefinition()? Data.getPointer()->Definition : nullptr;
1539e5dd7070Spatrick   }
1540e5dd7070Spatrick 
1541e5dd7070Spatrick   /// Starts the definition of this Objective-C class, taking it from
1542e5dd7070Spatrick   /// a forward declaration (\@class) to a definition (\@interface).
1543e5dd7070Spatrick   void startDefinition();
1544e5dd7070Spatrick 
1545*12c85518Srobert   /// Starts the definition without sharing it with other redeclarations.
1546*12c85518Srobert   /// Such definition shouldn't be used for anything but only to compare if
1547*12c85518Srobert   /// a duplicate is compatible with previous definition or if it is
1548*12c85518Srobert   /// a distinct duplicate.
1549*12c85518Srobert   void startDuplicateDefinitionForComparison();
1550*12c85518Srobert   void mergeDuplicateDefinitionWithCommon(const ObjCInterfaceDecl *Definition);
1551*12c85518Srobert 
1552e5dd7070Spatrick   /// Retrieve the superclass type.
getSuperClassType()1553e5dd7070Spatrick   const ObjCObjectType *getSuperClassType() const {
1554e5dd7070Spatrick     if (TypeSourceInfo *TInfo = getSuperClassTInfo())
1555e5dd7070Spatrick       return TInfo->getType()->castAs<ObjCObjectType>();
1556e5dd7070Spatrick 
1557e5dd7070Spatrick     return nullptr;
1558e5dd7070Spatrick   }
1559e5dd7070Spatrick 
1560e5dd7070Spatrick   // Retrieve the type source information for the superclass.
getSuperClassTInfo()1561e5dd7070Spatrick   TypeSourceInfo *getSuperClassTInfo() const {
1562e5dd7070Spatrick     // FIXME: Should make sure no callers ever do this.
1563e5dd7070Spatrick     if (!hasDefinition())
1564e5dd7070Spatrick       return nullptr;
1565e5dd7070Spatrick 
1566e5dd7070Spatrick     if (data().ExternallyCompleted)
1567e5dd7070Spatrick       LoadExternalDefinition();
1568e5dd7070Spatrick 
1569e5dd7070Spatrick     return data().SuperClassTInfo;
1570e5dd7070Spatrick   }
1571e5dd7070Spatrick 
1572e5dd7070Spatrick   // Retrieve the declaration for the superclass of this class, which
1573e5dd7070Spatrick   // does not include any type arguments that apply to the superclass.
1574e5dd7070Spatrick   ObjCInterfaceDecl *getSuperClass() const;
1575e5dd7070Spatrick 
setSuperClass(TypeSourceInfo * superClass)1576e5dd7070Spatrick   void setSuperClass(TypeSourceInfo *superClass) {
1577e5dd7070Spatrick     data().SuperClassTInfo = superClass;
1578e5dd7070Spatrick   }
1579e5dd7070Spatrick 
1580e5dd7070Spatrick   /// Iterator that walks over the list of categories, filtering out
1581e5dd7070Spatrick   /// those that do not meet specific criteria.
1582e5dd7070Spatrick   ///
1583e5dd7070Spatrick   /// This class template is used for the various permutations of category
1584e5dd7070Spatrick   /// and extension iterators.
1585e5dd7070Spatrick   template<bool (*Filter)(ObjCCategoryDecl *)>
1586e5dd7070Spatrick   class filtered_category_iterator {
1587e5dd7070Spatrick     ObjCCategoryDecl *Current = nullptr;
1588e5dd7070Spatrick 
1589e5dd7070Spatrick     void findAcceptableCategory();
1590e5dd7070Spatrick 
1591e5dd7070Spatrick   public:
1592e5dd7070Spatrick     using value_type = ObjCCategoryDecl *;
1593e5dd7070Spatrick     using reference = value_type;
1594e5dd7070Spatrick     using pointer = value_type;
1595e5dd7070Spatrick     using difference_type = std::ptrdiff_t;
1596e5dd7070Spatrick     using iterator_category = std::input_iterator_tag;
1597e5dd7070Spatrick 
1598e5dd7070Spatrick     filtered_category_iterator() = default;
filtered_category_iterator(ObjCCategoryDecl * Current)1599e5dd7070Spatrick     explicit filtered_category_iterator(ObjCCategoryDecl *Current)
1600e5dd7070Spatrick         : Current(Current) {
1601e5dd7070Spatrick       findAcceptableCategory();
1602e5dd7070Spatrick     }
1603e5dd7070Spatrick 
1604e5dd7070Spatrick     reference operator*() const { return Current; }
1605e5dd7070Spatrick     pointer operator->() const { return Current; }
1606e5dd7070Spatrick 
1607e5dd7070Spatrick     filtered_category_iterator &operator++();
1608e5dd7070Spatrick 
1609e5dd7070Spatrick     filtered_category_iterator operator++(int) {
1610e5dd7070Spatrick       filtered_category_iterator Tmp = *this;
1611e5dd7070Spatrick       ++(*this);
1612e5dd7070Spatrick       return Tmp;
1613e5dd7070Spatrick     }
1614e5dd7070Spatrick 
1615e5dd7070Spatrick     friend bool operator==(filtered_category_iterator X,
1616e5dd7070Spatrick                            filtered_category_iterator Y) {
1617e5dd7070Spatrick       return X.Current == Y.Current;
1618e5dd7070Spatrick     }
1619e5dd7070Spatrick 
1620e5dd7070Spatrick     friend bool operator!=(filtered_category_iterator X,
1621e5dd7070Spatrick                            filtered_category_iterator Y) {
1622e5dd7070Spatrick       return X.Current != Y.Current;
1623e5dd7070Spatrick     }
1624e5dd7070Spatrick   };
1625e5dd7070Spatrick 
1626e5dd7070Spatrick private:
1627e5dd7070Spatrick   /// Test whether the given category is visible.
1628e5dd7070Spatrick   ///
1629e5dd7070Spatrick   /// Used in the \c visible_categories_iterator.
1630e5dd7070Spatrick   static bool isVisibleCategory(ObjCCategoryDecl *Cat);
1631e5dd7070Spatrick 
1632e5dd7070Spatrick public:
1633e5dd7070Spatrick   /// Iterator that walks over the list of categories and extensions
1634e5dd7070Spatrick   /// that are visible, i.e., not hidden in a non-imported submodule.
1635e5dd7070Spatrick   using visible_categories_iterator =
1636e5dd7070Spatrick       filtered_category_iterator<isVisibleCategory>;
1637e5dd7070Spatrick 
1638e5dd7070Spatrick   using visible_categories_range =
1639e5dd7070Spatrick       llvm::iterator_range<visible_categories_iterator>;
1640e5dd7070Spatrick 
visible_categories()1641e5dd7070Spatrick   visible_categories_range visible_categories() const {
1642e5dd7070Spatrick     return visible_categories_range(visible_categories_begin(),
1643e5dd7070Spatrick                                     visible_categories_end());
1644e5dd7070Spatrick   }
1645e5dd7070Spatrick 
1646e5dd7070Spatrick   /// Retrieve an iterator to the beginning of the visible-categories
1647e5dd7070Spatrick   /// list.
visible_categories_begin()1648e5dd7070Spatrick   visible_categories_iterator visible_categories_begin() const {
1649e5dd7070Spatrick     return visible_categories_iterator(getCategoryListRaw());
1650e5dd7070Spatrick   }
1651e5dd7070Spatrick 
1652e5dd7070Spatrick   /// Retrieve an iterator to the end of the visible-categories list.
visible_categories_end()1653e5dd7070Spatrick   visible_categories_iterator visible_categories_end() const {
1654e5dd7070Spatrick     return visible_categories_iterator();
1655e5dd7070Spatrick   }
1656e5dd7070Spatrick 
1657e5dd7070Spatrick   /// Determine whether the visible-categories list is empty.
visible_categories_empty()1658e5dd7070Spatrick   bool visible_categories_empty() const {
1659e5dd7070Spatrick     return visible_categories_begin() == visible_categories_end();
1660e5dd7070Spatrick   }
1661e5dd7070Spatrick 
1662e5dd7070Spatrick private:
1663e5dd7070Spatrick   /// Test whether the given category... is a category.
1664e5dd7070Spatrick   ///
1665e5dd7070Spatrick   /// Used in the \c known_categories_iterator.
isKnownCategory(ObjCCategoryDecl *)1666e5dd7070Spatrick   static bool isKnownCategory(ObjCCategoryDecl *) { return true; }
1667e5dd7070Spatrick 
1668e5dd7070Spatrick public:
1669e5dd7070Spatrick   /// Iterator that walks over all of the known categories and
1670e5dd7070Spatrick   /// extensions, including those that are hidden.
1671e5dd7070Spatrick   using known_categories_iterator = filtered_category_iterator<isKnownCategory>;
1672e5dd7070Spatrick   using known_categories_range =
1673e5dd7070Spatrick      llvm::iterator_range<known_categories_iterator>;
1674e5dd7070Spatrick 
known_categories()1675e5dd7070Spatrick   known_categories_range known_categories() const {
1676e5dd7070Spatrick     return known_categories_range(known_categories_begin(),
1677e5dd7070Spatrick                                   known_categories_end());
1678e5dd7070Spatrick   }
1679e5dd7070Spatrick 
1680e5dd7070Spatrick   /// Retrieve an iterator to the beginning of the known-categories
1681e5dd7070Spatrick   /// list.
known_categories_begin()1682e5dd7070Spatrick   known_categories_iterator known_categories_begin() const {
1683e5dd7070Spatrick     return known_categories_iterator(getCategoryListRaw());
1684e5dd7070Spatrick   }
1685e5dd7070Spatrick 
1686e5dd7070Spatrick   /// Retrieve an iterator to the end of the known-categories list.
known_categories_end()1687e5dd7070Spatrick   known_categories_iterator known_categories_end() const {
1688e5dd7070Spatrick     return known_categories_iterator();
1689e5dd7070Spatrick   }
1690e5dd7070Spatrick 
1691e5dd7070Spatrick   /// Determine whether the known-categories list is empty.
known_categories_empty()1692e5dd7070Spatrick   bool known_categories_empty() const {
1693e5dd7070Spatrick     return known_categories_begin() == known_categories_end();
1694e5dd7070Spatrick   }
1695e5dd7070Spatrick 
1696e5dd7070Spatrick private:
1697e5dd7070Spatrick   /// Test whether the given category is a visible extension.
1698e5dd7070Spatrick   ///
1699e5dd7070Spatrick   /// Used in the \c visible_extensions_iterator.
1700e5dd7070Spatrick   static bool isVisibleExtension(ObjCCategoryDecl *Cat);
1701e5dd7070Spatrick 
1702e5dd7070Spatrick public:
1703e5dd7070Spatrick   /// Iterator that walks over all of the visible extensions, skipping
1704e5dd7070Spatrick   /// any that are known but hidden.
1705e5dd7070Spatrick   using visible_extensions_iterator =
1706e5dd7070Spatrick       filtered_category_iterator<isVisibleExtension>;
1707e5dd7070Spatrick 
1708e5dd7070Spatrick   using visible_extensions_range =
1709e5dd7070Spatrick       llvm::iterator_range<visible_extensions_iterator>;
1710e5dd7070Spatrick 
visible_extensions()1711e5dd7070Spatrick   visible_extensions_range visible_extensions() const {
1712e5dd7070Spatrick     return visible_extensions_range(visible_extensions_begin(),
1713e5dd7070Spatrick                                     visible_extensions_end());
1714e5dd7070Spatrick   }
1715e5dd7070Spatrick 
1716e5dd7070Spatrick   /// Retrieve an iterator to the beginning of the visible-extensions
1717e5dd7070Spatrick   /// list.
visible_extensions_begin()1718e5dd7070Spatrick   visible_extensions_iterator visible_extensions_begin() const {
1719e5dd7070Spatrick     return visible_extensions_iterator(getCategoryListRaw());
1720e5dd7070Spatrick   }
1721e5dd7070Spatrick 
1722e5dd7070Spatrick   /// Retrieve an iterator to the end of the visible-extensions list.
visible_extensions_end()1723e5dd7070Spatrick   visible_extensions_iterator visible_extensions_end() const {
1724e5dd7070Spatrick     return visible_extensions_iterator();
1725e5dd7070Spatrick   }
1726e5dd7070Spatrick 
1727e5dd7070Spatrick   /// Determine whether the visible-extensions list is empty.
visible_extensions_empty()1728e5dd7070Spatrick   bool visible_extensions_empty() const {
1729e5dd7070Spatrick     return visible_extensions_begin() == visible_extensions_end();
1730e5dd7070Spatrick   }
1731e5dd7070Spatrick 
1732e5dd7070Spatrick private:
1733e5dd7070Spatrick   /// Test whether the given category is an extension.
1734e5dd7070Spatrick   ///
1735e5dd7070Spatrick   /// Used in the \c known_extensions_iterator.
1736e5dd7070Spatrick   static bool isKnownExtension(ObjCCategoryDecl *Cat);
1737e5dd7070Spatrick 
1738e5dd7070Spatrick public:
1739e5dd7070Spatrick   friend class ASTDeclReader;
1740e5dd7070Spatrick   friend class ASTDeclWriter;
1741e5dd7070Spatrick   friend class ASTReader;
1742e5dd7070Spatrick 
1743e5dd7070Spatrick   /// Iterator that walks over all of the known extensions.
1744e5dd7070Spatrick   using known_extensions_iterator =
1745e5dd7070Spatrick       filtered_category_iterator<isKnownExtension>;
1746e5dd7070Spatrick   using known_extensions_range =
1747e5dd7070Spatrick       llvm::iterator_range<known_extensions_iterator>;
1748e5dd7070Spatrick 
known_extensions()1749e5dd7070Spatrick   known_extensions_range known_extensions() const {
1750e5dd7070Spatrick     return known_extensions_range(known_extensions_begin(),
1751e5dd7070Spatrick                                   known_extensions_end());
1752e5dd7070Spatrick   }
1753e5dd7070Spatrick 
1754e5dd7070Spatrick   /// Retrieve an iterator to the beginning of the known-extensions
1755e5dd7070Spatrick   /// list.
known_extensions_begin()1756e5dd7070Spatrick   known_extensions_iterator known_extensions_begin() const {
1757e5dd7070Spatrick     return known_extensions_iterator(getCategoryListRaw());
1758e5dd7070Spatrick   }
1759e5dd7070Spatrick 
1760e5dd7070Spatrick   /// Retrieve an iterator to the end of the known-extensions list.
known_extensions_end()1761e5dd7070Spatrick   known_extensions_iterator known_extensions_end() const {
1762e5dd7070Spatrick     return known_extensions_iterator();
1763e5dd7070Spatrick   }
1764e5dd7070Spatrick 
1765e5dd7070Spatrick   /// Determine whether the known-extensions list is empty.
known_extensions_empty()1766e5dd7070Spatrick   bool known_extensions_empty() const {
1767e5dd7070Spatrick     return known_extensions_begin() == known_extensions_end();
1768e5dd7070Spatrick   }
1769e5dd7070Spatrick 
1770e5dd7070Spatrick   /// Retrieve the raw pointer to the start of the category/extension
1771e5dd7070Spatrick   /// list.
getCategoryListRaw()1772e5dd7070Spatrick   ObjCCategoryDecl* getCategoryListRaw() const {
1773e5dd7070Spatrick     // FIXME: Should make sure no callers ever do this.
1774e5dd7070Spatrick     if (!hasDefinition())
1775e5dd7070Spatrick       return nullptr;
1776e5dd7070Spatrick 
1777e5dd7070Spatrick     if (data().ExternallyCompleted)
1778e5dd7070Spatrick       LoadExternalDefinition();
1779e5dd7070Spatrick 
1780e5dd7070Spatrick     return data().CategoryList;
1781e5dd7070Spatrick   }
1782e5dd7070Spatrick 
1783e5dd7070Spatrick   /// Set the raw pointer to the start of the category/extension
1784e5dd7070Spatrick   /// list.
setCategoryListRaw(ObjCCategoryDecl * category)1785e5dd7070Spatrick   void setCategoryListRaw(ObjCCategoryDecl *category) {
1786e5dd7070Spatrick     data().CategoryList = category;
1787e5dd7070Spatrick   }
1788e5dd7070Spatrick 
1789e5dd7070Spatrick   ObjCPropertyDecl
1790e5dd7070Spatrick     *FindPropertyVisibleInPrimaryClass(IdentifierInfo *PropertyId,
1791e5dd7070Spatrick                                        ObjCPropertyQueryKind QueryKind) const;
1792e5dd7070Spatrick 
1793*12c85518Srobert   void collectPropertiesToImplement(PropertyMap &PM) const override;
1794e5dd7070Spatrick 
1795e5dd7070Spatrick   /// isSuperClassOf - Return true if this class is the specified class or is a
1796e5dd7070Spatrick   /// super class of the specified interface class.
isSuperClassOf(const ObjCInterfaceDecl * I)1797e5dd7070Spatrick   bool isSuperClassOf(const ObjCInterfaceDecl *I) const {
1798e5dd7070Spatrick     // If RHS is derived from LHS it is OK; else it is not OK.
1799e5dd7070Spatrick     while (I != nullptr) {
1800e5dd7070Spatrick       if (declaresSameEntity(this, I))
1801e5dd7070Spatrick         return true;
1802e5dd7070Spatrick 
1803e5dd7070Spatrick       I = I->getSuperClass();
1804e5dd7070Spatrick     }
1805e5dd7070Spatrick     return false;
1806e5dd7070Spatrick   }
1807e5dd7070Spatrick 
1808e5dd7070Spatrick   /// isArcWeakrefUnavailable - Checks for a class or one of its super classes
1809e5dd7070Spatrick   /// to be incompatible with __weak references. Returns true if it is.
1810e5dd7070Spatrick   bool isArcWeakrefUnavailable() const;
1811e5dd7070Spatrick 
1812e5dd7070Spatrick   /// isObjCRequiresPropertyDefs - Checks that a class or one of its super
1813e5dd7070Spatrick   /// classes must not be auto-synthesized. Returns class decl. if it must not
1814e5dd7070Spatrick   /// be; 0, otherwise.
1815e5dd7070Spatrick   const ObjCInterfaceDecl *isObjCRequiresPropertyDefs() const;
1816e5dd7070Spatrick 
1817e5dd7070Spatrick   ObjCIvarDecl *lookupInstanceVariable(IdentifierInfo *IVarName,
1818e5dd7070Spatrick                                        ObjCInterfaceDecl *&ClassDeclared);
lookupInstanceVariable(IdentifierInfo * IVarName)1819e5dd7070Spatrick   ObjCIvarDecl *lookupInstanceVariable(IdentifierInfo *IVarName) {
1820e5dd7070Spatrick     ObjCInterfaceDecl *ClassDeclared;
1821e5dd7070Spatrick     return lookupInstanceVariable(IVarName, ClassDeclared);
1822e5dd7070Spatrick   }
1823e5dd7070Spatrick 
1824e5dd7070Spatrick   ObjCProtocolDecl *lookupNestedProtocol(IdentifierInfo *Name);
1825e5dd7070Spatrick 
1826e5dd7070Spatrick   // Lookup a method. First, we search locally. If a method isn't
1827e5dd7070Spatrick   // found, we search referenced protocols and class categories.
1828e5dd7070Spatrick   ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance,
1829e5dd7070Spatrick                                bool shallowCategoryLookup = false,
1830e5dd7070Spatrick                                bool followSuper = true,
1831e5dd7070Spatrick                                const ObjCCategoryDecl *C = nullptr) const;
1832e5dd7070Spatrick 
1833e5dd7070Spatrick   /// Lookup an instance method for a given selector.
lookupInstanceMethod(Selector Sel)1834e5dd7070Spatrick   ObjCMethodDecl *lookupInstanceMethod(Selector Sel) const {
1835e5dd7070Spatrick     return lookupMethod(Sel, true/*isInstance*/);
1836e5dd7070Spatrick   }
1837e5dd7070Spatrick 
1838e5dd7070Spatrick   /// Lookup a class method for a given selector.
lookupClassMethod(Selector Sel)1839e5dd7070Spatrick   ObjCMethodDecl *lookupClassMethod(Selector Sel) const {
1840e5dd7070Spatrick     return lookupMethod(Sel, false/*isInstance*/);
1841e5dd7070Spatrick   }
1842e5dd7070Spatrick 
1843e5dd7070Spatrick   ObjCInterfaceDecl *lookupInheritedClass(const IdentifierInfo *ICName);
1844e5dd7070Spatrick 
1845e5dd7070Spatrick   /// Lookup a method in the classes implementation hierarchy.
1846e5dd7070Spatrick   ObjCMethodDecl *lookupPrivateMethod(const Selector &Sel,
1847e5dd7070Spatrick                                       bool Instance=true) const;
1848e5dd7070Spatrick 
lookupPrivateClassMethod(const Selector & Sel)1849e5dd7070Spatrick   ObjCMethodDecl *lookupPrivateClassMethod(const Selector &Sel) {
1850e5dd7070Spatrick     return lookupPrivateMethod(Sel, false);
1851e5dd7070Spatrick   }
1852e5dd7070Spatrick 
1853e5dd7070Spatrick   /// Lookup a setter or getter in the class hierarchy,
1854e5dd7070Spatrick   /// including in all categories except for category passed
1855e5dd7070Spatrick   /// as argument.
lookupPropertyAccessor(const Selector Sel,const ObjCCategoryDecl * Cat,bool IsClassProperty)1856e5dd7070Spatrick   ObjCMethodDecl *lookupPropertyAccessor(const Selector Sel,
1857e5dd7070Spatrick                                          const ObjCCategoryDecl *Cat,
1858e5dd7070Spatrick                                          bool IsClassProperty) const {
1859e5dd7070Spatrick     return lookupMethod(Sel, !IsClassProperty/*isInstance*/,
1860e5dd7070Spatrick                         false/*shallowCategoryLookup*/,
1861e5dd7070Spatrick                         true /* followsSuper */,
1862e5dd7070Spatrick                         Cat);
1863e5dd7070Spatrick   }
1864e5dd7070Spatrick 
getEndOfDefinitionLoc()1865e5dd7070Spatrick   SourceLocation getEndOfDefinitionLoc() const {
1866e5dd7070Spatrick     if (!hasDefinition())
1867e5dd7070Spatrick       return getLocation();
1868e5dd7070Spatrick 
1869e5dd7070Spatrick     return data().EndLoc;
1870e5dd7070Spatrick   }
1871e5dd7070Spatrick 
setEndOfDefinitionLoc(SourceLocation LE)1872e5dd7070Spatrick   void setEndOfDefinitionLoc(SourceLocation LE) { data().EndLoc = LE; }
1873e5dd7070Spatrick 
1874e5dd7070Spatrick   /// Retrieve the starting location of the superclass.
1875e5dd7070Spatrick   SourceLocation getSuperClassLoc() const;
1876e5dd7070Spatrick 
1877e5dd7070Spatrick   /// isImplicitInterfaceDecl - check that this is an implicitly declared
1878e5dd7070Spatrick   /// ObjCInterfaceDecl node. This is for legacy objective-c \@implementation
1879e5dd7070Spatrick   /// declaration without an \@interface declaration.
isImplicitInterfaceDecl()1880e5dd7070Spatrick   bool isImplicitInterfaceDecl() const {
1881e5dd7070Spatrick     return hasDefinition() ? data().Definition->isImplicit() : isImplicit();
1882e5dd7070Spatrick   }
1883e5dd7070Spatrick 
1884e5dd7070Spatrick   /// ClassImplementsProtocol - Checks that 'lProto' protocol
1885e5dd7070Spatrick   /// has been implemented in IDecl class, its super class or categories (if
1886e5dd7070Spatrick   /// lookupCategory is true).
1887e5dd7070Spatrick   bool ClassImplementsProtocol(ObjCProtocolDecl *lProto,
1888e5dd7070Spatrick                                bool lookupCategory,
1889e5dd7070Spatrick                                bool RHSIsQualifiedID = false);
1890e5dd7070Spatrick 
1891e5dd7070Spatrick   using redecl_range = redeclarable_base::redecl_range;
1892e5dd7070Spatrick   using redecl_iterator = redeclarable_base::redecl_iterator;
1893e5dd7070Spatrick 
1894e5dd7070Spatrick   using redeclarable_base::redecls_begin;
1895e5dd7070Spatrick   using redeclarable_base::redecls_end;
1896e5dd7070Spatrick   using redeclarable_base::redecls;
1897e5dd7070Spatrick   using redeclarable_base::getPreviousDecl;
1898e5dd7070Spatrick   using redeclarable_base::getMostRecentDecl;
1899e5dd7070Spatrick   using redeclarable_base::isFirstDecl;
1900e5dd7070Spatrick 
1901e5dd7070Spatrick   /// Retrieves the canonical declaration of this Objective-C class.
getCanonicalDecl()1902e5dd7070Spatrick   ObjCInterfaceDecl *getCanonicalDecl() override { return getFirstDecl(); }
getCanonicalDecl()1903e5dd7070Spatrick   const ObjCInterfaceDecl *getCanonicalDecl() const { return getFirstDecl(); }
1904e5dd7070Spatrick 
1905e5dd7070Spatrick   // Low-level accessor
getTypeForDecl()1906e5dd7070Spatrick   const Type *getTypeForDecl() const { return TypeForDecl; }
setTypeForDecl(const Type * TD)1907e5dd7070Spatrick   void setTypeForDecl(const Type *TD) const { TypeForDecl = TD; }
1908e5dd7070Spatrick 
1909*12c85518Srobert   /// Get precomputed ODRHash or add a new one.
1910*12c85518Srobert   unsigned getODRHash();
1911*12c85518Srobert 
classof(const Decl * D)1912e5dd7070Spatrick   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
classofKind(Kind K)1913e5dd7070Spatrick   static bool classofKind(Kind K) { return K == ObjCInterface; }
1914e5dd7070Spatrick 
1915e5dd7070Spatrick private:
1916*12c85518Srobert   /// True if a valid hash is stored in ODRHash.
1917*12c85518Srobert   bool hasODRHash() const;
1918*12c85518Srobert   void setHasODRHash(bool HasHash);
1919*12c85518Srobert 
1920e5dd7070Spatrick   const ObjCInterfaceDecl *findInterfaceWithDesignatedInitializers() const;
1921e5dd7070Spatrick   bool inheritsDesignatedInitializers() const;
1922e5dd7070Spatrick };
1923e5dd7070Spatrick 
1924e5dd7070Spatrick /// ObjCIvarDecl - Represents an ObjC instance variable. In general, ObjC
1925e5dd7070Spatrick /// instance variables are identical to C. The only exception is Objective-C
1926e5dd7070Spatrick /// supports C++ style access control. For example:
1927e5dd7070Spatrick ///
1928e5dd7070Spatrick ///   \@interface IvarExample : NSObject
1929e5dd7070Spatrick ///   {
1930e5dd7070Spatrick ///     id defaultToProtected;
1931e5dd7070Spatrick ///   \@public:
1932e5dd7070Spatrick ///     id canBePublic; // same as C++.
1933e5dd7070Spatrick ///   \@protected:
1934e5dd7070Spatrick ///     id canBeProtected; // same as C++.
1935e5dd7070Spatrick ///   \@package:
1936e5dd7070Spatrick ///     id canBePackage; // framework visibility (not available in C++).
1937e5dd7070Spatrick ///   }
1938e5dd7070Spatrick ///
1939e5dd7070Spatrick class ObjCIvarDecl : public FieldDecl {
1940e5dd7070Spatrick   void anchor() override;
1941e5dd7070Spatrick 
1942e5dd7070Spatrick public:
1943e5dd7070Spatrick   enum AccessControl {
1944e5dd7070Spatrick     None, Private, Protected, Public, Package
1945e5dd7070Spatrick   };
1946e5dd7070Spatrick 
1947e5dd7070Spatrick private:
ObjCIvarDecl(ObjCContainerDecl * DC,SourceLocation StartLoc,SourceLocation IdLoc,IdentifierInfo * Id,QualType T,TypeSourceInfo * TInfo,AccessControl ac,Expr * BW,bool synthesized)1948e5dd7070Spatrick   ObjCIvarDecl(ObjCContainerDecl *DC, SourceLocation StartLoc,
1949e5dd7070Spatrick                SourceLocation IdLoc, IdentifierInfo *Id,
1950e5dd7070Spatrick                QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW,
1951e5dd7070Spatrick                bool synthesized)
1952e5dd7070Spatrick       : FieldDecl(ObjCIvar, DC, StartLoc, IdLoc, Id, T, TInfo, BW,
1953e5dd7070Spatrick                   /*Mutable=*/false, /*HasInit=*/ICIS_NoInit),
1954e5dd7070Spatrick         DeclAccess(ac), Synthesized(synthesized) {}
1955e5dd7070Spatrick 
1956e5dd7070Spatrick public:
1957e5dd7070Spatrick   static ObjCIvarDecl *Create(ASTContext &C, ObjCContainerDecl *DC,
1958e5dd7070Spatrick                               SourceLocation StartLoc, SourceLocation IdLoc,
1959e5dd7070Spatrick                               IdentifierInfo *Id, QualType T,
1960e5dd7070Spatrick                               TypeSourceInfo *TInfo,
1961e5dd7070Spatrick                               AccessControl ac, Expr *BW = nullptr,
1962e5dd7070Spatrick                               bool synthesized=false);
1963e5dd7070Spatrick 
1964e5dd7070Spatrick   static ObjCIvarDecl *CreateDeserialized(ASTContext &C, unsigned ID);
1965e5dd7070Spatrick 
1966e5dd7070Spatrick   /// Return the class interface that this ivar is logically contained
1967e5dd7070Spatrick   /// in; this is either the interface where the ivar was declared, or the
1968e5dd7070Spatrick   /// interface the ivar is conceptually a part of in the case of synthesized
1969e5dd7070Spatrick   /// ivars.
1970*12c85518Srobert   ObjCInterfaceDecl *getContainingInterface();
getContainingInterface()1971*12c85518Srobert   const ObjCInterfaceDecl *getContainingInterface() const {
1972*12c85518Srobert     return const_cast<ObjCIvarDecl *>(this)->getContainingInterface();
1973*12c85518Srobert   }
1974e5dd7070Spatrick 
getNextIvar()1975e5dd7070Spatrick   ObjCIvarDecl *getNextIvar() { return NextIvar; }
getNextIvar()1976e5dd7070Spatrick   const ObjCIvarDecl *getNextIvar() const { return NextIvar; }
setNextIvar(ObjCIvarDecl * ivar)1977e5dd7070Spatrick   void setNextIvar(ObjCIvarDecl *ivar) { NextIvar = ivar; }
1978e5dd7070Spatrick 
getCanonicalDecl()1979*12c85518Srobert   ObjCIvarDecl *getCanonicalDecl() override {
1980*12c85518Srobert     return cast<ObjCIvarDecl>(FieldDecl::getCanonicalDecl());
1981*12c85518Srobert   }
getCanonicalDecl()1982*12c85518Srobert   const ObjCIvarDecl *getCanonicalDecl() const {
1983*12c85518Srobert     return const_cast<ObjCIvarDecl *>(this)->getCanonicalDecl();
1984*12c85518Srobert   }
1985*12c85518Srobert 
setAccessControl(AccessControl ac)1986e5dd7070Spatrick   void setAccessControl(AccessControl ac) { DeclAccess = ac; }
1987e5dd7070Spatrick 
getAccessControl()1988e5dd7070Spatrick   AccessControl getAccessControl() const { return AccessControl(DeclAccess); }
1989e5dd7070Spatrick 
getCanonicalAccessControl()1990e5dd7070Spatrick   AccessControl getCanonicalAccessControl() const {
1991e5dd7070Spatrick     return DeclAccess == None ? Protected : AccessControl(DeclAccess);
1992e5dd7070Spatrick   }
1993e5dd7070Spatrick 
setSynthesize(bool synth)1994e5dd7070Spatrick   void setSynthesize(bool synth) { Synthesized = synth; }
getSynthesize()1995e5dd7070Spatrick   bool getSynthesize() const { return Synthesized; }
1996e5dd7070Spatrick 
1997e5dd7070Spatrick   /// Retrieve the type of this instance variable when viewed as a member of a
1998e5dd7070Spatrick   /// specific object type.
1999e5dd7070Spatrick   QualType getUsageType(QualType objectType) const;
2000e5dd7070Spatrick 
2001e5dd7070Spatrick   // Implement isa/cast/dyncast/etc.
classof(const Decl * D)2002e5dd7070Spatrick   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
classofKind(Kind K)2003e5dd7070Spatrick   static bool classofKind(Kind K) { return K == ObjCIvar; }
2004e5dd7070Spatrick 
2005e5dd7070Spatrick private:
2006e5dd7070Spatrick   /// NextIvar - Next Ivar in the list of ivars declared in class; class's
2007e5dd7070Spatrick   /// extensions and class's implementation
2008e5dd7070Spatrick   ObjCIvarDecl *NextIvar = nullptr;
2009e5dd7070Spatrick 
2010e5dd7070Spatrick   // NOTE: VC++ treats enums as signed, avoid using the AccessControl enum
2011e5dd7070Spatrick   unsigned DeclAccess : 3;
2012e5dd7070Spatrick   unsigned Synthesized : 1;
2013e5dd7070Spatrick };
2014e5dd7070Spatrick 
2015e5dd7070Spatrick /// Represents a field declaration created by an \@defs(...).
2016e5dd7070Spatrick class ObjCAtDefsFieldDecl : public FieldDecl {
ObjCAtDefsFieldDecl(DeclContext * DC,SourceLocation StartLoc,SourceLocation IdLoc,IdentifierInfo * Id,QualType T,Expr * BW)2017e5dd7070Spatrick   ObjCAtDefsFieldDecl(DeclContext *DC, SourceLocation StartLoc,
2018e5dd7070Spatrick                       SourceLocation IdLoc, IdentifierInfo *Id,
2019e5dd7070Spatrick                       QualType T, Expr *BW)
2020e5dd7070Spatrick       : FieldDecl(ObjCAtDefsField, DC, StartLoc, IdLoc, Id, T,
2021e5dd7070Spatrick                   /*TInfo=*/nullptr, // FIXME: Do ObjCAtDefs have declarators ?
2022e5dd7070Spatrick                   BW, /*Mutable=*/false, /*HasInit=*/ICIS_NoInit) {}
2023e5dd7070Spatrick 
2024e5dd7070Spatrick   void anchor() override;
2025e5dd7070Spatrick 
2026e5dd7070Spatrick public:
2027e5dd7070Spatrick   static ObjCAtDefsFieldDecl *Create(ASTContext &C, DeclContext *DC,
2028e5dd7070Spatrick                                      SourceLocation StartLoc,
2029e5dd7070Spatrick                                      SourceLocation IdLoc, IdentifierInfo *Id,
2030e5dd7070Spatrick                                      QualType T, Expr *BW);
2031e5dd7070Spatrick 
2032e5dd7070Spatrick   static ObjCAtDefsFieldDecl *CreateDeserialized(ASTContext &C, unsigned ID);
2033e5dd7070Spatrick 
2034e5dd7070Spatrick   // Implement isa/cast/dyncast/etc.
classof(const Decl * D)2035e5dd7070Spatrick   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
classofKind(Kind K)2036e5dd7070Spatrick   static bool classofKind(Kind K) { return K == ObjCAtDefsField; }
2037e5dd7070Spatrick };
2038e5dd7070Spatrick 
2039e5dd7070Spatrick /// Represents an Objective-C protocol declaration.
2040e5dd7070Spatrick ///
2041e5dd7070Spatrick /// Objective-C protocols declare a pure abstract type (i.e., no instance
2042e5dd7070Spatrick /// variables are permitted).  Protocols originally drew inspiration from
2043e5dd7070Spatrick /// C++ pure virtual functions (a C++ feature with nice semantics and lousy
2044e5dd7070Spatrick /// syntax:-). Here is an example:
2045e5dd7070Spatrick ///
2046e5dd7070Spatrick /// \code
2047e5dd7070Spatrick /// \@protocol NSDraggingInfo <refproto1, refproto2>
2048e5dd7070Spatrick /// - (NSWindow *)draggingDestinationWindow;
2049e5dd7070Spatrick /// - (NSImage *)draggedImage;
2050e5dd7070Spatrick /// \@end
2051e5dd7070Spatrick /// \endcode
2052e5dd7070Spatrick ///
2053e5dd7070Spatrick /// This says that NSDraggingInfo requires two methods and requires everything
2054e5dd7070Spatrick /// that the two "referenced protocols" 'refproto1' and 'refproto2' require as
2055e5dd7070Spatrick /// well.
2056e5dd7070Spatrick ///
2057e5dd7070Spatrick /// \code
2058e5dd7070Spatrick /// \@interface ImplementsNSDraggingInfo : NSObject \<NSDraggingInfo>
2059e5dd7070Spatrick /// \@end
2060e5dd7070Spatrick /// \endcode
2061e5dd7070Spatrick ///
2062e5dd7070Spatrick /// ObjC protocols inspired Java interfaces. Unlike Java, ObjC classes and
2063e5dd7070Spatrick /// protocols are in distinct namespaces. For example, Cocoa defines both
2064e5dd7070Spatrick /// an NSObject protocol and class (which isn't allowed in Java). As a result,
2065e5dd7070Spatrick /// protocols are referenced using angle brackets as follows:
2066e5dd7070Spatrick ///
2067e5dd7070Spatrick /// id \<NSDraggingInfo> anyObjectThatImplementsNSDraggingInfo;
2068e5dd7070Spatrick class ObjCProtocolDecl : public ObjCContainerDecl,
2069e5dd7070Spatrick                          public Redeclarable<ObjCProtocolDecl> {
2070e5dd7070Spatrick   struct DefinitionData {
2071e5dd7070Spatrick     // The declaration that defines this protocol.
2072e5dd7070Spatrick     ObjCProtocolDecl *Definition;
2073e5dd7070Spatrick 
2074e5dd7070Spatrick     /// Referenced protocols
2075e5dd7070Spatrick     ObjCProtocolList ReferencedProtocols;
2076*12c85518Srobert 
2077*12c85518Srobert     /// Tracks whether a ODR hash has been computed for this protocol.
2078*12c85518Srobert     unsigned HasODRHash : 1;
2079*12c85518Srobert 
2080*12c85518Srobert     /// A hash of parts of the class to help in ODR checking.
2081*12c85518Srobert     unsigned ODRHash = 0;
2082e5dd7070Spatrick   };
2083e5dd7070Spatrick 
2084e5dd7070Spatrick   /// Contains a pointer to the data associated with this class,
2085e5dd7070Spatrick   /// which will be NULL if this class has not yet been defined.
2086e5dd7070Spatrick   ///
2087e5dd7070Spatrick   /// The bit indicates when we don't need to check for out-of-date
2088e5dd7070Spatrick   /// declarations. It will be set unless modules are enabled.
2089e5dd7070Spatrick   llvm::PointerIntPair<DefinitionData *, 1, bool> Data;
2090e5dd7070Spatrick 
2091e5dd7070Spatrick   ObjCProtocolDecl(ASTContext &C, DeclContext *DC, IdentifierInfo *Id,
2092e5dd7070Spatrick                    SourceLocation nameLoc, SourceLocation atStartLoc,
2093e5dd7070Spatrick                    ObjCProtocolDecl *PrevDecl);
2094e5dd7070Spatrick 
2095e5dd7070Spatrick   void anchor() override;
2096e5dd7070Spatrick 
data()2097e5dd7070Spatrick   DefinitionData &data() const {
2098e5dd7070Spatrick     assert(Data.getPointer() && "Objective-C protocol has no definition!");
2099e5dd7070Spatrick     return *Data.getPointer();
2100e5dd7070Spatrick   }
2101e5dd7070Spatrick 
2102e5dd7070Spatrick   void allocateDefinitionData();
2103e5dd7070Spatrick 
2104e5dd7070Spatrick   using redeclarable_base = Redeclarable<ObjCProtocolDecl>;
2105e5dd7070Spatrick 
getNextRedeclarationImpl()2106e5dd7070Spatrick   ObjCProtocolDecl *getNextRedeclarationImpl() override {
2107e5dd7070Spatrick     return getNextRedeclaration();
2108e5dd7070Spatrick   }
2109e5dd7070Spatrick 
getPreviousDeclImpl()2110e5dd7070Spatrick   ObjCProtocolDecl *getPreviousDeclImpl() override {
2111e5dd7070Spatrick     return getPreviousDecl();
2112e5dd7070Spatrick   }
2113e5dd7070Spatrick 
getMostRecentDeclImpl()2114e5dd7070Spatrick   ObjCProtocolDecl *getMostRecentDeclImpl() override {
2115e5dd7070Spatrick     return getMostRecentDecl();
2116e5dd7070Spatrick   }
2117e5dd7070Spatrick 
2118*12c85518Srobert   /// True if a valid hash is stored in ODRHash.
2119*12c85518Srobert   bool hasODRHash() const;
2120*12c85518Srobert   void setHasODRHash(bool HasHash);
2121*12c85518Srobert 
2122e5dd7070Spatrick public:
2123e5dd7070Spatrick   friend class ASTDeclReader;
2124e5dd7070Spatrick   friend class ASTDeclWriter;
2125e5dd7070Spatrick   friend class ASTReader;
2126*12c85518Srobert   friend class ODRDiagsEmitter;
2127e5dd7070Spatrick 
2128e5dd7070Spatrick   static ObjCProtocolDecl *Create(ASTContext &C, DeclContext *DC,
2129e5dd7070Spatrick                                   IdentifierInfo *Id,
2130e5dd7070Spatrick                                   SourceLocation nameLoc,
2131e5dd7070Spatrick                                   SourceLocation atStartLoc,
2132e5dd7070Spatrick                                   ObjCProtocolDecl *PrevDecl);
2133e5dd7070Spatrick 
2134e5dd7070Spatrick   static ObjCProtocolDecl *CreateDeserialized(ASTContext &C, unsigned ID);
2135e5dd7070Spatrick 
getReferencedProtocols()2136e5dd7070Spatrick   const ObjCProtocolList &getReferencedProtocols() const {
2137e5dd7070Spatrick     assert(hasDefinition() && "No definition available!");
2138e5dd7070Spatrick     return data().ReferencedProtocols;
2139e5dd7070Spatrick   }
2140e5dd7070Spatrick 
2141e5dd7070Spatrick   using protocol_iterator = ObjCProtocolList::iterator;
2142e5dd7070Spatrick   using protocol_range = llvm::iterator_range<protocol_iterator>;
2143e5dd7070Spatrick 
protocols()2144e5dd7070Spatrick   protocol_range protocols() const {
2145e5dd7070Spatrick     return protocol_range(protocol_begin(), protocol_end());
2146e5dd7070Spatrick   }
2147e5dd7070Spatrick 
protocol_begin()2148e5dd7070Spatrick   protocol_iterator protocol_begin() const {
2149e5dd7070Spatrick     if (!hasDefinition())
2150e5dd7070Spatrick       return protocol_iterator();
2151e5dd7070Spatrick 
2152e5dd7070Spatrick     return data().ReferencedProtocols.begin();
2153e5dd7070Spatrick   }
2154e5dd7070Spatrick 
protocol_end()2155e5dd7070Spatrick   protocol_iterator protocol_end() const {
2156e5dd7070Spatrick     if (!hasDefinition())
2157e5dd7070Spatrick       return protocol_iterator();
2158e5dd7070Spatrick 
2159e5dd7070Spatrick     return data().ReferencedProtocols.end();
2160e5dd7070Spatrick   }
2161e5dd7070Spatrick 
2162e5dd7070Spatrick   using protocol_loc_iterator = ObjCProtocolList::loc_iterator;
2163e5dd7070Spatrick   using protocol_loc_range = llvm::iterator_range<protocol_loc_iterator>;
2164e5dd7070Spatrick 
protocol_locs()2165e5dd7070Spatrick   protocol_loc_range protocol_locs() const {
2166e5dd7070Spatrick     return protocol_loc_range(protocol_loc_begin(), protocol_loc_end());
2167e5dd7070Spatrick   }
2168e5dd7070Spatrick 
protocol_loc_begin()2169e5dd7070Spatrick   protocol_loc_iterator protocol_loc_begin() const {
2170e5dd7070Spatrick     if (!hasDefinition())
2171e5dd7070Spatrick       return protocol_loc_iterator();
2172e5dd7070Spatrick 
2173e5dd7070Spatrick     return data().ReferencedProtocols.loc_begin();
2174e5dd7070Spatrick   }
2175e5dd7070Spatrick 
protocol_loc_end()2176e5dd7070Spatrick   protocol_loc_iterator protocol_loc_end() const {
2177e5dd7070Spatrick     if (!hasDefinition())
2178e5dd7070Spatrick       return protocol_loc_iterator();
2179e5dd7070Spatrick 
2180e5dd7070Spatrick     return data().ReferencedProtocols.loc_end();
2181e5dd7070Spatrick   }
2182e5dd7070Spatrick 
protocol_size()2183e5dd7070Spatrick   unsigned protocol_size() const {
2184e5dd7070Spatrick     if (!hasDefinition())
2185e5dd7070Spatrick       return 0;
2186e5dd7070Spatrick 
2187e5dd7070Spatrick     return data().ReferencedProtocols.size();
2188e5dd7070Spatrick   }
2189e5dd7070Spatrick 
2190e5dd7070Spatrick   /// setProtocolList - Set the list of protocols that this interface
2191e5dd7070Spatrick   /// implements.
setProtocolList(ObjCProtocolDecl * const * List,unsigned Num,const SourceLocation * Locs,ASTContext & C)2192e5dd7070Spatrick   void setProtocolList(ObjCProtocolDecl *const*List, unsigned Num,
2193e5dd7070Spatrick                        const SourceLocation *Locs, ASTContext &C) {
2194e5dd7070Spatrick     assert(hasDefinition() && "Protocol is not defined");
2195e5dd7070Spatrick     data().ReferencedProtocols.set(List, Num, Locs, C);
2196e5dd7070Spatrick   }
2197e5dd7070Spatrick 
2198a9ac8606Spatrick   /// This is true iff the protocol is tagged with the
2199a9ac8606Spatrick   /// `objc_non_runtime_protocol` attribute.
2200a9ac8606Spatrick   bool isNonRuntimeProtocol() const;
2201a9ac8606Spatrick 
2202a9ac8606Spatrick   /// Get the set of all protocols implied by this protocols inheritance
2203a9ac8606Spatrick   /// hierarchy.
2204a9ac8606Spatrick   void getImpliedProtocols(llvm::DenseSet<const ObjCProtocolDecl *> &IPs) const;
2205a9ac8606Spatrick 
2206e5dd7070Spatrick   ObjCProtocolDecl *lookupProtocolNamed(IdentifierInfo *PName);
2207e5dd7070Spatrick 
2208e5dd7070Spatrick   // Lookup a method. First, we search locally. If a method isn't
2209e5dd7070Spatrick   // found, we search referenced protocols and class categories.
2210e5dd7070Spatrick   ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance) const;
2211e5dd7070Spatrick 
lookupInstanceMethod(Selector Sel)2212e5dd7070Spatrick   ObjCMethodDecl *lookupInstanceMethod(Selector Sel) const {
2213e5dd7070Spatrick     return lookupMethod(Sel, true/*isInstance*/);
2214e5dd7070Spatrick   }
2215e5dd7070Spatrick 
lookupClassMethod(Selector Sel)2216e5dd7070Spatrick   ObjCMethodDecl *lookupClassMethod(Selector Sel) const {
2217e5dd7070Spatrick     return lookupMethod(Sel, false/*isInstance*/);
2218e5dd7070Spatrick   }
2219e5dd7070Spatrick 
2220e5dd7070Spatrick   /// Determine whether this protocol has a definition.
hasDefinition()2221e5dd7070Spatrick   bool hasDefinition() const {
2222e5dd7070Spatrick     // If the name of this protocol is out-of-date, bring it up-to-date, which
2223e5dd7070Spatrick     // might bring in a definition.
2224e5dd7070Spatrick     // Note: a null value indicates that we don't have a definition and that
2225e5dd7070Spatrick     // modules are enabled.
2226e5dd7070Spatrick     if (!Data.getOpaqueValue())
2227e5dd7070Spatrick       getMostRecentDecl();
2228e5dd7070Spatrick 
2229e5dd7070Spatrick     return Data.getPointer();
2230e5dd7070Spatrick   }
2231e5dd7070Spatrick 
2232e5dd7070Spatrick   /// Retrieve the definition of this protocol, if any.
getDefinition()2233e5dd7070Spatrick   ObjCProtocolDecl *getDefinition() {
2234e5dd7070Spatrick     return hasDefinition()? Data.getPointer()->Definition : nullptr;
2235e5dd7070Spatrick   }
2236e5dd7070Spatrick 
2237e5dd7070Spatrick   /// Retrieve the definition of this protocol, if any.
getDefinition()2238e5dd7070Spatrick   const ObjCProtocolDecl *getDefinition() const {
2239e5dd7070Spatrick     return hasDefinition()? Data.getPointer()->Definition : nullptr;
2240e5dd7070Spatrick   }
2241e5dd7070Spatrick 
2242e5dd7070Spatrick   /// Determine whether this particular declaration is also the
2243e5dd7070Spatrick   /// definition.
isThisDeclarationADefinition()2244e5dd7070Spatrick   bool isThisDeclarationADefinition() const {
2245e5dd7070Spatrick     return getDefinition() == this;
2246e5dd7070Spatrick   }
2247e5dd7070Spatrick 
2248e5dd7070Spatrick   /// Starts the definition of this Objective-C protocol.
2249e5dd7070Spatrick   void startDefinition();
2250e5dd7070Spatrick 
2251*12c85518Srobert   /// Starts the definition without sharing it with other redeclarations.
2252*12c85518Srobert   /// Such definition shouldn't be used for anything but only to compare if
2253*12c85518Srobert   /// a duplicate is compatible with previous definition or if it is
2254*12c85518Srobert   /// a distinct duplicate.
2255*12c85518Srobert   void startDuplicateDefinitionForComparison();
2256*12c85518Srobert   void mergeDuplicateDefinitionWithCommon(const ObjCProtocolDecl *Definition);
2257*12c85518Srobert 
2258e5dd7070Spatrick   /// Produce a name to be used for protocol's metadata. It comes either via
2259e5dd7070Spatrick   /// objc_runtime_name attribute or protocol name.
2260e5dd7070Spatrick   StringRef getObjCRuntimeNameAsString() const;
2261e5dd7070Spatrick 
getSourceRange()2262e5dd7070Spatrick   SourceRange getSourceRange() const override LLVM_READONLY {
2263e5dd7070Spatrick     if (isThisDeclarationADefinition())
2264e5dd7070Spatrick       return ObjCContainerDecl::getSourceRange();
2265e5dd7070Spatrick 
2266e5dd7070Spatrick     return SourceRange(getAtStartLoc(), getLocation());
2267e5dd7070Spatrick   }
2268e5dd7070Spatrick 
2269e5dd7070Spatrick   using redecl_range = redeclarable_base::redecl_range;
2270e5dd7070Spatrick   using redecl_iterator = redeclarable_base::redecl_iterator;
2271e5dd7070Spatrick 
2272e5dd7070Spatrick   using redeclarable_base::redecls_begin;
2273e5dd7070Spatrick   using redeclarable_base::redecls_end;
2274e5dd7070Spatrick   using redeclarable_base::redecls;
2275e5dd7070Spatrick   using redeclarable_base::getPreviousDecl;
2276e5dd7070Spatrick   using redeclarable_base::getMostRecentDecl;
2277e5dd7070Spatrick   using redeclarable_base::isFirstDecl;
2278e5dd7070Spatrick 
2279e5dd7070Spatrick   /// Retrieves the canonical declaration of this Objective-C protocol.
getCanonicalDecl()2280e5dd7070Spatrick   ObjCProtocolDecl *getCanonicalDecl() override { return getFirstDecl(); }
getCanonicalDecl()2281e5dd7070Spatrick   const ObjCProtocolDecl *getCanonicalDecl() const { return getFirstDecl(); }
2282e5dd7070Spatrick 
2283*12c85518Srobert   void collectPropertiesToImplement(PropertyMap &PM) const override;
2284e5dd7070Spatrick 
2285e5dd7070Spatrick   void collectInheritedProtocolProperties(const ObjCPropertyDecl *Property,
2286e5dd7070Spatrick                                           ProtocolPropertySet &PS,
2287e5dd7070Spatrick                                           PropertyDeclOrder &PO) const;
2288e5dd7070Spatrick 
2289*12c85518Srobert   /// Get precomputed ODRHash or add a new one.
2290*12c85518Srobert   unsigned getODRHash();
2291*12c85518Srobert 
classof(const Decl * D)2292e5dd7070Spatrick   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
classofKind(Kind K)2293e5dd7070Spatrick   static bool classofKind(Kind K) { return K == ObjCProtocol; }
2294e5dd7070Spatrick };
2295e5dd7070Spatrick 
2296e5dd7070Spatrick /// ObjCCategoryDecl - Represents a category declaration. A category allows
2297e5dd7070Spatrick /// you to add methods to an existing class (without subclassing or modifying
2298e5dd7070Spatrick /// the original class interface or implementation:-). Categories don't allow
2299e5dd7070Spatrick /// you to add instance data. The following example adds "myMethod" to all
2300e5dd7070Spatrick /// NSView's within a process:
2301e5dd7070Spatrick ///
2302e5dd7070Spatrick /// \@interface NSView (MyViewMethods)
2303e5dd7070Spatrick /// - myMethod;
2304e5dd7070Spatrick /// \@end
2305e5dd7070Spatrick ///
2306e5dd7070Spatrick /// Categories also allow you to split the implementation of a class across
2307e5dd7070Spatrick /// several files (a feature more naturally supported in C++).
2308e5dd7070Spatrick ///
2309e5dd7070Spatrick /// Categories were originally inspired by dynamic languages such as Common
2310e5dd7070Spatrick /// Lisp and Smalltalk.  More traditional class-based languages (C++, Java)
2311e5dd7070Spatrick /// don't support this level of dynamism, which is both powerful and dangerous.
2312e5dd7070Spatrick class ObjCCategoryDecl : public ObjCContainerDecl {
2313e5dd7070Spatrick   /// Interface belonging to this category
2314e5dd7070Spatrick   ObjCInterfaceDecl *ClassInterface;
2315e5dd7070Spatrick 
2316e5dd7070Spatrick   /// The type parameters associated with this category, if any.
2317e5dd7070Spatrick   ObjCTypeParamList *TypeParamList = nullptr;
2318e5dd7070Spatrick 
2319e5dd7070Spatrick   /// referenced protocols in this category.
2320e5dd7070Spatrick   ObjCProtocolList ReferencedProtocols;
2321e5dd7070Spatrick 
2322e5dd7070Spatrick   /// Next category belonging to this class.
2323e5dd7070Spatrick   /// FIXME: this should not be a singly-linked list.  Move storage elsewhere.
2324e5dd7070Spatrick   ObjCCategoryDecl *NextClassCategory = nullptr;
2325e5dd7070Spatrick 
2326e5dd7070Spatrick   /// The location of the category name in this declaration.
2327e5dd7070Spatrick   SourceLocation CategoryNameLoc;
2328e5dd7070Spatrick 
2329e5dd7070Spatrick   /// class extension may have private ivars.
2330e5dd7070Spatrick   SourceLocation IvarLBraceLoc;
2331e5dd7070Spatrick   SourceLocation IvarRBraceLoc;
2332e5dd7070Spatrick 
2333e5dd7070Spatrick   ObjCCategoryDecl(DeclContext *DC, SourceLocation AtLoc,
2334e5dd7070Spatrick                    SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc,
2335e5dd7070Spatrick                    IdentifierInfo *Id, ObjCInterfaceDecl *IDecl,
2336e5dd7070Spatrick                    ObjCTypeParamList *typeParamList,
2337e5dd7070Spatrick                    SourceLocation IvarLBraceLoc = SourceLocation(),
2338e5dd7070Spatrick                    SourceLocation IvarRBraceLoc = SourceLocation());
2339e5dd7070Spatrick 
2340e5dd7070Spatrick   void anchor() override;
2341e5dd7070Spatrick 
2342e5dd7070Spatrick public:
2343e5dd7070Spatrick   friend class ASTDeclReader;
2344e5dd7070Spatrick   friend class ASTDeclWriter;
2345e5dd7070Spatrick 
2346e5dd7070Spatrick   static ObjCCategoryDecl *Create(ASTContext &C, DeclContext *DC,
2347e5dd7070Spatrick                                   SourceLocation AtLoc,
2348e5dd7070Spatrick                                   SourceLocation ClassNameLoc,
2349e5dd7070Spatrick                                   SourceLocation CategoryNameLoc,
2350e5dd7070Spatrick                                   IdentifierInfo *Id,
2351e5dd7070Spatrick                                   ObjCInterfaceDecl *IDecl,
2352e5dd7070Spatrick                                   ObjCTypeParamList *typeParamList,
2353e5dd7070Spatrick                                   SourceLocation IvarLBraceLoc=SourceLocation(),
2354e5dd7070Spatrick                                   SourceLocation IvarRBraceLoc=SourceLocation());
2355e5dd7070Spatrick   static ObjCCategoryDecl *CreateDeserialized(ASTContext &C, unsigned ID);
2356e5dd7070Spatrick 
getClassInterface()2357e5dd7070Spatrick   ObjCInterfaceDecl *getClassInterface() { return ClassInterface; }
getClassInterface()2358e5dd7070Spatrick   const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; }
2359e5dd7070Spatrick 
2360e5dd7070Spatrick   /// Retrieve the type parameter list associated with this category or
2361e5dd7070Spatrick   /// extension.
getTypeParamList()2362e5dd7070Spatrick   ObjCTypeParamList *getTypeParamList() const { return TypeParamList; }
2363e5dd7070Spatrick 
2364e5dd7070Spatrick   /// Set the type parameters of this category.
2365e5dd7070Spatrick   ///
2366e5dd7070Spatrick   /// This function is used by the AST importer, which must import the type
2367e5dd7070Spatrick   /// parameters after creating their DeclContext to avoid loops.
2368e5dd7070Spatrick   void setTypeParamList(ObjCTypeParamList *TPL);
2369e5dd7070Spatrick 
2370e5dd7070Spatrick 
2371e5dd7070Spatrick   ObjCCategoryImplDecl *getImplementation() const;
2372e5dd7070Spatrick   void setImplementation(ObjCCategoryImplDecl *ImplD);
2373e5dd7070Spatrick 
2374e5dd7070Spatrick   /// setProtocolList - Set the list of protocols that this interface
2375e5dd7070Spatrick   /// implements.
setProtocolList(ObjCProtocolDecl * const * List,unsigned Num,const SourceLocation * Locs,ASTContext & C)2376e5dd7070Spatrick   void setProtocolList(ObjCProtocolDecl *const*List, unsigned Num,
2377e5dd7070Spatrick                        const SourceLocation *Locs, ASTContext &C) {
2378e5dd7070Spatrick     ReferencedProtocols.set(List, Num, Locs, C);
2379e5dd7070Spatrick   }
2380e5dd7070Spatrick 
getReferencedProtocols()2381e5dd7070Spatrick   const ObjCProtocolList &getReferencedProtocols() const {
2382e5dd7070Spatrick     return ReferencedProtocols;
2383e5dd7070Spatrick   }
2384e5dd7070Spatrick 
2385e5dd7070Spatrick   using protocol_iterator = ObjCProtocolList::iterator;
2386e5dd7070Spatrick   using protocol_range = llvm::iterator_range<protocol_iterator>;
2387e5dd7070Spatrick 
protocols()2388e5dd7070Spatrick   protocol_range protocols() const {
2389e5dd7070Spatrick     return protocol_range(protocol_begin(), protocol_end());
2390e5dd7070Spatrick   }
2391e5dd7070Spatrick 
protocol_begin()2392e5dd7070Spatrick   protocol_iterator protocol_begin() const {
2393e5dd7070Spatrick     return ReferencedProtocols.begin();
2394e5dd7070Spatrick   }
2395e5dd7070Spatrick 
protocol_end()2396e5dd7070Spatrick   protocol_iterator protocol_end() const { return ReferencedProtocols.end(); }
protocol_size()2397e5dd7070Spatrick   unsigned protocol_size() const { return ReferencedProtocols.size(); }
2398e5dd7070Spatrick 
2399e5dd7070Spatrick   using protocol_loc_iterator = ObjCProtocolList::loc_iterator;
2400e5dd7070Spatrick   using protocol_loc_range = llvm::iterator_range<protocol_loc_iterator>;
2401e5dd7070Spatrick 
protocol_locs()2402e5dd7070Spatrick   protocol_loc_range protocol_locs() const {
2403e5dd7070Spatrick     return protocol_loc_range(protocol_loc_begin(), protocol_loc_end());
2404e5dd7070Spatrick   }
2405e5dd7070Spatrick 
protocol_loc_begin()2406e5dd7070Spatrick   protocol_loc_iterator protocol_loc_begin() const {
2407e5dd7070Spatrick     return ReferencedProtocols.loc_begin();
2408e5dd7070Spatrick   }
2409e5dd7070Spatrick 
protocol_loc_end()2410e5dd7070Spatrick   protocol_loc_iterator protocol_loc_end() const {
2411e5dd7070Spatrick     return ReferencedProtocols.loc_end();
2412e5dd7070Spatrick   }
2413e5dd7070Spatrick 
getNextClassCategory()2414e5dd7070Spatrick   ObjCCategoryDecl *getNextClassCategory() const { return NextClassCategory; }
2415e5dd7070Spatrick 
2416e5dd7070Spatrick   /// Retrieve the pointer to the next stored category (or extension),
2417e5dd7070Spatrick   /// which may be hidden.
getNextClassCategoryRaw()2418e5dd7070Spatrick   ObjCCategoryDecl *getNextClassCategoryRaw() const {
2419e5dd7070Spatrick     return NextClassCategory;
2420e5dd7070Spatrick   }
2421e5dd7070Spatrick 
IsClassExtension()2422e5dd7070Spatrick   bool IsClassExtension() const { return getIdentifier() == nullptr; }
2423e5dd7070Spatrick 
2424e5dd7070Spatrick   using ivar_iterator = specific_decl_iterator<ObjCIvarDecl>;
2425e5dd7070Spatrick   using ivar_range = llvm::iterator_range<specific_decl_iterator<ObjCIvarDecl>>;
2426e5dd7070Spatrick 
ivars()2427e5dd7070Spatrick   ivar_range ivars() const { return ivar_range(ivar_begin(), ivar_end()); }
2428e5dd7070Spatrick 
ivar_begin()2429e5dd7070Spatrick   ivar_iterator ivar_begin() const {
2430e5dd7070Spatrick     return ivar_iterator(decls_begin());
2431e5dd7070Spatrick   }
2432e5dd7070Spatrick 
ivar_end()2433e5dd7070Spatrick   ivar_iterator ivar_end() const {
2434e5dd7070Spatrick     return ivar_iterator(decls_end());
2435e5dd7070Spatrick   }
2436e5dd7070Spatrick 
ivar_size()2437e5dd7070Spatrick   unsigned ivar_size() const {
2438e5dd7070Spatrick     return std::distance(ivar_begin(), ivar_end());
2439e5dd7070Spatrick   }
2440e5dd7070Spatrick 
ivar_empty()2441e5dd7070Spatrick   bool ivar_empty() const {
2442e5dd7070Spatrick     return ivar_begin() == ivar_end();
2443e5dd7070Spatrick   }
2444e5dd7070Spatrick 
getCategoryNameLoc()2445e5dd7070Spatrick   SourceLocation getCategoryNameLoc() const { return CategoryNameLoc; }
setCategoryNameLoc(SourceLocation Loc)2446e5dd7070Spatrick   void setCategoryNameLoc(SourceLocation Loc) { CategoryNameLoc = Loc; }
2447e5dd7070Spatrick 
setIvarLBraceLoc(SourceLocation Loc)2448e5dd7070Spatrick   void setIvarLBraceLoc(SourceLocation Loc) { IvarLBraceLoc = Loc; }
getIvarLBraceLoc()2449e5dd7070Spatrick   SourceLocation getIvarLBraceLoc() const { return IvarLBraceLoc; }
setIvarRBraceLoc(SourceLocation Loc)2450e5dd7070Spatrick   void setIvarRBraceLoc(SourceLocation Loc) { IvarRBraceLoc = Loc; }
getIvarRBraceLoc()2451e5dd7070Spatrick   SourceLocation getIvarRBraceLoc() const { return IvarRBraceLoc; }
2452e5dd7070Spatrick 
classof(const Decl * D)2453e5dd7070Spatrick   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
classofKind(Kind K)2454e5dd7070Spatrick   static bool classofKind(Kind K) { return K == ObjCCategory; }
2455e5dd7070Spatrick };
2456e5dd7070Spatrick 
2457e5dd7070Spatrick class ObjCImplDecl : public ObjCContainerDecl {
2458e5dd7070Spatrick   /// Class interface for this class/category implementation
2459e5dd7070Spatrick   ObjCInterfaceDecl *ClassInterface;
2460e5dd7070Spatrick 
2461e5dd7070Spatrick   void anchor() override;
2462e5dd7070Spatrick 
2463e5dd7070Spatrick protected:
ObjCImplDecl(Kind DK,DeclContext * DC,ObjCInterfaceDecl * classInterface,IdentifierInfo * Id,SourceLocation nameLoc,SourceLocation atStartLoc)2464e5dd7070Spatrick   ObjCImplDecl(Kind DK, DeclContext *DC,
2465e5dd7070Spatrick                ObjCInterfaceDecl *classInterface,
2466e5dd7070Spatrick                IdentifierInfo *Id,
2467e5dd7070Spatrick                SourceLocation nameLoc, SourceLocation atStartLoc)
2468e5dd7070Spatrick       : ObjCContainerDecl(DK, DC, Id, nameLoc, atStartLoc),
2469e5dd7070Spatrick         ClassInterface(classInterface) {}
2470e5dd7070Spatrick 
2471e5dd7070Spatrick public:
getClassInterface()2472e5dd7070Spatrick   const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; }
getClassInterface()2473e5dd7070Spatrick   ObjCInterfaceDecl *getClassInterface() { return ClassInterface; }
2474e5dd7070Spatrick   void setClassInterface(ObjCInterfaceDecl *IFace);
2475e5dd7070Spatrick 
addInstanceMethod(ObjCMethodDecl * method)2476e5dd7070Spatrick   void addInstanceMethod(ObjCMethodDecl *method) {
2477e5dd7070Spatrick     // FIXME: Context should be set correctly before we get here.
2478e5dd7070Spatrick     method->setLexicalDeclContext(this);
2479e5dd7070Spatrick     addDecl(method);
2480e5dd7070Spatrick   }
2481e5dd7070Spatrick 
addClassMethod(ObjCMethodDecl * method)2482e5dd7070Spatrick   void addClassMethod(ObjCMethodDecl *method) {
2483e5dd7070Spatrick     // FIXME: Context should be set correctly before we get here.
2484e5dd7070Spatrick     method->setLexicalDeclContext(this);
2485e5dd7070Spatrick     addDecl(method);
2486e5dd7070Spatrick   }
2487e5dd7070Spatrick 
2488e5dd7070Spatrick   void addPropertyImplementation(ObjCPropertyImplDecl *property);
2489e5dd7070Spatrick 
2490e5dd7070Spatrick   ObjCPropertyImplDecl *FindPropertyImplDecl(IdentifierInfo *propertyId,
2491e5dd7070Spatrick                             ObjCPropertyQueryKind queryKind) const;
2492e5dd7070Spatrick   ObjCPropertyImplDecl *FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const;
2493e5dd7070Spatrick 
2494e5dd7070Spatrick   // Iterator access to properties.
2495e5dd7070Spatrick   using propimpl_iterator = specific_decl_iterator<ObjCPropertyImplDecl>;
2496e5dd7070Spatrick   using propimpl_range =
2497e5dd7070Spatrick       llvm::iterator_range<specific_decl_iterator<ObjCPropertyImplDecl>>;
2498e5dd7070Spatrick 
property_impls()2499e5dd7070Spatrick   propimpl_range property_impls() const {
2500e5dd7070Spatrick     return propimpl_range(propimpl_begin(), propimpl_end());
2501e5dd7070Spatrick   }
2502e5dd7070Spatrick 
propimpl_begin()2503e5dd7070Spatrick   propimpl_iterator propimpl_begin() const {
2504e5dd7070Spatrick     return propimpl_iterator(decls_begin());
2505e5dd7070Spatrick   }
2506e5dd7070Spatrick 
propimpl_end()2507e5dd7070Spatrick   propimpl_iterator propimpl_end() const {
2508e5dd7070Spatrick     return propimpl_iterator(decls_end());
2509e5dd7070Spatrick   }
2510e5dd7070Spatrick 
classof(const Decl * D)2511e5dd7070Spatrick   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
2512e5dd7070Spatrick 
classofKind(Kind K)2513e5dd7070Spatrick   static bool classofKind(Kind K) {
2514e5dd7070Spatrick     return K >= firstObjCImpl && K <= lastObjCImpl;
2515e5dd7070Spatrick   }
2516e5dd7070Spatrick };
2517e5dd7070Spatrick 
2518e5dd7070Spatrick /// ObjCCategoryImplDecl - An object of this class encapsulates a category
2519e5dd7070Spatrick /// \@implementation declaration. If a category class has declaration of a
2520e5dd7070Spatrick /// property, its implementation must be specified in the category's
2521e5dd7070Spatrick /// \@implementation declaration. Example:
2522e5dd7070Spatrick /// \@interface I \@end
2523e5dd7070Spatrick /// \@interface I(CATEGORY)
2524e5dd7070Spatrick ///    \@property int p1, d1;
2525e5dd7070Spatrick /// \@end
2526e5dd7070Spatrick /// \@implementation I(CATEGORY)
2527e5dd7070Spatrick ///  \@dynamic p1,d1;
2528e5dd7070Spatrick /// \@end
2529e5dd7070Spatrick ///
2530e5dd7070Spatrick /// ObjCCategoryImplDecl
2531e5dd7070Spatrick class ObjCCategoryImplDecl : public ObjCImplDecl {
2532e5dd7070Spatrick   // Category name location
2533e5dd7070Spatrick   SourceLocation CategoryNameLoc;
2534e5dd7070Spatrick 
ObjCCategoryImplDecl(DeclContext * DC,IdentifierInfo * Id,ObjCInterfaceDecl * classInterface,SourceLocation nameLoc,SourceLocation atStartLoc,SourceLocation CategoryNameLoc)2535e5dd7070Spatrick   ObjCCategoryImplDecl(DeclContext *DC, IdentifierInfo *Id,
2536e5dd7070Spatrick                        ObjCInterfaceDecl *classInterface,
2537e5dd7070Spatrick                        SourceLocation nameLoc, SourceLocation atStartLoc,
2538e5dd7070Spatrick                        SourceLocation CategoryNameLoc)
2539e5dd7070Spatrick       : ObjCImplDecl(ObjCCategoryImpl, DC, classInterface, Id,
2540e5dd7070Spatrick                      nameLoc, atStartLoc),
2541e5dd7070Spatrick         CategoryNameLoc(CategoryNameLoc) {}
2542e5dd7070Spatrick 
2543e5dd7070Spatrick   void anchor() override;
2544e5dd7070Spatrick 
2545e5dd7070Spatrick public:
2546e5dd7070Spatrick   friend class ASTDeclReader;
2547e5dd7070Spatrick   friend class ASTDeclWriter;
2548e5dd7070Spatrick 
2549e5dd7070Spatrick   static ObjCCategoryImplDecl *Create(ASTContext &C, DeclContext *DC,
2550e5dd7070Spatrick                                       IdentifierInfo *Id,
2551e5dd7070Spatrick                                       ObjCInterfaceDecl *classInterface,
2552e5dd7070Spatrick                                       SourceLocation nameLoc,
2553e5dd7070Spatrick                                       SourceLocation atStartLoc,
2554e5dd7070Spatrick                                       SourceLocation CategoryNameLoc);
2555e5dd7070Spatrick   static ObjCCategoryImplDecl *CreateDeserialized(ASTContext &C, unsigned ID);
2556e5dd7070Spatrick 
2557e5dd7070Spatrick   ObjCCategoryDecl *getCategoryDecl() const;
2558e5dd7070Spatrick 
getCategoryNameLoc()2559e5dd7070Spatrick   SourceLocation getCategoryNameLoc() const { return CategoryNameLoc; }
2560e5dd7070Spatrick 
classof(const Decl * D)2561e5dd7070Spatrick   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
classofKind(Kind K)2562e5dd7070Spatrick   static bool classofKind(Kind K) { return K == ObjCCategoryImpl;}
2563e5dd7070Spatrick };
2564e5dd7070Spatrick 
2565e5dd7070Spatrick raw_ostream &operator<<(raw_ostream &OS, const ObjCCategoryImplDecl &CID);
2566e5dd7070Spatrick 
2567e5dd7070Spatrick /// ObjCImplementationDecl - Represents a class definition - this is where
2568e5dd7070Spatrick /// method definitions are specified. For example:
2569e5dd7070Spatrick ///
2570e5dd7070Spatrick /// @code
2571e5dd7070Spatrick /// \@implementation MyClass
2572e5dd7070Spatrick /// - (void)myMethod { /* do something */ }
2573e5dd7070Spatrick /// \@end
2574e5dd7070Spatrick /// @endcode
2575e5dd7070Spatrick ///
2576e5dd7070Spatrick /// In a non-fragile runtime, instance variables can appear in the class
2577e5dd7070Spatrick /// interface, class extensions (nameless categories), and in the implementation
2578e5dd7070Spatrick /// itself, as well as being synthesized as backing storage for properties.
2579e5dd7070Spatrick ///
2580e5dd7070Spatrick /// In a fragile runtime, instance variables are specified in the class
2581e5dd7070Spatrick /// interface, \em not in the implementation. Nevertheless (for legacy reasons),
2582e5dd7070Spatrick /// we allow instance variables to be specified in the implementation. When
2583e5dd7070Spatrick /// specified, they need to be \em identical to the interface.
2584e5dd7070Spatrick class ObjCImplementationDecl : public ObjCImplDecl {
2585e5dd7070Spatrick   /// Implementation Class's super class.
2586e5dd7070Spatrick   ObjCInterfaceDecl *SuperClass;
2587e5dd7070Spatrick   SourceLocation SuperLoc;
2588e5dd7070Spatrick 
2589e5dd7070Spatrick   /// \@implementation may have private ivars.
2590e5dd7070Spatrick   SourceLocation IvarLBraceLoc;
2591e5dd7070Spatrick   SourceLocation IvarRBraceLoc;
2592e5dd7070Spatrick 
2593e5dd7070Spatrick   /// Support for ivar initialization.
2594e5dd7070Spatrick   /// The arguments used to initialize the ivars
2595e5dd7070Spatrick   LazyCXXCtorInitializersPtr IvarInitializers;
2596e5dd7070Spatrick   unsigned NumIvarInitializers = 0;
2597e5dd7070Spatrick 
2598e5dd7070Spatrick   /// Do the ivars of this class require initialization other than
2599e5dd7070Spatrick   /// zero-initialization?
2600e5dd7070Spatrick   bool HasNonZeroConstructors : 1;
2601e5dd7070Spatrick 
2602e5dd7070Spatrick   /// Do the ivars of this class require non-trivial destruction?
2603e5dd7070Spatrick   bool HasDestructors : 1;
2604e5dd7070Spatrick 
2605e5dd7070Spatrick   ObjCImplementationDecl(DeclContext *DC,
2606e5dd7070Spatrick                          ObjCInterfaceDecl *classInterface,
2607e5dd7070Spatrick                          ObjCInterfaceDecl *superDecl,
2608e5dd7070Spatrick                          SourceLocation nameLoc, SourceLocation atStartLoc,
2609e5dd7070Spatrick                          SourceLocation superLoc = SourceLocation(),
2610e5dd7070Spatrick                          SourceLocation IvarLBraceLoc=SourceLocation(),
2611e5dd7070Spatrick                          SourceLocation IvarRBraceLoc=SourceLocation())
2612e5dd7070Spatrick       : ObjCImplDecl(ObjCImplementation, DC, classInterface,
2613e5dd7070Spatrick                      classInterface ? classInterface->getIdentifier()
2614e5dd7070Spatrick                                     : nullptr,
2615e5dd7070Spatrick                      nameLoc, atStartLoc),
2616e5dd7070Spatrick          SuperClass(superDecl), SuperLoc(superLoc),
2617e5dd7070Spatrick          IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc),
2618e5dd7070Spatrick          HasNonZeroConstructors(false), HasDestructors(false) {}
2619e5dd7070Spatrick 
2620e5dd7070Spatrick   void anchor() override;
2621e5dd7070Spatrick 
2622e5dd7070Spatrick public:
2623e5dd7070Spatrick   friend class ASTDeclReader;
2624e5dd7070Spatrick   friend class ASTDeclWriter;
2625e5dd7070Spatrick 
2626e5dd7070Spatrick   static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC,
2627e5dd7070Spatrick                                         ObjCInterfaceDecl *classInterface,
2628e5dd7070Spatrick                                         ObjCInterfaceDecl *superDecl,
2629e5dd7070Spatrick                                         SourceLocation nameLoc,
2630e5dd7070Spatrick                                         SourceLocation atStartLoc,
2631e5dd7070Spatrick                                      SourceLocation superLoc = SourceLocation(),
2632e5dd7070Spatrick                                         SourceLocation IvarLBraceLoc=SourceLocation(),
2633e5dd7070Spatrick                                         SourceLocation IvarRBraceLoc=SourceLocation());
2634e5dd7070Spatrick 
2635e5dd7070Spatrick   static ObjCImplementationDecl *CreateDeserialized(ASTContext &C, unsigned ID);
2636e5dd7070Spatrick 
2637e5dd7070Spatrick   /// init_iterator - Iterates through the ivar initializer list.
2638e5dd7070Spatrick   using init_iterator = CXXCtorInitializer **;
2639e5dd7070Spatrick 
2640e5dd7070Spatrick   /// init_const_iterator - Iterates through the ivar initializer list.
2641e5dd7070Spatrick   using init_const_iterator = CXXCtorInitializer * const *;
2642e5dd7070Spatrick 
2643e5dd7070Spatrick   using init_range = llvm::iterator_range<init_iterator>;
2644e5dd7070Spatrick   using init_const_range = llvm::iterator_range<init_const_iterator>;
2645e5dd7070Spatrick 
inits()2646e5dd7070Spatrick   init_range inits() { return init_range(init_begin(), init_end()); }
2647e5dd7070Spatrick 
inits()2648e5dd7070Spatrick   init_const_range inits() const {
2649e5dd7070Spatrick     return init_const_range(init_begin(), init_end());
2650e5dd7070Spatrick   }
2651e5dd7070Spatrick 
2652e5dd7070Spatrick   /// init_begin() - Retrieve an iterator to the first initializer.
init_begin()2653e5dd7070Spatrick   init_iterator init_begin() {
2654e5dd7070Spatrick     const auto *ConstThis = this;
2655e5dd7070Spatrick     return const_cast<init_iterator>(ConstThis->init_begin());
2656e5dd7070Spatrick   }
2657e5dd7070Spatrick 
2658e5dd7070Spatrick   /// begin() - Retrieve an iterator to the first initializer.
2659e5dd7070Spatrick   init_const_iterator init_begin() const;
2660e5dd7070Spatrick 
2661e5dd7070Spatrick   /// init_end() - Retrieve an iterator past the last initializer.
init_end()2662e5dd7070Spatrick   init_iterator       init_end()       {
2663e5dd7070Spatrick     return init_begin() + NumIvarInitializers;
2664e5dd7070Spatrick   }
2665e5dd7070Spatrick 
2666e5dd7070Spatrick   /// end() - Retrieve an iterator past the last initializer.
init_end()2667e5dd7070Spatrick   init_const_iterator init_end() const {
2668e5dd7070Spatrick     return init_begin() + NumIvarInitializers;
2669e5dd7070Spatrick   }
2670e5dd7070Spatrick 
2671e5dd7070Spatrick   /// getNumArgs - Number of ivars which must be initialized.
getNumIvarInitializers()2672e5dd7070Spatrick   unsigned getNumIvarInitializers() const {
2673e5dd7070Spatrick     return NumIvarInitializers;
2674e5dd7070Spatrick   }
2675e5dd7070Spatrick 
setNumIvarInitializers(unsigned numNumIvarInitializers)2676e5dd7070Spatrick   void setNumIvarInitializers(unsigned numNumIvarInitializers) {
2677e5dd7070Spatrick     NumIvarInitializers = numNumIvarInitializers;
2678e5dd7070Spatrick   }
2679e5dd7070Spatrick 
2680e5dd7070Spatrick   void setIvarInitializers(ASTContext &C,
2681e5dd7070Spatrick                            CXXCtorInitializer ** initializers,
2682e5dd7070Spatrick                            unsigned numInitializers);
2683e5dd7070Spatrick 
2684e5dd7070Spatrick   /// Do any of the ivars of this class (not counting its base classes)
2685e5dd7070Spatrick   /// require construction other than zero-initialization?
hasNonZeroConstructors()2686e5dd7070Spatrick   bool hasNonZeroConstructors() const { return HasNonZeroConstructors; }
setHasNonZeroConstructors(bool val)2687e5dd7070Spatrick   void setHasNonZeroConstructors(bool val) { HasNonZeroConstructors = val; }
2688e5dd7070Spatrick 
2689e5dd7070Spatrick   /// Do any of the ivars of this class (not counting its base classes)
2690e5dd7070Spatrick   /// require non-trivial destruction?
hasDestructors()2691e5dd7070Spatrick   bool hasDestructors() const { return HasDestructors; }
setHasDestructors(bool val)2692e5dd7070Spatrick   void setHasDestructors(bool val) { HasDestructors = val; }
2693e5dd7070Spatrick 
2694e5dd7070Spatrick   /// getIdentifier - Get the identifier that names the class
2695e5dd7070Spatrick   /// interface associated with this implementation.
getIdentifier()2696e5dd7070Spatrick   IdentifierInfo *getIdentifier() const {
2697e5dd7070Spatrick     return getClassInterface()->getIdentifier();
2698e5dd7070Spatrick   }
2699e5dd7070Spatrick 
2700e5dd7070Spatrick   /// getName - Get the name of identifier for the class interface associated
2701e5dd7070Spatrick   /// with this implementation as a StringRef.
2702e5dd7070Spatrick   //
2703e5dd7070Spatrick   // FIXME: This is a bad API, we are hiding NamedDecl::getName with a different
2704e5dd7070Spatrick   // meaning.
getName()2705e5dd7070Spatrick   StringRef getName() const {
2706e5dd7070Spatrick     assert(getIdentifier() && "Name is not a simple identifier");
2707e5dd7070Spatrick     return getIdentifier()->getName();
2708e5dd7070Spatrick   }
2709e5dd7070Spatrick 
2710e5dd7070Spatrick   /// Get the name of the class associated with this interface.
2711e5dd7070Spatrick   //
2712e5dd7070Spatrick   // FIXME: Move to StringRef API.
getNameAsString()2713ec727ea7Spatrick   std::string getNameAsString() const { return std::string(getName()); }
2714e5dd7070Spatrick 
2715e5dd7070Spatrick   /// Produce a name to be used for class's metadata. It comes either via
2716e5dd7070Spatrick   /// class's objc_runtime_name attribute or class name.
2717e5dd7070Spatrick   StringRef getObjCRuntimeNameAsString() const;
2718e5dd7070Spatrick 
getSuperClass()2719e5dd7070Spatrick   const ObjCInterfaceDecl *getSuperClass() const { return SuperClass; }
getSuperClass()2720e5dd7070Spatrick   ObjCInterfaceDecl *getSuperClass() { return SuperClass; }
getSuperClassLoc()2721e5dd7070Spatrick   SourceLocation getSuperClassLoc() const { return SuperLoc; }
2722e5dd7070Spatrick 
setSuperClass(ObjCInterfaceDecl * superCls)2723e5dd7070Spatrick   void setSuperClass(ObjCInterfaceDecl * superCls) { SuperClass = superCls; }
2724e5dd7070Spatrick 
setIvarLBraceLoc(SourceLocation Loc)2725e5dd7070Spatrick   void setIvarLBraceLoc(SourceLocation Loc) { IvarLBraceLoc = Loc; }
getIvarLBraceLoc()2726e5dd7070Spatrick   SourceLocation getIvarLBraceLoc() const { return IvarLBraceLoc; }
setIvarRBraceLoc(SourceLocation Loc)2727e5dd7070Spatrick   void setIvarRBraceLoc(SourceLocation Loc) { IvarRBraceLoc = Loc; }
getIvarRBraceLoc()2728e5dd7070Spatrick   SourceLocation getIvarRBraceLoc() const { return IvarRBraceLoc; }
2729e5dd7070Spatrick 
2730e5dd7070Spatrick   using ivar_iterator = specific_decl_iterator<ObjCIvarDecl>;
2731e5dd7070Spatrick   using ivar_range = llvm::iterator_range<specific_decl_iterator<ObjCIvarDecl>>;
2732e5dd7070Spatrick 
ivars()2733e5dd7070Spatrick   ivar_range ivars() const { return ivar_range(ivar_begin(), ivar_end()); }
2734e5dd7070Spatrick 
ivar_begin()2735e5dd7070Spatrick   ivar_iterator ivar_begin() const {
2736e5dd7070Spatrick     return ivar_iterator(decls_begin());
2737e5dd7070Spatrick   }
2738e5dd7070Spatrick 
ivar_end()2739e5dd7070Spatrick   ivar_iterator ivar_end() const {
2740e5dd7070Spatrick     return ivar_iterator(decls_end());
2741e5dd7070Spatrick   }
2742e5dd7070Spatrick 
ivar_size()2743e5dd7070Spatrick   unsigned ivar_size() const {
2744e5dd7070Spatrick     return std::distance(ivar_begin(), ivar_end());
2745e5dd7070Spatrick   }
2746e5dd7070Spatrick 
ivar_empty()2747e5dd7070Spatrick   bool ivar_empty() const {
2748e5dd7070Spatrick     return ivar_begin() == ivar_end();
2749e5dd7070Spatrick   }
2750e5dd7070Spatrick 
classof(const Decl * D)2751e5dd7070Spatrick   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
classofKind(Kind K)2752e5dd7070Spatrick   static bool classofKind(Kind K) { return K == ObjCImplementation; }
2753e5dd7070Spatrick };
2754e5dd7070Spatrick 
2755e5dd7070Spatrick raw_ostream &operator<<(raw_ostream &OS, const ObjCImplementationDecl &ID);
2756e5dd7070Spatrick 
2757e5dd7070Spatrick /// ObjCCompatibleAliasDecl - Represents alias of a class. This alias is
2758e5dd7070Spatrick /// declared as \@compatibility_alias alias class.
2759e5dd7070Spatrick class ObjCCompatibleAliasDecl : public NamedDecl {
2760e5dd7070Spatrick   /// Class that this is an alias of.
2761e5dd7070Spatrick   ObjCInterfaceDecl *AliasedClass;
2762e5dd7070Spatrick 
ObjCCompatibleAliasDecl(DeclContext * DC,SourceLocation L,IdentifierInfo * Id,ObjCInterfaceDecl * aliasedClass)2763e5dd7070Spatrick   ObjCCompatibleAliasDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
2764e5dd7070Spatrick                           ObjCInterfaceDecl* aliasedClass)
2765e5dd7070Spatrick       : NamedDecl(ObjCCompatibleAlias, DC, L, Id), AliasedClass(aliasedClass) {}
2766e5dd7070Spatrick 
2767e5dd7070Spatrick   void anchor() override;
2768e5dd7070Spatrick 
2769e5dd7070Spatrick public:
2770e5dd7070Spatrick   static ObjCCompatibleAliasDecl *Create(ASTContext &C, DeclContext *DC,
2771e5dd7070Spatrick                                          SourceLocation L, IdentifierInfo *Id,
2772e5dd7070Spatrick                                          ObjCInterfaceDecl* aliasedClass);
2773e5dd7070Spatrick 
2774e5dd7070Spatrick   static ObjCCompatibleAliasDecl *CreateDeserialized(ASTContext &C,
2775e5dd7070Spatrick                                                      unsigned ID);
2776e5dd7070Spatrick 
getClassInterface()2777e5dd7070Spatrick   const ObjCInterfaceDecl *getClassInterface() const { return AliasedClass; }
getClassInterface()2778e5dd7070Spatrick   ObjCInterfaceDecl *getClassInterface() { return AliasedClass; }
setClassInterface(ObjCInterfaceDecl * D)2779e5dd7070Spatrick   void setClassInterface(ObjCInterfaceDecl *D) { AliasedClass = D; }
2780e5dd7070Spatrick 
classof(const Decl * D)2781e5dd7070Spatrick   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
classofKind(Kind K)2782e5dd7070Spatrick   static bool classofKind(Kind K) { return K == ObjCCompatibleAlias; }
2783e5dd7070Spatrick };
2784e5dd7070Spatrick 
2785e5dd7070Spatrick /// ObjCPropertyImplDecl - Represents implementation declaration of a property
2786e5dd7070Spatrick /// in a class or category implementation block. For example:
2787e5dd7070Spatrick /// \@synthesize prop1 = ivar1;
2788e5dd7070Spatrick ///
2789e5dd7070Spatrick class ObjCPropertyImplDecl : public Decl {
2790e5dd7070Spatrick public:
2791e5dd7070Spatrick   enum Kind {
2792e5dd7070Spatrick     Synthesize,
2793e5dd7070Spatrick     Dynamic
2794e5dd7070Spatrick   };
2795e5dd7070Spatrick 
2796e5dd7070Spatrick private:
2797e5dd7070Spatrick   SourceLocation AtLoc;   // location of \@synthesize or \@dynamic
2798e5dd7070Spatrick 
2799e5dd7070Spatrick   /// For \@synthesize, the location of the ivar, if it was written in
2800e5dd7070Spatrick   /// the source code.
2801e5dd7070Spatrick   ///
2802e5dd7070Spatrick   /// \code
2803e5dd7070Spatrick   /// \@synthesize int a = b
2804e5dd7070Spatrick   /// \endcode
2805e5dd7070Spatrick   SourceLocation IvarLoc;
2806e5dd7070Spatrick 
2807e5dd7070Spatrick   /// Property declaration being implemented
2808e5dd7070Spatrick   ObjCPropertyDecl *PropertyDecl;
2809e5dd7070Spatrick 
2810e5dd7070Spatrick   /// Null for \@dynamic. Required for \@synthesize.
2811e5dd7070Spatrick   ObjCIvarDecl *PropertyIvarDecl;
2812e5dd7070Spatrick 
2813e5dd7070Spatrick   /// The getter's definition, which has an empty body if synthesized.
2814e5dd7070Spatrick   ObjCMethodDecl *GetterMethodDecl = nullptr;
2815e5dd7070Spatrick   /// The getter's definition, which has an empty body if synthesized.
2816e5dd7070Spatrick   ObjCMethodDecl *SetterMethodDecl = nullptr;
2817e5dd7070Spatrick 
2818e5dd7070Spatrick   /// Null for \@dynamic. Non-null if property must be copy-constructed in
2819e5dd7070Spatrick   /// getter.
2820e5dd7070Spatrick   Expr *GetterCXXConstructor = nullptr;
2821e5dd7070Spatrick 
2822e5dd7070Spatrick   /// Null for \@dynamic. Non-null if property has assignment operator to call
2823e5dd7070Spatrick   /// in Setter synthesis.
2824e5dd7070Spatrick   Expr *SetterCXXAssignment = nullptr;
2825e5dd7070Spatrick 
ObjCPropertyImplDecl(DeclContext * DC,SourceLocation atLoc,SourceLocation L,ObjCPropertyDecl * property,Kind PK,ObjCIvarDecl * ivarDecl,SourceLocation ivarLoc)2826e5dd7070Spatrick   ObjCPropertyImplDecl(DeclContext *DC, SourceLocation atLoc, SourceLocation L,
2827e5dd7070Spatrick                        ObjCPropertyDecl *property,
2828e5dd7070Spatrick                        Kind PK,
2829e5dd7070Spatrick                        ObjCIvarDecl *ivarDecl,
2830e5dd7070Spatrick                        SourceLocation ivarLoc)
2831e5dd7070Spatrick       : Decl(ObjCPropertyImpl, DC, L), AtLoc(atLoc),
2832e5dd7070Spatrick         IvarLoc(ivarLoc), PropertyDecl(property), PropertyIvarDecl(ivarDecl) {
2833e5dd7070Spatrick     assert(PK == Dynamic || PropertyIvarDecl);
2834e5dd7070Spatrick   }
2835e5dd7070Spatrick 
2836e5dd7070Spatrick public:
2837e5dd7070Spatrick   friend class ASTDeclReader;
2838e5dd7070Spatrick 
2839e5dd7070Spatrick   static ObjCPropertyImplDecl *Create(ASTContext &C, DeclContext *DC,
2840e5dd7070Spatrick                                       SourceLocation atLoc, SourceLocation L,
2841e5dd7070Spatrick                                       ObjCPropertyDecl *property,
2842e5dd7070Spatrick                                       Kind PK,
2843e5dd7070Spatrick                                       ObjCIvarDecl *ivarDecl,
2844e5dd7070Spatrick                                       SourceLocation ivarLoc);
2845e5dd7070Spatrick 
2846e5dd7070Spatrick   static ObjCPropertyImplDecl *CreateDeserialized(ASTContext &C, unsigned ID);
2847e5dd7070Spatrick 
2848e5dd7070Spatrick   SourceRange getSourceRange() const override LLVM_READONLY;
2849e5dd7070Spatrick 
getBeginLoc()2850e5dd7070Spatrick   SourceLocation getBeginLoc() const LLVM_READONLY { return AtLoc; }
setAtLoc(SourceLocation Loc)2851e5dd7070Spatrick   void setAtLoc(SourceLocation Loc) { AtLoc = Loc; }
2852e5dd7070Spatrick 
getPropertyDecl()2853e5dd7070Spatrick   ObjCPropertyDecl *getPropertyDecl() const {
2854e5dd7070Spatrick     return PropertyDecl;
2855e5dd7070Spatrick   }
setPropertyDecl(ObjCPropertyDecl * Prop)2856e5dd7070Spatrick   void setPropertyDecl(ObjCPropertyDecl *Prop) { PropertyDecl = Prop; }
2857e5dd7070Spatrick 
getPropertyImplementation()2858e5dd7070Spatrick   Kind getPropertyImplementation() const {
2859e5dd7070Spatrick     return PropertyIvarDecl ? Synthesize : Dynamic;
2860e5dd7070Spatrick   }
2861e5dd7070Spatrick 
getPropertyIvarDecl()2862e5dd7070Spatrick   ObjCIvarDecl *getPropertyIvarDecl() const {
2863e5dd7070Spatrick     return PropertyIvarDecl;
2864e5dd7070Spatrick   }
getPropertyIvarDeclLoc()2865e5dd7070Spatrick   SourceLocation getPropertyIvarDeclLoc() const { return IvarLoc; }
2866e5dd7070Spatrick 
setPropertyIvarDecl(ObjCIvarDecl * Ivar,SourceLocation IvarLoc)2867e5dd7070Spatrick   void setPropertyIvarDecl(ObjCIvarDecl *Ivar,
2868e5dd7070Spatrick                            SourceLocation IvarLoc) {
2869e5dd7070Spatrick     PropertyIvarDecl = Ivar;
2870e5dd7070Spatrick     this->IvarLoc = IvarLoc;
2871e5dd7070Spatrick   }
2872e5dd7070Spatrick 
2873e5dd7070Spatrick   /// For \@synthesize, returns true if an ivar name was explicitly
2874e5dd7070Spatrick   /// specified.
2875e5dd7070Spatrick   ///
2876e5dd7070Spatrick   /// \code
2877e5dd7070Spatrick   /// \@synthesize int a = b; // true
2878e5dd7070Spatrick   /// \@synthesize int a; // false
2879e5dd7070Spatrick   /// \endcode
isIvarNameSpecified()2880e5dd7070Spatrick   bool isIvarNameSpecified() const {
2881e5dd7070Spatrick     return IvarLoc.isValid() && IvarLoc != getLocation();
2882e5dd7070Spatrick   }
2883e5dd7070Spatrick 
getGetterMethodDecl()2884e5dd7070Spatrick   ObjCMethodDecl *getGetterMethodDecl() const { return GetterMethodDecl; }
setGetterMethodDecl(ObjCMethodDecl * MD)2885e5dd7070Spatrick   void setGetterMethodDecl(ObjCMethodDecl *MD) { GetterMethodDecl = MD; }
2886e5dd7070Spatrick 
getSetterMethodDecl()2887e5dd7070Spatrick   ObjCMethodDecl *getSetterMethodDecl() const { return SetterMethodDecl; }
setSetterMethodDecl(ObjCMethodDecl * MD)2888e5dd7070Spatrick   void setSetterMethodDecl(ObjCMethodDecl *MD) { SetterMethodDecl = MD; }
2889e5dd7070Spatrick 
getGetterCXXConstructor()2890e5dd7070Spatrick   Expr *getGetterCXXConstructor() const {
2891e5dd7070Spatrick     return GetterCXXConstructor;
2892e5dd7070Spatrick   }
2893e5dd7070Spatrick 
setGetterCXXConstructor(Expr * getterCXXConstructor)2894e5dd7070Spatrick   void setGetterCXXConstructor(Expr *getterCXXConstructor) {
2895e5dd7070Spatrick     GetterCXXConstructor = getterCXXConstructor;
2896e5dd7070Spatrick   }
2897e5dd7070Spatrick 
getSetterCXXAssignment()2898e5dd7070Spatrick   Expr *getSetterCXXAssignment() const {
2899e5dd7070Spatrick     return SetterCXXAssignment;
2900e5dd7070Spatrick   }
2901e5dd7070Spatrick 
setSetterCXXAssignment(Expr * setterCXXAssignment)2902e5dd7070Spatrick   void setSetterCXXAssignment(Expr *setterCXXAssignment) {
2903e5dd7070Spatrick     SetterCXXAssignment = setterCXXAssignment;
2904e5dd7070Spatrick   }
2905e5dd7070Spatrick 
classof(const Decl * D)2906e5dd7070Spatrick   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
classofKind(Decl::Kind K)2907e5dd7070Spatrick   static bool classofKind(Decl::Kind K) { return K == ObjCPropertyImpl; }
2908e5dd7070Spatrick };
2909e5dd7070Spatrick 
2910e5dd7070Spatrick template<bool (*Filter)(ObjCCategoryDecl *)>
2911e5dd7070Spatrick void
2912e5dd7070Spatrick ObjCInterfaceDecl::filtered_category_iterator<Filter>::
findAcceptableCategory()2913e5dd7070Spatrick findAcceptableCategory() {
2914e5dd7070Spatrick   while (Current && !Filter(Current))
2915e5dd7070Spatrick     Current = Current->getNextClassCategoryRaw();
2916e5dd7070Spatrick }
2917e5dd7070Spatrick 
2918e5dd7070Spatrick template<bool (*Filter)(ObjCCategoryDecl *)>
2919e5dd7070Spatrick inline ObjCInterfaceDecl::filtered_category_iterator<Filter> &
2920e5dd7070Spatrick ObjCInterfaceDecl::filtered_category_iterator<Filter>::operator++() {
2921e5dd7070Spatrick   Current = Current->getNextClassCategoryRaw();
2922e5dd7070Spatrick   findAcceptableCategory();
2923e5dd7070Spatrick   return *this;
2924e5dd7070Spatrick }
2925e5dd7070Spatrick 
isVisibleCategory(ObjCCategoryDecl * Cat)2926e5dd7070Spatrick inline bool ObjCInterfaceDecl::isVisibleCategory(ObjCCategoryDecl *Cat) {
2927*12c85518Srobert   return !Cat->isInvalidDecl() && Cat->isUnconditionallyVisible();
2928e5dd7070Spatrick }
2929e5dd7070Spatrick 
isVisibleExtension(ObjCCategoryDecl * Cat)2930e5dd7070Spatrick inline bool ObjCInterfaceDecl::isVisibleExtension(ObjCCategoryDecl *Cat) {
2931*12c85518Srobert   return !Cat->isInvalidDecl() && Cat->IsClassExtension() &&
2932*12c85518Srobert          Cat->isUnconditionallyVisible();
2933e5dd7070Spatrick }
2934e5dd7070Spatrick 
isKnownExtension(ObjCCategoryDecl * Cat)2935e5dd7070Spatrick inline bool ObjCInterfaceDecl::isKnownExtension(ObjCCategoryDecl *Cat) {
2936*12c85518Srobert   return !Cat->isInvalidDecl() && Cat->IsClassExtension();
2937e5dd7070Spatrick }
2938e5dd7070Spatrick 
2939e5dd7070Spatrick } // namespace clang
2940e5dd7070Spatrick 
2941e5dd7070Spatrick #endif // LLVM_CLANG_AST_DECLOBJC_H
2942