Consider the following snippet: #include <algorithm> int main() { volatile int *v1[100]; volatile int *v2[100]; std::copy(v1, v1 + 100, v2); } 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 problem is that this is true: static_assert(std::is_trivially_copy_assignable<volatile int>::value, "" );
"volatile int*" is a pointer to a volatile type, but it isn't itself a volatile type. I think you meant the following? #include <algorithm> int main() { volatile int v1[100]; volatile int v2[100]; std::copy(v1, v1 + 100, v2); } Gives: error: cannot initialize a parameter of type 'void *' with an lvalue of type 'volatile int *'
(In reply to comment #2) > "volatile int*" is a pointer to a volatile type, but it isn't itself a > volatile type. I think you meant the following? > > > #include <algorithm> > > int main() { > volatile int v1[100]; > volatile int v2[100]; > > std::copy(v1, v1 + 100, v2); > } > > 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.
(In reply to comment #3) > 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).
(In reply to comment #4) > (In reply to comment #3) > > 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. https://godbolt.org/g/tC0y7b In file included from /tmp/gcc-explorer-compiler116613-82-1qhm7jl/example.cpp:1: /opt/clang+llvm-3.8.0-x86_64-linux-gnu-ubuntu-14.04/bin/../include/c++/v1/algorithm:1748:24: error: cannot initialize a parameter of type 'void *' with an lvalue of type 'volatile int *' _VSTD::memmove(__result, __first, __n * sizeof(_Up)); ^~~~~~~~ /opt/clang+llvm-3.8.0-x86_64-linux-gnu-ubuntu-14.04/bin/../include/c++/v1/algorithm:1757:19: note: in instantiation of function template specialization 'std::__1::__copy<volatile int, volatile int>' requested here return _VSTD::__copy(__unwrap_iter(__first), __unwrap_iter(__last), __unwrap_iter(__result)); ^ 7 : note: in instantiation of function template specialization 'std::__1::copy<volatile int *, volatile int *>' requested here std::copy(v1, v1 + 100, v2); ^ /usr/include/string.h:50:29: note: passing argument to parameter '__dest' here extern void *memmove (void *__dest, const void *__src, size_t __n) ^ 1 error generated. Compilation failed
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). =(
> Perhaps we need a separate trait to determine if copying an object is really equivalent to memcpy. 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 45103 has been marked as a duplicate of this bug. ***