Skip to content

Constant Evaluation Assertion Failure with C++ Concepts #82849

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

Closed
yuxuanchen1997 opened this issue Feb 24, 2024 · 12 comments · Fixed by #83997
Closed

Constant Evaluation Assertion Failure with C++ Concepts #82849

yuxuanchen1997 opened this issue Feb 24, 2024 · 12 comments · Fixed by #83997
Labels
c++20 clang:frontend Language frontend issues, e.g. anything involving "Sema" concepts C++20 concepts confirmed Verified by a second party crash Prefer [crash-on-valid] or [crash-on-invalid]

Comments

@yuxuanchen1997
Copy link
Member

yuxuanchen1997 commented Feb 24, 2024

If a concept contains a lambda expression, and if the arguments provided to the concept template-id expression are not dependent, Sema runs into an assertion failure.

Consider the following program:

template <typename> 
concept C = requires {
  [] {};
};

template <typename>
void b() {
  C<int>;
}

The assertion failure is

clang++: ~/llvm-project/clang/lib/AST/ExprConstant.cpp:15739: bool clang::Expr::EvaluateAsConstantExpr(EvalResult &, const ASTContext &, ConstantExprKind) const: Assertion `!isValueDependent() && "Expression evaluator can't be called on a dependent expression."' 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: /home/ych/llvm-project/build/bin/clang++ -cc1 -std=c++20 crash.cpp
1.      crash.cpp:8:9: current parser token ';'
2.      crash.cpp:7:10: parsing function body 'b'
3.      crash.cpp:7:10: in compound statement ('{}')
 #0 0x000055643425386d llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) /home/ych/llvm-project/llvm/lib/Support/Unix/Signals.inc:723:11
 #1 0x0000556434253d5b PrintStackTraceSignalHandler(void*) /home/ych/llvm-project/llvm/lib/Support/Unix/Signals.inc:798:1
 #2 0x0000556434251dc6 llvm::sys::RunSignalHandlers() /home/ych/llvm-project/llvm/lib/Support/Signals.cpp:105:5
 #3 0x0000556434254515 SignalHandler(int) /home/ych/llvm-project/llvm/lib/Support/Unix/Signals.inc:413:1
 #4 0x00007f2777e54db0 __restore_rt (/lib64/libc.so.6+0x54db0)
 #5 0x00007f2777ea365c __pthread_kill_implementation (/lib64/libc.so.6+0xa365c)
 #6 0x00007f2777e54d06 gsignal (/lib64/libc.so.6+0x54d06)
 #7 0x00007f2777e287f3 abort (/lib64/libc.so.6+0x287f3)
 #8 0x00007f2777e2871b _nl_load_domain.cold (/lib64/libc.so.6+0x2871b)
 #9 0x00007f2777e4dca6 (/lib64/libc.so.6+0x4dca6)
#10 0x000055643abfc801 clang::Expr::EvaluateAsConstantExpr(clang::Expr::EvalResult&, clang::ASTContext const&, clang::Expr::ConstantExprKind) const /home/ych/llvm-project/clang/lib/AST/ExprConstant.cpp:0:3
#11 0x0000556438f1a7a3 clang::ActionResult<clang::Expr*, true> calculateConstraintSatisfaction<calculateConstraintSatisfaction(clang::Sema&, clang::NamedDecl const*, clang::SourceLocation, clang::MultiLevelTemplateArgumentList const&, clang::Expr const*, clang::ConstraintSatisfaction&)::$_0>(clang::Sema&, clang::Expr const*, clang::ConstraintSatisfaction&, calculateConstraintSatisfaction(clang::Sema&, clang::NamedDecl const*, clang::SourceLocation, clang::MultiLevelTemplateArgumentList const&, clang::Expr const*, clang::ConstraintSatisfaction&)::$_0&&) /home/ych/llvm-project/clang/lib/Sema/SemaConcept.cpp:289:71
#12 0x0000556438f1a26c calculateConstraintSatisfaction(clang::Sema&, clang::NamedDecl const*, clang::SourceLocation, clang::MultiLevelTemplateArgumentList const&, clang::Expr const*, clang::ConstraintSatisfaction&) /home/ych/llvm-project/clang/lib/Sema/SemaConcept.cpp:339:10
#13 0x0000556438f13926 CheckConstraintSatisfaction(clang::Sema&, clang::NamedDecl const*, llvm::ArrayRef<clang::Expr const*>, llvm::SmallVectorImpl<clang::Expr*>&, clang::MultiLevelTemplateArgumentList const&, clang::SourceRange, clang::ConstraintSatisfaction&) /home/ych/llvm-project/clang/lib/Sema/SemaConcept.cpp:454:22
#14 0x0000556438f13623 clang::Sema::CheckConstraintSatisfaction(clang::NamedDecl const*, llvm::ArrayRef<clang::Expr const*>, llvm::SmallVectorImpl<clang::Expr*>&, clang::MultiLevelTemplateArgumentList const&, clang::SourceRange, clang::ConstraintSatisfaction&) /home/ych/llvm-project/clang/lib/Sema/SemaConcept.cpp:509:7
#15 0x0000556438f80ac4 clang::Sema::CheckConstraintSatisfaction(clang::NamedDecl const*, llvm::ArrayRef<clang::Expr const*>, clang::MultiLevelTemplateArgumentList const&, clang::SourceRange, clang::ConstraintSatisfaction&) /home/ych/llvm-project/clang/include/clang/Sema/Sema.h:7680:12
#16 0x0000556439dbc13b clang::Sema::CheckConceptTemplateId(clang::CXXScopeSpec const&, clang::SourceLocation, clang::DeclarationNameInfo const&, clang::NamedDecl*, clang::ConceptDecl*, clang::TemplateArgumentListInfo const*) /home/ych/llvm-project/clang/lib/Sema/SemaTemplate.cpp:5024:7
#17 0x0000556439dbc5b8 clang::Sema::BuildTemplateIdExpr(clang::CXXScopeSpec const&, clang::SourceLocation, clang::LookupResult&, bool, clang::TemplateArgumentListInfo const*) /home/ych/llvm-project/clang/lib/Sema/SemaTemplate.cpp:5077:12
#18 0x000055643950be62 clang::Sema::ActOnIdExpression(clang::Scope*, clang::CXXScopeSpec&, clang::SourceLocation, clang::UnqualifiedId&, bool, bool, clang::CorrectionCandidateCallback*, bool, clang::Token*) /home/ych/llvm-project/clang/lib/Sema/SemaExpr.cpp:2927:12
#19 0x0000556438accc2b clang::Parser::tryParseCXXIdExpression(clang::CXXScopeSpec&, bool, clang::Token&) /home/ych/llvm-project/clang/lib/Parse/ParseExprCXX.cpp:641:17
#20 0x0000556438ace58a clang::Parser::ParseCXXIdExpression(bool) /home/ych/llvm-project/clang/lib/Parse/ParseExprCXX.cpp:734:7
#21 0x0000556438ab8b50 clang::Parser::ParseCastExpression(clang::Parser::CastParseKind, bool, bool&, clang::Parser::TypeCastState, bool, bool*) /home/ych/llvm-project/clang/lib/Parse/ParseExpr.cpp:1687:11
#22 0x0000556438ab07c9 clang::Parser::ParseCastExpression(clang::Parser::CastParseKind, bool, clang::Parser::TypeCastState, bool, bool*) /home/ych/llvm-project/clang/lib/Parse/ParseExpr.cpp:693:20
#23 0x0000556438aaecb8 clang::Parser::ParseAssignmentExpression(clang::Parser::TypeCastState) /home/ych/llvm-project/clang/lib/Parse/ParseExpr.cpp:176:20
#24 0x0000556438aaeb6f clang::Parser::ParseExpression(clang::Parser::TypeCastState) /home/ych/llvm-project/clang/lib/Parse/ParseExpr.cpp:127:18
#25 0x0000556438b472c8 clang::Parser::ParseExprStatement(clang::Parser::ParsedStmtContext) /home/ych/llvm-project/clang/lib/Parse/ParseStmt.cpp:539:19
#26 0x0000556438b45678 clang::Parser::ParseStatementOrDeclarationAfterAttributes(llvm::SmallVector<clang::Stmt*, 32u>&, clang::Parser::ParsedStmtContext, clang::SourceLocation*, clang::ParsedAttributes&, clang::ParsedAttributes&) /home/ych/llvm-project/clang/lib/Parse/ParseStmt.cpp:277:14
#27 0x0000556438b44d4b clang::Parser::ParseStatementOrDeclaration(llvm::SmallVector<clang::Stmt*, 32u>&, clang::Parser::ParsedStmtContext, clang::SourceLocation*) /home/ych/llvm-project/clang/lib/Parse/ParseStmt.cpp:118:20
#28 0x0000556438b4dec2 clang::Parser::ParseCompoundStatementBody(bool) /home/ych/llvm-project/clang/lib/Parse/ParseStmt.cpp:1236:11
#29 0x0000556438b4f5b1 clang::Parser::ParseFunctionStatementBody(clang::Decl*, clang::Parser::ParseScope&) /home/ych/llvm-project/clang/lib/Parse/ParseStmt.cpp:2514:21
#30 0x0000556438a77d34 clang::Parser::ParseFunctionDefinition(clang::ParsingDeclarator&, clang::Parser::ParsedTemplateInfo const&, clang::Parser::LateParsedAttrList*) /home/ych/llvm-project/clang/lib/Parse/Parser.cpp:1517:3
#31 0x0000556438b1e41d clang::Parser::ParseDeclGroup(clang::ParsingDeclSpec&, clang::DeclaratorContext, clang::ParsedAttributes&, clang::Parser::ParsedTemplateInfo&, clang::SourceLocation*, clang::Parser::ForRangeInit*) /home/ych/llvm-project/clang/lib/Parse/ParseDecl.cpp:2320:21
#32 0x0000556438b66c33 clang::Parser::ParseDeclarationAfterTemplate(clang::DeclaratorContext, clang::Parser::ParsedTemplateInfo&, clang::ParsingDeclRAIIObject&, clang::SourceLocation&, clang::ParsedAttributes&, clang::AccessSpecifier) /home/ych/llvm-project/clang/lib/Parse/ParseTemplate.cpp:258:10
#33 0x0000556438b65da8 clang::Parser::ParseTemplateDeclarationOrSpecialization(clang::DeclaratorContext, clang::SourceLocation&, clang::ParsedAttributes&, clang::AccessSpecifier) /home/ych/llvm-project/clang/lib/Parse/ParseTemplate.cpp:174:10
#34 0x0000556438b657a0 clang::Parser::ParseDeclarationStartingWithTemplate(clang::DeclaratorContext, clang::SourceLocation&, clang::ParsedAttributes&) /home/ych/llvm-project/clang/lib/Parse/ParseTemplate.cpp:50:10
#35 0x0000556438b1ccbe clang::Parser::ParseDeclaration(clang::DeclaratorContext, clang::SourceLocation&, clang::ParsedAttributes&, clang::ParsedAttributes&, clang::SourceLocation*) /home/ych/llvm-project/clang/lib/Parse/ParseDecl.cpp:1919:12
#36 0x0000556438a7535e clang::Parser::ParseExternalDeclaration(clang::ParsedAttributes&, clang::ParsedAttributes&, clang::ParsingDeclSpec*) /home/ych/llvm-project/clang/lib/Parse/Parser.cpp:986:14
#37 0x0000556438a7372c clang::Parser::ParseTopLevelDecl(clang::OpaquePtr<clang::DeclGroupRef>&, clang::Sema::ModuleImportState&) /home/ych/llvm-project/clang/lib/Parse/Parser.cpp:760:12
#38 0x0000556438a6e4fa clang::ParseAST(clang::Sema&, bool, bool) /home/ych/llvm-project/clang/lib/Parse/ParseAST.cpp:163:16
#39 0x000055643564e06b clang::ASTFrontendAction::ExecuteAction() /home/ych/llvm-project/clang/lib/Frontend/FrontendAction.cpp:1185:1
#40 0x000055643564da8c clang::FrontendAction::Execute() /home/ych/llvm-project/clang/lib/Frontend/FrontendAction.cpp:1073:7
#41 0x000055643556daa7 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) /home/ych/llvm-project/clang/lib/Frontend/CompilerInstance.cpp:1057:23
#42 0x000055643581eac1 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) /home/ych/llvm-project/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp:272:8
#43 0x0000556432446a7b cc1_main(llvm::ArrayRef<char const*>, char const*, void*) /home/ych/llvm-project/clang/tools/driver/cc1_main.cpp:232:13
#44 0x0000556432437002 ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) /home/ych/llvm-project/clang/tools/driver/driver.cpp:365:5
#45 0x0000556432435d5b clang_main(int, char**, llvm::ToolContext const&) /home/ych/llvm-project/clang/tools/driver/driver.cpp:406:5
#46 0x000055643246b3b5 main /home/ych/llvm-project/build/tools/clang/tools/driver/clang-driver.cpp:17:3
#47 0x00007f2777e3feb0 __libc_start_call_main (/lib64/libc.so.6+0x3feb0)
#48 0x00007f2777e3ff60 __libc_start_main@GLIBC_2.2.5 (/lib64/libc.so.6+0x3ff60)
#49 0x00005564324357e5 _start (/home/ych/llvm-project/build/bin/clang+++0x57017e5)
fish: Job 1, '~/llvm-project/build/bin/clang+…' terminated by signal SIGABRT (Abort)

ExprConstant complains that this lambda after instantiation is still value dependent. getTypeDeclType on the instantiated lambda shows that the type for the lambda CXXRecordDecl is dependent. The reason being the parent DeclContext was dependent, which is also true in this case as we aren't instantiating function template b here.

It's worth noting that with an assertion-disabled clang++, this program compiles successfully and, as far as I can tell, correctly.

I can think of a few possible fixes:

  • Why does a template-id expression here causes the constraint to be checked if the function template b is not being instantiated? Can the fix just be that defer checking the constraint to performing pending instantiations? In Sema::CheckConceptTemplateId, we eagerly calculate the constraint satisfaction if the arguments to the concept template aren't dependent.
  • Why does DeclContext look at the parent context to tell if it's instantiated? This causes any AST nodes created with template instantiation we do during concept template constraints checking to be considered dependent.
  • Defer checking value dependency at ExprConstant evaluation. Since in our case, no actual dependent values can be reached, which explains why the assertion-free build successfully compiles this code.

Even though a Release build is not affected and won't block any production users (with doubt), I think this problem is still worth solving. I would like to consult upstream which approach I should take.

@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 new issue labels Feb 24, 2024
@llvmbot
Copy link
Member

llvmbot commented Feb 24, 2024

@llvm/issue-subscribers-clang-frontend

Author: Yuxuan Chen (yuxuanchen1997)

If a concept contains a lambda expression, the template-id expression
template &lt;typename&gt; 
concept C = requires {
  [] {};
};

template &lt;typename&gt;
void b() {
  C&lt;int&gt;;
}

The assertion failure is

clang++: ~/llvm-project/clang/lib/AST/ExprConstant.cpp:15739: bool clang::Expr::EvaluateAsConstantExpr(EvalResult &amp;, const ASTContext &amp;, ConstantExprKind) const: Assertion `!isValueDependent() &amp;&amp; "Expression evaluator can't be called on a dependent expression."' 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: /home/ych/llvm-project/build/bin/clang++ -cc1 -std=c++20 crash.cpp
1.      crash.cpp:8:9: current parser token ';'
2.      crash.cpp:7:10: parsing function body 'b'
3.      crash.cpp:7:10: in compound statement ('{}')
 #<!-- -->0 0x000055643425386d llvm::sys::PrintStackTrace(llvm::raw_ostream&amp;, int) /home/ych/llvm-project/llvm/lib/Support/Unix/Signals.inc:723:11
 #<!-- -->1 0x0000556434253d5b PrintStackTraceSignalHandler(void*) /home/ych/llvm-project/llvm/lib/Support/Unix/Signals.inc:798:1
 #<!-- -->2 0x0000556434251dc6 llvm::sys::RunSignalHandlers() /home/ych/llvm-project/llvm/lib/Support/Signals.cpp:105:5
 #<!-- -->3 0x0000556434254515 SignalHandler(int) /home/ych/llvm-project/llvm/lib/Support/Unix/Signals.inc:413:1
 #<!-- -->4 0x00007f2777e54db0 __restore_rt (/lib64/libc.so.6+0x54db0)
 #<!-- -->5 0x00007f2777ea365c __pthread_kill_implementation (/lib64/libc.so.6+0xa365c)
 #<!-- -->6 0x00007f2777e54d06 gsignal (/lib64/libc.so.6+0x54d06)
 #<!-- -->7 0x00007f2777e287f3 abort (/lib64/libc.so.6+0x287f3)
 #<!-- -->8 0x00007f2777e2871b _nl_load_domain.cold (/lib64/libc.so.6+0x2871b)
 #<!-- -->9 0x00007f2777e4dca6 (/lib64/libc.so.6+0x4dca6)
#<!-- -->10 0x000055643abfc801 clang::Expr::EvaluateAsConstantExpr(clang::Expr::EvalResult&amp;, clang::ASTContext const&amp;, clang::Expr::ConstantExprKind) const /home/ych/llvm-project/clang/lib/AST/ExprConstant.cpp:0:3
#<!-- -->11 0x0000556438f1a7a3 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;)::$_0&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;)::$_0&amp;&amp;) /home/ych/llvm-project/clang/lib/Sema/SemaConcept.cpp:289:71
#<!-- -->12 0x0000556438f1a26c calculateConstraintSatisfaction(clang::Sema&amp;, clang::NamedDecl const*, clang::SourceLocation, clang::MultiLevelTemplateArgumentList const&amp;, clang::Expr const*, clang::ConstraintSatisfaction&amp;) /home/ych/llvm-project/clang/lib/Sema/SemaConcept.cpp:339:10
#<!-- -->13 0x0000556438f13926 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;) /home/ych/llvm-project/clang/lib/Sema/SemaConcept.cpp:454:22
#<!-- -->14 0x0000556438f13623 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;) /home/ych/llvm-project/clang/lib/Sema/SemaConcept.cpp:509:7
#<!-- -->15 0x0000556438f80ac4 clang::Sema::CheckConstraintSatisfaction(clang::NamedDecl const*, llvm::ArrayRef&lt;clang::Expr const*&gt;, clang::MultiLevelTemplateArgumentList const&amp;, clang::SourceRange, clang::ConstraintSatisfaction&amp;) /home/ych/llvm-project/clang/include/clang/Sema/Sema.h:7680:12
#<!-- -->16 0x0000556439dbc13b clang::Sema::CheckConceptTemplateId(clang::CXXScopeSpec const&amp;, clang::SourceLocation, clang::DeclarationNameInfo const&amp;, clang::NamedDecl*, clang::ConceptDecl*, clang::TemplateArgumentListInfo const*) /home/ych/llvm-project/clang/lib/Sema/SemaTemplate.cpp:5024:7
#<!-- -->17 0x0000556439dbc5b8 clang::Sema::BuildTemplateIdExpr(clang::CXXScopeSpec const&amp;, clang::SourceLocation, clang::LookupResult&amp;, bool, clang::TemplateArgumentListInfo const*) /home/ych/llvm-project/clang/lib/Sema/SemaTemplate.cpp:5077:12
#<!-- -->18 0x000055643950be62 clang::Sema::ActOnIdExpression(clang::Scope*, clang::CXXScopeSpec&amp;, clang::SourceLocation, clang::UnqualifiedId&amp;, bool, bool, clang::CorrectionCandidateCallback*, bool, clang::Token*) /home/ych/llvm-project/clang/lib/Sema/SemaExpr.cpp:2927:12
#<!-- -->19 0x0000556438accc2b clang::Parser::tryParseCXXIdExpression(clang::CXXScopeSpec&amp;, bool, clang::Token&amp;) /home/ych/llvm-project/clang/lib/Parse/ParseExprCXX.cpp:641:17
#<!-- -->20 0x0000556438ace58a clang::Parser::ParseCXXIdExpression(bool) /home/ych/llvm-project/clang/lib/Parse/ParseExprCXX.cpp:734:7
#<!-- -->21 0x0000556438ab8b50 clang::Parser::ParseCastExpression(clang::Parser::CastParseKind, bool, bool&amp;, clang::Parser::TypeCastState, bool, bool*) /home/ych/llvm-project/clang/lib/Parse/ParseExpr.cpp:1687:11
#<!-- -->22 0x0000556438ab07c9 clang::Parser::ParseCastExpression(clang::Parser::CastParseKind, bool, clang::Parser::TypeCastState, bool, bool*) /home/ych/llvm-project/clang/lib/Parse/ParseExpr.cpp:693:20
#<!-- -->23 0x0000556438aaecb8 clang::Parser::ParseAssignmentExpression(clang::Parser::TypeCastState) /home/ych/llvm-project/clang/lib/Parse/ParseExpr.cpp:176:20
#<!-- -->24 0x0000556438aaeb6f clang::Parser::ParseExpression(clang::Parser::TypeCastState) /home/ych/llvm-project/clang/lib/Parse/ParseExpr.cpp:127:18
#<!-- -->25 0x0000556438b472c8 clang::Parser::ParseExprStatement(clang::Parser::ParsedStmtContext) /home/ych/llvm-project/clang/lib/Parse/ParseStmt.cpp:539:19
#<!-- -->26 0x0000556438b45678 clang::Parser::ParseStatementOrDeclarationAfterAttributes(llvm::SmallVector&lt;clang::Stmt*, 32u&gt;&amp;, clang::Parser::ParsedStmtContext, clang::SourceLocation*, clang::ParsedAttributes&amp;, clang::ParsedAttributes&amp;) /home/ych/llvm-project/clang/lib/Parse/ParseStmt.cpp:277:14
#<!-- -->27 0x0000556438b44d4b clang::Parser::ParseStatementOrDeclaration(llvm::SmallVector&lt;clang::Stmt*, 32u&gt;&amp;, clang::Parser::ParsedStmtContext, clang::SourceLocation*) /home/ych/llvm-project/clang/lib/Parse/ParseStmt.cpp:118:20
#<!-- -->28 0x0000556438b4dec2 clang::Parser::ParseCompoundStatementBody(bool) /home/ych/llvm-project/clang/lib/Parse/ParseStmt.cpp:1236:11
#<!-- -->29 0x0000556438b4f5b1 clang::Parser::ParseFunctionStatementBody(clang::Decl*, clang::Parser::ParseScope&amp;) /home/ych/llvm-project/clang/lib/Parse/ParseStmt.cpp:2514:21
#<!-- -->30 0x0000556438a77d34 clang::Parser::ParseFunctionDefinition(clang::ParsingDeclarator&amp;, clang::Parser::ParsedTemplateInfo const&amp;, clang::Parser::LateParsedAttrList*) /home/ych/llvm-project/clang/lib/Parse/Parser.cpp:1517:3
#<!-- -->31 0x0000556438b1e41d clang::Parser::ParseDeclGroup(clang::ParsingDeclSpec&amp;, clang::DeclaratorContext, clang::ParsedAttributes&amp;, clang::Parser::ParsedTemplateInfo&amp;, clang::SourceLocation*, clang::Parser::ForRangeInit*) /home/ych/llvm-project/clang/lib/Parse/ParseDecl.cpp:2320:21
#<!-- -->32 0x0000556438b66c33 clang::Parser::ParseDeclarationAfterTemplate(clang::DeclaratorContext, clang::Parser::ParsedTemplateInfo&amp;, clang::ParsingDeclRAIIObject&amp;, clang::SourceLocation&amp;, clang::ParsedAttributes&amp;, clang::AccessSpecifier) /home/ych/llvm-project/clang/lib/Parse/ParseTemplate.cpp:258:10
#<!-- -->33 0x0000556438b65da8 clang::Parser::ParseTemplateDeclarationOrSpecialization(clang::DeclaratorContext, clang::SourceLocation&amp;, clang::ParsedAttributes&amp;, clang::AccessSpecifier) /home/ych/llvm-project/clang/lib/Parse/ParseTemplate.cpp:174:10
#<!-- -->34 0x0000556438b657a0 clang::Parser::ParseDeclarationStartingWithTemplate(clang::DeclaratorContext, clang::SourceLocation&amp;, clang::ParsedAttributes&amp;) /home/ych/llvm-project/clang/lib/Parse/ParseTemplate.cpp:50:10
#<!-- -->35 0x0000556438b1ccbe clang::Parser::ParseDeclaration(clang::DeclaratorContext, clang::SourceLocation&amp;, clang::ParsedAttributes&amp;, clang::ParsedAttributes&amp;, clang::SourceLocation*) /home/ych/llvm-project/clang/lib/Parse/ParseDecl.cpp:1919:12
#<!-- -->36 0x0000556438a7535e clang::Parser::ParseExternalDeclaration(clang::ParsedAttributes&amp;, clang::ParsedAttributes&amp;, clang::ParsingDeclSpec*) /home/ych/llvm-project/clang/lib/Parse/Parser.cpp:986:14
#<!-- -->37 0x0000556438a7372c clang::Parser::ParseTopLevelDecl(clang::OpaquePtr&lt;clang::DeclGroupRef&gt;&amp;, clang::Sema::ModuleImportState&amp;) /home/ych/llvm-project/clang/lib/Parse/Parser.cpp:760:12
#<!-- -->38 0x0000556438a6e4fa clang::ParseAST(clang::Sema&amp;, bool, bool) /home/ych/llvm-project/clang/lib/Parse/ParseAST.cpp:163:16
#<!-- -->39 0x000055643564e06b clang::ASTFrontendAction::ExecuteAction() /home/ych/llvm-project/clang/lib/Frontend/FrontendAction.cpp:1185:1
#<!-- -->40 0x000055643564da8c clang::FrontendAction::Execute() /home/ych/llvm-project/clang/lib/Frontend/FrontendAction.cpp:1073:7
#<!-- -->41 0x000055643556daa7 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&amp;) /home/ych/llvm-project/clang/lib/Frontend/CompilerInstance.cpp:1057:23
#<!-- -->42 0x000055643581eac1 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) /home/ych/llvm-project/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp:272:8
#<!-- -->43 0x0000556432446a7b cc1_main(llvm::ArrayRef&lt;char const*&gt;, char const*, void*) /home/ych/llvm-project/clang/tools/driver/cc1_main.cpp:232:13
#<!-- -->44 0x0000556432437002 ExecuteCC1Tool(llvm::SmallVectorImpl&lt;char const*&gt;&amp;, llvm::ToolContext const&amp;) /home/ych/llvm-project/clang/tools/driver/driver.cpp:365:5
#<!-- -->45 0x0000556432435d5b clang_main(int, char**, llvm::ToolContext const&amp;) /home/ych/llvm-project/clang/tools/driver/driver.cpp:406:5
#<!-- -->46 0x000055643246b3b5 main /home/ych/llvm-project/build/tools/clang/tools/driver/clang-driver.cpp:17:3
#<!-- -->47 0x00007f2777e3feb0 __libc_start_call_main (/lib64/libc.so.6+0x3feb0)
#<!-- -->48 0x00007f2777e3ff60 __libc_start_main@<!-- -->GLIBC_2.2.5 (/lib64/libc.so.6+0x3ff60)
#<!-- -->49 0x00005564324357e5 _start (/home/ych/llvm-project/build/bin/clang+++0x57017e5)
fish: Job 1, '~/llvm-project/build/bin/clang+…' terminated by signal SIGABRT (Abort)

ExprConstant complains that this lambda after instantiation is still value dependent. getTypeDeclType on the instantiated lambda shows that the type for the lambda CXXRecordDecl is dependent. The reason being the parent DeclContext was dependent, which is also true in this case as we aren't instantiating function template b here.

It's worth noting that with an assertion-disabled clang++, this program compiles successfully and, as far as I can tell, correctly.

I can think of a few possible fixes:

  • Why does a template-id expression here causes the constraint to be checked if the function template b is not being instantiated? Can the fix just be that defer checking the constraint to performing pending instantiations? In Sema::CheckConceptTemplateId, we eagerly calculate the constraint satisfaction if the arguments to the concept template aren't dependent.
  • Why does DeclContext look at the parent context to tell if it's instantiated? This causes any AST nodes created with template instantiation we do during concept template constraints checking to be considered dependent.
  • Defer checking value dependency at ExprConstant evaluation. Since in our case, no actual dependent values can be reached, which explains why the assertion-free build successfully compiles this code.

Even though a Release build is not affected and won't block any production users (with doubt), I think this problem is still worth solving. I would like to consult upstream which approach I should take.

@llvmbot
Copy link
Member

llvmbot commented Feb 24, 2024

@llvm/issue-subscribers-c-20

Author: Yuxuan Chen (yuxuanchen1997)

If a concept contains a lambda expression, the template-id expression
template &lt;typename&gt; 
concept C = requires {
  [] {};
};

template &lt;typename&gt;
void b() {
  C&lt;int&gt;;
}

The assertion failure is

clang++: ~/llvm-project/clang/lib/AST/ExprConstant.cpp:15739: bool clang::Expr::EvaluateAsConstantExpr(EvalResult &amp;, const ASTContext &amp;, ConstantExprKind) const: Assertion `!isValueDependent() &amp;&amp; "Expression evaluator can't be called on a dependent expression."' 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: /home/ych/llvm-project/build/bin/clang++ -cc1 -std=c++20 crash.cpp
1.      crash.cpp:8:9: current parser token ';'
2.      crash.cpp:7:10: parsing function body 'b'
3.      crash.cpp:7:10: in compound statement ('{}')
 #<!-- -->0 0x000055643425386d llvm::sys::PrintStackTrace(llvm::raw_ostream&amp;, int) /home/ych/llvm-project/llvm/lib/Support/Unix/Signals.inc:723:11
 #<!-- -->1 0x0000556434253d5b PrintStackTraceSignalHandler(void*) /home/ych/llvm-project/llvm/lib/Support/Unix/Signals.inc:798:1
 #<!-- -->2 0x0000556434251dc6 llvm::sys::RunSignalHandlers() /home/ych/llvm-project/llvm/lib/Support/Signals.cpp:105:5
 #<!-- -->3 0x0000556434254515 SignalHandler(int) /home/ych/llvm-project/llvm/lib/Support/Unix/Signals.inc:413:1
 #<!-- -->4 0x00007f2777e54db0 __restore_rt (/lib64/libc.so.6+0x54db0)
 #<!-- -->5 0x00007f2777ea365c __pthread_kill_implementation (/lib64/libc.so.6+0xa365c)
 #<!-- -->6 0x00007f2777e54d06 gsignal (/lib64/libc.so.6+0x54d06)
 #<!-- -->7 0x00007f2777e287f3 abort (/lib64/libc.so.6+0x287f3)
 #<!-- -->8 0x00007f2777e2871b _nl_load_domain.cold (/lib64/libc.so.6+0x2871b)
 #<!-- -->9 0x00007f2777e4dca6 (/lib64/libc.so.6+0x4dca6)
#<!-- -->10 0x000055643abfc801 clang::Expr::EvaluateAsConstantExpr(clang::Expr::EvalResult&amp;, clang::ASTContext const&amp;, clang::Expr::ConstantExprKind) const /home/ych/llvm-project/clang/lib/AST/ExprConstant.cpp:0:3
#<!-- -->11 0x0000556438f1a7a3 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;)::$_0&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;)::$_0&amp;&amp;) /home/ych/llvm-project/clang/lib/Sema/SemaConcept.cpp:289:71
#<!-- -->12 0x0000556438f1a26c calculateConstraintSatisfaction(clang::Sema&amp;, clang::NamedDecl const*, clang::SourceLocation, clang::MultiLevelTemplateArgumentList const&amp;, clang::Expr const*, clang::ConstraintSatisfaction&amp;) /home/ych/llvm-project/clang/lib/Sema/SemaConcept.cpp:339:10
#<!-- -->13 0x0000556438f13926 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;) /home/ych/llvm-project/clang/lib/Sema/SemaConcept.cpp:454:22
#<!-- -->14 0x0000556438f13623 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;) /home/ych/llvm-project/clang/lib/Sema/SemaConcept.cpp:509:7
#<!-- -->15 0x0000556438f80ac4 clang::Sema::CheckConstraintSatisfaction(clang::NamedDecl const*, llvm::ArrayRef&lt;clang::Expr const*&gt;, clang::MultiLevelTemplateArgumentList const&amp;, clang::SourceRange, clang::ConstraintSatisfaction&amp;) /home/ych/llvm-project/clang/include/clang/Sema/Sema.h:7680:12
#<!-- -->16 0x0000556439dbc13b clang::Sema::CheckConceptTemplateId(clang::CXXScopeSpec const&amp;, clang::SourceLocation, clang::DeclarationNameInfo const&amp;, clang::NamedDecl*, clang::ConceptDecl*, clang::TemplateArgumentListInfo const*) /home/ych/llvm-project/clang/lib/Sema/SemaTemplate.cpp:5024:7
#<!-- -->17 0x0000556439dbc5b8 clang::Sema::BuildTemplateIdExpr(clang::CXXScopeSpec const&amp;, clang::SourceLocation, clang::LookupResult&amp;, bool, clang::TemplateArgumentListInfo const*) /home/ych/llvm-project/clang/lib/Sema/SemaTemplate.cpp:5077:12
#<!-- -->18 0x000055643950be62 clang::Sema::ActOnIdExpression(clang::Scope*, clang::CXXScopeSpec&amp;, clang::SourceLocation, clang::UnqualifiedId&amp;, bool, bool, clang::CorrectionCandidateCallback*, bool, clang::Token*) /home/ych/llvm-project/clang/lib/Sema/SemaExpr.cpp:2927:12
#<!-- -->19 0x0000556438accc2b clang::Parser::tryParseCXXIdExpression(clang::CXXScopeSpec&amp;, bool, clang::Token&amp;) /home/ych/llvm-project/clang/lib/Parse/ParseExprCXX.cpp:641:17
#<!-- -->20 0x0000556438ace58a clang::Parser::ParseCXXIdExpression(bool) /home/ych/llvm-project/clang/lib/Parse/ParseExprCXX.cpp:734:7
#<!-- -->21 0x0000556438ab8b50 clang::Parser::ParseCastExpression(clang::Parser::CastParseKind, bool, bool&amp;, clang::Parser::TypeCastState, bool, bool*) /home/ych/llvm-project/clang/lib/Parse/ParseExpr.cpp:1687:11
#<!-- -->22 0x0000556438ab07c9 clang::Parser::ParseCastExpression(clang::Parser::CastParseKind, bool, clang::Parser::TypeCastState, bool, bool*) /home/ych/llvm-project/clang/lib/Parse/ParseExpr.cpp:693:20
#<!-- -->23 0x0000556438aaecb8 clang::Parser::ParseAssignmentExpression(clang::Parser::TypeCastState) /home/ych/llvm-project/clang/lib/Parse/ParseExpr.cpp:176:20
#<!-- -->24 0x0000556438aaeb6f clang::Parser::ParseExpression(clang::Parser::TypeCastState) /home/ych/llvm-project/clang/lib/Parse/ParseExpr.cpp:127:18
#<!-- -->25 0x0000556438b472c8 clang::Parser::ParseExprStatement(clang::Parser::ParsedStmtContext) /home/ych/llvm-project/clang/lib/Parse/ParseStmt.cpp:539:19
#<!-- -->26 0x0000556438b45678 clang::Parser::ParseStatementOrDeclarationAfterAttributes(llvm::SmallVector&lt;clang::Stmt*, 32u&gt;&amp;, clang::Parser::ParsedStmtContext, clang::SourceLocation*, clang::ParsedAttributes&amp;, clang::ParsedAttributes&amp;) /home/ych/llvm-project/clang/lib/Parse/ParseStmt.cpp:277:14
#<!-- -->27 0x0000556438b44d4b clang::Parser::ParseStatementOrDeclaration(llvm::SmallVector&lt;clang::Stmt*, 32u&gt;&amp;, clang::Parser::ParsedStmtContext, clang::SourceLocation*) /home/ych/llvm-project/clang/lib/Parse/ParseStmt.cpp:118:20
#<!-- -->28 0x0000556438b4dec2 clang::Parser::ParseCompoundStatementBody(bool) /home/ych/llvm-project/clang/lib/Parse/ParseStmt.cpp:1236:11
#<!-- -->29 0x0000556438b4f5b1 clang::Parser::ParseFunctionStatementBody(clang::Decl*, clang::Parser::ParseScope&amp;) /home/ych/llvm-project/clang/lib/Parse/ParseStmt.cpp:2514:21
#<!-- -->30 0x0000556438a77d34 clang::Parser::ParseFunctionDefinition(clang::ParsingDeclarator&amp;, clang::Parser::ParsedTemplateInfo const&amp;, clang::Parser::LateParsedAttrList*) /home/ych/llvm-project/clang/lib/Parse/Parser.cpp:1517:3
#<!-- -->31 0x0000556438b1e41d clang::Parser::ParseDeclGroup(clang::ParsingDeclSpec&amp;, clang::DeclaratorContext, clang::ParsedAttributes&amp;, clang::Parser::ParsedTemplateInfo&amp;, clang::SourceLocation*, clang::Parser::ForRangeInit*) /home/ych/llvm-project/clang/lib/Parse/ParseDecl.cpp:2320:21
#<!-- -->32 0x0000556438b66c33 clang::Parser::ParseDeclarationAfterTemplate(clang::DeclaratorContext, clang::Parser::ParsedTemplateInfo&amp;, clang::ParsingDeclRAIIObject&amp;, clang::SourceLocation&amp;, clang::ParsedAttributes&amp;, clang::AccessSpecifier) /home/ych/llvm-project/clang/lib/Parse/ParseTemplate.cpp:258:10
#<!-- -->33 0x0000556438b65da8 clang::Parser::ParseTemplateDeclarationOrSpecialization(clang::DeclaratorContext, clang::SourceLocation&amp;, clang::ParsedAttributes&amp;, clang::AccessSpecifier) /home/ych/llvm-project/clang/lib/Parse/ParseTemplate.cpp:174:10
#<!-- -->34 0x0000556438b657a0 clang::Parser::ParseDeclarationStartingWithTemplate(clang::DeclaratorContext, clang::SourceLocation&amp;, clang::ParsedAttributes&amp;) /home/ych/llvm-project/clang/lib/Parse/ParseTemplate.cpp:50:10
#<!-- -->35 0x0000556438b1ccbe clang::Parser::ParseDeclaration(clang::DeclaratorContext, clang::SourceLocation&amp;, clang::ParsedAttributes&amp;, clang::ParsedAttributes&amp;, clang::SourceLocation*) /home/ych/llvm-project/clang/lib/Parse/ParseDecl.cpp:1919:12
#<!-- -->36 0x0000556438a7535e clang::Parser::ParseExternalDeclaration(clang::ParsedAttributes&amp;, clang::ParsedAttributes&amp;, clang::ParsingDeclSpec*) /home/ych/llvm-project/clang/lib/Parse/Parser.cpp:986:14
#<!-- -->37 0x0000556438a7372c clang::Parser::ParseTopLevelDecl(clang::OpaquePtr&lt;clang::DeclGroupRef&gt;&amp;, clang::Sema::ModuleImportState&amp;) /home/ych/llvm-project/clang/lib/Parse/Parser.cpp:760:12
#<!-- -->38 0x0000556438a6e4fa clang::ParseAST(clang::Sema&amp;, bool, bool) /home/ych/llvm-project/clang/lib/Parse/ParseAST.cpp:163:16
#<!-- -->39 0x000055643564e06b clang::ASTFrontendAction::ExecuteAction() /home/ych/llvm-project/clang/lib/Frontend/FrontendAction.cpp:1185:1
#<!-- -->40 0x000055643564da8c clang::FrontendAction::Execute() /home/ych/llvm-project/clang/lib/Frontend/FrontendAction.cpp:1073:7
#<!-- -->41 0x000055643556daa7 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&amp;) /home/ych/llvm-project/clang/lib/Frontend/CompilerInstance.cpp:1057:23
#<!-- -->42 0x000055643581eac1 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) /home/ych/llvm-project/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp:272:8
#<!-- -->43 0x0000556432446a7b cc1_main(llvm::ArrayRef&lt;char const*&gt;, char const*, void*) /home/ych/llvm-project/clang/tools/driver/cc1_main.cpp:232:13
#<!-- -->44 0x0000556432437002 ExecuteCC1Tool(llvm::SmallVectorImpl&lt;char const*&gt;&amp;, llvm::ToolContext const&amp;) /home/ych/llvm-project/clang/tools/driver/driver.cpp:365:5
#<!-- -->45 0x0000556432435d5b clang_main(int, char**, llvm::ToolContext const&amp;) /home/ych/llvm-project/clang/tools/driver/driver.cpp:406:5
#<!-- -->46 0x000055643246b3b5 main /home/ych/llvm-project/build/tools/clang/tools/driver/clang-driver.cpp:17:3
#<!-- -->47 0x00007f2777e3feb0 __libc_start_call_main (/lib64/libc.so.6+0x3feb0)
#<!-- -->48 0x00007f2777e3ff60 __libc_start_main@<!-- -->GLIBC_2.2.5 (/lib64/libc.so.6+0x3ff60)
#<!-- -->49 0x00005564324357e5 _start (/home/ych/llvm-project/build/bin/clang+++0x57017e5)
fish: Job 1, '~/llvm-project/build/bin/clang+…' terminated by signal SIGABRT (Abort)

ExprConstant complains that this lambda after instantiation is still value dependent. getTypeDeclType on the instantiated lambda shows that the type for the lambda CXXRecordDecl is dependent. The reason being the parent DeclContext was dependent, which is also true in this case as we aren't instantiating function template b here.

It's worth noting that with an assertion-disabled clang++, this program compiles successfully and, as far as I can tell, correctly.

I can think of a few possible fixes:

  • Why does a template-id expression here causes the constraint to be checked if the function template b is not being instantiated? Can the fix just be that defer checking the constraint to performing pending instantiations? In Sema::CheckConceptTemplateId, we eagerly calculate the constraint satisfaction if the arguments to the concept template aren't dependent.
  • Why does DeclContext look at the parent context to tell if it's instantiated? This causes any AST nodes created with template instantiation we do during concept template constraints checking to be considered dependent.
  • Defer checking value dependency at ExprConstant evaluation. Since in our case, no actual dependent values can be reached, which explains why the assertion-free build successfully compiles this code.

Even though a Release build is not affected and won't block any production users (with doubt), I think this problem is still worth solving. I would like to consult upstream which approach I should take.

@zyn0217
Copy link
Contributor

zyn0217 commented Feb 24, 2024

I’m also wondering if we could resolve this by refining the lambda dependency calculation e.g. If the transformed lambda doesn’t involve any template parameters, then it should be of NeverDependent type.

// FIXME: DependencyKind below is wrong when substituting inside a templated
// context that isn't a DeclContext (such as a variable template), or when
// substituting an unevaluated lambda inside of a function's parameter's type
// - as parameter types are not instantiated from within a function's DC. We
// use evaluation contexts to distinguish the function parameter case.
CXXRecordDecl::LambdaDependencyKind DependencyKind =
CXXRecordDecl::LDK_Unknown;
if ((getSema().isUnevaluatedContext() ||
getSema().isConstantEvaluatedContext()) &&
(getSema().CurContext->isFileContext() ||
!getSema().CurContext->getParent()->isDependentContext()))
DependencyKind = CXXRecordDecl::LDK_NeverDependent;

@yuxuanchen1997
Copy link
Member Author

@zyn0217
The lambda dependency ultimately came from the CXXRecordDecl's TypeDecl. In template instantiation we provided the parent DeclContext, which in the concept's case is dependent.

@zyn0217
Copy link
Contributor

zyn0217 commented Feb 24, 2024

The lambda dependency ultimately came from the CXXRecordDecl's TypeDecl. In template instantiation we provided the parent DeclContext, which in the concept's case is dependent.

The TypeDecl's dependency was determined by DeclContext::isDependentContext(), which does consider the lambda's dependency, right?
Moreover, I have experimented with a patch that sets the DependencyKind to always LDK_NeverDependent, and the crash was gone then.

@yuxuanchen1997
Copy link
Member Author

yuxuanchen1997 commented Feb 24, 2024 via email

@zygoloid
Copy link
Collaborator

If I am reading this right, that ended up calling isDependentContext on the parent DeclContext. Which belongs to the function template that is never instantiated.

That sounds wrong. The parent context of the lambda should not be the function template -- we should presumably be switching out the current context to that of the concept before we do a satisfaction check. I'd expect this means we get access checks wrong too. And we do: https://godbolt.org/z/bcYavzTzP (interestingly, GCC and EDG have the same bug...)

@jcsxky
Copy link
Contributor

jcsxky commented Feb 24, 2024

[temp.inst]p17
The type-constraints and requires-clause of a template specialization or member function are not instantiated
along with the specialization or function itself, even for a member function of a local class; substitution
into the atomic constraints formed from them is instead performed as specified in 13.5.3 and 13.5.2.3 when
determining whether the constraints are satisfied or as specified in 13.5.3 when comparing declarations.

I wonder why C should be instantiated as well. Here b is template function and not specialized and there is no need to check satisfaction and perform comparing declarations.

@zygoloid
Copy link
Collaborator

This is not a "type-constraint [or] requires-clause of a template specialization or member function" -- it's a concept-id, which has different rules. See [temp.names]/9.

@shafik
Copy link
Collaborator

shafik commented Feb 26, 2024

CC @erichkeane @cor3ntin

@shafik
Copy link
Collaborator

shafik commented Feb 26, 2024

Confirmed: https://godbolt.org/z/88PcYd94r

Assertion:

clang++: /root/llvm-project/clang/lib/AST/ExprConstant.cpp:14963:
bool clang::Expr::EvaluateAsConstantExpr(clang::Expr::EvalResult&, const clang::ASTContext&, clang::Expr::ConstantExprKind) const:
Assertion `!isValueDependent() && "Expression evaluator can't be called on a dependent expression."' failed.

@shafik shafik added the confirmed Verified by a second party label Feb 26, 2024
@yuxuanchen1997
Copy link
Member Author

we should presumably be switching out the current context to that of the concept before we do a satisfaction check

@zygoloid this sounds like the most appropriate fix here. However, ConceptDecls cannot be a DeclContext (yet). It's always a TemplateDecl which doesn't make things easy.

zyn0217 added a commit that referenced this issue Mar 7, 2024
…83997)

The dependency of a lambda inside of a `RequiresExprBodyDecl` was
previously affected by its parent, e.g.,
`ClassTemplateSpecializationDecl`. This made the lambda always dependent
regardless of the template arguments we had, which caused some crashes
on the constraint evaluation later.

This fixes #56556, fixes
#82849 and a case
demonstrated by
#49570 (comment).
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 confirmed Verified by a second party crash Prefer [crash-on-valid] or [crash-on-invalid]
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

7 participants