From: Richard Smith Date: Fri, 11 Jul 2014 18:22:58 +0000 (+0000) Subject: [modules] When merging a class template, also merge the definition of its pattern. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f51820546dc8019230a0f84774779ba3cb46e5f5;p=clang [modules] When merging a class template, also merge the definition of its pattern. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@212836 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index f9fed46ad9..5ef4a5cdab 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -1758,11 +1758,11 @@ ASTDeclReader::VisitClassTemplateSpecializationDeclImpl( Reader.MergedDeclContexts.insert( std::make_pair(D, CanonDD->Definition)); D->IsCompleteDefinition = false; - D->DefinitionData = CanonSpec->DefinitionData; } else { CanonSpec->DefinitionData = D->DefinitionData; } } + D->DefinitionData = CanonSpec->DefinitionData; } } } @@ -2037,10 +2037,27 @@ void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D, auto *DPattern = D->getTemplatedDecl(); auto *ExistingPattern = Existing->getTemplatedDecl(); RedeclarableResult Result(Reader, DsID, DPattern->getKind()); - if (auto *DClass = dyn_cast(DPattern)) - // FIXME: Merge definitions here, if both declarations had definitions. + if (auto *DClass = dyn_cast(DPattern)) { + // Merge with any existing definition. + // FIXME: This is duplicated in several places. Refactor. + auto *ExistingClass = + cast(ExistingPattern)->getCanonicalDecl(); + if (auto *DDD = DClass->DefinitionData.getNotUpdated()) { + if (auto *ExistingDD = ExistingClass->DefinitionData.getNotUpdated()) { + MergeDefinitionData(ExistingClass, *DDD); + Reader.PendingDefinitions.erase(DClass); + Reader.MergedDeclContexts.insert( + std::make_pair(DClass, ExistingDD->Definition)); + DClass->IsCompleteDefinition = false; + } else { + ExistingClass->DefinitionData = DClass->DefinitionData; + } + } + DClass->DefinitionData = ExistingClass->DefinitionData; + return mergeRedeclarable(DClass, cast(ExistingPattern), Result); + } if (auto *DFunction = dyn_cast(DPattern)) return mergeRedeclarable(DFunction, cast(ExistingPattern), Result); diff --git a/test/Modules/Inputs/cxx-templates-a.h b/test/Modules/Inputs/cxx-templates-a.h index 5ac1697bff..c95dc6325e 100644 --- a/test/Modules/Inputs/cxx-templates-a.h +++ b/test/Modules/Inputs/cxx-templates-a.h @@ -67,3 +67,9 @@ template<> struct WithExplicitSpecialization { template template constexpr int Outer::Inner::f() { return 1; } static_assert(Outer::Inner::f() == 1, ""); + +template struct MergeTemplateDefinitions { + static constexpr int f(); + static constexpr int g(); +}; +template constexpr int MergeTemplateDefinitions::f() { return 1; } diff --git a/test/Modules/Inputs/cxx-templates-c.h b/test/Modules/Inputs/cxx-templates-c.h index 4c0fc8a4a8..6daffadc6c 100644 --- a/test/Modules/Inputs/cxx-templates-c.h +++ b/test/Modules/Inputs/cxx-templates-c.h @@ -5,3 +5,9 @@ template struct MergeSpecializations { template<> struct MergeSpecializations { typedef int explicitly_specialized_in_c; }; + +template struct MergeTemplateDefinitions { + static constexpr int f(); + static constexpr int g(); +}; +template constexpr int MergeTemplateDefinitions::g() { return 2; } diff --git a/test/Modules/cxx-templates.cpp b/test/Modules/cxx-templates.cpp index 679d7d12b1..cbe9f35089 100644 --- a/test/Modules/cxx-templates.cpp +++ b/test/Modules/cxx-templates.cpp @@ -110,6 +110,9 @@ void g() { static_assert(Outer::Inner::f() == 1, ""); static_assert(Outer::Inner::g() == 2, ""); +static_assert(MergeTemplateDefinitions::f() == 1, ""); +static_assert(MergeTemplateDefinitions::g() == 2, ""); + RedeclaredAsFriend raf1; RedeclareTemplateAsFriend rtaf; RedeclaredAsFriend raf2;