llvm-project icon indicating copy to clipboard operation
llvm-project copied to clipboard

ICE while considering conversion functions in the context of copy-initializing a type from the same type

Open llvmbot opened this issue 3 years ago • 5 comments

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.

llvmbot avatar Aug 19 '21 20:08 llvmbot

<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)

Quuxplusone avatar Jan 16 '22 18:01 Quuxplusone

@llvm/issue-subscribers-c-20

llvmbot avatar Jan 16 '22 18:01 llvmbot

Fix out for review at https://reviews.llvm.org/D133052

luken-google avatar Aug 31 '22 21:08 luken-google

@llvm/issue-subscribers-clang-frontend

llvmbot avatar Aug 31 '22 21:08 llvmbot

This is similar to https://github.com/llvm/llvm-project/issues/44304

yuanfang-chen avatar Oct 13 '22 19:10 yuanfang-chen

Note, closing in on committing hte fix here: https://reviews.llvm.org/D136975

erichkeane avatar Nov 01 '22 17:11 erichkeane

Fixed by https://github.com/llvm/llvm-project/commit/2cee2663338ee65ff5786432c30ba22c8dcd711b

usx95 avatar Nov 01 '22 19:11 usx95