Open tbaederr opened 3 months ago
@llvm/issue-subscribers-clang-frontend
Author: Timm Baeder (tbaederr)
Also fails with integers:
constexpr int a[3][3] ={};
constexpr int diff2 = &a[1][3] - &a[0][0];
Hmm, IIUC the subexpression a[1][3]
already results in UB, so this ought to fail to compile. CWG2875 clarifies this.
~The current title "Clang can't compare 2 pointers into the same multidimensional array at compile time" doesn't match the example.~ The comparison is OK with Clang (Godbolt link) despite that the example should also be rejected.
struct A {};
constexpr A a[3][3];
constexpr bool is_greater = &a[1][3] > &a[0][0]; // UB -> ill-formed; a[1] + 3 > &a[0][0] is OK
static_assert(is_greater, "");
Assuming &a[1][3]
is replaced with a[1] + 3
(such transformation is required in C), the subtraction results in UB due to [expr.add]/5. These two pointers point to elements of different arrays, although the pointed to arrays are themselves elements of the same enclosing array.
Hmm, IIUC the subexpression
a[1][3]
already results in UB, so this ought to fail to compile
It's a one-past-the-end pointer which is fine to build an address to AFAIK. It's also accepted by all compilers.
Hmm, IIUC the subexpression
a[1][3]
already results in UB, so this ought to fail to compileIt's a one-past-the-end pointer which is fine to build an address to AFAIK. It's also accepted by all compilers.
It's OK to build such an address, but a[1][3]
additionally performs dereferencing via the the built-in operator[]
, and CWG2823 clarified that such dereferencing is UB.
C DR076/WG14 N721 made &a[1][3]
equivalent to a[1] + 3
and thus well-defined, but such equivalence isn't established in C++.
I attempted to submit an issue to apply C DR076 to C++, but the attempt was rejected. See cplusplus/CWG#464.
The comparison is OK with Clang (Godbolt link) despite that the example should also be rejected.
I think the comparison is fine; per [expr.rel]/4, "If two pointers point to different elements of the same array, or to subobjects thereof, the pointer to the element with the higher subscript is required to compare greater"
But for example:
constexpr int diff2 = &a[1][2] - &a[0][0];
is UB and hence non-constant by [expr.add]/5: "[...] if P and Q point to, respectively, array elements i and j of the same array object x, the expression P - Q has the value i - j [...] otherwise the behavior is undefined"
Take this example:
clang prints:
but all other compilers seem to accept this code just fine: https://godbolt.org/z/f7bGEThTT