Skip to content

Commit e56121c

Browse files
committed
Revert "Revert "Reland "Revert "[clang][CGRecordLayout] Remove dependency on isZeroSize (llvm#96422)" (#156)"" (llvm#2065)"
This reverts commit 4950ee0.
1 parent eff9613 commit e56121c

29 files changed

+259
-164
lines changed

clang/lib/CodeGen/ABIInfoImpl.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,41 @@ bool CodeGen::isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays,
304304
return true;
305305
}
306306

307+
bool CodeGen::isEmptyFieldForLayout(const ASTContext &Context,
308+
const FieldDecl *FD) {
309+
if (FD->isZeroLengthBitField())
310+
return true;
311+
312+
if (FD->isUnnamedBitField())
313+
return false;
314+
315+
return isEmptyRecordForLayout(Context, FD->getType());
316+
}
317+
318+
bool CodeGen::isEmptyRecordForLayout(const ASTContext &Context, QualType T) {
319+
const RecordType *RT = T->getAs<RecordType>();
320+
if (!RT)
321+
return false;
322+
323+
const RecordDecl *RD = RT->getDecl();
324+
325+
// If this is a C++ record, check the bases first.
326+
if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
327+
if (CXXRD->isDynamicClass())
328+
return false;
329+
330+
for (const auto &I : CXXRD->bases())
331+
if (!isEmptyRecordForLayout(Context, I.getType()))
332+
return false;
333+
}
334+
335+
for (const auto *I : RD->fields())
336+
if (!isEmptyFieldForLayout(Context, I))
337+
return false;
338+
339+
return true;
340+
}
341+
307342
const Type *CodeGen::isSingleElementStruct(QualType T, ASTContext &Context) {
308343
const RecordType *RT = T->getAs<RecordType>();
309344
if (!RT)

clang/lib/CodeGen/ABIInfoImpl.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,16 @@ bool isEmptyField(ASTContext &Context, const FieldDecl *FD, bool AllowArrays,
120120
bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays,
121121
bool AsIfNoUniqueAddr = false);
122122

123+
/// isEmptyFieldForLayout - Return true iff the field is "empty", that is,
124+
/// either a zero-width bit-field or an \ref isEmptyRecordForLayout.
125+
bool isEmptyFieldForLayout(const ASTContext &Context, const FieldDecl *FD);
126+
127+
/// isEmptyRecordForLayout - Return true iff a structure contains only empty
128+
/// base classes (per \ref isEmptyRecordForLayout) and fields (per
129+
/// \ref isEmptyFieldForLayout). Note, C++ record fields are considered empty
130+
/// if the [[no_unique_address]] attribute would have made them empty.
131+
bool isEmptyRecordForLayout(const ASTContext &Context, QualType T);
132+
123133
/// isSingleElementStruct - Determine if a structure is a "single
124134
/// element struct", i.e. it has exactly one non-empty field or
125135
/// exactly one field which is itself a single element

clang/lib/CodeGen/CGClass.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
#include "ABIInfoImpl.h"
1314
#include "CGBlocks.h"
1415
#include "CGCXXABI.h"
1516
#include "CGDebugInfo.h"
@@ -932,7 +933,7 @@ namespace {
932933
}
933934

934935
void addMemcpyableField(FieldDecl *F) {
935-
if (F->isZeroSize(CGF.getContext()))
936+
if (isEmptyFieldForLayout(CGF.getContext(), F))
936937
return;
937938
if (!FirstField)
938939
addInitialField(F);
@@ -1819,7 +1820,7 @@ namespace {
18191820
const CXXDestructorDecl *DD)
18201821
: Context(Context), EHStack(EHStack), DD(DD), StartIndex(std::nullopt) {}
18211822
void PushCleanupForField(const FieldDecl *Field) {
1822-
if (Field->isZeroSize(Context))
1823+
if (isEmptyFieldForLayout(Context, Field))
18231824
return;
18241825
unsigned FieldIndex = Field->getFieldIndex();
18251826
if (FieldHasTrivialDestructorBody(Context, Field)) {

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5119,7 +5119,7 @@ static Address emitAddrOfZeroSizeField(CodeGenFunction &CGF, Address Base,
51195119
/// The resulting address doesn't necessarily have the right type.
51205120
static Address emitAddrOfFieldStorage(CodeGenFunction &CGF, Address base,
51215121
const FieldDecl *field, bool IsInBounds) {
5122-
if (field->isZeroSize(CGF.getContext()))
5122+
if (isEmptyFieldForLayout(CGF.getContext(), field))
51235123
return emitAddrOfZeroSizeField(CGF, base, field, IsInBounds);
51245124

51255125
const RecordDecl *rec = field->getParent();

clang/lib/CodeGen/CGExprConstant.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
#include "ABIInfoImpl.h"
1314
#include "CGCXXABI.h"
1415
#include "CGObjCRuntime.h"
1516
#include "CGRecordLayout.h"
@@ -757,7 +758,7 @@ bool ConstStructBuilder::Build(const InitListExpr *ILE, bool AllowOverwrite) {
757758

758759
// Zero-sized fields are not emitted, but their initializers may still
759760
// prevent emission of this struct as a constant.
760-
if (Field->isZeroSize(CGM.getContext())) {
761+
if (isEmptyFieldForLayout(CGM.getContext(), Field)) {
761762
if (Init && Init->HasSideEffects(CGM.getContext()))
762763
return false;
763764
continue;
@@ -891,7 +892,8 @@ bool ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD,
891892
continue;
892893

893894
// Don't emit anonymous bitfields or zero-sized fields.
894-
if (Field->isUnnamedBitField() || Field->isZeroSize(CGM.getContext()))
895+
if (Field->isUnnamedBitField() ||
896+
isEmptyFieldForLayout(CGM.getContext(), *Field))
895897
continue;
896898

897899
// Emit the value of the initializer.
@@ -2641,8 +2643,10 @@ static llvm::Constant *EmitNullConstant(CodeGenModule &CGM,
26412643
cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
26422644

26432645
// Ignore empty bases.
2644-
if (base->isEmpty() ||
2645-
CGM.getContext().getASTRecordLayout(base).getNonVirtualSize()
2646+
if (isEmptyRecordForLayout(CGM.getContext(), I.getType()) ||
2647+
CGM.getContext()
2648+
.getASTRecordLayout(base)
2649+
.getNonVirtualSize()
26462650
.isZero())
26472651
continue;
26482652

@@ -2656,7 +2660,8 @@ static llvm::Constant *EmitNullConstant(CodeGenModule &CGM,
26562660
for (const auto *Field : record->fields()) {
26572661
// Fill in non-bitfields. (Bitfields always use a zero pattern, which we
26582662
// will fill in later.)
2659-
if (!Field->isBitField() && !Field->isZeroSize(CGM.getContext())) {
2663+
if (!Field->isBitField() &&
2664+
!isEmptyFieldForLayout(CGM.getContext(), Field)) {
26602665
unsigned fieldIndex = layout.getLLVMFieldNo(Field);
26612666
elements[fieldIndex] = CGM.EmitNullConstant(Field->getType());
26622667
}
@@ -2678,7 +2683,7 @@ static llvm::Constant *EmitNullConstant(CodeGenModule &CGM,
26782683
cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
26792684

26802685
// Ignore empty bases.
2681-
if (base->isEmpty())
2686+
if (isEmptyRecordForLayout(CGM.getContext(), I.getType()))
26822687
continue;
26832688

26842689
unsigned fieldIndex = layout.getVirtualBaseIndex(base);

clang/lib/CodeGen/CGOpenMPRuntime.cpp

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "CGOpenMPRuntime.h"
14+
#include "ABIInfoImpl.h"
1415
#include "CGCXXABI.h"
1516
#include "CGCleanup.h"
1617
#include "CGDebugInfo.h"
@@ -8106,23 +8107,28 @@ class MappableExprsHandler {
81068107
for (const auto &I : RD->bases()) {
81078108
if (I.isVirtual())
81088109
continue;
8109-
const auto *Base = I.getType()->getAsCXXRecordDecl();
8110+
8111+
QualType BaseTy = I.getType();
8112+
const auto *Base = BaseTy->getAsCXXRecordDecl();
81108113
// Ignore empty bases.
8111-
if (Base->isEmpty() || CGF.getContext()
8112-
.getASTRecordLayout(Base)
8113-
.getNonVirtualSize()
8114-
.isZero())
8114+
if (isEmptyRecordForLayout(CGF.getContext(), BaseTy) ||
8115+
CGF.getContext()
8116+
.getASTRecordLayout(Base)
8117+
.getNonVirtualSize()
8118+
.isZero())
81158119
continue;
81168120

81178121
unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base);
81188122
RecordLayout[FieldIndex] = Base;
81198123
}
81208124
// Fill in virtual bases.
81218125
for (const auto &I : RD->vbases()) {
8122-
const auto *Base = I.getType()->getAsCXXRecordDecl();
8126+
QualType BaseTy = I.getType();
81238127
// Ignore empty bases.
8124-
if (Base->isEmpty())
8128+
if (isEmptyRecordForLayout(CGF.getContext(), BaseTy))
81258129
continue;
8130+
8131+
const auto *Base = BaseTy->getAsCXXRecordDecl();
81268132
unsigned FieldIndex = RL.getVirtualBaseIndex(Base);
81278133
if (RecordLayout[FieldIndex])
81288134
continue;
@@ -8133,7 +8139,8 @@ class MappableExprsHandler {
81338139
for (const auto *Field : RD->fields()) {
81348140
// Fill in non-bitfields. (Bitfields always use a zero pattern, which we
81358141
// will fill in later.)
8136-
if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) {
8142+
if (!Field->isBitField() &&
8143+
!isEmptyFieldForLayout(CGF.getContext(), Field)) {
81378144
unsigned FieldIndex = RL.getLLVMFieldNo(Field);
81388145
RecordLayout[FieldIndex] = Field;
81398146
}

clang/lib/CodeGen/CGRecordLayoutBuilder.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
#include "CGRecordLayout.h"
13+
#include "ABIInfoImpl.h"
1414
#include "CGCXXABI.h"
15+
#include "CGRecordLayout.h"
1516
#include "CodeGenTypes.h"
1617
#include "clang/AST/ASTContext.h"
1718
#include "clang/AST/Attr.h"
@@ -384,7 +385,7 @@ void CGRecordLowering::accumulateFields(bool isNonVirtualBaseType) {
384385
Field = accumulateBitFields(isNonVirtualBaseType, Field, FieldEnd);
385386
assert((Field == FieldEnd || !Field->isBitField()) &&
386387
"Failed to accumulate all the bitfields");
387-
} else if (Field->isZeroSize(Context)) {
388+
} else if (isEmptyFieldForLayout(Context, *Field)) {
388389
// Empty fields have no storage.
389390
++Field;
390391
} else {
@@ -633,7 +634,7 @@ CGRecordLowering::accumulateBitFields(bool isNonVirtualBaseType,
633634
// non-reusable tail padding.
634635
CharUnits LimitOffset;
635636
for (auto Probe = Field; Probe != FieldEnd; ++Probe)
636-
if (!Probe->isZeroSize(Context)) {
637+
if (!isEmptyFieldForLayout(Context, *Probe)) {
637638
// A member with storage sets the limit.
638639
assert((getFieldBitOffset(*Probe) % CharBits) == 0 &&
639640
"Next storage is not byte-aligned");
@@ -731,7 +732,7 @@ void CGRecordLowering::accumulateBases() {
731732
// Bases can be zero-sized even if not technically empty if they
732733
// contain only a trailing array member.
733734
const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
734-
if (!BaseDecl->isEmpty() &&
735+
if (!isEmptyRecordForLayout(Context, Base.getType()) &&
735736
!Context.getASTRecordLayout(BaseDecl).getNonVirtualSize().isZero())
736737
Members.push_back(MemberInfo(Layout.getBaseClassOffset(BaseDecl),
737738
MemberInfo::Base, getStorageType(BaseDecl), BaseDecl));
@@ -879,7 +880,7 @@ CGRecordLowering::calculateTailClippingOffset(bool isNonVirtualBaseType) const {
879880
if (!isNonVirtualBaseType && isOverlappingVBaseABI())
880881
for (const auto &Base : RD->vbases()) {
881882
const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
882-
if (BaseDecl->isEmpty())
883+
if (isEmptyRecordForLayout(Context, Base.getType()))
883884
continue;
884885
// If the vbase is a primary virtual base of some base, then it doesn't
885886
// get its own storage location but instead lives inside of that base.
@@ -895,7 +896,7 @@ CGRecordLowering::calculateTailClippingOffset(bool isNonVirtualBaseType) const {
895896
void CGRecordLowering::accumulateVBases() {
896897
for (const auto &Base : RD->vbases()) {
897898
const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
898-
if (BaseDecl->isEmpty())
899+
if (isEmptyRecordForLayout(Context, Base.getType()))
899900
continue;
900901
CharUnits Offset = Layout.getVBaseClassOffset(BaseDecl);
901902
// If the vbase is a primary virtual base of some base, then it doesn't
@@ -1153,7 +1154,7 @@ CodeGenTypes::ComputeRecordLayout(const RecordDecl *D, llvm::StructType *Ty) {
11531154
const FieldDecl *FD = *it;
11541155

11551156
// Ignore zero-sized fields.
1156-
if (FD->isZeroSize(getContext()))
1157+
if (isEmptyFieldForLayout(getContext(), FD))
11571158
continue;
11581159

11591160
// For non-bit-fields, just check that the LLVM struct offset matches the

clang/lib/CodeGen/CodeGenTBAA.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
//===----------------------------------------------------------------------===//
1616

1717
#include "CodeGenTBAA.h"
18+
#include "ABIInfoImpl.h"
1819
#include "CGCXXABI.h"
1920
#include "CGRecordLayout.h"
2021
#include "CodeGenTypes.h"
@@ -447,7 +448,7 @@ CodeGenTBAA::CollectFields(uint64_t BaseOffset,
447448
unsigned idx = 0;
448449
for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
449450
i != e; ++i, ++idx) {
450-
if ((*i)->isZeroSize(Context))
451+
if (isEmptyFieldForLayout(Context, *i))
451452
continue;
452453

453454
uint64_t Offset =
Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,19 @@
1-
// RUN: %clang_cc1 -emit-llvm < %s | grep "zeroinitializer, i16 16877"
1+
// RUN: %clang_cc1 %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s --check-prefixes=CHECK,EMPTY
2+
// RUN: %clang_cc1 %s -emit-llvm -triple x86_64-windows-msvc -o - | FileCheck %s --check-prefixes=CHECK,EMPTY-MSVC
23
// PR4390
34
struct sysfs_dirent {
4-
union { struct sysfs_elem_dir {} s_dir; };
5+
union { struct sysfs_elem_dir { int x; } s_dir; };
56
unsigned short s_mode;
67
};
78
struct sysfs_dirent sysfs_root = { {}, 16877 };
89

10+
// CHECK: @sysfs_root = {{.*}}global { %union.anon, i16, [2 x i8] } { %union.anon zeroinitializer, i16 16877, [2 x i8] zeroinitializer }
11+
12+
struct Foo {
13+
union { struct empty {} x; };
14+
unsigned short s_mode;
15+
};
16+
struct Foo foo = { {}, 16877 };
17+
18+
// EMPTY: @foo = {{.*}}global %struct.Foo { i16 16877 }
19+
// EMPTY-MSVC: @foo = {{.*}}global %struct.Foo { [4 x i8] zeroinitializer, i16 16877 }

clang/test/CodeGen/X86/x86_64-vaarg.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ typedef struct {
5656
// CHECK: vaarg.end:
5757
// CHECK-NEXT: [[VAARG_ADDR:%.*]] = phi ptr [ [[TMP1]], [[VAARG_IN_REG]] ], [ [[OVERFLOW_ARG_AREA]], [[VAARG_IN_MEM]] ]
5858
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[RETVAL]], ptr align 8 [[VAARG_ADDR]], i64 8, i1 false)
59-
// CHECK-NEXT: [[TMP3:%.*]] = load double, ptr [[RETVAL]], align 8
59+
// CHECK-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_S1]], ptr [[RETVAL]], i32 0, i32 0
60+
// CHECK-NEXT: [[TMP3:%.*]] = load double, ptr [[COERCE_DIVE]], align 8
6061
// CHECK-NEXT: ret double [[TMP3]]
6162
//
6263
s1 f(int z, ...) {

0 commit comments

Comments
 (0)