https://github.com/kuhar updated https://github.com/llvm/llvm-project/pull/177722
>From caebed302b534f4aa1e788ac05f9c5d1d9642012 Mon Sep 17 00:00:00 2001 From: Jakub Kuderski <[email protected]> Date: Fri, 23 Jan 2026 20:10:03 -0500 Subject: [PATCH 1/7] [clang-tidy] Add llvm-use-vector-utils This new check suggests the following replacements: * `llvm::to_vector(llvm::map_range(X, Fn))` -> `llvm::map_to_vector(X, Fn)` * `llvm::to_vector(llvm::make_filter_range(X, Fn))` -> `llvm::filter_to_vector(X, Fn)` and add the `SmallVectorExtras.h` include when necessary. --- .../clang-tidy/llvm/CMakeLists.txt | 1 + .../clang-tidy/llvm/LLVMTidyModule.cpp | 2 + .../clang-tidy/llvm/UseVectorUtilsCheck.cpp | 128 ++++++++++++++++++ .../clang-tidy/llvm/UseVectorUtilsCheck.h | 41 ++++++ clang-tools-extra/docs/ReleaseNotes.rst | 7 + .../docs/clang-tidy/checks/list.rst | 1 + .../checks/llvm/use-vector-utils.rst | 32 +++++ .../checkers/llvm/use-vector-utils.cpp | 103 ++++++++++++++ 8 files changed, 315 insertions(+) create mode 100644 clang-tools-extra/clang-tidy/llvm/UseVectorUtilsCheck.cpp create mode 100644 clang-tools-extra/clang-tidy/llvm/UseVectorUtilsCheck.h create mode 100644 clang-tools-extra/docs/clang-tidy/checks/llvm/use-vector-utils.rst create mode 100644 clang-tools-extra/test/clang-tidy/checkers/llvm/use-vector-utils.cpp diff --git a/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt b/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt index 78ef0444305ff..56bf4f31bd0e8 100644 --- a/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt @@ -13,6 +13,7 @@ add_clang_library(clangTidyLLVMModule STATIC TwineLocalCheck.cpp UseNewMLIROpBuilderCheck.cpp UseRangesCheck.cpp + UseVectorUtilsCheck.cpp LINK_LIBS clangTidy diff --git a/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp b/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp index 56c6db05e9792..eb1ae820dabf8 100644 --- a/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp @@ -19,6 +19,7 @@ #include "TwineLocalCheck.h" #include "UseNewMLIROpBuilderCheck.h" #include "UseRangesCheck.h" +#include "UseVectorUtilsCheck.h" namespace clang::tidy { namespace llvm_check { @@ -45,6 +46,7 @@ class LLVMModule : public ClangTidyModule { CheckFactories.registerCheck<UseNewMlirOpBuilderCheck>( "llvm-use-new-mlir-op-builder"); CheckFactories.registerCheck<UseRangesCheck>("llvm-use-ranges"); + CheckFactories.registerCheck<UseVectorUtilsCheck>("llvm-use-vector-utils"); } ClangTidyOptions getModuleOptions() override { diff --git a/clang-tools-extra/clang-tidy/llvm/UseVectorUtilsCheck.cpp b/clang-tools-extra/clang-tidy/llvm/UseVectorUtilsCheck.cpp new file mode 100644 index 0000000000000..ba377339c1cd5 --- /dev/null +++ b/clang-tools-extra/clang-tidy/llvm/UseVectorUtilsCheck.cpp @@ -0,0 +1,128 @@ +//===----------------------------------------------------------------------===// +// +// 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 "UseVectorUtilsCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Lex/Lexer.h" + +using namespace clang::ast_matchers; + +namespace clang::tidy::llvm_check { + +UseVectorUtilsCheck::UseVectorUtilsCheck(StringRef Name, + ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), + Inserter(Options.getLocalOrGlobal("IncludeStyle", + utils::IncludeSorter::IS_LLVM), + areDiagsSelfContained()) {} + +void UseVectorUtilsCheck::registerPPCallbacks(const SourceManager &SM, + Preprocessor *PP, + Preprocessor *ModuleExpanderPP) { + Inserter.registerPreprocessor(PP); +} + +void UseVectorUtilsCheck::registerMatchers(MatchFinder *Finder) { + // Match `llvm::to_vector(llvm::map_range(X, F))`. + Finder->addMatcher( + callExpr( + callee(functionDecl(hasName("::llvm::to_vector"))), + hasArgument( + 0, callExpr(callee(functionDecl(hasName("::llvm::map_range")))) + .bind("inner_call"))) + .bind("map_range_call"), + this); + + // Match `llvm::to_vector(llvm::make_filter_range(X, Pred))`. + Finder->addMatcher( + callExpr( + callee(functionDecl(hasName("::llvm::to_vector"))), + hasArgument(0, callExpr(callee(functionDecl( + hasName("::llvm::make_filter_range")))) + .bind("inner_call"))) + .bind("filter_range_call"), + this); +} + +void UseVectorUtilsCheck::check(const MatchFinder::MatchResult &Result) { + const auto *MapRangeCall = + Result.Nodes.getNodeAs<CallExpr>("map_range_call"); + const auto *FilterRangeCall = + Result.Nodes.getNodeAs<CallExpr>("filter_range_call"); + if (!MapRangeCall && !FilterRangeCall) + return; + + const auto *InnerCall = Result.Nodes.getNodeAs<CallExpr>("inner_call"); + assert(InnerCall && "inner_call must be bound if map_range_call or " + "filter_range_call matched"); + // Only handle the 2-argument overloads of `map_range`/`make_filter_range`, to + // future-proof against additional overloads. + if (InnerCall->getNumArgs() != 2) + return; + + const CallExpr *OuterCall = MapRangeCall ? MapRangeCall : FilterRangeCall; + + const SourceManager &SM = *Result.SourceManager; + const LangOptions &LangOpts = getLangOpts(); + + // Determine the base replacement function name. + const StringRef ReplacementFuncBase = + MapRangeCall ? "llvm::map_to_vector" : "llvm::filter_to_vector"; + const StringRef InnerFuncName = + MapRangeCall ? "llvm::map_range" : "llvm::make_filter_range"; + + // Check if `to_vector` was called with an explicit size template argument. + std::string SizeTemplateArg; + if (const auto *DRE = + dyn_cast<DeclRefExpr>(OuterCall->getCallee()->IgnoreImplicit())) { + if (DRE->hasExplicitTemplateArgs()) { + // Extract the template argument text (e.g., `<4>`). + const auto TemplateArgsCharRange = CharSourceRange::getTokenRange( + DRE->getLAngleLoc(), DRE->getRAngleLoc()); + SizeTemplateArg = + Lexer::getSourceText(TemplateArgsCharRange, SM, LangOpts).str(); + } + } + + const std::string ReplacementFunc = + (ReplacementFuncBase + SizeTemplateArg).str(); + const std::string ToVectorFunc = "llvm::to_vector" + SizeTemplateArg; + + // Build the replacement: Replace the whole expression with the new function + // and the arguments from the inner call. + auto Diag = diag(OuterCall->getBeginLoc(), + "use '%0' instead of '%1(%2(...))'") + << ReplacementFunc << ToVectorFunc << InnerFuncName; + + // Get the range argument. + const SourceRange RangeArgRange = InnerCall->getArg(0)->getSourceRange(); + const auto RangeArgCharRange = CharSourceRange::getTokenRange(RangeArgRange); + const StringRef RangeArgText = + Lexer::getSourceText(RangeArgCharRange, SM, LangOpts); + + // Get the function/predicate argument. + const SourceRange FuncArgRange = InnerCall->getArg(1)->getSourceRange(); + const auto FuncArgCharRange = CharSourceRange::getTokenRange(FuncArgRange); + const StringRef FuncArgText = + Lexer::getSourceText(FuncArgCharRange, SM, LangOpts); + + // Create the replacement text. + const std::string Replacement = + (ReplacementFunc + "(" + RangeArgText + ", " + FuncArgText + ")").str(); + + Diag << FixItHint::CreateReplacement(OuterCall->getSourceRange(), Replacement); + + // Add include for `SmallVectorExtras.h` if needed. + if (auto IncludeFixit = Inserter.createIncludeInsertion( + SM.getFileID(OuterCall->getBeginLoc()), + "llvm/ADT/SmallVectorExtras.h")) + Diag << *IncludeFixit; +} + +} // namespace clang::tidy::llvm_check diff --git a/clang-tools-extra/clang-tidy/llvm/UseVectorUtilsCheck.h b/clang-tools-extra/clang-tidy/llvm/UseVectorUtilsCheck.h new file mode 100644 index 0000000000000..e2a2d2fe663a1 --- /dev/null +++ b/clang-tools-extra/clang-tidy/llvm/UseVectorUtilsCheck.h @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_USEVECTORUTILSCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_USEVECTORUTILSCHECK_H + +#include "../ClangTidyCheck.h" +#include "../utils/IncludeInserter.h" + +namespace clang::tidy::llvm_check { + +/// Finds calls to `llvm::to_vector(llvm::map_range(...))` and +/// `llvm::to_vector(llvm::make_filter_range(...))` that can be replaced with +/// `llvm::map_to_vector` and `llvm::filter_to_vector` from `SmallVectorExtras.h`. +/// +/// For the user-facing documentation see: +/// https://clang.llvm.org/extra/clang-tidy/checks/llvm/use-vector-utils.html +class UseVectorUtilsCheck : public ClangTidyCheck { +public: + UseVectorUtilsCheck(StringRef Name, ClangTidyContext *Context); + bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { + return LangOpts.CPlusPlus; + } + void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP, + Preprocessor *ModuleExpanderPP) override; + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + +private: + utils::IncludeInserter Inserter; +}; + +} // namespace clang::tidy::llvm_check + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_USEVECTORUTILSCHECK_H + diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 1e5d4ef5dbb3b..3b3a033f069ef 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -97,6 +97,13 @@ Improvements to clang-tidy New checks ^^^^^^^^^^ +- New :doc:`llvm-use-vector-utils + <clang-tidy/checks/llvm/use-vector-utils>` check. + + Finds calls to ``llvm::to_vector(llvm::map_range(...))`` and + ``llvm::to_vector(llvm::make_filter_range(...))`` that can be replaced with + ``llvm::map_to_vector`` and ``llvm::filter_to_vector``. + - New :doc:`modernize-use-string-view <clang-tidy/checks/modernize/use-string-view>` check. diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index a34fade4b8027..25d1354fc4c20 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -258,6 +258,7 @@ Clang-Tidy Checks :doc:`llvm-twine-local <llvm/twine-local>`, "Yes" :doc:`llvm-use-new-mlir-op-builder <llvm/use-new-mlir-op-builder>`, "Yes" :doc:`llvm-use-ranges <llvm/use-ranges>`, "Yes" + :doc:`llvm-use-vector-utils <llvm/use-vector-utils>`, "Yes" :doc:`llvmlibc-callee-namespace <llvmlibc/callee-namespace>`, :doc:`llvmlibc-implementation-in-namespace <llvmlibc/implementation-in-namespace>`, :doc:`llvmlibc-inline-function-decl <llvmlibc/inline-function-decl>`, "Yes" diff --git a/clang-tools-extra/docs/clang-tidy/checks/llvm/use-vector-utils.rst b/clang-tools-extra/docs/clang-tidy/checks/llvm/use-vector-utils.rst new file mode 100644 index 0000000000000..2c0d429be7fca --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/llvm/use-vector-utils.rst @@ -0,0 +1,32 @@ +.. title:: clang-tidy - llvm-use-vector-utils + +llvm-use-vector-utils +===================== + +Finds calls to ``llvm::to_vector`` with ``llvm::map_range`` or +``llvm::make_filter_range`` that can be replaced with the more concise +``llvm::map_to_vector`` and ``llvm::filter_to_vector`` utilities from +``llvm/ADT/SmallVectorExtras.h``. + +The check will add the necessary ``#include "llvm/ADT/SmallVectorExtras.h"`` +directive when applying fixes. + +Example +------- + +.. code-block:: c++ + + auto v1 = llvm::to_vector(llvm::map_range(container, func)); + auto v2 = llvm::to_vector(llvm::make_filter_range(container, pred)); + auto v3 = llvm::to_vector<4>(llvm::map_range(container, func)); + auto v4 = llvm::to_vector<4>(llvm::make_filter_range(container, pred)); + +Transforms to: + +.. code-block:: c++ + + auto v1 = llvm::map_to_vector(container, func); + auto v2 = llvm::filter_to_vector(container, pred); + auto v3 = llvm::map_to_vector<4>(container, func); + auto v4 = llvm::filter_to_vector<4>(container, pred); + diff --git a/clang-tools-extra/test/clang-tidy/checkers/llvm/use-vector-utils.cpp b/clang-tools-extra/test/clang-tidy/checkers/llvm/use-vector-utils.cpp new file mode 100644 index 0000000000000..b69f6824d13a4 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/llvm/use-vector-utils.cpp @@ -0,0 +1,103 @@ +// RUN: %check_clang_tidy %s llvm-use-vector-utils %t + +// CHECK-FIXES: #include "llvm/ADT/SmallVectorExtras.h" + +namespace llvm { + +template <typename T> class SmallVector {}; + +template <typename RangeT> +SmallVector<int> to_vector(RangeT &&Range); + +template <unsigned Size, typename RangeT> +SmallVector<int> to_vector(RangeT &&Range); + +template <typename Out, typename RangeT> +SmallVector<Out> to_vector_of(RangeT &&Range); + +template <typename Out, unsigned Size, typename RangeT> +SmallVector<Out> to_vector_of(RangeT &&Range); + +template <typename ContainerT, typename FuncT> +struct mapped_range {}; + +template <typename ContainerT, typename FuncT> +mapped_range<ContainerT, FuncT> map_range(ContainerT &&C, FuncT &&F); + +// Hypothetical 3-arg overload (for future-proofing). +template <typename ContainerT, typename FuncT, typename ExtraT> +mapped_range<ContainerT, FuncT> map_range(ContainerT &&C, FuncT &&F, ExtraT &&E); + +template <typename ContainerT, typename PredT> +struct filter_range {}; + +template <typename ContainerT, typename PredT> +filter_range<ContainerT, PredT> make_filter_range(ContainerT &&C, PredT &&P); + +// Hypothetical 3-arg overload (for future-proofing). +template <typename ContainerT, typename PredT, typename ExtraT> +filter_range<ContainerT, PredT> make_filter_range(ContainerT &&C, PredT &&P, ExtraT &&E); + +} // namespace llvm + +int transform(int x); +bool is_even(int x); + +void test_map_range() { + llvm::SmallVector<int> vec; + + auto result = llvm::to_vector(llvm::map_range(vec, transform)); + // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use 'llvm::map_to_vector' instead of 'llvm::to_vector(llvm::map_range(...))' + // CHECK-FIXES: auto result = llvm::map_to_vector(vec, transform); + + auto result_sized = llvm::to_vector<4>(llvm::map_range(vec, transform)); + // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use 'llvm::map_to_vector<4>' instead of 'llvm::to_vector<4>(llvm::map_range(...))' + // CHECK-FIXES: auto result_sized = llvm::map_to_vector<4>(vec, transform); +} + +void test_filter_range() { + llvm::SmallVector<int> vec; + + auto result = llvm::to_vector(llvm::make_filter_range(vec, is_even)); + // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use 'llvm::filter_to_vector' instead of 'llvm::to_vector(llvm::make_filter_range(...))' + // CHECK-FIXES: auto result = llvm::filter_to_vector(vec, is_even); + + auto result_sized = llvm::to_vector<6>(llvm::make_filter_range(vec, is_even)); + // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use 'llvm::filter_to_vector<6>' instead of 'llvm::to_vector<6>(llvm::make_filter_range(...))' + // CHECK-FIXES: auto result_sized = llvm::filter_to_vector<6>(vec, is_even); +} + +namespace llvm { + +void test_inside_llvm_namespace() { + SmallVector<int> vec; + + // Unprefixed calls inside the `llvm` namespace should also be detected. + auto result = to_vector(map_range(vec, transform)); + // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use 'llvm::map_to_vector' instead of 'llvm::to_vector(llvm::map_range(...))' + // CHECK-FIXES: auto result = llvm::map_to_vector(vec, transform); +} + +} // namespace llvm + +void test_negative() { + llvm::SmallVector<int> vec; + + // `to_vector` without inner `map_range`/`make_filter_range` should not trigger. + auto result1 = llvm::to_vector(vec); + auto result2 = llvm::to_vector<4>(vec); + + // Direct use of `map_range`/`make_filter_range` without `to_vector` should not trigger. + auto mapped = llvm::map_range(vec, transform); + auto filtered = llvm::make_filter_range(vec, is_even); + + // `to_vector_of` variants should not trigger (no `map_to_vector_of` exists). + auto result3 = llvm::to_vector_of<long>(llvm::map_range(vec, transform)); + auto result4 = llvm::to_vector_of<long, 4>(llvm::map_range(vec, transform)); + auto result5 = llvm::to_vector_of<long>(llvm::make_filter_range(vec, is_even)); + auto result6 = llvm::to_vector_of<long, 4>(llvm::make_filter_range(vec, is_even)); + + // Hypothetical 3-arg overloads should not trigger. + auto result7 = llvm::to_vector(llvm::map_range(vec, transform, 0)); + auto result8 = llvm::to_vector(llvm::make_filter_range(vec, is_even, 0)); +} >From 28447e42ba1abf2c2f16b275f5d14bf55509fb2a Mon Sep 17 00:00:00 2001 From: Jakub Kuderski <[email protected]> Date: Fri, 23 Jan 2026 20:21:47 -0500 Subject: [PATCH 2/7] Format --- .../clang-tidy/llvm/UseVectorUtilsCheck.cpp | 30 +++++++++---------- .../clang-tidy/llvm/UseVectorUtilsCheck.h | 4 +-- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/clang-tools-extra/clang-tidy/llvm/UseVectorUtilsCheck.cpp b/clang-tools-extra/clang-tidy/llvm/UseVectorUtilsCheck.cpp index ba377339c1cd5..2727f91e63fd4 100644 --- a/clang-tools-extra/clang-tidy/llvm/UseVectorUtilsCheck.cpp +++ b/clang-tools-extra/clang-tidy/llvm/UseVectorUtilsCheck.cpp @@ -31,28 +31,25 @@ void UseVectorUtilsCheck::registerPPCallbacks(const SourceManager &SM, void UseVectorUtilsCheck::registerMatchers(MatchFinder *Finder) { // Match `llvm::to_vector(llvm::map_range(X, F))`. Finder->addMatcher( - callExpr( - callee(functionDecl(hasName("::llvm::to_vector"))), - hasArgument( - 0, callExpr(callee(functionDecl(hasName("::llvm::map_range")))) - .bind("inner_call"))) + callExpr(callee(functionDecl(hasName("::llvm::to_vector"))), + hasArgument(0, callExpr(callee(functionDecl( + hasName("::llvm::map_range")))) + .bind("inner_call"))) .bind("map_range_call"), this); // Match `llvm::to_vector(llvm::make_filter_range(X, Pred))`. Finder->addMatcher( - callExpr( - callee(functionDecl(hasName("::llvm::to_vector"))), - hasArgument(0, callExpr(callee(functionDecl( - hasName("::llvm::make_filter_range")))) - .bind("inner_call"))) + callExpr(callee(functionDecl(hasName("::llvm::to_vector"))), + hasArgument(0, callExpr(callee(functionDecl(hasName( + "::llvm::make_filter_range")))) + .bind("inner_call"))) .bind("filter_range_call"), this); } void UseVectorUtilsCheck::check(const MatchFinder::MatchResult &Result) { - const auto *MapRangeCall = - Result.Nodes.getNodeAs<CallExpr>("map_range_call"); + const auto *MapRangeCall = Result.Nodes.getNodeAs<CallExpr>("map_range_call"); const auto *FilterRangeCall = Result.Nodes.getNodeAs<CallExpr>("filter_range_call"); if (!MapRangeCall && !FilterRangeCall) @@ -96,9 +93,9 @@ void UseVectorUtilsCheck::check(const MatchFinder::MatchResult &Result) { // Build the replacement: Replace the whole expression with the new function // and the arguments from the inner call. - auto Diag = diag(OuterCall->getBeginLoc(), - "use '%0' instead of '%1(%2(...))'") - << ReplacementFunc << ToVectorFunc << InnerFuncName; + auto Diag = + diag(OuterCall->getBeginLoc(), "use '%0' instead of '%1(%2(...))'") + << ReplacementFunc << ToVectorFunc << InnerFuncName; // Get the range argument. const SourceRange RangeArgRange = InnerCall->getArg(0)->getSourceRange(); @@ -116,7 +113,8 @@ void UseVectorUtilsCheck::check(const MatchFinder::MatchResult &Result) { const std::string Replacement = (ReplacementFunc + "(" + RangeArgText + ", " + FuncArgText + ")").str(); - Diag << FixItHint::CreateReplacement(OuterCall->getSourceRange(), Replacement); + Diag << FixItHint::CreateReplacement(OuterCall->getSourceRange(), + Replacement); // Add include for `SmallVectorExtras.h` if needed. if (auto IncludeFixit = Inserter.createIncludeInsertion( diff --git a/clang-tools-extra/clang-tidy/llvm/UseVectorUtilsCheck.h b/clang-tools-extra/clang-tidy/llvm/UseVectorUtilsCheck.h index e2a2d2fe663a1..557025856a09a 100644 --- a/clang-tools-extra/clang-tidy/llvm/UseVectorUtilsCheck.h +++ b/clang-tools-extra/clang-tidy/llvm/UseVectorUtilsCheck.h @@ -16,7 +16,8 @@ namespace clang::tidy::llvm_check { /// Finds calls to `llvm::to_vector(llvm::map_range(...))` and /// `llvm::to_vector(llvm::make_filter_range(...))` that can be replaced with -/// `llvm::map_to_vector` and `llvm::filter_to_vector` from `SmallVectorExtras.h`. +/// `llvm::map_to_vector` and `llvm::filter_to_vector` from +/// `SmallVectorExtras.h`. /// /// For the user-facing documentation see: /// https://clang.llvm.org/extra/clang-tidy/checks/llvm/use-vector-utils.html @@ -38,4 +39,3 @@ class UseVectorUtilsCheck : public ClangTidyCheck { } // namespace clang::tidy::llvm_check #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_USEVECTORUTILSCHECK_H - >From dbd41413b38c3cf7cd0cb8f36de680122dad7382 Mon Sep 17 00:00:00 2001 From: Jakub Kuderski <[email protected]> Date: Fri, 23 Jan 2026 20:37:55 -0500 Subject: [PATCH 3/7] Format --- .../docs/clang-tidy/checks/llvm/use-vector-utils.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/clang-tools-extra/docs/clang-tidy/checks/llvm/use-vector-utils.rst b/clang-tools-extra/docs/clang-tidy/checks/llvm/use-vector-utils.rst index 2c0d429be7fca..5fddc68f4a614 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/llvm/use-vector-utils.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/llvm/use-vector-utils.rst @@ -29,4 +29,3 @@ Transforms to: auto v2 = llvm::filter_to_vector(container, pred); auto v3 = llvm::map_to_vector<4>(container, func); auto v4 = llvm::filter_to_vector<4>(container, pred); - >From 616337da3b0f61d9049fad2ef41b2b28ed58b433 Mon Sep 17 00:00:00 2001 From: Jakub Kuderski <[email protected]> Date: Sat, 24 Jan 2026 09:26:38 -0500 Subject: [PATCH 4/7] Address comments --- .../clang-tidy/llvm/UseVectorUtilsCheck.cpp | 130 +++++++----------- .../checkers/llvm/use-vector-utils.cpp | 16 ++- 2 files changed, 63 insertions(+), 83 deletions(-) diff --git a/clang-tools-extra/clang-tidy/llvm/UseVectorUtilsCheck.cpp b/clang-tools-extra/clang-tidy/llvm/UseVectorUtilsCheck.cpp index 2727f91e63fd4..78543d9b58144 100644 --- a/clang-tools-extra/clang-tidy/llvm/UseVectorUtilsCheck.cpp +++ b/clang-tools-extra/clang-tidy/llvm/UseVectorUtilsCheck.cpp @@ -18,9 +18,7 @@ namespace clang::tidy::llvm_check { UseVectorUtilsCheck::UseVectorUtilsCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), - Inserter(Options.getLocalOrGlobal("IncludeStyle", - utils::IncludeSorter::IS_LLVM), - areDiagsSelfContained()) {} + Inserter(utils::IncludeSorter::IS_LLVM, areDiagsSelfContained()) {} void UseVectorUtilsCheck::registerPPCallbacks(const SourceManager &SM, Preprocessor *PP, @@ -29,94 +27,72 @@ void UseVectorUtilsCheck::registerPPCallbacks(const SourceManager &SM, } void UseVectorUtilsCheck::registerMatchers(MatchFinder *Finder) { - // Match `llvm::to_vector(llvm::map_range(X, F))`. + // Match `llvm::to_vector(llvm::map_range(X, F))` or + // `llvm::to_vector(llvm::make_filter_range(X, Pred))`. Finder->addMatcher( callExpr(callee(functionDecl(hasName("::llvm::to_vector"))), - hasArgument(0, callExpr(callee(functionDecl( - hasName("::llvm::map_range")))) - .bind("inner_call"))) - .bind("map_range_call"), + hasArgument(0, callExpr(callee(functionDecl(hasAnyName( + "::llvm::map_range", + "::llvm::make_filter_range"))), + argumentCountIs(2)) + .bind("inner_call")), + argumentCountIs(1)) + .bind("outer_call"), this); +} - // Match `llvm::to_vector(llvm::make_filter_range(X, Pred))`. - Finder->addMatcher( - callExpr(callee(functionDecl(hasName("::llvm::to_vector"))), - hasArgument(0, callExpr(callee(functionDecl(hasName( - "::llvm::make_filter_range")))) - .bind("inner_call"))) - .bind("filter_range_call"), - this); +// Returns the original qualifier spelling (e.g., `llvm::` or `::llvm::`) for +// the diagnostic message. +static StringRef getQualifierSpelling(const DeclRefExpr *DeclRef, + const MatchFinder::MatchResult &Result) { + if (const auto QualifierLoc = DeclRef->getQualifierLoc()) { + return Lexer::getSourceText( + CharSourceRange::getTokenRange(QualifierLoc.getSourceRange()), + *Result.SourceManager, Result.Context->getLangOpts()); + } + return ""; } void UseVectorUtilsCheck::check(const MatchFinder::MatchResult &Result) { - const auto *MapRangeCall = Result.Nodes.getNodeAs<CallExpr>("map_range_call"); - const auto *FilterRangeCall = - Result.Nodes.getNodeAs<CallExpr>("filter_range_call"); - if (!MapRangeCall && !FilterRangeCall) - return; + const auto *OuterCall = Result.Nodes.getNodeAs<CallExpr>("outer_call"); + assert(OuterCall); const auto *InnerCall = Result.Nodes.getNodeAs<CallExpr>("inner_call"); - assert(InnerCall && "inner_call must be bound if map_range_call or " - "filter_range_call matched"); - // Only handle the 2-argument overloads of `map_range`/`make_filter_range`, to - // future-proof against additional overloads. - if (InnerCall->getNumArgs() != 2) - return; - - const CallExpr *OuterCall = MapRangeCall ? MapRangeCall : FilterRangeCall; + assert(InnerCall); - const SourceManager &SM = *Result.SourceManager; - const LangOptions &LangOpts = getLangOpts(); + const auto *OuterCallee = + cast<DeclRefExpr>(OuterCall->getCallee()->IgnoreImplicit()); + const auto *InnerCallee = + cast<DeclRefExpr>(InnerCall->getCallee()->IgnoreImplicit()); - // Determine the base replacement function name. - const StringRef ReplacementFuncBase = - MapRangeCall ? "llvm::map_to_vector" : "llvm::filter_to_vector"; const StringRef InnerFuncName = - MapRangeCall ? "llvm::map_range" : "llvm::make_filter_range"; - - // Check if `to_vector` was called with an explicit size template argument. - std::string SizeTemplateArg; - if (const auto *DRE = - dyn_cast<DeclRefExpr>(OuterCall->getCallee()->IgnoreImplicit())) { - if (DRE->hasExplicitTemplateArgs()) { - // Extract the template argument text (e.g., `<4>`). - const auto TemplateArgsCharRange = CharSourceRange::getTokenRange( - DRE->getLAngleLoc(), DRE->getRAngleLoc()); - SizeTemplateArg = - Lexer::getSourceText(TemplateArgsCharRange, SM, LangOpts).str(); - } - } - - const std::string ReplacementFunc = - (ReplacementFuncBase + SizeTemplateArg).str(); - const std::string ToVectorFunc = "llvm::to_vector" + SizeTemplateArg; - - // Build the replacement: Replace the whole expression with the new function - // and the arguments from the inner call. - auto Diag = - diag(OuterCall->getBeginLoc(), "use '%0' instead of '%1(%2(...))'") - << ReplacementFunc << ToVectorFunc << InnerFuncName; - - // Get the range argument. - const SourceRange RangeArgRange = InnerCall->getArg(0)->getSourceRange(); - const auto RangeArgCharRange = CharSourceRange::getTokenRange(RangeArgRange); - const StringRef RangeArgText = - Lexer::getSourceText(RangeArgCharRange, SM, LangOpts); - - // Get the function/predicate argument. - const SourceRange FuncArgRange = InnerCall->getArg(1)->getSourceRange(); - const auto FuncArgCharRange = CharSourceRange::getTokenRange(FuncArgRange); - const StringRef FuncArgText = - Lexer::getSourceText(FuncArgCharRange, SM, LangOpts); - - // Create the replacement text. - const std::string Replacement = - (ReplacementFunc + "(" + RangeArgText + ", " + FuncArgText + ")").str(); - - Diag << FixItHint::CreateReplacement(OuterCall->getSourceRange(), - Replacement); + cast<NamedDecl>(InnerCallee->getDecl())->getName(); + + // Determine the replacement function name (unqualified). + const llvm::SmallDenseMap<StringRef, StringRef, 2> + InnerFuncNameToReplacementFuncName = { + {"map_range", "map_to_vector"}, + {"make_filter_range", "filter_to_vector"}, + }; + const StringRef ReplacementFuncName = + InnerFuncNameToReplacementFuncName.lookup(InnerFuncName); + assert(!ReplacementFuncName.empty() && "Unhandled function?"); + + auto Diag = diag(OuterCall->getBeginLoc(), "use '%0%1'") + << getQualifierSpelling(OuterCallee, Result) + << ReplacementFuncName; + + // Replace only the unqualified function name, preserving qualifier and + // template arguments. + const auto InnerCallUntilFirstArg = CharSourceRange::getCharRange( + InnerCall->getBeginLoc(), InnerCall->getArg(0)->getBeginLoc()); + Diag << FixItHint::CreateReplacement( + OuterCallee->getNameInfo().getSourceRange(), ReplacementFuncName) + << FixItHint::CreateRemoval(InnerCallUntilFirstArg) + << FixItHint::CreateRemoval(InnerCall->getRParenLoc()); // Add include for `SmallVectorExtras.h` if needed. + const SourceManager &SM = *Result.SourceManager; if (auto IncludeFixit = Inserter.createIncludeInsertion( SM.getFileID(OuterCall->getBeginLoc()), "llvm/ADT/SmallVectorExtras.h")) diff --git a/clang-tools-extra/test/clang-tidy/checkers/llvm/use-vector-utils.cpp b/clang-tools-extra/test/clang-tidy/checkers/llvm/use-vector-utils.cpp index b69f6824d13a4..b0f71614f7bec 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/llvm/use-vector-utils.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/llvm/use-vector-utils.cpp @@ -47,23 +47,27 @@ void test_map_range() { llvm::SmallVector<int> vec; auto result = llvm::to_vector(llvm::map_range(vec, transform)); - // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use 'llvm::map_to_vector' instead of 'llvm::to_vector(llvm::map_range(...))' + // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use 'llvm::map_to_vector' // CHECK-FIXES: auto result = llvm::map_to_vector(vec, transform); auto result_sized = llvm::to_vector<4>(llvm::map_range(vec, transform)); - // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use 'llvm::map_to_vector<4>' instead of 'llvm::to_vector<4>(llvm::map_range(...))' + // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use 'llvm::map_to_vector' // CHECK-FIXES: auto result_sized = llvm::map_to_vector<4>(vec, transform); + + auto result_global = ::llvm::to_vector(::llvm::map_range(vec, transform)); + // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use '::llvm::map_to_vector' + // CHECK-FIXES: auto result_global = ::llvm::map_to_vector(vec, transform); } void test_filter_range() { llvm::SmallVector<int> vec; auto result = llvm::to_vector(llvm::make_filter_range(vec, is_even)); - // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use 'llvm::filter_to_vector' instead of 'llvm::to_vector(llvm::make_filter_range(...))' + // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use 'llvm::filter_to_vector' // CHECK-FIXES: auto result = llvm::filter_to_vector(vec, is_even); auto result_sized = llvm::to_vector<6>(llvm::make_filter_range(vec, is_even)); - // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use 'llvm::filter_to_vector<6>' instead of 'llvm::to_vector<6>(llvm::make_filter_range(...))' + // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use 'llvm::filter_to_vector' // CHECK-FIXES: auto result_sized = llvm::filter_to_vector<6>(vec, is_even); } @@ -74,8 +78,8 @@ void test_inside_llvm_namespace() { // Unprefixed calls inside the `llvm` namespace should also be detected. auto result = to_vector(map_range(vec, transform)); - // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use 'llvm::map_to_vector' instead of 'llvm::to_vector(llvm::map_range(...))' - // CHECK-FIXES: auto result = llvm::map_to_vector(vec, transform); + // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use 'map_to_vector' + // CHECK-FIXES: auto result = map_to_vector(vec, transform); } } // namespace llvm >From 0363df9b347f8d0866d2661519c2663aeacb05ee Mon Sep 17 00:00:00 2001 From: Jakub Kuderski <[email protected]> Date: Sat, 24 Jan 2026 09:37:00 -0500 Subject: [PATCH 5/7] Simplify diagnostic --- .../clang-tidy/llvm/UseVectorUtilsCheck.cpp | 31 +++++-------------- .../checkers/llvm/use-vector-utils.cpp | 10 +++--- 2 files changed, 12 insertions(+), 29 deletions(-) diff --git a/clang-tools-extra/clang-tidy/llvm/UseVectorUtilsCheck.cpp b/clang-tools-extra/clang-tidy/llvm/UseVectorUtilsCheck.cpp index 78543d9b58144..a6de8630172c8 100644 --- a/clang-tools-extra/clang-tidy/llvm/UseVectorUtilsCheck.cpp +++ b/clang-tools-extra/clang-tidy/llvm/UseVectorUtilsCheck.cpp @@ -9,7 +9,6 @@ #include "UseVectorUtilsCheck.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" -#include "clang/Lex/Lexer.h" using namespace clang::ast_matchers; @@ -41,18 +40,6 @@ void UseVectorUtilsCheck::registerMatchers(MatchFinder *Finder) { this); } -// Returns the original qualifier spelling (e.g., `llvm::` or `::llvm::`) for -// the diagnostic message. -static StringRef getQualifierSpelling(const DeclRefExpr *DeclRef, - const MatchFinder::MatchResult &Result) { - if (const auto QualifierLoc = DeclRef->getQualifierLoc()) { - return Lexer::getSourceText( - CharSourceRange::getTokenRange(QualifierLoc.getSourceRange()), - *Result.SourceManager, Result.Context->getLangOpts()); - } - return ""; -} - void UseVectorUtilsCheck::check(const MatchFinder::MatchResult &Result) { const auto *OuterCall = Result.Nodes.getNodeAs<CallExpr>("outer_call"); assert(OuterCall); @@ -62,11 +49,9 @@ void UseVectorUtilsCheck::check(const MatchFinder::MatchResult &Result) { const auto *OuterCallee = cast<DeclRefExpr>(OuterCall->getCallee()->IgnoreImplicit()); - const auto *InnerCallee = - cast<DeclRefExpr>(InnerCall->getCallee()->IgnoreImplicit()); const StringRef InnerFuncName = - cast<NamedDecl>(InnerCallee->getDecl())->getName(); + cast<NamedDecl>(InnerCall->getCalleeDecl())->getName(); // Determine the replacement function name (unqualified). const llvm::SmallDenseMap<StringRef, StringRef, 2> @@ -78,17 +63,15 @@ void UseVectorUtilsCheck::check(const MatchFinder::MatchResult &Result) { InnerFuncNameToReplacementFuncName.lookup(InnerFuncName); assert(!ReplacementFuncName.empty() && "Unhandled function?"); - auto Diag = diag(OuterCall->getBeginLoc(), "use '%0%1'") - << getQualifierSpelling(OuterCallee, Result) - << ReplacementFuncName; + auto Diag = diag(OuterCall->getBeginLoc(), "use '%0'") << ReplacementFuncName; - // Replace only the unqualified function name, preserving qualifier and - // template arguments. - const auto InnerCallUntilFirstArg = CharSourceRange::getCharRange( - InnerCall->getBeginLoc(), InnerCall->getArg(0)->getBeginLoc()); + // Replace the outer function name (preserving qualifier and template args), + // and then remove the inner call's callee and opening paren and closing + // paren. Diag << FixItHint::CreateReplacement( OuterCallee->getNameInfo().getSourceRange(), ReplacementFuncName) - << FixItHint::CreateRemoval(InnerCallUntilFirstArg) + << FixItHint::CreateRemoval(CharSourceRange::getCharRange( + InnerCall->getBeginLoc(), InnerCall->getArg(0)->getBeginLoc())) << FixItHint::CreateRemoval(InnerCall->getRParenLoc()); // Add include for `SmallVectorExtras.h` if needed. diff --git a/clang-tools-extra/test/clang-tidy/checkers/llvm/use-vector-utils.cpp b/clang-tools-extra/test/clang-tidy/checkers/llvm/use-vector-utils.cpp index b0f71614f7bec..817db689378ee 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/llvm/use-vector-utils.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/llvm/use-vector-utils.cpp @@ -47,15 +47,15 @@ void test_map_range() { llvm::SmallVector<int> vec; auto result = llvm::to_vector(llvm::map_range(vec, transform)); - // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use 'llvm::map_to_vector' + // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use 'map_to_vector' // CHECK-FIXES: auto result = llvm::map_to_vector(vec, transform); auto result_sized = llvm::to_vector<4>(llvm::map_range(vec, transform)); - // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use 'llvm::map_to_vector' + // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use 'map_to_vector' // CHECK-FIXES: auto result_sized = llvm::map_to_vector<4>(vec, transform); auto result_global = ::llvm::to_vector(::llvm::map_range(vec, transform)); - // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use '::llvm::map_to_vector' + // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use 'map_to_vector' // CHECK-FIXES: auto result_global = ::llvm::map_to_vector(vec, transform); } @@ -63,11 +63,11 @@ void test_filter_range() { llvm::SmallVector<int> vec; auto result = llvm::to_vector(llvm::make_filter_range(vec, is_even)); - // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use 'llvm::filter_to_vector' + // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use 'filter_to_vector' // CHECK-FIXES: auto result = llvm::filter_to_vector(vec, is_even); auto result_sized = llvm::to_vector<6>(llvm::make_filter_range(vec, is_even)); - // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use 'llvm::filter_to_vector' + // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use 'filter_to_vector' // CHECK-FIXES: auto result_sized = llvm::filter_to_vector<6>(vec, is_even); } >From a3b31bd76107a8ff773d14157db9f59b68389559 Mon Sep 17 00:00:00 2001 From: Jakub Kuderski <[email protected]> Date: Sat, 24 Jan 2026 09:48:15 -0500 Subject: [PATCH 6/7] Add example --- clang-tools-extra/clang-tidy/llvm/UseVectorUtilsCheck.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/clang-tools-extra/clang-tidy/llvm/UseVectorUtilsCheck.cpp b/clang-tools-extra/clang-tidy/llvm/UseVectorUtilsCheck.cpp index a6de8630172c8..a5519429f9f73 100644 --- a/clang-tools-extra/clang-tidy/llvm/UseVectorUtilsCheck.cpp +++ b/clang-tools-extra/clang-tidy/llvm/UseVectorUtilsCheck.cpp @@ -67,7 +67,12 @@ void UseVectorUtilsCheck::check(const MatchFinder::MatchResult &Result) { // Replace the outer function name (preserving qualifier and template args), // and then remove the inner call's callee and opening paren and closing - // paren. + // paren. Example: + // ``` + // llvm::to_vector<4>(llvm::map_range(X, F)) + // ^replace~^ ^----remove-----^ ^ + // remove + // ``` Diag << FixItHint::CreateReplacement( OuterCallee->getNameInfo().getSourceRange(), ReplacementFuncName) << FixItHint::CreateRemoval(CharSourceRange::getCharRange( >From 8980bd26874dd51d1f69dc96f7fc29028a780aee Mon Sep 17 00:00:00 2001 From: Jakub Kuderski <[email protected]> Date: Sat, 24 Jan 2026 10:41:46 -0500 Subject: [PATCH 7/7] Preserve comments --- .../clang-tidy/llvm/UseVectorUtilsCheck.cpp | 7 +++++-- .../clang-tidy/checkers/llvm/use-vector-utils.cpp | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/clang-tools-extra/clang-tidy/llvm/UseVectorUtilsCheck.cpp b/clang-tools-extra/clang-tidy/llvm/UseVectorUtilsCheck.cpp index a5519429f9f73..e4e1717816b23 100644 --- a/clang-tools-extra/clang-tidy/llvm/UseVectorUtilsCheck.cpp +++ b/clang-tools-extra/clang-tidy/llvm/UseVectorUtilsCheck.cpp @@ -9,6 +9,7 @@ #include "UseVectorUtilsCheck.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Lex/Lexer.h" using namespace clang::ast_matchers; @@ -73,14 +74,16 @@ void UseVectorUtilsCheck::check(const MatchFinder::MatchResult &Result) { // ^replace~^ ^----remove-----^ ^ // remove // ``` + const SourceManager &SM = *Result.SourceManager; + const SourceLocation InnerLParenEnd = Lexer::getLocForEndOfToken( + InnerCall->getCallee()->getEndLoc(), 0, SM, getLangOpts()); Diag << FixItHint::CreateReplacement( OuterCallee->getNameInfo().getSourceRange(), ReplacementFuncName) << FixItHint::CreateRemoval(CharSourceRange::getCharRange( - InnerCall->getBeginLoc(), InnerCall->getArg(0)->getBeginLoc())) + InnerCall->getBeginLoc(), InnerLParenEnd.getLocWithOffset(1))) << FixItHint::CreateRemoval(InnerCall->getRParenLoc()); // Add include for `SmallVectorExtras.h` if needed. - const SourceManager &SM = *Result.SourceManager; if (auto IncludeFixit = Inserter.createIncludeInsertion( SM.getFileID(OuterCall->getBeginLoc()), "llvm/ADT/SmallVectorExtras.h")) diff --git a/clang-tools-extra/test/clang-tidy/checkers/llvm/use-vector-utils.cpp b/clang-tools-extra/test/clang-tidy/checkers/llvm/use-vector-utils.cpp index 817db689378ee..788b5e835c80e 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/llvm/use-vector-utils.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/llvm/use-vector-utils.cpp @@ -57,6 +57,21 @@ void test_map_range() { auto result_global = ::llvm::to_vector(::llvm::map_range(vec, transform)); // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use 'map_to_vector' // CHECK-FIXES: auto result_global = ::llvm::map_to_vector(vec, transform); + + // Check that comments between `to_vector(` and `map_range(` are preserved. + auto result_comment1 = llvm::to_vector(/*keep_me*/ llvm::map_range(vec, transform)); + // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: use 'map_to_vector' + // CHECK-FIXES: auto result_comment1 = llvm::map_to_vector(/*keep_me*/ vec, transform); + + // Check that comments between `to_vector<9>(` and `map_range(` are preserved. + auto result_comment2 = llvm::to_vector<9>(/*keep_me*/ llvm::map_range(vec, transform)); + // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: use 'map_to_vector' + // CHECK-FIXES: auto result_comment2 = llvm::map_to_vector<9>(/*keep_me*/ vec, transform); + + // Check that comments inside `map_range(` are also preserved. + auto result_comment3 = llvm::to_vector(llvm::map_range(/*keep_me*/ vec, transform)); + // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: use 'map_to_vector' + // CHECK-FIXES: auto result_comment3 = llvm::map_to_vector(/*keep_me*/ vec, transform); } void test_filter_range() { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
