1 | //===- ExprObjC.cpp - (ObjC) Expression AST Node Implementation -----------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file implements the subclesses of Expr class declared in ExprObjC.h |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "clang/AST/ExprObjC.h" |
14 | #include "clang/AST/ASTContext.h" |
15 | #include "clang/AST/ComputeDependence.h" |
16 | #include "clang/AST/SelectorLocationsKind.h" |
17 | #include "clang/AST/Type.h" |
18 | #include "clang/AST/TypeLoc.h" |
19 | #include "llvm/Support/ErrorHandling.h" |
20 | #include <cassert> |
21 | #include <cstdint> |
22 | |
23 | using namespace clang; |
24 | |
25 | ObjCArrayLiteral::ObjCArrayLiteral(ArrayRef<Expr *> Elements, QualType T, |
26 | ObjCMethodDecl *Method, SourceRange SR) |
27 | : Expr(ObjCArrayLiteralClass, T, VK_PRValue, OK_Ordinary), |
28 | NumElements(Elements.size()), Range(SR), ArrayWithObjectsMethod(Method) { |
29 | Expr **SaveElements = getElements(); |
30 | for (unsigned I = 0, N = Elements.size(); I != N; ++I) |
31 | SaveElements[I] = Elements[I]; |
32 | |
33 | setDependence(computeDependence(E: this)); |
34 | } |
35 | |
36 | ObjCArrayLiteral *ObjCArrayLiteral::Create(const ASTContext &C, |
37 | ArrayRef<Expr *> Elements, |
38 | QualType T, ObjCMethodDecl *Method, |
39 | SourceRange SR) { |
40 | void *Mem = C.Allocate(Size: totalSizeToAlloc<Expr *>(Counts: Elements.size())); |
41 | return new (Mem) ObjCArrayLiteral(Elements, T, Method, SR); |
42 | } |
43 | |
44 | ObjCArrayLiteral *ObjCArrayLiteral::CreateEmpty(const ASTContext &C, |
45 | unsigned NumElements) { |
46 | void *Mem = C.Allocate(Size: totalSizeToAlloc<Expr *>(Counts: NumElements)); |
47 | return new (Mem) ObjCArrayLiteral(EmptyShell(), NumElements); |
48 | } |
49 | |
50 | ObjCDictionaryLiteral::ObjCDictionaryLiteral(ArrayRef<ObjCDictionaryElement> VK, |
51 | bool HasPackExpansions, QualType T, |
52 | ObjCMethodDecl *method, |
53 | SourceRange SR) |
54 | : Expr(ObjCDictionaryLiteralClass, T, VK_PRValue, OK_Ordinary), |
55 | NumElements(VK.size()), HasPackExpansions(HasPackExpansions), Range(SR), |
56 | DictWithObjectsMethod(method) { |
57 | KeyValuePair *KeyValues = getTrailingObjects<KeyValuePair>(); |
58 | ExpansionData *Expansions = |
59 | HasPackExpansions ? getTrailingObjects<ExpansionData>() : nullptr; |
60 | for (unsigned I = 0; I < NumElements; I++) { |
61 | KeyValues[I].Key = VK[I].Key; |
62 | KeyValues[I].Value = VK[I].Value; |
63 | if (Expansions) { |
64 | Expansions[I].EllipsisLoc = VK[I].EllipsisLoc; |
65 | if (VK[I].NumExpansions) |
66 | Expansions[I].NumExpansionsPlusOne = *VK[I].NumExpansions + 1; |
67 | else |
68 | Expansions[I].NumExpansionsPlusOne = 0; |
69 | } |
70 | } |
71 | setDependence(computeDependence(E: this)); |
72 | } |
73 | |
74 | ObjCDictionaryLiteral * |
75 | ObjCDictionaryLiteral::Create(const ASTContext &C, |
76 | ArrayRef<ObjCDictionaryElement> VK, |
77 | bool HasPackExpansions, QualType T, |
78 | ObjCMethodDecl *method, SourceRange SR) { |
79 | void *Mem = C.Allocate(Size: totalSizeToAlloc<KeyValuePair, ExpansionData>( |
80 | Counts: VK.size(), Counts: HasPackExpansions ? VK.size() : 0)); |
81 | return new (Mem) ObjCDictionaryLiteral(VK, HasPackExpansions, T, method, SR); |
82 | } |
83 | |
84 | ObjCDictionaryLiteral * |
85 | ObjCDictionaryLiteral::CreateEmpty(const ASTContext &C, unsigned NumElements, |
86 | bool HasPackExpansions) { |
87 | void *Mem = C.Allocate(Size: totalSizeToAlloc<KeyValuePair, ExpansionData>( |
88 | Counts: NumElements, Counts: HasPackExpansions ? NumElements : 0)); |
89 | return new (Mem) |
90 | ObjCDictionaryLiteral(EmptyShell(), NumElements, HasPackExpansions); |
91 | } |
92 | |
93 | QualType ObjCPropertyRefExpr::getReceiverType(const ASTContext &ctx) const { |
94 | if (isClassReceiver()) |
95 | return ctx.getObjCInterfaceType(Decl: getClassReceiver()); |
96 | |
97 | if (isSuperReceiver()) |
98 | return getSuperReceiverType(); |
99 | |
100 | return getBase()->getType(); |
101 | } |
102 | |
103 | ObjCMessageExpr::ObjCMessageExpr(QualType T, ExprValueKind VK, |
104 | SourceLocation LBracLoc, |
105 | SourceLocation SuperLoc, bool IsInstanceSuper, |
106 | QualType SuperType, Selector Sel, |
107 | ArrayRef<SourceLocation> SelLocs, |
108 | SelectorLocationsKind SelLocsK, |
109 | ObjCMethodDecl *Method, ArrayRef<Expr *> Args, |
110 | SourceLocation RBracLoc, bool isImplicit) |
111 | : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary), |
112 | SelectorOrMethod( |
113 | reinterpret_cast<uintptr_t>(Method ? Method : Sel.getAsOpaquePtr())), |
114 | Kind(IsInstanceSuper ? SuperInstance : SuperClass), |
115 | HasMethod(Method != nullptr), IsDelegateInitCall(false), |
116 | IsImplicit(isImplicit), SuperLoc(SuperLoc), LBracLoc(LBracLoc), |
117 | RBracLoc(RBracLoc) { |
118 | initArgsAndSelLocs(Args, SelLocs, SelLocsK); |
119 | setReceiverPointer(SuperType.getAsOpaquePtr()); |
120 | setDependence(computeDependence(E: this)); |
121 | } |
122 | |
123 | ObjCMessageExpr::ObjCMessageExpr(QualType T, ExprValueKind VK, |
124 | SourceLocation LBracLoc, |
125 | TypeSourceInfo *Receiver, Selector Sel, |
126 | ArrayRef<SourceLocation> SelLocs, |
127 | SelectorLocationsKind SelLocsK, |
128 | ObjCMethodDecl *Method, ArrayRef<Expr *> Args, |
129 | SourceLocation RBracLoc, bool isImplicit) |
130 | : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary), |
131 | SelectorOrMethod( |
132 | reinterpret_cast<uintptr_t>(Method ? Method : Sel.getAsOpaquePtr())), |
133 | Kind(Class), HasMethod(Method != nullptr), IsDelegateInitCall(false), |
134 | IsImplicit(isImplicit), LBracLoc(LBracLoc), RBracLoc(RBracLoc) { |
135 | initArgsAndSelLocs(Args, SelLocs, SelLocsK); |
136 | setReceiverPointer(Receiver); |
137 | setDependence(computeDependence(E: this)); |
138 | } |
139 | |
140 | ObjCMessageExpr::ObjCMessageExpr(QualType T, ExprValueKind VK, |
141 | SourceLocation LBracLoc, Expr *Receiver, |
142 | Selector Sel, ArrayRef<SourceLocation> SelLocs, |
143 | SelectorLocationsKind SelLocsK, |
144 | ObjCMethodDecl *Method, ArrayRef<Expr *> Args, |
145 | SourceLocation RBracLoc, bool isImplicit) |
146 | : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary), |
147 | SelectorOrMethod( |
148 | reinterpret_cast<uintptr_t>(Method ? Method : Sel.getAsOpaquePtr())), |
149 | Kind(Instance), HasMethod(Method != nullptr), IsDelegateInitCall(false), |
150 | IsImplicit(isImplicit), LBracLoc(LBracLoc), RBracLoc(RBracLoc) { |
151 | initArgsAndSelLocs(Args, SelLocs, SelLocsK); |
152 | setReceiverPointer(Receiver); |
153 | setDependence(computeDependence(E: this)); |
154 | } |
155 | |
156 | void ObjCMessageExpr::initArgsAndSelLocs(ArrayRef<Expr *> Args, |
157 | ArrayRef<SourceLocation> SelLocs, |
158 | SelectorLocationsKind SelLocsK) { |
159 | setNumArgs(Args.size()); |
160 | Expr **MyArgs = getArgs(); |
161 | for (unsigned I = 0; I != Args.size(); ++I) |
162 | MyArgs[I] = Args[I]; |
163 | |
164 | SelLocsKind = SelLocsK; |
165 | if (!isImplicit() && SelLocsK == SelLoc_NonStandard) |
166 | llvm::copy(Range&: SelLocs, Out: getStoredSelLocs()); |
167 | } |
168 | |
169 | ObjCMessageExpr * |
170 | ObjCMessageExpr::Create(const ASTContext &Context, QualType T, ExprValueKind VK, |
171 | SourceLocation LBracLoc, SourceLocation SuperLoc, |
172 | bool IsInstanceSuper, QualType SuperType, Selector Sel, |
173 | ArrayRef<SourceLocation> SelLocs, |
174 | ObjCMethodDecl *Method, ArrayRef<Expr *> Args, |
175 | SourceLocation RBracLoc, bool isImplicit) { |
176 | assert((!SelLocs.empty() || isImplicit) && |
177 | "No selector locs for non-implicit message" ); |
178 | ObjCMessageExpr *Mem; |
179 | SelectorLocationsKind SelLocsK = SelectorLocationsKind(); |
180 | if (isImplicit) |
181 | Mem = alloc(C: Context, NumArgs: Args.size(), NumStoredSelLocs: 0); |
182 | else |
183 | Mem = alloc(C: Context, Args, RBraceLoc: RBracLoc, SelLocs, Sel, SelLocsK); |
184 | return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, SuperLoc, IsInstanceSuper, |
185 | SuperType, Sel, SelLocs, SelLocsK, Method, |
186 | Args, RBracLoc, isImplicit); |
187 | } |
188 | |
189 | ObjCMessageExpr * |
190 | ObjCMessageExpr::Create(const ASTContext &Context, QualType T, ExprValueKind VK, |
191 | SourceLocation LBracLoc, TypeSourceInfo *Receiver, |
192 | Selector Sel, ArrayRef<SourceLocation> SelLocs, |
193 | ObjCMethodDecl *Method, ArrayRef<Expr *> Args, |
194 | SourceLocation RBracLoc, bool isImplicit) { |
195 | assert((!SelLocs.empty() || isImplicit) && |
196 | "No selector locs for non-implicit message" ); |
197 | ObjCMessageExpr *Mem; |
198 | SelectorLocationsKind SelLocsK = SelectorLocationsKind(); |
199 | if (isImplicit) |
200 | Mem = alloc(C: Context, NumArgs: Args.size(), NumStoredSelLocs: 0); |
201 | else |
202 | Mem = alloc(C: Context, Args, RBraceLoc: RBracLoc, SelLocs, Sel, SelLocsK); |
203 | return new (Mem) |
204 | ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel, SelLocs, SelLocsK, Method, |
205 | Args, RBracLoc, isImplicit); |
206 | } |
207 | |
208 | ObjCMessageExpr * |
209 | ObjCMessageExpr::Create(const ASTContext &Context, QualType T, ExprValueKind VK, |
210 | SourceLocation LBracLoc, Expr *Receiver, Selector Sel, |
211 | ArrayRef<SourceLocation> SelLocs, |
212 | ObjCMethodDecl *Method, ArrayRef<Expr *> Args, |
213 | SourceLocation RBracLoc, bool isImplicit) { |
214 | assert((!SelLocs.empty() || isImplicit) && |
215 | "No selector locs for non-implicit message" ); |
216 | ObjCMessageExpr *Mem; |
217 | SelectorLocationsKind SelLocsK = SelectorLocationsKind(); |
218 | if (isImplicit) |
219 | Mem = alloc(C: Context, NumArgs: Args.size(), NumStoredSelLocs: 0); |
220 | else |
221 | Mem = alloc(C: Context, Args, RBraceLoc: RBracLoc, SelLocs, Sel, SelLocsK); |
222 | return new (Mem) |
223 | ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel, SelLocs, SelLocsK, Method, |
224 | Args, RBracLoc, isImplicit); |
225 | } |
226 | |
227 | ObjCMessageExpr *ObjCMessageExpr::CreateEmpty(const ASTContext &Context, |
228 | unsigned NumArgs, |
229 | unsigned NumStoredSelLocs) { |
230 | ObjCMessageExpr *Mem = alloc(C: Context, NumArgs, NumStoredSelLocs); |
231 | return new (Mem) ObjCMessageExpr(EmptyShell(), NumArgs); |
232 | } |
233 | |
234 | ObjCMessageExpr *ObjCMessageExpr::alloc(const ASTContext &C, |
235 | ArrayRef<Expr *> Args, |
236 | SourceLocation RBraceLoc, |
237 | ArrayRef<SourceLocation> SelLocs, |
238 | Selector Sel, |
239 | SelectorLocationsKind &SelLocsK) { |
240 | SelLocsK = hasStandardSelectorLocs(Sel, SelLocs, Args, EndLoc: RBraceLoc); |
241 | unsigned NumStoredSelLocs = |
242 | (SelLocsK == SelLoc_NonStandard) ? SelLocs.size() : 0; |
243 | return alloc(C, NumArgs: Args.size(), NumStoredSelLocs); |
244 | } |
245 | |
246 | ObjCMessageExpr *ObjCMessageExpr::alloc(const ASTContext &C, unsigned NumArgs, |
247 | unsigned NumStoredSelLocs) { |
248 | return (ObjCMessageExpr *)C.Allocate( |
249 | Size: totalSizeToAlloc<void *, SourceLocation>(Counts: NumArgs + 1, Counts: NumStoredSelLocs), |
250 | Align: alignof(ObjCMessageExpr)); |
251 | } |
252 | |
253 | void ObjCMessageExpr::getSelectorLocs( |
254 | SmallVectorImpl<SourceLocation> &SelLocs) const { |
255 | for (unsigned i = 0, e = getNumSelectorLocs(); i != e; ++i) |
256 | SelLocs.push_back(Elt: getSelectorLoc(Index: i)); |
257 | } |
258 | |
259 | |
260 | QualType ObjCMessageExpr::getCallReturnType(ASTContext &Ctx) const { |
261 | if (const ObjCMethodDecl *MD = getMethodDecl()) { |
262 | QualType QT = MD->getReturnType(); |
263 | if (QT == Ctx.getObjCInstanceType()) { |
264 | // instancetype corresponds to expression types. |
265 | return getType(); |
266 | } |
267 | return QT; |
268 | } |
269 | return Ctx.getReferenceQualifiedType(e: this); |
270 | } |
271 | |
272 | SourceRange ObjCMessageExpr::getReceiverRange() const { |
273 | switch (getReceiverKind()) { |
274 | case Instance: |
275 | return getInstanceReceiver()->getSourceRange(); |
276 | |
277 | case Class: |
278 | return getClassReceiverTypeInfo()->getTypeLoc().getSourceRange(); |
279 | |
280 | case SuperInstance: |
281 | case SuperClass: |
282 | return getSuperLoc(); |
283 | } |
284 | |
285 | llvm_unreachable("Invalid ReceiverKind!" ); |
286 | } |
287 | |
288 | Selector ObjCMessageExpr::getSelector() const { |
289 | if (HasMethod) |
290 | return reinterpret_cast<const ObjCMethodDecl *>(SelectorOrMethod) |
291 | ->getSelector(); |
292 | return Selector(SelectorOrMethod); |
293 | } |
294 | |
295 | QualType ObjCMessageExpr::getReceiverType() const { |
296 | switch (getReceiverKind()) { |
297 | case Instance: |
298 | return getInstanceReceiver()->getType(); |
299 | case Class: |
300 | return getClassReceiver(); |
301 | case SuperInstance: |
302 | case SuperClass: |
303 | return getSuperType(); |
304 | } |
305 | |
306 | llvm_unreachable("unexpected receiver kind" ); |
307 | } |
308 | |
309 | ObjCInterfaceDecl *ObjCMessageExpr::getReceiverInterface() const { |
310 | QualType T = getReceiverType(); |
311 | |
312 | if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>()) |
313 | return Ptr->getInterfaceDecl(); |
314 | |
315 | if (const ObjCObjectType *Ty = T->getAs<ObjCObjectType>()) |
316 | return Ty->getInterface(); |
317 | |
318 | return nullptr; |
319 | } |
320 | |
321 | Stmt::child_range ObjCMessageExpr::children() { |
322 | Stmt **begin; |
323 | if (getReceiverKind() == Instance) |
324 | begin = reinterpret_cast<Stmt **>(getTrailingObjects<void *>()); |
325 | else |
326 | begin = reinterpret_cast<Stmt **>(getArgs()); |
327 | return child_range(begin, |
328 | reinterpret_cast<Stmt **>(getArgs() + getNumArgs())); |
329 | } |
330 | |
331 | Stmt::const_child_range ObjCMessageExpr::children() const { |
332 | auto Children = const_cast<ObjCMessageExpr *>(this)->children(); |
333 | return const_child_range(Children.begin(), Children.end()); |
334 | } |
335 | |
336 | StringRef ObjCBridgedCastExpr::getBridgeKindName() const { |
337 | switch (getBridgeKind()) { |
338 | case OBC_Bridge: |
339 | return "__bridge" ; |
340 | case OBC_BridgeTransfer: |
341 | return "__bridge_transfer" ; |
342 | case OBC_BridgeRetained: |
343 | return "__bridge_retained" ; |
344 | } |
345 | |
346 | llvm_unreachable("Invalid BridgeKind!" ); |
347 | } |
348 | |