diff --git a/libc/test/ErrnoSetterMatcher.h b/libc/test/ErrnoSetterMatcher.h --- a/libc/test/ErrnoSetterMatcher.h +++ b/libc/test/ErrnoSetterMatcher.h @@ -29,15 +29,18 @@ ErrnoSetterMatcher(T ExpectedReturn, int ExpectedErrno) : ExpectedReturn(ExpectedReturn), ExpectedErrno(ExpectedErrno) {} - void explainError(testutils::StreamWrapper &OS) override { + void explainError() override { if (ActualReturn != ExpectedReturn) - OS << "Expected return to be " << ExpectedReturn << " but got " - << ActualReturn << ".\nExpecte errno to be " << strerror(ExpectedErrno) - << " but got " << strerror(ActualErrno) << ".\n"; + __llvm_libc::testing::tlog + << "Expected return to be " << ExpectedReturn << " but got " + << ActualReturn << ".\nExpecte errno to be " + << strerror(ExpectedErrno) << " but got " << strerror(ActualErrno) + << ".\n"; else - OS << "Correct value " << ExpectedReturn - << " was returned\nBut errno was unexpectely set to " - << strerror(ActualErrno) << ".\n"; + __llvm_libc::testing::tlog + << "Correct value " << ExpectedReturn + << " was returned\nBut errno was unexpectely set to " + << strerror(ActualErrno) << ".\n"; } bool match(T Got) { diff --git a/libc/test/UnitTest/CMakeLists.txt b/libc/test/UnitTest/CMakeLists.txt --- a/libc/test/UnitTest/CMakeLists.txt +++ b/libc/test/UnitTest/CMakeLists.txt @@ -1,20 +1,10 @@ -add_library( - TestLogger - TestLogger.cpp - TestLogger.h -) -target_include_directories(TestLogger PUBLIC ${LIBC_SOURCE_DIR}) -add_dependencies(TestLogger - libc.src.__support.CPP.string - libc.src.__support.CPP.string_view - libc.src.__support.OSUtil.osutil -) - add_library( LibcUnitTest Test.h LibcTest.cpp LibcTest.h + TestLogger.cpp + TestLogger.h ) target_include_directories(LibcUnitTest PUBLIC ${LIBC_SOURCE_DIR}) add_dependencies( @@ -22,8 +12,9 @@ libc.src.__support.CPP.string libc.src.__support.CPP.string_view libc.src.__support.CPP.type_traits - libc.src.__support.uint128 TestLogger) -target_link_libraries(LibcUnitTest PUBLIC libc_test_utils TestLogger) + libc.src.__support.OSUtil.osutil + libc.src.__support.uint128) +target_link_libraries(LibcUnitTest PUBLIC libc_test_utils) add_library( LibcUnitTestMain @@ -39,14 +30,14 @@ HDRS StringUtils.h DEPENDS - libc.src.__support.CPP.type_traits + libc.src.__support.CPP.string + libc.src.__support.CPP.type_traits ) add_library( LibcFPTestHelpers FPExceptMatcher.cpp FPExceptMatcher.h - FPMatcher.cpp FPMatcher.h ) target_include_directories(LibcFPTestHelpers PUBLIC ${LIBC_SOURCE_DIR}) @@ -57,6 +48,7 @@ libc.test.UnitTest.string_utils libc.src.__support.FPUtil.fp_bits libc.src.__support.FPUtil.fenv_impl + libc.test.UnitTest.string_utils ) add_library( diff --git a/libc/test/UnitTest/FPExceptMatcher.h b/libc/test/UnitTest/FPExceptMatcher.h --- a/libc/test/UnitTest/FPExceptMatcher.h +++ b/libc/test/UnitTest/FPExceptMatcher.h @@ -44,9 +44,10 @@ bool match(bool unused) { return exceptionRaised; } - void explainError(testutils::StreamWrapper &stream) override { - stream << "A floating point exception should have been raised but it " - << "wasn't\n"; + void explainError() override { + __llvm_libc::testing::tlog + << "A floating point exception should have been raised but it " + << "wasn't\n"; } }; diff --git a/libc/test/UnitTest/FPMatcher.h b/libc/test/UnitTest/FPMatcher.h --- a/libc/test/UnitTest/FPMatcher.h +++ b/libc/test/UnitTest/FPMatcher.h @@ -11,6 +11,7 @@ #include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/FPUtil/FPBits.h" +#include "test/UnitTest/StringUtils.h" #include "test/UnitTest/Test.h" #include "utils/testutils/RoundingModeUtils.h" @@ -20,9 +21,42 @@ namespace fputil { namespace testing { -template +template cpp::enable_if_t, void> -describeValue(const char *label, ValType value, StreamType &stream); +describeValue(const char *label, ValType value) { + __llvm_libc::testing::tlog << label; + + FPBits bits(value); + if (bits.is_nan()) { + __llvm_libc::testing::tlog << "(NaN)"; + } else if (bits.is_inf()) { + if (bits.get_sign()) + __llvm_libc::testing::tlog << "(-Infinity)"; + else + __llvm_libc::testing::tlog << "(+Infinity)"; + } else { + constexpr int exponentWidthInHex = + (fputil::ExponentWidth::VALUE - 1) / 4 + 1; + constexpr int mantissaWidthInHex = + (fputil::MantissaWidth::VALUE - 1) / 4 + 1; + constexpr int bitsWidthInHex = + sizeof(typename fputil::FPBits::UIntType) * 2; + + __llvm_libc::testing::tlog + << "0x" + << int_to_hex::UIntType>( + bits.uintval(), bitsWidthInHex) + << ", (S | E | M) = (" << (bits.get_sign() ? '1' : '0') << " | 0x" + << int_to_hex(bits.get_unbiased_exponent(), + exponentWidthInHex) + << " | 0x" + << int_to_hex::UIntType>( + bits.get_mantissa(), mantissaWidthInHex) + << ")"; + } + + __llvm_libc::testing::tlog << '\n'; +} template class FPMatcher : public __llvm_libc::testing::Matcher { @@ -52,9 +86,9 @@ (actualBits.uintval() != expectedBits.uintval()); } - void explainError(testutils::StreamWrapper &stream) override { - describeValue("Expected floating point value: ", expected, stream); - describeValue(" Actual floating point value: ", actual, stream); + void explainError() override { + describeValue("Expected floating point value: ", expected); + describeValue(" Actual floating point value: ", actual); } }; diff --git a/libc/test/UnitTest/FPMatcher.cpp b/libc/test/UnitTest/FPMatcher.cpp deleted file mode 100644 --- a/libc/test/UnitTest/FPMatcher.cpp +++ /dev/null @@ -1,72 +0,0 @@ -//===-- TestMatchers.cpp ----------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "FPMatcher.h" - -#include "src/__support/FPUtil/FPBits.h" - -#include "test/UnitTest/StringUtils.h" - -#include -#include - -namespace __llvm_libc { -namespace fputil { -namespace testing { - -template -cpp::enable_if_t, void> -describeValue(const char *label, ValType value, StreamType &stream) { - stream << label; - - FPBits bits(value); - if (bits.is_nan()) { - stream << "(NaN)"; - } else if (bits.is_inf()) { - if (bits.get_sign()) - stream << "(-Infinity)"; - else - stream << "(+Infinity)"; - } else { - constexpr int exponentWidthInHex = - (fputil::ExponentWidth::VALUE - 1) / 4 + 1; - constexpr int mantissaWidthInHex = - (fputil::MantissaWidth::VALUE - 1) / 4 + 1; - constexpr int bitsWidthInHex = - sizeof(typename fputil::FPBits::UIntType) * 2; - - stream << "0x" - << int_to_hex::UIntType>( - bits.uintval(), bitsWidthInHex) - << ", (S | E | M) = (" << (bits.get_sign() ? '1' : '0') << " | 0x" - << int_to_hex(bits.get_unbiased_exponent(), - exponentWidthInHex) - << " | 0x" - << int_to_hex::UIntType>( - bits.get_mantissa(), mantissaWidthInHex) - << ")"; - } - - stream << '\n'; -} - -template void describeValue(const char *, float, - testutils::StreamWrapper &); -template void describeValue(const char *, double, - testutils::StreamWrapper &); -template void describeValue(const char *, long double, - testutils::StreamWrapper &); - -template void describeValue(const char *, float, std::stringstream &); -template void describeValue(const char *, double, std::stringstream &); -template void describeValue(const char *, long double, - std::stringstream &); - -} // namespace testing -} // namespace fputil -} // namespace __llvm_libc diff --git a/libc/test/UnitTest/LibcTest.h b/libc/test/UnitTest/LibcTest.h --- a/libc/test/UnitTest/LibcTest.h +++ b/libc/test/UnitTest/LibcTest.h @@ -17,8 +17,8 @@ #include "src/__support/CPP/string.h" #include "src/__support/CPP/string_view.h" #include "src/__support/CPP/type_traits.h" +#include "test/UnitTest/TestLogger.h" #include "utils/testutils/ExecuteFunction.h" -#include "utils/testutils/StreamWrapper.h" namespace __llvm_libc { namespace testing { @@ -51,9 +51,7 @@ struct MatcherBase { virtual ~MatcherBase() {} - virtual void explainError(testutils::StreamWrapper &OS) { - OS << "unknown error\n"; - } + virtual void explainError() { tlog << "unknown error\n"; } // Override and return true to skip `explainError` step. virtual bool is_silent() const { return false; } }; diff --git a/libc/test/UnitTest/LibcTest.cpp b/libc/test/UnitTest/LibcTest.cpp --- a/libc/test/UnitTest/LibcTest.cpp +++ b/libc/test/UnitTest/LibcTest.cpp @@ -321,8 +321,7 @@ if (!Matcher.is_silent()) { tlog << File << ":" << Line << ": FAILURE\n" << "Failed to match " << LHSStr << " against " << RHSStr << ".\n"; - testutils::StreamWrapper OutsWrapper = testutils::outs(); - Matcher.explainError(OutsWrapper); + Matcher.explainError(); } return false; } diff --git a/libc/test/UnitTest/MemoryMatcher.h b/libc/test/UnitTest/MemoryMatcher.h --- a/libc/test/UnitTest/MemoryMatcher.h +++ b/libc/test/UnitTest/MemoryMatcher.h @@ -56,7 +56,7 @@ bool match(MemoryView actualValue); - void explainError(testutils::StreamWrapper &stream) override; + void explainError() override; }; } // namespace __llvm_libc::memory::testing diff --git a/libc/test/UnitTest/MemoryMatcher.cpp b/libc/test/UnitTest/MemoryMatcher.cpp --- a/libc/test/UnitTest/MemoryMatcher.cpp +++ b/libc/test/UnitTest/MemoryMatcher.cpp @@ -8,6 +8,10 @@ #include "MemoryMatcher.h" +#include "test/UnitTest/Test.h" + +using __llvm_libc::testing::tlog; + namespace __llvm_libc { namespace memory { namespace testing { @@ -32,42 +36,42 @@ return equals(expected, actual, mismatch_size, mismatch_index); } -void display(testutils::StreamWrapper &Stream, char C) { - const auto print = [&Stream](unsigned char I) { - Stream << static_cast(I < 10 ? '0' + I : 'A' + I - 10); +static void display(char C) { + const auto print = [](unsigned char I) { + tlog << static_cast(I < 10 ? '0' + I : 'A' + I - 10); }; print(static_cast(C) / 16); print(static_cast(C) & 15); } -void display(testutils::StreamWrapper &Stream, MemoryView View) { +static void display(MemoryView View) { for (auto C : View) { - Stream << ' '; - display(Stream, C); + tlog << ' '; + display(C); } } -void MemoryMatcher::explainError(testutils::StreamWrapper &Stream) { +void MemoryMatcher::explainError() { if (mismatch_size) { - Stream << "Size mismatch :"; - Stream << "expected : "; - Stream << expected.size(); - Stream << '\n'; - Stream << "actual : "; - Stream << actual.size(); - Stream << '\n'; + tlog << "Size mismatch :"; + tlog << "expected : "; + tlog << expected.size(); + tlog << '\n'; + tlog << "actual : "; + tlog << actual.size(); + tlog << '\n'; } else { - Stream << "Mismatch at position : "; - Stream << mismatch_index; - Stream << " / "; - Stream << expected.size(); - Stream << "\n"; - Stream << "expected :"; - display(Stream, expected); - Stream << '\n'; - Stream << "actual :"; - display(Stream, actual); - Stream << '\n'; + tlog << "Mismatch at position : "; + tlog << mismatch_index; + tlog << " / "; + tlog << expected.size(); + tlog << "\n"; + tlog << "expected :"; + display(expected); + tlog << '\n'; + tlog << "actual :"; + display(actual); + tlog << '\n'; } } diff --git a/libc/test/UnitTest/PrintfMatcher.h b/libc/test/UnitTest/PrintfMatcher.h --- a/libc/test/UnitTest/PrintfMatcher.h +++ b/libc/test/UnitTest/PrintfMatcher.h @@ -28,7 +28,7 @@ bool match(FormatSection actualValue); - void explainError(testutils::StreamWrapper &stream) override; + void explainError() override; }; } // namespace testing diff --git a/libc/test/UnitTest/PrintfMatcher.cpp b/libc/test/UnitTest/PrintfMatcher.cpp --- a/libc/test/UnitTest/PrintfMatcher.cpp +++ b/libc/test/UnitTest/PrintfMatcher.cpp @@ -12,9 +12,12 @@ #include "src/stdio/printf_core/core_structs.h" #include "test/UnitTest/StringUtils.h" +#include "test/UnitTest/Test.h" #include +using __llvm_libc::testing::tlog; + namespace __llvm_libc { namespace printf_core { namespace testing { @@ -29,30 +32,30 @@ #define IF_FLAG_SHOW_FLAG(flag_name) \ do { \ if ((form.flags & FormatFlags::flag_name) == FormatFlags::flag_name) \ - stream << "\n\t\t" << #flag_name; \ + tlog << "\n\t\t" << #flag_name; \ } while (false) #define CASE_LM(lm) \ case (LengthModifier::lm): \ - stream << #lm; \ + tlog << #lm; \ break -void display(testutils::StreamWrapper &stream, FormatSection form) { - stream << "Raw String (len " << form.raw_string.size() << "): \""; +static void display(FormatSection form) { + tlog << "Raw String (len " << form.raw_string.size() << "): \""; for (size_t i = 0; i < form.raw_string.size(); ++i) { - stream << form.raw_string[i]; + tlog << form.raw_string[i]; } - stream << "\""; + tlog << "\""; if (form.has_conv) { - stream << "\n\tHas Conv\n\tFlags:"; + tlog << "\n\tHas Conv\n\tFlags:"; IF_FLAG_SHOW_FLAG(LEFT_JUSTIFIED); IF_FLAG_SHOW_FLAG(FORCE_SIGN); IF_FLAG_SHOW_FLAG(SPACE_PREFIX); IF_FLAG_SHOW_FLAG(ALTERNATE_FORM); IF_FLAG_SHOW_FLAG(LEADING_ZEROES); - stream << "\n"; - stream << "\tmin width: " << form.min_width << "\n"; - stream << "\tprecision: " << form.precision << "\n"; - stream << "\tlength modifier: "; + tlog << "\n"; + tlog << "\tmin width: " << form.min_width << "\n"; + tlog << "\tprecision: " << form.precision << "\n"; + tlog << "\tlength modifier: "; switch (form.length_modifier) { CASE_LM(none); CASE_LM(l); @@ -64,29 +67,29 @@ CASE_LM(t); CASE_LM(L); } - stream << "\n"; - stream << "\tconversion name: " << form.conv_name << "\n"; + tlog << "\n"; + tlog << "\tconversion name: " << form.conv_name << "\n"; if (form.conv_name == 'p' || form.conv_name == 'n' || form.conv_name == 's') - stream << "\tpointer value: " - << int_to_hex( - reinterpret_cast(form.conv_val_ptr)) - << "\n"; + tlog << "\tpointer value: " + << int_to_hex( + reinterpret_cast(form.conv_val_ptr)) + << "\n"; else if (form.conv_name != '%') - stream << "\tvalue: " - << int_to_hex::UIntType>( - form.conv_val_raw) - << "\n"; + tlog << "\tvalue: " + << int_to_hex::UIntType>( + form.conv_val_raw) + << "\n"; } } } // anonymous namespace -void FormatSectionMatcher::explainError(testutils::StreamWrapper &stream) { - stream << "expected format section: "; - display(stream, expected); - stream << '\n'; - stream << "actual format section : "; - display(stream, actual); - stream << '\n'; +void FormatSectionMatcher::explainError() { + tlog << "expected format section: "; + display(expected); + tlog << '\n'; + tlog << "actual format section : "; + display(actual); + tlog << '\n'; } } // namespace testing diff --git a/libc/test/UnitTest/ScanfMatcher.h b/libc/test/UnitTest/ScanfMatcher.h --- a/libc/test/UnitTest/ScanfMatcher.h +++ b/libc/test/UnitTest/ScanfMatcher.h @@ -28,7 +28,7 @@ bool match(FormatSection actualValue); - void explainError(testutils::StreamWrapper &stream) override; + void explainError() override; }; } // namespace testing diff --git a/libc/test/UnitTest/ScanfMatcher.cpp b/libc/test/UnitTest/ScanfMatcher.cpp --- a/libc/test/UnitTest/ScanfMatcher.cpp +++ b/libc/test/UnitTest/ScanfMatcher.cpp @@ -12,9 +12,12 @@ #include "src/stdio/scanf_core/core_structs.h" #include "test/UnitTest/StringUtils.h" +#include "test/UnitTest/Test.h" #include +using __llvm_libc::testing::tlog; + namespace __llvm_libc { namespace scanf_core { namespace testing { @@ -29,26 +32,26 @@ #define IF_FLAG_SHOW_FLAG(flag_name) \ do { \ if ((form.flags & FormatFlags::flag_name) == FormatFlags::flag_name) \ - stream << "\n\t\t" << #flag_name; \ + tlog << "\n\t\t" << #flag_name; \ } while (false) #define CASE_LM(lm) \ case (LengthModifier::lm): \ - stream << #lm; \ + tlog << #lm; \ break -void display(testutils::StreamWrapper &stream, FormatSection form) { - stream << "Raw String (len " << form.raw_string.size() << "): \""; +void display(FormatSection form) { + tlog << "Raw String (len " << form.raw_string.size() << "): \""; for (size_t i = 0; i < form.raw_string.size(); ++i) { - stream << form.raw_string[i]; + tlog << form.raw_string[i]; } - stream << "\""; + tlog << "\""; if (form.has_conv) { - stream << "\n\tHas Conv\n\tFlags:"; + tlog << "\n\tHas Conv\n\tFlags:"; IF_FLAG_SHOW_FLAG(NO_WRITE); IF_FLAG_SHOW_FLAG(ALLOCATE); - stream << "\n"; - stream << "\tmax width: " << form.max_width << "\n"; - stream << "\tlength modifier: "; + tlog << "\n"; + tlog << "\tmax width: " << form.max_width << "\n"; + tlog << "\tlength modifier: "; switch (form.length_modifier) { CASE_LM(NONE); CASE_LM(l); @@ -60,38 +63,38 @@ CASE_LM(t); CASE_LM(L); } - stream << "\n"; + tlog << "\n"; // If the pointer is used (NO_WRITE is not set and the conversion isn't %). if (((form.flags & FormatFlags::NO_WRITE) == 0) && (form.conv_name != '%')) { - stream << "\tpointer value: " - << int_to_hex( - reinterpret_cast(form.output_ptr)) - << "\n"; + tlog << "\tpointer value: " + << int_to_hex( + reinterpret_cast(form.output_ptr)) + << "\n"; } - stream << "\tconversion name: " << form.conv_name << "\n"; + tlog << "\tconversion name: " << form.conv_name << "\n"; if (form.conv_name == '[') { - stream << "\t\t"; + tlog << "\t\t"; for (size_t i = 0; i < 256 /* char max */; ++i) { if (form.scan_set.test(i)) { - stream << static_cast(i); + tlog << static_cast(i); } } - stream << "\n\t]\n"; + tlog << "\n\t]\n"; } } } } // anonymous namespace -void FormatSectionMatcher::explainError(testutils::StreamWrapper &stream) { - stream << "expected format section: "; - display(stream, expected); - stream << '\n'; - stream << "actual format section : "; - display(stream, actual); - stream << '\n'; +void FormatSectionMatcher::explainError() { + tlog << "expected format section: "; + display(expected); + tlog << '\n'; + tlog << "actual format section : "; + display(actual); + tlog << '\n'; } } // namespace testing diff --git a/libc/test/UnitTest/StringUtils.h b/libc/test/UnitTest/StringUtils.h --- a/libc/test/UnitTest/StringUtils.h +++ b/libc/test/UnitTest/StringUtils.h @@ -9,24 +9,26 @@ #ifndef LLVM_LIBC_UTILS_UNITTEST_SIMPLE_STRING_CONV_H #define LLVM_LIBC_UTILS_UNITTEST_SIMPLE_STRING_CONV_H +#include "src/__support/CPP/string.h" #include "src/__support/CPP/type_traits.h" -#include - namespace __llvm_libc { // Return the first N hex digits of an integer as a string in upper case. template -cpp::enable_if_t, std::string> -int_to_hex(T X, size_t Length = sizeof(T) * 2) { - std::string s(Length, '0'); - - for (auto it = s.rbegin(), end = s.rend(); it != end; ++it, X >>= 4) { - unsigned char Mod = static_cast(X) & 15; - *it = (Mod < 10 ? '0' + Mod : 'a' + Mod - 10); +cpp::enable_if_t, cpp::string> +int_to_hex(T value, size_t length = sizeof(T) * 2) { + cpp::string s(length, '0'); + + constexpr char HEXADECIMALS[16] = {'0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + for (size_t i = 0; i < length; i += 2, value >>= 8) { + unsigned char mod = static_cast(value) & 0xFF; + s[length - i] = HEXADECIMALS[mod & 0x0F]; + s[length - (i + 1)] = HEXADECIMALS[mod & 0x0F]; } - return s; + return "0x" + s; } } // namespace __llvm_libc diff --git a/libc/test/UnitTest/TestLogger.cpp b/libc/test/UnitTest/TestLogger.cpp --- a/libc/test/UnitTest/TestLogger.cpp +++ b/libc/test/UnitTest/TestLogger.cpp @@ -1,7 +1,9 @@ #include "test/UnitTest/TestLogger.h" #include "src/__support/CPP/string.h" #include "src/__support/CPP/string_view.h" -#include "src/__support/OSUtil/io.h" //write_to_stderr +#include "src/__support/OSUtil/io.h" // write_to_stderr + +#include namespace __llvm_libc { namespace testing { @@ -23,11 +25,21 @@ return *this << cpp::string_view(str); } +// char* specialization +template <> TestLogger &TestLogger::operator<< (char *str) { + return *this << cpp::string_view(str); +} + // char specialization template <> TestLogger &TestLogger::operator<<(char ch) { return *this << cpp::string_view(&ch, 1); } +// void * specialization +template <> TestLogger &TestLogger::operator<<(void *addr) { + return *this << "0x" << cpp::to_string(reinterpret_cast(addr)); +} + template TestLogger &TestLogger::operator<<(T t) { return *this << cpp::to_string(t); } diff --git a/libc/test/src/math/log10_test.cpp b/libc/test/src/math/log10_test.cpp --- a/libc/test/src/math/log10_test.cpp +++ b/libc/test/src/math/log10_test.cpp @@ -12,14 +12,12 @@ #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include "utils/testutils/StreamWrapper.h" #include #include #include namespace mpfr = __llvm_libc::testing::mpfr; -auto outs = __llvm_libc::testutils::outs(); DECLARE_SPECIAL_CONSTANTS(double) @@ -104,23 +102,16 @@ } } } - outs << " Log10 failed: " << fails << "/" << count << "/" << cc - << " tests.\n"; - outs << " Max ULPs is at most: " << tol << ".\n"; if (fails) { EXPECT_MPFR_MATCH(mpfr::Operation::Log10, mx, mr, 0.5, rounding_mode); } }; - outs << " Test Rounding To Nearest...\n"; test(mpfr::RoundingMode::Nearest); - outs << " Test Rounding Downward...\n"; test(mpfr::RoundingMode::Downward); - outs << " Test Rounding Upward...\n"; test(mpfr::RoundingMode::Upward); - outs << " Test Rounding Toward Zero...\n"; test(mpfr::RoundingMode::TowardZero); } diff --git a/libc/test/src/time/TmMatcher.h b/libc/test/src/time/TmMatcher.h --- a/libc/test/src/time/TmMatcher.h +++ b/libc/test/src/time/TmMatcher.h @@ -37,24 +37,23 @@ actual.tm_isdst == expected.tm_isdst); } - void describeValue(const char *label, ::tm value, - __llvm_libc::testutils::StreamWrapper &stream) { - stream << label; - stream << " sec: " << value.tm_sec; - stream << " min: " << value.tm_min; - stream << " hour: " << value.tm_hour; - stream << " mday: " << value.tm_mday; - stream << " mon: " << value.tm_mon; - stream << " year: " << value.tm_year; - stream << " wday: " << value.tm_wday; - stream << " yday: " << value.tm_yday; - stream << " isdst: " << value.tm_isdst; - stream << '\n'; + void describeValue(const char *label, ::tm value) { + __llvm_libc::testing::tlog << label; + __llvm_libc::testing::tlog << " sec: " << value.tm_sec; + __llvm_libc::testing::tlog << " min: " << value.tm_min; + __llvm_libc::testing::tlog << " hour: " << value.tm_hour; + __llvm_libc::testing::tlog << " mday: " << value.tm_mday; + __llvm_libc::testing::tlog << " mon: " << value.tm_mon; + __llvm_libc::testing::tlog << " year: " << value.tm_year; + __llvm_libc::testing::tlog << " wday: " << value.tm_wday; + __llvm_libc::testing::tlog << " yday: " << value.tm_yday; + __llvm_libc::testing::tlog << " isdst: " << value.tm_isdst; + __llvm_libc::testing::tlog << '\n'; } - void explainError(__llvm_libc::testutils::StreamWrapper &stream) override { - describeValue("Expected tm_struct value: ", expected, stream); - describeValue(" Actual tm_struct value: ", actual, stream); + void explainError() override { + describeValue("Expected tm_struct value: ", expected); + describeValue(" Actual tm_struct value: ", actual); } }; diff --git a/libc/utils/MPFRWrapper/MPFRUtils.h b/libc/utils/MPFRWrapper/MPFRUtils.h --- a/libc/utils/MPFRWrapper/MPFRUtils.h +++ b/libc/utils/MPFRWrapper/MPFRUtils.h @@ -156,27 +156,30 @@ void explain_unary_operation_single_output_error(Operation op, T input, T match_value, double ulp_tolerance, - RoundingMode rounding, - testutils::StreamWrapper &OS); + RoundingMode rounding); template void explain_unary_operation_two_outputs_error( Operation op, T input, const BinaryOutput &match_value, - double ulp_tolerance, RoundingMode rounding, testutils::StreamWrapper &OS); + double ulp_tolerance, RoundingMode rounding); template void explain_binary_operation_two_outputs_error( Operation op, const BinaryInput &input, const BinaryOutput &match_value, double ulp_tolerance, - RoundingMode rounding, testutils::StreamWrapper &OS); + RoundingMode rounding); template -void explain_binary_operation_one_output_error( - Operation op, const BinaryInput &input, T match_value, - double ulp_tolerance, RoundingMode rounding, testutils::StreamWrapper &OS); +void explain_binary_operation_one_output_error(Operation op, + const BinaryInput &input, + T match_value, + double ulp_tolerance, + RoundingMode rounding); template -void explain_ternary_operation_one_output_error( - Operation op, const TernaryInput &input, T match_value, - double ulp_tolerance, RoundingMode rounding, testutils::StreamWrapper &OS); +void explain_ternary_operation_one_output_error(Operation op, + const TernaryInput &input, + T match_value, + double ulp_tolerance, + RoundingMode rounding); template class MPFRMatcher : public testing::Matcher { @@ -196,8 +199,8 @@ // This method is marked with NOLINT because it the name `explainError` // does not confirm to the coding style. - void explainError(testutils::StreamWrapper &OS) override { // NOLINT - explain_error(input, match_value, OS); + void explainError() override { // NOLINT + explain_error(input, match_value); } // Whether the `explainError` step is skipped or not. @@ -230,38 +233,30 @@ rounding); } - template - void explain_error(T in, T out, testutils::StreamWrapper &OS) { + template void explain_error(T in, T out) { explain_unary_operation_single_output_error(op, in, out, ulp_tolerance, - rounding, OS); + rounding); } - template - void explain_error(T in, const BinaryOutput &out, - testutils::StreamWrapper &OS) { + template void explain_error(T in, const BinaryOutput &out) { explain_unary_operation_two_outputs_error(op, in, out, ulp_tolerance, - rounding, OS); + rounding); } template - void explain_error(const BinaryInput &in, const BinaryOutput &out, - testutils::StreamWrapper &OS) { + void explain_error(const BinaryInput &in, const BinaryOutput &out) { explain_binary_operation_two_outputs_error(op, in, out, ulp_tolerance, - rounding, OS); + rounding); } - template - void explain_error(const BinaryInput &in, T out, - testutils::StreamWrapper &OS) { + template void explain_error(const BinaryInput &in, T out) { explain_binary_operation_one_output_error(op, in, out, ulp_tolerance, - rounding, OS); + rounding); } - template - void explain_error(const TernaryInput &in, T out, - testutils::StreamWrapper &OS) { + template void explain_error(const TernaryInput &in, T out) { explain_ternary_operation_one_output_error(op, in, out, ulp_tolerance, - rounding, OS); + rounding); } }; diff --git a/libc/utils/MPFRWrapper/MPFRUtils.cpp b/libc/utils/MPFRWrapper/MPFRUtils.cpp --- a/libc/utils/MPFRWrapper/MPFRUtils.cpp +++ b/libc/utils/MPFRWrapper/MPFRUtils.cpp @@ -8,6 +8,7 @@ #include "MPFRUtils.h" +#include "src/__support/CPP/string.h" #include "src/__support/CPP/string_view.h" #include "src/__support/FPUtil/FPBits.h" #include "src/__support/FPUtil/PlatformDefs.h" @@ -16,9 +17,7 @@ #include #include #include -#include #include -#include #ifdef CUSTOM_MPFR_INCLUDER // Some downstream repos are monoliths carrying MPFR sources in their third @@ -417,7 +416,7 @@ return result; } - std::string str() const { + cpp::string str() const { // 200 bytes should be more than sufficient to hold a 100-digit number // plus additional bytes for the decimal point, '-' sign etc. constexpr size_t printBufSize = 200; @@ -430,7 +429,7 @@ view.remove_prefix(1); while (!view.empty() && view.back() == whitespace) view.remove_suffix(1); - return std::string(view.data()); + return cpp::string(view.data()); } // These functions are useful for debugging. @@ -463,15 +462,16 @@ // of N between this number and [input]. // 4. A values of +0.0 and -0.0 are treated as equal. template - cpp::enable_if_t, double> ulp(T input) { + cpp::enable_if_t, MPFRNumber> + ulp_as_mpfr_number(T input) { T thisAsT = as(); if (thisAsT == input) - return T(0.0); + return MPFRNumber(0.0); if (is_nan()) { if (fputil::FPBits(input).is_nan()) - return T(0.0); - return T(fputil::FPBits::inf()); + return MPFRNumber(0.0); + return MPFRNumber(static_cast(fputil::FPBits::inf())); } int thisExponent = fputil::FPBits(thisAsT).get_exponent(); @@ -489,7 +489,7 @@ mpfr_mul_2si(inputMPFR.value, inputMPFR.value, -thisExponent + int(fputil::MantissaWidth::VALUE), MPFR_RNDN); - return inputMPFR.as(); + return inputMPFR; } // If the control reaches here, it means that this number and input are @@ -524,7 +524,20 @@ MPFR_RNDN); mpfr_add(minMPFR.value, minMPFR.value, maxMPFR.value, MPFR_RNDN); - return minMPFR.as(); + return minMPFR; + } + + template + cpp::enable_if_t, cpp::string> + ulp_as_string(T input) { + MPFRNumber num = ulp_as_mpfr_number(input); + return num.str(); + } + + template + cpp::enable_if_t, double> ulp(T input) { + MPFRNumber num = ulp_as_mpfr_number(input); + return num.as(); } }; @@ -682,93 +695,84 @@ void explain_unary_operation_single_output_error(Operation op, T input, T matchValue, double ulp_tolerance, - RoundingMode rounding, - testutils::StreamWrapper &OS) { + RoundingMode rounding) { unsigned int precision = get_precision(ulp_tolerance); MPFRNumber mpfrInput(input, precision); MPFRNumber mpfr_result; mpfr_result = unary_operation(op, input, precision, rounding); MPFRNumber mpfrMatchValue(matchValue); - std::stringstream ss; - ss << "Match value not within tolerance value of MPFR result:\n" - << " Input decimal: " << mpfrInput.str() << '\n'; - __llvm_libc::fputil::testing::describeValue(" Input bits: ", input, ss); - ss << '\n' << " Match decimal: " << mpfrMatchValue.str() << '\n'; - __llvm_libc::fputil::testing::describeValue(" Match bits: ", matchValue, - ss); - ss << '\n' << " MPFR result: " << mpfr_result.str() << '\n'; - __llvm_libc::fputil::testing::describeValue( - " MPFR rounded: ", mpfr_result.as(), ss); - ss << '\n'; - ss << " ULP error: " << std::to_string(mpfr_result.ulp(matchValue)) - << '\n'; - OS << ss.str(); + tlog << "Match value not within tolerance value of MPFR result:\n" + << " Input decimal: " << mpfrInput.str() << '\n'; + __llvm_libc::fputil::testing::describeValue(" Input bits: ", input); + tlog << '\n' << " Match decimal: " << mpfrMatchValue.str() << '\n'; + __llvm_libc::fputil::testing::describeValue(" Match bits: ", matchValue); + tlog << '\n' << " MPFR result: " << mpfr_result.str() << '\n'; + __llvm_libc::fputil::testing::describeValue(" MPFR rounded: ", + mpfr_result.as()); + tlog << '\n'; + tlog << " ULP error: " + << mpfr_result.ulp_as_mpfr_number(matchValue).str() << '\n'; } -template void -explain_unary_operation_single_output_error(Operation op, float, float, - double, RoundingMode, - testutils::StreamWrapper &); +template void explain_unary_operation_single_output_error(Operation op, + float, float, + double, + RoundingMode); template void explain_unary_operation_single_output_error( - Operation op, double, double, double, RoundingMode, - testutils::StreamWrapper &); + Operation op, double, double, double, RoundingMode); template void explain_unary_operation_single_output_error( - Operation op, long double, long double, double, RoundingMode, - testutils::StreamWrapper &); + Operation op, long double, long double, double, RoundingMode); template void explain_unary_operation_two_outputs_error( Operation op, T input, const BinaryOutput &libc_result, - double ulp_tolerance, RoundingMode rounding, testutils::StreamWrapper &OS) { + double ulp_tolerance, RoundingMode rounding) { unsigned int precision = get_precision(ulp_tolerance); MPFRNumber mpfrInput(input, precision); int mpfrIntResult; MPFRNumber mpfr_result = unary_operation_two_outputs(op, input, mpfrIntResult, precision, rounding); - std::stringstream ss; if (mpfrIntResult != libc_result.i) { - ss << "MPFR integral result: " << mpfrIntResult << '\n' - << "Libc integral result: " << libc_result.i << '\n'; + tlog << "MPFR integral result: " << mpfrIntResult << '\n' + << "Libc integral result: " << libc_result.i << '\n'; } else { - ss << "Integral result from libc matches integral result from MPFR.\n"; + tlog << "Integral result from libc matches integral result from MPFR.\n"; } MPFRNumber mpfrMatchValue(libc_result.f); - ss << "Libc floating point result is not within tolerance value of the MPFR " - << "result.\n\n"; - - ss << " Input decimal: " << mpfrInput.str() << "\n\n"; - - ss << "Libc floating point value: " << mpfrMatchValue.str() << '\n'; - __llvm_libc::fputil::testing::describeValue( - " Libc floating point bits: ", libc_result.f, ss); - ss << "\n\n"; - - ss << " MPFR result: " << mpfr_result.str() << '\n'; - __llvm_libc::fputil::testing::describeValue( - " MPFR rounded: ", mpfr_result.as(), ss); - ss << '\n' - << " ULP error: " - << std::to_string(mpfr_result.ulp(libc_result.f)) << '\n'; - OS << ss.str(); + tlog + << "Libc floating point result is not within tolerance value of the MPFR " + << "result.\n\n"; + + tlog << " Input decimal: " << mpfrInput.str() << "\n\n"; + + tlog << "Libc floating point value: " << mpfrMatchValue.str() << '\n'; + __llvm_libc::fputil::testing::describeValue(" Libc floating point bits: ", + libc_result.f); + tlog << "\n\n"; + + tlog << " MPFR result: " << mpfr_result.str() << '\n'; + __llvm_libc::fputil::testing::describeValue(" MPFR rounded: ", + mpfr_result.as()); + tlog << '\n' + << " ULP error: " + << mpfr_result.ulp_as_mpfr_number(libc_result.f).str() << '\n'; } template void explain_unary_operation_two_outputs_error( - Operation, float, const BinaryOutput &, double, RoundingMode, - testutils::StreamWrapper &); + Operation, float, const BinaryOutput &, double, RoundingMode); template void explain_unary_operation_two_outputs_error( - Operation, double, const BinaryOutput &, double, RoundingMode, - testutils::StreamWrapper &); + Operation, double, const BinaryOutput &, double, RoundingMode); template void explain_unary_operation_two_outputs_error( Operation, long double, const BinaryOutput &, double, - RoundingMode, testutils::StreamWrapper &); + RoundingMode); template void explain_binary_operation_two_outputs_error( Operation op, const BinaryInput &input, const BinaryOutput &libc_result, double ulp_tolerance, - RoundingMode rounding, testutils::StreamWrapper &OS) { + RoundingMode rounding) { unsigned int precision = get_precision(ulp_tolerance); MPFRNumber mpfrX(input.x, precision); MPFRNumber mpfrY(input.y, precision); @@ -776,36 +780,36 @@ MPFRNumber mpfr_result = binary_operation_two_outputs( op, input.x, input.y, mpfrIntResult, precision, rounding); MPFRNumber mpfrMatchValue(libc_result.f); - std::stringstream ss; - ss << "Input decimal: x: " << mpfrX.str() << " y: " << mpfrY.str() << '\n' - << "MPFR integral result: " << mpfrIntResult << '\n' - << "Libc integral result: " << libc_result.i << '\n' - << "Libc floating point result: " << mpfrMatchValue.str() << '\n' - << " MPFR result: " << mpfr_result.str() << '\n'; + tlog << "Input decimal: x: " << mpfrX.str() << " y: " << mpfrY.str() << '\n' + << "MPFR integral result: " << mpfrIntResult << '\n' + << "Libc integral result: " << libc_result.i << '\n' + << "Libc floating point result: " << mpfrMatchValue.str() << '\n' + << " MPFR result: " << mpfr_result.str() << '\n'; __llvm_libc::fputil::testing::describeValue( - "Libc floating point result bits: ", libc_result.f, ss); + "Libc floating point result bits: ", libc_result.f); __llvm_libc::fputil::testing::describeValue( - " MPFR rounded bits: ", mpfr_result.as(), ss); - ss << "ULP error: " << std::to_string(mpfr_result.ulp(libc_result.f)) << '\n'; - OS << ss.str(); + " MPFR rounded bits: ", mpfr_result.as()); + tlog << "ULP error: " << mpfr_result.ulp_as_mpfr_number(libc_result.f).str() + << '\n'; } template void explain_binary_operation_two_outputs_error( Operation, const BinaryInput &, const BinaryOutput &, double, - RoundingMode, testutils::StreamWrapper &); + RoundingMode); template void explain_binary_operation_two_outputs_error( Operation, const BinaryInput &, const BinaryOutput &, - double, RoundingMode, testutils::StreamWrapper &); + double, RoundingMode); template void explain_binary_operation_two_outputs_error( Operation, const BinaryInput &, - const BinaryOutput &, double, RoundingMode, - testutils::StreamWrapper &); + const BinaryOutput &, double, RoundingMode); template -void explain_binary_operation_one_output_error( - Operation op, const BinaryInput &input, T libc_result, - double ulp_tolerance, RoundingMode rounding, testutils::StreamWrapper &OS) { +void explain_binary_operation_one_output_error(Operation op, + const BinaryInput &input, + T libc_result, + double ulp_tolerance, + RoundingMode rounding) { unsigned int precision = get_precision(ulp_tolerance); MPFRNumber mpfrX(input.x, precision); MPFRNumber mpfrY(input.y, precision); @@ -814,38 +818,35 @@ MPFRNumber mpfr_result = binary_operation_one_output(op, input.x, input.y, precision, rounding); MPFRNumber mpfrMatchValue(libc_result); - std::stringstream ss; - ss << "Input decimal: x: " << mpfrX.str() << " y: " << mpfrY.str() << '\n'; - __llvm_libc::fputil::testing::describeValue("First input bits: ", input.x, - ss); - __llvm_libc::fputil::testing::describeValue("Second input bits: ", input.y, - ss); + tlog << "Input decimal: x: " << mpfrX.str() << " y: " << mpfrY.str() << '\n'; + __llvm_libc::fputil::testing::describeValue("First input bits: ", input.x); + __llvm_libc::fputil::testing::describeValue("Second input bits: ", input.y); - ss << "Libc result: " << mpfrMatchValue.str() << '\n' - << "MPFR result: " << mpfr_result.str() << '\n'; + tlog << "Libc result: " << mpfrMatchValue.str() << '\n' + << "MPFR result: " << mpfr_result.str() << '\n'; __llvm_libc::fputil::testing::describeValue( - "Libc floating point result bits: ", libc_result, ss); + "Libc floating point result bits: ", libc_result); __llvm_libc::fputil::testing::describeValue( - " MPFR rounded bits: ", mpfr_result.as(), ss); - ss << "ULP error: " << std::to_string(mpfr_result.ulp(libc_result)) << '\n'; - OS << ss.str(); + " MPFR rounded bits: ", mpfr_result.as()); + tlog << "ULP error: " << mpfr_result.ulp_as_mpfr_number(libc_result).str() + << '\n'; } template void explain_binary_operation_one_output_error( - Operation, const BinaryInput &, float, double, RoundingMode, - testutils::StreamWrapper &); + Operation, const BinaryInput &, float, double, RoundingMode); template void explain_binary_operation_one_output_error( - Operation, const BinaryInput &, double, double, RoundingMode, - testutils::StreamWrapper &); + Operation, const BinaryInput &, double, double, RoundingMode); template void explain_binary_operation_one_output_error( Operation, const BinaryInput &, long double, double, - RoundingMode, testutils::StreamWrapper &); + RoundingMode); template -void explain_ternary_operation_one_output_error( - Operation op, const TernaryInput &input, T libc_result, - double ulp_tolerance, RoundingMode rounding, testutils::StreamWrapper &OS) { +void explain_ternary_operation_one_output_error(Operation op, + const TernaryInput &input, + T libc_result, + double ulp_tolerance, + RoundingMode rounding) { unsigned int precision = get_precision(ulp_tolerance); MPFRNumber mpfrX(input.x, precision); MPFRNumber mpfrY(input.y, precision); @@ -856,36 +857,30 @@ MPFRNumber mpfr_result = ternary_operation_one_output( op, input.x, input.y, input.z, precision, rounding); MPFRNumber mpfrMatchValue(libc_result); - std::stringstream ss; - - ss << "Input decimal: x: " << mpfrX.str() << " y: " << mpfrY.str() - << " z: " << mpfrZ.str() << '\n'; - __llvm_libc::fputil::testing::describeValue("First input bits: ", input.x, - ss); - __llvm_libc::fputil::testing::describeValue("Second input bits: ", input.y, - ss); - __llvm_libc::fputil::testing::describeValue("Third input bits: ", input.z, - ss); - - ss << "Libc result: " << mpfrMatchValue.str() << '\n' - << "MPFR result: " << mpfr_result.str() << '\n'; + + tlog << "Input decimal: x: " << mpfrX.str() << " y: " << mpfrY.str() + << " z: " << mpfrZ.str() << '\n'; + __llvm_libc::fputil::testing::describeValue("First input bits: ", input.x); + __llvm_libc::fputil::testing::describeValue("Second input bits: ", input.y); + __llvm_libc::fputil::testing::describeValue("Third input bits: ", input.z); + + tlog << "Libc result: " << mpfrMatchValue.str() << '\n' + << "MPFR result: " << mpfr_result.str() << '\n'; __llvm_libc::fputil::testing::describeValue( - "Libc floating point result bits: ", libc_result, ss); + "Libc floating point result bits: ", libc_result); __llvm_libc::fputil::testing::describeValue( - " MPFR rounded bits: ", mpfr_result.as(), ss); - ss << "ULP error: " << std::to_string(mpfr_result.ulp(libc_result)) << '\n'; - OS << ss.str(); + " MPFR rounded bits: ", mpfr_result.as()); + tlog << "ULP error: " << mpfr_result.ulp_as_mpfr_number(libc_result).str() + << '\n'; } template void explain_ternary_operation_one_output_error( - Operation, const TernaryInput &, float, double, RoundingMode, - testutils::StreamWrapper &); + Operation, const TernaryInput &, float, double, RoundingMode); template void explain_ternary_operation_one_output_error( - Operation, const TernaryInput &, double, double, RoundingMode, - testutils::StreamWrapper &); + Operation, const TernaryInput &, double, double, RoundingMode); template void explain_ternary_operation_one_output_error( Operation, const TernaryInput &, long double, double, - RoundingMode, testutils::StreamWrapper &); + RoundingMode); template bool compare_unary_operation_single_output(Operation op, T input, T libc_result, diff --git a/libc/utils/testutils/CMakeLists.txt b/libc/utils/testutils/CMakeLists.txt --- a/libc/utils/testutils/CMakeLists.txt +++ b/libc/utils/testutils/CMakeLists.txt @@ -7,8 +7,6 @@ libc_test_utils RandUtils.cpp RandUtils.h - StreamWrapper.cpp - StreamWrapper.h ${EFFile} ExecuteFunction.h ${FDReaderFile} diff --git a/libc/utils/testutils/StreamWrapper.h b/libc/utils/testutils/StreamWrapper.h deleted file mode 100644 --- a/libc/utils/testutils/StreamWrapper.h +++ /dev/null @@ -1,39 +0,0 @@ -//===-- StreamWrapper.h -----------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIBC_UTILS_TESTUTILS_STREAMWRAPPER_H -#define LLVM_LIBC_UTILS_TESTUTILS_STREAMWRAPPER_H - -namespace __llvm_libc { -namespace testutils { - -// StreamWrapper is necessary because llvm/Support/raw_ostream.h includes -// standard headers so we must provide streams through indirection to not -// expose the system libc headers. -class StreamWrapper { -protected: - void *os; - -public: - StreamWrapper(void *OS) : os(OS) {} - - template StreamWrapper &operator<<(T t); -}; - -StreamWrapper outs(); - -class OutputFileStream : public StreamWrapper { -public: - explicit OutputFileStream(const char *FN); - ~OutputFileStream(); -}; - -} // namespace testutils -} // namespace __llvm_libc - -#endif // LLVM_LIBC_UTILS_TESTUTILS_STREAMWRAPPER_H diff --git a/libc/utils/testutils/StreamWrapper.cpp b/libc/utils/testutils/StreamWrapper.cpp deleted file mode 100644 --- a/libc/utils/testutils/StreamWrapper.cpp +++ /dev/null @@ -1,59 +0,0 @@ -//===-- StreamWrapper.cpp -------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "StreamWrapper.h" -#include -#include -#include -#include -#include - -namespace __llvm_libc { -namespace testutils { - -StreamWrapper outs() { return {std::addressof(std::cout)}; } - -template StreamWrapper &StreamWrapper::operator<<(T t) { - assert(os); - std::ostream &Stream = *reinterpret_cast(os); - Stream << t; - Stream.flush(); - return *this; -} - -template StreamWrapper &StreamWrapper::operator<<(void *t); -template StreamWrapper &StreamWrapper::operator<<(const char *t); -template StreamWrapper &StreamWrapper::operator<<(char *t); -template StreamWrapper &StreamWrapper::operator<<(char t); -template StreamWrapper &StreamWrapper::operator<<(short t); -template StreamWrapper &StreamWrapper::operator<<(int t); -template StreamWrapper &StreamWrapper::operator<<(long t); -template StreamWrapper &StreamWrapper::operator<<(long long t); -template StreamWrapper & - StreamWrapper::operator<<(unsigned char t); -template StreamWrapper & - StreamWrapper::operator<<(unsigned short t); -template StreamWrapper &StreamWrapper::operator<<(unsigned int t); -template StreamWrapper & - StreamWrapper::operator<<(unsigned long t); -template StreamWrapper & - StreamWrapper::operator<<(unsigned long long t); -template StreamWrapper &StreamWrapper::operator<<(bool t); -template StreamWrapper &StreamWrapper::operator<<(std::string t); -template StreamWrapper &StreamWrapper::operator<<(float t); -template StreamWrapper &StreamWrapper::operator<<(double t); - -OutputFileStream::OutputFileStream(const char *FN) - : StreamWrapper(new std::ofstream(FN)) {} - -OutputFileStream::~OutputFileStream() { - delete reinterpret_cast(os); -} - -} // namespace testutils -} // namespace __llvm_libc