-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[Sema] Fix false positive warnings for misaligned member access #150025
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Sema] Fix false positive warnings for misaligned member access #150025
Conversation
@llvm/pr-subscribers-clang Author: Vladimir Vuksanovic (vvuksanovic) ChangesThese 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 Full diff: https://github.com/llvm/llvm-project/pull/150025.diff 3 Files Affected:
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index b331acbe606b7..a2ad749d67259 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -2655,7 +2655,7 @@ class Sema final : public SemaBase {
/// Diagnoses the current set of gathered accesses. This typically
/// happens at full expression level. The set is cleared after emitting the
/// diagnostics.
- void DiagnoseMisalignedMembers();
+ void DiagnoseMisalignedMembers(const Expr *E);
/// This function checks if the expression is in the sef of potentially
/// misaligned members and it is converted to some pointer type T with lower
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 5e523fe887318..032cda4bd5d58 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -14086,7 +14086,7 @@ void Sema::CheckCompletedExpr(Expr *E, SourceLocation CheckLoc,
CheckUnsequencedOperations(E);
if (!IsConstexpr && !E->isValueDependent())
CheckForIntOverflow(E);
- DiagnoseMisalignedMembers();
+ DiagnoseMisalignedMembers(E);
}
void Sema::CheckBitFieldInitialization(SourceLocation InitLoc,
@@ -15534,17 +15534,28 @@ void Sema::AddPotentialMisalignedMembers(Expr *E, RecordDecl *RD, ValueDecl *MD,
MisalignedMembers.emplace_back(E, RD, MD, Alignment);
}
-void Sema::DiagnoseMisalignedMembers() {
- for (MisalignedMember &m : MisalignedMembers) {
- const NamedDecl *ND = m.RD;
+void Sema::DiagnoseMisalignedMembers(const Expr *E) {
+ // Only emit diagnostics related to the current expression.
+ const auto *EmitFrom = MisalignedMembers.begin();
+ if (E->getSourceRange().isValid()) {
+ EmitFrom = MisalignedMembers.end();
+ for (const auto &m : llvm::reverse(MisalignedMembers)) {
+ if (m.E->getSourceRange().isValid() &&
+ !E->getSourceRange().fullyContains(m.E->getSourceRange()))
+ break;
+ EmitFrom = &m;
+ }
+ }
+ for (const auto *m = EmitFrom; m != MisalignedMembers.end(); ++m) {
+ const NamedDecl *ND = m->RD;
if (ND->getName().empty()) {
- if (const TypedefNameDecl *TD = m.RD->getTypedefNameForAnonDecl())
+ if (const TypedefNameDecl *TD = m->RD->getTypedefNameForAnonDecl())
ND = TD;
}
- Diag(m.E->getBeginLoc(), diag::warn_taking_address_of_packed_member)
- << m.MD << ND << m.E->getSourceRange();
+ Diag(m->E->getBeginLoc(), diag::warn_taking_address_of_packed_member)
+ << m->MD << ND << m->E->getSourceRange();
}
- MisalignedMembers.clear();
+ MisalignedMembers.erase(EmitFrom, MisalignedMembers.end());
}
void Sema::DiscardMisalignedMemberAddress(const Type *T, Expr *E) {
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
+}
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the fix, please add a release note.
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.
ea9a498
to
118f0c1
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly good to me, I have a couple questions, but thats about it. I don't want to approve, but no longer need a 'request changes'(and github doesn't have a way of clearing it).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor preference for a better 'alias' name in the 1 section (or none at all), but otherwise this is fine to me. I'm Ok either way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still approve, LMK if you need someone to click the 'merge' button for you, or if you can merge it yourself.
Yes, can you merge this? I don't have commit access. |
I've set it up to auto-merge once CI passes. Ping me here if CI fails and you think it isn't your fault. |
Head branch was pushed to by a user without write access
Had to update to fix conflicts. Can you merge? |
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