Skip to content
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

[clang] Warn about memset/memcpy to NonTriviallyCopyable types #111434

Conversation

serge-sans-paille
Copy link
Collaborator

This implements a warning that's similar to what GCC does in that context: both memcpy and memset require their first and second operand to be trivially copyable, let's warn if that's not the case.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Oct 7, 2024
@llvmbot
Copy link
Member

llvmbot commented Oct 7, 2024

@llvm/pr-subscribers-pgo
@llvm/pr-subscribers-libcxx

@llvm/pr-subscribers-clang

Author: None (serge-sans-paille)

Changes

This implements a warning that's similar to what GCC does in that context: both memcpy and memset require their first and second operand to be trivially copyable, let's warn if that's not the case.


Full diff: https://github.com/llvm/llvm-project/pull/111434.diff

3 Files Affected:

  • (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+4)
  • (modified) clang/lib/Sema/SemaChecking.cpp (+24)
  • (modified) clang/test/SemaCXX/constexpr-string.cpp (+4)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 583475327c5227..d9bff4a559b3b7 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -790,6 +790,10 @@ def warn_cstruct_memaccess : Warning<
   "%1 call is a pointer to record %2 that is not trivial to "
   "%select{primitive-default-initialize|primitive-copy}3">,
   InGroup<NonTrivialMemaccess>;
+def warn_cxxstruct_memaccess : Warning<
+  "%select{destination for|source of|first operand of|second operand of}0 this "
+  "%1 call is a pointer to record %2 that is not trivially-copyable">,
+  InGroup<NonTrivialMemaccess>;
 def note_nontrivial_field : Note<
   "field is non-trivial to %select{copy|default-initialize}0">;
 def err_non_trivial_c_union_in_invalid_context : Error<
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 2bcb930acdcb57..46dda34d0ac8f3 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -8899,18 +8899,42 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call,
           << ArgIdx << FnName << PointeeTy
           << Call->getCallee()->getSourceRange());
     else if (const auto *RT = PointeeTy->getAs<RecordType>()) {
+
+      auto IsTriviallyCopyableCXXRecord = [](auto const *RT) {
+        auto const *D = RT->getDecl();
+        if (!D)
+          return true;
+        auto const *RD = dyn_cast<CXXRecordDecl>(D);
+        if (!RD)
+          return true;
+        RD = RD->getDefinition();
+        if (!RD)
+          return true;
+        return RD->isTriviallyCopyable();
+      };
+
       if ((BId == Builtin::BImemset || BId == Builtin::BIbzero) &&
           RT->getDecl()->isNonTrivialToPrimitiveDefaultInitialize()) {
         DiagRuntimeBehavior(Dest->getExprLoc(), Dest,
                             PDiag(diag::warn_cstruct_memaccess)
                                 << ArgIdx << FnName << PointeeTy << 0);
         SearchNonTrivialToInitializeField::diag(PointeeTy, Dest, *this);
+      } else if ((BId == Builtin::BImemset || BId == Builtin::BIbzero) &&
+                 !IsTriviallyCopyableCXXRecord(RT)) {
+        DiagRuntimeBehavior(Dest->getExprLoc(), Dest,
+                            PDiag(diag::warn_cxxstruct_memaccess)
+                                << ArgIdx << FnName << PointeeTy);
       } else if ((BId == Builtin::BImemcpy || BId == Builtin::BImemmove) &&
                  RT->getDecl()->isNonTrivialToPrimitiveCopy()) {
         DiagRuntimeBehavior(Dest->getExprLoc(), Dest,
                             PDiag(diag::warn_cstruct_memaccess)
                                 << ArgIdx << FnName << PointeeTy << 1);
         SearchNonTrivialToCopyField::diag(PointeeTy, Dest, *this);
+      } else if ((BId == Builtin::BImemcpy || BId == Builtin::BImemmove) &&
+                 !IsTriviallyCopyableCXXRecord(RT)) {
+        DiagRuntimeBehavior(Dest->getExprLoc(), Dest,
+                            PDiag(diag::warn_cxxstruct_memaccess)
+                                << ArgIdx << FnName << PointeeTy);
       } else {
         continue;
       }
diff --git a/clang/test/SemaCXX/constexpr-string.cpp b/clang/test/SemaCXX/constexpr-string.cpp
index c456740ef7551f..26e2e138ef34e0 100644
--- a/clang/test/SemaCXX/constexpr-string.cpp
+++ b/clang/test/SemaCXX/constexpr-string.cpp
@@ -603,12 +603,16 @@ namespace MemcpyEtc {
   };
   constexpr bool test_nontrivial_memcpy() { // expected-error {{never produces a constant}}
     NonTrivial arr[3] = {};
+    // expected-warning@+2 {{source of this '__builtin_memcpy' call is a pointer to record 'NonTrivial' that is not trivially-copyable}}
+    // expected-note@+1 {{explicitly cast the pointer to silence this warning}}
     __builtin_memcpy(arr, arr + 1, sizeof(NonTrivial)); // expected-note 2{{non-trivially-copyable}}
     return true;
   }
   static_assert(test_nontrivial_memcpy()); // expected-error {{constant}} expected-note {{in call}}
   constexpr bool test_nontrivial_memmove() { // expected-error {{never produces a constant}}
     NonTrivial arr[3] = {};
+    // expected-warning@+2 {{source of this '__builtin_memcpy' call is a pointer to record 'NonTrivial' that is not trivially-copyable}}
+    // expected-note@+1 {{explicitly cast the pointer to silence this warning}}
     __builtin_memcpy(arr, arr + 1, sizeof(NonTrivial)); // expected-note 2{{non-trivially-copyable}}
     return true;
   }

@serge-sans-paille
Copy link
Collaborator Author

This change is triggering warnings at several point in the code base, I'll fix that too.

@serge-sans-paille serge-sans-paille requested a review from a team as a code owner October 8, 2024 12:47
@llvmbot llvmbot added compiler-rt libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. PGO Profile Guided Optimizations llvm:adt labels Oct 8, 2024
@serge-sans-paille
Copy link
Collaborator Author

  • patches to make sure llvm, libc++ and compiler-rt don't trigger that extra warning

@serge-sans-paille serge-sans-paille force-pushed the feature/trivially-copyable-memcpy branch from 3f44807 to bc3b844 Compare October 8, 2024 16:30
@serge-sans-paille
Copy link
Collaborator Author

cc @ldionne got the compiler-rt part.

@serge-sans-paille
Copy link
Collaborator Author

Some of the libcxx builds fail, they are marked as "build stopped: interrupted by user."... I can't find the origin

@@ -102,7 +102,7 @@ struct __aliasing_iterator_wrapper {

_LIBCPP_HIDE_FROM_ABI _Alias operator*() const _NOEXCEPT {
_Alias __val;
__builtin_memcpy(&__val, std::__to_address(__base_), sizeof(value_type));
__builtin_memcpy(&__val, reinterpret_cast<void*>(std::__to_address(__base_)), sizeof(value_type));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO this is a false-positive. This inspects the non-trivial object and implicitly starts the lifetime of _Alias, which is perfectly defined behaviour.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cast should probably be static_cast<void*> also

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack for the false positive. I'll move that to a static_cast which should silent the warning.

@carlosgalvezp
Copy link
Contributor

carlosgalvezp commented Oct 9, 2024

Please note: GCC is more strict; for std::memset, it requires the type to be trivial, not just trivially copyable:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107361

I want to remember it was also more strict for std::memcpy, but I haven't been able to reproduce it.

I haven't looked at the patch in detail but for consistency with GCC it should also support suppressing the warning by explictly casting the pointers to void* (maybe it's already in place).

@serge-sans-paille serge-sans-paille force-pushed the feature/trivially-copyable-memcpy branch from bc3b844 to c9a013f Compare October 9, 2024 12:06
@serge-sans-paille
Copy link
Collaborator Author

Please note: GCC is more strict; for std::memset, it requires the type to be trivial, not just trivially copyable:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107361

ACK. Not a standard requirement though, is it?

I want to remember it was also more strict for std::memcpy, but I haven't been able to reproduce it.

I haven't looked at the patch in detail but for consistency with GCC it should also support suppressing the warning by explictly casting the pointers to void* (maybe it's already in place).

Yeah, that's part of current logic clang in clang too (thus the various cast added in this PR)

@carlosgalvezp
Copy link
Contributor

ACK. Not a standard requirement though, is it?

Correct, it's only UB on non-trivially-copyable. My point was more about if we want to be consistent with GCC or not. I don't have any strong opinion on that.

@serge-sans-paille serge-sans-paille force-pushed the feature/trivially-copyable-memcpy branch from c9a013f to 92f14e6 Compare October 9, 2024 13:12
@philnik777
Copy link
Contributor

ACK. Not a standard requirement though, is it?

Correct, it's only UB on non-trivially-copyable. My point was more about if we want to be consistent with GCC or not. I don't have any strong opinion on that.

I can see an argument that a user probably is doing something wrong if they memset a non-trivial type, especially since compilers are perfectly capable of optimizing zero-initializing loops into memsets. For memcpy/memmove we should definitely only diagnose non-trivially copyable cases, since it's quite a common optimization to memcpy trivially copyable objects.

Copy link
Collaborator

@AaronBallman AaronBallman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for this! It's missing a lot of test coverage that should be added to clang/test/SemaCXX and you should also add a release note to clang/docs/ReleaseNotes.rst so users know about the new diagnostic.

Comment on lines 794 to 795
"%select{destination for|source of|first operand of|second operand of}0 this "
"%1 call is a pointer to record %2 that is not trivially-copyable">,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"%select{destination for|source of|first operand of|second operand of}0 this "
"%1 call is a pointer to record %2 that is not trivially-copyable">,
"%select{destination for|source of|first operand of|second operand of}0 call to "
"%1 is a pointer to non-trivially copyable type %2">,

Slight rewording

@@ -8899,18 +8899,42 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call,
<< ArgIdx << FnName << PointeeTy
<< Call->getCallee()->getSourceRange());
else if (const auto *RT = PointeeTy->getAs<RecordType>()) {

auto IsTriviallyCopyableCXXRecord = [](auto const *RT) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
auto IsTriviallyCopyableCXXRecord = [](auto const *RT) {
auto IsTriviallyCopyableCXXRecord = [](const RecordType *RT) {

Do not use auto when there's only one type this can be called with (I just spent a lot of time writing comments that I had to delete because this can only accept a RecordType).

Actually, I don't think we even need the lambda. You could precalculate this as a local variable:

bool IsTriviallyCopyableCXXRecord = false;
if (const auto *RD = RT->getAsCXXRecordDecl())
  IsTriviallyCopyableCXXRecord = RD->isTriviallyCopyable();

should suffice. (The call should return false if the record has no definition because that's an incomplete type but that's a good test case to ensure we have.)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, @erichkeane just reminded me that we have QualType::isTriviallyCopyableType() -- that's an even better interface to use IMO.

@@ -8899,18 +8899,42 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call,
<< ArgIdx << FnName << PointeeTy
<< Call->getCallee()->getSourceRange());
else if (const auto *RT = PointeeTy->getAs<RecordType>()) {

auto IsTriviallyCopyableCXXRecord = [](auto const *RT) {
auto const *D = RT->getDecl();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
auto const *D = RT->getDecl();
const Decl *D = RT->getDecl();

Please only use auto when the type is spelled out in the initialization. Also, we use const Type and not Type const as the prevailing style, so you should stick with that.

auto const *D = RT->getDecl();
if (!D)
return true;
auto const *RD = dyn_cast<CXXRecordDecl>(D);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
auto const *RD = dyn_cast<CXXRecordDecl>(D);
const auto *RD = dyn_cast<CXXRecordDecl>(D);

@@ -102,7 +102,7 @@ struct __aliasing_iterator_wrapper {

_LIBCPP_HIDE_FROM_ABI _Alias operator*() const _NOEXCEPT {
_Alias __val;
__builtin_memcpy(&__val, std::__to_address(__base_), sizeof(value_type));
__builtin_memcpy(&__val, static_cast<const void*>(std::__to_address(__base_)), sizeof(value_type));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to make it visible again: IMO this is a false-positive, since this is inspecting a non-trivial type, which is perfectly defined behaviour.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's one thing I don't understand: my understanding is that passing a pointer to a non-trivially copyable type to memcpy first or second argument is UB and _BaseIter maybe a non-trivially copyable type, so what happens then?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this seems like it's plausibly UB. There's an assertion that __val is trivial, but I'm not seeing any such assertion for __base_; does something else ensure that _BaseIter is trivial?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@serge-sans-paille Sounds like this requires some extra investigation, which may be holding your patch for longer time than wanted. Would it make more sense to remove all the "silence warning" changes from this patch and focus only on getting the warning in?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be happy too, but that would break validation as libcxx has bots running with -Werror.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the part that gives inspecting an object well-defined behaviour is http://eel.is/c++draft/basic.types#general-4. I'm not 100% sure, though. There might be something more explicit (I was hoping someone here knows). https://eel.is/c++draft/cstring.syn#3 also states that "[The memcpy and memmove] functions implicitly create objects ([intro.object]) in the destination region of storage immediately prior to copying the sequence of characters to the destination", which sounds to me a lot like it's allowed to copy the bytes from anywhere.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we then limit this PR to detecting non-trivially copyable types in the dst argument only? Like GCC does.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so. If this is indeed UB we can still add the warnings later. It's always harder to get users to re-enable a warning than to introduce it in the first place. But let's see what @AaronBallman's thoughts on this are.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the goal is to inspect the bytes of the source object, then it's not UB because that inspection would be happening on a byte-by-byte level and not on the value representation level. So the memcpy itself is not really UB because it is only touching on a byte-by-byte level. Where I think the UB comes in is when someone attempts to use the _Alias object constructed by the call to memcpy because that object may not have a valid representation.

https://eel.is/c++draft/basic.indet#1.sentence-3
https://eel.is/c++draft/conv.lval#3.4

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AaronBallman IIUC you're saying that it would be UB if some padding bytes ended up in the value representation of a different type, which could indeed arguably be UB. We can't have this scenario here though, since we only instantiate the type with integers as the _Alias and make sure that the source objects have a unique object representation via __is_trivially_equality_comparable.

I think it would be interesting to diagnose such cases, but that seems quite complicated, since we'd have to check whether any padding bytes end up in non-padding bytes. (though definitely not impossible)

@serge-sans-paille serge-sans-paille force-pushed the feature/trivially-copyable-memcpy branch 3 times, most recently from 67de33b to 31be3da Compare October 11, 2024 21:09
@serge-sans-paille
Copy link
Collaborator Author

@AaronBallman doc, tests and style updated. Thanks for the review!

@serge-sans-paille
Copy link
Collaborator Author

@AaronBallman soft and gentle ping :-)

@serge-sans-paille serge-sans-paille force-pushed the feature/trivially-copyable-memcpy branch 2 times, most recently from 3d18356 to c00369f Compare October 24, 2024 19:17
@serge-sans-paille serge-sans-paille force-pushed the feature/trivially-copyable-memcpy branch from 1a951ae to 51adfc5 Compare October 28, 2024 16:52
Copy link
Collaborator

@AaronBallman AaronBallman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@nathanchance
Copy link
Member

Is it expected that this warns for C code? I only see cxx in this change but I see a new instance of this warning in my Linux kernel builds:

drivers/net/ethernet/netronome/nfp/nfdk/rings.c:60:18: warning: first argument in call to '__builtin_memset' is a pointer to non-trivially copyable type 'struct nfp_nfd3_tx_desc' [-Wnontrivial-memaccess]
   60 |         memset(tx_ring->txds, 0, tx_ring->size);
      |                         ^
drivers/net/ethernet/netronome/nfp/nfdk/rings.c:60:18: note: explicitly cast the pointer to silence this warning
   60 |         memset(tx_ring->txds, 0, tx_ring->size);
      |                         ^
      |                (void*)
include/linux/fortify-string.h:512:46: note: expanded from macro 'memset'
  512 | #define memset(p, c, s) __fortify_memset_chk(p, c, s,                   \
      |                                              ^
include/linux/fortify-string.h:504:22: note: expanded from macro '__fortify_memset_chk'
  504 |         __underlying_memset(p, c, __fortify_size);                      \
      |                             ^
1 warning generated.

https://elixir.bootlin.com/linux/v6.11.5/source/drivers/net/ethernet/netronome/nfp/nfdk/rings.c#L60

@AaronBallman
Copy link
Collaborator

Is it expected that this warns for C code? I only see cxx in this change but I see a new instance of this warning in my Linux kernel builds:

drivers/net/ethernet/netronome/nfp/nfdk/rings.c:60:18: warning: first argument in call to '__builtin_memset' is a pointer to non-trivially copyable type 'struct nfp_nfd3_tx_desc' [-Wnontrivial-memaccess]
   60 |         memset(tx_ring->txds, 0, tx_ring->size);
      |                         ^
drivers/net/ethernet/netronome/nfp/nfdk/rings.c:60:18: note: explicitly cast the pointer to silence this warning
   60 |         memset(tx_ring->txds, 0, tx_ring->size);
      |                         ^
      |                (void*)
include/linux/fortify-string.h:512:46: note: expanded from macro 'memset'
  512 | #define memset(p, c, s) __fortify_memset_chk(p, c, s,                   \
      |                                              ^
include/linux/fortify-string.h:504:22: note: expanded from macro '__fortify_memset_chk'
  504 |         __underlying_memset(p, c, __fortify_size);                      \
      |                             ^
1 warning generated.

https://elixir.bootlin.com/linux/v6.11.5/source/drivers/net/ethernet/netronome/nfp/nfdk/rings.c#L60

I would not expect this diagnostic in C code, that seems like a bug to me. @serge-sans-paille can you take care of that?

@serge-sans-paille
Copy link
Collaborator Author

@nathanchance could you share your preprocessed source so that I can get a reproducer? Thanks!

dschuff added a commit to emscripten-core/emscripten that referenced this pull request Oct 29, 2024
@nathanchance
Copy link
Member

@nathanchance could you share your preprocessed source so that I can get a reproducer? Thanks!

Sure thing!

$ clang --target=x86_64-linux-gnu -fcf-protection -fsyntax-only -Wno-{address-of-packed-member,constant-logical-operand,gnu,unused-value} -Wnontrivial-memaccess rings.i
rings.i:95832:214: warning: first argument in call to '__builtin_memset' is a pointer to non-trivially copyable type 'struct nfp_nfd3_tx_desc' [-Wnontrivial-memaccess]
 95832 |  ({ size_t __fortify_size = (size_t)(tx_ring->size); fortify_memset_chk(__fortify_size, __builtin_dynamic_object_size(tx_ring->txds, 0), __builtin_dynamic_object_size(tx_ring->txds, 1)), __builtin_memset(tx_ring->txds, 0, __fortify_size); });
       |                                                                                                                                                                                                                      ^
rings.i:95832:214: note: explicitly cast the pointer to silence this warning
 95832 |  ({ size_t __fortify_size = (size_t)(tx_ring->size); fortify_memset_chk(__fortify_size, __builtin_dynamic_object_size(tx_ring->txds, 0), __builtin_dynamic_object_size(tx_ring->txds, 1)), __builtin_memset(tx_ring->txds, 0, __fortify_size); });
       |                                                                                                                                                                                                                      ^
       |                                                                                                                                                                                                             (void*)
1 warning generated.

rings.i.txt

@serge-sans-paille
Copy link
Collaborator Author

Thanks! I can reproduce. The easy fix is to deactivate the warning for c source but I'd like to udnerstand why it considers that structure as non trivially copyable first :-)

@erichkeane
Copy link
Collaborator

Thanks! I can reproduce. The easy fix is to deactivate the warning for c source but I'd like to udnerstand why it considers that structure as non trivially copyable first :-)

Yeah, agreed completely. No C structure, afaik, should ever be non-trivially copyable.

@serge-sans-paille
Copy link
Collaborator Author

reproducer:

struct nfp_nfd3_tx_desc;

void
nfp_nfdk_tx_ring_reset(struct nfp_nfd3_tx_desc *txds)
{
 __builtin_memset(txds, 0, 8);
}

so we basically have an incomplete type, and we shouldn't warn in that case. I'll submit a patch.

@serge-sans-paille
Copy link
Collaborator Author

#114095 should do the trick

@zmodem
Copy link
Collaborator

zmodem commented Oct 31, 2024

Can we get a separate flag for this to make it easier to roll out?

NoumanAmir657 pushed a commit to NoumanAmir657/llvm-project that referenced this pull request Nov 4, 2024
…111434)

This implements a warning that's similar to what GCC does in that
context: both memcpy and memset require their first and second operand
to be trivially copyable, let's warn if that's not the case.
NoumanAmir657 pushed a commit to NoumanAmir657/llvm-project that referenced this pull request Nov 4, 2024
NoumanAmir657 pushed a commit to NoumanAmir657/llvm-project that referenced this pull request Nov 4, 2024
@drmdanowar
Copy link

This is the most important part

@AaronBallman
Copy link
Collaborator

CC @serge-sans-paille on the request for a separate flag

@serge-sans-paille
Copy link
Collaborator Author

Would you be ok with a flag, say -Wnontrivial-memcpy¸(any suggestion on another name ?) implied by -Wall but that we could disable with -Wno-nontrivial-memcpy ?

@carlosgalvezp
Copy link
Contributor

for this to make it easier to roll out?

Note that recently Clang introduced a mechanism for file-level suppression of warnings, for easier rollout of warnings:
https://clang.llvm.org/docs/UsersManual.html#controlling-diagnostics-via-suppression-mappings

Would that serve the same purpose?

@zmodem
Copy link
Collaborator

zmodem commented Nov 22, 2024

Note that recently Clang introduced a mechanism for file-level suppression of warnings, for easier rollout of warnings:
https://clang.llvm.org/docs/UsersManual.html#controlling-diagnostics-via-suppression-mappings
Would that serve the same purpose?

Well, that allows us to be gradual over a set of files.

However, it doesn't help adapting the set of warnings gradually. In this case, we already have -Wnontrivial-memaccess enabled. We don't want to have to disable it due to it gaining new warnings.

I don't know if it's written down anywhere, but it's been Clang's practice to add new flags for new warnings. The system with groups and subgroups of warnings makes that work nicely.

Would you be ok with a flag, say -Wnontrivial-memcpy¸(any suggestion on another name ?) implied by -Wall but that we could disable with -Wno-nontrivial-memcpy ?

The new flag should still be implied by -Wnontrivial-memaccess (which I assume is implied by -Wall).

I like -Wnontrivial-memcpy. I suppose it also applies to memove, memset, etc. but maybe -Wnontrivial-memcpy is still the best name? (or -Wnontrivial-mem-libcall?)

@serge-sans-paille
Copy link
Collaborator Author

-Wnontrivial-memcall to match -Wnontricial-memaccess ?

@zmodem
Copy link
Collaborator

zmodem commented Nov 22, 2024

-Wnontrivial-memcall to match -Wnontricial-memaccess ?

sgtm :)

serge-sans-paille added a commit to serge-sans-paille/llvm-project that referenced this pull request Nov 22, 2024
…s to its own flag

Namely -Wnontrivial-memcall, implied by -Wnontricial-memaccess

This is a followup to llvm#111434
serge-sans-paille added a commit that referenced this pull request Nov 28, 2024
#117387)

…s to its own flag

Namely -Wnontrivial-memcall, implied by -Wnontrivial-memaccess

This is a followup to #111434
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category compiler-rt libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. llvm:adt PGO Profile Guided Optimizations
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants