Support formatting formatv_objects.

Summary:
Support formatting formatv_objects.

While here, fix documentation about member-formatters, and attempted
perfect-forwarding (I think).

Reviewers: zturner

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D38997

llvm-svn: 316330
diff --git a/llvm/unittests/Support/FormatVariadicTest.cpp b/llvm/unittests/Support/FormatVariadicTest.cpp
index bfbe556..a6ce37e 100644
--- a/llvm/unittests/Support/FormatVariadicTest.cpp
+++ b/llvm/unittests/Support/FormatVariadicTest.cpp
@@ -578,3 +578,32 @@
   // 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);
+}