llvm-project
llvm-project copied to clipboard
Crash with`-funique-internal-linkage-names` on extern function
I'm getting a crash in clang when building with the flag -funique-internal-linkage-names.
$ cat test.c
inline void foo() {}
extern void foo();
$ clang -funique-internal-linkage-names test.c -c
llvm-project/clang/lib/AST/Decl.cpp:3614: bool clang::FunctionDecl::isInlineDefinitionExternallyVisible() const: Assertion `(doesThisDeclarationHaveABody() || willHaveBody() || hasAttr<AliasAttr>()) && "Must be a function definition"' failed.
And here is the backtrace
* thread #1, name = 'clang', stop reason = hit program assert
frame #0: 0x00007fffe084737f libc.so.6`raise + 271
frame #1: 0x00007fffe0831db5 libc.so.6`abort + 295
frame #2: 0x00007fffe0831c89 libc.so.6`.annobin_unwind_resume.c_end.unlikely + 15
frame #3: 0x00007fffe083fa76 libc.so.6`__assert_fail + 70
* frame #4: 0x00007fffdd16078b libclangAST.so.15git`clang::FunctionDecl::isInlineDefinitionExternallyVisible(this=0x00000000007516c8) const at Decl.cpp:3612:3
frame #5: 0x00007fffdcfc5835 libclangAST.so.15git`clang::ASTContext::GetGVALinkageForFunction(clang::FunctionDecl const*) const [inlined] basicGVALinkageForFunction(Context=0x00000000006e07e0, FD=0x00000000007516c8) at ASTContext.cpp:11259:13
frame #6: 0x00007fffdcfc56fd libclangAST.so.15git`clang::ASTContext::GetGVALinkageForFunction(this=0x00000000006e07e0, FD=0x00000000007516c8) const at ASTContext.cpp:11331:14
frame #7: 0x00007fffe74b3029 libclangCodeGen.so.15git`clang::CodeGen::CodeGenModule::getFunctionLinkage(this=0x00000000006f74f0, GD=<unavailable>) at CodeGenModule.cpp:1569:37
frame #8: 0x00007fffe7209358 libclangCodeGen.so.15git`clang::CodeGen::CodeGenModule::ConstructAttributeList(this=<unavailable>, Name=<unavailable>, FI=0x00000000007413d0, CalleeInfo=CGCalleeInfo @ 0x00007fffffff9450, AttrList=0x00007fffffff9480, CallingConv=<unavailable>, AttrOnCallSite=<unavailable>, IsThunk=<unavailable>) at CGCall.cpp:2227:17
frame #9: 0x00007fffe74b73b1 libclangCodeGen.so.15git`clang::CodeGen::CodeGenModule::SetFunctionAttributes(clang::GlobalDecl, llvm::Function*, bool, bool) [inlined] clang::CodeGen::CodeGenModule::SetLLVMFunctionAttributes(this=0x00000000006f74f0, GD=GlobalDecl @ 0x00000000027cb0d0, Info=0x00000000007413d0, F=0x000000000065f438, IsThunk=false) at CodeGenModule.cpp:1598:3
frame #10: 0x00007fffe74b734c libclangCodeGen.so.15git`clang::CodeGen::CodeGenModule::SetFunctionAttributes(this=0x00000000006f74f0, GD=<unavailable>, F=0x000000000065f438, IsIncompleteFunction=false, IsThunk=false) at CodeGenModule.cpp:2193:5
frame #11: 0x00007fffe74bb468 libclangCodeGen.so.15git`clang::CodeGen::CodeGenModule::GetOrCreateLLVMFunction(this=0x00000000006f74f0, MangledName=(Data = "foo", Length = 3), Ty=<unavailable>, GD=GlobalDecl @ 0x00007fffffff9508, ForVTable=<unavailable>, DontDefer=<unavailable>, IsThunk=<unavailable>, ExtraAttrs=(pImpl = 0x0000000000000000), IsForDefinition=<unavailable>) at CodeGenModule.cpp:3819:5
frame #12: 0x00007fffe74bd24a libclangCodeGen.so.15git`clang::CodeGen::CodeGenModule::EmitGlobal(this=0x00000000006f74f0, GD=<unavailable>) at CodeGenModule.cpp:3029:7
frame #13: 0x00007fffe74c3f4a libclangCodeGen.so.15git`clang::CodeGen::CodeGenModule::EmitTopLevelDecl(this=0x00000000006f74f0, D=0x00000000007516c8) at CodeGenModule.cpp:5919:5
frame #14: 0x00007fffe7559e2f libclangCodeGen.so.15git`(anonymous namespace)::CodeGeneratorImpl::HandleTopLevelDecl(this=0x00000000006f5910, DG=(D = 0x00000000007516c8)) at ModuleBuilder.cpp:179:18
frame #15: 0x00007fffe7494a46 libclangCodeGen.so.15git`clang::BackendConsumer::HandleTopLevelDecl(this=0x00000000006f56d0, D=(D = 0x00000000007516c8)) at CodeGenAction.cpp:230:12
frame #16: 0x00007fffdaff46b9 libclangParse.so.15git`clang::ParseAST(S=0x000000000072ea40, PrintStats=<unavailable>, SkipFunctionBodies=<unavailable>) at ParseAST.cpp:163:31
frame #17: 0x00007fffe5450291 libclangFrontend.so.15git`clang::FrontendAction::Execute(this=0x00000000006c8330) at FrontendAction.cpp:976:8
frame #18: 0x00007fffe53b498f libclangFrontend.so.15git`clang::CompilerInstance::ExecuteAction(this=0x00000000006bd9d0, Act=0x00000000006c8330) at CompilerInstance.cpp:1036:33
frame #19: 0x00007fffeaf0cd29 libclangFrontendTool.so.15git`clang::ExecuteCompilerInvocation(Clang=0x00000000006bd9d0) at ExecuteCompilerInvocation.cpp:263:25
frame #20: 0x000000000041487d clang`cc1_main(Argv=<unavailable>, Argv0="/data/users/ellishoag/repos/llvm-project/build/bin/clang-14", MainAddr=0x000000000040f7c0) at cc1_main.cpp:248:15
frame #21: 0x00000000004125fd clang`ExecuteCC1Tool(ArgV=<unavailable>) at driver.cpp:317:12
frame #22: 0x00007fffe4f45392 libclangDriver.so.15git`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::$_1>(long) [inlined] clang::driver::CC1Command::Execute(this=0x00007fffffffb960) const::$_1::operator()() const at Job.cpp:407:34
frame #23: 0x00007fffe4f45384 libclangDriver.so.15git`void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(callable=140737488337248) const::$_1>(long) at STLFunctionalExtras.h:45:12
frame #24: 0x00007fffe15c71b7 libLLVMSupport.so.15git`llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) [inlined] llvm::function_ref<void ()>::operator(this=<unavailable>)() const at STLFunctionalExtras.h:68:12
frame #25: 0x00007fffe15c71b1 libLLVMSupport.so.15git`llvm::CrashRecoveryContext::RunSafely(this=<unavailable>, Fn=function_ref<void ()> @ 0x0000000003ac7a20)>) at CrashRecoveryContext.cpp:428:3
frame #26: 0x00007fffe4f44de0 libclangDriver.so.15git`clang::driver::CC1Command::Execute(this=0x00000000006b79d0, Redirects=<unavailable>, ErrMsg=<unavailable>, ExecutionFailed=<unavailable>) const at Job.cpp:407:12
frame #27: 0x00007fffe4f11b28 libclangDriver.so.15git`clang::driver::Compilation::ExecuteCommand(this=0x0000000000642270, C=0x00000000006b79d0, FailingCommand=0x00007fffffffbe60) const at Compilation.cpp:196:15
frame #28: 0x00007fffe4f11ee7 libclangDriver.so.15git`clang::driver::Compilation::ExecuteJobs(this=<unavailable>, Jobs=<unavailable>, FailingCommands=0x00007fffffffbf90) const at Compilation.cpp:249:19
frame #29: 0x00007fffe4f29dac libclangDriver.so.15git`clang::driver::Driver::ExecuteCompilation(this=0x00007fffffffc6b8, C=0x0000000000642270, FailingCommands=0x00007fffffffbf90) at Driver.cpp:1614:5
frame #30: 0x0000000000411d9e clang`main(Argc=<unavailable>, Argv=<unavailable>) at driver.cpp:489:21
frame #31: 0x00007fffe0833493 libc.so.6`__libc_start_main + 243
frame #32: 0x000000000040f6ae clang`_start + 46
@llvm/issue-subscribers-clang-codegen
I think the https://reviews.llvm.org/D96109 might be the issue but I haven't had time to investigate.
@tmsri
I've done a bit of investigating for this bug. In the crash, getFunctionLinkage() eventually calls isInlineDefinitionExternallyVisible() on the declaration extern void foo(); and then crashes because it doesn't have a function body. Interestingly, if I reverse the lines in test.c the crash goes away because isInlineDefinitionExternallyVisible() is called on inline void foo() {} instead.
I found a possible solution that uses a different way to find the linkage in CGCall.cpp, but I'm not convinced the behavior is the same. Maybe @tmsri could help me here.
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index d69455d650f4..a6c6807600f2 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -2226,9 +2226,8 @@ void CodeGenModule::ConstructAttributeList(StringRef Name,
// Add "sample-profile-suffix-elision-policy" attribute for internal linkage
// functions with -funique-internal-linkage-names.
if (TargetDecl && CodeGenOpts.UniqueInternalLinkageNames) {
- if (isa<FunctionDecl>(TargetDecl)) {
- if (this->getFunctionLinkage(CalleeInfo.getCalleeDecl()) ==
- llvm::GlobalValue::InternalLinkage)
+ if (const auto *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl)) {
+ if (!FD->isExternallyVisible())
FuncAttrs.addAttribute("sample-profile-suffix-elision-policy",
"selected");
}
I'm guessing it would be better to fix the call to isInlineDefinitionExternallyVisible() to handle the no-function-body edge case. I'm not exactly sure if there are other scenarios that would trigger this bug.
On Fri, May 6, 2022 at 12:54 PM Ellis Hoag @.***> wrote:
I've done a bit of investigating for this bug. In the crash, getFunctionLinkage() eventually calls isInlineDefinitionExternallyVisible() on the declaration extern void foo(); and then crashes because it doesn't have a function body. Interestingly, if I reverse the lines in test.c the crash goes away because isInlineDefinitionExternallyVisible() is called on inline void foo() {} instead.
I found a possible solution that uses a different way to find the linkage in CGCall.cpp, but I'm not convinced the behavior is the same. Maybe @tmsri https://github.com/tmsri could help me here.
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index d69455d650f4..a6c6807600f2 100644--- a/clang/lib/CodeGen/CGCall.cpp+++ b/clang/lib/CodeGen/CGCall.cpp@@ -2226,9 +2226,8 @@ void CodeGenModule::ConstructAttributeList(StringRef Name, // Add "sample-profile-suffix-elision-policy" attribute for internal linkage // functions with -funique-internal-linkage-names. if (TargetDecl && CodeGenOpts.UniqueInternalLinkageNames) {- if (isa<FunctionDecl>(TargetDecl)) {- if (this->getFunctionLinkage(CalleeInfo.getCalleeDecl()) ==- llvm::GlobalValue::InternalLinkage)+ if (const auto *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl)) {+ if (!FD->isExternallyVisible()) FuncAttrs.addAttribute("sample-profile-suffix-elision-policy", "selected");
Thanks for looking at this. Shouldn't you also be checking for internal linkage explicitly here? Adding just that check "!FD->isExternallyVisible()" seems like it would work.
}
I'm guessing it would be better to fix the call to isInlineDefinitionExternallyVisible() to handle the no-function-body edge case. I'm not exactly sure if there are other scenarios that would trigger this bug.
— Reply to this email directly, view it on GitHub https://github.com/llvm/llvm-project/issues/54139#issuecomment-1119964664, or unsubscribe https://github.com/notifications/unsubscribe-auth/AJJPQR3M2DAJBVDJSWVM3VLVIV2GHANCNFSM5PVH7L3A . You are receiving this because you were mentioned.Message ID: @.***>
--
Sri Tallam |
Software Engineer |
@.*** |
Thanks for looking at this. Shouldn't you also be checking for internal linkage explicitly here? Adding just that check "!FD->isExternallyVisible()" seems like it would work.
There is no function to directly check for internal linkage from the declaration. From looking at the implementation for isExternallyVisible() I believe negating the result will tell you if it has internal linkage.
I've just posted https://reviews.llvm.org/D135926