diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2014-05-22 20:59:29 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2014-05-22 20:59:29 +0000 |
commit | 66936e192ccd1c61dd706fb57e267a483319569f (patch) | |
tree | 3404a78a709c09f67f00c74058d3d05efa525962 | |
parent | 3175e5fb93c1aeaaeafa01c34731c45c348aa804 (diff) | |
download | clang-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.cpp | 10 | ||||
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 13 | ||||
-rw-r--r-- | test/Modules/Inputs/cxx-templates-a.h | 6 | ||||
-rw-r--r-- | test/Modules/Inputs/cxx-templates-common.h | 3 | ||||
-rw-r--r-- | test/Modules/cxx-templates.cpp | 2 |
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; |