blob: e1a23f59858926d07a7d461160b38e6d499d3fd7 [file] [log] [blame]
//===- ExprObjC.cpp - (ObjC) Expression AST Node Implementation -----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// 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));
}
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()));
}
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!");
}