Bug 95153

Summary: Arrays of 'const void *' should not be copyable in C++20
Product: gcc Reporter: Alisdair Meredith <alisdairm>
Component: c++Assignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED INVALID    
Severity: normal CC: barry.revzin, daniel.kruegler, rs2740, webrown.cpp
Priority: P3    
Version: 10.1.0   
Target Milestone: ---   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed:

Description Alisdair Meredith 2020-05-15 13:37:15 UTC
In general, we do not expect array types to be copyable according to the 'is_copy_constructible_v' trait.  However, the following started passing in gcc 10:

#include <type_traits>
static_assert(!std::is_copy_constructible_v<const void *[13]>);

Note that the 'const' is important, arrays of 'void *' remain non-copyable according to the trait.

'void' may be a specific trigger too, as arrays of 'const int *' do not have this problem.

Finally, the array bound does not seem significant, other than it gives the expected answer again for an array of unknown bound.
Comment 1 Alisdair Meredith 2020-05-15 14:02:10 UTC
Forgot to add this is specific to -std=c++20 too.
Comment 2 TC 2020-05-15 16:39:22 UTC
This is behaving as specified.

const void* const a[10];
const void* const b[10](a);

is valid code in C++20; it initializes b[0] with &a[0] converted to a const void*, and the rest of b with null pointers.

The void* case is

void* const a[10];
void* const b[10](a);

which is invalid because &a[0] is a void* const*; converting that to void* is not allowed because it casts away constness.
Comment 3 Alisdair Meredith 2020-07-06 12:28:28 UTC
Sorry, thought I had confirmed that I agree with the analysis above - this is a (perhaps surprising) change to the specification of C++20.

What is the best way to withdraw this report as invalid?
Comment 4 Jonathan Wakely 2020-07-06 12:52:49 UTC
Status -> RESOLVED INVALID
Comment 5 Barry Revzin 2022-03-11 18:29:53 UTC
Just to follow up, gcc trunk right now does this:

int main() {
    int a[3]{};
    void const* b[3](a);  // ok

    void const* c[3]{};
    void const* d[3](c);  // error: array must be initialized with a brace-enclosed initializer
}

If 'd' is actually an error, then it's not because of that, so at the very least, the diagnostic is wrong.