aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/testsuite/std
diff options
context:
space:
mode:
authorTomasz Kamiński <tkaminsk@redhat.com>2025-04-16 13:39:04 +0200
committerTomasz Kamiński <tkaminsk@redhat.com>2025-04-16 14:32:57 +0200
commitaef87975224b0a4b5b103f241fd366b0e3a21360 (patch)
tree62e40c32b04285e548f944f40adf1f63f8ae2c2b /libstdc++-v3/testsuite/std
parentfa99720e9f3447565d274baaa81e23c2ddab4a67 (diff)
downloadgcc-aef87975224b0a4b5b103f241fd366b0e3a21360.zip
gcc-aef87975224b0a4b5b103f241fd366b0e3a21360.tar.gz
gcc-aef87975224b0a4b5b103f241fd366b0e3a21360.tar.bz2
libstdc++: Fix constification in range_formatter::format [PR109162]
The _Rg is deduced to lvalue reference for the lvalue arguments, and in such case __format::__maybe_const_range<_Rg, _CharT> is always _Rg (adding const to reference does not change behavior). Now we correctly check if _Range = remove_reference_t<_Rg> is const formattable range, furthermore as range_formatter<T> can only format ranges of values of type (possibly const) _Tp, we additional check if the remove_cvref_t<range_reference_t<const _Range>> is _Tp. The range_reference_t<R> and range_reference_t<const R> have different types (modulo remove_cvref_t) for std::vector<bool> (::reference and bool) or flat_map<T, U> (pair<const T&, U&> and pair<const T&, const U&>). PR libstdc++/109162 libstdc++-v3/ChangeLog: * include/std/format (range_formatter::format): Format const range, only if reference type is not changed. * testsuite/std/format/ranges/formatter.cc: New tests. Reviewed-by: Jonathan Wakely <jwakely@redhat.com> Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
Diffstat (limited to 'libstdc++-v3/testsuite/std')
-rw-r--r--libstdc++-v3/testsuite/std/format/ranges/formatter.cc22
1 files changed, 22 insertions, 0 deletions
diff --git a/libstdc++-v3/testsuite/std/format/ranges/formatter.cc b/libstdc++-v3/testsuite/std/format/ranges/formatter.cc
index a4f5d92..00ce9f6 100644
--- a/libstdc++-v3/testsuite/std/format/ranges/formatter.cc
+++ b/libstdc++-v3/testsuite/std/format/ranges/formatter.cc
@@ -1,5 +1,6 @@
// { dg-do run { target c++23 } }
+#include <flat_map>
#include <format>
#include <testsuite_hooks.h>
#include <vector>
@@ -138,6 +139,26 @@ test_nested()
VERIFY( res == "+<01; 02; 11; 12>+" );
}
+struct MyFlatMap : std::flat_map<int, int>
+{
+ using std::flat_map<int, int>::flat_map;
+};
+
+template<typename CharT>
+struct std::formatter<MyFlatMap, CharT>
+ // This cannot apply format BitVector const&, because formatted type would
+ // be std::pair<int const&, int const&>, and formatter for
+ // pair<int const&, int> cannot format it.
+ : std::range_formatter<MyFlatMap::reference>
+{};
+
+void test_const_ref_type_mismatch()
+{
+ MyFlatMap m{{1, 11}, {2, 22}};
+ std::string res = std::format("{:m}", m);
+ VERIFY( res == "{1: 11, 2: 22}" );
+}
+
template<typename T, typename CharT>
using VectorFormatter = std::formatter<std::vector<T>, CharT>;
@@ -146,4 +167,5 @@ int main()
test_outputs<std::range_formatter>();
test_outputs<VectorFormatter>();
test_nested();
+ test_const_ref_type_mismatch();
}