[PATCH] D50447: [clang-tidy] Add a whitelistClasses option in performance-for-range-copy check.

2018-08-09 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang-tidy/performance/ForRangeCopyCheck.cpp:39
+  auto WhitelistClassMatcher =
+  cxxRecordDecl(hasAnyName(SmallVector(
+  WhitelistClasses.begin(), WhitelistClasses.end(;

JonasToth wrote:
> I have seens this pattern now multiple times in various checks, we should 
> have some utility wrapping the `hasAnyName(MyList)`. (Just in general, does 
> not need to happen with this check)
no needed for this patch. But yes! Moving to utility is reasonable to me.



Comment at: clang-tidy/performance/ForRangeCopyCheck.cpp:93
 return false;
   if (utils::ExprMutationAnalyzer(ForRange.getBody(), )
   .isMutated())

JonasToth wrote:
> Adding a `..IsMutated() && IsReferenced(ForScope, LoopVar))` here 
> should fix the warning as well.
I think ignoring `for (auto _ : state)` is a sensible solution. Thanks!



Comment at: test/clang-tidy/performance-for-range-copy.cpp:1
-// 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
 

JonasToth wrote:
> I would prefer a single file, that has the configuration and leave the 
> standard test like it is.
> 
> with this, you can always track what is actually done by default and what is 
> done with different conigurations + potential inconsistencies that might 
> occur by bugs in the configured code.
no needed this configuration now.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50447



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50447: [clang-tidy] Add a whitelistClasses option in performance-for-range-copy check.

2018-08-09 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 159919.
hokein marked an inline comment as done.
hokein added a comment.

Adress review comment - ignore the case in the check.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50447

Files:
  clang-tidy/performance/ForRangeCopyCheck.cpp
  test/clang-tidy/performance-for-range-copy.cpp


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
@@ -260,3 +260,8 @@
 bool result = ConstOperatorInvokee != Mutable();
   }
 }
+
+void IgnoreLoopVariableNotUsedInLoopBody() {
+  for (auto _ : View>()) {
+  }
+}
Index: clang-tidy/performance/ForRangeCopyCheck.cpp
===
--- clang-tidy/performance/ForRangeCopyCheck.cpp
+++ clang-tidy/performance/ForRangeCopyCheck.cpp
@@ -8,6 +8,7 @@
 
//===--===//
 
 #include "ForRangeCopyCheck.h"
+#include "../utils/DeclRefExprUtils.h"
 #include "../utils/ExprMutationAnalyzer.h"
 #include "../utils/FixItHintUtils.h"
 #include "../utils/TypeTraits.h"
@@ -79,15 +80,27 @@
   utils::type_traits::isExpensiveToCopy(LoopVar.getType(), Context);
   if (LoopVar.getType().isConstQualified() || !Expensive || !*Expensive)
 return false;
-  if (utils::ExprMutationAnalyzer(ForRange.getBody(), )
-  .isMutated())
-return false;
-  diag(LoopVar.getLocation(),
-   "loop variable is copied but only used as const reference; consider "
-   "making it a const reference")
-  << utils::fixit::changeVarDeclToConst(LoopVar)
-  << utils::fixit::changeVarDeclToReference(LoopVar, Context);
-  return true;
+  // 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 (!utils::ExprMutationAnalyzer(ForRange.getBody(), )
+  .isMutated() &&
+  !utils::decl_ref_expr::allDeclRefExprs(LoopVar, *ForRange.getBody(),
+ Context)
+   .empty()) {
+diag(LoopVar.getLocation(),
+ "loop variable is copied but only used as const reference; consider "
+ "making it a const reference")
+<< utils::fixit::changeVarDeclToConst(LoopVar)
+<< utils::fixit::changeVarDeclToReference(LoopVar, Context);
+return true;
+  }
+  return false;
 }
 
 } // namespace performance


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
@@ -260,3 +260,8 @@
 bool result = ConstOperatorInvokee != Mutable();
   }
 }
+
+void IgnoreLoopVariableNotUsedInLoopBody() {
+  for (auto _ : View>()) {
+  }
+}
Index: clang-tidy/performance/ForRangeCopyCheck.cpp
===
--- clang-tidy/performance/ForRangeCopyCheck.cpp
+++ clang-tidy/performance/ForRangeCopyCheck.cpp
@@ -8,6 +8,7 @@
 //===--===//
 
 #include "ForRangeCopyCheck.h"
+#include "../utils/DeclRefExprUtils.h"
 #include "../utils/ExprMutationAnalyzer.h"
 #include "../utils/FixItHintUtils.h"
 #include "../utils/TypeTraits.h"
@@ -79,15 +80,27 @@
   utils::type_traits::isExpensiveToCopy(LoopVar.getType(), Context);
   if (LoopVar.getType().isConstQualified() || !Expensive || !*Expensive)
 return false;
-  if (utils::ExprMutationAnalyzer(ForRange.getBody(), )
-  .isMutated())
-return false;
-  diag(LoopVar.getLocation(),
-   "loop variable is copied but only used as const reference; consider "
-   "making it a const reference")
-  << utils::fixit::changeVarDeclToConst(LoopVar)
-  << utils::fixit::changeVarDeclToReference(LoopVar, Context);
-  return true;
+  // 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 (!utils::ExprMutationAnalyzer(ForRange.getBody(), )
+  .isMutated() &&
+  !utils::decl_ref_expr::allDeclRefExprs(LoopVar, *ForRange.getBody(),
+ Context)
+   .empty()) {
+diag(LoopVar.getLocation(),
+ "loop variable is copied but only used as const reference; consider "
+ "making it a const reference")
+<< utils::fixit::changeVarDeclToConst(LoopVar)
+<< 

[PATCH] D50447: [clang-tidy] Add a whitelistClasses option in performance-for-range-copy check.

2018-08-08 Thread Shuai Wang via Phabricator via cfe-commits
shuaiwang added a comment.

In https://reviews.llvm.org/D50447#1192393, @JonasToth wrote:

> ... just check if the variable is dereferenced in the scope of the loop (any
>  declRefExpr exists).


+1
And I would imagine it's very rare (as in categories not raw number of 
occurrences) for a loop variable to be not used in the loop body so it's 
probably a safe change. Though I'm interested to learn whether there's any real 
false negative by doing this.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50447



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50447: [clang-tidy] Add a whitelistClasses option in performance-for-range-copy check.

2018-08-08 Thread Jonas Toth via Phabricator via cfe-commits
JonasToth added a comment.

> But in our codebase, we have code intended to use like below, and it is in 
> base library, and is used widely. I think it makes sense to whitelist this 
> class in our internal configuration.
> 
>   for (auto _ : state) {
>  ... // no `_` being referenced in the for-loop body
>   }

I see.




Comment at: clang-tidy/performance/ForRangeCopyCheck.cpp:93
 return false;
   if (utils::ExprMutationAnalyzer(ForRange.getBody(), )
   .isMutated())

Adding a `..IsMutated() && IsReferenced(ForScope, LoopVar))` here 
should fix the warning as well.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50447



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50447: [clang-tidy] Add a whitelistClasses option in performance-for-range-copy check.

2018-08-08 Thread Jonas Toth via Phabricator via cfe-commits
JonasToth added a comment.

Given it is about the performance in loops and the optimizer?! can
better work with the copy-and-don't-use it might make sense to just
check if the variable is dereferenced in the scope of the loop (any
declRefExpr exists).

That is more userfriendly, too.

Am 08.08.2018 um 17:02 schrieb Haojian Wu via Phabricator:

> hokein added a comment.
> 
>> That looks remarkably like google benchmark main loop. (i don't know at hand 
>> if making this const will break it, but probably not?)
>> 
>>   I wonder if instead there should be an option to not complain about the 
>> variables that aren't actually used?
> 
> Yeah, it is google benchmark library.
> 
> The new fix `for (const auto& _ : state)` will trigger -Wunused warning. 
> `__attribute__((unused))` doesn't help to suppress the warning :(
> 
>   $ cat /tmp/main4.cc 
>   #include 
>   
>   struct __attribute__((unused)) Foo {
>   };
>   
>   void f() {
> std::vector foos;
> for (const Foo& _ : foos) {
> }
>   }
>   $ g++ /tmp/main4.cc -Wunused
>   
>
>   /tmp/main4.cc: In function ‘void f()’:
>   /tmp/main4.cc:8:19: warning: unused variable ‘_’ [-Wunused-variable]
>  for (const Foo& _ : foos) {
>  ^
> 
>> Is the type important, or specifics about the variable (e.g. the name?)
>> 
>>   The _ variable names are sometimes used for RAII variables/lambdas
>>   that shall just do some cleanup, e.g. gsl::finally().
>> 
>> It might make sense to give ExprMutAnalyzer an ignore-mechanism.
>> 
>> I wonder if instead there should be an option to not complain about the 
>> variables that aren't actually used?
>> 
>> Checking for variable usage would be simple. The ExprMutAnalyzer
>> 
>>   always analyses the scope, e.g. a function. You can match this scope for
>>   a DeclRefExpr of the variable, empty result means no usage.
> 
> Both type and variable name "_" can fix the issue here, but the variable name 
> seems a fragile way (if the name is changed, things will be broken again).
> 
> Yeah, adding an ignore mechanism to ExprMutAnalyzer is another option.
> 
> Repository:
> 
>   rCTE Clang Tools Extra
> 
> https://reviews.llvm.org/D50447


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50447



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50447: [clang-tidy] Add a whitelistClasses option in performance-for-range-copy check.

2018-08-08 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

> That looks remarkably like google benchmark main loop. (i don't know at hand 
> if making this const will break it, but probably not?)
>  I wonder if instead there should be an option to not complain about the 
> variables that aren't actually used?

Yeah, it is google benchmark library.

The new fix `for (const auto& _ : state)` will trigger -Wunused warning. 
`__attribute__((unused))` doesn't help to suppress the warning :(

  $ cat /tmp/main4.cc 
  #include 
  
  struct __attribute__((unused)) Foo {
  };
  
  void f() {
std::vector foos;
for (const Foo& _ : foos) {
}
  }
  $ g++ /tmp/main4.cc -Wunused  

   
  /tmp/main4.cc: In function ‘void f()’:
  /tmp/main4.cc:8:19: warning: unused variable ‘_’ [-Wunused-variable]
 for (const Foo& _ : foos) {
 ^



> Is the type important, or specifics about the variable (e.g. the name?)
>  The _ variable names are sometimes used for RAII variables/lambdas
>  that shall just do some cleanup, e.g. gsl::finally().
> 
> It might make sense to give ExprMutAnalyzer an ignore-mechanism.
> 
> I wonder if instead there should be an option to not complain about the 
> variables that aren't actually used?
> 
> Checking for variable usage would be simple. The ExprMutAnalyzer
>  always analyses the scope, e.g. a function. You can match this scope for
>  a DeclRefExpr of the variable, empty result means no usage.

Both type and variable name "_" can fix the issue here, but the variable name 
seems a fragile way (if the name is changed, things will be broken again).

Yeah, adding an ignore mechanism to ExprMutAnalyzer is another option.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50447



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50447: [clang-tidy] Add a whitelistClasses option in performance-for-range-copy check.

2018-08-08 Thread Jonas Toth via Phabricator via cfe-commits
JonasToth added a comment.

Is the type important, or specifics about the variable (e.g. the name?)
The `_` variable names are sometimes used for RAII variables/lambdas
that shall just do some cleanup, e.g. gsl::finally().

It might make sense to give `ExprMutAnalyzer` an ignore-mechanism.

I wonder if instead there should be an option to not complain about the 
variables that aren't actually used?

Checking for variable usage would be simple. The `ExprMutAnalyzer`
always analyses the scope, e.g. a function. You can match this scope for
a `DeclRefExpr` of the variable, empty result means no usage.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50447



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50447: [clang-tidy] Add a whitelistClasses option in performance-for-range-copy check.

2018-08-08 Thread Roman Lebedev via Phabricator via cfe-commits
lebedev.ri added a subscriber: EricWF.
lebedev.ri added a comment.

In https://reviews.llvm.org/D50447#1192316, @hokein wrote:

> In https://reviews.llvm.org/D50447#1192280, @JonasToth wrote:
>
> > If whitelisting works, thats fine. But I agree with @lebedev.ri that a 
> > contribution/improvement to the ExprMutAnalyzer is the better option. This 
> > is especially the case, because multiple checks (and maybe even some other 
> > parts then clang-tidy) will utilize this analysis.
>
>
> I'm sorry for not explaining it with more details. Might be "regression" is a 
> confusing world :(. It is not false positive. The change using 
> ExprMutAnalyzer is reasonable, IMO. It makes this check smarter to catch 
> cases which will not be caught before. For example,
>
>   for (auto widget : container) {
> widget.call_const_method(); // const usage recongized by ExprMutAnalyzer, 
> so it is fine to change widget to `const auto&`
>   } 
>
>
> But in our codebase, we have code intended to use like below, and it is in 
> base library, and is used widely. I think it makes sense to whitelist this 
> class in our internal configuration.
>
>   for (auto _ : state) {
>  ... // no `_` being referenced in the for-loop body
>   }
>


That looks remarkably like google benchmark main loop. (i don't know at hand if 
making this const will break it, but probably not?)
I wonder if instead there should be an option to not complain about the 
variables that aren't actually used?


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50447



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50447: [clang-tidy] Add a whitelistClasses option in performance-for-range-copy check.

2018-08-08 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

In https://reviews.llvm.org/D50447#1192280, @JonasToth wrote:

> If whitelisting works, thats fine. But I agree with @lebedev.ri that a 
> contribution/improvement to the ExprMutAnalyzer is the better option. This is 
> especially the case, because multiple checks (and maybe even some other parts 
> then clang-tidy) will utilize this analysis.


I'm sorry for not explaining it with more details. Might be "regression" is a 
confusing world :(. It is not false positive. The change using ExprMutAnalyzer 
is reasonable, IMO. It makes this check smarter to catch cases which will not 
be caught before. For example,

  for (auto widget : container) {
widget.call_const_method(); // const usage recongized by ExprMutAnalyzer, 
so it is fine to change widget to `const auto&`
  } 

But in our codebase, we have code intended to use like below, and it is in base 
library, and is used widely. I think it makes sense to whitelist this class in 
our internal configuration.

  for (auto _ : state) {
 ... // no `_` being referenced in the for-loop body
  }


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50447



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50447: [clang-tidy] Add a whitelistClasses option in performance-for-range-copy check.

2018-08-08 Thread Jonas Toth via Phabricator via cfe-commits
JonasToth added inline comments.



Comment at: test/clang-tidy/performance-for-range-copy.cpp:1
-// 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
 

I would prefer a single file, that has the configuration and leave the standard 
test like it is.

with this, you can always track what is actually done by default and what is 
done with different conigurations + potential inconsistencies that might occur 
by bugs in the configured code.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50447



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50447: [clang-tidy] Add a whitelistClasses option in performance-for-range-copy check.

2018-08-08 Thread Jonas Toth via Phabricator via cfe-commits
JonasToth added a comment.

If whitelisting works, thats fine. But I agree with @lebedev.ri that a 
contribution/improvement to the ExprMutAnalyzer is the better option. This is 
especially the case, because multiple checks (and maybe even some other parts 
then clang-tidy) will utilize this analysis.




Comment at: clang-tidy/performance/ForRangeCopyCheck.cpp:39
+  auto WhitelistClassMatcher =
+  cxxRecordDecl(hasAnyName(SmallVector(
+  WhitelistClasses.begin(), WhitelistClasses.end(;

I have seens this pattern now multiple times in various checks, we should have 
some utility wrapping the `hasAnyName(MyList)`. (Just in general, does not need 
to happen with this check)


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50447



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50447: [clang-tidy] Add a whitelistClasses option in performance-for-range-copy check.

2018-08-08 Thread Roman Lebedev via Phabricator via cfe-commits
lebedev.ri added subscribers: shuaiwang, JonasToth, lebedev.ri.
lebedev.ri added a comment.

Regression is very broad term. Is it a false-positive?
Perhaps it is better to address the issue in the ExprMutationAnalyzer itself?


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50447



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50447: [clang-tidy] Add a whitelistClasses option in performance-for-range-copy check.

2018-08-08 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added reviewers: ilya-biryukov, alexfh.
Herald added a subscriber: xazax.hun.

The upstream change r336737 causes a regression issue in our internal
base codebase.

Adding an option to the check allowing us whitelist these classes.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50447

Files:
  clang-tidy/performance/ForRangeCopyCheck.cpp
  clang-tidy/performance/ForRangeCopyCheck.h
  docs/clang-tidy/checks/performance-for-range-copy.rst
  test/clang-tidy/performance-for-range-copy.cpp


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>()) {
+  }
+}
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: clang-tidy/performance/ForRangeCopyCheck.h
===
--- clang-tidy/performance/ForRangeCopyCheck.h
+++ clang-tidy/performance/ForRangeCopyCheck.h
@@ -40,6 +40,7 @@
ASTContext );
 
   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 ) {
   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: 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 _ :