Skip to content

Commit 1f6f97e

Browse files
authored
[Clang] Loop over FieldDecls instead of all Decls (#99574)
Only FieldDecls are important when determining GEP indices. A struct defined within another struct has the same semantics as if it were defined outside of the struct. So there's no need to look into RecordDecls that aren't a field. See commit 5bcf31e ("[Clang] Loop over FieldDecls instead of all Decls (#89453)") Fixes 2039.
1 parent 8be714b commit 1f6f97e

File tree

2 files changed

+64
-11
lines changed

2 files changed

+64
-11
lines changed

clang/lib/CodeGen/CGExpr.cpp

+10-11
Original file line numberDiff line numberDiff line change
@@ -1071,21 +1071,20 @@ using RecIndicesTy =
10711071
SmallVector<std::pair<const RecordDecl *, llvm::Value *>, 8>;
10721072

10731073
static bool getGEPIndicesToField(CodeGenFunction &CGF, const RecordDecl *RD,
1074-
const FieldDecl *FD, RecIndicesTy &Indices) {
1074+
const FieldDecl *Field,
1075+
RecIndicesTy &Indices) {
10751076
const CGRecordLayout &Layout = CGF.CGM.getTypes().getCGRecordLayout(RD);
10761077
int64_t FieldNo = -1;
1077-
for (const Decl *D : RD->decls()) {
1078-
if (const auto *Field = dyn_cast<FieldDecl>(D)) {
1079-
FieldNo = Layout.getLLVMFieldNo(Field);
1080-
if (FD == Field) {
1081-
Indices.emplace_back(std::make_pair(RD, CGF.Builder.getInt32(FieldNo)));
1082-
return true;
1083-
}
1078+
for (const FieldDecl *FD : RD->fields()) {
1079+
FieldNo = Layout.getLLVMFieldNo(FD);
1080+
if (FD == Field) {
1081+
Indices.emplace_back(std::make_pair(RD, CGF.Builder.getInt32(FieldNo)));
1082+
return true;
10841083
}
10851084

1086-
if (const auto *Record = dyn_cast<RecordDecl>(D)) {
1087-
++FieldNo;
1088-
if (getGEPIndicesToField(CGF, Record, FD, Indices)) {
1085+
QualType Ty = FD->getType();
1086+
if (Ty->isRecordType()) {
1087+
if (getGEPIndicesToField(CGF, Ty->getAsRecordDecl(), Field, Indices)) {
10891088
if (RD->isUnion())
10901089
FieldNo = 0;
10911090
Indices.emplace_back(std::make_pair(RD, CGF.Builder.getInt32(FieldNo)));

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

+54
Original file line numberDiff line numberDiff line change
@@ -1852,3 +1852,57 @@ struct annotated_struct_array {
18521852
void test29(struct annotated_struct_array *ann, int idx1, int idx2) {
18531853
ann->ann_array[idx1]->array[idx2] = __builtin_dynamic_object_size(ann->ann_array[idx1]->array, 1);
18541854
}
1855+
1856+
typedef struct {
1857+
char __padding[0];
1858+
} test30_spinlock_t;
1859+
1860+
struct test30_struct {
1861+
struct test30_decl *name_node;
1862+
int priv_len;
1863+
test30_spinlock_t pcpu_refcnt;
1864+
char priv[] __counted_by(priv_len);
1865+
};
1866+
1867+
// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test30(
1868+
// SANITIZE-WITH-ATTR-SAME: ptr noundef [[PTR:%.*]], i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR5]] {
1869+
// SANITIZE-WITH-ATTR-NEXT: entry:
1870+
// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = zext i32 [[IDX]] to i64, !nosanitize [[META2]]
1871+
// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB39:[0-9]+]], i64 [[TMP0]]) #[[ATTR10]], !nosanitize [[META2]]
1872+
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]]
1873+
//
1874+
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test30(
1875+
// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef [[PTR:%.*]], i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR1]] {
1876+
// NO-SANITIZE-WITH-ATTR-NEXT: entry:
1877+
// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 8
1878+
// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4
1879+
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.smax.i32(i32 [[DOT_COUNTED_BY_LOAD]], i32 4)
1880+
// NO-SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i32 [[DOT_COUNTED_BY_LOAD]], 0
1881+
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = trunc i32 [[TMP0]] to i8
1882+
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = add i8 [[TMP1]], 12
1883+
// NO-SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = select i1 [[DOTINV]], i8 0, i8 [[TMP2]]
1884+
// NO-SANITIZE-WITH-ATTR-NEXT: [[PCPU_REFCNT:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 12
1885+
// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[IDX]] to i64
1886+
// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[PCPU_REFCNT]], i64 0, i64 [[IDXPROM]]
1887+
// NO-SANITIZE-WITH-ATTR-NEXT: store i8 [[CONV]], ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6]]
1888+
// NO-SANITIZE-WITH-ATTR-NEXT: ret void
1889+
//
1890+
// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test30(
1891+
// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[PTR:%.*]], i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR3]] {
1892+
// SANITIZE-WITHOUT-ATTR-NEXT: entry:
1893+
// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = zext i32 [[IDX]] to i64, !nosanitize [[META9]]
1894+
// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB15:[0-9]+]], i64 [[TMP0]]) #[[ATTR8]], !nosanitize [[META9]]
1895+
// SANITIZE-WITHOUT-ATTR-NEXT: unreachable, !nosanitize [[META9]]
1896+
//
1897+
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test30(
1898+
// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[PTR:%.*]], i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR0]] {
1899+
// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry:
1900+
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[PCPU_REFCNT:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 12
1901+
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[IDX]] to i64
1902+
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[PCPU_REFCNT]], i64 0, i64 [[IDXPROM]]
1903+
// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i8 -1, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6]]
1904+
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void
1905+
//
1906+
void test30(struct test30_struct *ptr, int idx) {
1907+
ptr->pcpu_refcnt.__padding[idx] = __builtin_dynamic_object_size(ptr, 1);
1908+
}

0 commit comments

Comments
 (0)