diff --git a/CMakeLists.txt b/CMakeLists.txt index 51ee620..5971bb7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,8 @@ option(RAPIDJSON_BUILD_TESTS "Build rapidjson perftests and unittests." ON) option(RAPIDJSON_BUILD_THIRDPARTY_GTEST "Use gtest installation in `thirdparty/gtest` by default if available" OFF) +option(RAPIDJSON_BUILD_CXX11 "Build rapidjson with C++11 (gcc/clang)" ON) + option(RAPIDJSON_HAS_STDSTRING "" OFF) if(RAPIDJSON_HAS_STDSTRING) add_definitions(-DRAPIDJSON_HAS_STDSTRING) @@ -27,8 +29,14 @@ endif() if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -Wall -Wextra -Werror") + if (RAPIDJSON_BUILD_CXX11) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + endif() elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -Wall -Wextra -Werror -Wno-missing-field-initializers") + if (RAPIDJSON_BUILD_CXX11) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + endif() elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") add_definitions(-D_CRT_SECURE_NO_WARNINGS=1) endif() diff --git a/example/serialize/serialize.cpp b/example/serialize/serialize.cpp index 6c5e5c2..cef5c66 100644 --- a/example/serialize/serialize.cpp +++ b/example/serialize/serialize.cpp @@ -11,6 +11,7 @@ using namespace rapidjson; class Person { public: Person(const std::string& name, unsigned age) : name_(name), age_(age) {} + Person(const Person& rhs) : name_(rhs.name_), age_(rhs.age_) {} virtual ~Person(); protected: @@ -38,6 +39,7 @@ Person::~Person() { class Education { public: Education(const std::string& school, double GPA) : school_(school), GPA_(GPA) {} + Education(const Education& rhs) : school_(rhs.school_), GPA_(rhs.GPA_) {} template void Serialize(Writer& writer) const { @@ -102,6 +104,7 @@ Dependent::~Dependent() { class Employee : public Person { public: Employee(const std::string& name, unsigned age, bool married) : Person(name, age), dependents_(), married_(married) {} + Employee(const Employee& rhs) : Person(rhs), dependents_(rhs.dependents_), married_(rhs.married_) {} virtual ~Employee(); void AddDependent(const Dependent& dependent) { diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index 095aa40..12187ea 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -31,6 +31,7 @@ RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(padded) RAPIDJSON_DIAG_OFF(switch-enum) +RAPIDJSON_DIAG_OFF(c++98-compat) #endif #ifdef __GNUC__ @@ -141,6 +142,7 @@ public: Otherwise, the copy constructor is implicitly defined. */ GenericMemberIterator(const NonConstIterator & it) : ptr_(it.ptr_) {} + Iterator& operator=(const NonConstIterator & it) { ptr_ = it.ptr_; return *this; } //! @name stepping //@{ @@ -314,8 +316,6 @@ struct GenericStringRef { const SizeType length; //!< length of the string (excluding the trailing NULL terminator) private: - //! Disallow copy-assignment - GenericStringRef operator=(const GenericStringRef&); //! Disallow construction from non-const array template GenericStringRef(CharType (&str)[N]) /* = delete */; diff --git a/include/rapidjson/internal/stack.h b/include/rapidjson/internal/stack.h index 3d691d3..12f8a8f 100644 --- a/include/rapidjson/internal/stack.h +++ b/include/rapidjson/internal/stack.h @@ -18,6 +18,11 @@ #include "../rapidjson.h" #include "swap.h" +#if defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + RAPIDJSON_NAMESPACE_BEGIN namespace internal { @@ -203,4 +208,8 @@ private: } // namespace internal RAPIDJSON_NAMESPACE_END +#if defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + #endif // RAPIDJSON_STACK_H_ diff --git a/include/rapidjson/internal/swap.h b/include/rapidjson/internal/swap.h index 39bc2e4..cbb2abd 100644 --- a/include/rapidjson/internal/swap.h +++ b/include/rapidjson/internal/swap.h @@ -17,6 +17,11 @@ #include "../rapidjson.h" +#if defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + RAPIDJSON_NAMESPACE_BEGIN namespace internal { @@ -34,4 +39,8 @@ inline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT { } // namespace internal RAPIDJSON_NAMESPACE_END +#if defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + #endif // RAPIDJSON_INTERNAL_SWAP_H_ diff --git a/include/rapidjson/stringbuffer.h b/include/rapidjson/stringbuffer.h index 40b51cd..0d32859 100644 --- a/include/rapidjson/stringbuffer.h +++ b/include/rapidjson/stringbuffer.h @@ -23,6 +23,11 @@ #include "internal/stack.h" +#if defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + RAPIDJSON_NAMESPACE_BEGIN //! Represents an in-memory output stream. @@ -103,4 +108,8 @@ inline void PutN(GenericStringBuffer >& stream, char c, size_t n) { RAPIDJSON_NAMESPACE_END +#if defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + #endif // RAPIDJSON_STRINGBUFFER_H_ diff --git a/test/unittest/documenttest.cpp b/test/unittest/documenttest.cpp index cdc4c31..c3438f3 100644 --- a/test/unittest/documenttest.cpp +++ b/test/unittest/documenttest.cpp @@ -21,6 +21,12 @@ #include #include +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +RAPIDJSON_DIAG_OFF(missing-variable-declarations) +#endif + using namespace rapidjson; template @@ -573,3 +579,7 @@ TYPED_TEST(DocumentMove, MoveAssignmentStack) { // Document d2; // d1 = d2; //} + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif diff --git a/test/unittest/readertest.cpp b/test/unittest/readertest.cpp index 3b84ab7..49888a9 100644 --- a/test/unittest/readertest.cpp +++ b/test/unittest/readertest.cpp @@ -31,6 +31,7 @@ RAPIDJSON_DIAG_OFF(missing-noreturn) #ifdef __clang__ RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(variadic-macros) +RAPIDJSON_DIAG_OFF(c++98-compat-pedantic) #endif template diff --git a/test/unittest/stringbuffertest.cpp b/test/unittest/stringbuffertest.cpp index fbacf51..28fdbc5 100644 --- a/test/unittest/stringbuffertest.cpp +++ b/test/unittest/stringbuffertest.cpp @@ -16,6 +16,11 @@ #include "rapidjson/stringbuffer.h" #include "rapidjson/writer.h" +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + using namespace rapidjson; TEST(StringBuffer, InitialSize) { @@ -148,3 +153,7 @@ TEST(StringBuffer, MoveAssignment) { } #endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif diff --git a/test/unittest/unittest.cpp b/test/unittest/unittest.cpp index dd562a2..655518a 100644 --- a/test/unittest/unittest.cpp +++ b/test/unittest/unittest.cpp @@ -15,8 +15,19 @@ #include "unittest.h" #include "rapidjson/rapidjson.h" +#ifdef __clang__ +#pragma GCC diagnostic push +#if __has_warning("-Wdeprecated") +#pragma GCC diagnostic ignored "-Wdeprecated" +#endif +#endif + AssertException::~AssertException() throw() {} +#ifdef __clang__ +#pragma GCC diagnostic pop +#endif + int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); diff --git a/test/unittest/unittest.h b/test/unittest/unittest.h index 6062410..60e6c18 100644 --- a/test/unittest/unittest.h +++ b/test/unittest/unittest.h @@ -99,12 +99,24 @@ inline FILE* TempFile(char *filename) { #pragma warning(disable : 4127) #endif +#ifdef __clang__ +#pragma GCC diagnostic push +#if __has_warning("-Wdeprecated") +#pragma GCC diagnostic ignored "-Wdeprecated" +#endif +#endif + class AssertException : public std::logic_error { public: AssertException(const char* w) : std::logic_error(w) {} + AssertException(const AssertException& rhs) : std::logic_error(rhs) {} virtual ~AssertException() throw(); }; +#ifdef __clang__ +#pragma GCC diagnostic pop +#endif + #define RAPIDJSON_ASSERT(x) if (!(x)) throw AssertException(RAPIDJSON_STRINGIFY(x)) class Random { diff --git a/test/unittest/valuetest.cpp b/test/unittest/valuetest.cpp index 245ccac..b2963fc 100644 --- a/test/unittest/valuetest.cpp +++ b/test/unittest/valuetest.cpp @@ -16,6 +16,11 @@ #include "rapidjson/document.h" #include +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + using namespace rapidjson; TEST(Value, DefaultConstructor) { @@ -764,15 +769,15 @@ TEST(Value, Array) { #if RAPIDJSON_HAS_CXX11_RVALUE_REFS // PushBack(GenericValue&&, Allocator&); { - Value y(kArrayType); - y.PushBack(Value(true), allocator); - y.PushBack(std::move(Value(kArrayType).PushBack(Value(1), allocator).PushBack("foo", allocator)), allocator); - EXPECT_EQ(2u, y.Size()); - EXPECT_TRUE(y[0].IsTrue()); - EXPECT_TRUE(y[1].IsArray()); - EXPECT_EQ(2u, y[1].Size()); - EXPECT_TRUE(y[1][0].IsInt()); - EXPECT_TRUE(y[1][1].IsString()); + Value y2(kArrayType); + y2.PushBack(Value(true), allocator); + y2.PushBack(std::move(Value(kArrayType).PushBack(Value(1), allocator).PushBack("foo", allocator)), allocator); + EXPECT_EQ(2u, y2.Size()); + EXPECT_TRUE(y2[0].IsTrue()); + EXPECT_TRUE(y2[1].IsArray()); + EXPECT_EQ(2u, y2[1].Size()); + EXPECT_TRUE(y2[1][0].IsInt()); + EXPECT_TRUE(y2[1][1].IsString()); } #endif @@ -1354,3 +1359,27 @@ TEST(Value, AcceptTerminationByHandler) { TEST_TERMINATION(11, "{\"a\":[]}"); TEST_TERMINATION(12, "{\"a\":[]}"); } + +struct ValueIntComparer { + bool operator()(const Value& lhs, const Value& rhs) const { + return lhs.GetInt() < rhs.GetInt(); + } +}; + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS +TEST(Value, Sorting) { + Value::AllocatorType allocator; + Value a(kArrayType); + a.PushBack(5, allocator); + a.PushBack(1, allocator); + a.PushBack(3, allocator); + std::sort(a.Begin(), a.End(), ValueIntComparer()); + EXPECT_EQ(1, a[0].GetInt()); + EXPECT_EQ(3, a[1].GetInt()); + EXPECT_EQ(5, a[2].GetInt()); +} +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif