diff --git a/clang/include/clang/AST/ExprObjC.h b/clang/include/clang/AST/ExprObjC.h index b8cef68a7d6d..5e237b91d740 100644 --- a/clang/include/clang/AST/ExprObjC.h +++ b/clang/include/clang/AST/ExprObjC.h @@ -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 SelLocs, + SelectorLocationsKind SelLocsK, ObjCMethodDecl *Method, ArrayRef Args, SourceLocation RBracLoc); @@ -508,7 +511,8 @@ class ObjCMessageExpr : public Expr { SourceLocation LBracLoc, TypeSourceInfo *Receiver, Selector Sel, - SourceLocation SelLoc, + ArrayRef SelLocs, + SelectorLocationsKind SelLocsK, ObjCMethodDecl *Method, ArrayRef Args, SourceLocation RBracLoc); @@ -516,11 +520,16 @@ class ObjCMessageExpr : public Expr { SourceLocation LBracLoc, Expr *Receiver, Selector Sel, - SourceLocation SelLoc, + ArrayRef SelLocs, + SelectorLocationsKind SelLocsK, ObjCMethodDecl *Method, ArrayRef Args, SourceLocation RBracLoc); + void initArgsAndSelLocs(ArrayRef Args, + ArrayRef SelLocs, + SelectorLocationsKind SelLocsK); + /// \brief Retrieve the pointer value of the message receiver. void *getReceiverPointer() const { return *const_cast( @@ -532,6 +541,40 @@ class ObjCMessageExpr : public Expr { *reinterpret_cast(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(getArgs() + getNumArgs()); + } + const SourceLocation *getStoredSelLocs() const { + return reinterpret_cast(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 Args, + SourceLocation RBraceLoc, + ArrayRef 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(getArgs()), + getNumArgs()), + RBracLoc); + return getStoredSelLocs()[Index]; + } + + void getSelectorLocs(SmallVectorImpl &SelLocs) const; + + unsigned getNumSelectorLocs() const { + Selector Sel = getSelector(); + if (Sel.isUnarySelector()) + return 1; + return Sel.getNumArgs(); + } void setSourceRange(SourceRange R) { LBracLoc = R.getBegin(); diff --git a/clang/include/clang/AST/SelectorLocationsKind.h b/clang/include/clang/AST/SelectorLocationsKind.h new file mode 100644 index 000000000000..b9b058d55b30 --- /dev/null +++ b/clang/include/clang/AST/SelectorLocationsKind.h @@ -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 SelLocs, + ArrayRef 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 Args, + SourceLocation EndLoc); + +} // end namespace clang + +#endif diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt index 00fad798ef24..1f0100a580a3 100644 --- a/clang/lib/AST/CMakeLists.txt +++ b/clang/lib/AST/CMakeLists.txt @@ -35,6 +35,7 @@ add_clang_library(clangAST ParentMap.cpp RecordLayout.cpp RecordLayoutBuilder.cpp + SelectorLocationsKind.cpp Stmt.cpp StmtDumper.cpp StmtIterator.cpp diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index f93ce72d254d..b7276aa82f41 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -2716,7 +2716,8 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T, bool IsInstanceSuper, QualType SuperType, Selector Sel, - SourceLocation SelLoc, + ArrayRef SelLocs, + SelectorLocationsKind SelLocsK, ObjCMethodDecl *Method, ArrayRef Args, SourceLocation RBracLoc) @@ -2728,12 +2729,10 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T, HasMethod(Method != 0), IsDelegateInitCall(false), SuperLoc(SuperLoc), SelectorOrMethod(reinterpret_cast(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 SelLocs, + SelectorLocationsKind SelLocsK, ObjCMethodDecl *Method, ArrayRef Args, SourceLocation RBracLoc) @@ -2752,23 +2752,10 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T, HasMethod(Method != 0), IsDelegateInitCall(false), SelectorOrMethod(reinterpret_cast(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 SelLocs, + SelectorLocationsKind SelLocsK, ObjCMethodDecl *Method, ArrayRef Args, SourceLocation RBracLoc) @@ -2788,10 +2776,16 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T, HasMethod(Method != 0), IsDelegateInitCall(false), SelectorOrMethod(reinterpret_cast(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 Args, + ArrayRef 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 Args, SourceLocation RBracLoc) { - unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) + - Args.size() * sizeof(Expr *); - void *Mem = Context.Allocate(Size, llvm::AlignOf::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 Args, SourceLocation RBracLoc) { - unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) + - Args.size() * sizeof(Expr *); - void *Mem = Context.Allocate(Size, llvm::AlignOf::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 Args, SourceLocation RBracLoc) { - unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) + - Args.size() * sizeof(Expr *); - void *Mem = Context.Allocate(Size, llvm::AlignOf::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::Alignment); + unsigned NumArgs, + unsigned NumStoredSelLocs) { + ObjCMessageExpr *Mem = alloc(Context, NumArgs, NumStoredSelLocs); return new (Mem) ObjCMessageExpr(EmptyShell(), NumArgs); } +ObjCMessageExpr *ObjCMessageExpr::alloc(ASTContext &C, + ArrayRef Args, + SourceLocation RBraceLoc, + ArrayRef 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::Alignment); +} + +void ObjCMessageExpr::getSelectorLocs( + SmallVectorImpl &SelLocs) const { + for (unsigned i = 0, e = getNumSelectorLocs(); i != e; ++i) + SelLocs.push_back(getSelectorLoc(i)); +} + SourceRange ObjCMessageExpr::getReceiverRange() const { switch (getReceiverKind()) { case Instance: diff --git a/clang/lib/AST/SelectorLocationsKind.cpp b/clang/lib/AST/SelectorLocationsKind.cpp new file mode 100644 index 000000000000..cafb105e996a --- /dev/null +++ b/clang/lib/AST/SelectorLocationsKind.cpp @@ -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 +SourceLocation getArgLoc(T* Arg); + +template <> +SourceLocation getArgLoc(Expr *Arg) { + return Arg->getLocStart(); +} + +template +SourceLocation getArgLoc(unsigned Index, ArrayRef Args) { + return Index < Args.size() ? getArgLoc(Args[Index]) : SourceLocation(); +} + +template +SelectorLocationsKind hasStandardSelLocs(Selector Sel, + ArrayRef SelLocs, + ArrayRef 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 SelLocs, + ArrayRef Args, + SourceLocation EndLoc) { + return hasStandardSelLocs(Sel, SelLocs, Args, EndLoc); +} + +SourceLocation clang::getStandardSelectorLoc(unsigned Index, + Selector Sel, + bool WithArgSpace, + ArrayRef Args, + SourceLocation EndLoc) { + return getStandardSelLoc(Index, Sel, WithArgSpace, + getArgLoc(Index, Args), EndLoc); +} diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 824e82b9d33c..d5d073fd6fa6 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -10129,7 +10129,7 @@ static ExprResult diagnoseUnknownAnyExpr(Sema &S, Expr *E) { d = mem->getMemberDecl(); } else if (ObjCMessageExpr *msg = dyn_cast(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) diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 509c450ced7a..99ddd239129f 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -2152,7 +2152,7 @@ public: /// \brief Build a new Objective-C class message. ExprResult RebuildObjCMessageExpr(TypeSourceInfo *ReceiverTypeInfo, Selector Sel, - SourceLocation SelectorLoc, + ArrayRef 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 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::TransformObjCMessageExpr(ObjCMessageExpr *E) { return SemaRef.Owned(E); // Build a new class message send. + SmallVector 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::TransformObjCMessageExpr(ObjCMessageExpr *E) { return SemaRef.Owned(E); // Build a new instance message send. + SmallVector SelLocs; + E->getSelectorLocs(SelLocs); return getDerived().RebuildObjCMessageExpr(Receiver.get(), E->getSelector(), - E->getSelectorLoc(), + SelLocs, E->getMethodDecl(), E->getLeftLoc(), move_arg(Args), diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 0571c10666e9..e2a78e9d1eaf 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -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(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); diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index a8c02a557f02..b7d7afdfa842 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -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; }