jankratochvil updated this revision to Diff 350900.
jankratochvil edited the summary of this revision.
jankratochvil added a comment.

This patch now requires: D101236 <https://reviews.llvm.org/D101236>, D103910 
<https://reviews.llvm.org/D103910> and D103966 
<https://reviews.llvm.org/D103966>.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D101237

Files:
  clang/lib/AST/ASTImporter.cpp
  clang/lib/CodeGen/CGDebugInfo.cpp
  clang/lib/CodeGen/CGDebugInfo.h
  lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp
  lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
  lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
  lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
  lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
  lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
  lldb/test/Shell/Expr/no_unique_address.cpp
  llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp

Index: llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
===================================================================
--- llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -1603,12 +1603,16 @@
       } else {
         addUInt(MemberDie, dwarf::DW_AT_data_bit_offset, None, Offset);
       }
+      assert(!(DT->getFlags() & DINode::FlagIsZeroSize) &&
+             "bitfields cannot have [[no_unique_address]]");
     } else {
       // This is not a bitfield.
       OffsetInBytes = DT->getOffsetInBits() / 8;
       if (AlignInBytes)
         addUInt(MemberDie, dwarf::DW_AT_alignment, dwarf::DW_FORM_udata,
                 AlignInBytes);
+      if (DT->getFlags() & DINode::FlagIsZeroSize)
+        addUInt(MemberDie, dwarf::DW_AT_byte_size, None, 0);
     }
 
     if (DD->getDwarfVersion() <= 2) {
Index: lldb/test/Shell/Expr/no_unique_address.cpp
===================================================================
--- /dev/null
+++ lldb/test/Shell/Expr/no_unique_address.cpp
@@ -0,0 +1,15 @@
+// Test LLDB does not assert on miscalculated field offsets.
+
+// RUN: %clang_host %s -g -c -o %t.o
+// RUN: %lldb %t.o -o "p c.c" -o exit | FileCheck %s
+
+// CHECK: (lldb) p c.c
+// CHECK-NEXT: (char) $0 = '\0'
+
+struct A {};
+struct B {
+  [[no_unique_address]] A a;
+};
+struct C : B {
+  char c;
+} c;
Index: lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
===================================================================
--- lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
+++ lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
@@ -843,11 +843,10 @@
                            CompilerType *child_type = nullptr);
 
   // Modifying RecordType
-  static clang::FieldDecl *AddFieldToRecordType(const CompilerType &type,
-                                                llvm::StringRef name,
-                                                const CompilerType &field_type,
-                                                lldb::AccessType access,
-                                                uint32_t bitfield_bit_size);
+  static clang::FieldDecl *
+  AddFieldToRecordType(const CompilerType &type, llvm::StringRef name,
+                       const CompilerType &field_type, lldb::AccessType access,
+                       uint32_t bitfield_bit_size, bool IsZeroSize = false);
 
   static void BuildIndirectFields(const CompilerType &type);
 
Index: lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
===================================================================
--- lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -7164,7 +7164,7 @@
 clang::FieldDecl *TypeSystemClang::AddFieldToRecordType(
     const CompilerType &type, llvm::StringRef name,
     const CompilerType &field_clang_type, AccessType access,
-    uint32_t bitfield_bit_size) {
+    uint32_t bitfield_bit_size, bool IsZeroSize) {
   if (!type.IsValid() || !field_clang_type.IsValid())
     return nullptr;
   TypeSystemClang *ast =
@@ -7196,6 +7196,8 @@
     if (bit_width)
       field->setBitWidth(bit_width);
     SetMemberOwningModule(field, record_decl);
+    if (IsZeroSize)
+      field->addAttr(NoUniqueAddressAttr::CreateImplicit(ast->getASTContext()));
 
     if (name.empty()) {
       // Determine whether this field corresponds to an anonymous struct or
Index: lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
+++ lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
@@ -1264,8 +1264,10 @@
       if (location_type == PDB_LocType::ThisRel)
         bit_size *= 8;
 
+      bool IsZeroSize = false; // FIXME: Is there [[no_unique_address]] in PDB?
       auto decl = TypeSystemClang::AddFieldToRecordType(
-          record_type, member_name.c_str(), member_comp_type, access, bit_size);
+          record_type, member_name.c_str(), member_comp_type, access, bit_size,
+          IsZeroSize);
       if (!decl)
         continue;
 
Index: lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
+++ lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
@@ -228,9 +228,10 @@
 
   lldb::AccessType access = TranslateMemberAccess(data_member.getAccess());
 
+  bool IsZeroSize = false; // FIXME: Is there [[no_unique_address]] in PDB?
   clang::FieldDecl *decl = TypeSystemClang::AddFieldToRecordType(
       m_derived_ct, data_member.Name, m_ast_builder.ToCompilerType(member_qt),
-      access, bitfield_width);
+      access, bitfield_width, IsZeroSize);
   // FIXME: Add a PdbSymUid namespace for field list members and update
   // the m_uid_to_decl map with this decl.
 
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -2472,6 +2472,7 @@
       }
     }
   }
+  bool IsZeroSize = byte_size && *byte_size == 0;
 
   if (prop_name) {
     ConstString fixed_setter;
@@ -2721,8 +2722,8 @@
         RequireCompleteType(member_clang_type);
 
         field_decl = TypeSystemClang::AddFieldToRecordType(
-            class_clang_type, name, member_clang_type, accessibility,
-            bit_size);
+            class_clang_type, name, member_clang_type, accessibility, bit_size,
+            IsZeroSize);
 
         m_ast.SetMetadataAsUserID(field_decl, die.GetID());
 
Index: lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp
===================================================================
--- lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp
+++ lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp
@@ -99,9 +99,12 @@
   if (ptr_obj)
     m_ptr_obj = ptr_obj->Clone(ConstString("pointer")).get();
 
-  ValueObjectSP del_obj = tuple_frontend->GetChildAtIndex(1);
-  if (del_obj)
-    m_del_obj = del_obj->Clone(ConstString("deleter")).get();
+  // GCC 11 std::default_delete<...> has existing child with GetByteSize()==1.
+  if (tuple_sp->GetByteSize() > ptr_obj->GetByteSize()) {
+    ValueObjectSP del_obj = tuple_frontend->GetChildAtIndex(1);
+    if (del_obj)
+      m_del_obj = del_obj->Clone(ConstString("deleter")).get();
+  }
 
   if (m_ptr_obj) {
     Status error;
Index: clang/lib/CodeGen/CGDebugInfo.h
===================================================================
--- clang/lib/CodeGen/CGDebugInfo.h
+++ clang/lib/CodeGen/CGDebugInfo.h
@@ -296,15 +296,16 @@
                                 SourceLocation loc, AccessSpecifier AS,
                                 uint64_t offsetInBits, uint32_t AlignInBits,
                                 llvm::DIFile *tunit, llvm::DIScope *scope,
+                                bool IsZeroSize,
                                 const RecordDecl *RD = nullptr);
 
   llvm::DIType *createFieldType(StringRef name, QualType type,
                                 SourceLocation loc, AccessSpecifier AS,
                                 uint64_t offsetInBits, llvm::DIFile *tunit,
-                                llvm::DIScope *scope,
+                                llvm::DIScope *scope, bool IsZeroSize,
                                 const RecordDecl *RD = nullptr) {
     return createFieldType(name, type, loc, AS, offsetInBits, 0, tunit, scope,
-                           RD);
+                           IsZeroSize, RD);
   }
 
   /// Create new bit field member.
Index: clang/lib/CodeGen/CGDebugInfo.cpp
===================================================================
--- clang/lib/CodeGen/CGDebugInfo.cpp
+++ clang/lib/CodeGen/CGDebugInfo.cpp
@@ -1401,11 +1401,10 @@
       Flags, DebugType);
 }
 
-llvm::DIType *
-CGDebugInfo::createFieldType(StringRef name, QualType type, SourceLocation loc,
-                             AccessSpecifier AS, uint64_t offsetInBits,
-                             uint32_t AlignInBits, llvm::DIFile *tunit,
-                             llvm::DIScope *scope, const RecordDecl *RD) {
+llvm::DIType *CGDebugInfo::createFieldType(
+    StringRef name, QualType type, SourceLocation loc, AccessSpecifier AS,
+    uint64_t offsetInBits, uint32_t AlignInBits, llvm::DIFile *tunit,
+    llvm::DIScope *scope, bool IsZeroSize, const RecordDecl *RD) {
   llvm::DIType *debugType = getOrCreateType(type, tunit);
 
   // Get the location for the field.
@@ -1422,6 +1421,8 @@
   }
 
   llvm::DINode::DIFlags flags = getAccessFlag(AS, RD);
+  if (IsZeroSize)
+    flags |= llvm::DINode::FlagIsZeroSize;
   return DBuilder.createMemberType(scope, name, file, line, SizeInBits, Align,
                                    offsetInBits, flags, debugType);
 }
@@ -1439,6 +1440,9 @@
                                              E = CXXDecl->captures_end();
        I != E; ++I, ++Field, ++fieldno) {
     const LambdaCapture &C = *I;
+    bool IsZeroSize = false;
+    assert(!Field->isZeroSize(CGM.getContext()) &&
+           "lambdas cannot use [[no_unique_address]]!");
     if (C.capturesVariable()) {
       SourceLocation Loc = C.getLocation();
       assert(!Field->isBitField() && "lambdas don't have bitfield members!");
@@ -1446,9 +1450,10 @@
       StringRef VName = V->getName();
       llvm::DIFile *VUnit = getOrCreateFile(Loc);
       auto Align = getDeclAlignIfRequired(V, CGM.getContext());
-      llvm::DIType *FieldType = createFieldType(
-          VName, Field->getType(), Loc, Field->getAccess(),
-          layout.getFieldOffset(fieldno), Align, VUnit, RecordTy, CXXDecl);
+      llvm::DIType *FieldType =
+          createFieldType(VName, Field->getType(), Loc, Field->getAccess(),
+                          layout.getFieldOffset(fieldno), Align, VUnit,
+                          RecordTy, IsZeroSize, CXXDecl);
       elements.push_back(FieldType);
     } else if (C.capturesThis()) {
       // TODO: Need to handle 'this' in some way by probably renaming the
@@ -1460,7 +1465,7 @@
       QualType type = f->getType();
       llvm::DIType *fieldType = createFieldType(
           "this", type, f->getLocation(), f->getAccess(),
-          layout.getFieldOffset(fieldno), VUnit, RecordTy, CXXDecl);
+          layout.getFieldOffset(fieldno), VUnit, RecordTy, IsZeroSize, CXXDecl);
 
       elements.push_back(fieldType);
     }
@@ -1513,9 +1518,10 @@
     FieldType = createBitFieldType(field, RecordTy, RD);
   } else {
     auto Align = getDeclAlignIfRequired(field, CGM.getContext());
+    bool IsZeroSize = field->isZeroSize(CGM.getContext());
     FieldType =
         createFieldType(name, type, field->getLocation(), field->getAccess(),
-                        OffsetInBits, Align, tunit, RecordTy, RD);
+                        OffsetInBits, Align, tunit, RecordTy, IsZeroSize, RD);
   }
 
   elements.push_back(FieldType);
@@ -4563,37 +4569,39 @@
     const CGBlockInfo &Block, const ASTContext &Context, SourceLocation Loc,
     const llvm::StructLayout &BlockLayout, llvm::DIFile *Unit,
     SmallVectorImpl<llvm::Metadata *> &Fields) {
+  bool IsZeroSize = false;
   // Blocks in OpenCL have unique constraints which make the standard fields
   // redundant while requiring size and align fields for enqueue_kernel. See
   // initializeForBlockHeader in CGBlocks.cpp
   if (CGM.getLangOpts().OpenCL) {
     Fields.push_back(createFieldType("__size", Context.IntTy, Loc, AS_public,
                                      BlockLayout.getElementOffsetInBits(0),
-                                     Unit, Unit));
+                                     Unit, Unit, IsZeroSize));
     Fields.push_back(createFieldType("__align", Context.IntTy, Loc, AS_public,
                                      BlockLayout.getElementOffsetInBits(1),
-                                     Unit, Unit));
+                                     Unit, Unit, IsZeroSize));
   } else {
     Fields.push_back(createFieldType("__isa", Context.VoidPtrTy, Loc, AS_public,
                                      BlockLayout.getElementOffsetInBits(0),
-                                     Unit, Unit));
+                                     Unit, Unit, IsZeroSize));
     Fields.push_back(createFieldType("__flags", Context.IntTy, Loc, AS_public,
                                      BlockLayout.getElementOffsetInBits(1),
-                                     Unit, Unit));
-    Fields.push_back(
-        createFieldType("__reserved", Context.IntTy, Loc, AS_public,
-                        BlockLayout.getElementOffsetInBits(2), Unit, Unit));
+                                     Unit, Unit, IsZeroSize));
+    Fields.push_back(createFieldType(
+        "__reserved", Context.IntTy, Loc, AS_public,
+        BlockLayout.getElementOffsetInBits(2), Unit, Unit, IsZeroSize));
     auto *FnTy = Block.getBlockExpr()->getFunctionType();
     auto FnPtrType = CGM.getContext().getPointerType(FnTy->desugar());
     Fields.push_back(createFieldType("__FuncPtr", FnPtrType, Loc, AS_public,
                                      BlockLayout.getElementOffsetInBits(3),
-                                     Unit, Unit));
+                                     Unit, Unit, IsZeroSize));
     Fields.push_back(createFieldType(
         "__descriptor",
         Context.getPointerType(Block.NeedsCopyDispose
                                    ? Context.getBlockDescriptorExtendedType()
                                    : Context.getBlockDescriptorType()),
-        Loc, AS_public, BlockLayout.getElementOffsetInBits(4), Unit, Unit));
+        Loc, AS_public, BlockLayout.getElementOffsetInBits(4), Unit, Unit,
+        IsZeroSize));
   }
 }
 
@@ -4669,8 +4677,9 @@
       else
         llvm_unreachable("unexpected block declcontext");
 
+      bool IsZeroSize = false;
       fields.push_back(createFieldType("this", type, loc, AS_public,
-                                       offsetInBits, tunit, tunit));
+                                       offsetInBits, tunit, tunit, IsZeroSize));
       continue;
     }
 
@@ -4691,8 +4700,10 @@
                                             llvm::DINode::FlagZero, fieldType);
     } else {
       auto Align = getDeclAlignIfRequired(variable, CGM.getContext());
-      fieldType = createFieldType(name, variable->getType(), loc, AS_public,
-                                  offsetInBits, Align, tunit, tunit);
+      bool IsZeroSize = false;
+      fieldType =
+          createFieldType(name, variable->getType(), loc, AS_public,
+                          offsetInBits, Align, tunit, tunit, IsZeroSize);
     }
     fields.push_back(fieldType);
   }
Index: clang/lib/AST/ASTImporter.cpp
===================================================================
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -3679,6 +3679,28 @@
                               D->getInClassInitStyle()))
     return ToField;
 
+  // FieldDecl::isZeroSize may need to check these.
+  if (const Attr *FromAttr = D->getAttr<NoUniqueAddressAttr>()) {
+    if (auto ToAttrOrErr = Importer.Import(FromAttr))
+      ToField->addAttr(*ToAttrOrErr);
+    else
+      return ToAttrOrErr.takeError();
+    RecordType *FromRT =
+        const_cast<RecordType *>(D->getType()->getAs<RecordType>());
+    // Is this field a struct? FieldDecl::isZeroSize will need its definition.
+    if (FromRT) {
+      RecordDecl *FromRD = FromRT->getDecl();
+      RecordType *ToRT =
+          const_cast<RecordType *>(ToField->getType()->getAs<RecordType>());
+      assert(ToRT && "RecordType import has different type");
+      RecordDecl *ToRD = ToRT->getDecl();
+      if (FromRD->isCompleteDefinition() && !ToRD->isCompleteDefinition()) {
+        if (Error Err = ImportDefinition(FromRD, ToRD, IDK_Basic))
+          return std::move(Err);
+      }
+    }
+  }
+
   ToField->setAccess(D->getAccess());
   ToField->setLexicalDeclContext(LexicalDC);
   if (ToInitializer)
@@ -8497,6 +8519,8 @@
   // Make sure that ImportImpl registered the imported decl.
   assert(ImportedDecls.count(FromD) != 0 && "Missing call to MapImported?");
 
+  // There may have been NoUniqueAddressAttr for FieldDecl::isZeroSize.
+  ToD->dropAttrs();
   if (FromD->hasAttrs())
     for (const Attr *FromAttr : FromD->getAttrs()) {
       auto ToAttrOrErr = Import(FromAttr);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to