From 704e7a88176c61822e092c81a5ebe6c09100ef7b Mon Sep 17 00:00:00 2001 From: carterl Date: Wed, 11 Feb 2015 09:16:57 +0100 Subject: [PATCH 01/12] Add a few useful methods --- posix.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/posix.h b/posix.h index 5ec80993..a7db31a1 100644 --- a/posix.h +++ b/posix.h @@ -181,18 +181,45 @@ public: // Opens a file. BufferedFile(fmt::StringRef filename, fmt::StringRef mode); + // Gets whether a file is opened + bool is_open() { return file_ != 0; } + // Closes the file. void close(); // Returns the pointer to a FILE object representing this file. FILE *get() const { return file_; } + void flush() { + if (is_open()) { + std::fflush(file_); + } + } + int fileno() const; + void write_raw(fmt::StringRef str) { + if (is_open()) { + std::fwrite(str.c_str(), str.size(), 1, file_); + } + } + void write_raw(char c) { + if (is_open()) { + std::fputc(c, file_); + } + } + 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. From 240965305f1f0e2622899dee31e1f090821ad48d Mon Sep 17 00:00:00 2001 From: carterl Date: Wed, 11 Feb 2015 10:02:20 +0100 Subject: [PATCH 02/12] Various fixes for MSVC --- format.cc | 14 +++++++------- format.h | 28 +++++++++++++++++++--------- posix.cc | 6 +++--- posix.h | 36 ++++++++++++++++++------------------ test/CMakeLists.txt | 14 ++++++++------ test/gtest-extra.cc | 2 +- test/gtest-extra.h | 2 +- test/util-test.cc | 3 +-- 8 files changed, 58 insertions(+), 47 deletions(-) diff --git a/format.cc b/format.cc index 9005302c..1a6e4e22 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 diff --git a/format.h b/format.h index c6bdd707..8468f89f 100644 --- a/format.h +++ b/format.h @@ -114,16 +114,26 @@ // 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) +# define FMT_NOEXCEPT noexcept +# define FMT_NOEXCEPT_EXPR(expr) noexcept(expr) #else -# define FMT_NOEXCEPT(expr) +# define FMT_NOEXCEPT throw() +# define FMT_NOEXCEPT_EXPR(expr) #endif // A macro to disallow the copy constructor and operator= functions // This should be used in the private: declarations for a class +#if FMT_HAS_FEATURE(cxx_deleted_functions)\ + || (FMT_GCC_VERSION >= 404 && __cplusplus >= 201103)\ + || (_MSC_VER >= 1800) +#define FMT_DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName&) = delete; \ + void operator=(const TypeName&) = delete +#else #define FMT_DISALLOW_COPY_AND_ASSIGN(TypeName) \ TypeName(const TypeName&); \ void operator=(const TypeName&) +#endif namespace fmt { @@ -290,7 +300,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 +633,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 @@ -1560,7 +1570,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 @@ -1684,7 +1694,7 @@ class BasicWriter { return *this; } - void clear() FMT_NOEXCEPT(true) { buffer_.clear(); } + void clear() FMT_NOEXCEPT { buffer_.clear(); } }; template @@ -2101,7 +2111,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 @@ -2144,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 diff --git a/posix.cc b/posix.cc index 945fe95b..b4893cd6 100644 --- a/posix.cc +++ b/posix.cc @@ -75,7 +75,7 @@ inline std::size_t convert_rwcount(std::size_t count) { return count; } #endif } -fmt::BufferedFile::~BufferedFile() FMT_NOEXCEPT(true) { +fmt::BufferedFile::~BufferedFile() FMT_NOEXCEPT { if (file_ && FMT_SYSTEM(fclose(file_)) != 0) fmt::report_system_error(errno, "cannot close file"); } @@ -114,7 +114,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) @@ -186,7 +186,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) diff --git a/posix.h b/posix.h index a7db31a1..cce1b1b2 100644 --- a/posix.h +++ b/posix.h @@ -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; } @@ -223,7 +223,7 @@ public: }; // 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 @@ -244,7 +244,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); @@ -262,10 +262,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; } @@ -286,7 +286,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; @@ -297,7 +297,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; } @@ -310,10 +310,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(); @@ -337,7 +337,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..5ab3c2eb 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -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/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()); } From 2e7e2279d278408269edcfa23fda492929d2b335 Mon Sep 17 00:00:00 2001 From: carterl Date: Wed, 11 Feb 2015 10:13:43 +0100 Subject: [PATCH 03/12] Try linking to format.lib automatically on MSVC --- format.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/format.h b/format.h index 8468f89f..51ef13e9 100644 --- a/format.h +++ b/format.h @@ -2497,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_ From 47148771fc62d575a129c21f10339a10d37752ca Mon Sep 17 00:00:00 2001 From: carterl Date: Wed, 11 Feb 2015 10:41:43 +0100 Subject: [PATCH 04/12] Fixes for extra methods --- .gitignore | 1 + posix.cc | 15 +++++++++++++++ posix.h | 36 +++++++++++++++++++----------------- 3 files changed, 35 insertions(+), 17 deletions(-) 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/posix.cc b/posix.cc index b4893cd6..63b37c37 100644 --- a/posix.cc +++ b/posix.cc @@ -75,6 +75,8 @@ inline std::size_t convert_rwcount(std::size_t count) { return count; } #endif } +// 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,18 @@ int fmt::BufferedFile::fileno() const { return fd; } +void fmt::BufferedFile::flush() { + if (!file_) + return; + // FIXME: int result = FMT_SYSTEM(fflush(file_)); + int result = ::fflush(file_); + if (result != 0) + throw SystemError(errno, "cannot flush file"); +} + + +// Implementations of fmt::File + fmt::File::File(fmt::StringRef path, int oflag) { int mode = S_IRUSR | S_IWUSR; #ifdef _WIN32 @@ -226,6 +240,7 @@ fmt::BufferedFile fmt::File::fdopen(const char *mode) { return file; } + long fmt::getpagesize() { #ifdef _WIN32 SYSTEM_INFO si = {}; diff --git a/posix.h b/posix.h index cce1b1b2..0dcc2960 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 @@ -182,31 +182,33 @@ public: BufferedFile(fmt::StringRef filename, fmt::StringRef mode); // Gets whether a file is opened - bool is_open() { return file_ != 0; } + 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_; } - - void flush() { - if (is_open()) { - std::fflush(file_); - } - } - + FILE *get() const FMT_NOEXCEPT{ return file_; } + + // Gets the file number of a file int fileno() const; - void write_raw(fmt::StringRef str) { - if (is_open()) { - std::fwrite(str.c_str(), str.size(), 1, file_); - } + // Flushes the buffer of a file + void flush(); // FIXME: Should be const? + + // Writes raw string without formatting + std::size_t write_raw(fmt::StringRef str) { + // FIXME: throw exception when failing + if (!is_open()) + return 0; + return ::fwrite(str.c_str(), str.size(), 1, file_); } + // Writes a single charactor without formatting void write_raw(char c) { - if (is_open()) { - std::fputc(c, file_); - } + // FIXME: throw exception when failing + if (!is_open()) + return; + ::fputc(c, file_); } void print(fmt::StringRef format_str, const ArgList &args) { From f1dd53de020ee2f408629c313d637cab1165ace5 Mon Sep 17 00:00:00 2001 From: carterl Date: Fri, 13 Feb 2015 03:27:14 +0100 Subject: [PATCH 05/12] Silence warnings of MinGW builds. 1. Remove initializers of out parameters: warning: missing initializer for member '_SYSTEM_INFO::dwPageSize' [-Wmissing-field-initializers] 2. Rename a local variable: warning: declaration of 'size' shadows a member of 'this' [-Wshadow] --- posix.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/posix.cc b/posix.cc index 63b37c37..43a6d15e 100644 --- a/posix.cc +++ b/posix.cc @@ -148,13 +148,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(); @@ -243,7 +243,7 @@ fmt::BufferedFile fmt::File::fdopen(const char *mode) { long fmt::getpagesize() { #ifdef _WIN32 - SYSTEM_INFO si = {}; + SYSTEM_INFO si; GetSystemInfo(&si); return si.dwPageSize; #else From adeb46ab09c58e9979b9101d00ba2bac82be7e97 Mon Sep 17 00:00:00 2001 From: carterl Date: Fri, 13 Feb 2015 04:19:56 +0100 Subject: [PATCH 06/12] Use nullptr where appropriate; also simulate it for ancient compilers. Since it's hard to find all places where using 0 as a pointer literal, only format.* & posix.* are replaced ( missing expected though ) --- format.cc | 18 +++++++++--------- format.h | 36 +++++++++++++++++++++++++++++++----- posix.cc | 2 +- posix.h | 14 +++++++------- 4 files changed, 48 insertions(+), 22 deletions(-) diff --git a/format.cc b/format.cc index 1a6e4e22..62d401d4 100644 --- a/format.cc +++ b/format.cc @@ -147,7 +147,7 @@ typedef void (*FormatFunc)(fmt::Writer &, int, fmt::StringRef); // Buffer should be at least of size 1. int safe_strerror( int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT { - assert(buffer != 0 && buffer_size != 0); + assert(buffer != nullptr && buffer_size != 0); int result = 0; #if ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE) || __ANDROID__ // XSI-compliant version of strerror_r. @@ -457,7 +457,7 @@ FMT_FUNC void fmt::internal::report_unknown_type(char code, const char *type) { FMT_FUNC fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) { int length = MultiByteToWideChar( - CP_UTF8, MB_ERR_INVALID_CHARS, s.c_str(), -1, 0, 0); + CP_UTF8, MB_ERR_INVALID_CHARS, s.c_str(), -1, nullptr, 0); static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16"; if (length == 0) FMT_THROW(WindowsError(GetLastError(), ERROR_MSG)); @@ -476,12 +476,12 @@ FMT_FUNC fmt::internal::UTF16ToUTF8::UTF16ToUTF8(fmt::WStringRef s) { } FMT_FUNC int fmt::internal::UTF16ToUTF8::convert(fmt::WStringRef s) { - int length = WideCharToMultiByte(CP_UTF8, 0, s.c_str(), -1, 0, 0, 0, 0); + int length = WideCharToMultiByte(CP_UTF8, 0, s.c_str(), -1, nullptr, 0, nullptr, nullptr); if (length == 0) return GetLastError(); buffer_.resize(length); length = WideCharToMultiByte( - CP_UTF8, 0, s.c_str(), -1, &buffer_[0], length, 0, 0); + CP_UTF8, 0, s.c_str(), -1, &buffer_[0], length, nullptr, nullptr); if (length == 0) return GetLastError(); return 0; @@ -536,9 +536,9 @@ FMT_FUNC void fmt::internal::format_windows_error( FMT_TRY { String system_message; if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - reinterpret_cast(system_message.ptr()), 0, 0)) { + reinterpret_cast(system_message.ptr()), 0, nullptr)) { UTF16ToUTF8 utf8_message; if (utf8_message.convert(system_message.c_str()) == ERROR_SUCCESS) { out << message << ": " << utf8_message; @@ -648,7 +648,7 @@ void fmt::BasicWriter::write_str( template inline Arg fmt::BasicFormatter::parse_arg_index(const Char *&s) { - const char *error = 0; + const char *error = nullptr; Arg arg = *s < '0' || *s > '9' ? next_arg(error) : get_arg(parse_nonnegative_int(s), error); if (error) { @@ -713,7 +713,7 @@ void fmt::internal::PrintfFormatter::parse_flags( template Arg fmt::internal::PrintfFormatter::get_arg( const Char *s, unsigned arg_index) { - const char *error = 0; + const char *error = nullptr; Arg arg = arg_index == UINT_MAX ? next_arg(error) : FormatterBase::get_arg(arg_index - 1, error); if (error) @@ -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 8ac48074..8a923b57 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,7 +113,7 @@ // 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) + (FMT_GCC_VERSION >= 408 && __cplusplus >= 201103L) # define FMT_NOEXCEPT noexcept # define FMT_NOEXCEPT_EXPR(expr) noexcept(expr) #else @@ -124,7 +124,7 @@ // A macro to disallow the copy constructor and operator= functions // This should be used in the private: declarations for a class #if FMT_HAS_FEATURE(cxx_deleted_functions)\ - || (FMT_GCC_VERSION >= 404 && __cplusplus >= 201103)\ + || (FMT_GCC_VERSION >= 404 && __cplusplus >= 201103L)\ || (_MSC_VER >= 1800) #define FMT_DISALLOW_COPY_AND_ASSIGN(TypeName) \ TypeName(const TypeName&) = delete; \ @@ -135,6 +135,32 @@ void operator=(const TypeName&) #endif +#if FMT_HAS_FEATURE(cxx_nullptr)\ + || (FMT_GCC_VERSION >= 406 && __cplusplus >= 201103L)\ + || (_MSC_VER >= 1600) +// Use nullptr +#else +// Simulate it +namespace std { +class nullptr_t { +public: + template + operator T*() const { + return 0; + } + template + operator T C::*() const + { + return 0; + } +private: + void operator&() const; +}; +} + +std::nullptr_t const nullptr = {}; +#endif + namespace fmt { // Fix the warning about long long on older versions of GCC @@ -273,7 +299,7 @@ class Buffer { std::size_t size_; std::size_t capacity_; - Buffer(T *ptr = 0, std::size_t capacity = 0) + Buffer(T *ptr = nullptr, std::size_t capacity = 0) : ptr_(ptr), size_(0), capacity_(capacity) {} virtual void grow(std::size_t size) = 0; diff --git a/posix.cc b/posix.cc index 43a6d15e..5415039b 100644 --- a/posix.cc +++ b/posix.cc @@ -92,7 +92,7 @@ void fmt::BufferedFile::close() { if (!file_) return; int result = FMT_SYSTEM(fclose(file_)); - file_ = 0; + file_ = nullptr; if (result != 0) throw SystemError(errno, "cannot close file"); } diff --git a/posix.h b/posix.h index 0dcc2960..b1b3a245 100644 --- a/posix.h +++ b/posix.h @@ -113,7 +113,7 @@ class BufferedFile { public: // Constructs a BufferedFile object which doesn't represent any file. - BufferedFile() FMT_NOEXCEPT : file_(0) {} + BufferedFile() FMT_NOEXCEPT : file_(nullptr) {} // Destroys the object closing the file it represents if any. ~BufferedFile() FMT_NOEXCEPT; @@ -167,13 +167,13 @@ public: public: BufferedFile(BufferedFile &&other) FMT_NOEXCEPT : file_(other.file_) { - other.file_ = 0; + other.file_ = nullptr; } BufferedFile& operator=(BufferedFile &&other) { close(); file_ = other.file_; - other.file_ = 0; + other.file_ = nullptr; return *this; } #endif @@ -182,13 +182,13 @@ public: BufferedFile(fmt::StringRef filename, fmt::StringRef mode); // Gets whether a file is opened - bool is_open() const FMT_NOEXCEPT { return file_ != 0; } + bool is_open() const FMT_NOEXCEPT { return file_ != nullptr; } // Closes the file. void close(); // Returns the pointer to a FILE object representing this file. - FILE *get() const FMT_NOEXCEPT{ return file_; } + FILE *get() const FMT_NOEXCEPT { return file_; } // Gets the file number of a file int fileno() const; @@ -198,14 +198,14 @@ public: // Writes raw string without formatting std::size_t write_raw(fmt::StringRef str) { - // FIXME: throw exception when failing + // TODO: throw exception when failing if (!is_open()) return 0; return ::fwrite(str.c_str(), str.size(), 1, file_); } // Writes a single charactor without formatting void write_raw(char c) { - // FIXME: throw exception when failing + // TODO: throw exception when failing if (!is_open()) return; ::fputc(c, file_); From 79adad5e33618dad928f9386037d4d097c6b6e77 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 13 Feb 2015 14:04:13 +0800 Subject: [PATCH 07/12] Enable C++11 when building main library too --- CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f9d40a29..0edb761f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,9 +77,12 @@ add_library(format ${FMT_SOURCES}) if (CMAKE_COMPILER_IS_GNUCXX) 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}) From e3ba8d9530e84a14b3c61da6f062b8bd3762da66 Mon Sep 17 00:00:00 2001 From: carterl Date: Fri, 13 Feb 2015 08:00:01 +0100 Subject: [PATCH 08/12] UT stub for extra methods in BufferedFile --- posix.cc | 29 +++++++++++++++++++++++------ posix.h | 14 ++------------ test/posix-test.cc | 12 ++++++++++++ test/posix-test.h | 4 ++++ 4 files changed, 41 insertions(+), 18 deletions(-) diff --git a/posix.cc b/posix.cc index 5415039b..68fe8e1d 100644 --- a/posix.cc +++ b/posix.cc @@ -105,12 +105,29 @@ int fmt::BufferedFile::fileno() const { } void fmt::BufferedFile::flush() { - if (!file_) - return; - // FIXME: int result = FMT_SYSTEM(fflush(file_)); - int result = ::fflush(file_); - if (result != 0) - throw SystemError(errno, "cannot flush file"); + 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); } diff --git a/posix.h b/posix.h index b1b3a245..672fe09d 100644 --- a/posix.h +++ b/posix.h @@ -197,19 +197,9 @@ public: void flush(); // FIXME: Should be const? // Writes raw string without formatting - std::size_t write_raw(fmt::StringRef str) { - // TODO: throw exception when failing - if (!is_open()) - return 0; - return ::fwrite(str.c_str(), str.size(), 1, file_); - } + void write_raw(fmt::StringRef str); // Writes a single charactor without formatting - void write_raw(char c) { - // TODO: throw exception when failing - if (!is_open()) - return; - ::fputc(c, file_); - } + void write_raw(char c); void print(fmt::StringRef format_str, const ArgList &args) { fmt::print(file_, format_str, args); 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 From 4fccc4399fbdeff42149d2059d9c20246cd0457a Mon Sep 17 00:00:00 2001 From: root Date: Fri, 13 Feb 2015 15:56:26 +0800 Subject: [PATCH 09/12] Try supporting clang, doesn't work yet --- CMakeLists.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0edb761f..32a03adc 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,7 +80,7 @@ if (BIICODE) endif () add_library(format ${FMT_SOURCES}) -if (CMAKE_COMPILER_IS_GNUCXX) +if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") set_target_properties(format PROPERTIES COMPILE_FLAGS "-Wall -Wextra -Wshadow -pedantic") if (CPP11_FLAG) From 52039e8b71b7199ad388534b53d8e5cfa16ee421 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 13 Feb 2015 20:05:57 +0800 Subject: [PATCH 10/12] Add feature testing codes in CMakeLists.txt for future use. Doesn't work though. --- CMakeLists.txt | 45 ++++++++++++++++++++++++++++++++++++++++++++- format.h | 35 ++++++++++++++++------------------- test/CMakeLists.txt | 2 +- 3 files changed, 61 insertions(+), 21 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 32a03adc..d765423a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -80,7 +80,7 @@ if (BIICODE) endif () add_library(format ${FMT_SOURCES}) -if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") +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) @@ -117,6 +117,49 @@ if (NOT FMT_VARIADIC_TEMPLATES) add_definitions(-DGTEST_LANG_CXX11=0) endif () +# g++ 4.6 supports nullptr with __cplusplus==1 +# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=1773 +check_cxx_source_compiles(" + int main(){int*p=nullptr;}" FMT_NULLPTR) +if (FMT_NULLPTR) + add_definitions(-DFMT_USE_NULLPTR=1) +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.h b/format.h index 8a923b57..a837f6a1 100644 --- a/format.h +++ b/format.h @@ -115,46 +115,43 @@ #if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \ (FMT_GCC_VERSION >= 408 && __cplusplus >= 201103L) # define FMT_NOEXCEPT noexcept -# define FMT_NOEXCEPT_EXPR(expr) noexcept(expr) #else # define FMT_NOEXCEPT throw() -# define FMT_NOEXCEPT_EXPR(expr) #endif // A macro to disallow the copy constructor and operator= functions // This should be used in the private: declarations for a class -#if FMT_HAS_FEATURE(cxx_deleted_functions)\ +#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; \ - void operator=(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 -#if FMT_HAS_FEATURE(cxx_nullptr)\ +#if FMT_USE_NULLPTR || FMT_HAS_FEATURE(cxx_nullptr)\ || (FMT_GCC_VERSION >= 406 && __cplusplus >= 201103L)\ || (_MSC_VER >= 1600) // Use nullptr #else // Simulate it namespace std { -class nullptr_t { -public: - template - operator T*() const { - return 0; - } - template - operator T C::*() const - { - return 0; - } -private: - void operator&() const; +class nullptr_t { +public: + template + operator T*() const { + return 0; + } + template + operator T C::*() const { + return 0; + } +private: + void operator&() const; }; } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 5ab3c2eb..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 () From 651f8286b1322f0745596bb6a1b43fbd1cfc9d47 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 13 Feb 2015 20:29:57 +0800 Subject: [PATCH 11/12] Attempt to fix g++-4.6 build Remove fake std::nullptr_t implementation --- CMakeLists.txt | 8 ++++---- format.h | 22 +++------------------- 2 files changed, 7 insertions(+), 23 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d765423a..3b2abc80 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -122,7 +122,7 @@ endif () check_cxx_source_compiles(" int main(){int*p=nullptr;}" FMT_NULLPTR) if (FMT_NULLPTR) - add_definitions(-DFMT_USE_NULLPTR=1) +# add_definitions(-DFMT_USE_NULLPTR=1) endif () check_cxx_source_compiles(" @@ -133,14 +133,14 @@ check_cxx_source_compiles(" }; int main(){}" FMT_DELETED_FUNCTIONS) if (FMT_DELETED_FUNCTIONS) - add_definitions(-DFMT_USE_DELETED_FUNCTIONS=1) +# 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) +# add_definitions(-DFMT_USE_NOEXCEPT=1) endif () check_cxx_source_compiles(" @@ -157,7 +157,7 @@ check_cxx_source_compiles(" MoveOnly c(MoveOnly()); }" FMT_RVALUE_REFERENCES) if (FMT_RVALUE_REFERENCES) - add_definitions(-DFMT_USE_RVALUE_REFERENCES=1) +# add_definitions(-DFMT_USE_RVALUE_REFERENCES=1) endif () # GTest doesn't detect with clang. diff --git a/format.h b/format.h index a837f6a1..1a6ff0e6 100644 --- a/format.h +++ b/format.h @@ -137,25 +137,9 @@ || (FMT_GCC_VERSION >= 406 && __cplusplus >= 201103L)\ || (_MSC_VER >= 1600) // Use nullptr -#else -// Simulate it -namespace std { -class nullptr_t { -public: - template - operator T*() const { - return 0; - } - template - operator T C::*() const { - return 0; - } -private: - void operator&() const; -}; -} - -std::nullptr_t const nullptr = {}; +#elif !defined(nullptr) +// Some standard library implementations define nullptr themselves such as libc++ +# define nullptr 0 #endif namespace fmt { From 2fb9ddafc60484030eb69794af78b282a8c555a9 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 13 Feb 2015 23:14:04 +0800 Subject: [PATCH 12/12] Revert changes of nullptr --- CMakeLists.txt | 8 -------- format.cc | 16 ++++++++-------- format.h | 11 +---------- posix.cc | 2 +- posix.h | 8 ++++---- 5 files changed, 14 insertions(+), 31 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b2abc80..198440aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -117,14 +117,6 @@ if (NOT FMT_VARIADIC_TEMPLATES) add_definitions(-DGTEST_LANG_CXX11=0) endif () -# g++ 4.6 supports nullptr with __cplusplus==1 -# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=1773 -check_cxx_source_compiles(" - int main(){int*p=nullptr;}" FMT_NULLPTR) -if (FMT_NULLPTR) -# add_definitions(-DFMT_USE_NULLPTR=1) -endif () - check_cxx_source_compiles(" struct C{ C()=delete; diff --git a/format.cc b/format.cc index 62d401d4..636e4144 100644 --- a/format.cc +++ b/format.cc @@ -147,7 +147,7 @@ typedef void (*FormatFunc)(fmt::Writer &, int, fmt::StringRef); // Buffer should be at least of size 1. int safe_strerror( int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT { - assert(buffer != nullptr && buffer_size != 0); + assert(buffer != 0 && buffer_size != 0); int result = 0; #if ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE) || __ANDROID__ // XSI-compliant version of strerror_r. @@ -457,7 +457,7 @@ FMT_FUNC void fmt::internal::report_unknown_type(char code, const char *type) { FMT_FUNC fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) { int length = MultiByteToWideChar( - CP_UTF8, MB_ERR_INVALID_CHARS, s.c_str(), -1, nullptr, 0); + CP_UTF8, MB_ERR_INVALID_CHARS, s.c_str(), -1, 0, 0); static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16"; if (length == 0) FMT_THROW(WindowsError(GetLastError(), ERROR_MSG)); @@ -476,12 +476,12 @@ FMT_FUNC fmt::internal::UTF16ToUTF8::UTF16ToUTF8(fmt::WStringRef s) { } FMT_FUNC int fmt::internal::UTF16ToUTF8::convert(fmt::WStringRef s) { - int length = WideCharToMultiByte(CP_UTF8, 0, s.c_str(), -1, nullptr, 0, nullptr, nullptr); + int length = WideCharToMultiByte(CP_UTF8, 0, s.c_str(), -1, 0, 0, 0, 0); if (length == 0) return GetLastError(); buffer_.resize(length); length = WideCharToMultiByte( - CP_UTF8, 0, s.c_str(), -1, &buffer_[0], length, nullptr, nullptr); + CP_UTF8, 0, s.c_str(), -1, &buffer_[0], length, 0, 0); if (length == 0) return GetLastError(); return 0; @@ -536,9 +536,9 @@ FMT_FUNC void fmt::internal::format_windows_error( FMT_TRY { String system_message; if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - reinterpret_cast(system_message.ptr()), 0, nullptr)) { + reinterpret_cast(system_message.ptr()), 0, 0)) { UTF16ToUTF8 utf8_message; if (utf8_message.convert(system_message.c_str()) == ERROR_SUCCESS) { out << message << ": " << utf8_message; @@ -648,7 +648,7 @@ void fmt::BasicWriter::write_str( template inline Arg fmt::BasicFormatter::parse_arg_index(const Char *&s) { - const char *error = nullptr; + const char *error = 0; Arg arg = *s < '0' || *s > '9' ? next_arg(error) : get_arg(parse_nonnegative_int(s), error); if (error) { @@ -713,7 +713,7 @@ void fmt::internal::PrintfFormatter::parse_flags( template Arg fmt::internal::PrintfFormatter::get_arg( const Char *s, unsigned arg_index) { - const char *error = nullptr; + const char *error = 0; Arg arg = arg_index == UINT_MAX ? next_arg(error) : FormatterBase::get_arg(arg_index - 1, error); if (error) diff --git a/format.h b/format.h index 1a6ff0e6..014abe00 100644 --- a/format.h +++ b/format.h @@ -133,15 +133,6 @@ TypeName& operator=(const TypeName&) #endif -#if FMT_USE_NULLPTR || FMT_HAS_FEATURE(cxx_nullptr)\ - || (FMT_GCC_VERSION >= 406 && __cplusplus >= 201103L)\ - || (_MSC_VER >= 1600) -// Use nullptr -#elif !defined(nullptr) -// Some standard library implementations define nullptr themselves such as libc++ -# define nullptr 0 -#endif - namespace fmt { // Fix the warning about long long on older versions of GCC @@ -280,7 +271,7 @@ class Buffer { std::size_t size_; std::size_t capacity_; - Buffer(T *ptr = nullptr, std::size_t capacity = 0) + Buffer(T *ptr = 0, std::size_t capacity = 0) : ptr_(ptr), size_(0), capacity_(capacity) {} virtual void grow(std::size_t size) = 0; diff --git a/posix.cc b/posix.cc index 68fe8e1d..f64290a9 100644 --- a/posix.cc +++ b/posix.cc @@ -92,7 +92,7 @@ void fmt::BufferedFile::close() { if (!file_) return; int result = FMT_SYSTEM(fclose(file_)); - file_ = nullptr; + file_ = 0; if (result != 0) throw SystemError(errno, "cannot close file"); } diff --git a/posix.h b/posix.h index 672fe09d..52ca5892 100644 --- a/posix.h +++ b/posix.h @@ -113,7 +113,7 @@ class BufferedFile { public: // Constructs a BufferedFile object which doesn't represent any file. - BufferedFile() FMT_NOEXCEPT : file_(nullptr) {} + BufferedFile() FMT_NOEXCEPT : file_(0) {} // Destroys the object closing the file it represents if any. ~BufferedFile() FMT_NOEXCEPT; @@ -167,13 +167,13 @@ public: public: BufferedFile(BufferedFile &&other) FMT_NOEXCEPT : file_(other.file_) { - other.file_ = nullptr; + other.file_ = 0; } BufferedFile& operator=(BufferedFile &&other) { close(); file_ = other.file_; - other.file_ = nullptr; + other.file_ = 0; return *this; } #endif @@ -182,7 +182,7 @@ public: BufferedFile(fmt::StringRef filename, fmt::StringRef mode); // Gets whether a file is opened - bool is_open() const FMT_NOEXCEPT { return file_ != nullptr; } + bool is_open() const FMT_NOEXCEPT { return file_ != 0; } // Closes the file. void close();