Index: clang-tidy/performance/ForRangeCopyCheck.h =================================================================== --- clang-tidy/performance/ForRangeCopyCheck.h +++ clang-tidy/performance/ForRangeCopyCheck.h @@ -40,6 +40,7 @@ ASTContext &Context); const bool WarnOnAllAutoCopies; + std::vector WhitelistClasses; }; } // namespace performance Index: clang-tidy/performance/ForRangeCopyCheck.cpp =================================================================== --- clang-tidy/performance/ForRangeCopyCheck.cpp +++ clang-tidy/performance/ForRangeCopyCheck.cpp @@ -11,6 +11,7 @@ #include "../utils/ExprMutationAnalyzer.h" #include "../utils/FixItHintUtils.h" #include "../utils/TypeTraits.h" +#include "../utils/OptionsUtils.h" using namespace clang::ast_matchers; @@ -20,18 +21,28 @@ ForRangeCopyCheck::ForRangeCopyCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), - WarnOnAllAutoCopies(Options.get("WarnOnAllAutoCopies", 0)) {} + WarnOnAllAutoCopies(Options.get("WarnOnAllAutoCopies", 0)), + WhitelistClasses(utils::options::parseStringList( + Options.get("WhitelistClasses", ""))) {} void ForRangeCopyCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "WarnOnAllAutoCopies", WarnOnAllAutoCopies); + Options.store(Opts, "WhitelistClasses", + utils::options::serializeStringList(WhitelistClasses)); } 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 WhitelistClassMatcher = + cxxRecordDecl(hasAnyName(SmallVector( + WhitelistClasses.begin(), WhitelistClasses.end()))); + auto WhitelistType = hasUnqualifiedDesugaredType( + recordType(hasDeclaration(WhitelistClassMatcher))); auto LoopVar = varDecl( - hasType(hasCanonicalType(unless(anyOf(referenceType(), pointerType())))), + hasType(hasCanonicalType( + unless(anyOf(referenceType(), pointerType(), WhitelistType)))), unless(hasInitializer(expr(hasDescendant(materializeTemporaryExpr()))))); Finder->addMatcher(cxxForRangeStmt(hasLoopVariable(LoopVar.bind("loopVar"))) .bind("forRange"), Index: docs/clang-tidy/checks/performance-for-range-copy.rst =================================================================== --- docs/clang-tidy/checks/performance-for-range-copy.rst +++ docs/clang-tidy/checks/performance-for-range-copy.rst @@ -25,3 +25,8 @@ When non-zero, warns on any use of `auto` as the type of the range-based for loop variable. Default is `0`. + +.. option:: WhitelistClasses + + A semicolon-separated list of names of whitelist classes, which will be + ignored by the check. Default is empty. Index: test/clang-tidy/performance-for-range-copy.cpp =================================================================== --- test/clang-tidy/performance-for-range-copy.cpp +++ test/clang-tidy/performance-for-range-copy.cpp @@ -1,4 +1,4 @@ -// RUN: %check_clang_tidy %s performance-for-range-copy %t -- -- -std=c++11 -fno-delayed-template-parsing +// RUN: %check_clang_tidy %s performance-for-range-copy %t -config="{CheckOptions: [{key: "performance-for-range-copy.WhitelistClasses", value: "WhitelistFoo"}]}" -- -std=c++11 -fno-delayed-template-parsing namespace std { @@ -260,3 +260,11 @@ bool result = ConstOperatorInvokee != Mutable(); } } + +struct WhitelistFoo { + ~WhitelistFoo(); +}; +void IgnoreBlacklistedType() { + for (auto _ : View>()) { + } +}