From: Richard Smith Date: Thu, 22 May 2014 20:59:29 +0000 (+0000) Subject: If a class template specialization from one module has its definition X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=66936e192ccd1c61dd706fb57e267a483319569f;p=clang 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 --- 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(RD); Spec->setTemplateSpecializationKind(TSK); Spec->setPointOfInstantiation(POI); + + if (Record[Idx++]) { + auto PartialSpec = + ReadDeclAs(Record, Idx); + SmallVector 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(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()) { + 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 { }; void InstantiateWithFriend(Std::WithFriend wfi) {} + +template struct WithPartialSpecialization { + 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 struct Outer { void g(); }; }; + +template struct WithPartialSpecialization {}; +typedef WithPartialSpecialization 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 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 tiv4; + + int &p = WithPartialSpecializationUse().f(); } RedeclaredAsFriend raf1;