diff --git a/.gitignore b/.gitignore index 88882270..c76d9961 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ CTestTestfile.cmake CMakeCache.txt CMakeFiles Makefile +/run-msbuild.bat diff --git a/CMakeLists.txt b/CMakeLists.txt index f9d40a29..198440aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,6 +25,12 @@ include(CheckCXXCompilerFlag) check_cxx_compiler_flag(-std=c++11 HAVE_STD_CPP11_FLAG) if (HAVE_STD_CPP11_FLAG) set(CPP11_FLAG -std=c++11) + # Use libc++. + # We may link with libc++abi as well, leave it for now + if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + message(STATUS "${CMAKE_CXX_COMPILER_ID} detected! Use libc++ as its standard library.") + set(CPP11_FLAG "-std=c++11 -stdlib=libc++ -lc++") + endif () else () check_cxx_compiler_flag(-std=c++0x HAVE_STD_CPP0X_FLAG) if (HAVE_STD_CPP0X_FLAG) @@ -74,12 +80,15 @@ if (BIICODE) endif () add_library(format ${FMT_SOURCES}) -if (CMAKE_COMPILER_IS_GNUCXX) +if (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") set_target_properties(format PROPERTIES COMPILE_FLAGS "-Wall -Wextra -Wshadow -pedantic") + if (CPP11_FLAG) + set_target_properties(format PROPERTIES COMPILE_FLAGS + "-Wall -Wextra -Wshadow -pedantic ${CPP11_FLAG}") + endif () endif () if (CPP11_FLAG AND FMT_EXTRA_TESTS) - set_target_properties(format PROPERTIES COMPILE_FLAGS ${CPP11_FLAG}) # Test compilation with default flags. file(GLOB src RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} test/*.cc test/*.h) add_library(testformat STATIC ${FMT_SOURCE_FILES} ${src}) @@ -108,6 +117,41 @@ if (NOT FMT_VARIADIC_TEMPLATES) add_definitions(-DGTEST_LANG_CXX11=0) endif () +check_cxx_source_compiles(" + struct C{ + C()=delete; + C(const C&)=delete; + C& operator=(const C&)=delete; + }; + int main(){}" FMT_DELETED_FUNCTIONS) +if (FMT_DELETED_FUNCTIONS) +# add_definitions(-DFMT_USE_DELETED_FUNCTIONS=1) +endif () + +check_cxx_source_compiles(" + void f() noexcept {} + int main(){ f(); }" FMT_BASIC_NOEXCEPT_SUPPORT) +if (FMT_BASIC_NOEXCEPT_SUPPORT) +# add_definitions(-DFMT_USE_NOEXCEPT=1) +endif () + +check_cxx_source_compiles(" + #include + struct MoveOnly { + MoveOnly() {} + MoveOnly(MoveOnly&&) {} + private: + MoveOnly(const MoveOnly&); + }; + int main() { + MoveOnly a; + MoveOnly b(std::move(a)); + MoveOnly c(MoveOnly()); + }" FMT_RVALUE_REFERENCES) +if (FMT_RVALUE_REFERENCES) +# add_definitions(-DFMT_USE_RVALUE_REFERENCES=1) +endif () + # GTest doesn't detect with clang. if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") target_compile_definitions(gmock PUBLIC GTEST_USE_OWN_TR1_TUPLE=1) diff --git a/format.cc b/format.cc index 9005302c..636e4144 100644 --- a/format.cc +++ b/format.cc @@ -146,7 +146,7 @@ typedef void (*FormatFunc)(fmt::Writer &, int, fmt::StringRef); // other - failure // Buffer should be at least of size 1. int safe_strerror( - int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT(true) { + int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT { assert(buffer != 0 && buffer_size != 0); int result = 0; #if ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE) || __ANDROID__ @@ -180,7 +180,7 @@ int safe_strerror( } void format_error_code(fmt::Writer &out, int error_code, - fmt::StringRef message) FMT_NOEXCEPT(true) { + fmt::StringRef message) FMT_NOEXCEPT { // Report error code making sure that the output fits into // INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential // bad_alloc. @@ -198,7 +198,7 @@ void format_error_code(fmt::Writer &out, int error_code, } void report_error(FormatFunc func, - int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) { + int error_code, fmt::StringRef message) FMT_NOEXCEPT { fmt::MemoryWriter full_message; func(full_message, error_code, message); // Use Writer::data instead of Writer::c_str to avoid potential memory @@ -500,7 +500,7 @@ FMT_FUNC void fmt::WindowsError::init( FMT_FUNC void fmt::internal::format_system_error( fmt::Writer &out, int error_code, - fmt::StringRef message) FMT_NOEXCEPT(true) { + fmt::StringRef message) FMT_NOEXCEPT { FMT_TRY { MemoryBuffer buffer; buffer.resize(INLINE_BUFFER_SIZE); @@ -522,7 +522,7 @@ FMT_FUNC void fmt::internal::format_system_error( #ifdef _WIN32 FMT_FUNC void fmt::internal::format_windows_error( fmt::Writer &out, int error_code, - fmt::StringRef message) FMT_NOEXCEPT(true) { + fmt::StringRef message) FMT_NOEXCEPT { class String { private: LPWSTR str_; @@ -1083,13 +1083,13 @@ void fmt::BasicFormatter::format( } FMT_FUNC void fmt::report_system_error( - int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) { + int error_code, fmt::StringRef message) FMT_NOEXCEPT { report_error(internal::format_system_error, error_code, message); } #ifdef _WIN32 FMT_FUNC void fmt::report_windows_error( - int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) { + int error_code, fmt::StringRef message) FMT_NOEXCEPT { report_error(internal::format_windows_error, error_code, message); } #endif @@ -1119,7 +1119,7 @@ FMT_FUNC void fmt::print_colored(Color c, StringRef format, ArgList args) { if (!GetConsoleScreenBufferInfo(handle, &info_con)) FMT_THROW(WindowsError(GetLastError(), "cannot get console information")); WORD reset_color = info_con.wAttributes; - WORD color = static_cast(c) >= ARRAYSIZE(WIN32_COLORS) ? reset_color : WIN32_COLORS[c]; + WORD color = static_cast(c) >= ARRAYSIZE(WIN32_COLORS) ? reset_color : WIN32_COLORS[c]; if (!SetConsoleTextAttribute(handle, color)) FMT_THROW(WindowsError(GetLastError(), "cannot set console color")); print(format, args); diff --git a/format.h b/format.h index 6d2ab9a1..014abe00 100644 --- a/format.h +++ b/format.h @@ -92,7 +92,7 @@ // since version 2013. # define FMT_USE_VARIADIC_TEMPLATES \ (FMT_HAS_FEATURE(cxx_variadic_templates) || \ - (FMT_GCC_VERSION >= 404 && __cplusplus >= 201103) || _MSC_VER >= 1800) + (FMT_GCC_VERSION >= 404 && __cplusplus >= 201103L) || _MSC_VER >= 1800) #endif #ifndef FMT_USE_RVALUE_REFERENCES @@ -103,7 +103,7 @@ # else # define FMT_USE_RVALUE_REFERENCES \ (FMT_HAS_FEATURE(cxx_rvalue_references) || \ - (FMT_GCC_VERSION >= 403 && __cplusplus >= 201103) || _MSC_VER >= 1600) + (FMT_GCC_VERSION >= 403 && __cplusplus >= 201103L) || _MSC_VER >= 1600) # endif #endif @@ -113,17 +113,25 @@ // Define FMT_USE_NOEXCEPT to make C++ Format use noexcept (C++11 feature). #if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \ - (FMT_GCC_VERSION >= 408 && __cplusplus >= 201103) -# define FMT_NOEXCEPT(expr) noexcept(expr) + (FMT_GCC_VERSION >= 408 && __cplusplus >= 201103L) +# define FMT_NOEXCEPT noexcept #else -# define FMT_NOEXCEPT(expr) +# define FMT_NOEXCEPT throw() #endif // A macro to disallow the copy constructor and operator= functions // This should be used in the private: declarations for a class +#if FMT_USE_DELETED_FUNCTIONS || FMT_HAS_FEATURE(cxx_deleted_functions)\ + || (FMT_GCC_VERSION >= 404 && __cplusplus >= 201103L)\ + || (_MSC_VER >= 1800) +#define FMT_DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName&) = delete; \ + TypeName& operator=(const TypeName&) = delete +#else #define FMT_DISALLOW_COPY_AND_ASSIGN(TypeName) \ TypeName(const TypeName&); \ - void operator=(const TypeName&) + TypeName& operator=(const TypeName&) +#endif namespace fmt { @@ -290,7 +298,7 @@ class Buffer { grow(capacity); } - void clear() FMT_NOEXCEPT(true) { size_ = 0; } + void clear() FMT_NOEXCEPT { size_ = 0; } void push_back(const T &value) { if (size_ == capacity_) @@ -623,11 +631,11 @@ class UTF16ToUTF8 { #endif void format_system_error(fmt::Writer &out, int error_code, - fmt::StringRef message) FMT_NOEXCEPT(true); + fmt::StringRef message) FMT_NOEXCEPT; #ifdef _WIN32 void format_windows_error(fmt::Writer &out, int error_code, - fmt::StringRef message) FMT_NOEXCEPT(true); + fmt::StringRef message) FMT_NOEXCEPT; #endif // Computes max(Arg, 1) at compile time. It is used to avoid errors about @@ -1561,7 +1569,7 @@ class BasicWriter { Returns a pointer to the output buffer content. No terminating null character is appended. */ - const Char *data() const FMT_NOEXCEPT(true) { return &buffer_[0]; } + const Char *data() const FMT_NOEXCEPT { return &buffer_[0]; } /** Returns a pointer to the output buffer content with terminating null @@ -1685,7 +1693,7 @@ class BasicWriter { return *this; } - void clear() FMT_NOEXCEPT(true) { buffer_.clear(); } + void clear() FMT_NOEXCEPT { buffer_.clear(); } }; template @@ -2102,7 +2110,7 @@ void format(BasicFormatter &f, const Char *&format_str, const T &value) { // Reports a system error without throwing an exception. // Can be used to report errors from destructors. -void report_system_error(int error_code, StringRef message) FMT_NOEXCEPT(true); +void report_system_error(int error_code, StringRef message) FMT_NOEXCEPT; #ifdef _WIN32 @@ -2146,7 +2154,7 @@ class WindowsError : public SystemError { // Reports a Windows error without throwing an exception. // Can be used to report errors from destructors. -void report_windows_error(int error_code, StringRef message) FMT_NOEXCEPT(true); +void report_windows_error(int error_code, StringRef message) FMT_NOEXCEPT; #endif @@ -2489,6 +2497,8 @@ FMT_VARIADIC(int, fprintf, std::FILE *, StringRef) #ifdef FMT_HEADER_ONLY # include "format.cc" +#elif _MSC_VER +# pragma comment(lib, "format.lib") #endif #endif // FMT_FORMAT_H_ diff --git a/posix.cc b/posix.cc index 945fe95b..f64290a9 100644 --- a/posix.cc +++ b/posix.cc @@ -75,7 +75,9 @@ inline std::size_t convert_rwcount(std::size_t count) { return count; } #endif } -fmt::BufferedFile::~BufferedFile() FMT_NOEXCEPT(true) { +// Implementations of fmt::BufferedFile + +fmt::BufferedFile::~BufferedFile() FMT_NOEXCEPT { if (file_ && FMT_SYSTEM(fclose(file_)) != 0) fmt::report_system_error(errno, "cannot close file"); } @@ -102,6 +104,35 @@ int fmt::BufferedFile::fileno() const { return fd; } +void fmt::BufferedFile::flush() { + if (!file_) + return; + int result = FMT_SYSTEM(fflush(file_)); + if (result != 0) + throw SystemError(errno, "cannot flush file"); +} + +void fmt::BufferedFile::write_raw(fmt::StringRef str) { + if (!file_) + return; + std::size_t result = FMT_SYSTEM(fwrite(str.c_str(), str.size(), 1, file_)); + if (result < str.size()) { + // FIXME: According to ```man fwrite```, fwrite won't set errno at all + throw SystemError(errno, "failed to write raw string, only {} character(s) written", result); + } +} + +void fmt::BufferedFile::write_raw(char c) { + if (!file_) + return; + int result = FMT_SYSTEM(fputc(c, file_)); + if (result == EOF) + throw SystemError(errno, "failed to write '{}'", result); +} + + +// Implementations of fmt::File + fmt::File::File(fmt::StringRef path, int oflag) { int mode = S_IRUSR | S_IWUSR; #ifdef _WIN32 @@ -114,7 +145,7 @@ fmt::File::File(fmt::StringRef path, int oflag) { throw SystemError(errno, "cannot open file {}", path); } -fmt::File::~File() FMT_NOEXCEPT(true) { +fmt::File::~File() FMT_NOEXCEPT { // Don't retry close in case of EINTR! // See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html if (fd_ != -1 && FMT_POSIX_CALL(close(fd_)) != 0) @@ -134,13 +165,13 @@ void fmt::File::close() { fmt::LongLong fmt::File::size() const { #ifdef _WIN32 - LARGE_INTEGER size = {}; + LARGE_INTEGER filesize; HANDLE handle = reinterpret_cast(_get_osfhandle(fd_)); - if (!FMT_SYSTEM(GetFileSizeEx(handle, &size))) + if (!FMT_SYSTEM(GetFileSizeEx(handle, &filesize))) throw WindowsError(GetLastError(), "cannot get file size"); - FMT_STATIC_ASSERT(sizeof(fmt::LongLong) >= sizeof(size.QuadPart), + FMT_STATIC_ASSERT(sizeof(fmt::LongLong) >= sizeof(filesize.QuadPart), "return type of File::size is not large enough"); - return size.QuadPart; + return filesize.QuadPart; #else typedef struct stat Stat; Stat file_stat = Stat(); @@ -186,7 +217,7 @@ void fmt::File::dup2(int fd) { } } -void fmt::File::dup2(int fd, ErrorCode &ec) FMT_NOEXCEPT(true) { +void fmt::File::dup2(int fd, ErrorCode &ec) FMT_NOEXCEPT { int result = 0; FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd))); if (result == -1) @@ -226,9 +257,10 @@ fmt::BufferedFile fmt::File::fdopen(const char *mode) { return file; } + long fmt::getpagesize() { #ifdef _WIN32 - SYSTEM_INFO si = {}; + SYSTEM_INFO si; GetSystemInfo(&si); return si.dwPageSize; #else diff --git a/posix.h b/posix.h index 5ec80993..52ca5892 100644 --- a/posix.h +++ b/posix.h @@ -53,7 +53,7 @@ #ifdef FMT_SYSTEM # define FMT_POSIX_CALL(call) FMT_SYSTEM(call) #else -# define FMT_SYSTEM(call) call +# define FMT_SYSTEM(call) ::call # ifdef _WIN32 // Fix warnings about deprecated symbols. # define FMT_POSIX_CALL(call) ::_##call @@ -68,7 +68,7 @@ # define FMT_UNUSED #endif -#if FMT_USE_STATIC_ASSERT +#if FMT_USE_STATIC_ASSERT || (defined _MSC_VER && _MSC_VER >= 1700) || FMT_HAS_CPP_ATTRIBUTE(cxx_static_assert) || (__cplusplus >= 201103L && FMT_GCC_VERSION >= 403) # define FMT_STATIC_ASSERT(cond, message) static_assert(cond, message) #else # define FMT_CONCAT_(a, b) FMT_CONCAT(a, b) @@ -97,9 +97,9 @@ class ErrorCode { int value_; public: - explicit ErrorCode(int value = 0) FMT_NOEXCEPT(true) : value_(value) {} + explicit ErrorCode(int value = 0) FMT_NOEXCEPT : value_(value) {} - int get() const FMT_NOEXCEPT(true) { return value_; } + int get() const FMT_NOEXCEPT { return value_; } }; // A buffered file. @@ -113,10 +113,10 @@ class BufferedFile { public: // Constructs a BufferedFile object which doesn't represent any file. - BufferedFile() FMT_NOEXCEPT(true) : file_(0) {} + BufferedFile() FMT_NOEXCEPT : file_(0) {} // Destroys the object closing the file it represents if any. - ~BufferedFile() FMT_NOEXCEPT(true); + ~BufferedFile() FMT_NOEXCEPT; #if !FMT_USE_RVALUE_REFERENCES // Emulate a move constructor and a move assignment operator if rvalue @@ -131,10 +131,10 @@ class BufferedFile { public: // A "move constructor" for moving from a temporary. - BufferedFile(Proxy p) FMT_NOEXCEPT(true) : file_(p.file) {} + BufferedFile(Proxy p) FMT_NOEXCEPT : file_(p.file) {} // A "move constructor" for for moving from an lvalue. - BufferedFile(BufferedFile &f) FMT_NOEXCEPT(true) : file_(f.file_) { + BufferedFile(BufferedFile &f) FMT_NOEXCEPT : file_(f.file_) { f.file_ = 0; } @@ -155,7 +155,7 @@ public: // Returns a proxy object for moving from a temporary: // BufferedFile file = BufferedFile(...); - operator Proxy() FMT_NOEXCEPT(true) { + operator Proxy() FMT_NOEXCEPT { Proxy p = {file_}; file_ = 0; return p; @@ -166,7 +166,7 @@ public: FMT_DISALLOW_COPY_AND_ASSIGN(BufferedFile); public: - BufferedFile(BufferedFile &&other) FMT_NOEXCEPT(true) : file_(other.file_) { + BufferedFile(BufferedFile &&other) FMT_NOEXCEPT : file_(other.file_) { other.file_ = 0; } @@ -181,22 +181,41 @@ public: // Opens a file. BufferedFile(fmt::StringRef filename, fmt::StringRef mode); + // Gets whether a file is opened + bool is_open() const FMT_NOEXCEPT { return file_ != 0; } + // Closes the file. void close(); // Returns the pointer to a FILE object representing this file. - FILE *get() const { return file_; } - + FILE *get() const FMT_NOEXCEPT { return file_; } + + // Gets the file number of a file int fileno() const; + // Flushes the buffer of a file + void flush(); // FIXME: Should be const? + + // Writes raw string without formatting + void write_raw(fmt::StringRef str); + // Writes a single charactor without formatting + void write_raw(char c); + void print(fmt::StringRef format_str, const ArgList &args) { fmt::print(file_, format_str, args); } + void printf(fmt::StringRef format_str, const ArgList &args) { + fmt::fprintf(file_, format_str, args); + } + void println() { + write_raw('\n'); + } FMT_VARIADIC(void, print, fmt::StringRef) + FMT_VARIADIC(void, printf, fmt::StringRef) }; // A file. Closed file is represented by a File object with descriptor -1. -// Methods that are not declared with FMT_NOEXCEPT(true) may throw +// Methods that are not declared with FMT_NOEXCEPT may throw // fmt::SystemError in case of failure. Note that some errors such as // closing the file multiple times will cause a crash on Windows rather // than an exception. You can get standard behavior by overriding the @@ -217,7 +236,7 @@ class File { }; // Constructs a File object which doesn't represent any file. - File() FMT_NOEXCEPT(true) : fd_(-1) {} + File() FMT_NOEXCEPT : fd_(-1) {} // Opens a file and constructs a File object representing this file. File(fmt::StringRef path, int oflag); @@ -235,10 +254,10 @@ class File { public: // A "move constructor" for moving from a temporary. - File(Proxy p) FMT_NOEXCEPT(true) : fd_(p.fd) {} + File(Proxy p) FMT_NOEXCEPT : fd_(p.fd) {} // A "move constructor" for for moving from an lvalue. - File(File &other) FMT_NOEXCEPT(true) : fd_(other.fd_) { + File(File &other) FMT_NOEXCEPT : fd_(other.fd_) { other.fd_ = -1; } @@ -259,7 +278,7 @@ class File { // Returns a proxy object for moving from a temporary: // File file = File(...); - operator Proxy() FMT_NOEXCEPT(true) { + operator Proxy() FMT_NOEXCEPT { Proxy p = {fd_}; fd_ = -1; return p; @@ -270,7 +289,7 @@ class File { FMT_DISALLOW_COPY_AND_ASSIGN(File); public: - File(File &&other) FMT_NOEXCEPT(true) : fd_(other.fd_) { + File(File &&other) FMT_NOEXCEPT : fd_(other.fd_) { other.fd_ = -1; } @@ -283,10 +302,10 @@ class File { #endif // Destroys the object closing the file it represents if any. - ~File() FMT_NOEXCEPT(true); + ~File() FMT_NOEXCEPT; // Returns the file descriptor. - int descriptor() const FMT_NOEXCEPT(true) { return fd_; } + int descriptor() const FMT_NOEXCEPT { return fd_; } // Closes the file. void close(); @@ -310,7 +329,7 @@ class File { // Makes fd be the copy of this file descriptor, closing fd first if // necessary. - void dup2(int fd, ErrorCode &ec) FMT_NOEXCEPT(true); + void dup2(int fd, ErrorCode &ec) FMT_NOEXCEPT; // Creates a pipe setting up read_end and write_end file objects for reading // and writing respectively. diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7be4c78b..8efe915f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -19,7 +19,7 @@ add_fmt_test(format-test) add_fmt_test(format-impl-test CUSTOM_LINK) add_fmt_test(printf-test) foreach (target format-test printf-test) - if (CMAKE_COMPILER_IS_GNUCXX) + if (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") set_target_properties(${target} PROPERTIES COMPILE_FLAGS "-Wall -Wextra -pedantic -Wno-long-long -Wno-variadic-macros") endif () @@ -64,12 +64,14 @@ set_target_properties(header-only-test PROPERTIES COMPILE_DEFINITIONS "FMT_HEADER_ONLY=1") target_link_libraries(header-only-test gmock) -# Test that the library can be compiled with exceptions disabled. -check_cxx_compiler_flag(-fno-exceptions HAVE_FNO_EXCEPTIONS_FLAG) -if (HAVE_FNO_EXCEPTIONS_FLAG) - add_library(noexception-test STATIC ../format.cc) - set_target_properties(noexception-test - PROPERTIES COMPILE_FLAGS -fno-exceptions) +if (NOT CMAKE_GENERATOR MATCHES "Visual Studio") + # Test that the library can be compiled with exceptions disabled. + check_cxx_compiler_flag(-fno-exceptions HAVE_FNO_EXCEPTIONS_FLAG) + if (HAVE_FNO_EXCEPTIONS_FLAG) + add_library(noexception-test STATIC ../format.cc) + set_target_properties(noexception-test + PROPERTIES COMPILE_FLAGS -fno-exceptions) + endif () endif () add_test(compile-test ${CMAKE_CTEST_COMMAND} diff --git a/test/gtest-extra.cc b/test/gtest-extra.cc index cbd4e934..93ca2193 100644 --- a/test/gtest-extra.cc +++ b/test/gtest-extra.cc @@ -62,7 +62,7 @@ OutputRedirect::OutputRedirect(FILE *file) : file_(file) { write_end.dup2(fd); } -OutputRedirect::~OutputRedirect() FMT_NOEXCEPT(true) { +OutputRedirect::~OutputRedirect() FMT_NOEXCEPT { try { restore(); } catch (const std::exception &e) { diff --git a/test/gtest-extra.h b/test/gtest-extra.h index aa03bdff..df9cb7f0 100644 --- a/test/gtest-extra.h +++ b/test/gtest-extra.h @@ -104,7 +104,7 @@ class OutputRedirect { public: explicit OutputRedirect(FILE *file); - ~OutputRedirect() FMT_NOEXCEPT(true); + ~OutputRedirect() FMT_NOEXCEPT; // Restores the original file, reads output from the pipe into a string // and returns it. diff --git a/test/posix-test.cc b/test/posix-test.cc index c9529688..fe18cd62 100644 --- a/test/posix-test.cc +++ b/test/posix-test.cc @@ -178,6 +178,18 @@ int test::fileno(FILE *stream) { return ::FMT_POSIX(fileno(stream)); } +int test::fflush(FILE *stream) { + return ::fflush(stream); +} + +int test::fwrite(const void *str, size_t size, size_t count, FILE *stream) { + return ::fwrite(str, size, count, stream); +} + +int test::fputc(int ch, FILE *stream) { + return ::fputc(ch, stream); +} + #ifndef _WIN32 # define EXPECT_RETRY(statement, func, message) \ func##_count = 1; \ diff --git a/test/posix-test.h b/test/posix-test.h index 4768cb94..48012e4b 100644 --- a/test/posix-test.h +++ b/test/posix-test.h @@ -73,6 +73,10 @@ int pipe(int *pfds, unsigned psize, int textmode); FILE *fopen(const char *filename, const char *mode); int fclose(FILE *stream); int fileno(FILE *stream); +int fflush(FILE *stream); + +int fwrite(const void *str, size_t size, size_t count, FILE *stream); +int fputc(int ch, FILE *stream); } // namespace test diff --git a/test/util-test.cc b/test/util-test.cc index fd295525..b04cb4a9 100644 --- a/test/util-test.cc +++ b/test/util-test.cc @@ -699,8 +699,7 @@ void test_count_digits() { } TEST(UtilTest, StringRef) { - char space[100]; - std::strcpy(space, "some string"); + char space[100] = "some string"; EXPECT_EQ(sizeof("some string") - 1, StringRef(space).size()); }