aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
Diffstat (limited to 'libstdc++-v3')
-rw-r--r--libstdc++-v3/include/bits/chrono_io.h61
-rw-r--r--libstdc++-v3/include/bits/stl_iterator.h30
-rw-r--r--libstdc++-v3/include/std/mdspan2
-rw-r--r--libstdc++-v3/testsuite/ext/verify_neg.cc28
-rw-r--r--libstdc++-v3/testsuite/std/time/format/format.cc7
-rw-r--r--libstdc++-v3/testsuite/std/time/format/pr117214_custom_timeput.cc37
-rw-r--r--libstdc++-v3/testsuite/util/testsuite_hooks.h17
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>