jarin created this revision.
jarin added a reviewer: teemperor.
jarin added a project: LLDB.
Herald added subscribers: lldb-commits, JDevlieghere.
Herald added a reviewer: shafik.
jarin requested review of this revision.

This patch is for discussion.

Currently, the evaluator does not know about static const fields if
the code does not contain a definition (but only a declaration).

For example:

  struct C { static const int f = 42; };
  int main() {
    return C::f;  // Evaluating C::f does not work here!
  }

This patch tries to fix that by initializing the varDecl of the static
field with the constant value. This works reasonably well when the
static member is only used as rvalue, but any lvalue usage still does
not work because the static member does not have a memory location.

To fix this properly, do we have to teach the materializer about the
static fields, too? What would be the best way to go about that?


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D85719

Files:
  lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
  lldb/test/API/lang/cpp/static_const_members/Makefile
  lldb/test/API/lang/cpp/static_const_members/TestStaticConstMembers.py
  lldb/test/API/lang/cpp/static_const_members/main.cpp

Index: lldb/test/API/lang/cpp/static_const_members/main.cpp
===================================================================
--- /dev/null
+++ lldb/test/API/lang/cpp/static_const_members/main.cpp
@@ -0,0 +1,29 @@
+enum class E {
+  E0 = 0,
+  E42 = 42,
+};
+
+struct C {
+  static const int static_const_i32 = 40;
+  static const int static_const_i32_neg = -40;
+  static constexpr int static_constexpr_i32 = 41;
+  static const unsigned static_const_ui32 = 0xffffffff;
+  static constexpr unsigned static_constexpr_ui32 = 0xfffffffe;
+  static const int static_const_var_i32;
+  static constexpr int static_constexpr_i32_other = 43;
+  static const E static_const_enum = E::E42;
+  static const char static_const_i8 = -1;
+};
+
+const int C::static_const_var_i32 = 42;
+constexpr int C::static_constexpr_i32_other;
+
+int deref(const int *p) { return *p; }
+
+int main() {
+  const int *pi = &C::static_constexpr_i32_other;
+  int rv = C::static_const_i32 + C::static_const_i32_neg +
+           C::static_constexpr_i32 + (int)C::static_const_ui32 +
+           C::static_const_var_i32 + deref(pi);
+  return rv; // break here
+}
Index: lldb/test/API/lang/cpp/static_const_members/TestStaticConstMembers.py
===================================================================
--- /dev/null
+++ lldb/test/API/lang/cpp/static_const_members/TestStaticConstMembers.py
@@ -0,0 +1,50 @@
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+import lldbsuite.test.lldbutil as lldbutil
+
+
+class TestStaticConstMembers(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+    NO_DEBUG_INFO_TESTCASE = True
+
+    def test_static_const_var_definition(self):
+        self.build()
+        lldbutil.run_to_source_breakpoint(self, "// break here",
+            lldb.SBFileSpec("main.cpp", False))
+        self.expect_expr("C::static_const_var_i32", result_value="42")
+        self.expect_expr("C::static_constexpr_i32_other", result_value="43")
+
+    @expectedFailureAll()
+    def test_static_const_member_lval(self):
+        self.build()
+        lldbutil.run_to_source_breakpoint(self, "// break here",
+            lldb.SBFileSpec("main.cpp", False))
+        self.expect_expr("C::static_const_i32", result_value="40")
+        self.expect_expr("C::static_const_i32_neg", result_value="-40")
+        self.expect_expr("C::static_constexpr_i32", result_value="41")
+        self.expect_expr("C::static_const_ui32", result_value="4294967295")
+        self.expect_expr("C::static_const_enum", result_value="E42")
+        self.expect_expr("C::static_const_i8", result_value="-1")
+
+    def test_static_const_member_rval(self):
+        self.build()
+        lldbutil.run_to_source_breakpoint(self, "// break here",
+            lldb.SBFileSpec("main.cpp", False))
+        self.expect_expr("C::static_const_i32 + 2", result_value="42")
+        self.expect_expr("-C::static_const_i32_neg", result_value="40")
+        self.expect_expr("C::static_constexpr_i32 | 0", result_value="41")
+        self.expect_expr("-C::static_const_ui32", result_value="1")
+        self.expect_expr("C::static_const_ui32 + 0u", result_value="4294967295")
+        self.expect_expr("-C::static_constexpr_ui32", result_value="2")
+        self.expect_expr("(int)C::static_const_enum", result_value="42")
+        self.expect_expr("C::static_const_i8 + 0", result_value="-1")
+
+    @expectedFailureAll()
+    def test_static_const_member_address(self):
+        self.build()
+        lldbutil.run_to_source_breakpoint(self, "// break here",
+            lldb.SBFileSpec("main.cpp", False))
+        self.expect_expr("deref(&(C::static_const_var_i32))", result_value="42")
+        self.expect_expr("deref(&(C::static_const_i32))", result_value="40")
Index: lldb/test/API/lang/cpp/static_const_members/Makefile
===================================================================
--- /dev/null
+++ lldb/test/API/lang/cpp/static_const_members/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -2355,6 +2355,7 @@
   bool is_external =
       false; // On DW_TAG_members, this means the member is static
   uint32_t i;
+  clang::Optional<uint64_t> integer_const_value;
   for (i = 0; i < num_attributes && !is_artificial; ++i) {
     const dw_attr_t attr = attributes.AttributeAtIndex(i);
     DWARFFormValue form_value;
@@ -2432,6 +2433,11 @@
       case DW_AT_external:
         is_external = form_value.Boolean();
         break;
+      case DW_AT_const_value:
+        if (DWARFFormValue::IsDataForm(form_value.Form())) {
+          integer_const_value = form_value.Unsigned();
+        }
+        break;
 
       default:
       case DW_AT_declaration:
@@ -2508,9 +2514,18 @@
     if (var_type) {
       if (accessibility == eAccessNone)
         accessibility = eAccessPublic;
-      TypeSystemClang::AddVariableToRecordType(
-          class_clang_type, name, var_type->GetLayoutCompilerType(),
-          accessibility);
+      CompilerType layout_var_type = var_type->GetLayoutCompilerType();
+      clang::VarDecl *var_decl = TypeSystemClang::AddVariableToRecordType(
+          class_clang_type, name, layout_var_type, accessibility);
+      bool is_signed = false;
+      if (integer_const_value &&
+          layout_var_type.IsIntegerOrEnumerationType(is_signed)) {
+        clang::QualType var_qual_type = var_decl->getType();
+        unsigned var_bit_size =
+            m_ast.getASTContext().getIntWidth(var_qual_type);
+        llvm::APInt init_value(var_bit_size, *integer_const_value, is_signed);
+        TypeSystemClang::SetIntegerInitializerForVariable(var_decl, init_value);
+      }
     }
     return;
   }
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
  • [Lldb-commits] [PATCH] D8... Jaroslav Sevcik via Phabricator via lldb-commits

Reply via email to