[clang] [clang][DebugInfo] Emit DW_AT_object_pointer on function definitions with explicit `this` (PR #122897)

Michael Buch via cfe-commits cfe-commits at lists.llvm.org
Tue Jan 14 04:49:52 PST 2025


https://github.com/Michael137 created https://github.com/llvm/llvm-project/pull/122897

We currently don't emit `DW_AT_object_pointer` on function declarations or definitions. GCC suffers from the same issue: https://godbolt.org/z/h4jeT54G5

If I interpreted the DWARFv5 spec correctly, it doesn't mandate this attribute be present *only* for implicit object parameters:
```
If the member function entry describes a non-static member function,
then that entry has a DW_AT_object_pointer attribute whose value is a reference to
the formal parameter entry that corresponds to the object for which the
function is called.

That parameter also has a DW_AT_artificial attribute whose value is true.
```

This patch attaches the `DW_AT_object_pointer` for function *defintions*. The declarations will be handled in a separate patch.

The part about `DW_AT_artificial` seems overly restrictive, and not true for explicit object parameters. We probably should relax this part of the DWARF spec.

This will help LLDB identify static vs. non-static member functions (see https://github.com/llvm/llvm-project/issues/120856).

Partially fixes https://github.com/llvm/llvm-project/issues/120974

>From d221dd5ef2c54f63fb6966ca5de8e41c5a8dd6bf Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Tue, 14 Jan 2025 11:33:33 +0000
Subject: [PATCH] [clang][DebugInfo] Emit DW_AT_object_pointer on function
 definitions with explicit `this`

We currently don't emit `DW_AT_object_pointer` on function
declarations or definitions. The DWARFv5 spec doesn't mandate
this attribute be present *only* for implicit object parameters:
```
If the member function entry describes a non-static member function,
then that entry has a DW_AT_object_pointer attribute whose value is a reference to
the formal parameter entry that corresponds to the object for which the
function is called.

That parameter also has a DW_AT_artificial attribute whose value is true.
```

The part about `DW_AT_artificial` seems overly restrictive, and not true for
explicit object parameters. We probably should relax this part of the DWARF spec.

This will help LLDB identify static vs. non-static member functions (see
https://github.com/llvm/llvm-project/issues/120856).

GCC suffers from the same issue: https://godbolt.org/z/h4jeT54G5

Partially fixes https://github.com/llvm/llvm-project/issues/120974
---
 clang/lib/CodeGen/CGDebugInfo.cpp             |  3 ++
 .../CodeGenCXX/debug-info-object-pointer.cpp  | 29 +++++++++++++++++++
 2 files changed, 32 insertions(+)
 create mode 100644 clang/test/CodeGenCXX/debug-info-object-pointer.cpp

diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index d7e5e95b7873a0..f9cba414dcfe2c 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -4829,6 +4829,9 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD,
     if (IPD->getParameterKind() == ImplicitParamKind::CXXThis ||
         IPD->getParameterKind() == ImplicitParamKind::ObjCSelf)
       Flags |= llvm::DINode::FlagObjectPointer;
+  } else if (const auto *PVD = dyn_cast<ParmVarDecl>(VD)) {
+    if (PVD->isExplicitObjectParameter())
+      Flags |= llvm::DINode::FlagObjectPointer;
   }
 
   // Note: Older versions of clang used to emit byval references with an extra
diff --git a/clang/test/CodeGenCXX/debug-info-object-pointer.cpp b/clang/test/CodeGenCXX/debug-info-object-pointer.cpp
new file mode 100644
index 00000000000000..594d4da791ee84
--- /dev/null
+++ b/clang/test/CodeGenCXX/debug-info-object-pointer.cpp
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -x c++ -std=c++23 -debug-info-kind=limited -emit-llvm < %s | FileCheck %s
+
+// CHECK: !DISubprogram(name: "bar",
+// CHECK-SAME:          flags: DIFlagPrototyped
+// CHECK: !DIDerivedType(tag: DW_TAG_pointer_type
+// CHECK-SAME:           flags: DIFlagArtificial | DIFlagObjectPointer
+//
+// // FIXME: DIFlagObjectPointer not attached to the explicit object
+// // argument in the subprogram declaration.
+// CHECK: !DISubprogram(name: "explicit_this",
+//                      flags: DIFlagPrototyped
+// CHECK-NOT: DIFlagObjectPointer
+// CHECK-NOT: DIFlagArtificial
+//
+// CHECK: !DILocalVariable(name: "this", arg: 1
+// CHECK-SAME:             flags: DIFlagArtificial | DIFlagObjectPointer
+//
+// CHECK-NOT: DIFlagArtificial
+// CHECK: !DILocalVariable(arg: 1, {{.*}}, flags: DIFlagObjectPointer)
+
+struct Foo {
+  void bar() {}
+  void explicit_this(this Foo &&) {}
+};
+
+void f() {
+  Foo{}.bar();
+  Foo{}.explicit_this();
+}



More information about the cfe-commits mailing list