Skip to content

Commit 08a6ad0

Browse files
bwendlingefriedma-quic
authored andcommitted
[Clang] Ignore empty FieldDecls when asking for the field number (#100040)
A FieldDecl that's an empty struct may not show up in CGRecordLayout. Go ahead and ignore such a field as it shouldn't make a difference to these calculations. Fixes: 1f6f97e ("[Clang] Loop over FieldDecls instead of all Decls (#99574)") Co-authored-by: Eli Friedman <[email protected]>
1 parent f2a841d commit 08a6ad0

File tree

3 files changed

+57
-0
lines changed

3 files changed

+57
-0
lines changed

clang/lib/CodeGen/CGExpr.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -1076,6 +1076,11 @@ static bool getGEPIndicesToField(CodeGenFunction &CGF, const RecordDecl *RD,
10761076
const CGRecordLayout &Layout = CGF.CGM.getTypes().getCGRecordLayout(RD);
10771077
int64_t FieldNo = -1;
10781078
for (const FieldDecl *FD : RD->fields()) {
1079+
if (!Layout.containsFieldDecl(FD))
1080+
// This could happen if the field has a struct type that's empty. I don't
1081+
// know why either.
1082+
continue;
1083+
10791084
FieldNo = Layout.getLLVMFieldNo(FD);
10801085
if (FD == Field) {
10811086
Indices.emplace_back(std::make_pair(RD, CGF.Builder.getInt32(FieldNo)));

clang/lib/CodeGen/CGRecordLayout.h

+4
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,10 @@ class CGRecordLayout {
193193
return IsZeroInitializableAsBase;
194194
}
195195

196+
bool containsFieldDecl(const FieldDecl *FD) const {
197+
return FieldInfo.count(FD) != 0;
198+
}
199+
196200
/// Return llvm::StructType element number that corresponds to the
197201
/// field FD.
198202
unsigned getLLVMFieldNo(const FieldDecl *FD) const {

clang/test/CodeGen/attr-counted-by.c

+48
Original file line numberDiff line numberDiff line change
@@ -1906,3 +1906,51 @@ struct test30_struct {
19061906
void test30(struct test30_struct *ptr, int idx) {
19071907
ptr->pcpu_refcnt.__padding[idx] = __builtin_dynamic_object_size(ptr, 1);
19081908
}
1909+
1910+
struct test31_empty {};
1911+
1912+
struct test31_struct {
1913+
struct test31_empty y;
1914+
int s;
1915+
int x[] __counted_by(s);
1916+
};
1917+
1918+
// SANITIZE-WITH-ATTR-LABEL: define dso_local i32 @test31(
1919+
// SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readonly [[PTR:%.*]], i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR2]] {
1920+
// SANITIZE-WITH-ATTR-NEXT: entry:
1921+
// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[PTR]], align 4
1922+
// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = sext i32 [[DOT_COUNTED_BY_LOAD]] to i64
1923+
// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = shl nsw i64 [[TMP0]], 2
1924+
// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = tail call i64 @llvm.smax.i64(i64 [[TMP1]], i64 0)
1925+
// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = trunc i64 [[TMP2]] to i32
1926+
// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = add i32 [[TMP3]], 4
1927+
// SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i32 [[DOT_COUNTED_BY_LOAD]], 0
1928+
// SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = select i1 [[DOTINV]], i32 0, i32 [[TMP4]]
1929+
// SANITIZE-WITH-ATTR-NEXT: ret i32 [[CONV]]
1930+
//
1931+
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local i32 @test31(
1932+
// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readonly [[PTR:%.*]], i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR2]] {
1933+
// NO-SANITIZE-WITH-ATTR-NEXT: entry:
1934+
// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[PTR]], align 4
1935+
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = sext i32 [[DOT_COUNTED_BY_LOAD]] to i64
1936+
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = shl nsw i64 [[TMP0]], 2
1937+
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = tail call i64 @llvm.smax.i64(i64 [[TMP1]], i64 0)
1938+
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = trunc i64 [[TMP2]] to i32
1939+
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = add i32 [[TMP3]], 4
1940+
// NO-SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i32 [[DOT_COUNTED_BY_LOAD]], 0
1941+
// NO-SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = select i1 [[DOTINV]], i32 0, i32 [[TMP4]]
1942+
// NO-SANITIZE-WITH-ATTR-NEXT: ret i32 [[CONV]]
1943+
//
1944+
// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i32 @test31(
1945+
// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[PTR:%.*]], i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR2]] {
1946+
// SANITIZE-WITHOUT-ATTR-NEXT: entry:
1947+
// SANITIZE-WITHOUT-ATTR-NEXT: ret i32 -1
1948+
//
1949+
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i32 @test31(
1950+
// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[PTR:%.*]], i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR1]] {
1951+
// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry:
1952+
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i32 -1
1953+
//
1954+
int test31(struct test31_struct *ptr, int idx) {
1955+
return __builtin_dynamic_object_size(ptr, 0);
1956+
}

0 commit comments

Comments
 (0)