Mordante updated this revision to Diff 282460. Mordante added a comment. Rebased the patch and updated the unit tests.
CHANGES SINCE LAST ACTION https://reviews.llvm.org/D72103/new/ https://reviews.llvm.org/D72103 Files: clang/lib/Sema/SemaTemplate.cpp clang/test/SemaTemplate/instantiate-var-template.cpp 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<typename... T> A<T...> 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 <bool> +struct enable_if; + +template <> +struct enable_if<true> { using type = void; }; + +template <typename T, typename = void> +constexpr bool always_false = false; + +// expected-error@+3 {{invalid operands to binary expression}} +// expected-note@+2 {{in instantiation of member function}} +template <typename T> +constexpr bool always_false<T, decltype(foo(T()))> = T() == T(); + +// expected-note@+2 {{candidate template ignored: substitution failure}} +template <typename T, typename = typename enable_if<always_false<T>>::type> +bool operator==(T, T); + +// expected-note@+2 {{candidate template ignored: substitution failure}} +template <typename T, typename = typename enable_if<always_false<T>>::type> +void data(T); + +template <int> +struct S {}; +// expected-note@+2 {{candidate template ignored: could not match}} +template <int x> +constexpr bool operator==(S<x>, S<x>) { return false; } + +template <int x> +constexpr bool s = S<x>() == S<x>() and s<x - 1>; + +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 <typename T> +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 <typename U, typename = typename enable_if<always_false<U>>::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<void> m; +}; + +} // namespace PR43221 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<typename... T> A<T...> 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 <bool> +struct enable_if; + +template <> +struct enable_if<true> { using type = void; }; + +template <typename T, typename = void> +constexpr bool always_false = false; + +// expected-error@+3 {{invalid operands to binary expression}} +// expected-note@+2 {{in instantiation of member function}} +template <typename T> +constexpr bool always_false<T, decltype(foo(T()))> = T() == T(); + +// expected-note@+2 {{candidate template ignored: substitution failure}} +template <typename T, typename = typename enable_if<always_false<T>>::type> +bool operator==(T, T); + +// expected-note@+2 {{candidate template ignored: substitution failure}} +template <typename T, typename = typename enable_if<always_false<T>>::type> +void data(T); + +template <int> +struct S {}; +// expected-note@+2 {{candidate template ignored: could not match}} +template <int x> +constexpr bool operator==(S<x>, S<x>) { return false; } + +template <int x> +constexpr bool s = S<x>() == S<x>() and s<x - 1>; + +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 <typename T> +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 <typename U, typename = typename enable_if<always_false<U>>::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<void> m; +}; + +} // namespace PR43221 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().
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits