Index: include/llvm/Support/FormatAdapters.h =================================================================== --- include/llvm/Support/FormatAdapters.h +++ include/llvm/Support/FormatAdapters.h @@ -17,11 +17,10 @@ #include "llvm/Support/raw_ostream.h" namespace llvm { -template class AdapterBase { +template class AdapterBase : public format_adapter { protected: - explicit AdapterBase(T &&Item) : Item(Item) {} + explicit AdapterBase(T &&Item) : format_adapter(Item) {} - T Item; static_assert(!detail::uses_missing_provider::value, "Item does not have a format provider!"); }; @@ -89,4 +88,4 @@ } } -#endif \ No newline at end of file +#endif Index: include/llvm/Support/FormatVariadicDetails.h =================================================================== --- include/llvm/Support/FormatVariadicDetails.h +++ include/llvm/Support/FormatVariadicDetails.h @@ -19,6 +19,20 @@ template struct format_provider {}; namespace detail { +class format_adapter {}; +} + +template +class format_adapter: public detail::format_adapter { + typedef T type; +protected: + explicit format_adapter(T Item) : Item(Item) {} + + T Item; +}; + + +namespace detail { class format_wrapper { protected: @@ -52,51 +66,6 @@ template class missing_format_wrapper; -// Test if T is a class that contains a member function with the signature: -// -// void format(raw_ostream &, StringRef); -// -// It is assumed T is a non-reference type. -template class has_FormatMember { -public: - static bool const value = false; -}; - -template -class has_FormatMember::value && - std::is_const::value>::type> { - using CleanT = typename std::remove_volatile::type; - using Signature_format = void (CleanT::*)(llvm::raw_ostream &S, - StringRef Options) const; - - template - static char test2(SameType *); - - template static double test2(...); - -public: - static bool const value = (sizeof(test2(nullptr)) == 1); -}; - -template -class has_FormatMember< - T, typename std::enable_if::value && - !std::is_const::value>::type> { - using CleanT = typename std::remove_cv::type; - using Signature_format = void (CleanT::*)(llvm::raw_ostream &S, - StringRef Options); - - template - static char test2(SameType *); - - template static double test2(...); - -public: - static bool const value = - (sizeof(test2(nullptr)) == 1) || has_FormatMember::value; -}; - // Test if format_provider is defined on T and contains a member function // with the signature: // static void format(const T&, raw_stream &, StringRef); @@ -122,7 +91,8 @@ struct uses_format_member : public std::integral_constant< bool, - has_FormatMember::type>::value> {}; + std::is_base_of::type>::value> {}; // Simple template that decides whether a type T should use the format_provider // based format() invocation. The member function takes priority, so this test Index: unittests/Support/FormatVariadicTest.cpp =================================================================== --- unittests/Support/FormatVariadicTest.cpp +++ unittests/Support/FormatVariadicTest.cpp @@ -15,11 +15,13 @@ // Compile-time tests for the uses_format_member template namespace { -struct ConstFormat { +struct ConstFormat : public format_adapter { + ConstFormat(int N) : format_adapter(N) {} void format(raw_ostream &OS, StringRef Opt) const { OS << "ConstFormat"; } }; -struct Format { +struct Format : public format_adapter { + Format(int N) : format_adapter(N) {} void format(raw_ostream &OS, StringRef Opt) { OS << "Format"; } }; @@ -28,10 +30,10 @@ static_assert(uses_format_member::value, ""); static_assert(uses_format_member::value, ""); static_assert(uses_format_member::value, ""); -static_assert(!uses_format_member::value, ""); -static_assert(!uses_format_member::value, ""); -static_assert(!uses_format_member::value, ""); -static_assert(!uses_format_member::value, ""); +static_assert(uses_format_member::value, ""); +static_assert(uses_format_member::value, ""); +static_assert(uses_format_member::value, ""); +static_assert(uses_format_member::value, ""); static_assert(uses_format_member::value, ""); static_assert(uses_format_member::value, ""); @@ -535,12 +537,10 @@ } TEST(FormatVariadicTest, Adapter) { - class Negative { - int N; - + class Negative: public format_adapter { public: - explicit Negative(int N) : N(N) {} - void format(raw_ostream &S, StringRef Options) const { S << -N; } + explicit Negative(int N) : format_adapter(N) {} + void format(raw_ostream &S, StringRef Options) const { S << -Item; } }; EXPECT_EQ("-7", formatv("{0}", Negative(7)).str()); @@ -567,24 +567,24 @@ } TEST(FormatVariadicTest, FormatMember) { - EXPECT_EQ("Format", formatv("{0}", Format()).str()); + 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()); + EXPECT_EQ("ConstFormat", formatv("{0}", ConstFormat(1)).str()); - ConstFormat var; + ConstFormat var(1); EXPECT_EQ("ConstFormat", formatv("{0}", var).str()); EXPECT_EQ("ConstFormat", formatv("{0}", std::move(var)).str()); - const ConstFormat cvar{}; + const ConstFormat cvar(1); EXPECT_EQ("ConstFormat", formatv("{0}", cvar).str()); }