}
/// \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
/// \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.
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);
}
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(
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);
+@import cxx_templates_common;
+
template<typename T> T f() { return T(); }
template<typename T> T f(T);
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;
+@import cxx_templates_common;
+
template<typename T> T f();
template<typename T> T f(T t) { return t; }
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;
--- /dev/null
+template<typename T> struct SomeTemplate {};
header "cxx-linkage-cache.h"
}
+module cxx_templates_common {
+ header "cxx-templates-common.h"
+}
+
module cxx_templates_a {
header "cxx-templates-a.h"
}
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'