Improve support of PDB as an external layout source
Summary:
This patch improves support of PDB as an external layout source
in the next cases:
- Multiple non-virtual inheritance from packed base classes. When using
external layout, there's no need to align `NonVirtualSize` of a base class.
It may cause an overlapping when the next base classes will be layouted
(but there is a slightly different case in the test because I can't find
a way to specify a base offset);
- Support of nameless structs and unions. There is no info about nameless child
structs and unions in Microsoft cl-emitted PDBs. Instead all its fields
are just treated as outer structure's (union's) fields. This also causes
a fields overlapping, and makes it possible for unions to have fields located
at a non-zero offset.
Reviewers: rsmith, zturner, rnk, mstorsjo, majnemer
Reviewed By: rnk
Subscribers: cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D49871
llvm-svn: 338353
diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp
index dd58b10..6f71d5b 100644
--- a/clang/lib/AST/RecordLayoutBuilder.cpp
+++ b/clang/lib/AST/RecordLayoutBuilder.cpp
@@ -2452,7 +2452,9 @@
auto RoundingAlignment = Alignment;
if (!MaxFieldAlignment.isZero())
RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment);
- NonVirtualSize = Size = Size.alignTo(RoundingAlignment);
+ if (!UseExternalLayout)
+ Size = Size.alignTo(RoundingAlignment);
+ NonVirtualSize = Size;
RequiredAlignment = std::max(
RequiredAlignment, Context.toCharUnitsFromBits(RD->getMaxAlignment()));
layoutVirtualBases(RD);
@@ -2653,21 +2655,16 @@
LastFieldIsNonZeroWidthBitfield = false;
ElementInfo Info = getAdjustedElementInfo(FD);
Alignment = std::max(Alignment, Info.Alignment);
- if (IsUnion) {
- placeFieldAtOffset(CharUnits::Zero());
- Size = std::max(Size, Info.Size);
- } else {
- CharUnits FieldOffset;
- if (UseExternalLayout) {
- FieldOffset =
- Context.toCharUnitsFromBits(External.getExternalFieldOffset(FD));
- assert(FieldOffset >= Size && "field offset already allocated");
- } else {
- FieldOffset = Size.alignTo(Info.Alignment);
- }
- placeFieldAtOffset(FieldOffset);
- Size = FieldOffset + Info.Size;
- }
+ CharUnits FieldOffset;
+ if (UseExternalLayout)
+ FieldOffset =
+ Context.toCharUnitsFromBits(External.getExternalFieldOffset(FD));
+ else if (IsUnion)
+ FieldOffset = CharUnits::Zero();
+ else
+ FieldOffset = Size.alignTo(Info.Alignment);
+ placeFieldAtOffset(FieldOffset);
+ Size = std::max(Size, FieldOffset + Info.Size);
}
void MicrosoftRecordLayoutBuilder::layoutBitField(const FieldDecl *FD) {
@@ -2692,18 +2689,17 @@
}
LastFieldIsNonZeroWidthBitfield = true;
CurrentBitfieldSize = Info.Size;
- if (IsUnion) {
- placeFieldAtOffset(CharUnits::Zero());
- Size = std::max(Size, Info.Size);
- // TODO: Add a Sema warning that MS ignores bitfield alignment in unions.
- } else if (UseExternalLayout) {
+ if (UseExternalLayout) {
auto FieldBitOffset = External.getExternalFieldOffset(FD);
placeFieldAtBitOffset(FieldBitOffset);
auto NewSize = Context.toCharUnitsFromBits(
llvm::alignTo(FieldBitOffset + Width, Context.getCharWidth()));
- assert(NewSize >= Size && "bit field offset already allocated");
- Size = NewSize;
+ Size = std::max(Size, NewSize);
Alignment = std::max(Alignment, Info.Alignment);
+ } else if (IsUnion) {
+ placeFieldAtOffset(CharUnits::Zero());
+ Size = std::max(Size, Info.Size);
+ // TODO: Add a Sema warning that MS ignores bitfield alignment in unions.
} else {
// Allocate a new block of memory and place the bitfield in it.
CharUnits FieldOffset = Size.alignTo(Info.Alignment);