-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Silence spurious -Wnontrivial-memcall warnings in C mode #137429
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
clang currently issues a warning when memset is used on a struct that contains an address-discriminated pointer field, even though this is entirely valid behavior. For example: ``` struct S { int * __ptrauth(1, 1, 100) p; } s; memset(&s, 0, sizeof(struct S)); ``` Only allow the warning to be emitted in C++ mode to silence the warning. rdar://142495870
@llvm/pr-subscribers-clang Author: Akira Hatanaka (ahatanak) Changesclang currently issues a warning when memset is used on a struct that contains an address-discriminated pointer field, even though this is entirely valid behavior. For example:
Only allow the warning to be emitted in C++ mode to silence the warning. rdar://142495870 Full diff: https://github.com/llvm/llvm-project/pull/137429.diff 2 Files Affected:
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 9c9372d9ee2b0..ee3b55c83699e 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -9724,9 +9724,9 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call,
// completed later. GCC does not diagnose such code, but we may want to
// consider diagnosing it in the future, perhaps under a different, but
// related, diagnostic group.
- bool MayBeTriviallyCopyableCXXRecord =
- RT->isIncompleteType() ||
- RT->desugar().isTriviallyCopyableType(Context);
+ bool NonTriviallyCopyableCXXRecord =
+ getLangOpts().CPlusPlus && !RT->isIncompleteType() &&
+ !RT->desugar().isTriviallyCopyableType(Context);
if ((BId == Builtin::BImemset || BId == Builtin::BIbzero) &&
RT->getDecl()->isNonTrivialToPrimitiveDefaultInitialize()) {
@@ -9735,7 +9735,7 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call,
<< ArgIdx << FnName << PointeeTy << 0);
SearchNonTrivialToInitializeField::diag(PointeeTy, Dest, *this);
} else if ((BId == Builtin::BImemset || BId == Builtin::BIbzero) &&
- !MayBeTriviallyCopyableCXXRecord && ArgIdx == 0) {
+ NonTriviallyCopyableCXXRecord && ArgIdx == 0) {
// FIXME: Limiting this warning to dest argument until we decide
// whether it's valid for source argument too.
DiagRuntimeBehavior(Dest->getExprLoc(), Dest,
@@ -9748,7 +9748,7 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call,
<< ArgIdx << FnName << PointeeTy << 1);
SearchNonTrivialToCopyField::diag(PointeeTy, Dest, *this);
} else if ((BId == Builtin::BImemcpy || BId == Builtin::BImemmove) &&
- !MayBeTriviallyCopyableCXXRecord && ArgIdx == 0) {
+ NonTriviallyCopyableCXXRecord && ArgIdx == 0) {
// FIXME: Limiting this warning to dest argument until we decide
// whether it's valid for source argument too.
DiagRuntimeBehavior(Dest->getExprLoc(), Dest,
diff --git a/clang/test/Sema/warn-nontrivial-struct-memaccess-ptrauth.c b/clang/test/Sema/warn-nontrivial-struct-memaccess-ptrauth.c
new file mode 100644
index 0000000000000..d9cd712330c1b
--- /dev/null
+++ b/clang/test/Sema/warn-nontrivial-struct-memaccess-ptrauth.c
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics -fsyntax-only -verify %s
+
+void *memset(void *, int, __SIZE_TYPE__);
+void bzero(void *, __SIZE_TYPE__);
+void *memcpy(void *, const void *, __SIZE_TYPE__);
+void *memmove(void *, const void *, __SIZE_TYPE__);
+
+#define AQ __ptrauth(1,1,50)
+#define IQ __ptrauth(1,0,50)
+
+struct PtrAuthTrivial {
+ int f0;
+ int * IQ f1;
+};
+
+struct PtrAuthNonTrivial0 {
+ int f0;
+ int * AQ f1; // expected-note 2 {{non-trivial to copy}}
+ int f2;
+};
+
+struct PtrAuthNonTrivial1 {
+ int * AQ f0; // expected-note 2 {{non-trivial to copy}}
+ int f1;
+ struct PtrAuthNonTrivial0 f2;
+};
+
+void testPtrAuthTrivial(struct PtrAuthTrivial *d, struct PtrAuthTrivial *s) {
+ memset(d, 0, sizeof(struct PtrAuthTrivial));
+ bzero(d, sizeof(struct PtrAuthTrivial));
+ memcpy(d, s, sizeof(struct PtrAuthTrivial));
+ memmove(d, s, sizeof(struct PtrAuthTrivial));
+}
+
+void testPtrAuthNonTrivial1(struct PtrAuthNonTrivial1 *d,
+ struct PtrAuthNonTrivial1 *s) {
+ memset(d, 0, sizeof(struct PtrAuthNonTrivial1));
+ bzero(d, sizeof(struct PtrAuthNonTrivial1));
+ memcpy(d, s, sizeof(struct PtrAuthNonTrivial1)); // expected-warning {{that is not trivial to primitive-copy}} expected-note {{explicitly cast the pointer to silence}}
+ memmove(d, s, sizeof(struct PtrAuthNonTrivial1)); // expected-warning {{that is not trivial to primitive-copy}} expected-note {{explicitly cast the pointer to silence}}
+}
|
RT->desugar().isTriviallyCopyableType(Context); | ||
bool NonTriviallyCopyableCXXRecord = | ||
getLangOpts().CPlusPlus && !RT->isIncompleteType() && | ||
!RT->desugar().isTriviallyCopyableType(Context); |
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 would like to have isTriviallyCopyableType
do any required desugaring or canonicalization rather than requiring every call site do this work, it's a constant hazard.
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.
Do we have to desugar the type before calling isTriviallyCopyableType
? It doesn't look like other call sites are doing so.
Why is the call to desugar` needed here?
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.
This should have a release note.
The |
// RUN: %clang_cc1 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics -fsyntax-only -x c++ -verify=cxx,expected %s | ||
// RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics -fsyntax-only -x c++ -verify=cxx,expected %s | ||
|
||
#if defined __cplusplus |
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.
ahahah, I was literally thinking "add a -D argument to say it's C++" because I'm a muppet and forgot the builtin macro :D
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/59/builds/16905 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/18/builds/15265 Here is the relevant piece of the build log for the reference
|
clang currently issues a warning when memset is used on a struct that contains an address-discriminated pointer field, even though this is entirely valid behavior. For example: ``` struct S { int * __ptrauth(1, 1, 100) p; } s; memset(&s, 0, sizeof(struct S)); ``` Only allow the warning to be emitted in C++ mode to silence the warning. rdar://142495870
clang currently issues a warning when memset is used on a struct that contains an address-discriminated pointer field, even though this is entirely valid behavior. For example: ``` struct S { int * __ptrauth(1, 1, 100) p; } s; memset(&s, 0, sizeof(struct S)); ``` Only allow the warning to be emitted in C++ mode to silence the warning. rdar://142495870
clang currently issues a warning when memset is used on a struct that contains an address-discriminated pointer field, even though this is entirely valid behavior. For example: ``` struct S { int * __ptrauth(1, 1, 100) p; } s; memset(&s, 0, sizeof(struct S)); ``` Only allow the warning to be emitted in C++ mode to silence the warning. rdar://142495870
clang currently issues a warning when memset is used on a struct that contains an address-discriminated pointer field, even though this is entirely valid behavior. For example: ``` struct S { int * __ptrauth(1, 1, 100) p; } s; memset(&s, 0, sizeof(struct S)); ``` Only allow the warning to be emitted in C++ mode to silence the warning. rdar://142495870
clang currently issues a warning when memset is used on a struct that contains an address-discriminated pointer field, even though this is entirely valid behavior.
For example:
Only allow the warning to be emitted in C++ mode to silence the warning.
rdar://142495870