Implement proper (de-)serialization for explicit template argument

lists with zero template arguments. Fixes some seriously scary
crashers in C++ PCH.

llvm-svn: 124862
This commit is contained in:
Douglas Gregor 2011-02-04 12:01:24 +00:00
parent 5d8b8babd5
commit 87866ceda7
8 changed files with 114 additions and 70 deletions

View File

@ -668,7 +668,9 @@ public:
/// \brief Construct an empty declaration reference expression.
static DeclRefExpr *CreateEmpty(ASTContext &Context,
bool HasQualifier, unsigned NumTemplateArgs);
bool HasQualifier,
bool HasExplicitTemplateArgs,
unsigned NumTemplateArgs);
ValueDecl *getDecl() { return DecoratedD.getPointer(); }
const ValueDecl *getDecl() const { return DecoratedD.getPointer(); }

View File

@ -1762,6 +1762,7 @@ public:
UnresolvedSetIterator End);
static UnresolvedLookupExpr *CreateEmpty(ASTContext &C,
bool HasExplicitTemplateArgs,
unsigned NumTemplateArgs);
/// True if this declaration should be extended by
@ -1883,6 +1884,7 @@ public:
const TemplateArgumentListInfo *TemplateArgs = 0);
static DependentScopeDeclRefExpr *CreateEmpty(ASTContext &C,
bool HasExplicitTemplateArgs,
unsigned NumTemplateArgs);
/// \brief Retrieve the name that this expression refers to.
@ -2223,7 +2225,8 @@ public:
const TemplateArgumentListInfo *TemplateArgs);
static CXXDependentScopeMemberExpr *
CreateEmpty(ASTContext &C, unsigned NumTemplateArgs);
CreateEmpty(ASTContext &C, bool HasExplicitTemplateArgs,
unsigned NumTemplateArgs);
/// \brief True if this is an implicit access, i.e. one in which the
/// member being accessed was not written in the source. The source
@ -2445,7 +2448,8 @@ public:
UnresolvedSetIterator Begin, UnresolvedSetIterator End);
static UnresolvedMemberExpr *
CreateEmpty(ASTContext &C, unsigned NumTemplateArgs);
CreateEmpty(ASTContext &C, bool HasExplicitTemplateArgs,
unsigned NumTemplateArgs);
/// \brief True if this is an implicit access, i.e. one in which the
/// member being accessed was not written in the source. The source

View File

@ -319,13 +319,15 @@ DeclRefExpr *DeclRefExpr::Create(ASTContext &Context,
TemplateArgs, T, VK);
}
DeclRefExpr *DeclRefExpr::CreateEmpty(ASTContext &Context, bool HasQualifier,
DeclRefExpr *DeclRefExpr::CreateEmpty(ASTContext &Context,
bool HasQualifier,
bool HasExplicitTemplateArgs,
unsigned NumTemplateArgs) {
std::size_t Size = sizeof(DeclRefExpr);
if (HasQualifier)
Size += sizeof(NameQualifier);
if (NumTemplateArgs)
if (HasExplicitTemplateArgs)
Size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs);
void *Mem = Context.Allocate(Size, llvm::alignOf<DeclRefExpr>());

View File

@ -265,14 +265,15 @@ UnresolvedLookupExpr::Create(ASTContext &C,
}
UnresolvedLookupExpr *
UnresolvedLookupExpr::CreateEmpty(ASTContext &C, unsigned NumTemplateArgs) {
UnresolvedLookupExpr::CreateEmpty(ASTContext &C, bool HasExplicitTemplateArgs,
unsigned NumTemplateArgs) {
std::size_t size = sizeof(UnresolvedLookupExpr);
if (NumTemplateArgs != 0)
if (HasExplicitTemplateArgs)
size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs);
void *Mem = C.Allocate(size, llvm::alignOf<UnresolvedLookupExpr>());
UnresolvedLookupExpr *E = new (Mem) UnresolvedLookupExpr(EmptyShell());
E->HasExplicitTemplateArgs = NumTemplateArgs != 0;
E->HasExplicitTemplateArgs = HasExplicitTemplateArgs;
return E;
}
@ -417,13 +418,17 @@ DependentScopeDeclRefExpr::Create(ASTContext &C,
DependentScopeDeclRefExpr *
DependentScopeDeclRefExpr::CreateEmpty(ASTContext &C,
bool HasExplicitTemplateArgs,
unsigned NumTemplateArgs) {
std::size_t size = sizeof(DependentScopeDeclRefExpr);
if (NumTemplateArgs)
if (HasExplicitTemplateArgs)
size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs);
void *Mem = C.Allocate(size);
return new (Mem) DependentScopeDeclRefExpr(QualType(), 0, SourceRange(),
DeclarationNameInfo(), 0);
DependentScopeDeclRefExpr *E
= new (Mem) DependentScopeDeclRefExpr(QualType(), 0, SourceRange(),
DeclarationNameInfo(), 0);
E->HasExplicitTemplateArgs = HasExplicitTemplateArgs;
return E;
}
StmtIterator DependentScopeDeclRefExpr::child_begin() {
@ -902,8 +907,9 @@ CXXDependentScopeMemberExpr::Create(ASTContext &C,
CXXDependentScopeMemberExpr *
CXXDependentScopeMemberExpr::CreateEmpty(ASTContext &C,
bool HasExplicitTemplateArgs,
unsigned NumTemplateArgs) {
if (NumTemplateArgs == 0)
if (!HasExplicitTemplateArgs)
return new (C) CXXDependentScopeMemberExpr(C, 0, QualType(),
0, SourceLocation(), 0,
SourceRange(), 0,
@ -978,14 +984,15 @@ UnresolvedMemberExpr::Create(ASTContext &C,
}
UnresolvedMemberExpr *
UnresolvedMemberExpr::CreateEmpty(ASTContext &C, unsigned NumTemplateArgs) {
UnresolvedMemberExpr::CreateEmpty(ASTContext &C, bool HasExplicitTemplateArgs,
unsigned NumTemplateArgs) {
std::size_t size = sizeof(UnresolvedMemberExpr);
if (NumTemplateArgs != 0)
if (HasExplicitTemplateArgs)
size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs);
void *Mem = C.Allocate(size, llvm::alignOf<UnresolvedMemberExpr>());
UnresolvedMemberExpr *E = new (Mem) UnresolvedMemberExpr(EmptyShell());
E->HasExplicitTemplateArgs = NumTemplateArgs != 0;
E->HasExplicitTemplateArgs = HasExplicitTemplateArgs;
return E;
}

View File

@ -419,19 +419,22 @@ void ASTStmtReader::VisitDeclRefExpr(DeclRefExpr *E) {
VisitExpr(E);
bool HasQualifier = Record[Idx++];
unsigned NumTemplateArgs = Record[Idx++];
bool HasExplicitTemplateArgs = Record[Idx++];
E->DecoratedD.setInt((HasQualifier? DeclRefExpr::HasQualifierFlag : 0) |
(NumTemplateArgs ? DeclRefExpr::HasExplicitTemplateArgumentListFlag : 0));
(HasExplicitTemplateArgs
? DeclRefExpr::HasExplicitTemplateArgumentListFlag : 0));
if (HasQualifier) {
E->getNameQualifier()->NNS = Reader.ReadNestedNameSpecifier(Record, Idx);
E->getNameQualifier()->Range = ReadSourceRange(Record, Idx);
}
if (NumTemplateArgs)
if (HasExplicitTemplateArgs) {
unsigned NumTemplateArgs = Record[Idx++];
ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(),
NumTemplateArgs);
}
E->setDecl(cast<ValueDecl>(Reader.GetDecl(Record[Idx++])));
E->setLocation(ReadSourceLocation(Record, Idx));
@ -1180,12 +1183,9 @@ void
ASTStmtReader::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){
VisitExpr(E);
unsigned NumTemplateArgs = Record[Idx++];
assert((NumTemplateArgs != 0) == E->hasExplicitTemplateArgs() &&
"Read wrong record during creation ?");
if (E->hasExplicitTemplateArgs())
if (Record[Idx++])
ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(),
NumTemplateArgs);
Record[Idx++]);
E->setBase(Reader.ReadSubExpr());
E->setBaseType(Reader.GetType(Record[Idx++]));
@ -1202,13 +1202,10 @@ void
ASTStmtReader::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
VisitExpr(E);
unsigned NumTemplateArgs = Record[Idx++];
assert((NumTemplateArgs != 0) == E->hasExplicitTemplateArgs() &&
"Read wrong record during creation ?");
if (E->hasExplicitTemplateArgs())
ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(),
NumTemplateArgs);
if (Record[Idx++])
ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(),
Record[Idx++]);
ReadDeclarationNameInfo(E->NameInfo, Record, Idx);
E->setQualifierRange(ReadSourceRange(Record, Idx));
E->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx));
@ -1229,12 +1226,10 @@ ASTStmtReader::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) {
void ASTStmtReader::VisitOverloadExpr(OverloadExpr *E) {
VisitExpr(E);
unsigned NumTemplateArgs = Record[Idx++];
assert((NumTemplateArgs != 0) == E->hasExplicitTemplateArgs() &&
"Read wrong record during creation ?");
if (E->hasExplicitTemplateArgs())
// Read the explicit template argument list, if available.
if (Record[Idx++])
ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(),
NumTemplateArgs);
Record[Idx++]);
unsigned NumDecls = Record[Idx++];
UnresolvedSet<8> Decls;
@ -1484,7 +1479,10 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) {
case EXPR_DECL_REF:
S = DeclRefExpr::CreateEmpty(*Context,
/*HasQualifier=*/Record[ASTStmtReader::NumExprFields],
/*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields + 1]);
/*HasExplicitTemplateArgs=*/Record[ASTStmtReader::NumExprFields + 1],
/*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields + 1]
? Record[ASTStmtReader::NumExprFields + 2]
: 0);
break;
case EXPR_INTEGER_LITERAL:
@ -1552,8 +1550,9 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) {
}
TemplateArgumentListInfo ArgInfo;
unsigned NumTemplateArgs = Record[Idx++];
if (NumTemplateArgs) {
bool HasExplicitTemplateArgs = Record[Idx++];
if (HasExplicitTemplateArgs) {
unsigned NumTemplateArgs = Record[Idx++];
ArgInfo.setLAngleLoc(ReadSourceLocation(F, Record, Idx));
ArgInfo.setRAngleLoc(ReadSourceLocation(F, Record, Idx));
for (unsigned i = 0; i != NumTemplateArgs; ++i)
@ -1575,7 +1574,7 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) {
S = MemberExpr::Create(*Context, Base, IsArrow, NNS, QualifierRange,
MemberD, FoundDecl, MemberNameInfo,
NumTemplateArgs ? &ArgInfo : 0, T, VK, OK);
HasExplicitTemplateArgs ? &ArgInfo : 0, T, VK, OK);
ReadDeclarationNameLoc(F, cast<MemberExpr>(S)->MemberDNLoc,
MemberD->getDeclName(), Record, Idx);
break;
@ -1812,12 +1811,18 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) {
case EXPR_CXX_DEPENDENT_SCOPE_MEMBER:
S = CXXDependentScopeMemberExpr::CreateEmpty(*Context,
/*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields]);
/*HasExplicitTemplateArgs=*/Record[ASTStmtReader::NumExprFields],
/*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields]
? Record[ASTStmtReader::NumExprFields + 1]
: 0);
break;
case EXPR_CXX_DEPENDENT_SCOPE_DECL_REF:
S = DependentScopeDeclRefExpr::CreateEmpty(*Context,
/*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields]);
/*HasExplicitTemplateArgs=*/Record[ASTStmtReader::NumExprFields],
/*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields]
? Record[ASTStmtReader::NumExprFields + 1]
: 0);
break;
case EXPR_CXX_UNRESOLVED_CONSTRUCT:
@ -1827,12 +1832,18 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) {
case EXPR_CXX_UNRESOLVED_MEMBER:
S = UnresolvedMemberExpr::CreateEmpty(*Context,
/*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields]);
/*HasExplicitTemplateArgs=*/Record[ASTStmtReader::NumExprFields],
/*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields]
? Record[ASTStmtReader::NumExprFields + 1]
: 0);
break;
case EXPR_CXX_UNRESOLVED_LOOKUP:
S = UnresolvedLookupExpr::CreateEmpty(*Context,
/*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields]);
/*HasExplicitTemplateArgs=*/Record[ASTStmtReader::NumExprFields],
/*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields]
? Record[ASTStmtReader::NumExprFields + 1]
: 0);
break;
case EXPR_CXX_UNARY_TYPE_TRAIT:

View File

@ -379,18 +379,18 @@ void ASTStmtWriter::VisitDeclRefExpr(DeclRefExpr *E) {
VisitExpr(E);
Record.push_back(E->hasQualifier());
unsigned NumTemplateArgs = E->getNumTemplateArgs();
assert((NumTemplateArgs != 0) == E->hasExplicitTemplateArgs() &&
"Template args list with no args ?");
Record.push_back(NumTemplateArgs);
Record.push_back(E->hasExplicitTemplateArgs());
if (E->hasQualifier()) {
Writer.AddNestedNameSpecifier(E->getQualifier(), Record);
Writer.AddSourceRange(E->getQualifierRange(), Record);
}
if (NumTemplateArgs)
if (E->hasExplicitTemplateArgs()) {
unsigned NumTemplateArgs = E->getNumTemplateArgs();
Record.push_back(NumTemplateArgs);
AddExplicitTemplateArgumentList(E->getExplicitTemplateArgs());
}
Writer.AddDeclRef(E->getDecl(), Record);
Writer.AddSourceLocation(E->getLocation(), Record);
@ -545,11 +545,10 @@ void ASTStmtWriter::VisitMemberExpr(MemberExpr *E) {
Writer.AddSourceRange(E->getQualifierRange(), Record);
}
unsigned NumTemplateArgs = E->getNumTemplateArgs();
assert((NumTemplateArgs != 0) == E->hasExplicitTemplateArgs() &&
"Template args list with no args ?");
Record.push_back(NumTemplateArgs);
if (NumTemplateArgs) {
Record.push_back(E->hasExplicitTemplateArgs());
if (E->hasExplicitTemplateArgs()) {
unsigned NumTemplateArgs = E->getNumTemplateArgs();
Record.push_back(NumTemplateArgs);
Writer.AddSourceLocation(E->getLAngleLoc(), Record);
Writer.AddSourceLocation(E->getRAngleLoc(), Record);
for (unsigned i=0; i != NumTemplateArgs; ++i)
@ -1169,16 +1168,14 @@ void
ASTStmtWriter::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){
VisitExpr(E);
// Don't emit anything here, NumTemplateArgs must be emitted first.
// Don't emit anything here, hasExplicitTemplateArgs() must be
// emitted first.
Record.push_back(E->hasExplicitTemplateArgs());
if (E->hasExplicitTemplateArgs()) {
const ExplicitTemplateArgumentList &Args = E->getExplicitTemplateArgs();
assert(Args.NumTemplateArgs &&
"Num of template args was zero! AST reading will mess up!");
Record.push_back(Args.NumTemplateArgs);
AddExplicitTemplateArgumentList(Args);
} else {
Record.push_back(0);
}
if (!E->isImplicitAccess())
@ -1199,16 +1196,13 @@ void
ASTStmtWriter::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
VisitExpr(E);
// Don't emit anything here, NumTemplateArgs must be emitted first.
// Don't emit anything here, hasExplicitTemplateArgs() must be
// emitted first.
Record.push_back(E->hasExplicitTemplateArgs());
if (E->hasExplicitTemplateArgs()) {
const ExplicitTemplateArgumentList &Args = E->getExplicitTemplateArgs();
assert(Args.NumTemplateArgs &&
"Num of template args was zero! AST reading will mess up!");
Record.push_back(Args.NumTemplateArgs);
AddExplicitTemplateArgumentList(Args);
} else {
Record.push_back(0);
}
Writer.AddDeclarationNameInfo(E->NameInfo, Record);
@ -1233,16 +1227,12 @@ ASTStmtWriter::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) {
void ASTStmtWriter::VisitOverloadExpr(OverloadExpr *E) {
VisitExpr(E);
// Don't emit anything here, NumTemplateArgs must be emitted first.
// Don't emit anything here, hasExplicitTemplateArgs() must be emitted first.
Record.push_back(E->hasExplicitTemplateArgs());
if (E->hasExplicitTemplateArgs()) {
const ExplicitTemplateArgumentList &Args = E->getExplicitTemplateArgs();
assert(Args.NumTemplateArgs &&
"Num of template args was zero! AST reading will mess up!");
Record.push_back(Args.NumTemplateArgs);
AddExplicitTemplateArgumentList(Args);
} else {
Record.push_back(0);
}
Record.push_back(E->getNumDecls());

View File

@ -39,3 +39,7 @@ void test(const int (&a6)[17]) {
template struct S4<int>;
S7<int[5]> s7_5;
namespace ZeroLengthExplicitTemplateArgs {
template void f<X>(X*);
}

View File

@ -169,3 +169,27 @@ template<typename T>
template<unsigned N>
struct S7<int[N]> : S6<const int[N]> { };
// Zero-length template argument lists
namespace ZeroLengthExplicitTemplateArgs {
template<typename T> void h();
struct Y {
template<typename T> void f();
};
template<typename T>
void f(T *ptr) {
T::template g<>(17);
ptr->template g2<>(17);
h<T>();
h<int>();
Y y;
y.f<int>();
}
struct X {
template<typename T> static void g(T);
template<typename T> void g2(T);
};
}