Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
llvmbot opened this issue Aug 19, 2021 · 7 comments
Assignees
Labels
bugzilla Issues migrated from bugzilla c++20 clang:frontend Language frontend issues, e.g. anything involving "Sema" concepts C++20 concepts

Comments

@llvmbot
Copy link
Collaborator

llvmbot commented Aug 19, 2021

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 llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 11, 2021
@Quuxplusone
Copy link
Contributor

<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 Quuxplusone added c++20 concepts C++20 concepts labels Jan 16, 2022
@llvmbot
Copy link
Collaborator Author

llvmbot commented Jan 16, 2022

@llvm/issue-subscribers-c-20

@Quuxplusone Quuxplusone changed the title considering conversion functions in the context of copy-initializing a type from the same type ICE while considering conversion functions in the context of copy-initializing a type from the same type Jan 16, 2022
saxbophone added a commit to saxbophone/arby that referenced this issue May 26, 2022
- Provided generic operator for everything else. Wanted to constrain it with concepts, couldn't because of Clang++ bug llvm/llvm-project#50891
- Modified float test case to be generic
@luken-google luken-google self-assigned this Aug 30, 2022
@luken-google
Copy link
Contributor

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

@EugeneZelenko EugeneZelenko added clang:frontend Language frontend issues, e.g. anything involving "Sema" and removed c++ labels Aug 31, 2022
@llvmbot
Copy link
Collaborator Author

llvmbot commented Aug 31, 2022

@llvm/issue-subscribers-clang-frontend

@yuanfang-chen
Copy link
Collaborator

This is similar to #44304

usx95 referenced this issue Oct 28, 2022
concept

When we failed the lookup of the function, we tried to form a
RecoveryExpr that caused us to recursively re-check the same constraint,
which caused us to try to double-insert the satisfaction into the cache.

This patch makes us just return the inner-cached version instead. We DO
end up double-evaluating thanks to the recovery-expr, but there isn't a
good way around that.
@erichkeane
Copy link
Collaborator

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

erichkeane pushed a commit that referenced this issue Nov 1, 2022
Based on discussion on the core reflector, it was made clear that a
concept that depends on itself should be a hard error, not a constraint
failure. This patch implements a stack of constraint-checks-in-progress
to make sure we quit, rather than hitting stack-exhaustion.

Note that we DO need to be careful to make sure we still check
constraints properly that are caused by a previous constraint, but not
derived from (such as when a check causes us to check special member
function generation), so we cannot use the existing logic to see if this
is being instantiated.

This fixes #44304 and
#50891.

Differential Revision: https://reviews.llvm.org/D136975
@usx95
Copy link
Contributor

usx95 commented Nov 1, 2022

Fixed by 2cee266

@usx95 usx95 closed this as completed Nov 1, 2022
veselypeta pushed a commit to veselypeta/cherillvm that referenced this issue May 28, 2024
Based on discussion on the core reflector, it was made clear that a
concept that depends on itself should be a hard error, not a constraint
failure. This patch implements a stack of constraint-checks-in-progress
to make sure we quit, rather than hitting stack-exhaustion.

Note that we DO need to be careful to make sure we still check
constraints properly that are caused by a previous constraint, but not
derived from (such as when a check causes us to check special member
function generation), so we cannot use the existing logic to see if this
is being instantiated.

This fixes llvm/llvm-project#44304 and
llvm/llvm-project#50891.

Differential Revision: https://reviews.llvm.org/D136975
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla c++20 clang:frontend Language frontend issues, e.g. anything involving "Sema" concepts C++20 concepts
Projects
Status: Done
Development

No branches or pull requests

7 participants