Skip to content

Commit 118f0c1

Browse files
committed
[Sema] Fix false positive warnings for misaligned member access
Potential misaligned accesses are collected and reported on a per full expression basis, however some of them are discarded before reporting. When a nested full expression is completed it will emit diagnostics for 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. This is fixed by maintaining separate potential candidate lists per expression evaluation context and processing only the list for the current context.
1 parent 28e1e7e commit 118f0c1

File tree

4 files changed

+24
-10
lines changed

4 files changed

+24
-10
lines changed

clang/include/clang/Sema/Sema.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3110,9 +3110,6 @@ class Sema final : public SemaBase {
31103110

31113111
bool operator==(const MisalignedMember &m) { return this->E == m.E; }
31123112
};
3113-
/// Small set of gathered accesses to potentially misaligned members
3114-
/// due to the packed attribute.
3115-
SmallVector<MisalignedMember, 4> MisalignedMembers;
31163113

31173114
/// Adds an expression to the set of gathered misaligned members.
31183115
void AddPotentialMisalignedMembers(Expr *E, RecordDecl *RD, ValueDecl *MD,
@@ -6765,6 +6762,10 @@ class Sema final : public SemaBase {
67656762
/// InLifetimeExtendingContext is true.
67666763
SmallVector<MaterializeTemporaryExpr *, 8> ForRangeLifetimeExtendTemps;
67676764

6765+
/// Small set of gathered accesses to potentially misaligned members
6766+
/// due to the packed attribute.
6767+
SmallVector<MisalignedMember, 4> MisalignedMembers;
6768+
67686769
/// \brief Describes whether we are in an expression constext which we have
67696770
/// to handle differently.
67706771
enum ExpressionKind {

clang/lib/Sema/SemaChecking.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14084,7 +14084,6 @@ void Sema::CheckCompletedExpr(Expr *E, SourceLocation CheckLoc,
1408414084
CheckUnsequencedOperations(E);
1408514085
if (!IsConstexpr && !E->isValueDependent())
1408614086
CheckForIntOverflow(E);
14087-
DiagnoseMisalignedMembers();
1408814087
}
1408914088

1409014089
void Sema::CheckBitFieldInitialization(SourceLocation InitLoc,
@@ -15529,11 +15528,13 @@ void Sema::CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr,
1552915528

1553015529
void Sema::AddPotentialMisalignedMembers(Expr *E, RecordDecl *RD, ValueDecl *MD,
1553115530
CharUnits Alignment) {
15532-
MisalignedMembers.emplace_back(E, RD, MD, Alignment);
15531+
currentEvaluationContext().MisalignedMembers.emplace_back(E, RD, MD,
15532+
Alignment);
1553315533
}
1553415534

1553515535
void Sema::DiagnoseMisalignedMembers() {
15536-
for (MisalignedMember &m : MisalignedMembers) {
15536+
auto &MisalignedMembersForExpr = currentEvaluationContext().MisalignedMembers;
15537+
for (MisalignedMember &m : MisalignedMembersForExpr) {
1553715538
const NamedDecl *ND = m.RD;
1553815539
if (ND->getName().empty()) {
1553915540
if (const TypedefNameDecl *TD = m.RD->getTypedefNameForAnonDecl())
@@ -15542,7 +15543,7 @@ void Sema::DiagnoseMisalignedMembers() {
1554215543
Diag(m.E->getBeginLoc(), diag::warn_taking_address_of_packed_member)
1554315544
<< m.MD << ND << m.E->getSourceRange();
1554415545
}
15545-
MisalignedMembers.clear();
15546+
MisalignedMembersForExpr.clear();
1554615547
}
1554715548

1554815549
void Sema::DiscardMisalignedMemberAddress(const Type *T, Expr *E) {
@@ -15553,13 +15554,15 @@ void Sema::DiscardMisalignedMemberAddress(const Type *T, Expr *E) {
1555315554
cast<UnaryOperator>(E)->getOpcode() == UO_AddrOf) {
1555415555
auto *Op = cast<UnaryOperator>(E)->getSubExpr()->IgnoreParens();
1555515556
if (isa<MemberExpr>(Op)) {
15556-
auto *MA = llvm::find(MisalignedMembers, MisalignedMember(Op));
15557-
if (MA != MisalignedMembers.end() &&
15557+
auto &MisalignedMembersForExpr =
15558+
currentEvaluationContext().MisalignedMembers;
15559+
auto *MA = llvm::find(MisalignedMembersForExpr, MisalignedMember(Op));
15560+
if (MA != MisalignedMembersForExpr.end() &&
1555815561
(T->isDependentType() || T->isIntegerType() ||
1555915562
(T->isPointerType() && (T->getPointeeType()->isIncompleteType() ||
1556015563
Context.getTypeAlignInChars(
1556115564
T->getPointeeType()) <= MA->Alignment))))
15562-
MisalignedMembers.erase(MA);
15565+
MisalignedMembersForExpr.erase(MA);
1556315566
}
1556415567
}
1556515568
}

clang/lib/Sema/SemaExpr.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18105,6 +18105,8 @@ void Sema::PopExpressionEvaluationContext() {
1810518105
MaybeODRUseExprs.insert_range(Rec.SavedMaybeODRUseExprs);
1810618106
}
1810718107

18108+
DiagnoseMisalignedMembers();
18109+
1810818110
// Pop the current expression evaluation context off the stack.
1810918111
ExprEvalContexts.pop_back();
1811018112
}

clang/test/Sema/address-packed.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,3 +338,11 @@ struct Invalid0 {
338338
void *g14(struct Invalid0 *ivl) {
339339
return &(ivl->x);
340340
}
341+
342+
void to_void_with_expr(void *ptr, int expr);
343+
344+
void g15(void) {
345+
struct Arguable arguable;
346+
to_void_with_expr(&arguable.x, 3); // no-warning
347+
to_void_with_expr(&arguable.x, ({3;})); // no-warning
348+
}

0 commit comments

Comments
 (0)