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