From 250ffb1fcb79ee8783e3c42f3232e6700dee36b8 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Sat, 5 Mar 2011 01:35:54 +0000 Subject: [PATCH] When we're deserializing a template parameter declaration, temporarily use the translation unit as its declaration context, then deserialize the actual lexical and semantic DeclContexts after the template parameter is complete. This avoids problems when the DeclContext itself (e.g., a class template) is dependent on the template parameter (e.g., for the injected-class-name). llvm-svn: 127056 --- clang/lib/AST/DeclBase.cpp | 3 --- clang/lib/Serialization/ASTReaderDecl.cpp | 26 +++++++++++++++++++++-- clang/test/PCH/cxx-templates.h | 12 +++++++++++ 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 0642f423c6f3..8d6a5412a55b 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -173,9 +173,6 @@ void PrettyStackTraceDecl::print(llvm::raw_ostream &OS) const { Decl::~Decl() { } void Decl::setDeclContext(DeclContext *DC) { - if (isOutOfSemaDC()) - delete getMultipleDC(); - DeclCtx = DC; } diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 1e4ff83d5fc3..a49f909c6f01 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -38,6 +38,9 @@ namespace clang { const RecordData &Record; unsigned &Idx; TypeID TypeIDForTypeDecl; + + DeclID DeclContextIDForTemplateParmDecl; + DeclID LexicalDeclContextIDForTemplateParmDecl; uint64_t GetCurrentCursorOffset(); SourceLocation ReadSourceLocation(const RecordData &R, unsigned &I) { @@ -175,13 +178,32 @@ void ASTDeclReader::Visit(Decl *D) { // FunctionDecl's body was written last after all other Stmts/Exprs. if (Record[Idx++]) FD->setLazyBody(GetCurrentCursorOffset()); + } else if (D->isTemplateParameter()) { + // If we have a fully initialized template parameter, we can now + // set its DeclContext. + D->setDeclContext( + cast_or_null( + Reader.GetDecl(DeclContextIDForTemplateParmDecl))); + D->setLexicalDeclContext( + cast_or_null( + Reader.GetDecl(LexicalDeclContextIDForTemplateParmDecl))); } } void ASTDeclReader::VisitDecl(Decl *D) { - D->setDeclContext(cast_or_null(Reader.GetDecl(Record[Idx++]))); - D->setLexicalDeclContext( + if (D->isTemplateParameter()) { + // We don't want to deserialize the DeclContext of a template + // parameter immediately, because the template parameter might be + // used in the formulation of its DeclContext. Use the translation + // unit DeclContext as a placeholder. + DeclContextIDForTemplateParmDecl = Record[Idx++]; + LexicalDeclContextIDForTemplateParmDecl = Record[Idx++]; + D->setDeclContext(Reader.getContext()->getTranslationUnitDecl()); + } else { + D->setDeclContext(cast_or_null(Reader.GetDecl(Record[Idx++]))); + D->setLexicalDeclContext( cast_or_null(Reader.GetDecl(Record[Idx++]))); + } D->setLocation(ReadSourceLocation(Record, Idx)); D->setInvalidDecl(Record[Idx++]); if (Record[Idx++]) { // hasAttrs diff --git a/clang/test/PCH/cxx-templates.h b/clang/test/PCH/cxx-templates.h index d2c820f877c6..c45e02dcb23c 100644 --- a/clang/test/PCH/cxx-templates.h +++ b/clang/test/PCH/cxx-templates.h @@ -193,3 +193,15 @@ namespace ZeroLengthExplicitTemplateArgs { template void g2(T); }; } + +namespace NonTypeTemplateParmContext { + template class Vector { }; + + struct String { + template + static String adopt(Vector&); + }; + + template + inline bool equalIgnoringNullity(const Vector& a, const String& b) { return false; } +}