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 @@ -4009,6 +4009,16 @@ } } + if (!S.CodeSynthesisContexts.empty()) + llvm::errs() << "Kind: " << S.CodeSynthesisContexts.back().Kind << "\n"; + + // Avoid an infinite template expansion loop in requirements checking by + // skipping the conversion functions check. + bool InRequirementInstantiation = + !S.CodeSynthesisContexts.empty() && + S.CodeSynthesisContexts.back().Kind == + Sema::CodeSynthesisContext::RequirementInstantiation; + // FIXME: Work around a bug in C++17 guaranteed copy elision. // // When initializing an object of class type T by constructor @@ -4021,7 +4031,7 @@ // Note: SecondStepOfCopyInit is only ever true in this case when // evaluating whether to produce a C++98 compatibility warning. if (S.getLangOpts().CPlusPlus17 && Args.size() == 1 && - !SecondStepOfCopyInit) { + !SecondStepOfCopyInit && !InRequirementInstantiation) { Expr *Initializer = Args[0]; auto *SourceRD = Initializer->getType()->getAsCXXRecordDecl(); if (SourceRD && S.isCompleteType(DeclLoc, Initializer->getType())) { 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