Simplify format member detection in FormatVariadic

Summary:
This replaces the format member search, which was quite complicated, with a more
direct approach to detecting whether a class should be formatted using the
format-member method. Instead we use a special type llvm::format_adapter, which
every adapter must inherit from. Then the search can be simply implemented with
the is_base_of type trait.

Aside from the simplification, I like this way more because it makes it more
explicit that you are supposed to use this type only for adapter-like
formattings, and the other approach (format_provider overloads) should be used
as a default (a mistake I made when first trying to use this library).

The only slight change in behaviour here is that now choose the format-adapter
branch even if the format member invocation will fail to compile (e.g. because it is a
non-const member function and we are passing a const adapter), whereas
previously we would have gone on to search for format_providers for the type.
However, I think that is actually a good thing, as it probably means the
programmer did something wrong.

Reviewers: zturner, inglorion

Subscribers: llvm-commits

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

llvm-svn: 289795
diff --git a/llvm/unittests/Support/FormatVariadicTest.cpp b/llvm/unittests/Support/FormatVariadicTest.cpp
index ca6df4c..9307c6d 100644
--- a/llvm/unittests/Support/FormatVariadicTest.cpp
+++ b/llvm/unittests/Support/FormatVariadicTest.cpp
@@ -13,33 +13,26 @@
 
 using namespace llvm;
 
-// Compile-time tests for the uses_format_member template
+// Compile-time tests templates in the detail namespace.
 namespace {
-struct ConstFormat {
-  void format(raw_ostream &OS, StringRef Opt) const { OS << "ConstFormat"; }
-};
-
-struct Format {
-  void format(raw_ostream &OS, StringRef Opt) { OS << "Format"; }
+struct Format : public FormatAdapter<int> {
+  Format(int N) : FormatAdapter<int>(std::move(N)) {}
+  void format(raw_ostream &OS, StringRef Opt) override { OS << "Format"; }
 };
 
 using detail::uses_format_member;
+using detail::uses_missing_provider;
 
 static_assert(uses_format_member<Format>::value, "");
 static_assert(uses_format_member<Format &>::value, "");
 static_assert(uses_format_member<Format &&>::value, "");
-static_assert(!uses_format_member<const Format>::value, "");
-static_assert(!uses_format_member<const Format &>::value, "");
-static_assert(!uses_format_member<const volatile Format>::value, "");
-static_assert(!uses_format_member<const volatile Format &>::value, "");
+static_assert(uses_format_member<const Format>::value, "");
+static_assert(uses_format_member<const Format &>::value, "");
+static_assert(uses_format_member<const volatile Format>::value, "");
+static_assert(uses_format_member<const volatile Format &>::value, "");
 
-static_assert(uses_format_member<ConstFormat>::value, "");
-static_assert(uses_format_member<ConstFormat &>::value, "");
-static_assert(uses_format_member<ConstFormat &&>::value, "");
-static_assert(uses_format_member<const ConstFormat>::value, "");
-static_assert(uses_format_member<const ConstFormat &>::value, "");
-static_assert(uses_format_member<const volatile ConstFormat>::value, "");
-static_assert(uses_format_member<const volatile ConstFormat &>::value, "");
+struct NoFormat {};
+static_assert(uses_missing_provider<NoFormat>::value, "");
 }
 
 TEST(FormatVariadicTest, EmptyFormatString) {
@@ -535,12 +528,10 @@
 }
 
 TEST(FormatVariadicTest, Adapter) {
-  class Negative {
-    int N;
-
+  class Negative : public FormatAdapter<int> {
   public:
-    explicit Negative(int N) : N(N) {}
-    void format(raw_ostream &S, StringRef Options) const { S << -N; }
+    explicit Negative(int N) : FormatAdapter<int>(std::move(N)) {}
+    void format(raw_ostream &S, StringRef Options) override { S << -Item; }
   };
 
   EXPECT_EQ("-7", formatv("{0}", Negative(7)).str());
@@ -566,25 +557,14 @@
   EXPECT_EQ("1 2", S2);
 }
 
-TEST(FormatVariadicTest, FormatMember) {
-  EXPECT_EQ("Format", formatv("{0}", Format()).str());
+TEST(FormatVariadicTest, FormatAdapter) {
+  EXPECT_EQ("Format", formatv("{0}", Format(1)).str());
 
-  Format var;
+  Format var(1);
   EXPECT_EQ("Format", formatv("{0}", var).str());
   EXPECT_EQ("Format", formatv("{0}", std::move(var)).str());
 
   // Not supposed to compile
-  // const Format cvar{};
+  // const Format cvar(1);
   // EXPECT_EQ("Format", formatv("{0}", cvar).str());
 }
-
-TEST(FormatVariadicTest, FormatMemberConst) {
-  EXPECT_EQ("ConstFormat", formatv("{0}", ConstFormat()).str());
-
-  ConstFormat var;
-  EXPECT_EQ("ConstFormat", formatv("{0}", var).str());
-  EXPECT_EQ("ConstFormat", formatv("{0}", std::move(var)).str());
-
-  const ConstFormat cvar{};
-  EXPECT_EQ("ConstFormat", formatv("{0}", cvar).str());
-}