summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2014-05-22 20:59:29 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2014-05-22 20:59:29 +0000
commit66936e192ccd1c61dd706fb57e267a483319569f (patch)
tree3404a78a709c09f67f00c74058d3d05efa525962
parent3175e5fb93c1aeaaeafa01c34731c45c348aa804 (diff)
downloadclang-66936e192ccd1c61dd706fb57e267a483319569f.tar.gz
clang-66936e192ccd1c61dd706fb57e267a483319569f.tar.bz2
clang-66936e192ccd1c61dd706fb57e267a483319569f.tar.xz
If a class template specialization from one module has its definition
instantiated in another module, and the instantiation uses a partial specialization, include the partial specialization and its template arguments in the update record. We'll need them if someone imports the second module and tries to instantiate a member of the template. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@209472 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp10
-rw-r--r--lib/Serialization/ASTWriter.cpp13
-rw-r--r--test/Modules/Inputs/cxx-templates-a.h6
-rw-r--r--test/Modules/Inputs/cxx-templates-common.h3
-rw-r--r--test/Modules/cxx-templates.cpp2
5 files changed, 34 insertions, 0 deletions
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index 696a78295c..d900f71c46 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -3201,6 +3201,16 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
cast<ClassTemplateSpecializationDecl>(RD);
Spec->setTemplateSpecializationKind(TSK);
Spec->setPointOfInstantiation(POI);
+
+ if (Record[Idx++]) {
+ auto PartialSpec =
+ ReadDeclAs<ClassTemplatePartialSpecializationDecl>(Record, Idx);
+ SmallVector<TemplateArgument, 8> TemplArgs;
+ Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx);
+ auto *TemplArgList = TemplateArgumentList::CreateCopy(
+ Reader.getContext(), TemplArgs.data(), TemplArgs.size());
+ Spec->setInstantiationOf(PartialSpec, TemplArgList);
+ }
}
RD->setTagKind((TagTypeKind)Record[Idx++]);
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index d335c94861..7753986d58 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -4531,6 +4531,19 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
auto *Spec = cast<ClassTemplateSpecializationDecl>(RD);
Record.push_back(Spec->getTemplateSpecializationKind());
AddSourceLocation(Spec->getPointOfInstantiation(), Record);
+
+ // The instantiation might have been resolved to a partial
+ // specialization. If so, record which one.
+ auto From = Spec->getInstantiatedFrom();
+ if (auto PartialSpec =
+ From.dyn_cast<ClassTemplatePartialSpecializationDecl*>()) {
+ Record.push_back(true);
+ AddDeclRef(PartialSpec, Record);
+ AddTemplateArgumentList(&Spec->getTemplateInstantiationArgs(),
+ Record);
+ } else {
+ Record.push_back(false);
+ }
}
Record.push_back(RD->getTagKind());
AddSourceLocation(RD->getLocation(), Record);
diff --git a/test/Modules/Inputs/cxx-templates-a.h b/test/Modules/Inputs/cxx-templates-a.h
index 6ecc2ca461..04acf5929d 100644
--- a/test/Modules/Inputs/cxx-templates-a.h
+++ b/test/Modules/Inputs/cxx-templates-a.h
@@ -50,3 +50,9 @@ template<> struct MergeSpecializations<char> {
};
void InstantiateWithFriend(Std::WithFriend<int> wfi) {}
+
+template<typename T> struct WithPartialSpecialization<T*> {
+ typedef int type;
+ T &f() { static T t; return t; }
+};
+typedef WithPartialSpecializationUse::type WithPartialSpecializationInstantiate;
diff --git a/test/Modules/Inputs/cxx-templates-common.h b/test/Modules/Inputs/cxx-templates-common.h
index 4a10e35880..a31be8758c 100644
--- a/test/Modules/Inputs/cxx-templates-common.h
+++ b/test/Modules/Inputs/cxx-templates-common.h
@@ -30,3 +30,6 @@ template<typename T> struct Outer {
void g();
};
};
+
+template<typename T> struct WithPartialSpecialization {};
+typedef WithPartialSpecialization<int*> WithPartialSpecializationUse;
diff --git a/test/Modules/cxx-templates.cpp b/test/Modules/cxx-templates.cpp
index ab65e3dd2d..a880c9b2f1 100644
--- a/test/Modules/cxx-templates.cpp
+++ b/test/Modules/cxx-templates.cpp
@@ -102,6 +102,8 @@ void g() {
TemplateInstantiationVisibility<char[3]> tiv3; // expected-error {{must be imported from module 'cxx_templates_b_impl'}}
// expected-note@cxx-templates-b-impl.h:10 {{previous definition is here}}
TemplateInstantiationVisibility<char[4]> tiv4;
+
+ int &p = WithPartialSpecializationUse().f();
}
RedeclaredAsFriend<int> raf1;