[Clang][PowerPC] PPC BCD builtins with insufficient arguments trigger Assertion `Arg < getNumArgs() && "Arg access out of range!"' failed.
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
Reproducer:
A fuzzing tool generated the following test case:
https://godbolt.org/z/3ebTxb6aK
```c++
vector unsigned char test_bcdsetsign_imm0(vector unsigned char a) {
return __builtin_ppc_bcdsetsign(); // Reproduced in Clang >= 22.1.
}
```
With Clang trunk and:
```
--target=powerpc64le-linux-gnu -mcpu=power9
```
Clang triggers:
```
clang++: /root/llvm-project/llvm/tools/clang/include/clang/AST/Expr.h:3159: clang::Expr* clang::CallExpr::getArg(unsigned int): Assertion `Arg < getNumArgs() && "Arg access out of range!"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace and dumped files.
Stack dump:
0. Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/clang++ -g -o /app/output.s -mllvm --x86-asm-syntax=intel -fno-verbose-asm -S --gcc-toolchain=/opt/compiler-explorer/gcc-snapshot -fcolor-diagnostics -fno-crash-diagnostics --target=powerpc64le-linux-gnu -mcpu=power9
1. :2:38: current parser token ')'
2. :1:67: parsing function body 'test_bcdsetsign_imm0'
3. :1:67: in compound statement ('{}')
#0 0x000000000448ebf8 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x448ebf8)
#1 0x000000000448baa4 llvm::sys::RunSignalHandlers() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x448baa4)
#2 0x000000000448c0dc llvm::sys::CleanupOnSignal(unsigned long) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x448c0dc)
#3 0x00000000043ca9d8 CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0
#4 0x000072a64c445330 (/lib/x86_64-linux-gnu/libc.so.6+0x45330)
#5 0x000072a64c49ec0c pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x9ec0c)
#6 0x000072a64c44527e raise (/lib/x86_64-linux-gnu/libc.so.6+0x4527e)
#7 0x000072a64c4288ff abort (/lib/x86_64-linux-gnu/libc.so.6+0x288ff)
#8 0x000072a64c42881b (/lib/x86_64-linux-gnu/libc.so.6+0x2881b)
#9 0x000072a64c43b517 (/lib/x86_64-linux-gnu/libc.so.6+0x3b517)
#10 0x0000000006f70e1a (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6f70e1a)
#11 0x000000000703a009 clang::Sema::BuiltinConstantArgRange(clang::CallExpr*, unsigned int, int, int, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x703a009)
#12 0x00000000077437ea clang::SemaPPC::CheckPPCBuiltinFunctionCall(clang::TargetInfo const&, unsigned int, clang::CallExpr*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x77437ea)
#13 0x00000000070675be clang::Sema::CheckBuiltinFunctionCall(clang::FunctionDecl*, unsigned int, clang::CallExpr*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x70675be)
#14 0x0000000007382fdb clang::Sema::BuildResolvedCallExpr(clang::Expr*, clang::NamedDecl*, clang::SourceLocation, llvm::ArrayRef, clang::SourceLocation, clang::Expr*, bool, clang::CallExpr::ADLCallKind) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x7382fdb)
#15 0x000000000737d94c clang::Sema::BuildCallExpr(clang::Scope*, clang::Expr*, clang::SourceLocation, llvm::MutableArrayRef, clang::SourceLocation, clang::Expr*, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x737d94c)
#16 0x0000000007383eaf clang::Sema::ActOnCallExpr(clang::Scope*, clang::Expr*, clang::SourceLocation, llvm::MutableArrayRef, clang::SourceLocation, clang::Expr*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x7383eaf)
#17 0x0000000006e432c3 clang::Parser::ParsePostfixExpressionSuffix(clang::ActionResult) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6e432c3)
#18 0x0000000006e3bc9a clang::Parser::ParseCastExpression(clang::CastParseKind, bool, bool&, clang::TypoCorrectionTypeBehavior, bool, bool*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6e3bc9a)
#19 0x0000000006e3df47 clang::Parser::ParseCastExpression(clang::CastParseKind, bool, clang::TypoCorrectionTypeBehavior, bool, bool*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6e3df47)
#20 0x0000000006e3dfd9 clang::Parser::ParseAssignmentExpression(clang::TypoCorrectionTypeBehavior) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6e3dfd9)
#21 0x0000000006e428c9 clang::Parser::ParseExpression(clang::TypoCorrectionTypeBehavior) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6e428c9)
#22 0x0000000006ec2022 clang::Parser::ParseReturnStatement() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6ec2022)
#23 0x0000000006ec5f6d clang::Parser::ParseStatementOrDeclarationAfterAttributes(llvm::SmallVector&, clang::Parser::ParsedStmtContext, clang::SourceLocation*, clang::ParsedAttributes&, clang::ParsedAttributes&, clang::LabelDecl*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6ec5f6d)
#24 0x0000000006ec7139 clang::Parser::ParseStatementOrDeclaration(llvm::SmallVector&, clang::Parser::ParsedStmtContext, clang::SourceLocation*, clang::LabelDecl*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6ec7139)
#25 0x0000000006ecf655 clang::Parser::ParseCompoundStatementBody(bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6ecf655)
#26 0x0000000006ecfe9a clang::Parser::ParseFunctionStatementBody(clang::Decl*, clang::Parser::ParseScope&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6ecfe9a)
#27 0x0000000006dccf8d clang::Parser::ParseFunctionDefinition(clang::ParsingDeclarator&, clang::Parser::ParsedTemplateInfo const&, clang::LateParsedAttrList*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6dccf8d)
#28 0x0000000006e169f6 clang::Parser::ParseDeclGroup(clang::ParsingDeclSpec&, clang::DeclaratorContext, clang::ParsedAttributes&, clang::Parser::ParsedTemplateInfo&, clang::SourceLocation*, clang::Parser::ForRangeInit*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6e169f6)
#29 0x0000000006dc13bb clang::Parser::ParseDeclOrFunctionDefInternal(clang::ParsedAttributes&, clang::ParsedAttributes&, clang::ParsingDeclSpec&, clang::AccessSpecifier) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6dc13bb)
#30 0x0000000006dc1baf clang::Parser::ParseDeclarationOrFunctionDefinition(clang::ParsedAttributes&, clang::ParsedAttributes&, clang::ParsingDeclSpec*, clang::AccessSpecifier) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6dc1baf)
#31 0x0000000006dce368 clang::Parser::ParseExternalDeclaration(clang::ParsedAttributes&, clang::ParsedAttributes&, clang::ParsingDeclSpec*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6dce368)
#32 0x0000000006dcf2c5 clang::Parser::ParseTopLevelDecl(clang::OpaquePtr&, clang::Sema::ModuleImportState&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6dcf2c5)
#33 0x0000000006dcf6b0 clang::Parser::ParseFirstTopLevelDecl(clang::OpaquePtr&, clang::Sema::ModuleImportState&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6dcf6b0)
#34 0x0000000006dac1ec clang::ParseAST(clang::Sema&, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6dac1ec)
#35 0x0000000004f92ef8 clang::CodeGenAction::ExecuteAction() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4f92ef8)
#36 0x00000000052bd7b8 clang::FrontendAction::Execute() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x52bd7b8)
#37 0x000000000524baed clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x524baed)
#38 0x00000000053927ed clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x53927ed)
#39 0x0000000000dae91c cc1_main(llvm::ArrayRef, char const*, void*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xdae91c)
#40 0x0000000000da553a ExecuteCC1Tool(llvm::SmallVectorImpl&, llvm::ToolContext const&, llvm::IntrusiveRefCntPtr) driver.cpp:0:0
#41 0x0000000000da56bd int llvm::function_ref&)>::callback_fn&)>(long, llvm::SmallVectorImpl&) driver.cpp:0:0
#42 0x000000000500bbc9 void llvm::function_ref::callback_fn>, std::__cxx11::basic_string, std::allocator>*, bool*) const::'lambda'()>(long) Job.cpp:0:0
#43 0x00000000043cae14 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x43cae14)
#44 0x000000000500c735 clang::driver::CC1Command::Execute(llvm::ArrayRef>, std::__cxx11::basic_string, std::allocator>*, bool*) const (.part.0) Job.cpp:0:0
#45 0x0000000004fc43e2 clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4fc43e2)
#46 0x0000000004fc8d47 clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl>&, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4fc8d47)
#47 0x0000000004fd3415 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4fd3415)
#48 0x0000000000daae1a clang_main(int, char**, llvm::ToolContext const&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xdaae1a)
#49 0x0000000000cc6b4a main (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xcc6b4a)
#50 0x000072a64c42a1ca (/lib/x86_64-linux-gnu/libc.so.6+0x2a1ca)
#51 0x000072a64c42a28b __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2a28b)
#52 0x0000000000da4ee5 _start (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xda4ee5)
clang++: error: clang frontend command failed due to signal (use -v to see invocation)
Compiler returned: 134
```
After further investigation, I found that the following PPC BCD builtins also trigger the same assertion when called with fewer arguments than required:
https://godbolt.org/z/7aG8cYYar
```c++
typedef vector unsigned char vec_uc;
void test_bcdshift() {
vec_uc a = {};
__builtin_ppc_bcdshift(a); // Reproduced in Clang trunk
}
void test_bcdshiftround() {
vec_uc a = {};
__builtin_ppc_bcdshiftround(a); // Reproduced in Clang trunk
}
void test_bcdtruncate() {
vec_uc a = {};
__builtin_ppc_bcdtruncate(a); // Reproduced in Clang trunk
}
void test_national2packed() {
vec_uc a = {};
__builtin_ppc_national2packed(a); // Reproduced in Clang >= 21.1
}
void test_packed2zoned() {
vec_uc a = {};
__builtin_ppc_packed2zoned(a); // Reproduced in Clang >= 21.1
}
void test_zoned2packed() {
vec_uc a = {};
__builtin_ppc_zoned2packed(a); // Reproduced in Clang >= 21.1
}
```
This issue may be related to #217023, where PPC min/max builtins called with fewer than 4 arguments trigger the same assertion. It is unclear whether the two issues have the same root cause.
Contributor guide
Research direction
Start by running the supplied reproducer with the shown PowerPC target flags, then inspect clang::SemaPPC::CheckPPCBuiltinFunctionCall and clang::Sema::BuiltinConstantArgRange, where the stack trace reaches clang/AST/Expr.h. Compare the listed BCD builtins with the related #217023 report. Done means insufficient-argument calls are handled without the assertion and the reproductions have regression coverage.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100