https://github.com/VitorRamos created 
https://github.com/llvm/llvm-project/pull/197928

Fix a crash when generating debug info for a template class that is
still being defined when its forward declaration is needed.

getTypeIdentifier() called getVTableLinkage() on a record that was only
"being defined" (not yet complete), which triggered premature
ASTRecordLayout computation and cached a layout with zero fields. Later,
CollectRecordFields used the stale cached layout and crashed on an
out-of-bounds field offset access.

Replace getDefinition() with isCompleteDefinition() to correctly skip
records whose definition is not yet complete.

Fixes #156352

>From f5bc8d2f166fdb4dc03ef610483f7be3ebd8faf1 Mon Sep 17 00:00:00 2001
From: vitorramos89 <[email protected]>
Date: Thu, 14 May 2026 20:11:55 -0300
Subject: [PATCH] [clang][CodeGen] Fix crash in CGDebugInfo on incomplete
 record type (#156352)

Fix a crash when generating debug info for a template class that is
still being defined when its forward declaration is needed.

getTypeIdentifier() called getVTableLinkage() on a record that was only
"being defined" (not yet complete), which triggered premature
ASTRecordLayout computation and cached a layout with zero fields. Later,
CollectRecordFields used the stale cached layout and crashed on an
out-of-bounds field offset access.

Replace getDefinition() with isCompleteDefinition() to correctly skip
records whose definition is not yet complete.

Fixes #156352
---
 clang/lib/CodeGen/CGDebugInfo.cpp             |  2 +-
 .../debug-info-template-incomplete-record.cpp | 83 +++++++++++++++++++
 2 files changed, 84 insertions(+), 1 deletion(-)
 create mode 100644 
clang/test/CodeGenCXX/debug-info-template-incomplete-record.cpp

diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp 
b/clang/lib/CodeGen/CGDebugInfo.cpp
index 578d09f7971d6..71a21f19fbd5b 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -1290,7 +1290,7 @@ static SmallString<256> getTypeIdentifier(const TagType 
*Ty, CodeGenModule &CGM,
   if (!needsTypeIdentifier(TD, CGM, TheCU))
     return Identifier;
   if (const auto *RD = dyn_cast<CXXRecordDecl>(TD))
-    if (RD->getDefinition())
+    if (RD->isCompleteDefinition())
       if (RD->isDynamicClass() &&
           CGM.getVTableLinkage(RD) == llvm::GlobalValue::ExternalLinkage)
         return Identifier;
diff --git a/clang/test/CodeGenCXX/debug-info-template-incomplete-record.cpp 
b/clang/test/CodeGenCXX/debug-info-template-incomplete-record.cpp
new file mode 100644
index 0000000000000..f81433d53d296
--- /dev/null
+++ b/clang/test/CodeGenCXX/debug-info-template-incomplete-record.cpp
@@ -0,0 +1,83 @@
+// RUN: %clang_cc1 -std=c++20 -debug-info-kind=standalone -fvisibility=hidden \
+// RUN:   -O2 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s
+//
+// Verify that we don't crash when generating debug info for a template class
+// that is still being defined when its forward declaration is needed. The bug
+// was that getTypeIdentifier() called getVTableLinkage() on a record that was
+// only "being defined" (not yet complete), which triggered premature
+// ASTRecordLayout computation and cached a layout with zero fields. Later,
+// CollectRecordFields used the stale cached layout and crashed on an
+// out-of-bounds field offset access.
+
+class a;
+template<class>
+class b;
+class c
+{
+public:
+   using d = a;
+};
+template<class>
+class f;
+template<class e>
+class h
+{
+   using j = typename e::j;
+   j k();
+};
+class l;
+class m
+{
+   using i = f<l>;
+   i n();
+};
+template<class>
+class f
+{
+public:
+   using e = l;
+   using o = e;
+   using d = b<e>;
+   d *p;
+};
+class L;
+class q
+{
+public:
+   using j = L;
+};
+class r
+{
+   ~r();
+   h<q> s;
+};
+r::~r() = default;
+class l
+{
+public:
+   using j = m;
+   using g = c;
+};
+class J
+{
+   h<l> t;
+};
+class a
+{
+public:
+   virtual ~a();
+};
+template<class e>
+class b : e::g::d
+{
+   using u = typename f<e>::o;
+   int v;
+};
+class L : J
+{
+};
+extern template class b<l>;
+
+// Just verify we produce debug info for b<l> with its field v.
+// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "b<l>"
+// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "v"

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to