diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 86bef765a5..8670b79db9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -259,6 +259,10 @@ There is a Continuous Integration job that runs clang-tidy on pull requests. The This ensures that configuration changes don't introduce new warnings across the codebase. +### Installing clang-tidy + +See the [environment setup guide](./docs/build/environment.md#clang-tidy) for platform-specific installation instructions. + ### Running clang-tidy locally Before running clang-tidy, you must build the project to generate required files (particularly protobuf headers). Refer to [`BUILD.md`](./BUILD.md) for build instructions. @@ -266,10 +270,15 @@ Before running clang-tidy, you must build the project to generate required files Then run clang-tidy on your local changes: ``` -run-clang-tidy -p build src tests +run-clang-tidy -p build src include tests ``` -This will check all source files in the `src` and `tests` directories using the compile commands from your `build` directory. +This will check all source files in the `src`, `include` and `tests` directories using the compile commands from your `build` directory. +If you wish to automatically fix whatever clang-tidy finds _and_ is capable of fixing, add `-fix` to the above command: + +``` +run-clang-tidy -p build -fix src include tests +``` ## Contracts and instrumentation diff --git a/conan.lock b/conan.lock index 900d3526e1..291258441f 100644 --- a/conan.lock +++ b/conan.lock @@ -6,11 +6,11 @@ "sqlite3/3.49.1#8631739a4c9b93bd3d6b753bac548a63%1765850149.926", "soci/4.0.3#a9f8d773cd33e356b5879a4b0564f287%1765850149.46", "snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1765850147.878", - "secp256k1/0.7.1#3a61e95e220062ef32c48d019e9c81f7%1770306721.686", + "secp256k1/0.7.1#481881709eb0bdd0185a12b912bbe8ad%1770910500.329", "rocksdb/10.5.1#4a197eca381a3e5ae8adf8cffa5aacd0%1765850186.86", - "re2/20230301#ca3b241baec15bd31ea9187150e0b333%1765850148.103", + "re2/20251105#8579cfd0bda4daf0683f9e3898f964b4%1772560729.95", "protobuf/6.32.1#f481fd276fc23a33b85a3ed1e898b693%1765850161.038", - "openssl/3.5.5#05a4ac5b7323f7a329b2db1391d9941f%1769599205.414", + "openssl/3.5.5#e6399de266349245a4542fc5f6c71552%1774367199.56", "nudb/2.0.9#0432758a24204da08fee953ec9ea03cb%1769436073.32", "lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1765850143.914", "libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1765842973.492", @@ -18,27 +18,27 @@ "libarchive/3.8.1#ffee18995c706e02bf96e7a2f7042e0d%1765850144.736", "jemalloc/5.3.0#e951da9cf599e956cebc117880d2d9f8%1729241615.244", "gtest/1.17.0#5224b3b3ff3b4ce1133cbdd27d53ee7d%1768312129.152", - "grpc/1.72.0#f244a57bff01e708c55a1100b12e1589%1765850193.734", + "grpc/1.72.0#500d27f2cbb105a0ffb708e64a0f1781%1774369626.679", "ed25519/2015.03#ae761bdc52730a843f0809bdf6c1b1f6%1765850143.772", "date/3.0.4#862e11e80030356b53c2c38599ceb32b%1765850143.772", "c-ares/1.34.5#5581c2b62a608b40bb85d965ab3ec7c8%1765850144.336", "bzip2/1.0.8#c470882369c2d95c5c77e970c0c7e321%1765850143.837", "boost/1.90.0#d5e8defe7355494953be18524a7f135b%1769454080.269", - "abseil/20250127.0#99262a368bd01c0ccca8790dfced9719%1766517936.993" + "abseil/20250127.0#bb0baf1f362bc4a725a24eddd419b8f7%1774365460.196" ], "build_requires": [ "zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76%1765850150.075", "strawberryperl/5.32.1.1#707032463aa0620fa17ec0d887f5fe41%1765850165.196", "protobuf/6.32.1#f481fd276fc23a33b85a3ed1e898b693%1765850161.038", "nasm/2.16.01#31e26f2ee3c4346ecd347911bd126904%1765850144.707", - "msys2/cci.latest#eea83308ad7e9023f7318c60d5a9e6cb%1770199879.083", - "m4/1.4.19#70dc8bbb33e981d119d2acc0175cf381%1763158052.846", + "msys2/cci.latest#d22fe7b2808f5fd34d0a7923ace9c54f%1770657326.649", + "m4/1.4.19#5d7a4994e5875d76faf7acf3ed056036%1774365463.87", "cmake/4.2.0#ae0a44f44a1ef9ab68fd4b3e9a1f8671%1765850153.937", "cmake/3.31.10#313d16a1aa16bbdb2ca0792467214b76%1765850153.479", "b2/5.3.3#107c15377719889654eb9a162a673975%1765850144.355", "automake/1.16.5#b91b7c384c3deaa9d535be02da14d04f%1755524470.56", "autoconf/2.71#51077f068e61700d65bb05541ea1e4b0%1731054366.86", - "abseil/20250127.0#99262a368bd01c0ccca8790dfced9719%1766517936.993" + "abseil/20250127.0#bb0baf1f362bc4a725a24eddd419b8f7%1774365460.196" ], "python_requires": [], "overrides": { @@ -46,7 +46,7 @@ null, "boost/1.90.0" ], - "protobuf/5.27.0": [ + "protobuf/[>=5.27.0 <7]": [ "protobuf/6.32.1" ], "lz4/1.9.4": [ diff --git a/docs/build/environment.md b/docs/build/environment.md index c67877a082..66bed06c26 100644 --- a/docs/build/environment.md +++ b/docs/build/environment.md @@ -109,3 +109,32 @@ Install CMake with Homebrew too: ``` brew install cmake ``` + +## Clang-tidy + +Clang-tidy is required to run static analysis checks locally (see [CONTRIBUTING.md](../../CONTRIBUTING.md)). +It is not required to build the project. Currently this project uses clang-tidy version 21. + +### Linux + +LLVM 21 is not available in the default Debian 12 (Bookworm) repositories. +Install it using the official LLVM apt installer: + +``` +wget https://apt.llvm.org/llvm.sh +chmod +x llvm.sh +sudo ./llvm.sh 21 +sudo apt install --yes clang-tidy-21 +``` + +Then use `run-clang-tidy-21` when running clang-tidy locally. + +### macOS + +Install LLVM 21 via Homebrew: + +``` +brew install llvm@21 +``` + +Then use `run-clang-tidy` from the LLVM 21 Homebrew prefix when running clang-tidy locally. diff --git a/src/libxrpl/ledger/View.cpp b/src/libxrpl/ledger/View.cpp index ef6a66744d..227eafbec8 100644 --- a/src/libxrpl/ledger/View.cpp +++ b/src/libxrpl/ledger/View.cpp @@ -433,8 +433,7 @@ doWithdraw( j) < amount) { // LCOV_EXCL_START - JLOG(j.error()) << "LoanBrokerCoverWithdraw: negative balance of " - "broker cover assets."; + JLOG(j.error()) << "doWithdraw: negative balance of broker cover assets."; return tefINTERNAL; // LCOV_EXCL_STOP } diff --git a/src/libxrpl/ledger/helpers/MPTokenHelpers.cpp b/src/libxrpl/ledger/helpers/MPTokenHelpers.cpp index 85b74151e5..0bffb3e853 100644 --- a/src/libxrpl/ledger/helpers/MPTokenHelpers.cpp +++ b/src/libxrpl/ledger/helpers/MPTokenHelpers.cpp @@ -1,6 +1,7 @@ #include // #include +#include #include #include #include @@ -12,21 +13,6 @@ namespace xrpl { -// Forward declarations for functions that remain in View.h/cpp -bool -isVaultPseudoAccountFrozen( - ReadView const& view, - AccountID const& account, - MPTIssue const& mptShare, - int depth); - -[[nodiscard]] TER -dirLink( - ApplyView& view, - AccountID const& owner, - std::shared_ptr& object, - SF_UINT64 const& node = sfOwnerNode); - bool isGlobalFrozen(ReadView const& view, MPTIssue const& mptIssue) { @@ -149,7 +135,7 @@ authorizeMPToken( // When a holder wants to unauthorize/delete a MPT, the ledger must // - delete mptokenKey from owner directory // - delete the MPToken - if ((flags & tfMPTUnauthorize) != 0u) + if ((flags & tfMPTUnauthorize) != 0) { auto const mptokenKey = keylet::mptoken(mptIssuanceID, account); auto const sleMpt = view.peek(mptokenKey); @@ -229,7 +215,7 @@ authorizeMPToken( // Issuer wants to unauthorize the holder, unset lsfMPTAuthorized on // their MPToken - if ((flags & tfMPTUnauthorize) != 0u) + if ((flags & tfMPTUnauthorize) != 0) { flagsOut &= ~lsfMPTAuthorized; } diff --git a/src/libxrpl/ledger/helpers/VaultHelpers.cpp b/src/libxrpl/ledger/helpers/VaultHelpers.cpp index 3ded720289..83a1b9fc4f 100644 --- a/src/libxrpl/ledger/helpers/VaultHelpers.cpp +++ b/src/libxrpl/ledger/helpers/VaultHelpers.cpp @@ -92,7 +92,7 @@ sharesToAssetsWithdraw( std::shared_ptr const& issuance, STAmount const& shares) { - XRPL_ASSERT(!shares.negative(), "xrpl::sharesToAssetsDeposit : non-negative shares"); + XRPL_ASSERT(!shares.negative(), "xrpl::sharesToAssetsWithdraw : non-negative shares"); XRPL_ASSERT( shares.asset() == vault->at(sfShareMPTID), "xrpl::sharesToAssetsWithdraw : shares and vault match"); diff --git a/src/libxrpl/tx/transactors/permissioned_domain/PermissionedDomainSet.cpp b/src/libxrpl/tx/transactors/permissioned_domain/PermissionedDomainSet.cpp index e8df51c9d9..30f24241aa 100644 --- a/src/libxrpl/tx/transactors/permissioned_domain/PermissionedDomainSet.cpp +++ b/src/libxrpl/tx/transactors/permissioned_domain/PermissionedDomainSet.cpp @@ -100,8 +100,6 @@ PermissionedDomainSet::doApply() Keylet const pdKeylet = keylet::permissionedDomain(account_, ctx_.tx.getFieldU32(sfSequence)); auto slePd = std::make_shared(pdKeylet); - if (!slePd) - return tefINTERNAL; // LCOV_EXCL_LINE slePd->setAccountID(sfOwner, account_); slePd->setFieldU32(sfSequence, ctx_.tx.getFieldU32(sfSequence)); diff --git a/src/libxrpl/tx/transactors/vault/VaultDelete.cpp b/src/libxrpl/tx/transactors/vault/VaultDelete.cpp index 1e2e46e165..5a60c0032c 100644 --- a/src/libxrpl/tx/transactors/vault/VaultDelete.cpp +++ b/src/libxrpl/tx/transactors/vault/VaultDelete.cpp @@ -55,7 +55,7 @@ VaultDelete::preclaim(PreclaimContext const& ctx) if (!sleMPT) { // LCOV_EXCL_START - JLOG(ctx.j.error()) << "VaultDeposit: missing issuance of vault shares."; + JLOG(ctx.j.error()) << "VaultDelete: missing issuance of vault shares."; return tecOBJECT_NOT_FOUND; // LCOV_EXCL_STOP } @@ -63,7 +63,7 @@ VaultDelete::preclaim(PreclaimContext const& ctx) if (sleMPT->at(sfIssuer) != vault->getAccountID(sfAccount)) { // LCOV_EXCL_START - JLOG(ctx.j.error()) << "VaultDeposit: invalid owner of vault shares."; + JLOG(ctx.j.error()) << "VaultDelete: invalid owner of vault shares."; return tecNO_PERMISSION; // LCOV_EXCL_STOP } @@ -200,8 +200,6 @@ VaultDelete::doApply() // Destroy the vault. view().erase(vault); - associateAsset(*vault, asset); - return tesSUCCESS; }