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
std::copy() calls memmove on nontrivially-copyable type #28901
Comments
assigned to @mclow |
The problem is that this is true: |
"volatile int*" is a pointer to a volatile type, but it isn't itself a volatile type. I think you meant the following?
Gives: error: cannot initialize a parameter of type 'void *' with an lvalue of type 'volatile int *' |
No, I meant 'volatile int *' -- a pointer to volatile ints. Those cannot be copied via memcpy() or memmove() under as-if because volatile int is not a trivially copyable type. |
Your original testcase passes a volatile int** to std::copy... which can be copied with memcpy (there aren't any volatile objects involved). |
Ugh, my brain some days. :-( You're absolutely right, this does pass a volatile int **. However, when I correct my test case to not be wrong, I still get misbehavior. In file included from /tmp/gcc-explorer-compiler116613-82-1qhm7jl/example.cpp:1: |
I get the same behavior (compiler error) on gcc, but not on MSVC. |
(Responding to Marshall's question from IRC) Per http://wg21.link/cwg2094, clang is correct to consider volatile types and types with volatile subobjects as being trivially copyable. Perhaps we need a separate trait to determine if copying an object is really equivalent to memcpy (trivially copyable and has no volatile subobjects). =( |
If we do that, then we can get rid of "is_trivially_copyable/is_trivially_copy_constructible/etc", because that's pretty much all it they're used for. |
*** Bug llvm/llvm-bugzilla-archive#45103 has been marked as a duplicate of this bug. *** |
mentioned in issue llvm/llvm-bugzilla-archive#45103 |
This should be solved by https://reviews.llvm.org/D139235. Per http://eel.is/c++draft/basic.types.general#3, we are allowed to I think any change in behavior here would require the core wording to change. FWIW if it's unsafe to perform this optimization for some types, I think we'll need a way for the compiler to tell us that, because we can't start pessimizing every legitimate trivially copyable Please let me know if you think I'm wrong or if you think I'm making a bad judgement call here. |
I agree with this interpretation but find it unfortunate (assuming I understand it properly, of course). As I read it, The scenario is: you have a It's not the most common use case, to be sure, but it'd be nice if what we provided was reliably useful. But I agree with you, it'd require a change to standards wording to get that. |
@AaronBallman Great, sounds like we're on the same page here. Just curious -- for the One more question -- if I'm reading the conversation right, it seems the title of the issue should be updated to something like |
Closing this, since the original issue is fixed. Fixing volatile semantics seems out of scope. |
Extended Description
Consider the following snippet:
This results in a call to memmove() rather than copying individual volatile elements of the array (https://godbolt.org/g/b0fv3R). This should be handled a bit more kindly, since volatile-qualified types are not trivially-copyable types ([basic.types]p9 states in part: "Cv-unqualified scalar types, trivially copyable class types (Clause 9), arrays of such types, and nonvolatile const-qualified versions of these types (3.9.3) are collectively called trivially copyable types.").
The text was updated successfully, but these errors were encountered: