[PATCH] Keep track of the operator location of MemberExprs
Joe Ranieri
joe at alacatialabs.com
Sat Mar 7 12:50:15 PST 2015
On Mon, Mar 2, 2015 at 2:51 PM, Kim Gräsman <kim.grasman at gmail.com> wrote:
> Hi Joe,
>
> I was just looking at some code in our tool that works around the lack
> of the operator location, so I would welcome this!
>
> I can't speak to the quality of the change, but the comments on our
> code makes me think you're missing some tests:
I've added a test involving macro expansion and one that verifies that
the operator location is invalid when the MemberExpr is implicit.
-- Joe
-------------- next part --------------
Index: include/clang/AST/Expr.h
===================================================================
--- include/clang/AST/Expr.h (revision 230679)
+++ include/clang/AST/Expr.h (working copy)
@@ -2325,6 +2325,9 @@
/// MemberLoc - This is the location of the member name.
SourceLocation MemberLoc;
+ /// This is the location of the -> or . in the expression.
+ SourceLocation OperatorLoc;
+
/// IsArrow - True if this is "X->F", false if this is "X.F".
bool IsArrow : 1;
@@ -2359,18 +2362,16 @@
}
public:
- MemberExpr(Expr *base, bool isarrow, ValueDecl *memberdecl,
- const DeclarationNameInfo &NameInfo, QualType ty,
- ExprValueKind VK, ExprObjectKind OK)
- : Expr(MemberExprClass, ty, VK, OK,
- base->isTypeDependent(),
- base->isValueDependent(),
- base->isInstantiationDependent(),
- base->containsUnexpandedParameterPack()),
- Base(base), MemberDecl(memberdecl), MemberDNLoc(NameInfo.getInfo()),
- MemberLoc(NameInfo.getLoc()), IsArrow(isarrow),
- HasQualifierOrFoundDecl(false), HasTemplateKWAndArgsInfo(false),
- HadMultipleCandidates(false) {
+ MemberExpr(Expr *base, bool isarrow, SourceLocation operatorloc,
+ ValueDecl *memberdecl, const DeclarationNameInfo &NameInfo,
+ QualType ty, ExprValueKind VK, ExprObjectKind OK)
+ : Expr(MemberExprClass, ty, VK, OK, base->isTypeDependent(),
+ base->isValueDependent(), base->isInstantiationDependent(),
+ base->containsUnexpandedParameterPack()),
+ Base(base), MemberDecl(memberdecl), MemberDNLoc(NameInfo.getInfo()),
+ MemberLoc(NameInfo.getLoc()), OperatorLoc(operatorloc),
+ IsArrow(isarrow), HasQualifierOrFoundDecl(false),
+ HasTemplateKWAndArgsInfo(false), HadMultipleCandidates(false) {
assert(memberdecl->getDeclName() == NameInfo.getName());
}
@@ -2378,25 +2379,25 @@
// the member name can not provide additional syntactic info
// (i.e., source locations for C++ operator names or type source info
// for constructors, destructors and conversion operators).
- MemberExpr(Expr *base, bool isarrow, ValueDecl *memberdecl,
- SourceLocation l, QualType ty,
+ MemberExpr(Expr *base, bool isarrow, SourceLocation operatorloc,
+ ValueDecl *memberdecl, SourceLocation l, QualType ty,
ExprValueKind VK, ExprObjectKind OK)
- : Expr(MemberExprClass, ty, VK, OK,
- base->isTypeDependent(), base->isValueDependent(),
- base->isInstantiationDependent(),
- base->containsUnexpandedParameterPack()),
- Base(base), MemberDecl(memberdecl), MemberDNLoc(), MemberLoc(l),
- IsArrow(isarrow),
- HasQualifierOrFoundDecl(false), HasTemplateKWAndArgsInfo(false),
- HadMultipleCandidates(false) {}
+ : Expr(MemberExprClass, ty, VK, OK, base->isTypeDependent(),
+ base->isValueDependent(), base->isInstantiationDependent(),
+ base->containsUnexpandedParameterPack()),
+ Base(base), MemberDecl(memberdecl), MemberDNLoc(), MemberLoc(l),
+ OperatorLoc(operatorloc), IsArrow(isarrow),
+ HasQualifierOrFoundDecl(false), HasTemplateKWAndArgsInfo(false),
+ HadMultipleCandidates(false) {}
static MemberExpr *Create(const ASTContext &C, Expr *base, bool isarrow,
+ SourceLocation OperatorLoc,
NestedNameSpecifierLoc QualifierLoc,
- SourceLocation TemplateKWLoc,
- ValueDecl *memberdecl, DeclAccessPair founddecl,
+ SourceLocation TemplateKWLoc, ValueDecl *memberdecl,
+ DeclAccessPair founddecl,
DeclarationNameInfo MemberNameInfo,
- const TemplateArgumentListInfo *targs,
- QualType ty, ExprValueKind VK, ExprObjectKind OK);
+ const TemplateArgumentListInfo *targs, QualType ty,
+ ExprValueKind VK, ExprObjectKind OK);
void setBase(Expr *E) { Base = E; }
Expr *getBase() const { return cast<Expr>(Base); }
@@ -2540,6 +2541,8 @@
MemberLoc, MemberDNLoc);
}
+ SourceLocation getOperatorLoc() const LLVM_READONLY { return OperatorLoc; }
+
bool isArrow() const { return IsArrow; }
void setArrow(bool A) { IsArrow = A; }
Index: lib/AST/Expr.cpp
===================================================================
--- lib/AST/Expr.cpp (revision 230679)
+++ lib/AST/Expr.cpp (working copy)
@@ -1403,16 +1403,12 @@
}
}
-MemberExpr *MemberExpr::Create(const ASTContext &C, Expr *base, bool isarrow,
- NestedNameSpecifierLoc QualifierLoc,
- SourceLocation TemplateKWLoc,
- ValueDecl *memberdecl,
- DeclAccessPair founddecl,
- DeclarationNameInfo nameinfo,
- const TemplateArgumentListInfo *targs,
- QualType ty,
- ExprValueKind vk,
- ExprObjectKind ok) {
+MemberExpr *MemberExpr::Create(
+ const ASTContext &C, Expr *base, bool isarrow, SourceLocation OperatorLoc,
+ NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc,
+ ValueDecl *memberdecl, DeclAccessPair founddecl,
+ DeclarationNameInfo nameinfo, const TemplateArgumentListInfo *targs,
+ QualType ty, ExprValueKind vk, ExprObjectKind ok) {
std::size_t Size = sizeof(MemberExpr);
bool hasQualOrFound = (QualifierLoc ||
@@ -1427,8 +1423,8 @@
Size += ASTTemplateKWAndArgsInfo::sizeFor(0);
void *Mem = C.Allocate(Size, llvm::alignOf<MemberExpr>());
- MemberExpr *E = new (Mem) MemberExpr(base, isarrow, memberdecl, nameinfo,
- ty, vk, ok);
+ MemberExpr *E = new (Mem)
+ MemberExpr(base, isarrow, OperatorLoc, memberdecl, nameinfo, ty, vk, ok);
if (hasQualOrFound) {
// FIXME: Wrong. We should be looking at the member declaration we found.
Index: lib/Frontend/Rewrite/RewriteModernObjC.cpp
===================================================================
--- lib/Frontend/Rewrite/RewriteModernObjC.cpp (revision 230679)
+++ lib/Frontend/Rewrite/RewriteModernObjC.cpp (working copy)
@@ -889,9 +889,9 @@
IvarT, nullptr,
/*BitWidth=*/nullptr, /*Mutable=*/true,
ICIS_NoInit);
- MemberExpr *ME = new (Context) MemberExpr(PE, true, FD, SourceLocation(),
- FD->getType(), VK_LValue,
- OK_Ordinary);
+ MemberExpr *ME = new (Context)
+ MemberExpr(PE, true, SourceLocation(), FD, SourceLocation(),
+ FD->getType(), VK_LValue, OK_Ordinary);
IvarT = Context->getDecltypeType(ME, ME->getType());
}
}
@@ -2767,11 +2767,9 @@
Context->getPointerType(Context->VoidPtrTy),
nullptr, /*BitWidth=*/nullptr,
/*Mutable=*/true, ICIS_NoInit);
- MemberExpr *ArrayLiteralME =
- new (Context) MemberExpr(NSArrayCallExpr, false, ARRFD,
- SourceLocation(),
- ARRFD->getType(), VK_LValue,
- OK_Ordinary);
+ MemberExpr *ArrayLiteralME = new (Context)
+ MemberExpr(NSArrayCallExpr, false, SourceLocation(), ARRFD,
+ SourceLocation(), ARRFD->getType(), VK_LValue, OK_Ordinary);
QualType ConstIdT = Context->getObjCIdType().withConst();
CStyleCastExpr * ArrayLiteralObjects =
NoTypeInfoCStyleCastExpr(Context,
@@ -2904,11 +2902,9 @@
Context->getPointerType(Context->VoidPtrTy),
nullptr, /*BitWidth=*/nullptr,
/*Mutable=*/true, ICIS_NoInit);
- MemberExpr *DictLiteralValueME =
- new (Context) MemberExpr(NSValueCallExpr, false, ARRFD,
- SourceLocation(),
- ARRFD->getType(), VK_LValue,
- OK_Ordinary);
+ MemberExpr *DictLiteralValueME = new (Context)
+ MemberExpr(NSValueCallExpr, false, SourceLocation(), ARRFD,
+ SourceLocation(), ARRFD->getType(), VK_LValue, OK_Ordinary);
QualType ConstIdT = Context->getObjCIdType().withConst();
CStyleCastExpr * DictValueObjects =
NoTypeInfoCStyleCastExpr(Context,
@@ -2919,13 +2915,11 @@
Expr *NSKeyCallExpr =
new (Context) CallExpr(*Context, NSDictDRE, KeyExprs,
NSDictFType, VK_LValue, SourceLocation());
-
- MemberExpr *DictLiteralKeyME =
- new (Context) MemberExpr(NSKeyCallExpr, false, ARRFD,
- SourceLocation(),
- ARRFD->getType(), VK_LValue,
- OK_Ordinary);
-
+
+ MemberExpr *DictLiteralKeyME = new (Context)
+ MemberExpr(NSKeyCallExpr, false, SourceLocation(), ARRFD,
+ SourceLocation(), ARRFD->getType(), VK_LValue, OK_Ordinary);
+
CStyleCastExpr * DictKeyObjects =
NoTypeInfoCStyleCastExpr(Context,
Context->getPointerType(ConstIdT),
@@ -3234,9 +3228,9 @@
returnType, nullptr,
/*BitWidth=*/nullptr,
/*Mutable=*/true, ICIS_NoInit);
- MemberExpr *ME = new (Context) MemberExpr(STCE, false, FieldD, SourceLocation(),
- FieldD->getType(), VK_LValue,
- OK_Ordinary);
+ MemberExpr *ME = new (Context)
+ MemberExpr(STCE, false, SourceLocation(), FieldD, SourceLocation(),
+ FieldD->getType(), VK_LValue, OK_Ordinary);
return ME;
}
@@ -4732,11 +4726,10 @@
Context->VoidPtrTy, nullptr,
/*BitWidth=*/nullptr, /*Mutable=*/true,
ICIS_NoInit);
- MemberExpr *ME = new (Context) MemberExpr(PE, true, FD, SourceLocation(),
- FD->getType(), VK_LValue,
- OK_Ordinary);
+ MemberExpr *ME =
+ new (Context) MemberExpr(PE, true, SourceLocation(), FD, SourceLocation(),
+ FD->getType(), VK_LValue, OK_Ordinary);
-
CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType,
CK_BitCast, ME);
PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), FunkCast);
@@ -4781,10 +4774,9 @@
Context->VoidPtrTy, nullptr,
/*BitWidth=*/nullptr, /*Mutable=*/true,
ICIS_NoInit);
- MemberExpr *ME = new (Context) MemberExpr(DeclRefExp, isArrow,
- FD, SourceLocation(),
- FD->getType(), VK_LValue,
- OK_Ordinary);
+ MemberExpr *ME = new (Context)
+ MemberExpr(DeclRefExp, isArrow, SourceLocation(), FD, SourceLocation(),
+ FD->getType(), VK_LValue, OK_Ordinary);
StringRef Name = VD->getName();
FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), SourceLocation(),
@@ -4792,11 +4784,10 @@
Context->VoidPtrTy, nullptr,
/*BitWidth=*/nullptr, /*Mutable=*/true,
ICIS_NoInit);
- ME = new (Context) MemberExpr(ME, true, FD, SourceLocation(),
- DeclRefExp->getType(), VK_LValue, OK_Ordinary);
-
-
-
+ ME =
+ new (Context) MemberExpr(ME, true, SourceLocation(), FD, SourceLocation(),
+ DeclRefExp->getType(), VK_LValue, OK_Ordinary);
+
// Need parens to enforce precedence.
ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(),
DeclRefExp->getExprLoc(),
@@ -7694,9 +7685,9 @@
IvarT, nullptr,
/*BitWidth=*/nullptr,
/*Mutable=*/true, ICIS_NoInit);
- MemberExpr *ME = new (Context) MemberExpr(PE, true, FD, SourceLocation(),
- FD->getType(), VK_LValue,
- OK_Ordinary);
+ MemberExpr *ME = new (Context)
+ MemberExpr(PE, true, SourceLocation(), FD, SourceLocation(),
+ FD->getType(), VK_LValue, OK_Ordinary);
IvarT = Context->getDecltypeType(ME, ME->getType());
}
}
@@ -7723,9 +7714,9 @@
D->getType(), nullptr,
/*BitWidth=*/D->getBitWidth(),
/*Mutable=*/true, ICIS_NoInit);
- MemberExpr *ME = new (Context) MemberExpr(PE, /*isArrow*/false, FD, SourceLocation(),
- FD->getType(), VK_LValue,
- OK_Ordinary);
+ MemberExpr *ME = new (Context)
+ MemberExpr(PE, /*isArrow*/ false, SourceLocation(), FD,
+ SourceLocation(), FD->getType(), VK_LValue, OK_Ordinary);
Replacement = ME;
}
Index: lib/Frontend/Rewrite/RewriteObjC.cpp
===================================================================
--- lib/Frontend/Rewrite/RewriteObjC.cpp (revision 230679)
+++ lib/Frontend/Rewrite/RewriteObjC.cpp (working copy)
@@ -3821,11 +3821,10 @@
Context->VoidPtrTy, nullptr,
/*BitWidth=*/nullptr, /*Mutable=*/true,
ICIS_NoInit);
- MemberExpr *ME = new (Context) MemberExpr(PE, true, FD, SourceLocation(),
- FD->getType(), VK_LValue,
- OK_Ordinary);
+ MemberExpr *ME =
+ new (Context) MemberExpr(PE, true, SourceLocation(), FD, SourceLocation(),
+ FD->getType(), VK_LValue, OK_Ordinary);
-
CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType,
CK_BitCast, ME);
PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), FunkCast);
@@ -3870,10 +3869,9 @@
Context->VoidPtrTy, nullptr,
/*BitWidth=*/nullptr, /*Mutable=*/true,
ICIS_NoInit);
- MemberExpr *ME = new (Context) MemberExpr(DeclRefExp, isArrow,
- FD, SourceLocation(),
- FD->getType(), VK_LValue,
- OK_Ordinary);
+ MemberExpr *ME = new (Context)
+ MemberExpr(DeclRefExp, isArrow, SourceLocation(), FD, SourceLocation(),
+ FD->getType(), VK_LValue, OK_Ordinary);
StringRef Name = VD->getName();
FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), SourceLocation(),
@@ -3881,11 +3879,10 @@
Context->VoidPtrTy, nullptr,
/*BitWidth=*/nullptr, /*Mutable=*/true,
ICIS_NoInit);
- ME = new (Context) MemberExpr(ME, true, FD, SourceLocation(),
- DeclRefExp->getType(), VK_LValue, OK_Ordinary);
-
-
-
+ ME =
+ new (Context) MemberExpr(ME, true, SourceLocation(), FD, SourceLocation(),
+ DeclRefExp->getType(), VK_LValue, OK_Ordinary);
+
// Need parens to enforce precedence.
ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(),
DeclRefExp->getExprLoc(),
@@ -5880,10 +5877,9 @@
castExpr);
if (IV->isFreeIvar() &&
declaresSameEntity(CurMethodDef->getClassInterface(), iFaceDecl->getDecl())) {
- MemberExpr *ME = new (Context) MemberExpr(PE, true, D,
- IV->getLocation(),
- D->getType(),
- VK_LValue, OK_Ordinary);
+ MemberExpr *ME = new (Context)
+ MemberExpr(PE, true, SourceLocation(), D, IV->getLocation(),
+ D->getType(), VK_LValue, OK_Ordinary);
Replacement = ME;
} else {
IV->setBase(PE);
Index: lib/Sema/SemaExprCXX.cpp
===================================================================
--- lib/Sema/SemaExprCXX.cpp (revision 230679)
+++ lib/Sema/SemaExprCXX.cpp (working copy)
@@ -5692,10 +5692,9 @@
if (Exp.isInvalid())
return true;
- MemberExpr *ME =
- new (Context) MemberExpr(Exp.get(), /*IsArrow=*/false, Method,
- SourceLocation(), Context.BoundMemberTy,
- VK_RValue, OK_Ordinary);
+ MemberExpr *ME = new (Context) MemberExpr(
+ Exp.get(), /*IsArrow=*/false, SourceLocation(), Method, SourceLocation(),
+ Context.BoundMemberTy, VK_RValue, OK_Ordinary);
if (HadMultipleCandidates)
ME->setHadMultipleCandidates(true);
MarkMemberReferenced(ME);
Index: lib/Sema/SemaExprMember.cpp
===================================================================
--- lib/Sema/SemaExprMember.cpp (revision 230679)
+++ lib/Sema/SemaExprMember.cpp (working copy)
@@ -732,8 +732,8 @@
static ExprResult
BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow,
- const CXXScopeSpec &SS, FieldDecl *Field,
- DeclAccessPair FoundDecl,
+ SourceLocation OpLoc, const CXXScopeSpec &SS,
+ FieldDecl *Field, DeclAccessPair FoundDecl,
const DeclarationNameInfo &MemberNameInfo);
ExprResult
@@ -820,10 +820,10 @@
// Make a nameInfo that properly uses the anonymous name.
DeclarationNameInfo memberNameInfo(field->getDeclName(), loc);
-
+
result = BuildFieldReferenceExpr(*this, result, baseObjectIsPointer,
- EmptySS, field, foundDecl,
- memberNameInfo).get();
+ SourceLocation(), EmptySS, field,
+ foundDecl, memberNameInfo).get();
if (!result)
return ExprError();
@@ -841,9 +841,10 @@
DeclAccessPair fakeFoundDecl =
DeclAccessPair::make(field, field->getAccess());
- result = BuildFieldReferenceExpr(*this, result, /*isarrow*/ false,
- (FI == FEnd? SS : EmptySS), field,
- fakeFoundDecl, memberNameInfo).get();
+ result =
+ BuildFieldReferenceExpr(*this, result, /*isarrow*/ false,
+ SourceLocation(), (FI == FEnd ? SS : EmptySS),
+ field, fakeFoundDecl, memberNameInfo).get();
}
return result;
@@ -863,18 +864,16 @@
}
/// \brief Build a MemberExpr AST node.
-static MemberExpr *
-BuildMemberExpr(Sema &SemaRef, ASTContext &C, Expr *Base, bool isArrow,
- const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
- ValueDecl *Member, DeclAccessPair FoundDecl,
- const DeclarationNameInfo &MemberNameInfo, QualType Ty,
- ExprValueKind VK, ExprObjectKind OK,
- const TemplateArgumentListInfo *TemplateArgs = nullptr) {
+static MemberExpr *BuildMemberExpr(
+ Sema &SemaRef, ASTContext &C, Expr *Base, bool isArrow,
+ SourceLocation OpLoc, const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+ ValueDecl *Member, DeclAccessPair FoundDecl,
+ const DeclarationNameInfo &MemberNameInfo, QualType Ty, ExprValueKind VK,
+ ExprObjectKind OK, const TemplateArgumentListInfo *TemplateArgs = nullptr) {
assert((!isArrow || Base->isRValue()) && "-> base must be a pointer rvalue");
- MemberExpr *E =
- MemberExpr::Create(C, Base, isArrow, SS.getWithLocInContext(C),
- TemplateKWLoc, Member, FoundDecl, MemberNameInfo,
- TemplateArgs, Ty, VK, OK);
+ MemberExpr *E = MemberExpr::Create(
+ C, Base, isArrow, OpLoc, SS.getWithLocInContext(C), TemplateKWLoc, Member,
+ FoundDecl, MemberNameInfo, TemplateArgs, Ty, VK, OK);
SemaRef.MarkMemberReferenced(E);
return E;
}
@@ -1057,8 +1056,8 @@
return ExprError();
if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl))
- return BuildFieldReferenceExpr(*this, BaseExpr, IsArrow,
- SS, FD, FoundDecl, MemberNameInfo);
+ return BuildFieldReferenceExpr(*this, BaseExpr, IsArrow, OpLoc, SS, FD,
+ FoundDecl, MemberNameInfo);
if (MSPropertyDecl *PD = dyn_cast<MSPropertyDecl>(MemberDecl))
return BuildMSPropertyRefExpr(*this, BaseExpr, IsArrow, SS, PD,
@@ -1072,8 +1071,8 @@
OpLoc);
if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {
- return BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS, TemplateKWLoc,
- Var, FoundDecl, MemberNameInfo,
+ return BuildMemberExpr(*this, Context, BaseExpr, IsArrow, OpLoc, SS,
+ TemplateKWLoc, Var, FoundDecl, MemberNameInfo,
Var->getType().getNonReferenceType(), VK_LValue,
OK_Ordinary);
}
@@ -1089,16 +1088,16 @@
type = MemberFn->getType();
}
- return BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS, TemplateKWLoc,
- MemberFn, FoundDecl, MemberNameInfo, type, valueKind,
- OK_Ordinary);
+ return BuildMemberExpr(*this, Context, BaseExpr, IsArrow, OpLoc, SS,
+ TemplateKWLoc, MemberFn, FoundDecl, MemberNameInfo,
+ type, valueKind, OK_Ordinary);
}
assert(!isa<FunctionDecl>(MemberDecl) && "member function not C++ method?");
if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) {
- return BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS, TemplateKWLoc,
- Enum, FoundDecl, MemberNameInfo, Enum->getType(),
- VK_RValue, OK_Ordinary);
+ return BuildMemberExpr(*this, Context, BaseExpr, IsArrow, OpLoc, SS,
+ TemplateKWLoc, Enum, FoundDecl, MemberNameInfo,
+ Enum->getType(), VK_RValue, OK_Ordinary);
}
// We found something that we didn't expect. Complain.
@@ -1643,8 +1642,8 @@
static ExprResult
BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow,
- const CXXScopeSpec &SS, FieldDecl *Field,
- DeclAccessPair FoundDecl,
+ SourceLocation OpLoc, const CXXScopeSpec &SS,
+ FieldDecl *Field, DeclAccessPair FoundDecl,
const DeclarationNameInfo &MemberNameInfo) {
// x.a is an l-value if 'a' has a reference type. Otherwise:
// x.a is an l-value/x-value/pr-value if the base is (and note
@@ -1697,7 +1696,7 @@
FoundDecl, Field);
if (Base.isInvalid())
return ExprError();
- return BuildMemberExpr(S, S.Context, Base.get(), IsArrow, SS,
+ return BuildMemberExpr(S, S.Context, Base.get(), IsArrow, OpLoc, SS,
/*TemplateKWLoc=*/SourceLocation(), Field, FoundDecl,
MemberNameInfo, MemberType, VK, OK);
}
Index: lib/Sema/SemaOverload.cpp
===================================================================
--- lib/Sema/SemaOverload.cpp (revision 230679)
+++ lib/Sema/SemaOverload.cpp (working copy)
@@ -12491,15 +12491,11 @@
type = Context.BoundMemberTy;
}
- MemberExpr *ME = MemberExpr::Create(Context, Base,
- MemExpr->isArrow(),
- MemExpr->getQualifierLoc(),
- MemExpr->getTemplateKeywordLoc(),
- Fn,
- Found,
- MemExpr->getMemberNameInfo(),
- TemplateArgs,
- type, valueKind, OK_Ordinary);
+ MemberExpr *ME = MemberExpr::Create(
+ Context, Base, MemExpr->isArrow(), MemExpr->getOperatorLoc(),
+ MemExpr->getQualifierLoc(), MemExpr->getTemplateKeywordLoc(), Fn, Found,
+ MemExpr->getMemberNameInfo(), TemplateArgs, type, valueKind,
+ OK_Ordinary);
ME->setHadMultipleCandidates(true);
MarkMemberReferenced(ME);
return ME;
Index: lib/Sema/TreeTransform.h
===================================================================
--- lib/Sema/TreeTransform.h (revision 230679)
+++ lib/Sema/TreeTransform.h (working copy)
@@ -1870,11 +1870,9 @@
return ExprError();
Base = BaseResult.get();
ExprValueKind VK = isArrow ? VK_LValue : Base->getValueKind();
- MemberExpr *ME =
- new (getSema().Context) MemberExpr(Base, isArrow,
- Member, MemberNameInfo,
- cast<FieldDecl>(Member)->getType(),
- VK, OK_Ordinary);
+ MemberExpr *ME = new (getSema().Context)
+ MemberExpr(Base, isArrow, OpLoc, Member, MemberNameInfo,
+ cast<FieldDecl>(Member)->getType(), VK, OK_Ordinary);
return ME;
}
Index: lib/Serialization/ASTReaderStmt.cpp
===================================================================
--- lib/Serialization/ASTReaderStmt.cpp (revision 230679)
+++ lib/Serialization/ASTReaderStmt.cpp (working copy)
@@ -2423,11 +2423,12 @@
SourceLocation MemberLoc = ReadSourceLocation(F, Record, Idx);
DeclarationNameInfo MemberNameInfo(MemberD->getDeclName(), MemberLoc);
bool IsArrow = Record[Idx++];
+ SourceLocation OperatorLoc = ReadSourceLocation(F, Record, Idx);
- S = MemberExpr::Create(Context, Base, IsArrow, QualifierLoc,
+ S = MemberExpr::Create(Context, Base, IsArrow, OperatorLoc, QualifierLoc,
TemplateKWLoc, MemberD, FoundDecl, MemberNameInfo,
- HasTemplateKWAndArgsInfo ? &ArgInfo : nullptr,
- T, VK, OK);
+ HasTemplateKWAndArgsInfo ? &ArgInfo : nullptr, T,
+ VK, OK);
ReadDeclarationNameLoc(F, cast<MemberExpr>(S)->MemberDNLoc,
MemberD->getDeclName(), Record, Idx);
if (HadMultipleCandidates)
Index: lib/Serialization/ASTWriterStmt.cpp
===================================================================
--- lib/Serialization/ASTWriterStmt.cpp (revision 230679)
+++ lib/Serialization/ASTWriterStmt.cpp (working copy)
@@ -555,6 +555,7 @@
Record.push_back(E->isArrow());
Writer.AddDeclarationNameLoc(E->MemberDNLoc,
E->getMemberDecl()->getDeclName(), Record);
+ Writer.AddSourceLocation(E->getOperatorLoc(), Record);
Code = serialization::EXPR_MEMBER;
}
Index: unittests/AST/SourceLocationTest.cpp
===================================================================
--- unittests/AST/SourceLocationTest.cpp (revision 230679)
+++ unittests/AST/SourceLocationTest.cpp (working copy)
@@ -109,6 +109,38 @@
memberExpr()));
}
+class MemberExprArrowLocVerifier : public RangeVerifier<MemberExpr> {
+protected:
+ virtual SourceRange getRange(const MemberExpr &Node) {
+ return Node.getOperatorLoc();
+ }
+};
+
+TEST(MemberExpr, ArrowRange) {
+ MemberExprArrowLocVerifier Verifier;
+ Verifier.expectRange(2, 19, 2, 19);
+ EXPECT_TRUE(Verifier.match("struct S { int x; };\n"
+ "void foo(S *s) { s->x = 0; }",
+ memberExpr()));
+}
+
+TEST(MemberExpr, MacroArrowRange) {
+ MemberExprArrowLocVerifier Verifier;
+ Verifier.expectRange(1, 24, 1, 24);
+ EXPECT_TRUE(Verifier.match("#define MEMBER(a, b) (a->b)\n"
+ "struct S { int x; };\n"
+ "void foo(S *s) { MEMBER(s, x) = 0; }",
+ memberExpr()));
+}
+
+TEST(MemberExpr, ImplicitArrowRange) {
+ MemberExprArrowLocVerifier Verifier;
+ Verifier.expectRange(0, 0, 0, 0);
+ EXPECT_TRUE(Verifier.match("struct S { int x; void Test(); };\n"
+ "void S::Test() { x = 1; }",
+ memberExpr()));
+}
+
TEST(VarDecl, VMTypeFixedVarDeclRange) {
RangeVerifier<VarDecl> Verifier;
Verifier.expectRange(1, 1, 1, 23);
More information about the cfe-commits
mailing list