diff --git a/arcanist/linter/CppVoidParameterLinter.php b/arcanist/linter/CppVoidParameterLinter.php --- a/arcanist/linter/CppVoidParameterLinter.php +++ b/arcanist/linter/CppVoidParameterLinter.php @@ -6,6 +6,10 @@ */ final class CppVoidParameterLinter extends ArcanistLinter { + const FALSE_POSITIVES = array( + "typeid(void)", + ); + const VOID_PARAMETER_FOUND = 1; public function getInfoName() { @@ -36,6 +40,15 @@ ); } + private function isFalsePositive($line) { + foreach(self::FALSE_POSITIVES as $falsePositive) { + if (strpos($line, $falsePositive) !== false) { + return true; + } + } + return false; + } + public function lintPath($path) { $absPath = Filesystem::resolvePath($path, $this->getProjectRoot()); $fileContent = Filesystem::readFile($absPath); @@ -44,6 +57,11 @@ PREG_OFFSET_CAPTURE)) { foreach ($voidParameters[0] as $voidParameter) { list($function, $offset) = $voidParameter; + + if ($this->isFalsePositive($function)) { + continue; + } + $this->raiseLintAtOffset( $offset, self::VOID_PARAMETER_FOUND, diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -150,6 +150,7 @@ raii_event_tests.cpp random_tests.cpp rcu_tests.cpp + ref_tests.cpp reverselock_tests.cpp rpc_tests.cpp rpc_server_tests.cpp diff --git a/src/test/ref_tests.cpp b/src/test/ref_tests.cpp new file mode 100644 --- /dev/null +++ b/src/test/ref_tests.cpp @@ -0,0 +1,32 @@ +// Copyright (c) 2020 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include + +BOOST_AUTO_TEST_SUITE(ref_tests) + +BOOST_AUTO_TEST_CASE(ref_test) { + util::Ref ref; + BOOST_CHECK(!ref.Has()); + BOOST_CHECK_THROW(ref.Get(), NonFatalCheckError); + int value = 5; + ref.Set(value); + BOOST_CHECK(ref.Has()); + BOOST_CHECK_EQUAL(ref.Get(), 5); + ++ref.Get(); + BOOST_CHECK_EQUAL(ref.Get(), 6); + BOOST_CHECK_EQUAL(value, 6); + ++value; + BOOST_CHECK_EQUAL(value, 7); + BOOST_CHECK_EQUAL(ref.Get(), 7); + BOOST_CHECK(!ref.Has()); + BOOST_CHECK_THROW(ref.Get(), NonFatalCheckError); + ref.Clear(); + BOOST_CHECK(!ref.Has()); + BOOST_CHECK_THROW(ref.Get(), NonFatalCheckError); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/util/check.h b/src/util/check.h --- a/src/util/check.h +++ b/src/util/check.h @@ -5,6 +5,10 @@ #ifndef BITCOIN_UTIL_CHECK_H #define BITCOIN_UTIL_CHECK_H +#if defined(HAVE_CONFIG_H) +#include +#endif + #include #include diff --git a/src/util/ref.h b/src/util/ref.h new file mode 100644 --- /dev/null +++ b/src/util/ref.h @@ -0,0 +1,48 @@ +// Copyright (c) 2020 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_UTIL_REF_H +#define BITCOIN_UTIL_REF_H + +#include + +#include + +namespace util { + +/** + * Type-safe dynamic reference. + * + * This implements a small subset of the functionality in C++17's std::any + * class, and can be dropped when the project updates to C++17 + * (https://github.com/bitcoin/bitcoin/issues/16684) + */ +class Ref { +public: + Ref() = default; + template Ref(T &value) { Set(value); } + template T &Get() const { + CHECK_NONFATAL(Has()); + return *static_cast(m_value); + } + template void Set(T &value) { + m_value = &value; + m_type = std::type_index(typeid(T)); + } + template bool Has() const { + return m_value && m_type == std::type_index(typeid(T)); + } + void Clear() { + m_value = nullptr; + m_type = std::type_index(typeid(void)); + } + +private: + void *m_value = nullptr; + std::type_index m_type = std::type_index(typeid(void)); +}; + +} // namespace util + +#endif // BITCOIN_UTIL_REF_H