llvm-project
llvm-project copied to clipboard
ICE while considering conversion functions in the context of copy-initializing a type from the same type
Bugzilla Link | 51549 |
Version | 11.0 |
OS | Windows NT |
Reporter | LLVM Bugzilla Contributor |
CC | @DougGregor,@saxbophone,@zygoloid |
Extended Description
Reduced from StackOverflow (https://stackoverflow.com/q/68853472/2069064):
template <typename T>
concept Numeric =
requires(T a) {
foo(a);
};
struct Deferred {
friend void foo(Deferred);
template <Numeric TO> operator TO();
};
static_assert(Numeric<Deferred>);
clang is trying to check to see if a.operator Derived()
is a valid expression as part of checking if foo(a)
is valid. But we shouldn't be going that route here at all, copy-initializing a Derived
from an lvalue of type Derived
should only check constructors, not conversion functions.
<source>:7:8: warning: stack nearly exhausted; compilation time may suffer, and crashes due to stack overflow are likely [-Wstack-exhausted]
struct Deferred {
^
<source>:4:9: note: in instantiation of requirement here
foo(a);
^~~~~~
<source>:3:5: note: while substituting template arguments into constraint expression here
requires(T a) {
^~~~~~~~~~~~~~~
<source>:9:15: note: while checking the satisfaction of concept 'Numeric<Deferred>' requested here
template <Numeric TO> operator TO();
^
<source>:9:15: note: while substituting template arguments into constraint expression here
template <Numeric TO> operator TO();
^~~~~~~
<source>:4:13: note: while checking constraint satisfaction for template 'operator type-parameter-0-0<Deferred>' required here
foo(a);
^
<source>:4:13: note: (skipping 1667 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
<source>:4:13: note: while checking constraint satisfaction for template 'operator type-parameter-0-0<Deferred>' required here
foo(a);
^
<source>:4:13: note: in instantiation of function template specialization 'Deferred::operator Deferred<Deferred>' requested here
<source>:4:9: note: in instantiation of requirement here
foo(a);
^~~~~~
<source>:3:5: note: while substituting template arguments into constraint expression here
requires(T a) {
^~~~~~~~~~~~~~~
<source>:12:15: note: while checking the satisfaction of concept 'Numeric<Deferred>' requested here
static_assert(Numeric<Deferred>);
^~~~~~~~~~~~~~~~~
fatal error: recursive template instantiation exceeded maximum depth of 1024
<source>:4:13: note: while substituting deduced template arguments into function template 'operator type-parameter-0-0' [with TO = Deferred]
foo(a);
^
<source>:4:9: note: in instantiation of requirement here
foo(a);
^~~~~~
<source>:3:5: note: while substituting template arguments into constraint expression here
requires(T a) {
^~~~~~~~~~~~~~~
<source>:9:15: note: while checking the satisfaction of concept 'Numeric<Deferred>' requested here
template <Numeric TO> operator TO();
^
<source>:9:15: note: while substituting template arguments into constraint expression here
template <Numeric TO> operator TO();
^~~~~~~
<source>:4:13: note: (skipping 2040 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
foo(a);
^
<source>:4:13: note: while checking constraint satisfaction for template 'operator type-parameter-0-0<Deferred>' required here
foo(a);
^
<source>:4:13: note: in instantiation of function template specialization 'Deferred::operator Deferred<Deferred>' requested here
<source>:4:9: note: in instantiation of requirement here
foo(a);
^~~~~~
<source>:3:5: note: while substituting template arguments into constraint expression here
requires(T a) {
^~~~~~~~~~~~~~~
<source>:12:15: note: while checking the satisfaction of concept 'Numeric<Deferred>' requested here
static_assert(Numeric<Deferred>);
^~~~~~~~~~~~~~~~~
clang++: /root/llvm-project/llvm/include/llvm/ADT/FoldingSet.h:479: void llvm::FoldingSetImpl<Derived, T>::InsertNode(T*) [with Derived = llvm::ContextualFoldingSet<clang::ConstraintSatisfaction, const clang::ASTContext&>; T = clang::ConstraintSatisfaction]: Assertion `Inserted == N && "Node already inserted!"' failed.
clang++: /root/llvm-project/llvm/include/llvm/ADT/FoldingSet.h:479: void llvm::FoldingSetImpl<Derived, T>::InsertNode(T*) [with Derived = llvm::ContextualFoldingSet<clang::ConstraintSatisfaction, const clang::ASTContext&>; T = clang::ConstraintSatisfaction]: Assertion `Inserted == N && "Node already inserted!"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0. Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/clang++ -g -o /app/output.s -S --gcc-toolchain=/opt/compiler-explorer/gcc-snapshot -fcolor-diagnostics -fno-crash-diagnostics -std=c++20 -O2 <source>
1. <source>:12:32: current parser token ')'
#0 0x00005610ca64e90f PrintStackTraceSignalHandler(void*) Signals.cpp:0:0
#1 0x00005610ca64c710 llvm::sys::CleanupOnSignal(unsigned long) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3a4c710)
#2 0x00005610ca583bd8 CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0
#3 0x00007f8950d433c0 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x153c0)
#4 0x00007f895081218b raise (/lib/x86_64-linux-gnu/libc.so.6+0x4618b)
#5 0x00007f89507f1859 abort (/lib/x86_64-linux-gnu/libc.so.6+0x25859)
#6 0x00007f89507f1729 (/lib/x86_64-linux-gnu/libc.so.6+0x25729)
#7 0x00007f8950802f36 (/lib/x86_64-linux-gnu/libc.so.6+0x36f36)
#8 0x00005610cc755f28 clang::Sema::CheckConstraintSatisfaction(clang::NamedDecl const*, llvm::ArrayRef<clang::Expr const*>, llvm::ArrayRef<clang::TemplateArgument>, clang::SourceRange, clang::ConstraintSatisfaction&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5b55f28)
#9 0x00005610ccc68cad clang::Sema::CheckConceptTemplateId(clang::CXXScopeSpec const&, clang::SourceLocation, clang::DeclarationNameInfo const&, clang::NamedDecl*, clang::ConceptDecl*, clang::TemplateArgumentListInfo const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6068cad)
#10 0x00005610ccd6fdcc clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformConceptSpecializationExpr(clang::ConceptSpecializationExpr*) SemaTemplateInstantiate.cpp:0:0
#11 0x00005610ccd57bbe clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformExpr(clang::Expr*) SemaTemplateInstantiate.cpp:0:0
#12 0x00005610ccd8a08f clang::Sema::SubstExpr(clang::Expr*, clang::MultiLevelTemplateArgumentList const&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x618a08f)
#13 0x00005610cc754811 calculateConstraintSatisfaction(clang::Sema&, clang::NamedDecl const*, llvm::ArrayRef<clang::TemplateArgument>, clang::SourceLocation, clang::MultiLevelTemplateArgumentList&, clang::Expr const*, clang::ConstraintSatisfaction&)::'lambda'(clang::Expr const*)::operator()(clang::Expr const*) const SemaConcept.cpp:0:0
#14 0x00005610cc755b70 bool calculateConstraintSatisfaction<calculateConstraintSatisfaction(clang::Sema&, clang::NamedDecl const*, llvm::ArrayRef<clang::TemplateArgument>, clang::SourceLocation, clang::MultiLevelTemplateArgumentList&, clang::Expr const*, clang::ConstraintSatisfaction&)::'lambda'(clang::Expr const*)>(clang::Sema&, clang::Expr const*, clang::ConstraintSatisfaction&, calculateConstraintSatisfaction(clang::Sema&, clang::NamedDecl const*, llvm::ArrayRef<clang::TemplateArgument>, clang::SourceLocation, clang::MultiLevelTemplateArgumentList&, clang::Expr const*, clang::ConstraintSatisfaction&)::'lambda'(clang::Expr const*)&&) SemaConcept.cpp:0:0
#15 0x00005610cc75633a clang::Sema::CheckConstraintSatisfaction(clang::NamedDecl const*, llvm::ArrayRef<clang::Expr const*>, llvm::ArrayRef<clang::TemplateArgument>, clang::SourceRange, clang::ConstraintSatisfaction&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5b5633a)
#16 0x00005610ccd90e9d clang::Sema::CheckInstantiatedFunctionTemplateConstraints(clang::SourceLocation, clang::FunctionDecl*, llvm::ArrayRef<clang::TemplateArgument>, clang::ConstraintSatisfaction&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6190e9d)
#17 0x00005610ccd27faa clang::Sema::FinishTemplateArgumentDeduction(clang::FunctionTemplateDecl*, llvm::SmallVectorImpl<clang::DeducedTemplateArgument>&, unsigned int, clang::FunctionDecl*&, clang::sema::TemplateDeductionInfo&, llvm::SmallVectorImpl<clang::Sema::OriginalCallArg> const*, bool, llvm::function_ref<bool ()>) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6127faa)
#18 0x00005610ccd28cee void llvm::function_ref<void ()>::callback_fn<clang::Sema::DeduceTemplateArguments(clang::FunctionTemplateDecl*, clang::QualType, clang::CXXConversionDecl*&, clang::sema::TemplateDeductionInfo&)::'lambda'()>(long) SemaTemplateDeduction.cpp:0:0
#19 0x00005610cc65609f clang::Sema::runWithSufficientStackSpace(clang::SourceLocation, llvm::function_ref<void ()>) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5a5609f)
#20 0x00005610ccd2151b clang::Sema::DeduceTemplateArguments(clang::FunctionTemplateDecl*, clang::QualType, clang::CXXConversionDecl*&, clang::sema::TemplateDeductionInfo&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x612151b)
#21 0x00005610ccbcdb97 clang::Sema::AddTemplateConversionCandidate(clang::FunctionTemplateDecl*, clang::DeclAccessPair, clang::CXXRecordDecl*, clang::Expr*, clang::QualType, clang::OverloadCandidateSet&, bool, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5fcdb97)
#22 0x00005610cca77d6e ResolveConstructorOverload(clang::Sema&, clang::SourceLocation, llvm::MutableArrayRef<clang::Expr*>, clang::OverloadCandidateSet&, clang::QualType, clang::DeclContextLookupResult, clang::OverloadCandidate*&, bool, bool, bool, bool, bool) SemaInit.cpp:0:0
#23 0x00005610cca8296a TryConstructorInitialization(clang::Sema&, clang::InitializedEntity const&, clang::InitializationKind const&, llvm::MutableArrayRef<clang::Expr*>, clang::QualType, clang::QualType, clang::InitializationSequence&, bool, bool) SemaInit.cpp:0:0
#24 0x00005610cca85a7f clang::InitializationSequence::InitializeFrom(clang::Sema&, clang::InitializedEntity const&, clang::InitializationKind const&, llvm::MutableArrayRef<clang::Expr*>, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5e85a7f)
#25 0x00005610cca8e9c7 clang::Sema::PerformCopyInitialization(clang::InitializedEntity const&, clang::SourceLocation, clang::ActionResult<clang::Expr*, true>, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5e8e9c7)
#26 0x00005610cc930855 clang::Sema::GatherArgumentsForCall(clang::SourceLocation, clang::FunctionDecl*, clang::FunctionProtoType const*, unsigned int, llvm::ArrayRef<clang::Expr*>, llvm::SmallVectorImpl<clang::Expr*>&, clang::Sema::VariadicCallType, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5d30855)
#27 0x00005610cc931310 clang::Sema::ConvertArgumentsForCall(clang::CallExpr*, clang::Expr*, clang::FunctionDecl*, clang::FunctionProtoType const*, llvm::ArrayRef<clang::Expr*>, clang::SourceLocation, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5d31310)
#28 0x00005610cc932c59 clang::Sema::BuildResolvedCallExpr(clang::Expr*, clang::NamedDecl*, clang::SourceLocation, llvm::ArrayRef<clang::Expr*>, clang::SourceLocation, clang::Expr*, bool, clang::CallExpr::ADLCallKind) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5d32c59)
#29 0x00005610ccbe7a38 FinishOverloadedCallExpr(clang::Sema&, clang::Scope*, clang::Expr*, clang::UnresolvedLookupExpr*, clang::SourceLocation, llvm::MutableArrayRef<clang::Expr*>, clang::SourceLocation, clang::Expr*, clang::OverloadCandidateSet*, clang::OverloadCandidate**, clang::OverloadingResult, bool) SemaOverload.cpp:0:0
#30 0x00005610ccbe8827 clang::Sema::BuildOverloadedCallExpr(clang::Scope*, clang::Expr*, clang::UnresolvedLookupExpr*, clang::SourceLocation, llvm::MutableArrayRef<clang::Expr*>, clang::SourceLocation, clang::Expr*, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5fe8827)
#31 0x00005610cc92f7ad clang::Sema::BuildCallExpr(clang::Scope*, clang::Expr*, clang::SourceLocation, llvm::MutableArrayRef<clang::Expr*>, clang::SourceLocation, clang::Expr*, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5d2f7ad)
#32 0x00005610cc9345b3 clang::Sema::ActOnCallExpr(clang::Scope*, clang::Expr*, clang::SourceLocation, llvm::MutableArrayRef<clang::Expr*>, clang::SourceLocation, clang::Expr*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5d345b3)
#33 0x00005610ccd5fc02 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformCallExpr(clang::CallExpr*) SemaTemplateInstantiate.cpp:0:0
#34 0x00005610ccd57b07 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformExpr(clang::Expr*) SemaTemplateInstantiate.cpp:0:0
#35 0x00005610ccd7a8d0 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformRequiresExpr(clang::RequiresExpr*) SemaTemplateInstantiate.cpp:0:0
#36 0x00005610ccd57f91 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformExpr(clang::Expr*) SemaTemplateInstantiate.cpp:0:0
#37 0x00005610ccd8a08f clang::Sema::SubstExpr(clang::Expr*, clang::MultiLevelTemplateArgumentList const&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x618a08f)
#38 0x00005610cc754811 calculateConstraintSatisfaction(clang::Sema&, clang::NamedDecl const*, llvm::ArrayRef<clang::TemplateArgument>, clang::SourceLocation, clang::MultiLevelTemplateArgumentList&, clang::Expr const*, clang::ConstraintSatisfaction&)::'lambda'(clang::Expr const*)::operator()(clang::Expr const*) const SemaConcept.cpp:0:0
#39 0x00005610cc755b70 bool calculateConstraintSatisfaction<calculateConstraintSatisfaction(clang::Sema&, clang::NamedDecl const*, llvm::ArrayRef<clang::TemplateArgument>, clang::SourceLocation, clang::MultiLevelTemplateArgumentList&, clang::Expr const*, clang::ConstraintSatisfaction&)::'lambda'(clang::Expr const*)>(clang::Sema&, clang::Expr const*, clang::ConstraintSatisfaction&, calculateConstraintSatisfaction(clang::Sema&, clang::NamedDecl const*, llvm::ArrayRef<clang::TemplateArgument>, clang::SourceLocation, clang::MultiLevelTemplateArgumentList&, clang::Expr const*, clang::ConstraintSatisfaction&)::'lambda'(clang::Expr const*)&&) SemaConcept.cpp:0:0
#40 0x00005610cc75633a clang::Sema::CheckConstraintSatisfaction(clang::NamedDecl const*, llvm::ArrayRef<clang::Expr const*>, llvm::ArrayRef<clang::TemplateArgument>, clang::SourceRange, clang::ConstraintSatisfaction&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5b5633a)
@llvm/issue-subscribers-c-20
Fix out for review at https://reviews.llvm.org/D133052
@llvm/issue-subscribers-clang-frontend
This is similar to https://github.com/llvm/llvm-project/issues/44304
Note, closing in on committing hte fix here: https://reviews.llvm.org/D136975
Fixed by https://github.com/llvm/llvm-project/commit/2cee2663338ee65ff5786432c30ba22c8dcd711b