summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/AST/DeclTemplate.h18
-rw-r--r--clang/lib/Serialization/ASTReader.cpp15
-rw-r--r--clang/test/Modules/Inputs/merge-template-members/def.h2
-rw-r--r--clang/test/Modules/Inputs/merge-template-members/module.modulemap2
-rw-r--r--clang/test/Modules/Inputs/merge-template-members/update.h2
-rw-r--r--clang/test/Modules/merge-template-members.cpp10
6 files changed, 40 insertions, 9 deletions
diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h
index 9283d2dc435..58f24d9b87e 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -788,9 +788,6 @@ protected:
friend class FunctionDecl;
- /// \brief Load any lazily-loaded specializations from the external source.
- void LoadLazySpecializations() const;
-
/// \brief Retrieve the set of function template specializations of this
/// function template.
llvm::FoldingSetVector<FunctionTemplateSpecializationInfo> &
@@ -804,6 +801,9 @@ protected:
void *InsertPos);
public:
+ /// \brief Load any lazily-loaded specializations from the external source.
+ void LoadLazySpecializations() const;
+
/// Get the underlying function declaration of the template.
FunctionDecl *getTemplatedDecl() const {
return static_cast<FunctionDecl*>(TemplatedDecl);
@@ -1827,9 +1827,6 @@ protected:
uint32_t *LazySpecializations;
};
- /// \brief Load any lazily-loaded specializations from the external source.
- void LoadLazySpecializations() const;
-
/// \brief Retrieve the set of specializations of this class template.
llvm::FoldingSetVector<ClassTemplateSpecializationDecl> &
getSpecializations() const;
@@ -1851,6 +1848,9 @@ protected:
}
public:
+ /// \brief Load any lazily-loaded specializations from the external source.
+ void LoadLazySpecializations() const;
+
/// \brief Get the underlying class declarations of the template.
CXXRecordDecl *getTemplatedDecl() const {
return static_cast<CXXRecordDecl *>(TemplatedDecl);
@@ -2662,9 +2662,6 @@ protected:
uint32_t *LazySpecializations;
};
- /// \brief Load any lazily-loaded specializations from the external source.
- void LoadLazySpecializations() const;
-
/// \brief Retrieve the set of specializations of this variable template.
llvm::FoldingSetVector<VarTemplateSpecializationDecl> &
getSpecializations() const;
@@ -2686,6 +2683,9 @@ protected:
}
public:
+ /// \brief Load any lazily-loaded specializations from the external source.
+ void LoadLazySpecializations() const;
+
/// \brief Get the underlying variable declarations of the template.
VarDecl *getTemplatedDecl() const {
return static_cast<VarDecl *>(TemplatedDecl);
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index f7822b74769..5b9ad12a3c5 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -6081,6 +6081,12 @@ Decl *ASTReader::GetExternalDecl(uint32_t ID) {
return GetDecl(ID);
}
+template<typename TemplateSpecializationDecl>
+static void completeRedeclChainForTemplateSpecialization(Decl *D) {
+ if (auto *TSD = dyn_cast<TemplateSpecializationDecl>(D))
+ TSD->getSpecializedTemplate()->LoadLazySpecializations();
+}
+
void ASTReader::CompleteRedeclChain(const Decl *D) {
if (NumCurrentElementsDeserializing) {
// We arrange to not care about the complete redeclaration chain while we're
@@ -6114,6 +6120,15 @@ void ASTReader::CompleteRedeclChain(const Decl *D) {
D->getDeclContext()->decls_begin();
}
}
+
+ if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D))
+ CTSD->getSpecializedTemplate()->LoadLazySpecializations();
+ if (auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(D))
+ VTSD->getSpecializedTemplate()->LoadLazySpecializations();
+ if (auto *FD = dyn_cast<FunctionDecl>(D)) {
+ if (auto *Template = FD->getPrimaryTemplate())
+ Template->LoadLazySpecializations();
+ }
}
uint64_t ASTReader::readCXXBaseSpecifiers(ModuleFile &M,
diff --git a/clang/test/Modules/Inputs/merge-template-members/def.h b/clang/test/Modules/Inputs/merge-template-members/def.h
new file mode 100644
index 00000000000..f9f65c34db0
--- /dev/null
+++ b/clang/test/Modules/Inputs/merge-template-members/def.h
@@ -0,0 +1,2 @@
+template<typename> struct A { int n; };
+template<typename> struct B { typedef A<void> C; };
diff --git a/clang/test/Modules/Inputs/merge-template-members/module.modulemap b/clang/test/Modules/Inputs/merge-template-members/module.modulemap
new file mode 100644
index 00000000000..9ce569074d8
--- /dev/null
+++ b/clang/test/Modules/Inputs/merge-template-members/module.modulemap
@@ -0,0 +1,2 @@
+module def { header "def.h" export * }
+module update { header "update.h" export * }
diff --git a/clang/test/Modules/Inputs/merge-template-members/update.h b/clang/test/Modules/Inputs/merge-template-members/update.h
new file mode 100644
index 00000000000..cceb52db403
--- /dev/null
+++ b/clang/test/Modules/Inputs/merge-template-members/update.h
@@ -0,0 +1,2 @@
+#include "def.h"
+B<int>::C use1;
diff --git a/clang/test/Modules/merge-template-members.cpp b/clang/test/Modules/merge-template-members.cpp
new file mode 100644
index 00000000000..99696d8ad1c
--- /dev/null
+++ b/clang/test/Modules/merge-template-members.cpp
@@ -0,0 +1,10 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -I%S/Inputs/merge-template-members -verify %s
+// expected-no-diagnostics
+
+template<typename> struct A { int n; };
+template<typename> struct B { typedef A<void> C; };
+template class B<int>;
+
+#include "update.h"
+B<int>::C use2;
OpenPOWER on IntegriCloud