diff options
| author | Douglas Gregor <dgregor@apple.com> | 2011-02-04 12:01:24 +0000 |
|---|---|---|
| committer | Douglas Gregor <dgregor@apple.com> | 2011-02-04 12:01:24 +0000 |
| commit | 87866ceda70f6ab0664dc7eb3bf7f71fd79cf379 (patch) | |
| tree | c59844d8d73395094c0595437765b0ff72945302 /clang | |
| parent | 5d8b8babd58ec4c7e6d14b1d36133401d41e98c3 (diff) | |
| download | bcm5719-llvm-87866ceda70f6ab0664dc7eb3bf7f71fd79cf379.tar.gz bcm5719-llvm-87866ceda70f6ab0664dc7eb3bf7f71fd79cf379.zip | |
Implement proper (de-)serialization for explicit template argument
lists with zero template arguments. Fixes some seriously scary
crashers in C++ PCH.
llvm-svn: 124862
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/include/clang/AST/Expr.h | 4 | ||||
| -rw-r--r-- | clang/include/clang/AST/ExprCXX.h | 8 | ||||
| -rw-r--r-- | clang/lib/AST/Expr.cpp | 6 | ||||
| -rw-r--r-- | clang/lib/AST/ExprCXX.cpp | 27 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTReaderStmt.cpp | 67 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTWriterStmt.cpp | 44 | ||||
| -rw-r--r-- | clang/test/PCH/cxx-templates.cpp | 4 | ||||
| -rw-r--r-- | clang/test/PCH/cxx-templates.h | 24 |
8 files changed, 114 insertions, 70 deletions
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index e718961866b..cf1faf1aff9 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -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(); } diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index addf35a1bcd..7c8ac952035 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -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 diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 9e8f801791d..04498f7b9a9 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -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>()); diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 7cd714ba3fa..a11d05a3a76 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -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; } diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index c704eb2ab4c..4335ff97068 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -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: diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 15a36701678..4a3bea5aaeb 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -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()); diff --git a/clang/test/PCH/cxx-templates.cpp b/clang/test/PCH/cxx-templates.cpp index 56b8ab7399f..e2ad46c6595 100644 --- a/clang/test/PCH/cxx-templates.cpp +++ b/clang/test/PCH/cxx-templates.cpp @@ -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*); +} diff --git a/clang/test/PCH/cxx-templates.h b/clang/test/PCH/cxx-templates.h index ec8becbdc95..d2c820f877c 100644 --- a/clang/test/PCH/cxx-templates.h +++ b/clang/test/PCH/cxx-templates.h @@ -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); + }; +} |

