Skip to content

[clang][DebugInfo] Add virtuality call-site target information in DWARF.#182510

Merged
CarlosAlbertoEnciso merged 2 commits intollvm:mainfrom
CarlosAlbertoEnciso:callsite-indirect-calls
Feb 25, 2026
Merged

[clang][DebugInfo] Add virtuality call-site target information in DWARF.#182510
CarlosAlbertoEnciso merged 2 commits intollvm:mainfrom
CarlosAlbertoEnciso:callsite-indirect-calls

Conversation

@CarlosAlbertoEnciso
Copy link
Member

Given the test case:

struct CBase {
  virtual void foo();
};

void bar(CBase *Base) {
  Base->foo();
}

and using '-emit-call-site-info' with 'llc', currently the following DWARF is produced for the indirect call 'Base->foo()':

0x10: DW_TAG_structure_type
        DW_AT_name	("CBase")

0x20:   DW_TAG_subprogram
          DW_AT_linkage_name	("_ZN5CBase3fooEv")
          DW_AT_name	("foo")
          ...

0x30: DW_TAG_subprogram
        DW_AT_linkage_name	("_Z3barP5CBase")
        DW_AT_name	("bar")
        ...

0x40:   DW_TAG_call_site
          DW_AT_call_target_clobbered	(DW_OP_breg0 RAX+0)
          DW_AT_call_return_pc	(0x000000000000000a)

Initial context from the SCE debugger point of view:

We can detect when a function has been affected by Identical Code Folding (ICF) from DWARF call-site information. For example,

  1. $RIP is currently in 'bar()'
  2. The call-site information in the parent frame indicates we should have called 'foo()'

If we see a situation like the above, we can infer that 'foo()' and 'bar()' have been code folded. This technique breaks when dealing with virtual functions because the call-site information only provides a way to find the target function at runtime.

However, if the call-site information includes information on which virtual function is being called, we can compare this against the $RIP location to see if we are in an implementation of the virtual function. If we are not, then we can assume we have been code folded.

For this to work we just to need to record which virtual function we are calling. We do not need to know the type of the 'this' pointer at the call-site.

This patch (available for all debuggers) helps in the identification of the intended target of a virtual call in the SCE debugger.

By adding the DW_AT_LLVM_virtual_call_origin for indirect calls, a debugger can identify the intended target of a call. These are the specific actions taking by the SCE debugger:

  • The debugger can detect functions that have been folding by comparing whether the DW_AT_call_origin matches the call frame function. If it does not, the debugger can assume the "true" target and the actual target have been code folded and add a frame annotation to the call stack to indicate this. That, or there is a tail call from foo to bar, but the debugger can disambiguate these cases by looking at the DW_AT_call_origin referenced subroutine DIE which has a tombstone DW_AT_low_pc in the ICF case.

  • For virtual calls such as the given test case, the existence of the DW_AT_LLVM_virtual_call_origin attribute tells the debugger that this is an indirect jump, and the DW_AT_LLVM_virtual_call_origin attribute, pointing to the base class method DIE, will tell which method is being called.

  • The debugger can confirm from the method's DIE that it is a virtual function call by looking at the attributes (DW_AT_virtuality, and DW_AT_vtable_elem_location) and can look at the parent DIE to work out the type.

This is the added DW_AT_LLVM_virtual_call_origin to identify the target call CBase::foo.

0x40:   DW_TAG_call_site
          DW_AT_call_target_clobbered	(DW_OP_breg0 RAX+0)
          DW_AT_call_return_pc	(0x000000000000000a)
          -----------------------------------------------
          DW_AT_LLVM_virtual_call_origin	(0x20 "_ZN5CBase3fooEv")
          -----------------------------------------------

The extra call site information is available by default for all debuggers and it is generated only for DWARF 5 or greater.

Given the test case:

  struct CBase {
    virtual void foo();
  };

  void bar(CBase *Base) {
    Base->foo();
  }

and using '-emit-call-site-info' with llc, the following DWARF
is produced for the indirect call 'Base->foo()':

1$: DW_TAG_structure_type "CBase"
      ...
2$:   DW_TAG_subprogram "foo"
        ...

3$: DW_TAG_subprogram "bar"
      ...
4$:   DW_TAG_call_site
        ...

We add DW_AT_LLVM_virtual_call_origin to existing call-site
information, linking indirect calls to the function-declaration
they correspond to.

4$:   DW_TAG_call_site
        ...
        DW_AT_LLVM_virtual_call_origin (2$ "_ZN5CBase3fooEv")

The new attribute DW_AT_LLVM_virtual_call_origin helps to
address the ambiguity to any consumer due to the usage of
DW_AT_call_origin.

The functionality is available to all supported debuggers.
@llvmbot
Copy link
Member

llvmbot commented Feb 20, 2026

@llvm/pr-subscribers-clang-codegen
@llvm/pr-subscribers-llvm-selectiondag
@llvm/pr-subscribers-lldb
@llvm/pr-subscribers-backend-aarch64
@llvm/pr-subscribers-backend-risc-v

@llvm/pr-subscribers-backend-mips

Author: Carlos Alberto Enciso (CarlosAlbertoEnciso)

Changes

Given the test case:

struct CBase {
  virtual void foo();
};

void bar(CBase *Base) {
  Base->foo();
}

and using '-emit-call-site-info' with 'llc', currently the following DWARF is produced for the indirect call 'Base->foo()':

0x10: DW_TAG_structure_type
        DW_AT_name	("CBase")

0x20:   DW_TAG_subprogram
          DW_AT_linkage_name	("_ZN5CBase3fooEv")
          DW_AT_name	("foo")
          ...

0x30: DW_TAG_subprogram
        DW_AT_linkage_name	("_Z3barP5CBase")
        DW_AT_name	("bar")
        ...

0x40:   DW_TAG_call_site
          DW_AT_call_target_clobbered	(DW_OP_breg0 RAX+0)
          DW_AT_call_return_pc	(0x000000000000000a)

Initial context from the SCE debugger point of view:

> We can detect when a function has been affected by Identical Code Folding (ICF) from DWARF call-site information. For example,
>
> 1. $RIP is currently in 'bar()'
> 2. The call-site information in the parent frame indicates we should have called 'foo()'
>
> If we see a situation like the above, we can infer that 'foo()' and 'bar()' have been code folded. This technique breaks when dealing with virtual functions because the call-site information only provides a way to find the target function at runtime.
>
> However, if the call-site information includes information on which virtual function is being called, we can compare this against the $RIP location to see if we are in an implementation of the virtual function. If we are not, then we can assume we have been code folded.
>
> For this to work we just to need to record which virtual function we are calling. We do not need to know the type of the 'this' pointer at the call-site.
>

This patch (available for all debuggers) helps in the identification of the intended target of a virtual call in the SCE debugger.

By adding the DW_AT_LLVM_virtual_call_origin for indirect calls, a debugger can identify the intended target of a call. These are the specific actions taking by the SCE debugger:

  • The debugger can detect functions that have been folding by comparing whether the DW_AT_call_origin matches the call frame function. If it does not, the debugger can assume the "true" target and the actual target have been code folded and add a frame annotation to the call stack to indicate this. That, or there is a tail call from foo to bar, but the debugger can disambiguate these cases by looking at the DW_AT_call_origin referenced subroutine DIE which has a tombstone DW_AT_low_pc in the ICF case.

  • For virtual calls such as the given test case, the existence of the DW_AT_LLVM_virtual_call_origin attribute tells the debugger that this is an indirect jump, and the DW_AT_LLVM_virtual_call_origin attribute, pointing to the base class method DIE, will tell which method is being called.

  • The debugger can confirm from the method's DIE that it is a virtual function call by looking at the attributes (DW_AT_virtuality, and DW_AT_vtable_elem_location) and can look at the parent DIE to work out the type.

This is the added DW_AT_LLVM_virtual_call_origin to identify the target call CBase::foo.

0x40:   DW_TAG_call_site
          DW_AT_call_target_clobbered	(DW_OP_breg0 RAX+0)
          DW_AT_call_return_pc	(0x000000000000000a)
          -----------------------------------------------
          DW_AT_LLVM_virtual_call_origin	(0x20 "_ZN5CBase3fooEv")
          -----------------------------------------------

The extra call site information is available by default for all debuggers and it is generated only for DWARF 5 or greater.


Patch is 32.70 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/182510.diff

25 Files Affected:

  • (modified) clang/lib/CodeGen/CGCall.cpp (+2)
  • (modified) clang/lib/CodeGen/CGDebugInfo.cpp (+23)
  • (modified) clang/lib/CodeGen/CGDebugInfo.h (+6)
  • (added) clang/test/DebugInfo/CXX/callsite-base.cpp (+70)
  • (added) clang/test/DebugInfo/CXX/callsite-derived.cpp (+58)
  • (added) clang/test/DebugInfo/CXX/callsite-edges.cpp (+93)
  • (added) cross-project-tests/debuginfo-tests/clang_llvm_roundtrip/callsite-crash.cpp (+20)
  • (added) cross-project-tests/debuginfo-tests/clang_llvm_roundtrip/callsite-dwarf.cpp (+99)
  • (modified) llvm/include/llvm/BinaryFormat/Dwarf.def (+1)
  • (modified) llvm/include/llvm/CodeGen/MachineFunction.h (+6)
  • (modified) llvm/include/llvm/CodeGen/TargetLowering.h (+4)
  • (modified) llvm/include/llvm/IR/FixedMetadataKinds.def (+1)
  • (modified) llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp (+10-5)
  • (modified) llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h (+4)
  • (modified) llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (+28-1)
  • (modified) llvm/lib/CodeGen/MIRPrinter.cpp (+1-1)
  • (modified) llvm/lib/CodeGen/MachineFunction.cpp (+3)
  • (modified) llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp (+14)
  • (modified) llvm/lib/DebugInfo/DWARF/DWARFDie.cpp (+2-1)
  • (modified) llvm/lib/Target/AArch64/AArch64ISelLowering.cpp (+1-2)
  • (modified) llvm/lib/Target/ARM/ARMISelLowering.cpp (+1-2)
  • (modified) llvm/lib/Target/Mips/MipsISelLowering.cpp (+1-2)
  • (modified) llvm/lib/Target/RISCV/RISCVISelLowering.cpp (+1-2)
  • (modified) llvm/lib/Target/X86/X86ISelLoweringCall.cpp (+1-2)
  • (modified) llvm/test/CodeGen/MIR/X86/callsite-emit-calleetypeid.ll (+3-5)
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 1d950ffed8a0b..b57802ebfced8 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -6438,6 +6438,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
       DI->EmitFuncDeclForCallSite(
           CI, DI->getFunctionType(CalleeDecl, ResTy, Args), CalleeGlobalDecl);
     }
+    // Generate call site target information.
+    DI->addCallTargetIfVirtual(CalleeDecl, CI);
   }
 
   return Ret;
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 2b123631c526c..401d8bc16d290 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -2332,6 +2332,12 @@ CGDebugInfo::GetMethodLinkageName(const CXXMethodDecl *Method) const {
   return CGM.getMangledName(Method);
 }
 
+bool CGDebugInfo::shouldGenerateVirtualCallSite() const {
+  // Check general conditions for call site generation.
+  return ((getCallSiteRelatedAttrs() != llvm::DINode::FlagZero) &&
+          (CGM.getCodeGenOpts().DwarfVersion >= 5));
+}
+
 llvm::DISubprogram *CGDebugInfo::CreateCXXMemberFunction(
     const CXXMethodDecl *Method, llvm::DIFile *Unit, llvm::DIType *RecordTy) {
   assert(Method);
@@ -4985,6 +4991,23 @@ void CGDebugInfo::EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc,
     Fn->setSubprogram(SP);
 }
 
+void CGDebugInfo::addCallTargetIfVirtual(const FunctionDecl *FD,
+                                         llvm::CallBase *CI) {
+  if (!shouldGenerateVirtualCallSite())
+    return;
+
+  if (!FD)
+    return;
+
+  assert(CI && "Invalid Call Instruction.");
+  if (!CI->isIndirectCall())
+    return;
+
+  // Always get the method declaration.
+  if (llvm::DISubprogram *MD = getFunctionDeclaration(FD))
+    CI->setMetadata(llvm::LLVMContext::MD_call_target, MD);
+}
+
 void CGDebugInfo::EmitFuncDeclForCallSite(llvm::CallBase *CallOrInvoke,
                                           QualType CalleeType,
                                           GlobalDecl CalleeGlobalDecl) {
diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h
index b36a597a80ede..8e1eda2d93ac0 100644
--- a/clang/lib/CodeGen/CGDebugInfo.h
+++ b/clang/lib/CodeGen/CGDebugInfo.h
@@ -683,6 +683,9 @@ class CGDebugInfo {
   /// that it is supported and enabled.
   llvm::DINode::DIFlags getCallSiteRelatedAttrs() const;
 
+  /// Add call target information.
+  void addCallTargetIfVirtual(const FunctionDecl *FD, llvm::CallBase *CI);
+
 private:
   /// Amend \p I's DebugLoc with \p Group (its source atom group) and \p
   /// Rank (lower nonzero rank is higher precedence). Does nothing if \p I
@@ -907,6 +910,9 @@ class CGDebugInfo {
   /// If one exists, returns the linkage name of the specified \
   /// (non-null) \c Method. Returns empty string otherwise.
   llvm::StringRef GetMethodLinkageName(const CXXMethodDecl *Method) const;
+
+  /// Returns true if we should generate call target information.
+  bool shouldGenerateVirtualCallSite() const;
 };
 
 /// A scoped helper to set the current debug location to the specified
diff --git a/clang/test/DebugInfo/CXX/callsite-base.cpp b/clang/test/DebugInfo/CXX/callsite-base.cpp
new file mode 100644
index 0000000000000..399e62ede0dec
--- /dev/null
+++ b/clang/test/DebugInfo/CXX/callsite-base.cpp
@@ -0,0 +1,70 @@
+// RUN: %clang_cc1 -triple=x86_64-linux -disable-llvm-passes -emit-llvm \
+// RUN:            -debug-info-kind=standalone -dwarf-version=5 -O1 %s \
+// RUN: -o - | FileCheck %s -check-prefix CHECK-BASE
+
+// RUN: %clang_cc1 -triple=x86_64-linux -disable-llvm-passes -emit-llvm \
+// RUN:            -debug-info-kind=standalone -dwarf-version=4 -O1 %s \
+// RUN: -o - | FileCheck %s -check-prefix CHECK-BASE-DW4
+
+// Simple class with only virtual methods: inlined and not-inlined
+//
+// The following three scenarios are considered:
+// - out-of-line defined virtual member function (f1)
+// - declared-but-not-defined virtual member function (f2)
+// - inline defined virtual member function (f3)
+//
+// 1) We check for a generated 'call_target' for: 'f1', 'f2' and 'f3'.
+// 2) Check that the 'CBase' type is defined.
+
+struct CBase {
+  virtual void f1();
+  virtual void f2();
+  virtual void f3() {}
+};
+void CBase::f1() {}
+
+void bar(CBase *Base) {
+  Base->f1();
+  Base->f2();
+  Base->f3();
+
+  // Because this will instantiate the ctor, the CBase type should be defined.
+  CBase B;
+  B.f1();
+}
+
+// CHECK-BASE: %struct.CBase = type { ptr }
+
+// CHECK-BASE: define {{.*}} @_Z3barP5CBase{{.*}} {
+// CHECK-BASE:   alloca %struct.CBase
+// CHECK-BASE:   call void %1{{.*}} !dbg {{![0-9]+}}, !call_target [[BASE_F1_DCL:![0-9]+]]
+// CHECK-BASE:   call void %3{{.*}} !dbg {{![0-9]+}}, !call_target [[BASE_F2_DCL:![0-9]+]]
+// CHECK-BASE:   call void %5{{.*}} !dbg {{![0-9]+}}, !call_target [[BASE_F3_DCL:![0-9]+]]
+// CHECK-BASE:   call void @_ZN5CBaseC1Ev{{.*}} !dbg {{![0-9]+}}
+// CHECK-BASE:   call void @_ZN5CBase2f1Ev{{.*}} !dbg {{![0-9]+}}
+// CHECK-BASE: }
+
+// CHECK-BASE: [[BASE_F1_DCL]] = {{.*}}!DISubprogram(name: "f1", linkageName: "_ZN5CBase2f1Ev", {{.*}}containingType
+// CHECK-BASE: [[BASE_F2_DCL]] = {{.*}}!DISubprogram(name: "f2", linkageName: "_ZN5CBase2f2Ev", {{.*}}containingType
+// CHECK-BASE: [[BASE_F3_DCL]] = {{.*}}!DISubprogram(name: "f3", linkageName: "_ZN5CBase2f3Ev", {{.*}}containingType
+
+// CHECK-BASE: [[BASE_F1_DEF:![0-9]+]] = {{.*}}!DISubprogram(name: "f1", linkageName: "_ZN5CBase2f1Ev", {{.*}}DISPFlagDefinition
+// CHECK-BASE: [[BASE_F3_DEF:![0-9]+]] = {{.*}}!DISubprogram(name: "f3", linkageName: "_ZN5CBase2f3Ev", {{.*}}DISPFlagDefinition
+
+// CHECK-BASE-DW4: %struct.CBase = type { ptr }
+
+// CHECK-BASE-DW4: define {{.*}} @_Z3barP5CBase{{.*}} {
+// CHECK-BASE-DW4:   alloca %struct.CBase
+// CHECK-BASE-DW4:   call void %1{{.*}} !dbg {{![0-9]+}}
+// CHECK-BASE-DW4:   call void %3{{.*}} !dbg {{![0-9]+}}
+// CHECK-BASE-DW4:   call void %5{{.*}} !dbg {{![0-9]+}}
+// CHECK-BASE-DW4:   call void @_ZN5CBaseC1Ev{{.*}} !dbg {{![0-9]+}}
+// CHECK-BASE-DW4:   call void @_ZN5CBase2f1Ev{{.*}} !dbg {{![0-9]+}}
+// CHECK-BASE-DW4: }
+
+// CHECK-BASE-DW4: {{.*}}!DISubprogram(name: "f1", linkageName: "_ZN5CBase2f1Ev", {{.*}}containingType
+// CHECK-BASE-DW4: {{.*}}!DISubprogram(name: "f2", linkageName: "_ZN5CBase2f2Ev", {{.*}}containingType
+// CHECK-BASE-DW4: {{.*}}!DISubprogram(name: "f3", linkageName: "_ZN5CBase2f3Ev", {{.*}}containingType
+
+// CHECK-BASE-DW4: {{.*}}!DISubprogram(name: "f1", linkageName: "_ZN5CBase2f1Ev", {{.*}}DISPFlagDefinition
+// CHECK-BASE-DW4: {{.*}}!DISubprogram(name: "f3", linkageName: "_ZN5CBase2f3Ev", {{.*}}DISPFlagDefinition
diff --git a/clang/test/DebugInfo/CXX/callsite-derived.cpp b/clang/test/DebugInfo/CXX/callsite-derived.cpp
new file mode 100644
index 0000000000000..3338290bdd829
--- /dev/null
+++ b/clang/test/DebugInfo/CXX/callsite-derived.cpp
@@ -0,0 +1,58 @@
+// RUN: %clang_cc1 -triple=x86_64-linux -disable-llvm-passes -emit-llvm \
+// RUN:            -debug-info-kind=constructor -dwarf-version=5 -O1 %s \
+// RUN:            -o - | FileCheck %s -check-prefix CHECK-DERIVED
+
+// Simple base and derived class with virtual and static methods:
+// We check for:
+// - a generated 'call_target' for 'f1'.
+// - not generated 'call_target' for 'f3'.
+
+struct CBase {
+  virtual void f1() {}
+  static void f3();
+};
+
+void CBase::f3() {
+}
+
+void foo(CBase *Base) {
+  CBase::f3();
+}
+
+struct CDerived : public CBase {
+  void f1() {}
+};
+void foo(CDerived *Derived);
+
+int main() {
+  CDerived D;
+  foo(&D);
+
+  return 0;
+}
+
+void foo(CDerived *Derived) {
+  Derived->f1();
+}
+
+// CHECK-DERIVED: define {{.*}} @_Z3fooP5CBase{{.*}} {
+// CHECK-DERIVED: call void @_ZN5CBase2f3Ev{{.*}} !dbg {{![0-9]+}}
+// CHECK-DERIVED: }
+
+// CHECK-DERIVED: define {{.*}} @main{{.*}} {
+// CHECK-DERIVED:  call void @_ZN8CDerivedC1Ev{{.*}} !dbg {{![0-9]+}}
+// CHECK-DERIVED:  call void @_Z3fooP8CDerived{{.*}} !dbg {{![0-9]+}}
+// CHECK-DERIVED: }
+
+// CHECK-DERIVED: define {{.*}} @_ZN8CDerivedC1Ev{{.*}} {
+// CHECK-DERIVED:  call void @_ZN8CDerivedC2Ev{{.*}} !dbg {{![0-9]+}}
+// CHECK-DERIVED: }
+
+// CHECK-DERIVED: define {{.*}} @_Z3fooP8CDerived{{.*}} {
+// CHECK-DERIVED:  call void %1{{.*}} !dbg {{![0-9]+}}, !call_target [[DERIVED_F1_DCL:![0-9]+]]
+// CHECK-DERIVED: }
+
+// CHECK-DERIVED: [[BASE_F1_DCL:![0-9]+]] = {{.*}}!DISubprogram(name: "f1", linkageName: "_ZN5CBase2f1Ev", {{.*}}containingType
+// CHECK-DERIVED: [[DERIVED_F1_DCL]] = {{.*}}!DISubprogram(name: "f1", linkageName: "_ZN8CDerived2f1Ev", {{.*}}containingType
+// CHECK-DERIVED: [[DERIVED_F1_DEF:![0-9]+]] = {{.*}}!DISubprogram(name: "f1", linkageName: "_ZN8CDerived2f1Ev", {{.*}}DISPFlagDefinition
+// CHECK-DERIVED: [[BASE_F1_DEF:![0-9]+]] = {{.*}}!DISubprogram(name: "f1", linkageName: "_ZN5CBase2f1Ev", {{.*}}DISPFlagDefinition
diff --git a/clang/test/DebugInfo/CXX/callsite-edges.cpp b/clang/test/DebugInfo/CXX/callsite-edges.cpp
new file mode 100644
index 0000000000000..812cfc1fb4cf2
--- /dev/null
+++ b/clang/test/DebugInfo/CXX/callsite-edges.cpp
@@ -0,0 +1,93 @@
+// RUN: %clang_cc1 -triple=x86_64-linux -disable-llvm-passes -emit-llvm \
+// RUN:            -debug-info-kind=constructor -dwarf-version=5 -O1 %s \
+// RUN:            -o - | FileCheck %s -check-prefix CHECK-EDGES
+
+// The following are identified edge cases involving the method being called:
+// 1) Method is declared but not defined in current CU.
+// 2) Pure virtual method but not defined in current CU.
+// 3) Virtual method defined in a deeply nested structure hierarchy.
+
+//---------------------------------------------------------------------
+// 1) Method is declared but not defined in current CU - Pass.
+//    Generate 'call_target' metadata for 'f1' and 'f2'.
+//---------------------------------------------------------------------
+struct CEmpty {
+  virtual void f1();
+  virtual void f2();
+};
+
+void CEmpty::f2() {
+}
+
+void edge_a(CEmpty *Empty) {
+  Empty->f1();
+  Empty->f2();
+}
+
+//---------------------------------------------------------------------
+// 2) Pure virtual method but not defined in current CU - Pass.
+//    Generate 'call_target' metadata for 'f1' and 'f2'.
+//---------------------------------------------------------------------
+struct CBase {
+  virtual void f1() = 0;
+  virtual void f2();
+};
+
+void CBase::f2() {
+}
+
+void edge_b(CBase *Base) {
+  Base->f1();
+  Base->f2();
+}
+
+//---------------------------------------------------------------------
+// 3) Virtual method defined in a deeply nested structure hierarchy - Pass.
+//    Generate 'call_target' metadata for 'd0', 'd1', 'd2' and 'd3'.
+//---------------------------------------------------------------------
+struct CD0 {
+  struct CD1 {
+    virtual void d1();
+  };
+
+  CD1 D1;
+  virtual void d0();
+};
+
+void CD0::d0() {}
+void CD0::CD1::d1() {}
+
+void edge_c(CD0 *D0) {
+  D0->d0();
+
+  CD0::CD1 *D1 = &D0->D1;
+  D1->d1();
+}
+
+// CHECK-EDGES: define {{.*}} @_Z6edge_aP6CEmpty{{.*}} {
+// CHECK-EDGES:  call void %1{{.*}} !dbg {{![0-9]+}}, !call_target [[CEMPTY_F1_DCL:![0-9]+]]
+// CHECK-EDGES:  call void %3{{.*}} !dbg {{![0-9]+}}, !call_target [[CEMPTY_F2_DCL:![0-9]+]]
+// CHECK-EDGES: }
+
+// CHECK-EDGES: define {{.*}} @_Z6edge_bP5CBase{{.*}} {
+// CHECK-EDGES:  call void %1{{.*}} !dbg {{![0-9]+}}, !call_target [[CBASE_F1_DCL:![0-9]+]]
+// CHECK-EDGES:  call void %3{{.*}} !dbg {{![0-9]+}}, !call_target [[CBASE_F2_DCL:![0-9]+]]
+// CHECK-EDGES: }
+
+// CHECK-EDGES: define {{.*}} @_Z6edge_cP3CD0{{.*}} {
+// CHECK-EDGES:  call void %1{{.*}} !dbg {{![0-9]+}}, !call_target [[CD0_D0_DCL:![0-9]+]]
+// CHECK-EDGES:  call void %4{{.*}} !dbg {{![0-9]+}}, !call_target [[CD0_D1_DCL:![0-9]+]]
+// CHECK-EDGES: }
+
+// CHECK-EDGES:  [[CD0_D1_DCL]] = {{.*}}!DISubprogram(name: "d1", linkageName: "_ZN3CD03CD12d1Ev", {{.*}}containingType
+// CHECK-EDGES:  [[CD0_D0_DCL]] = {{.*}}!DISubprogram(name: "d0", linkageName: "_ZN3CD02d0Ev", {{.*}}containingType
+
+// CHECK-EDGES:  [[CBASE_F1_DCL]] = {{.*}}!DISubprogram(name: "f1", linkageName: "_ZN5CBase2f1Ev", {{.*}}containingType
+// CHECK-EDGES:  [[CBASE_F2_DCL]] = {{.*}}!DISubprogram(name: "f2", linkageName: "_ZN5CBase2f2Ev", {{.*}}containingType
+// CHECK-EDGES:  [[CEMPTY_F2_DEF:![0-9]+]] = {{.*}}!DISubprogram(name: "f2", linkageName: "_ZN6CEmpty2f2Ev", {{.*}}DISPFlagDefinition
+// CHECK-EDGES:  [[CEMPTY_F2_DCL]] = {{.*}}!DISubprogram(name: "f2", linkageName: "_ZN6CEmpty2f2Ev", {{.*}}containingType
+// CHECK-EDGES:  [[CEMPTY_F1_DCL]] = {{.*}}!DISubprogram(name: "f1", linkageName: "_ZN6CEmpty2f1Ev", {{.*}}containingType
+// CHECK-EDGES:  [[CBASE_F2_DEF:![0-9]+]] = {{.*}}!DISubprogram(name: "f2", linkageName: "_ZN5CBase2f2Ev", {{.*}}DISPFlagDefinition
+
+// CHECK-EDGES:  [[CD0_D0_DEF:![0-9]+]] = {{.*}}!DISubprogram(name: "d0", linkageName: "_ZN3CD02d0Ev", {{.*}}DISPFlagDefinition
+// CHECK-EDGES:  [[CD0_D1_DEF:![0-9]+]] = {{.*}}!DISubprogram(name: "d1", linkageName: "_ZN3CD03CD12d1Ev", {{.*}}DISPFlagDefinition
diff --git a/cross-project-tests/debuginfo-tests/clang_llvm_roundtrip/callsite-crash.cpp b/cross-project-tests/debuginfo-tests/clang_llvm_roundtrip/callsite-crash.cpp
new file mode 100644
index 0000000000000..745ac967528da
--- /dev/null
+++ b/cross-project-tests/debuginfo-tests/clang_llvm_roundtrip/callsite-crash.cpp
@@ -0,0 +1,20 @@
+// REQUIRES: aarch64-registered-target
+
+// RUN: %clang --target=aarch64-unknown-fuchsia -c -g -O1 -gdwarf-4 %s -o - | \
+// RUN: llvm-dwarfdump --debug-info - | FileCheck %s --check-prefix=CHECK
+
+struct Base {
+  virtual void foo();
+} *B;
+
+void bar() {
+  B->foo();
+}
+
+// CHECK: DW_TAG_compile_unit
+// CHECK:   DW_TAG_subprogram
+// CHECK:     DW_AT_GNU_all_call_sites	(true)
+// CHECK:     DW_AT_linkage_name	("_Z3barv")
+// CHECK:     DW_TAG_GNU_call_site
+// CHECK:       DW_AT_GNU_call_site_target_clobbered
+// CHECK:       DW_AT_GNU_tail_call	(true)
diff --git a/cross-project-tests/debuginfo-tests/clang_llvm_roundtrip/callsite-dwarf.cpp b/cross-project-tests/debuginfo-tests/clang_llvm_roundtrip/callsite-dwarf.cpp
new file mode 100644
index 0000000000000..9fe6df6a0f61d
--- /dev/null
+++ b/cross-project-tests/debuginfo-tests/clang_llvm_roundtrip/callsite-dwarf.cpp
@@ -0,0 +1,99 @@
+// REQUIRES: x86-registered-target
+
+// RUN: %clang --target=x86_64-linux -c -g -O1 -gdwarf-5 %s -o - | \
+// RUN: llvm-dwarfdump --debug-info - | FileCheck %s --check-prefix=CHECK
+
+// RUN: %clang --target=x86_64-linux -c -g -O1 -gdwarf-4 %s -o - | \
+// RUN: llvm-dwarfdump --debug-info - | FileCheck %s --check-prefix=CHECK-DW4
+
+// Simple base and derived class with virtual:
+// We check for a generated 'DW_AT_LLVM_virtual_call_origin' for 'foo', that
+// corresponds to the 'call_target' metadata added to the indirect call
+// instruction, when generating DWARF-5 or greater.
+
+// Note: We should add a test case inside LLDB that make use of the
+//       virtuality call-site target information in DWARF.
+
+struct CBaseOne {
+  virtual void foo(int &);
+};
+
+struct CDerivedOne : CBaseOne {
+  void foo(int &);
+};
+
+void CDerivedOne::foo(int &) {}
+
+struct CBaseTwo {
+  CDerivedOne *DerivedOne;
+};
+
+struct CDerivedTwo : CBaseTwo {
+  void bar(int &);
+};
+
+void CDerivedTwo::bar(int &j) { DerivedOne->foo(j); }
+
+// The IR generated looks like:
+//
+// define dso_local void @_ZN11CDerivedTwo3barERi(...) !dbg !40 {
+// entry:
+//   ..
+//   %vtable = load ptr, ptr %0, align 8
+//   %vfn = getelementptr inbounds ptr, ptr %vtable, i64 0
+//   %2 = load ptr, ptr %vfn, align 8
+//   call void %2(...), !dbg !65, !call_target !25
+//   ret void
+// }
+//
+// !25 = !DISubprogram(name: "foo", linkageName: "_ZN11CDerivedOne3fooERi", ...)
+// !40 = !DISubprogram(name: "bar", linkageName: "_ZN11CDerivedTwo3barERi", ...)
+// !65 = !DILocation(line: 25, column: 15, scope: !40)
+
+// CHECK: DW_TAG_compile_unit
+// CHECK:   DW_TAG_structure_type
+// CHECK:     DW_AT_name	("CDerivedOne")
+// CHECK: [[FOO_DCL:0x[a-f0-9]+]]:    DW_TAG_subprogram
+// CHECK:       DW_AT_name	("foo")
+// CHECK:   DW_TAG_structure_type
+// CHECK:     DW_AT_name	("CBaseOne")
+// CHECK: [[FOO_DEF:0x[a-f0-9]+]]:  DW_TAG_subprogram
+// CHECK:     DW_AT_call_all_calls	(true)
+// CHECK:     DW_AT_specification	([[FOO_DCL]] "{{.*}}foo{{.*}}")
+// CHECK:   DW_TAG_structure_type
+// CHECK:     DW_AT_name	("CDerivedTwo")
+// CHECK:     DW_TAG_subprogram
+// CHECK:       DW_AT_name	("bar")
+// CHECK:   DW_TAG_structure_type
+// CHECK:     DW_AT_name	("CBaseTwo")
+// CHECK:   DW_TAG_subprogram
+// CHECK:     DW_AT_call_all_calls	(true)
+// CHECK:     DW_AT_specification	(0x{{.*}} "{{.*}}bar{{.*}}")
+// CHECK:     DW_TAG_call_site
+// CHECK:       DW_AT_call_target_clobbered	(DW_OP_reg0 RAX)
+// CHECK:       DW_AT_call_tail_call	(true)
+// CHECK:       DW_AT_call_pc	(0x{{.*}})
+// CHECK:       DW_AT_LLVM_virtual_call_origin	([[FOO_DCL]] "{{.*}}foo{{.*}}")
+
+// CHECK-DW4: DW_TAG_compile_unit
+// CHECK-DW4:   DW_TAG_structure_type
+// CHECK-DW4:     DW_AT_name	("CDerivedOne")
+// CHECK-DW4: [[FOO_DCL:0x[a-f0-9]+]]:    DW_TAG_subprogram
+// CHECK-DW4:       DW_AT_name	("foo")
+// CHECK-DW4:   DW_TAG_structure_type
+// CHECK-DW4:     DW_AT_name	("CBaseOne")
+// CHECK-DW4: [[FOO_DEF:0x[a-f0-9]+]]:  DW_TAG_subprogram
+// CHECK-DW4:     DW_AT_GNU_all_call_sites	(true)
+// CHECK-DW4:     DW_AT_specification	([[FOO_DCL]] "{{.*}}foo{{.*}}")
+// CHECK-DW4:   DW_TAG_structure_type
+// CHECK-DW4:     DW_AT_name	("CDerivedTwo")
+// CHECK-DW4:     DW_TAG_subprogram
+// CHECK-DW4:       DW_AT_name	("bar")
+// CHECK-DW4:   DW_TAG_structure_type
+// CHECK-DW4:     DW_AT_name	("CBaseTwo")
+// CHECK-DW4:   DW_TAG_subprogram
+// CHECK-DW4:     DW_AT_GNU_all_call_sites	(true)
+// CHECK-DW4:     DW_AT_specification	(0x{{.*}} "{{.*}}bar{{.*}}")
+// CHECK-DW4:     DW_TAG_GNU_call_site
+// CHECK-DW4:       DW_AT_GNU_call_site_target_clobbered	(DW_OP_reg0 RAX)
+// CHECK-DW4:       DW_AT_GNU_tail_call	(true)
diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def
index 75f1061c471c6..50b83884c851a 100644
--- a/llvm/include/llvm/BinaryFormat/Dwarf.def
+++ b/llvm/include/llvm/BinaryFormat/Dwarf.def
@@ -647,6 +647,7 @@ HANDLE_DW_AT(0x3e10, LLVM_address_space, 0, LLVM)
 HANDLE_DW_AT(0x3e11, LLVM_lanes, 0, LLVM)
 HANDLE_DW_AT(0x3e12, LLVM_lane_pc, 0, LLVM)
 HANDLE_DW_AT(0x3e13, LLVM_vector_size, 0, LLVM)
+HANDLE_DW_AT(0x3e14, LLVM_virtual_call_origin, 0, LLVM)
 
 // https://llvm.org/docs/AMDGPUUsage.html#address-space-identifier
 HANDLE_DW_ASPACE(0x0, none)
diff --git a/llvm/include/llvm/CodeGen/MachineFunction.h b/llvm/include/llvm/CodeGen/MachineFunction.h
index edb8963ce42b6..26b6c457a45ba 100644
--- a/llvm/include/llvm/CodeGen/MachineFunction.h
+++ b/llvm/include/llvm/CodeGen/MachineFunction.h
@@ -526,11 +526,17 @@ class LLVM_ABI MachineFunction {
     /// Callee type ids.
     SmallVector<ConstantInt *, 4> CalleeTypeIds;
 
+    /// 'call_target' metadata for the DISubprogram. It is the declaration
+    /// or definition of the target function and might be indirect.
+    MDNode *CallTarget = nullptr;
+
     CallSiteInfo() = default;
 
     /// Extracts the numeric type id from the CallBase's callee_type Metadata,
     /// and sets CalleeTypeIds. This is used as type id for the indirect call in
     /// the call graph section.
+    /// Extracts the MDNode from the CallBase's call_target Metadata to be used
+    /// during the construction of the debug info call site entries.
     LLVM_ABI CallSiteInfo(const CallBase &CB);
   };
 
diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index 37002d3bc227f..39699cb19a4b7 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -5936,6 +5936,10 @@ class LLVM_ABI TargetLowering : public TargetLoweringBase {
                                        LoadSDNode *OriginalLoad,
                                        SelectionDAG &DAG) const;
 
+protected:
+  void setTypeIdForCallsiteInfo(const CallBase *CB, MachineFunction &MF,
+                                MachineFunction::CallSiteInfo &CSInfo) const;
+
 private:
   SDValue foldSetCCWithAnd(EVT VT, SDValue N0, SDValue N1, ISD::CondCode Cond,
                            const SDLoc &DL, DAGCombinerInfo &DCI) const;
diff --git a/llvm/include/llvm/IR/FixedMetadataKinds.def b/llvm/include/llvm/IR/FixedMetadataKinds.def
index 98129985714b2..0d79677d...
[truncated]

@github-actions
Copy link

github-actions bot commented Feb 20, 2026

✅ With the latest revision this PR passed the C/C++ code formatter.

@CarlosAlbertoEnciso
Copy link
Member Author

CarlosAlbertoEnciso commented Feb 20, 2026

There are 2 main commits:

  • The changes that are already reviewed and approved by @dwblaikie and @felipepiovezan.
  • The changes that fix a failed test case and the reported crash.

The virtuality calls-site target information is NOT generated
if DWARF version less than 5 is requested.

Fixes issues discovered after the initial patch landed:

- Add missing 'REQUIRES: x86-registered-target'
  to fix buildbot failure:
    https://lab.llvm.org/buildbot/#/builders/190/builds/36803

- Crash when building Fuchsia code on arm platforms with DWARF 4 and -O2
@github-actions
Copy link

🐧 Linux x64 Test Results

  • 169907 tests passed
  • 3067 tests skipped
  • 1 test failed

Failed Tests

(click on a test name to see its output)

lldb-api

lldb-api.functionalities/data-formatter/data-formatter-stl/generic/list/TestDataFormatterGenericList.py
Script:
--
/usr/bin/python3 /home/gha/actions-runner/_work/llvm-project/llvm-project/lldb/test/API/dotest.py -u CXXFLAGS -u CFLAGS --env LLVM_LIBS_DIR=/home/gha/actions-runner/_work/llvm-project/llvm-project/build/./lib --env LLVM_INCLUDE_DIR=/home/gha/actions-runner/_work/llvm-project/llvm-project/build/include --env LLVM_TOOLS_DIR=/home/gha/actions-runner/_work/llvm-project/llvm-project/build/./bin --libcxx-include-dir /home/gha/actions-runner/_work/llvm-project/llvm-project/build/include/c++/v1 --libcxx-include-target-dir /home/gha/actions-runner/_work/llvm-project/llvm-project/build/include/x86_64-unknown-linux-gnu/c++/v1 --libcxx-library-dir /home/gha/actions-runner/_work/llvm-project/llvm-project/build/./lib/x86_64-unknown-linux-gnu --arch x86_64 --build-dir /home/gha/actions-runner/_work/llvm-project/llvm-project/build/lldb-test-build.noindex --lldb-module-cache-dir /home/gha/actions-runner/_work/llvm-project/llvm-project/build/lldb-test-build.noindex/module-cache-lldb/lldb-api --clang-module-cache-dir /home/gha/actions-runner/_work/llvm-project/llvm-project/build/lldb-test-build.noindex/module-cache-clang/lldb-api --executable /home/gha/actions-runner/_work/llvm-project/llvm-project/build/./bin/lldb --compiler /home/gha/actions-runner/_work/llvm-project/llvm-project/build/./bin/clang --dsymutil /home/gha/actions-runner/_work/llvm-project/llvm-project/build/./bin/dsymutil --make /usr/bin/gmake --llvm-tools-dir /home/gha/actions-runner/_work/llvm-project/llvm-project/build/./bin --lldb-obj-root /home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/lldb --lldb-libs-dir /home/gha/actions-runner/_work/llvm-project/llvm-project/build/./lib --cmake-build-type Release /home/gha/actions-runner/_work/llvm-project/llvm-project/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/list -p TestDataFormatterGenericList.py
--
Exit Code: 1

Command Output (stdout):
--
lldb version 23.0.0git (https://github.com/llvm/llvm-project revision f9173c2c56f6af25bcd1bb26308cc485e80b40d2)
  clang revision f9173c2c56f6af25bcd1bb26308cc485e80b40d2
  llvm revision f9173c2c56f6af25bcd1bb26308cc485e80b40d2
Skipping the following test categories: msvcstl, dsym, pdb, gmodules, debugserver, objc

--
Command Output (stderr):
--
UNSUPPORTED: LLDB (/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang-x86_64) :: test_ptr_and_ref_libcpp_dsym (TestDataFormatterGenericList.GenericListDataFormatterTestCase.test_ptr_and_ref_libcpp_dsym) (test case does not fall in any category of interest for this run) 
PASS: LLDB (/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang-x86_64) :: test_ptr_and_ref_libcpp_dwarf (TestDataFormatterGenericList.GenericListDataFormatterTestCase.test_ptr_and_ref_libcpp_dwarf)
PASS: LLDB (/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang-x86_64) :: test_ptr_and_ref_libcpp_dwo (TestDataFormatterGenericList.GenericListDataFormatterTestCase.test_ptr_and_ref_libcpp_dwo)
UNSUPPORTED: LLDB (/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang-x86_64) :: test_ptr_and_ref_libcpp_pdb (TestDataFormatterGenericList.GenericListDataFormatterTestCase.test_ptr_and_ref_libcpp_pdb) (test case does not fall in any category of interest for this run) 
UNSUPPORTED: LLDB (/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang-x86_64) :: test_ptr_and_ref_libstdcpp_dsym (TestDataFormatterGenericList.GenericListDataFormatterTestCase.test_ptr_and_ref_libstdcpp_dsym) (test case does not fall in any category of interest for this run) 
PASS: LLDB (/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang-x86_64) :: test_ptr_and_ref_libstdcpp_dwarf (TestDataFormatterGenericList.GenericListDataFormatterTestCase.test_ptr_and_ref_libstdcpp_dwarf)
PASS: LLDB (/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang-x86_64) :: test_ptr_and_ref_libstdcpp_dwo (TestDataFormatterGenericList.GenericListDataFormatterTestCase.test_ptr_and_ref_libstdcpp_dwo)
UNSUPPORTED: LLDB (/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang-x86_64) :: test_ptr_and_ref_libstdcpp_pdb (TestDataFormatterGenericList.GenericListDataFormatterTestCase.test_ptr_and_ref_libstdcpp_pdb) (test case does not fall in any category of interest for this run) 
UNSUPPORTED: LLDB (/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang-x86_64) :: test_ptr_and_ref_msvcstl_dsym (TestDataFormatterGenericList.GenericListDataFormatterTestCase.test_ptr_and_ref_msvcstl_dsym) (test case does not fall in any category of interest for this run) 
UNSUPPORTED: LLDB (/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang-x86_64) :: test_ptr_and_ref_msvcstl_dwarf (TestDataFormatterGenericList.GenericListDataFormatterTestCase.test_ptr_and_ref_msvcstl_dwarf) (test case does not fall in any category of interest for this run) 
UNSUPPORTED: LLDB (/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang-x86_64) :: test_ptr_and_ref_msvcstl_dwo (TestDataFormatterGenericList.GenericListDataFormatterTestCase.test_ptr_and_ref_msvcstl_dwo) (test case does not fall in any category of interest for this run) 
UNSUPPORTED: LLDB (/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang-x86_64) :: test_ptr_and_ref_msvcstl_pdb (TestDataFormatterGenericList.GenericListDataFormatterTestCase.test_ptr_and_ref_msvcstl_pdb) (test case does not fall in any category of interest for this run) 
UNSUPPORTED: LLDB (/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang-x86_64) :: test_with_run_command_libcpp_dsym (TestDataFormatterGenericList.GenericListDataFormatterTestCase.test_with_run_command_libcpp_dsym) (test case does not fall in any category of interest for this run) 
PASS: LLDB (/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang-x86_64) :: test_with_run_command_libcpp_dwarf (TestDataFormatterGenericList.GenericListDataFormatterTestCase.test_with_run_command_libcpp_dwarf)
PASS: LLDB (/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang-x86_64) :: test_with_run_command_libcpp_dwo (TestDataFormatterGenericList.GenericListDataFormatterTestCase.test_with_run_command_libcpp_dwo)
UNSUPPORTED: LLDB (/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang-x86_64) :: test_with_run_command_libcpp_pdb (TestDataFormatterGenericList.GenericListDataFormatterTestCase.test_with_run_command_libcpp_pdb) (test case does not fall in any category of interest for this run) 
UNSUPPORTED: LLDB (/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang-x86_64) :: test_with_run_command_libstdcpp_dsym (TestDataFormatterGenericList.GenericListDataFormatterTestCase.test_with_run_command_libstdcpp_dsym) (test case does not fall in any category of interest for this run) 
FAIL: LLDB (/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang-x86_64) :: test_with_run_command_libstdcpp_dwarf (TestDataFormatterGenericList.GenericListDataFormatterTestCase.test_with_run_command_libstdcpp_dwarf)
FAIL: LLDB (/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang-x86_64) :: test_with_run_command_libstdcpp_dwo (TestDataFormatterGenericList.GenericListDataFormatterTestCase.test_with_run_command_libstdcpp_dwo)
UNSUPPORTED: LLDB (/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang-x86_64) :: test_with_run_command_libstdcpp_pdb (TestDataFormatterGenericList.GenericListDataFormatterTestCase.test_with_run_command_libstdcpp_pdb) (test case does not fall in any category of interest for this run) 
UNSUPPORTED: LLDB (/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang-x86_64) :: test_with_run_command_msvcstl_dsym (TestDataFormatterGenericList.GenericListDataFormatterTestCase.test_with_run_command_msvcstl_dsym) (test case does not fall in any category of interest for this run) 
UNSUPPORTED: LLDB (/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang-x86_64) :: test_with_run_command_msvcstl_dwarf (TestDataFormatterGenericList.GenericListDataFormatterTestCase.test_with_run_command_msvcstl_dwarf) (test case does not fall in any category of interest for this run) 
UNSUPPORTED: LLDB (/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang-x86_64) :: test_with_run_command_msvcstl_dwo (TestDataFormatterGenericList.GenericListDataFormatterTestCase.test_with_run_command_msvcstl_dwo) (test case does not fall in any category of interest for this run) 
UNSUPPORTED: LLDB (/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang-x86_64) :: test_with_run_command_msvcstl_pdb (TestDataFormatterGenericList.GenericListDataFormatterTestCase.test_with_run_command_msvcstl_pdb) (test case does not fall in any category of interest for this run) 
======================================================================
FAIL: test_with_run_command_libstdcpp_dwarf (TestDataFormatterGenericList.GenericListDataFormatterTestCase.test_with_run_command_libstdcpp_dwarf)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/gha/actions-runner/_work/llvm-project/llvm-project/lldb/packages/Python/lldbsuite/test/lldbtest.py", line 1858, in test_method
    return attrvalue(self)
           ^^^^^^^^^^^^^^^
  File "/home/gha/actions-runner/_work/llvm-project/llvm-project/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/list/TestDataFormatterGenericList.py", line 302, in test_with_run_command_libstdcpp
    self.do_test_with_run_command(is_libstdcpp=True)
  File "/home/gha/actions-runner/_work/llvm-project/llvm-project/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/list/TestDataFormatterGenericList.py", line 64, in do_test_with_run_command
    self.expect(
  File "/home/gha/actions-runner/_work/llvm-project/llvm-project/lldb/packages/Python/lldbsuite/test/lldbtest.py", line 2477, in expect
    self.runCmd(
  File "/home/gha/actions-runner/_work/llvm-project/llvm-project/lldb/packages/Python/lldbsuite/test/lldbtest.py", line 1049, in runCmd
    self.assertTrue(self.res.Succeeded(), msg + output)
AssertionError: False is not true : Command 'frame variable &numbers_list._M_impl._M_node --raw' did not return successfully
Error output:
error: <user expression 0>:1:15: "_M_impl" is not a member of "(int_list) numbers_list"
   1 | &numbers_list._M_impl._M_node
     | ^

Config=x86_64-/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang
======================================================================
FAIL: test_with_run_command_libstdcpp_dwo (TestDataFormatterGenericList.GenericListDataFormatterTestCase.test_with_run_command_libstdcpp_dwo)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/gha/actions-runner/_work/llvm-project/llvm-project/lldb/packages/Python/lldbsuite/test/lldbtest.py", line 1858, in test_method
    return attrvalue(self)
           ^^^^^^^^^^^^^^^
  File "/home/gha/actions-runner/_work/llvm-project/llvm-project/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/list/TestDataFormatterGenericList.py", line 302, in test_with_run_command_libstdcpp
    self.do_test_with_run_command(is_libstdcpp=True)
  File "/home/gha/actions-runner/_work/llvm-project/llvm-project/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/list/TestDataFormatterGenericList.py", line 64, in do_test_with_run_command
    self.expect(
  File "/home/gha/actions-runner/_work/llvm-project/llvm-project/lldb/packages/Python/lldbsuite/test/lldbtest.py", line 2477, in expect
    self.runCmd(
  File "/home/gha/actions-runner/_work/llvm-project/llvm-project/lldb/packages/Python/lldbsuite/test/lldbtest.py", line 1049, in runCmd
    self.assertTrue(self.res.Succeeded(), msg + output)
AssertionError: False is not true : Command 'frame variable &numbers_list._M_impl._M_node --raw' did not return successfully
Error output:
error: <user expression 0>:1:15: "_M_impl" is not a member of "(int_list) numbers_list"
   1 | &numbers_list._M_impl._M_node
     | ^

Config=x86_64-/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang
----------------------------------------------------------------------
Ran 24 tests in 3.194s

FAILED (failures=2, skipped=16)

--

If these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the infrastructure label.

Copy link
Contributor

@ilovepi ilovepi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Do check with other reviewers, but it looks to me like this should fix the crash and there's a test case from our codebase, so I'm reasonably sure it should be fine.

Thanks again :)

@CarlosAlbertoEnciso
Copy link
Member Author

CarlosAlbertoEnciso commented Feb 23, 2026

@dwblaikie, @felipepiovezan Do you have any additional feedback on the commit that fixes the failed test case and crash? Thanks

@CarlosAlbertoEnciso
Copy link
Member Author

@jryans, @ilovepi Thanks for the review and approval.

Copy link
Collaborator

@dwblaikie dwblaikie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems plausible

@CarlosAlbertoEnciso CarlosAlbertoEnciso merged commit bc9d5b0 into llvm:main Feb 25, 2026
13 of 14 checks passed
@CarlosAlbertoEnciso
Copy link
Member Author

@dwblaikie Thanks for the review and approval.

@CarlosAlbertoEnciso CarlosAlbertoEnciso deleted the callsite-indirect-calls branch February 26, 2026 14:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants