[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 5bcf31ebfa ("[Clang] Loop over FieldDecls instead of all
Decls (#89453)")
Fixes 2039.
This commit is contained in:
@@ -1071,21 +1071,20 @@ using RecIndicesTy =
|
||||
SmallVector<std::pair<const RecordDecl *, llvm::Value *>, 8>;
|
||||
|
||||
static bool getGEPIndicesToField(CodeGenFunction &CGF, const RecordDecl *RD,
|
||||
const FieldDecl *FD, RecIndicesTy &Indices) {
|
||||
const FieldDecl *Field,
|
||||
RecIndicesTy &Indices) {
|
||||
const CGRecordLayout &Layout = CGF.CGM.getTypes().getCGRecordLayout(RD);
|
||||
int64_t FieldNo = -1;
|
||||
for (const Decl *D : RD->decls()) {
|
||||
if (const auto *Field = dyn_cast<FieldDecl>(D)) {
|
||||
FieldNo = Layout.getLLVMFieldNo(Field);
|
||||
if (FD == Field) {
|
||||
Indices.emplace_back(std::make_pair(RD, CGF.Builder.getInt32(FieldNo)));
|
||||
return true;
|
||||
}
|
||||
for (const FieldDecl *FD : RD->fields()) {
|
||||
FieldNo = Layout.getLLVMFieldNo(FD);
|
||||
if (FD == Field) {
|
||||
Indices.emplace_back(std::make_pair(RD, CGF.Builder.getInt32(FieldNo)));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (const auto *Record = dyn_cast<RecordDecl>(D)) {
|
||||
++FieldNo;
|
||||
if (getGEPIndicesToField(CGF, Record, FD, Indices)) {
|
||||
QualType Ty = FD->getType();
|
||||
if (Ty->isRecordType()) {
|
||||
if (getGEPIndicesToField(CGF, Ty->getAsRecordDecl(), Field, Indices)) {
|
||||
if (RD->isUnion())
|
||||
FieldNo = 0;
|
||||
Indices.emplace_back(std::make_pair(RD, CGF.Builder.getInt32(FieldNo)));
|
||||
|
||||
@@ -1852,3 +1852,57 @@ struct annotated_struct_array {
|
||||
void test29(struct annotated_struct_array *ann, int idx1, int idx2) {
|
||||
ann->ann_array[idx1]->array[idx2] = __builtin_dynamic_object_size(ann->ann_array[idx1]->array, 1);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
char __padding[0];
|
||||
} test30_spinlock_t;
|
||||
|
||||
struct test30_struct {
|
||||
struct test30_decl *name_node;
|
||||
int priv_len;
|
||||
test30_spinlock_t pcpu_refcnt;
|
||||
char priv[] __counted_by(priv_len);
|
||||
};
|
||||
|
||||
// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test30(
|
||||
// SANITIZE-WITH-ATTR-SAME: ptr noundef [[PTR:%.*]], i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR5]] {
|
||||
// SANITIZE-WITH-ATTR-NEXT: entry:
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = zext i32 [[IDX]] to i64, !nosanitize [[META2]]
|
||||
// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB39:[0-9]+]], i64 [[TMP0]]) #[[ATTR10]], !nosanitize [[META2]]
|
||||
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]]
|
||||
//
|
||||
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test30(
|
||||
// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef [[PTR:%.*]], i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR1]] {
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: entry:
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 8
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.smax.i32(i32 [[DOT_COUNTED_BY_LOAD]], i32 4)
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i32 [[DOT_COUNTED_BY_LOAD]], 0
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = trunc i32 [[TMP0]] to i8
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = add i8 [[TMP1]], 12
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = select i1 [[DOTINV]], i8 0, i8 [[TMP2]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[PCPU_REFCNT:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 12
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[IDX]] to i64
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[PCPU_REFCNT]], i64 0, i64 [[IDXPROM]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: store i8 [[CONV]], ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: ret void
|
||||
//
|
||||
// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test30(
|
||||
// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[PTR:%.*]], i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR3]] {
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: entry:
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = zext i32 [[IDX]] to i64, !nosanitize [[META9]]
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB15:[0-9]+]], i64 [[TMP0]]) #[[ATTR8]], !nosanitize [[META9]]
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: unreachable, !nosanitize [[META9]]
|
||||
//
|
||||
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test30(
|
||||
// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[PTR:%.*]], i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry:
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[PCPU_REFCNT:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 12
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[IDX]] to i64
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[PCPU_REFCNT]], i64 0, i64 [[IDXPROM]]
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i8 -1, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6]]
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void
|
||||
//
|
||||
void test30(struct test30_struct *ptr, int idx) {
|
||||
ptr->pcpu_refcnt.__padding[idx] = __builtin_dynamic_object_size(ptr, 1);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user