diff options
8 files changed, 71 insertions, 11 deletions
diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h index f247855f691..e83dfe2536d 100644 --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -373,9 +373,10 @@ private: /// it. llvm::SmallSetVector<const DeclContext *, 16> UpdatedDeclContexts; - /// \brief Keeps track of visible decls that were added in DeclContexts - /// coming from another AST file. - SmallVector<const Decl *, 16> UpdatingVisibleDecls; + /// \brief Keeps track of declarations that we must emit, even though we're + /// not guaranteed to be able to find them by walking the AST starting at the + /// translation unit. + SmallVector<const Decl *, 16> DeclsToEmitEvenIfUnreferenced; /// \brief The set of Objective-C class that have categories we /// should serialize. @@ -667,6 +668,14 @@ private: void CompletedTagDefinition(const TagDecl *D) override; void AddedVisibleDecl(const DeclContext *DC, const Decl *D) override; void AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) override; + void AddedCXXTemplateSpecialization( + const ClassTemplateDecl *TD, + const ClassTemplateSpecializationDecl *D) override; + void AddedCXXTemplateSpecialization( + const VarTemplateDecl *TD, + const VarTemplateSpecializationDecl *D) override; + void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD, + const FunctionDecl *D) override; void ResolvedExceptionSpec(const FunctionDecl *FD) override; void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) override; void ResolvedOperatorDelete(const CXXDestructorDecl *DD, diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index fff824e4373..cfe04433cfd 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -4472,8 +4472,9 @@ uint64_t ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, Number.second)); // Make sure visible decls, added to DeclContexts previously loaded from - // an AST file, are registered for serialization. - for (const auto *I : UpdatingVisibleDecls) { + // an AST file, are registered for serialization. Likewise for template + // specializations added to imported templates. + for (const auto *I : DeclsToEmitEvenIfUnreferenced) { GetDeclRef(I); } @@ -5818,9 +5819,9 @@ void ASTWriter::AddedVisibleDecl(const DeclContext *DC, const Decl *D) { // that we write out all of its lookup results so we don't get a nasty // surprise when we try to emit its lookup table. for (auto *Child : DC->decls()) - UpdatingVisibleDecls.push_back(Child); + DeclsToEmitEvenIfUnreferenced.push_back(Child); } - UpdatingVisibleDecls.push_back(D); + DeclsToEmitEvenIfUnreferenced.push_back(D); } void ASTWriter::AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) { @@ -5989,3 +5990,39 @@ void ASTWriter::AddedAttributeToRecord(const Attr *Attr, return; DeclUpdates[Record].push_back(DeclUpdate(UPD_ADDED_ATTR_TO_RECORD, Attr)); } + +void ASTWriter::AddedCXXTemplateSpecialization( + const ClassTemplateDecl *TD, const ClassTemplateSpecializationDecl *D) { + assert(!WritingAST && "Already writing the AST!"); + + if (!TD->getFirstDecl()->isFromASTFile()) + return; + if (Chain && Chain->isProcessingUpdateRecords()) + return; + + DeclsToEmitEvenIfUnreferenced.push_back(D); +} + +void ASTWriter::AddedCXXTemplateSpecialization( + const VarTemplateDecl *TD, const VarTemplateSpecializationDecl *D) { + assert(!WritingAST && "Already writing the AST!"); + + if (!TD->getFirstDecl()->isFromASTFile()) + return; + if (Chain && Chain->isProcessingUpdateRecords()) + return; + + DeclsToEmitEvenIfUnreferenced.push_back(D); +} + +void ASTWriter::AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD, + const FunctionDecl *D) { + assert(!WritingAST && "Already writing the AST!"); + + if (!TD->getFirstDecl()->isFromASTFile()) + return; + if (Chain && Chain->isProcessingUpdateRecords()) + return; + + DeclsToEmitEvenIfUnreferenced.push_back(D); +} diff --git a/clang/test/Modules/Inputs/merge-template-specializations/a.h b/clang/test/Modules/Inputs/merge-template-specializations/a.h new file mode 100644 index 00000000000..fb05647c0aa --- /dev/null +++ b/clang/test/Modules/Inputs/merge-template-specializations/a.h @@ -0,0 +1 @@ +template<unsigned> class SmallString {}; diff --git a/clang/test/Modules/Inputs/merge-template-specializations/b.h b/clang/test/Modules/Inputs/merge-template-specializations/b.h new file mode 100644 index 00000000000..96ce2bb1d8d --- /dev/null +++ b/clang/test/Modules/Inputs/merge-template-specializations/b.h @@ -0,0 +1,2 @@ +#include "a.h" +void f(SmallString<256>&); diff --git a/clang/test/Modules/Inputs/merge-template-specializations/c.h b/clang/test/Modules/Inputs/merge-template-specializations/c.h new file mode 100644 index 00000000000..100463a2f7f --- /dev/null +++ b/clang/test/Modules/Inputs/merge-template-specializations/c.h @@ -0,0 +1,3 @@ +#include "a.h" +struct X { SmallString<256> ss; }; +#include "b.h" diff --git a/clang/test/Modules/Inputs/merge-template-specializations/module.modulemap b/clang/test/Modules/Inputs/merge-template-specializations/module.modulemap new file mode 100644 index 00000000000..77e0a89e39a --- /dev/null +++ b/clang/test/Modules/Inputs/merge-template-specializations/module.modulemap @@ -0,0 +1,3 @@ +module a { header "a.h" export * } +module b { header "b.h" export * } +module c { header "c.h" export * } diff --git a/clang/test/Modules/cxx-templates.cpp b/clang/test/Modules/cxx-templates.cpp index 12dfdd0546e..c2d38497dd7 100644 --- a/clang/test/Modules/cxx-templates.cpp +++ b/clang/test/Modules/cxx-templates.cpp @@ -249,10 +249,10 @@ namespace Std { // CHECK-DUMP: ClassTemplateDecl {{.*}} <{{.*[/\\]}}cxx-templates-common.h:1:1, {{.*}}> col:{{.*}} in cxx_templates_common SomeTemplate // CHECK-DUMP: ClassTemplateSpecializationDecl {{.*}} prev {{.*}} SomeTemplate -// CHECK-DUMP-NEXT: TemplateArgument type 'char [1]' -// CHECK-DUMP: ClassTemplateSpecializationDecl {{.*}} SomeTemplate definition -// CHECK-DUMP-NEXT: TemplateArgument type 'char [1]' -// CHECK-DUMP: ClassTemplateSpecializationDecl {{.*}} prev {{.*}} SomeTemplate // CHECK-DUMP-NEXT: TemplateArgument type 'char [2]' // CHECK-DUMP: ClassTemplateSpecializationDecl {{.*}} SomeTemplate definition // CHECK-DUMP-NEXT: TemplateArgument type 'char [2]' +// CHECK-DUMP: ClassTemplateSpecializationDecl {{.*}} prev {{.*}} SomeTemplate +// CHECK-DUMP-NEXT: TemplateArgument type 'char [1]' +// CHECK-DUMP: ClassTemplateSpecializationDecl {{.*}} SomeTemplate definition +// CHECK-DUMP-NEXT: TemplateArgument type 'char [1]' diff --git a/clang/test/Modules/merge-template-specializations.cpp b/clang/test/Modules/merge-template-specializations.cpp new file mode 100644 index 00000000000..25db93fbbb2 --- /dev/null +++ b/clang/test/Modules/merge-template-specializations.cpp @@ -0,0 +1,5 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -fimplicit-module-maps -fmodules-local-submodule-visibility -I%S/Inputs/merge-template-specializations -std=c++11 -verify %s +// expected-no-diagnostics +#include "c.h" +X x; |