https://github.com/serge-sans-paille updated https://github.com/llvm/llvm-project/pull/114095
>From e15fcb76e2ed65a5678dd5da68137c31af983d4e Mon Sep 17 00:00:00 2001 From: serge-sans-paille <sguel...@mozilla.com> Date: Tue, 29 Oct 2024 18:31:13 +0100 Subject: [PATCH] [clang] Fix 71315698c9 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. --- clang/lib/Sema/SemaChecking.cpp | 9 ++++++--- clang/test/SemaCXX/constexpr-string.cpp | 2 -- clang/test/SemaCXX/warn-memaccess.cpp | 25 +++++++++++++++++++++---- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 3308b898a5b68f..511631448af195 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -8900,7 +8900,10 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call, << Call->getCallee()->getSourceRange()); else if (const auto *RT = PointeeTy->getAs<RecordType>()) { - bool IsTriviallyCopyableCXXRecord = + // FIXME: Do not consider incomplete type even though they may be + // completed later. + bool MayBeTriviallyCopyableCXXRecord = + RT->isIncompleteType() || RT->desugar().isTriviallyCopyableType(Context); if ((BId == Builtin::BImemset || BId == Builtin::BIbzero) && @@ -8910,7 +8913,7 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call, << ArgIdx << FnName << PointeeTy << 0); SearchNonTrivialToInitializeField::diag(PointeeTy, Dest, *this); } else if ((BId == Builtin::BImemset || BId == Builtin::BIbzero) && - !IsTriviallyCopyableCXXRecord && ArgIdx == 0) { + !MayBeTriviallyCopyableCXXRecord && ArgIdx == 0) { // FIXME: Limiting this warning to dest argument until we decide // whether it's valid for source argument too. DiagRuntimeBehavior(Dest->getExprLoc(), Dest, @@ -8923,7 +8926,7 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call, << ArgIdx << FnName << PointeeTy << 1); SearchNonTrivialToCopyField::diag(PointeeTy, Dest, *this); } else if ((BId == Builtin::BImemcpy || BId == Builtin::BImemmove) && - !IsTriviallyCopyableCXXRecord && ArgIdx == 0) { + !MayBeTriviallyCopyableCXXRecord && 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/SemaCXX/constexpr-string.cpp b/clang/test/SemaCXX/constexpr-string.cpp index 5448365489a514..c456740ef7551f 100644 --- a/clang/test/SemaCXX/constexpr-string.cpp +++ b/clang/test/SemaCXX/constexpr-string.cpp @@ -670,8 +670,6 @@ namespace MemcpyEtc { constexpr bool test_address_of_incomplete_struct_type() { // expected-error {{never produces a constant}} struct Incomplete; extern Incomplete x, y; - // expected-warning@+2 {{first argument in call to '__builtin_memcpy' is a pointer to non-trivially copyable type 'Incomplete'}} - // expected-note@+1 {{explicitly cast the pointer to silence this warning}} __builtin_memcpy(&x, &x, 4); // expected-note@-1 2{{cannot constant evaluate 'memcpy' between objects of incomplete type 'Incomplete'}} return true; diff --git a/clang/test/SemaCXX/warn-memaccess.cpp b/clang/test/SemaCXX/warn-memaccess.cpp index b4b7f6a6905b23..070b44891a91aa 100644 --- a/clang/test/SemaCXX/warn-memaccess.cpp +++ b/clang/test/SemaCXX/warn-memaccess.cpp @@ -7,12 +7,17 @@ extern "C" void *memcpy(void *s1, const void *s2, unsigned n); class TriviallyCopyable {}; class NonTriviallyCopyable { NonTriviallyCopyable(const NonTriviallyCopyable&);}; +struct Incomplete; void test_bzero(TriviallyCopyable* tc, - NonTriviallyCopyable *ntc) { + NonTriviallyCopyable *ntc, + Incomplete* i) { // OK bzero(tc, sizeof(*tc)); + // OK + bzero(i, 10); + // expected-warning@+2{{first argument in call to 'bzero' is a pointer to non-trivially copyable type 'NonTriviallyCopyable'}} // expected-note@+1{{explicitly cast the pointer to silence this warning}} bzero(ntc, sizeof(*ntc)); @@ -22,10 +27,14 @@ void test_bzero(TriviallyCopyable* tc, } void test_memset(TriviallyCopyable* tc, - NonTriviallyCopyable *ntc) { + NonTriviallyCopyable *ntc, + Incomplete* i) { // OK memset(tc, 0, sizeof(*tc)); + // OK + memset(i, 0, 10); + // expected-warning@+2{{first argument in call to 'memset' is a pointer to non-trivially copyable type 'NonTriviallyCopyable'}} // expected-note@+1{{explicitly cast the pointer to silence this warning}} memset(ntc, 0, sizeof(*ntc)); @@ -36,10 +45,14 @@ void test_memset(TriviallyCopyable* tc, void test_memcpy(TriviallyCopyable* tc0, TriviallyCopyable* tc1, - NonTriviallyCopyable *ntc0, NonTriviallyCopyable *ntc1) { + NonTriviallyCopyable *ntc0, NonTriviallyCopyable *ntc1, + Incomplete *i0, Incomplete *i1) { // OK memcpy(tc0, tc1, sizeof(*tc0)); + // OK + memcpy(i0, i1, 10); + // expected-warning@+2{{first argument in call to 'memcpy' is a pointer to non-trivially copyable type 'NonTriviallyCopyable'}} // expected-note@+1{{explicitly cast the pointer to silence this warning}} memcpy(ntc0, ntc1, sizeof(*ntc0)); @@ -52,10 +65,14 @@ void test_memcpy(TriviallyCopyable* tc0, TriviallyCopyable* tc1, } void test_memmove(TriviallyCopyable* tc0, TriviallyCopyable* tc1, - NonTriviallyCopyable *ntc0, NonTriviallyCopyable *ntc1) { + NonTriviallyCopyable *ntc0, NonTriviallyCopyable *ntc1, + Incomplete *i0, Incomplete *i1) { // OK memmove(tc0, tc1, sizeof(*tc0)); + // OK + memmove(i0, i1, 10); + // expected-warning@+2{{first argument in call to 'memmove' is a pointer to non-trivially copyable type 'NonTriviallyCopyable'}} // expected-note@+1{{explicitly cast the pointer to silence this warning}} memmove(ntc0, ntc1, sizeof(*ntc0)); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits