[Lldb-commits] [lldb] [lldb][DWARFASTParserClang] Fetch constant value from variable defintion if available (PR #71004)
Michael Buch via lldb-commits
lldb-commits at lists.llvm.org
Thu Nov 2 06:29:02 PDT 2023
https://github.com/Michael137 updated https://github.com/llvm/llvm-project/pull/71004
>From a3d165aa30e8cd32877f30812b41fee380e24e60 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Wed, 1 Nov 2023 12:25:06 +0000
Subject: [PATCH 1/6] [lldb][DWARFASTParserClang] Fetch constant value from
variable definition if available
---
.../SymbolFile/DWARF/DWARFASTParserClang.cpp | 63 ++++++++++++++++++-
.../SymbolFile/DWARF/DWARFASTParserClang.h | 3 +
.../SymbolFile/DWARF/SymbolFileDWARF.h | 10 +--
.../TestConstStaticIntegralMember.py | 21 +++++++
.../cpp/const_static_integral_member/main.cpp | 21 +++++++
5 files changed, 112 insertions(+), 6 deletions(-)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 182cc6764651747..8d1b08c492daa35 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -10,6 +10,7 @@
#include "DWARFASTParser.h"
#include "DWARFASTParserClang.h"
+#include "DWARFCompileUnit.h"
#include "DWARFDebugInfo.h"
#include "DWARFDeclContext.h"
#include "DWARFDefines.h"
@@ -26,11 +27,13 @@
#include "lldb/Core/Value.h"
#include "lldb/Host/Host.h"
#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/CompilerDeclContext.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/TypeList.h"
#include "lldb/Symbol/TypeMap.h"
+#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/Language.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Log.h"
@@ -133,6 +136,52 @@ static lldb::ModuleSP GetContainingClangModule(const DWARFDIE &die) {
return lldb::ModuleSP();
}
+std::optional<DWARFFormValue>
+DWARFASTParserClang::FindConstantOnVariableDefinition(DWARFDIE die) {
+ auto *dwarf = die.GetDWARF();
+ if (!dwarf)
+ return {};
+
+ ConstString name{die.GetName()};
+ if (!name)
+ return {};
+
+ auto *CU = die.GetCU();
+ if (!CU)
+ return {};
+
+ DWARFASTParser *dwarf_ast = dwarf->GetDWARFParser(*CU);
+ auto parent_decl_ctx = dwarf_ast->GetDeclContextContainingUIDFromDWARF(die);
+
+ // Make sure we populate the GetDieToVariable cache.
+ VariableList variables;
+ dwarf->FindGlobalVariables(name, parent_decl_ctx, UINT_MAX, variables);
+
+ // The cache contains the variable definition whose DW_AT_specification
+ // points to our declaration DIE. Look up that definition using our
+ // declaration.
+ auto const &die_to_var = dwarf->GetDIEToVariable();
+ auto it = die_to_var.find(die.GetDIE());
+ if (it == die_to_var.end())
+ return {};
+
+ auto var_sp = it->getSecond();
+ assert(var_sp != nullptr);
+
+ if (!var_sp->GetLocationIsConstantValueData())
+ return {};
+
+ auto def = dwarf->GetDIE(var_sp->GetID());
+ auto def_attrs = def.GetAttributes();
+ DWARFFormValue form_value;
+ if (!def_attrs.ExtractFormValueAtIndex(
+ def_attrs.FindAttributeIndex(llvm::dwarf::DW_AT_const_value),
+ form_value))
+ return {};
+
+ return form_value;
+}
+
TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc,
const DWARFDIE &die,
Log *log) {
@@ -2906,9 +2955,21 @@ void DWARFASTParserClang::ParseSingleMember(
bool unused;
// TODO: Support float/double static members as well.
- if (!attrs.const_value_form || !ct.IsIntegerOrEnumerationType(unused))
+ if (!ct.IsIntegerOrEnumerationType(unused))
return;
+ // Newer versions of Clang don't emit the DW_AT_const_value
+ // on the declaration of a inline static data member. Instead
+ // it's attached to the definition DIE. If that's the case,
+ // try and fetch it.
+ if (!attrs.const_value_form) {
+ auto maybe_form_value = FindConstantOnVariableDefinition(die);
+ if (!maybe_form_value)
+ return;
+
+ attrs.const_value_form = *maybe_form_value;
+ }
+
llvm::Expected<llvm::APInt> const_value_or_err =
ExtractIntFromFormValue(ct, *attrs.const_value_form);
if (!const_value_or_err) {
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
index c381c58fba74263..399a6b9176620fd 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
@@ -373,6 +373,9 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser {
lldb_private::CompilerType &class_clang_type,
const lldb::AccessType default_accesibility,
lldb_private::ClangASTImporter::LayoutInfo &layout_info);
+
+ std::optional<lldb_private::plugin::dwarf::DWARFFormValue>
+ FindConstantOnVariableDefinition(lldb_private::plugin::dwarf::DWARFDIE die);
};
/// Parsed form of all attributes that are relevant for type reconstruction.
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index 069a2050f0eaadc..ba4532c48338b76 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -342,6 +342,11 @@ class SymbolFileDWARF : public SymbolFileCommon {
return m_forward_decl_compiler_type_to_die;
}
+ typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::VariableSP>
+ DIEToVariableSP;
+
+ virtual DIEToVariableSP &GetDIEToVariable() { return m_die_to_variable_sp; }
+
virtual UniqueDWARFASTTypeMap &GetUniqueDWARFASTTypeMap();
bool ClassOrStructIsVirtual(const DWARFDIE &die);
@@ -361,9 +366,6 @@ class SymbolFileDWARF : public SymbolFileCommon {
Type *ResolveTypeUID(const DIERef &die_ref);
protected:
- typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::VariableSP>
- DIEToVariableSP;
-
SymbolFileDWARF(const SymbolFileDWARF &) = delete;
const SymbolFileDWARF &operator=(const SymbolFileDWARF &) = delete;
@@ -487,8 +489,6 @@ class SymbolFileDWARF : public SymbolFileCommon {
void UpdateExternalModuleListIfNeeded();
- virtual DIEToVariableSP &GetDIEToVariable() { return m_die_to_variable_sp; }
-
void BuildCuTranslationTable();
std::optional<uint32_t> GetDWARFUnitIndex(uint32_t cu_idx);
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..bd4a12ef9582720 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
@@ -138,3 +138,24 @@ def test_class_with_only_constexpr_static(self):
self.expect_expr(
"ClassWithEnumAlias::enum_alias_alias", result_value="scoped_enum_case1"
)
+
+ def test_shadowed_static_inline_members(self):
+ """Tests that the expression evaluator and SBAPI can both
+ correctly determine the requested inline static variable
+ in the presence of multiple variables of the same name."""
+
+ self.build()
+ lldbutil.run_to_name_breakpoint(self, "bar")
+
+ self.check_global_var("ns::Foo::mem", "const int", "10")
+
+ self.expect_expr("mem", result_value="10")
+ self.expect_expr("Foo::mem", result_value="10")
+ self.expect_expr("ns::Foo::mem", result_value="10")
+ self.expect_expr("::Foo::mem", result_value="-29")
+
+ @expectedFailureAll(bugnumber="target var doesn't honour global namespace")
+ def test_shadowed_static_inline_members_xfail(self):
+ self.build()
+ lldbutil.run_to_name_breakpoint(self, "bar")
+ self.check_global_var("::Foo::mem", "const int", "-29")
diff --git a/lldb/test/API/lang/cpp/const_static_integral_member/main.cpp b/lldb/test/API/lang/cpp/const_static_integral_member/main.cpp
index 4275f471df6aed1..26627b7148e45f5 100644
--- a/lldb/test/API/lang/cpp/const_static_integral_member/main.cpp
+++ b/lldb/test/API/lang/cpp/const_static_integral_member/main.cpp
@@ -1,3 +1,4 @@
+#include <cstdio>
#include <limits>
enum Enum {
@@ -89,6 +90,25 @@ struct ClassWithEnumAlias {
ScopedEnum::scoped_enum_case1;
};
+namespace ns {
+struct Foo {
+ constexpr static int mem = 10;
+
+ void bar() { return; }
+};
+} // namespace ns
+
+struct Foo {
+ constexpr static int mem = -29;
+};
+
+int func() {
+ Foo f1;
+ ns::Foo f2;
+ f2.bar();
+ return ns::Foo::mem + Foo::mem;
+}
+
int main() {
A a;
@@ -124,6 +144,7 @@ int main() {
auto enum_alias_val = ClassWithEnumAlias::enum_alias;
auto enum_alias_alias_val = ClassWithEnumAlias::enum_alias_alias;
+ auto ret = func();
return 0; // break here
}
>From 5a37a703cd7c44bf9ecdfdfb77491ce9a18a4a72 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Thu, 2 Nov 2023 13:08:48 +0000
Subject: [PATCH 2/6] fixup! doxygen comment and add assertion
---
.../Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp | 3 +++
lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h | 7 +++++++
2 files changed, 10 insertions(+)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 8d1b08c492daa35..e1486ced5bee784 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -44,6 +44,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Type.h"
+#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/Demangle/Demangle.h"
#include <map>
@@ -138,6 +139,8 @@ static lldb::ModuleSP GetContainingClangModule(const DWARFDIE &die) {
std::optional<DWARFFormValue>
DWARFASTParserClang::FindConstantOnVariableDefinition(DWARFDIE die) {
+ assert (die.Tag() == llvm::dwarf::DW_TAG_member);
+
auto *dwarf = die.GetDWARF();
if (!dwarf)
return {};
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
index 399a6b9176620fd..01b60bc8ac39f3d 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
@@ -374,6 +374,13 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser {
const lldb::AccessType default_accesibility,
lldb_private::ClangASTImporter::LayoutInfo &layout_info);
+ /// Tries to find the definition DW_TAG_variable DIE of the the specified
+ /// DW_TAG_member 'die'. If such definition exists, returns the DW_AT_const_value
+ /// of that definition if available. Returns std::nullopt otherwise.
+ ///
+ /// In newer versions of clang, DW_AT_const_value's are not attached to the
+ /// declaration of a inline static data-member anymore, but rather on its definition.
+ /// This function is used to locate said constant.
std::optional<lldb_private::plugin::dwarf::DWARFFormValue>
FindConstantOnVariableDefinition(lldb_private::plugin::dwarf::DWARFDIE die);
};
>From df6d86e5c99fbc25defcfa24c3bc3f0572465e5e Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Thu, 2 Nov 2023 13:11:59 +0000
Subject: [PATCH 3/6] fixup! remove redundant header additions
---
lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp | 2 --
1 file changed, 2 deletions(-)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index e1486ced5bee784..d4749893b9f7ce7 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -10,7 +10,6 @@
#include "DWARFASTParser.h"
#include "DWARFASTParserClang.h"
-#include "DWARFCompileUnit.h"
#include "DWARFDebugInfo.h"
#include "DWARFDeclContext.h"
#include "DWARFDefines.h"
@@ -27,7 +26,6 @@
#include "lldb/Core/Value.h"
#include "lldb/Host/Host.h"
#include "lldb/Symbol/CompileUnit.h"
-#include "lldb/Symbol/CompilerDeclContext.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolFile.h"
>From 564ce949f5e27c4f84e0a15fd08feeb2771db1f6 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Thu, 2 Nov 2023 13:12:58 +0000
Subject: [PATCH 4/6] fixup! remove redundant header additions
---
lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index d4749893b9f7ce7..069d61943ba5b4e 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -42,7 +42,6 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Type.h"
-#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/Demangle/Demangle.h"
#include <map>
>From bdd0ea604f5ce1b8c2b331aaa808ba5883c8aaac Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Thu, 2 Nov 2023 13:14:54 +0000
Subject: [PATCH 5/6] fixup! remove redundant header additions in test
---
lldb/test/API/lang/cpp/const_static_integral_member/main.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/lldb/test/API/lang/cpp/const_static_integral_member/main.cpp b/lldb/test/API/lang/cpp/const_static_integral_member/main.cpp
index 26627b7148e45f5..fb0b49e2d7aad7a 100644
--- a/lldb/test/API/lang/cpp/const_static_integral_member/main.cpp
+++ b/lldb/test/API/lang/cpp/const_static_integral_member/main.cpp
@@ -1,4 +1,3 @@
-#include <cstdio>
#include <limits>
enum Enum {
>From 878ed276d19bdc19ad1fcf8e9a9af15ea13b6d66 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Thu, 2 Nov 2023 13:28:16 +0000
Subject: [PATCH 6/6] fixup! clang-format
---
.../Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp | 2 +-
.../Plugins/SymbolFile/DWARF/DWARFASTParserClang.h | 9 +++++----
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 069d61943ba5b4e..228434211df56c7 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -136,7 +136,7 @@ static lldb::ModuleSP GetContainingClangModule(const DWARFDIE &die) {
std::optional<DWARFFormValue>
DWARFASTParserClang::FindConstantOnVariableDefinition(DWARFDIE die) {
- assert (die.Tag() == llvm::dwarf::DW_TAG_member);
+ assert(die.Tag() == llvm::dwarf::DW_TAG_member);
auto *dwarf = die.GetDWARF();
if (!dwarf)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
index 01b60bc8ac39f3d..893a0315c8524e4 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
@@ -375,12 +375,13 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser {
lldb_private::ClangASTImporter::LayoutInfo &layout_info);
/// Tries to find the definition DW_TAG_variable DIE of the the specified
- /// DW_TAG_member 'die'. If such definition exists, returns the DW_AT_const_value
- /// of that definition if available. Returns std::nullopt otherwise.
+ /// DW_TAG_member 'die'. If such definition exists, returns the
+ /// DW_AT_const_value of that definition if available. Returns std::nullopt
+ /// otherwise.
///
/// In newer versions of clang, DW_AT_const_value's are not attached to the
- /// declaration of a inline static data-member anymore, but rather on its definition.
- /// This function is used to locate said constant.
+ /// declaration of a inline static data-member anymore, but rather on its
+ /// definition. This function is used to locate said constant.
std::optional<lldb_private::plugin::dwarf::DWARFFormValue>
FindConstantOnVariableDefinition(lldb_private::plugin::dwarf::DWARFDIE die);
};
More information about the lldb-commits
mailing list