Allow getting all source locations of selector identifiers in a ObjCMessageExpr.

Instead of always storing all source locations for the selector identifiers
we check whether all the identifiers are in a "standard" position; "standard" position is

  -Immediately before the arguments: [foo first:1 second:2]
  -With a space between the arguments: [foo first: 1 second: 2]
  -For nullary selectors, immediately before ']': [foo release]

In such cases we infer the locations instead of storing them.

llvm-svn: 140987
This commit is contained in:
Argyrios Kyrtzidis 2011-10-03 06:36:51 +00:00
parent 59ad1e3f57
commit a6011e25a1
9 changed files with 328 additions and 61 deletions

View File

@ -16,6 +16,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/SelectorLocationsKind.h"
#include "clang/Basic/IdentifierTable.h"
namespace clang {
@ -471,6 +472,10 @@ class ObjCMessageExpr : public Expr {
/// \brief Whether this message send is a "delegate init call",
/// i.e. a call of an init method on self from within an init method.
unsigned IsDelegateInitCall : 1;
/// \brief Whether the locations of the selector identifiers are in a
/// "standard" position, a enum SelectorLocationsKind.
unsigned SelLocsKind : 2;
/// \brief When the message expression is a send to 'super', this is
/// the location of the 'super' keyword.
@ -481,9 +486,6 @@ class ObjCMessageExpr : public Expr {
/// referring to the method that we type-checked against.
uintptr_t SelectorOrMethod;
/// \brief Location of the selector.
SourceLocation SelectorLoc;
/// \brief The source locations of the open and close square
/// brackets ('[' and ']', respectively).
SourceLocation LBracLoc, RBracLoc;
@ -500,7 +502,8 @@ class ObjCMessageExpr : public Expr {
bool IsInstanceSuper,
QualType SuperType,
Selector Sel,
SourceLocation SelLoc,
ArrayRef<SourceLocation> SelLocs,
SelectorLocationsKind SelLocsK,
ObjCMethodDecl *Method,
ArrayRef<Expr *> Args,
SourceLocation RBracLoc);
@ -508,7 +511,8 @@ class ObjCMessageExpr : public Expr {
SourceLocation LBracLoc,
TypeSourceInfo *Receiver,
Selector Sel,
SourceLocation SelLoc,
ArrayRef<SourceLocation> SelLocs,
SelectorLocationsKind SelLocsK,
ObjCMethodDecl *Method,
ArrayRef<Expr *> Args,
SourceLocation RBracLoc);
@ -516,11 +520,16 @@ class ObjCMessageExpr : public Expr {
SourceLocation LBracLoc,
Expr *Receiver,
Selector Sel,
SourceLocation SelLoc,
ArrayRef<SourceLocation> SelLocs,
SelectorLocationsKind SelLocsK,
ObjCMethodDecl *Method,
ArrayRef<Expr *> Args,
SourceLocation RBracLoc);
void initArgsAndSelLocs(ArrayRef<Expr *> Args,
ArrayRef<SourceLocation> SelLocs,
SelectorLocationsKind SelLocsK);
/// \brief Retrieve the pointer value of the message receiver.
void *getReceiverPointer() const {
return *const_cast<void **>(
@ -532,6 +541,40 @@ class ObjCMessageExpr : public Expr {
*reinterpret_cast<void **>(this + 1) = Value;
}
SelectorLocationsKind getSelLocsKind() const {
return (SelectorLocationsKind)SelLocsKind;
}
bool hasStandardSelLocs() const {
return getSelLocsKind() != SelLoc_NonStandard;
}
/// \brief Get a pointer to the stored selector identifiers locations array.
/// No locations will be stored if HasStandardSelLocs is true.
SourceLocation *getStoredSelLocs() {
return reinterpret_cast<SourceLocation*>(getArgs() + getNumArgs());
}
const SourceLocation *getStoredSelLocs() const {
return reinterpret_cast<const SourceLocation*>(getArgs() + getNumArgs());
}
/// \brief Get the number of stored selector identifiers locations.
/// No locations will be stored if HasStandardSelLocs is true.
unsigned getNumStoredSelLocs() const {
if (hasStandardSelLocs())
return 0;
return getNumSelectorLocs();
}
static ObjCMessageExpr *alloc(ASTContext &C,
ArrayRef<Expr *> Args,
SourceLocation RBraceLoc,
ArrayRef<SourceLocation> SelLocs,
Selector Sel,
SelectorLocationsKind &SelLocsK);
static ObjCMessageExpr *alloc(ASTContext &C,
unsigned NumArgs,
unsigned NumStoredSelLocs);
public:
/// \brief The kind of receiver this message is sending to.
enum ReceiverKind {
@ -661,7 +704,9 @@ public:
///
/// \param NumArgs The number of message arguments, not including
/// the receiver.
static ObjCMessageExpr *CreateEmpty(ASTContext &Context, unsigned NumArgs);
static ObjCMessageExpr *CreateEmpty(ASTContext &Context,
unsigned NumArgs,
unsigned NumStoredSelLocs);
/// \brief Determine the kind of receiver that this message is being
/// sent to.
@ -831,7 +876,27 @@ public:
SourceLocation getLeftLoc() const { return LBracLoc; }
SourceLocation getRightLoc() const { return RBracLoc; }
SourceLocation getSelectorLoc() const { return SelectorLoc; }
SourceLocation getSelectorStartLoc() const { return getSelectorLoc(0); }
SourceLocation getSelectorLoc(unsigned Index) const {
assert(Index < getNumSelectorLocs() && "Index out of range!");
if (hasStandardSelLocs())
return getStandardSelectorLoc(Index, getSelector(),
getSelLocsKind() == SelLoc_StandardWithSpace,
llvm::makeArrayRef(const_cast<Expr**>(getArgs()),
getNumArgs()),
RBracLoc);
return getStoredSelLocs()[Index];
}
void getSelectorLocs(SmallVectorImpl<SourceLocation> &SelLocs) const;
unsigned getNumSelectorLocs() const {
Selector Sel = getSelector();
if (Sel.isUnarySelector())
return 1;
return Sel.getNumArgs();
}
void setSourceRange(SourceRange R) {
LBracLoc = R.getBegin();

View File

@ -0,0 +1,64 @@
//===--- SelectorLocationsKind.h - Kind of selector locations ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Describes whether the identifier locations for a selector are "standard"
// or not.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_SELECTORLOCATIONSKIND_H
#define LLVM_CLANG_AST_SELECTORLOCATIONSKIND_H
#include "clang/Basic/LLVM.h"
namespace clang {
class Selector;
class SourceLocation;
class Expr;
/// \brief Whether all locations of the selector identifiers are in a
/// "standard" position.
enum SelectorLocationsKind {
/// \brief Non-standard.
SelLoc_NonStandard = 0,
/// \brief For nullary selectors, immediately before the end:
/// "[foo release]" / "-(void)release;"
/// Or immediately before the arguments:
/// "[foo first:1 second:2]" / "-(id)first:(int)x second:(int)y;
SelLoc_StandardNoSpace = 1,
/// \brief For nullary selectors, immediately before the end:
/// "[foo release]" / "-(void)release;"
/// Or with a space between the arguments:
/// "[foo first: 1 second: 2]" / "-(id)first: (int)x second: (int)y;
SelLoc_StandardWithSpace = 2
};
/// \brief Returns true if all \arg SelLocs are in a "standard" location.
SelectorLocationsKind hasStandardSelectorLocs(Selector Sel,
ArrayRef<SourceLocation> SelLocs,
ArrayRef<Expr *> Args,
SourceLocation EndLoc);
/// \brief Get the "standard" location of a selector identifier, e.g:
/// For nullary selectors, immediately before ']': "[foo release]"
///
/// \param WithArgSpace if true the standard location is with a space apart
/// before arguments: "[foo first: 1 second: 2]"
/// If false: "[foo first:1 second:2]"
SourceLocation getStandardSelectorLoc(unsigned Index,
Selector Sel,
bool WithArgSpace,
ArrayRef<Expr *> Args,
SourceLocation EndLoc);
} // end namespace clang
#endif

View File

@ -35,6 +35,7 @@ add_clang_library(clangAST
ParentMap.cpp
RecordLayout.cpp
RecordLayoutBuilder.cpp
SelectorLocationsKind.cpp
Stmt.cpp
StmtDumper.cpp
StmtIterator.cpp

View File

@ -2716,7 +2716,8 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T,
bool IsInstanceSuper,
QualType SuperType,
Selector Sel,
SourceLocation SelLoc,
ArrayRef<SourceLocation> SelLocs,
SelectorLocationsKind SelLocsK,
ObjCMethodDecl *Method,
ArrayRef<Expr *> Args,
SourceLocation RBracLoc)
@ -2728,12 +2729,10 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T,
HasMethod(Method != 0), IsDelegateInitCall(false), SuperLoc(SuperLoc),
SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method
: Sel.getAsOpaquePtr())),
SelectorLoc(SelLoc), LBracLoc(LBracLoc), RBracLoc(RBracLoc)
LBracLoc(LBracLoc), RBracLoc(RBracLoc)
{
setNumArgs(Args.size());
initArgsAndSelLocs(Args, SelLocs, SelLocsK);
setReceiverPointer(SuperType.getAsOpaquePtr());
if (!Args.empty())
std::copy(Args.begin(), Args.end(), getArgs());
}
ObjCMessageExpr::ObjCMessageExpr(QualType T,
@ -2741,7 +2740,8 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T,
SourceLocation LBracLoc,
TypeSourceInfo *Receiver,
Selector Sel,
SourceLocation SelLoc,
ArrayRef<SourceLocation> SelLocs,
SelectorLocationsKind SelLocsK,
ObjCMethodDecl *Method,
ArrayRef<Expr *> Args,
SourceLocation RBracLoc)
@ -2752,23 +2752,10 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T,
HasMethod(Method != 0), IsDelegateInitCall(false),
SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method
: Sel.getAsOpaquePtr())),
SelectorLoc(SelLoc), LBracLoc(LBracLoc), RBracLoc(RBracLoc)
LBracLoc(LBracLoc), RBracLoc(RBracLoc)
{
setNumArgs(Args.size());
initArgsAndSelLocs(Args, SelLocs, SelLocsK);
setReceiverPointer(Receiver);
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];
}
}
ObjCMessageExpr::ObjCMessageExpr(QualType T,
@ -2776,7 +2763,8 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T,
SourceLocation LBracLoc,
Expr *Receiver,
Selector Sel,
SourceLocation SelLoc,
ArrayRef<SourceLocation> SelLocs,
SelectorLocationsKind SelLocsK,
ObjCMethodDecl *Method,
ArrayRef<Expr *> Args,
SourceLocation RBracLoc)
@ -2788,10 +2776,16 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T,
HasMethod(Method != 0), IsDelegateInitCall(false),
SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method
: Sel.getAsOpaquePtr())),
SelectorLoc(SelLoc), LBracLoc(LBracLoc), RBracLoc(RBracLoc)
LBracLoc(LBracLoc), RBracLoc(RBracLoc)
{
setNumArgs(Args.size());
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())
@ -2805,6 +2799,10 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T,
MyArgs[I] = Args[I];
}
SelLocsKind = SelLocsK;
if (SelLocsK == SelLoc_NonStandard)
std::copy(SelLocs.begin(), SelLocs.end(), getStoredSelLocs());
}
ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T,
@ -2818,12 +2816,11 @@ ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T,
ObjCMethodDecl *Method,
ArrayRef<Expr *> Args,
SourceLocation RBracLoc) {
unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) +
Args.size() * sizeof(Expr *);
void *Mem = Context.Allocate(Size, llvm::AlignOf<ObjCMessageExpr>::Alignment);
SelectorLocationsKind SelLocsK;
ObjCMessageExpr *Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK);
return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, SuperLoc, IsInstanceSuper,
SuperType, Sel, SelLocs.front(), Method,
Args, RBracLoc);
SuperType, Sel, SelLocs, SelLocsK,
Method, Args, RBracLoc);
}
ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T,
@ -2835,12 +2832,10 @@ ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T,
ObjCMethodDecl *Method,
ArrayRef<Expr *> Args,
SourceLocation RBracLoc) {
unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) +
Args.size() * sizeof(Expr *);
void *Mem = Context.Allocate(Size, llvm::AlignOf<ObjCMessageExpr>::Alignment);
SelectorLocationsKind SelLocsK;
ObjCMessageExpr *Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK);
return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel,
SelLocs.front(),
Method, Args, RBracLoc);
SelLocs, SelLocsK, Method, Args, RBracLoc);
}
ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T,
@ -2852,22 +2847,46 @@ ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T,
ObjCMethodDecl *Method,
ArrayRef<Expr *> Args,
SourceLocation RBracLoc) {
unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) +
Args.size() * sizeof(Expr *);
void *Mem = Context.Allocate(Size, llvm::AlignOf<ObjCMessageExpr>::Alignment);
SelectorLocationsKind SelLocsK;
ObjCMessageExpr *Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK);
return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel,
SelLocs.front(),
Method, Args, RBracLoc);
SelLocs, SelLocsK, Method, Args, RBracLoc);
}
ObjCMessageExpr *ObjCMessageExpr::CreateEmpty(ASTContext &Context,
unsigned NumArgs) {
unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) +
NumArgs * sizeof(Expr *);
void *Mem = Context.Allocate(Size, llvm::AlignOf<ObjCMessageExpr>::Alignment);
unsigned NumArgs,
unsigned NumStoredSelLocs) {
ObjCMessageExpr *Mem = alloc(Context, NumArgs, NumStoredSelLocs);
return new (Mem) ObjCMessageExpr(EmptyShell(), NumArgs);
}
ObjCMessageExpr *ObjCMessageExpr::alloc(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(ASTContext &C,
unsigned NumArgs,
unsigned NumStoredSelLocs) {
unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) +
NumArgs * sizeof(Expr *) + NumStoredSelLocs * sizeof(SourceLocation);
return (ObjCMessageExpr *)C.Allocate(Size,
llvm::AlignOf<ObjCMessageExpr>::Alignment);
}
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:

View File

@ -0,0 +1,102 @@
//===--- SelectorLocationsKind.cpp - Kind of selector locations -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Describes whether the identifier locations for a selector are "standard"
// or not.
//
//===----------------------------------------------------------------------===//
#include "clang/AST/SelectorLocationsKind.h"
#include "clang/AST/Expr.h"
using namespace clang;
static SourceLocation getStandardSelLoc(unsigned Index,
Selector Sel,
bool WithArgSpace,
SourceLocation ArgLoc,
SourceLocation EndLoc) {
unsigned NumSelArgs = Sel.getNumArgs();
if (NumSelArgs == 0) {
assert(Index == 0);
if (EndLoc.isInvalid())
return SourceLocation();
IdentifierInfo *II = Sel.getIdentifierInfoForSlot(0);
unsigned Len = II ? II->getLength() : 0;
return EndLoc.getLocWithOffset(-Len);
}
assert(Index < NumSelArgs);
if (ArgLoc.isInvalid())
return SourceLocation();
IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Index);
unsigned Len = /* selector id */ (II ? II->getLength() : 0) + /* ':' */ 1;
if (WithArgSpace)
++Len;
return ArgLoc.getLocWithOffset(-Len);
}
namespace {
template <typename T>
SourceLocation getArgLoc(T* Arg);
template <>
SourceLocation getArgLoc<Expr>(Expr *Arg) {
return Arg->getLocStart();
}
template <typename T>
SourceLocation getArgLoc(unsigned Index, ArrayRef<T*> Args) {
return Index < Args.size() ? getArgLoc(Args[Index]) : SourceLocation();
}
template <typename T>
SelectorLocationsKind hasStandardSelLocs(Selector Sel,
ArrayRef<SourceLocation> SelLocs,
ArrayRef<T *> Args,
SourceLocation EndLoc) {
// Are selector locations in standard position with no space between args ?
unsigned i;
for (i = 0; i != SelLocs.size(); ++i) {
if (SelLocs[i] != getStandardSelectorLoc(i, Sel, /*WithArgSpace=*/false,
Args, EndLoc))
break;
}
if (i == SelLocs.size())
return SelLoc_StandardNoSpace;
// Are selector locations in standard position with space between args ?
for (i = 0; i != SelLocs.size(); ++i) {
if (SelLocs[i] != getStandardSelectorLoc(i, Sel, /*WithArgSpace=*/true,
Args, EndLoc))
return SelLoc_NonStandard;
}
return SelLoc_StandardWithSpace;
}
} // anonymous namespace
SelectorLocationsKind
clang::hasStandardSelectorLocs(Selector Sel,
ArrayRef<SourceLocation> SelLocs,
ArrayRef<Expr *> Args,
SourceLocation EndLoc) {
return hasStandardSelLocs(Sel, SelLocs, Args, EndLoc);
}
SourceLocation clang::getStandardSelectorLoc(unsigned Index,
Selector Sel,
bool WithArgSpace,
ArrayRef<Expr *> Args,
SourceLocation EndLoc) {
return getStandardSelLoc(Index, Sel, WithArgSpace,
getArgLoc(Index, Args), EndLoc);
}

View File

@ -10129,7 +10129,7 @@ static ExprResult diagnoseUnknownAnyExpr(Sema &S, Expr *E) {
d = mem->getMemberDecl();
} else if (ObjCMessageExpr *msg = dyn_cast<ObjCMessageExpr>(E)) {
diagID = diag::err_uncasted_call_of_unknown_any;
loc = msg->getSelectorLoc();
loc = msg->getSelectorStartLoc();
d = msg->getMethodDecl();
if (!d) {
S.Diag(loc, diag::err_uncasted_send_to_unknown_any_method)

View File

@ -2152,7 +2152,7 @@ public:
/// \brief Build a new Objective-C class message.
ExprResult RebuildObjCMessageExpr(TypeSourceInfo *ReceiverTypeInfo,
Selector Sel,
SourceLocation SelectorLoc,
ArrayRef<SourceLocation> SelectorLocs,
ObjCMethodDecl *Method,
SourceLocation LBracLoc,
MultiExprArg Args,
@ -2160,14 +2160,14 @@ public:
return SemaRef.BuildClassMessage(ReceiverTypeInfo,
ReceiverTypeInfo->getType(),
/*SuperLoc=*/SourceLocation(),
Sel, Method, LBracLoc, SelectorLoc,
Sel, Method, LBracLoc, SelectorLocs,
RBracLoc, move(Args));
}
/// \brief Build a new Objective-C instance message.
ExprResult RebuildObjCMessageExpr(Expr *Receiver,
Selector Sel,
SourceLocation SelectorLoc,
ArrayRef<SourceLocation> SelectorLocs,
ObjCMethodDecl *Method,
SourceLocation LBracLoc,
MultiExprArg Args,
@ -2175,7 +2175,7 @@ public:
return SemaRef.BuildInstanceMessage(Receiver,
Receiver->getType(),
/*SuperLoc=*/SourceLocation(),
Sel, Method, LBracLoc, SelectorLoc,
Sel, Method, LBracLoc, SelectorLocs,
RBracLoc, move(Args));
}
@ -7794,9 +7794,11 @@ TreeTransform<Derived>::TransformObjCMessageExpr(ObjCMessageExpr *E) {
return SemaRef.Owned(E);
// Build a new class message send.
SmallVector<SourceLocation, 16> SelLocs;
E->getSelectorLocs(SelLocs);
return getDerived().RebuildObjCMessageExpr(ReceiverTypeInfo,
E->getSelector(),
E->getSelectorLoc(),
SelLocs,
E->getMethodDecl(),
E->getLeftLoc(),
move_arg(Args),
@ -7817,9 +7819,11 @@ TreeTransform<Derived>::TransformObjCMessageExpr(ObjCMessageExpr *E) {
return SemaRef.Owned(E);
// Build a new instance message send.
SmallVector<SourceLocation, 16> SelLocs;
E->getSelectorLocs(SelLocs);
return getDerived().RebuildObjCMessageExpr(Receiver.get(),
E->getSelector(),
E->getSelectorLoc(),
SelLocs,
E->getMethodDecl(),
E->getLeftLoc(),
move_arg(Args),

View File

@ -841,6 +841,8 @@ void ASTStmtReader::VisitObjCMessageExpr(ObjCMessageExpr *E) {
VisitExpr(E);
assert(Record[Idx] == E->getNumArgs());
++Idx;
unsigned NumStoredSelLocs = Record[Idx++];
E->SelLocsKind = Record[Idx++];
E->setDelegateInitCall(Record[Idx++]);
ObjCMessageExpr::ReceiverKind Kind
= static_cast<ObjCMessageExpr::ReceiverKind>(Record[Idx++]);
@ -871,10 +873,13 @@ void ASTStmtReader::VisitObjCMessageExpr(ObjCMessageExpr *E) {
E->LBracLoc = ReadSourceLocation(Record, Idx);
E->RBracLoc = ReadSourceLocation(Record, Idx);
E->SelectorLoc = ReadSourceLocation(Record, Idx);
for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
E->setArg(I, Reader.ReadSubExpr());
SourceLocation *Locs = E->getStoredSelLocs();
for (unsigned I = 0; I != NumStoredSelLocs; ++I)
Locs[I] = ReadSourceLocation(Record, Idx);
}
void ASTStmtReader::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
@ -1747,7 +1752,8 @@ Stmt *ASTReader::ReadStmtFromStream(Module &F) {
break;
case EXPR_OBJC_MESSAGE_EXPR:
S = ObjCMessageExpr::CreateEmpty(Context,
Record[ASTStmtReader::NumExprFields]);
Record[ASTStmtReader::NumExprFields],
Record[ASTStmtReader::NumExprFields + 1]);
break;
case EXPR_OBJC_ISA:
S = new (Context) ObjCIsaExpr(Empty);

View File

@ -806,6 +806,8 @@ void ASTStmtWriter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
void ASTStmtWriter::VisitObjCMessageExpr(ObjCMessageExpr *E) {
VisitExpr(E);
Record.push_back(E->getNumArgs());
Record.push_back(E->getNumStoredSelLocs());
Record.push_back(E->SelLocsKind);
Record.push_back(E->isDelegateInitCall());
Record.push_back((unsigned)E->getReceiverKind()); // FIXME: stable encoding
switch (E->getReceiverKind()) {
@ -834,11 +836,15 @@ void ASTStmtWriter::VisitObjCMessageExpr(ObjCMessageExpr *E) {
Writer.AddSourceLocation(E->getLeftLoc(), Record);
Writer.AddSourceLocation(E->getRightLoc(), Record);
Writer.AddSourceLocation(E->getSelectorLoc(), Record);
for (CallExpr::arg_iterator Arg = E->arg_begin(), ArgEnd = E->arg_end();
Arg != ArgEnd; ++Arg)
Writer.AddStmt(*Arg);
SourceLocation *Locs = E->getStoredSelLocs();
for (unsigned i = 0, e = E->getNumStoredSelLocs(); i != e; ++i)
Writer.AddSourceLocation(Locs[i], Record);
Code = serialization::EXPR_OBJC_MESSAGE_EXPR;
}