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

[GNU ObjC] Clang 14 regression: frontend crash in clang::CodeGen::CreateGNUObjCRuntime() building Objective-C++ code #54556

Closed
triplef opened this issue Mar 25, 2022 · 5 comments
Labels
clang:codegen crash Prefer [crash-on-valid] or [crash-on-invalid] objective-c

Comments

@triplef
Copy link
Member

triplef commented Mar 25, 2022

The following Objective-C++ code causes a frontend crash with Clang 14.0.0 using the GNU Objective-C runtime on Win64 and Win32 (and possibly other platforms). The same code does not crash with Clang 13.0.1 (both using pre-built binaries from GitHub). It also does not crash using the Apple runtime on macOS.

This seems to happen using various C++ standard library types as value arguments to Objective-C method, but not with pointer arguments or trivial self-defined C++ class types as value arguments. It also happens only with Objective-C instance methods, but not with class methods.

#include <string>

__attribute__((objc_root_class))
@interface Test
-(void)test:(std::string)x;
@end

@implementation Test
-(void)test:(std::string)x {}
@end

int main()
{
	Test *test = NULL;
	[test test:""];
}
Stack dump:
0.      Program arguments: "C:\\Program Files\\LLVM-14\\bin\\clang.exe" -emit-llvm -Xclang -disable-llvm-passes -c clang-14-crash.mm
1.      <eof> parser at end of file
2.      clang-14-crash.mm:12:5: LLVM IR generation of declaration 'main'
3.      clang-14-crash.mm:12:5: Generating code for declaration 'main'
 #0 0x00007ff702ab36e9 clang::CodeGen::CreateGNUObjCRuntime(class clang::CodeGen::CodeGenModule &) (clang.exe+0x11f36e9)
 #1 0x00007ff702a27332 clang::CodeGen::CodeGenFunction::EmitObjCMessageExpr(class clang::ObjCMessageExpr const *, class clang::CodeGen::ReturnValueSlot) (clang.exe+0x1167332)
 #2 0x00007ff702bc4bfb clang::CodeGen::CodeGenFunction::ShouldNullCheckClassCastValue(class clang::CastExpr const *) (clang.exe+0x1304bfb)
 #3 0x00007ff702bc47cb clang::CodeGen::CodeGenFunction::ShouldNullCheckClassCastValue(class clang::CastExpr const *) (clang.exe+0x13047cb)
 #4 0x00007ff702bbfb6f clang::CodeGen::CodeGenFunction::EmitScalarExpr(class clang::Expr const *, bool) (clang.exe+0x12ffb6f)
 #5 0x00007ff702a70c65 clang::CodeGen::CodeGenFunction::EmitIgnoredExpr(class clang::Expr const *) (clang.exe+0x11b0c65)
 #6 0x00007ff702b92bd0 clang::CodeGen::CodeGenFunction::EmitStmt(class clang::Stmt const *, class llvm::ArrayRef<class clang::Attr const *>) (clang.exe+0x12d2bd0)
 #7 0x00007ff702b8ebec clang::CodeGen::CodeGenFunction::EmitCompoundStmtWithoutScope(class clang::CompoundStmt const &, bool, class clang::CodeGen::AggValueSlot) (clang.exe+0x12cebec)
 #8 0x00007ff702a5a3a5 clang::CodeGen::CodeGenFunction::GenerateCode(class clang::GlobalDecl, class llvm::Function *, class clang::CodeGen::CGFunctionInfo const &) (clang.exe+0x119a3a5)
 #9 0x00007ff70294f6b0 clang::CodeGen::CodeGenModule::EmitGlobalFunctionDefinition(class clang::GlobalDecl, class llvm::GlobalValue *) (clang.exe+0x108f6b0)
#10 0x00007ff70294f2ef clang::CodeGen::CodeGenModule::EmitGlobalDefinition(class clang::GlobalDecl, class llvm::GlobalValue *) (clang.exe+0x108f2ef)
#11 0x00007ff70294ee1b clang::CodeGen::CodeGenModule::EmitGlobal(class clang::GlobalDecl) (clang.exe+0x108ee1b)
#12 0x00007ff702952334 clang::CodeGen::CodeGenModule::EmitTopLevelDecl(class clang::Decl *) (clang.exe+0x1092334)
#13 0x00007ff704aec6af clang::CodeGenerator::GetModule(void) (clang.exe+0x322c6af)
#14 0x00007ff704ae7a16 clang::BackendConsumer::HandleTopLevelDecl(class clang::DeclGroupRef) (clang.exe+0x3227a16)
#15 0x00007ff703a7fe47 clang::ParseAST(class clang::Sema &, bool, bool) (clang.exe+0x21bfe47)
#16 0x00007ff702f14f87 clang::ASTFrontendAction::ExecuteAction(void) (clang.exe+0x1654f87)
#17 0x00007ff704ae6e78 clang::CodeGenAction::ExecuteAction(void) (clang.exe+0x3226e78)
#18 0x00007ff702f14a02 clang::FrontendAction::Execute(void) (clang.exe+0x1654a02)
#19 0x00007ff702ede802 clang::CompilerInstance::ExecuteAction(class clang::FrontendAction &) (clang.exe+0x161e802)
#20 0x00007ff702f81228 clang::ExecuteCompilerInvocation(class clang::CompilerInstance *) (clang.exe+0x16c1228)
#21 0x00007ff701935c32 clang::CodeGen::TargetCodeGenInfo::testFPKind(class llvm::Value *, unsigned int, class clang::CodeGen::CGBuilderTy &, class clang::CodeGen::CodeGenModule &) const (clang.exe+0x75c32)
#22 0x00007ff701930b67 clang::ChainedDiagnosticConsumer::EndSourceFile(void) (clang.exe+0x70b67)
#23 0x00007ff702dfe917 clang::driver::toolchains::BareMetal::handlesTarget(class llvm::Triple const &) (clang.exe+0x153e917)
#24 0x00007ff70269709f llvm::CrashRecoveryContext::RunSafely(class llvm::function_ref<(void)>) (clang.exe+0xdd709f)
#25 0x00007ff702dfef70 clang::driver::CC1Command::Execute(class llvm::ArrayRef<class llvm::Optional<class llvm::StringRef>>, class std::basic_string<char, struct std::char_traits<char>, class std::allocator<char>> *, bool *) const (clang.exe+0x153ef70)
#26 0x00007ff702d7d2e0 clang::driver::Compilation::ExecuteCommand(class clang::driver::Command const &, class clang::driver::Command const *&) const (clang.exe+0x14bd2e0)
#27 0x00007ff702d7d62d clang::driver::Compilation::ExecuteJobs(class clang::driver::JobList const &, class llvm::SmallVectorImpl<struct std::pair<int, class clang::driver::Command const *>> &) const (clang.exe+0x14bd62d)
#28 0x00007ff702d64d48 clang::driver::Driver::ExecuteCompilation(class clang::driver::Compilation &, class llvm::SmallVectorImpl<struct std::pair<int, class clang::driver::Command const *>> &) (clang.exe+0x14a4d48)
#29 0x00007ff701932e6b llvm::slpvectorizer::BoUpSLP::BlockScheduling::ReadyList::insert(struct llvm::slpvectorizer::BoUpSLP::ScheduleData *) (clang.exe+0x72e6b)
#30 0x00007ff704887c8c clang::Preprocessor::LexUnexpandedNonComment(class clang::Token &) (clang.exe+0x2fc7c8c)
#31 0x00007ffb3c0554e0 (C:\WINDOWS\System32\KERNEL32.DLL+0x154e0)
#32 0x00007ffb3d7c485b (C:\WINDOWS\SYSTEM32\ntdll.dll+0x485b)
clang: error: clang frontend command failed due to signal (use -v to see invocation)
clang version 14.0.0
Target: x86_64-pc-windows-msvc
Thread model: posix
InstalledDir: C:\Program Files\LLVM-14\bin
clang: note: diagnostic msg:
********************

Preprocessed source and associated run script:
clang-14-crash.zip

@rjmccall I saw you made some changes to the non-Darwin runtime for llvm-14. I’d appreciate if you could take a look at this to see if this is related.

@EugeneZelenko EugeneZelenko added clang:codegen crash Prefer [crash-on-valid] or [crash-on-invalid] objective-c and removed new issue labels Mar 25, 2022
@llvmbot
Copy link
Collaborator

llvmbot commented Mar 25, 2022

@llvm/issue-subscribers-clang-codegen

@triplef triplef changed the title [win] Clang 14 regression: frontend crash in clang::CodeGen::CreateGNUObjCRuntime() building Objective-C++ code [GNU ObjC] Clang 14 regression: frontend crash in clang::CodeGen::CreateGNUObjCRuntime() building Objective-C++ code Apr 7, 2022
@davidchisnall
Copy link
Contributor

It does looks as if @rjmccall's change introduced this. RValue returns true to isScalar if the type is void, but then returns nullptr from getScalarVal(), causing the crash. The stack trace from Windows is quite misleading. This bug probably didn't get any attention because the title does not reflect the failure.

I believe the following patch fixes it:

diff --git a/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp
index ec459f07f..7bbe9af7e 100644
--- a/clang/lib/CodeGen/CGObjCGNU.cpp
+++ b/clang/lib/CodeGen/CGObjCGNU.cpp
@@ -2837,11 +2837,13 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF,
     // Enter the continuation block and emit a phi if required.
     CGF.EmitBlock(continueBB);
     if (msgRet.isScalar()) {
-      llvm::Value *v = msgRet.getScalarVal();
-      llvm::PHINode *phi = Builder.CreatePHI(v->getType(), 2);
-      phi->addIncoming(v, nonNilPathBB);
-      phi->addIncoming(CGM.EmitNullConstant(ResultType), nilPathBB);
-      msgRet = RValue::get(phi);
+      // If the return type is void, do nothing
+      if (llvm::Value *v = msgRet.getScalarVal()) {
+        llvm::PHINode *phi = Builder.CreatePHI(v->getType(), 2);
+        phi->addIncoming(v, nonNilPathBB);
+        phi->addIncoming(CGM.EmitNullConstant(ResultType), nilPathBB);
+        msgRet = RValue::get(phi);
+      }
     } else if (msgRet.isAggregate()) {
       // Aggregate zeroing is handled in nilCleanupBB when it's required.
     } else /* isComplex() */ {

@davidchisnall
Copy link
Contributor

The three conditions required to trigger this bug are:

  • The receiver might be nil.
  • At least one of the arguments is cleaned up by the callee and so must be handled in the caller for the nil case.
  • The return type is void.
  • Any GNU-flavoured runtime is targeted.

The Mac runtimes have an early return prior to the equivalent block and so never hit this condition.

@triplef
Copy link
Member Author

triplef commented Jun 23, 2022

@triplef
Copy link
Member Author

triplef commented Jul 25, 2022

Fixed via 94c3b16.

@triplef triplef closed this as completed Jul 25, 2022
triplef added a commit to gnustep/tools-windows-msvc that referenced this issue Sep 27, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:codegen crash Prefer [crash-on-valid] or [crash-on-invalid] objective-c
Projects
None yet
Development

No branches or pull requests

4 participants