kpdev42 updated this revision to Diff 511683.
kpdev42 edited the summary of this revision.
kpdev42 added a comment.

Address review comments


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D143347/new/

https://reviews.llvm.org/D143347

Files:
  lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
  lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
  lldb/test/API/lang/cpp/no_unique_address/Makefile
  lldb/test/API/lang/cpp/no_unique_address/TestNoUniqueAddress.py
  lldb/test/API/lang/cpp/no_unique_address/main.cpp

Index: lldb/test/API/lang/cpp/no_unique_address/main.cpp
===================================================================
--- /dev/null
+++ lldb/test/API/lang/cpp/no_unique_address/main.cpp
@@ -0,0 +1,67 @@
+struct C
+{
+ long c,d;
+};
+
+struct Q
+{
+ long h;
+};
+
+struct D
+{
+};
+
+struct B
+{
+  [[no_unique_address]] D x;
+};
+
+struct E
+{
+  [[no_unique_address]] D x;
+};
+
+struct Foo1 : B,E,C
+{
+ long a = 42,b = 52;
+} _f1;
+
+struct Foo2 : B,E
+{
+ long v = 42;
+} _f2;
+
+struct Foo3 : C,B,E
+{
+ long v = 42;
+} _f3;
+
+struct Foo4 : B,C,E,Q
+{
+ long v = 42;
+} _f4;
+
+struct Foo5 : B,C,E
+{
+ [[no_unique_address]] D x1;
+ [[no_unique_address]] D x2;
+ long v1 = 42;
+ [[no_unique_address]] D y1;
+ [[no_unique_address]] D y2;
+ long v2 = 52;
+ [[no_unique_address]] D z1;
+ [[no_unique_address]] D z2;
+} _f5;
+
+struct Foo6 : B,E
+{
+ long v1 = 42;
+ [[no_unique_address]] D y1;
+ [[no_unique_address]] D y2;
+ long v2 = 52;
+} _f6;
+
+int main() {
+  return 0; // Set breakpoint here.
+}
Index: lldb/test/API/lang/cpp/no_unique_address/TestNoUniqueAddress.py
===================================================================
--- /dev/null
+++ lldb/test/API/lang/cpp/no_unique_address/TestNoUniqueAddress.py
@@ -0,0 +1,28 @@
+"""
+Test that we correctly handle [[no_unique_address]] attribute.
+"""
+
+import lldb
+
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class TestInlineNamespace(TestBase):
+
+    def test(self):
+        self.build()
+
+        lldbutil.run_to_source_breakpoint(self,
+            "// Set breakpoint here.", lldb.SBFileSpec("main.cpp"))
+
+        self.expect_expr("_f1.a", result_type="long", result_value="42")
+        self.expect_expr("_f1.b", result_type="long", result_value="52")
+        self.expect_expr("_f2.v", result_type="long", result_value="42")
+        self.expect_expr("_f3.v", result_type="long", result_value="42")
+        self.expect_expr("_f4.v", result_type="long", result_value="42")
+        self.expect_expr("_f5.v1", result_type="long", result_value="42")
+        self.expect_expr("_f5.v2", result_type="long", result_value="52")
+        self.expect_expr("_f6.v1", result_type="long", result_value="42")
+        self.expect_expr("_f6.v2", result_type="long", result_value="52")
Index: lldb/test/API/lang/cpp/no_unique_address/Makefile
===================================================================
--- /dev/null
+++ lldb/test/API/lang/cpp/no_unique_address/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
@@ -223,6 +223,7 @@
     uint64_t bit_size = 0;
     uint64_t bit_offset = 0;
     bool is_bitfield = false;
+    clang::FieldDecl *field_decl = nullptr;
 
     FieldInfo() = default;
 
@@ -275,6 +276,10 @@
                               const ParsedDWARFTypeAttributes &attrs);
   lldb::TypeSP ParsePointerToMemberType(const DWARFDIE &die,
                                         const ParsedDWARFTypeAttributes &attrs);
+  void FixupBaseClasses(
+      std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> &base_classes,
+      const lldb_private::ClangASTImporter::LayoutInfo &layout_info,
+      long byte_offset);
 
   /// Parses a DW_TAG_inheritance DIE into a base/super class.
   ///
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -1366,6 +1366,28 @@
   return nullptr;
 }
 
+void DWARFASTParserClang::FixupBaseClasses(
+    std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> &base_classes,
+    const ClangASTImporter::LayoutInfo &layout_info, long byte_offset) {
+  for (auto it = base_classes.rbegin(); it != base_classes.rend(); ++it) {
+    clang::CXXRecordDecl *prev_base_decl =
+        (*it)->getType()->getAsCXXRecordDecl();
+    // We've already marked this class, exit.
+    if (prev_base_decl->isEmpty())
+      break;
+    auto it_layout = layout_info.base_offsets.find(prev_base_decl);
+    if (it_layout == layout_info.base_offsets.end())
+      continue;
+    // We found a normal base class, exit.
+    if (it_layout->second.getQuantity() < byte_offset)
+      break;
+    prev_base_decl->markEmpty();
+    for (auto *field : prev_base_decl->fields())
+      field->addAttr(clang::NoUniqueAddressAttr::Create(m_ast.getASTContext(),
+                                                        clang::SourceRange()));
+  }
+}
+
 void DWARFASTParserClang::ParseInheritance(
     const DWARFDIE &die, const DWARFDIE &parent_die,
     const CompilerType class_clang_type, const AccessType default_accessibility,
@@ -1460,8 +1482,6 @@
   if (!result)
     return;
 
-  base_classes.push_back(std::move(result));
-
   if (is_virtual) {
     // Do not specify any offset for virtual inheritance. The DWARF
     // produced by clang doesn't give us a constant offset, but gives
@@ -1476,10 +1496,18 @@
     // be removed from LayoutRecordType() in the external
     // AST source in clang.
   } else {
+    // DWARF doesn't have any representation for [[no_unique_address]]
+    // attribute. Empty base classes with [[no_unique_address]] fields
+    // confuse lldb and prevent construction of object memory layout.
+    // To fix this we scan base classes in reverse order to determine
+    // overlapping offsets. Wnen found we consider such class as empty
+    // base with all fields having [[no_unique_address]] attribute.
+    FixupBaseClasses(base_classes, layout_info, member_byte_offset);
     layout_info.base_offsets.insert(std::make_pair(
         ast->GetAsCXXRecordDecl(base_class_clang_type.GetOpaqueQualType()),
         clang::CharUnits::fromQuantity(member_byte_offset)));
   }
+  base_classes.push_back(std::move(result));
 }
 
 TypeSP DWARFASTParserClang::UpdateSymbolContextScopeForType(
@@ -2991,7 +3019,7 @@
       attrs.bit_size);
 
   m_ast.SetMetadataAsUserID(field_decl, die.GetID());
-
+  last_field_info.field_decl = field_decl;
   layout_info.field_offsets.insert(
       std::make_pair(field_decl, field_bit_offset));
 }
@@ -3007,6 +3035,7 @@
     return false;
 
   FieldInfo last_field_info;
+  std::vector<FieldInfo> seen_fields;
 
   ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule();
   auto ts = class_clang_type.GetTypeSystem();
@@ -3025,6 +3054,21 @@
     case DW_TAG_member:
       ParseSingleMember(die, parent_die, class_clang_type,
                         default_accessibility, layout_info, last_field_info);
+      if (!last_field_info.field_decl)
+        break;
+      for (auto it = seen_fields.rbegin(); it != seen_fields.rend(); ++it) {
+        FieldInfo &fi = *it;
+        if (fi.field_decl->hasAttr<clang::NoUniqueAddressAttr>())
+          break;
+        if (fi.bit_offset >= last_field_info.bit_offset)
+          fi.field_decl->addAttr(clang::NoUniqueAddressAttr::Create(
+              ast->getASTContext(), clang::SourceRange()));
+        else
+          break;
+      }
+      FixupBaseClasses(base_classes, layout_info,
+                        last_field_info.bit_offset / 8);
+      seen_fields.push_back(last_field_info);
       break;
 
     case DW_TAG_subprogram:
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to