diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -210,7 +210,8 @@ This fixes `GH51182 ` - Fixes an assert crash caused by looking up missing vtable information on ``consteval`` virtual functions. Fixes `GH55065 `_. - +- Fixed a crash during template instantiation on a conversion operator during constraint + evaulation. Fixes `GH50891 `_. C++2b Feature Support ^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -4033,9 +4033,16 @@ FunctionTemplateDecl *ConvTemplate = dyn_cast(D); CXXConversionDecl *Conv; - if (ConvTemplate) + if (ConvTemplate) { + // It is possible with C++20 constraints to cause an infinite template + // expansion loop. In those instances the conversion operator has the + // same specialized template argument type as the destination type, + // and we skip it to avoid the crash. + if (Initializer->getType().getCanonicalType() == + DestType.getCanonicalType()) + continue; Conv = cast(ConvTemplate->getTemplatedDecl()); - else + } else Conv = cast(D); if (ConvTemplate) diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp --- a/clang/test/SemaTemplate/concepts.cpp +++ b/clang/test/SemaTemplate/concepts.cpp @@ -256,3 +256,20 @@ C auto **&j2 = g(); // expected-error {{deduced type 'int' does not satisfy 'C'}} C auto **&&j3 = g(); // expected-error {{deduced type 'int' does not satisfy 'C'}} } + +namespace Issue50891 { + +template +concept Numeric = + requires(T a) { + foo(a); + }; + +struct Deferred { + friend void foo(Deferred); + template operator TO(); +}; + +static_assert(Numeric); // should not crash clang + +} // namespace Issue50891