summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/Support/FormatVariadic.h12
-rw-r--r--llvm/include/llvm/Support/FormatVariadicDetails.h2
-rw-r--r--llvm/unittests/Support/FormatVariadicTest.cpp29
3 files changed, 39 insertions, 4 deletions
diff --git a/llvm/include/llvm/Support/FormatVariadic.h b/llvm/include/llvm/Support/FormatVariadic.h
index 408c6d8b2e0..8c08a7d9488 100644
--- a/llvm/include/llvm/Support/FormatVariadic.h
+++ b/llvm/include/llvm/Support/FormatVariadic.h
@@ -230,9 +230,8 @@ public:
// For a given parameter of type T, the following steps are executed in order
// until a match is found:
//
-// 1. If the parameter is of class type, and contains a method
-// void format(raw_ostream &Stream, StringRef Options)
-// Then this method is invoked to produce the formatted output. The
+// 1. If the parameter is of class type, and inherits from format_adapter,
+// Then format() is invoked on it to produce the formatted output. The
// implementation should write the formatted text into `Stream`.
// 2. If there is a suitable template specialization of format_provider<>
// for type T containing a method whose signature is:
@@ -259,6 +258,13 @@ inline auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object<decltype(
std::make_tuple(detail::build_format_adapter(std::forward<Ts>(Vals))...));
}
+// Allow a formatv_object to be formatted (no options supported).
+template <typename T> struct format_provider<formatv_object<T>> {
+ static void format(const formatv_object<T> &V, raw_ostream &OS, StringRef) {
+ OS << V;
+ }
+};
+
} // end namespace llvm
#endif // LLVM_SUPPORT_FORMATVARIADIC_H
diff --git a/llvm/include/llvm/Support/FormatVariadicDetails.h b/llvm/include/llvm/Support/FormatVariadicDetails.h
index b4a564ffc26..9b60462209d 100644
--- a/llvm/include/llvm/Support/FormatVariadicDetails.h
+++ b/llvm/include/llvm/Support/FormatVariadicDetails.h
@@ -31,7 +31,7 @@ template <typename T> class provider_format_adapter : public format_adapter {
T Item;
public:
- explicit provider_format_adapter(T &&Item) : Item(Item) {}
+ explicit provider_format_adapter(T &&Item) : Item(std::forward<T>(Item)) {}
void format(llvm::raw_ostream &S, StringRef Options) override {
format_provider<typename std::decay<T>::type>::format(Item, S, Options);
diff --git a/llvm/unittests/Support/FormatVariadicTest.cpp b/llvm/unittests/Support/FormatVariadicTest.cpp
index bfbe556b31a..a6ce37e014f 100644
--- a/llvm/unittests/Support/FormatVariadicTest.cpp
+++ b/llvm/unittests/Support/FormatVariadicTest.cpp
@@ -578,3 +578,32 @@ TEST(FormatVariadicTest, FormatAdapter) {
// const Format cvar(1);
// EXPECT_EQ("Format", formatv("{0}", cvar).str());
}
+
+TEST(FormatVariadicTest, FormatFormatvObject) {
+ EXPECT_EQ("Format", formatv("F{0}t", formatv("o{0}a", "rm")).str());
+ EXPECT_EQ("[ ! ]", formatv("[{0,+5}]", formatv("{0,-2}", "!")).str());
+}
+
+namespace {
+struct Recorder {
+ int Copied = 0, Moved = 0;
+ Recorder() = default;
+ Recorder(const Recorder &Copy) : Copied(1 + Copy.Copied), Moved(Copy.Moved) {}
+ Recorder(const Recorder &&Move)
+ : Copied(Move.Copied), Moved(1 + Move.Moved) {}
+};
+} // namespace
+template <> struct llvm::format_provider<Recorder> {
+ static void format(const Recorder &R, raw_ostream &OS, StringRef style) {
+ OS << R.Copied << "C " << R.Moved << "M";
+ }
+};
+
+TEST(FormatVariadicTest, CopiesAndMoves) {
+ Recorder R;
+ EXPECT_EQ("0C 0M", formatv("{0}", R).str());
+ EXPECT_EQ("0C 3M", formatv("{0}", std::move(R)).str());
+ EXPECT_EQ("0C 3M", formatv("{0}", Recorder()).str());
+ EXPECT_EQ(0, R.Copied);
+ EXPECT_EQ(0, R.Moved);
+}
OpenPOWER on IntegriCloud