Author: Vladimir Vuksanovic Date: 2025-08-14T06:14:43-07:00 New Revision: 9d1dd9a26445f55b0f60f008adbacd937c7aad14
URL: https://github.com/llvm/llvm-project/commit/9d1dd9a26445f55b0f60f008adbacd937c7aad14 DIFF: https://github.com/llvm/llvm-project/commit/9d1dd9a26445f55b0f60f008adbacd937c7aad14.diff LOG: [Sema] Fix false positive warnings for misaligned member access (#150025) These warnings are reported on a per expression basis, however some potential misaligned accesses are discarded before that happens. The problem is when a new expression starts while processing another expression. The new expression will end first and emit all potential misaligned accesses collected up to that point. That includes candidates that were found in the parent expression, even though they might have gotten discarded later. Fixed by checking if the candidate is located withing the currently processed expression. Fixes #144729 Added: Modified: clang/docs/ReleaseNotes.rst clang/include/clang/Sema/Sema.h clang/lib/Sema/SemaChecking.cpp clang/lib/Sema/SemaExpr.cpp clang/test/Sema/address-packed.c Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 031a196bbc83f..e23b7a1267ac2 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -168,6 +168,10 @@ Improvements to Clang's diagnostics "signedness of format specifier 'u' is incompatible with 'c' [-Wformat-signedness]" and the API-visible diagnostic id will be appropriate. +- Fixed false positives in ``-Waddress-of-packed-member`` diagnostics when + potential misaligned members get processed before they can get discarded. + (#GH144729) + Improvements to Clang's time-trace ---------------------------------- diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 1dfc276147fd4..f933803450600 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -2659,9 +2659,9 @@ class Sema final : public SemaBase { /// identifies the magic value. typedef std::pair<const IdentifierInfo *, uint64_t> TypeTagMagicValue; - /// Diagnoses the current set of gathered accesses. This typically - /// happens at full expression level. The set is cleared after emitting the - /// diagnostics. + /// Diagnoses the current set of gathered accesses. This happens at the end of + /// each expression evaluation context. Diagnostics are emitted only for + /// accesses gathered in the current evaluation context. void DiagnoseMisalignedMembers(); /// This function checks if the expression is in the sef of potentially @@ -3117,9 +3117,6 @@ class Sema final : public SemaBase { bool operator==(const MisalignedMember &m) { return this->E == m.E; } }; - /// Small set of gathered accesses to potentially misaligned members - /// due to the packed attribute. - SmallVector<MisalignedMember, 4> MisalignedMembers; /// Adds an expression to the set of gathered misaligned members. void AddPotentialMisalignedMembers(Expr *E, RecordDecl *RD, ValueDecl *MD, @@ -6765,6 +6762,10 @@ class Sema final : public SemaBase { /// InLifetimeExtendingContext is true. SmallVector<MaterializeTemporaryExpr *, 8> ForRangeLifetimeExtendTemps; + /// Small set of gathered accesses to potentially misaligned members + /// due to the packed attribute. + SmallVector<MisalignedMember, 4> MisalignedMembers; + /// \brief Describes whether we are in an expression constext which we have /// to handle diff erently. enum ExpressionKind { diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 0205460cc0bc9..2dc4ee74dc9df 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -14125,7 +14125,6 @@ void Sema::CheckCompletedExpr(Expr *E, SourceLocation CheckLoc, CheckUnsequencedOperations(E); if (!IsConstexpr && !E->isValueDependent()) CheckForIntOverflow(E); - DiagnoseMisalignedMembers(); } void Sema::CheckBitFieldInitialization(SourceLocation InitLoc, @@ -15570,11 +15569,12 @@ void Sema::CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr, void Sema::AddPotentialMisalignedMembers(Expr *E, RecordDecl *RD, ValueDecl *MD, CharUnits Alignment) { - MisalignedMembers.emplace_back(E, RD, MD, Alignment); + currentEvaluationContext().MisalignedMembers.emplace_back(E, RD, MD, + Alignment); } void Sema::DiagnoseMisalignedMembers() { - for (MisalignedMember &m : MisalignedMembers) { + for (MisalignedMember &m : currentEvaluationContext().MisalignedMembers) { const NamedDecl *ND = m.RD; if (ND->getName().empty()) { if (const TypedefNameDecl *TD = m.RD->getTypedefNameForAnonDecl()) @@ -15583,7 +15583,7 @@ void Sema::DiagnoseMisalignedMembers() { Diag(m.E->getBeginLoc(), diag::warn_taking_address_of_packed_member) << m.MD << ND << m.E->getSourceRange(); } - MisalignedMembers.clear(); + currentEvaluationContext().MisalignedMembers.clear(); } void Sema::DiscardMisalignedMemberAddress(const Type *T, Expr *E) { @@ -15594,13 +15594,15 @@ void Sema::DiscardMisalignedMemberAddress(const Type *T, Expr *E) { cast<UnaryOperator>(E)->getOpcode() == UO_AddrOf) { auto *Op = cast<UnaryOperator>(E)->getSubExpr()->IgnoreParens(); if (isa<MemberExpr>(Op)) { - auto *MA = llvm::find(MisalignedMembers, MisalignedMember(Op)); - if (MA != MisalignedMembers.end() && + auto &MisalignedMembersForExpr = + currentEvaluationContext().MisalignedMembers; + auto *MA = llvm::find(MisalignedMembersForExpr, MisalignedMember(Op)); + if (MA != MisalignedMembersForExpr.end() && (T->isDependentType() || T->isIntegerType() || (T->isPointerType() && (T->getPointeeType()->isIncompleteType() || Context.getTypeAlignInChars( T->getPointeeType()) <= MA->Alignment)))) - MisalignedMembers.erase(MA); + MisalignedMembersForExpr.erase(MA); } } } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 85320396fd17a..237c068f59283 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -18121,6 +18121,8 @@ void Sema::PopExpressionEvaluationContext() { MaybeODRUseExprs.insert_range(Rec.SavedMaybeODRUseExprs); } + DiagnoseMisalignedMembers(); + // Pop the current expression evaluation context off the stack. ExprEvalContexts.pop_back(); } diff --git a/clang/test/Sema/address-packed.c b/clang/test/Sema/address-packed.c index 29f12490e9fab..f826b7d57d91c 100644 --- a/clang/test/Sema/address-packed.c +++ b/clang/test/Sema/address-packed.c @@ -338,3 +338,11 @@ struct Invalid0 { void *g14(struct Invalid0 *ivl) { return &(ivl->x); } + +void to_void_with_expr(void *ptr, int expr); + +void g15(void) { + struct Arguable arguable; + to_void_with_expr(&arguable.x, 3); // no-warning + to_void_with_expr(&arguable.x, ({3;})); // no-warning +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits