diff options
Diffstat (limited to 'libstdc++-v3')
-rw-r--r-- | libstdc++-v3/include/bits/chrono_io.h | 61 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/stl_iterator.h | 30 | ||||
-rw-r--r-- | libstdc++-v3/include/std/mdspan | 2 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/ext/verify_neg.cc | 28 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/std/time/format/format.cc | 7 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/std/time/format/pr117214_custom_timeput.cc | 37 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/util/testsuite_hooks.h | 17 |
7 files changed, 142 insertions, 40 deletions
diff --git a/libstdc++-v3/include/bits/chrono_io.h b/libstdc++-v3/include/bits/chrono_io.h index 72cd569..75ee7e8 100644 --- a/libstdc++-v3/include/bits/chrono_io.h +++ b/libstdc++-v3/include/bits/chrono_io.h @@ -280,8 +280,8 @@ namespace __format // in the format-spec, e.g. "{:L%a}" is localized and locale-specific, // but "{:L}" is only localized and "{:%a}" is only locale-specific. unsigned _M_locale_specific : 1; - // Indicates that we are handling duration. - unsigned _M_time_only : 1; + // Indicates that we are handling time_point. + unsigned _M_time_point : 1; // Indicates that duration should be treated as floating point. unsigned _M_floating_point_rep : 1; // Indicate that duration uses user-defined representation. @@ -693,8 +693,11 @@ namespace __format __allowed_mods = _Mod_O; break; case 'j': - __needed = __spec._M_time_only ? _HoursMinutesSeconds - : _DayOfYear; + __needed = __parts & _DayOfYear; + // If we do not know day-of-year then we must have a duration, + // which is to be formatted as decimal number of days. + if (__needed == _None) + __needed = _HoursMinutesSeconds; break; case 'm': __needed = _Month; @@ -919,7 +922,13 @@ namespace __format { switch (__conv) { + case 'a': + case 'A': + case 'b': + case 'B': case 'c': + case 'h': + case 'p': case 'r': case 'x': case 'X': @@ -947,6 +956,32 @@ namespace __format return __out; } + void + _M_check_ok(const _ChronoData<_CharT>& __t, _CharT __conv) const + { + // n.b. for time point all date parts are computed, so + // they are always ok. + if (_M_spec._M_time_point || _M_spec._M_debug) + return; + + switch (__conv) + { + case 'a': + case 'A': + if (!__t._M_weekday.ok()) [[unlikely]] + __throw_format_error("format error: invalid weekday"); + return; + case 'b': + case 'h': + case 'B': + if (!__t._M_month.ok()) [[unlikely]] + __throw_format_error("format error: invalid month"); + return; + default: + return; + } + } + template<typename _OutIter, typename _FormatContext> _OutIter _M_format_to(const _ChronoData<_CharT>& __t, _OutIter __out, @@ -1003,6 +1038,8 @@ namespace __format do { _CharT __c = *__first++; + _M_check_ok(__t, __c); + if (__use_locale_fmt && _S_localized_spec(__c, __mod)) [[unlikely]] __out = _M_locale_fmt(std::move(__out), __fc.locale(), __tm, __c, __mod); @@ -1153,11 +1190,8 @@ namespace __format { // %a Locale's abbreviated weekday name. // %A Locale's full weekday name. - if (!__wd.ok()) + if (_M_spec._M_debug && !__wd.ok()) { - if (!_M_spec._M_debug) - __throw_format_error("format error: invalid weekday"); - _CharT __buf[3]; __out = __format::__write(std::move(__out), _S_str_d1(__buf, __wd.c_encoding())); @@ -1183,11 +1217,8 @@ namespace __format { // %b Locale's abbreviated month name. // %B Locale's full month name. - if (!__m.ok()) + if (_M_spec._M_debug && !__m.ok()) { - if (!_M_spec._M_debug) - __throw_format_error("format error: invalid month"); - _CharT __buf[3]; __out = __format::__write(std::move(__out), _S_str_d1(__buf, (unsigned)__m)); @@ -1419,7 +1450,7 @@ namespace __format _OutIter _M_j(const _ChronoData<_CharT>& __t, _OutIter __out) const { - if (_M_spec._M_time_only) + if (!_M_spec._M_needs(_ChronoParts::_DayOfYear)) { // Decimal number of days, without padding. auto __d = chrono::floor<chrono::days>(__t._M_hours).count(); @@ -1766,7 +1797,7 @@ namespace __format { if (__n < 100) [[likely]] return _S_two_digits(__n); - return _S_str_d3(__buf, __n); + return _S_str_d3(__buf, __n); } // Returns decimal representation of __n, padded to 3 digits. @@ -1811,7 +1842,7 @@ namespace __format using enum _ChronoParts; _ChronoSpec<_CharT> __res{}; - __res._M_time_only = (__parts & _Date) == 0; + __res._M_time_point = (__parts & _DateTime) == _DateTime; __res._M_floating_point_rep = chrono::treat_as_floating_point_v<_Rep>; __res._M_custom_rep = !is_arithmetic_v<_Rep>; __res._M_prec = chrono::hh_mm_ss<_Duration>::fractional_width; diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h index a7188f4..75e794f 100644 --- a/libstdc++-v3/include/bits/stl_iterator.h +++ b/libstdc++-v3/include/bits/stl_iterator.h @@ -1211,7 +1211,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #else // Forward iterator requirements template<typename _Iter> - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1220,7 +1220,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_NOEXCEPT { return __lhs.base() == __rhs.base(); } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1229,7 +1229,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __lhs.base() == __rhs.base(); } template<typename _Iter> - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1238,7 +1238,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_NOEXCEPT { return __lhs.base() != __rhs.base(); } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1248,15 +1248,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Random access iterator requirements template<typename _Iter> + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR + _GLIBCXX_CONSTEXPR inline bool operator<(const __normal_iterator& __lhs, const __normal_iterator<_Iter, _Container>& __rhs) _GLIBCXX_NOEXCEPT { return __lhs.base() < __rhs.base(); } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX20_CONSTEXPR bool @@ -1265,15 +1266,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __lhs.base() < __rhs.base(); } template<typename _Iter> + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR + _GLIBCXX_CONSTEXPR bool operator>(const __normal_iterator& __lhs, const __normal_iterator<_Iter, _Container>& __rhs) _GLIBCXX_NOEXCEPT { return __lhs.base() > __rhs.base(); } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1282,7 +1284,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __lhs.base() > __rhs.base(); } template<typename _Iter> - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1291,7 +1293,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_NOEXCEPT { return __lhs.base() <= __rhs.base(); } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1300,7 +1302,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __lhs.base() <= __rhs.base(); } template<typename _Iter> - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1309,7 +1311,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_NOEXCEPT { return __lhs.base() >= __rhs.base(); } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1341,7 +1343,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif { return __lhs.base() - __rhs.base(); } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR difference_type @@ -1349,7 +1351,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_NOEXCEPT { return __lhs.base() - __rhs.base(); } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR __normal_iterator diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan index c72a640..4a06fb2 100644 --- a/libstdc++-v3/include/std/mdspan +++ b/libstdc++-v3/include/std/mdspan @@ -509,7 +509,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Layout, typename _Mapping> concept __mapping_of = - is_same_v<typename _Layout::mapping<typename _Mapping::extents_type>, + is_same_v<typename _Layout::template mapping<typename _Mapping::extents_type>, _Mapping>; template<typename _Mapping> diff --git a/libstdc++-v3/testsuite/ext/verify_neg.cc b/libstdc++-v3/testsuite/ext/verify_neg.cc new file mode 100644 index 0000000..ce03374 --- /dev/null +++ b/libstdc++-v3/testsuite/ext/verify_neg.cc @@ -0,0 +1,28 @@ +// { dg-do compile { target c++11 } } + +#include <testsuite_hooks.h> + +struct X { explicit operator void*() const { return nullptr; } }; + +void +test_VERIFY(int i) +{ + // This should not be parsed as a function type bool(bool(i)): + VERIFY( bool(i) ); + + // This should not produce warnings about lambda in unevaluated context: + VERIFY( []{ return 1; }() ); + + // Only one expression allowed: + VERIFY(1, 2); // { dg-error "in expansion of macro" } + // { dg-error "compound expression in functional cast" "" { target *-*-* } 0 } + + // A scoped enum is not contextually convertible to bool: + enum class E { E0 }; + VERIFY( E::E0 ); // { dg-error "could not convert" } + + // explicit conversion to void* is not contextually convertible to bool: + X x; + VERIFY( x ); // { dg-error "in expansion of macro" } + // { dg-error "invalid cast .* to type 'bool'" "" { target *-*-* } 0 } +} diff --git a/libstdc++-v3/testsuite/std/time/format/format.cc b/libstdc++-v3/testsuite/std/time/format/format.cc index d6e3583..00affb9 100644 --- a/libstdc++-v3/testsuite/std/time/format/format.cc +++ b/libstdc++-v3/testsuite/std/time/format/format.cc @@ -78,6 +78,13 @@ test_bad_format_strings() VERIFY( not is_format_string_for("{:%OOy}", t) ); VERIFY( not is_format_string_for("{:%OEy}", t) ); VERIFY( not is_format_string_for("{:%EOy}", t) ); + + // weekday and month values for which ok() is false + VERIFY( not is_format_string_for("{:%a}", std::chrono::weekday(8)) ); + VERIFY( not is_format_string_for("{:%A}", std::chrono::weekday(8)) ); + VERIFY( not is_format_string_for("{:%b}", std::chrono::month(13)) ); + VERIFY( not is_format_string_for("{:%h}", std::chrono::month(13)) ); + VERIFY( not is_format_string_for("{:%B}", std::chrono::month(13)) ); } template<typename I> diff --git a/libstdc++-v3/testsuite/std/time/format/pr117214_custom_timeput.cc b/libstdc++-v3/testsuite/std/time/format/pr117214_custom_timeput.cc new file mode 100644 index 0000000..03b9496 --- /dev/null +++ b/libstdc++-v3/testsuite/std/time/format/pr117214_custom_timeput.cc @@ -0,0 +1,37 @@ +// { dg-do run { target c++20 } } + +#include <chrono> +#include <format> +#include <locale> +#include <testsuite_hooks.h> + +struct custom_time_put : std::time_put<char> +{ + iter_type + do_put(iter_type out, std::ios_base& io, char_type fill, const tm* t, + char format, char modifier) const override + { + using Base = std::time_put<char>; + + switch (format) { + case 'a': case 'A': case 'b': case 'h': case 'B': case 'p': + *out++ = '['; + *out++ = format; + *out++ = ']'; + } + return Base::do_put(out, io, fill, t, format, modifier); + } +}; + +int main() +{ + using namespace std::chrono; + std::locale loc(std::locale::classic(), new custom_time_put); +#define test(t, fmt, exp) VERIFY( std::format(loc, fmt, t) == exp ) + test(Monday, "{:L%a}", "[a]Mon"); + test(Monday, "{:L%A}", "[A]Monday"); + test(January, "{:L%b}", "[b]Jan"); + test(January, "{:L%h}", "[h]Jan"); + test(January, "{:L%B}", "[B]January"); + test(1h, "{:L%p}", "[p]AM"); +} diff --git a/libstdc++-v3/testsuite/util/testsuite_hooks.h b/libstdc++-v3/testsuite/util/testsuite_hooks.h index faa01ba..bf34fd1 100644 --- a/libstdc++-v3/testsuite/util/testsuite_hooks.h +++ b/libstdc++-v3/testsuite/util/testsuite_hooks.h @@ -58,16 +58,13 @@ # define _VERIFY_PRINT(S, F, L, P, C) __builtin_printf(S, F, L, P, C) #endif -#define VERIFY(fn) \ - do \ - { \ - if (! (fn)) \ - { \ - _VERIFY_PRINT("%s:%d: %s: Assertion '%s' failed.\n", \ - __FILE__, __LINE__, __PRETTY_FUNCTION__, #fn); \ - __builtin_abort(); \ - } \ - } while (false) +#define VERIFY(...) \ + ((void)((__VA_ARGS__) \ + ? (void)(true ? true : bool(__VA_ARGS__)) \ + : (_VERIFY_PRINT("%s:%d: %s: Assertion '%s' failed.\n", \ + __FILE__, __LINE__, __PRETTY_FUNCTION__, \ + #__VA_ARGS__), \ + __builtin_abort()))) #ifdef _GLIBCXX_HAVE_UNISTD_H # include <unistd.h> |