[clang] [lldb] [clang][DebugInfo] Emit global variable definitions for static data members with constant initializers (PR #70639)

Michael Buch via cfe-commits cfe-commits at lists.llvm.org
Wed Nov 1 07:36:45 PDT 2023


https://github.com/Michael137 updated https://github.com/llvm/llvm-project/pull/70639

>From 18db082fc5008283f77cc98d9c733a47c63b7096 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Fri, 27 Oct 2023 16:19:47 +0100
Subject: [PATCH 1/8] [clang][DebugInfo] Emit global variable definitions for
 static data members with constant initializers
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

When an LLDB user asks for the value of a static data member, LLDB starts by
searching the Names accelerator table for the corresponding variable definition
DIE. For static data members with out-of-class definitions that works fine,
because those get represented as global variables with a location and making them
eligible to be added to the Names table. However, in-class definitions won’t get
indexed because we usually don't emit global variables for them. So in DWARF
we end up with a single `DW_TAG_member` that usually holds the constant initializer.
But we don't get a corresponding CU-level `DW_TAG_variable` like we do for
out-of-class definitions.

To make it more convenient for debuggers to get to the value of inline static data members,
this patch makes sure we emit definitions for static variables with constant initializers
the same way we do for other static variables. This also aligns Clang closer to GCC, which
produces CU-level definitions for inline statics and also emits these into `.debug_pubnames`.

The implementation keeps track of newly created static data members. Then in
`CGDebugInfo::finalize`, we emit a global `DW_TAG_variable` with a `DW_AT_const_value` for
any of those declarations that didn't end up with a definition in the `DeclCache`.

The newly emitted `DW_TAG_variable` will look as follows:
```
0x0000007b:   DW_TAG_structure_type
                DW_AT_calling_convention        (DW_CC_pass_by_value)
                DW_AT_name      ("Foo")
                ...

0x0000008d:     DW_TAG_member
                  DW_AT_name    ("i")
                  DW_AT_type    (0x00000062 "const int")
                  DW_AT_external        (true)
                  DW_AT_declaration     (true)
                  DW_AT_const_value     (4)

Newly added
vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

0x0000009a:   DW_TAG_variable
                DW_AT_specification     (0x0000008d "i")
                DW_AT_const_value       (4)
                DW_AT_linkage_name      ("_ZN2t2IiE1iIfEE")
```
---
 clang/lib/CodeGen/CGDebugInfo.cpp             | 46 +++++++++++
 clang/lib/CodeGen/CGDebugInfo.h               |  6 ++
 clang/test/CodeGenCXX/debug-info-class.cpp    | 13 ++-
 .../debug-info-static-inline-member.cpp       | 79 +++++++++++++++++++
 .../TestConstStaticIntegralMember.py          |  7 +-
 5 files changed, 144 insertions(+), 7 deletions(-)
 create mode 100644 clang/test/CodeGenCXX/debug-info-static-inline-member.cpp

diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 0aaf678bf287c6e..7529f114996d2ec 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -1693,6 +1693,7 @@ CGDebugInfo::CreateRecordStaticField(const VarDecl *Var, llvm::DIType *RecordTy,
   llvm::DIDerivedType *GV = DBuilder.createStaticMemberType(
       RecordTy, VName, VUnit, LineNumber, VTy, Flags, C, Align);
   StaticDataMemberCache[Var->getCanonicalDecl()].reset(GV);
+  StaticDataMemberDefinitionsToEmit.push_back(Var->getCanonicalDecl());
   return GV;
 }
 
@@ -5613,6 +5614,39 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, const APValue &Init) {
       TemplateParameters, Align));
 }
 
+void CGDebugInfo::EmitGlobalVariable(const VarDecl *VD) {
+  assert(VD->hasInit());
+  assert(CGM.getCodeGenOpts().hasReducedDebugInfo());
+  if (VD->hasAttr<NoDebugAttr>())
+    return;
+
+  auto &GV = DeclCache[VD];
+  if (GV)
+    return;
+
+  auto const *InitVal = VD->evaluateValue();
+  if (!InitVal)
+    return;
+
+  llvm::DIFile *Unit = nullptr;
+  llvm::DIScope *DContext = nullptr;
+  unsigned LineNo;
+  StringRef DeclName, LinkageName;
+  QualType T;
+  llvm::MDTuple *TemplateParameters = nullptr;
+  collectVarDeclProps(VD, Unit, LineNo, T, DeclName, LinkageName,
+                      TemplateParameters, DContext);
+
+  auto Align = getDeclAlignIfRequired(VD, CGM.getContext());
+  llvm::DINodeArray Annotations = CollectBTFDeclTagAnnotations(VD);
+  llvm::DIExpression *InitExpr = createConstantValueExpression(VD, *InitVal);
+
+  GV.reset(DBuilder.createGlobalVariableExpression(
+      TheCU, DeclName, LinkageName, Unit, LineNo, getOrCreateType(T, Unit),
+      true, true, InitExpr, getOrCreateStaticDataMemberDeclarationOrNull(VD),
+      TemplateParameters, Align, Annotations));
+}
+
 void CGDebugInfo::EmitExternalVariable(llvm::GlobalVariable *Var,
                                        const VarDecl *D) {
   assert(CGM.getCodeGenOpts().hasReducedDebugInfo());
@@ -5883,6 +5917,18 @@ void CGDebugInfo::finalize() {
     DBuilder.replaceTemporary(std::move(FwdDecl), cast<llvm::MDNode>(Repl));
   }
 
+  for (auto const *VD : StaticDataMemberDefinitionsToEmit) {
+    assert (VD->isStaticDataMember());
+
+    if (auto It = DeclCache.find(VD); It != DeclCache.end())
+      continue;
+
+    if (!VD->hasInit())
+      continue;
+
+    EmitGlobalVariable(VD);
+  }
+
   // We keep our own list of retained types, because we need to look
   // up the final type in the type cache.
   for (auto &RT : RetainedTypes)
diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h
index ae12485850ca775..3a508bfa4f6d3e6 100644
--- a/clang/lib/CodeGen/CGDebugInfo.h
+++ b/clang/lib/CodeGen/CGDebugInfo.h
@@ -161,6 +161,9 @@ class CGDebugInfo {
   llvm::DenseMap<const Decl *, llvm::TypedTrackingMDRef<llvm::DIDerivedType>>
       StaticDataMemberCache;
 
+  /// Keeps track of static data members for which we should emit a definition.
+  std::vector<const VarDecl *> StaticDataMemberDefinitionsToEmit;
+
   using ParamDecl2StmtTy = llvm::DenseMap<const ParmVarDecl *, const Stmt *>;
   using Param2DILocTy =
       llvm::DenseMap<const ParmVarDecl *, llvm::DILocalVariable *>;
@@ -526,6 +529,9 @@ class CGDebugInfo {
   /// Emit a constant global variable's debug info.
   void EmitGlobalVariable(const ValueDecl *VD, const APValue &Init);
 
+  /// Emit debug-info for a variable with a constant initializer.
+  void EmitGlobalVariable(const VarDecl *VD);
+
   /// Emit information about an external variable.
   void EmitExternalVariable(llvm::GlobalVariable *GV, const VarDecl *Decl);
 
diff --git a/clang/test/CodeGenCXX/debug-info-class.cpp b/clang/test/CodeGenCXX/debug-info-class.cpp
index ef84b91b67821a9..a3111cd7c3640a0 100644
--- a/clang/test/CodeGenCXX/debug-info-class.cpp
+++ b/clang/test/CodeGenCXX/debug-info-class.cpp
@@ -116,11 +116,19 @@ int main(int argc, char **argv) {
 // CHECK-SAME:                             DIFlagFwdDecl
 // CHECK-NOT:                             identifier:
 // CHECK-SAME:                            ){{$}}
+
+// CHECK:      !DIGlobalVariableExpression(var: ![[HDR_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, 52, DW_OP_stack_value))
+// CHECK:      ![[HDR_VAR]] = distinct !DIGlobalVariable(name: "HdrSize",
+// CHECK-SAME:                isLocal: true, isDefinition: true, declaration: ![[HDR_VAR_DECL:[0-9]+]])
+// CHECK:      ![[INT:[0-9]+]] = !DIBasicType(name: "int"
+// CHECK:      ![[HDR_VAR_DECL]] = !DIDerivedType(tag: DW_TAG_member, name: "HdrSize"
+
+// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "A"
+
 // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "I"
 // CHECK-NOT:              DIFlagFwdDecl
 // CHECK-SAME:             ){{$}}
 
-// CHECK: ![[INT:[0-9]+]] = !DIBasicType(name: "int"
 // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "foo"
 // CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "bar"
 // CHECK: !DICompositeType(tag: DW_TAG_union_type, name: "baz"
@@ -186,8 +194,5 @@ int main(int argc, char **argv) {
 // CHECK: [[G_INNER_I]] = !DIDerivedType(tag: DW_TAG_member, name: "j"
 // CHECK-SAME:                           baseType: ![[INT]]
 
-// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "A"
-// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "HdrSize"
-//
 // CHECK: ![[EXCEPTLOC]] = !DILocation(line: 100,
 // CHECK: ![[RETLOC]] = !DILocation(line: 99,
diff --git a/clang/test/CodeGenCXX/debug-info-static-inline-member.cpp b/clang/test/CodeGenCXX/debug-info-static-inline-member.cpp
new file mode 100644
index 000000000000000..917e101714846d7
--- /dev/null
+++ b/clang/test/CodeGenCXX/debug-info-static-inline-member.cpp
@@ -0,0 +1,79 @@
+// RUN: %clangxx -target arm64-apple-macosx11.0.0 -g %s -emit-llvm -S -o - | FileCheck --check-prefixes=CHECK %s
+
+enum class Enum : int {
+  VAL = -1
+};
+
+struct Empty {};
+
+constexpr auto func() { return 25; }
+
+struct Foo {
+    static constexpr int cexpr_int = func();
+    static constexpr int cexpr_int2 = func() + 1;
+    static constexpr float cexpr_float = 2.0 + 1.0;
+    static constexpr Enum cexpr_enum = Enum::VAL;
+    static constexpr Empty cexpr_empty{};
+
+    template<typename T>
+    static constexpr T cexpr_template{};
+};
+
+int main() {
+    Foo f;
+
+    // Force global variable definitions to be emitted.
+    (void)&Foo::cexpr_int;
+    (void)&Foo::cexpr_empty;
+
+    return Foo::cexpr_int + Foo::cexpr_float
+           + (int)Foo::cexpr_enum + Foo::cexpr_template<short>;
+}
+
+// CHECK:      @{{.*}}cexpr_int{{.*}} =
+// CHECK-SAME:   !dbg ![[INT_GLOBAL:[0-9]+]]
+
+// CHECK:      @{{.*}}cexpr_empty{{.*}} = 
+// CHECK-SAME    !dbg ![[EMPTY_GLOBAL:[0-9]+]]
+
+// CHECK:      !DIGlobalVariableExpression(var: ![[INT_VAR:[0-9]+]], expr: !DIExpression())
+// CHECK:      ![[INT_VAR]] = distinct !DIGlobalVariable(name: "cexpr_int", linkageName:
+// CHECK-SAME:                isLocal: false, isDefinition: true, declaration: ![[INT_DECL:[0-9]+]])
+
+// CHECK:      ![[INT_DECL]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_int",
+// CHECK-SAME:                 flags: DIFlagStaticMember, extraData: i32 25)
+
+// CHECK:      ![[INT_DECL2:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_int2",
+// CHECK-SAME:                         flags: DIFlagStaticMember, extraData: i32 26)
+
+// CHECK:      ![[FLOAT_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_float",
+// CHECK-SAME:                          flags: DIFlagStaticMember, extraData: float
+
+// CHECK:      ![[ENUM_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_enum",
+// CHECK-SAME:                         flags: DIFlagStaticMember, extraData: i32 -1)
+
+// CHECK:      ![[EMPTY_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_empty",
+// CHECK-SAME:                          flags: DIFlagStaticMember)
+
+// CHECK:      ![[TEMPLATE_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_template",
+// CHECK-SAME:                             flags: DIFlagStaticMember, extraData: i16 0)
+
+// CHECK:      !DIGlobalVariableExpression(var: ![[EMPTY_VAR:[0-9]+]], expr: !DIExpression())
+// CHECK:      ![[EMPTY_VAR]] = distinct !DIGlobalVariable(name: "cexpr_empty", linkageName:
+// CHECK-SAME:                  isLocal: false, isDefinition: true, declaration: ![[EMPTY_DECL]])
+
+// CHECK:      !DIGlobalVariableExpression(var: ![[INT_VAR2:[0-9]+]], expr: !DIExpression(DW_OP_constu, 26, DW_OP_stack_value))
+// CHECK:      ![[INT_VAR2]] = distinct !DIGlobalVariable(name: "cexpr_int2", linkageName:
+// CHECK-SAME:                 isLocal: true, isDefinition: true, declaration: ![[INT_DECL2]])
+
+// CHECK:      !DIGlobalVariableExpression(var: ![[FLOAT_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, {{.*}}, DW_OP_stack_value))
+// CHECK:      ![[FLOAT_VAR]] = distinct !DIGlobalVariable(name: "cexpr_float", linkageName:
+// CHECK-SAME:                  isLocal: true, isDefinition: true, declaration: ![[FLOAT_DECL]])
+
+// CHECK:      !DIGlobalVariableExpression(var: ![[ENUM_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, {{.*}}, DW_OP_stack_value))
+// CHECK:      ![[ENUM_VAR]] = distinct !DIGlobalVariable(name: "cexpr_enum", linkageName:
+// CHECK-SAME:                 isLocal: true, isDefinition: true, declaration: ![[ENUM_DECL]])
+
+// CHECK:      !DIGlobalVariableExpression(var: ![[TEMPLATE_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, 0, DW_OP_stack_value))
+// CHECK:      ![[TEMPLATE_VAR]] = distinct !DIGlobalVariable(name: "cexpr_template", linkageName:
+// CHECK-SAME:                     isLocal: true, isDefinition: true, declaration: ![[TEMPLATE_DECL]], templateParams: ![[TEMPLATE_PARMS:[0-9]+]])
diff --git a/lldb/test/API/lang/cpp/const_static_integral_member/TestConstStaticIntegralMember.py b/lldb/test/API/lang/cpp/const_static_integral_member/TestConstStaticIntegralMember.py
index 530191e8a37ba1b..78ea23ac8f70610 100644
--- a/lldb/test/API/lang/cpp/const_static_integral_member/TestConstStaticIntegralMember.py
+++ b/lldb/test/API/lang/cpp/const_static_integral_member/TestConstStaticIntegralMember.py
@@ -102,9 +102,10 @@ def test(self):
         # it does not crash.
         self.expect("image lookup -t A")
 
-    # dsymutil strips the debug info for classes that only have const static
-    # data members without a definition namespace scope.
-    @expectedFailureAll(debug_info=["dsym"])
+    # For debug-info produced by older versions of clang, dsymutil strips the
+    # debug info for classes that only have const static data members without
+    # definitions.
+    @expectedFailureAll(compiler=["clang"], compiler_version=["<", "18.0"])
     def test_class_with_only_const_static(self):
         self.build()
         lldbutil.run_to_source_breakpoint(

>From bb9a80a28fdc2dab8148128f8052a3979ca0edba Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Mon, 30 Oct 2023 10:16:47 +0000
Subject: [PATCH 2/8] fixup! add test-case for explicitly inline member

---
 clang/test/CodeGenCXX/debug-info-static-inline-member.cpp | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/clang/test/CodeGenCXX/debug-info-static-inline-member.cpp b/clang/test/CodeGenCXX/debug-info-static-inline-member.cpp
index 917e101714846d7..745b5fef69f33e7 100644
--- a/clang/test/CodeGenCXX/debug-info-static-inline-member.cpp
+++ b/clang/test/CodeGenCXX/debug-info-static-inline-member.cpp
@@ -14,6 +14,7 @@ struct Foo {
     static constexpr float cexpr_float = 2.0 + 1.0;
     static constexpr Enum cexpr_enum = Enum::VAL;
     static constexpr Empty cexpr_empty{};
+    static inline    Enum inline_enum = Enum::VAL;
 
     template<typename T>
     static constexpr T cexpr_template{};
@@ -55,6 +56,9 @@ int main() {
 // CHECK:      ![[EMPTY_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_empty",
 // CHECK-SAME:                          flags: DIFlagStaticMember)
 
+// CHECK:      ![[IENUM_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "inline_enum",
+// CHECK-SAME:                          flags: DIFlagStaticMember, extraData: i32 -1)
+
 // CHECK:      ![[TEMPLATE_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_template",
 // CHECK-SAME:                             flags: DIFlagStaticMember, extraData: i16 0)
 
@@ -74,6 +78,10 @@ int main() {
 // CHECK:      ![[ENUM_VAR]] = distinct !DIGlobalVariable(name: "cexpr_enum", linkageName:
 // CHECK-SAME:                 isLocal: true, isDefinition: true, declaration: ![[ENUM_DECL]])
 
+// CHECK:      !DIGlobalVariableExpression(var: ![[IENUM_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, {{.*}}, DW_OP_stack_value))
+// CHECK:      ![[IENUM_VAR]] = distinct !DIGlobalVariable(name: "inline_enum", linkageName:
+// CHECK-SAME:                  isLocal: true, isDefinition: true, declaration: ![[IENUM_DECL]])
+
 // CHECK:      !DIGlobalVariableExpression(var: ![[TEMPLATE_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, 0, DW_OP_stack_value))
 // CHECK:      ![[TEMPLATE_VAR]] = distinct !DIGlobalVariable(name: "cexpr_template", linkageName:
 // CHECK-SAME:                     isLocal: true, isDefinition: true, declaration: ![[TEMPLATE_DECL]], templateParams: ![[TEMPLATE_PARMS:[0-9]+]])

>From 9ccb456958189b069d123cb6daaef935f4e9128e Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Mon, 30 Oct 2023 10:18:05 +0000
Subject: [PATCH 3/8] fixup! clang-format

---
 clang/lib/CodeGen/CGDebugInfo.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 7529f114996d2ec..032652522df458e 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -5918,7 +5918,7 @@ void CGDebugInfo::finalize() {
   }
 
   for (auto const *VD : StaticDataMemberDefinitionsToEmit) {
-    assert (VD->isStaticDataMember());
+    assert(VD->isStaticDataMember());
 
     if (auto It = DeclCache.find(VD); It != DeclCache.end())
       continue;

>From 28c5575271b0a8bbb5ff7acacb988c492947a4f3 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Tue, 31 Oct 2023 08:55:36 +0000
Subject: [PATCH 4/8] [clang][DebugInfo] Stop emitting DW_AT_const_value on
 static member declarations

Since `f07cf5aaf96a70123530239d07c1e655dc91b98d` we emit a definition
for any static data member with a constant initializer. That definition
will either have a location or constant attached to it. So having the
constant on the declaration is redundant. It also helps with the
type merging inconsistencies encountered in
https://github.com/llvm/llvm-project/pull/68721
---
 clang/lib/CodeGen/CGDebugInfo.cpp             | 12 +----------
 .../debug-info-static-inline-member.cpp       | 21 ++++++++++++-------
 .../CodeGenCXX/debug-info-static-member.cpp   | 14 ++++++-------
 3 files changed, 22 insertions(+), 25 deletions(-)

diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 032652522df458e..38ac8c530286bde 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -1677,21 +1677,11 @@ CGDebugInfo::CreateRecordStaticField(const VarDecl *Var, llvm::DIType *RecordTy,
 
   unsigned LineNumber = getLineNumber(Var->getLocation());
   StringRef VName = Var->getName();
-  llvm::Constant *C = nullptr;
-  if (Var->getInit()) {
-    const APValue *Value = Var->evaluateValue();
-    if (Value) {
-      if (Value->isInt())
-        C = llvm::ConstantInt::get(CGM.getLLVMContext(), Value->getInt());
-      if (Value->isFloat())
-        C = llvm::ConstantFP::get(CGM.getLLVMContext(), Value->getFloat());
-    }
-  }
 
   llvm::DINode::DIFlags Flags = getAccessFlag(Var->getAccess(), RD);
   auto Align = getDeclAlignIfRequired(Var, CGM.getContext());
   llvm::DIDerivedType *GV = DBuilder.createStaticMemberType(
-      RecordTy, VName, VUnit, LineNumber, VTy, Flags, C, Align);
+      RecordTy, VName, VUnit, LineNumber, VTy, Flags, /* Val */ nullptr, Align);
   StaticDataMemberCache[Var->getCanonicalDecl()].reset(GV);
   StaticDataMemberDefinitionsToEmit.push_back(Var->getCanonicalDecl());
   return GV;
diff --git a/clang/test/CodeGenCXX/debug-info-static-inline-member.cpp b/clang/test/CodeGenCXX/debug-info-static-inline-member.cpp
index 745b5fef69f33e7..2a17dfc88140553 100644
--- a/clang/test/CodeGenCXX/debug-info-static-inline-member.cpp
+++ b/clang/test/CodeGenCXX/debug-info-static-inline-member.cpp
@@ -42,25 +42,32 @@ int main() {
 // CHECK-SAME:                isLocal: false, isDefinition: true, declaration: ![[INT_DECL:[0-9]+]])
 
 // CHECK:      ![[INT_DECL]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_int",
-// CHECK-SAME:                 flags: DIFlagStaticMember, extraData: i32 25)
+// CHECK-SAME:                 flags: DIFlagStaticMember
+// CHECK-NOT:                  extraData:
 
 // CHECK:      ![[INT_DECL2:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_int2",
-// CHECK-SAME:                         flags: DIFlagStaticMember, extraData: i32 26)
+// CHECK-SAME:                         flags: DIFlagStaticMember
+// CHECK-NOT:                          extraData:
 
 // CHECK:      ![[FLOAT_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_float",
-// CHECK-SAME:                          flags: DIFlagStaticMember, extraData: float
+// CHECK-SAME:                          flags: DIFlagStaticMember
+// CHECK-NOT:                           extraData:
 
 // CHECK:      ![[ENUM_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_enum",
-// CHECK-SAME:                         flags: DIFlagStaticMember, extraData: i32 -1)
+// CHECK-SAME:                         flags: DIFlagStaticMember
+// CHECK-NOT:                          extraData:
 
 // CHECK:      ![[EMPTY_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_empty",
-// CHECK-SAME:                          flags: DIFlagStaticMember)
+// CHECK-SAME:                          flags: DIFlagStaticMember
+// CHECK-NOT:                           extraData:
 
 // CHECK:      ![[IENUM_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "inline_enum",
-// CHECK-SAME:                          flags: DIFlagStaticMember, extraData: i32 -1)
+// CHECK-SAME:                          flags: DIFlagStaticMember
+// CHECK-NOT:                           extraData:
 
 // CHECK:      ![[TEMPLATE_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_template",
-// CHECK-SAME:                             flags: DIFlagStaticMember, extraData: i16 0)
+// CHECK-SAME:                             flags: DIFlagStaticMember
+// CHECK-NOT:                              extraData:
 
 // CHECK:      !DIGlobalVariableExpression(var: ![[EMPTY_VAR:[0-9]+]], expr: !DIExpression())
 // CHECK:      ![[EMPTY_VAR]] = distinct !DIGlobalVariable(name: "cexpr_empty", linkageName:
diff --git a/clang/test/CodeGenCXX/debug-info-static-member.cpp b/clang/test/CodeGenCXX/debug-info-static-member.cpp
index 260a3afdd6524f3..7ac389adaf9a85c 100644
--- a/clang/test/CodeGenCXX/debug-info-static-member.cpp
+++ b/clang/test/CodeGenCXX/debug-info-static-member.cpp
@@ -67,15 +67,15 @@ int C::a = 4;
 // CHECK-NOT:            size:
 // CHECK-NOT:            align:
 // CHECK-NOT:            offset:
-// CHECK-SAME:           flags: DIFlagStaticMember,
-// CHECK-SAME:           extraData: i1 true)
+// CHECK-SAME:           flags: DIFlagStaticMember
+// CHECK-NOT:            extraData:
 
 // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "const_b"
 // CHECK-NOT:            size:
 // CHECK-NOT:            align:
 // CHECK-NOT:            offset:
-// CHECK-SAME:           flags: DIFlagProtected | DIFlagStaticMember,
-// CHECK-SAME:           extraData: float 0x{{.*}})
+// CHECK-SAME:           flags: DIFlagProtected | DIFlagStaticMember
+// CHECK-NOT:            extraData:
 
 // CHECK: ![[DECL_C:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "c"
 // CHECK-NOT:                                 size:
@@ -87,8 +87,8 @@ int C::a = 4;
 // CHECK-NOT:            size:
 // CHECK-NOT:            align:
 // CHECK-NOT:            offset:
-// CHECK-SAME:           flags: DIFlagPublic | DIFlagStaticMember,
-// CHECK-SAME:           extraData: i32 18)
+// CHECK-SAME:           flags: DIFlagPublic | DIFlagStaticMember
+// CHECK-NOT:            extraData:
 //
 // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "x_a"
 // CHECK-SAME:           flags: DIFlagPublic | DIFlagStaticMember)
@@ -144,7 +144,7 @@ struct V {
 // const_va is not emitted for MS targets.
 // NOT-MS: !DIDerivedType(tag: DW_TAG_member, name: "const_va",
 // NOT-MS-SAME:           line: [[@LINE-5]]
-// NOT-MS-SAME:           extraData: i32 42
+// NOT-MS-NOT:            extraData:
 const int V::const_va;
 
 namespace x {

>From fd190d6c614c531578ab357650509768d0cd41c7 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Tue, 31 Oct 2023 22:46:46 +0000
Subject: [PATCH 5/8] fixup! simplify DeclCache check

---
 clang/lib/CodeGen/CGDebugInfo.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 38ac8c530286bde..275aae8bd7530a1 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -5910,7 +5910,7 @@ void CGDebugInfo::finalize() {
   for (auto const *VD : StaticDataMemberDefinitionsToEmit) {
     assert(VD->isStaticDataMember());
 
-    if (auto It = DeclCache.find(VD); It != DeclCache.end())
+    if (DeclCache.contains(VD))
       continue;
 
     if (!VD->hasInit())

>From 0b1f03bfda1311e1ec61abe7b01c83d02aabb0ad Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Tue, 31 Oct 2023 22:47:10 +0000
Subject: [PATCH 6/8] fixup! tests: add checks for existence of definition

---
 .../CodeGenCXX/debug-info-static-member.cpp   | 50 ++++++++++++-------
 1 file changed, 31 insertions(+), 19 deletions(-)

diff --git a/clang/test/CodeGenCXX/debug-info-static-member.cpp b/clang/test/CodeGenCXX/debug-info-static-member.cpp
index 7ac389adaf9a85c..578995801c6400b 100644
--- a/clang/test/CodeGenCXX/debug-info-static-member.cpp
+++ b/clang/test/CodeGenCXX/debug-info-static-member.cpp
@@ -63,19 +63,19 @@ int C::a = 4;
 // CHECK-NOT:                                 offset:
 // CHECK-SAME:                                flags: DIFlagStaticMember)
 //
-// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "const_a"
-// CHECK-NOT:            size:
-// CHECK-NOT:            align:
-// CHECK-NOT:            offset:
-// CHECK-SAME:           flags: DIFlagStaticMember
-// CHECK-NOT:            extraData:
-
-// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "const_b"
-// CHECK-NOT:            size:
-// CHECK-NOT:            align:
-// CHECK-NOT:            offset:
-// CHECK-SAME:           flags: DIFlagProtected | DIFlagStaticMember
-// CHECK-NOT:            extraData:
+// CHECK:    ![[CONST_A_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "const_a"
+// CHECK-NOT:                           size:
+// CHECK-NOT:                           align:
+// CHECK-NOT:                           offset:
+// CHECK-SAME:                          flags: DIFlagStaticMember
+// CHECK-NOT:                           extraData:
+
+// CHECK:     ![[CONST_B_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "const_b"
+// CHECK-NOT:                            size:
+// CHECK-NOT:                            align:
+// CHECK-NOT:                            offset:
+// CHECK-SAME:                           flags: DIFlagProtected | DIFlagStaticMember
+// CHECK-NOT:                            extraData:
 
 // CHECK: ![[DECL_C:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "c"
 // CHECK-NOT:                                 size:
@@ -83,12 +83,12 @@ int C::a = 4;
 // CHECK-NOT:                                 offset:
 // CHECK-SAME:                                flags: DIFlagPublic | DIFlagStaticMember)
 //
-// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "const_c"
-// CHECK-NOT:            size:
-// CHECK-NOT:            align:
-// CHECK-NOT:            offset:
-// CHECK-SAME:           flags: DIFlagPublic | DIFlagStaticMember
-// CHECK-NOT:            extraData:
+// CHECK:     ![[CONST_C_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "const_c"
+// CHECK-NOT:                            size:
+// CHECK-NOT:                            align:
+// CHECK-NOT:                            offset:
+// CHECK-SAME:                           flags: DIFlagPublic | DIFlagStaticMember
+// CHECK-NOT:                            extraData:
 //
 // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "x_a"
 // CHECK-SAME:           flags: DIFlagPublic | DIFlagStaticMember)
@@ -156,3 +156,15 @@ struct y {
 };
 int y::z;
 }
+
+// CHECK:      !DIGlobalVariableExpression(var: ![[CONST_A_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, 1, DW_OP_stack_value))
+// CHECK:      ![[CONST_A_VAR]] = distinct !DIGlobalVariable(name: "const_a"
+// CHECK-SAME:                    isLocal: true, isDefinition: true, declaration: ![[CONST_A_DECL]])
+
+// CHECK:      !DIGlobalVariableExpression(var: ![[CONST_B_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, {{.*}}, DW_OP_stack_value))
+// CHECK:      ![[CONST_B_VAR]] = distinct !DIGlobalVariable(name: "const_b"
+// CHECK-SAME:                    isLocal: true, isDefinition: true, declaration: ![[CONST_B_DECL]])
+
+// CHECK:      !DIGlobalVariableExpression(var: ![[CONST_C_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, 18, DW_OP_stack_value))
+// CHECK:      ![[CONST_C_VAR]] = distinct !DIGlobalVariable(name: "const_c"
+// CHECK-SAME:                    isLocal: true, isDefinition: true, declaration: ![[CONST_C_DECL]])

>From f5b814c70dc1b610652e358b30b71f94ff748940 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Tue, 31 Oct 2023 22:53:20 +0000
Subject: [PATCH 7/8] fixup! test: make variable name clearer

---
 .../debug-info-static-inline-member.cpp       | 22 +++++++++----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/clang/test/CodeGenCXX/debug-info-static-inline-member.cpp b/clang/test/CodeGenCXX/debug-info-static-inline-member.cpp
index 2a17dfc88140553..16872b752167ad9 100644
--- a/clang/test/CodeGenCXX/debug-info-static-inline-member.cpp
+++ b/clang/test/CodeGenCXX/debug-info-static-inline-member.cpp
@@ -9,11 +9,11 @@ struct Empty {};
 constexpr auto func() { return 25; }
 
 struct Foo {
-    static constexpr int cexpr_int = func();
+    static constexpr int cexpr_int_with_addr = func();
     static constexpr int cexpr_int2 = func() + 1;
     static constexpr float cexpr_float = 2.0 + 1.0;
     static constexpr Enum cexpr_enum = Enum::VAL;
-    static constexpr Empty cexpr_empty{};
+    static constexpr Empty cexpr_struct_with_addr{};
     static inline    Enum inline_enum = Enum::VAL;
 
     template<typename T>
@@ -24,24 +24,24 @@ int main() {
     Foo f;
 
     // Force global variable definitions to be emitted.
-    (void)&Foo::cexpr_int;
-    (void)&Foo::cexpr_empty;
+    (void)&Foo::cexpr_int_with_addr;
+    (void)&Foo::cexpr_struct_with_addr;
 
-    return Foo::cexpr_int + Foo::cexpr_float
+    return Foo::cexpr_int_with_addr + Foo::cexpr_float
            + (int)Foo::cexpr_enum + Foo::cexpr_template<short>;
 }
 
-// CHECK:      @{{.*}}cexpr_int{{.*}} =
+// CHECK:      @{{.*}}cexpr_int_with_addr{{.*}} =
 // CHECK-SAME:   !dbg ![[INT_GLOBAL:[0-9]+]]
 
-// CHECK:      @{{.*}}cexpr_empty{{.*}} = 
+// CHECK:      @{{.*}}cexpr_struct_with_addr{{.*}} = 
 // CHECK-SAME    !dbg ![[EMPTY_GLOBAL:[0-9]+]]
 
 // CHECK:      !DIGlobalVariableExpression(var: ![[INT_VAR:[0-9]+]], expr: !DIExpression())
-// CHECK:      ![[INT_VAR]] = distinct !DIGlobalVariable(name: "cexpr_int", linkageName:
+// CHECK:      ![[INT_VAR]] = distinct !DIGlobalVariable(name: "cexpr_int_with_addr", linkageName:
 // CHECK-SAME:                isLocal: false, isDefinition: true, declaration: ![[INT_DECL:[0-9]+]])
 
-// CHECK:      ![[INT_DECL]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_int",
+// CHECK:      ![[INT_DECL]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_int_with_addr",
 // CHECK-SAME:                 flags: DIFlagStaticMember
 // CHECK-NOT:                  extraData:
 
@@ -57,7 +57,7 @@ int main() {
 // CHECK-SAME:                         flags: DIFlagStaticMember
 // CHECK-NOT:                          extraData:
 
-// CHECK:      ![[EMPTY_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_empty",
+// CHECK:      ![[EMPTY_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_struct_with_addr",
 // CHECK-SAME:                          flags: DIFlagStaticMember
 // CHECK-NOT:                           extraData:
 
@@ -70,7 +70,7 @@ int main() {
 // CHECK-NOT:                              extraData:
 
 // CHECK:      !DIGlobalVariableExpression(var: ![[EMPTY_VAR:[0-9]+]], expr: !DIExpression())
-// CHECK:      ![[EMPTY_VAR]] = distinct !DIGlobalVariable(name: "cexpr_empty", linkageName:
+// CHECK:      ![[EMPTY_VAR]] = distinct !DIGlobalVariable(name: "cexpr_struct_with_addr", linkageName:
 // CHECK-SAME:                  isLocal: false, isDefinition: true, declaration: ![[EMPTY_DECL]])
 
 // CHECK:      !DIGlobalVariableExpression(var: ![[INT_VAR2:[0-9]+]], expr: !DIExpression(DW_OP_constu, 26, DW_OP_stack_value))

>From d1894b0b3eec4e3ed3fda8f9e2bf0dc5fc3da179 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Wed, 1 Nov 2023 14:33:55 +0000
Subject: [PATCH 8/8] fixup! fix lldb-dap test

---
 .../API/tools/lldb-dap/variables/TestDAP_variables.py    | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/lldb/test/API/tools/lldb-dap/variables/TestDAP_variables.py b/lldb/test/API/tools/lldb-dap/variables/TestDAP_variables.py
index 11d9bf18db7a6e1..d2a21ad3cd1d44f 100644
--- a/lldb/test/API/tools/lldb-dap/variables/TestDAP_variables.py
+++ b/lldb/test/API/tools/lldb-dap/variables/TestDAP_variables.py
@@ -87,10 +87,11 @@ def verify_values(self, verify_dict, actual, varref_dict=None, expression=None):
     def verify_variables(self, verify_dict, variables, varref_dict=None):
         for variable in variables:
             name = variable["name"]
-            self.assertIn(
-                name, verify_dict, 'variable "%s" in verify dictionary' % (name)
-            )
-            self.verify_values(verify_dict[name], variable, varref_dict)
+            if not name.startswith("std::"):
+                self.assertIn(
+                    name, verify_dict, 'variable "%s" in verify dictionary' % (name)
+                )
+                self.verify_values(verify_dict[name], variable, varref_dict)
 
     def darwin_dwarf_missing_obj(self, initCommands):
         self.build(debug_info="dwarf")



More information about the cfe-commits mailing list