ASTTemplateKWAndArgsInfo,
TemplateArgumentLoc> {
friend class ASTReader;
+ friend class ASTStmtReader;
friend class ASTStmtWriter;
friend TrailingObjects;
return MemberExprBits.HasTemplateKWAndArgsInfo;
}
+ MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc,
+ ValueDecl *MemberDecl, const DeclarationNameInfo &NameInfo,
+ QualType T, ExprValueKind VK, ExprObjectKind OK);
+ MemberExpr(EmptyShell Empty)
+ : Expr(MemberExprClass, Empty), Base(), MemberDecl() {}
+
public:
- 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()) {
- assert(memberdecl->getDeclName() == NameInfo.getName());
- MemberExprBits.IsArrow = isarrow;
- MemberExprBits.HasQualifierOrFoundDecl = false;
- MemberExprBits.HasTemplateKWAndArgsInfo = false;
- MemberExprBits.HadMultipleCandidates = false;
- MemberExprBits.OperatorLoc = operatorloc;
- }
-
- // NOTE: this constructor should be used only when it is known that
- // 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, 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) {
- MemberExprBits.IsArrow = isarrow;
- MemberExprBits.HasQualifierOrFoundDecl = false;
- MemberExprBits.HasTemplateKWAndArgsInfo = false;
- MemberExprBits.HadMultipleCandidates = false;
- MemberExprBits.OperatorLoc = operatorloc;
- }
-
- static MemberExpr *Create(const ASTContext &C, Expr *base, bool isarrow,
+ 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 *TemplateArgs,
+ QualType T, ExprValueKind VK, ExprObjectKind OK);
+
+ /// Create an implicit MemberExpr, with no location, qualifier, template
+ /// arguments, and so on.
+ static MemberExpr *CreateImplicit(const ASTContext &C, Expr *Base,
+ bool IsArrow, ValueDecl *MemberDecl,
+ QualType T, ExprValueKind VK,
+ ExprObjectKind OK) {
+ return Create(C, Base, IsArrow, SourceLocation(), NestedNameSpecifierLoc(),
+ SourceLocation(), MemberDecl,
+ DeclAccessPair::make(MemberDecl, MemberDecl->getAccess()),
+ DeclarationNameInfo(), nullptr, T, VK, OK);
+ }
+
+ static MemberExpr *CreateEmpty(const ASTContext &Context, bool HasQualifier,
+ bool HasFoundDecl,
+ bool HasTemplateKWAndArgsInfo,
+ unsigned NumTemplateArgs);
void setBase(Expr *E) { Base = E; }
Expr *getBase() const { return cast<Expr>(Base); }
enum { NumCallExprBits = 32 };
class MemberExprBitfields {
+ friend class ASTStmtReader;
friend class MemberExpr;
unsigned : NumExprBits;
if (isa<TranslationUnitDecl>(this) ||
isa<TemplateTypeParmDecl>(this) ||
isa<NonTypeTemplateParmDecl>(this) ||
+ !getDeclContext() ||
!isa<CXXRecordDecl>(getDeclContext()) ||
isInvalidDecl() ||
isa<StaticAssertDecl>(this) ||
}
}
+MemberExpr::MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc,
+ ValueDecl *MemberDecl,
+ const DeclarationNameInfo &NameInfo, QualType T,
+ ExprValueKind VK, ExprObjectKind OK)
+ : Expr(MemberExprClass, T, VK, OK, Base->isTypeDependent(),
+ Base->isValueDependent(), Base->isInstantiationDependent(),
+ Base->containsUnexpandedParameterPack()),
+ Base(Base), MemberDecl(MemberDecl), MemberDNLoc(NameInfo.getInfo()),
+ MemberLoc(NameInfo.getLoc()) {
+ assert(!NameInfo.getName() ||
+ MemberDecl->getDeclName() == NameInfo.getName());
+ MemberExprBits.IsArrow = IsArrow;
+ MemberExprBits.HasQualifierOrFoundDecl = false;
+ MemberExprBits.HasTemplateKWAndArgsInfo = false;
+ MemberExprBits.HadMultipleCandidates = false;
+ MemberExprBits.OperatorLoc = OperatorLoc;
+}
+
MemberExpr *MemberExpr::Create(
- const ASTContext &C, Expr *base, bool isarrow, SourceLocation OperatorLoc,
+ 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) {
-
- bool hasQualOrFound = (QualifierLoc ||
- founddecl.getDecl() != memberdecl ||
- founddecl.getAccess() != memberdecl->getAccess());
-
- bool HasTemplateKWAndArgsInfo = targs || TemplateKWLoc.isValid();
+ ValueDecl *MemberDecl, DeclAccessPair FoundDecl,
+ DeclarationNameInfo NameInfo, const TemplateArgumentListInfo *TemplateArgs,
+ QualType T, ExprValueKind VK, ExprObjectKind OK) {
+ bool HasQualOrFound = QualifierLoc || FoundDecl.getDecl() != MemberDecl ||
+ FoundDecl.getAccess() != MemberDecl->getAccess();
+ bool HasTemplateKWAndArgsInfo = TemplateArgs || TemplateKWLoc.isValid();
std::size_t Size =
totalSizeToAlloc<MemberExprNameQualifier, ASTTemplateKWAndArgsInfo,
- TemplateArgumentLoc>(hasQualOrFound ? 1 : 0,
- HasTemplateKWAndArgsInfo ? 1 : 0,
- targs ? targs->size() : 0);
+ TemplateArgumentLoc>(
+ HasQualOrFound ? 1 : 0, HasTemplateKWAndArgsInfo ? 1 : 0,
+ TemplateArgs ? TemplateArgs->size() : 0);
void *Mem = C.Allocate(Size, alignof(MemberExpr));
MemberExpr *E = new (Mem)
- MemberExpr(base, isarrow, OperatorLoc, memberdecl, nameinfo, ty, vk, ok);
+ MemberExpr(Base, IsArrow, OperatorLoc, MemberDecl, NameInfo, T, VK, OK);
- if (hasQualOrFound) {
+ if (HasQualOrFound) {
// FIXME: Wrong. We should be looking at the member declaration we found.
if (QualifierLoc && QualifierLoc.getNestedNameSpecifier()->isDependent()) {
E->setValueDependent(true);
MemberExprNameQualifier *NQ =
E->getTrailingObjects<MemberExprNameQualifier>();
NQ->QualifierLoc = QualifierLoc;
- NQ->FoundDecl = founddecl;
+ NQ->FoundDecl = FoundDecl;
}
E->MemberExprBits.HasTemplateKWAndArgsInfo =
- (targs || TemplateKWLoc.isValid());
+ TemplateArgs || TemplateKWLoc.isValid();
- if (targs) {
+ if (TemplateArgs) {
bool Dependent = false;
bool InstantiationDependent = false;
bool ContainsUnexpandedParameterPack = false;
E->getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
- TemplateKWLoc, *targs, E->getTrailingObjects<TemplateArgumentLoc>(),
- Dependent, InstantiationDependent, ContainsUnexpandedParameterPack);
+ TemplateKWLoc, *TemplateArgs,
+ E->getTrailingObjects<TemplateArgumentLoc>(), Dependent,
+ InstantiationDependent, ContainsUnexpandedParameterPack);
if (InstantiationDependent)
E->setInstantiationDependent(true);
} else if (TemplateKWLoc.isValid()) {
return E;
}
+MemberExpr *MemberExpr::CreateEmpty(const ASTContext &Context,
+ bool HasQualifier, bool HasFoundDecl,
+ bool HasTemplateKWAndArgsInfo,
+ unsigned NumTemplateArgs) {
+ assert((!NumTemplateArgs || HasTemplateKWAndArgsInfo) &&
+ "template args but no template arg info?");
+ bool HasQualOrFound = HasQualifier || HasFoundDecl;
+ std::size_t Size =
+ totalSizeToAlloc<MemberExprNameQualifier, ASTTemplateKWAndArgsInfo,
+ TemplateArgumentLoc>(HasQualOrFound ? 1 : 0,
+ HasTemplateKWAndArgsInfo ? 1 : 0,
+ NumTemplateArgs);
+ void *Mem = Context.Allocate(Size, alignof(MemberExpr));
+ return new (Mem) MemberExpr(EmptyShell());
+}
+
SourceLocation MemberExpr::getBeginLoc() const {
if (isImplicitAccess()) {
if (hasQualifier())
IvarT, nullptr,
/*BitWidth=*/nullptr, /*Mutable=*/true,
ICIS_NoInit);
- MemberExpr *ME = new (Context)
- MemberExpr(PE, true, SourceLocation(), FD, SourceLocation(),
- FD->getType(), VK_LValue, OK_Ordinary);
+ MemberExpr *ME = MemberExpr::CreateImplicit(
+ *Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary);
IvarT = Context->getDecltypeType(ME, ME->getType());
}
}
Context->getPointerType(Context->VoidPtrTy),
nullptr, /*BitWidth=*/nullptr,
/*Mutable=*/true, ICIS_NoInit);
- MemberExpr *ArrayLiteralME = new (Context)
- MemberExpr(NSArrayCallExpr, false, SourceLocation(), ARRFD,
- SourceLocation(), ARRFD->getType(), VK_LValue, OK_Ordinary);
+ MemberExpr *ArrayLiteralME =
+ MemberExpr::CreateImplicit(*Context, NSArrayCallExpr, false, ARRFD,
+ ARRFD->getType(), VK_LValue, OK_Ordinary);
QualType ConstIdT = Context->getObjCIdType().withConst();
CStyleCastExpr * ArrayLiteralObjects =
NoTypeInfoCStyleCastExpr(Context,
Context->getPointerType(Context->VoidPtrTy),
nullptr, /*BitWidth=*/nullptr,
/*Mutable=*/true, ICIS_NoInit);
- MemberExpr *DictLiteralValueME = new (Context)
- MemberExpr(NSValueCallExpr, false, SourceLocation(), ARRFD,
- SourceLocation(), ARRFD->getType(), VK_LValue, OK_Ordinary);
+ MemberExpr *DictLiteralValueME =
+ MemberExpr::CreateImplicit(*Context, NSValueCallExpr, false, ARRFD,
+ ARRFD->getType(), VK_LValue, OK_Ordinary);
QualType ConstIdT = Context->getObjCIdType().withConst();
CStyleCastExpr * DictValueObjects =
NoTypeInfoCStyleCastExpr(Context,
Expr *NSKeyCallExpr = CallExpr::Create(
*Context, NSDictDRE, KeyExprs, NSDictFType, VK_LValue, SourceLocation());
- MemberExpr *DictLiteralKeyME = new (Context)
- MemberExpr(NSKeyCallExpr, false, SourceLocation(), ARRFD,
- SourceLocation(), ARRFD->getType(), VK_LValue, OK_Ordinary);
+ MemberExpr *DictLiteralKeyME =
+ MemberExpr::CreateImplicit(*Context, NSKeyCallExpr, false, ARRFD,
+ ARRFD->getType(), VK_LValue, OK_Ordinary);
CStyleCastExpr * DictKeyObjects =
NoTypeInfoCStyleCastExpr(Context,
returnType, nullptr,
/*BitWidth=*/nullptr,
/*Mutable=*/true, ICIS_NoInit);
- MemberExpr *ME = new (Context)
- MemberExpr(STCE, false, SourceLocation(), FieldD, SourceLocation(),
- FieldD->getType(), VK_LValue, OK_Ordinary);
+ MemberExpr *ME = MemberExpr::CreateImplicit(
+ *Context, STCE, false, FieldD, FieldD->getType(), VK_LValue, OK_Ordinary);
return ME;
}
Context->VoidPtrTy, nullptr,
/*BitWidth=*/nullptr, /*Mutable=*/true,
ICIS_NoInit);
- MemberExpr *ME =
- new (Context) MemberExpr(PE, true, SourceLocation(), FD, SourceLocation(),
- FD->getType(), VK_LValue, OK_Ordinary);
+ MemberExpr *ME = MemberExpr::CreateImplicit(
+ *Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary);
CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType,
CK_BitCast, ME);
Context->VoidPtrTy, nullptr,
/*BitWidth=*/nullptr, /*Mutable=*/true,
ICIS_NoInit);
- MemberExpr *ME = new (Context)
- MemberExpr(DeclRefExp, isArrow, SourceLocation(), FD, SourceLocation(),
- FD->getType(), VK_LValue, OK_Ordinary);
+ MemberExpr *ME = MemberExpr::CreateImplicit(
+ *Context, DeclRefExp, isArrow, FD, FD->getType(), VK_LValue, OK_Ordinary);
StringRef Name = VD->getName();
FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), SourceLocation(),
Context->VoidPtrTy, nullptr,
/*BitWidth=*/nullptr, /*Mutable=*/true,
ICIS_NoInit);
- ME =
- new (Context) MemberExpr(ME, true, SourceLocation(), FD, SourceLocation(),
- DeclRefExp->getType(), VK_LValue, OK_Ordinary);
+ ME = MemberExpr::CreateImplicit(*Context, ME, true, FD, DeclRefExp->getType(),
+ VK_LValue, OK_Ordinary);
// Need parens to enforce precedence.
ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(),
IvarT, nullptr,
/*BitWidth=*/nullptr,
/*Mutable=*/true, ICIS_NoInit);
- MemberExpr *ME = new (Context)
- MemberExpr(PE, true, SourceLocation(), FD, SourceLocation(),
- FD->getType(), VK_LValue, OK_Ordinary);
+ MemberExpr *ME = MemberExpr::CreateImplicit(
+ *Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary);
IvarT = Context->getDecltypeType(ME, ME->getType());
}
}
D->getType(), nullptr,
/*BitWidth=*/D->getBitWidth(),
/*Mutable=*/true, ICIS_NoInit);
- MemberExpr *ME = new (Context)
- MemberExpr(PE, /*isArrow*/ false, SourceLocation(), FD,
- SourceLocation(), FD->getType(), VK_LValue, OK_Ordinary);
+ MemberExpr *ME =
+ MemberExpr::CreateImplicit(*Context, PE, /*isArrow*/ false, FD,
+ FD->getType(), VK_LValue, OK_Ordinary);
Replacement = ME;
}
Context->VoidPtrTy, nullptr,
/*BitWidth=*/nullptr, /*Mutable=*/true,
ICIS_NoInit);
- MemberExpr *ME =
- new (Context) MemberExpr(PE, true, SourceLocation(), FD, SourceLocation(),
- FD->getType(), VK_LValue, OK_Ordinary);
+ MemberExpr *ME = MemberExpr::CreateImplicit(
+ *Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary);
CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType,
CK_BitCast, ME);
Context->VoidPtrTy, nullptr,
/*BitWidth=*/nullptr, /*Mutable=*/true,
ICIS_NoInit);
- MemberExpr *ME = new (Context)
- MemberExpr(DeclRefExp, isArrow, SourceLocation(), FD, SourceLocation(),
- FD->getType(), VK_LValue, OK_Ordinary);
+ MemberExpr *ME =
+ MemberExpr::CreateImplicit(*Context, DeclRefExp, isArrow, FD,
+ FD->getType(), VK_LValue, OK_Ordinary);
StringRef Name = VD->getName();
FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), SourceLocation(),
Context->VoidPtrTy, nullptr,
/*BitWidth=*/nullptr, /*Mutable=*/true,
ICIS_NoInit);
- ME =
- new (Context) MemberExpr(ME, true, SourceLocation(), FD, SourceLocation(),
- DeclRefExp->getType(), VK_LValue, OK_Ordinary);
+ ME = MemberExpr::CreateImplicit(*Context, ME, true, FD, DeclRefExp->getType(),
+ VK_LValue, OK_Ordinary);
// Need parens to enforce precedence.
ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(),
OldRange.getEnd(),
castExpr);
if (IV->isFreeIvar() &&
- declaresSameEntity(CurMethodDef->getClassInterface(), iFaceDecl->getDecl())) {
- MemberExpr *ME = new (Context)
- MemberExpr(PE, true, SourceLocation(), D, IV->getLocation(),
- D->getType(), VK_LValue, OK_Ordinary);
+ declaresSameEntity(CurMethodDef->getClassInterface(),
+ iFaceDecl->getDecl())) {
+ MemberExpr *ME = MemberExpr::CreateImplicit(
+ *Context, PE, true, D, D->getType(), VK_LValue, OK_Ordinary);
Replacement = ME;
} else {
IV->setBase(PE);
}
}
- MemberExpr *ME = new (Context) MemberExpr(
- Exp.get(), /*IsArrow=*/false, SourceLocation(), Method, SourceLocation(),
- Context.BoundMemberTy, VK_RValue, OK_Ordinary);
+ MemberExpr *ME = MemberExpr::Create(
+ Context, Exp.get(), /*IsArrow=*/false, SourceLocation(),
+ NestedNameSpecifierLoc(), SourceLocation(), Method,
+ DeclAccessPair::make(FoundDecl, FoundDecl->getAccess()),
+ DeclarationNameInfo(), /*TemplateArgs=*/nullptr, Context.BoundMemberTy,
+ VK_RValue, OK_Ordinary);
if (HadMultipleCandidates)
ME->setHadMultipleCandidates(true);
MarkMemberReferenced(ME);
}
void ASTStmtReader::VisitMemberExpr(MemberExpr *E) {
- // Don't call VisitExpr, this is fully initialized at creation.
- assert(E->getStmtClass() == Stmt::MemberExprClass &&
- "It's a subclass, we must advance Idx!");
+ VisitExpr(E);
+
+ bool HasQualifier = Record.readInt();
+ bool HasFoundDecl = Record.readInt();
+ bool HasTemplateInfo = Record.readInt();
+ unsigned NumTemplateArgs = Record.readInt();
+
+ E->Base = Record.readSubExpr();
+ E->MemberDecl = Record.readDeclAs<ValueDecl>();
+ Record.readDeclarationNameLoc(E->MemberDNLoc, E->MemberDecl->getDeclName());
+ E->MemberLoc = Record.readSourceLocation();
+ E->MemberExprBits.IsArrow = Record.readInt();
+ E->MemberExprBits.HasQualifierOrFoundDecl = HasQualifier || HasFoundDecl;
+ E->MemberExprBits.HasTemplateKWAndArgsInfo = HasTemplateInfo;
+ E->MemberExprBits.HadMultipleCandidates = Record.readInt();
+ E->MemberExprBits.OperatorLoc = Record.readSourceLocation();
+
+ if (HasQualifier || HasFoundDecl) {
+ DeclAccessPair FoundDecl;
+ if (HasFoundDecl) {
+ auto *FoundD = Record.readDeclAs<NamedDecl>();
+ auto AS = (AccessSpecifier)Record.readInt();
+ FoundDecl = DeclAccessPair::make(FoundD, AS);
+ } else {
+ FoundDecl = DeclAccessPair::make(E->MemberDecl,
+ E->MemberDecl->getAccess());
+ }
+ E->getTrailingObjects<MemberExprNameQualifier>()->FoundDecl = FoundDecl;
+
+ NestedNameSpecifierLoc QualifierLoc;
+ if (HasQualifier)
+ QualifierLoc = Record.readNestedNameSpecifierLoc();
+ E->getTrailingObjects<MemberExprNameQualifier>()->QualifierLoc =
+ QualifierLoc;
+ }
+
+ if (HasTemplateInfo)
+ ReadTemplateKWAndArgsInfo(
+ *E->getTrailingObjects<ASTTemplateKWAndArgsInfo>(),
+ E->getTrailingObjects<TemplateArgumentLoc>(), NumTemplateArgs);
}
void ASTStmtReader::VisitObjCIsaExpr(ObjCIsaExpr *E) {
Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], Empty);
break;
- case EXPR_MEMBER: {
- // We load everything here and fully initialize it at creation.
- // That way we can use MemberExpr::Create and don't have to duplicate its
- // logic with a MemberExpr::CreateEmpty.
-
- assert(Record.getIdx() == 0);
- NestedNameSpecifierLoc QualifierLoc;
- if (Record.readInt()) { // HasQualifier.
- QualifierLoc = Record.readNestedNameSpecifierLoc();
- }
-
- SourceLocation TemplateKWLoc;
- TemplateArgumentListInfo ArgInfo;
- bool HasTemplateKWAndArgsInfo = Record.readInt();
- if (HasTemplateKWAndArgsInfo) {
- TemplateKWLoc = Record.readSourceLocation();
- unsigned NumTemplateArgs = Record.readInt();
- ArgInfo.setLAngleLoc(Record.readSourceLocation());
- ArgInfo.setRAngleLoc(Record.readSourceLocation());
- for (unsigned i = 0; i != NumTemplateArgs; ++i)
- ArgInfo.addArgument(Record.readTemplateArgumentLoc());
- }
-
- bool HadMultipleCandidates = Record.readInt();
-
- auto *FoundD = Record.readDeclAs<NamedDecl>();
- auto AS = (AccessSpecifier)Record.readInt();
- DeclAccessPair FoundDecl = DeclAccessPair::make(FoundD, AS);
-
- QualType T = Record.readType();
- auto VK = static_cast<ExprValueKind>(Record.readInt());
- auto OK = static_cast<ExprObjectKind>(Record.readInt());
- Expr *Base = ReadSubExpr();
- auto *MemberD = Record.readDeclAs<ValueDecl>();
- SourceLocation MemberLoc = Record.readSourceLocation();
- DeclarationNameInfo MemberNameInfo(MemberD->getDeclName(), MemberLoc);
- bool IsArrow = Record.readInt();
- SourceLocation OperatorLoc = Record.readSourceLocation();
-
- S = MemberExpr::Create(Context, Base, IsArrow, OperatorLoc, QualifierLoc,
- TemplateKWLoc, MemberD, FoundDecl, MemberNameInfo,
- HasTemplateKWAndArgsInfo ? &ArgInfo : nullptr, T,
- VK, OK);
- Record.readDeclarationNameLoc(cast<MemberExpr>(S)->MemberDNLoc,
- MemberD->getDeclName());
- if (HadMultipleCandidates)
- cast<MemberExpr>(S)->setHadMultipleCandidates(true);
+ case EXPR_MEMBER:
+ S = MemberExpr::CreateEmpty(Context, Record[ASTStmtReader::NumExprFields],
+ Record[ASTStmtReader::NumExprFields + 1],
+ Record[ASTStmtReader::NumExprFields + 2],
+ Record[ASTStmtReader::NumExprFields + 3]);
break;
- }
case EXPR_BINARY_OPERATOR:
S = new (Context) BinaryOperator(Empty);
}
void ASTStmtWriter::VisitMemberExpr(MemberExpr *E) {
- // Don't call VisitExpr, we'll write everything here.
-
- Record.push_back(E->hasQualifier());
- if (E->hasQualifier())
- Record.AddNestedNameSpecifierLoc(E->getQualifierLoc());
-
- Record.push_back(E->hasTemplateKWAndArgsInfo());
- if (E->hasTemplateKWAndArgsInfo()) {
- Record.AddSourceLocation(E->getTemplateKeywordLoc());
- unsigned NumTemplateArgs = E->getNumTemplateArgs();
- Record.push_back(NumTemplateArgs);
- Record.AddSourceLocation(E->getLAngleLoc());
- Record.AddSourceLocation(E->getRAngleLoc());
- for (unsigned i=0; i != NumTemplateArgs; ++i)
- Record.AddTemplateArgumentLoc(E->getTemplateArgs()[i]);
- }
+ VisitExpr(E);
- Record.push_back(E->hadMultipleCandidates());
+ bool HasQualifier = E->hasQualifier();
+ bool HasFoundDecl =
+ E->hasQualifierOrFoundDecl() &&
+ (E->getFoundDecl().getDecl() != E->getMemberDecl() ||
+ E->getFoundDecl().getAccess() != E->getMemberDecl()->getAccess());
+ bool HasTemplateInfo = E->hasTemplateKWAndArgsInfo();
+ unsigned NumTemplateArgs = E->getNumTemplateArgs();
- DeclAccessPair FoundDecl = E->getFoundDecl();
- Record.AddDeclRef(FoundDecl.getDecl());
- Record.push_back(FoundDecl.getAccess());
+ // Write these first for easy access when deserializing, as they affect the
+ // size of the MemberExpr.
+ Record.push_back(HasQualifier);
+ Record.push_back(HasFoundDecl);
+ Record.push_back(HasTemplateInfo);
+ Record.push_back(NumTemplateArgs);
- Record.AddTypeRef(E->getType());
- Record.push_back(E->getValueKind());
- Record.push_back(E->getObjectKind());
Record.AddStmt(E->getBase());
Record.AddDeclRef(E->getMemberDecl());
+ Record.AddDeclarationNameLoc(E->MemberDNLoc,
+ E->getMemberDecl()->getDeclName());
Record.AddSourceLocation(E->getMemberLoc());
Record.push_back(E->isArrow());
+ Record.push_back(E->hadMultipleCandidates());
Record.AddSourceLocation(E->getOperatorLoc());
- Record.AddDeclarationNameLoc(E->MemberDNLoc,
- E->getMemberDecl()->getDeclName());
+
+ if (HasFoundDecl) {
+ DeclAccessPair FoundDecl = E->getFoundDecl();
+ Record.AddDeclRef(FoundDecl.getDecl());
+ Record.push_back(FoundDecl.getAccess());
+ }
+
+ if (HasQualifier)
+ Record.AddNestedNameSpecifierLoc(E->getQualifierLoc());
+
+ if (HasTemplateInfo)
+ AddTemplateKWAndArgsInfo(*E->getTrailingObjects<ASTTemplateKWAndArgsInfo>(),
+ E->getTrailingObjects<TemplateArgumentLoc>());
+
Code = serialization::EXPR_MEMBER;
}
static_assert(A<4>().f<0>() == 2, "");
static_assert(A<4>().f<1>() == 1, "");
}
+
+namespace DependentMemberExpr {
+#ifndef NO_ERRORS
+ // This used to mark 'f' invalid without producing any diagnostic. That's a
+ // little hard to detect, but we can make sure that constexpr evaluation
+ // fails when it should.
+ static_assert(A<int>().f() == 1); // expected-error {{static_assert failed}}
+#endif
+}
template<> template<> constexpr int B<0>::w<int> = 7;
template<> template<> constexpr int B<0>::w<float> = 8;
}
+
+namespace DependentMemberExpr {
+ struct Base {
+ constexpr int setstate() { return 0; }
+ };
+ template<typename T> struct A : Base {
+ constexpr int f() { return Base::setstate(); }
+ };
+}