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 deducing constrained components of member pointer type #57958

Closed
JohelEGP opened this issue Sep 24, 2022 · 7 comments
Closed

ICE deducing constrained components of member pointer type #57958

JohelEGP opened this issue Sep 24, 2022 · 7 comments
Labels
c++23 clang:frontend Language frontend issues, e.g. anything involving "Sema" concepts C++20 concepts crash Prefer [crash-on-valid] or [crash-on-invalid]

Comments

@JohelEGP
Copy link

JohelEGP commented Sep 24, 2022

See https://godbolt.org/z/oacKbYb48.

#include <concepts>
#include <cstdint>
#include <functional>
#include <type_traits>

struct ratio {
  std::intmax_t numerator;
  std::intmax_t denominator{1};
};

template<auto F> concept constant_invocable = requires { typename std::integral_constant<int, (F(), 0)>; };

template<auto P> requires std::is_member_object_pointer_v<decltype(P)>
inline constexpr bool default_initialization_leaves_uninitialized =
  []<std::default_initializable T, std::copy_constructible M>(M T::*) {
    return not constant_invocable<[]() {
      T v;
      (void)M{std::invoke(P, v)};
    }>;
  }(P);

static_assert(default_initialization_leaves_uninitialized<&ratio::numerator>);
static_assert(not default_initialization_leaves_uninitialized<&ratio::denominator>);

Output:

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-trunk/bin/clang++ -gdwarf-4 -g -o /app/output.s -mllvm --x86-asm-syntax=intel -S --gcc-toolchain=/opt/compiler-explorer/gcc-snapshot -fcolor-diagnostics -fno-crash-diagnostics -std=c++2b -stdlib=libc++ -pedantic -Wall -Wextra -Wconversion <source>
1.	<source>:23:77: current parser token ')'
2.	<source>:15:23: instantiating variable definition 'default_initialization_leaves_uninitialized<&ratio::numerator>'
 #0 0x00005608bb286a54 PrintStackTraceSignalHandler(void*) Signals.cpp:0:0
 #1 0x00005608bb2848bc llvm::sys::CleanupOnSignal(unsigned long) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x3a748bc)
 #2 0x00005608bb1c2758 CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0
 #3 0x00007fbfe0014420 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x14420)
 #4 0x00005608be655bbd clang::StmtVisitorBase<llvm::make_const_ptr, (anonymous namespace)::IntExprEvaluator, bool>::Visit(clang::Stmt const*) ExprConstant.cpp:0:0
 #5 0x00005608be65c126 Evaluate(clang::APValue&, (anonymous namespace)::EvalInfo&, clang::Expr const*) ExprConstant.cpp:0:0
 #6 0x00005608be6765ee EvaluateInPlace(clang::APValue&, (anonymous namespace)::EvalInfo&, (anonymous namespace)::LValue const&, clang::Expr const*, bool) ExprConstant.cpp:0:0
 #7 0x00005608be6a74d0 clang::Expr::EvaluateAsConstantExpr(clang::Expr::EvalResult&, clang::ASTContext const&, clang::Expr::ConstantExprKind) const (/opt/compiler-explorer/clang-trunk/bin/clang+++0x6e974d0)
 #8 0x00005608bd9379bd clang::ActionResult<clang::Expr*, true> calculateConstraintSatisfaction<calculateConstraintSatisfaction(clang::Sema&, clang::NamedDecl const*, clang::SourceLocation, clang::MultiLevelTemplateArgumentList const&, clang::Expr const*, clang::ConstraintSatisfaction&)::'lambda'(clang::Expr const*)>(clang::Sema&, clang::Expr const*, clang::ConstraintSatisfaction&, calculateConstraintSatisfaction(clang::Sema&, clang::NamedDecl const*, clang::SourceLocation, clang::MultiLevelTemplateArgumentList const&, clang::Expr const*, clang::ConstraintSatisfaction&)::'lambda'(clang::Expr const*)&&) SemaConcept.cpp:0:0
 #9 0x00005608bd937ee0 CheckConstraintSatisfaction(clang::Sema&, clang::NamedDecl const*, llvm::ArrayRef<clang::Expr const*>, llvm::SmallVectorImpl<clang::Expr*>&, clang::MultiLevelTemplateArgumentList const&, clang::SourceRange, clang::ConstraintSatisfaction&) SemaConcept.cpp:0:0
#10 0x00005608bd938373 clang::Sema::CheckConstraintSatisfaction(clang::NamedDecl const*, llvm::ArrayRef<clang::Expr const*>, llvm::SmallVectorImpl<clang::Expr*>&, clang::MultiLevelTemplateArgumentList const&, clang::SourceRange, clang::ConstraintSatisfaction&) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x6128373)
#11 0x00005608bd9387b9 clang::Sema::CheckInstantiatedFunctionTemplateConstraints(clang::SourceLocation, clang::FunctionDecl*, llvm::ArrayRef<clang::TemplateArgument>, clang::ConstraintSatisfaction&) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x61287b9)
#12 0x00005608be0c3e8d 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-trunk/bin/clang+++0x68b3e8d)
#13 0x00005608be0c4d1e void llvm::function_ref<void ()>::callback_fn<clang::Sema::DeduceTemplateArguments(clang::FunctionTemplateDecl*, clang::TemplateArgumentListInfo*, llvm::ArrayRef<clang::Expr*>, clang::FunctionDecl*&, clang::sema::TemplateDeductionInfo&, bool, llvm::function_ref<bool (llvm::ArrayRef<clang::QualType>)>)::'lambda1'()>(long) SemaTemplateDeduction.cpp:0:0
#14 0x00005608bd7e1185 clang::Sema::runWithSufficientStackSpace(clang::SourceLocation, llvm::function_ref<void ()>) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x5fd1185)
#15 0x00005608be0ce5d3 clang::Sema::DeduceTemplateArguments(clang::FunctionTemplateDecl*, clang::TemplateArgumentListInfo*, llvm::ArrayRef<clang::Expr*>, clang::FunctionDecl*&, clang::sema::TemplateDeductionInfo&, bool, llvm::function_ref<bool (llvm::ArrayRef<clang::QualType>)>) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x68be5d3)
#16 0x00005608bdef2af7 clang::Sema::AddMethodTemplateCandidate(clang::FunctionTemplateDecl*, clang::DeclAccessPair, clang::CXXRecordDecl*, clang::TemplateArgumentListInfo*, clang::QualType, clang::Expr::Classification, llvm::ArrayRef<clang::Expr*>, clang::OverloadCandidateSet&, bool, bool, clang::OverloadCandidateParamOrder) (.constprop.0) SemaOverload.cpp:0:0
#17 0x00005608bdef2fa1 clang::Sema::AddMethodCandidate(clang::DeclAccessPair, clang::QualType, clang::Expr::Classification, llvm::ArrayRef<clang::Expr*>, clang::OverloadCandidateSet&, bool, clang::OverloadCandidateParamOrder) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x66e2fa1)
#18 0x00005608bdf0e4fc clang::Sema::BuildCallToObjectOfClassType(clang::Scope*, clang::Expr*, clang::SourceLocation, llvm::MutableArrayRef<clang::Expr*>, clang::SourceLocation) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x66fe4fc)
#19 0x00005608bdbe0ce5 clang::Sema::BuildCallExpr(clang::Scope*, clang::Expr*, clang::SourceLocation, llvm::MutableArrayRef<clang::Expr*>, clang::SourceLocation, clang::Expr*, bool, bool) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x63d0ce5)
#20 0x00005608bdbe5dab clang::Sema::ActOnCallExpr(clang::Scope*, clang::Expr*, clang::SourceLocation, llvm::MutableArrayRef<clang::Expr*>, clang::SourceLocation, clang::Expr*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x63d5dab)
#21 0x00005608be10a193 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformCallExpr(clang::CallExpr*) SemaTemplateInstantiate.cpp:0:0
#22 0x00005608be101496 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformExpr(clang::Expr*) SemaTemplateInstantiate.cpp:0:0
#23 0x00005608be101ef5 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformInitializer(clang::Expr*, bool) SemaTemplateInstantiate.cpp:0:0
#24 0x00005608be1038be clang::Sema::SubstInitializer(clang::Expr*, clang::MultiLevelTemplateArgumentList const&, bool) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x68f38be)
#25 0x00005608be13eef6 clang::Sema::InstantiateVariableInitializer(clang::VarDecl*, clang::VarDecl*, clang::MultiLevelTemplateArgumentList const&) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x692eef6)
#26 0x00005608be13f1b1 clang::Sema::CompleteVarTemplateSpecializationDecl(clang::VarTemplateSpecializationDecl*, clang::VarDecl*, clang::MultiLevelTemplateArgumentList const&) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x692f1b1)
#27 0x00005608be17dc9e clang::Sema::InstantiateVariableDefinition(clang::SourceLocation, clang::VarDecl*, bool, bool, bool) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x696dc9e)
#28 0x00005608bd7e1185 clang::Sema::runWithSufficientStackSpace(clang::SourceLocation, llvm::function_ref<void ()>) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x5fd1185)
#29 0x00005608bdbafa6c DoMarkVarDeclReferenced(clang::Sema&, clang::SourceLocation, clang::VarDecl*, clang::Expr*, llvm::DenseMap<clang::VarDecl const*, int, llvm::DenseMapInfo<clang::VarDecl const*, void>, llvm::detail::DenseMapPair<clang::VarDecl const*, int>>&) SemaExpr.cpp:0:0
#30 0x00005608bdbb02ac clang::Sema::MarkDeclRefReferenced(clang::DeclRefExpr*, clang::Expr const*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x63a02ac)
#31 0x00005608bdbb0790 clang::Sema::BuildDeclRefExpr(clang::ValueDecl*, clang::QualType, clang::ExprValueKind, clang::DeclarationNameInfo const&, clang::NestedNameSpecifierLoc, clang::NamedDecl*, clang::SourceLocation, clang::TemplateArgumentListInfo const*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x63a0790)
#32 0x00005608bdbb1378 clang::Sema::BuildDeclarationNameExpr(clang::CXXScopeSpec const&, clang::DeclarationNameInfo const&, clang::NamedDecl*, clang::NamedDecl*, clang::TemplateArgumentListInfo const*, bool) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x63a1378)
#33 0x00005608bdfdadf3 clang::Sema::BuildTemplateIdExpr(clang::CXXScopeSpec const&, clang::SourceLocation, clang::LookupResult&, bool, clang::TemplateArgumentListInfo const*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x67cadf3)
#34 0x00005608bdbc7f31 clang::Sema::ActOnIdExpression(clang::Scope*, clang::CXXScopeSpec&, clang::SourceLocation, clang::UnqualifiedId&, bool, bool, clang::CorrectionCandidateCallback*, bool, clang::Token*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x63b7f31)
#35 0x00005608bd714dcc clang::Parser::tryParseCXXIdExpression(clang::CXXScopeSpec&, bool, clang::Token&) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x5f04dcc)
#36 0x00005608bd715006 clang::Parser::ParseCXXIdExpression(bool) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x5f05006)
#37 0x00005608bd6f5749 clang::Parser::ParseCastExpression(clang::Parser::CastParseKind, bool, bool&, clang::Parser::TypeCastState, bool, bool*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x5ee5749)
#38 0x00005608bd6f6030 clang::Parser::ParseCastExpression(clang::Parser::CastParseKind, bool, bool&, clang::Parser::TypeCastState, bool, bool*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x5ee6030)
#39 0x00005608bd703b4d clang::Parser::ParseConstantExpressionInExprEvalContext(clang::Parser::TypeCastState) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x5ef3b4d)
#40 0x00005608bd6dbdb6 clang::Parser::ParseStaticAssertDeclaration(clang::SourceLocation&) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x5ecbdb6)
#41 0x00005608bd6ca09f clang::Parser::ParseDeclaration(clang::DeclaratorContext, clang::SourceLocation&, clang::ParsedAttributes&, clang::ParsedAttributes&, clang::SourceLocation*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x5eba09f)
#42 0x00005608bd69b5bb clang::Parser::ParseExternalDeclaration(clang::ParsedAttributes&, clang::ParsingDeclSpec*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x5e8b5bb)
#43 0x00005608bd69d38a clang::Parser::ParseTopLevelDecl(clang::OpaquePtr<clang::DeclGroupRef>&, clang::Sema::ModuleImportState&) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x5e8d38a)
#44 0x00005608bd68cc7a clang::ParseAST(clang::Sema&, bool, bool) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x5e7cc7a)
#45 0x00005608bc4f6155 clang::CodeGenAction::ExecuteAction() (/opt/compiler-explorer/clang-trunk/bin/clang+++0x4ce6155)
#46 0x00005608bbdff2a1 clang::FrontendAction::Execute() (/opt/compiler-explorer/clang-trunk/bin/clang+++0x45ef2a1)
#47 0x00005608bbd84f03 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x4574f03)
#48 0x00005608bbee26cb clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x46d26cb)
#49 0x00005608b8aa5994 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x1295994)
#50 0x00005608b8a9ef4b ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&) driver.cpp:0:0
#51 0x00005608bbbeff79 void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<llvm::Optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const::'lambda'()>(long) Job.cpp:0:0
#52 0x00005608bb1c2ec7 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x39b2ec7)
#53 0x00005608bbbf01ac clang::driver::CC1Command::Execute(llvm::ArrayRef<llvm::Optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const (.part.0) Job.cpp:0:0
#54 0x00005608bbbbb619 clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (/opt/compiler-explorer/clang-trunk/bin/clang+++0x43ab619)
#55 0x00005608bbbbc00d clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&, bool) const (/opt/compiler-explorer/clang-trunk/bin/clang+++0x43ac00d)
#56 0x00005608bbbc676c clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x43b676c)
#57 0x00005608b8aa36b9 clang_main(int, char**) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x12936b9)
#58 0x00007fbfdfac2083 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24083)
#59 0x00005608b8a9eb5e _start (/opt/compiler-explorer/clang-trunk/bin/clang+++0x128eb5e)
clang-16: error: clang frontend command failed with exit code 139 (use -v to see invocation)
Compiler returned: 139

The following works:

-  []<std::default_initializable T, std::copy_constructible M>(M T::*) {
+  []<class T, class M>(M T::*) {
@EugeneZelenko EugeneZelenko added clang:frontend Language frontend issues, e.g. anything involving "Sema" crash Prefer [crash-on-valid] or [crash-on-invalid] and removed new issue labels Sep 24, 2022
@llvmbot
Copy link
Member

llvmbot commented Sep 24, 2022

@llvm/issue-subscribers-clang-frontend

@EugeneZelenko EugeneZelenko added concepts C++20 concepts c++23 labels Sep 24, 2022
@llvmbot
Copy link
Member

llvmbot commented Sep 24, 2022

@llvm/issue-subscribers-c-2b

@erichkeane
Copy link
Collaborator

Got it, thanks. Looking at this plus one other regression from the deferred concepts instantiation patch, on Monday

@JohelEGP
Copy link
Author

Simplified: https://godbolt.org/z/f6MEcfz8z.

template<class> concept C = true;
template<int> constexpr bool v = [](C auto) { return true; }(0);
int _ = v<0>;

This is rejected, but should be valid: https://godbolt.org/z/qeGjaW1v5.

template<class> concept C = true;
template<int> constexpr bool v = [](C auto...) { return true; }(0);
int _ = v<0>;
<source>:2:34: error: no matching function for call to object of type '(lambda at <source>:2:34)'
template<int> constexpr bool v = [](C auto...) { return true; }(0);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:3:9: note: in instantiation of variable template specialization 'v<0>' requested here
int _ = v<0>;
        ^
<source>:2:34: note: candidate template ignored: constraints not satisfied [with auto:1 = <int>]
template<int> constexpr bool v = [](C auto...) { return true; }(0);
                                 ^
<source>:2:37: note: because substituted constraint expression is ill-formed: value of type '<dependent type>' is not contextually convertible to 'bool'
template<int> constexpr bool v = [](C auto...) { return true; }(0);
                                    ^
1 error generated.
Compiler returned: 1

@erichkeane
Copy link
Collaborator

Ok then, those look similar to what we saw from an additional reported bug, I suspect the instantiation setup for a lambda has a bug in it. The improper rejection is for about the same reason, it looks like we're not setting up the instantiation correctly for lambdas in certain situations.

It is at least similar (if not identical) to the issue that @davidstone reported, so hopefully they won't take too long to debug.

Thank you very much for the report, and the minimization.

@erichkeane
Copy link
Collaborator

Patch up for review here: https://reviews.llvm.org/D134874

Took a little longer than I wish it did, it required a significant refactor of some pretty crufty/old code.

erichkeane pushed a commit that referenced this issue Oct 3, 2022
As fallout of the Deferred Concept Instantiation patch (babdef2), we
got a number of reports of a regression, where we asserted when
instantiating a constraint on a generic lambda inside of a variable
template. See: #57958

The problem was that getTemplateInstantiationArgs function only walked
up declaration contexts, and missed that this is not necessarily the
case with a lambda (which can ALSO be in a separate context).

This patch refactors the getTemplateInstantiationArgs function in a way
that is hopefully more readable, and fixes the problem with the concepts
on a generic lambda.

Differential Revision: https://reviews.llvm.org/D134874
@erichkeane
Copy link
Collaborator

veselypeta pushed a commit to veselypeta/cherillvm that referenced this issue May 22, 2024
As fallout of the Deferred Concept Instantiation patch (babdef2), we
got a number of reports of a regression, where we asserted when
instantiating a constraint on a generic lambda inside of a variable
template. See: llvm/llvm-project#57958

The problem was that getTemplateInstantiationArgs function only walked
up declaration contexts, and missed that this is not necessarily the
case with a lambda (which can ALSO be in a separate context).

This patch refactors the getTemplateInstantiationArgs function in a way
that is hopefully more readable, and fixes the problem with the concepts
on a generic lambda.

Differential Revision: https://reviews.llvm.org/D134874
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++23 clang:frontend Language frontend issues, e.g. anything involving "Sema" concepts C++20 concepts crash Prefer [crash-on-valid] or [crash-on-invalid]
Projects
Status: No status
Development

No branches or pull requests

4 participants