Index: clang/lib/Sema/SemaTemplate.cpp =================================================================== --- clang/lib/Sema/SemaTemplate.cpp +++ clang/lib/Sema/SemaTemplate.cpp @@ -4465,6 +4465,17 @@ } } + // The InsertPos needs to be reloaded: + // The call to TemplateSpecializationType::anyDependentTemplateArguments + // above may call ASTContext::getSubstTemplateTypeParmType. This function + // adds a new element in the FoldingSet InsertPos points at. If the + // FoldingSet resizes due to this insertion the 'iterator' is no longer + // valid. + VarTemplateSpecializationDecl *Spec = + Template->findSpecialization(Converted, InsertPos); + assert(!Spec && "Reloading InsertPos found a template specialization"); + (void)Spec; + // 2. Create the canonical declaration. // Note that we do not instantiate a definition until we see an odr-use // in DoMarkVarDeclReferenced(). Index: clang/test/SemaTemplate/instantiate-var-template.cpp =================================================================== --- clang/test/SemaTemplate/instantiate-var-template.cpp +++ clang/test/SemaTemplate/instantiate-var-template.cpp @@ -40,3 +40,68 @@ template A models; template<> struct B models<>; // expected-error {{incomplete type 'struct B'}} expected-note {{forward declaration}} } + +namespace PR43221 { +// This test crashed before so the main reason for the test is to see that it +// no longer will crash. + +template +struct enable_if; + +template <> +struct enable_if { using type = void; }; + +template +constexpr bool always_false = false; + +// expected-error@+3 {{invalid operands to binary expression}} +// expected-note@+2 {{in instantiation of member function}} +template +constexpr bool always_false = T() == T(); + +// expected-note@+2 {{candidate template ignored: substitution failure}} +template >::type> +bool operator==(T, T); + +// expected-note@+2 {{candidate template ignored: substitution failure}} +template >::type> +void data(T); + +template +struct S {}; +// expected-note@+2 {{candidate template ignored: could not match}} +template +constexpr bool operator==(S, S) { return false; } + +template +constexpr bool s = S() == S() and s; + +template <> +constexpr bool s<0> = S<0>() == S<0>(); + +void test() { s<127>; } // expected-warning {{expression result unused}} + +// expected-note@+2 2 {{while substituting deduced template arguments into function template}} +template +struct wrapper { + wrapper() = default; + wrapper(wrapper &&) = default; + + // expected-note@+3 {{in instantiation of variable template specialization}} + // expected-note@+2 {{during template argument deduction for variable template partial specialization}} + // expected-note@+2 2 {{in instantiation of default argument}} + template >::type> + explicit wrapper(U); + + // expected-error@+1 {{no matching function for call to 'data'}} + friend auto foo(wrapper w) { data(w.m); } + + int m; +}; + +// expected-note@+1 2 {{while declaring the implicit copy constructor for}} +struct wrapper2 { + wrapper m; +}; + +} // namespace PR43221