-
Couldn't load subscription status.
- Fork 15k
[LLVM][Support] Allow char[N] parameters in llvm::format
#159541
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
@llvm/pr-subscribers-llvm-support Author: Tomohiro Kashiwada (kikairoya) ChangesCygwin builds are currently broken after #157312, which effectively reverted #138117. The root cause is that Cygwin defines This patch allows Other array types remain rejected:
Full diff: https://github.com/llvm/llvm-project/pull/159541.diff 3 Files Affected:
diff --git a/llvm/include/llvm/Support/Format.h b/llvm/include/llvm/Support/Format.h
index 2553002b37899..6cd73a213177d 100644
--- a/llvm/include/llvm/Support/Format.h
+++ b/llvm/include/llvm/Support/Format.h
@@ -78,6 +78,7 @@ class LLVM_ABI format_object_base {
/// printed, this synthesizes the string into a temporary buffer provided and
/// returns whether or not it is big enough.
+namespace detail {
// Helper to validate that format() parameters are scalars or pointers.
template <typename... Args> struct validate_format_parameters;
template <typename Arg, typename... Args>
@@ -88,9 +89,19 @@ struct validate_format_parameters<Arg, Args...> {
};
template <> struct validate_format_parameters<> {};
+template <typename T> struct decay_if_c_char_array {
+ using type = T;
+};
+template <std::size_t N> struct decay_if_c_char_array<char[N]> {
+ using type = const char *;
+};
+template <typename T>
+using decay_if_c_char_array_t = typename decay_if_c_char_array<T>::type;
+} // namespace detail
+
template <typename... Ts>
class format_object final : public format_object_base {
- std::tuple<Ts...> Vals;
+ std::tuple<detail::decay_if_c_char_array_t<Ts>...> Vals;
template <std::size_t... Is>
int snprint_tuple(char *Buffer, unsigned BufferSize,
@@ -105,7 +116,8 @@ class format_object final : public format_object_base {
public:
format_object(const char *fmt, const Ts &... vals)
: format_object_base(fmt), Vals(vals...) {
- validate_format_parameters<Ts...>();
+ detail::validate_format_parameters<
+ detail::decay_if_c_char_array_t<Ts>...>();
}
int snprint(char *Buffer, unsigned BufferSize) const override {
diff --git a/llvm/unittests/Support/CMakeLists.txt b/llvm/unittests/Support/CMakeLists.txt
index d1dfb1dc4a722..1f2a68545d107 100644
--- a/llvm/unittests/Support/CMakeLists.txt
+++ b/llvm/unittests/Support/CMakeLists.txt
@@ -44,6 +44,7 @@ add_llvm_unittest(SupportTests
ExtensibleRTTITest.cpp
FileCollectorTest.cpp
FileOutputBufferTest.cpp
+ Format.cpp
FormatVariadicTest.cpp
FSUniqueIDTest.cpp
GenericDomTreeTest.cpp
diff --git a/llvm/unittests/Support/Format.cpp b/llvm/unittests/Support/Format.cpp
new file mode 100644
index 0000000000000..c4e421fe9dc4c
--- /dev/null
+++ b/llvm/unittests/Support/Format.cpp
@@ -0,0 +1,56 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Format.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+template <typename FormatTy>
+std::string printToString(unsigned MaxN, FormatTy &&Fmt) {
+ std::vector<char> Dst(MaxN + 2);
+ int N = Fmt.snprint(Dst.data(), Dst.size());
+ Dst.back() = 0;
+ return N < 0 ? "" : Dst.data();
+}
+
+template <typename Expected, typename Arg>
+constexpr bool checkDecayTypeEq(const Arg &arg) {
+ return std::is_same_v<detail::decay_if_c_char_array_t<Arg>, Expected>;
+}
+
+TEST(Format, DecayIfCCharArray) {
+ char Array[] = "Array";
+ const char ConstArray[] = "ConstArray";
+ char PtrBuf[] = "Ptr";
+ char *Ptr = PtrBuf;
+ const char *PtrToConst = "PtrToConst";
+
+ EXPECT_EQ(" Literal", printToString(20, format("%15s", "Literal")));
+ EXPECT_EQ(" Array", printToString(20, format("%15s", Array)));
+ EXPECT_EQ(" ConstArray", printToString(20, format("%15s", ConstArray)));
+ EXPECT_EQ(" Ptr", printToString(20, format("%15s", Ptr)));
+ EXPECT_EQ(" PtrToConst", printToString(20, format("%15s", PtrToConst)));
+
+ EXPECT_TRUE(checkDecayTypeEq<const char *>("Literal"));
+ EXPECT_TRUE(checkDecayTypeEq<const char *>(Array));
+ EXPECT_TRUE(checkDecayTypeEq<const char *>(ConstArray));
+ EXPECT_TRUE(checkDecayTypeEq<char *>(Ptr));
+ EXPECT_TRUE(checkDecayTypeEq<const char *>(PtrToConst));
+ EXPECT_TRUE(checkDecayTypeEq<char>(PtrToConst[0]));
+ EXPECT_TRUE(
+ checkDecayTypeEq<const char *>(static_cast<const char *>("Literal")));
+
+ wchar_t WCharArray[] = L"WCharArray";
+ EXPECT_TRUE(checkDecayTypeEq<wchar_t[11]>(WCharArray));
+ EXPECT_TRUE(checkDecayTypeEq<wchar_t>(WCharArray[0]));
+}
+
+} // namespace
|
|
ping |
Cygwin builds are currently broken after llvm#157312, which effectively reverted llvm#138117. The root cause is that Cygwin defines `DL_info::dli_fname` as `char[N]`, which is not a valid parameter type for `llvm::format`. This patch allows `llvm::format` to accept `char[N]` by decaying it to `const char *`. As a result, string literals are also accepted without an explicit cast. Other array types remain rejected: - Wide/unicode character arrays (e.g., `wchar_t[N]`) are not supported, as LLVM does not use them and they are less compatible with platform's `printf` implementations. - Non-character arrays (e.g., `int[N]`) are also rejected, since passing such arrays to `printf` is meaningless.
f5d7184 to
f74084c
Compare
|
ping |
|
ping. @kazutakahirata @tgymnich Could you please take a look at this? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the breakage and delay in reviewing this.
LGTM. Thanks!
|
Thank you for the reviewing and merging this! |
…9541) Cygwin builds are currently broken after llvm#157312, which effectively reverted llvm#138117. The root cause is that Cygwin defines `DL_info::dli_fname` as `char[N]`, which is not a valid parameter type for `llvm::format`. This patch allows `llvm::format` to accept `char[N]` by decaying it to `const char *`. As a result, string literals are also accepted without an explicit cast. Other array types remain rejected: - Wide/unicode character arrays (e.g., `wchar_t[N]`) are not supported, as LLVM does not use them and they are less compatible with platform's `printf` implementations. - Non-character arrays (e.g., `int[N]`) are also rejected, since passing such arrays to `printf` is meaningless.
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/168/builds/16618 Here is the relevant piece of the build log for the reference |
…9541) Cygwin builds are currently broken after llvm#157312, which effectively reverted llvm#138117. The root cause is that Cygwin defines `DL_info::dli_fname` as `char[N]`, which is not a valid parameter type for `llvm::format`. This patch allows `llvm::format` to accept `char[N]` by decaying it to `const char *`. As a result, string literals are also accepted without an explicit cast. Other array types remain rejected: - Wide/unicode character arrays (e.g., `wchar_t[N]`) are not supported, as LLVM does not use them and they are less compatible with platform's `printf` implementations. - Non-character arrays (e.g., `int[N]`) are also rejected, since passing such arrays to `printf` is meaningless.
Cygwin builds are currently broken after #157312, which effectively reverted #138117. The root cause is that Cygwin defines
DL_info::dli_fnameaschar[N], which is not a valid parameter type forllvm::format.This patch allows
llvm::formatto acceptchar[N]by decaying it toconst char *. As a result, string literals are also accepted without an explicit cast.Other array types remain rejected:
wchar_t[N]) are not supported, as LLVM does not use them and they are less compatible with platform'sprintfimplementations.int[N]) are also rejected, since passing such arrays toprintfis meaningless.