From: Richard Smith Date: Fri, 27 Feb 2015 00:25:58 +0000 (+0000) Subject: [modules] When loading in multiple canonical definitions of a template, X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=128b685d8fd20c188ec4281970da6d44939a7a19;p=clang [modules] When loading in multiple canonical definitions of a template, accumulate the set of specializations rather than overwriting one list with another. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@230712 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 339d0b87c2..a10ae1edf9 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -66,7 +66,12 @@ namespace clang { serialization::DeclID ReadDeclID(const RecordData &R, unsigned &I) { return Reader.ReadDeclID(F, R, I); } - + + void ReadDeclIDList(SmallVectorImpl &IDs) { + for (unsigned I = 0, Size = Record[Idx++]; I != Size; ++I) + IDs.push_back(ReadDeclID(Record, Idx)); + } + Decl *ReadDecl(const RecordData &R, unsigned &I) { return Reader.ReadDecl(F, R, I); } @@ -398,7 +403,6 @@ void ASTDeclReader::Visit(Decl *D) { // FunctionDecl's body was written last after all other Stmts/Exprs. // We only read it if FD doesn't already have a body (e.g., from another // module). - // FIXME: Also consider = default and = delete. // FIXME: Can we diagnose ODR violations somehow? if (Record[Idx++]) { Reader.PendingBodies[FD] = GetCurrentCursorOffset(); @@ -1393,8 +1397,6 @@ void ASTDeclReader::MergeDefinitionData( } // FIXME: Move this out into a .def file? - // FIXME: Issue a diagnostic on a mismatched MATCH_FIELD, rather than - // asserting; this can happen in the case of an ODR violation. bool DetectedOdrViolation = false; #define OR_FIELD(Field) DD.Field |= MergeDD.Field; #define MATCH_FIELD(Field) \ @@ -1723,36 +1725,37 @@ ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { return Redecl; } +static DeclID *newDeclIDList(ASTContext &Context, DeclID *Old, + SmallVectorImpl &IDs) { + assert(!IDs.empty() && "no IDs to add to list"); + + size_t OldCount = Old ? *Old : 0; + size_t NewCount = OldCount + IDs.size(); + auto *Result = new (Context) DeclID[1 + NewCount]; + auto *Pos = Result; + *Pos++ = NewCount; + if (OldCount) + Pos = std::copy(Old + 1, Old + 1 + OldCount, Pos); + std::copy(IDs.begin(), IDs.end(), Pos); + return Result; +} + void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) { RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D); if (ThisDeclID == Redecl.getFirstID()) { // This ClassTemplateDecl owns a CommonPtr; read it to keep track of all of // the specializations. - SmallVector SpecIDs; - SpecIDs.push_back(0); - + SmallVector SpecIDs; // Specializations. - unsigned Size = Record[Idx++]; - SpecIDs[0] += Size; - for (unsigned I = 0; I != Size; ++I) - SpecIDs.push_back(ReadDeclID(Record, Idx)); - + ReadDeclIDList(SpecIDs); // Partial specializations. - Size = Record[Idx++]; - SpecIDs[0] += Size; - for (unsigned I = 0; I != Size; ++I) - SpecIDs.push_back(ReadDeclID(Record, Idx)); - - ClassTemplateDecl::Common *CommonPtr = D->getCommonPtr(); - if (SpecIDs[0]) { - typedef serialization::DeclID DeclID; - - // FIXME: Append specializations! - CommonPtr->LazySpecializations - = new (Reader.getContext()) DeclID [SpecIDs.size()]; - memcpy(CommonPtr->LazySpecializations, SpecIDs.data(), - SpecIDs.size() * sizeof(DeclID)); + ReadDeclIDList(SpecIDs); + + if (!SpecIDs.empty()) { + auto *CommonPtr = D->getCommonPtr(); + CommonPtr->LazySpecializations = newDeclIDList( + Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs); } } @@ -1774,30 +1777,16 @@ void ASTDeclReader::VisitVarTemplateDecl(VarTemplateDecl *D) { if (ThisDeclID == Redecl.getFirstID()) { // This VarTemplateDecl owns a CommonPtr; read it to keep track of all of // the specializations. - SmallVector SpecIDs; - SpecIDs.push_back(0); - + SmallVector SpecIDs; // Specializations. - unsigned Size = Record[Idx++]; - SpecIDs[0] += Size; - for (unsigned I = 0; I != Size; ++I) - SpecIDs.push_back(ReadDeclID(Record, Idx)); - + ReadDeclIDList(SpecIDs); // Partial specializations. - Size = Record[Idx++]; - SpecIDs[0] += Size; - for (unsigned I = 0; I != Size; ++I) - SpecIDs.push_back(ReadDeclID(Record, Idx)); - - VarTemplateDecl::Common *CommonPtr = D->getCommonPtr(); - if (SpecIDs[0]) { - typedef serialization::DeclID DeclID; - - // FIXME: Append specializations! - CommonPtr->LazySpecializations = - new (Reader.getContext()) DeclID[SpecIDs.size()]; - memcpy(CommonPtr->LazySpecializations, SpecIDs.data(), - SpecIDs.size() * sizeof(DeclID)); + ReadDeclIDList(SpecIDs); + + if (!SpecIDs.empty()) { + auto *CommonPtr = D->getCommonPtr(); + CommonPtr->LazySpecializations = newDeclIDList( + Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs); } } } @@ -1909,17 +1898,13 @@ void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { if (ThisDeclID == Redecl.getFirstID()) { // This FunctionTemplateDecl owns a CommonPtr; read it. + SmallVector SpecIDs; + ReadDeclIDList(SpecIDs); - // Read the function specialization declaration IDs. The specializations - // themselves will be loaded if they're needed. - if (unsigned NumSpecs = Record[Idx++]) { - // FIXME: Append specializations! - FunctionTemplateDecl::Common *CommonPtr = D->getCommonPtr(); - CommonPtr->LazySpecializations = new (Reader.getContext()) - serialization::DeclID[NumSpecs + 1]; - CommonPtr->LazySpecializations[0] = NumSpecs; - for (unsigned I = 0; I != NumSpecs; ++I) - CommonPtr->LazySpecializations[I + 1] = ReadDeclID(Record, Idx); + if (!SpecIDs.empty()) { + auto *CommonPtr = D->getCommonPtr(); + CommonPtr->LazySpecializations = newDeclIDList( + Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs); } } } diff --git a/test/Modules/Inputs/merge-decl-context/a.h b/test/Modules/Inputs/merge-decl-context/a.h index bd08ecaf41..89cc7120fd 100644 --- a/test/Modules/Inputs/merge-decl-context/a.h +++ b/test/Modules/Inputs/merge-decl-context/a.h @@ -8,6 +8,8 @@ struct A { } A(double) {} A(double, double) {} + A(double, int) {} + A(int, double) {} }; template diff --git a/test/Modules/Inputs/merge-decl-context/d.h b/test/Modules/Inputs/merge-decl-context/d.h new file mode 100644 index 0000000000..ccc7308b24 --- /dev/null +++ b/test/Modules/Inputs/merge-decl-context/d.h @@ -0,0 +1,7 @@ +#ifndef D_H +#define D_H + +#include "a.h" +#include "b.h" + +#endif diff --git a/test/Modules/Inputs/merge-decl-context/merge-decl-context.modulemap b/test/Modules/Inputs/merge-decl-context/merge-decl-context.modulemap index fedc5dfbbe..46f69548bc 100644 --- a/test/Modules/Inputs/merge-decl-context/merge-decl-context.modulemap +++ b/test/Modules/Inputs/merge-decl-context/merge-decl-context.modulemap @@ -11,3 +11,8 @@ module "c" { export * header "c.h" } + +module "d" { + export * + header "d.h" +} diff --git a/test/Modules/merge-decl-context.cpp b/test/Modules/merge-decl-context.cpp index 90c234b66f..208ba9212e 100644 --- a/test/Modules/merge-decl-context.cpp +++ b/test/Modules/merge-decl-context.cpp @@ -4,21 +4,25 @@ // RUN: -emit-module %S/Inputs/merge-decl-context/merge-decl-context.modulemap -I%S/Inputs \ // RUN: -I %S/Inputs/merge-decl-context // RUN: %clang_cc1 -x c++ -std=c++11 -fmodules -fmodule-name=c -o %t/c.pcm -fmodule-maps \ -// RUN: -fmodule-file=%t/b.pcm \ +// RUN: -fmodule-file=%t/b.pcm -fno-implicit-modules \ +// RUN: -emit-module %S/Inputs/merge-decl-context/merge-decl-context.modulemap -I%S/Inputs \ +// RUN: -I %S/Inputs/merge-decl-context +// RUN: %clang_cc1 -x c++ -std=c++11 -fmodules -fmodule-name=d -o %t/d.pcm -fmodule-maps \ +// RUN: -fmodule-file=%t/b.pcm -fno-implicit-modules \ // RUN: -emit-module %S/Inputs/merge-decl-context/merge-decl-context.modulemap -I%S/Inputs \ // RUN: -I %S/Inputs/merge-decl-context // Use the two modules in a single compile. // RUN: %clang_cc1 -x c++ -std=c++11 -fmodules -fmodule-file=%t/c.pcm -fmodule-file=%t/b.pcm \ +// RUN: -fmodule-file=%t/d.pcm -fno-implicit-modules \ // RUN: -fmodule-map-file=%S/Inputs/merge-decl-context/merge-decl-context.modulemap -I%S/Inputs \ // RUN: -emit-llvm -o %t/test.o %s #include "Inputs/merge-decl-context/a.h" #include "Inputs/merge-decl-context/b.h" #include "Inputs/merge-decl-context/c.h" +#include "Inputs/merge-decl-context/d.h" void t() { ff(42); } - -