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

[clang] ICE when dealing with some certain requires clauses in calculateConstraintSatisfaction #69307

Closed
RungeCC opened this issue Oct 17, 2023 · 8 comments · Fixed by #93206
Closed
Labels
c++20 clang:frontend Language frontend issues, e.g. anything involving "Sema" concepts C++20 concepts crash Prefer [crash-on-valid] or [crash-on-invalid]

Comments

@RungeCC
Copy link

RungeCC commented Oct 17, 2023

Descriptions

Example:

#include <concepts>
#include <type_traits>
#include <utility>

[[maybe_unused]] constexpr inline static auto lpartial =
    [](auto fn, auto... t0) constexpr noexcept {
      return [=](auto... rest) constexpr noexcept
        requires requires { fn(t0..., rest...); }
      { return fn(t0..., rest...); };
    };

[[maybe_unused]] constexpr inline static auto fix =
    [](auto self) constexpr noexcept {
      return [=](auto... args) constexpr noexcept
        requires requires { self(self, args...); }
      { return self(self, args...); };
    };

[[maybe_unused]] constexpr inline static auto currify0 =
    [](auto self, auto v, auto fn) constexpr noexcept {
      return [=](auto... as) constexpr noexcept
        requires(
            (v.value > sizeof...(as) && requires { lpartial(fn, as...); }) ||
            (v.value == sizeof...(as) && requires { fn(as...); }))
      {
        if constexpr (v.value > sizeof...(as))
          return self(self, std::integral_constant<std::size_t, v.value - sizeof...(as)>{}, lpartial(fn, as...));
        else
          return fn(as...);
      };
    };

[[maybe_unused]] constexpr static inline auto plus =
    [](auto x, auto y) constexpr noexcept
  requires requires { x + y; }
{ return x + y; };

#undef lambda_body

[[maybe_unused]] constexpr static inline auto plus_ =
    fix(currify0)(std::integral_constant<std::size_t, 2>{}, plus);

Expected behavior:

Accepts the above code, just as gcc(13.2 and trunk), msvc(latest) do.

Actual behavior:

Crash, with output:

Click me
clang++: /root/llvm-project/llvm/include/llvm/ADT/SmallVector.h:294: T& llvm::SmallVectorTemplateCommon<T, <template-parameter-1-2> >::operator[](llvm::SmallVectorTemplateCommon<T, <template-parameter-1-2> >::size_type) [with T = clang::sema::FunctionScopeInfo*; <template-parameter-1-2> = void; llvm::SmallVectorTemplateCommon<T, <template-parameter-1-2> >::reference = clang::sema::FunctionScopeInfo*&; llvm::SmallVectorTemplateCommon<T, <template-parameter-1-2> >::size_type = long unsigned int]: Assertion `idx < size()' 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++ -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 <source>
1.	<source>:41:65: current parser token ')'
 #0 0x000000000372dc98 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x372dc98)
 #1 0x000000000372b95c llvm::sys::CleanupOnSignal(unsigned long) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x372b95c)
 #2 0x0000000003674298 CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0
 #3 0x00007f6fdb26c420 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x14420)
 #4 0x00007f6fdad2f00b raise (/lib/x86_64-linux-gnu/libc.so.6+0x4300b)
 #5 0x00007f6fdad0e859 abort (/lib/x86_64-linux-gnu/libc.so.6+0x22859)
 #6 0x00007f6fdad0e729 (/lib/x86_64-linux-gnu/libc.so.6+0x22729)
 #7 0x00007f6fdad1ffd6 (/lib/x86_64-linux-gnu/libc.so.6+0x33fd6)
 #8 0x00000000063ebb23 clang::Sema::tryCaptureVariable(clang::ValueDecl*, clang::SourceLocation, clang::Sema::TryCaptureKind, clang::SourceLocation, bool, clang::QualType&, clang::QualType&, unsigned int const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x63ebb23)
 #9 0x0000000006419256 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-assertions-trunk/bin/clang+++0x6419256)
#10 0x0000000006419aac clang::Sema::BuildDeclRefExpr(clang::ValueDecl*, clang::QualType, clang::ExprValueKind, clang::DeclarationNameInfo const&, clang::CXXScopeSpec const*, clang::NamedDecl*, clang::SourceLocation, clang::TemplateArgumentListInfo const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6419aac)
#11 0x000000000641eca1 clang::Sema::BuildDeclarationNameExpr(clang::CXXScopeSpec const&, clang::DeclarationNameInfo const&, clang::NamedDecl*, clang::NamedDecl*, clang::TemplateArgumentListInfo const*, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x641eca1)
#12 0x00000000069d6f5a (anonymous namespace)::TemplateInstantiator::TransformDeclRefExpr(clang::DeclRefExpr*) SemaTemplateInstantiate.cpp:0:0
#13 0x00000000069b4b7b clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformExpr(clang::Expr*) SemaTemplateInstantiate.cpp:0:0
#14 0x00000000069b5f14 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformExprs(clang::Expr* const*, unsigned int, bool, llvm::SmallVectorImpl<clang::Expr*>&, bool*) SemaTemplateInstantiate.cpp:0:0
#15 0x00000000069be861 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformCallExpr(clang::CallExpr*) SemaTemplateInstantiate.cpp:0:0
#16 0x00000000069b4c68 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformExpr(clang::Expr*) SemaTemplateInstantiate.cpp:0:0
#17 0x00000000069dd736 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformRequiresExpr(clang::RequiresExpr*) SemaTemplateInstantiate.cpp:0:0
#18 0x00000000069df13e (anonymous namespace)::TemplateInstantiator::TransformRequiresExpr(clang::RequiresExpr*) SemaTemplateInstantiate.cpp:0:0
#19 0x00000000069b46f2 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformExpr(clang::Expr*) SemaTemplateInstantiate.cpp:0:0
#20 0x00000000069efdc8 clang::Sema::SubstConstraintExpr(clang::Expr*, clang::MultiLevelTemplateArgumentList const&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x69efdc8)
#21 0x000000000614ad70 calculateConstraintSatisfaction(clang::Sema&, clang::NamedDecl const*, clang::SourceLocation, clang::MultiLevelTemplateArgumentList const&, clang::Expr const*, clang::ConstraintSatisfaction&)::'lambda'(clang::Expr const*)::operator()(clang::Expr const*) const SemaConcept.cpp:0:0
#22 0x000000000614c23b 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
#23 0x000000000614cad2 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
#24 0x000000000614d10a 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-assertions-trunk/bin/clang+++0x614d10a)
#25 0x000000000614e1cb clang::Sema::CheckInstantiatedFunctionTemplateConstraints(clang::SourceLocation, clang::FunctionDecl*, llvm::ArrayRef<clang::TemplateArgument>, clang::ConstraintSatisfaction&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x614e1cb)
#26 0x00000000069748d7 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+++0x69748d7)
#27 0x0000000006975eca void llvm::function_ref<void ()>::callback_fn<clang::Sema::DeduceTemplateArguments(clang::FunctionTemplateDecl*, clang::TemplateArgumentListInfo*, llvm::ArrayRef<clang::Expr*>, clang::FunctionDecl*&, clang::sema::TemplateDeductionInfo&, bool, bool, clang::QualType, clang::Expr::Classification, llvm::function_ref<bool (llvm::ArrayRef<clang::QualType>)>)::'lambda1'()>(long) SemaTemplateDeduction.cpp:0:0
#28 0x0000000005ff1051 clang::Sema::runWithSufficientStackSpace(clang::SourceLocation, llvm::function_ref<void ()>) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5ff1051)
#29 0x000000000697fbdf clang::Sema::DeduceTemplateArguments(clang::FunctionTemplateDecl*, clang::TemplateArgumentListInfo*, llvm::ArrayRef<clang::Expr*>, clang::FunctionDecl*&, clang::sema::TemplateDeductionInfo&, bool, bool, clang::QualType, clang::Expr::Classification, llvm::function_ref<bool (llvm::ArrayRef<clang::QualType>)>) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x697fbdf)
#30 0x000000000679a60d 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
#31 0x000000000679aff3 clang::Sema::AddMethodCandidate(clang::DeclAccessPair, clang::QualType, clang::Expr::Classification, llvm::ArrayRef<clang::Expr*>, clang::OverloadCandidateSet&, bool, clang::OverloadCandidateParamOrder) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x679aff3)
#32 0x00000000067aac2f clang::Sema::BuildCallToObjectOfClassType(clang::Scope*, clang::Expr*, clang::SourceLocation, llvm::MutableArrayRef<clang::Expr*>, clang::SourceLocation) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x67aac2f)
#33 0x000000000644731e 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+++0x644731e)
#34 0x000000000644918c 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+++0x644918c)
#35 0x0000000005f0e40d clang::Parser::ParsePostfixExpressionSuffix(clang::ActionResult<clang::Expr*, true>) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5f0e40d)
#36 0x0000000005f05a41 clang::Parser::ParseCastExpression(clang::Parser::CastParseKind, bool, bool&, clang::Parser::TypeCastState, bool, bool*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5f05a41)
#37 0x0000000005f08c8a clang::Parser::ParseCastExpression(clang::Parser::CastParseKind, bool, clang::Parser::TypeCastState, bool, bool*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5f08c8a)
#38 0x0000000005f08e29 clang::Parser::ParseAssignmentExpression(clang::Parser::TypeCastState) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5f08e29)
#39 0x0000000005ec96bd clang::Parser::ParseDeclarationAfterDeclaratorAndAttributes(clang::Declarator&, clang::Parser::ParsedTemplateInfo const&, clang::Parser::ForRangeInit*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5ec96bd)
#40 0x0000000005ed6dd0 clang::Parser::ParseDeclGroup(clang::ParsingDeclSpec&, clang::DeclaratorContext, clang::ParsedAttributes&, clang::SourceLocation*, clang::Parser::ForRangeInit*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5ed6dd0)
#41 0x0000000005ea442b clang::Parser::ParseDeclOrFunctionDefInternal(clang::ParsedAttributes&, clang::ParsedAttributes&, clang::ParsingDeclSpec&, clang::AccessSpecifier) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5ea442b)
#42 0x0000000005ea4b5f clang::Parser::ParseDeclarationOrFunctionDefinition(clang::ParsedAttributes&, clang::ParsedAttributes&, clang::ParsingDeclSpec*, clang::AccessSpecifier) (.part.0) Parser.cpp:0:0
#43 0x0000000005eac504 clang::Parser::ParseExternalDeclaration(clang::ParsedAttributes&, clang::ParsedAttributes&, clang::ParsingDeclSpec*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5eac504)
#44 0x0000000005eacd2d clang::Parser::ParseTopLevelDecl(clang::OpaquePtr<clang::DeclGroupRef>&, clang::Sema::ModuleImportState&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5eacd2d)
#45 0x0000000005e9fdda clang::ParseAST(clang::Sema&, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5e9fdda)
#46 0x0000000004999d08 clang::CodeGenAction::ExecuteAction() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4999d08)
#47 0x00000000041fd819 clang::FrontendAction::Execute() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x41fd819)
#48 0x000000000417ecbe clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x417ecbe)
#49 0x00000000042dc99e clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x42dc99e)
#50 0x0000000000befa36 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xbefa36)
#51 0x0000000000be72fa ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) driver.cpp:0:0
#52 0x0000000003fdaea9 void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const::'lambda'()>(long) Job.cpp:0:0
#53 0x0000000003674744 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3674744)
#54 0x0000000003fdb49f clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const (.part.0) Job.cpp:0:0
#55 0x0000000003fa3665 clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3fa3665)
#56 0x0000000003fa40cd clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3fa40cd)
#57 0x0000000003fabff5 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3fabff5)
#58 0x0000000000becedc clang_main(int, char**, llvm::ToolContext const&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xbecedc)
#59 0x0000000000ae7071 main (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xae7071)
#60 0x00007f6fdad10083 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24083)
#61 0x0000000000be6dde _start (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xbe6dde)
clang++: error: clang frontend command failed with exit code 134 (use -v to see invocation)
Compiler returned: 134

Versions:

trunk(Online compiler, with assertions) and:

clang version 18.0.0 (https://github.com/llvm/llvm-project.git 2bc613bd4f83032aa553b6f7f3e1bd5041882791)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /opt/llvm/bin

Notes

  • If I remove requires requires ... in the decl of lambda fix, then clang-trunk will accept it.
  • clang-17 accepts it but if with assertions rejects it(https://godbolt.org/z/vT1E8fWdh).
@github-actions github-actions bot added the clang Clang issues not falling into any other category label Oct 17, 2023
@EugeneZelenko EugeneZelenko added c++20 clang:frontend Language frontend issues, e.g. anything involving "Sema" concepts C++20 concepts crash Prefer [crash-on-valid] or [crash-on-invalid] and removed clang Clang issues not falling into any other category labels Oct 17, 2023
@llvmbot
Copy link
Member

llvmbot commented Oct 17, 2023

@llvm/issue-subscribers-clang-frontend

Author: Runge (RungeCC)

## Descriptions

Example:

#include &lt;concepts&gt;
#include &lt;type_traits&gt;
#include &lt;utility&gt;

[[maybe_unused]] constexpr inline static auto lpartial =
    [](auto fn, auto... t0) constexpr noexcept {
      return [=](auto... rest) constexpr noexcept
        requires requires { fn(t0..., rest...); }
      { return fn(t0..., rest...); };
    };

[[maybe_unused]] constexpr inline static auto fix =
    [](auto self) constexpr noexcept {
      return [=](auto... args) constexpr noexcept
        requires requires { self(self, args...); }
      { return self(self, args...); };
    };

[[maybe_unused]] constexpr inline static auto currify0 =
    [](auto self, auto v, auto fn) constexpr noexcept {
      return [=](auto... as) constexpr noexcept
        requires(
            (v.value &gt; sizeof...(as) &amp;&amp; requires { lpartial(fn, as...); }) ||
            (v.value == sizeof...(as) &amp;&amp; requires { fn(as...); }))
      {
        if constexpr (v.value &gt; sizeof...(as))
          return self(self, std::integral_constant&lt;std::size_t, v.value - sizeof...(as)&gt;{}, lpartial(fn, as...));
        else
          return fn(as...);
      };
    };

[[maybe_unused]] constexpr static inline auto plus =
    [](auto x, auto y) constexpr noexcept
  requires requires { x + y; }
{ return x + y; };

#undef lambda_body

[[maybe_unused]] constexpr static inline auto plus_ =
    fix(currify0)(std::integral_constant&lt;std::size_t, 2&gt;{}, plus);

Expected behavior:

Accepts the above code, just as gcc(13.2 and trunk), msvc(latest) do.

Actual behavior:

Crash, with output:

<details>
<summary>Click me</summary>

clang++: /root/llvm-project/llvm/include/llvm/ADT/SmallVector.h:294: T&amp; llvm::SmallVectorTemplateCommon&lt;T, &lt;template-parameter-1-2&gt; &gt;::operator[](llvm::SmallVectorTemplateCommon&lt;T, &lt;template-parameter-1-2&gt; &gt;::size_type) [with T = clang::sema::FunctionScopeInfo*; &lt;template-parameter-1-2&gt; = void; llvm::SmallVectorTemplateCommon&lt;T, &lt;template-parameter-1-2&gt; &gt;::reference = clang::sema::FunctionScopeInfo*&amp;; llvm::SmallVectorTemplateCommon&lt;T, &lt;template-parameter-1-2&gt; &gt;::size_type = long unsigned int]: Assertion `idx &lt; size()' 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++ -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 &lt;source&gt;
1.	&lt;source&gt;:41:65: current parser token ')'
 #<!-- -->0 0x000000000372dc98 llvm::sys::PrintStackTrace(llvm::raw_ostream&amp;, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x372dc98)
 #<!-- -->1 0x000000000372b95c llvm::sys::CleanupOnSignal(unsigned long) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x372b95c)
 #<!-- -->2 0x0000000003674298 CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0
 #<!-- -->3 0x00007f6fdb26c420 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x14420)
 #<!-- -->4 0x00007f6fdad2f00b raise (/lib/x86_64-linux-gnu/libc.so.6+0x4300b)
 #<!-- -->5 0x00007f6fdad0e859 abort (/lib/x86_64-linux-gnu/libc.so.6+0x22859)
 #<!-- -->6 0x00007f6fdad0e729 (/lib/x86_64-linux-gnu/libc.so.6+0x22729)
 #<!-- -->7 0x00007f6fdad1ffd6 (/lib/x86_64-linux-gnu/libc.so.6+0x33fd6)
 #<!-- -->8 0x00000000063ebb23 clang::Sema::tryCaptureVariable(clang::ValueDecl*, clang::SourceLocation, clang::Sema::TryCaptureKind, clang::SourceLocation, bool, clang::QualType&amp;, clang::QualType&amp;, unsigned int const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x63ebb23)
 #<!-- -->9 0x0000000006419256 clang::Sema::BuildDeclRefExpr(clang::ValueDecl*, clang::QualType, clang::ExprValueKind, clang::DeclarationNameInfo const&amp;, clang::NestedNameSpecifierLoc, clang::NamedDecl*, clang::SourceLocation, clang::TemplateArgumentListInfo const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6419256)
#<!-- -->10 0x0000000006419aac clang::Sema::BuildDeclRefExpr(clang::ValueDecl*, clang::QualType, clang::ExprValueKind, clang::DeclarationNameInfo const&amp;, clang::CXXScopeSpec const*, clang::NamedDecl*, clang::SourceLocation, clang::TemplateArgumentListInfo const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6419aac)
#<!-- -->11 0x000000000641eca1 clang::Sema::BuildDeclarationNameExpr(clang::CXXScopeSpec const&amp;, clang::DeclarationNameInfo const&amp;, clang::NamedDecl*, clang::NamedDecl*, clang::TemplateArgumentListInfo const*, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x641eca1)
#<!-- -->12 0x00000000069d6f5a (anonymous namespace)::TemplateInstantiator::TransformDeclRefExpr(clang::DeclRefExpr*) SemaTemplateInstantiate.cpp:0:0
#<!-- -->13 0x00000000069b4b7b clang::TreeTransform&lt;(anonymous namespace)::TemplateInstantiator&gt;::TransformExpr(clang::Expr*) SemaTemplateInstantiate.cpp:0:0
#<!-- -->14 0x00000000069b5f14 clang::TreeTransform&lt;(anonymous namespace)::TemplateInstantiator&gt;::TransformExprs(clang::Expr* const*, unsigned int, bool, llvm::SmallVectorImpl&lt;clang::Expr*&gt;&amp;, bool*) SemaTemplateInstantiate.cpp:0:0
#<!-- -->15 0x00000000069be861 clang::TreeTransform&lt;(anonymous namespace)::TemplateInstantiator&gt;::TransformCallExpr(clang::CallExpr*) SemaTemplateInstantiate.cpp:0:0
#<!-- -->16 0x00000000069b4c68 clang::TreeTransform&lt;(anonymous namespace)::TemplateInstantiator&gt;::TransformExpr(clang::Expr*) SemaTemplateInstantiate.cpp:0:0
#<!-- -->17 0x00000000069dd736 clang::TreeTransform&lt;(anonymous namespace)::TemplateInstantiator&gt;::TransformRequiresExpr(clang::RequiresExpr*) SemaTemplateInstantiate.cpp:0:0
#<!-- -->18 0x00000000069df13e (anonymous namespace)::TemplateInstantiator::TransformRequiresExpr(clang::RequiresExpr*) SemaTemplateInstantiate.cpp:0:0
#<!-- -->19 0x00000000069b46f2 clang::TreeTransform&lt;(anonymous namespace)::TemplateInstantiator&gt;::TransformExpr(clang::Expr*) SemaTemplateInstantiate.cpp:0:0
#<!-- -->20 0x00000000069efdc8 clang::Sema::SubstConstraintExpr(clang::Expr*, clang::MultiLevelTemplateArgumentList const&amp;) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x69efdc8)
#<!-- -->21 0x000000000614ad70 calculateConstraintSatisfaction(clang::Sema&amp;, clang::NamedDecl const*, clang::SourceLocation, clang::MultiLevelTemplateArgumentList const&amp;, clang::Expr const*, clang::ConstraintSatisfaction&amp;)::'lambda'(clang::Expr const*)::operator()(clang::Expr const*) const SemaConcept.cpp:0:0
#<!-- -->22 0x000000000614c23b clang::ActionResult&lt;clang::Expr*, true&gt; calculateConstraintSatisfaction&lt;calculateConstraintSatisfaction(clang::Sema&amp;, clang::NamedDecl const*, clang::SourceLocation, clang::MultiLevelTemplateArgumentList const&amp;, clang::Expr const*, clang::ConstraintSatisfaction&amp;)::'lambda'(clang::Expr const*)&gt;(clang::Sema&amp;, clang::Expr const*, clang::ConstraintSatisfaction&amp;, calculateConstraintSatisfaction(clang::Sema&amp;, clang::NamedDecl const*, clang::SourceLocation, clang::MultiLevelTemplateArgumentList const&amp;, clang::Expr const*, clang::ConstraintSatisfaction&amp;)::'lambda'(clang::Expr const*)&amp;&amp;) SemaConcept.cpp:0:0
#<!-- -->23 0x000000000614cad2 CheckConstraintSatisfaction(clang::Sema&amp;, clang::NamedDecl const*, llvm::ArrayRef&lt;clang::Expr const*&gt;, llvm::SmallVectorImpl&lt;clang::Expr*&gt;&amp;, clang::MultiLevelTemplateArgumentList const&amp;, clang::SourceRange, clang::ConstraintSatisfaction&amp;) SemaConcept.cpp:0:0
#<!-- -->24 0x000000000614d10a clang::Sema::CheckConstraintSatisfaction(clang::NamedDecl const*, llvm::ArrayRef&lt;clang::Expr const*&gt;, llvm::SmallVectorImpl&lt;clang::Expr*&gt;&amp;, clang::MultiLevelTemplateArgumentList const&amp;, clang::SourceRange, clang::ConstraintSatisfaction&amp;) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x614d10a)
#<!-- -->25 0x000000000614e1cb clang::Sema::CheckInstantiatedFunctionTemplateConstraints(clang::SourceLocation, clang::FunctionDecl*, llvm::ArrayRef&lt;clang::TemplateArgument&gt;, clang::ConstraintSatisfaction&amp;) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x614e1cb)
#<!-- -->26 0x00000000069748d7 clang::Sema::FinishTemplateArgumentDeduction(clang::FunctionTemplateDecl*, llvm::SmallVectorImpl&lt;clang::DeducedTemplateArgument&gt;&amp;, unsigned int, clang::FunctionDecl*&amp;, clang::sema::TemplateDeductionInfo&amp;, llvm::SmallVectorImpl&lt;clang::Sema::OriginalCallArg&gt; const*, bool, llvm::function_ref&lt;bool ()&gt;) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x69748d7)
#<!-- -->27 0x0000000006975eca void llvm::function_ref&lt;void ()&gt;::callback_fn&lt;clang::Sema::DeduceTemplateArguments(clang::FunctionTemplateDecl*, clang::TemplateArgumentListInfo*, llvm::ArrayRef&lt;clang::Expr*&gt;, clang::FunctionDecl*&amp;, clang::sema::TemplateDeductionInfo&amp;, bool, bool, clang::QualType, clang::Expr::Classification, llvm::function_ref&lt;bool (llvm::ArrayRef&lt;clang::QualType&gt;)&gt;)::'lambda1'()&gt;(long) SemaTemplateDeduction.cpp:0:0
#<!-- -->28 0x0000000005ff1051 clang::Sema::runWithSufficientStackSpace(clang::SourceLocation, llvm::function_ref&lt;void ()&gt;) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5ff1051)
#<!-- -->29 0x000000000697fbdf clang::Sema::DeduceTemplateArguments(clang::FunctionTemplateDecl*, clang::TemplateArgumentListInfo*, llvm::ArrayRef&lt;clang::Expr*&gt;, clang::FunctionDecl*&amp;, clang::sema::TemplateDeductionInfo&amp;, bool, bool, clang::QualType, clang::Expr::Classification, llvm::function_ref&lt;bool (llvm::ArrayRef&lt;clang::QualType&gt;)&gt;) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x697fbdf)
#<!-- -->30 0x000000000679a60d clang::Sema::AddMethodTemplateCandidate(clang::FunctionTemplateDecl*, clang::DeclAccessPair, clang::CXXRecordDecl*, clang::TemplateArgumentListInfo*, clang::QualType, clang::Expr::Classification, llvm::ArrayRef&lt;clang::Expr*&gt;, clang::OverloadCandidateSet&amp;, bool, bool, clang::OverloadCandidateParamOrder) (.constprop.0) SemaOverload.cpp:0:0
#<!-- -->31 0x000000000679aff3 clang::Sema::AddMethodCandidate(clang::DeclAccessPair, clang::QualType, clang::Expr::Classification, llvm::ArrayRef&lt;clang::Expr*&gt;, clang::OverloadCandidateSet&amp;, bool, clang::OverloadCandidateParamOrder) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x679aff3)
#<!-- -->32 0x00000000067aac2f clang::Sema::BuildCallToObjectOfClassType(clang::Scope*, clang::Expr*, clang::SourceLocation, llvm::MutableArrayRef&lt;clang::Expr*&gt;, clang::SourceLocation) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x67aac2f)
#<!-- -->33 0x000000000644731e clang::Sema::BuildCallExpr(clang::Scope*, clang::Expr*, clang::SourceLocation, llvm::MutableArrayRef&lt;clang::Expr*&gt;, clang::SourceLocation, clang::Expr*, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x644731e)
#<!-- -->34 0x000000000644918c clang::Sema::ActOnCallExpr(clang::Scope*, clang::Expr*, clang::SourceLocation, llvm::MutableArrayRef&lt;clang::Expr*&gt;, clang::SourceLocation, clang::Expr*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x644918c)
#<!-- -->35 0x0000000005f0e40d clang::Parser::ParsePostfixExpressionSuffix(clang::ActionResult&lt;clang::Expr*, true&gt;) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5f0e40d)
#<!-- -->36 0x0000000005f05a41 clang::Parser::ParseCastExpression(clang::Parser::CastParseKind, bool, bool&amp;, clang::Parser::TypeCastState, bool, bool*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5f05a41)
#<!-- -->37 0x0000000005f08c8a clang::Parser::ParseCastExpression(clang::Parser::CastParseKind, bool, clang::Parser::TypeCastState, bool, bool*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5f08c8a)
#<!-- -->38 0x0000000005f08e29 clang::Parser::ParseAssignmentExpression(clang::Parser::TypeCastState) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5f08e29)
#<!-- -->39 0x0000000005ec96bd clang::Parser::ParseDeclarationAfterDeclaratorAndAttributes(clang::Declarator&amp;, clang::Parser::ParsedTemplateInfo const&amp;, clang::Parser::ForRangeInit*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5ec96bd)
#<!-- -->40 0x0000000005ed6dd0 clang::Parser::ParseDeclGroup(clang::ParsingDeclSpec&amp;, clang::DeclaratorContext, clang::ParsedAttributes&amp;, clang::SourceLocation*, clang::Parser::ForRangeInit*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5ed6dd0)
#<!-- -->41 0x0000000005ea442b clang::Parser::ParseDeclOrFunctionDefInternal(clang::ParsedAttributes&amp;, clang::ParsedAttributes&amp;, clang::ParsingDeclSpec&amp;, clang::AccessSpecifier) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5ea442b)
#<!-- -->42 0x0000000005ea4b5f clang::Parser::ParseDeclarationOrFunctionDefinition(clang::ParsedAttributes&amp;, clang::ParsedAttributes&amp;, clang::ParsingDeclSpec*, clang::AccessSpecifier) (.part.0) Parser.cpp:0:0
#<!-- -->43 0x0000000005eac504 clang::Parser::ParseExternalDeclaration(clang::ParsedAttributes&amp;, clang::ParsedAttributes&amp;, clang::ParsingDeclSpec*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5eac504)
#<!-- -->44 0x0000000005eacd2d clang::Parser::ParseTopLevelDecl(clang::OpaquePtr&lt;clang::DeclGroupRef&gt;&amp;, clang::Sema::ModuleImportState&amp;) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5eacd2d)
#<!-- -->45 0x0000000005e9fdda clang::ParseAST(clang::Sema&amp;, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5e9fdda)
#<!-- -->46 0x0000000004999d08 clang::CodeGenAction::ExecuteAction() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4999d08)
#<!-- -->47 0x00000000041fd819 clang::FrontendAction::Execute() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x41fd819)
#<!-- -->48 0x000000000417ecbe clang::CompilerInstance::ExecuteAction(clang::FrontendAction&amp;) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x417ecbe)
#<!-- -->49 0x00000000042dc99e clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x42dc99e)
#<!-- -->50 0x0000000000befa36 cc1_main(llvm::ArrayRef&lt;char const*&gt;, char const*, void*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xbefa36)
#<!-- -->51 0x0000000000be72fa ExecuteCC1Tool(llvm::SmallVectorImpl&lt;char const*&gt;&amp;, llvm::ToolContext const&amp;) driver.cpp:0:0
#<!-- -->52 0x0000000003fdaea9 void llvm::function_ref&lt;void ()&gt;::callback_fn&lt;clang::driver::CC1Command::Execute(llvm::ArrayRef&lt;std::optional&lt;llvm::StringRef&gt;&gt;, std::__cxx11::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt;&gt;*, bool*) const::'lambda'()&gt;(long) Job.cpp:0:0
#<!-- -->53 0x0000000003674744 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref&lt;void ()&gt;) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3674744)
#<!-- -->54 0x0000000003fdb49f clang::driver::CC1Command::Execute(llvm::ArrayRef&lt;std::optional&lt;llvm::StringRef&gt;&gt;, std::__cxx11::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt;&gt;*, bool*) const (.part.0) Job.cpp:0:0
#<!-- -->55 0x0000000003fa3665 clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&amp;, clang::driver::Command const*&amp;, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3fa3665)
#<!-- -->56 0x0000000003fa40cd clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&amp;, llvm::SmallVectorImpl&lt;std::pair&lt;int, clang::driver::Command const*&gt;&gt;&amp;, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3fa40cd)
#<!-- -->57 0x0000000003fabff5 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&amp;, llvm::SmallVectorImpl&lt;std::pair&lt;int, clang::driver::Command const*&gt;&gt;&amp;) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3fabff5)
#<!-- -->58 0x0000000000becedc clang_main(int, char**, llvm::ToolContext const&amp;) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xbecedc)
#<!-- -->59 0x0000000000ae7071 main (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xae7071)
#<!-- -->60 0x00007f6fdad10083 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24083)
#<!-- -->61 0x0000000000be6dde _start (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xbe6dde)
clang++: error: clang frontend command failed with exit code 134 (use -v to see invocation)
Compiler returned: 134

</details>

Versions:

trunk(Online compiler, with assertions) and:

clang version 18.0.0 (https://github.com/llvm/llvm-project.git 2bc613bd4f83032aa553b6f7f3e1bd5041882791)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /opt/llvm/bin

Notes

  • If I remove requires requires ... in the decl of lambda fix, then clang-trunk will accept it.
  • clang-17 accepts it but if with assertions rejects it(https://godbolt.org/z/vT1E8fWdh).

@llvmbot
Copy link
Member

llvmbot commented Oct 17, 2023

@llvm/issue-subscribers-c-20

Author: Runge (RungeCC)

## Descriptions

Example:

#include &lt;concepts&gt;
#include &lt;type_traits&gt;
#include &lt;utility&gt;

[[maybe_unused]] constexpr inline static auto lpartial =
    [](auto fn, auto... t0) constexpr noexcept {
      return [=](auto... rest) constexpr noexcept
        requires requires { fn(t0..., rest...); }
      { return fn(t0..., rest...); };
    };

[[maybe_unused]] constexpr inline static auto fix =
    [](auto self) constexpr noexcept {
      return [=](auto... args) constexpr noexcept
        requires requires { self(self, args...); }
      { return self(self, args...); };
    };

[[maybe_unused]] constexpr inline static auto currify0 =
    [](auto self, auto v, auto fn) constexpr noexcept {
      return [=](auto... as) constexpr noexcept
        requires(
            (v.value &gt; sizeof...(as) &amp;&amp; requires { lpartial(fn, as...); }) ||
            (v.value == sizeof...(as) &amp;&amp; requires { fn(as...); }))
      {
        if constexpr (v.value &gt; sizeof...(as))
          return self(self, std::integral_constant&lt;std::size_t, v.value - sizeof...(as)&gt;{}, lpartial(fn, as...));
        else
          return fn(as...);
      };
    };

[[maybe_unused]] constexpr static inline auto plus =
    [](auto x, auto y) constexpr noexcept
  requires requires { x + y; }
{ return x + y; };

#undef lambda_body

[[maybe_unused]] constexpr static inline auto plus_ =
    fix(currify0)(std::integral_constant&lt;std::size_t, 2&gt;{}, plus);

Expected behavior:

Accepts the above code, just as gcc(13.2 and trunk), msvc(latest) do.

Actual behavior:

Crash, with output:

<details>
<summary>Click me</summary>

clang++: /root/llvm-project/llvm/include/llvm/ADT/SmallVector.h:294: T&amp; llvm::SmallVectorTemplateCommon&lt;T, &lt;template-parameter-1-2&gt; &gt;::operator[](llvm::SmallVectorTemplateCommon&lt;T, &lt;template-parameter-1-2&gt; &gt;::size_type) [with T = clang::sema::FunctionScopeInfo*; &lt;template-parameter-1-2&gt; = void; llvm::SmallVectorTemplateCommon&lt;T, &lt;template-parameter-1-2&gt; &gt;::reference = clang::sema::FunctionScopeInfo*&amp;; llvm::SmallVectorTemplateCommon&lt;T, &lt;template-parameter-1-2&gt; &gt;::size_type = long unsigned int]: Assertion `idx &lt; size()' 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++ -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 &lt;source&gt;
1.	&lt;source&gt;:41:65: current parser token ')'
 #<!-- -->0 0x000000000372dc98 llvm::sys::PrintStackTrace(llvm::raw_ostream&amp;, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x372dc98)
 #<!-- -->1 0x000000000372b95c llvm::sys::CleanupOnSignal(unsigned long) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x372b95c)
 #<!-- -->2 0x0000000003674298 CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0
 #<!-- -->3 0x00007f6fdb26c420 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x14420)
 #<!-- -->4 0x00007f6fdad2f00b raise (/lib/x86_64-linux-gnu/libc.so.6+0x4300b)
 #<!-- -->5 0x00007f6fdad0e859 abort (/lib/x86_64-linux-gnu/libc.so.6+0x22859)
 #<!-- -->6 0x00007f6fdad0e729 (/lib/x86_64-linux-gnu/libc.so.6+0x22729)
 #<!-- -->7 0x00007f6fdad1ffd6 (/lib/x86_64-linux-gnu/libc.so.6+0x33fd6)
 #<!-- -->8 0x00000000063ebb23 clang::Sema::tryCaptureVariable(clang::ValueDecl*, clang::SourceLocation, clang::Sema::TryCaptureKind, clang::SourceLocation, bool, clang::QualType&amp;, clang::QualType&amp;, unsigned int const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x63ebb23)
 #<!-- -->9 0x0000000006419256 clang::Sema::BuildDeclRefExpr(clang::ValueDecl*, clang::QualType, clang::ExprValueKind, clang::DeclarationNameInfo const&amp;, clang::NestedNameSpecifierLoc, clang::NamedDecl*, clang::SourceLocation, clang::TemplateArgumentListInfo const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6419256)
#<!-- -->10 0x0000000006419aac clang::Sema::BuildDeclRefExpr(clang::ValueDecl*, clang::QualType, clang::ExprValueKind, clang::DeclarationNameInfo const&amp;, clang::CXXScopeSpec const*, clang::NamedDecl*, clang::SourceLocation, clang::TemplateArgumentListInfo const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6419aac)
#<!-- -->11 0x000000000641eca1 clang::Sema::BuildDeclarationNameExpr(clang::CXXScopeSpec const&amp;, clang::DeclarationNameInfo const&amp;, clang::NamedDecl*, clang::NamedDecl*, clang::TemplateArgumentListInfo const*, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x641eca1)
#<!-- -->12 0x00000000069d6f5a (anonymous namespace)::TemplateInstantiator::TransformDeclRefExpr(clang::DeclRefExpr*) SemaTemplateInstantiate.cpp:0:0
#<!-- -->13 0x00000000069b4b7b clang::TreeTransform&lt;(anonymous namespace)::TemplateInstantiator&gt;::TransformExpr(clang::Expr*) SemaTemplateInstantiate.cpp:0:0
#<!-- -->14 0x00000000069b5f14 clang::TreeTransform&lt;(anonymous namespace)::TemplateInstantiator&gt;::TransformExprs(clang::Expr* const*, unsigned int, bool, llvm::SmallVectorImpl&lt;clang::Expr*&gt;&amp;, bool*) SemaTemplateInstantiate.cpp:0:0
#<!-- -->15 0x00000000069be861 clang::TreeTransform&lt;(anonymous namespace)::TemplateInstantiator&gt;::TransformCallExpr(clang::CallExpr*) SemaTemplateInstantiate.cpp:0:0
#<!-- -->16 0x00000000069b4c68 clang::TreeTransform&lt;(anonymous namespace)::TemplateInstantiator&gt;::TransformExpr(clang::Expr*) SemaTemplateInstantiate.cpp:0:0
#<!-- -->17 0x00000000069dd736 clang::TreeTransform&lt;(anonymous namespace)::TemplateInstantiator&gt;::TransformRequiresExpr(clang::RequiresExpr*) SemaTemplateInstantiate.cpp:0:0
#<!-- -->18 0x00000000069df13e (anonymous namespace)::TemplateInstantiator::TransformRequiresExpr(clang::RequiresExpr*) SemaTemplateInstantiate.cpp:0:0
#<!-- -->19 0x00000000069b46f2 clang::TreeTransform&lt;(anonymous namespace)::TemplateInstantiator&gt;::TransformExpr(clang::Expr*) SemaTemplateInstantiate.cpp:0:0
#<!-- -->20 0x00000000069efdc8 clang::Sema::SubstConstraintExpr(clang::Expr*, clang::MultiLevelTemplateArgumentList const&amp;) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x69efdc8)
#<!-- -->21 0x000000000614ad70 calculateConstraintSatisfaction(clang::Sema&amp;, clang::NamedDecl const*, clang::SourceLocation, clang::MultiLevelTemplateArgumentList const&amp;, clang::Expr const*, clang::ConstraintSatisfaction&amp;)::'lambda'(clang::Expr const*)::operator()(clang::Expr const*) const SemaConcept.cpp:0:0
#<!-- -->22 0x000000000614c23b clang::ActionResult&lt;clang::Expr*, true&gt; calculateConstraintSatisfaction&lt;calculateConstraintSatisfaction(clang::Sema&amp;, clang::NamedDecl const*, clang::SourceLocation, clang::MultiLevelTemplateArgumentList const&amp;, clang::Expr const*, clang::ConstraintSatisfaction&amp;)::'lambda'(clang::Expr const*)&gt;(clang::Sema&amp;, clang::Expr const*, clang::ConstraintSatisfaction&amp;, calculateConstraintSatisfaction(clang::Sema&amp;, clang::NamedDecl const*, clang::SourceLocation, clang::MultiLevelTemplateArgumentList const&amp;, clang::Expr const*, clang::ConstraintSatisfaction&amp;)::'lambda'(clang::Expr const*)&amp;&amp;) SemaConcept.cpp:0:0
#<!-- -->23 0x000000000614cad2 CheckConstraintSatisfaction(clang::Sema&amp;, clang::NamedDecl const*, llvm::ArrayRef&lt;clang::Expr const*&gt;, llvm::SmallVectorImpl&lt;clang::Expr*&gt;&amp;, clang::MultiLevelTemplateArgumentList const&amp;, clang::SourceRange, clang::ConstraintSatisfaction&amp;) SemaConcept.cpp:0:0
#<!-- -->24 0x000000000614d10a clang::Sema::CheckConstraintSatisfaction(clang::NamedDecl const*, llvm::ArrayRef&lt;clang::Expr const*&gt;, llvm::SmallVectorImpl&lt;clang::Expr*&gt;&amp;, clang::MultiLevelTemplateArgumentList const&amp;, clang::SourceRange, clang::ConstraintSatisfaction&amp;) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x614d10a)
#<!-- -->25 0x000000000614e1cb clang::Sema::CheckInstantiatedFunctionTemplateConstraints(clang::SourceLocation, clang::FunctionDecl*, llvm::ArrayRef&lt;clang::TemplateArgument&gt;, clang::ConstraintSatisfaction&amp;) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x614e1cb)
#<!-- -->26 0x00000000069748d7 clang::Sema::FinishTemplateArgumentDeduction(clang::FunctionTemplateDecl*, llvm::SmallVectorImpl&lt;clang::DeducedTemplateArgument&gt;&amp;, unsigned int, clang::FunctionDecl*&amp;, clang::sema::TemplateDeductionInfo&amp;, llvm::SmallVectorImpl&lt;clang::Sema::OriginalCallArg&gt; const*, bool, llvm::function_ref&lt;bool ()&gt;) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x69748d7)
#<!-- -->27 0x0000000006975eca void llvm::function_ref&lt;void ()&gt;::callback_fn&lt;clang::Sema::DeduceTemplateArguments(clang::FunctionTemplateDecl*, clang::TemplateArgumentListInfo*, llvm::ArrayRef&lt;clang::Expr*&gt;, clang::FunctionDecl*&amp;, clang::sema::TemplateDeductionInfo&amp;, bool, bool, clang::QualType, clang::Expr::Classification, llvm::function_ref&lt;bool (llvm::ArrayRef&lt;clang::QualType&gt;)&gt;)::'lambda1'()&gt;(long) SemaTemplateDeduction.cpp:0:0
#<!-- -->28 0x0000000005ff1051 clang::Sema::runWithSufficientStackSpace(clang::SourceLocation, llvm::function_ref&lt;void ()&gt;) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5ff1051)
#<!-- -->29 0x000000000697fbdf clang::Sema::DeduceTemplateArguments(clang::FunctionTemplateDecl*, clang::TemplateArgumentListInfo*, llvm::ArrayRef&lt;clang::Expr*&gt;, clang::FunctionDecl*&amp;, clang::sema::TemplateDeductionInfo&amp;, bool, bool, clang::QualType, clang::Expr::Classification, llvm::function_ref&lt;bool (llvm::ArrayRef&lt;clang::QualType&gt;)&gt;) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x697fbdf)
#<!-- -->30 0x000000000679a60d clang::Sema::AddMethodTemplateCandidate(clang::FunctionTemplateDecl*, clang::DeclAccessPair, clang::CXXRecordDecl*, clang::TemplateArgumentListInfo*, clang::QualType, clang::Expr::Classification, llvm::ArrayRef&lt;clang::Expr*&gt;, clang::OverloadCandidateSet&amp;, bool, bool, clang::OverloadCandidateParamOrder) (.constprop.0) SemaOverload.cpp:0:0
#<!-- -->31 0x000000000679aff3 clang::Sema::AddMethodCandidate(clang::DeclAccessPair, clang::QualType, clang::Expr::Classification, llvm::ArrayRef&lt;clang::Expr*&gt;, clang::OverloadCandidateSet&amp;, bool, clang::OverloadCandidateParamOrder) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x679aff3)
#<!-- -->32 0x00000000067aac2f clang::Sema::BuildCallToObjectOfClassType(clang::Scope*, clang::Expr*, clang::SourceLocation, llvm::MutableArrayRef&lt;clang::Expr*&gt;, clang::SourceLocation) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x67aac2f)
#<!-- -->33 0x000000000644731e clang::Sema::BuildCallExpr(clang::Scope*, clang::Expr*, clang::SourceLocation, llvm::MutableArrayRef&lt;clang::Expr*&gt;, clang::SourceLocation, clang::Expr*, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x644731e)
#<!-- -->34 0x000000000644918c clang::Sema::ActOnCallExpr(clang::Scope*, clang::Expr*, clang::SourceLocation, llvm::MutableArrayRef&lt;clang::Expr*&gt;, clang::SourceLocation, clang::Expr*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x644918c)
#<!-- -->35 0x0000000005f0e40d clang::Parser::ParsePostfixExpressionSuffix(clang::ActionResult&lt;clang::Expr*, true&gt;) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5f0e40d)
#<!-- -->36 0x0000000005f05a41 clang::Parser::ParseCastExpression(clang::Parser::CastParseKind, bool, bool&amp;, clang::Parser::TypeCastState, bool, bool*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5f05a41)
#<!-- -->37 0x0000000005f08c8a clang::Parser::ParseCastExpression(clang::Parser::CastParseKind, bool, clang::Parser::TypeCastState, bool, bool*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5f08c8a)
#<!-- -->38 0x0000000005f08e29 clang::Parser::ParseAssignmentExpression(clang::Parser::TypeCastState) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5f08e29)
#<!-- -->39 0x0000000005ec96bd clang::Parser::ParseDeclarationAfterDeclaratorAndAttributes(clang::Declarator&amp;, clang::Parser::ParsedTemplateInfo const&amp;, clang::Parser::ForRangeInit*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5ec96bd)
#<!-- -->40 0x0000000005ed6dd0 clang::Parser::ParseDeclGroup(clang::ParsingDeclSpec&amp;, clang::DeclaratorContext, clang::ParsedAttributes&amp;, clang::SourceLocation*, clang::Parser::ForRangeInit*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5ed6dd0)
#<!-- -->41 0x0000000005ea442b clang::Parser::ParseDeclOrFunctionDefInternal(clang::ParsedAttributes&amp;, clang::ParsedAttributes&amp;, clang::ParsingDeclSpec&amp;, clang::AccessSpecifier) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5ea442b)
#<!-- -->42 0x0000000005ea4b5f clang::Parser::ParseDeclarationOrFunctionDefinition(clang::ParsedAttributes&amp;, clang::ParsedAttributes&amp;, clang::ParsingDeclSpec*, clang::AccessSpecifier) (.part.0) Parser.cpp:0:0
#<!-- -->43 0x0000000005eac504 clang::Parser::ParseExternalDeclaration(clang::ParsedAttributes&amp;, clang::ParsedAttributes&amp;, clang::ParsingDeclSpec*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5eac504)
#<!-- -->44 0x0000000005eacd2d clang::Parser::ParseTopLevelDecl(clang::OpaquePtr&lt;clang::DeclGroupRef&gt;&amp;, clang::Sema::ModuleImportState&amp;) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5eacd2d)
#<!-- -->45 0x0000000005e9fdda clang::ParseAST(clang::Sema&amp;, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5e9fdda)
#<!-- -->46 0x0000000004999d08 clang::CodeGenAction::ExecuteAction() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4999d08)
#<!-- -->47 0x00000000041fd819 clang::FrontendAction::Execute() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x41fd819)
#<!-- -->48 0x000000000417ecbe clang::CompilerInstance::ExecuteAction(clang::FrontendAction&amp;) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x417ecbe)
#<!-- -->49 0x00000000042dc99e clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x42dc99e)
#<!-- -->50 0x0000000000befa36 cc1_main(llvm::ArrayRef&lt;char const*&gt;, char const*, void*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xbefa36)
#<!-- -->51 0x0000000000be72fa ExecuteCC1Tool(llvm::SmallVectorImpl&lt;char const*&gt;&amp;, llvm::ToolContext const&amp;) driver.cpp:0:0
#<!-- -->52 0x0000000003fdaea9 void llvm::function_ref&lt;void ()&gt;::callback_fn&lt;clang::driver::CC1Command::Execute(llvm::ArrayRef&lt;std::optional&lt;llvm::StringRef&gt;&gt;, std::__cxx11::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt;&gt;*, bool*) const::'lambda'()&gt;(long) Job.cpp:0:0
#<!-- -->53 0x0000000003674744 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref&lt;void ()&gt;) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3674744)
#<!-- -->54 0x0000000003fdb49f clang::driver::CC1Command::Execute(llvm::ArrayRef&lt;std::optional&lt;llvm::StringRef&gt;&gt;, std::__cxx11::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt;&gt;*, bool*) const (.part.0) Job.cpp:0:0
#<!-- -->55 0x0000000003fa3665 clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&amp;, clang::driver::Command const*&amp;, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3fa3665)
#<!-- -->56 0x0000000003fa40cd clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&amp;, llvm::SmallVectorImpl&lt;std::pair&lt;int, clang::driver::Command const*&gt;&gt;&amp;, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3fa40cd)
#<!-- -->57 0x0000000003fabff5 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&amp;, llvm::SmallVectorImpl&lt;std::pair&lt;int, clang::driver::Command const*&gt;&gt;&amp;) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3fabff5)
#<!-- -->58 0x0000000000becedc clang_main(int, char**, llvm::ToolContext const&amp;) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xbecedc)
#<!-- -->59 0x0000000000ae7071 main (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xae7071)
#<!-- -->60 0x00007f6fdad10083 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24083)
#<!-- -->61 0x0000000000be6dde _start (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xbe6dde)
clang++: error: clang frontend command failed with exit code 134 (use -v to see invocation)
Compiler returned: 134

</details>

Versions:

trunk(Online compiler, with assertions) and:

clang version 18.0.0 (https://github.com/llvm/llvm-project.git 2bc613bd4f83032aa553b6f7f3e1bd5041882791)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /opt/llvm/bin

Notes

  • If I remove requires requires ... in the decl of lambda fix, then clang-trunk will accept it.
  • clang-17 accepts it but if with assertions rejects it(https://godbolt.org/z/vT1E8fWdh).

@RungeCC
Copy link
Author

RungeCC commented Oct 25, 2023

I have found a strange workaround:

Convert a function call that will trigger clang ICE, like:

fix(currify0)(std::integral_constant<std::size_t, 2>{}, plus)

into an equivalent form:

[]<class=void> requires requires {
        fix(currify0)(std::integral_constant<std::size_t, 2>{}, plus); } {
            return fix(currify0)(std::integral_constant<std::size_t, 2>{}, plus);
        }();

Then clang could work with it, without crashing or emitting any warnings.

See online compiler.

@shafik
Copy link
Collaborator

shafik commented Oct 25, 2023

Possibly related: #67260

CC @erichkeane @cor3ntin

@RungeCC
Copy link
Author

RungeCC commented Oct 25, 2023

A minimal example is:

constexpr auto ICE = [](auto a) { // a dependent ParmVar
  return [=]()   // #1, ICE
  //     [&]()   // #2, ICE
  //     [ ]()   // #3, OK
  //     [r=a]() // #4, OK
  //     [a]()   // #5, OK
  //     [&r=a]()// #6, OK with warning
  //     [&a]()  // #7, OK with warning   
    requires requires { a; } 
  { return 1; };
};

constexpr auto Ret = ICE(1)();
constexpr auto ICE = [](auto a) {
  return [=]() 
    requires requires { a; } 
  { return a; }; // #8, implicitly captured, OK
};

constexpr auto Ret = ICE(1)();

Note:

  1. according to [expr.prim.lambda.capture], a in 1-8 shall not be implicitly captured; then 1-3 no capture and 4-7 explicitly capture.
  2. the original case could also be fixed by explicitly capturing self.
  3. and for #67260: https://godbolt.org/z/5fbcqbeqW.
  4. It's weird, seems clang is trying to capturing something shall not be implicitly captured (a variable that is not potentially evaluated, or a function id).

@RungeCC
Copy link
Author

RungeCC commented Oct 26, 2023

I think the following code is suspicious:

if (LSI && !LSI->AfterParameterList) {
// This allows capturing parameters from a default value which does not
// seems correct
if (isa<ParmVarDecl>(Var) && !Var->getDeclContext()->isFunctionOrMethod())
return true;
}

Consider:

constexpr auto ICE(auto a) { // template function, not lambda
  return [=]()
    requires requires { a; } 
  { return 1; };
};

ICE happens when checking satisfaction of constraints of the operator() of the result closure object. We call tryCaptureVariable to determine whether we should capture a though we always shall not capture it (it's pretty weird up to this point). Then !Var->getDeclContext()->isFunctionOrMethod()) obtains false since auto a is exactly declared in a Function scope, we missed our last chance to return to the caller (with true). Then since in the context calling the operator() of the closure object (returned by function ICE), FunctionScopes.size() == 1, before we reach the declaration scope of auto a, --FunctionScopesIndex causes underflow, which made FunctionScopes[FunctionScopesIndex] trigger the assertion in the next loop step.

It seems that before 3ed9e9e the above example is somehow like (ignoring incorrect syntax):

constexpr auto ICE(auto a) { // template function, not lambda
  return [=]()
  { requires requires { a; }; return 1; };
};

LambdaScopeInfo *LSI = nullptr;
if (!FunctionScopes.empty())
LSI = dyn_cast_or_null<LambdaScopeInfo>(
FunctionScopes[FunctionScopesIndex]);
bool IsInScopeDeclarationContext =
!LSI || LSI->AfterParameterList || CurContext == LSI->CallOperator;
if (LSI && !LSI->AfterParameterList) {
// This allows capturing parameters from a default value which does not
// seems correct
if (isa<ParmVarDecl>(Var) && !Var->getDeclContext()->isFunctionOrMethod())
return true;
}
// If the variable is declared in the current context, there is no need to
// capture it.
if (IsInScopeDeclarationContext &&
FunctionScopesIndex == MaxFunctionScopesIndex && VarDC == DC)
return true;
// Only block literals, captured statements, and lambda expressions can
// capture; other scopes don't work.
DeclContext *ParentDC =
!IsInScopeDeclarationContext
? DC->getParent()
: getParentOfCapturingContextOrNull(DC, Var, ExprLoc,
BuildAndDiagnose, *this);
// We need to check for the parent *first* because, if we *have*
// private-captured a global variable, we need to recursively capture it in
// intermediate blocks, lambdas, etc.
if (!ParentDC) {
if (IsGlobal) {
FunctionScopesIndex = MaxFunctionScopesIndex - 1;
break;
}
return true;
}

As at that time LSI->AfterParameterList is true for the lambda scope(the inner-most FunctionScopes), so the ParentDC will be nullptr and the whole function will return at line 19814. This behavior seems to be changed by 3ed9e9e. After that commit inside CheckFunctionConstraint we need to rebuild lambda scope info(done by construct an instance of LambdaScopeForCallOperatorInstantiationRAII, it calls RebuildLambdaScopeInfo), and it will made LSI->AfterParameter become false:

// This function in calls in situation where the context of the call operator
// is not entered, so we set AfterParameterList to false, so that
// `tryCaptureVariable` finds explicit captures in the appropriate context.
LSI->AfterParameterList = false;

CC: @cor3ntin

Note: The above analysis may be completely wrong, as I've only recently started reading the clang source code.

@RungeCC
Copy link
Author

RungeCC commented Oct 26, 2023

I think this theory makes some sense, since I notice this:

constexpr auto ICE() { 
    constexpr auto b = 1;
    return [=](auto c) -> int
    requires requires { b + c; }
    {
        return 1;
    };
};

constexpr auto Ret = ICE()(1);

also triggers the same ICE(https://godbolt.org/z/cjc4arcTW).

HerrCai0907 added a commit that referenced this issue Jan 18, 2024
Expression in `RequiresExprBodyDecl` is resolved as constants and should not be captured.
Fixes: #69307, #76593.
HerrCai0907 added a commit that referenced this issue Jan 20, 2024
Expression in `RequiresExprBodyDecl` is resolved as constants and should not be captured.
Fixes: #69307, #76593.
@l1nxy
Copy link

l1nxy commented Apr 21, 2024

I will submit a pull request to attempt to fix this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++20 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: Done
5 participants