From 74b51950894ee361e456fcd2b8b411fe2bb75b08 Mon Sep 17 00:00:00 2001 From: Saman <100295082+enum-class@users.noreply.github.com> Date: Fri, 6 Jan 2023 12:11:11 +0800 Subject: [PATCH] Fix operator==() generated for field of fixed sized array (#7749) * Fix operator==() generated for field of fixed sized array * Compare address * noexcept * Grammer Co-authored-by: Derek Bailey --- include/flatbuffers/array.h | 10 ++++ src/idl_gen_cpp.cpp | 3 +- tests/arrays_test_generated.h | 12 ++--- tests/key_field/key_field_sample_generated.h | 4 +- tests/test.cpp | 49 ++++++++++++++++++++ 5 files changed, 69 insertions(+), 9 deletions(-) diff --git a/include/flatbuffers/array.h b/include/flatbuffers/array.h index ec34deea5..2ff58c6fb 100644 --- a/include/flatbuffers/array.h +++ b/include/flatbuffers/array.h @@ -17,6 +17,8 @@ #ifndef FLATBUFFERS_ARRAY_H_ #define FLATBUFFERS_ARRAY_H_ +#include + #include "flatbuffers/base.h" #include "flatbuffers/stl_emulation.h" #include "flatbuffers/vector.h" @@ -238,6 +240,14 @@ const Array &CastToArrayOfEnum(const T (&arr)[length]) { return *reinterpret_cast *>(arr); } +template +bool operator==(const Array &lhs, + const Array &rhs) noexcept { + return std::addressof(lhs) == std::addressof(rhs) || + (lhs.size() == rhs.size() && + std::memcmp(lhs.Data(), rhs.Data(), rhs.size() * sizeof(T)) == 0); +} + } // namespace flatbuffers #endif // FLATBUFFERS_ARRAY_H_ diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index 5b9e181eb..4f6236fbc 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -2044,7 +2044,6 @@ class CppGenerator : public BaseGenerator { const auto accessor = Name(field) + accessSuffix; const auto lhs_accessor = "lhs." + accessor; const auto rhs_accessor = "rhs." + accessor; - if (!field.deprecated && // Deprecated fields won't be accessible. field.value.type.base_type != BASE_TYPE_UTYPE && (field.value.type.base_type != BASE_TYPE_VECTOR || @@ -2067,6 +2066,8 @@ class CppGenerator : public BaseGenerator { " const &b) { return (a == b) || (a && b && *a == *b); })"; compare_op += "(" + equal_length + " && " + elements_equal + ")"; + } else if (field.value.type.base_type == BASE_TYPE_ARRAY) { + compare_op += "(*" + lhs_accessor + " == *" + rhs_accessor + ")"; } else { compare_op += "(" + lhs_accessor + " == " + rhs_accessor + ")"; } diff --git a/tests/arrays_test_generated.h b/tests/arrays_test_generated.h index cbe838996..147d16fe9 100644 --- a/tests/arrays_test_generated.h +++ b/tests/arrays_test_generated.h @@ -141,10 +141,10 @@ FLATBUFFERS_STRUCT_END(NestedStruct, 32); inline bool operator==(const NestedStruct &lhs, const NestedStruct &rhs) { return - (lhs.a() == rhs.a()) && + (*lhs.a() == *rhs.a()) && (lhs.b() == rhs.b()) && - (lhs.c() == rhs.c()) && - (lhs.d() == rhs.d()); + (*lhs.c() == *rhs.c()) && + (*lhs.d() == *rhs.d()); } inline bool operator!=(const NestedStruct &lhs, const NestedStruct &rhs) { @@ -257,11 +257,11 @@ FLATBUFFERS_STRUCT_END(ArrayStruct, 160); inline bool operator==(const ArrayStruct &lhs, const ArrayStruct &rhs) { return (lhs.a() == rhs.a()) && - (lhs.b() == rhs.b()) && + (*lhs.b() == *rhs.b()) && (lhs.c() == rhs.c()) && - (lhs.d() == rhs.d()) && + (*lhs.d() == *rhs.d()) && (lhs.e() == rhs.e()) && - (lhs.f() == rhs.f()); + (*lhs.f() == *rhs.f()); } inline bool operator!=(const ArrayStruct &lhs, const ArrayStruct &rhs) { diff --git a/tests/key_field/key_field_sample_generated.h b/tests/key_field/key_field_sample_generated.h index 31cc40016..d4574ce5d 100644 --- a/tests/key_field/key_field_sample_generated.h +++ b/tests/key_field/key_field_sample_generated.h @@ -88,7 +88,7 @@ FLATBUFFERS_STRUCT_END(Baz, 5); inline bool operator==(const Baz &lhs, const Baz &rhs) { return - (lhs.a() == rhs.a()) && + (*lhs.a() == *rhs.a()) && (lhs.b() == rhs.b()); } @@ -161,7 +161,7 @@ FLATBUFFERS_STRUCT_END(Bar, 16); inline bool operator==(const Bar &lhs, const Bar &rhs) { return - (lhs.a() == rhs.a()) && + (*lhs.a() == *rhs.a()) && (lhs.b() == rhs.b()); } diff --git a/tests/test.cpp b/tests/test.cpp index e13bc6ee2..0ad755a32 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -829,6 +829,54 @@ void FixedLengthArrayConstructorTest() { void FixedLengthArrayConstructorTest() {} #endif +void FixedLengthArrayOperatorEqualTest() { + const int32_t nested_a[2] = { 1, 2 }; + MyGame::Example::TestEnum nested_c[2] = { MyGame::Example::TestEnum::A, + MyGame::Example::TestEnum::B }; + + MyGame::Example::TestEnum nested_cc[2] = { MyGame::Example::TestEnum::A, + MyGame::Example::TestEnum::C }; + const int64_t int64_2[2] = { -2, -1 }; + + std::array init_d = { + { MyGame::Example::NestedStruct(nested_a, MyGame::Example::TestEnum::B, + nested_c, int64_2), + MyGame::Example::NestedStruct(nested_a, MyGame::Example::TestEnum::B, + nested_c, + std::array{ { -2, -1 } }) } + }; + + auto different = MyGame::Example::NestedStruct( + nested_a, MyGame::Example::TestEnum::B, nested_cc, + std::array{ { -2, -1 } }); + + TEST_ASSERT(init_d[0] == init_d[1]); + TEST_ASSERT(init_d[0] != different); + + std::array arr_struct = { + MyGame::Example::ArrayStruct( + 8.125, + std::array{ + { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } }, + -17, init_d, 10, int64_2), + + MyGame::Example::ArrayStruct( + 8.125, + std::array{ + { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } }, + -17, init_d, 10, int64_2), + + MyGame::Example::ArrayStruct( + 8.125, + std::array{ + { 1000, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } }, + -17, init_d, 10, int64_2) + }; + + TEST_ASSERT(arr_struct[0] == arr_struct[1]); + TEST_ASSERT(arr_struct[1] != arr_struct[2]); +} + void NativeTypeTest() { const int N = 3; @@ -1560,6 +1608,7 @@ int FlatBufferTests(const std::string &tests_data_path) { ParseFlexbuffersFromJsonWithNullTest(); FlatbuffersSpanTest(); FixedLengthArrayConstructorTest(); + FixedLengthArrayOperatorEqualTest(); FieldIdentifierTest(); StringVectorDefaultsTest(); FlexBuffersFloatingPointTest();