[AST][NFC] Pack DependentScopeDeclRefExpr and CXXUnresolvedConstructExpr

Use the newly available space in the bit-fields of Stmt.
This saves 1 pointer per DependentScopeDeclRefExpr/CXXUnresolvedConstructExpr.

Additionally rename "TypeSourceInfo *Type;" to "TypeSourceInfo *TSI;"
as was done in D56022 (r350003) (but this is an internal detail anyway),
and clang-format both classes. NFC.

llvm-svn: 350525
This commit is contained in:
Bruno Ricci 2019-01-07 14:27:04 +00:00
parent 26e6c86b79
commit 49ee964e19
5 changed files with 123 additions and 110 deletions

View File

@ -2936,6 +2936,10 @@ class DependentScopeDeclRefExpr final
private llvm::TrailingObjects<DependentScopeDeclRefExpr, private llvm::TrailingObjects<DependentScopeDeclRefExpr,
ASTTemplateKWAndArgsInfo, ASTTemplateKWAndArgsInfo,
TemplateArgumentLoc> { TemplateArgumentLoc> {
friend class ASTStmtReader;
friend class ASTStmtWriter;
friend TrailingObjects;
/// The nested-name-specifier that qualifies this unresolved /// The nested-name-specifier that qualifies this unresolved
/// declaration name. /// declaration name.
NestedNameSpecifierLoc QualifierLoc; NestedNameSpecifierLoc QualifierLoc;
@ -2943,32 +2947,26 @@ class DependentScopeDeclRefExpr final
/// The name of the entity we will be referencing. /// The name of the entity we will be referencing.
DeclarationNameInfo NameInfo; DeclarationNameInfo NameInfo;
/// Whether the name includes info for explicit template DependentScopeDeclRefExpr(QualType Ty, NestedNameSpecifierLoc QualifierLoc,
/// keyword and arguments.
bool HasTemplateKWAndArgsInfo;
DependentScopeDeclRefExpr(QualType T,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc, SourceLocation TemplateKWLoc,
const DeclarationNameInfo &NameInfo, const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *Args); const TemplateArgumentListInfo *Args);
size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
return HasTemplateKWAndArgsInfo ? 1 : 0; return hasTemplateKWAndArgsInfo();
}
bool hasTemplateKWAndArgsInfo() const {
return DependentScopeDeclRefExprBits.HasTemplateKWAndArgsInfo;
} }
public: public:
friend class ASTStmtReader; static DependentScopeDeclRefExpr *
friend class ASTStmtWriter; Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc,
friend TrailingObjects; SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs);
static DependentScopeDeclRefExpr *Create(const ASTContext &C, static DependentScopeDeclRefExpr *CreateEmpty(const ASTContext &Context,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs);
static DependentScopeDeclRefExpr *CreateEmpty(const ASTContext &C,
bool HasTemplateKWAndArgsInfo, bool HasTemplateKWAndArgsInfo,
unsigned NumTemplateArgs); unsigned NumTemplateArgs);
@ -2996,21 +2994,24 @@ public:
/// Retrieve the location of the template keyword preceding /// Retrieve the location of the template keyword preceding
/// this name, if any. /// this 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 name, if any. /// explicit template argument list following the 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 name, if any. /// explicit template argument list following the 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;
} }
@ -3164,7 +3165,7 @@ class CXXUnresolvedConstructExpr final
friend TrailingObjects; friend TrailingObjects;
/// The type being constructed. /// The type being constructed.
TypeSourceInfo *Type = nullptr; TypeSourceInfo *TSI;
/// The location of the left parentheses ('('). /// The location of the left parentheses ('(').
SourceLocation LParenLoc; SourceLocation LParenLoc;
@ -3172,34 +3173,31 @@ class CXXUnresolvedConstructExpr final
/// The location of the right parentheses (')'). /// The location of the right parentheses (')').
SourceLocation RParenLoc; SourceLocation RParenLoc;
/// The number of arguments used to construct the type. CXXUnresolvedConstructExpr(TypeSourceInfo *TSI, SourceLocation LParenLoc,
unsigned NumArgs; ArrayRef<Expr *> Args, SourceLocation RParenLoc);
CXXUnresolvedConstructExpr(TypeSourceInfo *Type,
SourceLocation LParenLoc,
ArrayRef<Expr*> Args,
SourceLocation RParenLoc);
CXXUnresolvedConstructExpr(EmptyShell Empty, unsigned NumArgs) CXXUnresolvedConstructExpr(EmptyShell Empty, unsigned NumArgs)
: Expr(CXXUnresolvedConstructExprClass, Empty), NumArgs(NumArgs) {} : Expr(CXXUnresolvedConstructExprClass, Empty) {
CXXUnresolvedConstructExprBits.NumArgs = NumArgs;
}
public: public:
static CXXUnresolvedConstructExpr *Create(const ASTContext &C, static CXXUnresolvedConstructExpr *Create(const ASTContext &Context,
TypeSourceInfo *Type, TypeSourceInfo *Type,
SourceLocation LParenLoc, SourceLocation LParenLoc,
ArrayRef<Expr*> Args, ArrayRef<Expr *> Args,
SourceLocation RParenLoc); SourceLocation RParenLoc);
static CXXUnresolvedConstructExpr *CreateEmpty(const ASTContext &C, static CXXUnresolvedConstructExpr *CreateEmpty(const ASTContext &Context,
unsigned NumArgs); unsigned NumArgs);
/// Retrieve the type that is being constructed, as specified /// Retrieve the type that is being constructed, as specified
/// in the source code. /// in the source code.
QualType getTypeAsWritten() const { return Type->getType(); } QualType getTypeAsWritten() const { return TSI->getType(); }
/// Retrieve the type source information for the type being /// Retrieve the type source information for the type being
/// constructed. /// constructed.
TypeSourceInfo *getTypeSourceInfo() const { return Type; } TypeSourceInfo *getTypeSourceInfo() const { return TSI; }
/// Retrieve the location of the left parentheses ('(') that /// Retrieve the location of the left parentheses ('(') that
/// precedes the argument list. /// precedes the argument list.
@ -3217,46 +3215,43 @@ public:
bool isListInitialization() const { return LParenLoc.isInvalid(); } bool isListInitialization() const { return LParenLoc.isInvalid(); }
/// Retrieve the number of arguments. /// Retrieve the number of arguments.
unsigned arg_size() const { return NumArgs; } unsigned arg_size() const { return CXXUnresolvedConstructExprBits.NumArgs; }
using arg_iterator = Expr **; using arg_iterator = Expr **;
using arg_range = llvm::iterator_range<arg_iterator>; using arg_range = llvm::iterator_range<arg_iterator>;
arg_iterator arg_begin() { return getTrailingObjects<Expr *>(); } arg_iterator arg_begin() { return getTrailingObjects<Expr *>(); }
arg_iterator arg_end() { return arg_begin() + NumArgs; } arg_iterator arg_end() { return arg_begin() + arg_size(); }
arg_range arguments() { return arg_range(arg_begin(), arg_end()); } arg_range arguments() { return arg_range(arg_begin(), arg_end()); }
using const_arg_iterator = const Expr* const *; using const_arg_iterator = const Expr* const *;
using const_arg_range = llvm::iterator_range<const_arg_iterator>; using const_arg_range = llvm::iterator_range<const_arg_iterator>;
const_arg_iterator arg_begin() const { return getTrailingObjects<Expr *>(); } const_arg_iterator arg_begin() const { return getTrailingObjects<Expr *>(); }
const_arg_iterator arg_end() const { const_arg_iterator arg_end() const { return arg_begin() + arg_size(); }
return arg_begin() + NumArgs;
}
const_arg_range arguments() const { const_arg_range arguments() const {
return const_arg_range(arg_begin(), arg_end()); return const_arg_range(arg_begin(), arg_end());
} }
Expr *getArg(unsigned I) { Expr *getArg(unsigned I) {
assert(I < NumArgs && "Argument index out-of-range"); assert(I < arg_size() && "Argument index out-of-range");
return *(arg_begin() + I); return arg_begin()[I];
} }
const Expr *getArg(unsigned I) const { const Expr *getArg(unsigned I) const {
assert(I < NumArgs && "Argument index out-of-range"); assert(I < arg_size() && "Argument index out-of-range");
return *(arg_begin() + I); return arg_begin()[I];
} }
void setArg(unsigned I, Expr *E) { void setArg(unsigned I, Expr *E) {
assert(I < NumArgs && "Argument index out-of-range"); assert(I < arg_size() && "Argument index out-of-range");
*(arg_begin() + I) = E; arg_begin()[I] = E;
} }
SourceLocation getBeginLoc() const LLVM_READONLY; SourceLocation getBeginLoc() const LLVM_READONLY;
SourceLocation getEndLoc() const LLVM_READONLY { SourceLocation getEndLoc() const LLVM_READONLY {
if (!RParenLoc.isValid() && NumArgs > 0) if (!RParenLoc.isValid() && arg_size() > 0)
return getArg(NumArgs - 1)->getEndLoc(); return getArg(arg_size() - 1)->getEndLoc();
return RParenLoc; return RParenLoc;
} }
@ -3267,7 +3262,7 @@ public:
// Iterators // Iterators
child_range children() { child_range children() {
auto **begin = reinterpret_cast<Stmt **>(arg_begin()); auto **begin = reinterpret_cast<Stmt **>(arg_begin());
return child_range(begin, begin + NumArgs); return child_range(begin, begin + arg_size());
} }
}; };

View File

@ -655,6 +655,18 @@ protected:
unsigned NumArgs : 32 - 8 - 1 - NumExprBits; unsigned NumArgs : 32 - 8 - 1 - NumExprBits;
}; };
class DependentScopeDeclRefExprBitfields {
friend class ASTStmtReader;
friend class ASTStmtWriter;
friend class DependentScopeDeclRefExpr;
unsigned : NumExprBits;
/// Whether the name includes info for explicit template
/// keyword and arguments.
unsigned HasTemplateKWAndArgsInfo : 1;
};
class CXXConstructExprBitfields { class CXXConstructExprBitfields {
friend class ASTStmtReader; friend class ASTStmtReader;
friend class CXXConstructExpr; friend class CXXConstructExpr;
@ -683,6 +695,16 @@ protected:
unsigned NumObjects : 32 - 1 - NumExprBits; unsigned NumObjects : 32 - 1 - NumExprBits;
}; };
class CXXUnresolvedConstructExprBitfields {
friend class ASTStmtReader;
friend class CXXUnresolvedConstructExpr;
unsigned : NumExprBits;
/// The number of arguments used to construct the type.
unsigned NumArgs;
};
//===--- C++ Coroutines TS bitfields classes ---===// //===--- C++ Coroutines TS bitfields classes ---===//
class CoawaitExprBitfields { class CoawaitExprBitfields {
@ -765,8 +787,10 @@ protected:
CXXDefaultInitExprBitfields CXXDefaultInitExprBits; CXXDefaultInitExprBitfields CXXDefaultInitExprBits;
CXXDeleteExprBitfields CXXDeleteExprBits; CXXDeleteExprBitfields CXXDeleteExprBits;
TypeTraitExprBitfields TypeTraitExprBits; TypeTraitExprBitfields TypeTraitExprBits;
DependentScopeDeclRefExprBitfields DependentScopeDeclRefExprBits;
CXXConstructExprBitfields CXXConstructExprBits; CXXConstructExprBitfields CXXConstructExprBits;
ExprWithCleanupsBitfields ExprWithCleanupsBits; ExprWithCleanupsBitfields ExprWithCleanupsBits;
CXXUnresolvedConstructExprBitfields CXXUnresolvedConstructExprBits;
// C++ Coroutines TS expressions // C++ Coroutines TS expressions
CoawaitExprBitfields CoawaitBits; CoawaitExprBitfields CoawaitBits;

View File

@ -385,23 +385,22 @@ CXXRecordDecl *OverloadExpr::getNamingClass() const {
} }
// DependentScopeDeclRefExpr // DependentScopeDeclRefExpr
DependentScopeDeclRefExpr::DependentScopeDeclRefExpr(QualType T, DependentScopeDeclRefExpr::DependentScopeDeclRefExpr(
NestedNameSpecifierLoc QualifierLoc, QualType Ty, NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo,
const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *Args)
const TemplateArgumentListInfo *Args) : Expr(
: Expr(DependentScopeDeclRefExprClass, T, VK_LValue, OK_Ordinary, DependentScopeDeclRefExprClass, Ty, VK_LValue, OK_Ordinary, true,
true, true, true,
(NameInfo.isInstantiationDependent() || (NameInfo.isInstantiationDependent() ||
(QualifierLoc && (QualifierLoc &&
QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent())), QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent())),
(NameInfo.containsUnexpandedParameterPack() || (NameInfo.containsUnexpandedParameterPack() ||
(QualifierLoc && (QualifierLoc && QualifierLoc.getNestedNameSpecifier()
QualifierLoc.getNestedNameSpecifier() ->containsUnexpandedParameterPack()))),
->containsUnexpandedParameterPack()))), QualifierLoc(QualifierLoc), NameInfo(NameInfo) {
QualifierLoc(QualifierLoc), NameInfo(NameInfo), DependentScopeDeclRefExprBits.HasTemplateKWAndArgsInfo =
HasTemplateKWAndArgsInfo(Args != nullptr || TemplateKWLoc.isValid()) (Args != nullptr) || TemplateKWLoc.isValid();
{
if (Args) { if (Args) {
bool Dependent = true; bool Dependent = true;
bool InstantiationDependent = true; bool InstantiationDependent = true;
@ -417,36 +416,34 @@ DependentScopeDeclRefExpr::DependentScopeDeclRefExpr(QualType T,
} }
} }
DependentScopeDeclRefExpr * DependentScopeDeclRefExpr *DependentScopeDeclRefExpr::Create(
DependentScopeDeclRefExpr::Create(const ASTContext &C, const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc,
NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo,
SourceLocation TemplateKWLoc, const TemplateArgumentListInfo *Args) {
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *Args) {
assert(QualifierLoc && "should be created for dependent qualifiers"); assert(QualifierLoc && "should be created for dependent qualifiers");
bool HasTemplateKWAndArgsInfo = Args || TemplateKWLoc.isValid(); bool HasTemplateKWAndArgsInfo = Args || TemplateKWLoc.isValid();
std::size_t Size = std::size_t Size =
totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>( totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
HasTemplateKWAndArgsInfo, Args ? Args->size() : 0); HasTemplateKWAndArgsInfo, Args ? Args->size() : 0);
void *Mem = C.Allocate(Size); void *Mem = Context.Allocate(Size);
return new (Mem) DependentScopeDeclRefExpr(C.DependentTy, QualifierLoc, return new (Mem) DependentScopeDeclRefExpr(Context.DependentTy, QualifierLoc,
TemplateKWLoc, NameInfo, Args); TemplateKWLoc, NameInfo, Args);
} }
DependentScopeDeclRefExpr * DependentScopeDeclRefExpr *
DependentScopeDeclRefExpr::CreateEmpty(const ASTContext &C, DependentScopeDeclRefExpr::CreateEmpty(const ASTContext &Context,
bool HasTemplateKWAndArgsInfo, bool HasTemplateKWAndArgsInfo,
unsigned NumTemplateArgs) { unsigned NumTemplateArgs) {
assert(NumTemplateArgs == 0 || HasTemplateKWAndArgsInfo); assert(NumTemplateArgs == 0 || HasTemplateKWAndArgsInfo);
std::size_t Size = std::size_t Size =
totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>( totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
HasTemplateKWAndArgsInfo, NumTemplateArgs); HasTemplateKWAndArgsInfo, NumTemplateArgs);
void *Mem = C.Allocate(Size); void *Mem = Context.Allocate(Size);
auto *E = auto *E = new (Mem) DependentScopeDeclRefExpr(
new (Mem) DependentScopeDeclRefExpr(QualType(), NestedNameSpecifierLoc(), QualType(), NestedNameSpecifierLoc(), SourceLocation(),
SourceLocation(), DeclarationNameInfo(), nullptr);
DeclarationNameInfo(), nullptr); E->DependentScopeDeclRefExprBits.HasTemplateKWAndArgsInfo =
E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo; HasTemplateKWAndArgsInfo;
return E; return E;
} }
@ -1216,22 +1213,22 @@ ExprWithCleanups *ExprWithCleanups::Create(const ASTContext &C,
return new (buffer) ExprWithCleanups(empty, numObjects); return new (buffer) ExprWithCleanups(empty, numObjects);
} }
CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(TypeSourceInfo *Type, CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(TypeSourceInfo *TSI,
SourceLocation LParenLoc, SourceLocation LParenLoc,
ArrayRef<Expr*> Args, ArrayRef<Expr *> Args,
SourceLocation RParenLoc) SourceLocation RParenLoc)
: Expr(CXXUnresolvedConstructExprClass, : Expr(CXXUnresolvedConstructExprClass,
Type->getType().getNonReferenceType(), TSI->getType().getNonReferenceType(),
(Type->getType()->isLValueReferenceType() (TSI->getType()->isLValueReferenceType()
? VK_LValue ? VK_LValue
: Type->getType()->isRValueReferenceType() ? VK_XValue : TSI->getType()->isRValueReferenceType() ? VK_XValue
: VK_RValue), : VK_RValue),
OK_Ordinary, OK_Ordinary,
Type->getType()->isDependentType() || TSI->getType()->isDependentType() ||
Type->getType()->getContainedDeducedType(), TSI->getType()->getContainedDeducedType(),
true, true, Type->getType()->containsUnexpandedParameterPack()), true, true, TSI->getType()->containsUnexpandedParameterPack()),
Type(Type), LParenLoc(LParenLoc), RParenLoc(RParenLoc), TSI(TSI), LParenLoc(LParenLoc), RParenLoc(RParenLoc) {
NumArgs(Args.size()) { CXXUnresolvedConstructExprBits.NumArgs = Args.size();
auto **StoredArgs = getTrailingObjects<Expr *>(); auto **StoredArgs = getTrailingObjects<Expr *>();
for (unsigned I = 0; I != Args.size(); ++I) { for (unsigned I = 0; I != Args.size(); ++I) {
if (Args[I]->containsUnexpandedParameterPack()) if (Args[I]->containsUnexpandedParameterPack())
@ -1241,25 +1238,22 @@ CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(TypeSourceInfo *Type,
} }
} }
CXXUnresolvedConstructExpr * CXXUnresolvedConstructExpr *CXXUnresolvedConstructExpr::Create(
CXXUnresolvedConstructExpr::Create(const ASTContext &C, const ASTContext &Context, TypeSourceInfo *TSI, SourceLocation LParenLoc,
TypeSourceInfo *Type, ArrayRef<Expr *> Args, SourceLocation RParenLoc) {
SourceLocation LParenLoc, void *Mem = Context.Allocate(totalSizeToAlloc<Expr *>(Args.size()));
ArrayRef<Expr*> Args, return new (Mem) CXXUnresolvedConstructExpr(TSI, LParenLoc, Args, RParenLoc);
SourceLocation RParenLoc) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(Args.size()));
return new (Mem) CXXUnresolvedConstructExpr(Type, LParenLoc, Args, RParenLoc);
} }
CXXUnresolvedConstructExpr * CXXUnresolvedConstructExpr *
CXXUnresolvedConstructExpr::CreateEmpty(const ASTContext &C, unsigned NumArgs) { CXXUnresolvedConstructExpr::CreateEmpty(const ASTContext &Context,
Stmt::EmptyShell Empty; unsigned NumArgs) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(NumArgs)); void *Mem = Context.Allocate(totalSizeToAlloc<Expr *>(NumArgs));
return new (Mem) CXXUnresolvedConstructExpr(Empty, NumArgs); return new (Mem) CXXUnresolvedConstructExpr(EmptyShell(), NumArgs);
} }
SourceLocation CXXUnresolvedConstructExpr::getBeginLoc() const { SourceLocation CXXUnresolvedConstructExpr::getBeginLoc() const {
return Type->getTypeLoc().getBeginLoc(); return TSI->getTypeLoc().getBeginLoc();
} }
CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr( CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(

View File

@ -1612,7 +1612,7 @@ ASTStmtReader::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) {
Record.skipInts(1); Record.skipInts(1);
for (unsigned I = 0, N = E->arg_size(); I != N; ++I) for (unsigned I = 0, N = E->arg_size(); I != N; ++I)
E->setArg(I, Record.readSubExpr()); E->setArg(I, Record.readSubExpr());
E->Type = GetTypeSourceInfo(); E->TSI = GetTypeSourceInfo();
E->setLParenLoc(ReadSourceLocation()); E->setLParenLoc(ReadSourceLocation());
E->setRParenLoc(ReadSourceLocation()); E->setRParenLoc(ReadSourceLocation());
} }

View File

@ -1583,8 +1583,8 @@ ASTStmtWriter::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
// Don't emit anything here, HasTemplateKWAndArgsInfo must be // Don't emit anything here, HasTemplateKWAndArgsInfo must be
// emitted first. // emitted first.
Record.push_back(E->HasTemplateKWAndArgsInfo); Record.push_back(E->DependentScopeDeclRefExprBits.HasTemplateKWAndArgsInfo);
if (E->HasTemplateKWAndArgsInfo) { if (E->DependentScopeDeclRefExprBits.HasTemplateKWAndArgsInfo) {
const ASTTemplateKWAndArgsInfo &ArgInfo = const ASTTemplateKWAndArgsInfo &ArgInfo =
*E->getTrailingObjects<ASTTemplateKWAndArgsInfo>(); *E->getTrailingObjects<ASTTemplateKWAndArgsInfo>();
Record.push_back(ArgInfo.NumTemplateArgs); Record.push_back(ArgInfo.NumTemplateArgs);