diff --git a/CHANGELOG.md b/CHANGELOG.md index 481b2ed..d1acce5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,13 @@ [#263](https://github.com/ethereum/evmc/pull/263)] The `vmtester` tool now builds with MSVC with `/std:c++17`. +## [6.2.2] - 2019-05-16 + +- Fixed: [[#281](https://github.com/ethereum/evmc/pull/281)] + Compilation error of `evmc::result::raw()` in Visual Studio fixed. +- Fixed: [[#282](https://github.com/ethereum/evmc/pull/282)] + The `evmc::result`'s move assignment operator fixed. + ## [6.2.1] - 2019-04-29 - Fixed: @@ -159,6 +166,7 @@ [6.3.0]: https://github.com/ethereum/evmc/compare/v6.2.1...master +[6.2.2]: https://github.com/ethereum/evmc/releases/tag/v6.2.2 [6.2.1]: https://github.com/ethereum/evmc/releases/tag/v6.2.1 [6.2.0]: https://github.com/ethereum/evmc/releases/tag/v6.2.0 [6.1.1]: https://github.com/ethereum/evmc/releases/tag/v6.1.1 diff --git a/include/evmc/evmc.hpp b/include/evmc/evmc.hpp index fc1f738..d460266 100644 --- a/include/evmc/evmc.hpp +++ b/include/evmc/evmc.hpp @@ -39,16 +39,20 @@ public: /// Move constructor. result(result&& other) noexcept : evmc_result{other} { - // Disable releaser of the rvalue object. - other.release = nullptr; + other.release = nullptr; // Disable releasing of the rvalue object. } - result(result const&) = delete; - - /// Move-and-swap assignment operator. - result& operator=(result other) noexcept + /// Move assignment operator. + /// + /// The self-assigment MUST never happen. + /// + /// @param other The other result object. + /// @return The reference to the left-hand side object. + result& operator=(result&& other) noexcept { - std::swap(*this, other); + this->~result(); // Release this object. + static_cast(*this) = other; // Copy data. + other.release = nullptr; // Disable releasing of the rvalue object. return *this; } @@ -56,8 +60,8 @@ public: /// releases the ownership of the resources and invalidates this object. evmc_result raw() noexcept { - auto out = evmc_result{}; - std::swap(out, *this); + const auto out = evmc_result{*this}; // Copy data. + this->release = nullptr; // Disable releasing of this object. return out; } }; diff --git a/test/unittests/test_cpp.cpp b/test/unittests/test_cpp.cpp index 9f7c525..cb813f5 100644 --- a/test/unittests/test_cpp.cpp +++ b/test/unittests/test_cpp.cpp @@ -2,6 +2,10 @@ // Copyright 2018-2019 The EVMC Authors. // Licensed under the Apache License, Version 2.0. +// The vector is not used here, but including it was causing compilation issues +// previously related to using explicit template argument (SFINAE disabled). +#include + #include "../../examples/example_host.h" #include "../../examples/example_vm.h" @@ -120,3 +124,77 @@ TEST(cpp, host_call) example_host_destroy_context(host_context); } + +TEST(cpp, result_raii) +{ + static auto release_called = 0; + release_called = 0; + auto release_fn = [](const evmc_result*) noexcept { ++release_called; }; + + { + auto raw_result = evmc_result{}; + raw_result.status_code = EVMC_INTERNAL_ERROR; + raw_result.release = release_fn; + + auto raii_result = evmc::result{raw_result}; + EXPECT_EQ(raii_result.status_code, EVMC_INTERNAL_ERROR); + EXPECT_EQ(raii_result.gas_left, 0); + raii_result.gas_left = -1; + + auto raw_result2 = raii_result.raw(); + EXPECT_EQ(raw_result2.status_code, EVMC_INTERNAL_ERROR); + EXPECT_EQ(raw_result.status_code, EVMC_INTERNAL_ERROR); + EXPECT_EQ(raw_result2.gas_left, -1); + EXPECT_EQ(raw_result.gas_left, 0); + EXPECT_EQ(raw_result2.release, release_fn); + EXPECT_EQ(raw_result.release, release_fn); + } + EXPECT_EQ(release_called, 0); + + { + auto raw_result = evmc_result{}; + raw_result.status_code = EVMC_INTERNAL_ERROR; + raw_result.release = release_fn; + + auto raii_result = evmc::result{raw_result}; + EXPECT_EQ(raii_result.status_code, EVMC_INTERNAL_ERROR); + } + EXPECT_EQ(release_called, 1); +} + +TEST(cpp, result_move) +{ + static auto release_called = 0; + auto release_fn = [](const evmc_result*) noexcept { ++release_called; }; + + release_called = 0; + { + auto raw = evmc_result{}; + raw.gas_left = -1; + raw.release = release_fn; + + auto r0 = evmc::result{raw}; + EXPECT_EQ(r0.gas_left, raw.gas_left); + + auto r1 = std::move(r0); + EXPECT_EQ(r1.gas_left, raw.gas_left); + } + EXPECT_EQ(release_called, 1); + + release_called = 0; + { + auto raw1 = evmc_result{}; + raw1.gas_left = 1; + raw1.release = release_fn; + + auto raw2 = evmc_result{}; + raw2.gas_left = 1; + raw2.release = release_fn; + + auto r1 = evmc::result{raw1}; + auto r2 = evmc::result{raw2}; + + r2 = std::move(r1); + } + EXPECT_EQ(release_called, 2); +}