Skip to content

[clang] Ill-formed block expressions within a lambda can yield assert-failures #109148

@katzdm

Description

@katzdm

The following program produces an assert failure with a clang binary built with assertions, when compiled with -fblocks:

template<typename... Ts>
struct Cls {
  static_assert([] consteval -> void {
    (^Ts);
  });
};

The assertion:

Assertion failed: ((!Unexpanded.empty() || Visitor.containsFunctionParmPackExpr()) && "Unable to find unexpanded parameter packs"), function DiagnoseUnexpandedParameterPack, file SemaTemplateVariadic.cpp, line 467.
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: /Users/dkatz85/src/bloomberg/clang-p2996/build-llvm/bin/clang-20 -cc1 -triple arm64-apple-macosx14.0.0 -Wundef-prefix=TARGET_OS_ -Werror=undef-prefix -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-isa-usage -emit-obj -dumpdir build-llvm/main.tsk- -disable-free -clear-ast-before-backend -main-file-name main.cpp -mrelocation-model pic -pic-level 2 -mframe-pointer=non-leaf -ffp-contract=on -fno-rounding-math -funwind-tables=1 -target-sdk-version=15.0 -fcompatibility-qualified-id-block-type-checking -fvisibility-inlines-hidden-static-local-var -fdefine-target-os-macros -fno-modulemap-allow-subdirectory-search -target-cpu apple-m1 -target-feature +zcm -target-feature +zcz -target-feature +v8.4a -target-feature +aes -target-feature +altnzcv -target-feature +ccdp -target-feature +complxnum -target-feature +crc -target-feature +dotprod -target-feature +fp-armv8 -target-feature +fp16fml -target-feature +fptoint -target-feature +fullfp16 -target-feature +jsconv -target-feature +lse -target-feature +neon -target-feature +pauth -target-feature +perfmon -target-feature +predres -target-feature +ras -target-feature +rcpc -target-feature +rdm -target-feature +sb -target-feature +sha2 -target-feature +sha3 -target-feature +specrestrict -target-feature +ssbs -target-abi darwinpcs -debug-info-kind=standalone -dwarf-version=4 -debugger-tuning=lldb -fdebug-compilation-dir=/Users/dkatz85/src/bloomberg/clang-p2996 -target-linker-version 1053.12 -fcoverage-compilation-dir=/Users/dkatz85/src/bloomberg/clang-p2996 -resource-dir /Users/dkatz85/src/bloomberg/clang-p2996/build-llvm/lib/clang/20 -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk -internal-isystem /Users/dkatz85/src/bloomberg/clang-p2996/build-llvm/bin/../include/c++/v1 -internal-isystem /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/local/include -internal-isystem /Users/dkatz85/src/bloomberg/clang-p2996/build-llvm/lib/clang/20/include -internal-externc-isystem /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include -std=c++26 -fdeprecated-macro -fbracket-depth 1500 -ferror-limit 30 -stack-protector 1 -freflection -freflection-new-syntax -fparameter-reflection -fannotation-attributes -fconsteval-blocks -fexpansion-statements -fblocks -fencode-extended-block-signature -fregister-global-dtors-with-atexit -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fcxx-exceptions -fexceptions -freflection-latest -fmax-type-align=16 -fcolor-diagnostics -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /var/folders/cp/8xfkfz156mx13fdc89796sv40000gq/T/main-f5020e.o -x c++ main.cpp
1.	main.cpp:2:57: current parser token ')'
 #0 0x00000001026f5684 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/Users/dkatz85/src/bloomberg/clang-p2996/build-llvm/bin/clang-20+0x102609684)
 #1 0x00000001026f3748 llvm::sys::RunSignalHandlers() (/Users/dkatz85/src/bloomberg/clang-p2996/build-llvm/bin/clang-20+0x102607748)
 #2 0x00000001026f5cf0 SignalHandler(int) (/Users/dkatz85/src/bloomberg/clang-p2996/build-llvm/bin/clang-20+0x102609cf0)
 #3 0x0000000182f3e584 (/usr/lib/system/libsystem_platform.dylib+0x18047a584)
 #4 0x0000000182f0dc20 (/usr/lib/system/libsystem_pthread.dylib+0x180449c20)
 #5 0x0000000182e1aa30 (/usr/lib/system/libsystem_c.dylib+0x180356a30)
 #6 0x0000000182e19d20 (/usr/lib/system/libsystem_c.dylib+0x180355d20)
 #7 0x00000001055ef650 clang::Sema::DiagnoseUnexpandedParameterPackInRequiresExpr(clang::RequiresExpr*) (.cold.1) (/Users/dkatz85/src/bloomberg/clang-p2996/build-llvm/bin/clang-20+0x105503650)
 #8 0x000000010496d01c clang::Sema::DiagnoseUnexpandedParameterPack(clang::Expr*, clang::Sema::UnexpandedParameterPackContext) (/Users/dkatz85/src/bloomberg/clang-p2996/build-llvm/bin/clang-20+0x10488101c)
 #9 0x00000001043569d8 clang::Sema::ActOnParamDefaultArgument(clang::Decl*, clang::SourceLocation, clang::Expr*) (/Users/dkatz85/src/bloomberg/clang-p2996/build-llvm/bin/clang-20+0x10426a9d8)
#10 0x000000010401ec1c clang::Parser::ParseParameterDeclarationClause(clang::DeclaratorContext, clang::ParsedAttributes&, llvm::SmallVectorImpl<clang::DeclaratorChunk::ParamInfo>&, clang::SourceLocation&, bool) (/Users/dkatz85/src/bloomberg/clang-p2996/build-llvm/bin/clang-20+0x103f32c1c)
#11 0x000000010401bd88 clang::Parser::ParseFunctionDeclarator(clang::Declarator&, clang::ParsedAttributes&, clang::BalancedDelimiterTracker&, bool, bool) (/Users/dkatz85/src/bloomberg/clang-p2996/build-llvm/bin/clang-20+0x103f2fd88)
#12 0x0000000104019cb8 clang::Parser::ParseDirectDeclarator(clang::Declarator&) (/Users/dkatz85/src/bloomberg/clang-p2996/build-llvm/bin/clang-20+0x103f2dcb8)
#13 0x0000000104017fb8 clang::Parser::ParseDeclaratorInternal(clang::Declarator&, void (clang::Parser::*)(clang::Declarator&)) (/Users/dkatz85/src/bloomberg/clang-p2996/build-llvm/bin/clang-20+0x103f2bfb8)
#14 0x0000000104171358 clang::Sema::runWithSufficientStackSpace(clang::SourceLocation, llvm::function_ref<void ()>) (/Users/dkatz85/src/bloomberg/clang-p2996/build-llvm/bin/clang-20+0x104085358)
#15 0x0000000104008520 clang::Parser::ParseDeclGroup(clang::ParsingDeclSpec&, clang::DeclaratorContext, clang::ParsedAttributes&, clang::Parser::ParsedTemplateInfo&, clang::SourceLocation*, clang::Parser::ForRangeInit*) (/Users/dkatz85/src/bloomberg/clang-p2996/build-llvm/bin/clang-20+0x103f1c520)
#16 0x00000001040af4ec clang::Parser::ParseDeclarationAfterTemplate(clang::DeclaratorContext, clang::Parser::ParsedTemplateInfo&, clang::ParsingDeclRAIIObject&, clang::SourceLocation&, clang::ParsedAttributes&, clang::AccessSpecifier) (/Users/dkatz85/src/bloomberg/clang-p2996/build-llvm/bin/clang-20+0x103fc34ec)
#17 0x00000001040ae744 clang::Parser::ParseTemplateDeclarationOrSpecialization(clang::DeclaratorContext, clang::SourceLocation&, clang::ParsedAttributes&, clang::AccessSpecifier) (/Users/dkatz85/src/bloomberg/clang-p2996/build-llvm/bin/clang-20+0x103fc2744)
#18 0x00000001040ae070 clang::Parser::ParseDeclarationStartingWithTemplate(clang::DeclaratorContext, clang::SourceLocation&, clang::ParsedAttributes&) (/Users/dkatz85/src/bloomberg/clang-p2996/build-llvm/bin/clang-20+0x103fc2070)
#19 0x0000000104007374 clang::Parser::ParseDeclaration(clang::DeclaratorContext, clang::SourceLocation&, clang::ParsedAttributes&, clang::ParsedAttributes&, clang::SourceLocation*) (/Users/dkatz85/src/bloomberg/clang-p2996/build-llvm/bin/clang-20+0x103f1b374)
#20 0x00000001040be608 clang::Parser::ParseExternalDeclaration(clang::ParsedAttributes&, clang::ParsedAttributes&, clang::ParsingDeclSpec*) (/Users/dkatz85/src/bloomberg/clang-p2996/build-llvm/bin/clang-20+0x103fd2608)
#21 0x00000001040bcee8 clang::Parser::ParseTopLevelDecl(clang::OpaquePtr<clang::DeclGroupRef>&, clang::Sema::ModuleImportState&) (/Users/dkatz85/src/bloomberg/clang-p2996/build-llvm/bin/clang-20+0x103fd0ee8)
#22 0x00000001040bc6b8 clang::Parser::ParseFirstTopLevelDecl(clang::OpaquePtr<clang::DeclGroupRef>&, clang::Sema::ModuleImportState&) (/Users/dkatz85/src/bloomberg/clang-p2996/build-llvm/bin/clang-20+0x103fd06b8)
#23 0x0000000103ff1510 clang::ParseAST(clang::Sema&, bool, bool) (/Users/dkatz85/src/bloomberg/clang-p2996/build-llvm/bin/clang-20+0x103f05510)
#24 0x00000001031a35c4 clang::FrontendAction::Execute() (/Users/dkatz85/src/bloomberg/clang-p2996/build-llvm/bin/clang-20+0x1030b75c4)
#25 0x0000000103132998 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/Users/dkatz85/src/bloomberg/clang-p2996/build-llvm/bin/clang-20+0x103046998)
#26 0x000000010321e8e8 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/Users/dkatz85/src/bloomberg/clang-p2996/build-llvm/bin/clang-20+0x1031328e8)
#27 0x00000001000f5844 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/Users/dkatz85/src/bloomberg/clang-p2996/build-llvm/bin/clang-20+0x100009844)
#28 0x00000001000f2ee8 ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) (/Users/dkatz85/src/bloomberg/clang-p2996/build-llvm/bin/clang-20+0x100006ee8)
#29 0x00000001000f236c clang_main(int, char**, llvm::ToolContext const&) (/Users/dkatz85/src/bloomberg/clang-p2996/build-llvm/bin/clang-20+0x10000636c)
#30 0x00000001000fe674 main (/Users/dkatz85/src/bloomberg/clang-p2996/build-llvm/bin/clang-20+0x100012674)
#31 0x0000000182b83154 
clang++: error: unable to execute command: Abort trap: 6
clang++: error: clang frontend command failed due to signal (use -v to see invocation)

Here is another example that fails the same assertion:

template <typename... Ts>
void fn(int = [] consteval -> int { (^Ts); return 0; }());

Both have the same root cause:

  1. While parsing the CompoundStmt body of the lambda, clang begins to parse ^Ts as a BlockExpr.
  2. The Sema::ActOnBlockArguments function invokes DiagnoseUnexpandedParameterPacks, which sets LambdaScopeInfo::ContainsUnexpandedParameterPacks to true, prior to recognizing that the BlockExpr is ill-formed.
  3. The ill-formed BlockExpr is diagnosed, and is subsequently discarded from the CompoundStmt representing the body of the lambda.
  4. The LambdaScopeInfo is used to initialize the LambdaExpr, resulting in LambdaExpr::ContainsUnexpandedParameterPack being set to true.
  5. The LambdaExpr becomes an argument to some other semantic construct (e.g., StaticAssertDecl, ParameterDecl), whose semantic analysis calls DiagnoseUnexpandedParameterPack.
  6. The above assertion triggers because the LambdaExpr reports that it contains an unexpanded parameter pack, but the tree walk fails to find any pack (since the ill-formed BlockExpr was discarded from the CompoundStmt).

Although I can imagine a few ways to patch this (e.g., keep an "error" representation of the ill-formed BlockExpr in CompoundStmt, rollback the setting of LambdaScopeInfo::ContainsUnexpandedParameterPack when the BlockExpr is ill-formed, just remove the assertion from DiagnoseUnexpandedParameterPacks), I'm not sure I love any of them. For now, I figured I'd just report the issue.

Metadata

Metadata

Assignees

Labels

clang:frontendLanguage frontend issues, e.g. anything involving "Sema"confirmedVerified by a second partyconstevalC++20 constevalcrashPrefer [crash-on-valid] or [crash-on-invalid]lambdaC++11 lambda expressions

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions