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