summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Serialization/ASTWriter.h15
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp45
-rw-r--r--clang/test/Modules/Inputs/merge-template-specializations/a.h1
-rw-r--r--clang/test/Modules/Inputs/merge-template-specializations/b.h2
-rw-r--r--clang/test/Modules/Inputs/merge-template-specializations/c.h3
-rw-r--r--clang/test/Modules/Inputs/merge-template-specializations/module.modulemap3
-rw-r--r--clang/test/Modules/cxx-templates.cpp8
-rw-r--r--clang/test/Modules/merge-template-specializations.cpp5
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;
OpenPOWER on IntegriCloud