Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 0 additions & 33 deletions clang/lib/CodeGen/ABIInfoImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,39 +301,6 @@ bool CodeGen::isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays,
return true;
}

bool CodeGen::isEmptyFieldForLayout(const ASTContext &Context,
const FieldDecl *FD) {
if (FD->isZeroLengthBitField())
return true;

if (FD->isUnnamedBitField())
return false;

return isEmptyRecordForLayout(Context, FD->getType());
}

bool CodeGen::isEmptyRecordForLayout(const ASTContext &Context, QualType T) {
const auto *RD = T->getAsRecordDecl();
if (!RD)
return false;

// If this is a C++ record, check the bases first.
if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
if (CXXRD->isDynamicClass())
return false;

for (const auto &I : CXXRD->bases())
if (!isEmptyRecordForLayout(Context, I.getType()))
return false;
}

for (const auto *I : RD->fields())
if (!isEmptyFieldForLayout(Context, I))
return false;

return true;
}

const Type *CodeGen::isSingleElementStruct(QualType T, ASTContext &Context) {
const auto *RD = T->getAsRecordDecl();
if (!RD)
Expand Down
10 changes: 0 additions & 10 deletions clang/lib/CodeGen/ABIInfoImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,16 +120,6 @@ bool isEmptyField(ASTContext &Context, const FieldDecl *FD, bool AllowArrays,
bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays,
bool AsIfNoUniqueAddr = false);

/// isEmptyFieldForLayout - Return true iff the field is "empty", that is,
/// either a zero-width bit-field or an \ref isEmptyRecordForLayout.
bool isEmptyFieldForLayout(const ASTContext &Context, const FieldDecl *FD);

/// isEmptyRecordForLayout - Return true iff a structure contains only empty
/// base classes (per \ref isEmptyRecordForLayout) and fields (per
/// \ref isEmptyFieldForLayout). Note, C++ record fields are considered empty
/// if the [[no_unique_address]] attribute would have made them empty.
bool isEmptyRecordForLayout(const ASTContext &Context, QualType T);

/// isSingleElementStruct - Determine if a structure is a "single
/// element struct", i.e. it has exactly one non-empty field or
/// exactly one field which is itself a single element
Expand Down
5 changes: 2 additions & 3 deletions clang/lib/CodeGen/CGClass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
//
//===----------------------------------------------------------------------===//

#include "ABIInfoImpl.h"
#include "CGBlocks.h"
#include "CGCXXABI.h"
#include "CGDebugInfo.h"
Expand Down Expand Up @@ -927,7 +926,7 @@ namespace {
}

void addMemcpyableField(FieldDecl *F) {
if (isEmptyFieldForLayout(CGF.getContext(), F))
if (F->isZeroSize(CGF.getContext()))
return;
if (!FirstField)
addInitialField(F);
Expand Down Expand Up @@ -1884,7 +1883,7 @@ namespace {
const CXXDestructorDecl *DD)
: Context(Context), EHStack(EHStack), DD(DD), StartIndex(std::nullopt) {}
void PushCleanupForField(const FieldDecl *Field) {
if (isEmptyFieldForLayout(Context, Field))
if (Field->isZeroSize(Context))
return;
unsigned FieldIndex = Field->getFieldIndex();
if (FieldHasTrivialDestructorBody(Context, Field)) {
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5283,7 +5283,7 @@ static Address emitAddrOfZeroSizeField(CodeGenFunction &CGF, Address Base,
/// The resulting address doesn't necessarily have the right type.
static Address emitAddrOfFieldStorage(CodeGenFunction &CGF, Address base,
const FieldDecl *field, bool IsInBounds) {
if (isEmptyFieldForLayout(CGF.getContext(), field))
if (field->isZeroSize(CGF.getContext()))
return emitAddrOfZeroSizeField(CGF, base, field, IsInBounds);

const RecordDecl *rec = field->getParent();
Expand Down
17 changes: 6 additions & 11 deletions clang/lib/CodeGen/CGExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
//
//===----------------------------------------------------------------------===//

#include "ABIInfoImpl.h"
#include "CGCXXABI.h"
#include "CGObjCRuntime.h"
#include "CGRecordLayout.h"
Expand Down Expand Up @@ -758,7 +757,7 @@ bool ConstStructBuilder::Build(const InitListExpr *ILE, bool AllowOverwrite) {

// Zero-sized fields are not emitted, but their initializers may still
// prevent emission of this struct as a constant.
if (isEmptyFieldForLayout(CGM.getContext(), Field)) {
if (Field->isZeroSize(CGM.getContext())) {
if (Init && Init->HasSideEffects(CGM.getContext()))
return false;
continue;
Expand Down Expand Up @@ -893,8 +892,7 @@ bool ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD,
continue;

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

// Emit the value of the initializer.
Expand Down Expand Up @@ -2642,10 +2640,8 @@ static llvm::Constant *EmitNullConstant(CodeGenModule &CGM,

const auto *base = I.getType()->castAsCXXRecordDecl();
// Ignore empty bases.
if (isEmptyRecordForLayout(CGM.getContext(), I.getType()) ||
CGM.getContext()
.getASTRecordLayout(base)
.getNonVirtualSize()
if (base->isEmpty() ||
CGM.getContext().getASTRecordLayout(base).getNonVirtualSize()
.isZero())
continue;

Expand All @@ -2659,8 +2655,7 @@ static llvm::Constant *EmitNullConstant(CodeGenModule &CGM,
for (const auto *Field : record->fields()) {
// Fill in non-bitfields. (Bitfields always use a zero pattern, which we
// will fill in later.)
if (!Field->isBitField() &&
!isEmptyFieldForLayout(CGM.getContext(), Field)) {
if (!Field->isBitField() && !Field->isZeroSize(CGM.getContext())) {
unsigned fieldIndex = layout.getLLVMFieldNo(Field);
elements[fieldIndex] = CGM.EmitNullConstant(Field->getType());
}
Expand All @@ -2680,7 +2675,7 @@ static llvm::Constant *EmitNullConstant(CodeGenModule &CGM,
for (const auto &I : CXXR->vbases()) {
const auto *base = I.getType()->castAsCXXRecordDecl();
// Ignore empty bases.
if (isEmptyRecordForLayout(CGM.getContext(), I.getType()))
if (base->isEmpty())
continue;

unsigned fieldIndex = layout.getVirtualBaseIndex(base);
Expand Down
23 changes: 8 additions & 15 deletions clang/lib/CodeGen/CGOpenMPRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
//===----------------------------------------------------------------------===//

#include "CGOpenMPRuntime.h"
#include "ABIInfoImpl.h"
#include "CGCXXABI.h"
#include "CGCleanup.h"
#include "CGDebugInfo.h"
Expand Down Expand Up @@ -8472,28 +8471,23 @@ class MappableExprsHandler {
for (const auto &I : RD->bases()) {
if (I.isVirtual())
continue;

QualType BaseTy = I.getType();
const auto *Base = BaseTy->getAsCXXRecordDecl();
const auto *Base = I.getType()->getAsCXXRecordDecl();
// Ignore empty bases.
if (isEmptyRecordForLayout(CGF.getContext(), BaseTy) ||
CGF.getContext()
.getASTRecordLayout(Base)
.getNonVirtualSize()
.isZero())
if (Base->isEmpty() || CGF.getContext()
.getASTRecordLayout(Base)
.getNonVirtualSize()
.isZero())
continue;

unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base);
RecordLayout[FieldIndex] = Base;
}
// Fill in virtual bases.
for (const auto &I : RD->vbases()) {
QualType BaseTy = I.getType();
const auto *Base = I.getType()->getAsCXXRecordDecl();
// Ignore empty bases.
if (isEmptyRecordForLayout(CGF.getContext(), BaseTy))
if (Base->isEmpty())
continue;

const auto *Base = BaseTy->getAsCXXRecordDecl();
unsigned FieldIndex = RL.getVirtualBaseIndex(Base);
if (RecordLayout[FieldIndex])
continue;
Expand All @@ -8504,8 +8498,7 @@ class MappableExprsHandler {
for (const auto *Field : RD->fields()) {
// Fill in non-bitfields. (Bitfields always use a zero pattern, which we
// will fill in later.)
if (!Field->isBitField() &&
!isEmptyFieldForLayout(CGF.getContext(), Field)) {
if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) {
unsigned FieldIndex = RL.getLLVMFieldNo(Field);
RecordLayout[FieldIndex] = Field;
}
Expand Down
15 changes: 7 additions & 8 deletions clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@
//
//===----------------------------------------------------------------------===//

#include "ABIInfoImpl.h"
#include "CGCXXABI.h"
#include "CGRecordLayout.h"
#include "CGCXXABI.h"
#include "CodeGenTypes.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
Expand Down Expand Up @@ -385,7 +384,7 @@ void CGRecordLowering::accumulateFields(bool isNonVirtualBaseType) {
Field = accumulateBitFields(isNonVirtualBaseType, Field, FieldEnd);
assert((Field == FieldEnd || !Field->isBitField()) &&
"Failed to accumulate all the bitfields");
} else if (isEmptyFieldForLayout(Context, *Field)) {
} else if (Field->isZeroSize(Context)) {
// Empty fields have no storage.
++Field;
} else {
Expand Down Expand Up @@ -634,7 +633,7 @@ CGRecordLowering::accumulateBitFields(bool isNonVirtualBaseType,
// non-reusable tail padding.
CharUnits LimitOffset;
for (auto Probe = Field; Probe != FieldEnd; ++Probe)
if (!isEmptyFieldForLayout(Context, *Probe)) {
if (!Probe->isZeroSize(Context)) {
// A member with storage sets the limit.
assert((getFieldBitOffset(*Probe) % CharBits) == 0 &&
"Next storage is not byte-aligned");
Expand Down Expand Up @@ -732,7 +731,7 @@ void CGRecordLowering::accumulateBases() {
// Bases can be zero-sized even if not technically empty if they
// contain only a trailing array member.
const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
if (!isEmptyRecordForLayout(Context, Base.getType()) &&
if (!BaseDecl->isEmpty() &&
!Context.getASTRecordLayout(BaseDecl).getNonVirtualSize().isZero())
Members.push_back(MemberInfo(Layout.getBaseClassOffset(BaseDecl),
MemberInfo::Base, getStorageType(BaseDecl), BaseDecl));
Expand Down Expand Up @@ -880,7 +879,7 @@ CGRecordLowering::calculateTailClippingOffset(bool isNonVirtualBaseType) const {
if (!isNonVirtualBaseType && isOverlappingVBaseABI())
for (const auto &Base : RD->vbases()) {
const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
if (isEmptyRecordForLayout(Context, Base.getType()))
if (BaseDecl->isEmpty())
continue;
// If the vbase is a primary virtual base of some base, then it doesn't
// get its own storage location but instead lives inside of that base.
Expand All @@ -896,7 +895,7 @@ CGRecordLowering::calculateTailClippingOffset(bool isNonVirtualBaseType) const {
void CGRecordLowering::accumulateVBases() {
for (const auto &Base : RD->vbases()) {
const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
if (isEmptyRecordForLayout(Context, Base.getType()))
if (BaseDecl->isEmpty())
continue;
CharUnits Offset = Layout.getVBaseClassOffset(BaseDecl);
// If the vbase is a primary virtual base of some base, then it doesn't
Expand Down Expand Up @@ -1157,7 +1156,7 @@ CodeGenTypes::ComputeRecordLayout(const RecordDecl *D, llvm::StructType *Ty) {
const FieldDecl *FD = *it;

// Ignore zero-sized fields.
if (isEmptyFieldForLayout(getContext(), FD))
if (FD->isZeroSize(getContext()))
continue;

// For non-bit-fields, just check that the LLVM struct offset matches the
Expand Down
3 changes: 1 addition & 2 deletions clang/lib/CodeGen/CodeGenTBAA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
//===----------------------------------------------------------------------===//

#include "CodeGenTBAA.h"
#include "ABIInfoImpl.h"
#include "CGCXXABI.h"
#include "CGRecordLayout.h"
#include "CodeGenTypes.h"
Expand Down Expand Up @@ -448,7 +447,7 @@ CodeGenTBAA::CollectFields(uint64_t BaseOffset,
unsigned idx = 0;
for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
i != e; ++i, ++idx) {
if (isEmptyFieldForLayout(Context, *i))
if ((*i)->isZeroSize(Context))
continue;

uint64_t Offset =
Expand Down
15 changes: 2 additions & 13 deletions clang/test/CodeGen/2009-06-14-anonymous-union-init.c
Original file line number Diff line number Diff line change
@@ -1,19 +1,8 @@
// RUN: %clang_cc1 %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s --check-prefixes=CHECK,EMPTY
// RUN: %clang_cc1 %s -emit-llvm -triple x86_64-windows-msvc -o - | FileCheck %s --check-prefixes=CHECK,EMPTY-MSVC
// RUN: %clang_cc1 -emit-llvm < %s | grep "zeroinitializer, i16 16877"
// PR4390
struct sysfs_dirent {
union { struct sysfs_elem_dir { int x; } s_dir; };
union { struct sysfs_elem_dir {} s_dir; };
unsigned short s_mode;
};
struct sysfs_dirent sysfs_root = { {}, 16877 };

// CHECK: @sysfs_root = {{.*}}global { %union.anon, i16, [2 x i8] } { %union.anon zeroinitializer, i16 16877, [2 x i8] zeroinitializer }

struct Foo {
union { struct empty {} x; };
unsigned short s_mode;
};
struct Foo foo = { {}, 16877 };

// EMPTY: @foo = {{.*}}global %struct.Foo { i16 16877 }
// EMPTY-MSVC: @foo = {{.*}}global %struct.Foo { [4 x i8] zeroinitializer, i16 16877 }
3 changes: 1 addition & 2 deletions clang/test/CodeGen/X86/x86_64-vaarg.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,7 @@ typedef struct {
// CHECK: vaarg.end:
// CHECK-NEXT: [[VAARG_ADDR:%.*]] = phi ptr [ [[TMP1]], [[VAARG_IN_REG]] ], [ [[OVERFLOW_ARG_AREA]], [[VAARG_IN_MEM]] ]
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[RETVAL]], ptr align 8 [[VAARG_ADDR]], i64 8, i1 false)
// CHECK-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_S1]], ptr [[RETVAL]], i32 0, i32 0
// CHECK-NEXT: [[TMP3:%.*]] = load double, ptr [[COERCE_DIVE]], align 8
// CHECK-NEXT: [[TMP3:%.*]] = load double, ptr [[RETVAL]], align 8
// CHECK-NEXT: ret double [[TMP3]]
//
s1 f(int z, ...) {
Expand Down
15 changes: 9 additions & 6 deletions clang/test/CodeGen/paren-list-agg-init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,14 @@ struct E {
~E() {};
};

// CHECK-DAG: [[STRUCT_F:%.*]] = type { i8 }
struct F {
F (int i = 1);
F (const F &f) = delete;
F (F &&f) = default;
};

// CHECK-DAG: [[STRUCT_G:%.*]] = type <{ i32, [4 x i8] }>
// CHECK-DAG: [[STRUCT_G:%.*]] = type <{ i32, [[STRUCT_F]], [3 x i8] }>
struct G {
int a;
F f;
Expand All @@ -77,12 +78,12 @@ namespace gh61145 {
~Vec();
};

// CHECK-DAG: [[STRUCT_S1:%.*]] = type { i8 }
// CHECK-DAG: [[STRUCT_S1:%.*]] = type { [[STRUCT_VEC]] }
struct S1 {
Vec v;
};

// CHECK-DAG: [[STRUCT_S2:%.*]] = type { i8, i8 }
// CHECK-DAG: [[STRUCT_S2:%.*]] = type { [[STRUCT_VEC]], i8 }
struct S2 {
Vec v;
char c;
Expand Down Expand Up @@ -376,7 +377,7 @@ void foo18() {
// CHECK-NEXT: [[G:%.*g.*]] = alloca [[STRUCT_G]], align 4
// CHECK-NEXT: [[A:%.*a.*]] = getelementptr inbounds nuw [[STRUCT_G]], ptr [[G]], i32 0, i32 0
// CHECK-NEXT: store i32 2, ptr [[A]], align 4
// CHECK-NEXT: [[F:%.*]] = getelementptr inbounds i8, ptr [[G]], i64 4
// CHECK-NEXT: [[F:%.*f.*]] = getelementptr inbounds nuw [[STRUCT_G]], ptr [[G]], i32 0, i32 1
// CHECk-NEXT: call void @{{.*F.*}}(ptr noundef nonnull align 1 dereferenceable(1)) [[F]], ie32 noundef 1)
// CHECK: ret void
void foo19() {
Expand All @@ -391,8 +392,9 @@ namespace gh61145 {
// CHECK-NEXT: [[AGG_TMP_ENSURED:%.*agg.tmp.ensured.*]] = alloca [[STRUCT_S1]], align 1
// a.k.a. Vec::Vec()
// CHECK-NEXT: call void @_ZN7gh611453VecC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[V]])
// CHECK-NEXT: [[V1:%.*v1.*]] = getelementptr inbounds nuw [[STRUCT_S1]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 0
// a.k.a. Vec::Vec(Vec&&)
// CHECK-NEXT: call void @_ZN7gh611453VecC1EOS0_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_TMP_ENSURED]], ptr noundef nonnull align 1 dereferenceable(1) [[V]])
// CHECK-NEXT: call void @_ZN7gh611453VecC1EOS0_(ptr noundef nonnull align 1 dereferenceable(1) [[V1]], ptr noundef nonnull align 1 dereferenceable(1) [[V]])
// a.k.a. S1::~S1()
// CHECK-NEXT: call void @_ZN7gh611452S1D1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_TMP_ENSURED]])
// a.k.a.Vec::~Vec()
Expand All @@ -411,8 +413,9 @@ namespace gh61145 {
// CHECK-NEXT: [[AGG_TMP_ENSURED:%.*agg.tmp.ensured.*]] = alloca [[STRUCT_S2]], align 1
// a.k.a. Vec::Vec()
// CHECK-NEXT: call void @_ZN7gh611453VecC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[V]])
// CHECK-NEXT: [[V1:%.*v1.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 0
// a.k.a. Vec::Vec(Vec&&)
// CHECK-NEXT: call void @_ZN7gh611453VecC1EOS0_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_TMP_ENSURED]], ptr noundef nonnull align 1 dereferenceable(1) [[V]])
// CHECK-NEXT: call void @_ZN7gh611453VecC1EOS0_(ptr noundef nonnull align 1 dereferenceable(1) [[V1]], ptr noundef nonnull align 1 dereferenceable(1) [[V]])
// CHECK-NEXT: [[C:%.*c.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[AGG_TMP_ENSURED]], i32 0, i32
// CHECK-NEXT: store i8 0, ptr [[C]], align 1
// a.k.a. S2::~S2()
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGen/union-init2.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ union z {
};
union z y = {};

// CHECK: @foo = {{.*}}global %union.Foo undef, align 1
// CHECK: @foo = {{.*}}global %union.Foo zeroinitializer, align 1
// CHECK-CXX: @foo = {{.*}}global %union.Foo undef, align 1
union Foo {
struct Empty {} val;
Expand Down
3 changes: 1 addition & 2 deletions clang/test/CodeGen/voidptr-vaarg.c
Original file line number Diff line number Diff line change
Expand Up @@ -245,8 +245,7 @@ typedef struct {
// CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4
// CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[LIST_ADDR]], align 4
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[RETVAL]], ptr align 4 [[ARGP_CUR]], i32 4, i1 false)
// CHECK-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_EMPTY_INT_T]], ptr [[RETVAL]], i32 0, i32 0
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[COERCE_DIVE]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[RETVAL]], align 4
// CHECK-NEXT: ret i32 [[TMP0]]
//
empty_int_t empty_int(__builtin_va_list list) {
Expand Down
Loading