[libcxx-commits] [PATCH] D121530: [libc++][format] Implement format-string.

Victor Zverovich via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Sat Jun 4 08:35:10 PDT 2022


vitaut requested changes to this revision.
vitaut added a comment.
This revision now requires changes to proceed.

In general looks good but I would strongly recommend not to instantiate all of formatting path just to validate width/precision (see an inline comment).



================
Comment at: libcxx/benchmarks/formatter_float.bench.cpp:219-220
     std::array<char, 20'000> output;
     std::string fmt{std::string("{:") + Alignment<A::value>::fmt + Precision<P::value>::fmt +
                     Localization<L::value>::fmt + DisplayType<DT::value>::fmt + "}"};
 
----------------
Since all the components are known at compile time why not make format string construction `constexpr` and make the benchmark more realistic by replacing `vformat_to` with `format_to`?


================
Comment at: libcxx/docs/ReleaseNotes.rst:115
 
+- The format functions (``std::format``, ``std:;format_to``,
+  ``std::format_to_n``, and ``std::formatted_size``) now validate the format
----------------
typo: `std:;format_to` -> `std::format_to`


================
Comment at: libcxx/docs/ReleaseNotes.rst:117
+  ``std::format_to_n``, and ``std::formatted_size``) now validate the format
+  string compile-time. This means the argument needs to be a compile time
+  literal. This may break existing code. When the format string is invalid this
----------------
compile-time -> at compile time
compile time literal -> compile-time literal


================
Comment at: libcxx/docs/ReleaseNotes.rst:119
+  literal. This may break existing code. When the format string is invalid this
+  will make the code ill-formed instead of throwing an exception run-time.
+  (This does not affect the ``v`` functions.)
----------------
run-time -> at run time.


================
Comment at: libcxx/include/__format/parser_std_format_spec.h:260
    */
-  constexpr bool __has_width_field() const noexcept {
-    return __width_as_arg || __width;
-  }
+  constexpr bool __width_needs_substitution() const noexcept { return __width_as_arg; }
 
----------------
Why make it public? Isn't it only called by subclasses?


================
Comment at: libcxx/include/format:217
+template <class _CharT>
+class _LIBCPP_TEMPLATE_VIS __compile_time_handle {
+public:
----------------
What is this class for? A comment would be nice.


================
Comment at: libcxx/include/format:259
+  _LIBCPP_HIDE_FROM_ABI constexpr __arg_t arg(size_t __id) const {
+    // Accessing array out of bounds is UB thus an error.
+    return __args_[__id];
----------------
Does it give a user-friendly error? Perhaps it would be better to generate an error ourselves with a better message because this is a pretty common case.


================
Comment at: libcxx/include/format:302
+  case __arg_t::__long_long:
+#  ifndef _LIBCPP_HAS_NO_INT128
+  case __arg_t::__i128:
----------------
Is this ifdef needed? In principle you could always define `__i128` and `__u128` but only use it if `_LIBCPP_HAS_NO_INT128` is set. This might be beneficial for ABI compatibility and simplify some code like the one here.


================
Comment at: libcxx/include/format:313
+  default:
+    __throw_format_error("Argument isn't an integral");
+  }
----------------
Should be either "isn't integral" or "isn't an integral type"


================
Comment at: libcxx/include/format:502-503
+  consteval __basic_format_string(const _Tp& __str) : __str_{__str} {
+    __format::__vformat_to(basic_format_parse_context<_CharT>{__str_, sizeof...(_Args)},
+                           _Context{__types_.data(), __handles_.data()});
+  }
----------------
Using `__vformat_to` to do validation is an interesting idea but instantiation all of the formatting code just to check dynamic width/precision will likely have negative impact on compile times. I would recommend only doing parsing here and a small dynamic width/precision validation step. This should also make `__compile_time_basic_format_context` unnecessary.


================
Comment at: libcxx/include/format:569-573
+#    ifdef _WIN32
+          __basic_format_string<char, type_identity_t<_Args>...> __fmt,
+#    else
+          __format_string<_Args...> __fmt,
+#    endif
----------------
Can we avoid these ugly ifdefs? Why not rename `__format_string` to `__format_string_t` or similar?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121530/new/

https://reviews.llvm.org/D121530



More information about the libcxx-commits mailing list