diff --git a/llvm/include/llvm/Support/FormatProviders.h b/llvm/include/llvm/Support/FormatProviders.h --- a/llvm/include/llvm/Support/FormatProviders.h +++ b/llvm/include/llvm/Support/FormatProviders.h @@ -355,7 +355,6 @@ template class format_provider> { using value = typename std::iterator_traits::value_type; - using reference = typename std::iterator_traits::reference; static StringRef consumeOneOption(StringRef &Style, char Indicator, StringRef Default) { @@ -403,15 +402,13 @@ auto Begin = V.begin(); auto End = V.end(); if (Begin != End) { - auto Adapter = - detail::build_format_adapter(std::forward(*Begin)); + auto Adapter = detail::build_format_adapter(*Begin); Adapter.format(Stream, ArgStyle); ++Begin; } while (Begin != End) { Stream << Sep; - auto Adapter = - detail::build_format_adapter(std::forward(*Begin)); + auto Adapter = detail::build_format_adapter(*Begin); Adapter.format(Stream, ArgStyle); ++Begin; } diff --git a/llvm/include/llvm/Support/FormatVariadicDetails.h b/llvm/include/llvm/Support/FormatVariadicDetails.h --- a/llvm/include/llvm/Support/FormatVariadicDetails.h +++ b/llvm/include/llvm/Support/FormatVariadicDetails.h @@ -75,8 +75,6 @@ // Test if raw_ostream& << T -> raw_ostream& is findable via ADL. template class has_StreamOperator { public: - using ConstRefT = const std::decay_t &; - template static char test( std::enable_if_t() @@ -86,7 +84,8 @@ template static double test(...); - static bool const value = (sizeof(test(nullptr)) == 1); + // NOLINTNEXTLINE(readability-identifier-naming) + static bool const value = (sizeof(test(nullptr)) == 1); }; // Simple template that decides whether a type T should use the member-function diff --git a/llvm/unittests/Support/FormatVariadicTest.cpp b/llvm/unittests/Support/FormatVariadicTest.cpp --- a/llvm/unittests/Support/FormatVariadicTest.cpp +++ b/llvm/unittests/Support/FormatVariadicTest.cpp @@ -698,3 +698,49 @@ EXPECT_EQ("X", formatv("{0}", fmt_consume(std::move(E1))).str()); EXPECT_FALSE(E1.isA()); // consumed } + +TEST(FormatVariadicTest, FormatFilterRange) { + std::vector Vec{0, 1, 2}; + auto Range = map_range(Vec, [](int V) { return V + 1; }); + EXPECT_EQ("1, 2, 3", formatv("{0}", Range).str()); +} + +namespace { + +class IntegerValuesRange final + : public indexed_accessor_range { +public: + using indexed_accessor_range::indexed_accessor_range; + + static int dereference(const NoneType &, ptrdiff_t Index) { + return static_cast(Index); + } +}; + +TEST(FormatVariadicTest, FormatRangeNonRef) { + IntegerValuesRange Range(None, 0, 3); + EXPECT_EQ("0, 1, 2", + formatv("{0}", make_range(Range.begin(), Range.end())).str()); +} + +class PassByRef { +public: + int Val = 0; + PassByRef(int Val) : Val(Val) {} +}; + +raw_ostream &operator<<(raw_ostream &OS, PassByRef &Obj) { + return OS << Obj.Val; +} + +static_assert(detail::has_StreamOperator::value, ""); +static_assert(detail::uses_stream_operator::value, ""); + +TEST(FormatVariadicTest, StreamOperatorPassByRef) { + PassByRef Obj(10); + EXPECT_EQ("10", formatv("{0}", Obj).str()); +} + +} // namespace