diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index d109518bca3f3..7dc465708c72b 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -166,6 +166,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 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 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 ForRangeLifetimeExtendTemps; + /// Small set of gathered accesses to potentially misaligned members + /// due to the packed attribute. + SmallVector MisalignedMembers; + /// \brief Describes whether we are in an expression constext which we have /// to handle differently. 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(E)->getOpcode() == UO_AddrOf) { auto *Op = cast(E)->getSubExpr()->IgnoreParens(); if (isa(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 +}