forked from OSchip/llvm-project
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:
parent
5d8b8babd5
commit
87866ceda7
|
@ -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(); }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>());
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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*);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue