[llvm-branch-commits] [libcxx] [libc++][format][5/7] Improve std::format_to_n (PR #101831)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sat Aug 3 08:20:24 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libcxx

Author: Mark de Wever (mordante)

<details>
<summary>Changes</summary>

__format_to_n_buffer is not used in the public library interface so the changes are not an ABI break.

Before
Benchmark                                                                           Time             CPU      Time Old      Time New       CPU Old       CPU New
----------------------------------------------------------------------------------------------------------------------------------------------------------------
BM_format_to_n_string_back_inserter<std::string>/1                               -0.0160         -0.0136            59            58            59            58
BM_format_to_n_string_back_inserter<std::string>/2                               +0.0020         +0.0044            58            59            58            59
BM_format_to_n_string_back_inserter<std::string>/4                               +0.0084         +0.0109            58            59            58            59
BM_format_to_n_string_back_inserter<std::string>/8                               -0.0014         +0.0014            59            59            58            59
BM_format_to_n_string_back_inserter<std::string>/16                              -0.0042         -0.0018            59            58            59            58
BM_format_to_n_string_back_inserter<std::string>/32                              -0.0136         -0.0112            78            77            78            77
BM_format_to_n_string_back_inserter<std::string>/64                              -0.0096         -0.0072            78            77            77            77
BM_format_to_n_string_back_inserter<std::string>/128                             -0.1486         -0.1465            91            77            91            77
BM_format_to_n_string_back_inserter<std::string>/256                             -0.1215         -0.1191           102            90           102            90
BM_format_to_n_string_back_inserter<std::string>/512                             -0.1412         -0.1391           158           136           158           136
BM_format_to_n_string_back_inserter<std::string>/1024                            -0.1135         -0.1114           290           257           289           257
BM_format_to_n_string_back_inserter<std::string>/2048                            -0.1551         -0.1530           489           413           488           413
BM_format_to_n_string_back_inserter<std::string>/4096                            -0.1665         -0.1642           801           668           799           668
BM_format_to_n_string_back_inserter<std::string>/8192                            -0.2301         -0.2282          1449          1116          1445          1116
BM_format_to_n_string_back_inserter<std::string>/16384                           -0.1988         -0.1965          2942          2357          2933          2357
BM_format_to_n_string_back_inserter<std::string>/32768                           -0.2129         -0.2109          5676          4467          5661          4467
BM_format_to_n_string_back_inserter<std::string>/65536                           -0.2469         -0.2449         12437          9366         12404          9366
BM_format_to_n_string_back_inserter<std::string>/131072                          -0.2294         -0.2274         25855         19923         25787         19923
BM_format_to_n_string_back_inserter<std::string>/262144                          -0.1906         -0.1885         52880         42798         52739         42798
BM_format_to_n_string_back_inserter<std::string>/524288                          -0.1898         -0.1876        107703         87261        107410         87257
BM_format_to_n_string_back_inserter<std::string>/1048576                         -0.2162         -0.2139        231479        181427        230781        181426
BM_format_to_n_string_back_inserter<std::vector<char>>/1                         -0.0035         -0.0007            72            72            72            72
BM_format_to_n_string_back_inserter<std::vector<char>>/2                         +0.0104         +0.0128            73            73            72            73
BM_format_to_n_string_back_inserter<std::vector<char>>/4                         -0.0022         +0.0003            74            74            74            74
BM_format_to_n_string_back_inserter<std::vector<char>>/8                         +0.0092         +0.0116            75            76            75            76
BM_format_to_n_string_back_inserter<std::vector<char>>/16                        -0.0019         +0.0005            79            79            79            79
BM_format_to_n_string_back_inserter<std::vector<char>>/32                        +0.0168         +0.0195            89            90            88            90
BM_format_to_n_string_back_inserter<std::vector<char>>/64                        -0.0077         -0.0054            91            90            90            90
BM_format_to_n_string_back_inserter<std::vector<char>>/128                       -0.1628         -0.1608           109            91           109            91
BM_format_to_n_string_back_inserter<std::vector<char>>/256                       -0.0994         -0.0971           120           108           119           108
BM_format_to_n_string_back_inserter<std::vector<char>>/512                       -0.1116         -0.1095           186           165           186           165
BM_format_to_n_string_back_inserter<std::vector<char>>/1024                      -0.1168         -0.1144           284           250           283           250
BM_format_to_n_string_back_inserter<std::vector<char>>/2048                      -0.1664         -0.1644           484           404           483           404
BM_format_to_n_string_back_inserter<std::vector<char>>/4096                      -0.2161         -0.2143           802           629           800           629
BM_format_to_n_string_back_inserter<std::vector<char>>/8192                      -0.2834         -0.2817          1469          1053          1466          1053
BM_format_to_n_string_back_inserter<std::vector<char>>/16384                     -0.2365         -0.2344          2700          2062          2693          2062
BM_format_to_n_string_back_inserter<std::vector<char>>/32768                     -0.2359         -0.2341          4979          3805          4967          3805
BM_format_to_n_string_back_inserter<std::vector<char>>/65536                     -0.2754         -0.2736         10431          7558         10405          7558
BM_format_to_n_string_back_inserter<std::vector<char>>/131072                    -0.2505         -0.2487         22646         16973         22591         16973
BM_format_to_n_string_back_inserter<std::vector<char>>/262144                    -0.1981         -0.1958         46278         37110         46148         37111
BM_format_to_n_string_back_inserter<std::vector<char>>/524288                    -0.2027         -0.2011         91695         73110         91511         73108
BM_format_to_n_string_back_inserter<std::vector<char>>/1048576                   -0.2367         -0.2348        195458        149194        194988        149197
BM_format_to_n_string_back_inserter<std::list<char>>/1                           +0.0045         +0.0068            66            66            65            66
BM_format_to_n_string_back_inserter<std::list<char>>/2                           +0.0068         +0.0092            79            79            79            79
BM_format_to_n_string_back_inserter<std::list<char>>/4                           -0.0026         +0.0001           107           107           107           107
BM_format_to_n_string_back_inserter<std::list<char>>/8                           +0.0498         +0.0523           171           180           171           180
BM_format_to_n_string_back_inserter<std::list<char>>/16                          +0.0100         +0.0124           331           334           330           334
BM_format_to_n_string_back_inserter<std::list<char>>/32                          +0.0320         +0.0345           641           662           640           662
BM_format_to_n_string_back_inserter<std::list<char>>/64                          +0.0242         +0.0270          1237          1267          1233          1267
BM_format_to_n_string_back_inserter<std::list<char>>/128                         +0.0025         +0.0047          2474          2480          2469          2480
BM_format_to_n_string_back_inserter<std::list<char>>/256                         -0.0122         -0.0098          4984          4923          4972          4924
BM_format_to_n_string_back_inserter<std::list<char>>/512                         +0.0074         +0.0098          9740          9812          9716          9811
BM_format_to_n_string_back_inserter<std::list<char>>/1024                        +0.0045         +0.0072         19503         19590         19451         19591
BM_format_to_n_string_back_inserter<std::list<char>>/2048                        +0.0021         +0.0046         39078         39161         38981         39159
BM_format_to_n_string_back_inserter<std::list<char>>/4096                        -0.0002         +0.0023         78329         78316         78132         78315
BM_format_to_n_string_back_inserter<std::list<char>>/8192                        +0.0001         +0.0026        156689        156709        156291        156699
BM_format_to_n_string_back_inserter<std::list<char>>/16384                       -0.0025         +0.0004        313624        312842        312732        312842
BM_format_to_n_string_back_inserter<std::list<char>>/32768                       -0.0009         +0.0017        630336        629744        628711        629751
BM_format_to_n_string_back_inserter<std::list<char>>/65536                       -0.0029         -0.0001       1261542       1257851       1258055       1257872
BM_format_to_n_string_back_inserter<std::list<char>>/131072                      -0.0047         -0.0016       2543001       2531022       2535000       2530835
BM_format_to_n_string_back_inserter<std::list<char>>/262144                      -0.0061         -0.0017       5214390       5182786       5191608       5182661
BM_format_to_n_string_back_inserter<std::list<char>>/524288                      -0.0079         -0.0040      10650366      10566644      10609616      10566709
BM_format_to_n_string_back_inserter<std::list<char>>/1048576                     -0.0165         -0.0108      21677130      21319849      21550764      21318080
BM_format_to_n_string_begin<std::string>/1                                       -0.0931         -0.0909            54            49            54            49
BM_format_to_n_string_begin<std::string>/2                                       -0.0861         -0.0839            53            48            53            48
BM_format_to_n_string_begin<std::string>/4                                       -0.0872         -0.0847            53            49            53            49
BM_format_to_n_string_begin<std::string>/8                                       -0.0963         -0.0939            54            48            54            48
BM_format_to_n_string_begin<std::string>/16                                      -0.0969         -0.0947            54            48            54            48
BM_format_to_n_string_begin<std::string>/32                                      -0.1108         -0.1086            54            48            54            48
BM_format_to_n_string_begin<std::string>/64                                      -0.1107         -0.1086            54            48            54            48
BM_format_to_n_string_begin<std::string>/128                                     -0.2054         -0.2036            61            48            61            48
BM_format_to_n_string_begin<std::string>/256                                     -0.2768         -0.2751            69            50            69            50
BM_format_to_n_string_begin<std::string>/512                                     -0.4127         -0.4112            90            53            89            53
BM_format_to_n_string_begin<std::string>/1024                                    -0.5743         -0.5734           132            56           132            56
BM_format_to_n_string_begin<std::string>/2048                                    -0.7063         -0.7056           229            67           228            67
BM_format_to_n_string_begin<std::string>/4096                                    -0.7617         -0.7611           425           101           424           101
BM_format_to_n_string_begin<std::string>/8192                                    -0.8153         -0.8148           812           150           810           150
BM_format_to_n_string_begin<std::string>/16384                                   -0.8140         -0.8136          1656           308          1652           308
BM_format_to_n_string_begin<std::string>/32768                                   -0.5789         -0.5779          3179          1339          3171          1339
BM_format_to_n_string_begin<std::string>/65536                                   -0.5170         -0.5158          6818          3293          6802          3293
BM_format_to_n_string_begin<std::string>/131072                                  -0.5552         -0.5539         14829          6596         14788          6596
BM_format_to_n_string_begin<std::string>/262144                                  -0.5240         -0.5228         29547         14064         29471         14065
BM_format_to_n_string_begin<std::string>/524288                                  -0.5049         -0.5036         59436         29428         59284         29428
BM_format_to_n_string_begin<std::string>/1048576                                 -0.5123         -0.5110        120292         58666        119974         58666
BM_format_to_n_string_begin<std::vector<char>>/1                                 -0.0947         -0.0925            53            48            53            48
BM_format_to_n_string_begin<std::vector<char>>/2                                 -0.0859         -0.0834            53            48            53            48
BM_format_to_n_string_begin<std::vector<char>>/4                                 -0.0913         -0.0892            53            48            53            48
BM_format_to_n_string_begin<std::vector<char>>/8                                 -0.0808         -0.0786            52            48            52            48
BM_format_to_n_string_begin<std::vector<char>>/16                                -0.0808         -0.0786            53            48            53            48
BM_format_to_n_string_begin<std::vector<char>>/32                                -0.0921         -0.0899            53            48            53            48
BM_format_to_n_string_begin<std::vector<char>>/64                                -0.0918         -0.0897            53            48            53            48
BM_format_to_n_string_begin<std::vector<char>>/128                               -0.1769         -0.1747            59            48            59            48
BM_format_to_n_string_begin<std::vector<char>>/256                               -0.3249         -0.3233            73            49            73            49
BM_format_to_n_string_begin<std::vector<char>>/512                               -0.4552         -0.4539            97            53            96            53
BM_format_to_n_string_begin<std::vector<char>>/1024                              -0.5978         -0.5969           138            56           138            56
BM_format_to_n_string_begin<std::vector<char>>/2048                              -0.7152         -0.7144           235            67           235            67
BM_format_to_n_string_begin<std::vector<char>>/4096                              -0.7780         -0.7775           439            98           438            98
BM_format_to_n_string_begin<std::vector<char>>/8192                              -0.8230         -0.8226           853           151           851           151
BM_format_to_n_string_begin<std::vector<char>>/16384                             -0.8065         -0.8060          1627           315          1623           315
BM_format_to_n_string_begin<std::vector<char>>/32768                             -0.5823         -0.5811          3221          1345          3212          1345
BM_format_to_n_string_begin<std::vector<char>>/65536                             -0.5351         -0.5340          7089          3295          7072          3295
BM_format_to_n_string_begin<std::vector<char>>/131072                            -0.5683         -0.5672         15268          6591         15229          6590
BM_format_to_n_string_begin<std::vector<char>>/262144                            -0.5351         -0.5339         30296         14084         30219         14084
BM_format_to_n_string_begin<std::vector<char>>/524288                            -0.5061         -0.5049         61230         30239         61074         30238
BM_format_to_n_string_begin<std::vector<char>>/1048576                           -0.5143         -0.5128        124101         60270        123704         60271
BM_format_to_n_string_begin<std::list<char>>/1                                   +0.0383         +0.0408            49            51            49            51
BM_format_to_n_string_begin<std::list<char>>/2                                   +0.0278         +0.0301            50            51            50            51
BM_format_to_n_string_begin<std::list<char>>/4                                   +0.0388         +0.0412            51            53            51            53
BM_format_to_n_string_begin<std::list<char>>/8                                   -0.0386         -0.0360            64            62            64            62
BM_format_to_n_string_begin<std::list<char>>/16                                  -0.0225         -0.0201            85            83            85            83
BM_format_to_n_string_begin<std::list<char>>/32                                  -0.0095         -0.0071           127           126           127           126
BM_format_to_n_string_begin<std::list<char>>/64                                  -0.0072         -0.0048           214           212           213           212
BM_format_to_n_string_begin<std::list<char>>/128                                 -0.0117         -0.0092           389           385           388           385
BM_format_to_n_string_begin<std::list<char>>/256                                 -0.0034         -0.0009           749           746           747           746
BM_format_to_n_string_begin<std::list<char>>/512                                 -0.0098         -0.0074          1453          1439          1449          1439
BM_format_to_n_string_begin<std::list<char>>/1024                                +0.0109         +0.0132          2852          2883          2845          2882
BM_format_to_n_string_begin<std::list<char>>/2048                                +0.0088         +0.0113          5685          5735          5671          5735
BM_format_to_n_string_begin<std::list<char>>/4096                                +0.0043         +0.0068         11312         11360         11283         11360
BM_format_to_n_string_begin<std::list<char>>/8192                                +0.0171         +0.0197         22644         23030         22586         23030
BM_format_to_n_string_begin<std::list<char>>/16384                               +0.0146         +0.0172         45298         45959         45180         45958
BM_format_to_n_string_begin<std::list<char>>/32768                               +0.0167         +0.0195         90351         91864         90110         91864
BM_format_to_n_string_begin<std::list<char>>/65536                               +0.0150         +0.0180        180594        183305        180048        183298
BM_format_to_n_string_begin<std::list<char>>/131072                              +0.0060         +0.0092        373023        375274        371863        375279
BM_format_to_n_string_begin<std::list<char>>/262144                              -0.0354         -0.0318        895166        863452        891717        863366
BM_format_to_n_string_begin<std::list<char>>/524288                              -0.0745         -0.0712       2209006       2044442       2201104       2044356
BM_format_to_n_string_begin<std::list<char>>/1048576                             -0.0161         -0.0125       4421130       4349820       4404315       4349352
BM_format_to_n_string_span<char>/1                                               -0.0987         -0.0965            53            48            53            48
BM_format_to_n_string_span<char>/2                                               -0.0768         -0.0745            53            48            52            48
BM_format_to_n_string_span<char>/4                                               -0.0904         -0.0882            53            48            53            48
BM_format_to_n_string_span<char>/8                                               -0.0868         -0.0846            53            48            53            48
BM_format_to_n_string_span<char>/16                                              -0.0957         -0.0932            54            49            54            49
BM_format_to_n_string_span<char>/32                                              -0.0926         -0.0904            53            48            53            48
BM_format_to_n_string_span<char>/64                                              -0.0923         -0.0876            53            48            53            48
BM_format_to_n_string_span<char>/128                                             -0.1998         -0.1977            61            49            61            49
BM_format_to_n_string_span<char>/256                                             -0.2900         -0.2883            69            49            69            49
BM_format_to_n_string_span<char>/512                                             -0.4116         -0.4100            90            53            89            53
BM_format_to_n_string_span<char>/1024                                            -0.5854         -0.5844           134            56           134            56
BM_format_to_n_string_span<char>/2048                                            -0.7000         -0.6993           223            67           222            67
BM_format_to_n_string_span<char>/4096                                            -0.7731         -0.7725           427            97           426            97
BM_format_to_n_string_span<char>/8192                                            -0.8164         -0.8159           818           150           816           150
BM_format_to_n_string_span<char>/16384                                           -0.3453         -0.3436          1622          1062          1617          1062
BM_format_to_n_string_span<char>/32768                                           -0.5885         -0.5875          3137          1291          3129          1291
BM_format_to_n_string_span<char>/65536                                           -0.5064         -0.5052          6698          3306          6682          3306
BM_format_to_n_string_span<char>/131072                                          -0.5622         -0.5612         14925          6534         14888          6534
BM_format_to_n_string_span<char>/262144                                          -0.5215         -0.5201         29688         14207         29603         14207
BM_format_to_n_string_span<char>/524288                                          -0.4899         -0.4888         59308         30252         59180         30253
BM_format_to_n_string_span<char>/1048576                                         -0.4927         -0.4913        118765         60247        118433         60248
BM_format_to_n_string_pointer<char>/1                                            -0.0827         -0.0804            52            48            52            48
BM_format_to_n_string_pointer<char>/2                                            -0.0843         -0.0821            53            48            53            48
BM_format_to_n_string_pointer<char>/4                                            -0.0944         -0.0920            53            48            53            48
BM_format_to_n_string_pointer<char>/8                                            -0.0875         -0.0853            53            48            53            48
BM_format_to_n_string_pointer<char>/16                                           -0.0793         -0.0771            53            48            53            48
BM_format_to_n_string_pointer<char>/32                                           -0.0767         -0.0743            52            48            52            48
BM_format_to_n_string_pointer<char>/64                                           -0.0935         -0.0914            53            48            53            48
BM_format_to_n_string_pointer<char>/128                                          -0.2203         -0.2182            62            49            62            49
BM_format_to_n_string_pointer<char>/256                                          -0.2950         -0.2933            70            49            69            49
BM_format_to_n_string_pointer<char>/512                                          -0.4038         -0.4025            88            53            88            53
BM_format_to_n_string_pointer<char>/1024                                         -0.5755         -0.5745           131            56           131            56
BM_format_to_n_string_pointer<char>/2048                                         -0.7043         -0.7036           226            67           225            67
BM_format_to_n_string_pointer<char>/4096                                         -0.7726         -0.7719           426            97           425            97
BM_format_to_n_string_pointer<char>/8192                                         -0.8157         -0.8153           815           150           813           150
BM_format_to_n_string_pointer<char>/16384                                        -0.3490         -0.3473          1618          1053          1614          1053
BM_format_to_n_string_pointer<char>/32768                                        -0.5880         -0.5870          3137          1293          3129          1292
BM_format_to_n_string_pointer<char>/65536                                        -0.5062         -0.5048          6693          3305          6675          3305
BM_format_to_n_string_pointer<char>/131072                                       -0.5617         -0.5606         14912          6536         14876          6536
BM_format_to_n_string_pointer<char>/262144                                       -0.5206         -0.5194         29685         14230         29609         14230
BM_format_to_n_string_pointer<char>/524288                                       -0.4884         -0.4873         59254         30316         59133         30315
BM_format_to_n_string_pointer<char>/1048576                                      -0.4924         -0.4915        118746         60274        118523         60275


---
Full diff: https://github.com/llvm/llvm-project/pull/101831.diff


8 Files Affected:

- (modified) libcxx/include/__format/buffer.h (+115-111) 
- (modified) libcxx/test/libcxx/transitive_includes/cxx03.csv (+1) 
- (modified) libcxx/test/libcxx/transitive_includes/cxx11.csv (+1) 
- (modified) libcxx/test/libcxx/transitive_includes/cxx14.csv (+1) 
- (modified) libcxx/test/libcxx/transitive_includes/cxx17.csv (+1) 
- (modified) libcxx/test/libcxx/transitive_includes/cxx20.csv (+2) 
- (modified) libcxx/test/libcxx/transitive_includes/cxx23.csv (+2) 
- (modified) libcxx/test/libcxx/transitive_includes/cxx26.csv (+2) 


``````````diff
diff --git a/libcxx/include/__format/buffer.h b/libcxx/include/__format/buffer.h
index ccf79077dfa70..c41ea73b3eb7e 100644
--- a/libcxx/include/__format/buffer.h
+++ b/libcxx/include/__format/buffer.h
@@ -39,6 +39,7 @@
 #include <__type_traits/conditional.h>
 #include <__utility/exception_guard.h>
 #include <__utility/move.h>
+#include <climits> // LLVM-20 remove
 #include <cstddef>
 #include <stdexcept>
 #include <string_view>
@@ -56,6 +57,30 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 namespace __format {
 
+// A helper to limit the total size of code units written.
+class _LIBCPP_HIDE_FROM_ABI __max_output_size {
+public:
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __max_output_size(size_t __max_size) : __max_size_{__max_size} {}
+
+  // This function adjusts the size of a (bulk) write operations. It ensures the
+  // number of code units written by a __output_buffer never exceed
+  // __max_size_ code units.
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_t __write_request(size_t __code_units) {
+    size_t __result =
+        __code_units_written_ < __max_size_ ? std::min(__code_units, __max_size_ - __code_units_written_) : 0;
+    __code_units_written_ += __code_units;
+    return __result;
+  }
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_t __code_units_written() const noexcept { return __code_units_written_; }
+
+private:
+  size_t __max_size_;
+  // The code units that would have been written if there was no limit.
+  // format_to_n returns this value.
+  size_t __code_units_written_{0};
+};
+
 /// A "buffer" that handles writing to the proper iterator.
 ///
 /// This helper is used together with the @ref back_insert_iterator to offer
@@ -81,9 +106,6 @@ namespace __format {
 /// This class is ABI-tagged, still the new design does not change the size of
 /// objects of this class.
 ///
-/// The new design contains information regarding format_to_n changes, these
-/// will be implemented in follow-up patch.
-///
 /// The new design is the following.
 /// - There is an external object that connects the buffer to the output.
 /// - This buffer object:
@@ -189,12 +211,21 @@ class _LIBCPP_TEMPLATE_VIS __output_buffer {
       : __ptr_(__ptr),
         __capacity_(__capacity),
         __flush_([](_CharT* __p, size_t __n, void* __o) { static_cast<_Tp*>(__o)->__flush(__p, __n); }),
-        __obj_(__obj) {}
+        __data_{.__version_llvm_20__ = false, .__obj_ = reinterpret_cast<uintptr_t>(__obj) >> 1} {}
 
   // New LLVM-20 function.
   [[nodiscard]]
   _LIBCPP_HIDE_FROM_ABI explicit __output_buffer(_CharT* __ptr, size_t __capacity, __prepare_write_type __prepare_write)
-      : __ptr_(__ptr), __capacity_(__capacity), __prepare_write_(__prepare_write), __obj_(nullptr) {}
+      : __output_buffer{__ptr, __capacity, __prepare_write, nullptr} {}
+
+  // New LLVM-20 function.
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __output_buffer(
+      _CharT* __ptr, size_t __capacity, __prepare_write_type __prepare_write, __max_output_size* __max_output_size)
+      : __ptr_(__ptr),
+        __capacity_(__capacity),
+        __prepare_write_(__prepare_write),
+        __data_{.__version_llvm_20_ = true, .__max_output_size_ = reinterpret_cast<uintptr_t>(__max_output_size) >> 1} {
+  }
 
   // Deprecated LLVM-19 function.
   _LIBCPP_HIDE_FROM_ABI void __reset(_CharT* __ptr, size_t __capacity) {
@@ -215,6 +246,10 @@ class _LIBCPP_TEMPLATE_VIS __output_buffer {
 
   // Used in std::back_insert_iterator.
   _LIBCPP_HIDE_FROM_ABI void push_back(_CharT __c) {
+    if (__data_.__version_llvm_20_ && __data_.__max_output_size_ &&
+        reinterpret_cast<__max_output_size*>(__data_.__max_output_size_ << 1)->__write_request(1) == 0)
+      return;
+
     __ptr_[__size_++] = __c;
 
     // Profiling showed flushing after adding is more efficient than flushing
@@ -241,6 +276,11 @@ class _LIBCPP_TEMPLATE_VIS __output_buffer {
     // upper case. For integral these strings are short.
     // TODO FMT Look at the improvements above.
     size_t __n = __str.size();
+    if (__data_.__version_llvm_20_ && __data_.__max_output_size_) {
+      __n = reinterpret_cast<__max_output_size*>(__data_.__max_output_size_ << 1)->__write_request(__n);
+      if (__n == 0)
+        return;
+    }
 
     __flush_on_overflow(__n);
     if (__n < __capacity_) { // push_back requires the buffer to have room for at least one character (so use <).
@@ -273,6 +313,12 @@ class _LIBCPP_TEMPLATE_VIS __output_buffer {
     _LIBCPP_ASSERT_INTERNAL(__first <= __last, "not a valid range");
 
     size_t __n = static_cast<size_t>(__last - __first);
+    if (__data_.__version_llvm_20_ && __data_.__max_output_size_) {
+      __n = reinterpret_cast<__max_output_size*>(__data_.__max_output_size_ << 1)->__write_request(__n);
+      if (__n == 0)
+        return;
+    }
+
     __flush_on_overflow(__n);
     if (__n < __capacity_) { //  push_back requires the buffer to have room for at least one character (so use <).
       std::transform(__first, __last, std::addressof(__ptr_[__size_]), std::move(__operation));
@@ -295,6 +341,12 @@ class _LIBCPP_TEMPLATE_VIS __output_buffer {
 
   /// A \c fill_n wrapper.
   _LIBCPP_HIDE_FROM_ABI void __fill(size_t __n, _CharT __value) {
+    if (__data_.__version_llvm_20_ && __data_.__max_output_size_) {
+      __n = reinterpret_cast<__max_output_size*>(__data_.__max_output_size_ << 1)->__write_request(__n);
+      if (__n == 0)
+        return;
+    }
+
     __flush_on_overflow(__n);
     if (__n < __capacity_) { //  push_back requires the buffer to have room for at least one character (so use <).
       std::fill_n(std::addressof(__ptr_[__size_]), __n, __value);
@@ -315,9 +367,9 @@ class _LIBCPP_TEMPLATE_VIS __output_buffer {
   }
 
   _LIBCPP_HIDE_FROM_ABI void __flush(size_t __size_hint) {
-    if (__obj_) {
+    if (!__data_.__version_llvm_20_) {
       // LLVM-19 code path
-      __flush_(__ptr_, __size_, __obj_);
+      __flush_(__ptr_, __size_, reinterpret_cast<void*>(__data_.__obj_ << 1));
       __size_ = 0;
     } else {
       // LLVM-20 code path
@@ -340,7 +392,20 @@ class _LIBCPP_TEMPLATE_VIS __output_buffer {
   };
   static_assert(sizeof(__flush_) == sizeof(__prepare_write_), "The union is an ABI break.");
   static_assert(alignof(decltype(__flush_)) == alignof(decltype(__prepare_write_)), "The union is an ABI break.");
-  void* __obj_;
+  // Note this code is quite ugly, but it can cleaned up once the LLVM-19 parts
+  // of the code are removed.
+  union {
+    struct {
+      uintptr_t __version_llvm_20__ : 1;
+      uintptr_t __obj_ : CHAR_BIT * sizeof(void*) - 1;
+    };
+    struct {
+      uintptr_t __version_llvm_20_ : 1;
+      uintptr_t __max_output_size_ : CHAR_BIT * sizeof(__max_output_size*) - 1;
+    };
+  } __data_;
+  static_assert(sizeof(__data_) == sizeof(void*), "The struct is an ABI break.");
+  static_assert(alignof(decltype(__data_)) == alignof(void*), "The struct is an ABI break.");
 
   /// Flushes the buffer when the output operation would overflow the buffer.
   ///
@@ -560,105 +625,6 @@ class _LIBCPP_TEMPLATE_VIS __formatted_size_buffer {
   size_t __size_{0};
 };
 
-/// The base of a buffer that counts and limits the number of insertions.
-template <class _OutIt, __fmt_char_type _CharT, bool>
-  requires(output_iterator<_OutIt, const _CharT&>)
-struct _LIBCPP_TEMPLATE_VIS __format_to_n_buffer_base {
-  using _Size = iter_difference_t<_OutIt>;
-
-public:
-  _LIBCPP_HIDE_FROM_ABI explicit __format_to_n_buffer_base(_OutIt __out_it, _Size __max_size)
-      : __writer_(std::move(__out_it)), __max_size_(std::max(_Size(0), __max_size)) {}
-
-  _LIBCPP_HIDE_FROM_ABI void __flush(_CharT* __ptr, size_t __n) {
-    if (_Size(__size_) <= __max_size_)
-      __writer_.__flush(__ptr, std::min(_Size(__n), __max_size_ - __size_));
-    __size_ += __n;
-  }
-
-protected:
-  __internal_storage<_CharT> __storage_;
-  __output_buffer<_CharT> __output_{__storage_.__begin(), __storage_.__buffer_size, this};
-  typename __writer_selector<_OutIt, _CharT>::type __writer_;
-
-  _Size __max_size_;
-  _Size __size_{0};
-};
-
-/// The base of a buffer that counts and limits the number of insertions.
-///
-/// This version is used when \c __enable_direct_output<_OutIt, _CharT> == true.
-///
-/// This class limits the size available to the direct writer so it will not
-/// exceed the maximum number of code units.
-template <class _OutIt, __fmt_char_type _CharT>
-  requires(output_iterator<_OutIt, const _CharT&>)
-class _LIBCPP_TEMPLATE_VIS __format_to_n_buffer_base<_OutIt, _CharT, true> {
-  using _Size = iter_difference_t<_OutIt>;
-
-public:
-  _LIBCPP_HIDE_FROM_ABI explicit __format_to_n_buffer_base(_OutIt __out_it, _Size __max_size)
-      : __output_(std::__unwrap_iter(__out_it), __max_size, this),
-        __writer_(std::move(__out_it)),
-        __max_size_(__max_size) {
-    if (__max_size <= 0) [[unlikely]]
-      __output_.__reset(__storage_.__begin(), __storage_.__buffer_size);
-  }
-
-  _LIBCPP_HIDE_FROM_ABI void __flush(_CharT* __ptr, size_t __n) {
-    // A __flush to the direct writer happens in the following occasions:
-    // - The format function has written the maximum number of allowed code
-    //   units. At this point it's no longer valid to write to this writer. So
-    //   switch to the internal storage. This internal storage doesn't need to
-    //   be written anywhere so the __flush for that storage writes no output.
-    // - Like above, but the next "mass write" operation would overflow the
-    //   buffer. In that case the buffer is pre-emptively switched. The still
-    //   valid code units will be written separately.
-    // - The format_to_n function is finished. In this case there's no need to
-    //   switch the buffer, but for simplicity the buffers are still switched.
-    // When the __max_size <= 0 the constructor already switched the buffers.
-    if (__size_ == 0 && __ptr != __storage_.__begin()) {
-      __writer_.__flush(__ptr, __n);
-      __output_.__reset(__storage_.__begin(), __storage_.__buffer_size);
-    } else if (__size_ < __max_size_) {
-      // Copies a part of the internal buffer to the output up to n characters.
-      // See __output_buffer<_CharT>::__flush_on_overflow for more information.
-      _Size __s = std::min(_Size(__n), __max_size_ - __size_);
-      std::copy_n(__ptr, __s, __writer_.__out_it());
-      __writer_.__flush(__ptr, __s);
-    }
-
-    __size_ += __n;
-  }
-
-protected:
-  __internal_storage<_CharT> __storage_;
-  __output_buffer<_CharT> __output_;
-  __writer_direct<_OutIt, _CharT> __writer_;
-
-  _Size __max_size_;
-  _Size __size_{0};
-};
-
-/// The buffer that counts and limits the number of insertions.
-template <class _OutIt, __fmt_char_type _CharT>
-  requires(output_iterator<_OutIt, const _CharT&>)
-struct _LIBCPP_TEMPLATE_VIS __format_to_n_buffer final
-    : public __format_to_n_buffer_base< _OutIt, _CharT, __enable_direct_output<_OutIt, _CharT>> {
-  using _Base = __format_to_n_buffer_base<_OutIt, _CharT, __enable_direct_output<_OutIt, _CharT>>;
-  using _Size = iter_difference_t<_OutIt>;
-
-public:
-  _LIBCPP_HIDE_FROM_ABI explicit __format_to_n_buffer(_OutIt __out_it, _Size __max_size)
-      : _Base(std::move(__out_it), __max_size) {}
-  _LIBCPP_HIDE_FROM_ABI auto __make_output_iterator() { return this->__output_.__make_output_iterator(); }
-
-  _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __result() && {
-    this->__output_.__flush(0);
-    return {std::move(this->__writer_).__out_it(), this->__size_};
-  }
-};
-
 // ***** ***** ***** LLVM-20 classes ***** ***** *****
 
 // A dynamically growing buffer.
@@ -668,8 +634,11 @@ class _LIBCPP_TEMPLATE_VIS __allocating_buffer : public __output_buffer<_CharT>
   __allocating_buffer(const __allocating_buffer&)            = delete;
   __allocating_buffer& operator=(const __allocating_buffer&) = delete;
 
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI __allocating_buffer()
-      : __output_buffer<_CharT>{__buffer_, __buffer_size_, __prepare_write} {}
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI __allocating_buffer() : __allocating_buffer{nullptr} {}
+
+  [[nodiscard]]
+  _LIBCPP_HIDE_FROM_ABI explicit __allocating_buffer(__max_output_size* __max_output_size)
+      : __output_buffer<_CharT>{__buffer_, __buffer_size_, __prepare_write, __max_output_size} {}
 
   _LIBCPP_HIDE_FROM_ABI ~__allocating_buffer() {
     if (__ptr_ != __buffer_) {
@@ -690,6 +659,7 @@ class _LIBCPP_TEMPLATE_VIS __allocating_buffer : public __output_buffer<_CharT>
   // its capacity is exceeded a dynamic buffer will be allocated.
   static constexpr size_t __buffer_size_ = 256;
   _CharT __buffer_[__buffer_size_];
+
   _CharT* __ptr_{__buffer_};
 
   _LIBCPP_HIDE_FROM_ABI void __grow_buffer(size_t __capacity) {
@@ -729,7 +699,12 @@ template <class _OutIt, __fmt_char_type _CharT>
 class _LIBCPP_TEMPLATE_VIS __direct_iterator_buffer : public __output_buffer<_CharT> {
 public:
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __direct_iterator_buffer(_OutIt __out_it)
-      : __output_buffer<_CharT>{std::__unwrap_iter(__out_it), __buffer_size, __prepare_write}, __out_it_(__out_it) {}
+      : __direct_iterator_buffer{__out_it, nullptr} {}
+
+  [[nodiscard]]
+  _LIBCPP_HIDE_FROM_ABI explicit __direct_iterator_buffer(_OutIt __out_it, __max_output_size* __max_output_size)
+      : __output_buffer<_CharT>{std::__unwrap_iter(__out_it), __buffer_size, __prepare_write, __max_output_size},
+        __out_it_(__out_it) {}
 
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _OutIt __out_it() && { return __out_it_ + this->__size(); }
 
@@ -753,7 +728,12 @@ template <class _OutIt, __fmt_char_type _CharT>
 class _LIBCPP_TEMPLATE_VIS __container_inserter_buffer : public __output_buffer<_CharT> {
 public:
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __container_inserter_buffer(_OutIt __out_it)
-      : __output_buffer<_CharT>{__buffer_, __buffer_size, __prepare_write}, __container_{__out_it.__get_container()} {}
+      : __container_inserter_buffer{__out_it, nullptr} {}
+
+  [[nodiscard]]
+  _LIBCPP_HIDE_FROM_ABI explicit __container_inserter_buffer(_OutIt __out_it, __max_output_size* __max_output_size)
+      : __output_buffer<_CharT>{__buffer_, __buffer_size, __prepare_write, __max_output_size},
+        __container_{__out_it.__get_container()} {}
 
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI auto __out_it() && {
     __container_->insert(__container_->end(), __buffer_, __buffer_ + this->__size());
@@ -791,6 +771,9 @@ class _LIBCPP_TEMPLATE_VIS __iterator_buffer : public __allocating_buffer<_CharT
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __iterator_buffer(_OutIt __out_it)
       : __allocating_buffer<_CharT>{}, __out_it_{std::move(__out_it)} {}
 
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __iterator_buffer(_OutIt __out_it, __max_output_size* __max_output_size)
+      : __allocating_buffer<_CharT>{__max_output_size}, __out_it_{std::move(__out_it)} {}
+
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI auto __out_it() && {
     return std::ranges::copy(this->__view(), std::move(__out_it_)).out;
   }
@@ -813,6 +796,27 @@ class _LIBCPP_TEMPLATE_VIS __buffer_selector {
                                   __iterator_buffer<_OutIt, _CharT>>>;
 };
 
+// A buffer that counts and limits the number of insertions.
+template <class _OutIt, __fmt_char_type _CharT>
+class _LIBCPP_TEMPLATE_VIS __format_to_n_buffer : private __buffer_selector<_OutIt, _CharT>::type {
+public:
+  using _Base = __buffer_selector<_OutIt, _CharT>::type;
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI __format_to_n_buffer(_OutIt __out_it, iter_difference_t<_OutIt> __n)
+      : _Base{std::move(__out_it), std::addressof(__max_output_size_)},
+        __max_output_size_{__n < 0 ? size_t{0} : static_cast<size_t>(__n)} {}
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI auto __make_output_iterator() { return _Base::__make_output_iterator(); }
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __result() && {
+    return {static_cast<_Base&&>(*this).__out_it(),
+            static_cast<iter_difference_t<_OutIt>>(__max_output_size_.__code_units_written())};
+  }
+
+private:
+  __max_output_size __max_output_size_;
+};
+
 // ***** ***** ***** LLVM-19 and LLVM-20 class ***** ***** *****
 
 // A dynamically growing buffer intended to be used for retargeting a context.
diff --git a/libcxx/test/libcxx/transitive_includes/cxx03.csv b/libcxx/test/libcxx/transitive_includes/cxx03.csv
index 622fced5ffa40..f6e7db17f413f 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx03.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx03.csv
@@ -860,6 +860,7 @@ thread atomic
 thread cctype
 thread cerrno
 thread chrono
+thread climits
 thread clocale
 thread compare
 thread cstddef
diff --git a/libcxx/test/libcxx/transitive_includes/cxx11.csv b/libcxx/test/libcxx/transitive_includes/cxx11.csv
index 11c3c1322c406..752fea058e63b 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx11.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx11.csv
@@ -867,6 +867,7 @@ thread atomic
 thread cctype
 thread cerrno
 thread chrono
+thread climits
 thread clocale
 thread compare
 thread cstddef
diff --git a/libcxx/test/libcxx/transitive_includes/cxx14.csv b/libcxx/test/libcxx/transitive_includes/cxx14.csv
index 666d5c3896467..010f7e2fb82e9 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx14.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx14.csv
@@ -870,6 +870,7 @@ thread atomic
 thread cctype
 thread cerrno
 thread chrono
+thread climits
 thread clocale
 thread compare
 thread cstddef
diff --git a/libcxx/test/libcxx/transitive_includes/cxx17.csv b/libcxx/test/libcxx/transitive_includes/cxx17.csv
index 3a3aa5a894473..64c2db3eef6f9 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx17.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx17.csv
@@ -881,6 +881,7 @@ thread atomic
 thread cctype
 thread cerrno
 thread chrono
+thread climits
 thread clocale
 thread compare
 thread cstddef
diff --git a/libcxx/test/libcxx/transitive_includes/cxx20.csv b/libcxx/test/libcxx/transitive_includes/cxx20.csv
index 982c2013e3417..a7ea7f8dddbea 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx20.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx20.csv
@@ -276,6 +276,7 @@ filesystem version
 format array
 format cctype
 format cerrno
+format climits
 format clocale
 format cmath
 format cstddef
@@ -896,6 +897,7 @@ thread array
 thread atomic
 thread cctype
 thread cerrno
+thread climits
 thread clocale
 thread compare
 thread cstddef
diff --git a/libcxx/test/libcxx/transitive_includes/cxx23.csv b/libcxx/test/libcxx/transitive_includes/cxx23.csv
index 8ffb71d8b566b..a7310f20125b9 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx23.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx23.csv
@@ -180,6 +180,7 @@ filesystem version
 format array
 format cctype
 format cerrno
+format climits
 format clocale
 format cmath
 format cstddef
@@ -616,6 +617,7 @@ thread array
 thread atomic
 thread cctype
 thread cerrno
+thread climits
 thread clocale
 thread compare
 thread cstddef
diff --git a/libcxx/test/libcxx/transitive_includes/cxx26.csv b/libcxx/test/libcxx/transitive_includes/cxx26.csv
index 8ffb71d8b566b..a7310f20125b9 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx26.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx26.csv
@@ -180,6 +180,7 @@ filesystem version
 format array
 format cctype
 format cerrno
+format climits
 format clocale
 format cmath
 format cstddef
@@ -616,6 +617,7 @@ thread array
 thread atomic
 thread cctype
 thread cerrno
+thread climits
 thread clocale
 thread compare
 thread cstddef

``````````

</details>


https://github.com/llvm/llvm-project/pull/101831


More information about the llvm-branch-commits mailing list