jankratochvil updated this revision to Diff 350361.
jankratochvil added a comment.
Herald added subscribers: llvm-commits, cfe-commits, dexonsmith, sstefan1,
martong, hiraditya.
Herald added a reviewer: shafik.
Herald added a reviewer: jdoerfert.
Herald added a reviewer: shafik.
Herald added projects: clang, LLVM.
`DW_AT_byte_size 0` implementation as suggested by @teemperor.
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/include/llvm/IR/DebugInfoFlags.def
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: llvm/include/llvm/IR/DebugInfoFlags.def
===================================================================
--- llvm/include/llvm/IR/DebugInfoFlags.def
+++ llvm/include/llvm/IR/DebugInfoFlags.def
@@ -58,6 +58,8 @@
HANDLE_DI_FLAG((1 << 27), BigEndian)
HANDLE_DI_FLAG((1 << 28), LittleEndian)
HANDLE_DI_FLAG((1 << 29), AllCallsDescribed)
+// FIXME: Move it to ReservedBit4?
+HANDLE_DI_FLAG((1 << 30), IsZeroSize)
// To avoid needing a dedicated value for IndirectVirtualBase, we use
// the bitwise or of Virtual and FwdDecl, which does not otherwise
@@ -67,7 +69,7 @@
#ifdef DI_FLAG_LARGEST_NEEDED
// intended to be used with ADT/BitmaskEnum.h
// NOTE: always must be equal to largest flag, check this when adding new flag
-HANDLE_DI_FLAG((1 << 29), Largest)
+HANDLE_DI_FLAG((1 << 30), Largest)
#undef DI_FLAG_LARGEST_NEEDED
#endif
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
@@ -3677,6 +3677,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)
@@ -8453,6 +8475,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);
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits