From 886848e9e7982cfc68bfcf28173e4dc3fc3fafd1 Mon Sep 17 00:00:00 2001 From: Owen Anderson Date: Mon, 28 Jul 2025 23:05:24 +0800 Subject: [PATCH] [CHERI CSA] When inferring the alignment of the first field in a struct, use the alignment of the struct itself to help infer higher alignment. --- .../Checkers/PointerAlignmentChecker.cpp | 14 ++++++++++++++ clang/test/Analysis/pointer-alignment.c | 12 ++++++++++++ 2 files changed, 26 insertions(+) diff --git a/clang/lib/StaticAnalyzer/Checkers/PointerAlignmentChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/PointerAlignmentChecker.cpp index f6810fd409019..bbe4e9e6a9243 100644 --- a/clang/lib/StaticAnalyzer/Checkers/PointerAlignmentChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/PointerAlignmentChecker.cpp @@ -190,6 +190,20 @@ int getTrailingZerosCount(const MemRegion *R, ProgramStateRef State, return -1; unsigned NaturalAlign = ASTCtx.getTypeAlignInChars(PT).getQuantity(); + if (const FieldRegion *FR = R->getAs()) { + // If this is the first field of a larger struct, we can use the alignment + // of the containing struct try to increase the assumed alignment. + const RegionOffset &Offset = FR->getAsOffset(); + if (!Offset.hasSymbolicOffset() && Offset.getOffset() == 0) { + if (const auto *Base = + FR->getSuperRegion()->getAs()) { + auto BaseTy = Base->getValueType(); + unsigned BaseAlign = ASTCtx.getTypeAlignInChars(BaseTy).getQuantity(); + NaturalAlign = std::max(NaturalAlign, BaseAlign); + } + } + } + if (const ElementRegion *ER = R->getAs()) { int ElTyTZ = APSInt::getUnsigned(NaturalAlign).countTrailingZeros(); diff --git a/clang/test/Analysis/pointer-alignment.c b/clang/test/Analysis/pointer-alignment.c index 9df8dec56b249..4accc82c80a49 100644 --- a/clang/test/Analysis/pointer-alignment.c +++ b/clang/test/Analysis/pointer-alignment.c @@ -202,3 +202,15 @@ void cast_and_assign(void) { // no duplicate assign warn *i = 42; } + +// ---- +struct __attribute__((aligned(8))) AlignedParentStruct { + int a; + int b; +}; + +void write_to_first_member(struct AlignedParentStruct *chunk) { + // No warning because alignment of is inferred from the parent struct. + *(long long*)(&chunk->a) = 0; +} +