SERVER-102107 Fix and reenable mongo polyfill check (#34879)
GitOrigin-RevId: 721448be067332e2106b165a7b410809e1a263d9
This commit is contained in:
parent
c53f216dce
commit
6d35264914
@ -75,6 +75,7 @@ Checks: '-*,
|
||||
mongo-invariant-status-is-ok-check,
|
||||
mongo-macro-definition-leaks-check,
|
||||
mongo-mutex-check,
|
||||
mongo-polyfill-check,
|
||||
mongo-rand-check,
|
||||
mongo-std-atomic-check,
|
||||
mongo-std-optional-check,
|
||||
|
||||
@ -37,7 +37,6 @@
|
||||
#include <s2regioncoverer.h>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
|
||||
|
||||
@ -50,6 +49,7 @@
|
||||
#include "mongo/db/query/interval.h"
|
||||
#include "mongo/logv2/log.h"
|
||||
#include "mongo/platform/atomic_word.h"
|
||||
#include "mongo/stdx/unordered_set.h"
|
||||
#include "mongo/util/assert_util.h"
|
||||
|
||||
#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kQuery
|
||||
@ -200,7 +200,7 @@ void ExpressionMapping::S2CellIdsToIntervalsWithParents(const std::vector<S2Cell
|
||||
const S2IndexingParams& indexParams,
|
||||
OrderedIntervalList* oilOut) {
|
||||
// There may be duplicates when going up parent cells if two cells share a parent
|
||||
std::unordered_set<S2CellId> exactSet; // NOLINT
|
||||
stdx::unordered_set<S2CellId> exactSet;
|
||||
for (const S2CellId& interval : intervalSet) {
|
||||
S2CellId coveredCell = interval;
|
||||
// Look at the cells that cover us. We want to look at every cell that contains the
|
||||
|
||||
@ -50,6 +50,7 @@
|
||||
#include "mongo/db/pipeline/expression_context.h"
|
||||
#include "mongo/db/query/fle/encrypted_predicate_test_fixtures.h"
|
||||
#include "mongo/db/query/fle/text_search_predicate.h"
|
||||
#include "mongo/stdx/unordered_map.h"
|
||||
#include "mongo/unittest/unittest.h"
|
||||
#include "mongo/util/assert_util.h"
|
||||
|
||||
@ -168,7 +169,7 @@ private:
|
||||
};
|
||||
// Key the tags for agg expressions based on values only, since we don't have access to the
|
||||
// field name. The Value in the map must contain BSONBinData type used for payloads.
|
||||
std::unordered_map<Value, std::vector<PrfBlock>, KeyHash, KeyEqual> _exprTags;
|
||||
stdx::unordered_map<Value, std::vector<PrfBlock>, KeyHash, KeyEqual> _exprTags;
|
||||
};
|
||||
|
||||
class TextSearchPredicateRewriteTestWithFFP : public EncryptedPredicateRewriteTest {
|
||||
|
||||
@ -132,7 +132,7 @@ void IntentRegistry::deregisterIntent(IntentRegistry::IntentToken token) {
|
||||
stdx::future<ReplicationStateTransitionGuard> IntentRegistry::killConflictingOperations(
|
||||
IntentRegistry::InterruptionType interrupt, boost::optional<uint32_t> timeout_sec) {
|
||||
LOGV2(9945003, "Intent Registry killConflictingOperations", "interrupt"_attr = interrupt);
|
||||
auto timeOutSec = std::chrono::seconds(
|
||||
auto timeOutSec = stdx::chrono::seconds(
|
||||
timeout_sec ? *timeout_sec : repl::fassertOnLockTimeoutForStepUpDown.load());
|
||||
{
|
||||
stdx::unique_lock<stdx::mutex> lock(_stateMutex);
|
||||
@ -172,14 +172,14 @@ stdx::future<ReplicationStateTransitionGuard> IntentRegistry::killConflictingOpe
|
||||
break;
|
||||
}
|
||||
|
||||
_waitForDrain(Intent::PreparedTransaction, std::chrono::milliseconds(0));
|
||||
_waitForDrain(Intent::PreparedTransaction, stdx::chrono::milliseconds(0));
|
||||
|
||||
if (intents) {
|
||||
for (auto intent : *intents) {
|
||||
_killOperationsByIntent(intent);
|
||||
}
|
||||
Timer timer;
|
||||
auto timeout = std::chrono::duration_cast<std::chrono::milliseconds>(timeOutSec);
|
||||
auto timeout = stdx::chrono::duration_cast<stdx::chrono::milliseconds>(timeOutSec);
|
||||
for (auto intent : *intents) {
|
||||
_waitForDrain(intent, timeout);
|
||||
// Negative duration to cv::wait_for can cause undefined behavior
|
||||
@ -187,7 +187,7 @@ stdx::future<ReplicationStateTransitionGuard> IntentRegistry::killConflictingOpe
|
||||
// non-zero timeout to ever drop to 0 by setting it to at least to 1ms
|
||||
if (timeout.count()) {
|
||||
timeout -= std::min(
|
||||
std::chrono::milliseconds(durationCount<Milliseconds>(timer.elapsed())),
|
||||
stdx::chrono::milliseconds(durationCount<Milliseconds>(timer.elapsed())),
|
||||
timeout - 1ms);
|
||||
}
|
||||
}
|
||||
@ -262,7 +262,7 @@ void IntentRegistry::_killOperationsByIntent(IntentRegistry::Intent intent) {
|
||||
}
|
||||
|
||||
void IntentRegistry::_waitForDrain(IntentRegistry::Intent intent,
|
||||
std::chrono::milliseconds timeout) {
|
||||
stdx::chrono::milliseconds timeout) {
|
||||
auto& tokenMap = _tokenMaps[(size_t)intent];
|
||||
stdx::unique_lock<stdx::mutex> lock(tokenMap.lock);
|
||||
if (timeout.count() &&
|
||||
|
||||
@ -36,6 +36,7 @@
|
||||
#include "mongo/db/repl/repl_server_parameters_gen.h"
|
||||
#include "mongo/db/service_context.h"
|
||||
#include "mongo/platform/atomic_word.h"
|
||||
#include "mongo/stdx/chrono.h"
|
||||
#include "mongo/stdx/future.h"
|
||||
#include "mongo/stdx/mutex.h"
|
||||
#include "mongo/stdx/unordered_map.h"
|
||||
@ -184,7 +185,7 @@ private:
|
||||
};
|
||||
bool _validIntent(Intent intent) const;
|
||||
void _killOperationsByIntent(Intent intent);
|
||||
void _waitForDrain(Intent intent, std::chrono::milliseconds timeout);
|
||||
void _waitForDrain(Intent intent, stdx::chrono::milliseconds timeout);
|
||||
static std::string _intentToString(Intent intent);
|
||||
|
||||
bool _enabled = true;
|
||||
|
||||
@ -29,6 +29,8 @@
|
||||
|
||||
#include "mongo/db/repl/intent_guard.h"
|
||||
#include "mongo/db/repl/intent_registry_test_fixture.h"
|
||||
#include "mongo/stdx/chrono.h"
|
||||
#include "mongo/stdx/thread.h"
|
||||
|
||||
|
||||
namespace mongo {
|
||||
@ -143,7 +145,7 @@ TEST_F(IntentRegistryTest, KillConflictingOperationsStepUp) {
|
||||
guard->reset();
|
||||
}
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(kPostInterruptSleepMs));
|
||||
stdx::this_thread::sleep_for(stdx::chrono::milliseconds(kPostInterruptSleepMs));
|
||||
{
|
||||
auto clientWritePrepared = serviceContext->getService()->makeClient("testClientWrite");
|
||||
auto opCtx = clientWritePrepared->makeOperationContext();
|
||||
@ -499,7 +501,7 @@ TEST_F(IntentRegistryTest, KillConflictingOperationsShutdown) {
|
||||
}
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(kPostInterruptSleepMs));
|
||||
stdx::this_thread::sleep_for(stdx::chrono::milliseconds(kPostInterruptSleepMs));
|
||||
|
||||
// Any attempt to register an intent during a Shutdown interruption should throw an
|
||||
// exception.
|
||||
@ -593,7 +595,7 @@ TEST_F(IntentRegistryTest, KillConflictingOperationsRollback) {
|
||||
guard->reset();
|
||||
}
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(kPostInterruptSleepMs));
|
||||
stdx::this_thread::sleep_for(stdx::chrono::milliseconds(kPostInterruptSleepMs));
|
||||
|
||||
// Any attempt to register an intent during a Rollback interruption should throw an
|
||||
// exception.
|
||||
@ -686,7 +688,7 @@ TEST_F(IntentRegistryTest, KillConflictingOperationsStepDown) {
|
||||
guard->reset();
|
||||
}
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(kPostInterruptSleepMs));
|
||||
stdx::this_thread::sleep_for(stdx::chrono::milliseconds(kPostInterruptSleepMs));
|
||||
{
|
||||
auto clientWritePrepared =
|
||||
serviceContext->getService()->makeClient("testClientWritePrepared");
|
||||
|
||||
@ -37,6 +37,7 @@
|
||||
#include "mongo/db/storage/wiredtiger/spill_record_store.h"
|
||||
#include "mongo/db/storage/wiredtiger/wiredtiger_record_store_test_harness.h"
|
||||
#include "mongo/db/storage/wiredtiger/wiredtiger_util.h"
|
||||
#include "mongo/stdx/unordered_set.h"
|
||||
#include "mongo/unittest/unittest.h"
|
||||
|
||||
namespace mongo {
|
||||
@ -364,7 +365,7 @@ TEST_F(SpillRecordStoreTest, TableCreation) {
|
||||
}
|
||||
|
||||
auto allIdents = _kvEngine->getAllIdents(wtRu);
|
||||
std::unordered_set<std::string> allIdentsSet(allIdents.begin(), allIdents.end());
|
||||
stdx::unordered_set<std::string> allIdentsSet(allIdents.begin(), allIdents.end());
|
||||
ASSERT_EQ(allIdentsSet.size(), 4);
|
||||
ASSERT_TRUE(allIdentsSet.contains("a.b"));
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
|
||||
@ -55,6 +55,7 @@
|
||||
#include "mongo/db/timeseries/timeseries_test_fixture.h"
|
||||
#include "mongo/db/timeseries/write_ops/timeseries_write_ops_utils_internal.h"
|
||||
#include "mongo/stdx/thread.h"
|
||||
#include "mongo/stdx/unordered_set.h"
|
||||
#include "mongo/unittest/death_test.h"
|
||||
#include "mongo/unittest/unittest.h"
|
||||
#include "mongo/util/assert_util.h"
|
||||
@ -5583,7 +5584,7 @@ TEST_F(BucketCatalogTest, PrepareInsertsToBucketsRespectsStartIndexNoMeta) {
|
||||
BSON(_timeField << Date_t::fromMillisSinceEpoch(6)),
|
||||
};
|
||||
|
||||
std::unordered_set<size_t> expectedIndices = {2, 3, 4, 5, 6};
|
||||
stdx::unordered_set<size_t> expectedIndices = {2, 3, 4, 5, 6};
|
||||
size_t startIndex = 2;
|
||||
size_t numDocsToStage = 5;
|
||||
|
||||
@ -5607,8 +5608,8 @@ TEST_F(BucketCatalogTest, PrepareInsertsToBucketsRespectsStartIndexNoMeta) {
|
||||
|
||||
auto writeBatch = writeBatches.front();
|
||||
ASSERT_EQ(writeBatch->measurements.size(), numDocsToStage);
|
||||
ASSERT_EQ(std::unordered_set<size_t>(writeBatch->userBatchIndices.begin(),
|
||||
writeBatch->userBatchIndices.end()),
|
||||
ASSERT_EQ(stdx::unordered_set<size_t>(writeBatch->userBatchIndices.begin(),
|
||||
writeBatch->userBatchIndices.end()),
|
||||
expectedIndices);
|
||||
}
|
||||
|
||||
@ -5628,7 +5629,7 @@ TEST_F(BucketCatalogTest, PrepareInsertsToBucketsRespectsStartIndexWithMeta) {
|
||||
BSON(_metaField << _metaValue << _timeField << Date_t::fromMillisSinceEpoch(6)),
|
||||
};
|
||||
|
||||
std::unordered_set<size_t> expectedIndices = {2, 3, 4, 5, 6};
|
||||
stdx::unordered_set<size_t> expectedIndices = {2, 3, 4, 5, 6};
|
||||
size_t startIndex = 2;
|
||||
size_t numDocsToStage = 5;
|
||||
|
||||
@ -5650,7 +5651,7 @@ TEST_F(BucketCatalogTest, PrepareInsertsToBucketsRespectsStartIndexWithMeta) {
|
||||
auto writeBatches = swWriteBatches.getValue();
|
||||
ASSERT_EQ(writeBatches.size(), 3);
|
||||
|
||||
std::unordered_set<size_t> actualIndices;
|
||||
stdx::unordered_set<size_t> actualIndices;
|
||||
for (auto& batch : writeBatches) {
|
||||
for (auto index : batch->userBatchIndices) {
|
||||
actualIndices.insert(index);
|
||||
@ -5703,9 +5704,9 @@ TEST_F(BucketCatalogTest, PrepareInsertsToBucketsRespectsDocsToRetryNoMeta) {
|
||||
|
||||
auto writeBatch = writeBatches.front();
|
||||
ASSERT_EQ(writeBatch->measurements.size(), docsToRetry.size());
|
||||
ASSERT_EQ(std::unordered_set<size_t>(writeBatch->userBatchIndices.begin(),
|
||||
writeBatch->userBatchIndices.end()),
|
||||
std::unordered_set<size_t>(docsToRetry.begin(), docsToRetry.end()));
|
||||
ASSERT_EQ(stdx::unordered_set<size_t>(writeBatch->userBatchIndices.begin(),
|
||||
writeBatch->userBatchIndices.end()),
|
||||
stdx::unordered_set<size_t>(docsToRetry.begin(), docsToRetry.end()));
|
||||
}
|
||||
|
||||
TEST_F(BucketCatalogTest, PrepareInsertsToBucketsRespectsDocsToRetryWithMeta) {
|
||||
@ -5749,14 +5750,14 @@ TEST_F(BucketCatalogTest, PrepareInsertsToBucketsRespectsDocsToRetryWithMeta) {
|
||||
auto writeBatches = swWriteBatches.getValue();
|
||||
ASSERT_EQ(writeBatches.size(), 3);
|
||||
|
||||
std::unordered_set<size_t> actualIndices;
|
||||
stdx::unordered_set<size_t> actualIndices;
|
||||
for (auto& batch : writeBatches) {
|
||||
for (auto index : batch->userBatchIndices) {
|
||||
actualIndices.insert(index);
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT_EQ(actualIndices, std::unordered_set<size_t>(docsToRetry.begin(), docsToRetry.end()));
|
||||
ASSERT_EQ(actualIndices, stdx::unordered_set<size_t>(docsToRetry.begin(), docsToRetry.end()));
|
||||
}
|
||||
|
||||
TEST_F(BucketCatalogTest, CreateOrderedPotentialBucketsVectorWithoutAnyBuckets) {
|
||||
|
||||
@ -41,6 +41,7 @@
|
||||
#include "mongo/db/timeseries/write_ops/timeseries_write_ops.h"
|
||||
#include "mongo/db/transaction/session_catalog_mongod_transaction_interface_impl.h"
|
||||
#include "mongo/db/transaction/transaction_participant.h"
|
||||
#include "mongo/stdx/unordered_set.h"
|
||||
#include "mongo/unittest/unittest.h"
|
||||
#include "mongo/util/assert_util.h"
|
||||
|
||||
|
||||
@ -66,6 +66,7 @@
|
||||
#include "mongo/executor/remote_command_response.h"
|
||||
#include "mongo/logv2/log.h"
|
||||
#include "mongo/logv2/log_severity_suppressor.h"
|
||||
#include "mongo/stdx/unordered_map.h"
|
||||
#include "mongo/util/assert_util.h"
|
||||
#include "mongo/util/duration.h"
|
||||
#include "mongo/util/fail_point.h"
|
||||
@ -129,7 +130,7 @@ void TLTypeFactory::shutdown() {
|
||||
|
||||
stdx::lock_guard<stdx::mutex> lk(_mutex);
|
||||
|
||||
std::unordered_map<std::string, int> counts;
|
||||
stdx::unordered_map<std::string, int> counts;
|
||||
for (const Type* collar : _collars) {
|
||||
++counts[demangleName(typeid(collar))];
|
||||
}
|
||||
|
||||
@ -133,7 +133,7 @@ void MockNetwork::runUntilIdle() {
|
||||
} while (_net->hasReadyNetworkOperations());
|
||||
}
|
||||
|
||||
void MockNetwork::runUntilExpectationsSatisfied(std::chrono::seconds timeoutSeconds) {
|
||||
void MockNetwork::runUntilExpectationsSatisfied(stdx::chrono::seconds timeoutSeconds) {
|
||||
Timer timer;
|
||||
// If there exist extra threads beside the executor and the mock/test thread, when the
|
||||
// network is idle, the extra threads may be running and will schedule new requests. As a
|
||||
|
||||
@ -43,6 +43,7 @@
|
||||
#include "mongo/executor/network_interface_mock.h"
|
||||
#include "mongo/executor/remote_command_response.h"
|
||||
#include "mongo/logv2/log.h"
|
||||
#include "mongo/stdx/chrono.h"
|
||||
#include "mongo/stdx/thread.h"
|
||||
#include "mongo/util/assert_util.h"
|
||||
#include "mongo/util/duration.h"
|
||||
@ -375,7 +376,7 @@ public:
|
||||
// Run until both the executor and the network are idle and all expectations are satisfied.
|
||||
// Otherwise, it fatal logs after timeoutSeconds.
|
||||
void runUntilExpectationsSatisfied(
|
||||
std::chrono::seconds timeoutSeconds = std::chrono::seconds(120));
|
||||
stdx::chrono::seconds timeoutSeconds = stdx::chrono::seconds(120));
|
||||
|
||||
private:
|
||||
bool _allExpectationsSatisfied() const;
|
||||
|
||||
@ -39,6 +39,7 @@
|
||||
#include "mongo/executor/thread_pool_task_executor.h"
|
||||
#include "mongo/executor/thread_pool_task_executor_test_fixture.h"
|
||||
#include "mongo/rpc/op_msg_rpc_impls.h"
|
||||
#include "mongo/stdx/chrono.h"
|
||||
#include "mongo/transport/mock_session.h"
|
||||
#include "mongo/transport/test_fixtures.h"
|
||||
#include "mongo/transport/transport_layer.h"
|
||||
@ -133,7 +134,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
return _readyRequestCV.wait_for(lk, std::chrono::seconds(10), [&] {
|
||||
return _readyRequestCV.wait_for(lk, stdx::chrono::seconds(10), [&] {
|
||||
return _hasWaitingSinkMessage || _hasWaitingSourceMessage;
|
||||
});
|
||||
}
|
||||
|
||||
@ -29,97 +29,157 @@
|
||||
|
||||
#include "MongoPolyFillCheck.h"
|
||||
|
||||
#include <vector>
|
||||
#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",
|
||||
"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<std::string>& bannedNames) {
|
||||
const std::vector<llvm::StringRef>& bannedNames) {
|
||||
std::vector<std::string> fullyBannedNames;
|
||||
for (const auto& name : bannedNames) {
|
||||
fullyBannedNames.push_back("std::" + name);
|
||||
fullyBannedNames.push_back("boost::" + name);
|
||||
for (auto&& name : bannedNames) {
|
||||
fullyBannedNames.push_back("std::" + name.str());
|
||||
fullyBannedNames.push_back("boost::" + name.str());
|
||||
}
|
||||
return fullyBannedNames;
|
||||
}
|
||||
|
||||
// List of base polyfill names from the std and boost namespaces to be checked
|
||||
std::vector<std::string> MongoPolyFillCheck::basePolyfillNames = {"adopt_lock",
|
||||
"async",
|
||||
"chrono",
|
||||
"condition_variable",
|
||||
"condition_variable_any",
|
||||
"cv_status",
|
||||
"defer_lock",
|
||||
"future",
|
||||
"future_status",
|
||||
"get_terminate",
|
||||
"launch",
|
||||
"lock_guard",
|
||||
"mutex",
|
||||
"notify_all_at_thread_exit",
|
||||
"packaged_task",
|
||||
"promise",
|
||||
"recursive_mutex",
|
||||
"set_terminate",
|
||||
"shared_lock",
|
||||
"shared_mutex",
|
||||
"shared_timed_mutex",
|
||||
"this_thread",
|
||||
"thread",
|
||||
"timed_mutex",
|
||||
"try_to_lock",
|
||||
"unique_lock",
|
||||
"unordered_map",
|
||||
"unordered_multimap",
|
||||
"unordered_multiset",
|
||||
"unordered_set"};
|
||||
|
||||
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) {
|
||||
// Create an ArrayRef from the vector of banned names. This provides a
|
||||
// lightweight, non-owning reference to the array of names.
|
||||
std::vector<llvm::StringRef> basePolyfillNamesRefVector(basePolyfillNames.begin(),
|
||||
basePolyfillNames.end());
|
||||
llvm::ArrayRef<llvm::StringRef> basePolyfillNamesRefArray(basePolyfillNamesRefVector);
|
||||
|
||||
// Register an AST Matcher to find type declarations that use any of the banned names
|
||||
Finder->addMatcher(loc(hasUnqualifiedDesugaredType(recordType(
|
||||
hasDeclaration(namedDecl(hasAnyName(basePolyfillNamesRefArray))))))
|
||||
.bind("bannedNames"),
|
||||
// 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::check(const ast_matchers::MatchFinder::MatchResult& Result) {
|
||||
const auto* MatchedTypeLoc = Result.Nodes.getNodeAs<TypeLoc>("bannedNames");
|
||||
if (MatchedTypeLoc) {
|
||||
auto typeStr = MatchedTypeLoc->getType().getAsString();
|
||||
// we catch this_thread but not this_thread::at_thread_exit
|
||||
if (typeStr.find("this_thread::at_thread_exit") != std::string::npos)
|
||||
return;
|
||||
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 (const auto& name : fullyQualifiedPolyfillNames) {
|
||||
if ((typeStr.find("std") == 0 || typeStr.find("boost") == 0) &&
|
||||
typeStr.find(name) != std::string::npos) {
|
||||
auto location = MatchedTypeLoc->getBeginLoc();
|
||||
if (location.isValid())
|
||||
diag(MatchedTypeLoc->getBeginLoc(),
|
||||
"Illegal use of banned name from std::/boost:: for %0, use mongo::stdx:: "
|
||||
"variant instead")
|
||||
<< name;
|
||||
}
|
||||
// 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,12 +43,11 @@ namespace mongo::tidy {
|
||||
* 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;
|
||||
static std::vector<std::string> basePolyfillNames;
|
||||
void checkBannedName(clang::SourceLocation loc, llvm::StringRef name);
|
||||
|
||||
private:
|
||||
std::vector<std::string> fullyQualifiedPolyfillNames;
|
||||
|
||||
@ -406,12 +406,27 @@ class MongoTidyTests(unittest.TestCase):
|
||||
""")
|
||||
)
|
||||
|
||||
test_names = [
|
||||
"std::mutex myMutex",
|
||||
"std::lock_guard lock{myMutex, std::adopt_lock}",
|
||||
"std::adopt_lock",
|
||||
"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",
|
||||
]
|
||||
|
||||
self.expected_output = [
|
||||
"error: Illegal use of banned name from std::/boost:: for std::mutex, use mongo::stdx:: variant instead",
|
||||
"error: Illegal use of banned name from std::/boost:: for std::future, use mongo::stdx:: variant instead",
|
||||
"error: Illegal use of banned name from std::/boost:: for std::condition_variable, use mongo::stdx:: variant instead",
|
||||
"error: Illegal use of banned name from std::/boost:: for std::unordered_map, use mongo::stdx:: variant instead",
|
||||
"error: Illegal use of banned name from std::/boost:: for boost::unordered_map, use mongo::stdx:: variant instead",
|
||||
"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
|
||||
]
|
||||
|
||||
self.run_clang_tidy()
|
||||
|
||||
@ -2,11 +2,18 @@
|
||||
#include <condition_variable>
|
||||
#include <future>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace mongo {
|
||||
void mongoPolyFillCheckTest() {
|
||||
std::mutex myMutex;
|
||||
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;
|
||||
|
||||
@ -34,6 +34,8 @@
|
||||
#include <opentelemetry/sdk/trace/exporter.h>
|
||||
#include <opentelemetry/sdk/trace/recordable.h>
|
||||
|
||||
#include "mongo/stdx/unordered_map.h"
|
||||
|
||||
namespace mongo {
|
||||
namespace tracing {
|
||||
|
||||
@ -76,7 +78,7 @@ public:
|
||||
opentelemetry::trace::SpanId parentId;
|
||||
opentelemetry::trace::StatusCode status = opentelemetry::trace::StatusCode::kUnset;
|
||||
std::string name;
|
||||
std::unordered_map<std::string, opentelemetry::common::AttributeValue> attributes;
|
||||
stdx::unordered_map<std::string, opentelemetry::common::AttributeValue> attributes;
|
||||
};
|
||||
|
||||
class MockExporter : public opentelemetry::sdk::trace::SpanExporter {
|
||||
|
||||
@ -42,6 +42,7 @@
|
||||
#include <opentelemetry/trace/provider.h>
|
||||
|
||||
#include "mongo/logv2/log.h"
|
||||
#include "mongo/stdx/chrono.h"
|
||||
#include "mongo/tracing/trace_settings_gen.h"
|
||||
|
||||
#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kControl
|
||||
@ -130,7 +131,7 @@ Status initialize(std::string name) {
|
||||
void shutdown() {
|
||||
if (!gOpenTelemetryHttpEndpoint.empty() || !gOpenTelemetryTraceDirectory.empty()) {
|
||||
auto tracer = opentelemetry::trace::Provider::GetTracerProvider()->GetTracer("mongodb");
|
||||
tracer->Close(std::chrono::seconds{1});
|
||||
tracer->Close(stdx::chrono::seconds{1});
|
||||
|
||||
trace_api::Provider::SetTracerProvider({});
|
||||
}
|
||||
|
||||
@ -36,6 +36,7 @@
|
||||
#include "mongo/base/string_data.h"
|
||||
#include "mongo/logv2/log.h"
|
||||
#include "mongo/platform/atomic.h"
|
||||
#include "mongo/stdx/thread.h"
|
||||
#include "mongo/stdx/type_traits.h"
|
||||
#include "mongo/unittest/death_test.h"
|
||||
#include "mongo/unittest/unittest.h"
|
||||
@ -268,7 +269,7 @@ DEATH_TEST_F(MallocFreeOStreamGuardTest, WithBlockedSignal, "[survived][sig<0>][
|
||||
auto h0 = handlerCount.load();
|
||||
blockSignal(sig<0>, false);
|
||||
while (handlerCount.load() == h0)
|
||||
std::this_thread::yield();
|
||||
stdx::this_thread::yield();
|
||||
}
|
||||
|
||||
class BlockInsideSignalHandlerTest : public MallocFreeOStreamGuardTest {
|
||||
|
||||
@ -27,12 +27,12 @@
|
||||
* it in the license file.
|
||||
*/
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdlib>
|
||||
#include <functional>
|
||||
#include <future>
|
||||
#include <link.h>
|
||||
|
||||
#include "mongo/stdx/chrono.h"
|
||||
#include "mongo/stdx/future.h"
|
||||
#include "mongo/unittest/death_test.h"
|
||||
#include "mongo/unittest/join_thread.h"
|
||||
#include "mongo/unittest/unittest.h"
|
||||
@ -52,13 +52,13 @@ public:
|
||||
return _f.wait();
|
||||
}
|
||||
|
||||
bool waitFor(std::chrono::milliseconds dur) const {
|
||||
return _f.wait_for(dur) == std::future_status::ready;
|
||||
bool waitFor(stdx::chrono::milliseconds dur) const {
|
||||
return _f.wait_for(dur) == stdx::future_status::ready;
|
||||
}
|
||||
|
||||
private:
|
||||
std::promise<void> _p; // NOLINT
|
||||
std::future<void> _f{_p.get_future()}; // NOLINT
|
||||
stdx::promise<void> _p;
|
||||
stdx::future<void> _f{_p.get_future()};
|
||||
};
|
||||
|
||||
using OnPhdrFunc = std::function<int(dl_phdr_info*, size_t)>;
|
||||
@ -92,7 +92,7 @@ public:
|
||||
void wait() {
|
||||
return _paused.wait();
|
||||
}
|
||||
bool waitFor(std::chrono::milliseconds dur) const {
|
||||
bool waitFor(stdx::chrono::milliseconds dur) const {
|
||||
return _paused.waitFor(dur);
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user