Vendor import of libc++ trunk r307894:

https://llvm.org/svn/llvm-project/libcxx/trunk@307894
This commit is contained in:
Dimitry Andric 2017-07-13 19:25:57 +00:00
parent 9d043122e0
commit 289ae9e3ac
32 changed files with 855 additions and 427 deletions

View File

@ -352,6 +352,13 @@ else()
endif() endif()
file(MAKE_DIRECTORY "${LIBCXX_BINARY_INCLUDE_DIR}") file(MAKE_DIRECTORY "${LIBCXX_BINARY_INCLUDE_DIR}")
set(LIBCXX_INSTALL_PREFIX "" CACHE STRING
"Define libc++ destination prefix.")
if (NOT LIBCXX_INSTALL_PREFIX MATCHES "^$|.*/")
message(FATAL_ERROR "LIBCXX_INSTALL_PREFIX has to end with \"/\".")
endif()
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LIBCXX_LIBRARY_DIR}) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LIBCXX_LIBRARY_DIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${LIBCXX_LIBRARY_DIR}) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${LIBCXX_LIBRARY_DIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${LIBCXX_LIBRARY_DIR}) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${LIBCXX_LIBRARY_DIR})

View File

@ -55,7 +55,7 @@ macro(setup_abi_lib abidefines abilib abifiles abidirs)
) )
if (LIBCXX_INSTALL_HEADERS) if (LIBCXX_INSTALL_HEADERS)
install(FILES "${LIBCXX_BINARY_INCLUDE_DIR}/${fpath}" install(FILES "${LIBCXX_BINARY_INCLUDE_DIR}/${fpath}"
DESTINATION include/c++/v1/${dstdir} DESTINATION ${LIBCXX_INSTALL_PREFIX}include/c++/v1/${dstdir}
COMPONENT libcxx COMPONENT libcxx
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
) )

View File

@ -216,6 +216,11 @@ libc++ specific options
Extra suffix to append to the directory where libraries are to be installed. Extra suffix to append to the directory where libraries are to be installed.
This option overrides `LLVM_LIBDIR_SUFFIX`. This option overrides `LLVM_LIBDIR_SUFFIX`.
.. option:: LIBCXX_INSTALL_PREFIX:STRING
**Default**: ``""``
Define libc++ destination prefix.
.. _libc++experimental options: .. _libc++experimental options:

View File

@ -20,7 +20,7 @@ endif()
if (LIBCXX_INSTALL_HEADERS) if (LIBCXX_INSTALL_HEADERS)
install(DIRECTORY . install(DIRECTORY .
DESTINATION include/c++/v1 DESTINATION ${LIBCXX_INSTALL_PREFIX}include/c++/v1
COMPONENT cxx-headers COMPONENT cxx-headers
FILES_MATCHING FILES_MATCHING
${LIBCXX_HEADER_PATTERN} ${LIBCXX_HEADER_PATTERN}
@ -44,7 +44,7 @@ if (LIBCXX_INSTALL_HEADERS)
set(generated_config_deps generate_config_header) set(generated_config_deps generate_config_header)
# Install the generated header as __config. # Install the generated header as __config.
install(FILES ${LIBCXX_BINARY_DIR}/__generated_config install(FILES ${LIBCXX_BINARY_DIR}/__generated_config
DESTINATION include/c++/v1 DESTINATION ${LIBCXX_INSTALL_PREFIX}include/c++/v1
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
RENAME __config RENAME __config
COMPONENT cxx-headers) COMPONENT cxx-headers)

View File

@ -549,7 +549,7 @@ hypot(_A1 __lcpp_x, _A2 __lcpp_y, _A3 __lcpp_z) _NOEXCEPT
template <class _A1> template <class _A1>
_LIBCPP_ALWAYS_INLINE _LIBCPP_ALWAYS_INLINE
_LIBCPP_CONSTEXPR typename enable_if<is_floating_point<_A1>::value, bool>::type _LIBCPP_CONSTEXPR typename enable_if<is_floating_point<_A1>::value, bool>::type
__libcpp_isnan(_A1 __lcpp_x) _NOEXCEPT __libcpp_isnan_or_builtin(_A1 __lcpp_x) _NOEXCEPT
{ {
#if __has_builtin(__builtin_isnan) #if __has_builtin(__builtin_isnan)
return __builtin_isnan(__lcpp_x); return __builtin_isnan(__lcpp_x);
@ -561,7 +561,7 @@ __libcpp_isnan(_A1 __lcpp_x) _NOEXCEPT
template <class _A1> template <class _A1>
_LIBCPP_ALWAYS_INLINE _LIBCPP_ALWAYS_INLINE
_LIBCPP_CONSTEXPR typename enable_if<!is_floating_point<_A1>::value, bool>::type _LIBCPP_CONSTEXPR typename enable_if<!is_floating_point<_A1>::value, bool>::type
__libcpp_isnan(_A1 __lcpp_x) _NOEXCEPT __libcpp_isnan_or_builtin(_A1 __lcpp_x) _NOEXCEPT
{ {
return isnan(__lcpp_x); return isnan(__lcpp_x);
} }
@ -569,7 +569,7 @@ __libcpp_isnan(_A1 __lcpp_x) _NOEXCEPT
template <class _A1> template <class _A1>
_LIBCPP_ALWAYS_INLINE _LIBCPP_ALWAYS_INLINE
_LIBCPP_CONSTEXPR typename enable_if<is_floating_point<_A1>::value, bool>::type _LIBCPP_CONSTEXPR typename enable_if<is_floating_point<_A1>::value, bool>::type
__libcpp_isinf(_A1 __lcpp_x) _NOEXCEPT __libcpp_isinf_or_builtin(_A1 __lcpp_x) _NOEXCEPT
{ {
#if __has_builtin(__builtin_isinf) #if __has_builtin(__builtin_isinf)
return __builtin_isinf(__lcpp_x); return __builtin_isinf(__lcpp_x);
@ -581,7 +581,7 @@ __libcpp_isinf(_A1 __lcpp_x) _NOEXCEPT
template <class _A1> template <class _A1>
_LIBCPP_ALWAYS_INLINE _LIBCPP_ALWAYS_INLINE
_LIBCPP_CONSTEXPR typename enable_if<!is_floating_point<_A1>::value, bool>::type _LIBCPP_CONSTEXPR typename enable_if<!is_floating_point<_A1>::value, bool>::type
__libcpp_isinf(_A1 __lcpp_x) _NOEXCEPT __libcpp_isinf_or_builtin(_A1 __lcpp_x) _NOEXCEPT
{ {
return isinf(__lcpp_x); return isinf(__lcpp_x);
} }
@ -589,7 +589,7 @@ __libcpp_isinf(_A1 __lcpp_x) _NOEXCEPT
template <class _A1> template <class _A1>
_LIBCPP_ALWAYS_INLINE _LIBCPP_ALWAYS_INLINE
_LIBCPP_CONSTEXPR typename enable_if<is_floating_point<_A1>::value, bool>::type _LIBCPP_CONSTEXPR typename enable_if<is_floating_point<_A1>::value, bool>::type
__libcpp_isfinite(_A1 __lcpp_x) _NOEXCEPT __libcpp_isfinite_or_builtin(_A1 __lcpp_x) _NOEXCEPT
{ {
#if __has_builtin(__builtin_isfinite) #if __has_builtin(__builtin_isfinite)
return __builtin_isfinite(__lcpp_x); return __builtin_isfinite(__lcpp_x);
@ -601,7 +601,7 @@ __libcpp_isfinite(_A1 __lcpp_x) _NOEXCEPT
template <class _A1> template <class _A1>
_LIBCPP_ALWAYS_INLINE _LIBCPP_ALWAYS_INLINE
_LIBCPP_CONSTEXPR typename enable_if<!is_floating_point<_A1>::value, bool>::type _LIBCPP_CONSTEXPR typename enable_if<!is_floating_point<_A1>::value, bool>::type
__libcpp_isfinite(_A1 __lcpp_x) _NOEXCEPT __libcpp_isfinite_or_builtin(_A1 __lcpp_x) _NOEXCEPT
{ {
return isfinite(__lcpp_x); return isfinite(__lcpp_x);
} }

View File

@ -599,39 +599,39 @@ operator*(const complex<_Tp>& __z, const complex<_Tp>& __w)
_Tp __bc = __b * __c; _Tp __bc = __b * __c;
_Tp __x = __ac - __bd; _Tp __x = __ac - __bd;
_Tp __y = __ad + __bc; _Tp __y = __ad + __bc;
if (__libcpp_isnan(__x) && __libcpp_isnan(__y)) if (__libcpp_isnan_or_builtin(__x) && __libcpp_isnan_or_builtin(__y))
{ {
bool __recalc = false; bool __recalc = false;
if (__libcpp_isinf(__a) || __libcpp_isinf(__b)) if (__libcpp_isinf_or_builtin(__a) || __libcpp_isinf_or_builtin(__b))
{ {
__a = copysign(__libcpp_isinf(__a) ? _Tp(1) : _Tp(0), __a); __a = copysign(__libcpp_isinf_or_builtin(__a) ? _Tp(1) : _Tp(0), __a);
__b = copysign(__libcpp_isinf(__b) ? _Tp(1) : _Tp(0), __b); __b = copysign(__libcpp_isinf_or_builtin(__b) ? _Tp(1) : _Tp(0), __b);
if (__libcpp_isnan(__c)) if (__libcpp_isnan_or_builtin(__c))
__c = copysign(_Tp(0), __c); __c = copysign(_Tp(0), __c);
if (__libcpp_isnan(__d)) if (__libcpp_isnan_or_builtin(__d))
__d = copysign(_Tp(0), __d); __d = copysign(_Tp(0), __d);
__recalc = true; __recalc = true;
} }
if (__libcpp_isinf(__c) || __libcpp_isinf(__d)) if (__libcpp_isinf_or_builtin(__c) || __libcpp_isinf_or_builtin(__d))
{ {
__c = copysign(__libcpp_isinf(__c) ? _Tp(1) : _Tp(0), __c); __c = copysign(__libcpp_isinf_or_builtin(__c) ? _Tp(1) : _Tp(0), __c);
__d = copysign(__libcpp_isinf(__d) ? _Tp(1) : _Tp(0), __d); __d = copysign(__libcpp_isinf_or_builtin(__d) ? _Tp(1) : _Tp(0), __d);
if (__libcpp_isnan(__a)) if (__libcpp_isnan_or_builtin(__a))
__a = copysign(_Tp(0), __a); __a = copysign(_Tp(0), __a);
if (__libcpp_isnan(__b)) if (__libcpp_isnan_or_builtin(__b))
__b = copysign(_Tp(0), __b); __b = copysign(_Tp(0), __b);
__recalc = true; __recalc = true;
} }
if (!__recalc && (__libcpp_isinf(__ac) || __libcpp_isinf(__bd) || if (!__recalc && (__libcpp_isinf_or_builtin(__ac) || __libcpp_isinf_or_builtin(__bd) ||
__libcpp_isinf(__ad) || __libcpp_isinf(__bc))) __libcpp_isinf_or_builtin(__ad) || __libcpp_isinf_or_builtin(__bc)))
{ {
if (__libcpp_isnan(__a)) if (__libcpp_isnan_or_builtin(__a))
__a = copysign(_Tp(0), __a); __a = copysign(_Tp(0), __a);
if (__libcpp_isnan(__b)) if (__libcpp_isnan_or_builtin(__b))
__b = copysign(_Tp(0), __b); __b = copysign(_Tp(0), __b);
if (__libcpp_isnan(__c)) if (__libcpp_isnan_or_builtin(__c))
__c = copysign(_Tp(0), __c); __c = copysign(_Tp(0), __c);
if (__libcpp_isnan(__d)) if (__libcpp_isnan_or_builtin(__d))
__d = copysign(_Tp(0), __d); __d = copysign(_Tp(0), __d);
__recalc = true; __recalc = true;
} }
@ -674,7 +674,7 @@ operator/(const complex<_Tp>& __z, const complex<_Tp>& __w)
_Tp __c = __w.real(); _Tp __c = __w.real();
_Tp __d = __w.imag(); _Tp __d = __w.imag();
_Tp __logbw = logb(fmax(fabs(__c), fabs(__d))); _Tp __logbw = logb(fmax(fabs(__c), fabs(__d)));
if (__libcpp_isfinite(__logbw)) if (__libcpp_isfinite_or_builtin(__logbw))
{ {
__ilogbw = static_cast<int>(__logbw); __ilogbw = static_cast<int>(__logbw);
__c = scalbn(__c, -__ilogbw); __c = scalbn(__c, -__ilogbw);
@ -683,24 +683,24 @@ operator/(const complex<_Tp>& __z, const complex<_Tp>& __w)
_Tp __denom = __c * __c + __d * __d; _Tp __denom = __c * __c + __d * __d;
_Tp __x = scalbn((__a * __c + __b * __d) / __denom, -__ilogbw); _Tp __x = scalbn((__a * __c + __b * __d) / __denom, -__ilogbw);
_Tp __y = scalbn((__b * __c - __a * __d) / __denom, -__ilogbw); _Tp __y = scalbn((__b * __c - __a * __d) / __denom, -__ilogbw);
if (__libcpp_isnan(__x) && __libcpp_isnan(__y)) if (__libcpp_isnan_or_builtin(__x) && __libcpp_isnan_or_builtin(__y))
{ {
if ((__denom == _Tp(0)) && (!__libcpp_isnan(__a) || !__libcpp_isnan(__b))) if ((__denom == _Tp(0)) && (!__libcpp_isnan_or_builtin(__a) || !__libcpp_isnan_or_builtin(__b)))
{ {
__x = copysign(_Tp(INFINITY), __c) * __a; __x = copysign(_Tp(INFINITY), __c) * __a;
__y = copysign(_Tp(INFINITY), __c) * __b; __y = copysign(_Tp(INFINITY), __c) * __b;
} }
else if ((__libcpp_isinf(__a) || __libcpp_isinf(__b)) && __libcpp_isfinite(__c) && __libcpp_isfinite(__d)) else if ((__libcpp_isinf_or_builtin(__a) || __libcpp_isinf_or_builtin(__b)) && __libcpp_isfinite_or_builtin(__c) && __libcpp_isfinite_or_builtin(__d))
{ {
__a = copysign(__libcpp_isinf(__a) ? _Tp(1) : _Tp(0), __a); __a = copysign(__libcpp_isinf_or_builtin(__a) ? _Tp(1) : _Tp(0), __a);
__b = copysign(__libcpp_isinf(__b) ? _Tp(1) : _Tp(0), __b); __b = copysign(__libcpp_isinf_or_builtin(__b) ? _Tp(1) : _Tp(0), __b);
__x = _Tp(INFINITY) * (__a * __c + __b * __d); __x = _Tp(INFINITY) * (__a * __c + __b * __d);
__y = _Tp(INFINITY) * (__b * __c - __a * __d); __y = _Tp(INFINITY) * (__b * __c - __a * __d);
} }
else if (__libcpp_isinf(__logbw) && __logbw > _Tp(0) && __libcpp_isfinite(__a) && __libcpp_isfinite(__b)) else if (__libcpp_isinf_or_builtin(__logbw) && __logbw > _Tp(0) && __libcpp_isfinite_or_builtin(__a) && __libcpp_isfinite_or_builtin(__b))
{ {
__c = copysign(__libcpp_isinf(__c) ? _Tp(1) : _Tp(0), __c); __c = copysign(__libcpp_isinf_or_builtin(__c) ? _Tp(1) : _Tp(0), __c);
__d = copysign(__libcpp_isinf(__d) ? _Tp(1) : _Tp(0), __d); __d = copysign(__libcpp_isinf_or_builtin(__d) ? _Tp(1) : _Tp(0), __d);
__x = _Tp(0) * (__a * __c + __b * __d); __x = _Tp(0) * (__a * __c + __b * __d);
__y = _Tp(0) * (__b * __c - __a * __d); __y = _Tp(0) * (__b * __c - __a * __d);
} }
@ -910,9 +910,9 @@ inline _LIBCPP_INLINE_VISIBILITY
_Tp _Tp
norm(const complex<_Tp>& __c) norm(const complex<_Tp>& __c)
{ {
if (__libcpp_isinf(__c.real())) if (__libcpp_isinf_or_builtin(__c.real()))
return abs(__c.real()); return abs(__c.real());
if (__libcpp_isinf(__c.imag())) if (__libcpp_isinf_or_builtin(__c.imag()))
return abs(__c.imag()); return abs(__c.imag());
return __c.real() * __c.real() + __c.imag() * __c.imag(); return __c.real() * __c.real() + __c.imag() * __c.imag();
} }
@ -955,7 +955,7 @@ complex<_Tp>
proj(const complex<_Tp>& __c) proj(const complex<_Tp>& __c)
{ {
std::complex<_Tp> __r = __c; std::complex<_Tp> __r = __c;
if (__libcpp_isinf(__c.real()) || __libcpp_isinf(__c.imag())) if (__libcpp_isinf_or_builtin(__c.real()) || __libcpp_isinf_or_builtin(__c.imag()))
__r = complex<_Tp>(INFINITY, copysign(_Tp(0), __c.imag())); __r = complex<_Tp>(INFINITY, copysign(_Tp(0), __c.imag()));
return __r; return __r;
} }
@ -969,7 +969,7 @@ typename enable_if
>::type >::type
proj(_Tp __re) proj(_Tp __re)
{ {
if (__libcpp_isinf(__re)) if (__libcpp_isinf_or_builtin(__re))
__re = abs(__re); __re = abs(__re);
return complex<_Tp>(__re); return complex<_Tp>(__re);
} }
@ -993,25 +993,25 @@ template<class _Tp>
complex<_Tp> complex<_Tp>
polar(const _Tp& __rho, const _Tp& __theta = _Tp(0)) polar(const _Tp& __rho, const _Tp& __theta = _Tp(0))
{ {
if (__libcpp_isnan(__rho) || signbit(__rho)) if (__libcpp_isnan_or_builtin(__rho) || signbit(__rho))
return complex<_Tp>(_Tp(NAN), _Tp(NAN)); return complex<_Tp>(_Tp(NAN), _Tp(NAN));
if (__libcpp_isnan(__theta)) if (__libcpp_isnan_or_builtin(__theta))
{ {
if (__libcpp_isinf(__rho)) if (__libcpp_isinf_or_builtin(__rho))
return complex<_Tp>(__rho, __theta); return complex<_Tp>(__rho, __theta);
return complex<_Tp>(__theta, __theta); return complex<_Tp>(__theta, __theta);
} }
if (__libcpp_isinf(__theta)) if (__libcpp_isinf_or_builtin(__theta))
{ {
if (__libcpp_isinf(__rho)) if (__libcpp_isinf_or_builtin(__rho))
return complex<_Tp>(__rho, _Tp(NAN)); return complex<_Tp>(__rho, _Tp(NAN));
return complex<_Tp>(_Tp(NAN), _Tp(NAN)); return complex<_Tp>(_Tp(NAN), _Tp(NAN));
} }
_Tp __x = __rho * cos(__theta); _Tp __x = __rho * cos(__theta);
if (__libcpp_isnan(__x)) if (__libcpp_isnan_or_builtin(__x))
__x = 0; __x = 0;
_Tp __y = __rho * sin(__theta); _Tp __y = __rho * sin(__theta);
if (__libcpp_isnan(__y)) if (__libcpp_isnan_or_builtin(__y))
__y = 0; __y = 0;
return complex<_Tp>(__x, __y); return complex<_Tp>(__x, __y);
} }
@ -1042,13 +1042,13 @@ template<class _Tp>
complex<_Tp> complex<_Tp>
sqrt(const complex<_Tp>& __x) sqrt(const complex<_Tp>& __x)
{ {
if (__libcpp_isinf(__x.imag())) if (__libcpp_isinf_or_builtin(__x.imag()))
return complex<_Tp>(_Tp(INFINITY), __x.imag()); return complex<_Tp>(_Tp(INFINITY), __x.imag());
if (__libcpp_isinf(__x.real())) if (__libcpp_isinf_or_builtin(__x.real()))
{ {
if (__x.real() > _Tp(0)) if (__x.real() > _Tp(0))
return complex<_Tp>(__x.real(), __libcpp_isnan(__x.imag()) ? __x.imag() : copysign(_Tp(0), __x.imag())); return complex<_Tp>(__x.real(), __libcpp_isnan_or_builtin(__x.imag()) ? __x.imag() : copysign(_Tp(0), __x.imag()));
return complex<_Tp>(__libcpp_isnan(__x.imag()) ? __x.imag() : _Tp(0), copysign(__x.real(), __x.imag())); return complex<_Tp>(__libcpp_isnan_or_builtin(__x.imag()) ? __x.imag() : _Tp(0), copysign(__x.real(), __x.imag()));
} }
return polar(sqrt(abs(__x)), arg(__x) / _Tp(2)); return polar(sqrt(abs(__x)), arg(__x) / _Tp(2));
} }
@ -1060,21 +1060,21 @@ complex<_Tp>
exp(const complex<_Tp>& __x) exp(const complex<_Tp>& __x)
{ {
_Tp __i = __x.imag(); _Tp __i = __x.imag();
if (__libcpp_isinf(__x.real())) if (__libcpp_isinf_or_builtin(__x.real()))
{ {
if (__x.real() < _Tp(0)) if (__x.real() < _Tp(0))
{ {
if (!__libcpp_isfinite(__i)) if (!__libcpp_isfinite_or_builtin(__i))
__i = _Tp(1); __i = _Tp(1);
} }
else if (__i == 0 || !__libcpp_isfinite(__i)) else if (__i == 0 || !__libcpp_isfinite_or_builtin(__i))
{ {
if (__libcpp_isinf(__i)) if (__libcpp_isinf_or_builtin(__i))
__i = _Tp(NAN); __i = _Tp(NAN);
return complex<_Tp>(__x.real(), __i); return complex<_Tp>(__x.real(), __i);
} }
} }
else if (__libcpp_isnan(__x.real()) && __x.imag() == 0) else if (__libcpp_isnan_or_builtin(__x.real()) && __x.imag() == 0)
return __x; return __x;
_Tp __e = exp(__x.real()); _Tp __e = exp(__x.real());
return complex<_Tp>(__e * cos(__i), __e * sin(__i)); return complex<_Tp>(__e * cos(__i), __e * sin(__i));
@ -1132,23 +1132,23 @@ complex<_Tp>
asinh(const complex<_Tp>& __x) asinh(const complex<_Tp>& __x)
{ {
const _Tp __pi(atan2(+0., -0.)); const _Tp __pi(atan2(+0., -0.));
if (__libcpp_isinf(__x.real())) if (__libcpp_isinf_or_builtin(__x.real()))
{ {
if (__libcpp_isnan(__x.imag())) if (__libcpp_isnan_or_builtin(__x.imag()))
return __x; return __x;
if (__libcpp_isinf(__x.imag())) if (__libcpp_isinf_or_builtin(__x.imag()))
return complex<_Tp>(__x.real(), copysign(__pi * _Tp(0.25), __x.imag())); return complex<_Tp>(__x.real(), copysign(__pi * _Tp(0.25), __x.imag()));
return complex<_Tp>(__x.real(), copysign(_Tp(0), __x.imag())); return complex<_Tp>(__x.real(), copysign(_Tp(0), __x.imag()));
} }
if (__libcpp_isnan(__x.real())) if (__libcpp_isnan_or_builtin(__x.real()))
{ {
if (__libcpp_isinf(__x.imag())) if (__libcpp_isinf_or_builtin(__x.imag()))
return complex<_Tp>(__x.imag(), __x.real()); return complex<_Tp>(__x.imag(), __x.real());
if (__x.imag() == 0) if (__x.imag() == 0)
return __x; return __x;
return complex<_Tp>(__x.real(), __x.real()); return complex<_Tp>(__x.real(), __x.real());
} }
if (__libcpp_isinf(__x.imag())) if (__libcpp_isinf_or_builtin(__x.imag()))
return complex<_Tp>(copysign(__x.imag(), __x.real()), copysign(__pi/_Tp(2), __x.imag())); return complex<_Tp>(copysign(__x.imag(), __x.real()), copysign(__pi/_Tp(2), __x.imag()));
complex<_Tp> __z = log(__x + sqrt(pow(__x, _Tp(2)) + _Tp(1))); complex<_Tp> __z = log(__x + sqrt(pow(__x, _Tp(2)) + _Tp(1)));
return complex<_Tp>(copysign(__z.real(), __x.real()), copysign(__z.imag(), __x.imag())); return complex<_Tp>(copysign(__z.real(), __x.real()), copysign(__z.imag(), __x.imag()));
@ -1161,11 +1161,11 @@ complex<_Tp>
acosh(const complex<_Tp>& __x) acosh(const complex<_Tp>& __x)
{ {
const _Tp __pi(atan2(+0., -0.)); const _Tp __pi(atan2(+0., -0.));
if (__libcpp_isinf(__x.real())) if (__libcpp_isinf_or_builtin(__x.real()))
{ {
if (__libcpp_isnan(__x.imag())) if (__libcpp_isnan_or_builtin(__x.imag()))
return complex<_Tp>(abs(__x.real()), __x.imag()); return complex<_Tp>(abs(__x.real()), __x.imag());
if (__libcpp_isinf(__x.imag())) if (__libcpp_isinf_or_builtin(__x.imag()))
{ {
if (__x.real() > 0) if (__x.real() > 0)
return complex<_Tp>(__x.real(), copysign(__pi * _Tp(0.25), __x.imag())); return complex<_Tp>(__x.real(), copysign(__pi * _Tp(0.25), __x.imag()));
@ -1176,13 +1176,13 @@ acosh(const complex<_Tp>& __x)
return complex<_Tp>(-__x.real(), copysign(__pi, __x.imag())); return complex<_Tp>(-__x.real(), copysign(__pi, __x.imag()));
return complex<_Tp>(__x.real(), copysign(_Tp(0), __x.imag())); return complex<_Tp>(__x.real(), copysign(_Tp(0), __x.imag()));
} }
if (__libcpp_isnan(__x.real())) if (__libcpp_isnan_or_builtin(__x.real()))
{ {
if (__libcpp_isinf(__x.imag())) if (__libcpp_isinf_or_builtin(__x.imag()))
return complex<_Tp>(abs(__x.imag()), __x.real()); return complex<_Tp>(abs(__x.imag()), __x.real());
return complex<_Tp>(__x.real(), __x.real()); return complex<_Tp>(__x.real(), __x.real());
} }
if (__libcpp_isinf(__x.imag())) if (__libcpp_isinf_or_builtin(__x.imag()))
return complex<_Tp>(abs(__x.imag()), copysign(__pi/_Tp(2), __x.imag())); return complex<_Tp>(abs(__x.imag()), copysign(__pi/_Tp(2), __x.imag()));
complex<_Tp> __z = log(__x + sqrt(pow(__x, _Tp(2)) - _Tp(1))); complex<_Tp> __z = log(__x + sqrt(pow(__x, _Tp(2)) - _Tp(1)));
return complex<_Tp>(copysign(__z.real(), _Tp(0)), copysign(__z.imag(), __x.imag())); return complex<_Tp>(copysign(__z.real(), _Tp(0)), copysign(__z.imag(), __x.imag()));
@ -1195,21 +1195,21 @@ complex<_Tp>
atanh(const complex<_Tp>& __x) atanh(const complex<_Tp>& __x)
{ {
const _Tp __pi(atan2(+0., -0.)); const _Tp __pi(atan2(+0., -0.));
if (__libcpp_isinf(__x.imag())) if (__libcpp_isinf_or_builtin(__x.imag()))
{ {
return complex<_Tp>(copysign(_Tp(0), __x.real()), copysign(__pi/_Tp(2), __x.imag())); return complex<_Tp>(copysign(_Tp(0), __x.real()), copysign(__pi/_Tp(2), __x.imag()));
} }
if (__libcpp_isnan(__x.imag())) if (__libcpp_isnan_or_builtin(__x.imag()))
{ {
if (__libcpp_isinf(__x.real()) || __x.real() == 0) if (__libcpp_isinf_or_builtin(__x.real()) || __x.real() == 0)
return complex<_Tp>(copysign(_Tp(0), __x.real()), __x.imag()); return complex<_Tp>(copysign(_Tp(0), __x.real()), __x.imag());
return complex<_Tp>(__x.imag(), __x.imag()); return complex<_Tp>(__x.imag(), __x.imag());
} }
if (__libcpp_isnan(__x.real())) if (__libcpp_isnan_or_builtin(__x.real()))
{ {
return complex<_Tp>(__x.real(), __x.real()); return complex<_Tp>(__x.real(), __x.real());
} }
if (__libcpp_isinf(__x.real())) if (__libcpp_isinf_or_builtin(__x.real()))
{ {
return complex<_Tp>(copysign(_Tp(0), __x.real()), copysign(__pi/_Tp(2), __x.imag())); return complex<_Tp>(copysign(_Tp(0), __x.real()), copysign(__pi/_Tp(2), __x.imag()));
} }
@ -1227,11 +1227,11 @@ template<class _Tp>
complex<_Tp> complex<_Tp>
sinh(const complex<_Tp>& __x) sinh(const complex<_Tp>& __x)
{ {
if (__libcpp_isinf(__x.real()) && !__libcpp_isfinite(__x.imag())) if (__libcpp_isinf_or_builtin(__x.real()) && !__libcpp_isfinite_or_builtin(__x.imag()))
return complex<_Tp>(__x.real(), _Tp(NAN)); return complex<_Tp>(__x.real(), _Tp(NAN));
if (__x.real() == 0 && !__libcpp_isfinite(__x.imag())) if (__x.real() == 0 && !__libcpp_isfinite_or_builtin(__x.imag()))
return complex<_Tp>(__x.real(), _Tp(NAN)); return complex<_Tp>(__x.real(), _Tp(NAN));
if (__x.imag() == 0 && !__libcpp_isfinite(__x.real())) if (__x.imag() == 0 && !__libcpp_isfinite_or_builtin(__x.real()))
return __x; return __x;
return complex<_Tp>(sinh(__x.real()) * cos(__x.imag()), cosh(__x.real()) * sin(__x.imag())); return complex<_Tp>(sinh(__x.real()) * cos(__x.imag()), cosh(__x.real()) * sin(__x.imag()));
} }
@ -1242,13 +1242,13 @@ template<class _Tp>
complex<_Tp> complex<_Tp>
cosh(const complex<_Tp>& __x) cosh(const complex<_Tp>& __x)
{ {
if (__libcpp_isinf(__x.real()) && !__libcpp_isfinite(__x.imag())) if (__libcpp_isinf_or_builtin(__x.real()) && !__libcpp_isfinite_or_builtin(__x.imag()))
return complex<_Tp>(abs(__x.real()), _Tp(NAN)); return complex<_Tp>(abs(__x.real()), _Tp(NAN));
if (__x.real() == 0 && !__libcpp_isfinite(__x.imag())) if (__x.real() == 0 && !__libcpp_isfinite_or_builtin(__x.imag()))
return complex<_Tp>(_Tp(NAN), __x.real()); return complex<_Tp>(_Tp(NAN), __x.real());
if (__x.real() == 0 && __x.imag() == 0) if (__x.real() == 0 && __x.imag() == 0)
return complex<_Tp>(_Tp(1), __x.imag()); return complex<_Tp>(_Tp(1), __x.imag());
if (__x.imag() == 0 && !__libcpp_isfinite(__x.real())) if (__x.imag() == 0 && !__libcpp_isfinite_or_builtin(__x.real()))
return complex<_Tp>(abs(__x.real()), __x.imag()); return complex<_Tp>(abs(__x.real()), __x.imag());
return complex<_Tp>(cosh(__x.real()) * cos(__x.imag()), sinh(__x.real()) * sin(__x.imag())); return complex<_Tp>(cosh(__x.real()) * cos(__x.imag()), sinh(__x.real()) * sin(__x.imag()));
} }
@ -1259,19 +1259,19 @@ template<class _Tp>
complex<_Tp> complex<_Tp>
tanh(const complex<_Tp>& __x) tanh(const complex<_Tp>& __x)
{ {
if (__libcpp_isinf(__x.real())) if (__libcpp_isinf_or_builtin(__x.real()))
{ {
if (!__libcpp_isfinite(__x.imag())) if (!__libcpp_isfinite_or_builtin(__x.imag()))
return complex<_Tp>(_Tp(1), _Tp(0)); return complex<_Tp>(_Tp(1), _Tp(0));
return complex<_Tp>(_Tp(1), copysign(_Tp(0), sin(_Tp(2) * __x.imag()))); return complex<_Tp>(_Tp(1), copysign(_Tp(0), sin(_Tp(2) * __x.imag())));
} }
if (__libcpp_isnan(__x.real()) && __x.imag() == 0) if (__libcpp_isnan_or_builtin(__x.real()) && __x.imag() == 0)
return __x; return __x;
_Tp __2r(_Tp(2) * __x.real()); _Tp __2r(_Tp(2) * __x.real());
_Tp __2i(_Tp(2) * __x.imag()); _Tp __2i(_Tp(2) * __x.imag());
_Tp __d(cosh(__2r) + cos(__2i)); _Tp __d(cosh(__2r) + cos(__2i));
_Tp __2rsh(sinh(__2r)); _Tp __2rsh(sinh(__2r));
if (__libcpp_isinf(__2rsh) && __libcpp_isinf(__d)) if (__libcpp_isinf_or_builtin(__2rsh) && __libcpp_isinf_or_builtin(__d))
return complex<_Tp>(__2rsh > _Tp(0) ? _Tp(1) : _Tp(-1), return complex<_Tp>(__2rsh > _Tp(0) ? _Tp(1) : _Tp(-1),
__2i > _Tp(0) ? _Tp(0) : _Tp(-0.)); __2i > _Tp(0) ? _Tp(0) : _Tp(-0.));
return complex<_Tp>(__2rsh/__d, sin(__2i)/__d); return complex<_Tp>(__2rsh/__d, sin(__2i)/__d);
@ -1294,11 +1294,11 @@ complex<_Tp>
acos(const complex<_Tp>& __x) acos(const complex<_Tp>& __x)
{ {
const _Tp __pi(atan2(+0., -0.)); const _Tp __pi(atan2(+0., -0.));
if (__libcpp_isinf(__x.real())) if (__libcpp_isinf_or_builtin(__x.real()))
{ {
if (__libcpp_isnan(__x.imag())) if (__libcpp_isnan_or_builtin(__x.imag()))
return complex<_Tp>(__x.imag(), __x.real()); return complex<_Tp>(__x.imag(), __x.real());
if (__libcpp_isinf(__x.imag())) if (__libcpp_isinf_or_builtin(__x.imag()))
{ {
if (__x.real() < _Tp(0)) if (__x.real() < _Tp(0))
return complex<_Tp>(_Tp(0.75) * __pi, -__x.imag()); return complex<_Tp>(_Tp(0.75) * __pi, -__x.imag());
@ -1308,13 +1308,13 @@ acos(const complex<_Tp>& __x)
return complex<_Tp>(__pi, signbit(__x.imag()) ? -__x.real() : __x.real()); return complex<_Tp>(__pi, signbit(__x.imag()) ? -__x.real() : __x.real());
return complex<_Tp>(_Tp(0), signbit(__x.imag()) ? __x.real() : -__x.real()); return complex<_Tp>(_Tp(0), signbit(__x.imag()) ? __x.real() : -__x.real());
} }
if (__libcpp_isnan(__x.real())) if (__libcpp_isnan_or_builtin(__x.real()))
{ {
if (__libcpp_isinf(__x.imag())) if (__libcpp_isinf_or_builtin(__x.imag()))
return complex<_Tp>(__x.real(), -__x.imag()); return complex<_Tp>(__x.real(), -__x.imag());
return complex<_Tp>(__x.real(), __x.real()); return complex<_Tp>(__x.real(), __x.real());
} }
if (__libcpp_isinf(__x.imag())) if (__libcpp_isinf_or_builtin(__x.imag()))
return complex<_Tp>(__pi/_Tp(2), -__x.imag()); return complex<_Tp>(__pi/_Tp(2), -__x.imag());
if (__x.real() == 0 && (__x.imag() == 0 || isnan(__x.imag()))) if (__x.real() == 0 && (__x.imag() == 0 || isnan(__x.imag())))
return complex<_Tp>(__pi/_Tp(2), -__x.imag()); return complex<_Tp>(__pi/_Tp(2), -__x.imag());

View File

@ -439,46 +439,122 @@ struct __optional_storage_base<_Tp, true>
} }
}; };
template <class _Tp, bool = is_trivially_copyable<_Tp>::value> template <class _Tp, bool = is_trivially_copy_constructible<_Tp>::value>
struct __optional_storage; struct __optional_copy_base : __optional_storage_base<_Tp>
template <class _Tp>
struct __optional_storage<_Tp, true> : __optional_storage_base<_Tp>
{ {
using __optional_storage_base<_Tp>::__optional_storage_base; using __optional_storage_base<_Tp>::__optional_storage_base;
}; };
template <class _Tp> template <class _Tp>
struct __optional_storage<_Tp, false> : __optional_storage_base<_Tp> struct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp>
{ {
using value_type = _Tp;
using __optional_storage_base<_Tp>::__optional_storage_base; using __optional_storage_base<_Tp>::__optional_storage_base;
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
__optional_storage() = default; __optional_copy_base() = default;
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
__optional_storage(const __optional_storage& __opt) __optional_copy_base(const __optional_copy_base& __opt)
{ {
this->__construct_from(__opt); this->__construct_from(__opt);
} }
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
__optional_storage(__optional_storage&& __opt) __optional_copy_base(__optional_copy_base&&) = default;
_LIBCPP_INLINE_VISIBILITY
__optional_copy_base& operator=(const __optional_copy_base&) = default;
_LIBCPP_INLINE_VISIBILITY
__optional_copy_base& operator=(__optional_copy_base&&) = default;
};
template <class _Tp, bool = is_trivially_move_constructible<_Tp>::value>
struct __optional_move_base : __optional_copy_base<_Tp>
{
using __optional_copy_base<_Tp>::__optional_copy_base;
};
template <class _Tp>
struct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp>
{
using value_type = _Tp;
using __optional_copy_base<_Tp>::__optional_copy_base;
_LIBCPP_INLINE_VISIBILITY
__optional_move_base() = default;
_LIBCPP_INLINE_VISIBILITY
__optional_move_base(const __optional_move_base&) = default;
_LIBCPP_INLINE_VISIBILITY
__optional_move_base(__optional_move_base&& __opt)
noexcept(is_nothrow_move_constructible_v<value_type>) noexcept(is_nothrow_move_constructible_v<value_type>)
{ {
this->__construct_from(_VSTD::move(__opt)); this->__construct_from(_VSTD::move(__opt));
} }
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
__optional_storage& operator=(const __optional_storage& __opt) __optional_move_base& operator=(const __optional_move_base&) = default;
_LIBCPP_INLINE_VISIBILITY
__optional_move_base& operator=(__optional_move_base&&) = default;
};
template <class _Tp, bool =
is_trivially_destructible<_Tp>::value &&
is_trivially_copy_constructible<_Tp>::value &&
is_trivially_copy_assignable<_Tp>::value>
struct __optional_copy_assign_base : __optional_move_base<_Tp>
{
using __optional_move_base<_Tp>::__optional_move_base;
};
template <class _Tp>
struct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp>
{
using __optional_move_base<_Tp>::__optional_move_base;
_LIBCPP_INLINE_VISIBILITY
__optional_copy_assign_base() = default;
_LIBCPP_INLINE_VISIBILITY
__optional_copy_assign_base(const __optional_copy_assign_base&) = default;
_LIBCPP_INLINE_VISIBILITY
__optional_copy_assign_base(__optional_copy_assign_base&&) = default;
_LIBCPP_INLINE_VISIBILITY
__optional_copy_assign_base& operator=(const __optional_copy_assign_base& __opt)
{ {
this->__assign_from(__opt); this->__assign_from(__opt);
return *this; return *this;
} }
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
__optional_storage& operator=(__optional_storage&& __opt) __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default;
};
template <class _Tp, bool =
is_trivially_destructible<_Tp>::value &&
is_trivially_move_constructible<_Tp>::value &&
is_trivially_move_assignable<_Tp>::value>
struct __optional_move_assign_base : __optional_copy_assign_base<_Tp>
{
using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
};
template <class _Tp>
struct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp>
{
using value_type = _Tp;
using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
_LIBCPP_INLINE_VISIBILITY
__optional_move_assign_base() = default;
_LIBCPP_INLINE_VISIBILITY
__optional_move_assign_base(const __optional_move_assign_base& __opt) = default;
_LIBCPP_INLINE_VISIBILITY
__optional_move_assign_base(__optional_move_assign_base&&) = default;
_LIBCPP_INLINE_VISIBILITY
__optional_move_assign_base& operator=(const __optional_move_assign_base&) = default;
_LIBCPP_INLINE_VISIBILITY
__optional_move_assign_base& operator=(__optional_move_assign_base&& __opt)
noexcept(is_nothrow_move_assignable_v<value_type> && noexcept(is_nothrow_move_assignable_v<value_type> &&
is_nothrow_move_constructible_v<value_type>) is_nothrow_move_constructible_v<value_type>)
{ {
@ -501,11 +577,11 @@ using __optional_sfinae_assign_base_t = __sfinae_assign_base<
template <class _Tp> template <class _Tp>
class optional class optional
: private __optional_storage<_Tp> : private __optional_move_assign_base<_Tp>
, private __optional_sfinae_ctor_base_t<_Tp> , private __optional_sfinae_ctor_base_t<_Tp>
, private __optional_sfinae_assign_base_t<_Tp> , private __optional_sfinae_assign_base_t<_Tp>
{ {
using __base = __optional_storage<_Tp>; using __base = __optional_move_assign_base<_Tp>;
public: public:
using value_type = _Tp; using value_type = _Tp;

View File

@ -6142,7 +6142,7 @@ regex_iterator<_BidirectionalIterator, _CharT, _Traits>::operator++()
{ {
__flags_ |= regex_constants::__no_update_pos; __flags_ |= regex_constants::__no_update_pos;
_BidirectionalIterator __start = __match_[0].second; _BidirectionalIterator __start = __match_[0].second;
if (__match_.empty()) if (__match_[0].first == __match_[0].second)
{ {
if (__start == __end_) if (__start == __end_)
{ {

View File

@ -676,11 +676,11 @@ private:
}; };
#if _LIBCPP_BIG_ENDIAN #if _LIBCPP_BIG_ENDIAN
enum {__short_mask = 0x01}; static const size_type __short_mask = 0x01;
enum {__long_mask = 0x1ul}; static const size_type __long_mask = 0x1ul;
#else // _LIBCPP_BIG_ENDIAN #else // _LIBCPP_BIG_ENDIAN
enum {__short_mask = 0x80}; static const size_type __short_mask = 0x80;
enum {__long_mask = ~(size_type(~0) >> 1)}; static const size_type __long_mask = ~(size_type(~0) >> 1);
#endif // _LIBCPP_BIG_ENDIAN #endif // _LIBCPP_BIG_ENDIAN
enum {__min_cap = (sizeof(__long) - 1)/sizeof(value_type) > 2 ? enum {__min_cap = (sizeof(__long) - 1)/sizeof(value_type) > 2 ?
@ -706,11 +706,11 @@ private:
}; };
#if _LIBCPP_BIG_ENDIAN #if _LIBCPP_BIG_ENDIAN
enum {__short_mask = 0x80}; static const size_type __short_mask = 0x80;
enum {__long_mask = ~(size_type(~0) >> 1)}; static const size_type __long_mask = ~(size_type(~0) >> 1);
#else // _LIBCPP_BIG_ENDIAN #else // _LIBCPP_BIG_ENDIAN
enum {__short_mask = 0x01}; static const size_type __short_mask = 0x01;
enum {__long_mask = 0x1ul}; static const size_type __long_mask = 0x1ul;
#endif // _LIBCPP_BIG_ENDIAN #endif // _LIBCPP_BIG_ENDIAN
enum {__min_cap = (sizeof(__long) - 1)/sizeof(value_type) > 2 ? enum {__min_cap = (sizeof(__long) - 1)/sizeof(value_type) > 2 ?

View File

@ -355,8 +355,8 @@ if (LIBCXX_INSTALL_LIBRARY)
set(experimental_lib cxx_experimental) set(experimental_lib cxx_experimental)
endif() endif()
install(TARGETS ${LIBCXX_TARGETS} ${experimental_lib} install(TARGETS ${LIBCXX_TARGETS} ${experimental_lib}
LIBRARY DESTINATION lib${LIBCXX_LIBDIR_SUFFIX} COMPONENT cxx LIBRARY DESTINATION ${LIBCXX_INSTALL_PREFIX}lib${LIBCXX_LIBDIR_SUFFIX} COMPONENT cxx
ARCHIVE DESTINATION lib${LIBCXX_LIBDIR_SUFFIX} COMPONENT cxx ARCHIVE DESTINATION ${LIBCXX_INSTALL_PREFIX}lib${LIBCXX_LIBDIR_SUFFIX} COMPONENT cxx
) )
# NOTE: This install command must go after the cxx install command otherwise # NOTE: This install command must go after the cxx install command otherwise
# it will not be executed after the library symlinks are installed. # it will not be executed after the library symlinks are installed.
@ -364,7 +364,7 @@ if (LIBCXX_INSTALL_LIBRARY)
# Replace the libc++ filename with $<TARGET_LINKER_FILE:cxx> # Replace the libc++ filename with $<TARGET_LINKER_FILE:cxx>
# after we required CMake 3.0. # after we required CMake 3.0.
install(FILES "${LIBCXX_LIBRARY_DIR}/libc++${CMAKE_SHARED_LIBRARY_SUFFIX}" install(FILES "${LIBCXX_LIBRARY_DIR}/libc++${CMAKE_SHARED_LIBRARY_SUFFIX}"
DESTINATION lib${LIBCXX_LIBDIR_SUFFIX} DESTINATION ${LIBCXX_INSTALL_PREFIX}lib${LIBCXX_LIBDIR_SUFFIX}
COMPONENT libcxx) COMPONENT libcxx)
endif() endif()
endif() endif()

View File

@ -0,0 +1,173 @@
//===----------------------------------------------------------------------===////
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===////
#ifndef FILESYSTEM_TIME_HELPER_H
#define FILESYSTEM_TIME_HELPER_H
#include "experimental/__config"
#include "chrono"
#include "cstdlib"
#include "climits"
#include <unistd.h>
#include <sys/stat.h>
#if !defined(UTIME_OMIT)
#include <sys/time.h> // for ::utimes as used in __last_write_time
#endif
_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_FILESYSTEM
namespace time_detail { namespace {
using namespace chrono;
template <class FileTimeT,
bool IsFloat = is_floating_point<typename FileTimeT::rep>::value>
struct fs_time_util_base {
static constexpr auto max_seconds =
duration_cast<seconds>(FileTimeT::duration::max()).count();
static constexpr auto max_nsec =
duration_cast<nanoseconds>(FileTimeT::duration::max() -
seconds(max_seconds))
.count();
static constexpr auto min_seconds =
duration_cast<seconds>(FileTimeT::duration::min()).count();
static constexpr auto min_nsec_timespec =
duration_cast<nanoseconds>(
(FileTimeT::duration::min() - seconds(min_seconds)) + seconds(1))
.count();
// Static assert that these values properly round trip.
static_assert((seconds(min_seconds) +
duration_cast<microseconds>(nanoseconds(min_nsec_timespec))) -
duration_cast<microseconds>(seconds(1)) ==
FileTimeT::duration::min(),
"");
};
template <class FileTimeT>
struct fs_time_util_base<FileTimeT, true> {
static const long long max_seconds;
static const long long max_nsec;
static const long long min_seconds;
static const long long min_nsec_timespec;
};
template <class FileTimeT>
const long long fs_time_util_base<FileTimeT, true>::max_seconds =
duration_cast<seconds>(FileTimeT::duration::max()).count();
template <class FileTimeT>
const long long fs_time_util_base<FileTimeT, true>::max_nsec =
duration_cast<nanoseconds>(FileTimeT::duration::max() -
seconds(max_seconds))
.count();
template <class FileTimeT>
const long long fs_time_util_base<FileTimeT, true>::min_seconds =
duration_cast<seconds>(FileTimeT::duration::min()).count();
template <class FileTimeT>
const long long fs_time_util_base<FileTimeT, true>::min_nsec_timespec =
duration_cast<nanoseconds>((FileTimeT::duration::min() -
seconds(min_seconds)) +
seconds(1))
.count();
template <class FileTimeT, class TimeT, class TimeSpecT>
struct fs_time_util : fs_time_util_base<FileTimeT> {
using Base = fs_time_util_base<FileTimeT>;
using Base::max_nsec;
using Base::max_seconds;
using Base::min_nsec_timespec;
using Base::min_seconds;
public:
template <class CType, class ChronoType>
static bool checked_set(CType* out, ChronoType time) {
using Lim = numeric_limits<CType>;
if (time > Lim::max() || time < Lim::min())
return false;
*out = static_cast<CType>(time);
return true;
}
static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool is_representable(TimeSpecT tm) {
if (tm.tv_sec >= 0) {
return (tm.tv_sec < max_seconds) ||
(tm.tv_sec == max_seconds && tm.tv_nsec <= max_nsec);
} else if (tm.tv_sec == (min_seconds - 1)) {
return tm.tv_nsec >= min_nsec_timespec;
} else {
return (tm.tv_sec >= min_seconds);
}
}
static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool is_representable(FileTimeT tm) {
auto secs = duration_cast<seconds>(tm.time_since_epoch());
auto nsecs = duration_cast<nanoseconds>(tm.time_since_epoch() - secs);
if (nsecs.count() < 0) {
secs = secs + seconds(1);
nsecs = nsecs + seconds(1);
}
using TLim = numeric_limits<TimeT>;
if (secs.count() >= 0)
return secs.count() <= TLim::max();
return secs.count() >= TLim::min();
}
static _LIBCPP_CONSTEXPR_AFTER_CXX11 FileTimeT
convert_timespec(TimeSpecT tm) {
auto adj_msec = duration_cast<microseconds>(nanoseconds(tm.tv_nsec));
if (tm.tv_sec >= 0) {
auto Dur = seconds(tm.tv_sec) + microseconds(adj_msec);
return FileTimeT(Dur);
} else if (duration_cast<microseconds>(nanoseconds(tm.tv_nsec)).count() ==
0) {
return FileTimeT(seconds(tm.tv_sec));
} else { // tm.tv_sec < 0
auto adj_subsec =
duration_cast<microseconds>(seconds(1) - nanoseconds(tm.tv_nsec));
auto Dur = seconds(tm.tv_sec + 1) - adj_subsec;
return FileTimeT(Dur);
}
}
template <class SubSecDurT, class SubSecT>
static bool set_times_checked(TimeT* sec_out, SubSecT* subsec_out,
FileTimeT tp) {
using namespace chrono;
auto dur = tp.time_since_epoch();
auto sec_dur = duration_cast<seconds>(dur);
auto subsec_dur = duration_cast<SubSecDurT>(dur - sec_dur);
// The tv_nsec and tv_usec fields must not be negative so adjust accordingly
if (subsec_dur.count() < 0) {
if (sec_dur.count() > min_seconds) {
sec_dur -= seconds(1);
subsec_dur += seconds(1);
} else {
subsec_dur = SubSecDurT::zero();
}
}
return checked_set(sec_out, sec_dur.count()) &&
checked_set(subsec_out, subsec_dur.count());
}
};
} // end namespace
} // end namespace time_detail
using time_detail::fs_time_util;
_LIBCPP_END_NAMESPACE_EXPERIMENTAL_FILESYSTEM
#endif // FILESYSTEM_TIME_HELPER_H

View File

@ -15,6 +15,8 @@
#include "cstdlib" #include "cstdlib"
#include "climits" #include "climits"
#include "filesystem_time_helper.h"
#include <unistd.h> #include <unistd.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/statvfs.h> #include <sys/statvfs.h>
@ -426,17 +428,20 @@ void __current_path(const path& p, std::error_code *ec) {
bool __equivalent(const path& p1, const path& p2, std::error_code *ec) bool __equivalent(const path& p1, const path& p2, std::error_code *ec)
{ {
auto make_unsupported_error = [&]() {
set_or_throw(make_error_code(errc::not_supported), ec,
"equivalent", p1, p2);
return false;
};
std::error_code ec1, ec2; std::error_code ec1, ec2;
struct ::stat st1 = {}; struct ::stat st1 = {};
struct ::stat st2 = {}; struct ::stat st2 = {};
auto s1 = detail::posix_stat(p1.native(), st1, &ec1); auto s1 = detail::posix_stat(p1.native(), st1, &ec1);
if (!exists(s1))
return make_unsupported_error();
auto s2 = detail::posix_stat(p2.native(), st2, &ec2); auto s2 = detail::posix_stat(p2.native(), st2, &ec2);
if (!exists(s2))
if ((!exists(s1) && !exists(s2)) || (is_other(s1) && is_other(s2))) { return make_unsupported_error();
set_or_throw(make_error_code(errc::not_supported), ec,
"equivalent", p1, p2);
return false;
}
if (ec) ec->clear(); if (ec) ec->clear();
return (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino); return (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino);
} }
@ -502,17 +507,6 @@ bool __fs_is_empty(const path& p, std::error_code *ec)
namespace detail { namespace { namespace detail { namespace {
using namespace std::chrono;
template <class CType, class ChronoType>
bool checked_set(CType* out, ChronoType time) {
using Lim = numeric_limits<CType>;
if (time > Lim::max() || time < Lim::min())
return false;
*out = static_cast<CType>(time);
return true;
}
using TimeSpec = struct timespec; using TimeSpec = struct timespec;
using StatT = struct stat; using StatT = struct stat;
@ -525,137 +519,10 @@ __attribute__((unused)) // Suppress warning
TimeSpec extract_atime(StatT const& st) { return st.st_atim; } TimeSpec extract_atime(StatT const& st) { return st.st_atim; }
#endif #endif
constexpr auto max_seconds = duration_cast<seconds>(
file_time_type::duration::max()).count();
constexpr auto max_nsec = duration_cast<nanoseconds>(
file_time_type::duration::max() - seconds(max_seconds)).count();
constexpr auto min_seconds = duration_cast<seconds>(
file_time_type::duration::min()).count();
constexpr auto min_nsec_timespec = duration_cast<nanoseconds>(
(file_time_type::duration::min() - seconds(min_seconds)) + seconds(1)).count();
// Static assert that these values properly round trip.
static_assert((seconds(min_seconds) + duration_cast<microseconds>(nanoseconds(min_nsec_timespec)))
- duration_cast<microseconds>(seconds(1))
== file_time_type::duration::min(), "");
constexpr auto max_time_t = numeric_limits<time_t>::max();
constexpr auto min_time_t = numeric_limits<time_t>::min();
#if !defined(__LP64__) && defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wtautological-constant-out-of-range-compare"
#endif
_LIBCPP_CONSTEXPR_AFTER_CXX11
bool is_representable(TimeSpec const& tm) {
if (tm.tv_sec >= 0) {
return (tm.tv_sec < max_seconds) ||
(tm.tv_sec == max_seconds && tm.tv_nsec <= max_nsec);
} else if (tm.tv_sec == (min_seconds - 1)) {
return tm.tv_nsec >= min_nsec_timespec;
} else {
return (tm.tv_sec >= min_seconds);
}
}
#ifndef _LIBCPP_HAS_NO_CXX14_CONSTEXPR
#if defined(__LP64__)
static_assert(is_representable({max_seconds, max_nsec}), "");
static_assert(!is_representable({max_seconds + 1, 0}), "");
static_assert(!is_representable({max_seconds, max_nsec + 1}), "");
static_assert(!is_representable({max_time_t, 0}), "");
static_assert(is_representable({min_seconds, 0}), "");
static_assert(is_representable({min_seconds - 1, min_nsec_timespec}), "");
static_assert(is_representable({min_seconds - 1, min_nsec_timespec + 1}), "");
static_assert(!is_representable({min_seconds - 1, min_nsec_timespec - 1}), "");
static_assert(!is_representable({min_time_t, 999999999}), "");
#else
static_assert(is_representable({max_time_t, 999999999}), "");
static_assert(is_representable({max_time_t, 1000000000}), "");
static_assert(is_representable({min_time_t, 0}), "");
#endif
#endif
_LIBCPP_CONSTEXPR_AFTER_CXX11
bool is_representable(file_time_type const& tm) {
auto secs = duration_cast<seconds>(tm.time_since_epoch());
auto nsecs = duration_cast<nanoseconds>(tm.time_since_epoch() - secs);
if (nsecs.count() < 0) {
secs = secs + seconds(1);
nsecs = nsecs + seconds(1);
}
using TLim = numeric_limits<time_t>;
if (secs.count() >= 0)
return secs.count() <= TLim::max();
return secs.count() >= TLim::min();
}
#ifndef _LIBCPP_HAS_NO_CXX14_CONSTEXPR
#if defined(__LP64__)
static_assert(is_representable(file_time_type::max()), "");
static_assert(is_representable(file_time_type::min()), "");
#else
static_assert(!is_representable(file_time_type::max()), "");
static_assert(!is_representable(file_time_type::min()), "");
static_assert(is_representable(file_time_type(seconds(max_time_t))), "");
static_assert(is_representable(file_time_type(seconds(min_time_t))), "");
#endif
#endif
_LIBCPP_CONSTEXPR_AFTER_CXX11
file_time_type convert_timespec(TimeSpec const& tm) {
auto adj_msec = duration_cast<microseconds>(nanoseconds(tm.tv_nsec));
if (tm.tv_sec >= 0) {
auto Dur = seconds(tm.tv_sec) + microseconds(adj_msec);
return file_time_type(Dur);
} else if (duration_cast<microseconds>(nanoseconds(tm.tv_nsec)).count() == 0) {
return file_time_type(seconds(tm.tv_sec));
} else { // tm.tv_sec < 0
auto adj_subsec = duration_cast<microseconds>(seconds(1) - nanoseconds(tm.tv_nsec));
auto Dur = seconds(tm.tv_sec + 1) - adj_subsec;
return file_time_type(Dur);
}
}
#ifndef _LIBCPP_HAS_NO_CXX14_CONSTEXPR
#if defined(__LP64__)
static_assert(convert_timespec({max_seconds, max_nsec}) == file_time_type::max(), "");
static_assert(convert_timespec({max_seconds, max_nsec - 1}) < file_time_type::max(), "");
static_assert(convert_timespec({max_seconds - 1, 999999999}) < file_time_type::max(), "");
static_assert(convert_timespec({min_seconds - 1, min_nsec_timespec}) == file_time_type::min(), "");
static_assert(convert_timespec({min_seconds - 1, min_nsec_timespec + 1}) > file_time_type::min(), "");
static_assert(convert_timespec({min_seconds , 0}) > file_time_type::min(), "");
#else
// FIXME add tests for 32 bit builds
#endif
#endif
#if !defined(__LP64__) && defined(__clang__)
#pragma clang diagnostic pop
#endif
template <class SubSecDurT, class SubSecT>
bool set_times_checked(time_t* sec_out, SubSecT* subsec_out, file_time_type tp) {
using namespace chrono;
auto dur = tp.time_since_epoch();
auto sec_dur = duration_cast<seconds>(dur);
auto subsec_dur = duration_cast<SubSecDurT>(dur - sec_dur);
// The tv_nsec and tv_usec fields must not be negative so adjust accordingly
if (subsec_dur.count() < 0) {
if (sec_dur.count() > min_seconds) {
sec_dur -= seconds(1);
subsec_dur += seconds(1);
} else {
subsec_dur = SubSecDurT::zero();
}
}
return checked_set(sec_out, sec_dur.count())
&& checked_set(subsec_out, subsec_dur.count());
}
}} // end namespace detail }} // end namespace detail
using FSTime = fs_time_util<file_time_type, time_t, struct timespec>;
file_time_type __last_write_time(const path& p, std::error_code *ec) file_time_type __last_write_time(const path& p, std::error_code *ec)
{ {
using namespace ::std::chrono; using namespace ::std::chrono;
@ -668,12 +535,12 @@ file_time_type __last_write_time(const path& p, std::error_code *ec)
} }
if (ec) ec->clear(); if (ec) ec->clear();
auto ts = detail::extract_mtime(st); auto ts = detail::extract_mtime(st);
if (!detail::is_representable(ts)) { if (!FSTime::is_representable(ts)) {
set_or_throw(error_code(EOVERFLOW, generic_category()), ec, set_or_throw(error_code(EOVERFLOW, generic_category()), ec,
"last_write_time", p); "last_write_time", p);
return file_time_type::min(); return file_time_type::min();
} }
return detail::convert_timespec(ts); return FSTime::convert_timespec(ts);
} }
void __last_write_time(const path& p, file_time_type new_time, void __last_write_time(const path& p, file_time_type new_time,
@ -698,7 +565,7 @@ void __last_write_time(const path& p, file_time_type new_time,
struct ::timeval tbuf[2]; struct ::timeval tbuf[2];
tbuf[0].tv_sec = atime.tv_sec; tbuf[0].tv_sec = atime.tv_sec;
tbuf[0].tv_usec = duration_cast<microseconds>(nanoseconds(atime.tv_nsec)).count(); tbuf[0].tv_usec = duration_cast<microseconds>(nanoseconds(atime.tv_nsec)).count();
const bool overflowed = !detail::set_times_checked<microseconds>( const bool overflowed = !FSTime::set_times_checked<microseconds>(
&tbuf[1].tv_sec, &tbuf[1].tv_usec, new_time); &tbuf[1].tv_sec, &tbuf[1].tv_usec, new_time);
if (overflowed) { if (overflowed) {
@ -714,7 +581,7 @@ void __last_write_time(const path& p, file_time_type new_time,
tbuf[0].tv_sec = 0; tbuf[0].tv_sec = 0;
tbuf[0].tv_nsec = UTIME_OMIT; tbuf[0].tv_nsec = UTIME_OMIT;
const bool overflowed = !detail::set_times_checked<nanoseconds>( const bool overflowed = !FSTime::set_times_checked<nanoseconds>(
&tbuf[1].tv_sec, &tbuf[1].tv_nsec, new_time); &tbuf[1].tv_sec, &tbuf[1].tv_nsec, new_time);
if (overflowed) { if (overflowed) {
set_or_throw(make_error_code(errc::invalid_argument), set_or_throw(make_error_code(errc::invalid_argument),

View File

@ -7,8 +7,8 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#ifndef _LIBCPP___REFSTRING #ifndef _LIBCPP_REFSTRING_H
#define _LIBCPP___REFSTRING #define _LIBCPP_REFSTRING_H
#include <__config> #include <__config>
#include <stdexcept> #include <stdexcept>
@ -124,4 +124,4 @@ bool __libcpp_refstring::__uses_refcount() const {
_LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
#endif //_LIBCPP___REFSTRING #endif //_LIBCPP_REFSTRING_H

View File

@ -11,7 +11,7 @@
#include "new" #include "new"
#include "string" #include "string"
#include "system_error" #include "system_error"
#include "__refstring" #include "include/refstring.h"
/* For _LIBCPPABI_VERSION */ /* For _LIBCPPABI_VERSION */
#if !defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY) && \ #if !defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY) && \

View File

@ -85,3 +85,36 @@ if (LIBCXX_GENERATE_COVERAGE)
set(extract_dirs "${LIBCXX_SOURCE_DIR}/include;${LIBCXX_SOURCE_DIR}/src") set(extract_dirs "${LIBCXX_SOURCE_DIR}/include;${LIBCXX_SOURCE_DIR}/src")
setup_lcov_test_target_coverage("cxx" "${output_dir}" "${capture_dirs}" "${extract_dirs}") setup_lcov_test_target_coverage("cxx" "${output_dir}" "${capture_dirs}" "${extract_dirs}")
endif() endif()
if (LIBCXX_CONFIGURE_IDE)
# Create dummy targets for each of the tests in the test suite, this allows
# IDE's such as CLion to correctly highlight the tests because it knows
# roughly what include paths/compile flags/macro definitions are needed.
include_directories(support)
file(GLOB_RECURSE LIBCXX_TESTS ${CMAKE_CURRENT_SOURCE_DIR}/*.pass.cpp)
file(GLOB LIBCXX_TEST_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/support/*)
file(GLOB_RECURSE LIBCXX_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/../include/*)
add_executable(libcxx_test_objects EXCLUDE_FROM_ALL
${LIBCXX_TESTS} ${LIBCXX_TEST_HEADERS} ${LIBCXX_HEADERS})
add_dependencies(libcxx_test_objects cxx)
set(STATIC_ROOT ${LIBCXX_SOURCE_DIR}/test/std/experimental/filesystem/Inputs/static_test_env)
add_definitions(-DLIBCXX_FILESYSTEM_STATIC_TEST_ROOT="${STATIC_ROOT}")
set(DYNAMIC_ROOT ${LIBCXX_BINARY_DIR}/test/filesystem/Output/dynamic_env)
add_definitions(-DLIBCXX_FILESYSTEM_DYNAMIC_TEST_ROOT="${DYNAMIC_ROOT}")
set(DYNAMIC_HELPER "python ${LIBCXX_SOURCE_DIR}/test/support/filesystem_dynamic_test_helper.py ")
add_definitions(-DLIBCXX_FILESYSTEM_DYNAMIC_TEST_HELPER="${DYNAMIC_HELPER}")
split_list(LIBCXX_COMPILE_FLAGS)
split_list(LIBCXX_LINK_FLAGS)
set_target_properties(libcxx_test_objects
PROPERTIES
COMPILE_FLAGS "${LIBCXX_COMPILE_FLAGS}"
LINK_FLAGS "${LIBCXX_LINK_FLAGS}"
EXCLUDE_FROM_ALL ON
)
endif()

View File

@ -16,7 +16,7 @@
// UNSUPPORTED: c++98, c++03, c++11 // UNSUPPORTED: c++98, c++03, c++11
// The sanitizers replace new/delete with versions that do not throw bad_alloc. // The sanitizers replace new/delete with versions that do not throw bad_alloc.
// UNSUPPORTED: sanitizer-new-delete, ubsan // UNSUPPORTED: sanitizer-new-delete
#include <experimental/dynarray> #include <experimental/dynarray>

View File

@ -0,0 +1,200 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11
// <experimental/filesystem>
// typedef TrivialClock file_time_type;
// RUN: %build -I%libcxx_src_root/src/experimental/filesystem
// RUN: %run
#include <experimental/filesystem>
#include <chrono>
#include <type_traits>
#include <limits>
#include <cstddef>
#include <cassert>
#include "filesystem_time_helper.h"
using namespace std::chrono;
namespace fs = std::experimental::filesystem;
using fs::file_time_type;
using fs::fs_time_util;
enum TestKind { TK_64Bit, TK_32Bit, TK_FloatingPoint };
template <class FileTimeT, class TimeT, class TimeSpec>
constexpr TestKind getTestKind() {
if (sizeof(TimeT) == 8 && !std::is_floating_point<TimeT>::value)
return TK_64Bit;
else if (sizeof(TimeT) == 4 && !std::is_floating_point<TimeT>::value)
return TK_32Bit;
else if (std::is_floating_point<TimeT>::value)
return TK_FloatingPoint;
else
assert(false && "test kind not supported");
}
template <class FileTimeT, class TimeT, class TimeSpecT,
class Base = fs_time_util<FileTimeT, TimeT, TimeSpecT>,
TestKind = getTestKind<FileTimeT, TimeT, TimeSpecT>()>
struct check_is_representable;
template <class FileTimeT, class TimeT, class TimeSpecT, class Base>
struct check_is_representable<FileTimeT, TimeT, TimeSpecT, Base, TK_64Bit>
: public Base {
using Base::convert_timespec;
using Base::is_representable;
using Base::max_nsec;
using Base::max_seconds;
using Base::min_nsec_timespec;
using Base::min_seconds;
static constexpr auto max_time_t = std::numeric_limits<TimeT>::max();
static constexpr auto min_time_t = std::numeric_limits<TimeT>::min();
static constexpr bool test_timespec() {
static_assert(is_representable(TimeSpecT{max_seconds, max_nsec}), "");
static_assert(!is_representable(TimeSpecT{max_seconds + 1, 0}), "");
static_assert(!is_representable(TimeSpecT{max_seconds, max_nsec + 1}), "");
static_assert(!is_representable(TimeSpecT{max_time_t, 0}), "");
static_assert(is_representable(TimeSpecT{min_seconds, 0}), "");
static_assert(
is_representable(TimeSpecT{min_seconds - 1, min_nsec_timespec}), "");
static_assert(
is_representable(TimeSpecT{min_seconds - 1, min_nsec_timespec + 1}),
"");
static_assert(
!is_representable(TimeSpecT{min_seconds - 1, min_nsec_timespec - 1}),
"");
static_assert(!is_representable(TimeSpecT{min_time_t, 999999999}), "");
return true;
}
static constexpr bool test_file_time_type() {
static_assert(Base::is_representable(FileTimeT::max()), "");
static_assert(Base::is_representable(FileTimeT::min()), "");
return true;
}
static constexpr bool test_convert_timespec() {
static_assert(convert_timespec(TimeSpecT{max_seconds, max_nsec}) ==
FileTimeT::max(),
"");
static_assert(convert_timespec(TimeSpecT{max_seconds, max_nsec - 1}) <
FileTimeT::max(),
"");
static_assert(convert_timespec(TimeSpecT{max_seconds - 1, 999999999}) <
FileTimeT::max(),
"");
static_assert(convert_timespec(TimeSpecT{
min_seconds - 1, min_nsec_timespec}) == FileTimeT::min(),
"");
static_assert(
convert_timespec(TimeSpecT{min_seconds - 1, min_nsec_timespec + 1}) >
FileTimeT::min(),
"");
static_assert(
convert_timespec(TimeSpecT{min_seconds, 0}) > FileTimeT::min(), "");
return true;
}
static bool test() {
static_assert(test_timespec(), "");
static_assert(test_file_time_type(), "");
static_assert(test_convert_timespec(), "");
return true;
}
};
template <class FileTimeT, class TimeT, class TimeSpecT, class Base>
struct check_is_representable<FileTimeT, TimeT, TimeSpecT, Base, TK_32Bit>
: public Base {
static constexpr auto max_time_t = std::numeric_limits<TimeT>::max();
static constexpr auto min_time_t = std::numeric_limits<TimeT>::min();
using Base::convert_timespec;
using Base::is_representable;
using Base::max_nsec;
using Base::max_seconds;
using Base::min_nsec_timespec;
using Base::min_seconds;
static constexpr bool test_timespec() {
static_assert(is_representable(TimeSpecT{max_time_t, 999999999}), "");
static_assert(is_representable(TimeSpecT{max_time_t, 1000000000}), "");
static_assert(is_representable(TimeSpecT{min_time_t, 0}), "");
return true;
}
static constexpr bool test_file_time_type() {
static_assert(!is_representable(FileTimeT::max()), "");
static_assert(!is_representable(FileTimeT::min()), "");
static_assert(is_representable(FileTimeT(seconds(max_time_t))), "");
static_assert(is_representable(FileTimeT(seconds(min_time_t))), "");
return true;
}
static constexpr bool test_convert_timespec() {
// FIXME add tests for 32 bit builds
return true;
}
static bool test() {
static_assert(test_timespec(), "");
static_assert(test_file_time_type(), "");
static_assert(test_convert_timespec(), "");
return true;
}
};
template <class FileTimeT, class TimeT, class TimeSpec, class Base>
struct check_is_representable<FileTimeT, TimeT, TimeSpec, Base,
TK_FloatingPoint> : public Base {
static bool test() { return true; }
};
template <class TimeT, class NSecT = long>
struct TestTimeSpec {
TimeT tv_sec;
NSecT tv_nsec;
};
template <class Dur>
struct TestClock {
typedef Dur duration;
typedef typename duration::rep rep;
typedef typename duration::period period;
typedef std::chrono::time_point<TestClock> time_point;
static constexpr const bool is_steady = false;
static time_point now() noexcept { return {}; }
};
template <class IntType, class Dur = duration<IntType, std::micro> >
using TestFileTimeT = time_point<TestClock<Dur> >;
int main() {
assert((
check_is_representable<file_time_type, time_t, struct timespec>::test()));
assert((check_is_representable<TestFileTimeT<int64_t>, int64_t,
TestTimeSpec<int64_t, long> >::test()));
assert((check_is_representable<TestFileTimeT<long long>, int32_t,
TestTimeSpec<int32_t, int32_t> >::test()));
// Test that insane platforms like ppc64 linux, which use long double as time_t,
// at least compile.
assert((check_is_representable<TestFileTimeT<long double>, double,
TestTimeSpec<long double, long> >::test()));
}

View File

@ -23,9 +23,9 @@
#include <cmath> #include <cmath>
static_assert(std::__libcpp_isnan(0.) == false, ""); static_assert(std::__libcpp_isnan_or_builtin(0.) == false, "");
static_assert(std::__libcpp_isinf(0.0) == false, ""); static_assert(std::__libcpp_isinf_or_builtin(0.0) == false, "");
static_assert(std::__libcpp_isfinite(0.0) == true, ""); static_assert(std::__libcpp_isfinite_or_builtin(0.0) == true, "");
int main() int main()
{ {

View File

@ -0,0 +1,28 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// test that cmath builds with -fdelayed-template-parsing
// REQUIRES: fdelayed-template-parsing
// RUN: %build -fdelayed-template-parsing
// RUN: %run
#include <cmath>
#include <cassert>
#include "test_macros.h"
int main() {
assert(std::isfinite(1.0));
assert(!std::isinf(1.0));
assert(!std::isnan(1.0));
}
using namespace std;

View File

@ -1,66 +0,0 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03, c++11, c++14
// <optional>
#include <optional>
#include <type_traits>
#include <cassert>
#include "archetypes.hpp"
template <class T>
struct SpecialMemberTest {
using O = std::optional<T>;
template <template <class> class TestMF>
static constexpr bool check_same() {
return TestMF<O>::value == TestMF<T>::value;
}
// Test that optional inherits the correct trivial/non-trivial members
static_assert(check_same<std::is_trivially_destructible>(), "");
static_assert(check_same<std::is_trivially_copyable>(), "");
};
template <class ...Args> static void sink(Args&&...) {}
template <class ...TestTypes>
struct DoTestsMetafunction {
DoTestsMetafunction() { sink(SpecialMemberTest<TestTypes>{}...); }
};
struct TrivialMoveNonTrivialCopy {
TrivialMoveNonTrivialCopy() = default;
TrivialMoveNonTrivialCopy(const TrivialMoveNonTrivialCopy&) {}
TrivialMoveNonTrivialCopy(TrivialMoveNonTrivialCopy&&) = default;
TrivialMoveNonTrivialCopy& operator=(const TrivialMoveNonTrivialCopy&) { return *this; }
TrivialMoveNonTrivialCopy& operator=(TrivialMoveNonTrivialCopy&&) = default;
};
struct TrivialCopyNonTrivialMove {
TrivialCopyNonTrivialMove() = default;
TrivialCopyNonTrivialMove(const TrivialCopyNonTrivialMove&) = default;
TrivialCopyNonTrivialMove(TrivialCopyNonTrivialMove&&) {}
TrivialCopyNonTrivialMove& operator=(const TrivialCopyNonTrivialMove&) = default;
TrivialCopyNonTrivialMove& operator=(TrivialCopyNonTrivialMove&&) { return *this; }
};
int main()
{
sink(
ImplicitTypes::ApplyTypes<DoTestsMetafunction>{},
ExplicitTypes::ApplyTypes<DoTestsMetafunction>{},
NonLiteralTypes::ApplyTypes<DoTestsMetafunction>{},
NonTrivialTypes::ApplyTypes<DoTestsMetafunction>{},
DoTestsMetafunction<TrivialMoveNonTrivialCopy, TrivialCopyNonTrivialMove>{}
);
}

View File

@ -25,6 +25,40 @@ template <typename T> void checkAlwaysLockFree() {
assert(std::atomic<T>().is_lock_free()); assert(std::atomic<T>().is_lock_free());
} }
// FIXME: This separate test is needed to work around llvm.org/PR31864
// which causes ATOMIC_LLONG_LOCK_FREE to be defined as '1' in 32-bit builds
// even though __atomic_always_lock_free returns true for the same type.
constexpr bool NeedWorkaroundForPR31864 =
#if defined(__clang__)
(sizeof(void*) == 4); // Needed on 32 bit builds
#else
false;
#endif
template <bool Disable = NeedWorkaroundForPR31864,
std::enable_if_t<!Disable>* = nullptr,
class LLong = long long,
class ULLong = unsigned long long>
void checkLongLongTypes() {
static_assert(std::atomic<LLong>::is_always_lock_free == (2 == ATOMIC_LLONG_LOCK_FREE));
static_assert(std::atomic<ULLong>::is_always_lock_free == (2 == ATOMIC_LLONG_LOCK_FREE));
}
// Used to make the calls to __atomic_always_lock_free dependent on a template
// parameter.
template <class T> constexpr size_t getSizeOf() { return sizeof(T); }
template <bool Enable = NeedWorkaroundForPR31864,
std::enable_if_t<Enable>* = nullptr,
class LLong = long long,
class ULLong = unsigned long long>
void checkLongLongTypes() {
constexpr bool ExpectLockFree = __atomic_always_lock_free(getSizeOf<LLong>(), 0);
static_assert(std::atomic<LLong>::is_always_lock_free == ExpectLockFree, "");
static_assert(std::atomic<ULLong>::is_always_lock_free == ExpectLockFree, "");
static_assert((0 != ATOMIC_LLONG_LOCK_FREE) == ExpectLockFree, "");
}
int main() int main()
{ {
// structs and unions can't be defined in the template invocation. // structs and unions can't be defined in the template invocation.
@ -94,8 +128,7 @@ int main()
static_assert(std::atomic<unsigned int>::is_always_lock_free == (2 == ATOMIC_INT_LOCK_FREE)); static_assert(std::atomic<unsigned int>::is_always_lock_free == (2 == ATOMIC_INT_LOCK_FREE));
static_assert(std::atomic<long>::is_always_lock_free == (2 == ATOMIC_LONG_LOCK_FREE)); static_assert(std::atomic<long>::is_always_lock_free == (2 == ATOMIC_LONG_LOCK_FREE));
static_assert(std::atomic<unsigned long>::is_always_lock_free == (2 == ATOMIC_LONG_LOCK_FREE)); static_assert(std::atomic<unsigned long>::is_always_lock_free == (2 == ATOMIC_LONG_LOCK_FREE));
static_assert(std::atomic<long long>::is_always_lock_free == (2 == ATOMIC_LLONG_LOCK_FREE)); checkLongLongTypes();
static_assert(std::atomic<unsigned long long>::is_always_lock_free == (2 == ATOMIC_LLONG_LOCK_FREE));
static_assert(std::atomic<void*>::is_always_lock_free == (2 == ATOMIC_POINTER_LOCK_FREE)); static_assert(std::atomic<void*>::is_always_lock_free == (2 == ATOMIC_POINTER_LOCK_FREE));
static_assert(std::atomic<std::nullptr_t>::is_always_lock_free == (2 == ATOMIC_POINTER_LOCK_FREE)); static_assert(std::atomic<std::nullptr_t>::is_always_lock_free == (2 == ATOMIC_POINTER_LOCK_FREE));
} }

View File

@ -26,63 +26,87 @@ using namespace std::experimental::filesystem;
TEST_SUITE(equivalent_test_suite) TEST_SUITE(equivalent_test_suite)
TEST_CASE(signature_test) TEST_CASE(signature_test) {
{ const path p;
const path p; ((void)p); ((void)p);
std::error_code ec; ((void)ec); std::error_code ec;
ASSERT_NOEXCEPT(equivalent(p, p, ec)); ((void)ec);
ASSERT_NOT_NOEXCEPT(equivalent(p, p)); ASSERT_NOEXCEPT(equivalent(p, p, ec));
ASSERT_NOT_NOEXCEPT(equivalent(p, p));
} }
TEST_CASE(equivalent_test) TEST_CASE(equivalent_test) {
{ struct TestCase {
struct TestCase { path lhs;
path lhs; path rhs;
path rhs; bool expect;
bool expect; };
}; const TestCase testCases[] = {
const TestCase testCases[] = { {StaticEnv::Dir, StaticEnv::Dir, true},
{StaticEnv::Dir, StaticEnv::Dir, true}, {StaticEnv::File, StaticEnv::Dir, false},
{StaticEnv::File, StaticEnv::Dir, false}, {StaticEnv::Dir, StaticEnv::SymlinkToDir, true},
{StaticEnv::Dir, StaticEnv::SymlinkToDir, true}, {StaticEnv::Dir, StaticEnv::SymlinkToFile, false},
{StaticEnv::Dir, StaticEnv::SymlinkToFile, false}, {StaticEnv::File, StaticEnv::File, true},
{StaticEnv::File, StaticEnv::File, true}, {StaticEnv::File, StaticEnv::SymlinkToFile, true},
{StaticEnv::File, StaticEnv::SymlinkToFile, true}, };
}; for (auto& TC : testCases) {
for (auto& TC : testCases) { std::error_code ec;
std::error_code ec; TEST_CHECK(equivalent(TC.lhs, TC.rhs, ec) == TC.expect);
TEST_CHECK(equivalent(TC.lhs, TC.rhs, ec) == TC.expect); TEST_CHECK(!ec);
TEST_CHECK(!ec); }
}
} }
TEST_CASE(equivalent_reports_double_dne) TEST_CASE(equivalent_reports_error_if_input_dne) {
{ const path E = StaticEnv::File;
const path E = StaticEnv::File; const path DNE = StaticEnv::DNE;
const path DNE = StaticEnv::DNE; { // Test that an error is reported when either of the paths don't exist
{ // Test that no exception is thrown if one of the paths exists std::error_code ec = GetTestEC();
TEST_CHECK(equivalent(E, DNE) == false); TEST_CHECK(equivalent(E, DNE, ec) == false);
TEST_CHECK(equivalent(DNE, E) == false); TEST_CHECK(ec);
} TEST_CHECK(ec != GetTestEC());
{ // Test that an exception is thrown if both paths do not exist. }
TEST_CHECK_THROW(filesystem_error, equivalent(DNE, DNE)); {
} std::error_code ec = GetTestEC();
{ TEST_CHECK(equivalent(DNE, E, ec) == false);
std::error_code ec; TEST_CHECK(ec);
TEST_CHECK(equivalent(DNE, DNE, ec) == false); TEST_CHECK(ec != GetTestEC());
TEST_CHECK(ec); }
} {
TEST_CHECK_THROW(filesystem_error, equivalent(DNE, E));
TEST_CHECK_THROW(filesystem_error, equivalent(E, DNE));
}
{ // Test that an exception is thrown if both paths do not exist.
TEST_CHECK_THROW(filesystem_error, equivalent(DNE, DNE));
}
{
std::error_code ec = GetTestEC();
TEST_CHECK(equivalent(DNE, DNE, ec) == false);
TEST_CHECK(ec);
TEST_CHECK(ec != GetTestEC());
}
} }
TEST_CASE(equivalent_is_other_succeeds) TEST_CASE(equivalent_hardlink_succeeds) {
{ scoped_test_env env;
scoped_test_env env; path const file = env.create_file("file", 42);
path const file = env.create_file("file", 42); const path hl1 = env.create_hardlink(file, "hl1");
const path hl1 = env.create_hardlink(file, "hl1"); const path hl2 = env.create_hardlink(file, "hl2");
const path hl2 = env.create_hardlink(file, "hl2"); TEST_CHECK(equivalent(file, hl1));
TEST_CHECK(equivalent(file, hl1)); TEST_CHECK(equivalent(file, hl2));
TEST_CHECK(equivalent(file, hl2)); TEST_CHECK(equivalent(hl1, hl2));
TEST_CHECK(equivalent(hl1, hl2)); }
TEST_CASE(equivalent_is_other_succeeds) {
scoped_test_env env;
path const file = env.create_file("file", 42);
const path fifo1 = env.create_fifo("fifo1");
const path fifo2 = env.create_fifo("fifo2");
// Required to test behavior for inputs where is_other(p) is true.
TEST_REQUIRE(is_other(fifo1));
TEST_CHECK(!equivalent(file, fifo1));
TEST_CHECK(!equivalent(fifo2, file));
TEST_CHECK(!equivalent(fifo1, fifo2));
TEST_CHECK(equivalent(fifo1, fifo1));
} }
TEST_SUITE_END() TEST_SUITE_END()

View File

@ -95,4 +95,22 @@ int main()
assert((*i2).position() == 0); assert((*i2).position() == 0);
assert((*i2).str() == "555-1234"); assert((*i2).str() == "555-1234");
} }
{ // http://llvm.org/PR33681
std::regex rex(".*");
const char foo[] = "foo";
// The -1 is because we don't want the implicit null from the array.
std::cregex_iterator i(std::begin(foo), std::end(foo) - 1, rex);
std::cregex_iterator e;
assert(i != e);
assert((*i).size() == 1);
assert((*i).str() == "foo");
++i;
assert(i != e);
assert((*i).size() == 1);
assert((*i).str() == "");
++i;
assert(i == e);
}
} }

View File

@ -30,5 +30,5 @@ typedef volatile std::packaged_task<A(int, char)> VPT;
int main() int main()
{ {
PT p { std::allocator_arg_t{}, test_allocator<A>{}, VPT {}}; // expected-error {{no matching constructor for initialization of 'PT' (aka 'packaged_task<A (int, char)>')}} PT p { std::allocator_arg_t{}, test_allocator<A>{}, VPT {}}; // expected-error {{no matching constructor for initialization of 'PT' (aka 'packaged_task<A (int, char)>')}}
// expected-note@future:* 1 {{candidate template ignored: disabled by 'enable_if'}} // expected-note-re@future:* 1 {{candidate template ignored: {{(disabled by 'enable_if')|(requirement '.*' was not satisfied)}}}}
} }

View File

@ -29,11 +29,12 @@ struct A
int main() int main()
{ {
globalMemCounter.reset();
std::allocator<A> a; std::allocator<A> a;
assert(globalMemCounter.checkOutstandingNewEq(0)); assert(globalMemCounter.checkOutstandingNewEq(0));
assert(A_constructed == 0); assert(A_constructed == 0);
globalMemCounter.last_new_size = 0; globalMemCounter.last_new_size = 0;
A* ap = a.allocate(3); A* volatile ap = a.allocate(3);
assert(globalMemCounter.checkOutstandingNewEq(1)); assert(globalMemCounter.checkOutstandingNewEq(1));
assert(globalMemCounter.checkLastNewSizeEq(3 * sizeof(int))); assert(globalMemCounter.checkLastNewSizeEq(3 * sizeof(int)));
assert(A_constructed == 0); assert(A_constructed == 0);
@ -42,7 +43,7 @@ int main()
assert(A_constructed == 0); assert(A_constructed == 0);
globalMemCounter.last_new_size = 0; globalMemCounter.last_new_size = 0;
A* ap2 = a.allocate(3, (const void*)5); A* volatile ap2 = a.allocate(3, (const void*)5);
assert(globalMemCounter.checkOutstandingNewEq(1)); assert(globalMemCounter.checkOutstandingNewEq(1));
assert(globalMemCounter.checkLastNewSizeEq(3 * sizeof(int))); assert(globalMemCounter.checkLastNewSizeEq(3 * sizeof(int)));
assert(A_constructed == 0); assert(A_constructed == 0);

View File

@ -147,27 +147,27 @@ int main()
} }
{ {
struct ThrowsMove { struct ThrowsMove {
ThrowsMove() noexcept {} ThrowsMove() noexcept {}
ThrowsMove(ThrowsMove const&) noexcept {} ThrowsMove(ThrowsMove const&) noexcept {}
ThrowsMove(ThrowsMove &&) noexcept(false) {} ThrowsMove(ThrowsMove &&) noexcept(false) {}
ThrowsMove& operator=(ThrowsMove const&) noexcept { return *this; } ThrowsMove& operator=(ThrowsMove const&) noexcept { return *this; }
ThrowsMove& operator=(ThrowsMove &&) noexcept { return *this; } ThrowsMove& operator=(ThrowsMove &&) noexcept { return *this; }
}; };
static_assert(!std::is_nothrow_move_assignable<optional<ThrowsMove>>::value, ""); static_assert(!std::is_nothrow_move_assignable<optional<ThrowsMove>>::value, "");
struct ThrowsMoveAssign { struct ThrowsMoveAssign {
ThrowsMoveAssign() noexcept {} ThrowsMoveAssign() noexcept {}
ThrowsMoveAssign(ThrowsMoveAssign const&) noexcept {} ThrowsMoveAssign(ThrowsMoveAssign const&) noexcept {}
ThrowsMoveAssign(ThrowsMoveAssign &&) noexcept {} ThrowsMoveAssign(ThrowsMoveAssign &&) noexcept {}
ThrowsMoveAssign& operator=(ThrowsMoveAssign const&) noexcept { return *this; } ThrowsMoveAssign& operator=(ThrowsMoveAssign const&) noexcept { return *this; }
ThrowsMoveAssign& operator=(ThrowsMoveAssign &&) noexcept(false) { return *this; } ThrowsMoveAssign& operator=(ThrowsMoveAssign &&) noexcept(false) { return *this; }
}; };
static_assert(!std::is_nothrow_move_assignable<optional<ThrowsMoveAssign>>::value, ""); static_assert(!std::is_nothrow_move_assignable<optional<ThrowsMoveAssign>>::value, "");
struct NoThrowMove { struct NoThrowMove {
NoThrowMove() noexcept(false) {} NoThrowMove() noexcept(false) {}
NoThrowMove(NoThrowMove const&) noexcept(false) {} NoThrowMove(NoThrowMove const&) noexcept(false) {}
NoThrowMove(NoThrowMove &&) noexcept {} NoThrowMove(NoThrowMove &&) noexcept {}
NoThrowMove& operator=(NoThrowMove const&) noexcept { return *this; } NoThrowMove& operator=(NoThrowMove const&) noexcept { return *this; }
NoThrowMove& operator=(NoThrowMove&&) noexcept { return *this; } NoThrowMove& operator=(NoThrowMove&&) noexcept { return *this; }
}; };
static_assert(std::is_nothrow_move_assignable<optional<NoThrowMove>>::value, ""); static_assert(std::is_nothrow_move_assignable<optional<NoThrowMove>>::value, "");
} }

View File

@ -45,10 +45,10 @@ constexpr bool constexpr_test(InitArgs&&... args)
void test_throwing_ctor() { void test_throwing_ctor() {
#ifndef TEST_HAS_NO_EXCEPTIONS #ifndef TEST_HAS_NO_EXCEPTIONS
struct Z { struct Z {
Z() : count(0) {} Z() : count(0) {}
Z(Z const& o) : count(o.count + 1) Z(Z const& o) : count(o.count + 1)
{ if (count == 2) throw 6; } { if (count == 2) throw 6; }
int count; int count;
}; };
const Z z; const Z z;
const optional<Z> rhs(z); const optional<Z> rhs(z);

View File

@ -55,10 +55,10 @@ constexpr bool constexpr_test(InitArgs&&... args)
void test_throwing_ctor() { void test_throwing_ctor() {
#ifndef TEST_HAS_NO_EXCEPTIONS #ifndef TEST_HAS_NO_EXCEPTIONS
struct Z { struct Z {
Z() : count(0) {} Z() : count(0) {}
Z(Z&& o) : count(o.count + 1) Z(Z&& o) : count(o.count + 1)
{ if (count == 2) throw 6; } { if (count == 2) throw 6; }
int count; int count;
}; };
Z z; Z z;
optional<Z> rhs(std::move(z)); optional<Z> rhs(std::move(z));

View File

@ -33,10 +33,38 @@ struct SpecialMemberTest {
"optional<T> is copy assignable if and only if T is both copy " "optional<T> is copy assignable if and only if T is both copy "
"constructible and copy assignable."); "constructible and copy assignable.");
static_assert(std::is_move_assignable_v<O> == static_assert(std::is_move_assignable_v<O> ==
((std::is_copy_constructible_v<T> && std::is_copy_assignable_v<T>) || ((std::is_move_constructible_v<T> && std::is_move_assignable_v<T>) ||
(std::is_move_constructible_v<T> && std::is_move_assignable_v<T>)), (std::is_copy_constructible_v<T> && std::is_copy_assignable_v<T>)),
"optional<T> is move assignable if and only if T is both move assignable and " "optional<T> is move assignable if and only if T is both move constructible and "
"move constructible, or both copy constructible and copy assignable."); "move assignable, or both copy constructible and copy assignable.");
// The following tests are for not-yet-standardized behavior (P0602):
static_assert(std::is_trivially_destructible_v<O> ==
std::is_trivially_destructible_v<T>,
"optional<T> is trivially destructible if and only if T is.");
static_assert(std::is_trivially_copy_constructible_v<O> ==
std::is_trivially_copy_constructible_v<T>,
"optional<T> is trivially copy constructible if and only if T is.");
static_assert(std::is_trivially_move_constructible_v<O> ==
std::is_trivially_move_constructible_v<T> ||
(!std::is_move_constructible_v<T> && std::is_trivially_copy_constructible_v<T>),
"optional<T> is trivially move constructible if T is trivially move constructible, "
"or if T is trivially copy constructible and is not move constructible.");
static_assert(std::is_trivially_copy_assignable_v<O> ==
(std::is_trivially_destructible_v<T> &&
std::is_trivially_copy_constructible_v<T> &&
std::is_trivially_copy_assignable_v<T>),
"optional<T> is trivially copy assignable if and only if T is trivially destructible, "
"trivially copy constructible, and trivially copy assignable.");
static_assert(std::is_trivially_move_assignable_v<O> ==
(std::is_trivially_destructible_v<T> &&
((std::is_trivially_move_constructible_v<T> && std::is_trivially_move_assignable_v<T>) ||
((!std::is_move_constructible_v<T> || !std::is_move_assignable_v<T>) &&
std::is_trivially_copy_constructible_v<T> && std::is_trivially_copy_assignable_v<T>))),
"optional<T> is trivially move assignable if T is trivially destructible, and either "
"(1) trivially move constructible and trivially move assignable, or "
"(2) not move constructible or not move assignable, and "
"trivially copy constructible and trivially copy assignable.");
}; };
template <class ...Args> static void sink(Args&&...) {} template <class ...Args> static void sink(Args&&...) {}

View File

@ -440,6 +440,9 @@ class Configuration(object):
# C++17 aligned allocation. # C++17 aligned allocation.
self.config.available_features.add('no-aligned-allocation') self.config.available_features.add('no-aligned-allocation')
if self.cxx.hasCompileFlag('-fdelayed-template-parsing'):
self.config.available_features.add('fdelayed-template-parsing')
if self.get_lit_bool('has_libatomic', False): if self.get_lit_bool('has_libatomic', False):
self.config.available_features.add('libatomic') self.config.available_features.add('libatomic')
@ -888,6 +891,7 @@ class Configuration(object):
self.cxx.addWarningFlagIfSupported('-Wno-c++11-extensions') self.cxx.addWarningFlagIfSupported('-Wno-c++11-extensions')
self.cxx.addWarningFlagIfSupported('-Wno-user-defined-literals') self.cxx.addWarningFlagIfSupported('-Wno-user-defined-literals')
self.cxx.addWarningFlagIfSupported('-Wno-noexcept-type') self.cxx.addWarningFlagIfSupported('-Wno-noexcept-type')
self.cxx.addWarningFlagIfSupported('-Wno-aligned-allocation-unavailable')
# These warnings should be enabled in order to support the MSVC # These warnings should be enabled in order to support the MSVC
# team using the test suite; They enable the warnings below and # team using the test suite; They enable the warnings below and
# expect the test suite to be clean. # expect the test suite to be clean.
@ -1015,6 +1019,7 @@ class Configuration(object):
cxx_path = pipes.quote(self.cxx.path) cxx_path = pipes.quote(self.cxx.path)
# Configure compiler substitutions # Configure compiler substitutions
sub.append(('%cxx', cxx_path)) sub.append(('%cxx', cxx_path))
sub.append(('%libcxx_src_root', self.libcxx_src_root))
# Configure flags substitutions # Configure flags substitutions
flags_str = ' '.join([pipes.quote(f) for f in self.cxx.flags]) flags_str = ' '.join([pipes.quote(f) for f in self.cxx.flags])
compile_flags_str = ' '.join([pipes.quote(f) for f in self.cxx.compile_flags]) compile_flags_str = ' '.join([pipes.quote(f) for f in self.cxx.compile_flags])

View File

@ -169,10 +169,6 @@ class DarwinLocalTI(DefaultTargetInfo):
# should be available in libc++ directly. # should be available in libc++ directly.
return False return False
def add_sanitizer_features(self, sanitizer_type, features):
if sanitizer_type == 'Undefined':
features.add('sanitizer-new-delete')
class FreeBSDLocalTI(DefaultTargetInfo): class FreeBSDLocalTI(DefaultTargetInfo):
def __init__(self, full_config): def __init__(self, full_config):

View File

@ -64,7 +64,7 @@
<tr><td><a href="http://wg21.link/LWG2597">2597</a></td><td>std::log misspecified for complex numbers</td><td>Toronto</td><td></td></tr> <tr><td><a href="http://wg21.link/LWG2597">2597</a></td><td>std::log misspecified for complex numbers</td><td>Toronto</td><td></td></tr>
<tr><td><a href="http://wg21.link/LWG2783">2783</a></td><td>stack::emplace() and queue::emplace() should return decltype(auto)</td><td>Toronto</td><td></td></tr> <tr><td><a href="http://wg21.link/LWG2783">2783</a></td><td>stack::emplace() and queue::emplace() should return decltype(auto)</td><td>Toronto</td><td></td></tr>
<tr><td><a href="http://wg21.link/LWG2932">2932</a></td><td>Constraints on parallel algorithm implementations are underspecified</td><td>Toronto</td><td></td></tr> <tr><td><a href="http://wg21.link/LWG2932">2932</a></td><td>Constraints on parallel algorithm implementations are underspecified</td><td>Toronto</td><td></td></tr>
<tr><td><a href="http://wg21.link/LWG2937">2937</a></td><td>Is equivalent("existing_thing", "not_existing_thing") an error?</td><td>Toronto</td><td></td></tr> <tr><td><a href="http://wg21.link/LWG2937">2937</a></td><td>Is equivalent("existing_thing", "not_existing_thing") an error?</td><td>Toronto</td><td>Complete</td></tr>
<tr><td><a href="http://wg21.link/LWG2940">2940</a></td><td>result_of specification also needs a little cleanup</td><td>Toronto</td><td></td></tr> <tr><td><a href="http://wg21.link/LWG2940">2940</a></td><td>result_of specification also needs a little cleanup</td><td>Toronto</td><td></td></tr>
<tr><td><a href="http://wg21.link/LWG2942">2942</a></td><td>LWG 2873's resolution missed weak_ptr::owner_before</td><td>Toronto</td><td></td></tr> <tr><td><a href="http://wg21.link/LWG2942">2942</a></td><td>LWG 2873's resolution missed weak_ptr::owner_before</td><td>Toronto</td><td></td></tr>
<tr><td><a href="http://wg21.link/LWG2954">2954</a></td><td>Specialization of the convenience variable templates should be prohibited</td><td>Toronto</td><td></td></tr> <tr><td><a href="http://wg21.link/LWG2954">2954</a></td><td>Specialization of the convenience variable templates should be prohibited</td><td>Toronto</td><td></td></tr>
@ -84,7 +84,7 @@
<li>2597 - I think we do this already; probably needs tests</li> <li>2597 - I think we do this already; probably needs tests</li>
<li>2783 - should be easy to change; needs tests</li> <li>2783 - should be easy to change; needs tests</li>
<li>2932 - We're not doing the parallel algorithms yet.</li> <li>2932 - We're not doing the parallel algorithms yet.</li>
<li>2937 - file system; Eric?</li> <li>2937 - Implemented with tests. The PR LGTM (Eric)</li>
<li>2940 - We haven't implemented result_of yet, but I don't think that this will require any changes.</li> <li>2940 - We haven't implemented result_of yet, but I don't think that this will require any changes.</li>
<li>2942 - all of our owner_before overloads are already noexcept; just need to update the tests.</li> <li>2942 - all of our owner_before overloads are already noexcept; just need to update the tests.</li>
<li>2954 - I don't think there's anything to do here.</li> <li>2954 - I don't think there's anything to do here.</li>