Skip to content

Commit 6bb4ce0

Browse files
authored
Silence spurious -Wnontrivial-memcall warnings in C mode (#137429)
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
1 parent a01a5b8 commit 6bb4ce0

File tree

2 files changed

+65
-5
lines changed

2 files changed

+65
-5
lines changed

clang/lib/Sema/SemaChecking.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9735,9 +9735,9 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call,
97359735
// completed later. GCC does not diagnose such code, but we may want to
97369736
// consider diagnosing it in the future, perhaps under a different, but
97379737
// related, diagnostic group.
9738-
bool MayBeTriviallyCopyableCXXRecord =
9739-
RT->isIncompleteType() ||
9740-
RT->desugar().isTriviallyCopyableType(Context);
9738+
bool NonTriviallyCopyableCXXRecord =
9739+
getLangOpts().CPlusPlus && !RT->isIncompleteType() &&
9740+
!RT->desugar().isTriviallyCopyableType(Context);
97419741

97429742
if ((BId == Builtin::BImemset || BId == Builtin::BIbzero) &&
97439743
RT->getDecl()->isNonTrivialToPrimitiveDefaultInitialize()) {
@@ -9746,7 +9746,7 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call,
97469746
<< ArgIdx << FnName << PointeeTy << 0);
97479747
SearchNonTrivialToInitializeField::diag(PointeeTy, Dest, *this);
97489748
} else if ((BId == Builtin::BImemset || BId == Builtin::BIbzero) &&
9749-
!MayBeTriviallyCopyableCXXRecord && ArgIdx == 0) {
9749+
NonTriviallyCopyableCXXRecord && ArgIdx == 0) {
97509750
// FIXME: Limiting this warning to dest argument until we decide
97519751
// whether it's valid for source argument too.
97529752
DiagRuntimeBehavior(Dest->getExprLoc(), Dest,
@@ -9759,7 +9759,7 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call,
97599759
<< ArgIdx << FnName << PointeeTy << 1);
97609760
SearchNonTrivialToCopyField::diag(PointeeTy, Dest, *this);
97619761
} else if ((BId == Builtin::BImemcpy || BId == Builtin::BImemmove) &&
9762-
!MayBeTriviallyCopyableCXXRecord && ArgIdx == 0) {
9762+
NonTriviallyCopyableCXXRecord && ArgIdx == 0) {
97639763
// FIXME: Limiting this warning to dest argument until we decide
97649764
// whether it's valid for source argument too.
97659765
DiagRuntimeBehavior(Dest->getExprLoc(), Dest,
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// RUN: %clang_cc1 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics -fsyntax-only -verify=c,expected %s
2+
// RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics -fsyntax-only -verify=c,expected %s
3+
// RUN: %clang_cc1 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics -fsyntax-only -x c++ -verify=cxx,expected %s
4+
// RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics -fsyntax-only -x c++ -verify=cxx,expected %s
5+
6+
#if defined __cplusplus
7+
extern "C" {
8+
#endif
9+
10+
void *memset(void *, int, __SIZE_TYPE__);
11+
void bzero(void *, __SIZE_TYPE__);
12+
void *memcpy(void *, const void *, __SIZE_TYPE__);
13+
void *memmove(void *, const void *, __SIZE_TYPE__);
14+
15+
#if defined __cplusplus
16+
}
17+
#endif
18+
19+
#define AQ __ptrauth(1,1,50)
20+
#define IQ __ptrauth(1,0,50)
21+
22+
struct PtrAuthTrivial {
23+
int f0;
24+
int * IQ f1;
25+
};
26+
27+
struct PtrAuthNonTrivial0 {
28+
int f0;
29+
int * AQ f1; // c-note 2 {{non-trivial to copy}}
30+
int f2;
31+
};
32+
33+
struct PtrAuthNonTrivial1 {
34+
int * AQ f0; // c-note 2 {{non-trivial to copy}}
35+
int f1;
36+
struct PtrAuthNonTrivial0 f2;
37+
};
38+
39+
void testPtrAuthTrivial(struct PtrAuthTrivial *d, struct PtrAuthTrivial *s) {
40+
memset(d, 0, sizeof(struct PtrAuthTrivial));
41+
memset(d, 1, sizeof(struct PtrAuthTrivial));
42+
bzero(d, sizeof(struct PtrAuthTrivial));
43+
memcpy(d, s, sizeof(struct PtrAuthTrivial));
44+
memmove(d, s, sizeof(struct PtrAuthTrivial));
45+
}
46+
47+
void testPtrAuthNonTrivial1(struct PtrAuthNonTrivial1 *d,
48+
struct PtrAuthNonTrivial1 *s) {
49+
memset(d, 0, sizeof(struct PtrAuthNonTrivial1)); // cxx-warning {{is a pointer to non-trivially copyable type 'struct PtrAuthNonTrivial1'}} // cxx-note {{explicitly cast the pointer to silence}}
50+
memset(d, 1, sizeof(struct PtrAuthNonTrivial1)); // cxx-warning {{is a pointer to non-trivially copyable type 'struct PtrAuthNonTrivial1'}} // cxx-note {{explicitly cast the pointer to silence}}
51+
bzero(d, sizeof(struct PtrAuthNonTrivial1)); // cxx-warning {{is a pointer to non-trivially copyable type 'struct PtrAuthNonTrivial1'}} // cxx-note {{explicitly cast the pointer to silence}}
52+
memcpy(d, s, sizeof(struct PtrAuthNonTrivial1));
53+
// c-warning@-1 {{that is not trivial to primitive-copy}}
54+
// cxx-warning@-2 {{is a pointer to non-trivially copyable type 'struct PtrAuthNonTrivial1'}}
55+
// expected-note@-3 {{explicitly cast the pointer to silence}}
56+
memmove(d, s, sizeof(struct PtrAuthNonTrivial1));
57+
// c-warning@-1 {{that is not trivial to primitive-copy}}
58+
// cxx-warning@-2 {{is a pointer to non-trivially copyable type 'struct PtrAuthNonTrivial1'}}
59+
// expected-note@-3 {{explicitly cast the pointer to silence}}
60+
}

0 commit comments

Comments
 (0)