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++ crashes when using fmt on object with consteval constructor #55871

Closed
jack-interpret-cast opened this issue Jun 4, 2022 · 6 comments
Closed

Comments

@jack-interpret-cast
Copy link

jack-interpret-cast commented Jun 4, 2022

Minimal working example:

https://godbolt.org/z/ErPn95a8T

Note gcc successfully compiles this

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-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++20 <source> -isystem/opt/compiler-explorer/libs/fmt/trunk/include
1.	<eof> parser at end of file
2.	<source>:25:5: LLVM IR generation of declaration 'main'
3.	<source>:25:5: Generating code for declaration 'main'
 #0 0x000055fc6f47dd7f PrintStackTraceSignalHandler(void*) Signals.cpp:0:0
 #1 0x000055fc6f47bbb4 llvm::sys::CleanupOnSignal(unsigned long) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x367bbb4)
 #2 0x000055fc6f3b4b48 CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0
 #3 0x00007f5cd18ce3c0 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x143c0)
 #4 0x000055fc6f83ff0d clang::CodeGen::ConstantEmitter::tryEmitPrivate(clang::APValue const&, clang::QualType) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x3a3ff0d)
 #5 0x000055fc6f840ad5 clang::CodeGen::ConstantEmitter::tryEmitConstantExpr(clang::ConstantExpr const*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x3a40ad5)
 #6 0x000055fc6fb4013a (anonymous namespace)::AggExprEmitter::VisitConstantExpr(clang::ConstantExpr*) CGExprAgg.cpp:0:0
 #7 0x000055fc6fb3e2eb clang::StmtVisitorBase<std::add_pointer, (anonymous namespace)::AggExprEmitter, void>::Visit(clang::Stmt*) CGExprAgg.cpp:0:0
 #8 0x000055fc6fb40351 clang::CodeGen::CodeGenFunction::EmitAggExpr(clang::Expr const*, clang::CodeGen::AggValueSlot) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x3d40351)
 #9 0x000055fc6fb32561 clang::CodeGen::CodeGenFunction::EmitAnyExprToMem(clang::Expr const*, clang::CodeGen::Address, clang::Qualifiers, bool) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x3d32561)
#10 0x000055fc6fb36b06 clang::CodeGen::CodeGenFunction::EmitMaterializeTemporaryExpr(clang::MaterializeTemporaryExpr const*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x3d36b06)
#11 0x000055fc6fb2d53e clang::CodeGen::CodeGenFunction::EmitLValue(clang::Expr const*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x3d2d53e)
#12 0x000055fc6fb366dd clang::CodeGen::CodeGenFunction::EmitReferenceBindingToExpr(clang::Expr const*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x3d366dd)
#13 0x000055fc6fac5954 clang::CodeGen::CodeGenFunction::EmitCallArg(clang::CodeGen::CallArgList&, clang::Expr const*, clang::QualType) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x3cc5954)
#14 0x000055fc6fac6f8f clang::CodeGen::CodeGenFunction::EmitCallArgs(clang::CodeGen::CallArgList&, clang::CodeGen::CodeGenFunction::PrototypeWrapper, llvm::iterator_range<clang::Stmt::CastIterator<clang::Expr, clang::Expr const* const, clang::Stmt const* const>>, clang::CodeGen::CodeGenFunction::AbstractCallee, unsigned int, clang::CodeGen::CodeGenFunction::EvaluationOrder) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x3cc6f8f)
#15 0x000055fc6fb2b79e clang::CodeGen::CodeGenFunction::EmitCall(clang::QualType, clang::CodeGen::CGCallee const&, clang::CallExpr const*, clang::CodeGen::ReturnValueSlot, llvm::Value*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x3d2b79e)
#16 0x000055fc6fb38368 clang::CodeGen::CodeGenFunction::EmitCallExpr(clang::CallExpr const*, clang::CodeGen::ReturnValueSlot) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x3d38368)
#17 0x000055fc6fb74960 (anonymous namespace)::ScalarExprEmitter::VisitCallExpr(clang::CallExpr const*) CGExprScalar.cpp:0:0
#18 0x000055fc6fb68df3 (anonymous namespace)::ScalarExprEmitter::Visit(clang::Expr*) CGExprScalar.cpp:0:0
#19 0x000055fc6fb69cba (anonymous namespace)::ScalarExprEmitter::Visit(clang::Expr*) CGExprScalar.cpp:0:0
#20 0x000055fc6fb6b373 clang::CodeGen::CodeGenFunction::EmitScalarExpr(clang::Expr const*, bool) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x3d6b373)
#21 0x000055fc6fb1d767 clang::CodeGen::CodeGenFunction::EmitAnyExpr(clang::Expr const*, clang::CodeGen::AggValueSlot, bool) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x3d1d767)
#22 0x000055fc6fb36841 clang::CodeGen::CodeGenFunction::EmitIgnoredExpr(clang::Expr const*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x3d36841)
#23 0x000055fc6f85b51c clang::CodeGen::CodeGenFunction::EmitStmt(clang::Stmt const*, llvm::ArrayRef<clang::Attr const*>) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x3a5b51c)
#24 0x000055fc6f86110c clang::CodeGen::CodeGenFunction::EmitCompoundStmtWithoutScope(clang::CompoundStmt const&, bool, clang::CodeGen::AggValueSlot) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x3a6110c)
#25 0x000055fc6f8b40f3 clang::CodeGen::CodeGenFunction::EmitFunctionBody(clang::Stmt const*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x3ab40f3)
#26 0x000055fc6f8bcc3c clang::CodeGen::CodeGenFunction::GenerateCode(clang::GlobalDecl, llvm::Function*, clang::CodeGen::CGFunctionInfo const&) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x3abcc3c)
#27 0x000055fc6f903c28 clang::CodeGen::CodeGenModule::EmitGlobalFunctionDefinition(clang::GlobalDecl, llvm::GlobalValue*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x3b03c28)
#28 0x000055fc6f900885 clang::CodeGen::CodeGenModule::EmitGlobalDefinition(clang::GlobalDecl, llvm::GlobalValue*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x3b00885)
#29 0x000055fc6f900fc3 clang::CodeGen::CodeGenModule::EmitGlobal(clang::GlobalDecl) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x3b00fc3)
#30 0x000055fc6f9070f1 clang::CodeGen::CodeGenModule::EmitTopLevelDecl(clang::Decl*) (.part.5860) CodeGenModule.cpp:0:0
#31 0x000055fc70491361 (anonymous namespace)::CodeGeneratorImpl::HandleTopLevelDecl(clang::DeclGroupRef) ModuleBuilder.cpp:0:0
#32 0x000055fc70484ac2 clang::BackendConsumer::HandleTopLevelDecl(clang::DeclGroupRef) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x4684ac2)
#33 0x000055fc713d0484 clang::ParseAST(clang::Sema&, bool, bool) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x55d0484)
#34 0x000055fc7048fbad clang::CodeGenAction::ExecuteAction() (/opt/compiler-explorer/clang-trunk/bin/clang+++0x468fbad)
#35 0x000055fc6fe6c551 clang::FrontendAction::Execute() (/opt/compiler-explorer/clang-trunk/bin/clang+++0x406c551)
#36 0x000055fc6fe03e32 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x4003e32)
#37 0x000055fc6ff39753 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x4139753)
#38 0x000055fc6d0090a4 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x12090a4)
#39 0x000055fc6d00507d ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&) driver.cpp:0:0
#40 0x000055fc6fc953f5 void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<llvm::Optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const::'lambda'()>(long) Job.cpp:0:0
#41 0x000055fc6f3b5133 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x35b5133)
#42 0x000055fc6fc974c8 clang::driver::CC1Command::Execute(llvm::ArrayRef<llvm::Optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const (/opt/compiler-explorer/clang-trunk/bin/clang+++0x3e974c8)
#43 0x000055fc6fc6632a clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&) const (/opt/compiler-explorer/clang-trunk/bin/clang+++0x3e6632a)
#44 0x000055fc6fc66e6f clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&) const (/opt/compiler-explorer/clang-trunk/bin/clang+++0x3e66e6f)
#45 0x000055fc6fc6fba5 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x3e6fba5)
#46 0x000055fc6cf32693 main (/opt/compiler-explorer/clang-trunk/bin/clang+++0x1132693)
#47 0x00007f5cd137c0b3 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x240b3)
#48 0x000055fc6d004bfa _start (/opt/compiler-explorer/clang-trunk/bin/clang+++0x1204bfa)
clang-15: error: clang frontend command failed with exit code 139 (use -v to see invocation)
Compiler returned: 139
@EugeneZelenko EugeneZelenko added clang:codegen crash Prefer [crash-on-valid] or [crash-on-invalid] and removed new issue labels Jun 4, 2022
@llvmbot
Copy link
Collaborator

llvmbot commented Jun 4, 2022

@llvm/issue-subscribers-clang-codegen

@Philippe91
Copy link

The crash point seems to be the same. In my case, this happens randomly (> 50% of the time, just compiling again (and again...) can solve the problem and produce apparently valid code). But I can't figure out where exactly in my code. In my case, fmt and consteval are not used.

Process:               clang [32503]
Path:                  /Applications/Xcode13.4.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang
Identifier:            clang
Version:               ???
Code Type:             ARM-64 (Native)
Parent Process:        clang [32492]
Responsible:           Xcode [3029]
User ID:               501

Date/Time:             2022-06-12 10:45:28.9844 +0200
OS Version:            macOS 12.4 (21F79)
Report Version:        12
Anonymous UUID:        277805D3-EBB5-F47F-212E-126C1C8AE96B

Sleep/Wake UUID:       7630AEAA-1F12-4698-BDAC-30B8BA1B0674

Time Awake Since Boot: 270000 seconds
Time Since Wake:       135 seconds

System Integrity Protection: enabled

Crashed Thread:        0  Dispatch queue: com.apple.main-thread

Exception Type:        EXC_BAD_ACCESS (SIGSEGV)
Exception Codes:       KERN_INVALID_ADDRESS at 0x000000013c2b866c
Exception Codes:       0x0000000000000001, 0x000000013c2b866c
Exception Note:        EXC_CORPSE_NOTIFY

Termination Reason:    Namespace SIGNAL, Code 11 Segmentation fault: 11
Terminating Process:   exc handler [32503]

VM Region Info: 0x13c2b866c is not in any region.  Bytes after previous region: 2852461  Bytes before following region: 64256404
      REGION TYPE                    START - END         [ VSIZE] PRT/MAX SHRMOD  REGION DETAIL
      MALLOC_SMALL                13b800000-13c000000    [ 8192K] rw-/rwx SM=PRV  
--->  GAP OF 0x4000000 BYTES
      MALLOC_MEDIUM               140000000-140800000    [ 8192K] rw-/rwx SM=PRV  

Thread 0 Crashed::  Dispatch queue: com.apple.main-thread
0   clang                         	       0x105e5c0b4 clang::CodeGen::ConstantEmitter::tryEmitPrivate(clang::APValue const&, clang::QualType) + 60
1   clang                         	       0x105e5d614 clang::CodeGen::ConstantEmitter::tryEmitPrivateForMemory(clang::APValue const&, clang::QualType) + 260
2   clang                         	       0x105e5d614 clang::CodeGen::ConstantEmitter::tryEmitPrivateForMemory(clang::APValue const&, clang::QualType) + 260
3   clang                         	       0x105e61058 (anonymous namespace)::ConstStructBuilder::Build(clang::APValue const&, clang::RecordDecl const*, bool, clang::CXXRecordDecl const*, clang::CharUnits) + 1428
4   clang                         	       0x105e5c170 clang::CodeGen::ConstantEmitter::tryEmitPrivate(clang::APValue const&, clang::QualType) + 248
5   clang                         	       0x105e5c014 clang::CodeGen::ConstantEmitter::tryEmitPrivate(clang::Expr const*, clang::QualType) + 224
6   clang                         	       0x105e5d4c4 clang::CodeGen::ConstantEmitter::tryEmitPrivateForMemory(clang::Expr const*, clang::QualType) + 260
7   clang                         	       0x105e66220 (anonymous namespace)::ConstStructBuilder::Build(clang::InitListExpr*, bool) + 624
8   clang                         	       0x105e665c4 (anonymous namespace)::ConstStructBuilder::BuildStruct(clang::CodeGen::ConstantEmitter&, clang::InitListExpr*, clang::QualType) + 104
9   clang                         	       0x105e5bed8 clang::CodeGen::ConstantEmitter::tryEmitPrivateForVarInit(clang::VarDecl const&) + 532
10  clang                         	       0x105e5d374 clang::CodeGen::ConstantEmitter::tryEmitForInitializer(clang::VarDecl const&) + 72
11  clang                         	       0x105e11ce8 clang::CodeGen::CodeGenFunction::AddInitializerToStaticVarDecl(clang::VarDecl const&, llvm::GlobalVariable*) + 84
12  clang                         	       0x105e10cec clang::CodeGen::CodeGenFunction::EmitStaticVarDecl(clang::VarDecl const&, llvm::GlobalValue::LinkageTypes) + 428
13  clang                         	       0x105e1073c clang::CodeGen::CodeGenFunction::EmitDecl(clang::Decl const&) + 212
14  clang                         	       0x105f46eb8 clang::CodeGen::CodeGenFunction::EmitSimpleStmt(clang::Stmt const*, llvm::ArrayRef<clang::Attr const*>) + 708
15  clang                         	       0x105f465ac clang::CodeGen::CodeGenFunction::EmitStmt(clang::Stmt const*, llvm::ArrayRef<clang::Attr const*>) + 188
16  clang                         	       0x105f4e8d8 clang::CodeGen::CodeGenFunction::EmitCompoundStmtWithoutScope(clang::CompoundStmt const&, bool, clang::CodeGen::AggValueSlot) + 180
17  clang                         	       0x105f4dfac clang::CodeGen::CodeGenFunction::EmitCompoundStmt(clang::CompoundStmt const&, bool, clang::CodeGen::AggValueSlot) + 280
18  clang                         	       0x105f46d1c clang::CodeGen::CodeGenFunction::EmitSimpleStmt(clang::Stmt const*, llvm::ArrayRef<clang::Attr const*>) + 296
19  clang                         	       0x105f465ac clang::CodeGen::CodeGenFunction::EmitStmt(clang::Stmt const*, llvm::ArrayRef<clang::Attr const*>) + 188
20  clang                         	       0x105f47404 clang::CodeGen::CodeGenFunction::EmitIfStmt(clang::IfStmt const&) + 1128
21  clang                         	       0x105f467a8 clang::CodeGen::CodeGenFunction::EmitStmt(clang::Stmt const*, llvm::ArrayRef<clang::Attr const*>) + 696
22  clang                         	       0x105f4e8d8 clang::CodeGen::CodeGenFunction::EmitCompoundStmtWithoutScope(clang::CompoundStmt const&, bool, clang::CodeGen::AggValueSlot) + 180
23  clang                         	       0x105f91cdc clang::CodeGen::CodeGenFunction::EmitFunctionBody(clang::Stmt const*) + 316
24  clang                         	       0x105f925dc clang::CodeGen::CodeGenFunction::GenerateCode(clang::GlobalDecl, llvm::Function*, clang::CodeGen::CGFunctionInfo const&) + 912
25  clang                         	       0x105faa954 clang::CodeGen::CodeGenModule::EmitGlobalFunctionDefinition(clang::GlobalDecl, llvm::GlobalValue*) + 324
26  clang                         	       0x105fa4c3c clang::CodeGen::CodeGenModule::EmitGlobalDefinition(clang::GlobalDecl, llvm::GlobalValue*) + 444
27  clang                         	       0x105f9bc68 clang::CodeGen::CodeGenModule::EmitDeferred() + 476
28  clang                         	       0x105f9bc80 clang::CodeGen::CodeGenModule::EmitDeferred() + 500
29  clang                         	       0x105f9bc80 clang::CodeGen::CodeGenModule::EmitDeferred() + 500
30  clang                         	       0x105f9bc80 clang::CodeGen::CodeGenModule::EmitDeferred() + 500
31  clang                         	       0x105f9bc80 clang::CodeGen::CodeGenModule::EmitDeferred() + 500
32  clang                         	       0x105f9bc80 clang::CodeGen::CodeGenModule::EmitDeferred() + 500
33  clang                         	       0x105f9bc80 clang::CodeGen::CodeGenModule::EmitDeferred() + 500
34  clang                         	       0x105f9bc80 clang::CodeGen::CodeGenModule::EmitDeferred() + 500
35  clang                         	       0x105f9bc80 clang::CodeGen::CodeGenModule::EmitDeferred() + 500
36  clang                         	       0x105f9bc80 clang::CodeGen::CodeGenModule::EmitDeferred() + 500
37  clang                         	       0x105f9bc80 clang::CodeGen::CodeGenModule::EmitDeferred() + 500

@Abstract-Everything
Copy link
Contributor

I have managed to reproduce the crash without the dependencies. I would also like to note that using parenthesis for constructor initialisation instead of braces does not result in a crash. Also using a single parameter does not lead to a crash, that is modifying function to take a single Item parameter.

Godbolt: https://godbolt.org/z/bP571b477
Sample:

struct Item
{
    consteval Item(char c) : _char{c} {}
    char _char;
};

int function(const Item& item1, const Item& item2)
{
	return 0;
}

int main()
{
    return function(Item{'a'}, Item{'a'});
}

The crash seems to be caused from a null pointer access at ConstStructBuilder::BuildStruct when it tries to access a null QualType. The QualType variable is created in ConstantEmitter::tryEmitConstantExpr. It was never assigned because the code only assign it if the expression has type CallExpr or CXXConstructExpr but a CXXFunctionalCastExpr is found. The dump of the expression is:

CXXFunctionalCastExpr 0x555568c89bd8 'struct Item' functional cast to struct Item <ConstructorConversion>
`-CXXConstructExpr 0x555568c89ba8 'struct Item' 'void (char)'
  `-CharacterLiteral 0x555568c64a18 'char' 97

This tree is last modified by RemoveNestedImmediateInvocation. Upon entering the function the expression looks as follows:

CXXTemporaryObjectExpr 0x555568c89550 'struct Item' 'void (char)' list
`-CharacterLiteral 0x555568c648b8 'char' 97

Eventually TransformCXXTemporaryObjectExpr is called, this in turn calls RebuildCXXTemporaryObjectExpr but passes false for the ListInitialization parameter. This is interesting because during parsing BuildCXXTypeConstructExpr is called with list initialisation set to true, there is a comment in the code stating that BuildCXXTypeConstructExpr is not prepared to handle ListInitialization set to true without a child InitListExpr. At some point the function explicitly checks the ListInitialization parameter and seeing it false it creates a CXXFunctionalCastExpr. This results in the expression seen before in ConstStructBuilder::BuildStruct:

CXXFunctionalCastExpr 0x555568c899e0 'struct Item' functional cast to struct Item <ConstructorConversion>
`-CXXConstructExpr 0x555568c899b0 'struct Item' 'void (char)'
  `-CharacterLiteral 0x555568c648b8 'char' 97

This is all that I have found for now. From what I can see the fix involves changing RebuildCXXTemporaryObjectExpr to correctly consider the expression as a list initialised constructor, but I am not familiar enough with the clang code to figure out what exactly needs to change. Another fix might be to just consider conversion from CXXFunctionalCastExpr in tryEmitConstantExpr to get the underlying CXXConstructorExpr but this feels like a hack. I would appreciate if someone more familiar with this area could provide some insight.

@amosbird
Copy link

There are similar crash issues related to the fmt library when the fmt arguments are ill-formed.

@AaronBallman AaronBallman added confirmed Verified by a second party crash-on-valid c++20 labels Aug 4, 2022
@llvmbot
Copy link
Collaborator

llvmbot commented Aug 4, 2022

@llvm/issue-subscribers-c-20

@AaronBallman
Copy link
Collaborator

I can confirm this is an issue, and thank you @Abstract-Everything for the detailed investigative work! I've taken a stab at working around this issue in https://reviews.llvm.org/D131194 -- the changes to the template instantiation code are likely to be far more involved.

@EugeneZelenko EugeneZelenko removed the crash Prefer [crash-on-valid] or [crash-on-invalid] label Aug 4, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants