diff options
| -rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 23 | ||||
| -rw-r--r-- | clang/test/Modules/Inputs/cxx-templates-a.h | 6 | ||||
| -rw-r--r-- | clang/test/Modules/Inputs/cxx-templates-c.h | 6 | ||||
| -rw-r--r-- | clang/test/Modules/cxx-templates.cpp | 3 |
4 files changed, 35 insertions, 3 deletions
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index f9fed46ad9c..5ef4a5cdabd 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/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<CXXRecordDecl>(DPattern)) - // FIXME: Merge definitions here, if both declarations had definitions. + if (auto *DClass = dyn_cast<CXXRecordDecl>(DPattern)) { + // Merge with any existing definition. + // FIXME: This is duplicated in several places. Refactor. + auto *ExistingClass = + cast<CXXRecordDecl>(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<TagDecl>(ExistingPattern), Result); + } if (auto *DFunction = dyn_cast<FunctionDecl>(DPattern)) return mergeRedeclarable(DFunction, cast<FunctionDecl>(ExistingPattern), Result); diff --git a/clang/test/Modules/Inputs/cxx-templates-a.h b/clang/test/Modules/Inputs/cxx-templates-a.h index 5ac1697bff6..c95dc6325e4 100644 --- a/clang/test/Modules/Inputs/cxx-templates-a.h +++ b/clang/test/Modules/Inputs/cxx-templates-a.h @@ -67,3 +67,9 @@ template<> struct WithExplicitSpecialization<int> { template<typename T> template<typename U> constexpr int Outer<T>::Inner<U>::f() { return 1; } static_assert(Outer<int>::Inner<int>::f() == 1, ""); + +template<typename T> struct MergeTemplateDefinitions { + static constexpr int f(); + static constexpr int g(); +}; +template<typename T> constexpr int MergeTemplateDefinitions<T>::f() { return 1; } diff --git a/clang/test/Modules/Inputs/cxx-templates-c.h b/clang/test/Modules/Inputs/cxx-templates-c.h index 4c0fc8a4a82..6daffadc6ce 100644 --- a/clang/test/Modules/Inputs/cxx-templates-c.h +++ b/clang/test/Modules/Inputs/cxx-templates-c.h @@ -5,3 +5,9 @@ template<typename T> struct MergeSpecializations<T[]> { template<> struct MergeSpecializations<bool> { typedef int explicitly_specialized_in_c; }; + +template<typename T> struct MergeTemplateDefinitions { + static constexpr int f(); + static constexpr int g(); +}; +template<typename T> constexpr int MergeTemplateDefinitions<T>::g() { return 2; } diff --git a/clang/test/Modules/cxx-templates.cpp b/clang/test/Modules/cxx-templates.cpp index 679d7d12b1b..cbe9f350895 100644 --- a/clang/test/Modules/cxx-templates.cpp +++ b/clang/test/Modules/cxx-templates.cpp @@ -110,6 +110,9 @@ void g() { static_assert(Outer<int>::Inner<int>::f() == 1, ""); static_assert(Outer<int>::Inner<int>::g() == 2, ""); +static_assert(MergeTemplateDefinitions<int>::f() == 1, ""); +static_assert(MergeTemplateDefinitions<int>::g() == 2, ""); + RedeclaredAsFriend<int> raf1; RedeclareTemplateAsFriend<double> rtaf; RedeclaredAsFriend<double> raf2; |

