[AST] Pack CXXDependentScopeMemberExpr

Use the newly available space in the bit-fields of Stmt. Additionally store
FirstQualifierFoundInScope as a trailing object since it is most of the time
null (non-null for 2 of the 35446 CXXDependentScopeMemberExpr when parsing
all of Boost).

It would be possible to move the data for the nested-name-specifier to a
trailing object too to save another 2 pointers, however doing so did actually
regress the time taken to parse all of Boost slightly.

This saves 8 bytes + 1 pointer per CXXDependentScopeMemberExpr in the vast
majority of cases.

Differential Revision: https://reviews.llvm.org/D56367

Reviewed By: rjmccall

llvm-svn: 350625
This commit is contained in:
Bruno Ricci 2019-01-08 14:17:00 +00:00
parent efb5ad1c58
commit 2e6dc538be
5 changed files with 189 additions and 128 deletions

View File

@ -3306,7 +3306,11 @@ class CXXDependentScopeMemberExpr final
: public Expr, : public Expr,
private llvm::TrailingObjects<CXXDependentScopeMemberExpr, private llvm::TrailingObjects<CXXDependentScopeMemberExpr,
ASTTemplateKWAndArgsInfo, ASTTemplateKWAndArgsInfo,
TemplateArgumentLoc> { TemplateArgumentLoc, NamedDecl *> {
friend class ASTStmtReader;
friend class ASTStmtWriter;
friend TrailingObjects;
/// The expression for the base pointer or class reference, /// The expression for the base pointer or class reference,
/// e.g., the \c x in x.f. Can be null in implicit accesses. /// e.g., the \c x in x.f. Can be null in implicit accesses.
Stmt *Base; Stmt *Base;
@ -3315,40 +3319,53 @@ class CXXDependentScopeMemberExpr final
/// implicit accesses. /// implicit accesses.
QualType BaseType; QualType BaseType;
/// Whether this member expression used the '->' operator or
/// the '.' operator.
bool IsArrow : 1;
/// Whether this member expression has info for explicit template
/// keyword and arguments.
bool HasTemplateKWAndArgsInfo : 1;
/// The location of the '->' or '.' operator.
SourceLocation OperatorLoc;
/// The nested-name-specifier that precedes the member name, if any. /// The nested-name-specifier that precedes the member name, if any.
/// FIXME: This could be in principle store as a trailing object.
/// However the performance impact of doing so should be investigated first.
NestedNameSpecifierLoc QualifierLoc; NestedNameSpecifierLoc QualifierLoc;
/// In a qualified member access expression such as t->Base::f, this
/// member stores the resolves of name lookup in the context of the member
/// access expression, to be used at instantiation time.
///
/// FIXME: This member, along with the QualifierLoc, could
/// be stuck into a structure that is optionally allocated at the end of
/// the CXXDependentScopeMemberExpr, to save space in the common case.
NamedDecl *FirstQualifierFoundInScope;
/// The member to which this member expression refers, which /// The member to which this member expression refers, which
/// can be name, overloaded operator, or destructor. /// can be name, overloaded operator, or destructor.
/// ///
/// FIXME: could also be a template-id /// FIXME: could also be a template-id
DeclarationNameInfo MemberNameInfo; DeclarationNameInfo MemberNameInfo;
size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { // CXXDependentScopeMemberExpr is followed by several trailing objects,
return HasTemplateKWAndArgsInfo ? 1 : 0; // some of which optional. They are in order:
//
// * An optional ASTTemplateKWAndArgsInfo for the explicitly specified
// template keyword and arguments. Present if and only if
// hasTemplateKWAndArgsInfo().
//
// * An array of getNumTemplateArgs() TemplateArgumentLoc containing location
// information for the explicitly specified template arguments.
//
// * An optional NamedDecl *. In a qualified member access expression such
// as t->Base::f, this member stores the resolves of name lookup in the
// context of the member access expression, to be used at instantiation
// time. Present if and only if hasFirstQualifierFoundInScope().
bool hasTemplateKWAndArgsInfo() const {
return CXXDependentScopeMemberExprBits.HasTemplateKWAndArgsInfo;
} }
CXXDependentScopeMemberExpr(const ASTContext &C, Expr *Base, bool hasFirstQualifierFoundInScope() const {
return CXXDependentScopeMemberExprBits.HasFirstQualifierFoundInScope;
}
unsigned numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
return hasTemplateKWAndArgsInfo();
}
unsigned numTrailingObjects(OverloadToken<TemplateArgumentLoc>) const {
return getNumTemplateArgs();
}
unsigned numTrailingObjects(OverloadToken<NamedDecl *>) const {
return hasFirstQualifierFoundInScope();
}
CXXDependentScopeMemberExpr(const ASTContext &Ctx, Expr *Base,
QualType BaseType, bool IsArrow, QualType BaseType, bool IsArrow,
SourceLocation OperatorLoc, SourceLocation OperatorLoc,
NestedNameSpecifierLoc QualifierLoc, NestedNameSpecifierLoc QualifierLoc,
@ -3357,33 +3374,29 @@ class CXXDependentScopeMemberExpr final
DeclarationNameInfo MemberNameInfo, DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs); const TemplateArgumentListInfo *TemplateArgs);
CXXDependentScopeMemberExpr(EmptyShell Empty, bool HasTemplateKWAndArgsInfo,
bool HasFirstQualifierFoundInScope);
public: public:
friend class ASTStmtReader;
friend class ASTStmtWriter;
friend TrailingObjects;
CXXDependentScopeMemberExpr(const ASTContext &C, Expr *Base,
QualType BaseType, bool IsArrow,
SourceLocation OperatorLoc,
NestedNameSpecifierLoc QualifierLoc,
NamedDecl *FirstQualifierFoundInScope,
DeclarationNameInfo MemberNameInfo);
static CXXDependentScopeMemberExpr * static CXXDependentScopeMemberExpr *
Create(const ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, Create(const ASTContext &Ctx, Expr *Base, QualType BaseType, bool IsArrow,
SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope, SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope,
DeclarationNameInfo MemberNameInfo, DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs); const TemplateArgumentListInfo *TemplateArgs);
static CXXDependentScopeMemberExpr * static CXXDependentScopeMemberExpr *
CreateEmpty(const ASTContext &C, bool HasTemplateKWAndArgsInfo, CreateEmpty(const ASTContext &Ctx, bool HasTemplateKWAndArgsInfo,
unsigned NumTemplateArgs); unsigned NumTemplateArgs, bool HasFirstQualifierFoundInScope);
/// True if this is an implicit access, i.e. one in which the /// True if this is an implicit access, i.e. one in which the
/// member being accessed was not written in the source. The source /// member being accessed was not written in the source. The source
/// location of the operator is invalid in this case. /// location of the operator is invalid in this case.
bool isImplicitAccess() const; bool isImplicitAccess() const {
if (!Base)
return true;
return cast<Expr>(Base)->isImplicitCXXThis();
}
/// Retrieve the base object of this member expressions, /// Retrieve the base object of this member expressions,
/// e.g., the \c x in \c x.m. /// e.g., the \c x in \c x.m.
@ -3396,13 +3409,14 @@ public:
/// Determine whether this member expression used the '->' /// Determine whether this member expression used the '->'
/// operator; otherwise, it used the '.' operator. /// operator; otherwise, it used the '.' operator.
bool isArrow() const { return IsArrow; } bool isArrow() const { return CXXDependentScopeMemberExprBits.IsArrow; }
/// Retrieve the location of the '->' or '.' operator. /// Retrieve the location of the '->' or '.' operator.
SourceLocation getOperatorLoc() const { return OperatorLoc; } SourceLocation getOperatorLoc() const {
return CXXDependentScopeMemberExprBits.OperatorLoc;
}
/// Retrieve the nested-name-specifier that qualifies the member /// Retrieve the nested-name-specifier that qualifies the member name.
/// name.
NestedNameSpecifier *getQualifier() const { NestedNameSpecifier *getQualifier() const {
return QualifierLoc.getNestedNameSpecifier(); return QualifierLoc.getNestedNameSpecifier();
} }
@ -3423,17 +3437,17 @@ public:
/// combined with the results of name lookup into the type of the object /// combined with the results of name lookup into the type of the object
/// expression itself (the class type of x). /// expression itself (the class type of x).
NamedDecl *getFirstQualifierFoundInScope() const { NamedDecl *getFirstQualifierFoundInScope() const {
return FirstQualifierFoundInScope; if (!hasFirstQualifierFoundInScope())
return nullptr;
return *getTrailingObjects<NamedDecl *>();
} }
/// Retrieve the name of the member that this expression /// Retrieve the name of the member that this expression refers to.
/// refers to.
const DeclarationNameInfo &getMemberNameInfo() const { const DeclarationNameInfo &getMemberNameInfo() const {
return MemberNameInfo; return MemberNameInfo;
} }
/// Retrieve the name of the member that this expression /// Retrieve the name of the member that this expression refers to.
/// refers to.
DeclarationName getMember() const { return MemberNameInfo.getName(); } DeclarationName getMember() const { return MemberNameInfo.getName(); }
// Retrieve the location of the name of the member that this // Retrieve the location of the name of the member that this
@ -3443,21 +3457,24 @@ public:
/// Retrieve the location of the template keyword preceding the /// Retrieve the location of the template keyword preceding the
/// member name, if any. /// member name, if any.
SourceLocation getTemplateKeywordLoc() const { SourceLocation getTemplateKeywordLoc() const {
if (!HasTemplateKWAndArgsInfo) return SourceLocation(); if (!hasTemplateKWAndArgsInfo())
return SourceLocation();
return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc; return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc;
} }
/// Retrieve the location of the left angle bracket starting the /// Retrieve the location of the left angle bracket starting the
/// explicit template argument list following the member name, if any. /// explicit template argument list following the member name, if any.
SourceLocation getLAngleLoc() const { SourceLocation getLAngleLoc() const {
if (!HasTemplateKWAndArgsInfo) return SourceLocation(); if (!hasTemplateKWAndArgsInfo())
return SourceLocation();
return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc; return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc;
} }
/// Retrieve the location of the right angle bracket ending the /// Retrieve the location of the right angle bracket ending the
/// explicit template argument list following the member name, if any. /// explicit template argument list following the member name, if any.
SourceLocation getRAngleLoc() const { SourceLocation getRAngleLoc() const {
if (!HasTemplateKWAndArgsInfo) return SourceLocation(); if (!hasTemplateKWAndArgsInfo())
return SourceLocation();
return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc; return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc;
} }

View File

@ -738,6 +738,28 @@ protected:
unsigned NumArgs; unsigned NumArgs;
}; };
class CXXDependentScopeMemberExprBitfields {
friend class ASTStmtReader;
friend class CXXDependentScopeMemberExpr;
unsigned : NumExprBits;
/// Whether this member expression used the '->' operator or
/// the '.' operator.
unsigned IsArrow : 1;
/// Whether this member expression has info for explicit template
/// keyword and arguments.
unsigned HasTemplateKWAndArgsInfo : 1;
/// See getFirstQualifierFoundInScope() and the comment listing
/// the trailing objects.
unsigned HasFirstQualifierFoundInScope : 1;
/// The location of the '->' or '.' operator.
SourceLocation OperatorLoc;
};
//===--- C++ Coroutines TS bitfields classes ---===// //===--- C++ Coroutines TS bitfields classes ---===//
class CoawaitExprBitfields { class CoawaitExprBitfields {
@ -825,6 +847,7 @@ protected:
CXXConstructExprBitfields CXXConstructExprBits; CXXConstructExprBitfields CXXConstructExprBits;
ExprWithCleanupsBitfields ExprWithCleanupsBits; ExprWithCleanupsBitfields ExprWithCleanupsBits;
CXXUnresolvedConstructExprBitfields CXXUnresolvedConstructExprBits; CXXUnresolvedConstructExprBitfields CXXUnresolvedConstructExprBits;
CXXDependentScopeMemberExprBitfields CXXDependentScopeMemberExprBits;
// C++ Coroutines TS expressions // C++ Coroutines TS expressions
CoawaitExprBitfields CoawaitBits; CoawaitExprBitfields CoawaitBits;

View File

@ -1301,24 +1301,26 @@ SourceLocation CXXUnresolvedConstructExpr::getBeginLoc() const {
} }
CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr( CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(
const ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, const ASTContext &Ctx, Expr *Base, QualType BaseType, bool IsArrow,
SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope, SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope,
DeclarationNameInfo MemberNameInfo, DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs) const TemplateArgumentListInfo *TemplateArgs)
: Expr(CXXDependentScopeMemberExprClass, C.DependentTy, VK_LValue, : Expr(CXXDependentScopeMemberExprClass, Ctx.DependentTy, VK_LValue,
OK_Ordinary, true, true, true, OK_Ordinary, true, true, true,
((Base && Base->containsUnexpandedParameterPack()) || ((Base && Base->containsUnexpandedParameterPack()) ||
(QualifierLoc && (QualifierLoc && QualifierLoc.getNestedNameSpecifier()
QualifierLoc.getNestedNameSpecifier() ->containsUnexpandedParameterPack()) ||
->containsUnexpandedParameterPack()) ||
MemberNameInfo.containsUnexpandedParameterPack())), MemberNameInfo.containsUnexpandedParameterPack())),
Base(Base), BaseType(BaseType), IsArrow(IsArrow), Base(Base), BaseType(BaseType), QualifierLoc(QualifierLoc),
HasTemplateKWAndArgsInfo(TemplateArgs != nullptr ||
TemplateKWLoc.isValid()),
OperatorLoc(OperatorLoc), QualifierLoc(QualifierLoc),
FirstQualifierFoundInScope(FirstQualifierFoundInScope),
MemberNameInfo(MemberNameInfo) { MemberNameInfo(MemberNameInfo) {
CXXDependentScopeMemberExprBits.IsArrow = IsArrow;
CXXDependentScopeMemberExprBits.HasTemplateKWAndArgsInfo =
(TemplateArgs != nullptr) || TemplateKWLoc.isValid();
CXXDependentScopeMemberExprBits.HasFirstQualifierFoundInScope =
FirstQualifierFoundInScope != nullptr;
CXXDependentScopeMemberExprBits.OperatorLoc = OperatorLoc;
if (TemplateArgs) { if (TemplateArgs) {
bool Dependent = true; bool Dependent = true;
bool InstantiationDependent = true; bool InstantiationDependent = true;
@ -1332,56 +1334,54 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(
getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom( getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
TemplateKWLoc); TemplateKWLoc);
} }
if (hasFirstQualifierFoundInScope())
*getTrailingObjects<NamedDecl *>() = FirstQualifierFoundInScope;
} }
CXXDependentScopeMemberExpr * CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(
CXXDependentScopeMemberExpr::Create(const ASTContext &C, EmptyShell Empty, bool HasTemplateKWAndArgsInfo,
Expr *Base, QualType BaseType, bool IsArrow, bool HasFirstQualifierFoundInScope)
SourceLocation OperatorLoc, : Expr(CXXDependentScopeMemberExprClass, Empty) {
NestedNameSpecifierLoc QualifierLoc, CXXDependentScopeMemberExprBits.HasTemplateKWAndArgsInfo =
SourceLocation TemplateKWLoc, HasTemplateKWAndArgsInfo;
NamedDecl *FirstQualifierFoundInScope, CXXDependentScopeMemberExprBits.HasFirstQualifierFoundInScope =
DeclarationNameInfo MemberNameInfo, HasFirstQualifierFoundInScope;
const TemplateArgumentListInfo *TemplateArgs) { }
bool HasTemplateKWAndArgsInfo = TemplateArgs || TemplateKWLoc.isValid();
CXXDependentScopeMemberExpr *CXXDependentScopeMemberExpr::Create(
const ASTContext &Ctx, Expr *Base, QualType BaseType, bool IsArrow,
SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope,
DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs) {
bool HasTemplateKWAndArgsInfo =
(TemplateArgs != nullptr) || TemplateKWLoc.isValid();
unsigned NumTemplateArgs = TemplateArgs ? TemplateArgs->size() : 0; unsigned NumTemplateArgs = TemplateArgs ? TemplateArgs->size() : 0;
std::size_t Size = bool HasFirstQualifierFoundInScope = FirstQualifierFoundInScope != nullptr;
totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
HasTemplateKWAndArgsInfo, NumTemplateArgs);
void *Mem = C.Allocate(Size, alignof(CXXDependentScopeMemberExpr)); unsigned Size = totalSizeToAlloc<ASTTemplateKWAndArgsInfo,
return new (Mem) CXXDependentScopeMemberExpr(C, Base, BaseType, TemplateArgumentLoc, NamedDecl *>(
IsArrow, OperatorLoc, HasTemplateKWAndArgsInfo, NumTemplateArgs, HasFirstQualifierFoundInScope);
QualifierLoc,
TemplateKWLoc, void *Mem = Ctx.Allocate(Size, alignof(CXXDependentScopeMemberExpr));
FirstQualifierFoundInScope, return new (Mem) CXXDependentScopeMemberExpr(
MemberNameInfo, TemplateArgs); Ctx, Base, BaseType, IsArrow, OperatorLoc, QualifierLoc, TemplateKWLoc,
FirstQualifierFoundInScope, MemberNameInfo, TemplateArgs);
} }
CXXDependentScopeMemberExpr * CXXDependentScopeMemberExpr *CXXDependentScopeMemberExpr::CreateEmpty(
CXXDependentScopeMemberExpr::CreateEmpty(const ASTContext &C, const ASTContext &Ctx, bool HasTemplateKWAndArgsInfo,
bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs, bool HasFirstQualifierFoundInScope) {
unsigned NumTemplateArgs) {
assert(NumTemplateArgs == 0 || HasTemplateKWAndArgsInfo); assert(NumTemplateArgs == 0 || HasTemplateKWAndArgsInfo);
std::size_t Size =
totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
HasTemplateKWAndArgsInfo, NumTemplateArgs);
void *Mem = C.Allocate(Size, alignof(CXXDependentScopeMemberExpr));
auto *E =
new (Mem) CXXDependentScopeMemberExpr(C, nullptr, QualType(),
false, SourceLocation(),
NestedNameSpecifierLoc(),
SourceLocation(), nullptr,
DeclarationNameInfo(), nullptr);
E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo;
return E;
}
bool CXXDependentScopeMemberExpr::isImplicitAccess() const { unsigned Size = totalSizeToAlloc<ASTTemplateKWAndArgsInfo,
if (!Base) TemplateArgumentLoc, NamedDecl *>(
return true; HasTemplateKWAndArgsInfo, NumTemplateArgs, HasFirstQualifierFoundInScope);
return cast<Expr>(Base)->isImplicitCXXThis(); void *Mem = Ctx.Allocate(Size, alignof(CXXDependentScopeMemberExpr));
return new (Mem) CXXDependentScopeMemberExpr(
EmptyShell(), HasTemplateKWAndArgsInfo, HasFirstQualifierFoundInScope);
} }
static bool hasOnlyNonStaticMemberFunctions(UnresolvedSetIterator begin, static bool hasOnlyNonStaticMemberFunctions(UnresolvedSetIterator begin,

View File

@ -1584,22 +1584,37 @@ void ASTStmtReader::VisitExprWithCleanups(ExprWithCleanups *E) {
E->SubExpr = Record.readSubExpr(); E->SubExpr = Record.readSubExpr();
} }
void void ASTStmtReader::VisitCXXDependentScopeMemberExpr(
ASTStmtReader::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){ CXXDependentScopeMemberExpr *E) {
VisitExpr(E); VisitExpr(E);
if (Record.readInt()) // HasTemplateKWAndArgsInfo bool HasTemplateKWAndArgsInfo = Record.readInt();
unsigned NumTemplateArgs = Record.readInt();
bool HasFirstQualifierFoundInScope = Record.readInt();
assert((HasTemplateKWAndArgsInfo == E->hasTemplateKWAndArgsInfo()) &&
"Wrong HasTemplateKWAndArgsInfo!");
assert(
(HasFirstQualifierFoundInScope == E->hasFirstQualifierFoundInScope()) &&
"Wrong HasFirstQualifierFoundInScope!");
if (HasTemplateKWAndArgsInfo)
ReadTemplateKWAndArgsInfo( ReadTemplateKWAndArgsInfo(
*E->getTrailingObjects<ASTTemplateKWAndArgsInfo>(), *E->getTrailingObjects<ASTTemplateKWAndArgsInfo>(),
E->getTrailingObjects<TemplateArgumentLoc>(), E->getTrailingObjects<TemplateArgumentLoc>(), NumTemplateArgs);
/*NumTemplateArgs=*/Record.readInt());
E->Base = Record.readSubExpr(); assert((NumTemplateArgs == E->getNumTemplateArgs()) &&
"Wrong NumTemplateArgs!");
E->CXXDependentScopeMemberExprBits.IsArrow = Record.readInt();
E->CXXDependentScopeMemberExprBits.OperatorLoc = ReadSourceLocation();
E->BaseType = Record.readType(); E->BaseType = Record.readType();
E->IsArrow = Record.readInt();
E->OperatorLoc = ReadSourceLocation();
E->QualifierLoc = Record.readNestedNameSpecifierLoc(); E->QualifierLoc = Record.readNestedNameSpecifierLoc();
E->FirstQualifierFoundInScope = ReadDeclAs<NamedDecl>(); E->Base = Record.readSubExpr();
if (HasFirstQualifierFoundInScope)
*E->getTrailingObjects<NamedDecl *>() = ReadDeclAs<NamedDecl>();
ReadDeclarationNameInfo(E->MemberNameInfo); ReadDeclarationNameInfo(E->MemberNameInfo);
} }
@ -3224,11 +3239,12 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
break; break;
case EXPR_CXX_DEPENDENT_SCOPE_MEMBER: case EXPR_CXX_DEPENDENT_SCOPE_MEMBER:
S = CXXDependentScopeMemberExpr::CreateEmpty(Context, S = CXXDependentScopeMemberExpr::CreateEmpty(
/*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields], Context,
/*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields] /*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields],
? Record[ASTStmtReader::NumExprFields + 1] /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields + 1],
: 0); /*HasFirstQualifierFoundInScope=*/
Record[ASTStmtReader::NumExprFields + 2]);
break; break;
case EXPR_CXX_DEPENDENT_SCOPE_DECL_REF: case EXPR_CXX_DEPENDENT_SCOPE_DECL_REF:

View File

@ -1554,31 +1554,36 @@ void ASTStmtWriter::VisitExprWithCleanups(ExprWithCleanups *E) {
Code = serialization::EXPR_EXPR_WITH_CLEANUPS; Code = serialization::EXPR_EXPR_WITH_CLEANUPS;
} }
void void ASTStmtWriter::VisitCXXDependentScopeMemberExpr(
ASTStmtWriter::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){ CXXDependentScopeMemberExpr *E) {
VisitExpr(E); VisitExpr(E);
// Don't emit anything here, HasTemplateKWAndArgsInfo must be // Don't emit anything here (or if you do you will have to update
// emitted first. // the corresponding deserialization function).
Record.push_back(E->HasTemplateKWAndArgsInfo); Record.push_back(E->hasTemplateKWAndArgsInfo());
if (E->HasTemplateKWAndArgsInfo) { Record.push_back(E->getNumTemplateArgs());
Record.push_back(E->hasFirstQualifierFoundInScope());
if (E->hasTemplateKWAndArgsInfo()) {
const ASTTemplateKWAndArgsInfo &ArgInfo = const ASTTemplateKWAndArgsInfo &ArgInfo =
*E->getTrailingObjects<ASTTemplateKWAndArgsInfo>(); *E->getTrailingObjects<ASTTemplateKWAndArgsInfo>();
Record.push_back(ArgInfo.NumTemplateArgs);
AddTemplateKWAndArgsInfo(ArgInfo, AddTemplateKWAndArgsInfo(ArgInfo,
E->getTrailingObjects<TemplateArgumentLoc>()); E->getTrailingObjects<TemplateArgumentLoc>());
} }
Record.push_back(E->isArrow());
Record.AddSourceLocation(E->getOperatorLoc());
Record.AddTypeRef(E->getBaseType());
Record.AddNestedNameSpecifierLoc(E->getQualifierLoc());
if (!E->isImplicitAccess()) if (!E->isImplicitAccess())
Record.AddStmt(E->getBase()); Record.AddStmt(E->getBase());
else else
Record.AddStmt(nullptr); Record.AddStmt(nullptr);
Record.AddTypeRef(E->getBaseType());
Record.push_back(E->isArrow()); if (E->hasFirstQualifierFoundInScope())
Record.AddSourceLocation(E->getOperatorLoc()); Record.AddDeclRef(E->getFirstQualifierFoundInScope());
Record.AddNestedNameSpecifierLoc(E->getQualifierLoc());
Record.AddDeclRef(E->getFirstQualifierFoundInScope());
Record.AddDeclarationNameInfo(E->MemberNameInfo); Record.AddDeclarationNameInfo(E->MemberNameInfo);
Code = serialization::EXPR_CXX_DEPENDENT_SCOPE_MEMBER; Code = serialization::EXPR_CXX_DEPENDENT_SCOPE_MEMBER;
} }