Description
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 templateb
is not being instantiated? Can the fix just be that defer checking the constraint to performing pending instantiations? InSema::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.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status