diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/AST/ExprObjC.cpp')
| -rw-r--r-- | contrib/llvm-project/clang/lib/AST/ExprObjC.cpp | 396 |
1 files changed, 396 insertions, 0 deletions
diff --git a/contrib/llvm-project/clang/lib/AST/ExprObjC.cpp b/contrib/llvm-project/clang/lib/AST/ExprObjC.cpp new file mode 100644 index 000000000000..53d0e873f8c9 --- /dev/null +++ b/contrib/llvm-project/clang/lib/AST/ExprObjC.cpp @@ -0,0 +1,396 @@ +//===- ExprObjC.cpp - (ObjC) Expression AST Node Implementation -----------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements the subclesses of Expr class declared in ExprObjC.h +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/ExprObjC.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/SelectorLocationsKind.h" +#include "clang/AST/Type.h" +#include "clang/AST/TypeLoc.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/ErrorHandling.h" +#include <algorithm> +#include <cassert> +#include <cstdint> + +using namespace clang; + +ObjCArrayLiteral::ObjCArrayLiteral(ArrayRef<Expr *> Elements, QualType T, + ObjCMethodDecl *Method, SourceRange SR) + : Expr(ObjCArrayLiteralClass, T, VK_RValue, OK_Ordinary, false, false, + false, false), + NumElements(Elements.size()), Range(SR), ArrayWithObjectsMethod(Method) { + Expr **SaveElements = getElements(); + for (unsigned I = 0, N = Elements.size(); I != N; ++I) { + if (Elements[I]->isTypeDependent() || Elements[I]->isValueDependent()) + ExprBits.ValueDependent = true; + if (Elements[I]->isInstantiationDependent()) + ExprBits.InstantiationDependent = true; + if (Elements[I]->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; + + SaveElements[I] = Elements[I]; + } +} + +ObjCArrayLiteral *ObjCArrayLiteral::Create(const ASTContext &C, + ArrayRef<Expr *> Elements, + QualType T, ObjCMethodDecl *Method, + SourceRange SR) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(Elements.size())); + return new (Mem) ObjCArrayLiteral(Elements, T, Method, SR); +} + +ObjCArrayLiteral *ObjCArrayLiteral::CreateEmpty(const ASTContext &C, + unsigned NumElements) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(NumElements)); + return new (Mem) ObjCArrayLiteral(EmptyShell(), NumElements); +} + +ObjCDictionaryLiteral::ObjCDictionaryLiteral(ArrayRef<ObjCDictionaryElement> VK, + bool HasPackExpansions, QualType T, + ObjCMethodDecl *method, + SourceRange SR) + : Expr(ObjCDictionaryLiteralClass, T, VK_RValue, OK_Ordinary, false, false, + false, false), + NumElements(VK.size()), HasPackExpansions(HasPackExpansions), Range(SR), + DictWithObjectsMethod(method) { + KeyValuePair *KeyValues = getTrailingObjects<KeyValuePair>(); + ExpansionData *Expansions = + HasPackExpansions ? getTrailingObjects<ExpansionData>() : nullptr; + for (unsigned I = 0; I < NumElements; I++) { + if (VK[I].Key->isTypeDependent() || VK[I].Key->isValueDependent() || + VK[I].Value->isTypeDependent() || VK[I].Value->isValueDependent()) + ExprBits.ValueDependent = true; + if (VK[I].Key->isInstantiationDependent() || + VK[I].Value->isInstantiationDependent()) + ExprBits.InstantiationDependent = true; + if (VK[I].EllipsisLoc.isInvalid() && + (VK[I].Key->containsUnexpandedParameterPack() || + VK[I].Value->containsUnexpandedParameterPack())) + ExprBits.ContainsUnexpandedParameterPack = true; + + KeyValues[I].Key = VK[I].Key; + KeyValues[I].Value = VK[I].Value; + if (Expansions) { + Expansions[I].EllipsisLoc = VK[I].EllipsisLoc; + if (VK[I].NumExpansions) + Expansions[I].NumExpansionsPlusOne = *VK[I].NumExpansions + 1; + else + Expansions[I].NumExpansionsPlusOne = 0; + } + } +} + +ObjCDictionaryLiteral * +ObjCDictionaryLiteral::Create(const ASTContext &C, + ArrayRef<ObjCDictionaryElement> VK, + bool HasPackExpansions, QualType T, + ObjCMethodDecl *method, SourceRange SR) { + void *Mem = C.Allocate(totalSizeToAlloc<KeyValuePair, ExpansionData>( + VK.size(), HasPackExpansions ? VK.size() : 0)); + return new (Mem) ObjCDictionaryLiteral(VK, HasPackExpansions, T, method, SR); +} + +ObjCDictionaryLiteral * +ObjCDictionaryLiteral::CreateEmpty(const ASTContext &C, unsigned NumElements, + bool HasPackExpansions) { + void *Mem = C.Allocate(totalSizeToAlloc<KeyValuePair, ExpansionData>( + NumElements, HasPackExpansions ? NumElements : 0)); + return new (Mem) + ObjCDictionaryLiteral(EmptyShell(), NumElements, HasPackExpansions); +} + +QualType ObjCPropertyRefExpr::getReceiverType(const ASTContext &ctx) const { + if (isClassReceiver()) + return ctx.getObjCInterfaceType(getClassReceiver()); + + if (isSuperReceiver()) + return getSuperReceiverType(); + + return getBase()->getType(); +} + +ObjCMessageExpr::ObjCMessageExpr(QualType T, ExprValueKind VK, + SourceLocation LBracLoc, + SourceLocation SuperLoc, bool IsInstanceSuper, + QualType SuperType, Selector Sel, + ArrayRef<SourceLocation> SelLocs, + SelectorLocationsKind SelLocsK, + ObjCMethodDecl *Method, ArrayRef<Expr *> Args, + SourceLocation RBracLoc, bool isImplicit) + : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, + /*TypeDependent=*/false, /*ValueDependent=*/false, + /*InstantiationDependent=*/false, + /*ContainsUnexpandedParameterPack=*/false), + SelectorOrMethod( + reinterpret_cast<uintptr_t>(Method ? Method : Sel.getAsOpaquePtr())), + Kind(IsInstanceSuper ? SuperInstance : SuperClass), + HasMethod(Method != nullptr), IsDelegateInitCall(false), + IsImplicit(isImplicit), SuperLoc(SuperLoc), LBracLoc(LBracLoc), + RBracLoc(RBracLoc) { + initArgsAndSelLocs(Args, SelLocs, SelLocsK); + setReceiverPointer(SuperType.getAsOpaquePtr()); +} + +ObjCMessageExpr::ObjCMessageExpr(QualType T, ExprValueKind VK, + SourceLocation LBracLoc, + TypeSourceInfo *Receiver, Selector Sel, + ArrayRef<SourceLocation> SelLocs, + SelectorLocationsKind SelLocsK, + ObjCMethodDecl *Method, ArrayRef<Expr *> Args, + SourceLocation RBracLoc, bool isImplicit) + : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, T->isDependentType(), + T->isDependentType(), T->isInstantiationDependentType(), + T->containsUnexpandedParameterPack()), + SelectorOrMethod( + reinterpret_cast<uintptr_t>(Method ? Method : Sel.getAsOpaquePtr())), + Kind(Class), HasMethod(Method != nullptr), IsDelegateInitCall(false), + IsImplicit(isImplicit), LBracLoc(LBracLoc), RBracLoc(RBracLoc) { + initArgsAndSelLocs(Args, SelLocs, SelLocsK); + setReceiverPointer(Receiver); +} + +ObjCMessageExpr::ObjCMessageExpr(QualType T, ExprValueKind VK, + SourceLocation LBracLoc, Expr *Receiver, + Selector Sel, ArrayRef<SourceLocation> SelLocs, + SelectorLocationsKind SelLocsK, + ObjCMethodDecl *Method, ArrayRef<Expr *> Args, + SourceLocation RBracLoc, bool isImplicit) + : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, + Receiver->isTypeDependent(), Receiver->isTypeDependent(), + Receiver->isInstantiationDependent(), + Receiver->containsUnexpandedParameterPack()), + SelectorOrMethod( + reinterpret_cast<uintptr_t>(Method ? Method : Sel.getAsOpaquePtr())), + Kind(Instance), HasMethod(Method != nullptr), IsDelegateInitCall(false), + IsImplicit(isImplicit), LBracLoc(LBracLoc), RBracLoc(RBracLoc) { + initArgsAndSelLocs(Args, SelLocs, SelLocsK); + setReceiverPointer(Receiver); +} + +void ObjCMessageExpr::initArgsAndSelLocs(ArrayRef<Expr *> Args, + ArrayRef<SourceLocation> SelLocs, + SelectorLocationsKind SelLocsK) { + setNumArgs(Args.size()); + Expr **MyArgs = getArgs(); + for (unsigned I = 0; I != Args.size(); ++I) { + if (Args[I]->isTypeDependent()) + ExprBits.TypeDependent = true; + if (Args[I]->isValueDependent()) + ExprBits.ValueDependent = true; + if (Args[I]->isInstantiationDependent()) + ExprBits.InstantiationDependent = true; + if (Args[I]->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; + + MyArgs[I] = Args[I]; + } + + SelLocsKind = SelLocsK; + if (!isImplicit()) { + if (SelLocsK == SelLoc_NonStandard) + std::copy(SelLocs.begin(), SelLocs.end(), getStoredSelLocs()); + } +} + +ObjCMessageExpr * +ObjCMessageExpr::Create(const ASTContext &Context, QualType T, ExprValueKind VK, + SourceLocation LBracLoc, SourceLocation SuperLoc, + bool IsInstanceSuper, QualType SuperType, Selector Sel, + ArrayRef<SourceLocation> SelLocs, + ObjCMethodDecl *Method, ArrayRef<Expr *> Args, + SourceLocation RBracLoc, bool isImplicit) { + assert((!SelLocs.empty() || isImplicit) && + "No selector locs for non-implicit message"); + ObjCMessageExpr *Mem; + SelectorLocationsKind SelLocsK = SelectorLocationsKind(); + if (isImplicit) + Mem = alloc(Context, Args.size(), 0); + else + Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK); + return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, SuperLoc, IsInstanceSuper, + SuperType, Sel, SelLocs, SelLocsK, Method, + Args, RBracLoc, isImplicit); +} + +ObjCMessageExpr * +ObjCMessageExpr::Create(const ASTContext &Context, QualType T, ExprValueKind VK, + SourceLocation LBracLoc, TypeSourceInfo *Receiver, + Selector Sel, ArrayRef<SourceLocation> SelLocs, + ObjCMethodDecl *Method, ArrayRef<Expr *> Args, + SourceLocation RBracLoc, bool isImplicit) { + assert((!SelLocs.empty() || isImplicit) && + "No selector locs for non-implicit message"); + ObjCMessageExpr *Mem; + SelectorLocationsKind SelLocsK = SelectorLocationsKind(); + if (isImplicit) + Mem = alloc(Context, Args.size(), 0); + else + Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK); + return new (Mem) + ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel, SelLocs, SelLocsK, Method, + Args, RBracLoc, isImplicit); +} + +ObjCMessageExpr * +ObjCMessageExpr::Create(const ASTContext &Context, QualType T, ExprValueKind VK, + SourceLocation LBracLoc, Expr *Receiver, Selector Sel, + ArrayRef<SourceLocation> SelLocs, + ObjCMethodDecl *Method, ArrayRef<Expr *> Args, + SourceLocation RBracLoc, bool isImplicit) { + assert((!SelLocs.empty() || isImplicit) && + "No selector locs for non-implicit message"); + ObjCMessageExpr *Mem; + SelectorLocationsKind SelLocsK = SelectorLocationsKind(); + if (isImplicit) + Mem = alloc(Context, Args.size(), 0); + else + Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK); + return new (Mem) + ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel, SelLocs, SelLocsK, Method, + Args, RBracLoc, isImplicit); +} + +ObjCMessageExpr *ObjCMessageExpr::CreateEmpty(const ASTContext &Context, + unsigned NumArgs, + unsigned NumStoredSelLocs) { + ObjCMessageExpr *Mem = alloc(Context, NumArgs, NumStoredSelLocs); + return new (Mem) ObjCMessageExpr(EmptyShell(), NumArgs); +} + +ObjCMessageExpr *ObjCMessageExpr::alloc(const ASTContext &C, + ArrayRef<Expr *> Args, + SourceLocation RBraceLoc, + ArrayRef<SourceLocation> SelLocs, + Selector Sel, + SelectorLocationsKind &SelLocsK) { + SelLocsK = hasStandardSelectorLocs(Sel, SelLocs, Args, RBraceLoc); + unsigned NumStoredSelLocs = + (SelLocsK == SelLoc_NonStandard) ? SelLocs.size() : 0; + return alloc(C, Args.size(), NumStoredSelLocs); +} + +ObjCMessageExpr *ObjCMessageExpr::alloc(const ASTContext &C, unsigned NumArgs, + unsigned NumStoredSelLocs) { + return (ObjCMessageExpr *)C.Allocate( + totalSizeToAlloc<void *, SourceLocation>(NumArgs + 1, NumStoredSelLocs), + alignof(ObjCMessageExpr)); +} + +void ObjCMessageExpr::getSelectorLocs( + SmallVectorImpl<SourceLocation> &SelLocs) const { + for (unsigned i = 0, e = getNumSelectorLocs(); i != e; ++i) + SelLocs.push_back(getSelectorLoc(i)); +} + + +QualType ObjCMessageExpr::getCallReturnType(ASTContext &Ctx) const { + if (const ObjCMethodDecl *MD = getMethodDecl()) { + QualType QT = MD->getReturnType(); + if (QT == Ctx.getObjCInstanceType()) { + // instancetype corresponds to expression types. + return getType(); + } + return QT; + } + + // Expression type might be different from an expected call return type, + // as expression type would never be a reference even if call returns a + // reference. Reconstruct the original expression type. + QualType QT = getType(); + switch (getValueKind()) { + case VK_LValue: + return Ctx.getLValueReferenceType(QT); + case VK_XValue: + return Ctx.getRValueReferenceType(QT); + case VK_RValue: + return QT; + } + llvm_unreachable("Unsupported ExprValueKind"); +} + +SourceRange ObjCMessageExpr::getReceiverRange() const { + switch (getReceiverKind()) { + case Instance: + return getInstanceReceiver()->getSourceRange(); + + case Class: + return getClassReceiverTypeInfo()->getTypeLoc().getSourceRange(); + + case SuperInstance: + case SuperClass: + return getSuperLoc(); + } + + llvm_unreachable("Invalid ReceiverKind!"); +} + +Selector ObjCMessageExpr::getSelector() const { + if (HasMethod) + return reinterpret_cast<const ObjCMethodDecl *>(SelectorOrMethod) + ->getSelector(); + return Selector(SelectorOrMethod); +} + +QualType ObjCMessageExpr::getReceiverType() const { + switch (getReceiverKind()) { + case Instance: + return getInstanceReceiver()->getType(); + case Class: + return getClassReceiver(); + case SuperInstance: + case SuperClass: + return getSuperType(); + } + + llvm_unreachable("unexpected receiver kind"); +} + +ObjCInterfaceDecl *ObjCMessageExpr::getReceiverInterface() const { + QualType T = getReceiverType(); + + if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>()) + return Ptr->getInterfaceDecl(); + + if (const ObjCObjectType *Ty = T->getAs<ObjCObjectType>()) + return Ty->getInterface(); + + return nullptr; +} + +Stmt::child_range ObjCMessageExpr::children() { + Stmt **begin; + if (getReceiverKind() == Instance) + begin = reinterpret_cast<Stmt **>(getTrailingObjects<void *>()); + else + begin = reinterpret_cast<Stmt **>(getArgs()); + return child_range(begin, + reinterpret_cast<Stmt **>(getArgs() + getNumArgs())); +} + +Stmt::const_child_range ObjCMessageExpr::children() const { + auto Children = const_cast<ObjCMessageExpr *>(this)->children(); + return const_child_range(Children.begin(), Children.end()); +} + +StringRef ObjCBridgedCastExpr::getBridgeKindName() const { + switch (getBridgeKind()) { + case OBC_Bridge: + return "__bridge"; + case OBC_BridgeTransfer: + return "__bridge_transfer"; + case OBC_BridgeRetained: + return "__bridge_retained"; + } + + llvm_unreachable("Invalid BridgeKind!"); +} |
