diff --git a/libcxx/docs/Cxx2aStatusIssuesStatus.csv b/libcxx/docs/Cxx2aStatusIssuesStatus.csv --- a/libcxx/docs/Cxx2aStatusIssuesStatus.csv +++ b/libcxx/docs/Cxx2aStatusIssuesStatus.csv @@ -186,7 +186,7 @@ "`3274 `__","Missing feature test macro for ````\ ","Belfast","","" "`3276 `__","Class ``split_view::outer_iterator::value_type``\ should inherit from ``view_interface``\ ","Belfast","","" "`3277 `__","Pre-increment on prvalues is not a requirement of ``weakly_incrementable``\ ","Belfast","","" -"`3149 `__","``DefaultConstructible``\ should require default initialization","Belfast","","" +"`3149 `__","``DefaultConstructible``\ should require default initialization","Belfast","|Complete|","12.0" "","","","","" "`1203 `__","More useful rvalue stream insertion","Prague","|Complete|","12.0" "`2859 `__","Definition of *reachable* in [ptr.launder] misses pointer arithmetic from pointer-interconvertible object","Prague","","" diff --git a/libcxx/include/concepts b/libcxx/include/concepts --- a/libcxx/include/concepts +++ b/libcxx/include/concepts @@ -167,6 +167,16 @@ concept constructible_from = destructible<_Tp> && _VSTD::is_constructible_v<_Tp, _Args...>; +// [concept.default.init] + +template +concept __default_initializable = requires { ::new _Tp; }; + +template +concept default_initializable = constructible_from<_Tp> && + requires { _Tp{}; } && __default_initializable<_Tp>; + + #endif //_LIBCPP_STD_VER > 17 && defined(__cpp_concepts) && __cpp_concepts >= 201811L _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/test/std/concepts/concept.default.init/default_initializable.compile.pass.cpp b/libcxx/test/std/concepts/concept.default.init/default_initializable.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/concepts/concept.default.init/default_initializable.compile.pass.cpp @@ -0,0 +1,237 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts + +// template +// concept default_initializable = constructible_from && +// requires { T{}; } && +// is-default-initializable; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "test_macros.h" + +struct Empty{}; + +struct CtorDefaulted{ CtorDefaulted() = default; }; +struct CtorDeleted{ CtorDeleted() = delete; }; +struct DtorDefaulted{ ~DtorDefaulted() = default; }; +struct DtorDeleted{ ~DtorDeleted() = delete; }; + +struct Noexcept{ ~Noexcept() noexcept; }; +struct NoexceptTrue{ ~NoexceptTrue() noexcept(true); }; +struct NoexceptFalse{ ~NoexceptFalse() noexcept(false); }; + +// Since C++17 dynamic exception specifications are no longer +// part of the standard. +struct Throw{ ~Throw() throw(); }; + +struct CtorProtected { protected: CtorProtected() = default; }; +struct CtorPrivate { private: CtorPrivate() = default; }; +struct DtorProtected { protected: ~DtorProtected() = default; }; +struct DtorPrivate { private: ~DtorPrivate() = default; }; + +template +struct NoexceptDependant { + ~NoexceptDependant() noexcept(std::is_same_v); +}; + +struct CtorExplicit{ explicit CtorExplicit() = default; }; +struct CtorArgument{ CtorArgument(int) {} }; +struct CtorDefaultArgument{ CtorDefaultArgument(int = 0) {} }; +struct CtorExplicitDefaultArgument { + explicit CtorExplicitDefaultArgument(int = 0) {} +}; + +struct Derived : public Empty {}; + +class Abstract +{ + virtual void foo() = 0; +}; + +class AbstractDestructor +{ + virtual ~AbstractDestructor() = 0; +}; + +class OperatorNewDeleted { + void* operator new(std::size_t) = delete; + void operator delete(void* ptr) = delete; +}; + +[[maybe_unused]] auto Lambda = [](const int&, int&&, double){}; + +template +void test_not_const() +{ + static_assert( std::default_initializable< T>); + static_assert(!std::default_initializable); + static_assert( std::default_initializable< volatile T>); + static_assert(!std::default_initializable); +} + +template +void test_true() +{ + static_assert( std::default_initializable< T>); + static_assert( std::default_initializable); + static_assert( std::default_initializable< volatile T>); + static_assert( std::default_initializable); +} + +template +void test_false() +{ + static_assert(!std::default_initializable< T>); + static_assert(!std::default_initializable); + static_assert(!std::default_initializable< volatile T>); + static_assert(!std::default_initializable); +} + +void test() +{ + test_not_const(); + test_not_const(); + test_not_const(); + test_not_const(); + + test_false (); + test_not_const(); + + test_not_const(); + test_false (); + test_not_const(); + test_false (); + test_false (); + + test_true (); + + test_true (); + test_false (); + test_true (); + test_false (); + + test_true (); + test_true (); + test_false (); + + test_true (); + + test_false (); + test_false (); + test_false (); + test_false (); + + test_true >(); + test_false >(); + + test_true (); + test_false (); + test_true (); + test_true (); + + test_true (); + test_false (); + test_false (); + + test_true (); + + test_true (); + test_not_const(); + test_not_const(); + test_not_const(); + test_not_const(); + test_not_const(); + test_not_const(); + test_not_const(); + test_not_const(); + test_not_const(); + test_not_const(); + test_not_const(); + + // Sequence containers + test_not_const>(); + test_not_const>(); + test_false >(); + test_not_const>(); + test_false >(); + test_true >(); + test_true >(); + test_true >(); + test_true >(); + test_true >(); + test_true >(); + test_true >(); + + // Associative containers + test_true >(); + test_true >(); + test_true >(); + test_true >(); + + // Unordered associative containers + test_true >(); + test_true >(); + test_true >(); + test_true >(); + + // Container adaptors + test_true >(); + test_true >(); + test_true >(); + test_true >(); + test_true >(); + test_true >(); + + test_true >(); + test_true >(); + test_true >(); + test_true >(); + + // Strings + test_true (); + test_true (); + test_true (); + test_true (); + test_true (); + + // String views + test_true (); + test_true (); + test_true (); + test_true (); + test_true (); + + // Smart pointers + test_true >(); + test_true >(); + test_true >(); + +} + +// Required for MSVC internal test runner compatibility. +int main(int, char**) { + return 0; +} diff --git a/libcxx/test/std/concepts/concept.default.init/default_initializable.verify.cpp b/libcxx/test/std/concepts/concept.default.init/default_initializable.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/concepts/concept.default.init/default_initializable.verify.cpp @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts + +// template +// concept default_initializable = constructible_from && +// requires { T{}; } && +// is-default-initializable; + +#include +#include + +template +concept brace_initializable = requires { T{}; }; + +void test() { + // LWG3149 + // Changed the concept from constructible_from + // to constructible_from && + // requires { T{}; } && is-default-initializable + struct S0 { explicit S0() = default; }; + S0 x0; + S0 y0{}; + static_assert( std::constructible_from); + static_assert( brace_initializable); + static_assert( std::__default_initializable); + static_assert( std::default_initializable); + + struct S1 { S0 x; }; // Note: aggregate + S1 x1; + S1 y1{}; // expected-error {{chosen constructor is explicit in copy-initialization}} + static_assert( std::constructible_from); + static_assert(!brace_initializable); + static_assert( std::__default_initializable); + static_assert(!std::default_initializable); + + const int x2; // expected-error {{default initialization of an object of const type 'const int'}} + const int y2{}; + + static_assert( std::constructible_from); + static_assert( brace_initializable); + static_assert(!std::__default_initializable); + static_assert(!std::default_initializable); + + const int x3[1]; // expected-error {{default initialization of an object of const type 'const int [1]'}} + const int y3[1]{}; + static_assert( std::constructible_from); + static_assert( brace_initializable); + static_assert(!std::__default_initializable); + static_assert(!std::default_initializable); + + // Zero-length array extension + const int x4[]; // expected-error {{definition of variable with array type needs an explicit size or an initializer}} + const int y4[]{}; + static_assert(!std::constructible_from); + static_assert( brace_initializable); + static_assert(!std::__default_initializable); + static_assert(!std::default_initializable); +} + +int main(int, char**) { + test(); + + return 0; +}