Skip to content

Commit ee7ef82

Browse files
committed
[CHERI CSA] Extend inference of increase alignment to fields other than the first field of a struct.
1 parent 502aaee commit ee7ef82

File tree

2 files changed

+17
-4
lines changed

2 files changed

+17
-4
lines changed

clang/lib/StaticAnalyzer/Checkers/PointerAlignmentChecker.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -191,15 +191,22 @@ int getTrailingZerosCount(const MemRegion *R, ProgramStateRef State,
191191
unsigned NaturalAlign = ASTCtx.getTypeAlignInChars(PT).getQuantity();
192192

193193
if (const FieldRegion *FR = R->getAs<FieldRegion>()) {
194-
// If this is the first field of a larger struct, we can use the alignment
195-
// of the containing struct try to increase the assumed alignment.
194+
// If this is the a field of a larger struct, we can use the alignment
195+
// of the containing struct combined with the offset to try to increase
196+
// the assumed alignment.
196197
const RegionOffset &Offset = FR->getAsOffset();
197-
if (!Offset.hasSymbolicOffset() && Offset.getOffset() == 0) {
198+
if (!Offset.hasSymbolicOffset()) {
198199
if (const auto *Base =
199200
FR->getSuperRegion()->getAs<TypedValueRegion>()) {
200201
auto BaseTy = Base->getValueType();
201202
unsigned BaseAlign = ASTCtx.getTypeAlignInChars(BaseTy).getQuantity();
202-
NaturalAlign = std::max(NaturalAlign, BaseAlign);
203+
uint64_t FieldOffsetBits = Offset.getOffset();
204+
unsigned Offset =
205+
ASTCtx.toCharUnitsFromBits(FieldOffsetBits).getQuantity();
206+
unsigned OffsetAlign =
207+
(Offset == 0) ? BaseAlign : (1ULL << llvm::countr_zero(Offset));
208+
unsigned InferredAlign = std::min(BaseAlign, OffsetAlign);
209+
NaturalAlign = std::max(NaturalAlign, InferredAlign);
203210
}
204211
}
205212
}

clang/test/Analysis/pointer-alignment.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,10 +207,16 @@ void cast_and_assign(void) {
207207
struct __attribute__((aligned(8))) AlignedParentStruct {
208208
int a;
209209
int b;
210+
int c;
211+
int d;
210212
};
211213

212214
void write_to_first_member(struct AlignedParentStruct *chunk) {
213215
// No warning because alignment of is inferred from the parent struct.
214216
*(long long*)(&chunk->a) = 0;
215217
}
216218

219+
void write_to_second_member(struct AlignedParentStruct *chunk) {
220+
// No warning because alignment of is inferred from the parent struct.
221+
*(long long*)(&chunk->c) = 0;
222+
}

0 commit comments

Comments
 (0)