SERVER-104800 Adjust clang tidy std bans (#39064)
GitOrigin-RevId: 7ea0cb3ba6d7ff5ff0c7f84cf47ba8bed310ff0d
This commit is contained in:
parent
18cfe7e7f2
commit
b97884cb49
@ -65,6 +65,7 @@ Checks: '-*,
|
||||
modernize-unary-static-assert,
|
||||
modernize-use-override,
|
||||
mongo-assert-check,
|
||||
mongo-banned-names-check,
|
||||
mongo-cctype-check,
|
||||
mongo-collection-sharding-runtime-check,
|
||||
mongo-config-header-check,
|
||||
@ -76,10 +77,7 @@ Checks: '-*,
|
||||
mongo-invariant-ddl-coordinator-check,
|
||||
mongo-macro-definition-leaks-check,
|
||||
mongo-mutex-check,
|
||||
mongo-polyfill-check,
|
||||
mongo-rand-check,
|
||||
mongo-std-atomic-check,
|
||||
mongo-std-optional-check,
|
||||
mongo-stringdata-const-ref-check,
|
||||
mongo-trace-check,
|
||||
mongo-uninterruptible-lock-guard-check,
|
||||
|
||||
@ -1769,7 +1769,7 @@ TEST_F(DConcurrencyTestFixture,
|
||||
boost::optional<Lock::DBLock> dbIX = Lock::DBLock{opCtx1, dbName, LockMode::MODE_IX};
|
||||
shard_role_details::getLocker(opCtx1)->releaseTicket();
|
||||
|
||||
stdx::packaged_task<void()> task{[opCtx2, &dbName] {
|
||||
std::packaged_task<void()> task{[opCtx2, &dbName] { // NOLINT
|
||||
Lock::GlobalLock globalIX{opCtx2, LockMode::MODE_IX};
|
||||
Lock::DBLock dbX{opCtx2, dbName, LockMode::MODE_X};
|
||||
}};
|
||||
|
||||
@ -93,6 +93,7 @@ static const StringMap<MetaType> kMetaNameToMetaType = {
|
||||
{changeStreamControlEventName, MetaType::kChangeStreamControlEvent},
|
||||
};
|
||||
|
||||
// NOLINTNEXTLINE needs audit
|
||||
static const std::unordered_map<MetaType, StringData> kMetaTypeToMetaName = {
|
||||
{MetaType::kScore, scoreName},
|
||||
{MetaType::kVectorSearchScore, vectorSearchScoreName},
|
||||
|
||||
@ -770,7 +770,7 @@ public:
|
||||
boost::optional<Date_t> maxTime,
|
||||
WaitFn waitFn) {
|
||||
auto barrier = std::make_shared<unittest::Barrier>(2);
|
||||
task = stdx::packaged_task<bool()>([=, this] {
|
||||
task = std::packaged_task<bool()>([=, this] { // NOLINT
|
||||
if (maxTime)
|
||||
opCtx->setDeadlineByDate(*maxTime, ErrorCodes::ExceededTimeLimit);
|
||||
stdx::unique_lock<stdx::mutex> lk(mutex);
|
||||
@ -795,7 +795,7 @@ public:
|
||||
stdx::mutex mutex;
|
||||
stdx::condition_variable cv;
|
||||
bool isSignaled = false;
|
||||
stdx::packaged_task<bool()> task;
|
||||
std::packaged_task<bool()> task; // NOLINT
|
||||
JoinThread waiter;
|
||||
};
|
||||
|
||||
|
||||
@ -54,6 +54,7 @@ public:
|
||||
};
|
||||
|
||||
TEST_F(ProfileFilterTest, FilterOnAllOpDebugFields) {
|
||||
// NOLINTNEXTLINE
|
||||
const std::unordered_set<std::string> allowedOpDebugFields = {"ts",
|
||||
"client",
|
||||
"appName",
|
||||
|
||||
@ -50,6 +50,9 @@
|
||||
namespace mongo {
|
||||
namespace {
|
||||
|
||||
template <typename T>
|
||||
using nolint_promise = std::promise<T>; // NOLINT
|
||||
|
||||
using unittest::assertGet;
|
||||
|
||||
class MoveChunkRegistration : public ShardServerTestFixture {
|
||||
@ -177,9 +180,9 @@ TEST_F(MoveChunkRegistration, TestReceiveChunkIsRejectedWhenRegistryIsLocked) {
|
||||
|
||||
TEST_F(MoveChunkRegistration,
|
||||
TestReceiveChunkWithWaitForConflictingOpsIsBlockedWhenRegistryIsLocked) {
|
||||
stdx::promise<void> blockReceive;
|
||||
stdx::promise<void> readyToLock;
|
||||
stdx::promise<void> inLock;
|
||||
nolint_promise<void> blockReceive;
|
||||
nolint_promise<void> readyToLock;
|
||||
nolint_promise<void> inLock;
|
||||
|
||||
// Registry thread.
|
||||
auto result = stdx::async(stdx::launch::async, [&] {
|
||||
@ -245,9 +248,9 @@ TEST_F(MoveChunkRegistration,
|
||||
// in progress. The test will fail if any of the futures are not signalled indicating that some part
|
||||
// of the sequence is not working correctly.
|
||||
TEST_F(MoveChunkRegistration, TestBlockingWhileDonateInProgress) {
|
||||
stdx::promise<void> blockDonate;
|
||||
stdx::promise<void> readyToLock;
|
||||
stdx::promise<void> inLock;
|
||||
nolint_promise<void> blockDonate;
|
||||
nolint_promise<void> readyToLock;
|
||||
nolint_promise<void> inLock;
|
||||
|
||||
// Migration thread.
|
||||
auto result = stdx::async(stdx::launch::async, [&] {
|
||||
@ -309,9 +312,9 @@ TEST_F(MoveChunkRegistration, TestBlockingWhileDonateInProgress) {
|
||||
// in progress. The test will fail if any of the futures are not signalled indicating that some part
|
||||
// of the sequence is not working correctly.
|
||||
TEST_F(MoveChunkRegistration, TestBlockingWhileReceiveInProgress) {
|
||||
stdx::promise<void> blockReceive;
|
||||
stdx::promise<void> readyToLock;
|
||||
stdx::promise<void> inLock;
|
||||
nolint_promise<void> blockReceive;
|
||||
nolint_promise<void> readyToLock;
|
||||
nolint_promise<void> inLock;
|
||||
|
||||
// Migration thread.
|
||||
auto result = stdx::async(stdx::launch::async, [&] {
|
||||
|
||||
@ -1484,7 +1484,7 @@ TEST_F(SessionCatalogTestWithDefaultOpCtx, KillSessionsThroughScanSessions) {
|
||||
return {lsid0, lsid1, lsid2};
|
||||
}();
|
||||
|
||||
std::vector<stdx::future<void>> futures;
|
||||
std::vector<std::future<void>> futures; // NOLINT
|
||||
unittest::Barrier firstUseOfTheSessionReachedBarrier(lsids.size() + 1);
|
||||
|
||||
for (const auto& lsid : lsids) {
|
||||
@ -1563,7 +1563,7 @@ TEST_F(SessionCatalogTestWithDefaultOpCtx, ConcurrentCheckOutAndKill) {
|
||||
auto opCtx = cc().makeOperationContext();
|
||||
opCtx->setLogicalSessionId(lsid);
|
||||
|
||||
stdx::future<void> normalCheckOutFinish, killCheckOutFinish;
|
||||
std::future<void> normalCheckOutFinish, killCheckOutFinish; // NOLINT
|
||||
|
||||
// This variable is protected by the session check-out.
|
||||
std::string lastSessionCheckOut = "first session";
|
||||
@ -1633,7 +1633,7 @@ TEST_F(SessionCatalogTest, CheckOutForKillTimeout) {
|
||||
// Check out the session to block checkOutForKill.
|
||||
OperationContextSession firstCheckOut(opCtx.get());
|
||||
|
||||
stdx::future<void> killCheckOutTimeout = stdx::async(stdx::launch::async, [&] {
|
||||
std::future<void> killCheckOutTimeout = std::async(std::launch::async, [&] { // NOLINT
|
||||
ThreadClient tc(getServiceContext()->getService());
|
||||
auto sideOpCtx = Client::getCurrent()->makeOperationContext();
|
||||
sideOpCtx->setLogicalSessionId(lsid);
|
||||
|
||||
@ -148,7 +148,7 @@ public:
|
||||
int jobs();
|
||||
|
||||
private:
|
||||
stdx::recursive_mutex _timersMutex;
|
||||
std::recursive_mutex _timersMutex; // NOLINT
|
||||
stdx::unordered_set<std::shared_ptr<AsyncTimerMockImpl>> _timers;
|
||||
Milliseconds _curTime;
|
||||
};
|
||||
|
||||
@ -95,7 +95,7 @@ public:
|
||||
template <class T>
|
||||
class FutureHandle {
|
||||
public:
|
||||
FutureHandle(stdx::future<T> future,
|
||||
FutureHandle(std::future<T> future, // NOLINT
|
||||
executor::TaskExecutor* executor,
|
||||
executor::NetworkInterfaceMock* network)
|
||||
: _future(std::move(future)), _executor(executor), _network(network) {}
|
||||
@ -140,7 +140,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
stdx::future<T> _future;
|
||||
std::future<T> _future; // NOLINT
|
||||
executor::TaskExecutor* _executor;
|
||||
executor::NetworkInterfaceMock* _network;
|
||||
};
|
||||
|
||||
@ -157,6 +157,7 @@ private:
|
||||
std::exception_ptr exception = nullptr;
|
||||
};
|
||||
|
||||
// NOLINTNEXTLINE needs audit
|
||||
static std::unordered_set<std::string> forbiddenKeywords{
|
||||
"legacy", "cursor", "endSessions", "ok", "isWritablePrimary", "n"};
|
||||
|
||||
|
||||
@ -186,6 +186,7 @@ public:
|
||||
// Do not destroy the cursor if the error is any of the errors in
|
||||
// 'safeErrorCodes' since for those errors we can guarantee that the data
|
||||
// has not been corrupted and it is safe to continue the execution.
|
||||
// NOLINTNEXTLINE needs audit
|
||||
static const std::unordered_set<ErrorCodes::Error> safeErrorCodes{
|
||||
ErrorCodes::QueryExceededMemoryLimitNoDiskUseAllowed,
|
||||
ErrorCodes::CursorInUse,
|
||||
|
||||
@ -806,6 +806,7 @@ Status AsyncResultsMerger::releaseMemory() {
|
||||
// 'safeErrorCodes' since for those errors we can guarantee that the data has not been
|
||||
// corrupted and it is safe to continue the execution. We must wait for the other shards
|
||||
// to be sure that none returned a fatal error.
|
||||
// NOLINTNEXTLINE needs audit
|
||||
static const std::unordered_set<ErrorCodes::Error> safeErrorCodes{
|
||||
ErrorCodes::QueryExceededMemoryLimitNoDiskUseAllowed,
|
||||
ErrorCodes::CursorInUse,
|
||||
|
||||
@ -819,8 +819,8 @@ private:
|
||||
}
|
||||
|
||||
private:
|
||||
stdx::promise<void> _promise;
|
||||
stdx::shared_future<void> _future;
|
||||
std::promise<void> _promise; // NOLINT needs audit
|
||||
std::shared_future<void> _future;
|
||||
};
|
||||
|
||||
boost::optional<CompletePromiseFuture> _killCompleteInfo;
|
||||
|
||||
@ -11,6 +11,7 @@ cc_library(
|
||||
name = "mongo_tidy_checks_static",
|
||||
srcs = [
|
||||
"MongoAssertCheck.cpp",
|
||||
"MongoBannedNamesCheck.cpp",
|
||||
"MongoCctypeCheck.cpp",
|
||||
"MongoCollectionShardingRuntimeCheck.cpp",
|
||||
"MongoConfigHeaderCheck.cpp",
|
||||
@ -22,11 +23,8 @@ cc_library(
|
||||
"MongoInvariantStatusIsOKCheck.cpp",
|
||||
"MongoMacroDefinitionLeaksCheck.cpp",
|
||||
"MongoNoUniqueAddressCheck.cpp",
|
||||
"MongoPolyFillCheck.cpp",
|
||||
"MongoRWMutexCheck.cpp",
|
||||
"MongoRandCheck.cpp",
|
||||
"MongoStdAtomicCheck.cpp",
|
||||
"MongoStdOptionalCheck.cpp",
|
||||
"MongoStringDataConstRefCheck.cpp",
|
||||
"MongoStringDataStringViewApi.cpp",
|
||||
"MongoTidyModule.cpp",
|
||||
@ -37,6 +35,7 @@ cc_library(
|
||||
],
|
||||
hdrs = [
|
||||
"MongoAssertCheck.h",
|
||||
"MongoBannedNamesCheck.h",
|
||||
"MongoCctypeCheck.h",
|
||||
"MongoCollectionShardingRuntimeCheck.h",
|
||||
"MongoConfigHeaderCheck.h",
|
||||
@ -48,11 +47,8 @@ cc_library(
|
||||
"MongoInvariantStatusIsOKCheck.h",
|
||||
"MongoMacroDefinitionLeaksCheck.h",
|
||||
"MongoNoUniqueAddressCheck.h",
|
||||
"MongoPolyFillCheck.h",
|
||||
"MongoRWMutexCheck.h",
|
||||
"MongoRandCheck.h",
|
||||
"MongoStdAtomicCheck.h",
|
||||
"MongoStdOptionalCheck.h",
|
||||
"MongoStringDataConstRefCheck.h",
|
||||
"MongoStringDataStringViewApi.h",
|
||||
"MongoTidyUtils.h",
|
||||
|
||||
249
src/mongo/tools/mongo_tidy_checks/MongoBannedNamesCheck.cpp
Normal file
249
src/mongo/tools/mongo_tidy_checks/MongoBannedNamesCheck.cpp
Normal file
@ -0,0 +1,249 @@
|
||||
/**
|
||||
* Copyright (C) 2025-present MongoDB, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the Server Side Public License, version 1,
|
||||
* as published by MongoDB, Inc.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* Server Side Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the Server Side Public License
|
||||
* along with this program. If not, see
|
||||
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
||||
*
|
||||
* As a special exception, the copyright holders give permission to link the
|
||||
* code of portions of this program with the OpenSSL library under certain
|
||||
* conditions as described in each individual source file and distribute
|
||||
* linked combinations including the program with the OpenSSL library. You
|
||||
* must comply with the Server Side Public License in all respects for
|
||||
* all of the code used other than as permitted herein. If you modify file(s)
|
||||
* with this exception, you may extend this exception to your version of the
|
||||
* file(s), but you are not obligated to do so. If you do not wish to do so,
|
||||
* delete this exception statement from your version. If you delete this
|
||||
* exception statement from all source files in the program, then also delete
|
||||
* it in the license file.
|
||||
*/
|
||||
|
||||
#include "MongoBannedNamesCheck.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include <clang/Lex/Lexer.h>
|
||||
|
||||
namespace mongo::tidy {
|
||||
|
||||
using namespace clang;
|
||||
using namespace clang::ast_matchers;
|
||||
|
||||
namespace {
|
||||
|
||||
enum Action {
|
||||
kStdxReplacement,
|
||||
kMongoReplacement,
|
||||
kBoostReplacement,
|
||||
kDoNotUse,
|
||||
};
|
||||
|
||||
enum Namespace {
|
||||
kStd,
|
||||
kBoost,
|
||||
};
|
||||
|
||||
struct BanInfo {
|
||||
std::string produceBanMessage(const llvm::StringRef sourceText) const {
|
||||
auto msg = [&]() -> std::string {
|
||||
switch (action) {
|
||||
case kStdxReplacement:
|
||||
return "Consider using alternatives such as the polyfills from the "
|
||||
"mongo::stdx:: namespace.";
|
||||
case kMongoReplacement:
|
||||
case kBoostReplacement:
|
||||
return "Consider using " + message + " instead.";
|
||||
case kDoNotUse:
|
||||
return "Do not use. " + message;
|
||||
}
|
||||
return std::string();
|
||||
}();
|
||||
|
||||
std::ostringstream err;
|
||||
err << "Forbidden use of banned name in " << sourceText.str() << ". " << msg
|
||||
<< " Use '// NOLINT' if usage is absolutely necessary."
|
||||
<< " Be especially careful doing so outside of test code.";
|
||||
return err.str();
|
||||
}
|
||||
|
||||
bool fromBannedNamespace(const llvm::StringRef sourceText) const {
|
||||
for (auto&& ns : namespaces) {
|
||||
switch (ns) {
|
||||
case kStd:
|
||||
if (sourceText.find("std::" + name.str()) != llvm::StringRef::npos)
|
||||
return true;
|
||||
break;
|
||||
case kBoost:
|
||||
if (sourceText.find("boost::" + name.str()) != llvm::StringRef::npos)
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
llvm::StringRef name;
|
||||
Action action;
|
||||
std::vector<Namespace> namespaces;
|
||||
std::string message;
|
||||
};
|
||||
|
||||
std::vector<llvm::StringRef> getNames(const std::vector<BanInfo>& infos) {
|
||||
std::vector<llvm::StringRef> names;
|
||||
for (auto&& info : infos) {
|
||||
names.push_back(info.name);
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
// List of base type names from the std and boost namespaces to be checked
|
||||
const std::vector<BanInfo> baseTypeInfos = {
|
||||
{"atomic", kMongoReplacement, {kStd, kBoost}, "mongo::Atomic<T>"},
|
||||
{"condition_variable", kStdxReplacement, {kStd, kBoost}},
|
||||
{"condition_variable_any", kStdxReplacement, {kStd, kBoost}},
|
||||
{"future", kMongoReplacement, {kStd, kBoost}, "mongo::Future"},
|
||||
{"launch", kDoNotUse, {kStd}},
|
||||
{"optional", kBoostReplacement, {kStd}, "boost::optional"},
|
||||
{"packaged_task", kMongoReplacement, {kStd, kBoost}, "mongo::PackagedTask"},
|
||||
{"promise", kMongoReplacement, {kStd, kBoost}, "mongo::Promise"},
|
||||
{"recursive_mutex",
|
||||
kDoNotUse,
|
||||
{kStd, kBoost},
|
||||
"A recursive mutex is often an indication of a design problem and is prone to deadlocks "
|
||||
"because you don't know what code you are calling while holding the lock."},
|
||||
{"shared_mutex",
|
||||
kMongoReplacement,
|
||||
{kStd, kBoost},
|
||||
"a type from src/mongo/platform/rwmutex.h or a LockManager lock"},
|
||||
{"shared_timed_mutex",
|
||||
kMongoReplacement,
|
||||
{kStd, kBoost},
|
||||
"a type from src/mongo/platform/rwmutex.h or a LockManager lock"},
|
||||
{"thread", kStdxReplacement, {kStd, kBoost}},
|
||||
{"timed_mutex", kDoNotUse, {kStd, kBoost}, "timed_mutex acquisitions are not interruptible."},
|
||||
{"unordered_map", kStdxReplacement, {kStd, kBoost}},
|
||||
{"unordered_set", kStdxReplacement, {kStd, kBoost}},
|
||||
};
|
||||
|
||||
// List of base enum names from the std and boost namespaces to be checked
|
||||
const std::vector<BanInfo> baseEnumInfos = {};
|
||||
|
||||
// List of base function names from the std and boost namespaces to be checked
|
||||
const std::vector<BanInfo> baseFuncInfos = {
|
||||
{"async", kDoNotUse, {kStd, kBoost}},
|
||||
{"get_terminate", kStdxReplacement, {kStd}},
|
||||
{"notify_all_at_thread_exit", kDoNotUse, {kStd, kBoost}},
|
||||
{"regex_search", kMongoReplacement, {kStd, kBoost}, "mongo::pcre::Regex"},
|
||||
{"set_terminate", kStdxReplacement, {kStd}},
|
||||
};
|
||||
|
||||
// List of base namespace names from the std and boost namespaces to be checked
|
||||
const std::vector<BanInfo> baseNamespaceInfos = {};
|
||||
|
||||
const std::vector<BanInfo> allInfos = [] {
|
||||
std::vector<BanInfo> infos;
|
||||
auto add = [&](auto& r) {
|
||||
infos.insert(infos.end(), r.begin(), r.end());
|
||||
};
|
||||
add(baseTypeInfos);
|
||||
add(baseEnumInfos);
|
||||
add(baseFuncInfos);
|
||||
add(baseNamespaceInfos);
|
||||
return infos;
|
||||
}();
|
||||
} // namespace
|
||||
|
||||
void MongoBannedNamesCheck::registerMatchers(ast_matchers::MatchFinder* Finder) {
|
||||
// Register AST Matchers to find any use of the banned names.
|
||||
Finder->addMatcher(declRefExpr(hasDeclaration(enumConstantDecl(
|
||||
hasParent(enumDecl(hasAnyName(getNames(baseEnumInfos)))))))
|
||||
.bind("enumConstants"),
|
||||
this);
|
||||
// The type matcher matches against DeclaratorDecl nodes, which means return types and
|
||||
// references will not be matched here. Matching against only declarations should be
|
||||
// sufficient and will not generate extra noise when developers decide to use a banned type.
|
||||
Finder->addMatcher(
|
||||
declaratorDecl(hasType(namedDecl(hasAnyName(getNames(baseTypeInfos))))).bind("typeNames"),
|
||||
this);
|
||||
Finder->addMatcher(
|
||||
usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(anyOf(hasAnyName(getNames(baseTypeInfos)),
|
||||
hasAnyName(getNames(baseFuncInfos))))))
|
||||
.bind("usingNames"),
|
||||
this);
|
||||
Finder->addMatcher(callExpr(callee(expr(hasDescendant(declRefExpr(hasDeclaration(
|
||||
functionDecl(hasAnyName(getNames(baseFuncInfos)))))))))
|
||||
.bind("functionNames"),
|
||||
this);
|
||||
Finder->addMatcher(declRefExpr(hasDeclaration(namedDecl(hasParent(
|
||||
namespaceDecl(hasAnyName(getNames(baseNamespaceInfos)))))))
|
||||
.bind("namespaceFromRef"),
|
||||
this);
|
||||
Finder->addMatcher(expr(hasType(qualType(hasDeclaration(namedDecl(hasParent(
|
||||
namespaceDecl(hasAnyName(getNames(baseNamespaceInfos)))))))))
|
||||
.bind("namespaceFromType"),
|
||||
this);
|
||||
Finder->addMatcher(
|
||||
declaratorDecl(hasParent(namespaceDecl(hasAnyName(getNames(baseNamespaceInfos)))))
|
||||
.bind("namespaceFromDecl"),
|
||||
this);
|
||||
}
|
||||
|
||||
void MongoBannedNamesCheck::checkNamespace(const SourceLocation loc,
|
||||
const llvm::StringRef sourceText) {
|
||||
if (!loc.isValid()) {
|
||||
return;
|
||||
}
|
||||
for (auto&& info : allInfos) {
|
||||
if (sourceText.contains(info.name.str()) && info.fromBannedNamespace(sourceText)) {
|
||||
diag(loc, info.produceBanMessage(sourceText));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get text as written in source from a clang node to ensure any alias makes it into the
|
||||
// returned string.
|
||||
template <typename Node>
|
||||
llvm::StringRef getTextFromSource(const Node* node, const clang::ASTContext& Context) {
|
||||
const clang::SourceManager& SM = Context.getSourceManager();
|
||||
clang::SourceRange Range = node->getSourceRange();
|
||||
return Lexer::getSourceText(CharSourceRange::getTokenRange(Range), SM, Context.getLangOpts());
|
||||
}
|
||||
|
||||
void MongoBannedNamesCheck::check(const ast_matchers::MatchFinder::MatchResult& Result) {
|
||||
auto chkAs = [&]<typename As>(std::type_identity<As>,
|
||||
std::initializer_list<std::string> matchNames) {
|
||||
for (auto&& name : matchNames) {
|
||||
if (auto node = Result.Nodes.getNodeAs<As>(name)) {
|
||||
checkNamespace(node->getBeginLoc(), getTextFromSource(node, *Result.Context));
|
||||
}
|
||||
}
|
||||
};
|
||||
chkAs(std::type_identity<Expr>{},
|
||||
{
|
||||
"functionNames",
|
||||
"enumConstants",
|
||||
"namespaceFromRef",
|
||||
"namespaceFromType",
|
||||
});
|
||||
chkAs(std::type_identity<DeclaratorDecl>{},
|
||||
{
|
||||
"typeNames",
|
||||
"namespaceFromDecl",
|
||||
});
|
||||
chkAs(std::type_identity<UsingDecl>{},
|
||||
{
|
||||
"usingNames",
|
||||
});
|
||||
}
|
||||
} // namespace mongo::tidy
|
||||
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (C) 2023-present MongoDB, Inc.
|
||||
* Copyright (C) 2025-present MongoDB, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the Server Side Public License, version 1,
|
||||
@ -34,17 +34,15 @@
|
||||
namespace mongo::tidy {
|
||||
|
||||
/**
|
||||
* check for usage of std::atomic
|
||||
* Overrides the default registerMatchers function to add matcher to match the
|
||||
* usage of std::atomic. overrides the default check function to
|
||||
* flag the uses of std::atomic to enforce our commitment to boost::atomic
|
||||
* MongoBannedNamesCheck is a custom clang-tidy check for detecting
|
||||
* the usage of listed names from the std or boost libraries (std,
|
||||
* boost, or global namespace) in the source code.
|
||||
*/
|
||||
class MongoStdAtomicCheck : public clang::tidy::ClangTidyCheck {
|
||||
|
||||
class MongoBannedNamesCheck : public clang::tidy::ClangTidyCheck {
|
||||
public:
|
||||
MongoStdAtomicCheck(clang::StringRef Name, clang::tidy::ClangTidyContext* Context);
|
||||
using clang::tidy::ClangTidyCheck::ClangTidyCheck;
|
||||
void registerMatchers(clang::ast_matchers::MatchFinder* Finder) override;
|
||||
void check(const clang::ast_matchers::MatchFinder::MatchResult& Result) override;
|
||||
void checkNamespace(clang::SourceLocation loc, llvm::StringRef name);
|
||||
};
|
||||
|
||||
} // namespace mongo::tidy
|
||||
@ -1,187 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2023-present MongoDB, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the Server Side Public License, version 1,
|
||||
* as published by MongoDB, Inc.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* Server Side Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the Server Side Public License
|
||||
* along with this program. If not, see
|
||||
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
||||
*
|
||||
* As a special exception, the copyright holders give permission to link the
|
||||
* code of portions of this program with the OpenSSL library under certain
|
||||
* conditions as described in each individual source file and distribute
|
||||
* linked combinations including the program with the OpenSSL library. You
|
||||
* must comply with the Server Side Public License in all respects for
|
||||
* all of the code used other than as permitted herein. If you modify file(s)
|
||||
* with this exception, you may extend this exception to your version of the
|
||||
* file(s), but you are not obligated to do so. If you do not wish to do so,
|
||||
* delete this exception statement from your version. If you delete this
|
||||
* exception statement from all source files in the program, then also delete
|
||||
* it in the license file.
|
||||
*/
|
||||
|
||||
#include "MongoPolyFillCheck.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
#include <clang/Lex/Lexer.h>
|
||||
|
||||
namespace mongo::tidy {
|
||||
|
||||
using namespace clang;
|
||||
using namespace clang::ast_matchers;
|
||||
|
||||
namespace {
|
||||
|
||||
// List of base polyfill type names from the std and boost namespaces to be checked
|
||||
constexpr std::initializer_list<llvm::StringRef> basePolyfillTypeNames = {
|
||||
"condition_variable",
|
||||
"condition_variable_any",
|
||||
"cv_status",
|
||||
"future",
|
||||
"future_status",
|
||||
"launch",
|
||||
"packaged_task",
|
||||
"promise",
|
||||
"recursive_mutex",
|
||||
"shared_mutex",
|
||||
"shared_timed_mutex",
|
||||
"thread",
|
||||
"timed_mutex",
|
||||
"unordered_map",
|
||||
"unordered_multimap",
|
||||
"unordered_multiset",
|
||||
"unordered_set",
|
||||
};
|
||||
|
||||
// List of base polyfill enum names from the std and boost namespaces to be checked
|
||||
constexpr std::initializer_list<llvm::StringRef> basePolyfillEnumNames = {
|
||||
"cv_status",
|
||||
"future_status",
|
||||
"launch",
|
||||
};
|
||||
|
||||
// List of base polyfill function names from the std and boost namespaces to be checked
|
||||
constexpr std::initializer_list<llvm::StringRef> basePolyfillFuncNames = {
|
||||
"async",
|
||||
"get_terminate",
|
||||
"notify_all_at_thread_exit",
|
||||
"regex_search",
|
||||
"set_terminate",
|
||||
};
|
||||
|
||||
// List of base polyfill namespace names from the std and boost namespaces to be checked
|
||||
constexpr std::initializer_list<llvm::StringRef> basePolyfillNamespaces = {
|
||||
"this_thread",
|
||||
"chrono",
|
||||
};
|
||||
} // namespace
|
||||
|
||||
// Generate a list of fully qualified polyfill names by prefixing each name
|
||||
// in the input list with 'std::' and 'boost::'
|
||||
std::vector<std::string> generateQualifiedPolyfillNames(
|
||||
const std::vector<llvm::StringRef>& bannedNames) {
|
||||
std::vector<std::string> fullyBannedNames;
|
||||
for (auto&& name : bannedNames) {
|
||||
fullyBannedNames.push_back("std::" + name.str());
|
||||
fullyBannedNames.push_back("boost::" + name.str());
|
||||
}
|
||||
return fullyBannedNames;
|
||||
}
|
||||
|
||||
MongoPolyFillCheck::MongoPolyFillCheck(StringRef Name, clang::tidy::ClangTidyContext* Context)
|
||||
: ClangTidyCheck(Name, Context) {
|
||||
std::vector<llvm::StringRef> basePolyfillNames;
|
||||
basePolyfillNames.insert(
|
||||
basePolyfillNames.end(), basePolyfillTypeNames.begin(), basePolyfillTypeNames.end());
|
||||
basePolyfillNames.insert(
|
||||
basePolyfillNames.end(), basePolyfillEnumNames.begin(), basePolyfillEnumNames.end());
|
||||
basePolyfillNames.insert(
|
||||
basePolyfillNames.end(), basePolyfillFuncNames.begin(), basePolyfillFuncNames.end());
|
||||
basePolyfillNames.insert(
|
||||
basePolyfillNames.end(), basePolyfillNamespaces.begin(), basePolyfillNamespaces.end());
|
||||
// Generate a list of fully polyfill names
|
||||
fullyQualifiedPolyfillNames = generateQualifiedPolyfillNames(basePolyfillNames);
|
||||
}
|
||||
|
||||
|
||||
void MongoPolyFillCheck::registerMatchers(ast_matchers::MatchFinder* Finder) {
|
||||
// Register AST Matchers to find any use of the banned names.
|
||||
Finder->addMatcher(declRefExpr(hasDeclaration(enumConstantDecl(
|
||||
hasParent(enumDecl(hasAnyName(basePolyfillEnumNames))))))
|
||||
.bind("bannedEnumConstants"),
|
||||
this);
|
||||
Finder->addMatcher(declaratorDecl(hasType(namedDecl(hasAnyName(basePolyfillTypeNames))))
|
||||
.bind("bannedTypeNames"),
|
||||
this);
|
||||
Finder->addMatcher(callExpr(callee(expr(hasDescendant(declRefExpr(hasDeclaration(
|
||||
functionDecl(hasAnyName(basePolyfillFuncNames))))))))
|
||||
.bind("bannedFunctionNames"),
|
||||
this);
|
||||
Finder->addMatcher(declRefExpr(hasDeclaration(namedDecl(hasParent(
|
||||
namespaceDecl(hasAnyName(basePolyfillNamespaces))))))
|
||||
.bind("bannedNamespaceFromRef"),
|
||||
this);
|
||||
Finder->addMatcher(expr(hasType(qualType(hasDeclaration(namedDecl(
|
||||
hasParent(namespaceDecl(hasAnyName(basePolyfillNamespaces))))))))
|
||||
.bind("bannedNamespaceFromType"),
|
||||
this);
|
||||
Finder->addMatcher(declaratorDecl(hasParent(namespaceDecl(hasAnyName(basePolyfillNamespaces))))
|
||||
.bind("bannedNamespaceFromDecl"),
|
||||
this);
|
||||
}
|
||||
|
||||
void MongoPolyFillCheck::checkBannedName(const SourceLocation loc, const llvm::StringRef name) {
|
||||
// we catch this_thread but not this_thread::at_thread_exit
|
||||
if (name.find("this_thread::at_thread_exit") != std::string::npos)
|
||||
return;
|
||||
|
||||
// Check if the type string starts with 'std' or 'boost' and contains a banned name.
|
||||
for (auto&& polyfillName : fullyQualifiedPolyfillNames) {
|
||||
if ((name.starts_with("std::") || name.starts_with("boost::")) &&
|
||||
name.find(polyfillName) != std::string::npos) {
|
||||
if (loc.isValid())
|
||||
diag(loc,
|
||||
"Illegal use of banned name from std::/boost:: for %0. Consider using "
|
||||
"alternatives such as the polyfills from the mongo::stdx:: namespace.")
|
||||
<< name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get full name as written in source from a clang node to ensure any alias makes it into the
|
||||
// returned string.
|
||||
template <typename Node>
|
||||
llvm::StringRef getFullName(const Node* node, const clang::ASTContext& Context) {
|
||||
const clang::SourceManager& SM = Context.getSourceManager();
|
||||
clang::SourceRange Range = node->getSourceRange();
|
||||
return Lexer::getSourceText(CharSourceRange::getTokenRange(Range), SM, Context.getLangOpts());
|
||||
}
|
||||
|
||||
void MongoPolyFillCheck::check(const ast_matchers::MatchFinder::MatchResult& Result) {
|
||||
for (auto&& matcher : {"bannedFunctionNames",
|
||||
"bannedEnumConstants",
|
||||
"bannedNamespaceFromRef",
|
||||
"bannedNamespaceFromType"}) {
|
||||
if (const auto* matched = Result.Nodes.getNodeAs<Expr>(matcher)) {
|
||||
auto name = getFullName(matched, *Result.Context);
|
||||
checkBannedName(matched->getBeginLoc(), std::move(name));
|
||||
}
|
||||
}
|
||||
|
||||
// DeclaratorDecl inherits from Decl instead of Expr, so it's extracted separately.
|
||||
for (auto&& matcher : {"bannedTypeNames", "bannedNamespaceFromDecl"}) {
|
||||
if (const auto* matched = Result.Nodes.getNodeAs<DeclaratorDecl>(matcher)) {
|
||||
auto name = getFullName(matched, *Result.Context);
|
||||
checkBannedName(matched->getBeginLoc(), std::move(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace mongo::tidy
|
||||
@ -1,55 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2023-present MongoDB, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the Server Side Public License, version 1,
|
||||
* as published by MongoDB, Inc.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* Server Side Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the Server Side Public License
|
||||
* along with this program. If not, see
|
||||
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
||||
*
|
||||
* As a special exception, the copyright holders give permission to link the
|
||||
* code of portions of this program with the OpenSSL library under certain
|
||||
* conditions as described in each individual source file and distribute
|
||||
* linked combinations including the program with the OpenSSL library. You
|
||||
* must comply with the Server Side Public License in all respects for
|
||||
* all of the code used other than as permitted herein. If you modify file(s)
|
||||
* with this exception, you may extend this exception to your version of the
|
||||
* file(s), but you are not obligated to do so. If you do not wish to do so,
|
||||
* delete this exception statement from your version. If you delete this
|
||||
* exception statement from all source files in the program, then also delete
|
||||
* it in the license file.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <clang-tidy/ClangTidy.h>
|
||||
#include <clang-tidy/ClangTidyCheck.h>
|
||||
|
||||
namespace mongo::tidy {
|
||||
|
||||
/**
|
||||
* MongoPolyFillCheck is a custom clang-tidy check for detecting
|
||||
* the usage of listed names from the std or boost namespace in the source code.
|
||||
*
|
||||
* It extends ClangTidyCheck and overrides the registerMatchers
|
||||
* and check functions. The registerMatchers function adds matchers
|
||||
* to identify the usage of banned names, while the check function
|
||||
* flags the matched occurrences.
|
||||
*/
|
||||
class MongoPolyFillCheck : public clang::tidy::ClangTidyCheck {
|
||||
public:
|
||||
MongoPolyFillCheck(clang::StringRef Name, clang::tidy::ClangTidyContext* Context);
|
||||
void registerMatchers(clang::ast_matchers::MatchFinder* Finder) override;
|
||||
void check(const clang::ast_matchers::MatchFinder::MatchResult& Result) override;
|
||||
void checkBannedName(clang::SourceLocation loc, llvm::StringRef name);
|
||||
|
||||
private:
|
||||
std::vector<std::string> fullyQualifiedPolyfillNames;
|
||||
};
|
||||
} // namespace mongo::tidy
|
||||
@ -1,64 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2023-present MongoDB, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the Server Side Public License, version 1,
|
||||
* as published by MongoDB, Inc.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* Server Side Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the Server Side Public License
|
||||
* along with this program. If not, see
|
||||
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
||||
*
|
||||
* As a special exception, the copyright holders give permission to link the
|
||||
* code of portions of this program with the OpenSSL library under certain
|
||||
* conditions as described in each individual source file and distribute
|
||||
* linked combinations including the program with the OpenSSL library. You
|
||||
* must comply with the Server Side Public License in all respects for
|
||||
* all of the code used other than as permitted herein. If you modify file(s)
|
||||
* with this exception, you may extend this exception to your version of the
|
||||
* file(s), but you are not obligated to do so. If you do not wish to do so,
|
||||
* delete this exception statement from your version. If you delete this
|
||||
* exception statement from all source files in the program, then also delete
|
||||
* it in the license file.
|
||||
*/
|
||||
|
||||
#include "MongoStdAtomicCheck.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "MongoTidyUtils.h"
|
||||
|
||||
namespace mongo::tidy {
|
||||
|
||||
using namespace clang;
|
||||
using namespace clang::ast_matchers;
|
||||
|
||||
MongoStdAtomicCheck::MongoStdAtomicCheck(StringRef Name, clang::tidy::ClangTidyContext* Context)
|
||||
: ClangTidyCheck(Name, Context) {}
|
||||
|
||||
void MongoStdAtomicCheck::registerMatchers(ast_matchers::MatchFinder* Finder) {
|
||||
|
||||
// match parameter decl, variable Decl, Field Decl, Reference Decl, Template Decl regarding
|
||||
// std::atomic
|
||||
Finder->addMatcher(loc(templateSpecializationType(
|
||||
hasDeclaration(namedDecl(hasName("atomic"), isFromStdNamespace()))))
|
||||
.bind("loc_atomic"),
|
||||
this);
|
||||
}
|
||||
|
||||
void MongoStdAtomicCheck::check(const ast_matchers::MatchFinder::MatchResult& Result) {
|
||||
|
||||
const auto* loc_match = Result.Nodes.getNodeAs<TypeLoc>("loc_atomic");
|
||||
if (loc_match) {
|
||||
diag(loc_match->getBeginLoc(),
|
||||
"Illegal use of prohibited std::atomic<T>, use Atomic<T> or other types from "
|
||||
"\"mongo/platform/atomic.h\"");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mongo::tidy
|
||||
@ -1,73 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2023-present MongoDB, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the Server Side Public License, version 1,
|
||||
* as published by MongoDB, Inc.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* Server Side Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the Server Side Public License
|
||||
* along with this program. If not, see
|
||||
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
||||
*
|
||||
* As a special exception, the copyright holders give permission to link the
|
||||
* code of portions of this program with the OpenSSL library under certain
|
||||
* conditions as described in each individual source file and distribute
|
||||
* linked combinations including the program with the OpenSSL library. You
|
||||
* must comply with the Server Side Public License in all respects for
|
||||
* all of the code used other than as permitted herein. If you modify file(s)
|
||||
* with this exception, you may extend this exception to your version of the
|
||||
* file(s), but you are not obligated to do so. If you do not wish to do so,
|
||||
* delete this exception statement from your version. If you delete this
|
||||
* exception statement from all source files in the program, then also delete
|
||||
* it in the license file.
|
||||
*/
|
||||
|
||||
#include "MongoStdOptionalCheck.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "MongoTidyUtils.h"
|
||||
|
||||
namespace mongo::tidy {
|
||||
|
||||
using namespace clang;
|
||||
using namespace clang::ast_matchers;
|
||||
|
||||
MongoStdOptionalCheck::MongoStdOptionalCheck(StringRef Name, clang::tidy::ClangTidyContext* Context)
|
||||
: ClangTidyCheck(Name, Context) {}
|
||||
|
||||
void MongoStdOptionalCheck::registerMatchers(ast_matchers::MatchFinder* Finder) {
|
||||
|
||||
// match using std::optional;
|
||||
Finder->addMatcher(usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(
|
||||
allOf(hasName("optional"), isFromStdNamespace()))))
|
||||
.bind("decl_optional"),
|
||||
this);
|
||||
|
||||
// match parameter decl, variable Decl, Field Decl, Reference Decl, Template Decl regarding
|
||||
// std::optional
|
||||
Finder->addMatcher(loc(templateSpecializationType(hasDeclaration(
|
||||
namedDecl(hasName("optional"), isFromStdNamespace()))))
|
||||
.bind("loc_optional"),
|
||||
this);
|
||||
}
|
||||
|
||||
void MongoStdOptionalCheck::check(const ast_matchers::MatchFinder::MatchResult& Result) {
|
||||
|
||||
const auto* decl_match = Result.Nodes.getNodeAs<UsingDecl>("decl_optional");
|
||||
const auto* loc_match = Result.Nodes.getNodeAs<TypeLoc>("loc_optional");
|
||||
|
||||
if (decl_match) {
|
||||
diag(decl_match->getBeginLoc(), "Use of std::optional, use boost::optional instead. ");
|
||||
}
|
||||
if (loc_match && !loc_match->getBeginLoc().isInvalid()) {
|
||||
diag(loc_match->getBeginLoc(), "Use of std::optional, use boost::optional instead. ");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mongo::tidy
|
||||
@ -1,49 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2023-present MongoDB, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the Server Side Public License, version 1,
|
||||
* as published by MongoDB, Inc.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* Server Side Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the Server Side Public License
|
||||
* along with this program. If not, see
|
||||
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
||||
*
|
||||
* As a special exception, the copyright holders give permission to link the
|
||||
* code of portions of this program with the OpenSSL library under certain
|
||||
* conditions as described in each individual source file and distribute
|
||||
* linked combinations including the program with the OpenSSL library. You
|
||||
* must comply with the Server Side Public License in all respects for
|
||||
* all of the code used other than as permitted herein. If you modify file(s)
|
||||
* with this exception, you may extend this exception to your version of the
|
||||
* file(s), but you are not obligated to do so. If you do not wish to do so,
|
||||
* delete this exception statement from your version. If you delete this
|
||||
* exception statement from all source files in the program, then also delete
|
||||
* it in the license file.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <clang-tidy/ClangTidy.h>
|
||||
#include <clang-tidy/ClangTidyCheck.h>
|
||||
namespace mongo::tidy {
|
||||
|
||||
/**
|
||||
* check for usage of std::optional
|
||||
* Overrides the default registerMatchers function to add matcher to match the
|
||||
* usage of std::optional. overrides the default check function to
|
||||
* flag the uses of std::optional to enforce our commitment to boost::optional
|
||||
*/
|
||||
class MongoStdOptionalCheck : public clang::tidy::ClangTidyCheck {
|
||||
|
||||
public:
|
||||
MongoStdOptionalCheck(clang::StringRef Name, clang::tidy::ClangTidyContext* Context);
|
||||
void registerMatchers(clang::ast_matchers::MatchFinder* Finder) override;
|
||||
void check(const clang::ast_matchers::MatchFinder::MatchResult& Result) override;
|
||||
};
|
||||
|
||||
} // namespace mongo::tidy
|
||||
@ -28,6 +28,7 @@
|
||||
*/
|
||||
|
||||
#include "MongoAssertCheck.h"
|
||||
#include "MongoBannedNamesCheck.h"
|
||||
#include "MongoCctypeCheck.h"
|
||||
#include "MongoCollectionShardingRuntimeCheck.h"
|
||||
#include "MongoConfigHeaderCheck.h"
|
||||
@ -39,11 +40,8 @@
|
||||
#include "MongoInvariantStatusIsOKCheck.h"
|
||||
#include "MongoMacroDefinitionLeaksCheck.h"
|
||||
#include "MongoNoUniqueAddressCheck.h"
|
||||
#include "MongoPolyFillCheck.h"
|
||||
#include "MongoRWMutexCheck.h"
|
||||
#include "MongoRandCheck.h"
|
||||
#include "MongoStdAtomicCheck.h"
|
||||
#include "MongoStdOptionalCheck.h"
|
||||
#include "MongoStringDataConstRefCheck.h"
|
||||
#include "MongoStringDataStringViewApi.h"
|
||||
#include "MongoTraceCheck.h"
|
||||
@ -70,10 +68,8 @@ public:
|
||||
CheckFactories.registerCheck<MongoCxx20BannedIncludesCheck>(
|
||||
"mongo-cxx20-banned-includes-check");
|
||||
CheckFactories.registerCheck<MongoCxx20StdChronoCheck>("mongo-cxx20-std-chrono-check");
|
||||
CheckFactories.registerCheck<MongoStdOptionalCheck>("mongo-std-optional-check");
|
||||
CheckFactories.registerCheck<MongoVolatileCheck>("mongo-volatile-check");
|
||||
CheckFactories.registerCheck<MongoTraceCheck>("mongo-trace-check");
|
||||
CheckFactories.registerCheck<MongoStdAtomicCheck>("mongo-std-atomic-check");
|
||||
CheckFactories.registerCheck<MongoAssertCheck>("mongo-assert-check");
|
||||
CheckFactories.registerCheck<MongoFCVConstantCheck>("mongo-fcv-constant-check");
|
||||
CheckFactories.registerCheck<MongoUnstructuredLogCheck>("mongo-unstructured-log-check");
|
||||
@ -82,7 +78,7 @@ public:
|
||||
CheckFactories.registerCheck<MongoMacroDefinitionLeaksCheck>(
|
||||
"mongo-macro-definition-leaks-check");
|
||||
CheckFactories.registerCheck<MongoRandCheck>("mongo-rand-check");
|
||||
CheckFactories.registerCheck<MongoPolyFillCheck>("mongo-polyfill-check");
|
||||
CheckFactories.registerCheck<MongoBannedNamesCheck>("mongo-banned-names-check");
|
||||
CheckFactories.registerCheck<MongoNoUniqueAddressCheck>("mongo-no-unique-address-check");
|
||||
CheckFactories.registerCheck<MongoStringDataConstRefCheck>(
|
||||
"mongo-stringdata-const-ref-check");
|
||||
|
||||
@ -26,9 +26,7 @@ tests = [
|
||||
"test_MongoConfigHeaderCheck",
|
||||
"test_MongoCxx20BannedIncludesCheck",
|
||||
"test_MongoCxx20StdChronoCheck",
|
||||
"test_MongoStdOptionalCheck",
|
||||
"test_MongoTraceCheck",
|
||||
"test_MongoStdAtomicCheck",
|
||||
"test_MongoAssertCheck",
|
||||
"test_MongoFCVConstantCheck",
|
||||
"test_MongoUnstructuredLogCheck",
|
||||
@ -36,7 +34,7 @@ tests = [
|
||||
"test_MongoMacroDefinitionLeaksCheck",
|
||||
"test_MongoRandCheck",
|
||||
"test_MongoRWMutexCheck",
|
||||
"test_MongoPolyFillCheck",
|
||||
"test_MongoBannedNamesCheck",
|
||||
"test_MongoNoUniqueAddressCheck",
|
||||
"test_MongoStringDataConstRefCheck1",
|
||||
"test_MongoStringDataConstRefCheck2",
|
||||
|
||||
@ -114,24 +114,6 @@ class MongoTidyTests(unittest.TestCase):
|
||||
]
|
||||
self.run_clang_tidy()
|
||||
|
||||
def test_MongoStdOptionalCheck(self):
|
||||
msg = "Use of std::optional, use boost::optional instead."
|
||||
opt = "mongo-std-optional-check,-warnings-as-errors"
|
||||
self.expected_output = [
|
||||
f"{msg} [{opt}]\n{n:5} | {src}"
|
||||
for n, src in [
|
||||
(36, "void f(std::optional<std::string> parameterDeclTest) {"),
|
||||
(37, " std::optional<std::string> variableDeclTest;"),
|
||||
(42, " std::optional<int> fieldDeclTest = 5;"),
|
||||
(46, "void functionName(const std::optional<int>& referenceDeclTest) {"),
|
||||
(52, "std::optional<std::string> functionReturnTypeDeclTest(StringData name);"),
|
||||
(55, "std::optional<T> templateDeclTest;"),
|
||||
(57, "using std::optional;"),
|
||||
]
|
||||
]
|
||||
|
||||
self.run_clang_tidy()
|
||||
|
||||
def test_MongoVolatileCheck(self):
|
||||
msg = 'Illegal use of the volatile storage keyword, use Atomic instead from "mongo/platform/atomic.h"'
|
||||
opt = "mongo-volatile-check,-warnings-as-errors"
|
||||
@ -159,19 +141,6 @@ class MongoTidyTests(unittest.TestCase):
|
||||
|
||||
self.run_clang_tidy()
|
||||
|
||||
def test_MongoStdAtomicCheck(self):
|
||||
msg = 'Illegal use of prohibited std::atomic<T>, use Atomic<T> or other types from "mongo/platform/atomic.h"'
|
||||
opt = "mongo-std-atomic-check,-warnings-as-errors"
|
||||
self.expected_output = [
|
||||
f"{msg} [{opt}]\n{n:5} | {src}"
|
||||
for n, src in [
|
||||
(6, "std::atomic<int> atomic_var;"),
|
||||
(10, " std::atomic<int> field_decl;"),
|
||||
]
|
||||
]
|
||||
|
||||
self.run_clang_tidy()
|
||||
|
||||
def test_MongoAssertCheck(self):
|
||||
self.expected_output = [
|
||||
"error: Illegal use of the bare assert macro, use a macro function from assert_util.h instead",
|
||||
@ -244,26 +213,29 @@ class MongoTidyTests(unittest.TestCase):
|
||||
|
||||
self.run_clang_tidy()
|
||||
|
||||
def test_MongoPolyFillCheck(self):
|
||||
def test_MongoBannedNamesCheck(self):
|
||||
stdx_replacement_str = "Consider using alternatives such as the polyfills from the mongo::stdx:: namespace."
|
||||
|
||||
test_names = [
|
||||
"std::cv_status wait_result{std::cv_status::timeout}",
|
||||
"std::cv_status::timeout",
|
||||
"std::cv_status::timeout",
|
||||
"std::this_thread::get_id",
|
||||
"std::get_terminate()",
|
||||
"std::chrono::seconds(1)",
|
||||
"std::future<int> myFuture",
|
||||
"std::condition_variable cv",
|
||||
"std::unordered_map<int, int> myMap",
|
||||
"boost::unordered_map<int, int> boostMap",
|
||||
"std::regex_search(std::string(\"\"), std::regex(\"\"))",
|
||||
("std::get_terminate()", stdx_replacement_str),
|
||||
("std::future<int> myFuture", "Consider using mongo::Future instead."),
|
||||
("std::recursive_mutex recursiveMut", "Do not use. A recursive mutex is often an indication of a design problem and is prone to deadlocks because you don't know what code you are calling while holding the lock."),
|
||||
("const std::condition_variable cv", stdx_replacement_str),
|
||||
("static std::unordered_map<int, int> myMap", stdx_replacement_str),
|
||||
("boost::unordered_map<int, int> boostMap", stdx_replacement_str),
|
||||
("std::regex_search(std::string(\"\"), std::regex(\"\"))", "Consider using mongo::pcre::Regex instead."),
|
||||
("std::atomic<int> atomicVar", "Consider using mongo::Atomic<T> instead."),
|
||||
("std::optional<std::string> strOpt", "Consider using boost::optional instead."),
|
||||
("std::atomic<int> fieldDecl", "Consider using mongo::Atomic<T> instead."),
|
||||
("std::optional<T> templateDecl", "Consider using boost::optional instead."),
|
||||
("using std::optional", "Consider using boost::optional instead."),
|
||||
]
|
||||
|
||||
self.expected_output = [
|
||||
"error: Illegal use of banned name from std::/boost:: for "
|
||||
+ name
|
||||
+ ". Consider using alternatives such as the polyfills from the mongo::stdx:: namespace."
|
||||
for name in test_names
|
||||
"error: Forbidden use of banned name in "
|
||||
+ name + ". " + msg
|
||||
+ " Use '// NOLINT' if usage is absolutely necessary. Be especially careful doing so outside of test code."
|
||||
for (name, msg) in test_names
|
||||
]
|
||||
|
||||
self.run_clang_tidy()
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <future>
|
||||
#include <mutex>
|
||||
#include <regex>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
namespace mongo {
|
||||
void mongoBannedNamesCheckTest() {
|
||||
std::get_terminate();
|
||||
std::future<int> myFuture;
|
||||
std::recursive_mutex recursiveMut;
|
||||
const std::condition_variable cv;
|
||||
static std::unordered_map<int, int> myMap;
|
||||
boost::unordered_map<int, int> boostMap;
|
||||
std::atomic<int> atomicVar;
|
||||
std::optional<std::string> strOpt;
|
||||
std::regex_search(std::string(""), std::regex(""));
|
||||
}
|
||||
|
||||
struct AtomicStruct {
|
||||
std::atomic<int> fieldDecl;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
std::optional<T> templateDecl;
|
||||
|
||||
using std::optional;
|
||||
} // namespace mongo
|
||||
@ -0,0 +1,2 @@
|
||||
Checks: '-*,mongo-banned-names-check'
|
||||
WarningsAsErrors: '*'
|
||||
@ -1,26 +0,0 @@
|
||||
#include <condition_variable>
|
||||
#include <future>
|
||||
#include <mutex>
|
||||
#include <regex>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
namespace mongo {
|
||||
void mongoPolyFillCheckTest() {
|
||||
std::cv_status wait_result{std::cv_status::timeout};
|
||||
if (wait_result == std::cv_status::timeout) {
|
||||
}
|
||||
std::this_thread::get_id();
|
||||
std::get_terminate();
|
||||
std::chrono::seconds(1);
|
||||
std::chrono::seconds seconds(1);
|
||||
std::future<int> myFuture;
|
||||
std::condition_variable cv;
|
||||
std::unordered_map<int, int> myMap;
|
||||
boost::unordered_map<int, int> boostMap;
|
||||
std::regex_search(std::string(""), std::regex(""));
|
||||
}
|
||||
|
||||
} // namespace mongo
|
||||
@ -1,2 +0,0 @@
|
||||
Checks: '-*,mongo-polyfill-check'
|
||||
WarningsAsErrors: '*'
|
||||
@ -1,13 +0,0 @@
|
||||
#include <atomic>
|
||||
|
||||
namespace mongo {
|
||||
|
||||
// Variable Decl
|
||||
std::atomic<int> atomic_var;
|
||||
|
||||
// Field Decl
|
||||
struct structName {
|
||||
std::atomic<int> field_decl;
|
||||
};
|
||||
|
||||
} // namespace mongo
|
||||
@ -1,2 +0,0 @@
|
||||
Checks: '-*,mongo-std-atomic-check'
|
||||
WarningsAsErrors: '*'
|
||||
@ -1,59 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2023-present MongoDB, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the Server Side Public License, version 1,
|
||||
* as published by MongoDB, Inc.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* Server Side Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the Server Side Public License
|
||||
* along with this program. If not, see
|
||||
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
||||
*
|
||||
* As a special exception, the copyright holders give permission to link the
|
||||
* code of portions of this program with the OpenSSL library under certain
|
||||
* conditions as described in each individual source file and distribute
|
||||
* linked combinations including the program with the OpenSSL library. You
|
||||
* must comply with the Server Side Public License in all respects for
|
||||
* all of the code used other than as permitted herein. If you modify file(s)
|
||||
* with this exception, you may extend this exception to your version of the
|
||||
* file(s), but you are not obligated to do so. If you do not wish to do so,
|
||||
* delete this exception statement from your version. If you delete this
|
||||
* exception statement from all source files in the program, then also delete
|
||||
* it in the license file.
|
||||
*/
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
namespace mongo {
|
||||
|
||||
// Variable Decl and Parameter Decl
|
||||
void f(std::optional<std::string> parameterDeclTest) {
|
||||
std::optional<std::string> variableDeclTest;
|
||||
}
|
||||
|
||||
// Field Decl
|
||||
struct CertInformationToLog {
|
||||
std::optional<int> fieldDeclTest = 5;
|
||||
};
|
||||
|
||||
// Reference Decl
|
||||
void functionName(const std::optional<int>& referenceDeclTest) {
|
||||
return;
|
||||
}
|
||||
|
||||
class StringData {};
|
||||
// Function Return type Decl
|
||||
std::optional<std::string> functionReturnTypeDeclTest(StringData name);
|
||||
|
||||
template <typename T>
|
||||
std::optional<T> templateDeclTest;
|
||||
|
||||
using std::optional;
|
||||
|
||||
} // namespace mongo
|
||||
@ -1,2 +0,0 @@
|
||||
Checks: '-*,mongo-std-optional-check'
|
||||
WarningsAsErrors: '*'
|
||||
@ -102,7 +102,7 @@ TEST(BasicLockableAdapter, TestWithMutexTypes) {
|
||||
}
|
||||
|
||||
{
|
||||
stdx::timed_mutex mut;
|
||||
std::timed_mutex mut; // NOLINT
|
||||
callUnderLock(mut);
|
||||
}
|
||||
|
||||
|
||||
@ -53,13 +53,13 @@ public:
|
||||
return _f.wait();
|
||||
}
|
||||
|
||||
bool waitFor(stdx::chrono::milliseconds dur) const {
|
||||
return _f.wait_for(dur) == stdx::future_status::ready;
|
||||
bool waitFor(std::chrono::milliseconds dur) const {
|
||||
return _f.wait_for(dur) == std::future_status::ready; // NOLINT
|
||||
}
|
||||
|
||||
private:
|
||||
stdx::promise<void> _p;
|
||||
stdx::future<void> _f{_p.get_future()};
|
||||
std::promise<void> _p; // NOLINT
|
||||
std::future<void> _f{_p.get_future()}; // NOLINT
|
||||
};
|
||||
|
||||
using OnPhdrFunc = std::function<int(dl_phdr_info*, size_t)>;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user