-
Notifications
You must be signed in to change notification settings - Fork 13.4k
[Clang,debuginfo] added vtt parameter in destructor DISubroutineType #130674
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
Conversation
@llvm/pr-subscribers-clang @llvm/pr-subscribers-debuginfo Author: None (mgschossmann) ChangesFixes issue #104765: When creating a virtual destructor with an artificial "vtt" argument, the type of "vtt" was previously missing in the This commit fixes this behavior and adds a regression test. Full diff: https://github.com/llvm/llvm-project/pull/130674.diff 3 Files Affected:
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 0e6daa42ee7bf..ae1ce18ee1831 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -2003,8 +2003,17 @@ CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method,
return getOrCreateInstanceMethodType(ThisType, Func, Unit);
}
-llvm::DISubroutineType *CGDebugInfo::getOrCreateInstanceMethodType(
- QualType ThisPtr, const FunctionProtoType *Func, llvm::DIFile *Unit) {
+llvm::DISubroutineType *CGDebugInfo::getOrCreateMethodTypeForDestructor(
+ const CXXMethodDecl *Method, llvm::DIFile *Unit, QualType FNType) {
+ const FunctionProtoType *Func = FNType->getAs<FunctionProtoType>();
+ // skip the first param since it is also this
+ return getOrCreateInstanceMethodType(Method->getThisType(), Func, Unit, true);
+}
+
+llvm::DISubroutineType *
+CGDebugInfo::getOrCreateInstanceMethodType(QualType ThisPtr,
+ const FunctionProtoType *Func,
+ llvm::DIFile *Unit, bool SkipFirst) {
FunctionProtoType::ExtProtoInfo EPI = Func->getExtProtoInfo();
Qualifiers &Qc = EPI.TypeQuals;
Qc.removeConst();
@@ -2044,7 +2053,7 @@ llvm::DISubroutineType *CGDebugInfo::getOrCreateInstanceMethodType(
}
// Copy rest of the arguments.
- for (unsigned i = 1, e = Args.size(); i != e; ++i)
+ for (unsigned i = (SkipFirst ? 2 : 1), e = Args.size(); i != e; ++i)
Elts.push_back(Args[i]);
// Attach FlagObjectPointer to the explicit "this" parameter.
@@ -4352,6 +4361,10 @@ llvm::DISubroutineType *CGDebugInfo::getOrCreateFunctionType(const Decl *D,
// subprogram DIE will miss DW_AT_decl_file and DW_AT_decl_line fields.
return DBuilder.createSubroutineType(DBuilder.getOrCreateTypeArray({}));
+ if (const auto *Method = dyn_cast<CXXDestructorDecl>(D)) {
+ return getOrCreateMethodTypeForDestructor(Method, F, FnType);
+ }
+
if (const auto *Method = dyn_cast<CXXMethodDecl>(D))
return getOrCreateMethodType(Method, F);
diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h
index 38f73eca561b7..8d7591da0f518 100644
--- a/clang/lib/CodeGen/CGDebugInfo.h
+++ b/clang/lib/CodeGen/CGDebugInfo.h
@@ -249,9 +249,14 @@ class CGDebugInfo {
/// to get a method type which includes \c this pointer.
llvm::DISubroutineType *getOrCreateMethodType(const CXXMethodDecl *Method,
llvm::DIFile *F);
+
+ llvm::DISubroutineType *
+ getOrCreateMethodTypeForDestructor(const CXXMethodDecl *Method,
+ llvm::DIFile *F, QualType FNType);
+
llvm::DISubroutineType *
getOrCreateInstanceMethodType(QualType ThisPtr, const FunctionProtoType *Func,
- llvm::DIFile *Unit);
+ llvm::DIFile *Unit, bool SkipFirst = false);
llvm::DISubroutineType *
getOrCreateFunctionType(const Decl *D, QualType FnType, llvm::DIFile *F);
/// \return debug info descriptor for vtable.
diff --git a/clang/test/CodeGenCXX/debug-info-vtt.cpp b/clang/test/CodeGenCXX/debug-info-vtt.cpp
new file mode 100644
index 0000000000000..f888994d08d53
--- /dev/null
+++ b/clang/test/CodeGenCXX/debug-info-vtt.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang -g -c -emit-llvm %s -o - | llvm-dis | FileCheck %s
+
+struct B {
+ virtual ~B() {}
+};
+
+struct A : virtual B {
+};
+
+A a;
+
+// CHECK-DAG: distinct !DISubprogram(name: "~A", linkageName: "_ZN1AD2Ev", {{.*}}, type: ![[subroutinetype:[0-9]+]]
+// CHECK-DAG: ![[subroutinetype]] = !DISubroutineType(types: ![[types:[0-9]+]])
+// CHECK-DAG: [[types]] = !{null, !{{[0-9]+}}, !{{[0-9]+}}}
+
+
|
|
1f54eaa
to
017a07e
Compare
… for i686-pc-windows-msvc)
ping @rnk @dwblaikie @adrian-prantl |
@@ -0,0 +1,16 @@ | |||
// RUN: %clang_cc1 -triple x86_64-none-linux-gnu -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a test for the MSVC ABI, since I don't think it has VTT parameters, and I'm not sure the code you added does the right thing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your comment. Indeed, my code changes behavior when compiling for i686-pc-windows-msvc, which I did not expect.
However, there seems to be the same problem: There is an implicit parameter should_call_delete
, whose DILocalVariable
has arg: 2
even though there is no second argument in the function type's types
array. Similarly to vtt
, the patched code adds this parameter to the array.
Additionally, it changes the return type of the destructor to a void pointer. I am unsure, why this happens, since that does not happen on ItaniumABI. Does the MSVC ABI feature an implicit void return? Unfortunately, I am lacking knowledge of the MSVC ABI to be able to judge what the correct behavior should be.
Following are clang outputs for debug-info-vtt.cpp
:
clang_outputs.zip
PS: I am unsure whether the bug is that the AST is not correctly updated in clang/lib/CodeGen/ItaniumCXXABI.cpp
(and clang/lib/CodeGen/MicrosoftCXXABI.cpp
) or that the AST is not correctly read in clang/lib/CodeGen/CGDebugInfo.cpp
. In the former case, my patch feels like a workaround.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I looked at the files, and I think the new debug info looks good, it adds a DISubroutineType int parameter.
However, I don't understand why the patch you've posted here has that effect. Do you have more local changes? Why does skipping more arguments in this loop create more subroutine parameter types? I'm struggling to understand, and I just assumed adding more testing would provide answers to these questions.
Please do create a test case out of the IR you shared, it does seem relevant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The key change of this pull request is that debug info for destructors is now taken from FNType
instead of D->getType()
/ Method->getType()
. Method->getType()
does not include the implicit arguments, while FNType
does. FNType
however also includes the this
argument. In order to prevent duplicate emission of this
, the pull request introduces the SkipFirst
argument in getOrCreateInstanceMethodType
.
I now also added a test for MSVC, which checks for presence of the should_call_delete
arg. It also enforces that the return value be void*
. The new test seems to pass, however there seems to be an issue in the CI, so it is reported as failed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the comment!
Thanks for your approval. As I do not have write permissions, can you please merge the PR for me? |
…lvm#130674) Fixes issue llvm#104765: When creating a virtual destructor with an artificial "vtt" argument, the type of "vtt" was previously missing in the `DISubroutineType` `types` array. This commit fixes this behavior and adds a regression test.
I believe this commit introduced a crash. Here's a minimal repro:
with the following flags:
|
Thanks! It looks like the new IR after this change doesn't pass verification, and presumably this causes the crash later:
If you disable the verifier you can see the generated IR, but you can't see the "attributes beyond the last parameter". I guess they don't exist, so they don't get printed:
Actual base destructor (D0) prototypes have argument attributes that look like this:
It's not clear what the BPF target is doing that's special that's forcing the compiler to emit this otherwise unused destructor declaration, that seems like the edge case here. Regardless, let's roll it back for now. |
Hm, reverting this change doesn't fix the verifier error, the issue still repros for me with this change reverted. Are we sure this was bisected correctly? Maybe the verifier error was pre-existing, but after this change, now we crash when previously we silently generated IR that doesn't verify. |
That would be my suspicion. I ran two different root cause analyses and they both identified this revision as causing the crash, but I didn't look at verification at all. |
…ineType (#130674)" This reverts commit 27c1aa9. See comments on PR. After this change, Clang now asserts like this: clang: ../llvm/include/llvm/IR/Metadata.h:1435: const MDOperand &llvm::MDNode::getOperand(unsigned int) const: Assertion `I < getNumOperands() && "Out of range"' failed. ... #8 0x000055f345c4e4cb clang::CodeGen::CGDebugInfo::getOrCreateInstanceMethodType() #9 0x000055f345c5ba4f clang::CodeGen::CGDebugInfo::EmitFunctionDecl() #10 0x000055f345b52519 clang::CodeGen::CodeGenModule::EmitExternalFunctionDeclaration() This is due to pre-existing jankiness in the way BPF emits extra declarations for debug info, but we should rollback and then fix forward.
This was actually user error on my side, after messing around a bit I was able to reproduce the problem and confirm that the rollback worked, so I landed it. |
The actual underlying issue appears to come from ae0d224 / #91310 , which added |
Use GetAddrOfGlobal, which is a more general API that takes a GlobalDecl, and handles declaring C++ destructors and other types in a general way. It's possible we can generalize this to handle external variable declarations. This fixes issues reported on llvm#130674 by @lexi-nadia .
We should be able to reland after #137079 lands |
…37079) Use GetAddrOfGlobal, which is a more general API that takes a GlobalDecl, and handles declaring C++ destructors and other types in a general way. We can use this to generalize over functions and variable declarations. This fixes issues reported on #130674 by @lexi-nadia .
I attempted to reapply this patch, but the BPF test which I added fails with this test for reasons I don't understand. @mgschossmann , feel free to take a look if you have time. |
…ineType (llvm#130674)" This reverts commit 27c1aa9. See comments on PR. After this change, Clang now asserts like this: clang: ../llvm/include/llvm/IR/Metadata.h:1435: const MDOperand &llvm::MDNode::getOperand(unsigned int) const: Assertion `I < getNumOperands() && "Out of range"' failed. ... llvm#8 0x000055f345c4e4cb clang::CodeGen::CGDebugInfo::getOrCreateInstanceMethodType() llvm#9 0x000055f345c5ba4f clang::CodeGen::CGDebugInfo::EmitFunctionDecl() llvm#10 0x000055f345b52519 clang::CodeGen::CodeGenModule::EmitExternalFunctionDeclaration() This is due to pre-existing jankiness in the way BPF emits extra declarations for debug info, but we should rollback and then fix forward.
…vm#137079) Use GetAddrOfGlobal, which is a more general API that takes a GlobalDecl, and handles declaring C++ destructors and other types in a general way. We can use this to generalize over functions and variable declarations. This fixes issues reported on llvm#130674 by @lexi-nadia .
…ineType (llvm#130674)" This reverts commit 27c1aa9. See comments on PR. After this change, Clang now asserts like this: clang: ../llvm/include/llvm/IR/Metadata.h:1435: const MDOperand &llvm::MDNode::getOperand(unsigned int) const: Assertion `I < getNumOperands() && "Out of range"' failed. ... llvm#8 0x000055f345c4e4cb clang::CodeGen::CGDebugInfo::getOrCreateInstanceMethodType() llvm#9 0x000055f345c5ba4f clang::CodeGen::CGDebugInfo::EmitFunctionDecl() llvm#10 0x000055f345b52519 clang::CodeGen::CodeGenModule::EmitExternalFunctionDeclaration() This is due to pre-existing jankiness in the way BPF emits extra declarations for debug info, but we should rollback and then fix forward.
…vm#137079) Use GetAddrOfGlobal, which is a more general API that takes a GlobalDecl, and handles declaring C++ destructors and other types in a general way. We can use this to generalize over functions and variable declarations. This fixes issues reported on llvm#130674 by @lexi-nadia .
Fixes issue #104765: When creating a virtual destructor with an artificial "vtt" argument, the type of "vtt" was previously missing in the
DISubroutineType
types
array.This commit fixes this behavior and adds a regression test.