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/DeclObjC.h"
#include "clang/AST/Expr.h" #include "clang/AST/Expr.h"
#include "clang/AST/SelectorLocationsKind.h"
#include "clang/Basic/IdentifierTable.h" #include "clang/Basic/IdentifierTable.h"
namespace clang { namespace clang {
@ -471,6 +472,10 @@ class ObjCMessageExpr : public Expr {
/// \brief Whether this message send is a "delegate init call", /// \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. /// i.e. a call of an init method on self from within an init method.
unsigned IsDelegateInitCall : 1; 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 /// \brief When the message expression is a send to 'super', this is
/// the location of the 'super' keyword. /// the location of the 'super' keyword.
@ -481,9 +486,6 @@ class ObjCMessageExpr : public Expr {
/// referring to the method that we type-checked against. /// referring to the method that we type-checked against.
uintptr_t SelectorOrMethod; uintptr_t SelectorOrMethod;
/// \brief Location of the selector.
SourceLocation SelectorLoc;
/// \brief The source locations of the open and close square /// \brief The source locations of the open and close square
/// brackets ('[' and ']', respectively). /// brackets ('[' and ']', respectively).
SourceLocation LBracLoc, RBracLoc; SourceLocation LBracLoc, RBracLoc;
@ -500,7 +502,8 @@ class ObjCMessageExpr : public Expr {
bool IsInstanceSuper, bool IsInstanceSuper,
QualType SuperType, QualType SuperType,
Selector Sel, Selector Sel,
SourceLocation SelLoc, ArrayRef<SourceLocation> SelLocs,
SelectorLocationsKind SelLocsK,
ObjCMethodDecl *Method, ObjCMethodDecl *Method,
ArrayRef<Expr *> Args, ArrayRef<Expr *> Args,
SourceLocation RBracLoc); SourceLocation RBracLoc);
@ -508,7 +511,8 @@ class ObjCMessageExpr : public Expr {
SourceLocation LBracLoc, SourceLocation LBracLoc,
TypeSourceInfo *Receiver, TypeSourceInfo *Receiver,
Selector Sel, Selector Sel,
SourceLocation SelLoc, ArrayRef<SourceLocation> SelLocs,
SelectorLocationsKind SelLocsK,
ObjCMethodDecl *Method, ObjCMethodDecl *Method,
ArrayRef<Expr *> Args, ArrayRef<Expr *> Args,
SourceLocation RBracLoc); SourceLocation RBracLoc);
@ -516,11 +520,16 @@ class ObjCMessageExpr : public Expr {
SourceLocation LBracLoc, SourceLocation LBracLoc,
Expr *Receiver, Expr *Receiver,
Selector Sel, Selector Sel,
SourceLocation SelLoc, ArrayRef<SourceLocation> SelLocs,
SelectorLocationsKind SelLocsK,
ObjCMethodDecl *Method, ObjCMethodDecl *Method,
ArrayRef<Expr *> Args, ArrayRef<Expr *> Args,
SourceLocation RBracLoc); SourceLocation RBracLoc);
void initArgsAndSelLocs(ArrayRef<Expr *> Args,
ArrayRef<SourceLocation> SelLocs,
SelectorLocationsKind SelLocsK);
/// \brief Retrieve the pointer value of the message receiver. /// \brief Retrieve the pointer value of the message receiver.
void *getReceiverPointer() const { void *getReceiverPointer() const {
return *const_cast<void **>( return *const_cast<void **>(
@ -532,6 +541,40 @@ class ObjCMessageExpr : public Expr {
*reinterpret_cast<void **>(this + 1) = Value; *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: public:
/// \brief The kind of receiver this message is sending to. /// \brief The kind of receiver this message is sending to.
enum ReceiverKind { enum ReceiverKind {
@ -661,7 +704,9 @@ public:
/// ///
/// \param NumArgs The number of message arguments, not including /// \param NumArgs The number of message arguments, not including
/// the receiver. /// 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 /// \brief Determine the kind of receiver that this message is being
/// sent to. /// sent to.
@ -831,7 +876,27 @@ public:
SourceLocation getLeftLoc() const { return LBracLoc; } SourceLocation getLeftLoc() const { return LBracLoc; }
SourceLocation getRightLoc() const { return RBracLoc; } 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) { void setSourceRange(SourceRange R) {
LBracLoc = R.getBegin(); 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 ParentMap.cpp
RecordLayout.cpp RecordLayout.cpp
RecordLayoutBuilder.cpp RecordLayoutBuilder.cpp
SelectorLocationsKind.cpp
Stmt.cpp Stmt.cpp
StmtDumper.cpp StmtDumper.cpp
StmtIterator.cpp StmtIterator.cpp

View File

@ -2716,7 +2716,8 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T,
bool IsInstanceSuper, bool IsInstanceSuper,
QualType SuperType, QualType SuperType,
Selector Sel, Selector Sel,
SourceLocation SelLoc, ArrayRef<SourceLocation> SelLocs,
SelectorLocationsKind SelLocsK,
ObjCMethodDecl *Method, ObjCMethodDecl *Method,
ArrayRef<Expr *> Args, ArrayRef<Expr *> Args,
SourceLocation RBracLoc) SourceLocation RBracLoc)
@ -2728,12 +2729,10 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T,
HasMethod(Method != 0), IsDelegateInitCall(false), SuperLoc(SuperLoc), HasMethod(Method != 0), IsDelegateInitCall(false), SuperLoc(SuperLoc),
SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method
: Sel.getAsOpaquePtr())), : Sel.getAsOpaquePtr())),
SelectorLoc(SelLoc), LBracLoc(LBracLoc), RBracLoc(RBracLoc) LBracLoc(LBracLoc), RBracLoc(RBracLoc)
{ {
setNumArgs(Args.size()); initArgsAndSelLocs(Args, SelLocs, SelLocsK);
setReceiverPointer(SuperType.getAsOpaquePtr()); setReceiverPointer(SuperType.getAsOpaquePtr());
if (!Args.empty())
std::copy(Args.begin(), Args.end(), getArgs());
} }
ObjCMessageExpr::ObjCMessageExpr(QualType T, ObjCMessageExpr::ObjCMessageExpr(QualType T,
@ -2741,7 +2740,8 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T,
SourceLocation LBracLoc, SourceLocation LBracLoc,
TypeSourceInfo *Receiver, TypeSourceInfo *Receiver,
Selector Sel, Selector Sel,
SourceLocation SelLoc, ArrayRef<SourceLocation> SelLocs,
SelectorLocationsKind SelLocsK,
ObjCMethodDecl *Method, ObjCMethodDecl *Method,
ArrayRef<Expr *> Args, ArrayRef<Expr *> Args,
SourceLocation RBracLoc) SourceLocation RBracLoc)
@ -2752,23 +2752,10 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T,
HasMethod(Method != 0), IsDelegateInitCall(false), HasMethod(Method != 0), IsDelegateInitCall(false),
SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method
: Sel.getAsOpaquePtr())), : Sel.getAsOpaquePtr())),
SelectorLoc(SelLoc), LBracLoc(LBracLoc), RBracLoc(RBracLoc) LBracLoc(LBracLoc), RBracLoc(RBracLoc)
{ {
setNumArgs(Args.size()); initArgsAndSelLocs(Args, SelLocs, SelLocsK);
setReceiverPointer(Receiver); 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, ObjCMessageExpr::ObjCMessageExpr(QualType T,
@ -2776,7 +2763,8 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T,
SourceLocation LBracLoc, SourceLocation LBracLoc,
Expr *Receiver, Expr *Receiver,
Selector Sel, Selector Sel,
SourceLocation SelLoc, ArrayRef<SourceLocation> SelLocs,
SelectorLocationsKind SelLocsK,
ObjCMethodDecl *Method, ObjCMethodDecl *Method,
ArrayRef<Expr *> Args, ArrayRef<Expr *> Args,
SourceLocation RBracLoc) SourceLocation RBracLoc)
@ -2788,10 +2776,16 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T,
HasMethod(Method != 0), IsDelegateInitCall(false), HasMethod(Method != 0), IsDelegateInitCall(false),
SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method
: Sel.getAsOpaquePtr())), : Sel.getAsOpaquePtr())),
SelectorLoc(SelLoc), LBracLoc(LBracLoc), RBracLoc(RBracLoc) LBracLoc(LBracLoc), RBracLoc(RBracLoc)
{ {
setNumArgs(Args.size()); initArgsAndSelLocs(Args, SelLocs, SelLocsK);
setReceiverPointer(Receiver); setReceiverPointer(Receiver);
}
void ObjCMessageExpr::initArgsAndSelLocs(ArrayRef<Expr *> Args,
ArrayRef<SourceLocation> SelLocs,
SelectorLocationsKind SelLocsK) {
setNumArgs(Args.size());
Expr **MyArgs = getArgs(); Expr **MyArgs = getArgs();
for (unsigned I = 0; I != Args.size(); ++I) { for (unsigned I = 0; I != Args.size(); ++I) {
if (Args[I]->isTypeDependent()) if (Args[I]->isTypeDependent())
@ -2805,6 +2799,10 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T,
MyArgs[I] = Args[I]; MyArgs[I] = Args[I];
} }
SelLocsKind = SelLocsK;
if (SelLocsK == SelLoc_NonStandard)
std::copy(SelLocs.begin(), SelLocs.end(), getStoredSelLocs());
} }
ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T, ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T,
@ -2818,12 +2816,11 @@ ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T,
ObjCMethodDecl *Method, ObjCMethodDecl *Method,
ArrayRef<Expr *> Args, ArrayRef<Expr *> Args,
SourceLocation RBracLoc) { SourceLocation RBracLoc) {
unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) + SelectorLocationsKind SelLocsK;
Args.size() * sizeof(Expr *); ObjCMessageExpr *Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK);
void *Mem = Context.Allocate(Size, llvm::AlignOf<ObjCMessageExpr>::Alignment);
return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, SuperLoc, IsInstanceSuper, return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, SuperLoc, IsInstanceSuper,
SuperType, Sel, SelLocs.front(), Method, SuperType, Sel, SelLocs, SelLocsK,
Args, RBracLoc); Method, Args, RBracLoc);
} }
ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T, ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T,
@ -2835,12 +2832,10 @@ ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T,
ObjCMethodDecl *Method, ObjCMethodDecl *Method,
ArrayRef<Expr *> Args, ArrayRef<Expr *> Args,
SourceLocation RBracLoc) { SourceLocation RBracLoc) {
unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) + SelectorLocationsKind SelLocsK;
Args.size() * sizeof(Expr *); ObjCMessageExpr *Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK);
void *Mem = Context.Allocate(Size, llvm::AlignOf<ObjCMessageExpr>::Alignment);
return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel, return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel,
SelLocs.front(), SelLocs, SelLocsK, Method, Args, RBracLoc);
Method, Args, RBracLoc);
} }
ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T, ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T,
@ -2852,22 +2847,46 @@ ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T,
ObjCMethodDecl *Method, ObjCMethodDecl *Method,
ArrayRef<Expr *> Args, ArrayRef<Expr *> Args,
SourceLocation RBracLoc) { SourceLocation RBracLoc) {
unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) + SelectorLocationsKind SelLocsK;
Args.size() * sizeof(Expr *); ObjCMessageExpr *Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK);
void *Mem = Context.Allocate(Size, llvm::AlignOf<ObjCMessageExpr>::Alignment);
return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel, return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel,
SelLocs.front(), SelLocs, SelLocsK, Method, Args, RBracLoc);
Method, Args, RBracLoc);
} }
ObjCMessageExpr *ObjCMessageExpr::CreateEmpty(ASTContext &Context, ObjCMessageExpr *ObjCMessageExpr::CreateEmpty(ASTContext &Context,
unsigned NumArgs) { unsigned NumArgs,
unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) + unsigned NumStoredSelLocs) {
NumArgs * sizeof(Expr *); ObjCMessageExpr *Mem = alloc(Context, NumArgs, NumStoredSelLocs);
void *Mem = Context.Allocate(Size, llvm::AlignOf<ObjCMessageExpr>::Alignment);
return new (Mem) ObjCMessageExpr(EmptyShell(), NumArgs); 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 { SourceRange ObjCMessageExpr::getReceiverRange() const {
switch (getReceiverKind()) { switch (getReceiverKind()) {
case Instance: 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(); d = mem->getMemberDecl();
} else if (ObjCMessageExpr *msg = dyn_cast<ObjCMessageExpr>(E)) { } else if (ObjCMessageExpr *msg = dyn_cast<ObjCMessageExpr>(E)) {
diagID = diag::err_uncasted_call_of_unknown_any; diagID = diag::err_uncasted_call_of_unknown_any;
loc = msg->getSelectorLoc(); loc = msg->getSelectorStartLoc();
d = msg->getMethodDecl(); d = msg->getMethodDecl();
if (!d) { if (!d) {
S.Diag(loc, diag::err_uncasted_send_to_unknown_any_method) 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. /// \brief Build a new Objective-C class message.
ExprResult RebuildObjCMessageExpr(TypeSourceInfo *ReceiverTypeInfo, ExprResult RebuildObjCMessageExpr(TypeSourceInfo *ReceiverTypeInfo,
Selector Sel, Selector Sel,
SourceLocation SelectorLoc, ArrayRef<SourceLocation> SelectorLocs,
ObjCMethodDecl *Method, ObjCMethodDecl *Method,
SourceLocation LBracLoc, SourceLocation LBracLoc,
MultiExprArg Args, MultiExprArg Args,
@ -2160,14 +2160,14 @@ public:
return SemaRef.BuildClassMessage(ReceiverTypeInfo, return SemaRef.BuildClassMessage(ReceiverTypeInfo,
ReceiverTypeInfo->getType(), ReceiverTypeInfo->getType(),
/*SuperLoc=*/SourceLocation(), /*SuperLoc=*/SourceLocation(),
Sel, Method, LBracLoc, SelectorLoc, Sel, Method, LBracLoc, SelectorLocs,
RBracLoc, move(Args)); RBracLoc, move(Args));
} }
/// \brief Build a new Objective-C instance message. /// \brief Build a new Objective-C instance message.
ExprResult RebuildObjCMessageExpr(Expr *Receiver, ExprResult RebuildObjCMessageExpr(Expr *Receiver,
Selector Sel, Selector Sel,
SourceLocation SelectorLoc, ArrayRef<SourceLocation> SelectorLocs,
ObjCMethodDecl *Method, ObjCMethodDecl *Method,
SourceLocation LBracLoc, SourceLocation LBracLoc,
MultiExprArg Args, MultiExprArg Args,
@ -2175,7 +2175,7 @@ public:
return SemaRef.BuildInstanceMessage(Receiver, return SemaRef.BuildInstanceMessage(Receiver,
Receiver->getType(), Receiver->getType(),
/*SuperLoc=*/SourceLocation(), /*SuperLoc=*/SourceLocation(),
Sel, Method, LBracLoc, SelectorLoc, Sel, Method, LBracLoc, SelectorLocs,
RBracLoc, move(Args)); RBracLoc, move(Args));
} }
@ -7794,9 +7794,11 @@ TreeTransform<Derived>::TransformObjCMessageExpr(ObjCMessageExpr *E) {
return SemaRef.Owned(E); return SemaRef.Owned(E);
// Build a new class message send. // Build a new class message send.
SmallVector<SourceLocation, 16> SelLocs;
E->getSelectorLocs(SelLocs);
return getDerived().RebuildObjCMessageExpr(ReceiverTypeInfo, return getDerived().RebuildObjCMessageExpr(ReceiverTypeInfo,
E->getSelector(), E->getSelector(),
E->getSelectorLoc(), SelLocs,
E->getMethodDecl(), E->getMethodDecl(),
E->getLeftLoc(), E->getLeftLoc(),
move_arg(Args), move_arg(Args),
@ -7817,9 +7819,11 @@ TreeTransform<Derived>::TransformObjCMessageExpr(ObjCMessageExpr *E) {
return SemaRef.Owned(E); return SemaRef.Owned(E);
// Build a new instance message send. // Build a new instance message send.
SmallVector<SourceLocation, 16> SelLocs;
E->getSelectorLocs(SelLocs);
return getDerived().RebuildObjCMessageExpr(Receiver.get(), return getDerived().RebuildObjCMessageExpr(Receiver.get(),
E->getSelector(), E->getSelector(),
E->getSelectorLoc(), SelLocs,
E->getMethodDecl(), E->getMethodDecl(),
E->getLeftLoc(), E->getLeftLoc(),
move_arg(Args), move_arg(Args),

View File

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

View File

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