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
26using namespace clang;
27
28ObjCArrayLiteral::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(this));
37}
38
39ObjCArrayLiteral *ObjCArrayLiteral::Create(const ASTContext &C,
40                                           ArrayRef<Expr *> Elements,
41                                           QualType T, ObjCMethodDecl *Method,
42                                           SourceRange SR) {
43  void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(Elements.size()));
44  return new (Mem) ObjCArrayLiteral(Elements, T, Method, SR);
45}
46
47ObjCArrayLiteral *ObjCArrayLiteral::CreateEmpty(const ASTContext &C,
48                                                unsigned NumElements) {
49  void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(NumElements));
50  return new (Mem) ObjCArrayLiteral(EmptyShell(), NumElements);
51}
52
53ObjCDictionaryLiteral::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(this));
75}
76
77ObjCDictionaryLiteral *
78ObjCDictionaryLiteral::Create(const ASTContext &C,
79                              ArrayRef<ObjCDictionaryElement> VK,
80                              bool HasPackExpansions, QualType T,
81                              ObjCMethodDecl *method, SourceRange SR) {
82  void *Mem = C.Allocate(totalSizeToAlloc<KeyValuePair, ExpansionData>(
83      VK.size(), HasPackExpansions ? VK.size() : 0));
84  return new (Mem) ObjCDictionaryLiteral(VK, HasPackExpansions, T, method, SR);
85}
86
87ObjCDictionaryLiteral *
88ObjCDictionaryLiteral::CreateEmpty(const ASTContext &C, unsigned NumElements,
89                                   bool HasPackExpansions) {
90  void *Mem = C.Allocate(totalSizeToAlloc<KeyValuePair, ExpansionData>(
91      NumElements, HasPackExpansions ? NumElements : 0));
92  return new (Mem)
93      ObjCDictionaryLiteral(EmptyShell(), NumElements, HasPackExpansions);
94}
95
96QualType ObjCPropertyRefExpr::getReceiverType(const ASTContext &ctx) const {
97  if (isClassReceiver())
98    return ctx.getObjCInterfaceType(getClassReceiver());
99
100  if (isSuperReceiver())
101    return getSuperReceiverType();
102
103  return getBase()->getType();
104}
105
106ObjCMessageExpr::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(this));
124}
125
126ObjCMessageExpr::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(this));
141}
142
143ObjCMessageExpr::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(this));
157}
158
159void 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(SelLocs.begin(), SelLocs.end(), getStoredSelLocs());
171  }
172}
173
174ObjCMessageExpr *
175ObjCMessageExpr::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(Context, Args.size(), 0);
187  else
188    Mem = alloc(Context, Args, 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
194ObjCMessageExpr *
195ObjCMessageExpr::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(Context, Args.size(), 0);
206  else
207    Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK);
208  return new (Mem)
209      ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel, SelLocs, SelLocsK, Method,
210                      Args, RBracLoc, isImplicit);
211}
212
213ObjCMessageExpr *
214ObjCMessageExpr::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(Context, Args.size(), 0);
225  else
226    Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK);
227  return new (Mem)
228      ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel, SelLocs, SelLocsK, Method,
229                      Args, RBracLoc, isImplicit);
230}
231
232ObjCMessageExpr *ObjCMessageExpr::CreateEmpty(const ASTContext &Context,
233                                              unsigned NumArgs,
234                                              unsigned NumStoredSelLocs) {
235  ObjCMessageExpr *Mem = alloc(Context, NumArgs, NumStoredSelLocs);
236  return new (Mem) ObjCMessageExpr(EmptyShell(), NumArgs);
237}
238
239ObjCMessageExpr *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, RBraceLoc);
246  unsigned NumStoredSelLocs =
247      (SelLocsK == SelLoc_NonStandard) ? SelLocs.size() : 0;
248  return alloc(C, Args.size(), NumStoredSelLocs);
249}
250
251ObjCMessageExpr *ObjCMessageExpr::alloc(const ASTContext &C, unsigned NumArgs,
252                                        unsigned NumStoredSelLocs) {
253  return (ObjCMessageExpr *)C.Allocate(
254      totalSizeToAlloc<void *, SourceLocation>(NumArgs + 1, NumStoredSelLocs),
255      alignof(ObjCMessageExpr));
256}
257
258void ObjCMessageExpr::getSelectorLocs(
259    SmallVectorImpl<SourceLocation> &SelLocs) const {
260  for (unsigned i = 0, e = getNumSelectorLocs(); i != e; ++i)
261    SelLocs.push_back(getSelectorLoc(i));
262}
263
264
265QualType 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
277SourceRange 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
293Selector ObjCMessageExpr::getSelector() const {
294  if (HasMethod)
295    return reinterpret_cast<const ObjCMethodDecl *>(SelectorOrMethod)
296        ->getSelector();
297  return Selector(SelectorOrMethod);
298}
299
300QualType 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
314ObjCInterfaceDecl *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
326Stmt::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
336Stmt::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
341StringRef 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