From 9db7f57c1e3db8a2d06a833a4e0341f0fe310640 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Tue, 25 Jun 2013 01:25:15 +0000 Subject: [PATCH] Fix deserializing of class template partial specializations. Assign sequence numbers as we deserialize class template partial specializations. We can't assume that the old sequence numbers will work. The sequence numbers are still deterministic, but are now a lot less predictable for class template partial specializations in modules/PCH. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@184811 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/DeclTemplate.h | 7 +++-- lib/Serialization/ASTReaderDecl.cpp | 11 ++++---- lib/Serialization/ASTWriterDecl.cpp | 2 -- test/Modules/Inputs/cxx-templates-a.h | 6 +++++ test/Modules/Inputs/cxx-templates-b.h | 6 +++++ test/Modules/Inputs/cxx-templates-common.h | 1 + test/Modules/Inputs/module.map | 4 +++ test/Modules/cxx-templates.cpp | 31 +++++++++++++--------- 8 files changed, 47 insertions(+), 21 deletions(-) create mode 100644 test/Modules/Inputs/cxx-templates-common.h diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index d301da8b3f..89c0f05a8f 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -1711,7 +1711,8 @@ public: } /// \brief Get the sequence number for this class template partial - /// specialization. + /// specialization. Internal, only valid for specializations which + /// are in the specialized class template's folding set. unsigned getSequenceNumber() const { return SequenceNumber; } /// \brief Retrieve the member class template partial specialization from @@ -1928,7 +1929,9 @@ public: /// \brief Return the next partial specialization sequence number. unsigned getNextPartialSpecSequenceNumber() { - return getPartialSpecializations().size(); + // Do not load lazy specializations here. They get numbered as they are + // loaded. + return getCommonPtr()->PartialSpecializations.size(); } /// \brief Retrieve the partial specializations as an ordered list. diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index a7305c887d..df6abc934f 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -1458,9 +1458,12 @@ ASTDeclReader::VisitClassTemplateSpecializationDeclImpl( if (writtenAsCanonicalDecl) { ClassTemplateDecl *CanonPattern = ReadDeclAs(Record,Idx); if (D->isCanonicalDecl()) { // It's kept in the folding set. - if (ClassTemplatePartialSpecializationDecl *Partial - = dyn_cast(D)) { - CanonPattern->getCommonPtr()->PartialSpecializations.GetOrInsertNode(Partial); + if (ClassTemplatePartialSpecializationDecl *Partial = + dyn_cast(D)) { + Partial->SequenceNumber = + CanonPattern->getNextPartialSpecSequenceNumber(); + CanonPattern->getCommonPtr()->PartialSpecializations + .GetOrInsertNode(Partial); } else { CanonPattern->getCommonPtr()->Specializations.GetOrInsertNode(D); } @@ -1485,8 +1488,6 @@ void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl( D->ArgsAsWritten[i] = Reader.ReadTemplateArgumentLoc(F, Record, Idx); } - D->SequenceNumber = Record[Idx++]; - // These are read/set from/to the first declaration. if (ThisDeclID == Redecl.getFirstID()) { D->InstantiatedFromMember.setPointer( diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index b60106408f..d8d351ae5f 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -1174,8 +1174,6 @@ void ASTDeclWriter::VisitClassTemplatePartialSpecializationDecl( for (int i = 0, e = D->getNumTemplateArgsAsWritten(); i != e; ++i) Writer.AddTemplateArgumentLoc(D->getTemplateArgsAsWritten()[i], Record); - Record.push_back(D->getSequenceNumber()); - // These are read/set from/to the first declaration. if (D->getPreviousDecl() == 0) { Writer.AddDeclRef(D->getInstantiatedFromMember(), Record); diff --git a/test/Modules/Inputs/cxx-templates-a.h b/test/Modules/Inputs/cxx-templates-a.h index 76997c7bdb..7770d345ed 100644 --- a/test/Modules/Inputs/cxx-templates-a.h +++ b/test/Modules/Inputs/cxx-templates-a.h @@ -1,3 +1,5 @@ +@import cxx_templates_common; + template T f() { return T(); } template T f(T); namespace N { @@ -8,3 +10,7 @@ namespace N { template int template_param_kinds_1(); template class> int template_param_kinds_2(); template class> int template_param_kinds_3(); + +template struct SomeTemplate; +template struct SomeTemplate {}; +typedef SomeTemplate SomeTemplateIntPtr; diff --git a/test/Modules/Inputs/cxx-templates-b.h b/test/Modules/Inputs/cxx-templates-b.h index c50d7059b4..e0f67d076c 100644 --- a/test/Modules/Inputs/cxx-templates-b.h +++ b/test/Modules/Inputs/cxx-templates-b.h @@ -1,3 +1,5 @@ +@import cxx_templates_common; + template T f(); template T f(T t) { return t; } namespace N { @@ -8,3 +10,7 @@ namespace N { template int template_param_kinds_1(); template class> int template_param_kinds_2(); template class> int template_param_kinds_3(); + +template struct SomeTemplate {}; +template struct SomeTemplate; +typedef SomeTemplate SomeTemplateIntRef; diff --git a/test/Modules/Inputs/cxx-templates-common.h b/test/Modules/Inputs/cxx-templates-common.h new file mode 100644 index 0000000000..950a2a61e3 --- /dev/null +++ b/test/Modules/Inputs/cxx-templates-common.h @@ -0,0 +1 @@ +template struct SomeTemplate {}; diff --git a/test/Modules/Inputs/module.map b/test/Modules/Inputs/module.map index d2ed75830b..a4ac5b14de 100644 --- a/test/Modules/Inputs/module.map +++ b/test/Modules/Inputs/module.map @@ -188,6 +188,10 @@ module cxx_linkage_cache { header "cxx-linkage-cache.h" } +module cxx_templates_common { + header "cxx-templates-common.h" +} + module cxx_templates_a { header "cxx-templates-a.h" } diff --git a/test/Modules/cxx-templates.cpp b/test/Modules/cxx-templates.cpp index 7d500f4896..84c93df5a3 100644 --- a/test/Modules/cxx-templates.cpp +++ b/test/Modules/cxx-templates.cpp @@ -17,37 +17,44 @@ void g() { f(1.0); f(); f(); // expected-error {{no matching function}} - // expected-note@Inputs/cxx-templates-b.h:1 {{couldn't infer template argument}} - // expected-note@Inputs/cxx-templates-b.h:2 {{requires single argument}} + // expected-note@Inputs/cxx-templates-b.h:3 {{couldn't infer template argument}} + // expected-note@Inputs/cxx-templates-b.h:4 {{requires single argument}} N::f(0); N::f(1.0); N::f(); N::f(); // expected-error {{no matching function}} - // expected-note@Inputs/cxx-templates-a.h:4 {{couldn't infer template argument}} - // expected-note@Inputs/cxx-templates-a.h:5 {{requires 1 argument, but 0 were provided}} + // expected-note@Inputs/cxx-templates-a.h:6 {{couldn't infer template argument}} + // expected-note@Inputs/cxx-templates-a.h:7 {{requires 1 argument, but 0 were provided}} template_param_kinds_1<0>(); // ok, from cxx-templates-a.h template_param_kinds_1(); // ok, from cxx-templates-b.h template_param_kinds_2(); // expected-error {{no matching function}} - // expected-note@Inputs/cxx-templates-a.h:9 {{invalid explicitly-specified argument}} - // expected-note@Inputs/cxx-templates-b.h:9 {{invalid explicitly-specified argument}} + // expected-note@Inputs/cxx-templates-a.h:11 {{invalid explicitly-specified argument}} + // expected-note@Inputs/cxx-templates-b.h:11 {{invalid explicitly-specified argument}} template_param_kinds_2(); // expected-error {{ambiguous}} - // expected-note@Inputs/cxx-templates-a.h:9 {{candidate}} - // expected-note@Inputs/cxx-templates-b.h:9 {{candidate}} + // expected-note@Inputs/cxx-templates-a.h:11 {{candidate}} + // expected-note@Inputs/cxx-templates-b.h:11 {{candidate}} // FIXME: This should be valid, but we incorrectly match the template template // argument against both template template parameters. template_param_kinds_3(); // expected-error {{ambiguous}} - // expected-note@Inputs/cxx-templates-a.h:10 {{candidate}} - // expected-note@Inputs/cxx-templates-b.h:10 {{candidate}} + // expected-note@Inputs/cxx-templates-a.h:12 {{candidate}} + // expected-note@Inputs/cxx-templates-b.h:12 {{candidate}} template_param_kinds_3(); // expected-error {{ambiguous}} - // expected-note@Inputs/cxx-templates-a.h:10 {{candidate}} - // expected-note@Inputs/cxx-templates-b.h:10 {{candidate}} + // expected-note@Inputs/cxx-templates-a.h:12 {{candidate}} + // expected-note@Inputs/cxx-templates-b.h:12 {{candidate}} } +@import cxx_templates_common; + +typedef SomeTemplate SomeTemplateIntPtr; +typedef SomeTemplate SomeTemplateIntRef; +SomeTemplate some_template_char_ptr; +SomeTemplate some_template_char_ref; + // FIXME: There should only be two 'f's here. // CHECK-GLOBAL: DeclarationName 'f' // CHECK-GLOBAL-NEXT: |-FunctionTemplate {{.*}} 'f' -- 2.40.0