diff --git a/.arclint b/.arclint --- a/.arclint +++ b/.arclint @@ -94,6 +94,14 @@ "exclude": [ "(^src/(secp256k1|univalue|leveldb)/)" ] + }, + "lint-include-guard": { + "type": "lint-include-guard", + "include": "(^src/.*\\.h$)", + "exclude": [ + "(^src/(crypto/ctaes|secp256k1|univalue|leveldb)/)", + "(^src/tinyformat.h$)" + ] } } } diff --git a/arcanist/.phutil_module_cache b/arcanist/.phutil_module_cache --- a/arcanist/.phutil_module_cache +++ b/arcanist/.phutil_module_cache @@ -1 +1 @@ -{"__symbol_cache_version__":11,"2809b09d2021203b43c57da33d1fe8bf":{"have":{"class":{"AssertWithSideEffectsLinter":210}},"need":{"function":{"pht":439},"class":{"ArcanistLinter":246,"ArcanistLintSeverity":926,"Filesystem":1170}},"xmap":{"AssertWithSideEffectsLinter":["ArcanistLinter"]}},"90a8b110dc475955f15bb81d37268cb5":{"have":{"class":{"AutoPEP8FormatLinter":75}},"need":{"function":{"pht":297,"execx":769,"id":1903},"class":{"ArcanistExternalLinter":104,"ArcanistLintMessage":1910,"Filesystem":1754,"ArcanistLinter":2017,"ArcanistLintSeverity":2095}},"xmap":{"AutoPEP8FormatLinter":["ArcanistExternalLinter"]}},"38f0c676bff5192a344464142caaa253":{"have":{"class":{"CHeaderLinter":99}},"need":{"function":{"pht":611},"class":{"ArcanistLinter":121,"ArcanistLintSeverity":1060,"Filesystem":1307}},"xmap":{"CHeaderLinter":["ArcanistLinter"]}},"a30e4e25376ca05d4ae719915441be9e":{"have":{"class":{"CheckDocLinter":106}},"need":{"function":{"pht":323,"id":1848},"class":{"ArcanistExternalLinter":129,"ArcanistLintMessage":1855,"Filesystem":731,"ArcanistLinter":1903,"ArcanistLintSeverity":1989}},"xmap":{"CheckDocLinter":["ArcanistExternalLinter"]}},"6af7410cfea496ff1d4dcc2624b6b8ea":{"have":{"class":{"ClangFormatLinter":79}},"need":{"function":{"pht":302,"execx":781,"id":1653},"class":{"ArcanistExternalLinter":105,"ArcanistLintMessage":1660,"Filesystem":1504,"ArcanistLinter":1767,"ArcanistLintSeverity":1845}},"xmap":{"ClangFormatLinter":["ArcanistExternalLinter"]}},"9285ad9415f8ebe564f7119e5a72c559":{"have":{"class":{"FormatStringLinter":146}},"need":{"function":{"pht":377,"csprintf":1492,"id":1872},"class":{"ArcanistExternalLinter":173,"ArcanistLintMessage":1879,"Filesystem":827,"ArcanistLinter":1956,"ArcanistLintSeverity":2044}},"xmap":{"FormatStringLinter":["ArcanistExternalLinter"]}},"224d394856b17878058b4c14acb7178b":{"have":{"class":{"LocaleDependenceLinter":160}},"need":{"function":{"pht":5400},"class":{"ArcanistLinter":191,"ArcanistLintSeverity":5903,"Filesystem":6149}},"xmap":{"LocaleDependenceLinter":["ArcanistLinter"]}},"6f2f22dd0f259fb2eaa284b4fab3bc29":{"have":{"class":{"PythonFormatLinter":123}},"need":{"function":{"pht":353,"id":1838},"class":{"ArcanistExternalLinter":150,"ArcanistLintMessage":1845,"Filesystem":776,"ArcanistLinter":1970,"ArcanistLintSeverity":2053}},"xmap":{"PythonFormatLinter":["ArcanistExternalLinter"]}},"25781df78f6eebfb223296b8265e9d19":{"have":{"class":{"TestsLinter":103}},"need":{"function":{"pht":318,"id":2629},"class":{"ArcanistExternalLinter":123,"ArcanistLintMessage":2636,"Filesystem":776,"ArcanistLinter":2684,"ArcanistLintSeverity":2792}},"xmap":{"TestsLinter":["ArcanistExternalLinter"]}},"6264c994972b4c70b499e92f6c59678a":{"have":{"class":{"IncludeQuotesLinter":100}},"need":{"function":{"pht":306},"class":{"ArcanistLinter":128,"ArcanistLintSeverity":807,"Filesystem":1108}},"xmap":{"IncludeQuotesLinter":["ArcanistLinter"]}}} \ No newline at end of file +{"__symbol_cache_version__":11,"2809b09d2021203b43c57da33d1fe8bf":{"have":{"class":{"AssertWithSideEffectsLinter":210}},"need":{"function":{"pht":439},"class":{"ArcanistLinter":246,"ArcanistLintSeverity":926,"Filesystem":1170}},"xmap":{"AssertWithSideEffectsLinter":["ArcanistLinter"]}},"90a8b110dc475955f15bb81d37268cb5":{"have":{"class":{"AutoPEP8FormatLinter":75}},"need":{"function":{"pht":297,"execx":769,"id":1903},"class":{"ArcanistExternalLinter":104,"ArcanistLintMessage":1910,"Filesystem":1754,"ArcanistLinter":2017,"ArcanistLintSeverity":2095}},"xmap":{"AutoPEP8FormatLinter":["ArcanistExternalLinter"]}},"38f0c676bff5192a344464142caaa253":{"have":{"class":{"CHeaderLinter":99}},"need":{"function":{"pht":611},"class":{"ArcanistLinter":121,"ArcanistLintSeverity":1060,"Filesystem":1307}},"xmap":{"CHeaderLinter":["ArcanistLinter"]}},"a30e4e25376ca05d4ae719915441be9e":{"have":{"class":{"CheckDocLinter":106}},"need":{"function":{"pht":323,"id":1848},"class":{"ArcanistExternalLinter":129,"ArcanistLintMessage":1855,"Filesystem":731,"ArcanistLinter":1903,"ArcanistLintSeverity":1989}},"xmap":{"CheckDocLinter":["ArcanistExternalLinter"]}},"6af7410cfea496ff1d4dcc2624b6b8ea":{"have":{"class":{"ClangFormatLinter":79}},"need":{"function":{"pht":302,"execx":781,"id":1653},"class":{"ArcanistExternalLinter":105,"ArcanistLintMessage":1660,"Filesystem":1504,"ArcanistLinter":1767,"ArcanistLintSeverity":1845}},"xmap":{"ClangFormatLinter":["ArcanistExternalLinter"]}},"9285ad9415f8ebe564f7119e5a72c559":{"have":{"class":{"FormatStringLinter":146}},"need":{"function":{"pht":377,"csprintf":1492,"id":1872},"class":{"ArcanistExternalLinter":173,"ArcanistLintMessage":1879,"Filesystem":827,"ArcanistLinter":1956,"ArcanistLintSeverity":2044}},"xmap":{"FormatStringLinter":["ArcanistExternalLinter"]}},"2cbb6e7228d81557f777ad648704f343":{"have":{"class":{"IncludeQuotesLinter":100}},"need":{"function":{"pht":306},"class":{"ArcanistLinter":128,"ArcanistLintSeverity":663,"Filesystem":964}},"xmap":{"IncludeQuotesLinter":["ArcanistLinter"]}},"224d394856b17878058b4c14acb7178b":{"have":{"class":{"LocaleDependenceLinter":160}},"need":{"function":{"pht":5400},"class":{"ArcanistLinter":191,"ArcanistLintSeverity":5903,"Filesystem":6149}},"xmap":{"LocaleDependenceLinter":["ArcanistLinter"]}},"6f2f22dd0f259fb2eaa284b4fab3bc29":{"have":{"class":{"PythonFormatLinter":123}},"need":{"function":{"pht":353,"id":1838},"class":{"ArcanistExternalLinter":150,"ArcanistLintMessage":1845,"Filesystem":776,"ArcanistLinter":1970,"ArcanistLintSeverity":2053}},"xmap":{"PythonFormatLinter":["ArcanistExternalLinter"]}},"25781df78f6eebfb223296b8265e9d19":{"have":{"class":{"TestsLinter":103}},"need":{"function":{"pht":318,"id":2629},"class":{"ArcanistExternalLinter":123,"ArcanistLintMessage":2636,"Filesystem":776,"ArcanistLinter":2684,"ArcanistLintSeverity":2792}},"xmap":{"TestsLinter":["ArcanistExternalLinter"]}},"1f9bac7956f4f948a187828dcc6ba2d0":{"have":{"class":{"IncludeGuardLinter":98}},"need":{"function":{"pht":368},"class":{"ArcanistLinter":125,"ArcanistLintSeverity":721,"Filesystem":970}},"xmap":{"IncludeGuardLinter":["ArcanistLinter"]}}} \ No newline at end of file diff --git a/arcanist/__phutil_library_map__.php b/arcanist/__phutil_library_map__.php --- a/arcanist/__phutil_library_map__.php +++ b/arcanist/__phutil_library_map__.php @@ -15,6 +15,7 @@ 'CheckDocLinter' => 'linter/CheckDocLinter.php', 'ClangFormatLinter' => 'linter/ClangFormatLinter.php', 'FormatStringLinter' => 'linter/FormatStringLinter.php', + 'IncludeGuardLinter' => 'linter/IncludeGuardLinter.php', 'IncludeQuotesLinter' => 'linter/IncludeQuotesLinter.php', 'LocaleDependenceLinter' => 'linter/LocaleDependenceLinter.php', 'PythonFormatLinter' => 'linter/PythonFormatLinter.php', @@ -28,6 +29,7 @@ 'CheckDocLinter' => 'ArcanistExternalLinter', 'ClangFormatLinter' => 'ArcanistExternalLinter', 'FormatStringLinter' => 'ArcanistExternalLinter', + 'IncludeGuardLinter' => 'ArcanistLinter', 'IncludeQuotesLinter' => 'ArcanistLinter', 'LocaleDependenceLinter' => 'ArcanistLinter', 'PythonFormatLinter' => 'ArcanistExternalLinter', diff --git a/arcanist/linter/IncludeGuardLinter.php b/arcanist/linter/IncludeGuardLinter.php new file mode 100644 --- /dev/null +++ b/arcanist/linter/IncludeGuardLinter.php @@ -0,0 +1,71 @@ + ArcanistLintSeverity::SEVERITY_ERROR, + ); + } + + public function getLintNameMap() { + return array( + self::INCLUDE_GUARD_INVALID => pht('Include guard malformed or missing.'), + ); + } + + public function lintPath($path) { + $abspath = Filesystem::resolvePath($path, $this->getProjectRoot()); + $fileContent = Filesystem::readFile($abspath); + + $pathInfo = pathinfo($path); + + // Get the path components. They are relative to project root. + $guard = explode('/', $pathInfo['dirname']); + // Add the file name (without extension) to the path components. + $guard[] = $pathInfo['filename']; + // Skip the upper 'src' directory + $guard = array_slice($guard, 1); + // Join to a string using an underscore ('_') as the delimiter. + $guard = implode('_', $guard); + // Transform the whole string to uppercase. + $guard = strtoupper($guard); + // Surround with prefix and suffix. + $guard = self::GUARD_PREFIX.$guard.self::GUARD_SUFFIX; + + if (preg_match_all('/#(?:ifndef|define) '.$guard.'/', $fileContent) != 2) { + return $this->raiseLintAtPath( + self::INCLUDE_GUARD_INVALID, + pht("Include guard is malformed or missing. Expected format:\n". + "\t#ifndef %s\n". + "\t#define %s\n". + "\t...\n". + "\t#endif // %s", $guard, $guard, $guard)); + } + } +} diff --git a/doc/developer-notes.md b/doc/developer-notes.md --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -533,6 +533,16 @@ All headers should be lexically ordered inside their block. +- Use include guards to avoid the problem of double inclusion. The header file + `foo/bar.h` should use the include guard identifier `BITCOIN_FOO_BAR_H`, e.g. + +```c++ +#ifndef BITCOIN_FOO_BAR_H +#define BITCOIN_FOO_BAR_H +... +#endif // BITCOIN_FOO_BAR_H +``` + GUI ----- diff --git a/src/blockencodings.h b/src/blockencodings.h --- a/src/blockencodings.h +++ b/src/blockencodings.h @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef BITCOIN_BLOCK_ENCODINGS_H -#define BITCOIN_BLOCK_ENCODINGS_H +#ifndef BITCOIN_BLOCKENCODINGS_H +#define BITCOIN_BLOCKENCODINGS_H #include @@ -236,4 +236,4 @@ const std::vector &vtx_missing); }; -#endif +#endif // BITCOIN_BLOCKENCODINGS_H diff --git a/src/blockindexworkcomparator.h b/src/blockindexworkcomparator.h --- a/src/blockindexworkcomparator.h +++ b/src/blockindexworkcomparator.h @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef BITCOIN_BLOCK_INDEX_WORK_COMPARATOR_H -#define BITCOIN_BLOCK_INDEX_WORK_COMPARATOR_H +#ifndef BITCOIN_BLOCKINDEXWORKCOMPARATOR_H +#define BITCOIN_BLOCKINDEXWORKCOMPARATOR_H // TODO: Split chain.h apart and only include CBlockIndex #include @@ -40,4 +40,4 @@ } }; -#endif // BITCOIN_BLOCK_INDEX_WORK_COMPARATOR_H +#endif // BITCOIN_BLOCKINDEXWORKCOMPARATOR_H diff --git a/src/cashaddr.h b/src/cashaddr.h --- a/src/cashaddr.h +++ b/src/cashaddr.h @@ -3,6 +3,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#ifndef BITCOIN_CASHADDR_H +#define BITCOIN_CASHADDR_H + // Cashaddr is an address format inspired by bech32. #include @@ -24,3 +27,5 @@ Decode(const std::string &str, const std::string &default_prefix); } // namespace cashaddr + +#endif // BITCOIN_CASHADDR_H diff --git a/src/compat/setenv.h b/src/compat/setenv.h --- a/src/compat/setenv.h +++ b/src/compat/setenv.h @@ -1,5 +1,9 @@ -#ifndef HAVE_DECL_SETENV -#define HAVE_DECL_SETENV +// Copyright (c) 2018-2019 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_COMPAT_SETENV_H +#define BITCOIN_COMPAT_SETENV_H #if defined(WIN32) @@ -11,4 +15,4 @@ #endif -#endif // HAVE_DECL_SETENV \ No newline at end of file +#endif // BITCOIN_COMPAT_SETENV_H diff --git a/src/consensus/merkle.h b/src/consensus/merkle.h --- a/src/consensus/merkle.h +++ b/src/consensus/merkle.h @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef BITCOIN_MERKLE -#define BITCOIN_MERKLE +#ifndef BITCOIN_CONSENSUS_MERKLE_H +#define BITCOIN_CONSENSUS_MERKLE_H #include #include diff --git a/src/policy/fees.h b/src/policy/fees.h --- a/src/policy/fees.h +++ b/src/policy/fees.h @@ -2,8 +2,8 @@ // Copyright (c) 2009-2016 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_POLICYESTIMATOR_H -#define BITCOIN_POLICYESTIMATOR_H +#ifndef BITCOIN_POLICY_FEES_H +#define BITCOIN_POLICY_FEES_H #include #include @@ -37,4 +37,5 @@ std::set feeset; FastRandomContext insecure_rand; }; -#endif /*BITCOIN_POLICYESTIMATOR_H */ + +#endif // BITCOIN_POLICY_FEES_H diff --git a/src/qt/test/paymentrequestdata.h b/src/qt/test/paymentrequestdata.h --- a/src/qt/test/paymentrequestdata.h +++ b/src/qt/test/paymentrequestdata.h @@ -2,6 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#ifndef BITCOIN_QT_TEST_PAYMENTREQUESTDATA_H +#define BITCOIN_QT_TEST_PAYMENTREQUESTDATA_H + // // Data for paymentservertests.cpp // @@ -449,3 +452,5 @@ XR2T3Gy2LzRvhVA25QgGqpz0/juS2BtmNbsZPkN9gMMwKimgzc+PuCzmEKwPK9cQ\ YQ==\ "; + +#endif // BITCOIN_QT_TEST_PAYMENTREQUESTDATA_H diff --git a/src/qt/test/rpcnestedtests.h b/src/qt/test/rpcnestedtests.h --- a/src/qt/test/rpcnestedtests.h +++ b/src/qt/test/rpcnestedtests.h @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef BITCOIN_QT_TEST_RPC_NESTED_TESTS_H -#define BITCOIN_QT_TEST_RPC_NESTED_TESTS_H +#ifndef BITCOIN_QT_TEST_RPCNESTEDTESTS_H +#define BITCOIN_QT_TEST_RPCNESTEDTESTS_H #include #include @@ -18,4 +18,4 @@ void rpcNestedTests(); }; -#endif // BITCOIN_QT_TEST_RPC_NESTED_TESTS_H +#endif // BITCOIN_QT_TEST_RPCNESTEDTESTS_H diff --git a/src/rpc/blockchain.h b/src/rpc/blockchain.h --- a/src/rpc/blockchain.h +++ b/src/rpc/blockchain.h @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef BITCOIN_RPCBLOCKCHAIN_H -#define BITCOIN_RPCBLOCKCHAIN_H +#ifndef BITCOIN_RPC_BLOCKCHAIN_H +#define BITCOIN_RPC_BLOCKCHAIN_H #include @@ -39,4 +39,4 @@ UniValue blockheaderToJSON(const CBlockIndex *tip, const CBlockIndex *blockindex); -#endif // BITCOIN_RPCBLOCKCHAIN_H +#endif // BITCOIN_RPC_BLOCKCHAIN_H diff --git a/src/rpc/client.h b/src/rpc/client.h --- a/src/rpc/client.h +++ b/src/rpc/client.h @@ -3,8 +3,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef BITCOIN_RPCCLIENT_H -#define BITCOIN_RPCCLIENT_H +#ifndef BITCOIN_RPC_CLIENT_H +#define BITCOIN_RPC_CLIENT_H #include @@ -22,4 +22,4 @@ */ UniValue ParseNonRFCJSONValue(const std::string &strVal); -#endif // BITCOIN_RPCCLIENT_H +#endif // BITCOIN_RPC_CLIENT_H diff --git a/src/rpc/misc.h b/src/rpc/misc.h --- a/src/rpc/misc.h +++ b/src/rpc/misc.h @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef BITCOIN_RPCMISC_H -#define BITCOIN_RPCMISC_H +#ifndef BITCOIN_RPC_MISC_H +#define BITCOIN_RPC_MISC_H #include