mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-14 11:39:35 +00:00
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. llvm-svn: 184811
This commit is contained in:
parent
0423b76be1
commit
5de91b58d0
@ -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.
|
||||
|
@ -1458,9 +1458,12 @@ ASTDeclReader::VisitClassTemplateSpecializationDeclImpl(
|
||||
if (writtenAsCanonicalDecl) {
|
||||
ClassTemplateDecl *CanonPattern = ReadDeclAs<ClassTemplateDecl>(Record,Idx);
|
||||
if (D->isCanonicalDecl()) { // It's kept in the folding set.
|
||||
if (ClassTemplatePartialSpecializationDecl *Partial
|
||||
= dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) {
|
||||
CanonPattern->getCommonPtr()->PartialSpecializations.GetOrInsertNode(Partial);
|
||||
if (ClassTemplatePartialSpecializationDecl *Partial =
|
||||
dyn_cast<ClassTemplatePartialSpecializationDecl>(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(
|
||||
|
@ -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);
|
||||
|
@ -1,3 +1,5 @@
|
||||
@import cxx_templates_common;
|
||||
|
||||
template<typename T> T f() { return T(); }
|
||||
template<typename T> T f(T);
|
||||
namespace N {
|
||||
@ -8,3 +10,7 @@ namespace N {
|
||||
template<int N> int template_param_kinds_1();
|
||||
template<template<typename T, int, int> class> int template_param_kinds_2();
|
||||
template<template<typename T, typename U, T> class> int template_param_kinds_3();
|
||||
|
||||
template<typename T> struct SomeTemplate<T*>;
|
||||
template<typename T> struct SomeTemplate<T*> {};
|
||||
typedef SomeTemplate<int*> SomeTemplateIntPtr;
|
||||
|
@ -1,3 +1,5 @@
|
||||
@import cxx_templates_common;
|
||||
|
||||
template<typename T> T f();
|
||||
template<typename T> T f(T t) { return t; }
|
||||
namespace N {
|
||||
@ -8,3 +10,7 @@ namespace N {
|
||||
template<typename> int template_param_kinds_1();
|
||||
template<template<typename, int, int...> class> int template_param_kinds_2();
|
||||
template<template<typename T, typename U, U> class> int template_param_kinds_3();
|
||||
|
||||
template<typename T> struct SomeTemplate<T&> {};
|
||||
template<typename T> struct SomeTemplate<T&>;
|
||||
typedef SomeTemplate<int&> SomeTemplateIntRef;
|
||||
|
1
clang/test/Modules/Inputs/cxx-templates-common.h
Normal file
1
clang/test/Modules/Inputs/cxx-templates-common.h
Normal file
@ -0,0 +1 @@
|
||||
template<typename T> struct SomeTemplate {};
|
@ -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"
|
||||
}
|
||||
|
@ -17,37 +17,44 @@ void g() {
|
||||
f<double>(1.0);
|
||||
f<int>();
|
||||
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<double>(1.0);
|
||||
N::f<int>();
|
||||
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<int>(); // ok, from cxx-templates-b.h
|
||||
|
||||
template_param_kinds_2<Tmpl_T_C>(); // 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<Tmpl_T_I_I>(); // 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<Tmpl_T_T_A>(); // 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<Tmpl_T_T_B>(); // 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<int*> SomeTemplateIntPtr;
|
||||
typedef SomeTemplate<int&> SomeTemplateIntRef;
|
||||
SomeTemplate<char*> some_template_char_ptr;
|
||||
SomeTemplate<char&> some_template_char_ref;
|
||||
|
||||
// FIXME: There should only be two 'f's here.
|
||||
// CHECK-GLOBAL: DeclarationName 'f'
|
||||
// CHECK-GLOBAL-NEXT: |-FunctionTemplate {{.*}} 'f'
|
||||
|
Loading…
Reference in New Issue
Block a user