From 4e7c56907182993644a5dbd6c99bcac7c141387d Mon Sep 17 00:00:00 2001 From: antonio2368 Date: Tue, 17 Nov 2020 10:07:31 +0100 Subject: [PATCH] Migrate code to C++20 (#44) --- .clang-format | 1 + CMakeLists.txt | 2 +- libs/setup.sh | 2 +- .../frontend/ast/cypher_main_visitor.cpp | 12 +++- .../frontend/stripped_lexer_constants.hpp | 70 ++++++++++++++----- src/utils/small_vector.hpp | 29 ++++---- tests/benchmark/query/execution.cpp | 13 +++- tests/benchmark/skip_list_vs_stl.cpp | 4 +- tests/integration/audit/tester.cpp | 3 + tests/mgbench/client.cpp | 1 + tests/unit/cypher_main_visitor.cpp | 24 +++++-- tests/unit/query_procedure_mgp_module.cpp | 7 +- tests/unit/skip_list.cpp | 5 +- tests/unit/stripped.cpp | 16 +++-- tests/unit/utils_memory.cpp | 13 ++-- 15 files changed, 148 insertions(+), 54 deletions(-) diff --git a/.clang-format b/.clang-format index da20b3084..9a4a1f6f1 100644 --- a/.clang-format +++ b/.clang-format @@ -6,4 +6,5 @@ UseTab: Never DerivePointerAlignment: false PointerAlignment: Right ColumnLimit : 80 +IncludeBlocks: Preserve ... diff --git a/CMakeLists.txt b/CMakeLists.txt index a3d6f0649..7864887b4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -149,7 +149,7 @@ add_custom_target(clean_all # is easier debugging of compilation and linker flags. set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) # c99-designator is disabled because of required mixture of designated and # non-designated initializers in Python Query Module code (`py_module.cpp`). diff --git a/libs/setup.sh b/libs/setup.sh index b02f73477..adaccedd1 100755 --- a/libs/setup.sh +++ b/libs/setup.sh @@ -100,7 +100,7 @@ rm neo4j.tar.gz # We use head on Sep 1, 2017 instead of last release since it was long time ago. mkdir -p json cd json -wget "https://raw.githubusercontent.com/nlohmann/json/91e003285312167ad8365f387438ea371b465a7e/src/json.hpp" +wget "https://raw.githubusercontent.com/nlohmann/json/b3e5cb7f20dcc5c806e418df34324eca60d17d4e/single_include/nlohmann/json.hpp" cd .. bzip2_tag="0405487e2b1de738e7f1c8afb50d19cf44e8d580" # v1.0.6 (May 26, 2011) diff --git a/src/query/frontend/ast/cypher_main_visitor.cpp b/src/query/frontend/ast/cypher_main_visitor.cpp index f4462a664..499b3a7ac 100644 --- a/src/query/frontend/ast/cypher_main_visitor.cpp +++ b/src/query/frontend/ast/cypher_main_visitor.cpp @@ -1,3 +1,14 @@ +////////////////////////////////////////////////////// +// THIS INCLUDE SHOULD ALWAYS COME BEFORE THE +// "cypher_main_visitor.hpp" +// "module.hpp" includes json.hpp which uses libc's +// EOF macro while "cypher_main_visitor.hpp" includes +// "antlr4-runtime.h" which contains a static variable +// of the same name, EOF. +// This hides the definition of the macro which causes +// the compilation to fail. +#include "query/procedure/module.hpp" +////////////////////////////////////////////////////// #include "query/frontend/ast/cypher_main_visitor.hpp" #include @@ -16,7 +27,6 @@ #include "query/exceptions.hpp" #include "query/frontend/parsing.hpp" #include "query/interpret/awesome_memgraph_functions.hpp" -#include "query/procedure/module.hpp" #include "utils/exceptions.hpp" #include "utils/string.hpp" diff --git a/src/query/frontend/stripped_lexer_constants.hpp b/src/query/frontend/stripped_lexer_constants.hpp index 5a85de853..4d5ada255 100644 --- a/src/query/frontend/stripped_lexer_constants.hpp +++ b/src/query/frontend/stripped_lexer_constants.hpp @@ -16,9 +16,9 @@ namespace trie { // StrippedQuery is not degraded by the change. Also there are no tests that // directly test this class, but there are tests that test StrippedQuery. -namespace { -int Noop(int x) { return x; } -}; +namespace detail { +inline int Noop(int x) { return x; } +}; // namespace detail class Trie { public: @@ -47,7 +47,7 @@ class Trie { nodes_[node_id].finish = true; } - template + template int Match(const char *s) const { int node_id = kRootIndex; int longest_found_len = 0; @@ -72,7 +72,7 @@ class Trie { const static int kRootIndex = 0; std::vector nodes_{1}; }; -} +} // namespace trie // All word constants should be lowercase in this file. @@ -2759,14 +2759,52 @@ const std::bitset kSpaceParts(std::string( "00000000000000000000000000000000000000000000000000000000000000000000000000" "0000000000000111110000000000000011111000000000")); -const trie::Trie kSpecialTokens = { - ";", ",", "=", "+=", "*", "(", - ")", "[", "]", ":", "|", "..", - "+", "-", "/", "%", "^", "=~", - "<>", "!=", "<", ">", "<=", ">=", - ".", "{", "}", "$", u8"\u27e8", u8"\u3008", - u8"\ufe64", u8"\uff1c", u8"\u27e9", u8"\u3009", u8"\ufe65", u8"\uff1e", - u8"\u00ad", u8"\u2010", u8"\u2011", u8"\u2012", u8"\u2013", u8"\u2014", - u8"\u2015", u8"\u2212", u8"\ufe58", u8"\ufe63", u8"\uff0d"}; -} -} +const trie::Trie kSpecialTokens = {";", + ",", + "=", + "+=", + "*", + "(", + ")", + "[", + "]", + ":", + "|", + "..", + "+", + "-", + "/", + "%", + "^", + "=~", + "<>", + "!=", + "<", + ">", + "<=", + ">=", + ".", + "{", + "}", + "$", + "\xE2\x9F\xA8", // u8"\u27e8" + "\xE3\x80\x88", // u8"\u3008" + "\xEF\xB9\xA4", // u8"\ufe64" + "\xEF\xBC\x9C", // u8"\uff1c" + "\xE2\x9F\xA9", // u8"\u27e9" + "\xE3\x80\x89", // u8"\u3009" + "\xEF\xB9\xA5", // u8"\ufe65" + "\xEF\xBC\x9E", // u8"\uff1e" + "\xC2\xAD", // u8"\u00ad" + "\xE2\x80\x90", // u8"\u2010" + "\xE2\x80\x91", // u8"\u2011" + "\xE2\x80\x92", // u8"\u2012" + "\xE2\x80\x93", // u8"\u2013" + "\xE2\x80\x94", // u8"\u2014" + "\xE2\x80\x95", // u8"\u2015" + "\xE2\x88\x92", // u8"\u2212" + "\xEF\xB9\x98", // u8"\ufe58" + "\xEF\xB9\xA3", // u8"\ufe63" + "\xEF\xBC\x8D"}; // u8"\uff0d" +} // namespace lexer_constants +} // namespace query diff --git a/src/utils/small_vector.hpp b/src/utils/small_vector.hpp index eac685df7..ffec76c84 100644 --- a/src/utils/small_vector.hpp +++ b/src/utils/small_vector.hpp @@ -20,6 +20,7 @@ #include #include #include +#include #include "utils/likely.hpp" @@ -52,8 +53,8 @@ inline uint64_t NextPowerOf2(uint64_t a) { a |= (a >> 32); return a + 1; } -} -} +} // namespace detail +} // namespace utils namespace utils { @@ -307,10 +308,8 @@ class SmallVectorTemplateBase : public SmallVectorTemplateCommon { /// Copy the range [i, e) onto the uninitialized memory /// starting with "dest", constructing elements into it as needed. template - static void UninitializedCopy( - T1 *i, T1 *e, T2 *dest, - typename std::enable_if::type, - T2>::value>::type * = nullptr) { + requires std::is_same_v, T2> static void + UninitializedCopy(T1 *i, T1 *e, T2 *dest) { // Use memcpy for PODs iterated by pointers (which includes SmallVector // iterators): std::uninitialized_copy optimizes to memmove, but we can // use memcpy here. Note that i and e are iterators and thus might be @@ -334,12 +333,14 @@ class SmallVectorTemplateBase : public SmallVectorTemplateCommon { void pop_back() { this->SetEnd(this->end() - 1); } }; +template +constexpr bool is_pod = std::is_standard_layout_v &&std::is_trivial_v; + /// This class consists of common code factored out of the SmallVector class to /// reduce code duplication based on the SmallVector 'n' template parameter. template -class SmallVectorImpl - : public SmallVectorTemplateBase::value> { - typedef SmallVectorTemplateBase::value> SuperClass; +class SmallVectorImpl : public SmallVectorTemplateBase> { + typedef SmallVectorTemplateBase> SuperClass; SmallVectorImpl(const SmallVectorImpl &) = delete; @@ -351,7 +352,7 @@ class SmallVectorImpl protected: // Default ctor - Initialize to empty. explicit SmallVectorImpl(unsigned n) - : SmallVectorTemplateBase::value>(n * sizeof(T)) {} + : SmallVectorTemplateBase>(n * sizeof(T)) {} public: ~SmallVectorImpl() { @@ -644,7 +645,7 @@ class SmallVectorImpl } template - void emplace_back(TArgTypes &&... args) { + void emplace_back(TArgTypes &&...args) { if (UNLIKELY(this->end_x_ >= this->capacity_x_)) this->Grow(); ::new ((void *)this->end()) T(std::forward(args)...); this->SetEnd(this->end() + 1); @@ -906,7 +907,7 @@ static inline size_t capacity_in_bytes(const SmallVector &x) { return x.capacity_in_bytes(); } -} // End utils namespace +} // namespace utils namespace std { /// Implement std::swap in terms of SmallVector swap. @@ -921,7 +922,7 @@ template inline void swap(utils::SmallVector &lhs, utils::SmallVector &rhs) { lhs.swap(rhs); } -} +} // namespace std namespace utils { /// GrowPod - This is an implementation of the Grow() method which only works @@ -950,4 +951,4 @@ inline void SmallVectorBase::GrowPod(void *first_el, size_t min_size_in_bytes, this->begin_x_ = new_elts; this->capacity_x_ = (char *)this->begin_x_ + new_capacity_in_bytes; } -} +} // namespace utils diff --git a/tests/benchmark/query/execution.cpp b/tests/benchmark/query/execution.cpp index cc8942504..8bb1a9b5c 100644 --- a/tests/benchmark/query/execution.cpp +++ b/tests/benchmark/query/execution.cpp @@ -3,12 +3,23 @@ #include + +////////////////////////////////////////////////////// +// THIS INCLUDE SHOULD ALWAYS COME BEFORE THE +// OTHER INCLUDES +// "planner.hpp" includes json.hpp which uses libc's +// EOF macro while in the other includes +// is included which contains a static +// variable of the same name, EOF. +// This hides the definition of the macro which causes +// the compilation to fail. +#include "query/plan/planner.hpp" +////////////////////////////////////////////////////// #include "communication/result_stream_faker.hpp" #include "query/frontend/opencypher/parser.hpp" #include "query/frontend/semantic/required_privileges.hpp" #include "query/frontend/semantic/symbol_generator.hpp" #include "query/interpreter.hpp" -#include "query/plan/planner.hpp" #include "storage/v2/storage.hpp" // The following classes are wrappers for utils::MemoryResource, so that we can diff --git a/tests/benchmark/skip_list_vs_stl.cpp b/tests/benchmark/skip_list_vs_stl.cpp index 765fbfbe0..49caf5485 100644 --- a/tests/benchmark/skip_list_vs_stl.cpp +++ b/tests/benchmark/skip_list_vs_stl.cpp @@ -327,7 +327,7 @@ class StdMapWithPoolAllocatorInsertFixture : public benchmark::Fixture { 1024U /* max_block_size */, utils::NewDeleteResource()}; std::map, - utils::Allocator>> + utils::Allocator>> container{&memory_}; utils::SpinLock lock; }; @@ -440,7 +440,7 @@ class StdMapWithPoolAllocatorFindFixture : public benchmark::Fixture { 1024U /* max_block_size */, utils::NewDeleteResource()}; std::map, - utils::Allocator>> + utils::Allocator>> container{&memory_}; utils::SpinLock lock; }; diff --git a/tests/integration/audit/tester.cpp b/tests/integration/audit/tester.cpp index 33b0f80cf..0a05527c2 100644 --- a/tests/integration/audit/tester.cpp +++ b/tests/integration/audit/tester.cpp @@ -1,5 +1,6 @@ #include #include + #include #include "communication/bolt/client.hpp" @@ -54,6 +55,8 @@ communication::bolt::Value JsonToValue(const nlohmann::json &jv) { ret = map; break; } + case nlohmann::json::value_t::binary: + LOG(FATAL) << "Unexpected 'binary' type in json value!"; case nlohmann::json::value_t::discarded: LOG(FATAL) << "Unexpected 'discarded' type in json value!"; break; diff --git a/tests/mgbench/client.cpp b/tests/mgbench/client.cpp index c68de30f8..1a03bf430 100644 --- a/tests/mgbench/client.cpp +++ b/tests/mgbench/client.cpp @@ -91,6 +91,7 @@ communication::bolt::Value JsonToBoltValue(const nlohmann::json &data) { } return {std::move(map)}; } + case nlohmann::json::value_t::binary: case nlohmann::json::value_t::discarded: LOG(FATAL) << "Unexpected JSON type!"; } diff --git a/tests/unit/cypher_main_visitor.cpp b/tests/unit/cypher_main_visitor.cpp index 364e925ce..469e11b9f 100644 --- a/tests/unit/cypher_main_visitor.cpp +++ b/tests/unit/cypher_main_visitor.cpp @@ -5,6 +5,15 @@ #include #include +////////////////////////////////////////////////////// +// "json.hpp" should always come before "antrl4-runtime.h" +// "json.hpp" uses libc's EOF macro while +// "antrl4-runtime.h" contains a static variable of the +// same name, EOF. +// This hides the definition of the macro which causes +// the compilation to fail. +#include +////////////////////////////////////////////////////// #include #include #include @@ -456,8 +465,7 @@ TEST_P(CypherMainVisitorTest, NullLiteral) { auto *single_query = query->single_query_; auto *return_clause = dynamic_cast(single_query->clauses_[0]); ast_generator.CheckLiteral( - return_clause->body_.named_expressions[0]->expression_, TypedValue(), - 1); + return_clause->body_.named_expressions[0]->expression_, TypedValue(), 1); } TEST_P(CypherMainVisitorTest, ParenthesizedExpression) { @@ -909,7 +917,11 @@ TEST_P(CypherMainVisitorTest, StringLiteralEscapedUtf16) { auto *return_clause = dynamic_cast(single_query->clauses_[0]); ast_generator.CheckLiteral( return_clause->body_.named_expressions[0]->expression_, - u8"\u221daaa\u221daaa", 1); + "\xE2\x88\x9D" + "aaa" + "\xE2\x88\x9D" + "aaa", + 1); // u8"\u221daaa\u221daaa" } TEST_P(CypherMainVisitorTest, StringLiteralEscapedUtf16Error) { @@ -928,7 +940,11 @@ TEST_P(CypherMainVisitorTest, StringLiteralEscapedUtf32) { auto *return_clause = dynamic_cast(single_query->clauses_[0]); ast_generator.CheckLiteral( return_clause->body_.named_expressions[0]->expression_, - u8"\U0001F600aaaa\U0001F600aaaaaaaa", 1); + "\xF0\x9F\x98\x80" + "aaaa" + "\xF0\x9F\x98\x80" + "aaaaaaaa", + 1); // u8"\U0001F600aaaa\U0001F600aaaaaaaa" } TEST_P(CypherMainVisitorTest, DoubleLiteral) { diff --git a/tests/unit/query_procedure_mgp_module.cpp b/tests/unit/query_procedure_mgp_module.cpp index 3f93a9a02..2d9ab9f5a 100644 --- a/tests/unit/query_procedure_mgp_module.cpp +++ b/tests/unit/query_procedure_mgp_module.cpp @@ -12,10 +12,13 @@ TEST(Module, InvalidProcedureRegistration) { mgp_module module(utils::NewDeleteResource()); EXPECT_FALSE(mgp_module_add_read_procedure(&module, "dashes-not-supported", DummyCallback)); + // as u8string this is u8"unicode\u22c6not\u2014supported" EXPECT_FALSE(mgp_module_add_read_procedure( - &module, u8"unicode\u22c6not\u2014supported", DummyCallback)); + &module, "unicode\xE2\x8B\x86not\xE2\x80\x94supported", DummyCallback)); + // as u8string this is u8"`backticks⋆\u22c6won't-save\u2014you`" EXPECT_FALSE(mgp_module_add_read_procedure( - &module, u8"`backticks⋆\u22c6won't-save\u2014you`", DummyCallback)); + &module, "`backticks⋆\xE2\x8B\x86won't-save\xE2\x80\x94you`", + DummyCallback)); EXPECT_FALSE(mgp_module_add_read_procedure( &module, "42_name_must_not_start_with_number", DummyCallback)); EXPECT_FALSE(mgp_module_add_read_procedure(&module, "div/", DummyCallback)); diff --git a/tests/unit/skip_list.cpp b/tests/unit/skip_list.cpp index 00e1b215c..7d6efe0b8 100644 --- a/tests/unit/skip_list.cpp +++ b/tests/unit/skip_list.cpp @@ -1,9 +1,8 @@ #include -#include - #include #include +#include #include "utils/skip_list.hpp" #include "utils/timer.hpp" @@ -198,6 +197,8 @@ struct OnlyCopyable { OnlyCopyable(const OnlyCopyable &) = default; OnlyCopyable &operator=(OnlyCopyable &&) = delete; OnlyCopyable &operator=(const OnlyCopyable &) = default; + + OnlyCopyable(const uint64_t val) : value{val} {} uint64_t value; }; diff --git a/tests/unit/stripped.cpp b/tests/unit/stripped.cpp index 3ada5b941..f3bb739d6 100644 --- a/tests/unit/stripped.cpp +++ b/tests/unit/stripped.cpp @@ -5,6 +5,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" + #include "query/exceptions.hpp" #include "query/frontend/stripped.hpp" #include "query/typed_value.hpp" @@ -132,7 +133,8 @@ TEST(QueryStripper, StringLiteral3) { TEST(QueryStripper, StringLiteral4) { StrippedQuery stripped("RETURN '\\u1Aa4'"); EXPECT_EQ(stripped.literals().size(), 1); - EXPECT_EQ(stripped.literals().At(0).second.ValueString(), u8"\u1Aa4"); + EXPECT_EQ(stripped.literals().At(0).second.ValueString(), + "\xE1\xAA\xA4"); // "u8"\u1Aa4 EXPECT_EQ(stripped.query(), "RETURN " + kStrippedStringToken); } @@ -147,7 +149,8 @@ TEST(QueryStripper, LowSurrogateAlone) { TEST(QueryStripper, Surrogates) { StrippedQuery stripped("RETURN '\\ud83d\\udeeb'"); EXPECT_EQ(stripped.literals().size(), 1); - EXPECT_EQ(stripped.literals().At(0).second.ValueString(), u8"\U0001f6eb"); + EXPECT_EQ(stripped.literals().At(0).second.ValueString(), + "\xF0\x9F\x9B\xAB"); // u8"\U0001f6eb" EXPECT_EQ(stripped.query(), "RETURN " + kStrippedStringToken); } @@ -211,9 +214,11 @@ TEST(QueryStripper, UnescapedName) { } TEST(QueryStripper, UnescapedName2) { - StrippedQuery stripped(u8"MATCH (n:\uffd5\u04c2\u04c2pero\u0078pe)"); + // using u8string this string is u8"\uffd5\u04c2\u04c2pero\u0078pe" + StrippedQuery stripped("MATCH (n:\xEF\xBF\x95\xD3\x82\xD3\x82pero\x78pe)"); EXPECT_EQ(stripped.literals().size(), 0); - EXPECT_EQ(stripped.query(), u8"MATCH ( n : \uffd5\u04c2\u04c2pero\u0078pe )"); + EXPECT_EQ(stripped.query(), + "MATCH ( n : \xEF\xBF\x95\xD3\x82\xD3\x82pero\x78pe )"); } TEST(QueryStripper, MixedCaseKeyword) { @@ -268,7 +273,8 @@ TEST(QueryStripper, LineComment5) { } TEST(QueryStripper, Spaces) { - StrippedQuery stripped(u8"RETURN \r\n\u202f\t\u2007 NuLl"); + // using u8string this string is u8"\u202f" + StrippedQuery stripped("RETURN \r\n\xE2\x80\xAF\t\xE2\x80\x87 NuLl"); EXPECT_EQ(stripped.literals().size(), 0); EXPECT_EQ(stripped.query(), "RETURN NuLl"); } diff --git a/tests/unit/utils_memory.cpp b/tests/unit/utils_memory.cpp index 89544fd1b..e53ecffac 100644 --- a/tests/unit/utils_memory.cpp +++ b/tests/unit/utils_memory.cpp @@ -359,7 +359,8 @@ TEST(MonotonicBufferResource, ResetGrowthFactor) { mem.Release(); mem.Allocate(stack_data_size + 1); ASSERT_EQ(test_mem.allocated_sizes_.size(), 2); - ASSERT_EQ(test_mem.allocated_sizes_.front(), test_mem.allocated_sizes_.back()); + ASSERT_EQ(test_mem.allocated_sizes_.front(), + test_mem.allocated_sizes_.back()); } // NOLINTNEXTLINE(hicpp-special-member-functions) @@ -423,8 +424,9 @@ TYPED_TEST(AllocatorTest, PropagatesToStdUsesAllocator) { TYPED_TEST(AllocatorTest, PropagatesToStdPairUsesAllocator) { { - std::vector, - utils::Allocator> + std::vector< + std::pair, + utils::Allocator>> vec(utils::NewDeleteResource()); vec.emplace_back(1, 2); const auto &pair = vec.front(); @@ -434,8 +436,9 @@ TYPED_TEST(AllocatorTest, PropagatesToStdPairUsesAllocator) { EXPECT_EQ(pair.second.memory_, utils::NewDeleteResource()); } { - std::vector, - utils::Allocator> + std::vector< + std::pair, + utils::Allocator>> vec(utils::NewDeleteResource()); vec.emplace_back(1, 2); const auto &pair = vec.front();