Skip to content

Commit e15fcb7

Browse files
[clang] Fix 7131569 in presence of incomplete types
Incomplete types are not considered trivially copyable by clang but we don't want to warn about invalid argument for memcpy / memset in that case because we cannot prove they are not Trivially Copyable.
1 parent a9c417c commit e15fcb7

File tree

3 files changed

+27
-9
lines changed

3 files changed

+27
-9
lines changed

clang/lib/Sema/SemaChecking.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8900,7 +8900,10 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call,
89008900
<< Call->getCallee()->getSourceRange());
89018901
else if (const auto *RT = PointeeTy->getAs<RecordType>()) {
89028902

8903-
bool IsTriviallyCopyableCXXRecord =
8903+
// FIXME: Do not consider incomplete type even though they may be
8904+
// completed later.
8905+
bool MayBeTriviallyCopyableCXXRecord =
8906+
RT->isIncompleteType() ||
89048907
RT->desugar().isTriviallyCopyableType(Context);
89058908

89068909
if ((BId == Builtin::BImemset || BId == Builtin::BIbzero) &&
@@ -8910,7 +8913,7 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call,
89108913
<< ArgIdx << FnName << PointeeTy << 0);
89118914
SearchNonTrivialToInitializeField::diag(PointeeTy, Dest, *this);
89128915
} else if ((BId == Builtin::BImemset || BId == Builtin::BIbzero) &&
8913-
!IsTriviallyCopyableCXXRecord && ArgIdx == 0) {
8916+
!MayBeTriviallyCopyableCXXRecord && ArgIdx == 0) {
89148917
// FIXME: Limiting this warning to dest argument until we decide
89158918
// whether it's valid for source argument too.
89168919
DiagRuntimeBehavior(Dest->getExprLoc(), Dest,
@@ -8923,7 +8926,7 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call,
89238926
<< ArgIdx << FnName << PointeeTy << 1);
89248927
SearchNonTrivialToCopyField::diag(PointeeTy, Dest, *this);
89258928
} else if ((BId == Builtin::BImemcpy || BId == Builtin::BImemmove) &&
8926-
!IsTriviallyCopyableCXXRecord && ArgIdx == 0) {
8929+
!MayBeTriviallyCopyableCXXRecord && ArgIdx == 0) {
89278930
// FIXME: Limiting this warning to dest argument until we decide
89288931
// whether it's valid for source argument too.
89298932
DiagRuntimeBehavior(Dest->getExprLoc(), Dest,

clang/test/SemaCXX/constexpr-string.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -670,8 +670,6 @@ namespace MemcpyEtc {
670670
constexpr bool test_address_of_incomplete_struct_type() { // expected-error {{never produces a constant}}
671671
struct Incomplete;
672672
extern Incomplete x, y;
673-
// expected-warning@+2 {{first argument in call to '__builtin_memcpy' is a pointer to non-trivially copyable type 'Incomplete'}}
674-
// expected-note@+1 {{explicitly cast the pointer to silence this warning}}
675673
__builtin_memcpy(&x, &x, 4);
676674
// expected-note@-1 2{{cannot constant evaluate 'memcpy' between objects of incomplete type 'Incomplete'}}
677675
return true;

clang/test/SemaCXX/warn-memaccess.cpp

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,17 @@ extern "C" void *memcpy(void *s1, const void *s2, unsigned n);
77

88
class TriviallyCopyable {};
99
class NonTriviallyCopyable { NonTriviallyCopyable(const NonTriviallyCopyable&);};
10+
struct Incomplete;
1011

1112
void test_bzero(TriviallyCopyable* tc,
12-
NonTriviallyCopyable *ntc) {
13+
NonTriviallyCopyable *ntc,
14+
Incomplete* i) {
1315
// OK
1416
bzero(tc, sizeof(*tc));
1517

18+
// OK
19+
bzero(i, 10);
20+
1621
// expected-warning@+2{{first argument in call to 'bzero' is a pointer to non-trivially copyable type 'NonTriviallyCopyable'}}
1722
// expected-note@+1{{explicitly cast the pointer to silence this warning}}
1823
bzero(ntc, sizeof(*ntc));
@@ -22,10 +27,14 @@ void test_bzero(TriviallyCopyable* tc,
2227
}
2328

2429
void test_memset(TriviallyCopyable* tc,
25-
NonTriviallyCopyable *ntc) {
30+
NonTriviallyCopyable *ntc,
31+
Incomplete* i) {
2632
// OK
2733
memset(tc, 0, sizeof(*tc));
2834

35+
// OK
36+
memset(i, 0, 10);
37+
2938
// expected-warning@+2{{first argument in call to 'memset' is a pointer to non-trivially copyable type 'NonTriviallyCopyable'}}
3039
// expected-note@+1{{explicitly cast the pointer to silence this warning}}
3140
memset(ntc, 0, sizeof(*ntc));
@@ -36,10 +45,14 @@ void test_memset(TriviallyCopyable* tc,
3645

3746

3847
void test_memcpy(TriviallyCopyable* tc0, TriviallyCopyable* tc1,
39-
NonTriviallyCopyable *ntc0, NonTriviallyCopyable *ntc1) {
48+
NonTriviallyCopyable *ntc0, NonTriviallyCopyable *ntc1,
49+
Incomplete *i0, Incomplete *i1) {
4050
// OK
4151
memcpy(tc0, tc1, sizeof(*tc0));
4252

53+
// OK
54+
memcpy(i0, i1, 10);
55+
4356
// expected-warning@+2{{first argument in call to 'memcpy' is a pointer to non-trivially copyable type 'NonTriviallyCopyable'}}
4457
// expected-note@+1{{explicitly cast the pointer to silence this warning}}
4558
memcpy(ntc0, ntc1, sizeof(*ntc0));
@@ -52,10 +65,14 @@ void test_memcpy(TriviallyCopyable* tc0, TriviallyCopyable* tc1,
5265
}
5366

5467
void test_memmove(TriviallyCopyable* tc0, TriviallyCopyable* tc1,
55-
NonTriviallyCopyable *ntc0, NonTriviallyCopyable *ntc1) {
68+
NonTriviallyCopyable *ntc0, NonTriviallyCopyable *ntc1,
69+
Incomplete *i0, Incomplete *i1) {
5670
// OK
5771
memmove(tc0, tc1, sizeof(*tc0));
5872

73+
// OK
74+
memmove(i0, i1, 10);
75+
5976
// expected-warning@+2{{first argument in call to 'memmove' is a pointer to non-trivially copyable type 'NonTriviallyCopyable'}}
6077
// expected-note@+1{{explicitly cast the pointer to silence this warning}}
6178
memmove(ntc0, ntc1, sizeof(*ntc0));

0 commit comments

Comments
 (0)