[libcxx-commits] [PATCH] D80452: [libc++] Complete overhaul of constexpr support in std::array
Louis Dionne via Phabricator via libcxx-commits
libcxx-commits at lists.llvm.org
Mon May 25 11:14:48 PDT 2020
ldionne added a comment.
Thanks @zoecarver and @miscco for the comments and review! I'm addressing your comments.
In D80452#2051973 <https://reviews.llvm.org/D80452#2051973>, @miscco wrote:
> What I completely forgot, thisimplements the array portion of the [[ http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1032r1.html | misc_constexpr ]]paper so you should adopt/add the feature test macro ````__cpp_lib_array_constexpr = 201811L```
Good catch! Will add in the next update.
================
Comment at: libcxx/include/array:246
+ struct _Empty { };
+ typedef typename conditional<is_const<_Tp>::value, const _Empty,
+ _Empty>::type _CharType;
----------------
zoecarver wrote:
> zoecarver wrote:
> > Why use a new `_Empty` struct? `char` makes more sense and has a defined size in the standard.
> Nit: this could be `add_const`.
Default constructing a `char` leaves it to an undefined value, which you can't do inside `constexpr`. So something like `std::array<int, 0> a;` isn't valid inside `constexpr` if the empty-array implementation holds a `char` internally, but it does work with an empty struct.
But regardless, this is being undone anyway since I'm moving to the `union` trick.
================
Comment at: libcxx/include/array:352
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
+ value_type* data() _NOEXCEPT {return nullptr;}
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
----------------
zoecarver wrote:
> This will probably break some people's code. I would much prefer not returning `nullptr` here. What's the downside of using something similar to D60666's implementation of `data()`?
Indeed -- I spent some more time on this and it does work. Updated.
================
Comment at: libcxx/test/std/containers/sequences/array/array.cons/deduct.pass.cpp:33
-int main(int, char**)
+template <typename Dummy = void>
+constexpr bool tests()
----------------
miscco wrote:
> being new to the party, what is the reason for the template?
It's to avoid this error:
```
at.pass.cpp:27:27: error: constexpr function never produces a constant expression [-Winvalid-constexpr]
TEST_CONSTEXPR_CXX14 bool tests()
```
It triggers when e.g. `at()` is not marked as `constexpr` in the given standard mode, but the `tests()` function that calls it is.
However, in this specific case, it's not useful because the test is only enabled in c++17 and above, so there's no `constexpr` mismatch. But it is useful in other tests, like the ones for `at`, `data` and probably others. I'll remove the unnecessary ones.
================
Comment at: libcxx/test/std/containers/sequences/array/array.cons/implicit_copy.pass.cpp:39
+ {
+ typedef double T;
+ typedef std::array<T, 3> C;
----------------
miscco wrote:
> Would it make sense to consistently drop all those typedefs?
>
> If not what is their purpose?
I think it would make sense to drop them -- I'm not a big fan. It's just the way the tests were written originally I guess. I don't really want to systematically remove the typedefs in this patch, though.
================
Comment at: libcxx/test/std/containers/sequences/array/array.cons/initializer_list.pass.cpp:27
typedef std::array<T, 3> C;
- C c = {1, 2, 3.5};
+ C const c = {1, 2, 3.5};
assert(c.size() == 3);
----------------
miscco wrote:
> preexisting: Are those conversions from into double intentional?
I am pretty sure they are, we're likely testing that aggregate initialization works as expected.
================
Comment at: libcxx/test/std/containers/sequences/array/array.data/data.pass.cpp:37
+template <typename Dummy = void>
+TEST_CONSTEXPR_CXX14 bool tests()
{
----------------
miscco wrote:
> This is `TEST_CONSTEXPR_CXX14` but the constexpr test is `#if TEST_STD_VER >= 17`
>
> Could we define a macro `TEST_CONSTEXPR_CXX14`?
>
> Notably this should not compile for C++14 as data is not constexpr.
>
> Occurs at other places too
> Could we define a macro `TEST_CONSTEXPR_CXX14`?
Do you mean `TEST_CONSTEXPR_CXX17`?
I'm making the test code `constexpr` whenever it can be marked as such, I'm just not checking the constexpr-ness of `std::array` itself unless the Standard mandates it. That's the purpose of the `Dummy` template parameter -- it makes it OK to have `constexpr` on the `tests()` function in C++14, despite its body not being `constexpr`-friendly (because `data()` isn't `constexpr` as you mention).
================
Comment at: libcxx/test/std/containers/sequences/array/array.data/data.pass.cpp:53
T* p = c.data();
- LIBCPP_ASSERT(p != nullptr);
+ (void)p;
}
----------------
zoecarver wrote:
> I don't see the point of this test anymore (lines 48-54).
I've re-added the check for `p != nullptr`, so this is moot.
================
Comment at: libcxx/test/std/containers/sequences/array/array.data/data_const.pass.cpp:95
+ const T* p = c.data();
+ std::uintptr_t pint = reinterpret_cast<std::uintptr_t>(p);
+ assert(pint % TEST_ALIGNOF(T) == 0);
----------------
zoecarver wrote:
> `pint` will always be zero, no? I think it would make more sense to test this with non-null data (`std::array<T, 1>` maybe).
Moot since I'm using the `union` trick.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D80452/new/
https://reviews.llvm.org/D80452
More information about the libcxx-commits
mailing list