-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang][Sema] Fix crash on atomic builtins with incomplete type args #96374
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
Conversation
@llvm/pr-subscribers-clang Author: Takuya Shimizu (hazohelet) ChangesThis patch fixes the crash when pointers to incomplete type are passed to atomic builtins such as Relevant PR: #91057 Full diff: https://github.com/llvm/llvm-project/pull/96374.diff 2 Files Affected:
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 7a2076d139c69..1872bdb5767f0 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -4570,7 +4570,8 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
}
// Pointer to object of size zero is not allowed.
- if (Context.getTypeInfoInChars(AtomTy).Width.isZero()) {
+ if (!AtomTy->isIncompleteType() &&
+ Context.getTypeInfoInChars(AtomTy).Width.isZero()) {
Diag(ExprRange.getBegin(), diag::err_atomic_builtin_must_be_pointer)
<< Ptr->getType() << 1 << Ptr->getSourceRange();
return ExprError();
diff --git a/clang/test/Sema/atomic-ops.c b/clang/test/Sema/atomic-ops.c
index 2024b81ce6aec..d957461b6cb75 100644
--- a/clang/test/Sema/atomic-ops.c
+++ b/clang/test/Sema/atomic-ops.c
@@ -671,6 +671,36 @@ void zeroSizeArgError(struct Z *a, struct Z *b, struct Z *c) {
}
+struct IncompleteTy IncA, IncB, IncC; // expected-error 3{{tentative definition has type 'struct IncompleteTy' that is never completed}} \
+ // expected-note 3{{forward declaration of 'struct IncompleteTy'}}
+void incompleteTypeArgError() {
+ __atomic_exchange(&IncB, &IncB, &IncC, memory_order_relaxed); // expected-error {{must be a pointer to a trivially-copyable type}}
+ __atomic_exchange(&IncB, &IncB, &IncC, memory_order_acq_rel); // expected-error {{must be a pointer to a trivially-copyable type}}
+ __atomic_exchange(&IncB, &IncB, &IncC, memory_order_acquire); // expected-error {{must be a pointer to a trivially-copyable type}}
+ __atomic_exchange(&IncB, &IncB, &IncC, memory_order_consume); // expected-error {{must be a pointer to a trivially-copyable type}}
+ __atomic_exchange(&IncB, &IncB, &IncC, memory_order_release); // expected-error {{must be a pointer to a trivially-copyable type}}
+ __atomic_exchange(&IncB, &IncB, &IncC, memory_order_seq_cst); // expected-error {{must be a pointer to a trivially-copyable type}}
+ __atomic_load(&IncA, &IncB, memory_order_relaxed); // expected-error {{must be a pointer to a trivially-copyable type}}
+ __atomic_load(&IncA, &IncB, memory_order_acq_rel); // expected-error {{must be a pointer to a trivially-copyable type}}
+ __atomic_load(&IncA, &IncB, memory_order_acquire); // expected-error {{must be a pointer to a trivially-copyable type}}
+ __atomic_load(&IncA, &IncB, memory_order_consume); // expected-error {{must be a pointer to a trivially-copyable type}}
+ __atomic_load(&IncA, &IncB, memory_order_release); // expected-error {{must be a pointer to a trivially-copyable type}}
+ __atomic_load(&IncA, &IncB, memory_order_seq_cst); // expected-error {{must be a pointer to a trivially-copyable type}}
+ __atomic_store(&IncA, &IncB, memory_order_relaxed); // expected-error {{must be a pointer to a trivially-copyable type}}
+ __atomic_store(&IncA, &IncB, memory_order_acq_rel); // expected-error {{must be a pointer to a trivially-copyable type}}
+ __atomic_store(&IncA, &IncB, memory_order_acquire); // expected-error {{must be a pointer to a trivially-copyable type}}
+ __atomic_store(&IncA, &IncB, memory_order_consume); // expected-error {{must be a pointer to a trivially-copyable type}}
+ __atomic_store(&IncA, &IncB, memory_order_release); // expected-error {{must be a pointer to a trivially-copyable type}}
+ __atomic_store(&IncA, &IncB, memory_order_seq_cst); // expected-error {{must be a pointer to a trivially-copyable type}}
+ __atomic_compare_exchange(&IncA, &IncB, &IncC, 0, memory_order_relaxed, memory_order_relaxed); // expected-error {{must be a pointer to a trivially-copyable type}}
+ __atomic_compare_exchange(&IncA, &IncB, &IncC, 0, memory_order_acq_rel, memory_order_acq_rel); // expected-error {{must be a pointer to a trivially-copyable type}}
+ __atomic_compare_exchange(&IncA, &IncB, &IncC, 0, memory_order_acquire, memory_order_acquire); // expected-error {{must be a pointer to a trivially-copyable type}}
+ __atomic_compare_exchange(&IncA, &IncB, &IncC, 0, memory_order_consume, memory_order_consume); // expected-error {{must be a pointer to a trivially-copyable type}}
+ __atomic_compare_exchange(&IncA, &IncB, &IncC, 0, memory_order_release, memory_order_release); // expected-error {{must be a pointer to a trivially-copyable type}}
+ __atomic_compare_exchange(&IncA, &IncB, &IncC, 0, memory_order_seq_cst, memory_order_seq_cst); // expected-error {{must be a pointer to a trivially-copyable type}}
+
+}
+
void nullPointerWarning(void) {
volatile _Atomic(int) vai;
_Atomic(int) ai;
|
Could you knock out a related bug at the same time: template<typename>
struct X {
char arr[1];
};
extern X<void>* p, *q;
//X<void> inst;
void f() {
__atomic_exchange(p, p, q, __ATOMIC_RELAXED);
} With the line commented out, currently this crashes, but in Clang 18 and with your patch, it fails as
|
|
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! The changes should also come with a release note in clang/docs/ReleaseNotes.rst
so users know about the improvement.
clang/lib/Sema/SemaChecking.cpp
Outdated
@@ -4570,7 +4570,8 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange, | |||
} | |||
|
|||
// Pointer to object of size zero is not allowed. | |||
if (Context.getTypeInfoInChars(AtomTy).Width.isZero()) { | |||
if (!AtomTy->isIncompleteType() && |
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.
If you call RequireCompleteType()
before this if
instead of checking for an incomplete type, do you get better diagnostic behavior?
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.
The current diagnostic message only says we need trivially-copyable type here, and the RequireCompleteType
version would say we need complete type here and it sounds more understandable to me.
Thanks for the feedback. |
7a76e4f
to
dd9bbf5
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.
LGTM!
…lvm#96374) This patch fixes the crash when pointers to incomplete type are passed to atomic builtins such as `__atomic_load`. `ASTContext::getTypeInfoInChars` assumes that the argument type is a complete type, so I added a check to eliminate cases where incomplete types gets passed to this function Relevant PR: llvm#91057 Fixes llvm#96289
This patch fixes the crash when pointers to incomplete type are passed to atomic builtins such as
__atomic_load
.ASTContext::getTypeInfoInChars
assumes that the argument type is a complete type, so I added a check to eliminate cases where incomplete types gets passed to this functionRelevant PR: #91057
Fixes #96289