diff options
author | vitalyisaev <vitalyisaev@yandex-team.com> | 2023-06-29 10:00:50 +0300 |
---|---|---|
committer | vitalyisaev <vitalyisaev@yandex-team.com> | 2023-06-29 10:00:50 +0300 |
commit | 6ffe9e53658409f212834330e13564e4952558f6 (patch) | |
tree | 85b1e00183517648b228aafa7c8fb07f5276f419 /contrib/libs/clang14/tools/extra/clang-tidy/performance/ForRangeCopyCheck.cpp | |
parent | 726057070f9c5a91fc10fde0d5024913d10f1ab9 (diff) | |
download | ydb-6ffe9e53658409f212834330e13564e4952558f6.tar.gz |
YQ Connector: support managed ClickHouse
Со стороны dqrun можно обратиться к инстансу коннектора, который работает на streaming стенде, и извлечь данные из облачного CH.
Diffstat (limited to 'contrib/libs/clang14/tools/extra/clang-tidy/performance/ForRangeCopyCheck.cpp')
-rw-r--r-- | contrib/libs/clang14/tools/extra/clang-tidy/performance/ForRangeCopyCheck.cpp | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/contrib/libs/clang14/tools/extra/clang-tidy/performance/ForRangeCopyCheck.cpp b/contrib/libs/clang14/tools/extra/clang-tidy/performance/ForRangeCopyCheck.cpp new file mode 100644 index 0000000000..8046301e3c --- /dev/null +++ b/contrib/libs/clang14/tools/extra/clang-tidy/performance/ForRangeCopyCheck.cpp @@ -0,0 +1,136 @@ +//===--- ForRangeCopyCheck.cpp - clang-tidy--------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "ForRangeCopyCheck.h" +#include "../utils/DeclRefExprUtils.h" +#include "../utils/FixItHintUtils.h" +#include "../utils/Matchers.h" +#include "../utils/OptionsUtils.h" +#include "../utils/TypeTraits.h" +#include "clang/Analysis/Analyses/ExprMutationAnalyzer.h" +#include "clang/Basic/Diagnostic.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace performance { + +ForRangeCopyCheck::ForRangeCopyCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), + WarnOnAllAutoCopies(Options.get("WarnOnAllAutoCopies", false)), + AllowedTypes( + utils::options::parseStringList(Options.get("AllowedTypes", ""))) {} + +void ForRangeCopyCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "WarnOnAllAutoCopies", WarnOnAllAutoCopies); + Options.store(Opts, "AllowedTypes", + utils::options::serializeStringList(AllowedTypes)); +} + +void ForRangeCopyCheck::registerMatchers(MatchFinder *Finder) { + // Match loop variables that are not references or pointers or are already + // initialized through MaterializeTemporaryExpr which indicates a type + // conversion. + auto HasReferenceOrPointerTypeOrIsAllowed = hasType(qualType( + unless(anyOf(hasCanonicalType(anyOf(referenceType(), pointerType())), + hasDeclaration(namedDecl( + matchers::matchesAnyListedName(AllowedTypes))))))); + auto IteratorReturnsValueType = cxxOperatorCallExpr( + hasOverloadedOperatorName("*"), + callee( + cxxMethodDecl(returns(unless(hasCanonicalType(referenceType())))))); + auto NotConstructedByCopy = cxxConstructExpr( + hasDeclaration(cxxConstructorDecl(unless(isCopyConstructor())))); + auto ConstructedByConversion = cxxMemberCallExpr(callee(cxxConversionDecl())); + auto LoopVar = + varDecl(HasReferenceOrPointerTypeOrIsAllowed, + unless(hasInitializer(expr(hasDescendant(expr( + anyOf(materializeTemporaryExpr(), IteratorReturnsValueType, + NotConstructedByCopy, ConstructedByConversion))))))); + Finder->addMatcher( + traverse(TK_AsIs, + cxxForRangeStmt(hasLoopVariable(LoopVar.bind("loopVar"))) + .bind("forRange")), + this); +} + +void ForRangeCopyCheck::check(const MatchFinder::MatchResult &Result) { + const auto *Var = Result.Nodes.getNodeAs<VarDecl>("loopVar"); + + // Ignore code in macros since we can't place the fixes correctly. + if (Var->getBeginLoc().isMacroID()) + return; + if (handleConstValueCopy(*Var, *Result.Context)) + return; + const auto *ForRange = Result.Nodes.getNodeAs<CXXForRangeStmt>("forRange"); + handleCopyIsOnlyConstReferenced(*Var, *ForRange, *Result.Context); +} + +bool ForRangeCopyCheck::handleConstValueCopy(const VarDecl &LoopVar, + ASTContext &Context) { + if (WarnOnAllAutoCopies) { + // For aggressive check just test that loop variable has auto type. + if (!isa<AutoType>(LoopVar.getType())) + return false; + } else if (!LoopVar.getType().isConstQualified()) { + return false; + } + llvm::Optional<bool> Expensive = + utils::type_traits::isExpensiveToCopy(LoopVar.getType(), Context); + if (!Expensive || !*Expensive) + return false; + auto Diagnostic = + diag(LoopVar.getLocation(), + "the loop variable's type is not a reference type; this creates a " + "copy in each iteration; consider making this a reference") + << utils::fixit::changeVarDeclToReference(LoopVar, Context); + if (!LoopVar.getType().isConstQualified()) { + if (llvm::Optional<FixItHint> Fix = utils::fixit::addQualifierToVarDecl( + LoopVar, Context, DeclSpec::TQ::TQ_const)) + Diagnostic << *Fix; + } + return true; +} + +bool ForRangeCopyCheck::handleCopyIsOnlyConstReferenced( + const VarDecl &LoopVar, const CXXForRangeStmt &ForRange, + ASTContext &Context) { + llvm::Optional<bool> Expensive = + utils::type_traits::isExpensiveToCopy(LoopVar.getType(), Context); + if (LoopVar.getType().isConstQualified() || !Expensive || !*Expensive) + return false; + // We omit the case where the loop variable is not used in the loop body. E.g. + // + // for (auto _ : benchmark_state) { + // } + // + // Because the fix (changing to `const auto &`) will introduce an unused + // compiler warning which can't be suppressed. + // Since this case is very rare, it is safe to ignore it. + if (!ExprMutationAnalyzer(*ForRange.getBody(), Context).isMutated(&LoopVar) && + !utils::decl_ref_expr::allDeclRefExprs(LoopVar, *ForRange.getBody(), + Context) + .empty()) { + auto Diag = diag( + LoopVar.getLocation(), + "loop variable is copied but only used as const reference; consider " + "making it a const reference"); + + if (llvm::Optional<FixItHint> Fix = utils::fixit::addQualifierToVarDecl( + LoopVar, Context, DeclSpec::TQ::TQ_const)) + Diag << *Fix << utils::fixit::changeVarDeclToReference(LoopVar, Context); + + return true; + } + return false; +} + +} // namespace performance +} // namespace tidy +} // namespace clang |