Re: Preventing several replacements on a macro call.

2015-09-09 Thread Angel Garcia via cfe-commits
+cfe-commits

On Tue, Sep 8, 2015 at 6:56 PM, Angel Garcia  wrote:

> Hi Ted,
>
> I was working on a clang-tidy check, and today I discovered that it was
> unable to do several replacements in different arguments of the same macro
> call. At first, I thought it was a bug, and trying to figure out why this
> was happening, I found that the replacements were rejected in
> *lib/Edit/EditedSource.cpp:46*, where there is a comment that says
> "Trying to write in a macro argument input that has already been written
> for another argument of the same macro". This comment means that this
> changes are rejected on purpose.
>
> At the commit history, I saw that you had commited
>  this code (that's why I am asking
> you). Do you think that there is a way around this? I don't really
> understand why there is a particular case for the macros here, and
> understanding it would help me to decide whether I should give up on trying
> to make this work, or try to find a "better" solution.
>
> Thanks and sorry for the inconvenience,
> Angel
>
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D12734: Another patch for modernize-loop-convert.

2015-09-09 Thread Angel Garcia via cfe-commits
angelgarcia created this revision.
angelgarcia added a reviewer: klimek.
angelgarcia added subscribers: cfe-commits, alexfh.

1. Avoid converting loops that iterate over the size of a container and don't 
use its elements, as this would result in an unused-result warning.
2. Never capture the elements by value on lambdas, thus avoiding doing 
unnecessary copies and errors with non-copyable types.
3. The 'const auto &' instead of 'auto &' substitution on const containers now 
works on arrays and pseudoarrays as well.
4. The error about multiple replacements in the same macro call is now 
documented in the tests (not solved though).
5. Due to [1], I had to add a dummy usage of the range element (like "(void) 
*It;" or similars) on the tests that had empty loops.
6. I removed the braces from the CHECK comments. I think that there is no need 
for them, and they confuse vim.

http://reviews.llvm.org/D12734

Files:
  clang-tidy/modernize/LoopConvertCheck.cpp
  clang-tidy/modernize/LoopConvertCheck.h
  clang-tidy/modernize/LoopConvertUtils.cpp
  test/clang-tidy/Inputs/modernize-loop-convert/structures.h
  test/clang-tidy/modernize-loop-convert-basic.cpp
  test/clang-tidy/modernize-loop-convert-extra.cpp
  test/clang-tidy/modernize-loop-convert-negative.cpp

Index: test/clang-tidy/modernize-loop-convert-negative.cpp
===
--- test/clang-tidy/modernize-loop-convert-negative.cpp
+++ test/clang-tidy/modernize-loop-convert-negative.cpp
@@ -290,7 +290,6 @@
 dependent v;
 dependent *pv;
 
-transparent> cv;
 int Sum = 0;
 
 // Checks for the Index start and end:
@@ -473,3 +472,41 @@
 }
 
 } // namespace NegativeMultiEndCall
+
+namespace NoUsages {
+
+const int N = 6;
+int arr[N] = {1, 2, 3, 4, 5, 6};
+S s;
+dependent v;
+int Count = 0;
+
+void foo();
+
+void f() {
+  for (int I = 0; I < N; ++I) {}
+  for (int I = 0; I < N; ++I)
+printf("Hello world\n");
+  for (int I = 0; I < N; ++I)
+++Count;
+  for (int I = 0; I < N; ++I)
+foo();
+
+  for (S::iterator I = s.begin(), E = s.end(); I != E; ++I) {}
+  for (S::iterator I = s.begin(), E = s.end(); I != E; ++I)
+printf("Hello world\n");
+  for (S::iterator I = s.begin(), E = s.end(); I != E; ++I)
+++Count;
+  for (S::iterator I = s.begin(), E = s.end(); I != E; ++I)
+foo();
+
+  for (int I = 0; I < v.size(); ++I) {}
+  for (int I = 0; I < v.size(); ++I)
+printf("Hello world\n");
+  for (int I = 0; I < v.size(); ++I)
+++Count;
+  for (int I = 0; I < v.size(); ++I)
+foo();
+}
+
+} // namespace NoUsages
Index: test/clang-tidy/modernize-loop-convert-extra.cpp
===
--- test/clang-tidy/modernize-loop-convert-extra.cpp
+++ test/clang-tidy/modernize-loop-convert-extra.cpp
@@ -14,10 +14,9 @@
 int b = arr[i][a];
   }
   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto & elem : arr) {
+  // CHECK-FIXES: for (auto & elem : arr)
   // CHECK-FIXES-NEXT: int a = 0;
   // CHECK-FIXES-NEXT: int b = elem[a];
-  // CHECK-FIXES-NEXT: }
 
   for (int j = 0; j < M; ++j) {
 int a = 0;
@@ -121,16 +120,16 @@
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto alias : IntArr)
-  // CHECK-FIXES-NEXT: if (alias) {
+  // CHECK-FIXES-NEXT: if (alias)
 
   for (unsigned i = 0; i < N; ++i) {
 while (int alias = IntArr[i]) {
   sideEffect(alias);
 }
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto alias : IntArr)
-  // CHECK-FIXES-NEXT: while (alias) {
+  // CHECK-FIXES-NEXT: while (alias)
 
   for (unsigned i = 0; i < N; ++i) {
 switch (int alias = IntArr[i]) {
@@ -140,32 +139,32 @@
   }
   // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto alias : IntArr)
-  // CHECK-FIXES-NEXT: switch (alias) {
+  // CHECK-FIXES-NEXT: switch (alias)
 
   for (unsigned i = 0; i < N; ++i) {
 for (int alias = IntArr[i]; alias < N; ++alias) {
   sideEffect(alias);
 }
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto alias : IntArr)
-  // CHECK-FIXES-NEXT: for (; alias < N; ++alias) {
+  // CHECK-FIXES-NEXT: for (; alias < N; ++alias)
 
   for (unsigned i = 0; i < N; ++i) {
 for (unsigned j = 0; int alias = IntArr[i]; ++j) {
   sideEffect(alias);
 }
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto alias : IntArr)
-  // CHECK-FIXES-NEXT: for (unsigned j = 0; alias; ++j) {
+  // CHECK-FIXES-NEXT: for (unsigned j = 0; alias; ++j)
 
   struct IntRef { IntRef(const int& i); };
   for (int i = 0; i < N; ++i) {
 IntRef Int(IntArr[i]);
   }
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto & elem : IntArr) 

Re: [PATCH] D12734: Another patch for modernize-loop-convert.

2015-09-10 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 34422.
angelgarcia marked 4 inline comments as done.
angelgarcia added a comment.

Document Usage's fields and other comments.


http://reviews.llvm.org/D12734

Files:
  clang-tidy/modernize/LoopConvertCheck.cpp
  clang-tidy/modernize/LoopConvertCheck.h
  clang-tidy/modernize/LoopConvertUtils.cpp
  clang-tidy/modernize/LoopConvertUtils.h
  test/clang-tidy/Inputs/modernize-loop-convert/structures.h
  test/clang-tidy/modernize-loop-convert-basic.cpp
  test/clang-tidy/modernize-loop-convert-extra.cpp
  test/clang-tidy/modernize-loop-convert-negative.cpp

Index: test/clang-tidy/modernize-loop-convert-negative.cpp
===
--- test/clang-tidy/modernize-loop-convert-negative.cpp
+++ test/clang-tidy/modernize-loop-convert-negative.cpp
@@ -290,7 +290,6 @@
 dependent v;
 dependent *pv;
 
-transparent> cv;
 int Sum = 0;
 
 // Checks for the Index start and end:
@@ -473,3 +472,41 @@
 }
 
 } // namespace NegativeMultiEndCall
+
+namespace NoUsages {
+
+const int N = 6;
+int arr[N] = {1, 2, 3, 4, 5, 6};
+S s;
+dependent v;
+int Count = 0;
+
+void foo();
+
+void f() {
+  for (int I = 0; I < N; ++I) {}
+  for (int I = 0; I < N; ++I)
+printf("Hello world\n");
+  for (int I = 0; I < N; ++I)
+++Count;
+  for (int I = 0; I < N; ++I)
+foo();
+
+  for (S::iterator I = s.begin(), E = s.end(); I != E; ++I) {}
+  for (S::iterator I = s.begin(), E = s.end(); I != E; ++I)
+printf("Hello world\n");
+  for (S::iterator I = s.begin(), E = s.end(); I != E; ++I)
+++Count;
+  for (S::iterator I = s.begin(), E = s.end(); I != E; ++I)
+foo();
+
+  for (int I = 0; I < v.size(); ++I) {}
+  for (int I = 0; I < v.size(); ++I)
+printf("Hello world\n");
+  for (int I = 0; I < v.size(); ++I)
+++Count;
+  for (int I = 0; I < v.size(); ++I)
+foo();
+}
+
+} // namespace NoUsages
Index: test/clang-tidy/modernize-loop-convert-extra.cpp
===
--- test/clang-tidy/modernize-loop-convert-extra.cpp
+++ test/clang-tidy/modernize-loop-convert-extra.cpp
@@ -14,10 +14,9 @@
 int b = arr[i][a];
   }
   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto & elem : arr) {
+  // CHECK-FIXES: for (auto & elem : arr)
   // CHECK-FIXES-NEXT: int a = 0;
   // CHECK-FIXES-NEXT: int b = elem[a];
-  // CHECK-FIXES-NEXT: }
 
   for (int j = 0; j < M; ++j) {
 int a = 0;
@@ -121,16 +120,16 @@
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto alias : IntArr)
-  // CHECK-FIXES-NEXT: if (alias) {
+  // CHECK-FIXES-NEXT: if (alias)
 
   for (unsigned i = 0; i < N; ++i) {
 while (int alias = IntArr[i]) {
   sideEffect(alias);
 }
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto alias : IntArr)
-  // CHECK-FIXES-NEXT: while (alias) {
+  // CHECK-FIXES-NEXT: while (alias)
 
   for (unsigned i = 0; i < N; ++i) {
 switch (int alias = IntArr[i]) {
@@ -140,32 +139,32 @@
   }
   // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto alias : IntArr)
-  // CHECK-FIXES-NEXT: switch (alias) {
+  // CHECK-FIXES-NEXT: switch (alias)
 
   for (unsigned i = 0; i < N; ++i) {
 for (int alias = IntArr[i]; alias < N; ++alias) {
   sideEffect(alias);
 }
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto alias : IntArr)
-  // CHECK-FIXES-NEXT: for (; alias < N; ++alias) {
+  // CHECK-FIXES-NEXT: for (; alias < N; ++alias)
 
   for (unsigned i = 0; i < N; ++i) {
 for (unsigned j = 0; int alias = IntArr[i]; ++j) {
   sideEffect(alias);
 }
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto alias : IntArr)
-  // CHECK-FIXES-NEXT: for (unsigned j = 0; alias; ++j) {
+  // CHECK-FIXES-NEXT: for (unsigned j = 0; alias; ++j)
 
   struct IntRef { IntRef(const int& i); };
   for (int i = 0; i < N; ++i) {
 IntRef Int(IntArr[i]);
   }
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto & elem : IntArr) {
+  // CHECK-FIXES: for (auto & elem : IntArr)
   // CHECK-FIXES-NEXT: IntRef Int(elem);
 }
 
@@ -288,7 +287,7 @@
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & DEFs_it : DEFs)
-  // CHECK-FIXES-NEXT: if (DEFs_it == DEF) {
+  // CHECK-FIXES-NEXT: if (DEFs_it == DEF)
   // CHECK-FIXES-NEXT: printf("I found %d\n", DEFs_it);
 }
 
@@ -315,8 +314,8 @@
   T Vals;
   // Using the name "Val", although it is the name of an existing struct, is
   // safe in this loop since it will only exist within this scope.
-  for (T::iterator it = Vals.begin(), e = Vals.end(); it != e; ++it) {
-  }
+  for (T::iterato

Re: [PATCH] D12734: Another patch for modernize-loop-convert.

2015-09-10 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 34427.
angelgarcia added a comment.

Replace the IsArrow field of Usage with an enum.


http://reviews.llvm.org/D12734

Files:
  clang-tidy/modernize/LoopConvertCheck.cpp
  clang-tidy/modernize/LoopConvertCheck.h
  clang-tidy/modernize/LoopConvertUtils.cpp
  clang-tidy/modernize/LoopConvertUtils.h
  test/clang-tidy/Inputs/modernize-loop-convert/structures.h
  test/clang-tidy/modernize-loop-convert-basic.cpp
  test/clang-tidy/modernize-loop-convert-extra.cpp
  test/clang-tidy/modernize-loop-convert-negative.cpp

Index: test/clang-tidy/modernize-loop-convert-negative.cpp
===
--- test/clang-tidy/modernize-loop-convert-negative.cpp
+++ test/clang-tidy/modernize-loop-convert-negative.cpp
@@ -290,7 +290,6 @@
 dependent v;
 dependent *pv;
 
-transparent> cv;
 int Sum = 0;
 
 // Checks for the Index start and end:
@@ -473,3 +472,41 @@
 }
 
 } // namespace NegativeMultiEndCall
+
+namespace NoUsages {
+
+const int N = 6;
+int arr[N] = {1, 2, 3, 4, 5, 6};
+S s;
+dependent v;
+int Count = 0;
+
+void foo();
+
+void f() {
+  for (int I = 0; I < N; ++I) {}
+  for (int I = 0; I < N; ++I)
+printf("Hello world\n");
+  for (int I = 0; I < N; ++I)
+++Count;
+  for (int I = 0; I < N; ++I)
+foo();
+
+  for (S::iterator I = s.begin(), E = s.end(); I != E; ++I) {}
+  for (S::iterator I = s.begin(), E = s.end(); I != E; ++I)
+printf("Hello world\n");
+  for (S::iterator I = s.begin(), E = s.end(); I != E; ++I)
+++Count;
+  for (S::iterator I = s.begin(), E = s.end(); I != E; ++I)
+foo();
+
+  for (int I = 0; I < v.size(); ++I) {}
+  for (int I = 0; I < v.size(); ++I)
+printf("Hello world\n");
+  for (int I = 0; I < v.size(); ++I)
+++Count;
+  for (int I = 0; I < v.size(); ++I)
+foo();
+}
+
+} // namespace NoUsages
Index: test/clang-tidy/modernize-loop-convert-extra.cpp
===
--- test/clang-tidy/modernize-loop-convert-extra.cpp
+++ test/clang-tidy/modernize-loop-convert-extra.cpp
@@ -14,10 +14,9 @@
 int b = arr[i][a];
   }
   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto & elem : arr) {
+  // CHECK-FIXES: for (auto & elem : arr)
   // CHECK-FIXES-NEXT: int a = 0;
   // CHECK-FIXES-NEXT: int b = elem[a];
-  // CHECK-FIXES-NEXT: }
 
   for (int j = 0; j < M; ++j) {
 int a = 0;
@@ -121,16 +120,16 @@
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto alias : IntArr)
-  // CHECK-FIXES-NEXT: if (alias) {
+  // CHECK-FIXES-NEXT: if (alias)
 
   for (unsigned i = 0; i < N; ++i) {
 while (int alias = IntArr[i]) {
   sideEffect(alias);
 }
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto alias : IntArr)
-  // CHECK-FIXES-NEXT: while (alias) {
+  // CHECK-FIXES-NEXT: while (alias)
 
   for (unsigned i = 0; i < N; ++i) {
 switch (int alias = IntArr[i]) {
@@ -140,32 +139,32 @@
   }
   // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto alias : IntArr)
-  // CHECK-FIXES-NEXT: switch (alias) {
+  // CHECK-FIXES-NEXT: switch (alias)
 
   for (unsigned i = 0; i < N; ++i) {
 for (int alias = IntArr[i]; alias < N; ++alias) {
   sideEffect(alias);
 }
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto alias : IntArr)
-  // CHECK-FIXES-NEXT: for (; alias < N; ++alias) {
+  // CHECK-FIXES-NEXT: for (; alias < N; ++alias)
 
   for (unsigned i = 0; i < N; ++i) {
 for (unsigned j = 0; int alias = IntArr[i]; ++j) {
   sideEffect(alias);
 }
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto alias : IntArr)
-  // CHECK-FIXES-NEXT: for (unsigned j = 0; alias; ++j) {
+  // CHECK-FIXES-NEXT: for (unsigned j = 0; alias; ++j)
 
   struct IntRef { IntRef(const int& i); };
   for (int i = 0; i < N; ++i) {
 IntRef Int(IntArr[i]);
   }
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto & elem : IntArr) {
+  // CHECK-FIXES: for (auto & elem : IntArr)
   // CHECK-FIXES-NEXT: IntRef Int(elem);
 }
 
@@ -288,7 +287,7 @@
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & DEFs_it : DEFs)
-  // CHECK-FIXES-NEXT: if (DEFs_it == DEF) {
+  // CHECK-FIXES-NEXT: if (DEFs_it == DEF)
   // CHECK-FIXES-NEXT: printf("I found %d\n", DEFs_it);
 }
 
@@ -315,8 +314,8 @@
   T Vals;
   // Using the name "Val", although it is the name of an existing struct, is
   // safe in this loop since it will only exist within this scope.
-  for (T::iterator it = Vals.begin(), e = Vals.end(); it != e; ++it) {
-  }
+  for (T::iterator it = Vals.begin(), e = Vals.end(); it !

Re: [PATCH] D12734: Another patch for modernize-loop-convert.

2015-09-10 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 34428.
angelgarcia added a comment.

Comment the enumerators.

> Do we need default?


I think so. We need to set the cases that do not fall in any of these 
categories to something, and I think that using one of the other three as the 
default kind would be confusing. But maybe there is a better name than just 
UK_Default. Any ideas?


http://reviews.llvm.org/D12734

Files:
  clang-tidy/modernize/LoopConvertCheck.cpp
  clang-tidy/modernize/LoopConvertCheck.h
  clang-tidy/modernize/LoopConvertUtils.cpp
  clang-tidy/modernize/LoopConvertUtils.h
  test/clang-tidy/Inputs/modernize-loop-convert/structures.h
  test/clang-tidy/modernize-loop-convert-basic.cpp
  test/clang-tidy/modernize-loop-convert-extra.cpp
  test/clang-tidy/modernize-loop-convert-negative.cpp

Index: test/clang-tidy/modernize-loop-convert-negative.cpp
===
--- test/clang-tidy/modernize-loop-convert-negative.cpp
+++ test/clang-tidy/modernize-loop-convert-negative.cpp
@@ -290,7 +290,6 @@
 dependent v;
 dependent *pv;
 
-transparent> cv;
 int Sum = 0;
 
 // Checks for the Index start and end:
@@ -473,3 +472,41 @@
 }
 
 } // namespace NegativeMultiEndCall
+
+namespace NoUsages {
+
+const int N = 6;
+int arr[N] = {1, 2, 3, 4, 5, 6};
+S s;
+dependent v;
+int Count = 0;
+
+void foo();
+
+void f() {
+  for (int I = 0; I < N; ++I) {}
+  for (int I = 0; I < N; ++I)
+printf("Hello world\n");
+  for (int I = 0; I < N; ++I)
+++Count;
+  for (int I = 0; I < N; ++I)
+foo();
+
+  for (S::iterator I = s.begin(), E = s.end(); I != E; ++I) {}
+  for (S::iterator I = s.begin(), E = s.end(); I != E; ++I)
+printf("Hello world\n");
+  for (S::iterator I = s.begin(), E = s.end(); I != E; ++I)
+++Count;
+  for (S::iterator I = s.begin(), E = s.end(); I != E; ++I)
+foo();
+
+  for (int I = 0; I < v.size(); ++I) {}
+  for (int I = 0; I < v.size(); ++I)
+printf("Hello world\n");
+  for (int I = 0; I < v.size(); ++I)
+++Count;
+  for (int I = 0; I < v.size(); ++I)
+foo();
+}
+
+} // namespace NoUsages
Index: test/clang-tidy/modernize-loop-convert-extra.cpp
===
--- test/clang-tidy/modernize-loop-convert-extra.cpp
+++ test/clang-tidy/modernize-loop-convert-extra.cpp
@@ -14,10 +14,9 @@
 int b = arr[i][a];
   }
   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto & elem : arr) {
+  // CHECK-FIXES: for (auto & elem : arr)
   // CHECK-FIXES-NEXT: int a = 0;
   // CHECK-FIXES-NEXT: int b = elem[a];
-  // CHECK-FIXES-NEXT: }
 
   for (int j = 0; j < M; ++j) {
 int a = 0;
@@ -121,16 +120,16 @@
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto alias : IntArr)
-  // CHECK-FIXES-NEXT: if (alias) {
+  // CHECK-FIXES-NEXT: if (alias)
 
   for (unsigned i = 0; i < N; ++i) {
 while (int alias = IntArr[i]) {
   sideEffect(alias);
 }
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto alias : IntArr)
-  // CHECK-FIXES-NEXT: while (alias) {
+  // CHECK-FIXES-NEXT: while (alias)
 
   for (unsigned i = 0; i < N; ++i) {
 switch (int alias = IntArr[i]) {
@@ -140,32 +139,32 @@
   }
   // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto alias : IntArr)
-  // CHECK-FIXES-NEXT: switch (alias) {
+  // CHECK-FIXES-NEXT: switch (alias)
 
   for (unsigned i = 0; i < N; ++i) {
 for (int alias = IntArr[i]; alias < N; ++alias) {
   sideEffect(alias);
 }
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto alias : IntArr)
-  // CHECK-FIXES-NEXT: for (; alias < N; ++alias) {
+  // CHECK-FIXES-NEXT: for (; alias < N; ++alias)
 
   for (unsigned i = 0; i < N; ++i) {
 for (unsigned j = 0; int alias = IntArr[i]; ++j) {
   sideEffect(alias);
 }
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto alias : IntArr)
-  // CHECK-FIXES-NEXT: for (unsigned j = 0; alias; ++j) {
+  // CHECK-FIXES-NEXT: for (unsigned j = 0; alias; ++j)
 
   struct IntRef { IntRef(const int& i); };
   for (int i = 0; i < N; ++i) {
 IntRef Int(IntArr[i]);
   }
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto & elem : IntArr) {
+  // CHECK-FIXES: for (auto & elem : IntArr)
   // CHECK-FIXES-NEXT: IntRef Int(elem);
 }
 
@@ -288,7 +287,7 @@
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & DEFs_it : DEFs)
-  // CHECK-FIXES-NEXT: if (DEFs_it == DEF) {
+  // CHECK-FIXES-NEXT: if (DEFs_it == DEF)
   // CHECK-FIXES-NEXT: printf("I found %d\n", DEFs_it);
 }
 
@@ -315,8 +314,8 @@
   T Vals;
   // Using the name "Val", alt

Re: Preventing several replacements on a macro call.

2015-09-10 Thread Angel Garcia via cfe-commits
Hi Argyrios,

Thank you for your answer. I think that it is pretty clear that we don't
really want to allow changes like the one in your example. But my problem
is almost the opposite. I have something like this:

#define MY_MAC(x,y) doSomething(x, y);

which is used in this way:

MY_MAC(var1, var1);

and I want to replace all usages of "var1" to another thing, "var2". Each
of the arguments of the macro is used only once, so it should be safe to
replace each of them independently and obtain

MY_MAC(var2, var2);

But right now what I would obtain is

MY_MAC(var2, );

They look like different cases to me, even though the threshold is not very
clear. Maybe there is a way to allow this transformation, but still
disallow yours. Or do you think that this isn't safe? I started working on
this hardly a month ago, so I am not totally aware of the risks of these
things.

Angel



On Thu, Sep 10, 2015 at 9:01 PM, Argyrios Kyrtzidis 
wrote:

> Hi Angel,
>
> This part of the code is conservative because it is not clear if accepting
> the change in all the different places where the macro argument is expanded
> is acceptable or not.
> For a contrived example, let’s say you have this macro definition:
>
> #define MY_MAC(x) foo(x) + bar(x)
>
> and you use it like this:
>
> int a = MY_MAC(b);
>
> which expands to this:
>
> int a = foo(b) + bar(b);
>
> Now suppose you want to find all places where “foo(b)” is used and change
> it to “foo(b.c)”. You walk the AST and find “foo(b)” from the macro
> expansion and you change ‘b’ to ‘b.c’. This change will apply to the macro
> argument:
>
> int a = MY_MAC(b.c);
>
> But this now expands like this:
>
> int a = foo(b.c) + bar(b.c)
>
> And you unintentionally also changed the ‘bar’ call.
>
>
> Now, ideally we would keep track of all such changes and if you tried to
> change the ‘b’ in both “foo(b)” and “bar(b)” we would automatically accept
> it; but this is a bit complicated.
> In the meantime we could add a ‘knob' to control this behavior. We could
> have a field in Commit object that you set to true to indicate that it is
> ok to accept a change in a macro argument that expands in multiple places,
> and also for convenience add such a knob to EditedSource object for
> accepting in all commits without needing to set it for each commit
> separately.
>
> What do you think ?
>
> On Sep 9, 2015, at 6:05 AM, Angel Garcia via cfe-commits <
> cfe-commits@lists.llvm.org> wrote:
>
> +cfe-commits
>
> On Tue, Sep 8, 2015 at 6:56 PM, Angel Garcia 
> wrote:
>
>> Hi Ted,
>>
>> I was working on a clang-tidy check, and today I discovered that it was
>> unable to do several replacements in different arguments of the same macro
>> call. At first, I thought it was a bug, and trying to figure out why this
>> was happening, I found that the replacements were rejected in
>> *lib/Edit/EditedSource.cpp:46*, where there is a comment that says
>> "Trying to write in a macro argument input that has already been written
>> for another argument of the same macro". This comment means that this
>> changes are rejected on purpose.
>>
>> At the commit history, I saw that you had commited
>> <http://reviews.llvm.org/rL152141> this code (that's why I am asking
>> you). Do you think that there is a way around this? I don't really
>> understand why there is a particular case for the macros here, and
>> understanding it would help me to decide whether I should give up on trying
>> to make this work, or try to find a "better" solution.
>>
>> Thanks and sorry for the inconvenience,
>> Angel
>>
>
> ___
> cfe-commits mailing list
> cfe-commits@lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
>
>
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D12734: Another patch for modernize-loop-convert.

2015-09-11 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 34535.
angelgarcia added a comment.

Add examples of 'default' usages.


http://reviews.llvm.org/D12734

Files:
  clang-tidy/modernize/LoopConvertCheck.cpp
  clang-tidy/modernize/LoopConvertCheck.h
  clang-tidy/modernize/LoopConvertUtils.cpp
  clang-tidy/modernize/LoopConvertUtils.h
  test/clang-tidy/Inputs/modernize-loop-convert/structures.h
  test/clang-tidy/modernize-loop-convert-basic.cpp
  test/clang-tidy/modernize-loop-convert-extra.cpp
  test/clang-tidy/modernize-loop-convert-negative.cpp

Index: test/clang-tidy/modernize-loop-convert-negative.cpp
===
--- test/clang-tidy/modernize-loop-convert-negative.cpp
+++ test/clang-tidy/modernize-loop-convert-negative.cpp
@@ -290,7 +290,6 @@
 dependent v;
 dependent *pv;
 
-transparent> cv;
 int Sum = 0;
 
 // Checks for the Index start and end:
@@ -473,3 +472,41 @@
 }
 
 } // namespace NegativeMultiEndCall
+
+namespace NoUsages {
+
+const int N = 6;
+int arr[N] = {1, 2, 3, 4, 5, 6};
+S s;
+dependent v;
+int Count = 0;
+
+void foo();
+
+void f() {
+  for (int I = 0; I < N; ++I) {}
+  for (int I = 0; I < N; ++I)
+printf("Hello world\n");
+  for (int I = 0; I < N; ++I)
+++Count;
+  for (int I = 0; I < N; ++I)
+foo();
+
+  for (S::iterator I = s.begin(), E = s.end(); I != E; ++I) {}
+  for (S::iterator I = s.begin(), E = s.end(); I != E; ++I)
+printf("Hello world\n");
+  for (S::iterator I = s.begin(), E = s.end(); I != E; ++I)
+++Count;
+  for (S::iterator I = s.begin(), E = s.end(); I != E; ++I)
+foo();
+
+  for (int I = 0; I < v.size(); ++I) {}
+  for (int I = 0; I < v.size(); ++I)
+printf("Hello world\n");
+  for (int I = 0; I < v.size(); ++I)
+++Count;
+  for (int I = 0; I < v.size(); ++I)
+foo();
+}
+
+} // namespace NoUsages
Index: test/clang-tidy/modernize-loop-convert-extra.cpp
===
--- test/clang-tidy/modernize-loop-convert-extra.cpp
+++ test/clang-tidy/modernize-loop-convert-extra.cpp
@@ -14,10 +14,9 @@
 int b = arr[i][a];
   }
   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto & elem : arr) {
+  // CHECK-FIXES: for (auto & elem : arr)
   // CHECK-FIXES-NEXT: int a = 0;
   // CHECK-FIXES-NEXT: int b = elem[a];
-  // CHECK-FIXES-NEXT: }
 
   for (int j = 0; j < M; ++j) {
 int a = 0;
@@ -121,16 +120,16 @@
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto alias : IntArr)
-  // CHECK-FIXES-NEXT: if (alias) {
+  // CHECK-FIXES-NEXT: if (alias)
 
   for (unsigned i = 0; i < N; ++i) {
 while (int alias = IntArr[i]) {
   sideEffect(alias);
 }
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto alias : IntArr)
-  // CHECK-FIXES-NEXT: while (alias) {
+  // CHECK-FIXES-NEXT: while (alias)
 
   for (unsigned i = 0; i < N; ++i) {
 switch (int alias = IntArr[i]) {
@@ -140,32 +139,32 @@
   }
   // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto alias : IntArr)
-  // CHECK-FIXES-NEXT: switch (alias) {
+  // CHECK-FIXES-NEXT: switch (alias)
 
   for (unsigned i = 0; i < N; ++i) {
 for (int alias = IntArr[i]; alias < N; ++alias) {
   sideEffect(alias);
 }
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto alias : IntArr)
-  // CHECK-FIXES-NEXT: for (; alias < N; ++alias) {
+  // CHECK-FIXES-NEXT: for (; alias < N; ++alias)
 
   for (unsigned i = 0; i < N; ++i) {
 for (unsigned j = 0; int alias = IntArr[i]; ++j) {
   sideEffect(alias);
 }
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto alias : IntArr)
-  // CHECK-FIXES-NEXT: for (unsigned j = 0; alias; ++j) {
+  // CHECK-FIXES-NEXT: for (unsigned j = 0; alias; ++j)
 
   struct IntRef { IntRef(const int& i); };
   for (int i = 0; i < N; ++i) {
 IntRef Int(IntArr[i]);
   }
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto & elem : IntArr) {
+  // CHECK-FIXES: for (auto & elem : IntArr)
   // CHECK-FIXES-NEXT: IntRef Int(elem);
 }
 
@@ -288,7 +287,7 @@
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & DEFs_it : DEFs)
-  // CHECK-FIXES-NEXT: if (DEFs_it == DEF) {
+  // CHECK-FIXES-NEXT: if (DEFs_it == DEF)
   // CHECK-FIXES-NEXT: printf("I found %d\n", DEFs_it);
 }
 
@@ -315,8 +314,8 @@
   T Vals;
   // Using the name "Val", although it is the name of an existing struct, is
   // safe in this loop since it will only exist within this scope.
-  for (T::iterator it = Vals.begin(), e = Vals.end(); it != e; ++it) {
-  }
+  for (T::iterator it = Vals.begin(), e = Vals.end(); it != e; ++it)
+   

[PATCH] D12797: Refactor LoopConvertCheck.

2015-09-11 Thread Angel Garcia via cfe-commits
angelgarcia created this revision.
angelgarcia added a reviewer: klimek.
angelgarcia added subscribers: alexfh, cfe-commits.

Reorder the code in a more logical and understandable way.

http://reviews.llvm.org/D12797

Files:
  clang-tidy/modernize/LoopConvertCheck.cpp
  clang-tidy/modernize/LoopConvertCheck.h
  test/clang-tidy/modernize-loop-convert-basic.cpp

Index: test/clang-tidy/modernize-loop-convert-basic.cpp
===
--- test/clang-tidy/modernize-loop-convert-basic.cpp
+++ test/clang-tidy/modernize-loop-convert-basic.cpp
@@ -406,12 +406,12 @@
 for (const_iterator I = begin(), E = end(); I != E; ++I)
   (void) *I;
 // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
-// CHECK-FIXES: for (auto & elem : *this)
+// CHECK-FIXES: for (const auto & elem : *this)
 
 for (const_iterator I = C::begin(), E = C::end(); I != E; ++I)
   (void) *I;
 // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
-// CHECK-FIXES: for (auto & elem : *this)
+// CHECK-FIXES: for (const auto & elem : *this)
 
 for (const_iterator I = begin(), E = end(); I != E; ++I) {
   (void) *I;
Index: clang-tidy/modernize/LoopConvertCheck.h
===
--- clang-tidy/modernize/LoopConvertCheck.h
+++ clang-tidy/modernize/LoopConvertCheck.h
@@ -26,25 +26,32 @@
 
 private:
   struct RangeDescriptor {
+RangeDescriptor();
 bool ContainerNeedsDereference;
 bool DerefByConstRef;
 bool DerefByValue;
 bool IsTriviallyCopyable;
+StringRef ContainerString;
   };
 
   void doConversion(ASTContext *Context, const VarDecl *IndexVar,
-const VarDecl *MaybeContainer, StringRef ContainerString,
-const UsageResult &Usages, const DeclStmt *AliasDecl,
-bool AliasUseRequired, bool AliasFromForInit,
-const ForStmt *TheLoop, RangeDescriptor Descriptor);
-
-  StringRef checkRejections(ASTContext *Context, const Expr *ContainerExpr,
-const ForStmt *TheLoop);
-
-  void findAndVerifyUsages(ASTContext *Context, const VarDecl *LoopVar,
-   const VarDecl *EndVar, const Expr *ContainerExpr,
-   const Expr *BoundExpr, const ForStmt *TheLoop,
-   LoopFixerKind FixerKind, RangeDescriptor Descriptor);
+const VarDecl *MaybeContainer, const UsageResult &Usages,
+const DeclStmt *AliasDecl, bool AliasUseRequired,
+bool AliasFromForInit, const ForStmt *Loop,
+RangeDescriptor Descriptor);
+
+  StringRef getContainerString(ASTContext *Context, const ForStmt *Loop,
+   const Expr *ContainerExpr);
+
+  void determineRangeDescriptor(ASTContext *Context,
+const ast_matchers::BoundNodes &Nodes,
+const ForStmt *Loop, LoopFixerKind FixerKind,
+const Expr *ContainerExpr,
+const UsageResult &Usages,
+RangeDescriptor &Descriptor);
+
+  bool isConvertible(ASTContext *Context, const ast_matchers::BoundNodes &Nodes,
+ const ForStmt *Loop, LoopFixerKind FixerKind);
 
   std::unique_ptr TUInfo;
   Confidence::Level MinConfidence;
Index: clang-tidy/modernize/LoopConvertCheck.cpp
===
--- clang-tidy/modernize/LoopConvertCheck.cpp
+++ clang-tidy/modernize/LoopConvertCheck.cpp
@@ -395,6 +395,10 @@
   return false;
 }
 
+LoopConvertCheck::RangeDescriptor::RangeDescriptor()
+: ContainerNeedsDereference(false), DerefByConstRef(false),
+  DerefByValue(false), IsTriviallyCopyable(false) {}
+
 LoopConvertCheck::LoopConvertCheck(StringRef Name, ClangTidyContext *Context)
 : ClangTidyCheck(Name, Context), TUInfo(new TUTrackingInfo),
   MinConfidence(StringSwitch(
@@ -408,19 +412,24 @@
   Options.store(Opts, "MinConfidence", Confs[static_cast(MinConfidence)]);
 }
 
+void LoopConvertCheck::registerMatchers(MatchFinder *Finder) {
+  // Only register the matchers for C++. Because this checker is used for
+  // modernization, it is reasonable to run it on any C++ standard with the
+  // assumption the user is trying to modernize their codebase.
+  if (getLangOpts().CPlusPlus) {
+Finder->addMatcher(makeArrayLoopMatcher(), this);
+Finder->addMatcher(makeIteratorLoopMatcher(), this);
+Finder->addMatcher(makePseudoArrayLoopMatcher(), this);
+  }
+}
+
 /// \brief Computes the changes needed to convert a given for loop, and
-/// applies it.
+/// applies them.
 void LoopConvertCheck::doConversion(
 ASTContext *Context, const VarDecl *IndexVar, const VarDecl *MaybeContainer,
-StringRef ContainerString, const UsageResult &Usages,
-co

Re: [PATCH] D12797: Refactor LoopConvertCheck.

2015-09-17 Thread Angel Garcia via cfe-commits
angelgarcia marked 9 inline comments as done.


Comment at: clang-tidy/modernize/LoopConvertCheck.cpp:494-495
@@ -493,4 +502,2 @@
 } else {
-  if (Descriptor.DerefByConstRef)
-AutoRefType = Context->getConstType(AutoRefType);
   AutoRefType = Context->getLValueReferenceType(AutoRefType);

klimek wrote:
> I assume the change in the tests is due to the bug here? :)
I'm not sure if it was a bug or just different priorities, but that's not 
reason. "DerefByValue" is a weird case and we don't have many tests for that. 
The change is due to:

// If the initializer and variable have both the same type just use auto
// otherwise we test for const qualification of the pointed-at type.

At line 726 (somewhere inside the iterator loops logic). I removed the 
conditional because we always want to check for const qualification.




http://reviews.llvm.org/D12797



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


Re: [PATCH] D12797: Refactor LoopConvertCheck.

2015-09-17 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 34985.
angelgarcia added a comment.

Split a function and several other small changes.


http://reviews.llvm.org/D12797

Files:
  clang-tidy/modernize/LoopConvertCheck.cpp
  clang-tidy/modernize/LoopConvertCheck.h
  test/clang-tidy/modernize-loop-convert-basic.cpp

Index: test/clang-tidy/modernize-loop-convert-basic.cpp
===
--- test/clang-tidy/modernize-loop-convert-basic.cpp
+++ test/clang-tidy/modernize-loop-convert-basic.cpp
@@ -406,12 +406,12 @@
 for (const_iterator I = begin(), E = end(); I != E; ++I)
   (void) *I;
 // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
-// CHECK-FIXES: for (auto & elem : *this)
+// CHECK-FIXES: for (const auto & elem : *this)
 
 for (const_iterator I = C::begin(), E = C::end(); I != E; ++I)
   (void) *I;
 // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
-// CHECK-FIXES: for (auto & elem : *this)
+// CHECK-FIXES: for (const auto & elem : *this)
 
 for (const_iterator I = begin(), E = end(); I != E; ++I) {
   (void) *I;
Index: clang-tidy/modernize/LoopConvertCheck.h
===
--- clang-tidy/modernize/LoopConvertCheck.h
+++ clang-tidy/modernize/LoopConvertCheck.h
@@ -26,25 +26,42 @@
 
 private:
   struct RangeDescriptor {
+RangeDescriptor();
 bool ContainerNeedsDereference;
 bool DerefByConstRef;
 bool DerefByValue;
 bool IsTriviallyCopyable;
+std::string ContainerString;
   };
 
   void doConversion(ASTContext *Context, const VarDecl *IndexVar,
-const VarDecl *MaybeContainer, StringRef ContainerString,
-const UsageResult &Usages, const DeclStmt *AliasDecl,
-bool AliasUseRequired, bool AliasFromForInit,
-const ForStmt *TheLoop, RangeDescriptor Descriptor);
-
-  StringRef checkRejections(ASTContext *Context, const Expr *ContainerExpr,
-const ForStmt *TheLoop);
-
-  void findAndVerifyUsages(ASTContext *Context, const VarDecl *LoopVar,
-   const VarDecl *EndVar, const Expr *ContainerExpr,
-   const Expr *BoundExpr, const ForStmt *TheLoop,
-   LoopFixerKind FixerKind, RangeDescriptor Descriptor);
+const VarDecl *MaybeContainer, const UsageResult &Usages,
+const DeclStmt *AliasDecl, bool AliasUseRequired,
+bool AliasFromForInit, const ForStmt *Loop,
+RangeDescriptor Descriptor);
+
+  StringRef getContainerString(ASTContext *Context, const ForStmt *Loop,
+   const Expr *ContainerExpr);
+
+  void getArrayLoopQualifiers(ASTContext *Context,
+  const ast_matchers::BoundNodes &Nodes,
+  const Expr *ContainerExpr,
+  const UsageResult &Usages,
+  RangeDescriptor &Descriptor);
+
+  void getIteratorLoopQualifiers(ASTContext *Context,
+ const ast_matchers::BoundNodes &Nodes,
+ RangeDescriptor &Descriptor);
+
+  void determineRangeDescriptor(ASTContext *Context,
+const ast_matchers::BoundNodes &Nodes,
+const ForStmt *Loop, LoopFixerKind FixerKind,
+const Expr *ContainerExpr,
+const UsageResult &Usages,
+RangeDescriptor &Descriptor);
+
+  bool isConvertible(ASTContext *Context, const ast_matchers::BoundNodes &Nodes,
+ const ForStmt *Loop, LoopFixerKind FixerKind);
 
   std::unique_ptr TUInfo;
   Confidence::Level MinConfidence;
Index: clang-tidy/modernize/LoopConvertCheck.cpp
===
--- clang-tidy/modernize/LoopConvertCheck.cpp
+++ clang-tidy/modernize/LoopConvertCheck.cpp
@@ -395,6 +395,10 @@
   return false;
 }
 
+LoopConvertCheck::RangeDescriptor::RangeDescriptor()
+: ContainerNeedsDereference(false), DerefByConstRef(false),
+  DerefByValue(false), IsTriviallyCopyable(false) {}
+
 LoopConvertCheck::LoopConvertCheck(StringRef Name, ClangTidyContext *Context)
 : ClangTidyCheck(Name, Context), TUInfo(new TUTrackingInfo),
   MinConfidence(StringSwitch(
@@ -408,19 +412,25 @@
   Options.store(Opts, "MinConfidence", Confs[static_cast(MinConfidence)]);
 }
 
+void LoopConvertCheck::registerMatchers(MatchFinder *Finder) {
+  // Only register the matchers for C++. Because this checker is used for
+  // modernization, it is reasonable to run it on any C++ standard with the
+  // assumption the user is trying to modernize their codebase.
+  if (!getLangOpts().CPlusPlus)
+return;
+
+  Finder->addMatcher(m

[PATCH] D12933: Add a test to modernize-loop-convert.

2015-09-17 Thread Angel Garcia via cfe-commits
angelgarcia created this revision.
angelgarcia added a reviewer: alexfh.
angelgarcia added subscribers: klimek, cfe-commits.

Add the test about replacements in several arguments of the same macro call, 
now that the problem has been fixed.

http://reviews.llvm.org/D12933

Files:
  test/clang-tidy/modernize-loop-convert-extra.cpp

Index: test/clang-tidy/modernize-loop-convert-extra.cpp
===
--- test/clang-tidy/modernize-loop-convert-extra.cpp
+++ test/clang-tidy/modernize-loop-convert-extra.cpp
@@ -702,21 +702,15 @@
 printf("Value: %d\n", CONT arr[i]);
   }
 
-  // FIXME: Right now, clang-tidy does not allow to make insertions in several
-  // arguments of the same macro call. The following code:
-  // \code
-  //   for (int i = 0; i < N; ++i) {
-  //TWO_PARAM(arr[i], arr[i]);
-  //THREE_PARAM(arr[i], arr[i], arr[i]);
-  //   }
-  // \endcode
-  // Should be converted to this:
-  // \code
-  //   for (auto & elem : arr) {
-  //TWO_PARAM(elem, elem);
-  //THREE_PARAM(elem, elem, elem);
-  //   }
-  // \endcode
+  // Multiple arguments.
+  for (int i = 0; i < N; ++i) {
+TWO_PARAM(arr[i], arr[i]);
+THREE_PARAM(arr[i], arr[i], arr[i]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & elem : arr)
+  // CHECK-FIXES-NEXT: TWO_PARAM(elem, elem);
+  // CHECK-FIXES-NEXT: THREE_PARAM(elem, elem, elem);
 }
 
 } // namespace Macros


Index: test/clang-tidy/modernize-loop-convert-extra.cpp
===
--- test/clang-tidy/modernize-loop-convert-extra.cpp
+++ test/clang-tidy/modernize-loop-convert-extra.cpp
@@ -702,21 +702,15 @@
 printf("Value: %d\n", CONT arr[i]);
   }
 
-  // FIXME: Right now, clang-tidy does not allow to make insertions in several
-  // arguments of the same macro call. The following code:
-  // \code
-  //   for (int i = 0; i < N; ++i) {
-  //TWO_PARAM(arr[i], arr[i]);
-  //THREE_PARAM(arr[i], arr[i], arr[i]);
-  //   }
-  // \endcode
-  // Should be converted to this:
-  // \code
-  //   for (auto & elem : arr) {
-  //TWO_PARAM(elem, elem);
-  //THREE_PARAM(elem, elem, elem);
-  //   }
-  // \endcode
+  // Multiple arguments.
+  for (int i = 0; i < N; ++i) {
+TWO_PARAM(arr[i], arr[i]);
+THREE_PARAM(arr[i], arr[i], arr[i]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & elem : arr)
+  // CHECK-FIXES-NEXT: TWO_PARAM(elem, elem);
+  // CHECK-FIXES-NEXT: THREE_PARAM(elem, elem, elem);
 }
 
 } // namespace Macros
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D12933: Add a test to modernize-loop-convert.

2015-09-17 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 34993.
angelgarcia added a comment.

Done.


http://reviews.llvm.org/D12933

Files:
  test/clang-tidy/modernize-loop-convert-extra.cpp

Index: test/clang-tidy/modernize-loop-convert-extra.cpp
===
--- test/clang-tidy/modernize-loop-convert-extra.cpp
+++ test/clang-tidy/modernize-loop-convert-extra.cpp
@@ -702,21 +702,15 @@
 printf("Value: %d\n", CONT arr[i]);
   }
 
-  // FIXME: Right now, clang-tidy does not allow to make insertions in several
-  // arguments of the same macro call. The following code:
-  // \code
-  //   for (int i = 0; i < N; ++i) {
-  //TWO_PARAM(arr[i], arr[i]);
-  //THREE_PARAM(arr[i], arr[i], arr[i]);
-  //   }
-  // \endcode
-  // Should be converted to this:
-  // \code
-  //   for (auto & elem : arr) {
-  //TWO_PARAM(elem, elem);
-  //THREE_PARAM(elem, elem, elem);
-  //   }
-  // \endcode
+  // Multiple macro arguments.
+  for (int i = 0; i < N; ++i) {
+TWO_PARAM(arr[i], arr[i]);
+THREE_PARAM(arr[i], arr[i], arr[i]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & elem : arr)
+  // CHECK-FIXES-NEXT: TWO_PARAM(elem, elem);
+  // CHECK-FIXES-NEXT: THREE_PARAM(elem, elem, elem);
 }
 
 } // namespace Macros


Index: test/clang-tidy/modernize-loop-convert-extra.cpp
===
--- test/clang-tidy/modernize-loop-convert-extra.cpp
+++ test/clang-tidy/modernize-loop-convert-extra.cpp
@@ -702,21 +702,15 @@
 printf("Value: %d\n", CONT arr[i]);
   }
 
-  // FIXME: Right now, clang-tidy does not allow to make insertions in several
-  // arguments of the same macro call. The following code:
-  // \code
-  //   for (int i = 0; i < N; ++i) {
-  //TWO_PARAM(arr[i], arr[i]);
-  //THREE_PARAM(arr[i], arr[i], arr[i]);
-  //   }
-  // \endcode
-  // Should be converted to this:
-  // \code
-  //   for (auto & elem : arr) {
-  //TWO_PARAM(elem, elem);
-  //THREE_PARAM(elem, elem, elem);
-  //   }
-  // \endcode
+  // Multiple macro arguments.
+  for (int i = 0; i < N; ++i) {
+TWO_PARAM(arr[i], arr[i]);
+THREE_PARAM(arr[i], arr[i], arr[i]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & elem : arr)
+  // CHECK-FIXES-NEXT: TWO_PARAM(elem, elem);
+  // CHECK-FIXES-NEXT: THREE_PARAM(elem, elem, elem);
 }
 
 } // namespace Macros
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D12961: Update clang-tidy documentation.

2015-09-18 Thread Angel Garcia via cfe-commits
angelgarcia created this revision.
angelgarcia added subscribers: alexfh, klimek, cfe-commits.

Update documentation of the modernize module with clang-modernize's 
documentation.

http://reviews.llvm.org/D12961

Files:
  docs/clang-tidy/checks/modernize-loop-convert.rst
  docs/clang-tidy/checks/modernize-pass-by-value.rst
  docs/clang-tidy/checks/modernize-replace-auto-ptr.rst
  docs/clang-tidy/checks/modernize-use-auto.rst
  docs/clang-tidy/checks/modernize-use-nullptr.rst

Index: docs/clang-tidy/checks/modernize-use-nullptr.rst
===
--- docs/clang-tidy/checks/modernize-use-nullptr.rst
+++ docs/clang-tidy/checks/modernize-use-nullptr.rst
@@ -1,4 +1,65 @@
 modernize-use-nullptr
 =
 
+The check converts the usage of null pointer constants (eg. ``NULL``, ``0``)
+to use the new C++11 ``nullptr`` keyword.
 
+Example
+===
+
+.. code-block:: c++
+
+  void assignment() {
+char *a = NULL;
+char *b = 0;
+char c = 0;
+  }
+
+  int *ret_ptr() {
+return 0;
+  }
+
+
+transforms to:
+
+.. code-block:: c++
+
+  void assignment() {
+char *a = nullptr;
+char *b = nullptr;
+char c = 0;
+  }
+
+  int *ret_ptr() {
+return nullptr;
+  }
+
+
+User defined macros
+===
+
+By default this transform will only replace the ``NULL`` macro and will skip any
+user-defined macros that behaves like ``NULL``. The user can use the
+:option:``UserNullMacros`` option to specify a comma-separated list of macro
+names that will be transformed along with ``NULL``.
+
+Example
+---
+
+.. code-block:: c++
+
+  #define MY_NULL (void*)0
+  void assignment() {
+void *p = MY_NULL;
+  }
+
+transforms to:
+
+.. code-block:: c++
+
+  #define MY_NULL NULL
+  void assignment() {
+int *p = nullptr;
+  }
+
+  if the ``UserNullMacros`` option is set to ``MY_NULL``.
Index: docs/clang-tidy/checks/modernize-use-auto.rst
===
--- docs/clang-tidy/checks/modernize-use-auto.rst
+++ docs/clang-tidy/checks/modernize-use-auto.rst
@@ -1,4 +1,134 @@
 modernize-use-auto
 ==
 
+This check is responsible for using the ``auto`` type specifier for
+variable declarations to *improve code readability and maintainability*.
+For example:
+
+.. code-block:: c++
+
+  std::vector::iterator I = my_container.begin();
+
+  // transforms to:
+
+  auto I = my_container.begin();
+
+The ``auto`` type specifier will only be introduced in situations where the
+variable type matches the type of the initializer expression. In other words
+``auto`` should deduce the same type that was originally spelled in the source.
+However, not every situation should be transformed:
+
+.. code-block:: c++
+
+  int val = 42;
+  InfoStruct &I = SomeObject.getInfo();
+
+  // Should not become:
+
+  auto val = 42;
+  auto &I = SomeObject.getInfo();
+
+In this example using ``auto`` for builtins doesn't improve readability. In
+other situations it makes the code less self-documenting impairing readability
+and maintainability. As a result, ``auto`` is used only introduced in specific
+situations described below.
+
+Iterators
+=
+
+Iterator type specifiers tend to be long and used frequently, especially in
+loop constructs. Since the functions generating iterators have a common format,
+the type specifier can be replaced without obscuring the meaning of code while 
+improving readability and maintainability.
+
+.. code-block:: c++
+
+  for (std::vector::iterator I = my_container.begin(),
+  E = my_container.end();
+   I != E; ++I) {
+  }
+
+  // becomes
+
+  for (auto I = my_container.begin(), E = my_container.end(); I != E; ++I) {
+  }
+
+The transform will only replace iterator type-specifiers when all of the
+following conditions are satisfied:
+* The iterator is for one of the standard container in ``std`` namespace:
+
+  * ``array``
+
+  * ``deque``
+
+  * ``forward_list``
+
+  * ``list``
+
+  * ``vector``
+
+  * ``map``
+
+  * ``multimap``
+
+  * ``set``
+
+  * ``multiset``
+
+  * ``unordered_map``
+
+  * ``unordered_multimap``
+
+  * ``unordered_set``
+
+  * ``unordered_multiset``
+
+  * ``queue``
+
+  * ``priority_queue``
+
+  * ``stack``
+
+* The iterator is one of the possible iterator types for standard containers:
+
+  * ``iterator``
+
+  * ``reverse_iterator``
+
+  * ``const_iterator``
+
+  * ``const_reverse_iterator``
+
+* In addition to using iterator types directly, typedefs or other ways of
+  referring to those types are also allowed. However, implementation-specific
+  types for which a type like ``std::vector::iterator`` is itself a
+  typedef will not be transformed. Consider the following examples:
+
+.. code-block:: c++
+
+  // The following direct uses of iterator types will be transformed.
+  std::vector::iterator I = MyVec.begin();
+  {
+using namespace std;
+list::iterator I = MyList.begin();
+  }
+
+  // The type

Re: [PATCH] D12961: Update clang-tidy documentation.

2015-09-18 Thread Angel Garcia via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL247987: Update clang-tidy documentation. (authored by 
angelgarcia).

Changed prior to commit:
  http://reviews.llvm.org/D12961?vs=35080&id=35081#toc

Repository:
  rL LLVM

http://reviews.llvm.org/D12961

Files:
  clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-loop-convert.rst
  clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-pass-by-value.rst
  clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-replace-auto-ptr.rst
  clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-auto.rst
  clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-nullptr.rst

Index: clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-auto.rst
===
--- clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-auto.rst
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-auto.rst
@@ -1,4 +1,134 @@
 modernize-use-auto
 ==
 
+This check is responsible for using the ``auto`` type specifier for
+variable declarations to *improve code readability and maintainability*.
+For example:
+
+.. code-block:: c++
+
+  std::vector::iterator I = my_container.begin();
+
+  // transforms to:
+
+  auto I = my_container.begin();
+
+The ``auto`` type specifier will only be introduced in situations where the
+variable type matches the type of the initializer expression. In other words
+``auto`` should deduce the same type that was originally spelled in the source.
+However, not every situation should be transformed:
+
+.. code-block:: c++
+
+  int val = 42;
+  InfoStruct &I = SomeObject.getInfo();
+
+  // Should not become:
+
+  auto val = 42;
+  auto &I = SomeObject.getInfo();
+
+In this example using ``auto`` for builtins doesn't improve readability. In
+other situations it makes the code less self-documenting impairing readability
+and maintainability. As a result, ``auto`` is used only introduced in specific
+situations described below.
+
+Iterators
+=
+
+Iterator type specifiers tend to be long and used frequently, especially in
+loop constructs. Since the functions generating iterators have a common format,
+the type specifier can be replaced without obscuring the meaning of code while 
+improving readability and maintainability.
+
+.. code-block:: c++
+
+  for (std::vector::iterator I = my_container.begin(),
+  E = my_container.end();
+   I != E; ++I) {
+  }
+
+  // becomes
+
+  for (auto I = my_container.begin(), E = my_container.end(); I != E; ++I) {
+  }
+
+The transform will only replace iterator type-specifiers when all of the
+following conditions are satisfied:
+* The iterator is for one of the standard container in ``std`` namespace:
+
+  * ``array``
+
+  * ``deque``
+
+  * ``forward_list``
+
+  * ``list``
+
+  * ``vector``
+
+  * ``map``
+
+  * ``multimap``
+
+  * ``set``
+
+  * ``multiset``
+
+  * ``unordered_map``
+
+  * ``unordered_multimap``
+
+  * ``unordered_set``
+
+  * ``unordered_multiset``
+
+  * ``queue``
+
+  * ``priority_queue``
+
+  * ``stack``
+
+* The iterator is one of the possible iterator types for standard containers:
+
+  * ``iterator``
+
+  * ``reverse_iterator``
+
+  * ``const_iterator``
+
+  * ``const_reverse_iterator``
+
+* In addition to using iterator types directly, typedefs or other ways of
+  referring to those types are also allowed. However, implementation-specific
+  types for which a type like ``std::vector::iterator`` is itself a
+  typedef will not be transformed. Consider the following examples:
+
+.. code-block:: c++
+
+  // The following direct uses of iterator types will be transformed.
+  std::vector::iterator I = MyVec.begin();
+  {
+using namespace std;
+list::iterator I = MyList.begin();
+  }
+
+  // The type specifier for J would transform to auto since it's a typedef
+  // to a standard iterator type.
+  typedef std::map::const_iterator map_iterator;
+  map_iterator J = MyMap.begin();
+
+  // The following implementation-specific iterator type for which
+  // std::vector::iterator could be a typedef would not be transformed.
+  __gnu_cxx::__normal_iterator K = MyVec.begin();
+
+* The initializer for the variable being declared is not a braced initializer
+  list. Otherwise, use of ``auto`` would cause the type of the variable to be
+  deduced as``std::initializer_list``.
+
+Known Limitations
+=
+* If the initializer is an explicit conversion constructor, the transform will
+  not replace the type specifier even though it would be safe to do so.
+* User-defined iterators are not handled at this time.
 
Index: clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-nullptr.rst
===
--- clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-nullptr.rst
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-nullptr.rst
@

[PATCH] D13006: Replace references to "transform" with references to "check" where neccessary in the documentation.

2015-09-21 Thread Angel Garcia via cfe-commits
angelgarcia created this revision.
angelgarcia added a reviewer: alexfh.
angelgarcia added subscribers: klimek, cfe-commits.

Replace references to "transform" with references to "check" where neccessary 
in the documentation.

http://reviews.llvm.org/D13006

Files:
  docs/clang-tidy/checks/modernize-loop-convert.rst
  docs/clang-tidy/checks/modernize-pass-by-value.rst
  docs/clang-tidy/checks/modernize-replace-auto-ptr.rst
  docs/clang-tidy/checks/modernize-use-auto.rst
  docs/clang-tidy/checks/modernize-use-nullptr.rst

Index: docs/clang-tidy/checks/modernize-use-nullptr.rst
===
--- docs/clang-tidy/checks/modernize-use-nullptr.rst
+++ docs/clang-tidy/checks/modernize-use-nullptr.rst
@@ -38,7 +38,7 @@
 User defined macros
 ===
 
-By default this transform will only replace the ``NULL`` macro and will skip any
+By default this check will only replace the ``NULL`` macro and will skip any
 user-defined macros that behaves like ``NULL``. The user can use the
 :option:``UserNullMacros`` option to specify a comma-separated list of macro
 names that will be transformed along with ``NULL``.
Index: docs/clang-tidy/checks/modernize-use-auto.rst
===
--- docs/clang-tidy/checks/modernize-use-auto.rst
+++ docs/clang-tidy/checks/modernize-use-auto.rst
@@ -53,7 +53,7 @@
   for (auto I = my_container.begin(), E = my_container.end(); I != E; ++I) {
   }
 
-The transform will only replace iterator type-specifiers when all of the
+The check will only replace iterator type-specifiers when all of the
 following conditions are satisfied:
 * The iterator is for one of the standard container in ``std`` namespace:
 
@@ -128,7 +128,7 @@
 
 Known Limitations
 =
-* If the initializer is an explicit conversion constructor, the transform will
+* If the initializer is an explicit conversion constructor, the check will
   not replace the type specifier even though it would be safe to do so.
 * User-defined iterators are not handled at this time.
 
Index: docs/clang-tidy/checks/modernize-replace-auto-ptr.rst
===
--- docs/clang-tidy/checks/modernize-replace-auto-ptr.rst
+++ docs/clang-tidy/checks/modernize-replace-auto-ptr.rst
@@ -26,13 +26,13 @@
}
 
 Since `std::move()` is a library function declared in `` it may be
-necessary to add this include. The transform will add the include directive when
+necessary to add this include. The check will add the include directive when
 necessary.
 
 Known Limitations
 =
 * If headers modification is not activated or if a header is not allowed to be
-  changed this transform will produce broken code (compilation error), where the
+  changed this check will produce broken code (compilation error), where the
   the headers' code will stay unchanged while the code using them will be
   changed.
 
Index: docs/clang-tidy/checks/modernize-pass-by-value.rst
===
--- docs/clang-tidy/checks/modernize-pass-by-value.rst
+++ docs/clang-tidy/checks/modernize-pass-by-value.rst
@@ -4,7 +4,7 @@
 With move semantics added to the language and the standard library updated with
 move constructors added for many types it is now interesting to take an argument
 directly by value, instead of by const-reference, and then copy. This
-transformation allows the compiler to take care of choosing the best way to
+check allows the compiler to take care of choosing the best way to
 construct the copy.
 
 The transformation is usually beneficial when the calling code passes an
@@ -34,7 +34,7 @@
 into class fields. The parameter is then moved with `std::move()`.
 
 Since `std::move()` is a library function declared in `` it may be
-necessary to add this include. The transform will add the include directive when
+necessary to add this include. The check will add the include directive when
 necessary.
 
   .. code-block:: c++
Index: docs/clang-tidy/checks/modernize-loop-convert.rst
===
--- docs/clang-tidy/checks/modernize-loop-convert.rst
+++ docs/clang-tidy/checks/modernize-loop-convert.rst
@@ -81,19 +81,19 @@
   v.push_back(2);
   v.push_back(3);
 
-  // safe transform
+  // safe conversion
   for (int i = 0; i < N; ++i)
 cout << arr[i];
 
-  // reasonable transform
+  // reasonable conversion
   for (vector::iterator it = v.begin(); it != v.end(); ++it)
 cout << *it;*
 
-  // reasonable transform
+  // reasonable conversion
   for (int i = 0; i < v.size(); ++i)
 cout << v[i];
 
-After transformation with confidence level set to ``reasonable`` (default):
+After applying the check with minimum confidence level set to ``reasonable`` (default):
 
 .. code-block:: c++
 
@@ -104,24 +104,24 @@
   v.push_back(2);
   v.push_back(3);
 
-  // safe transform
+  // safe

Re: [PATCH] D13006: Replace references to "transform" with references to "check" where neccessary in the documentation.

2015-09-21 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 35232.
angelgarcia added a comment.

Done.


http://reviews.llvm.org/D13006

Files:
  docs/clang-tidy/checks/modernize-loop-convert.rst
  docs/clang-tidy/checks/modernize-pass-by-value.rst
  docs/clang-tidy/checks/modernize-replace-auto-ptr.rst
  docs/clang-tidy/checks/modernize-use-auto.rst
  docs/clang-tidy/checks/modernize-use-nullptr.rst

Index: docs/clang-tidy/checks/modernize-use-nullptr.rst
===
--- docs/clang-tidy/checks/modernize-use-nullptr.rst
+++ docs/clang-tidy/checks/modernize-use-nullptr.rst
@@ -38,7 +38,7 @@
 User defined macros
 ===
 
-By default this transform will only replace the ``NULL`` macro and will skip any
+By default this check will only replace the ``NULL`` macro and will skip any
 user-defined macros that behaves like ``NULL``. The user can use the
 :option:``UserNullMacros`` option to specify a comma-separated list of macro
 names that will be transformed along with ``NULL``.
Index: docs/clang-tidy/checks/modernize-use-auto.rst
===
--- docs/clang-tidy/checks/modernize-use-auto.rst
+++ docs/clang-tidy/checks/modernize-use-auto.rst
@@ -1,9 +1,8 @@
 modernize-use-auto
 ==
 
-This check is responsible for using the ``auto`` type specifier for
-variable declarations to *improve code readability and maintainability*.
-For example:
+This check is responsible for using the ``auto`` type specifier for variable
+declarations to *improve code readability and maintainability*.  For example:
 
 .. code-block:: c++
 
@@ -38,7 +37,7 @@
 
 Iterator type specifiers tend to be long and used frequently, especially in
 loop constructs. Since the functions generating iterators have a common format,
-the type specifier can be replaced without obscuring the meaning of code while 
+the type specifier can be replaced without obscuring the meaning of code while
 improving readability and maintainability.
 
 .. code-block:: c++
@@ -53,50 +52,33 @@
   for (auto I = my_container.begin(), E = my_container.end(); I != E; ++I) {
   }
 
-The transform will only replace iterator type-specifiers when all of the
-following conditions are satisfied:
+The check will only replace iterator type-specifiers when all of the following
+conditions are satisfied:
+
 * The iterator is for one of the standard container in ``std`` namespace:
 
   * ``array``
-
   * ``deque``
-
   * ``forward_list``
-
   * ``list``
-
   * ``vector``
-
   * ``map``
-
   * ``multimap``
-
   * ``set``
-
   * ``multiset``
-
   * ``unordered_map``
-
   * ``unordered_multimap``
-
   * ``unordered_set``
-
   * ``unordered_multiset``
-
   * ``queue``
-
   * ``priority_queue``
-
   * ``stack``
 
 * The iterator is one of the possible iterator types for standard containers:
 
   * ``iterator``
-
   * ``reverse_iterator``
-
   * ``const_iterator``
-
   * ``const_reverse_iterator``
 
 * In addition to using iterator types directly, typedefs or other ways of
@@ -128,7 +110,8 @@
 
 Known Limitations
 =
-* If the initializer is an explicit conversion constructor, the transform will
-  not replace the type specifier even though it would be safe to do so.
+* If the initializer is an explicit conversion constructor, the check will not
+  replace the type specifier even though it would be safe to do so.
+
 * User-defined iterators are not handled at this time.
 
Index: docs/clang-tidy/checks/modernize-replace-auto-ptr.rst
===
--- docs/clang-tidy/checks/modernize-replace-auto-ptr.rst
+++ docs/clang-tidy/checks/modernize-replace-auto-ptr.rst
@@ -26,24 +26,23 @@
}
 
 Since `std::move()` is a library function declared in `` it may be
-necessary to add this include. The transform will add the include directive when
+necessary to add this include. The check will add the include directive when
 necessary.
 
 Known Limitations
 =
 * If headers modification is not activated or if a header is not allowed to be
-  changed this transform will produce broken code (compilation error), where the
-  the headers' code will stay unchanged while the code using them will be
-  changed.
-
-* Client code that declares a reference to an ``std::auto_ptr`` coming from code
-  that can't be migrated (such as a header coming from a 3\ :sup:`rd` party
-  library) will produce a compilation error after migration. This is because the
-  type of the reference will be changed to ``std::unique_ptr`` but the type
-  returned by the library won't change, binding a reference to
+  changed this check will produce broken code (compilation error), where the
+  headers' code will stay unchanged while the code using them will be changed.
+
+* Client code that declares a reference to an ``std::auto_ptr`` coming from
+  code that can't be migrated (such as a header coming from a 3\ :sup:`rd`
+  party library

Re: [PATCH] D13006: Replace references to "transform" with references to "check" where neccessary in the documentation.

2015-09-21 Thread Angel Garcia via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL248153: Replace references to "transform" with references to 
"check" where neccessary… (authored by angelgarcia).

Changed prior to commit:
  http://reviews.llvm.org/D13006?vs=35232&id=35238#toc

Repository:
  rL LLVM

http://reviews.llvm.org/D13006

Files:
  clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-loop-convert.rst
  clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-pass-by-value.rst
  clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-replace-auto-ptr.rst
  clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-auto.rst
  clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-nullptr.rst

Index: clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-nullptr.rst
===
--- clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-nullptr.rst
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-nullptr.rst
@@ -38,7 +38,7 @@
 User defined macros
 ---
 
-By default this transform will only replace the ``NULL`` macro and will skip any
+By default this check will only replace the ``NULL`` macro and will skip any
 user-defined macros that behaves like ``NULL``. The user can use the
 :option:``UserNullMacros`` option to specify a comma-separated list of macro
 names that will be transformed along with ``NULL``.
Index: clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-pass-by-value.rst
===
--- clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-pass-by-value.rst
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-pass-by-value.rst
@@ -2,10 +2,10 @@
 ===
 
 With move semantics added to the language and the standard library updated with
-move constructors added for many types it is now interesting to take an argument
-directly by value, instead of by const-reference, and then copy. This
-transformation allows the compiler to take care of choosing the best way to
-construct the copy.
+move constructors added for many types it is now interesting to take an
+argument directly by value, instead of by const-reference, and then copy. This
+check allows the compiler to take care of choosing the best way to construct
+the copy.
 
 The transformation is usually beneficial when the calling code passes an
 *rvalue* and assumes the move construction is a cheap operation. This short
@@ -34,7 +34,7 @@
 into class fields. The parameter is then moved with `std::move()`.
 
 Since `std::move()` is a library function declared in `` it may be
-necessary to add this include. The transform will add the include directive when
+necessary to add this include. The check will add the include directive when
 necessary.
 
   .. code-block:: c++
Index: clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-auto.rst
===
--- clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-auto.rst
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-auto.rst
@@ -1,9 +1,8 @@
 modernize-use-auto
 ==
 
-This check is responsible for using the ``auto`` type specifier for
-variable declarations to *improve code readability and maintainability*.
-For example:
+This check is responsible for using the ``auto`` type specifier for variable
+declarations to *improve code readability and maintainability*.  For example:
 
 .. code-block:: c++
 
@@ -38,7 +37,7 @@
 
 Iterator type specifiers tend to be long and used frequently, especially in
 loop constructs. Since the functions generating iterators have a common format,
-the type specifier can be replaced without obscuring the meaning of code while 
+the type specifier can be replaced without obscuring the meaning of code while
 improving readability and maintainability.
 
 .. code-block:: c++
@@ -53,50 +52,33 @@
   for (auto I = my_container.begin(), E = my_container.end(); I != E; ++I) {
   }
 
-The transform will only replace iterator type-specifiers when all of the
-following conditions are satisfied:
+The check will only replace iterator type-specifiers when all of the following
+conditions are satisfied:
+
 * The iterator is for one of the standard container in ``std`` namespace:
 
   * ``array``
-
   * ``deque``
-
   * ``forward_list``
-
   * ``list``
-
   * ``vector``
-
   * ``map``
-
   * ``multimap``
-
   * ``set``
-
   * ``multiset``
-
   * ``unordered_map``
-
   * ``unordered_multimap``
-
   * ``unordered_set``
-
   * ``unordered_multiset``
-
   * ``queue``
-
   * ``priority_queue``
-
   * ``stack``
 
 * The iterator is one of the possible iterator types for standard containers:
 
   * ``iterator``
-
   * ``reverse_iterator``
-
   * ``const_iterator``
-
   * ``const_reverse_iterator``
 
 * In addition to using iterator types directly, typedefs or other ways of
@@ -128,7 +110

[PATCH] D13052: Add NamingStyle option to modernize-loop-convert.

2015-09-22 Thread Angel Garcia via cfe-commits
angelgarcia created this revision.
angelgarcia added a reviewer: alexfh.
angelgarcia added subscribers: klimek, cfe-commits.

Add an option to specify wich style must be followed when choosing the new 
index name.

http://reviews.llvm.org/D13052

Files:
  clang-tidy/modernize/LoopConvertCheck.cpp
  clang-tidy/modernize/LoopConvertCheck.h
  clang-tidy/modernize/LoopConvertUtils.cpp
  clang-tidy/modernize/LoopConvertUtils.h
  clang-tidy/modernize/ModernizeTidyModule.cpp
  test/clang-tidy/modernize-loop-convert-basic.cpp
  test/clang-tidy/modernize-loop-convert-extra.cpp

Index: test/clang-tidy/modernize-loop-convert-extra.cpp
===
--- test/clang-tidy/modernize-loop-convert-extra.cpp
+++ test/clang-tidy/modernize-loop-convert-extra.cpp
@@ -14,9 +14,9 @@
 int b = arr[i][a];
   }
   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto & elem : arr)
+  // CHECK-FIXES: for (auto & Elem : arr)
   // CHECK-FIXES-NEXT: int a = 0;
-  // CHECK-FIXES-NEXT: int b = elem[a];
+  // CHECK-FIXES-NEXT: int b = Elem[a];
 
   for (int j = 0; j < M; ++j) {
 int a = 0;
@@ -64,21 +64,21 @@
 int z = Arr[i].x + t.x;
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto & elem : Arr)
-  // CHECK-FIXES-NEXT: Val &t = elem;
+  // CHECK-FIXES: for (auto & Elem : Arr)
+  // CHECK-FIXES-NEXT: Val &t = Elem;
   // CHECK-FIXES-NEXT: int y = t.x;
-  // CHECK-FIXES-NEXT: int z = elem.x + t.x;
+  // CHECK-FIXES-NEXT: int z = Elem.x + t.x;
 
   for (int i = 0; i < N; ++i) {
 Val t = Arr[i];
 int y = t.x;
 int z = Arr[i].x + t.x;
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto & elem : Arr)
-  // CHECK-FIXES-NEXT: Val t = elem;
+  // CHECK-FIXES: for (auto & Elem : Arr)
+  // CHECK-FIXES-NEXT: Val t = Elem;
   // CHECK-FIXES-NEXT: int y = t.x;
-  // CHECK-FIXES-NEXT: int z = elem.x + t.x;
+  // CHECK-FIXES-NEXT: int z = Elem.x + t.x;
 
   // The same for pseudo-arrays like std::vector (or here dependent)
   // which provide a subscript operator[].
@@ -108,8 +108,8 @@
 int y = t.x;
   }
   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto & elem : Arr)
-  // CHECK-FIXES-NEXT: Val &t = func(elem);
+  // CHECK-FIXES: for (auto & Elem : Arr)
+  // CHECK-FIXES-NEXT: Val &t = func(Elem);
   // CHECK-FIXES-NEXT: int y = t.x;
 
   int IntArr[N];
@@ -164,8 +164,8 @@
 IntRef Int(IntArr[i]);
   }
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto & elem : IntArr)
-  // CHECK-FIXES-NEXT: IntRef Int(elem);
+  // CHECK-FIXES: for (auto & Elem : IntArr)
+  // CHECK-FIXES-NEXT: IntRef Int(Elem);
 }
 
 
@@ -218,8 +218,8 @@
 unsigned othersize = other.size();
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto & elem : dep)
-  // CHECK-FIXES-NEXT: printf("%d\n", elem);
+  // CHECK-FIXES: for (auto & Elem : dep)
+  // CHECK-FIXES-NEXT: printf("%d\n", Elem);
   // CHECK-FIXES-NEXT: const int& idx = other[0];
   // CHECK-FIXES-NEXT: unsigned othersize = other.size();
 
@@ -418,10 +418,10 @@
   }
   // CHECK-MESSAGES: :[[@LINE-8]]:3: warning: use range-based for loop instead
   // CHECK-MESSAGES: :[[@LINE-8]]:5: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto & elem : Arr)
+  // CHECK-FIXES: for (auto & Elem : Arr)
   // CHECK-FIXES-NEXT: for (auto & Arr_j : Arr)
-  // CHECK-FIXES-NEXT: int k = elem.x + Arr_j.x;
-  // CHECK-FIXES-NOT: int l = elem.x + elem.x;
+  // CHECK-FIXES-NEXT: int k = Elem.x + Arr_j.x;
+  // CHECK-FIXES-NOT: int l = Elem.x + Elem.x;
 
   // The inner loop is also convertible, but doesn't need to be converted
   // immediately. FIXME: update this test when that changes.
@@ -432,9 +432,9 @@
 }
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto & elem : Nest)
+  // CHECK-FIXES: for (auto & Elem : Nest)
   // CHECK-FIXES-NEXT: for (int j = 0; j < M; ++j)
-  // CHECK-FIXES-NEXT: printf("Got item %d", elem[j].x);
+  // CHECK-FIXES-NEXT: printf("Got item %d", Elem[j].x);
 
   // Note that the order of M and N are switched for this test.
   for (int j = 0; j < M; ++j) {
@@ -445,8 +445,8 @@
   // CHECK-MESSAGES: :[[@LINE-4]]:5: warning: use range-based for loop instead
   // CHECK-FIXES-NOT: for (auto & {{[a-zA-Z_]+}} : Nest[i])
   // CHECK-FIXES: for (int j = 0; j < M; ++j)
-  // CHECK-FIXES-NEXT: for (auto & elem : Nest)
-  // CHECK-FIXES-NEXT: printf("Got item %d", elem[j].x);
+  // CHECK-FIXES-NEXT: for (auto & Elem : Nest)
+  // CHECK-FIXES-NEXT: printf("Got item %d", Elem[j].x);
 
   // The inner loop is also convertible.
   Nested NestT;
@@ -456,8 +456,8 @@
 }
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warni

Re: [PATCH] D13052: Add NamingStyle option to modernize-loop-convert.

2015-09-22 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 35362.
angelgarcia added a comment.

Remove related FIXME.


http://reviews.llvm.org/D13052

Files:
  clang-tidy/modernize/LoopConvertCheck.cpp
  clang-tidy/modernize/LoopConvertCheck.h
  clang-tidy/modernize/LoopConvertUtils.cpp
  clang-tidy/modernize/LoopConvertUtils.h
  clang-tidy/modernize/ModernizeTidyModule.cpp
  test/clang-tidy/modernize-loop-convert-basic.cpp
  test/clang-tidy/modernize-loop-convert-extra.cpp

Index: test/clang-tidy/modernize-loop-convert-extra.cpp
===
--- test/clang-tidy/modernize-loop-convert-extra.cpp
+++ test/clang-tidy/modernize-loop-convert-extra.cpp
@@ -14,9 +14,9 @@
 int b = arr[i][a];
   }
   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto & elem : arr)
+  // CHECK-FIXES: for (auto & Elem : arr)
   // CHECK-FIXES-NEXT: int a = 0;
-  // CHECK-FIXES-NEXT: int b = elem[a];
+  // CHECK-FIXES-NEXT: int b = Elem[a];
 
   for (int j = 0; j < M; ++j) {
 int a = 0;
@@ -64,21 +64,21 @@
 int z = Arr[i].x + t.x;
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto & elem : Arr)
-  // CHECK-FIXES-NEXT: Val &t = elem;
+  // CHECK-FIXES: for (auto & Elem : Arr)
+  // CHECK-FIXES-NEXT: Val &t = Elem;
   // CHECK-FIXES-NEXT: int y = t.x;
-  // CHECK-FIXES-NEXT: int z = elem.x + t.x;
+  // CHECK-FIXES-NEXT: int z = Elem.x + t.x;
 
   for (int i = 0; i < N; ++i) {
 Val t = Arr[i];
 int y = t.x;
 int z = Arr[i].x + t.x;
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto & elem : Arr)
-  // CHECK-FIXES-NEXT: Val t = elem;
+  // CHECK-FIXES: for (auto & Elem : Arr)
+  // CHECK-FIXES-NEXT: Val t = Elem;
   // CHECK-FIXES-NEXT: int y = t.x;
-  // CHECK-FIXES-NEXT: int z = elem.x + t.x;
+  // CHECK-FIXES-NEXT: int z = Elem.x + t.x;
 
   // The same for pseudo-arrays like std::vector (or here dependent)
   // which provide a subscript operator[].
@@ -108,8 +108,8 @@
 int y = t.x;
   }
   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto & elem : Arr)
-  // CHECK-FIXES-NEXT: Val &t = func(elem);
+  // CHECK-FIXES: for (auto & Elem : Arr)
+  // CHECK-FIXES-NEXT: Val &t = func(Elem);
   // CHECK-FIXES-NEXT: int y = t.x;
 
   int IntArr[N];
@@ -164,8 +164,8 @@
 IntRef Int(IntArr[i]);
   }
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto & elem : IntArr)
-  // CHECK-FIXES-NEXT: IntRef Int(elem);
+  // CHECK-FIXES: for (auto & Elem : IntArr)
+  // CHECK-FIXES-NEXT: IntRef Int(Elem);
 }
 
 
@@ -218,8 +218,8 @@
 unsigned othersize = other.size();
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto & elem : dep)
-  // CHECK-FIXES-NEXT: printf("%d\n", elem);
+  // CHECK-FIXES: for (auto & Elem : dep)
+  // CHECK-FIXES-NEXT: printf("%d\n", Elem);
   // CHECK-FIXES-NEXT: const int& idx = other[0];
   // CHECK-FIXES-NEXT: unsigned othersize = other.size();
 
@@ -418,10 +418,10 @@
   }
   // CHECK-MESSAGES: :[[@LINE-8]]:3: warning: use range-based for loop instead
   // CHECK-MESSAGES: :[[@LINE-8]]:5: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto & elem : Arr)
+  // CHECK-FIXES: for (auto & Elem : Arr)
   // CHECK-FIXES-NEXT: for (auto & Arr_j : Arr)
-  // CHECK-FIXES-NEXT: int k = elem.x + Arr_j.x;
-  // CHECK-FIXES-NOT: int l = elem.x + elem.x;
+  // CHECK-FIXES-NEXT: int k = Elem.x + Arr_j.x;
+  // CHECK-FIXES-NOT: int l = Elem.x + Elem.x;
 
   // The inner loop is also convertible, but doesn't need to be converted
   // immediately. FIXME: update this test when that changes.
@@ -432,9 +432,9 @@
 }
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto & elem : Nest)
+  // CHECK-FIXES: for (auto & Elem : Nest)
   // CHECK-FIXES-NEXT: for (int j = 0; j < M; ++j)
-  // CHECK-FIXES-NEXT: printf("Got item %d", elem[j].x);
+  // CHECK-FIXES-NEXT: printf("Got item %d", Elem[j].x);
 
   // Note that the order of M and N are switched for this test.
   for (int j = 0; j < M; ++j) {
@@ -445,8 +445,8 @@
   // CHECK-MESSAGES: :[[@LINE-4]]:5: warning: use range-based for loop instead
   // CHECK-FIXES-NOT: for (auto & {{[a-zA-Z_]+}} : Nest[i])
   // CHECK-FIXES: for (int j = 0; j < M; ++j)
-  // CHECK-FIXES-NEXT: for (auto & elem : Nest)
-  // CHECK-FIXES-NEXT: printf("Got item %d", elem[j].x);
+  // CHECK-FIXES-NEXT: for (auto & Elem : Nest)
+  // CHECK-FIXES-NEXT: printf("Got item %d", Elem[j].x);
 
   // The inner loop is also convertible.
   Nested NestT;
@@ -456,8 +456,8 @@
 }
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto & elem : NestT)
-  // CHECK-FIXES-NEXT: for (T

Re: [PATCH] D13052: Add NamingStyle option to modernize-loop-convert.

2015-09-22 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 35380.
angelgarcia marked 10 inline comments as done.
angelgarcia added a comment.

Use CamelCase on the existing tests and add a test for every other naming 
convention.


http://reviews.llvm.org/D13052

Files:
  clang-tidy/modernize/LoopConvertCheck.cpp
  clang-tidy/modernize/LoopConvertCheck.h
  clang-tidy/modernize/LoopConvertUtils.cpp
  clang-tidy/modernize/LoopConvertUtils.h
  clang-tidy/modernize/ModernizeTidyModule.cpp
  test/clang-tidy/Inputs/modernize-loop-convert/structures.h
  test/clang-tidy/modernize-loop-convert-basic.cpp
  test/clang-tidy/modernize-loop-convert-camelback.cpp
  test/clang-tidy/modernize-loop-convert-extra.cpp
  test/clang-tidy/modernize-loop-convert-lowercase.cpp
  test/clang-tidy/modernize-loop-convert-negative.cpp
  test/clang-tidy/modernize-loop-convert-uppercase.cpp

Index: test/clang-tidy/modernize-loop-convert-uppercase.cpp
===
--- /dev/null
+++ test/clang-tidy/modernize-loop-convert-uppercase.cpp
@@ -0,0 +1,49 @@
+// RUN: %python %S/check_clang_tidy.py %s modernize-loop-convert %t \
+// RUN:   -config="{CheckOptions: [{key: modernize-loop-convert.NamingStyle, value: 'UPPER_CASE'}]}" \
+// RUN:   -- -std=c++11 -I %S/Inputs/modernize-loop-convert
+
+#include "structures.h"
+
+const int N = 10;
+int ARR[N];
+int NUMS[N];
+
+void naming() {
+  for (int I = 0; I < N; ++I) {
+printf("%d\n", ARR[I]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead [modernize-loop-convert]
+  // CHECK-FIXES: for (auto & ELEM : ARR)
+  // CHECK-FIXES-NEXT: printf("%d\n", ELEM);
+
+  for (int I = 0; I < N; ++I) {
+printf("%d\n", NUMS[I]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & NUM : NUMS)
+  // CHECK-FIXES-NEXT: printf("%d\n", NUM);
+
+  int NUM = 0;
+  for (int I = 0; I < N; ++I) {
+printf("%d\n", NUMS[I] + NUM);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & ELEM : NUMS)
+  // CHECK-FIXES-NEXT: printf("%d\n", ELEM + NUM);
+
+  int ELEM = 0;
+  for (int I = 0; I < N; ++I) {
+printf("%d\n", NUMS[I] + NUM + ELEM);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & NUMS_I : NUMS)
+  // CHECK-FIXES-NEXT: printf("%d\n", NUMS_I + NUM + ELEM);
+
+  int NUMS_I = 0;
+  for (int I = 0; I < N; ++I) {
+printf("%d\n", NUMS[I] + NUM + ELEM + NUMS_I);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & NUMS_ELEM : NUMS)
+  // CHECK-FIXES-NEXT: printf("%d\n", NUMS_ELEM + NUM + ELEM + NUMS_I);
+}
Index: test/clang-tidy/modernize-loop-convert-negative.cpp
===
--- test/clang-tidy/modernize-loop-convert-negative.cpp
+++ test/clang-tidy/modernize-loop-convert-negative.cpp
@@ -8,47 +8,47 @@
 namespace Negative {
 
 const int N = 6;
-int arr[N] = {1, 2, 3, 4, 5, 6};
-int (*pArr)[N] = &arr;
+int Arr[N] = {1, 2, 3, 4, 5, 6};
+int (*pArr)[N] = &Arr;
 int Sum = 0;
 
 // Checks for the Index start and end:
 void IndexStartAndEnd() {
   for (int I = 0; I < N + 1; ++I)
-Sum += arr[I];
+Sum += Arr[I];
 
   for (int I = 0; I < N - 1; ++I)
-Sum += arr[I];
+Sum += Arr[I];
 
   for (int I = 1; I < N; ++I)
-Sum += arr[I];
+Sum += Arr[I];
 
   for (int I = 1; I < N; ++I)
-Sum += arr[I];
+Sum += Arr[I];
 
   for (int I = 0;; ++I)
 Sum += (*pArr)[I];
 }
 
 // Checks for invalid increment steps:
 void increment() {
   for (int I = 0; I < N; --I)
-Sum += arr[I];
+Sum += Arr[I];
 
   for (int I = 0; I < N; I)
-Sum += arr[I];
+Sum += Arr[I];
 
   for (int I = 0; I < N;)
-Sum += arr[I];
+Sum += Arr[I];
 
   for (int I = 0; I < N; I += 2)
 Sum++;
 }
 
 // Checks to make sure that the Index isn't used outside of the array:
 void IndexUse() {
   for (int I = 0; I < N; ++I)
-arr[I] += 1 + I;
+Arr[I] += 1 + I;
 }
 
 // Check for loops that don't mention arrays
@@ -65,30 +65,30 @@
 
 // Checks for incorrect loop variables.
 void mixedVariables() {
-  int badIndex;
-  for (int I = 0; badIndex < N; ++I)
-Sum += arr[I];
+  int BadIndex;
+  for (int I = 0; BadIndex < N; ++I)
+Sum += Arr[I];
 
-  for (int I = 0; I < N; ++badIndex)
-Sum += arr[I];
+  for (int I = 0; I < N; ++BadIndex)
+Sum += Arr[I];
 
-  for (int I = 0; badIndex < N; ++badIndex)
-Sum += arr[I];
+  for (int I = 0; BadIndex < N; ++BadIndex)
+Sum += Arr[I];
 
-  for (int I = 0; badIndex < N; ++badIndex)
-Sum += arr[badIndex];
+  for (int I = 0; BadIndex < N; ++BadIndex)
+Sum += Arr[BadIndex];
 }
 
 // Checks for multiple arrays Indexed.
 void multipleArrays() {
-  int badArr[N];
+  int BadArr[N];
 
   for (int I = 0; I < N; ++I)
-Sum += arr[I] + badArr[I];
+Sum += Arr[I] + BadArr[I

Re: [PATCH] D13052: Add NamingStyle option to modernize-loop-convert.

2015-09-24 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 35608.
angelgarcia added a comment.

> No need to check the length. `endswith` handles this itself.


I am checking that it is strictly greater than one, because we don't want an 
empty identifier after removing the "s".


http://reviews.llvm.org/D13052

Files:
  clang-tidy/modernize/LoopConvertCheck.cpp
  clang-tidy/modernize/LoopConvertCheck.h
  clang-tidy/modernize/LoopConvertUtils.cpp
  clang-tidy/modernize/LoopConvertUtils.h
  clang-tidy/modernize/ModernizeTidyModule.cpp
  test/clang-tidy/Inputs/modernize-loop-convert/structures.h
  test/clang-tidy/modernize-loop-convert-basic.cpp
  test/clang-tidy/modernize-loop-convert-camelback.cpp
  test/clang-tidy/modernize-loop-convert-extra.cpp
  test/clang-tidy/modernize-loop-convert-lowercase.cpp
  test/clang-tidy/modernize-loop-convert-negative.cpp
  test/clang-tidy/modernize-loop-convert-uppercase.cpp

Index: test/clang-tidy/modernize-loop-convert-uppercase.cpp
===
--- /dev/null
+++ test/clang-tidy/modernize-loop-convert-uppercase.cpp
@@ -0,0 +1,49 @@
+// RUN: %python %S/check_clang_tidy.py %s modernize-loop-convert %t \
+// RUN:   -config="{CheckOptions: [{key: modernize-loop-convert.NamingStyle, value: 'UPPER_CASE'}]}" \
+// RUN:   -- -std=c++11 -I %S/Inputs/modernize-loop-convert
+
+#include "structures.h"
+
+const int N = 10;
+int ARR[N];
+int NUMS[N];
+
+void naming() {
+  for (int I = 0; I < N; ++I) {
+printf("%d\n", ARR[I]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead [modernize-loop-convert]
+  // CHECK-FIXES: for (auto & ELEM : ARR)
+  // CHECK-FIXES-NEXT: printf("%d\n", ELEM);
+
+  for (int I = 0; I < N; ++I) {
+printf("%d\n", NUMS[I]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & NUM : NUMS)
+  // CHECK-FIXES-NEXT: printf("%d\n", NUM);
+
+  int NUM = 0;
+  for (int I = 0; I < N; ++I) {
+printf("%d\n", NUMS[I] + NUM);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & ELEM : NUMS)
+  // CHECK-FIXES-NEXT: printf("%d\n", ELEM + NUM);
+
+  int ELEM = 0;
+  for (int I = 0; I < N; ++I) {
+printf("%d\n", NUMS[I] + NUM + ELEM);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & NUMS_I : NUMS)
+  // CHECK-FIXES-NEXT: printf("%d\n", NUMS_I + NUM + ELEM);
+
+  int NUMS_I = 0;
+  for (int I = 0; I < N; ++I) {
+printf("%d\n", NUMS[I] + NUM + ELEM + NUMS_I);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & NUMS_ELEM : NUMS)
+  // CHECK-FIXES-NEXT: printf("%d\n", NUMS_ELEM + NUM + ELEM + NUMS_I);
+}
Index: test/clang-tidy/modernize-loop-convert-negative.cpp
===
--- test/clang-tidy/modernize-loop-convert-negative.cpp
+++ test/clang-tidy/modernize-loop-convert-negative.cpp
@@ -8,47 +8,47 @@
 namespace Negative {
 
 const int N = 6;
-int arr[N] = {1, 2, 3, 4, 5, 6};
-int (*pArr)[N] = &arr;
+int Arr[N] = {1, 2, 3, 4, 5, 6};
+int (*pArr)[N] = &Arr;
 int Sum = 0;
 
 // Checks for the Index start and end:
 void IndexStartAndEnd() {
   for (int I = 0; I < N + 1; ++I)
-Sum += arr[I];
+Sum += Arr[I];
 
   for (int I = 0; I < N - 1; ++I)
-Sum += arr[I];
+Sum += Arr[I];
 
   for (int I = 1; I < N; ++I)
-Sum += arr[I];
+Sum += Arr[I];
 
   for (int I = 1; I < N; ++I)
-Sum += arr[I];
+Sum += Arr[I];
 
   for (int I = 0;; ++I)
 Sum += (*pArr)[I];
 }
 
 // Checks for invalid increment steps:
 void increment() {
   for (int I = 0; I < N; --I)
-Sum += arr[I];
+Sum += Arr[I];
 
   for (int I = 0; I < N; I)
-Sum += arr[I];
+Sum += Arr[I];
 
   for (int I = 0; I < N;)
-Sum += arr[I];
+Sum += Arr[I];
 
   for (int I = 0; I < N; I += 2)
 Sum++;
 }
 
 // Checks to make sure that the Index isn't used outside of the array:
 void IndexUse() {
   for (int I = 0; I < N; ++I)
-arr[I] += 1 + I;
+Arr[I] += 1 + I;
 }
 
 // Check for loops that don't mention arrays
@@ -65,30 +65,30 @@
 
 // Checks for incorrect loop variables.
 void mixedVariables() {
-  int badIndex;
-  for (int I = 0; badIndex < N; ++I)
-Sum += arr[I];
+  int BadIndex;
+  for (int I = 0; BadIndex < N; ++I)
+Sum += Arr[I];
 
-  for (int I = 0; I < N; ++badIndex)
-Sum += arr[I];
+  for (int I = 0; I < N; ++BadIndex)
+Sum += Arr[I];
 
-  for (int I = 0; badIndex < N; ++badIndex)
-Sum += arr[I];
+  for (int I = 0; BadIndex < N; ++BadIndex)
+Sum += Arr[I];
 
-  for (int I = 0; badIndex < N; ++badIndex)
-Sum += arr[badIndex];
+  for (int I = 0; BadIndex < N; ++BadIndex)
+Sum += Arr[BadIndex];
 }
 
 // Checks for multiple arrays Indexed.
 void multipleArrays() {
-  int badArr[N];
+  int BadArr[N];
 
   for (int I = 0; I < N; ++I)
-Sum +=

Re: [Diffusion] rL248418: Fix loop-convert for const references to containers.

2015-09-24 Thread Angel Garcia via cfe-commits
angelgarcia added a comment.

I sent a patch with that.


Users:
  klimek (Author)

http://reviews.llvm.org/rL248418



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


[PATCH] D13129: Solve comment on rL248418.

2015-09-24 Thread Angel Garcia via cfe-commits
angelgarcia created this revision.
angelgarcia added a reviewer: alexfh.
angelgarcia added subscribers: klimek, cfe-commits.

Solve comment on rL248418.

http://reviews.llvm.org/D13129

Files:
  clang-tidy/modernize/LoopConvertCheck.cpp

Index: clang-tidy/modernize/LoopConvertCheck.cpp
===
--- clang-tidy/modernize/LoopConvertCheck.cpp
+++ clang-tidy/modernize/LoopConvertCheck.cpp
@@ -394,9 +394,7 @@
 // If VDec is a reference to a container, Dereference is false,
 // but we still need to check the const-ness of the underlying container
 // type.
-if (const auto &RT = CType->getAs()) {
-  CType = RT->getPointeeType();
-}
+CType = CType.getNonReferenceType();
 return CType.isConstQualified();
   }
   return false;


Index: clang-tidy/modernize/LoopConvertCheck.cpp
===
--- clang-tidy/modernize/LoopConvertCheck.cpp
+++ clang-tidy/modernize/LoopConvertCheck.cpp
@@ -394,9 +394,7 @@
 // If VDec is a reference to a container, Dereference is false,
 // but we still need to check the const-ness of the underlying container
 // type.
-if (const auto &RT = CType->getAs()) {
-  CType = RT->getPointeeType();
-}
+CType = CType.getNonReferenceType();
 return CType.isConstQualified();
   }
   return false;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D13133: Remove dangling parenthesis.

2015-09-24 Thread Angel Garcia via cfe-commits
angelgarcia created this revision.
angelgarcia added a reviewer: alexfh.
angelgarcia added subscribers: klimek, cfe-commits.

Remove parenthesis surrounding the new loop index.

http://reviews.llvm.org/D13133

Files:
  clang-tidy/modernize/LoopConvertCheck.cpp
  test/clang-tidy/modernize-loop-convert-basic.cpp
  test/clang-tidy/modernize-loop-convert-extra.cpp

Index: test/clang-tidy/modernize-loop-convert-extra.cpp
===
--- test/clang-tidy/modernize-loop-convert-extra.cpp
+++ test/clang-tidy/modernize-loop-convert-extra.cpp
@@ -267,16 +267,16 @@
   }
   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & MAXs_it : MAXs)
-  // CHECK-FIXES-NEXT: printf("s has value %d\n", (MAXs_it).x);
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", MAXs_it.x);
   // CHECK-FIXES-NEXT: printf("Max of 3 and 5: %d\n", MAX(3, 5));
 
   for (S::const_iterator it = MAXs.begin(), e = MAXs.end(); it != e; ++it) {
 printf("s has value %d\n", (*it).x);
 printf("Max of 3 and 5: %d\n", MAX(3, 5));
   }
   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto MAXs_it : MAXs)
-  // CHECK-FIXES-NEXT: printf("s has value %d\n", (MAXs_it).x);
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", MAXs_it.x);
   // CHECK-FIXES-NEXT: printf("Max of 3 and 5: %d\n", MAX(3, 5));
 
   T DEFs;
@@ -307,7 +307,7 @@
   }
   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & __FUNCTION__s_elem : __FUNCTION__s)
-  // CHECK-FIXES-NEXT: int __FUNCTION__s_it = (__FUNCTION__s_elem).x + 2;
+  // CHECK-FIXES-NEXT: int __FUNCTION__s_it = __FUNCTION__s_elem.x + 2;
 }
 
 void typeConflict() {
@@ -457,7 +457,7 @@
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & elem : NestT)
-  // CHECK-FIXES-NEXT: for (T::iterator TI = (elem).begin(), TE = (elem).end(); TI != TE; ++TI)
+  // CHECK-FIXES-NEXT: for (T::iterator TI = elem.begin(), TE = elem.end(); TI != TE; ++TI)
   // CHECK-FIXES-NEXT: printf("%d", *TI);
 
   // The inner loop is also convertible.
@@ -469,7 +469,7 @@
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto elem : NestS)
-  // CHECK-FIXES-NEXT: for (S::const_iterator SI = (elem).begin(), SE = (elem).end(); SI != SE; ++SI)
+  // CHECK-FIXES-NEXT: for (S::const_iterator SI = elem.begin(), SE = elem.end(); SI != SE; ++SI)
   // CHECK-FIXES-NEXT: printf("%d", *SI);
 
   for (Nested::const_iterator I = NestS.begin(), E = NestS.end(); I != E; ++I) {
@@ -557,15 +557,15 @@
   }
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & elem : s)
-  // CHECK-FIXES-NEXT: printf("s has value %d\n", (elem).x);
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", elem.x);
 
   S *ps;
   for (S::iterator it = ps->begin(); it != ps->end(); ++it) {
 printf("s has value %d\n", (*it).x);
   }
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & p : *ps)
-  // CHECK-FIXES-NEXT: printf("s has value %d\n", (p).x);
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", p.x);
 
   for (S::iterator it = s.begin(); it != s.end(); ++it) {
 printf("s has value %d\n", it->x);
@@ -586,7 +586,7 @@
   }
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & elem : s)
-  // CHECK-FIXES-NEXT: (elem).x = 3;
+  // CHECK-FIXES-NEXT: elem.x = 3;
 
   for (S::iterator it = s.begin(); it != s.end(); ++it) {
 it->nonConstFun(4, 5);
@@ -608,7 +608,7 @@
   }
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & elem : u)
-  // CHECK-FIXES-NEXT: printf("s has value %d\n", (elem).x);
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", elem.x);
 
   U::iterator A;
   for (U::iterator i = u.begin(); i != u.end(); ++i)
@@ -656,15 +656,15 @@
   }
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto elem : s)
-  // CHECK-FIXES-NEXT: printf("s has value %d\n", (elem).x);
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", elem.x);
 
   S *ps;
   for (S::const_iterator it = ps->begin(); it != ps->end(); ++it) {
 printf("s has value %d\n", (*it).x);
   }
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto p : *ps)
-  // CHECK-FIXES-NEXT: printf("s has value %d\n", (p).x);
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", p.x);
 
   // v.begin() returns a user-defined type 'iterator' which, since it's
   // different from const_iterator, disqualifies these loops from
Index: test/clang-tidy/modernize-loop-convert-basic.cpp
===
--- test/clang-tidy/

Re: [PATCH] D13133: Remove dangling parenthesis.

2015-09-24 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 35626.
angelgarcia added a comment.

Added a test where the parenthesis must not be removed, and one where they 
should.


http://reviews.llvm.org/D13133

Files:
  clang-tidy/modernize/LoopConvertCheck.cpp
  test/clang-tidy/modernize-loop-convert-basic.cpp
  test/clang-tidy/modernize-loop-convert-extra.cpp

Index: test/clang-tidy/modernize-loop-convert-extra.cpp
===
--- test/clang-tidy/modernize-loop-convert-extra.cpp
+++ test/clang-tidy/modernize-loop-convert-extra.cpp
@@ -267,16 +267,16 @@
   }
   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & MAXs_it : MAXs)
-  // CHECK-FIXES-NEXT: printf("s has value %d\n", (MAXs_it).x);
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", MAXs_it.x);
   // CHECK-FIXES-NEXT: printf("Max of 3 and 5: %d\n", MAX(3, 5));
 
   for (S::const_iterator it = MAXs.begin(), e = MAXs.end(); it != e; ++it) {
 printf("s has value %d\n", (*it).x);
 printf("Max of 3 and 5: %d\n", MAX(3, 5));
   }
   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto MAXs_it : MAXs)
-  // CHECK-FIXES-NEXT: printf("s has value %d\n", (MAXs_it).x);
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", MAXs_it.x);
   // CHECK-FIXES-NEXT: printf("Max of 3 and 5: %d\n", MAX(3, 5));
 
   T DEFs;
@@ -307,7 +307,7 @@
   }
   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & __FUNCTION__s_elem : __FUNCTION__s)
-  // CHECK-FIXES-NEXT: int __FUNCTION__s_it = (__FUNCTION__s_elem).x + 2;
+  // CHECK-FIXES-NEXT: int __FUNCTION__s_it = __FUNCTION__s_elem.x + 2;
 }
 
 void typeConflict() {
@@ -457,7 +457,7 @@
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & elem : NestT)
-  // CHECK-FIXES-NEXT: for (T::iterator TI = (elem).begin(), TE = (elem).end(); TI != TE; ++TI)
+  // CHECK-FIXES-NEXT: for (T::iterator TI = elem.begin(), TE = elem.end(); TI != TE; ++TI)
   // CHECK-FIXES-NEXT: printf("%d", *TI);
 
   // The inner loop is also convertible.
@@ -469,7 +469,7 @@
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto elem : NestS)
-  // CHECK-FIXES-NEXT: for (S::const_iterator SI = (elem).begin(), SE = (elem).end(); SI != SE; ++SI)
+  // CHECK-FIXES-NEXT: for (S::const_iterator SI = elem.begin(), SE = elem.end(); SI != SE; ++SI)
   // CHECK-FIXES-NEXT: printf("%d", *SI);
 
   for (Nested::const_iterator I = NestS.begin(), E = NestS.end(); I != E; ++I) {
@@ -557,15 +557,15 @@
   }
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & elem : s)
-  // CHECK-FIXES-NEXT: printf("s has value %d\n", (elem).x);
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", elem.x);
 
   S *ps;
   for (S::iterator it = ps->begin(); it != ps->end(); ++it) {
 printf("s has value %d\n", (*it).x);
   }
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & p : *ps)
-  // CHECK-FIXES-NEXT: printf("s has value %d\n", (p).x);
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", p.x);
 
   for (S::iterator it = s.begin(); it != s.end(); ++it) {
 printf("s has value %d\n", it->x);
@@ -586,7 +586,7 @@
   }
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & elem : s)
-  // CHECK-FIXES-NEXT: (elem).x = 3;
+  // CHECK-FIXES-NEXT: elem.x = 3;
 
   for (S::iterator it = s.begin(); it != s.end(); ++it) {
 it->nonConstFun(4, 5);
@@ -608,7 +608,7 @@
   }
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & elem : u)
-  // CHECK-FIXES-NEXT: printf("s has value %d\n", (elem).x);
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", elem.x);
 
   U::iterator A;
   for (U::iterator i = u.begin(); i != u.end(); ++i)
@@ -656,15 +656,15 @@
   }
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto elem : s)
-  // CHECK-FIXES-NEXT: printf("s has value %d\n", (elem).x);
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", elem.x);
 
   S *ps;
   for (S::const_iterator it = ps->begin(); it != ps->end(); ++it) {
 printf("s has value %d\n", (*it).x);
   }
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto p : *ps)
-  // CHECK-FIXES-NEXT: printf("s has value %d\n", (p).x);
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", p.x);
 
   // v.begin() returns a user-defined type 'iterator' which, since it's
   // different from const_iterator, disqualifies these loops from
Index: test/clang-tidy/modernize-loop-convert-basic.cpp
===
--- test/clang-tidy/modernize-loo

Re: [PATCH] D13133: Remove dangling parenthesis.

2015-09-24 Thread Angel Garcia via cfe-commits
angelgarcia added a comment.

Usage.Expression can be:
-CXXMemberCallExpr: "container.at(i)"
-CXXOperatorCallExpr: "*it" or "container[i]"
-ArraySubscripExpr: "Arr[i]"
-UnaryOperator: "*ptr"
-MemberExpr: "it->member" (we only replace "it->" with "elem." in this
case).

The point is that all of them except the last one will be replaced by
"elem" (or any other identifier), so it will be a DeclRefExpr after the
change, and the parenthesis can always be removed. I can add a comment
explaining this.


http://reviews.llvm.org/D13133



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


Re: [PATCH] D13133: Remove dangling parenthesis.

2015-09-24 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 35629.
angelgarcia added a comment.

Add comment.


http://reviews.llvm.org/D13133

Files:
  clang-tidy/modernize/LoopConvertCheck.cpp
  test/clang-tidy/modernize-loop-convert-basic.cpp
  test/clang-tidy/modernize-loop-convert-extra.cpp

Index: test/clang-tidy/modernize-loop-convert-extra.cpp
===
--- test/clang-tidy/modernize-loop-convert-extra.cpp
+++ test/clang-tidy/modernize-loop-convert-extra.cpp
@@ -267,16 +267,16 @@
   }
   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & MAXs_it : MAXs)
-  // CHECK-FIXES-NEXT: printf("s has value %d\n", (MAXs_it).x);
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", MAXs_it.x);
   // CHECK-FIXES-NEXT: printf("Max of 3 and 5: %d\n", MAX(3, 5));
 
   for (S::const_iterator it = MAXs.begin(), e = MAXs.end(); it != e; ++it) {
 printf("s has value %d\n", (*it).x);
 printf("Max of 3 and 5: %d\n", MAX(3, 5));
   }
   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto MAXs_it : MAXs)
-  // CHECK-FIXES-NEXT: printf("s has value %d\n", (MAXs_it).x);
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", MAXs_it.x);
   // CHECK-FIXES-NEXT: printf("Max of 3 and 5: %d\n", MAX(3, 5));
 
   T DEFs;
@@ -307,7 +307,7 @@
   }
   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & __FUNCTION__s_elem : __FUNCTION__s)
-  // CHECK-FIXES-NEXT: int __FUNCTION__s_it = (__FUNCTION__s_elem).x + 2;
+  // CHECK-FIXES-NEXT: int __FUNCTION__s_it = __FUNCTION__s_elem.x + 2;
 }
 
 void typeConflict() {
@@ -457,7 +457,7 @@
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & elem : NestT)
-  // CHECK-FIXES-NEXT: for (T::iterator TI = (elem).begin(), TE = (elem).end(); TI != TE; ++TI)
+  // CHECK-FIXES-NEXT: for (T::iterator TI = elem.begin(), TE = elem.end(); TI != TE; ++TI)
   // CHECK-FIXES-NEXT: printf("%d", *TI);
 
   // The inner loop is also convertible.
@@ -469,7 +469,7 @@
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto elem : NestS)
-  // CHECK-FIXES-NEXT: for (S::const_iterator SI = (elem).begin(), SE = (elem).end(); SI != SE; ++SI)
+  // CHECK-FIXES-NEXT: for (S::const_iterator SI = elem.begin(), SE = elem.end(); SI != SE; ++SI)
   // CHECK-FIXES-NEXT: printf("%d", *SI);
 
   for (Nested::const_iterator I = NestS.begin(), E = NestS.end(); I != E; ++I) {
@@ -557,15 +557,15 @@
   }
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & elem : s)
-  // CHECK-FIXES-NEXT: printf("s has value %d\n", (elem).x);
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", elem.x);
 
   S *ps;
   for (S::iterator it = ps->begin(); it != ps->end(); ++it) {
 printf("s has value %d\n", (*it).x);
   }
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & p : *ps)
-  // CHECK-FIXES-NEXT: printf("s has value %d\n", (p).x);
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", p.x);
 
   for (S::iterator it = s.begin(); it != s.end(); ++it) {
 printf("s has value %d\n", it->x);
@@ -586,7 +586,7 @@
   }
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & elem : s)
-  // CHECK-FIXES-NEXT: (elem).x = 3;
+  // CHECK-FIXES-NEXT: elem.x = 3;
 
   for (S::iterator it = s.begin(); it != s.end(); ++it) {
 it->nonConstFun(4, 5);
@@ -608,7 +608,7 @@
   }
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & elem : u)
-  // CHECK-FIXES-NEXT: printf("s has value %d\n", (elem).x);
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", elem.x);
 
   U::iterator A;
   for (U::iterator i = u.begin(); i != u.end(); ++i)
@@ -656,15 +656,15 @@
   }
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto elem : s)
-  // CHECK-FIXES-NEXT: printf("s has value %d\n", (elem).x);
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", elem.x);
 
   S *ps;
   for (S::const_iterator it = ps->begin(); it != ps->end(); ++it) {
 printf("s has value %d\n", (*it).x);
   }
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto p : *ps)
-  // CHECK-FIXES-NEXT: printf("s has value %d\n", (p).x);
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", p.x);
 
   // v.begin() returns a user-defined type 'iterator' which, since it's
   // different from const_iterator, disqualifies these loops from
Index: test/clang-tidy/modernize-loop-convert-basic.cpp
===
--- test/clang-tidy/modernize-loop-convert-basic.cpp
+++ test/clang-tidy/modernize-loop-convert-basic.cp

Re: [PATCH] D13052: Add NamingStyle option to modernize-loop-convert.

2015-09-24 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 35630.
angelgarcia added a comment.

Done!


http://reviews.llvm.org/D13052

Files:
  clang-tidy/modernize/LoopConvertCheck.cpp
  clang-tidy/modernize/LoopConvertCheck.h
  clang-tidy/modernize/LoopConvertUtils.cpp
  clang-tidy/modernize/LoopConvertUtils.h
  clang-tidy/modernize/ModernizeTidyModule.cpp
  test/clang-tidy/Inputs/modernize-loop-convert/structures.h
  test/clang-tidy/modernize-loop-convert-basic.cpp
  test/clang-tidy/modernize-loop-convert-camelback.cpp
  test/clang-tidy/modernize-loop-convert-extra.cpp
  test/clang-tidy/modernize-loop-convert-lowercase.cpp
  test/clang-tidy/modernize-loop-convert-negative.cpp
  test/clang-tidy/modernize-loop-convert-uppercase.cpp

Index: test/clang-tidy/modernize-loop-convert-uppercase.cpp
===
--- /dev/null
+++ test/clang-tidy/modernize-loop-convert-uppercase.cpp
@@ -0,0 +1,65 @@
+// RUN: %python %S/check_clang_tidy.py %s modernize-loop-convert %t \
+// RUN:   -config="{CheckOptions: [{key: modernize-loop-convert.NamingStyle, value: 'UPPER_CASE'}]}" \
+// RUN:   -- -std=c++11 -I %S/Inputs/modernize-loop-convert
+
+#include "structures.h"
+
+const int N = 10;
+int ARR[N];
+int NUMS[N];
+
+void naming() {
+  for (int I = 0; I < N; ++I) {
+printf("%d\n", ARR[I]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead [modernize-loop-convert]
+  // CHECK-FIXES: for (auto & ELEM : ARR)
+  // CHECK-FIXES-NEXT: printf("%d\n", ELEM);
+
+  for (int I = 0; I < N; ++I) {
+printf("%d\n", NUMS[I]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & NUM : NUMS)
+  // CHECK-FIXES-NEXT: printf("%d\n", NUM);
+
+  int NUM = 0;
+  for (int I = 0; I < N; ++I) {
+printf("%d\n", NUMS[I] + NUM);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & ELEM : NUMS)
+  // CHECK-FIXES-NEXT: printf("%d\n", ELEM + NUM);
+
+  int ELEM = 0;
+  for (int I = 0; I < N; ++I) {
+printf("%d\n", NUMS[I] + NUM + ELEM);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & NUMS_I : NUMS)
+  // CHECK-FIXES-NEXT: printf("%d\n", NUMS_I + NUM + ELEM);
+
+  int NUMS_I = 0;
+  for (int I = 0; I < N; ++I) {
+printf("%d\n", NUMS[I] + NUM + ELEM + NUMS_I);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & NUMS_ELEM : NUMS)
+  // CHECK-FIXES-NEXT: printf("%d\n", NUMS_ELEM + NUM + ELEM + NUMS_I);
+
+  int NUMS_ELEM = 0;
+  for (int I = 0; I < N; ++I) {
+printf("%d\n", NUMS[I] + NUM + ELEM + NUMS_I + NUMS_ELEM);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & GIVE_ME_NAME_0 : NUMS)
+  // CHECK-FIXES-NEXT: printf("%d\n", GIVE_ME_NAME_0 + NUM + ELEM + NUMS_I + NUMS_ELEM);
+
+  int GIVE_ME_NAME_0 = 0;
+  for (int I = 0; I < N; ++I) {
+printf("%d\n", NUMS[I] + NUM + ELEM + NUMS_I + NUMS_ELEM + GIVE_ME_NAME_0);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & GIVE_ME_NAME_1 : NUMS)
+  // CHECK-FIXES-NEXT: printf("%d\n", GIVE_ME_NAME_1 + NUM + ELEM + NUMS_I + NUMS_ELEM + GIVE_ME_NAME_0);
+}
Index: test/clang-tidy/modernize-loop-convert-negative.cpp
===
--- test/clang-tidy/modernize-loop-convert-negative.cpp
+++ test/clang-tidy/modernize-loop-convert-negative.cpp
@@ -8,47 +8,47 @@
 namespace Negative {
 
 const int N = 6;
-int arr[N] = {1, 2, 3, 4, 5, 6};
-int (*pArr)[N] = &arr;
+int Arr[N] = {1, 2, 3, 4, 5, 6};
+int (*pArr)[N] = &Arr;
 int Sum = 0;
 
 // Checks for the Index start and end:
 void IndexStartAndEnd() {
   for (int I = 0; I < N + 1; ++I)
-Sum += arr[I];
+Sum += Arr[I];
 
   for (int I = 0; I < N - 1; ++I)
-Sum += arr[I];
+Sum += Arr[I];
 
   for (int I = 1; I < N; ++I)
-Sum += arr[I];
+Sum += Arr[I];
 
   for (int I = 1; I < N; ++I)
-Sum += arr[I];
+Sum += Arr[I];
 
   for (int I = 0;; ++I)
 Sum += (*pArr)[I];
 }
 
 // Checks for invalid increment steps:
 void increment() {
   for (int I = 0; I < N; --I)
-Sum += arr[I];
+Sum += Arr[I];
 
   for (int I = 0; I < N; I)
-Sum += arr[I];
+Sum += Arr[I];
 
   for (int I = 0; I < N;)
-Sum += arr[I];
+Sum += Arr[I];
 
   for (int I = 0; I < N; I += 2)
 Sum++;
 }
 
 // Checks to make sure that the Index isn't used outside of the array:
 void IndexUse() {
   for (int I = 0; I < N; ++I)
-arr[I] += 1 + I;
+Arr[I] += 1 + I;
 }
 
 // Check for loops that don't mention arrays
@@ -65,30 +65,30 @@
 
 // Checks for incorrect loop variables.
 void mixedVariables() {
-  int badIndex;
-  for (int I = 0; badIndex < N; ++I)
-Sum += arr[I];
+  int BadIndex;
+  for (int I = 0; BadIndex < N; ++I)
+

[PATCH] D13166: Create modernize-make-unique check.

2015-09-25 Thread Angel Garcia via cfe-commits
angelgarcia created this revision.
angelgarcia added a reviewer: alexfh.
angelgarcia added subscribers: klimek, cfe-commits.

create a check that replaces 'std::unique_ptr(new type(args...))' with 
'std::make_unique(args...)'. It was on the list of "Ideas for new Tools". 
It needs to be tested more carefully, but first I wanted to know if you think 
it is worth the effort.

http://reviews.llvm.org/D13166

Files:
  clang-tidy/modernize/CMakeLists.txt
  clang-tidy/modernize/MakeUniqueCheck.cpp
  clang-tidy/modernize/MakeUniqueCheck.h
  clang-tidy/modernize/ModernizeTidyModule.cpp
  test/clang-tidy/modernize-make-unique.cpp

Index: test/clang-tidy/modernize-make-unique.cpp
===
--- /dev/null
+++ test/clang-tidy/modernize-make-unique.cpp
@@ -0,0 +1,92 @@
+// RUN: %python %S/check_clang_tidy.py %s modernize-make-unique %t
+
+namespace std {
+
+template 
+class unique_ptr {
+public:
+  unique_ptr(type *ptr);
+  unique_ptr(const unique_ptr &t) = delete;
+  unique_ptr(unique_ptr &&t);
+  ~unique_ptr();
+  type &operator*() { return *ptr; }
+  type *operator->() { return ptr; }
+  type *release();
+  void reset();
+  void reset(type *pt);
+
+private:
+  type *ptr;
+};
+
+}
+
+struct Base {
+  Base();
+  Base(int, int);
+};
+
+struct Derived : public Base {
+  Derived();
+  Derived(int, int);
+};
+
+struct Pair {
+  int a, b;
+};
+
+int g(std::unique_ptr P);
+
+std::unique_ptr getPointer() {
+  return std::unique_ptr(new Base);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use std::make_unique instead
+  // CHECK-FIXES: return std::make_unique();
+}
+
+void f() {
+  std::unique_ptr P1 = std::unique_ptr(new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_unique instead [modernize-make-unique]
+  // CHECK-FIXES: std::unique_ptr P1 = std::make_unique();
+
+  // Without parenthesis
+  std::unique_ptr P2 = std::unique_ptr(new int);
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_unique instead [modernize-make-unique]
+  // CHECK-FIXES: std::unique_ptr P2 = std::make_unique();
+
+  // With auto.
+  auto P3 = std::unique_ptr(new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_unique instead
+  // CHECK-FIXES: auto P3 = std::make_unique();
+
+  {
+// No std.
+using namespace std;
+unique_ptr Q = unique_ptr(new int());
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use std::make_unique instead
+// CHECK-FIXES: unique_ptr Q = std::make_unique();
+  }
+
+  std::unique_ptr R(new int());
+
+  // Create the unique_ptr as a parameter to a function.
+  int T = g(std::unique_ptr(new int()));
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_unique instead
+  // CHECK-FIXES: int T = g(std::make_unique());
+
+  // Arguments are correctly handled.
+  std::unique_ptr Pbase = std::unique_ptr(new Base(5, T));
+  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr Pbase = std::make_unique(5, T);
+
+  // Works with init lists.
+  std::unique_ptr Ppair = std::unique_ptr(new Pair{T, 1});
+  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr Ppair = std::make_unique({T, 1});
+
+  // Only replace if the type in the template is the same than the type returned
+  // by the new operator.
+  auto Pderived = std::unique_ptr(new Derived());
+
+  // The pointer is returned by the function, nothing to do.
+  std::unique_ptr RetPtr = getPointer();
+}
Index: clang-tidy/modernize/ModernizeTidyModule.cpp
===
--- clang-tidy/modernize/ModernizeTidyModule.cpp
+++ clang-tidy/modernize/ModernizeTidyModule.cpp
@@ -11,6 +11,7 @@
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
 #include "LoopConvertCheck.h"
+#include "MakeUniqueCheck.h"
 #include "PassByValueCheck.h"
 #include "ReplaceAutoPtrCheck.h"
 #include "ShrinkToFitCheck.h"
@@ -28,6 +29,8 @@
 public:
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
 CheckFactories.registerCheck("modernize-loop-convert");
+CheckFactories.registerCheck(
+"modernize-make-unique");
 CheckFactories.registerCheck("modernize-pass-by-value");
 CheckFactories.registerCheck(
 "modernize-replace-auto-ptr");
Index: clang-tidy/modernize/MakeUniqueCheck.h
===
--- /dev/null
+++ clang-tidy/modernize/MakeUniqueCheck.h
@@ -0,0 +1,41 @@
+//===--- MakeUniqueCheck.h - clang-tidy--*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_MAKE_UNIQUE_H
+#define LLVM_CLANG_T

Re: [PATCH] D13166: Create modernize-make-unique check.

2015-09-28 Thread Angel Garcia via cfe-commits
angelgarcia added inline comments.


Comment at: clang-tidy/modernize/MakeUniqueCheck.cpp:25-27
@@ +24,5 @@
+
+/// \brief Returns the length of the token that goes since the beggining of the
+/// constructor call until the '<' of the template. This token should either be
+/// 'unique_ptr' or 'std::unique_ptr'. In any other case, it returns 0.
+static int getTokenLength(SourceLocation TokenStart, const SourceManager &SM,

klimek wrote:
> How can that ever return 0 if you have matchesName("::std::unique_ptr") below?
Maybe using macros or something like that. As I said, it needs to be more 
carefully tested.


http://reviews.llvm.org/D13166



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


Re: [PATCH] D13166: Create modernize-make-unique check.

2015-09-28 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 35839.
angelgarcia marked an inline comment as done.
angelgarcia added a comment.

Remove 'hasCanonicalType'.


http://reviews.llvm.org/D13166

Files:
  clang-tidy/modernize/CMakeLists.txt
  clang-tidy/modernize/MakeUniqueCheck.cpp
  clang-tidy/modernize/MakeUniqueCheck.h
  clang-tidy/modernize/ModernizeTidyModule.cpp
  test/clang-tidy/modernize-make-unique.cpp

Index: test/clang-tidy/modernize-make-unique.cpp
===
--- /dev/null
+++ test/clang-tidy/modernize-make-unique.cpp
@@ -0,0 +1,92 @@
+// RUN: %python %S/check_clang_tidy.py %s modernize-make-unique %t
+
+namespace std {
+
+template 
+class unique_ptr {
+public:
+  unique_ptr(type *ptr);
+  unique_ptr(const unique_ptr &t) = delete;
+  unique_ptr(unique_ptr &&t);
+  ~unique_ptr();
+  type &operator*() { return *ptr; }
+  type *operator->() { return ptr; }
+  type *release();
+  void reset();
+  void reset(type *pt);
+
+private:
+  type *ptr;
+};
+
+}
+
+struct Base {
+  Base();
+  Base(int, int);
+};
+
+struct Derived : public Base {
+  Derived();
+  Derived(int, int);
+};
+
+struct Pair {
+  int a, b;
+};
+
+int g(std::unique_ptr P);
+
+std::unique_ptr getPointer() {
+  return std::unique_ptr(new Base);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use std::make_unique instead
+  // CHECK-FIXES: return std::make_unique();
+}
+
+void f() {
+  std::unique_ptr P1 = std::unique_ptr(new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_unique instead [modernize-make-unique]
+  // CHECK-FIXES: std::unique_ptr P1 = std::make_unique();
+
+  // Without parenthesis
+  std::unique_ptr P2 = std::unique_ptr(new int);
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_unique instead [modernize-make-unique]
+  // CHECK-FIXES: std::unique_ptr P2 = std::make_unique();
+
+  // With auto.
+  auto P3 = std::unique_ptr(new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_unique instead
+  // CHECK-FIXES: auto P3 = std::make_unique();
+
+  {
+// No std.
+using namespace std;
+unique_ptr Q = unique_ptr(new int());
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use std::make_unique instead
+// CHECK-FIXES: unique_ptr Q = std::make_unique();
+  }
+
+  std::unique_ptr R(new int());
+
+  // Create the unique_ptr as a parameter to a function.
+  int T = g(std::unique_ptr(new int()));
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_unique instead
+  // CHECK-FIXES: int T = g(std::make_unique());
+
+  // Arguments are correctly handled.
+  std::unique_ptr Pbase = std::unique_ptr(new Base(5, T));
+  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr Pbase = std::make_unique(5, T);
+
+  // Works with init lists.
+  std::unique_ptr Ppair = std::unique_ptr(new Pair{T, 1});
+  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr Ppair = std::make_unique({T, 1});
+
+  // Only replace if the type in the template is the same than the type returned
+  // by the new operator.
+  auto Pderived = std::unique_ptr(new Derived());
+
+  // The pointer is returned by the function, nothing to do.
+  std::unique_ptr RetPtr = getPointer();
+}
Index: clang-tidy/modernize/ModernizeTidyModule.cpp
===
--- clang-tidy/modernize/ModernizeTidyModule.cpp
+++ clang-tidy/modernize/ModernizeTidyModule.cpp
@@ -11,6 +11,7 @@
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
 #include "LoopConvertCheck.h"
+#include "MakeUniqueCheck.h"
 #include "PassByValueCheck.h"
 #include "ReplaceAutoPtrCheck.h"
 #include "ShrinkToFitCheck.h"
@@ -28,6 +29,8 @@
 public:
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
 CheckFactories.registerCheck("modernize-loop-convert");
+CheckFactories.registerCheck(
+"modernize-make-unique");
 CheckFactories.registerCheck("modernize-pass-by-value");
 CheckFactories.registerCheck(
 "modernize-replace-auto-ptr");
Index: clang-tidy/modernize/MakeUniqueCheck.h
===
--- /dev/null
+++ clang-tidy/modernize/MakeUniqueCheck.h
@@ -0,0 +1,41 @@
+//===--- MakeUniqueCheck.h - clang-tidy--*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_MAKE_UNIQUE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_MAKE_UNIQUE_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+/// Replace the pattern:
+/// \code
+///   std::unique_ptr(new type(args...))
+/// 

Re: [PATCH] D13166: Create modernize-make-unique check.

2015-09-28 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 35841.
angelgarcia added a comment.

Two tests in which 'getTokenLength' returns 0.


http://reviews.llvm.org/D13166

Files:
  clang-tidy/modernize/CMakeLists.txt
  clang-tidy/modernize/MakeUniqueCheck.cpp
  clang-tidy/modernize/MakeUniqueCheck.h
  clang-tidy/modernize/ModernizeTidyModule.cpp
  test/clang-tidy/modernize-make-unique.cpp

Index: test/clang-tidy/modernize-make-unique.cpp
===
--- /dev/null
+++ test/clang-tidy/modernize-make-unique.cpp
@@ -0,0 +1,99 @@
+// RUN: %python %S/check_clang_tidy.py %s modernize-make-unique %t
+
+namespace std {
+
+template 
+class unique_ptr {
+public:
+  unique_ptr(type *ptr);
+  unique_ptr(const unique_ptr &t) = delete;
+  unique_ptr(unique_ptr &&t);
+  ~unique_ptr();
+  type &operator*() { return *ptr; }
+  type *operator->() { return ptr; }
+  type *release();
+  void reset();
+  void reset(type *pt);
+
+private:
+  type *ptr;
+};
+
+}
+
+struct Base {
+  Base();
+  Base(int, int);
+};
+
+struct Derived : public Base {
+  Derived();
+  Derived(int, int);
+};
+
+struct Pair {
+  int a, b;
+};
+
+int g(std::unique_ptr P);
+
+std::unique_ptr getPointer() {
+  return std::unique_ptr(new Base);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use std::make_unique instead
+  // CHECK-FIXES: return std::make_unique();
+}
+
+void f() {
+  std::unique_ptr P1 = std::unique_ptr(new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_unique instead [modernize-make-unique]
+  // CHECK-FIXES: std::unique_ptr P1 = std::make_unique();
+
+  // Without parenthesis.
+  std::unique_ptr P2 = std::unique_ptr(new int);
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_unique instead [modernize-make-unique]
+  // CHECK-FIXES: std::unique_ptr P2 = std::make_unique();
+
+  // With auto.
+  auto P3 = std::unique_ptr(new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_unique instead
+  // CHECK-FIXES: auto P3 = std::make_unique();
+
+  {
+// No std.
+using namespace std;
+unique_ptr Q = unique_ptr(new int());
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use std::make_unique instead
+// CHECK-FIXES: unique_ptr Q = std::make_unique();
+  }
+
+  std::unique_ptr R(new int());
+
+  // Create the unique_ptr as a parameter to a function.
+  int T = g(std::unique_ptr(new int()));
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_unique instead
+  // CHECK-FIXES: int T = g(std::make_unique());
+
+  // Arguments are correctly handled.
+  std::unique_ptr Pbase = std::unique_ptr(new Base(5, T));
+  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr Pbase = std::make_unique(5, T);
+
+  // Works with init lists.
+  std::unique_ptr Ppair = std::unique_ptr(new Pair{T, 1});
+  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr Ppair = std::make_unique({T, 1});
+
+  // Only replace if the type in the template is the same than the type returned
+  // by the new operator.
+  auto Pderived = std::unique_ptr(new Derived());
+
+  // The pointer is returned by the function, nothing to do.
+  std::unique_ptr RetPtr = getPointer();
+
+  typedef std::unique_ptr IntPtr;
+  IntPtr Ipt = IntPtr(new int);
+
+#define PTR unique_ptr
+  std::unique_ptr Macro = std::PTR(new int);
+#undef PTR
+}
Index: clang-tidy/modernize/ModernizeTidyModule.cpp
===
--- clang-tidy/modernize/ModernizeTidyModule.cpp
+++ clang-tidy/modernize/ModernizeTidyModule.cpp
@@ -11,6 +11,7 @@
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
 #include "LoopConvertCheck.h"
+#include "MakeUniqueCheck.h"
 #include "PassByValueCheck.h"
 #include "ReplaceAutoPtrCheck.h"
 #include "ShrinkToFitCheck.h"
@@ -28,6 +29,8 @@
 public:
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
 CheckFactories.registerCheck("modernize-loop-convert");
+CheckFactories.registerCheck(
+"modernize-make-unique");
 CheckFactories.registerCheck("modernize-pass-by-value");
 CheckFactories.registerCheck(
 "modernize-replace-auto-ptr");
Index: clang-tidy/modernize/MakeUniqueCheck.h
===
--- /dev/null
+++ clang-tidy/modernize/MakeUniqueCheck.h
@@ -0,0 +1,41 @@
+//===--- MakeUniqueCheck.h - clang-tidy--*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_MAKE_UNIQUE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_MAKE_UNIQUE_H
+
+#include "../ClangTidy.h"
+
+namespace clang 

Re: [PATCH] D13166: Create modernize-make-unique check.

2015-09-28 Thread Angel Garcia via cfe-commits
angelgarcia added a comment.

How can Lexer::getSourceText give us the range? My problem precisely is
that I couldn't find any way to obtain the range of the constructor call
without the template arguments.


http://reviews.llvm.org/D13166



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


Re: [PATCH] D13166: Create modernize-make-unique check.

2015-09-28 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 35864.
angelgarcia added a comment.

I think this is a bit better than before.


http://reviews.llvm.org/D13166

Files:
  clang-tidy/modernize/CMakeLists.txt
  clang-tidy/modernize/MakeUniqueCheck.cpp
  clang-tidy/modernize/MakeUniqueCheck.h
  clang-tidy/modernize/ModernizeTidyModule.cpp
  test/clang-tidy/modernize-make-unique.cpp

Index: test/clang-tidy/modernize-make-unique.cpp
===
--- /dev/null
+++ test/clang-tidy/modernize-make-unique.cpp
@@ -0,0 +1,116 @@
+// RUN: %python %S/check_clang_tidy.py %s modernize-make-unique %t
+
+namespace std {
+
+template 
+class unique_ptr {
+public:
+  unique_ptr(type *ptr);
+  unique_ptr(const unique_ptr &t) = delete;
+  unique_ptr(unique_ptr &&t);
+  ~unique_ptr();
+  type &operator*() { return *ptr; }
+  type *operator->() { return ptr; }
+  type *release();
+  void reset();
+  void reset(type *pt);
+
+private:
+  type *ptr;
+};
+
+}
+
+struct Base {
+  Base();
+  Base(int, int);
+};
+
+struct Derived : public Base {
+  Derived();
+  Derived(int, int);
+};
+
+struct Pair {
+  int a, b;
+};
+
+template using unique_ptr_ = std::unique_ptr;
+
+int g(std::unique_ptr P);
+
+std::unique_ptr getPointer() {
+  return std::unique_ptr(new Base);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use std::make_unique instead
+  // CHECK-FIXES: return std::make_unique();
+}
+
+void f() {
+  std::unique_ptr P1 = std::unique_ptr(new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_unique instead [modernize-make-unique]
+  // CHECK-FIXES: std::unique_ptr P1 = std::make_unique();
+
+  // Without parenthesis.
+  std::unique_ptr P2 = std::unique_ptr(new int);
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_unique instead [modernize-make-unique]
+  // CHECK-FIXES: std::unique_ptr P2 = std::make_unique();
+
+  // With auto.
+  auto P3 = std::unique_ptr(new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_unique instead
+  // CHECK-FIXES: auto P3 = std::make_unique();
+
+  {
+// No std.
+using namespace std;
+unique_ptr Q = unique_ptr(new int());
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use std::make_unique instead
+// CHECK-FIXES: unique_ptr Q = std::make_unique();
+  }
+
+  std::unique_ptr R(new int());
+
+  // Create the unique_ptr as a parameter to a function.
+  int T = g(std::unique_ptr(new int()));
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_unique instead
+  // CHECK-FIXES: int T = g(std::make_unique());
+
+  // Arguments are correctly handled.
+  std::unique_ptr Pbase = std::unique_ptr(new Base(5, T));
+  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr Pbase = std::make_unique(5, T);
+
+  // Works with init lists.
+  std::unique_ptr Ppair = std::unique_ptr(new Pair{T, 1});
+  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr Ppair = std::make_unique({T, 1});
+
+  // Only replace if the type in the template is the same than the type returned
+  // by the new operator.
+  auto Pderived = std::unique_ptr(new Derived());
+
+  // The pointer is returned by the function, nothing to do.
+  std::unique_ptr RetPtr = getPointer();
+
+  // Aliases.
+  typedef std::unique_ptr IntPtr;
+  IntPtr Typedef = IntPtr(new int);
+
+#define PTR unique_ptr
+  std::unique_ptr Macro = std::PTR(new int);
+#undef PTR
+
+  std::unique_ptr Using = unique_ptr_(new int);
+
+  // This emulates std::move.
+  std::unique_ptr Move = static_cast&&>(P1);
+
+  // Adding whitespaces.
+  auto Space = std::unique_ptr (new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use std::make_unique instead
+  // CHECK-FIXES: auto Space = std::make_unique();
+
+  auto Spaces = std  ::unique_ptr  (new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use std::make_unique instead
+  // CHECK-FIXES: auto Spaces = std::make_unique();
+}
Index: clang-tidy/modernize/ModernizeTidyModule.cpp
===
--- clang-tidy/modernize/ModernizeTidyModule.cpp
+++ clang-tidy/modernize/ModernizeTidyModule.cpp
@@ -11,6 +11,7 @@
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
 #include "LoopConvertCheck.h"
+#include "MakeUniqueCheck.h"
 #include "PassByValueCheck.h"
 #include "ReplaceAutoPtrCheck.h"
 #include "ShrinkToFitCheck.h"
@@ -28,6 +29,8 @@
 public:
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
 CheckFactories.registerCheck("modernize-loop-convert");
+CheckFactories.registerCheck(
+"modernize-make-unique");
 CheckFactories.registerCheck("modernize-pass-by-value");
 CheckFactories.registerCheck(
 "modernize-replace-auto-ptr");
Index: clang-tidy/modernize/MakeUniqueCheck.h
===
--- /dev/null
+++ clang-ti

Re: [PATCH] D13166: Create modernize-make-unique check.

2015-09-28 Thread Angel Garcia via cfe-commits
angelgarcia added a comment.

This raises a question. Do we want to do replacements when we use an alias
for std::unique_ptr? That fact that something is an unique_ptr might be an
implementation detail that should not be exposed, but it could also happen
that the alias is there only for brevity. What do you think?


http://reviews.llvm.org/D13166



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


Re: [PATCH] D13166: Create modernize-make-unique check.

2015-09-28 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 35873.
angelgarcia added a comment.

Also replace on aliases.


http://reviews.llvm.org/D13166

Files:
  clang-tidy/modernize/CMakeLists.txt
  clang-tidy/modernize/MakeUniqueCheck.cpp
  clang-tidy/modernize/MakeUniqueCheck.h
  clang-tidy/modernize/ModernizeTidyModule.cpp
  test/clang-tidy/modernize-make-unique.cpp

Index: test/clang-tidy/modernize-make-unique.cpp
===
--- /dev/null
+++ test/clang-tidy/modernize-make-unique.cpp
@@ -0,0 +1,122 @@
+// RUN: %python %S/check_clang_tidy.py %s modernize-make-unique %t
+
+namespace std {
+
+template 
+class unique_ptr {
+public:
+  unique_ptr(type *ptr);
+  unique_ptr(const unique_ptr &t) = delete;
+  unique_ptr(unique_ptr &&t);
+  ~unique_ptr();
+  type &operator*() { return *ptr; }
+  type *operator->() { return ptr; }
+  type *release();
+  void reset();
+  void reset(type *pt);
+
+private:
+  type *ptr;
+};
+
+}
+
+struct Base {
+  Base();
+  Base(int, int);
+};
+
+struct Derived : public Base {
+  Derived();
+  Derived(int, int);
+};
+
+struct Pair {
+  int a, b;
+};
+
+template using unique_ptr_ = std::unique_ptr;
+
+int g(std::unique_ptr P);
+
+std::unique_ptr getPointer() {
+  return std::unique_ptr(new Base);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use std::make_unique instead
+  // CHECK-FIXES: return std::make_unique();
+}
+
+void f() {
+  std::unique_ptr P1 = std::unique_ptr(new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_unique instead [modernize-make-unique]
+  // CHECK-FIXES: std::unique_ptr P1 = std::make_unique();
+
+  // Without parenthesis.
+  std::unique_ptr P2 = std::unique_ptr(new int);
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_unique instead [modernize-make-unique]
+  // CHECK-FIXES: std::unique_ptr P2 = std::make_unique();
+
+  // With auto.
+  auto P3 = std::unique_ptr(new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_unique instead
+  // CHECK-FIXES: auto P3 = std::make_unique();
+
+  {
+// No std.
+using namespace std;
+unique_ptr Q = unique_ptr(new int());
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use std::make_unique instead
+// CHECK-FIXES: unique_ptr Q = std::make_unique();
+  }
+
+  std::unique_ptr R(new int());
+
+  // Create the unique_ptr as a parameter to a function.
+  int T = g(std::unique_ptr(new int()));
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_unique instead
+  // CHECK-FIXES: int T = g(std::make_unique());
+
+  // Arguments are correctly handled.
+  std::unique_ptr Pbase = std::unique_ptr(new Base(5, T));
+  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr Pbase = std::make_unique(5, T);
+
+  // Works with init lists.
+  std::unique_ptr Ppair = std::unique_ptr(new Pair{T, 1});
+  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr Ppair = std::make_unique({T, 1});
+
+  // Only replace if the type in the template is the same than the type returned
+  // by the new operator.
+  auto Pderived = std::unique_ptr(new Derived());
+
+  // The pointer is returned by the function, nothing to do.
+  std::unique_ptr RetPtr = getPointer();
+
+  // Aliases.
+  typedef std::unique_ptr IntPtr;
+  IntPtr Typedef = IntPtr(new int);
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use std::make_unique instead
+  // CHECK-FIXES: IntPtr Typedef = std::make_unique();
+
+#define PTR unique_ptr
+  std::unique_ptr Macro = std::PTR(new int);
+  // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr Macro = std::make_unique();
+#undef PTR
+
+  std::unique_ptr Using = unique_ptr_(new int);
+  // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr Using = std::make_unique();
+
+  // This emulates std::move.
+  std::unique_ptr Move = static_cast&&>(P1);
+
+  // Adding whitespaces.
+  auto Space = std::unique_ptr (new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use std::make_unique instead
+  // CHECK-FIXES: auto Space = std::make_unique();
+
+  auto Spaces = std  ::unique_ptr  (new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use std::make_unique instead
+  // CHECK-FIXES: auto Spaces = std::make_unique();
+}
Index: clang-tidy/modernize/ModernizeTidyModule.cpp
===
--- clang-tidy/modernize/ModernizeTidyModule.cpp
+++ clang-tidy/modernize/ModernizeTidyModule.cpp
@@ -11,6 +11,7 @@
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
 #include "LoopConvertCheck.h"
+#include "MakeUniqueCheck.h"
 #include "PassByValueCheck.h"
 #include "ReplaceAutoPtrCheck.h"
 #include "ShrinkToFitCheck.h"
@@ -28,6 +29,8 @@
 public:
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
 CheckFa

Re: [PATCH] D13166: Create modernize-make-unique check.

2015-09-29 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 35949.
angelgarcia added a comment.

Add a comment.


http://reviews.llvm.org/D13166

Files:
  clang-tidy/modernize/CMakeLists.txt
  clang-tidy/modernize/MakeUniqueCheck.cpp
  clang-tidy/modernize/MakeUniqueCheck.h
  clang-tidy/modernize/ModernizeTidyModule.cpp
  test/clang-tidy/modernize-make-unique.cpp

Index: test/clang-tidy/modernize-make-unique.cpp
===
--- /dev/null
+++ test/clang-tidy/modernize-make-unique.cpp
@@ -0,0 +1,122 @@
+// RUN: %python %S/check_clang_tidy.py %s modernize-make-unique %t
+
+namespace std {
+
+template 
+class unique_ptr {
+public:
+  unique_ptr(type *ptr);
+  unique_ptr(const unique_ptr &t) = delete;
+  unique_ptr(unique_ptr &&t);
+  ~unique_ptr();
+  type &operator*() { return *ptr; }
+  type *operator->() { return ptr; }
+  type *release();
+  void reset();
+  void reset(type *pt);
+
+private:
+  type *ptr;
+};
+
+}
+
+struct Base {
+  Base();
+  Base(int, int);
+};
+
+struct Derived : public Base {
+  Derived();
+  Derived(int, int);
+};
+
+struct Pair {
+  int a, b;
+};
+
+template using unique_ptr_ = std::unique_ptr;
+
+int g(std::unique_ptr P);
+
+std::unique_ptr getPointer() {
+  return std::unique_ptr(new Base);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use std::make_unique instead
+  // CHECK-FIXES: return std::make_unique();
+}
+
+void f() {
+  std::unique_ptr P1 = std::unique_ptr(new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_unique instead [modernize-make-unique]
+  // CHECK-FIXES: std::unique_ptr P1 = std::make_unique();
+
+  // Without parenthesis.
+  std::unique_ptr P2 = std::unique_ptr(new int);
+  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_unique instead [modernize-make-unique]
+  // CHECK-FIXES: std::unique_ptr P2 = std::make_unique();
+
+  // With auto.
+  auto P3 = std::unique_ptr(new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_unique instead
+  // CHECK-FIXES: auto P3 = std::make_unique();
+
+  {
+// No std.
+using namespace std;
+unique_ptr Q = unique_ptr(new int());
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use std::make_unique instead
+// CHECK-FIXES: unique_ptr Q = std::make_unique();
+  }
+
+  std::unique_ptr R(new int());
+
+  // Create the unique_ptr as a parameter to a function.
+  int T = g(std::unique_ptr(new int()));
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_unique instead
+  // CHECK-FIXES: int T = g(std::make_unique());
+
+  // Arguments are correctly handled.
+  std::unique_ptr Pbase = std::unique_ptr(new Base(5, T));
+  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr Pbase = std::make_unique(5, T);
+
+  // Works with init lists.
+  std::unique_ptr Ppair = std::unique_ptr(new Pair{T, 1});
+  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr Ppair = std::make_unique({T, 1});
+
+  // Only replace if the type in the template is the same than the type returned
+  // by the new operator.
+  auto Pderived = std::unique_ptr(new Derived());
+
+  // The pointer is returned by the function, nothing to do.
+  std::unique_ptr RetPtr = getPointer();
+
+  // Aliases.
+  typedef std::unique_ptr IntPtr;
+  IntPtr Typedef = IntPtr(new int);
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use std::make_unique instead
+  // CHECK-FIXES: IntPtr Typedef = std::make_unique();
+
+#define PTR unique_ptr
+  std::unique_ptr Macro = std::PTR(new int);
+  // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr Macro = std::make_unique();
+#undef PTR
+
+  std::unique_ptr Using = unique_ptr_(new int);
+  // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use std::make_unique instead
+  // CHECK-FIXES: std::unique_ptr Using = std::make_unique();
+
+  // This emulates std::move.
+  std::unique_ptr Move = static_cast&&>(P1);
+
+  // Adding whitespaces.
+  auto Space = std::unique_ptr (new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use std::make_unique instead
+  // CHECK-FIXES: auto Space = std::make_unique();
+
+  auto Spaces = std  ::unique_ptr  (new int());
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use std::make_unique instead
+  // CHECK-FIXES: auto Spaces = std::make_unique();
+}
Index: clang-tidy/modernize/ModernizeTidyModule.cpp
===
--- clang-tidy/modernize/ModernizeTidyModule.cpp
+++ clang-tidy/modernize/ModernizeTidyModule.cpp
@@ -11,6 +11,7 @@
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
 #include "LoopConvertCheck.h"
+#include "MakeUniqueCheck.h"
 #include "PassByValueCheck.h"
 #include "ReplaceAutoPtrCheck.h"
 #include "ShrinkToFitCheck.h"
@@ -28,6 +29,8 @@
 public:
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
 CheckFactories.re

[PATCH] D13246: Fix bug in modernize-use-nullptr.

2015-09-29 Thread Angel Garcia via cfe-commits
angelgarcia created this revision.
angelgarcia added a reviewer: klimek.
angelgarcia added subscribers: alexfh, cfe-commits.

https://llvm.org/bugs/show_bug.cgi?id=24960

modernize-use-nullptr would hit an assertion in some cases involving macros and 
initializer lists, due to finding a node with more than one parent (the two 
forms of the initializer list).

However, this doesn't mean that the replacement is incorrect, so instead of 
just rejecting this case I tried to find a way to make it work. Looking at the 
semantic form of the InitListExpr made sense to me (looking at both forms 
results in false negatives) but I am not sure of the things that we can miss by 
skipping the syntactic form.

http://reviews.llvm.org/D13246

Files:
  clang-tidy/modernize/UseNullptrCheck.cpp
  test/clang-tidy/modernize-use-nullptr.cpp

Index: test/clang-tidy/modernize-use-nullptr.cpp
===
--- test/clang-tidy/modernize-use-nullptr.cpp
+++ test/clang-tidy/modernize-use-nullptr.cpp
@@ -174,4 +174,13 @@
 #define CALL(X) X
   OPTIONAL_CODE(NOT_NULL);
   CALL(NOT_NULL);
+
+#define ENTRY(X) {X}
+  struct A {
+int *Ptr;
+  } a[2] = {ENTRY(0), {0}};
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use nullptr
+  // CHECK-MESSAGES: :[[@LINE-2]]:24: warning: use nullptr
+  // CHECK-FIXES: a[2] = {ENTRY(nullptr), {nullptr}};
+#undef ENTRY
 }
Index: clang-tidy/modernize/UseNullptrCheck.cpp
===
--- clang-tidy/modernize/UseNullptrCheck.cpp
+++ clang-tidy/modernize/UseNullptrCheck.cpp
@@ -150,6 +150,23 @@
 return true;
   }
 
+  bool TraverseInitListExpr(InitListExpr *S) {
+// Only go through the semantic form of the InitListExpr, because
+// ImplicitCast don't appear in the syntactic form, and this results in
+// finding usages of the macro argument that don't have a ImplicitCast as 
an
+// ancestor (thus invalidating the replacement) when they actually have.
+InitListExpr *Sem = S->isSemanticForm() ? S : S->getSemanticForm();
+if (Sem) {
+  if (!WalkUpFromInitListExpr(Sem))
+return false;
+  for (Stmt *SubStmt : Sem->children()) {
+if (!TraverseStmt(SubStmt))
+  return false;
+  }
+}
+return true;
+  }
+
   bool foundInvalid() const { return InvalidFound; }
 
 private:
@@ -273,7 +290,7 @@
 // Visit children of this containing parent looking for the least-descended
 // nodes of the containing parent which are macro arg expansions that 
expand
 // from the given arg location.
-// Visitor needs: arg loc
+// Visitor needs: arg loc.
 MacroArgUsageVisitor ArgUsageVisitor(SM.getFileLoc(CastLoc), SM);
 if (const auto *D = ContainingAncestor.get())
   ArgUsageVisitor.TraverseDecl(const_cast(D));
@@ -345,8 +362,8 @@
   /// also handled.
   ///
   /// False means either:
-  /// - TestLoc is not from a macro expansion
-  /// - TestLoc is from a different macro expansion
+  /// - TestLoc is not from a macro expansion.
+  /// - TestLoc is from a different macro expansion.
   bool expandsFrom(SourceLocation TestLoc, SourceLocation TestMacroLoc) {
 if (TestLoc.isFileID()) {
   return false;
@@ -399,17 +416,24 @@
   ast_type_traits::DynTypedNode &Result) {
 // Below we're only following the first parent back up the AST. This should
 // be fine since for the statements we care about there should only be one
-// parent as far up as we care. If this assumption doesn't hold, need to
-// revisit what to do here.
+// parent, except for the case specified below.
 
 assert(MacroLoc.isFileID());
 
 while (true) {
   const auto &Parents = Context.getParents(Start);
   if (Parents.empty())
 return false;
-  assert(Parents.size() == 1 &&
- "Found an ancestor with more than one parent!");
+  if (Parents.size() > 1) {
+// If there are more than one parents, don't do the replacement unless
+// they are InitListsExpr (semantic and syntactic form). In this case 
we
+// can choose any one here, and the ASTVisitor will take care of
+// traversing the right one.
+for (const auto &Parent : Parents) {
+  if (!Parent.get())
+return false;
+}
+  }
 
   const ast_type_traits::DynTypedNode &Parent = Parents[0];
 


Index: test/clang-tidy/modernize-use-nullptr.cpp
===
--- test/clang-tidy/modernize-use-nullptr.cpp
+++ test/clang-tidy/modernize-use-nullptr.cpp
@@ -174,4 +174,13 @@
 #define CALL(X) X
   OPTIONAL_CODE(NOT_NULL);
   CALL(NOT_NULL);
+
+#define ENTRY(X) {X}
+  struct A {
+int *Ptr;
+  } a[2] = {ENTRY(0), {0}};
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use nullptr
+  // CHECK-MESSAGES: :[[@LINE-2]]:24: warning: use nullptr
+  // CHECK-FIXES: a[2] = {ENTRY(nullptr), {nullptr}};
+#undef ENTRY
 }
I

[PATCH] D13249: Divide TraverseInitListExpr to a different function for each form.

2015-09-29 Thread Angel Garcia via cfe-commits
angelgarcia created this revision.
angelgarcia added a reviewer: klimek.
angelgarcia added subscribers: alexfh, cfe-commits.

create TraverseSyntacticInitListExpr and TraverseSemanticInitListExpr.

http://reviews.llvm.org/D13249

Files:
  include/clang/AST/RecursiveASTVisitor.h

Index: include/clang/AST/RecursiveASTVisitor.h
===
--- include/clang/AST/RecursiveASTVisitor.h
+++ include/clang/AST/RecursiveASTVisitor.h
@@ -255,6 +255,13 @@
   /// \returns false if the visitation was terminated early, true otherwise.
   bool TraverseLambdaBody(LambdaExpr *LE);
 
+  /// \brief Recursively visit the syntactic and semantic forms of a
+  /// initialization list.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  bool TraverseSyntacticInitListExpr(InitListExpr *S);
+  bool TraverseSemanticInitListExpr(InitListExpr *S);
+
   //  Methods on Attrs 
 
   // \brief Visit an attribute.
@@ -2056,21 +2063,21 @@
   TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
 })
 
-// InitListExpr is a tricky one, because we want to do all our work on
-// the syntactic form of the listexpr, but this method takes the
-// semantic form by default.  We can't use the macro helper because it
-// calls WalkUp*() on the semantic form, before our code can convert
-// to the syntactic form.
 template 
-bool RecursiveASTVisitor::TraverseInitListExpr(InitListExpr *S) {
+bool RecursiveASTVisitor::TraverseSyntacticInitListExpr(InitListExpr 
*S) {
   InitListExpr *Syn = S->isSemanticForm() ? S->getSyntacticForm() : S;
   if (Syn) {
 TRY_TO(WalkUpFromInitListExpr(Syn));
 // All we need are the default actions.  FIXME: use a helper function.
 for (Stmt *SubStmt : Syn->children()) {
   TRY_TO(TraverseStmt(SubStmt));
 }
   }
+  return true;
+}
+
+template 
+bool RecursiveASTVisitor::TraverseSemanticInitListExpr(InitListExpr 
*S) {
   InitListExpr *Sem = S->isSemanticForm() ? S : S->getSemanticForm();
   if (Sem) {
 TRY_TO(WalkUpFromInitListExpr(Sem));
@@ -2081,6 +2088,18 @@
   return true;
 }
 
+// InitListExpr is a tricky one, because we want to do all our work on
+// the syntactic form of the listexpr, but this method takes the
+// semantic form by default.  We can't use the macro helper because it
+// calls WalkUp*() on the semantic form, before our code can convert
+// to the syntactic form.
+template 
+bool RecursiveASTVisitor::TraverseInitListExpr(InitListExpr *S) {
+  TRY_TO(TraverseSyntacticInitListExpr(S));
+  TRY_TO(TraverseSemanticInitListExpr(S));
+  return true;
+}
+
 // GenericSelectionExpr is a special case because the types and expressions
 // are interleaved.  We also need to watch out for null types (default
 // generic associations).


Index: include/clang/AST/RecursiveASTVisitor.h
===
--- include/clang/AST/RecursiveASTVisitor.h
+++ include/clang/AST/RecursiveASTVisitor.h
@@ -255,6 +255,13 @@
   /// \returns false if the visitation was terminated early, true otherwise.
   bool TraverseLambdaBody(LambdaExpr *LE);
 
+  /// \brief Recursively visit the syntactic and semantic forms of a
+  /// initialization list.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  bool TraverseSyntacticInitListExpr(InitListExpr *S);
+  bool TraverseSemanticInitListExpr(InitListExpr *S);
+
   //  Methods on Attrs 
 
   // \brief Visit an attribute.
@@ -2056,21 +2063,21 @@
   TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
 })
 
-// InitListExpr is a tricky one, because we want to do all our work on
-// the syntactic form of the listexpr, but this method takes the
-// semantic form by default.  We can't use the macro helper because it
-// calls WalkUp*() on the semantic form, before our code can convert
-// to the syntactic form.
 template 
-bool RecursiveASTVisitor::TraverseInitListExpr(InitListExpr *S) {
+bool RecursiveASTVisitor::TraverseSyntacticInitListExpr(InitListExpr *S) {
   InitListExpr *Syn = S->isSemanticForm() ? S->getSyntacticForm() : S;
   if (Syn) {
 TRY_TO(WalkUpFromInitListExpr(Syn));
 // All we need are the default actions.  FIXME: use a helper function.
 for (Stmt *SubStmt : Syn->children()) {
   TRY_TO(TraverseStmt(SubStmt));
 }
   }
+  return true;
+}
+
+template 
+bool RecursiveASTVisitor::TraverseSemanticInitListExpr(InitListExpr *S) {
   InitListExpr *Sem = S->isSemanticForm() ? S : S->getSemanticForm();
   if (Sem) {
 TRY_TO(WalkUpFromInitListExpr(Sem));
@@ -2081,6 +2088,18 @@
   return true;
 }
 
+// InitListExpr is a tricky one, because we want to do all our work on
+// the syntactic form of the listexpr, but this method takes the
+// semantic form by default.  We can't use the macro helper because it
+// calls WalkUp*() on the semantic form, before our code can convert
+// to the syntactic form.
+template 
+bool RecursiveASTVisitor::T

Re: [PATCH] D13249: Divide TraverseInitListExpr to a different function for each form.

2015-09-29 Thread Angel Garcia via cfe-commits
angelgarcia added a comment.

Yes, it breaks a few tests:

FAIL: Clang :: Analysis/operator-calls.cpp (598 of 8596)

FAIL: Clang :: Analysis/misc-ps-region-store.cpp (599 of 8596)

FAIL: Clang :: Analysis/array-struct-region.c (602 of 8596)


http://reviews.llvm.org/D13249



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


Re: [PATCH] D13249: Divide TraverseInitListExpr to a different function for each form.

2015-09-30 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 36099.
angelgarcia added a comment.

Add some comments.


http://reviews.llvm.org/D13249

Files:
  include/clang/AST/RecursiveASTVisitor.h

Index: include/clang/AST/RecursiveASTVisitor.h
===
--- include/clang/AST/RecursiveASTVisitor.h
+++ include/clang/AST/RecursiveASTVisitor.h
@@ -255,6 +255,13 @@
   /// \returns false if the visitation was terminated early, true otherwise.
   bool TraverseLambdaBody(LambdaExpr *LE);
 
+  /// \brief Recursively visit the syntactic and semantic forms of a
+  /// initialization list.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  bool TraverseSyntacticInitListExpr(InitListExpr *S);
+  bool TraverseSemanticInitListExpr(InitListExpr *S);
+
   //  Methods on Attrs 
 
   // \brief Visit an attribute.
@@ -2056,21 +2063,21 @@
   TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
 })
 
-// InitListExpr is a tricky one, because we want to do all our work on
-// the syntactic form of the listexpr, but this method takes the
-// semantic form by default.  We can't use the macro helper because it
-// calls WalkUp*() on the semantic form, before our code can convert
-// to the syntactic form.
 template 
-bool RecursiveASTVisitor::TraverseInitListExpr(InitListExpr *S) {
+bool RecursiveASTVisitor::TraverseSyntacticInitListExpr(InitListExpr 
*S) {
   InitListExpr *Syn = S->isSemanticForm() ? S->getSyntacticForm() : S;
   if (Syn) {
 TRY_TO(WalkUpFromInitListExpr(Syn));
 // All we need are the default actions.  FIXME: use a helper function.
 for (Stmt *SubStmt : Syn->children()) {
   TRY_TO(TraverseStmt(SubStmt));
 }
   }
+  return true;
+}
+
+template 
+bool RecursiveASTVisitor::TraverseSemanticInitListExpr(InitListExpr 
*S) {
   InitListExpr *Sem = S->isSemanticForm() ? S : S->getSemanticForm();
   if (Sem) {
 TRY_TO(WalkUpFromInitListExpr(Sem));
@@ -2081,6 +2088,25 @@
   return true;
 }
 
+// InitListExpr is a tricky one, because we want to do all our work on
+// the syntactic form of the listexpr, but this method takes the
+// semantic form by default.  We can't use the macro helper because it
+// calls WalkUp*() on the semantic form, before our code can convert
+// to the syntactic form.
+//
+// This method is called once for each pair of syntactic and semantic
+// InitListExpr, and it traverses the subtrees defined by the two forms. This
+// may cause some of the children to be visited twice, if they appear both in
+// the syntactic and the semantic form.
+//
+// There is no guarantee about which form \p S takes when this method is 
called.
+template 
+bool RecursiveASTVisitor::TraverseInitListExpr(InitListExpr *S) {
+  TRY_TO(TraverseSyntacticInitListExpr(S));
+  TRY_TO(TraverseSemanticInitListExpr(S));
+  return true;
+}
+
 // GenericSelectionExpr is a special case because the types and expressions
 // are interleaved.  We also need to watch out for null types (default
 // generic associations).


Index: include/clang/AST/RecursiveASTVisitor.h
===
--- include/clang/AST/RecursiveASTVisitor.h
+++ include/clang/AST/RecursiveASTVisitor.h
@@ -255,6 +255,13 @@
   /// \returns false if the visitation was terminated early, true otherwise.
   bool TraverseLambdaBody(LambdaExpr *LE);
 
+  /// \brief Recursively visit the syntactic and semantic forms of a
+  /// initialization list.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  bool TraverseSyntacticInitListExpr(InitListExpr *S);
+  bool TraverseSemanticInitListExpr(InitListExpr *S);
+
   //  Methods on Attrs 
 
   // \brief Visit an attribute.
@@ -2056,21 +2063,21 @@
   TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
 })
 
-// InitListExpr is a tricky one, because we want to do all our work on
-// the syntactic form of the listexpr, but this method takes the
-// semantic form by default.  We can't use the macro helper because it
-// calls WalkUp*() on the semantic form, before our code can convert
-// to the syntactic form.
 template 
-bool RecursiveASTVisitor::TraverseInitListExpr(InitListExpr *S) {
+bool RecursiveASTVisitor::TraverseSyntacticInitListExpr(InitListExpr *S) {
   InitListExpr *Syn = S->isSemanticForm() ? S->getSyntacticForm() : S;
   if (Syn) {
 TRY_TO(WalkUpFromInitListExpr(Syn));
 // All we need are the default actions.  FIXME: use a helper function.
 for (Stmt *SubStmt : Syn->children()) {
   TRY_TO(TraverseStmt(SubStmt));
 }
   }
+  return true;
+}
+
+template 
+bool RecursiveASTVisitor::TraverseSemanticInitListExpr(InitListExpr *S) {
   InitListExpr *Sem = S->isSemanticForm() ? S : S->getSemanticForm();
   if (Sem) {
 TRY_TO(WalkUpFromInitListExpr(Sem));
@@ -2081,6 +2088,25 @@
   return true;
 }
 
+// InitListExpr is a tricky one, because we want to do all our work on
+// the syn

Re: [PATCH] D13249: Divide TraverseInitListExpr to a different function for each form.

2015-09-30 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 36106.
angelgarcia added a comment.

Use only one function.

I find somewhat frustating that getSemanticForm() returns nullptr if the object 
is already in its semantic form (and the same for isSyntacticForm()). Something 
like QualType::getNonReferenceType(), that returns the object itself if it is 
already a non-reference type, would be more intuitive.


http://reviews.llvm.org/D13249

Files:
  include/clang/AST/RecursiveASTVisitor.h

Index: include/clang/AST/RecursiveASTVisitor.h
===
--- include/clang/AST/RecursiveASTVisitor.h
+++ include/clang/AST/RecursiveASTVisitor.h
@@ -255,6 +255,12 @@
   /// \returns false if the visitation was terminated early, true otherwise.
   bool TraverseLambdaBody(LambdaExpr *LE);
 
+  /// \brief Recursively visit the syntactic or semantic form of an
+  /// initialization list.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  bool TraverseSynOrSemInitListExpr(InitListExpr *S);
+
   //  Methods on Attrs 
 
   // \brief Visit an attribute.
@@ -2056,31 +2062,33 @@
   TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
 })
 
-// InitListExpr is a tricky one, because we want to do all our work on
-// the syntactic form of the listexpr, but this method takes the
-// semantic form by default.  We can't use the macro helper because it
-// calls WalkUp*() on the semantic form, before our code can convert
-// to the syntactic form.
 template 
-bool RecursiveASTVisitor::TraverseInitListExpr(InitListExpr *S) {
-  InitListExpr *Syn = S->isSemanticForm() ? S->getSyntacticForm() : S;
-  if (Syn) {
-TRY_TO(WalkUpFromInitListExpr(Syn));
+bool RecursiveASTVisitor::TraverseSynOrSemInitListExpr(InitListExpr 
*S) {
+  if (S) {
+TRY_TO(WalkUpFromInitListExpr(S));
 // All we need are the default actions.  FIXME: use a helper function.
-for (Stmt *SubStmt : Syn->children()) {
-  TRY_TO(TraverseStmt(SubStmt));
-}
-  }
-  InitListExpr *Sem = S->isSemanticForm() ? S : S->getSemanticForm();
-  if (Sem) {
-TRY_TO(WalkUpFromInitListExpr(Sem));
-for (Stmt *SubStmt : Sem->children()) {
+for (Stmt *SubStmt : S->children()) {
   TRY_TO(TraverseStmt(SubStmt));
 }
   }
   return true;
 }
 
+// This method is called once for each pair of syntactic and semantic
+// InitListExpr, and it traverses the subtrees defined by the two forms. This
+// may cause some of the children to be visited twice, if they appear both in
+// the syntactic and the semantic form.
+//
+// There is no guarantee about which form \p S takes when this method is 
called.
+template 
+bool RecursiveASTVisitor::TraverseInitListExpr(InitListExpr *S) {
+  TRY_TO(TraverseSynOrSemInitListExpr(
+  S->isSemanticForm() ? S->getSyntacticForm() : S));
+  TRY_TO(TraverseSynOrSemInitListExpr(
+  S->isSemanticForm() ? S : S->getSemanticForm()));
+  return true;
+}
+
 // GenericSelectionExpr is a special case because the types and expressions
 // are interleaved.  We also need to watch out for null types (default
 // generic associations).


Index: include/clang/AST/RecursiveASTVisitor.h
===
--- include/clang/AST/RecursiveASTVisitor.h
+++ include/clang/AST/RecursiveASTVisitor.h
@@ -255,6 +255,12 @@
   /// \returns false if the visitation was terminated early, true otherwise.
   bool TraverseLambdaBody(LambdaExpr *LE);
 
+  /// \brief Recursively visit the syntactic or semantic form of an
+  /// initialization list.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  bool TraverseSynOrSemInitListExpr(InitListExpr *S);
+
   //  Methods on Attrs 
 
   // \brief Visit an attribute.
@@ -2056,31 +2062,33 @@
   TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
 })
 
-// InitListExpr is a tricky one, because we want to do all our work on
-// the syntactic form of the listexpr, but this method takes the
-// semantic form by default.  We can't use the macro helper because it
-// calls WalkUp*() on the semantic form, before our code can convert
-// to the syntactic form.
 template 
-bool RecursiveASTVisitor::TraverseInitListExpr(InitListExpr *S) {
-  InitListExpr *Syn = S->isSemanticForm() ? S->getSyntacticForm() : S;
-  if (Syn) {
-TRY_TO(WalkUpFromInitListExpr(Syn));
+bool RecursiveASTVisitor::TraverseSynOrSemInitListExpr(InitListExpr *S) {
+  if (S) {
+TRY_TO(WalkUpFromInitListExpr(S));
 // All we need are the default actions.  FIXME: use a helper function.
-for (Stmt *SubStmt : Syn->children()) {
-  TRY_TO(TraverseStmt(SubStmt));
-}
-  }
-  InitListExpr *Sem = S->isSemanticForm() ? S : S->getSemanticForm();
-  if (Sem) {
-TRY_TO(WalkUpFromInitListExpr(Sem));
-for (Stmt *SubStmt : Sem->children()) {
+for (Stmt *SubStmt : S->children()) {
   TRY_TO(TraverseStmt(SubStmt));
 }
   }
   re

[PATCH] D13292: Add support for 'cbegin()' and 'cend()' on modernize-loop-convert.

2015-09-30 Thread Angel Garcia via cfe-commits
angelgarcia created this revision.
angelgarcia added a reviewer: klimek.
angelgarcia added subscribers: cfe-commits, alexfh.

This fixes https://llvm.org/bugs/show_bug.cgi?id=22196 .

Also add a non-trivially copyable type to fix some tests that were meant to be 
about using const-refs, but were changed in r248438.

http://reviews.llvm.org/D13292

Files:
  clang-tidy/modernize/LoopConvertCheck.cpp
  test/clang-tidy/Inputs/modernize-loop-convert/structures.h
  test/clang-tidy/modernize-loop-convert-basic.cpp

Index: test/clang-tidy/modernize-loop-convert-basic.cpp
===
--- test/clang-tidy/modernize-loop-convert-basic.cpp
+++ test/clang-tidy/modernize-loop-convert-basic.cpp
@@ -104,6 +104,14 @@
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto Elem : ConstArr)
   // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", Elem, Elem + Elem);
+
+  const NonTriviallyCopyable NonCopy[N]{};
+  for (int I = 0; I < N; ++I) {
+printf("2 * %d = %d\n", NonCopy[I].X, NonCopy[I].X + NonCopy[I].X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (const auto & Elem : NonCopy)
+  // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", Elem.X, Elem.X + Elem.X);
 }
 
 struct HasArr {
@@ -209,6 +217,13 @@
   // CHECK-FIXES: for (auto & P : *Ps)
   // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);
 
+  for (S::const_iterator It = Ss.cbegin(), E = Ss.cend(); It != E; ++It) {
+printf("s has value %d\n", (*It).X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto Elem : Ss)
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", Elem.X);
+
   for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
 printf("s has value %d\n", It->X);
   }
@@ -459,8 +474,8 @@
 const int N = 6;
 dependent V;
 dependent *Pv;
-const dependent Constv;
-const dependent *Pconstv;
+const dependent Constv;
+const dependent *Pconstv;
 
 transparent> Cv;
 
@@ -519,47 +534,47 @@
 void constness() {
   int Sum = 0;
   for (int I = 0, E = Constv.size(); I < E; ++I) {
-printf("Fibonacci number is %d\n", Constv[I]);
-Sum += Constv[I] + 2;
+printf("Fibonacci number is %d\n", Constv[I].X);
+Sum += Constv[I].X + 2;
   }
   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto Elem : Constv)
-  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem);
-  // CHECK-FIXES-NEXT: Sum += Elem + 2;
+  // CHECK-FIXES: for (const auto & Elem : Constv)
+  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem.X);
+  // CHECK-FIXES-NEXT: Sum += Elem.X + 2;
 
   for (int I = 0, E = Constv.size(); I < E; ++I) {
-printf("Fibonacci number is %d\n", Constv.at(I));
-Sum += Constv.at(I) + 2;
+printf("Fibonacci number is %d\n", Constv.at(I).X);
+Sum += Constv.at(I).X + 2;
   }
   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto Elem : Constv)
-  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem);
-  // CHECK-FIXES-NEXT: Sum += Elem + 2;
+  // CHECK-FIXES: for (const auto & Elem : Constv)
+  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem.X);
+  // CHECK-FIXES-NEXT: Sum += Elem.X + 2;
 
   for (int I = 0, E = Pconstv->size(); I < E; ++I) {
-printf("Fibonacci number is %d\n", Pconstv->at(I));
-Sum += Pconstv->at(I) + 2;
+printf("Fibonacci number is %d\n", Pconstv->at(I).X);
+Sum += Pconstv->at(I).X + 2;
   }
   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto Elem : *Pconstv)
-  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem);
-  // CHECK-FIXES-NEXT: Sum += Elem + 2;
+  // CHECK-FIXES: for (const auto & Elem : *Pconstv)
+  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem.X);
+  // CHECK-FIXES-NEXT: Sum += Elem.X + 2;
 
   // This test will fail if size() isn't called repeatedly, since it
   // returns unsigned int, and 0 is deduced to be signed int.
   // FIXME: Insert the necessary explicit conversion, or write out the types
   // explicitly.
   for (int I = 0; I < Pconstv->size(); ++I) {
-printf("Fibonacci number is %d\n", (*Pconstv).at(I));
-Sum += (*Pconstv)[I] + 2;
+printf("Fibonacci number is %d\n", (*Pconstv).at(I).X);
+Sum += (*Pconstv)[I].X + 2;
   }
   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto Elem : *Pconstv)
-  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem);
-  // CHECK-FIXES-NEXT: Sum += Elem + 2;
+  // CHECK-FIXES: for (const auto & Elem : *Pconstv)
+  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem.X);
+  // CHECK-FIXES-NEXT: Sum += Elem.X + 2;
 }
 
-void ConstRef(const dependent& ConstVRef) {
+void constRef(const dependent& ConstVRef) {
   int sum = 0;
   // F

Re: [PATCH] D13292: Add support for 'cbegin()' and 'cend()' on modernize-loop-convert.

2015-10-01 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 36198.
angelgarcia added a comment.

Yes, right now it is pretty hard to figure out what some of the tests are for, 
they are a bit messy. I plan to do something about it, but for now I added a 
comment on that test.


http://reviews.llvm.org/D13292

Files:
  clang-tidy/modernize/LoopConvertCheck.cpp
  test/clang-tidy/Inputs/modernize-loop-convert/structures.h
  test/clang-tidy/modernize-loop-convert-basic.cpp

Index: test/clang-tidy/modernize-loop-convert-basic.cpp
===
--- test/clang-tidy/modernize-loop-convert-basic.cpp
+++ test/clang-tidy/modernize-loop-convert-basic.cpp
@@ -104,6 +104,14 @@
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto Elem : ConstArr)
   // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", Elem, Elem + Elem);
+
+  const NonTriviallyCopyable NonCopy[N]{};
+  for (int I = 0; I < N; ++I) {
+printf("2 * %d = %d\n", NonCopy[I].X, NonCopy[I].X + NonCopy[I].X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (const auto & Elem : NonCopy)
+  // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", Elem.X, Elem.X + Elem.X);
 }
 
 struct HasArr {
@@ -209,6 +217,13 @@
   // CHECK-FIXES: for (auto & P : *Ps)
   // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);
 
+  for (S::const_iterator It = Ss.cbegin(), E = Ss.cend(); It != E; ++It) {
+printf("s has value %d\n", (*It).X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto Elem : Ss)
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", Elem.X);
+
   for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
 printf("s has value %d\n", It->X);
   }
@@ -459,8 +474,8 @@
 const int N = 6;
 dependent V;
 dependent *Pv;
-const dependent Constv;
-const dependent *Pconstv;
+const dependent Constv;
+const dependent *Pconstv;
 
 transparent> Cv;
 
@@ -516,50 +531,51 @@
   // CHECK-FIXES-NEXT: Sum += Elem + 2;
 }
 
+// Ensure that 'const auto &' is used with containers of non-trivial types.
 void constness() {
   int Sum = 0;
   for (int I = 0, E = Constv.size(); I < E; ++I) {
-printf("Fibonacci number is %d\n", Constv[I]);
-Sum += Constv[I] + 2;
+printf("Fibonacci number is %d\n", Constv[I].X);
+Sum += Constv[I].X + 2;
   }
   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto Elem : Constv)
-  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem);
-  // CHECK-FIXES-NEXT: Sum += Elem + 2;
+  // CHECK-FIXES: for (const auto & Elem : Constv)
+  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem.X);
+  // CHECK-FIXES-NEXT: Sum += Elem.X + 2;
 
   for (int I = 0, E = Constv.size(); I < E; ++I) {
-printf("Fibonacci number is %d\n", Constv.at(I));
-Sum += Constv.at(I) + 2;
+printf("Fibonacci number is %d\n", Constv.at(I).X);
+Sum += Constv.at(I).X + 2;
   }
   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto Elem : Constv)
-  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem);
-  // CHECK-FIXES-NEXT: Sum += Elem + 2;
+  // CHECK-FIXES: for (const auto & Elem : Constv)
+  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem.X);
+  // CHECK-FIXES-NEXT: Sum += Elem.X + 2;
 
   for (int I = 0, E = Pconstv->size(); I < E; ++I) {
-printf("Fibonacci number is %d\n", Pconstv->at(I));
-Sum += Pconstv->at(I) + 2;
+printf("Fibonacci number is %d\n", Pconstv->at(I).X);
+Sum += Pconstv->at(I).X + 2;
   }
   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto Elem : *Pconstv)
-  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem);
-  // CHECK-FIXES-NEXT: Sum += Elem + 2;
+  // CHECK-FIXES: for (const auto & Elem : *Pconstv)
+  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem.X);
+  // CHECK-FIXES-NEXT: Sum += Elem.X + 2;
 
   // This test will fail if size() isn't called repeatedly, since it
   // returns unsigned int, and 0 is deduced to be signed int.
   // FIXME: Insert the necessary explicit conversion, or write out the types
   // explicitly.
   for (int I = 0; I < Pconstv->size(); ++I) {
-printf("Fibonacci number is %d\n", (*Pconstv).at(I));
-Sum += (*Pconstv)[I] + 2;
+printf("Fibonacci number is %d\n", (*Pconstv).at(I).X);
+Sum += (*Pconstv)[I].X + 2;
   }
   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto Elem : *Pconstv)
-  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem);
-  // CHECK-FIXES-NEXT: Sum += Elem + 2;
+  // CHECK-FIXES: for (const auto & Elem : *Pconstv)
+  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem.X);
+  // CHECK-FIXES-NEXT: Sum += Elem.X + 2;
 }
 
-void ConstRef(const dependent& ConstVRef) {
+v

Re: [PATCH] D13292: Add support for 'cbegin()' and 'cend()' on modernize-loop-convert.

2015-10-01 Thread Angel Garcia via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL248994: Add support for 'cbegin()' and 'cend()' on 
modernize-loop-convert. (authored by angelgarcia).

Changed prior to commit:
  http://reviews.llvm.org/D13292?vs=36198&id=36200#toc

Repository:
  rL LLVM

http://reviews.llvm.org/D13292

Files:
  clang-tools-extra/trunk/clang-tidy/modernize/LoopConvertCheck.cpp
  
clang-tools-extra/trunk/test/clang-tidy/Inputs/modernize-loop-convert/structures.h
  clang-tools-extra/trunk/test/clang-tidy/modernize-loop-convert-basic.cpp

Index: clang-tools-extra/trunk/test/clang-tidy/modernize-loop-convert-basic.cpp
===
--- clang-tools-extra/trunk/test/clang-tidy/modernize-loop-convert-basic.cpp
+++ clang-tools-extra/trunk/test/clang-tidy/modernize-loop-convert-basic.cpp
@@ -104,6 +104,14 @@
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto Elem : ConstArr)
   // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", Elem, Elem + Elem);
+
+  const NonTriviallyCopyable NonCopy[N]{};
+  for (int I = 0; I < N; ++I) {
+printf("2 * %d = %d\n", NonCopy[I].X, NonCopy[I].X + NonCopy[I].X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (const auto & Elem : NonCopy)
+  // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", Elem.X, Elem.X + Elem.X);
 }
 
 struct HasArr {
@@ -209,6 +217,13 @@
   // CHECK-FIXES: for (auto & P : *Ps)
   // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);
 
+  for (S::const_iterator It = Ss.cbegin(), E = Ss.cend(); It != E; ++It) {
+printf("s has value %d\n", (*It).X);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto Elem : Ss)
+  // CHECK-FIXES-NEXT: printf("s has value %d\n", Elem.X);
+
   for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
 printf("s has value %d\n", It->X);
   }
@@ -459,8 +474,8 @@
 const int N = 6;
 dependent V;
 dependent *Pv;
-const dependent Constv;
-const dependent *Pconstv;
+const dependent Constv;
+const dependent *Pconstv;
 
 transparent> Cv;
 
@@ -516,50 +531,51 @@
   // CHECK-FIXES-NEXT: Sum += Elem + 2;
 }
 
+// Ensure that 'const auto &' is used with containers of non-trivial types.
 void constness() {
   int Sum = 0;
   for (int I = 0, E = Constv.size(); I < E; ++I) {
-printf("Fibonacci number is %d\n", Constv[I]);
-Sum += Constv[I] + 2;
+printf("Fibonacci number is %d\n", Constv[I].X);
+Sum += Constv[I].X + 2;
   }
   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto Elem : Constv)
-  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem);
-  // CHECK-FIXES-NEXT: Sum += Elem + 2;
+  // CHECK-FIXES: for (const auto & Elem : Constv)
+  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem.X);
+  // CHECK-FIXES-NEXT: Sum += Elem.X + 2;
 
   for (int I = 0, E = Constv.size(); I < E; ++I) {
-printf("Fibonacci number is %d\n", Constv.at(I));
-Sum += Constv.at(I) + 2;
+printf("Fibonacci number is %d\n", Constv.at(I).X);
+Sum += Constv.at(I).X + 2;
   }
   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto Elem : Constv)
-  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem);
-  // CHECK-FIXES-NEXT: Sum += Elem + 2;
+  // CHECK-FIXES: for (const auto & Elem : Constv)
+  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem.X);
+  // CHECK-FIXES-NEXT: Sum += Elem.X + 2;
 
   for (int I = 0, E = Pconstv->size(); I < E; ++I) {
-printf("Fibonacci number is %d\n", Pconstv->at(I));
-Sum += Pconstv->at(I) + 2;
+printf("Fibonacci number is %d\n", Pconstv->at(I).X);
+Sum += Pconstv->at(I).X + 2;
   }
   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto Elem : *Pconstv)
-  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem);
-  // CHECK-FIXES-NEXT: Sum += Elem + 2;
+  // CHECK-FIXES: for (const auto & Elem : *Pconstv)
+  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem.X);
+  // CHECK-FIXES-NEXT: Sum += Elem.X + 2;
 
   // This test will fail if size() isn't called repeatedly, since it
   // returns unsigned int, and 0 is deduced to be signed int.
   // FIXME: Insert the necessary explicit conversion, or write out the types
   // explicitly.
   for (int I = 0; I < Pconstv->size(); ++I) {
-printf("Fibonacci number is %d\n", (*Pconstv).at(I));
-Sum += (*Pconstv)[I] + 2;
+printf("Fibonacci number is %d\n", (*Pconstv).at(I).X);
+Sum += (*Pconstv)[I].X + 2;
   }
   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto Elem : *Pconstv)
-  // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem);
-  // CHECK-FIXES-NEXT: Sum += Elem + 2;
+  // CHECK-FIXES: for (const au

[PATCH] D13342: Prevent loop-convert from leaving empty lines after removing an alias declaration.

2015-10-01 Thread Angel Garcia via cfe-commits
angelgarcia created this revision.
angelgarcia added a reviewer: klimek.
angelgarcia added subscribers: alexfh, cfe-commits.

This fixes https://llvm.org/bugs/show_bug.cgi?id=17716.

http://reviews.llvm.org/D13342

Files:
  clang-tidy/modernize/LoopConvertCheck.cpp
  clang-tidy/modernize/LoopConvertCheck.h
  test/clang-tidy/modernize-loop-convert-extra.cpp

Index: test/clang-tidy/modernize-loop-convert-extra.cpp
===
--- test/clang-tidy/modernize-loop-convert-extra.cpp
+++ test/clang-tidy/modernize-loop-convert-extra.cpp
@@ -53,7 +53,7 @@
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & T : Arr)
   // CHECK-FIXES-NOT: Val &{{[a-z_]+}} =
-  // CHECK-FIXES: {}
+  // CHECK-FIXES-NEXT: {}
   // CHECK-FIXES-NEXT: int Y = T.X;
 
   // The container was not only used to initialize a temporary loop variable for
@@ -89,7 +89,7 @@
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & T : V)
-  // CHECK-FIXES: {}
+  // CHECK-FIXES-NEXT: {}
   // CHECK-FIXES-NEXT: int Y = T.X;
 
   // The same with a call to at()
@@ -100,7 +100,7 @@
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & T : *Pv)
-  // CHECK-FIXES: {}
+  // CHECK-FIXES-NEXT: {}
   // CHECK-FIXES-NEXT: int Y = T.X;
 
   for (int I = 0; I < N; ++I) {
@@ -166,8 +166,17 @@
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & Elem : IntArr)
   // CHECK-FIXES-NEXT: IntRef Int(Elem);
-}
 
+  // Ensure that removing the alias doesn't leave empty lines behind.
+  for (int I = 0; I < N; ++I) {
+auto &X = IntArr[I];
+X = 0;
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & X : IntArr) {
+  // CHECK-FIXES-NEXT: {{^X = 0;$}}
+  // CHECK-FIXES-NEXT: {{^  }$}}
+}
 
 void refs_and_vals() {
   // The following tests check that the transform correctly preserves the
@@ -186,7 +195,7 @@
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto Alias : S_const)
   // CHECK-FIXES-NOT: MutableVal {{[a-z_]+}} =
-  // CHECK-FIXES: {}
+  // CHECK-FIXES-NEXT: {}
   // CHECK-FIXES-NEXT: Alias.X = 0;
 
   for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
@@ -197,7 +206,7 @@
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto Alias : Ss)
   // CHECK-FIXES-NOT: MutableVal {{[a-z_]+}} =
-  // CHECK-FIXES: {}
+  // CHECK-FIXES-NEXT: {}
   // CHECK-FIXES-NEXT: Alias.X = 0;
 
   for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
@@ -208,7 +217,7 @@
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & Alias : Ss)
   // CHECK-FIXES-NOT: MutableVal &{{[a-z_]+}} =
-  // CHECK-FIXES: {}
+  // CHECK-FIXES-NEXT: {}
   // CHECK-FIXES-NEXT: Alias.X = 0;
 
   dependent Dep, Other;
@@ -863,7 +872,7 @@
   // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto R5 : Arr)
   // CHECK-FIXES-NEXT: auto G5 = [&]()
-  // CHECK-FIXES: int J5 = 8 + R5;
+  // CHECK-FIXES-NEXT: int J5 = 8 + R5;
 
   // Alias by reference.
   for (int I = 0; I < N; ++I) {
@@ -875,7 +884,7 @@
   // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & R6 : Arr)
   // CHECK-FIXES-NEXT: auto G6 = [&]()
-  // CHECK-FIXES: int J6 = -1 + R6;
+  // CHECK-FIXES-NEXT: int J6 = -1 + R6;
 }
 
 void iterators() {
@@ -953,7 +962,8 @@
 E Ee{ { { g( { Array[I] } ) } } };
   }
   // CHECK-MESSAGES: :[[@LINE-7]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: int A{ Elem };
+  // CHECK-FIXES: for (auto & Elem : Array)
+  // CHECK-FIXES-NEXT: int A{ Elem };
   // CHECK-FIXES-NEXT: int B{ g(Elem) };
   // CHECK-FIXES-NEXT: int C{ g( { Elem } ) };
   // CHECK-FIXES-NEXT: D Dd{ { g( { Elem } ) } };
Index: clang-tidy/modernize/LoopConvertCheck.h
===
--- clang-tidy/modernize/LoopConvertCheck.h
+++ clang-tidy/modernize/LoopConvertCheck.h
@@ -34,6 +34,8 @@
 std::string ContainerString;
   };
 
+  void getAliasRange(SourceManager &SM, SourceRange &DeclRange);
+
   void doConversion(ASTContext *Context, const VarDecl *IndexVar,
 const VarDecl *MaybeContainer, const UsageResult &Usages,
 const DeclStmt *AliasDecl, bool AliasUseRequired,
Index: clang-tidy/modernize/LoopConvertCheck.cpp
===
--- clang-tidy/modernize/LoopConvertCheck.cpp
+++ clang-tidy/modernize/LoopConvertCheck.cpp
@@ -442,6 +442,30 @@
   Finder->addMatcher(makePseudoArrayLoopMatcher(), this);
 }
 
+/// \brief Given the range of a sin

Re: [PATCH] D13342: Prevent loop-convert from leaving empty lines after removing an alias declaration.

2015-10-01 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 36234.
angelgarcia added a comment.

Change a comment.


http://reviews.llvm.org/D13342

Files:
  clang-tidy/modernize/LoopConvertCheck.cpp
  clang-tidy/modernize/LoopConvertCheck.h
  test/clang-tidy/modernize-loop-convert-extra.cpp

Index: test/clang-tidy/modernize-loop-convert-extra.cpp
===
--- test/clang-tidy/modernize-loop-convert-extra.cpp
+++ test/clang-tidy/modernize-loop-convert-extra.cpp
@@ -53,7 +53,7 @@
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & T : Arr)
   // CHECK-FIXES-NOT: Val &{{[a-z_]+}} =
-  // CHECK-FIXES: {}
+  // CHECK-FIXES-NEXT: {}
   // CHECK-FIXES-NEXT: int Y = T.X;
 
   // The container was not only used to initialize a temporary loop variable for
@@ -89,7 +89,7 @@
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & T : V)
-  // CHECK-FIXES: {}
+  // CHECK-FIXES-NEXT: {}
   // CHECK-FIXES-NEXT: int Y = T.X;
 
   // The same with a call to at()
@@ -100,7 +100,7 @@
   }
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & T : *Pv)
-  // CHECK-FIXES: {}
+  // CHECK-FIXES-NEXT: {}
   // CHECK-FIXES-NEXT: int Y = T.X;
 
   for (int I = 0; I < N; ++I) {
@@ -166,8 +166,17 @@
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & Elem : IntArr)
   // CHECK-FIXES-NEXT: IntRef Int(Elem);
-}
 
+  // Ensure that removing the alias doesn't leave empty lines behind.
+  for (int I = 0; I < N; ++I) {
+auto &X = IntArr[I];
+X = 0;
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & X : IntArr) {
+  // CHECK-FIXES-NEXT: {{^X = 0;$}}
+  // CHECK-FIXES-NEXT: {{^  }$}}
+}
 
 void refs_and_vals() {
   // The following tests check that the transform correctly preserves the
@@ -186,7 +195,7 @@
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto Alias : S_const)
   // CHECK-FIXES-NOT: MutableVal {{[a-z_]+}} =
-  // CHECK-FIXES: {}
+  // CHECK-FIXES-NEXT: {}
   // CHECK-FIXES-NEXT: Alias.X = 0;
 
   for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
@@ -197,7 +206,7 @@
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto Alias : Ss)
   // CHECK-FIXES-NOT: MutableVal {{[a-z_]+}} =
-  // CHECK-FIXES: {}
+  // CHECK-FIXES-NEXT: {}
   // CHECK-FIXES-NEXT: Alias.X = 0;
 
   for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
@@ -208,7 +217,7 @@
   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & Alias : Ss)
   // CHECK-FIXES-NOT: MutableVal &{{[a-z_]+}} =
-  // CHECK-FIXES: {}
+  // CHECK-FIXES-NEXT: {}
   // CHECK-FIXES-NEXT: Alias.X = 0;
 
   dependent Dep, Other;
@@ -863,7 +872,7 @@
   // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto R5 : Arr)
   // CHECK-FIXES-NEXT: auto G5 = [&]()
-  // CHECK-FIXES: int J5 = 8 + R5;
+  // CHECK-FIXES-NEXT: int J5 = 8 + R5;
 
   // Alias by reference.
   for (int I = 0; I < N; ++I) {
@@ -875,7 +884,7 @@
   // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & R6 : Arr)
   // CHECK-FIXES-NEXT: auto G6 = [&]()
-  // CHECK-FIXES: int J6 = -1 + R6;
+  // CHECK-FIXES-NEXT: int J6 = -1 + R6;
 }
 
 void iterators() {
@@ -953,7 +962,8 @@
 E Ee{ { { g( { Array[I] } ) } } };
   }
   // CHECK-MESSAGES: :[[@LINE-7]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: int A{ Elem };
+  // CHECK-FIXES: for (auto & Elem : Array)
+  // CHECK-FIXES-NEXT: int A{ Elem };
   // CHECK-FIXES-NEXT: int B{ g(Elem) };
   // CHECK-FIXES-NEXT: int C{ g( { Elem } ) };
   // CHECK-FIXES-NEXT: D Dd{ { g( { Elem } ) } };
Index: clang-tidy/modernize/LoopConvertCheck.h
===
--- clang-tidy/modernize/LoopConvertCheck.h
+++ clang-tidy/modernize/LoopConvertCheck.h
@@ -34,6 +34,8 @@
 std::string ContainerString;
   };
 
+  void getAliasRange(SourceManager &SM, SourceRange &DeclRange);
+
   void doConversion(ASTContext *Context, const VarDecl *IndexVar,
 const VarDecl *MaybeContainer, const UsageResult &Usages,
 const DeclStmt *AliasDecl, bool AliasUseRequired,
Index: clang-tidy/modernize/LoopConvertCheck.cpp
===
--- clang-tidy/modernize/LoopConvertCheck.cpp
+++ clang-tidy/modernize/LoopConvertCheck.cpp
@@ -442,6 +442,30 @@
   Finder->addMatcher(makePseudoArrayLoopMatcher(), this);
 }
 
+/// \brief Given the range of a single declaration, such as:
+/// \code
+///   unsigned &ThisIsADeclarationThatCanSpanS

[PATCH] D13346: Update clang-tidy documentation.

2015-10-01 Thread Angel Garcia via cfe-commits
angelgarcia created this revision.
angelgarcia added a reviewer: klimek.
angelgarcia added subscribers: alexfh, cfe-commits.

Improve modernize-use-auto documentation 
(https://llvm.org/bugs/show_bug.cgi?id=24962).
Add documentation for modernize-make-unique.

http://reviews.llvm.org/D13346

Files:
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/modernize-make-unique.rst
  docs/clang-tidy/checks/modernize-use-auto.rst

Index: docs/clang-tidy/checks/modernize-use-auto.rst
===
--- docs/clang-tidy/checks/modernize-use-auto.rst
+++ docs/clang-tidy/checks/modernize-use-auto.rst
@@ -108,6 +108,39 @@
   list. Otherwise, use of ``auto`` would cause the type of the variable to be
   deduced as``std::initializer_list``.
 
+New expressions
+---
+
+Frequently, when a pointer is declared and initialized with ``new``, the
+pointee type has to be written twice: in the declaration type and in the
+``new`` expression. In this cases, the declaration type can be replaced with
+``auto`` improving readability and maintainability.
+
+.. code-block:: c++
+
+  TypeName *my_pointer = new TypeName(my_param);
+
+  // becomes
+
+  auto my_pointer = new TypeName(my_param);
+
+The check will also replace the declaration type in multiple declarations, if
+the following conditions are satisfied:
+
+* All declared variables have the same type (i.e. all of them are pointers to
+  the same type).
+* All declared variables are initialized with a ``new`` expression.
+* The types of all the new expressions are the same than the pointee of the
+  declaration type.
+
+.. code-block:: c++
+
+  TypeName *my_first_pointer = new TypeName, *my_second_pointer = new TypeName;
+
+  // becomes
+
+  auto my_first_pointer = new TypeName, my_second_pointer = new TypeName;
+
 Known Limitations
 -
 * If the initializer is an explicit conversion constructor, the check will not
Index: docs/clang-tidy/checks/modernize-make-unique.rst
===
--- /dev/null
+++ docs/clang-tidy/checks/modernize-make-unique.rst
@@ -0,0 +1,15 @@
+modernize-make-unique
+=
+
+This check finds the creation of ``std::unique_ptr`` objects by explicitly
+calling the constructor and a ``new`` expression, and replaces it with a call
+to ``std::make_unique``, introduced in C++14.
+
+.. code-block:: c++
+
+  auto my_ptr = std::unique_ptr(new MyPair(1, 2));
+
+  // becomes
+
+  auto my_ptr = std::make_unique(1, 2);
+
Index: docs/clang-tidy/checks/list.rst
===
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -42,6 +42,7 @@
misc-unused-parameters
misc-unused-raii
modernize-loop-convert
+   modernize-make-unique
modernize-pass-by-value
modernize-replace-auto-ptr
modernize-shrink-to-fit


Index: docs/clang-tidy/checks/modernize-use-auto.rst
===
--- docs/clang-tidy/checks/modernize-use-auto.rst
+++ docs/clang-tidy/checks/modernize-use-auto.rst
@@ -108,6 +108,39 @@
   list. Otherwise, use of ``auto`` would cause the type of the variable to be
   deduced as``std::initializer_list``.
 
+New expressions
+---
+
+Frequently, when a pointer is declared and initialized with ``new``, the
+pointee type has to be written twice: in the declaration type and in the
+``new`` expression. In this cases, the declaration type can be replaced with
+``auto`` improving readability and maintainability.
+
+.. code-block:: c++
+
+  TypeName *my_pointer = new TypeName(my_param);
+
+  // becomes
+
+  auto my_pointer = new TypeName(my_param);
+
+The check will also replace the declaration type in multiple declarations, if
+the following conditions are satisfied:
+
+* All declared variables have the same type (i.e. all of them are pointers to
+  the same type).
+* All declared variables are initialized with a ``new`` expression.
+* The types of all the new expressions are the same than the pointee of the
+  declaration type.
+
+.. code-block:: c++
+
+  TypeName *my_first_pointer = new TypeName, *my_second_pointer = new TypeName;
+
+  // becomes
+
+  auto my_first_pointer = new TypeName, my_second_pointer = new TypeName;
+
 Known Limitations
 -
 * If the initializer is an explicit conversion constructor, the check will not
Index: docs/clang-tidy/checks/modernize-make-unique.rst
===
--- /dev/null
+++ docs/clang-tidy/checks/modernize-make-unique.rst
@@ -0,0 +1,15 @@
+modernize-make-unique
+=
+
+This check finds the creation of ``std::unique_ptr`` objects by explicitly
+calling the constructor and a ``new`` expression, and replaces it with a call
+to ``std::make_unique``, introduced in C++14.
+
+.. code-block:: c++
+
+  auto my_ptr = std::unique_ptr(new MyPair(1, 2));

[PATCH] D13381: Handle trailing underscores on modernize-loop-convert variable namer.

2015-10-02 Thread Angel Garcia via cfe-commits
angelgarcia created this revision.
angelgarcia added a reviewer: klimek.
angelgarcia added subscribers: alexfh, cfe-commits.

https://llvm.org/bugs/show_bug.cgi?id=24961.

http://reviews.llvm.org/D13381

Files:
  clang-tidy/modernize/LoopConvertUtils.cpp
  test/clang-tidy/modernize-loop-convert-lowercase.cpp
  test/clang-tidy/modernize-loop-convert-uppercase.cpp

Index: test/clang-tidy/modernize-loop-convert-uppercase.cpp
===
--- test/clang-tidy/modernize-loop-convert-uppercase.cpp
+++ test/clang-tidy/modernize-loop-convert-uppercase.cpp
@@ -7,6 +7,7 @@
 const int N = 10;
 int ARR[N];
 int NUMS[N];
+int NUMS_[N];
 
 void naming() {
   for (int I = 0; I < N; ++I) {
@@ -23,6 +24,13 @@
   // CHECK-FIXES: for (auto & NUM : NUMS)
   // CHECK-FIXES-NEXT: printf("%d\n", NUM);
 
+  for (int I = 0; I < N; ++I) {
+printf("%d\n", NUMS_[I]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & NUM : NUMS_)
+  // CHECK-FIXES-NEXT: printf("%d\n", NUM);
+
   int NUM = 0;
   for (int I = 0; I < N; ++I) {
 printf("%d\n", NUMS[I] + NUM);
Index: test/clang-tidy/modernize-loop-convert-lowercase.cpp
===
--- test/clang-tidy/modernize-loop-convert-lowercase.cpp
+++ test/clang-tidy/modernize-loop-convert-lowercase.cpp
@@ -7,6 +7,7 @@
 const int n = 10;
 int arr[n];
 int nums[n];
+int nums_[n];
 
 void naming() {
   for (int i = 0; i < n; ++i) {
@@ -23,6 +24,13 @@
   // CHECK-FIXES: for (auto & num : nums)
   // CHECK-FIXES-NEXT: printf("%d\n", num);
 
+  for (int i = 0; i < n; ++i) {
+printf("%d\n", nums_[i]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & num : nums_)
+  // CHECK-FIXES-NEXT: printf("%d\n", num);
+
   int num = 0;
   for (int i = 0; i < n; ++i) {
 printf("%d\n", nums[i] + num);
Index: clang-tidy/modernize/LoopConvertUtils.cpp
===
--- clang-tidy/modernize/LoopConvertUtils.cpp
+++ clang-tidy/modernize/LoopConvertUtils.cpp
@@ -819,6 +819,14 @@
   size_t Len = ContainerName.size();
   if (Len > 1 && ContainerName.endswith(Style == NS_UpperCase ? "S" : "s")) {
 IteratorName = ContainerName.substr(0, Len - 1);
+// Ej: (auto thing : things)
+if (!declarationExists(IteratorName))
+  return IteratorName;
+  }
+
+  if (Len > 2 && ContainerName.endswith(Style == NS_UpperCase ? "S_" : "s_")) {
+IteratorName = ContainerName.substr(0, Len - 2);
+// Ej: (auto thing : things_)
 if (!declarationExists(IteratorName))
   return IteratorName;
   }
@@ -835,14 +843,17 @@
   case NS_UpperCase:
 Elem = "ELEM";
   }
+  // Ej: (auto elem : container)
   if (!declarationExists(Elem))
 return Elem;
 
   IteratorName = AppendWithStyle(ContainerName, OldIndex->getName());
+  // Ej: (auto container_i : container)
   if (!declarationExists(IteratorName))
 return IteratorName;
 
   IteratorName = AppendWithStyle(ContainerName, Elem);
+  // Ej: (auto container_elem : container)
   if (!declarationExists(IteratorName))
 return IteratorName;
 


Index: test/clang-tidy/modernize-loop-convert-uppercase.cpp
===
--- test/clang-tidy/modernize-loop-convert-uppercase.cpp
+++ test/clang-tidy/modernize-loop-convert-uppercase.cpp
@@ -7,6 +7,7 @@
 const int N = 10;
 int ARR[N];
 int NUMS[N];
+int NUMS_[N];
 
 void naming() {
   for (int I = 0; I < N; ++I) {
@@ -23,6 +24,13 @@
   // CHECK-FIXES: for (auto & NUM : NUMS)
   // CHECK-FIXES-NEXT: printf("%d\n", NUM);
 
+  for (int I = 0; I < N; ++I) {
+printf("%d\n", NUMS_[I]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & NUM : NUMS_)
+  // CHECK-FIXES-NEXT: printf("%d\n", NUM);
+
   int NUM = 0;
   for (int I = 0; I < N; ++I) {
 printf("%d\n", NUMS[I] + NUM);
Index: test/clang-tidy/modernize-loop-convert-lowercase.cpp
===
--- test/clang-tidy/modernize-loop-convert-lowercase.cpp
+++ test/clang-tidy/modernize-loop-convert-lowercase.cpp
@@ -7,6 +7,7 @@
 const int n = 10;
 int arr[n];
 int nums[n];
+int nums_[n];
 
 void naming() {
   for (int i = 0; i < n; ++i) {
@@ -23,6 +24,13 @@
   // CHECK-FIXES: for (auto & num : nums)
   // CHECK-FIXES-NEXT: printf("%d\n", num);
 
+  for (int i = 0; i < n; ++i) {
+printf("%d\n", nums_[i]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & num : nums_)
+  // CHECK-FIXES-NEXT: printf("%d\n", num);
+
   int num = 0;
   for (int i = 0; i < n; ++i) {
 printf("%d\n", nums[i] + num);
Index: clang-tidy/modernize/LoopConvertUtils.cpp
===
--- clang-tidy/modernize/Loop

Re: [PATCH] D13381: Handle trailing underscores on modernize-loop-convert variable namer.

2015-10-02 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 36358.
angelgarcia added a comment.

I forgot one.


http://reviews.llvm.org/D13381

Files:
  clang-tidy/modernize/LoopConvertUtils.cpp
  test/clang-tidy/modernize-loop-convert-lowercase.cpp
  test/clang-tidy/modernize-loop-convert-uppercase.cpp

Index: test/clang-tidy/modernize-loop-convert-uppercase.cpp
===
--- test/clang-tidy/modernize-loop-convert-uppercase.cpp
+++ test/clang-tidy/modernize-loop-convert-uppercase.cpp
@@ -7,6 +7,7 @@
 const int N = 10;
 int ARR[N];
 int NUMS[N];
+int NUMS_[N];
 
 void naming() {
   for (int I = 0; I < N; ++I) {
@@ -23,6 +24,13 @@
   // CHECK-FIXES: for (auto & NUM : NUMS)
   // CHECK-FIXES-NEXT: printf("%d\n", NUM);
 
+  for (int I = 0; I < N; ++I) {
+printf("%d\n", NUMS_[I]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & NUM : NUMS_)
+  // CHECK-FIXES-NEXT: printf("%d\n", NUM);
+
   int NUM = 0;
   for (int I = 0; I < N; ++I) {
 printf("%d\n", NUMS[I] + NUM);
Index: test/clang-tidy/modernize-loop-convert-lowercase.cpp
===
--- test/clang-tidy/modernize-loop-convert-lowercase.cpp
+++ test/clang-tidy/modernize-loop-convert-lowercase.cpp
@@ -7,6 +7,7 @@
 const int n = 10;
 int arr[n];
 int nums[n];
+int nums_[n];
 
 void naming() {
   for (int i = 0; i < n; ++i) {
@@ -23,6 +24,13 @@
   // CHECK-FIXES: for (auto & num : nums)
   // CHECK-FIXES-NEXT: printf("%d\n", num);
 
+  for (int i = 0; i < n; ++i) {
+printf("%d\n", nums_[i]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & num : nums_)
+  // CHECK-FIXES-NEXT: printf("%d\n", num);
+
   int num = 0;
   for (int i = 0; i < n; ++i) {
 printf("%d\n", nums[i] + num);
Index: clang-tidy/modernize/LoopConvertUtils.cpp
===
--- clang-tidy/modernize/LoopConvertUtils.cpp
+++ clang-tidy/modernize/LoopConvertUtils.cpp
@@ -819,6 +819,14 @@
   size_t Len = ContainerName.size();
   if (Len > 1 && ContainerName.endswith(Style == NS_UpperCase ? "S" : "s")) {
 IteratorName = ContainerName.substr(0, Len - 1);
+// E.g.: (auto thing : things)
+if (!declarationExists(IteratorName))
+  return IteratorName;
+  }
+
+  if (Len > 2 && ContainerName.endswith(Style == NS_UpperCase ? "S_" : "s_")) {
+IteratorName = ContainerName.substr(0, Len - 2);
+// E.g.: (auto thing : things_)
 if (!declarationExists(IteratorName))
   return IteratorName;
   }
@@ -835,14 +843,17 @@
   case NS_UpperCase:
 Elem = "ELEM";
   }
+  // E.g.: (auto elem : container)
   if (!declarationExists(Elem))
 return Elem;
 
   IteratorName = AppendWithStyle(ContainerName, OldIndex->getName());
+  // E.g.: (auto container_i : container)
   if (!declarationExists(IteratorName))
 return IteratorName;
 
   IteratorName = AppendWithStyle(ContainerName, Elem);
+  // E.g.: (auto container_elem : container)
   if (!declarationExists(IteratorName))
 return IteratorName;
 


Index: test/clang-tidy/modernize-loop-convert-uppercase.cpp
===
--- test/clang-tidy/modernize-loop-convert-uppercase.cpp
+++ test/clang-tidy/modernize-loop-convert-uppercase.cpp
@@ -7,6 +7,7 @@
 const int N = 10;
 int ARR[N];
 int NUMS[N];
+int NUMS_[N];
 
 void naming() {
   for (int I = 0; I < N; ++I) {
@@ -23,6 +24,13 @@
   // CHECK-FIXES: for (auto & NUM : NUMS)
   // CHECK-FIXES-NEXT: printf("%d\n", NUM);
 
+  for (int I = 0; I < N; ++I) {
+printf("%d\n", NUMS_[I]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & NUM : NUMS_)
+  // CHECK-FIXES-NEXT: printf("%d\n", NUM);
+
   int NUM = 0;
   for (int I = 0; I < N; ++I) {
 printf("%d\n", NUMS[I] + NUM);
Index: test/clang-tidy/modernize-loop-convert-lowercase.cpp
===
--- test/clang-tidy/modernize-loop-convert-lowercase.cpp
+++ test/clang-tidy/modernize-loop-convert-lowercase.cpp
@@ -7,6 +7,7 @@
 const int n = 10;
 int arr[n];
 int nums[n];
+int nums_[n];
 
 void naming() {
   for (int i = 0; i < n; ++i) {
@@ -23,6 +24,13 @@
   // CHECK-FIXES: for (auto & num : nums)
   // CHECK-FIXES-NEXT: printf("%d\n", num);
 
+  for (int i = 0; i < n; ++i) {
+printf("%d\n", nums_[i]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & num : nums_)
+  // CHECK-FIXES-NEXT: printf("%d\n", num);
+
   int num = 0;
   for (int i = 0; i < n; ++i) {
 printf("%d\n", nums[i] + num);
Index: clang-tidy/modernize/LoopConvertUtils.cpp
===
--- clang-tidy/modernize/LoopConvertUtils.cpp
+++ clang-tidy/modernize/LoopConvertUtils.cpp
@@ -

Re: [PATCH] D13381: Handle trailing underscores on modernize-loop-convert variable namer.

2015-10-02 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 36357.
angelgarcia added a comment.

Yes! Sorry.


http://reviews.llvm.org/D13381

Files:
  clang-tidy/modernize/LoopConvertUtils.cpp
  test/clang-tidy/modernize-loop-convert-lowercase.cpp
  test/clang-tidy/modernize-loop-convert-uppercase.cpp

Index: test/clang-tidy/modernize-loop-convert-uppercase.cpp
===
--- test/clang-tidy/modernize-loop-convert-uppercase.cpp
+++ test/clang-tidy/modernize-loop-convert-uppercase.cpp
@@ -7,6 +7,7 @@
 const int N = 10;
 int ARR[N];
 int NUMS[N];
+int NUMS_[N];
 
 void naming() {
   for (int I = 0; I < N; ++I) {
@@ -23,6 +24,13 @@
   // CHECK-FIXES: for (auto & NUM : NUMS)
   // CHECK-FIXES-NEXT: printf("%d\n", NUM);
 
+  for (int I = 0; I < N; ++I) {
+printf("%d\n", NUMS_[I]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & NUM : NUMS_)
+  // CHECK-FIXES-NEXT: printf("%d\n", NUM);
+
   int NUM = 0;
   for (int I = 0; I < N; ++I) {
 printf("%d\n", NUMS[I] + NUM);
Index: test/clang-tidy/modernize-loop-convert-lowercase.cpp
===
--- test/clang-tidy/modernize-loop-convert-lowercase.cpp
+++ test/clang-tidy/modernize-loop-convert-lowercase.cpp
@@ -7,6 +7,7 @@
 const int n = 10;
 int arr[n];
 int nums[n];
+int nums_[n];
 
 void naming() {
   for (int i = 0; i < n; ++i) {
@@ -23,6 +24,13 @@
   // CHECK-FIXES: for (auto & num : nums)
   // CHECK-FIXES-NEXT: printf("%d\n", num);
 
+  for (int i = 0; i < n; ++i) {
+printf("%d\n", nums_[i]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & num : nums_)
+  // CHECK-FIXES-NEXT: printf("%d\n", num);
+
   int num = 0;
   for (int i = 0; i < n; ++i) {
 printf("%d\n", nums[i] + num);
Index: clang-tidy/modernize/LoopConvertUtils.cpp
===
--- clang-tidy/modernize/LoopConvertUtils.cpp
+++ clang-tidy/modernize/LoopConvertUtils.cpp
@@ -819,6 +819,14 @@
   size_t Len = ContainerName.size();
   if (Len > 1 && ContainerName.endswith(Style == NS_UpperCase ? "S" : "s")) {
 IteratorName = ContainerName.substr(0, Len - 1);
+// Ej: (auto thing : things)
+if (!declarationExists(IteratorName))
+  return IteratorName;
+  }
+
+  if (Len > 2 && ContainerName.endswith(Style == NS_UpperCase ? "S_" : "s_")) {
+IteratorName = ContainerName.substr(0, Len - 2);
+// E.g.: (auto thing : things_)
 if (!declarationExists(IteratorName))
   return IteratorName;
   }
@@ -835,14 +843,17 @@
   case NS_UpperCase:
 Elem = "ELEM";
   }
+  // E.g.: (auto elem : container)
   if (!declarationExists(Elem))
 return Elem;
 
   IteratorName = AppendWithStyle(ContainerName, OldIndex->getName());
+  // E.g.: (auto container_i : container)
   if (!declarationExists(IteratorName))
 return IteratorName;
 
   IteratorName = AppendWithStyle(ContainerName, Elem);
+  // E.g.: (auto container_elem : container)
   if (!declarationExists(IteratorName))
 return IteratorName;
 


Index: test/clang-tidy/modernize-loop-convert-uppercase.cpp
===
--- test/clang-tidy/modernize-loop-convert-uppercase.cpp
+++ test/clang-tidy/modernize-loop-convert-uppercase.cpp
@@ -7,6 +7,7 @@
 const int N = 10;
 int ARR[N];
 int NUMS[N];
+int NUMS_[N];
 
 void naming() {
   for (int I = 0; I < N; ++I) {
@@ -23,6 +24,13 @@
   // CHECK-FIXES: for (auto & NUM : NUMS)
   // CHECK-FIXES-NEXT: printf("%d\n", NUM);
 
+  for (int I = 0; I < N; ++I) {
+printf("%d\n", NUMS_[I]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & NUM : NUMS_)
+  // CHECK-FIXES-NEXT: printf("%d\n", NUM);
+
   int NUM = 0;
   for (int I = 0; I < N; ++I) {
 printf("%d\n", NUMS[I] + NUM);
Index: test/clang-tidy/modernize-loop-convert-lowercase.cpp
===
--- test/clang-tidy/modernize-loop-convert-lowercase.cpp
+++ test/clang-tidy/modernize-loop-convert-lowercase.cpp
@@ -7,6 +7,7 @@
 const int n = 10;
 int arr[n];
 int nums[n];
+int nums_[n];
 
 void naming() {
   for (int i = 0; i < n; ++i) {
@@ -23,6 +24,13 @@
   // CHECK-FIXES: for (auto & num : nums)
   // CHECK-FIXES-NEXT: printf("%d\n", num);
 
+  for (int i = 0; i < n; ++i) {
+printf("%d\n", nums_[i]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & num : nums_)
+  // CHECK-FIXES-NEXT: printf("%d\n", num);
+
   int num = 0;
   for (int i = 0; i < n; ++i) {
 printf("%d\n", nums[i] + num);
Index: clang-tidy/modernize/LoopConvertUtils.cpp
===
--- clang-tidy/modernize/LoopConvertUtils.cpp
+++ clang-tidy/modernize/LoopConvertUtils.cpp
@@ -819,

Re: [PATCH] D13246: Fix bug in modernize-use-nullptr.

2015-10-02 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 36359.
angelgarcia added a comment.

Update this patch to the change in RecursiveASTVisitor.


http://reviews.llvm.org/D13246

Files:
  clang-tidy/modernize/UseNullptrCheck.cpp
  test/clang-tidy/modernize-use-nullptr.cpp

Index: test/clang-tidy/modernize-use-nullptr.cpp
===
--- test/clang-tidy/modernize-use-nullptr.cpp
+++ test/clang-tidy/modernize-use-nullptr.cpp
@@ -174,4 +174,13 @@
 #define CALL(X) X
   OPTIONAL_CODE(NOT_NULL);
   CALL(NOT_NULL);
+
+#define ENTRY(X) {X}
+  struct A {
+int *Ptr;
+  } a[2] = {ENTRY(0), {0}};
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use nullptr
+  // CHECK-MESSAGES: :[[@LINE-2]]:24: warning: use nullptr
+  // CHECK-FIXES: a[2] = {ENTRY(nullptr), {nullptr}};
+#undef ENTRY
 }
Index: clang-tidy/modernize/UseNullptrCheck.cpp
===
--- clang-tidy/modernize/UseNullptrCheck.cpp
+++ clang-tidy/modernize/UseNullptrCheck.cpp
@@ -150,6 +150,16 @@
 return true;
   }
 
+  bool TraverseInitListExpr(InitListExpr *S) {
+// Only go through the semantic form of the InitListExpr, because
+// ImplicitCast might not appear in the syntactic form, and this results in
+// finding usages of the macro argument that don't have a ImplicitCast as 
an
+// ancestor (thus invalidating the replacement) when they actually have.
+return RecursiveASTVisitor::
+TraverseSynOrSemInitListExpr(
+S->isSemanticForm() ? S : S->getSemanticForm());
+  }
+
   bool foundInvalid() const { return InvalidFound; }
 
 private:
@@ -273,7 +283,7 @@
 // Visit children of this containing parent looking for the least-descended
 // nodes of the containing parent which are macro arg expansions that 
expand
 // from the given arg location.
-// Visitor needs: arg loc
+// Visitor needs: arg loc.
 MacroArgUsageVisitor ArgUsageVisitor(SM.getFileLoc(CastLoc), SM);
 if (const auto *D = ContainingAncestor.get())
   ArgUsageVisitor.TraverseDecl(const_cast(D));
@@ -345,8 +355,8 @@
   /// also handled.
   ///
   /// False means either:
-  /// - TestLoc is not from a macro expansion
-  /// - TestLoc is from a different macro expansion
+  /// - TestLoc is not from a macro expansion.
+  /// - TestLoc is from a different macro expansion.
   bool expandsFrom(SourceLocation TestLoc, SourceLocation TestMacroLoc) {
 if (TestLoc.isFileID()) {
   return false;
@@ -399,17 +409,24 @@
   ast_type_traits::DynTypedNode &Result) {
 // Below we're only following the first parent back up the AST. This should
 // be fine since for the statements we care about there should only be one
-// parent as far up as we care. If this assumption doesn't hold, need to
-// revisit what to do here.
+// parent, except for the case specified below.
 
 assert(MacroLoc.isFileID());
 
 while (true) {
   const auto &Parents = Context.getParents(Start);
   if (Parents.empty())
 return false;
-  assert(Parents.size() == 1 &&
- "Found an ancestor with more than one parent!");
+  if (Parents.size() > 1) {
+// If there are more than one parents, don't do the replacement unless
+// they are InitListsExpr (semantic and syntactic form). In this case 
we
+// can choose any one here, and the ASTVisitor will take care of
+// traversing the right one.
+for (const auto &Parent : Parents) {
+  if (!Parent.get())
+return false;
+}
+  }
 
   const ast_type_traits::DynTypedNode &Parent = Parents[0];
 


Index: test/clang-tidy/modernize-use-nullptr.cpp
===
--- test/clang-tidy/modernize-use-nullptr.cpp
+++ test/clang-tidy/modernize-use-nullptr.cpp
@@ -174,4 +174,13 @@
 #define CALL(X) X
   OPTIONAL_CODE(NOT_NULL);
   CALL(NOT_NULL);
+
+#define ENTRY(X) {X}
+  struct A {
+int *Ptr;
+  } a[2] = {ENTRY(0), {0}};
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use nullptr
+  // CHECK-MESSAGES: :[[@LINE-2]]:24: warning: use nullptr
+  // CHECK-FIXES: a[2] = {ENTRY(nullptr), {nullptr}};
+#undef ENTRY
 }
Index: clang-tidy/modernize/UseNullptrCheck.cpp
===
--- clang-tidy/modernize/UseNullptrCheck.cpp
+++ clang-tidy/modernize/UseNullptrCheck.cpp
@@ -150,6 +150,16 @@
 return true;
   }
 
+  bool TraverseInitListExpr(InitListExpr *S) {
+// Only go through the semantic form of the InitListExpr, because
+// ImplicitCast might not appear in the syntactic form, and this results in
+// finding usages of the macro argument that don't have a ImplicitCast as an
+// ancestor (thus invalidating the replacement) when they actually have.
+return RecursiveASTVisitor::
+TraverseSynOrSemInitListExpr(
+S->isSemanticForm() ? S : S-

[PATCH] D13431: Document a bug in loop-convert and fix one of its subcases.

2015-10-05 Thread Angel Garcia via cfe-commits
angelgarcia created this revision.
angelgarcia added a reviewer: klimek.
angelgarcia added subscribers: cfe-commits, alexfh.

Now that we prioritize copying trivial types over using const-references where 
possible, I found some cases where, after the transformation, the loop was 
using the address of the local copy instead of the original object.

http://reviews.llvm.org/D13431

Files:
  clang-tidy/modernize/LoopConvertCheck.cpp
  test/clang-tidy/modernize-loop-convert-basic.cpp

Index: test/clang-tidy/modernize-loop-convert-basic.cpp
===
--- test/clang-tidy/modernize-loop-convert-basic.cpp
+++ test/clang-tidy/modernize-loop-convert-basic.cpp
@@ -97,7 +97,7 @@
   // CHECK-FIXES-NEXT: Tea.g();
 }
 
-void constArray() {
+const int *constArray() {
   for (int I = 0; I < N; ++I) {
 printf("2 * %d = %d\n", ConstArr[I], ConstArr[I] + ConstArr[I]);
   }
@@ -112,6 +112,16 @@
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (const auto & Elem : NonCopy)
   // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", Elem.X, Elem.X + Elem.X);
+
+  bool Something = false;
+  for (int I = 0; I < N; ++I) {
+if (Something)
+  return &ConstArr[I];
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (const auto & Elem : ConstArr)
+  // CHECK-FIXES-NEXT: if (Something)
+  // CHECK-FIXES-NEXT: return &Elem;
 }
 
 struct HasArr {
Index: clang-tidy/modernize/LoopConvertCheck.cpp
===
--- clang-tidy/modernize/LoopConvertCheck.cpp
+++ clang-tidy/modernize/LoopConvertCheck.cpp
@@ -477,6 +477,7 @@
   std::string VarName;
   bool VarNameFromAlias = (Usages.size() == 1) && AliasDecl;
   bool AliasVarIsRef = false;
+  bool CanCopy = true;
 
   if (VarNameFromAlias) {
 const auto *AliasVar = cast(AliasDecl->getSingleDecl());
@@ -525,6 +526,16 @@
 // and parenthesis around a simple DeclRefExpr can always be
 // removed.
 Range = Paren->getSourceRange();
+  } else if (const auto *Uop = Parents[0].get()) {
+// If we are taking the address of the loop variable, then we must
+// not use a copy, as it would mean taking the address of the 
loop's
+// local index instead.
+// FIXME: This won't catch cases where the address is taken outside
+// of the loop's body (for instance, in a function that got the
+// loop's index as a const reference parameter), or where we take
+// the address of a member (like "&Arr[i].A.B.C").
+if (Uop->getOpcode() == UO_AddrOf)
+  CanCopy = false;
   }
 }
   } else {
@@ -548,8 +559,10 @@
   // If the new variable name is from the aliased variable, then the reference
   // type for the new variable should only be used if the aliased variable was
   // declared as a reference.
-  bool UseCopy = (VarNameFromAlias && !AliasVarIsRef) ||
- (Descriptor.DerefByConstRef && 
Descriptor.IsTriviallyCopyable);
+  bool UseCopy =
+  CanCopy &&
+  ((VarNameFromAlias && !AliasVarIsRef) ||
+   (Descriptor.DerefByConstRef && Descriptor.IsTriviallyCopyable));
 
   if (!UseCopy) {
 if (Descriptor.DerefByConstRef) {


Index: test/clang-tidy/modernize-loop-convert-basic.cpp
===
--- test/clang-tidy/modernize-loop-convert-basic.cpp
+++ test/clang-tidy/modernize-loop-convert-basic.cpp
@@ -97,7 +97,7 @@
   // CHECK-FIXES-NEXT: Tea.g();
 }
 
-void constArray() {
+const int *constArray() {
   for (int I = 0; I < N; ++I) {
 printf("2 * %d = %d\n", ConstArr[I], ConstArr[I] + ConstArr[I]);
   }
@@ -112,6 +112,16 @@
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (const auto & Elem : NonCopy)
   // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", Elem.X, Elem.X + Elem.X);
+
+  bool Something = false;
+  for (int I = 0; I < N; ++I) {
+if (Something)
+  return &ConstArr[I];
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (const auto & Elem : ConstArr)
+  // CHECK-FIXES-NEXT: if (Something)
+  // CHECK-FIXES-NEXT: return &Elem;
 }
 
 struct HasArr {
Index: clang-tidy/modernize/LoopConvertCheck.cpp
===
--- clang-tidy/modernize/LoopConvertCheck.cpp
+++ clang-tidy/modernize/LoopConvertCheck.cpp
@@ -477,6 +477,7 @@
   std::string VarName;
   bool VarNameFromAlias = (Usages.size() == 1) && AliasDecl;
   bool AliasVarIsRef = false;
+  bool CanCopy = true;
 
   if (VarNameFromAlias) {
 const auto *AliasVar = cast(AliasDecl->getSingleDecl());
@@ -525,6 +526,16 @@
 // and parenthesis around a simple DeclRefExpr can always be
 // removed.
 Ran

Re: [PATCH] D13431: Document a bug in loop-convert and fix one of its subcases.

2015-10-05 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 36500.
angelgarcia added a comment.

Use "UOP".


http://reviews.llvm.org/D13431

Files:
  clang-tidy/modernize/LoopConvertCheck.cpp
  test/clang-tidy/modernize-loop-convert-basic.cpp

Index: test/clang-tidy/modernize-loop-convert-basic.cpp
===
--- test/clang-tidy/modernize-loop-convert-basic.cpp
+++ test/clang-tidy/modernize-loop-convert-basic.cpp
@@ -97,7 +97,7 @@
   // CHECK-FIXES-NEXT: Tea.g();
 }
 
-void constArray() {
+const int *constArray() {
   for (int I = 0; I < N; ++I) {
 printf("2 * %d = %d\n", ConstArr[I], ConstArr[I] + ConstArr[I]);
   }
@@ -112,6 +112,16 @@
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (const auto & Elem : NonCopy)
   // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", Elem.X, Elem.X + Elem.X);
+
+  bool Something = false;
+  for (int I = 0; I < N; ++I) {
+if (Something)
+  return &ConstArr[I];
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (const auto & Elem : ConstArr)
+  // CHECK-FIXES-NEXT: if (Something)
+  // CHECK-FIXES-NEXT: return &Elem;
 }
 
 struct HasArr {
Index: clang-tidy/modernize/LoopConvertCheck.cpp
===
--- clang-tidy/modernize/LoopConvertCheck.cpp
+++ clang-tidy/modernize/LoopConvertCheck.cpp
@@ -477,6 +477,7 @@
   std::string VarName;
   bool VarNameFromAlias = (Usages.size() == 1) && AliasDecl;
   bool AliasVarIsRef = false;
+  bool CanCopy = true;
 
   if (VarNameFromAlias) {
 const auto *AliasVar = cast(AliasDecl->getSingleDecl());
@@ -525,6 +526,16 @@
 // and parenthesis around a simple DeclRefExpr can always be
 // removed.
 Range = Paren->getSourceRange();
+  } else if (const auto *UOP = Parents[0].get()) {
+// If we are taking the address of the loop variable, then we must
+// not use a copy, as it would mean taking the address of the 
loop's
+// local index instead.
+// FIXME: This won't catch cases where the address is taken outside
+// of the loop's body (for instance, in a function that got the
+// loop's index as a const reference parameter), or where we take
+// the address of a member (like "&Arr[i].A.B.C").
+if (UOP->getOpcode() == UO_AddrOf)
+  CanCopy = false;
   }
 }
   } else {
@@ -548,8 +559,10 @@
   // If the new variable name is from the aliased variable, then the reference
   // type for the new variable should only be used if the aliased variable was
   // declared as a reference.
-  bool UseCopy = (VarNameFromAlias && !AliasVarIsRef) ||
- (Descriptor.DerefByConstRef && 
Descriptor.IsTriviallyCopyable);
+  bool UseCopy =
+  CanCopy &&
+  ((VarNameFromAlias && !AliasVarIsRef) ||
+   (Descriptor.DerefByConstRef && Descriptor.IsTriviallyCopyable));
 
   if (!UseCopy) {
 if (Descriptor.DerefByConstRef) {


Index: test/clang-tidy/modernize-loop-convert-basic.cpp
===
--- test/clang-tidy/modernize-loop-convert-basic.cpp
+++ test/clang-tidy/modernize-loop-convert-basic.cpp
@@ -97,7 +97,7 @@
   // CHECK-FIXES-NEXT: Tea.g();
 }
 
-void constArray() {
+const int *constArray() {
   for (int I = 0; I < N; ++I) {
 printf("2 * %d = %d\n", ConstArr[I], ConstArr[I] + ConstArr[I]);
   }
@@ -112,6 +112,16 @@
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (const auto & Elem : NonCopy)
   // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", Elem.X, Elem.X + Elem.X);
+
+  bool Something = false;
+  for (int I = 0; I < N; ++I) {
+if (Something)
+  return &ConstArr[I];
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (const auto & Elem : ConstArr)
+  // CHECK-FIXES-NEXT: if (Something)
+  // CHECK-FIXES-NEXT: return &Elem;
 }
 
 struct HasArr {
Index: clang-tidy/modernize/LoopConvertCheck.cpp
===
--- clang-tidy/modernize/LoopConvertCheck.cpp
+++ clang-tidy/modernize/LoopConvertCheck.cpp
@@ -477,6 +477,7 @@
   std::string VarName;
   bool VarNameFromAlias = (Usages.size() == 1) && AliasDecl;
   bool AliasVarIsRef = false;
+  bool CanCopy = true;
 
   if (VarNameFromAlias) {
 const auto *AliasVar = cast(AliasDecl->getSingleDecl());
@@ -525,6 +526,16 @@
 // and parenthesis around a simple DeclRefExpr can always be
 // removed.
 Range = Paren->getSourceRange();
+  } else if (const auto *UOP = Parents[0].get()) {
+// If we are taking the address of the loop variable, then we must
+// not use a copy, as it would mean taking the address of the loop's
+  

Re: [PATCH] D13431: Document a bug in loop-convert and fix one of its subcases.

2015-10-05 Thread Angel Garcia via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL249300: Document a bug in loop-convert and fix one of its 
subcases. (authored by angelgarcia).

Changed prior to commit:
  http://reviews.llvm.org/D13431?vs=36500&id=36501#toc

http://reviews.llvm.org/D13431

Files:
  clang-tools-extra/trunk/clang-tidy/modernize/LoopConvertCheck.cpp
  clang-tools-extra/trunk/test/clang-tidy/modernize-loop-convert-basic.cpp

Index: clang-tools-extra/trunk/clang-tidy/modernize/LoopConvertCheck.cpp
===
--- clang-tools-extra/trunk/clang-tidy/modernize/LoopConvertCheck.cpp
+++ clang-tools-extra/trunk/clang-tidy/modernize/LoopConvertCheck.cpp
@@ -477,6 +477,7 @@
   std::string VarName;
   bool VarNameFromAlias = (Usages.size() == 1) && AliasDecl;
   bool AliasVarIsRef = false;
+  bool CanCopy = true;
 
   if (VarNameFromAlias) {
 const auto *AliasVar = cast(AliasDecl->getSingleDecl());
@@ -525,6 +526,16 @@
 // and parenthesis around a simple DeclRefExpr can always be
 // removed.
 Range = Paren->getSourceRange();
+  } else if (const auto *UOP = Parents[0].get()) {
+// If we are taking the address of the loop variable, then we must
+// not use a copy, as it would mean taking the address of the 
loop's
+// local index instead.
+// FIXME: This won't catch cases where the address is taken outside
+// of the loop's body (for instance, in a function that got the
+// loop's index as a const reference parameter), or where we take
+// the address of a member (like "&Arr[i].A.B.C").
+if (UOP->getOpcode() == UO_AddrOf)
+  CanCopy = false;
   }
 }
   } else {
@@ -548,8 +559,10 @@
   // If the new variable name is from the aliased variable, then the reference
   // type for the new variable should only be used if the aliased variable was
   // declared as a reference.
-  bool UseCopy = (VarNameFromAlias && !AliasVarIsRef) ||
- (Descriptor.DerefByConstRef && 
Descriptor.IsTriviallyCopyable);
+  bool UseCopy =
+  CanCopy &&
+  ((VarNameFromAlias && !AliasVarIsRef) ||
+   (Descriptor.DerefByConstRef && Descriptor.IsTriviallyCopyable));
 
   if (!UseCopy) {
 if (Descriptor.DerefByConstRef) {
Index: clang-tools-extra/trunk/test/clang-tidy/modernize-loop-convert-basic.cpp
===
--- clang-tools-extra/trunk/test/clang-tidy/modernize-loop-convert-basic.cpp
+++ clang-tools-extra/trunk/test/clang-tidy/modernize-loop-convert-basic.cpp
@@ -97,7 +97,7 @@
   // CHECK-FIXES-NEXT: Tea.g();
 }
 
-void constArray() {
+const int *constArray() {
   for (int I = 0; I < N; ++I) {
 printf("2 * %d = %d\n", ConstArr[I], ConstArr[I] + ConstArr[I]);
   }
@@ -112,6 +112,16 @@
   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (const auto & Elem : NonCopy)
   // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", Elem.X, Elem.X + Elem.X);
+
+  bool Something = false;
+  for (int I = 0; I < N; ++I) {
+if (Something)
+  return &ConstArr[I];
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (const auto & Elem : ConstArr)
+  // CHECK-FIXES-NEXT: if (Something)
+  // CHECK-FIXES-NEXT: return &Elem;
 }
 
 struct HasArr {


Index: clang-tools-extra/trunk/clang-tidy/modernize/LoopConvertCheck.cpp
===
--- clang-tools-extra/trunk/clang-tidy/modernize/LoopConvertCheck.cpp
+++ clang-tools-extra/trunk/clang-tidy/modernize/LoopConvertCheck.cpp
@@ -477,6 +477,7 @@
   std::string VarName;
   bool VarNameFromAlias = (Usages.size() == 1) && AliasDecl;
   bool AliasVarIsRef = false;
+  bool CanCopy = true;
 
   if (VarNameFromAlias) {
 const auto *AliasVar = cast(AliasDecl->getSingleDecl());
@@ -525,6 +526,16 @@
 // and parenthesis around a simple DeclRefExpr can always be
 // removed.
 Range = Paren->getSourceRange();
+  } else if (const auto *UOP = Parents[0].get()) {
+// If we are taking the address of the loop variable, then we must
+// not use a copy, as it would mean taking the address of the loop's
+// local index instead.
+// FIXME: This won't catch cases where the address is taken outside
+// of the loop's body (for instance, in a function that got the
+// loop's index as a const reference parameter), or where we take
+// the address of a member (like "&Arr[i].A.B.C").
+if (UOP->getOpcode() == UO_AddrOf)
+  CanCopy = false;
   }
 }
   } else {
@@ -548,8 +559,10 @@
   // If the new variable name is from the aliased variable, then the reference
   // type for the new 

[PATCH] D13433: Use better mocks in modernize-make-unique, and fix matcher.

2015-10-05 Thread Angel Garcia via cfe-commits
angelgarcia created this revision.
angelgarcia added a reviewer: klimek.
angelgarcia added subscribers: cfe-commits, alexfh.

Add the second template argument to the unique_ptr mock, and update the matcher 
so that it only matches against cases where the second argument is the default.

http://reviews.llvm.org/D13433

Files:
  clang-tidy/modernize/MakeUniqueCheck.cpp
  test/clang-tidy/modernize-make-unique.cpp

Index: test/clang-tidy/modernize-make-unique.cpp
===
--- test/clang-tidy/modernize-make-unique.cpp
+++ test/clang-tidy/modernize-make-unique.cpp
@@ -2,7 +2,10 @@
 
 namespace std {
 
-template 
+template 
+class default_delete {};
+
+template >
 class unique_ptr {
 public:
   unique_ptr(type *ptr);
Index: clang-tidy/modernize/MakeUniqueCheck.cpp
===
--- clang-tidy/modernize/MakeUniqueCheck.cpp
+++ clang-tidy/modernize/MakeUniqueCheck.cpp
@@ -29,10 +29,18 @@
 cxxConstructExpr(
 
hasType(qualType(hasDeclaration(classTemplateSpecializationDecl(
 matchesName("::std::unique_ptr"),
-templateArgumentCountIs(1),
+templateArgumentCountIs(2),
+hasTemplateArgument(0, templateArgument(refersToType(
+   qualType().bind(PointerType,
 hasTemplateArgument(
-0, templateArgument(
-   
refersToType(qualType().bind(PointerType,
+1, templateArgument(refersToType(qualType(
+   hasDeclaration(classTemplateSpecializationDecl(
+   matchesName("::std::default_delete"),
+   templateArgumentCountIs(1),
+   hasTemplateArgument(
+   0, templateArgument(refersToType(
+  qualType(equalsBoundNode(
+  PointerType))),
 argumentCountIs(1),
 hasArgument(0, cxxNewExpr(hasType(pointsTo(qualType(
   equalsBoundNode(PointerType)


Index: test/clang-tidy/modernize-make-unique.cpp
===
--- test/clang-tidy/modernize-make-unique.cpp
+++ test/clang-tidy/modernize-make-unique.cpp
@@ -2,7 +2,10 @@
 
 namespace std {
 
-template 
+template 
+class default_delete {};
+
+template >
 class unique_ptr {
 public:
   unique_ptr(type *ptr);
Index: clang-tidy/modernize/MakeUniqueCheck.cpp
===
--- clang-tidy/modernize/MakeUniqueCheck.cpp
+++ clang-tidy/modernize/MakeUniqueCheck.cpp
@@ -29,10 +29,18 @@
 cxxConstructExpr(
 hasType(qualType(hasDeclaration(classTemplateSpecializationDecl(
 matchesName("::std::unique_ptr"),
-templateArgumentCountIs(1),
+templateArgumentCountIs(2),
+hasTemplateArgument(0, templateArgument(refersToType(
+   qualType().bind(PointerType,
 hasTemplateArgument(
-0, templateArgument(
-   refersToType(qualType().bind(PointerType,
+1, templateArgument(refersToType(qualType(
+   hasDeclaration(classTemplateSpecializationDecl(
+   matchesName("::std::default_delete"),
+   templateArgumentCountIs(1),
+   hasTemplateArgument(
+   0, templateArgument(refersToType(
+  qualType(equalsBoundNode(
+  PointerType))),
 argumentCountIs(1),
 hasArgument(0, cxxNewExpr(hasType(pointsTo(qualType(
   equalsBoundNode(PointerType)
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D13469: Create interfaces and tests for the overlapping replacements fix in clang-tidy.

2015-10-06 Thread Angel Garcia via cfe-commits
angelgarcia created this revision.
angelgarcia added a reviewer: klimek.
angelgarcia added subscribers: cfe-commits, alexfh.

No changes in clang-tidy yet.

http://reviews.llvm.org/D13469

Files:
  unittests/clang-tidy/CMakeLists.txt
  unittests/clang-tidy/ClangTidyTest.h
  unittests/clang-tidy/OverlappingReplacementsTest.cpp
  unittests/clang-tidy/ReadabilityModuleTest.cpp

Index: unittests/clang-tidy/ReadabilityModuleTest.cpp
===
--- unittests/clang-tidy/ReadabilityModuleTest.cpp
+++ unittests/clang-tidy/ReadabilityModuleTest.cpp
@@ -237,7 +237,7 @@
 
 TEST(BracesAroundStatementsCheck, IfElseWithShortStatements) {
   ClangTidyOptions Options;
-  Options.CheckOptions["test-check.ShortStatementLines"] = "1";
+  Options.CheckOptions["test-check-0.ShortStatementLines"] = "1";
 
   EXPECT_EQ("int main() {\n"
 "  if (true) return 1;\n"
Index: unittests/clang-tidy/OverlappingReplacementsTest.cpp
===
--- /dev/null
+++ unittests/clang-tidy/OverlappingReplacementsTest.cpp
@@ -0,0 +1,344 @@
+//=== OverlappingReplacementsTest.cpp - clang-tidy ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#include "ClangTidyTest.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace tidy {
+namespace test {
+namespace {
+
+const char BoundDecl[] = "decl";
+const char BoundIf[] = "if";
+
+class UseCharCheck : public ClangTidyCheck {
+public:
+  UseCharCheck(StringRef CheckName, ClangTidyContext *Context)
+  : ClangTidyCheck(CheckName, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override {
+using namespace ast_matchers;
+Finder->addMatcher(varDecl(hasType(isInteger())).bind(BoundDecl), this);
+  }
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override {
+auto *VD = Result.Nodes.getNodeAs(BoundDecl);
+diag(VD->getLocStart(), "use char") << FixItHint::CreateReplacement(
+CharSourceRange::getTokenRange(VD->getLocStart(), VD->getLocStart()),
+"char");
+  }
+};
+
+class IfFalseCheck : public ClangTidyCheck {
+public:
+  IfFalseCheck(StringRef CheckName, ClangTidyContext *Context)
+  : ClangTidyCheck(CheckName, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override {
+using namespace ast_matchers;
+Finder->addMatcher(ifStmt().bind(BoundIf), this);
+  }
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override {
+auto *If = Result.Nodes.getNodeAs(BoundIf);
+auto *Cond = If->getCond();
+SourceRange Range = Cond->getSourceRange();
+if (auto *D = If->getConditionVariable()) {
+  Range = SourceRange(D->getLocStart(), D->getLocEnd());
+}
+diag(Range.getBegin(), "the cake is a lie") << FixItHint::CreateReplacement(
+CharSourceRange::getTokenRange(Range), "false");
+  }
+};
+
+class RefactorCheck : public ClangTidyCheck {
+public:
+  RefactorCheck(StringRef CheckName, ClangTidyContext *Context)
+  : ClangTidyCheck(CheckName, Context), NamePattern("::$") {}
+  RefactorCheck(StringRef CheckName, ClangTidyContext *Context,
+StringRef NamePattern)
+  : ClangTidyCheck(CheckName, Context), NamePattern(NamePattern) {}
+  virtual std::string newName(StringRef OldName) = 0;
+
+  void registerMatchers(ast_matchers::MatchFinder *Finder) final {
+using namespace ast_matchers;
+Finder->addMatcher(varDecl(matchesName(NamePattern)).bind(BoundDecl), this);
+  }
+
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) final {
+auto *VD = Result.Nodes.getNodeAs(BoundDecl);
+std::string NewName = newName(VD->getName());
+
+auto Diag = diag(VD->getLocation(), "refactor")
+<< FixItHint::CreateReplacement(
+CharSourceRange::getTokenRange(VD->getLocation(),
+   VD->getLocation()),
+NewName);
+
+class UsageVisitor : public RecursiveASTVisitor {
+public:
+  UsageVisitor(const ValueDecl *VD, StringRef NewName,
+   DiagnosticBuilder &Diag)
+  : VD(VD), NewName(NewName), Diag(Diag) {}
+  bool VisitDeclRefExpr(DeclRefExpr *E) {
+if (const ValueDecl *D = E->getDecl()) {
+  if (VD->getCanonicalDecl() == D->getCanonicalDecl()) {
+Diag << FixItHint::CreateReplacement(
+CharSourceRange::getTokenRange(E->getSourceRange()), NewName);
+  }
+}
+return RecursiveASTVisitor::VisitDeclRefExpr(E);
+  }
+
+private:
+  const ValueDecl *VD;
+  StringRef NewName;
+  DiagnosticBuilder &Diag;
+};
+

Re: [PATCH] D13469: Create interfaces and tests for the overlapping replacements fix in clang-tidy.

2015-10-06 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 36615.
angelgarcia added a comment.

This test was intended to ensure that we don't have a bug in the mock checks. 
I've split it up into one test for each mock check, I hope it is more 
descriptive now.


http://reviews.llvm.org/D13469

Files:
  unittests/clang-tidy/CMakeLists.txt
  unittests/clang-tidy/ClangTidyTest.h
  unittests/clang-tidy/OverlappingReplacementsTest.cpp
  unittests/clang-tidy/ReadabilityModuleTest.cpp

Index: unittests/clang-tidy/ReadabilityModuleTest.cpp
===
--- unittests/clang-tidy/ReadabilityModuleTest.cpp
+++ unittests/clang-tidy/ReadabilityModuleTest.cpp
@@ -237,7 +237,7 @@
 
 TEST(BracesAroundStatementsCheck, IfElseWithShortStatements) {
   ClangTidyOptions Options;
-  Options.CheckOptions["test-check.ShortStatementLines"] = "1";
+  Options.CheckOptions["test-check-0.ShortStatementLines"] = "1";
 
   EXPECT_EQ("int main() {\n"
 "  if (true) return 1;\n"
Index: unittests/clang-tidy/OverlappingReplacementsTest.cpp
===
--- /dev/null
+++ unittests/clang-tidy/OverlappingReplacementsTest.cpp
@@ -0,0 +1,375 @@
+//=== OverlappingReplacementsTest.cpp - clang-tidy ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#include "ClangTidyTest.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace tidy {
+namespace test {
+namespace {
+
+const char BoundDecl[] = "decl";
+const char BoundIf[] = "if";
+
+class UseCharCheck : public ClangTidyCheck {
+public:
+  UseCharCheck(StringRef CheckName, ClangTidyContext *Context)
+  : ClangTidyCheck(CheckName, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override {
+using namespace ast_matchers;
+Finder->addMatcher(varDecl(hasType(isInteger())).bind(BoundDecl), this);
+  }
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override {
+auto *VD = Result.Nodes.getNodeAs(BoundDecl);
+diag(VD->getLocStart(), "use char") << FixItHint::CreateReplacement(
+CharSourceRange::getTokenRange(VD->getLocStart(), VD->getLocStart()),
+"char");
+  }
+};
+
+class IfFalseCheck : public ClangTidyCheck {
+public:
+  IfFalseCheck(StringRef CheckName, ClangTidyContext *Context)
+  : ClangTidyCheck(CheckName, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override {
+using namespace ast_matchers;
+Finder->addMatcher(ifStmt().bind(BoundIf), this);
+  }
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override {
+auto *If = Result.Nodes.getNodeAs(BoundIf);
+auto *Cond = If->getCond();
+SourceRange Range = Cond->getSourceRange();
+if (auto *D = If->getConditionVariable()) {
+  Range = SourceRange(D->getLocStart(), D->getLocEnd());
+}
+diag(Range.getBegin(), "the cake is a lie") << FixItHint::CreateReplacement(
+CharSourceRange::getTokenRange(Range), "false");
+  }
+};
+
+class RefactorCheck : public ClangTidyCheck {
+public:
+  RefactorCheck(StringRef CheckName, ClangTidyContext *Context)
+  : ClangTidyCheck(CheckName, Context), NamePattern("::$") {}
+  RefactorCheck(StringRef CheckName, ClangTidyContext *Context,
+StringRef NamePattern)
+  : ClangTidyCheck(CheckName, Context), NamePattern(NamePattern) {}
+  virtual std::string newName(StringRef OldName) = 0;
+
+  void registerMatchers(ast_matchers::MatchFinder *Finder) final {
+using namespace ast_matchers;
+Finder->addMatcher(varDecl(matchesName(NamePattern)).bind(BoundDecl), this);
+  }
+
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) final {
+auto *VD = Result.Nodes.getNodeAs(BoundDecl);
+std::string NewName = newName(VD->getName());
+
+auto Diag = diag(VD->getLocation(), "refactor")
+<< FixItHint::CreateReplacement(
+CharSourceRange::getTokenRange(VD->getLocation(),
+   VD->getLocation()),
+NewName);
+
+class UsageVisitor : public RecursiveASTVisitor {
+public:
+  UsageVisitor(const ValueDecl *VD, StringRef NewName,
+   DiagnosticBuilder &Diag)
+  : VD(VD), NewName(NewName), Diag(Diag) {}
+  bool VisitDeclRefExpr(DeclRefExpr *E) {
+if (const ValueDecl *D = E->getDecl()) {
+  if (VD->getCanonicalDecl() == D->getCanonicalDecl()) {
+Diag << FixItHint::CreateReplacement(
+CharSourceRange::getTokenRange(E->getSourceRange()), NewName);
+  }
+}
+return RecursiveASTVisitor::VisitDeclRefExpr(E);
+  }
+
+private:
+

Re: [PATCH] D13469: Create interfaces and tests for the overlapping replacements fix in clang-tidy.

2015-10-06 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 36620.
angelgarcia added a comment.

Explain why we have defined these mocks.


http://reviews.llvm.org/D13469

Files:
  unittests/clang-tidy/CMakeLists.txt
  unittests/clang-tidy/ClangTidyTest.h
  unittests/clang-tidy/OverlappingReplacementsTest.cpp
  unittests/clang-tidy/ReadabilityModuleTest.cpp

Index: unittests/clang-tidy/ReadabilityModuleTest.cpp
===
--- unittests/clang-tidy/ReadabilityModuleTest.cpp
+++ unittests/clang-tidy/ReadabilityModuleTest.cpp
@@ -237,7 +237,7 @@
 
 TEST(BracesAroundStatementsCheck, IfElseWithShortStatements) {
   ClangTidyOptions Options;
-  Options.CheckOptions["test-check.ShortStatementLines"] = "1";
+  Options.CheckOptions["test-check-0.ShortStatementLines"] = "1";
 
   EXPECT_EQ("int main() {\n"
 "  if (true) return 1;\n"
Index: unittests/clang-tidy/OverlappingReplacementsTest.cpp
===
--- /dev/null
+++ unittests/clang-tidy/OverlappingReplacementsTest.cpp
@@ -0,0 +1,379 @@
+//=== OverlappingReplacementsTest.cpp - clang-tidy ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#include "ClangTidyTest.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace tidy {
+namespace test {
+namespace {
+
+const char BoundDecl[] = "decl";
+const char BoundIf[] = "if";
+
+// We define a reduced set of very small checks that allow to test different
+// overlapping situations (no overlapping, replacements partially overlap, etc),
+// as well as different kinds of diagnostics (one check produces several errors,
+// several replacement ranges in an error, etc).
+class UseCharCheck : public ClangTidyCheck {
+public:
+  UseCharCheck(StringRef CheckName, ClangTidyContext *Context)
+  : ClangTidyCheck(CheckName, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override {
+using namespace ast_matchers;
+Finder->addMatcher(varDecl(hasType(isInteger())).bind(BoundDecl), this);
+  }
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override {
+auto *VD = Result.Nodes.getNodeAs(BoundDecl);
+diag(VD->getLocStart(), "use char") << FixItHint::CreateReplacement(
+CharSourceRange::getTokenRange(VD->getLocStart(), VD->getLocStart()),
+"char");
+  }
+};
+
+class IfFalseCheck : public ClangTidyCheck {
+public:
+  IfFalseCheck(StringRef CheckName, ClangTidyContext *Context)
+  : ClangTidyCheck(CheckName, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override {
+using namespace ast_matchers;
+Finder->addMatcher(ifStmt().bind(BoundIf), this);
+  }
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override {
+auto *If = Result.Nodes.getNodeAs(BoundIf);
+auto *Cond = If->getCond();
+SourceRange Range = Cond->getSourceRange();
+if (auto *D = If->getConditionVariable()) {
+  Range = SourceRange(D->getLocStart(), D->getLocEnd());
+}
+diag(Range.getBegin(), "the cake is a lie") << FixItHint::CreateReplacement(
+CharSourceRange::getTokenRange(Range), "false");
+  }
+};
+
+class RefactorCheck : public ClangTidyCheck {
+public:
+  RefactorCheck(StringRef CheckName, ClangTidyContext *Context)
+  : ClangTidyCheck(CheckName, Context), NamePattern("::$") {}
+  RefactorCheck(StringRef CheckName, ClangTidyContext *Context,
+StringRef NamePattern)
+  : ClangTidyCheck(CheckName, Context), NamePattern(NamePattern) {}
+  virtual std::string newName(StringRef OldName) = 0;
+
+  void registerMatchers(ast_matchers::MatchFinder *Finder) final {
+using namespace ast_matchers;
+Finder->addMatcher(varDecl(matchesName(NamePattern)).bind(BoundDecl), this);
+  }
+
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) final {
+auto *VD = Result.Nodes.getNodeAs(BoundDecl);
+std::string NewName = newName(VD->getName());
+
+auto Diag = diag(VD->getLocation(), "refactor")
+<< FixItHint::CreateReplacement(
+CharSourceRange::getTokenRange(VD->getLocation(),
+   VD->getLocation()),
+NewName);
+
+class UsageVisitor : public RecursiveASTVisitor {
+public:
+  UsageVisitor(const ValueDecl *VD, StringRef NewName,
+   DiagnosticBuilder &Diag)
+  : VD(VD), NewName(NewName), Diag(Diag) {}
+  bool VisitDeclRefExpr(DeclRefExpr *E) {
+if (const ValueDecl *D = E->getDecl()) {
+  if (VD->getCanonicalDecl() == D->getCanonicalDecl()) {
+Diag << FixItHint::CreateReplacement(
+CharSourc

[PATCH] D13504: Prevent modernize-use-auto from emitting a warning when 'auto' was already being used.

2015-10-07 Thread Angel Garcia via cfe-commits
angelgarcia created this revision.
angelgarcia added reviewers: klimek, bkramer.
angelgarcia added subscribers: alexfh, cfe-commits.

This fixes https://llvm.org/bugs/show_bug.cgi?id=25082 .

http://reviews.llvm.org/D13504

Files:
  clang-tidy/modernize/UseAutoCheck.cpp
  test/clang-tidy/modernize-use-auto-new.cpp

Index: test/clang-tidy/modernize-use-auto-new.cpp
===
--- test/clang-tidy/modernize-use-auto-new.cpp
+++ test/clang-tidy/modernize-use-auto-new.cpp
@@ -95,4 +95,7 @@
 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing 
with new
 // CHECK-FIXES: auto g = new int*, h = new int_p;
   }
+
+  // Don't warn when 'auto' is already being used.
+  auto aut = new MyType();
 }
Index: clang-tidy/modernize/UseAutoCheck.cpp
===
--- clang-tidy/modernize/UseAutoCheck.cpp
+++ clang-tidy/modernize/UseAutoCheck.cpp
@@ -222,6 +222,8 @@
  has(varDecl()),
  unless(has(varDecl(anyOf(
  unless(hasInitializer(ignoringParenImpCasts(cxxNewExpr(,
+ // Skip declarations that are already using auto.
+ hasType(autoType()),
  // FIXME: TypeLoc information is not reliable where CV
  // qualifiers are concerned so these types can't be
  // handled for now.


Index: test/clang-tidy/modernize-use-auto-new.cpp
===
--- test/clang-tidy/modernize-use-auto-new.cpp
+++ test/clang-tidy/modernize-use-auto-new.cpp
@@ -95,4 +95,7 @@
 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
 // CHECK-FIXES: auto g = new int*, h = new int_p;
   }
+
+  // Don't warn when 'auto' is already being used.
+  auto aut = new MyType();
 }
Index: clang-tidy/modernize/UseAutoCheck.cpp
===
--- clang-tidy/modernize/UseAutoCheck.cpp
+++ clang-tidy/modernize/UseAutoCheck.cpp
@@ -222,6 +222,8 @@
  has(varDecl()),
  unless(has(varDecl(anyOf(
  unless(hasInitializer(ignoringParenImpCasts(cxxNewExpr(,
+ // Skip declarations that are already using auto.
+ hasType(autoType()),
  // FIXME: TypeLoc information is not reliable where CV
  // qualifiers are concerned so these types can't be
  // handled for now.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D13504: Prevent modernize-use-auto from emitting a warning when 'auto' was already being used.

2015-10-07 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 36724.
angelgarcia added a comment.

Good point. Solved.


http://reviews.llvm.org/D13504

Files:
  clang-tidy/modernize/UseAutoCheck.cpp
  test/clang-tidy/modernize-use-auto-new.cpp

Index: test/clang-tidy/modernize-use-auto-new.cpp
===
--- test/clang-tidy/modernize-use-auto-new.cpp
+++ test/clang-tidy/modernize-use-auto-new.cpp
@@ -95,4 +95,9 @@
 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing 
with new
 // CHECK-FIXES: auto g = new int*, h = new int_p;
   }
+
+  // Don't warn when 'auto' is already being used.
+  auto aut = new MyType();
+  auto *paut = new MyType();
+  const auto *pcaut = new MyType();
 }
Index: clang-tidy/modernize/UseAutoCheck.cpp
===
--- clang-tidy/modernize/UseAutoCheck.cpp
+++ clang-tidy/modernize/UseAutoCheck.cpp
@@ -222,6 +222,9 @@
  has(varDecl()),
  unless(has(varDecl(anyOf(
  unless(hasInitializer(ignoringParenImpCasts(cxxNewExpr(,
+ // Skip declarations that are already using auto.
+ anyOf(hasType(autoType()),
+   hasType(pointerType(pointee(autoType(),
  // FIXME: TypeLoc information is not reliable where CV
  // qualifiers are concerned so these types can't be
  // handled for now.


Index: test/clang-tidy/modernize-use-auto-new.cpp
===
--- test/clang-tidy/modernize-use-auto-new.cpp
+++ test/clang-tidy/modernize-use-auto-new.cpp
@@ -95,4 +95,9 @@
 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
 // CHECK-FIXES: auto g = new int*, h = new int_p;
   }
+
+  // Don't warn when 'auto' is already being used.
+  auto aut = new MyType();
+  auto *paut = new MyType();
+  const auto *pcaut = new MyType();
 }
Index: clang-tidy/modernize/UseAutoCheck.cpp
===
--- clang-tidy/modernize/UseAutoCheck.cpp
+++ clang-tidy/modernize/UseAutoCheck.cpp
@@ -222,6 +222,9 @@
  has(varDecl()),
  unless(has(varDecl(anyOf(
  unless(hasInitializer(ignoringParenImpCasts(cxxNewExpr(,
+ // Skip declarations that are already using auto.
+ anyOf(hasType(autoType()),
+   hasType(pointerType(pointee(autoType(),
  // FIXME: TypeLoc information is not reliable where CV
  // qualifiers are concerned so these types can't be
  // handled for now.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D13516: Fix overlapping replacements in clang-tidy.

2015-10-07 Thread Angel Garcia via cfe-commits
angelgarcia created this revision.
angelgarcia added reviewers: klimek, bkramer.
angelgarcia added subscribers: alexfh, cfe-commits.

Prevent clang-tidy from applying fixes to errors that overlap with other 
errors' fixes, with one exception: if one fix is completely contained inside 
another one, then we can apply the big one.

http://reviews.llvm.org/D13516

Files:
  clang-tidy/ClangTidyDiagnosticConsumer.cpp
  clang-tidy/ClangTidyDiagnosticConsumer.h
  unittests/clang-tidy/OverlappingReplacementsTest.cpp

Index: unittests/clang-tidy/OverlappingReplacementsTest.cpp
===
--- unittests/clang-tidy/OverlappingReplacementsTest.cpp
+++ unittests/clang-tidy/OverlappingReplacementsTest.cpp
@@ -77,11 +77,12 @@
 auto *VD = Result.Nodes.getNodeAs(BoundDecl);
 std::string NewName = newName(VD->getName());
 
-auto Diag = diag(VD->getLocation(), "refactor")
+auto Diag = diag(VD->getLocation(), "refactor %0 into %1")
+<< VD->getName() << NewName
 << FixItHint::CreateReplacement(
-CharSourceRange::getTokenRange(VD->getLocation(),
-   VD->getLocation()),
-NewName);
+   CharSourceRange::getTokenRange(VD->getLocation(),
+  VD->getLocation()),
+   NewName);
 
 class UsageVisitor : public RecursiveASTVisitor {
 public:
@@ -281,7 +282,7 @@
 
   // Apply the UseCharCheck together with the IfFalseCheck.
   //
-  // The 'If' fix is bigger, so that is the one that has to be applied.
+  // The 'If' fix contains the other, so that is the one that has to be applied.
   // } else if (int a = 0) {
   //^^^ -> char
   //~ -> false
@@ -294,16 +295,16 @@
   }
 })";
   Res = runCheckOnCode(Code);
-  // FIXME: EXPECT_EQ(CharIfFix, Res);
+  EXPECT_EQ(CharIfFix, Res);
 
   // Apply the IfFalseCheck with the StartsWithPotaCheck.
   //
   // The 'If' replacement is bigger here.
   // if (char potato = 0) {
   //  ^^ -> tomato
   // ~~~ -> false
   //
-  // But the refactoring is bigger here:
+  // But the refactoring is the one that contains the other here:
   // char potato = 0;
   //  ^^ -> tomato
   // if (potato) potato;
@@ -318,60 +319,73 @@
   }
 })";
   Res = runCheckOnCode(Code);
-  // FIXME: EXPECT_EQ(IfStartsFix, Res);
-
-  // Silence warnings.
-  (void)CharIfFix;
-  (void)IfStartsFix;
+  EXPECT_EQ(IfStartsFix, Res);
 }
 
-TEST(OverlappingReplacementsTest, ApplyFullErrorOrNothingWhenOverlapping) {
-  std::string Res;
+TEST(OverlappingReplacements, TwoReplacementsInsideOne) {
   const char Code[] =
   R"(void f() {
-  int potato = 0;
-  potato += potato * potato;
-  if (char this_name_make_this_if_really_long = potato) potato;
+  if (int potato = 0) {
+int a = 0;
+  }
 })";
 
-  // StartsWithPotaCheck will try to refactor 'potato' into 'tomato',
-  // and EndsWithTatoCheck will try to use 'pomelo'. We have to apply
-  // either all conversions from one check, or all from the other.
-  const char StartsFix[] =
+  // The two smallest replacements should not be applied.
+  // if (int potato = 0) {
+  // ^^ -> tomato
+  // *** -> char
+  // ~~ -> false
+  // But other errors from the same checks should not be affected.
+  //   int a = 0;
+  //   *** -> char
+  const char Fix[] =
   R"(void f() {
-  int tomato = 0;
-  tomato += tomato * tomato;
-  if (char this_name_make_this_if_really_long = tomato) tomato;
+  if (false) {
+char a = 0;
+  }
 })";
-  const char EndsFix[] =
+  std::string Res =
+  runCheckOnCode(Code);
+  EXPECT_EQ(Fix, Res);
+}
+
+TEST(OverlappingReplacementsTest, DiscardBothChangesWhenPartialOverlapping) {
+  const char Code[] =
   R"(void f() {
-  int pomelo = 0;
-  pomelo += pomelo * pomelo;
-  if (char this_name_make_this_if_really_long = pomelo) pomelo;
+  if (int potato = 0) {
+int a = potato;
+  }
 })";
-  // In case of overlapping, we will prioritize the biggest fix. However, these
-  // two fixes have the same size and position, so we don't know yet which one
-  // will have preference.
-  Res = runCheckOnCode(Code);
-  // FIXME: EXPECT_TRUE(Res == StartsFix || Res == EndsFix);
 
-  // StartsWithPotaCheck will try to refactor 'potato' into 'tomato', but
-  // replacing the 'if' condition is a bigger change than all the refactoring
-  // changes together (48 vs 36), so this is the one that is going to be
-  // applied.
-  const char IfFix[] =
+  // These two replacements overlap, but none of them is completely contained
+  // inside the other. Both of them are discarded.
+  // if (int potato = 0) {
+  // ^^ -> tomato
+  // ~~ -> false
+  //   int a = potato;
+  //   ^^ -> tomato
+  std::string Res = runCheckOnCode(Code);
+  EXPECT_EQ(Code, Res);
+}
+
+TEST(

[PATCH] D11946: Create clang-tidy module modernize. Add pass-by-value check.

2015-08-11 Thread Angel Garcia via cfe-commits
angelgarcia created this revision.
angelgarcia added a reviewer: alexfh.
angelgarcia added a subscriber: cfe-commits.
angelgarcia changed the visibility of this Differential Revision from "Public 
(No Login Required)" to "All Users".

This is the first step for migrating cppmodernize to clang-tidy.

http://reviews.llvm.org/D11946

Files:
  clang-tidy/CMakeLists.txt
  clang-tidy/Makefile
  clang-tidy/modernize/CMakeLists.txt
  clang-tidy/modernize/Makefile
  clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tidy/modernize/PassByValueCheck.cpp
  clang-tidy/modernize/PassByValueCheck.h
  clang-tidy/tool/CMakeLists.txt
  clang-tidy/tool/ClangTidyMain.cpp
  clang-tidy/tool/Makefile
  test/clang-tidy/modernize-pass-by-value.cpp

Index: test/clang-tidy/modernize-pass-by-value.cpp
===
--- test/clang-tidy/modernize-pass-by-value.cpp
+++ test/clang-tidy/modernize-pass-by-value.cpp
@@ -0,0 +1,185 @@
+// RUN: $(dirname %s)/check_clang_tidy.sh %s modernize-pass-by-value %t
+// REQUIRES: shell
+
+// CHECK: #include 
+
+namespace {
+// POD types are trivially move constructible
+struct Movable {
+  int a, b, c;
+};
+
+struct NotMovable {
+  NotMovable() = default;
+  NotMovable(const NotMovable &) = default;
+  NotMovable(NotMovable &&) = delete;
+  int a, b, c;
+};
+}
+
+struct A {
+  A(const Movable &M) : M(M) {}
+  // CHECK: A(Movable M) : M(std::move(M)) {}
+  // SAFE_RISK: A(const Movable &M) : M(M) {}
+  Movable M;
+};
+
+// Test that we aren't modifying other things than a parameter
+Movable GlobalObj;
+struct B {
+  B(const Movable &M) : M(GlobalObj) {}
+  // CHECK: B(const Movable &M) : M(GlobalObj) {}
+  Movable M;
+};
+
+// Test that a parameter with more than one reference to it won't be changed.
+struct C {
+  // Tests extra-reference in body
+  C(const Movable &M) : M(M) { this->i = M.a; }
+  // CHECK: C(const Movable &M) : M(M) { this->i = M.a; }
+
+  // Tests extra-reference in init-list
+  C(const Movable &M, int) : M(M), i(M.a) {}
+  // CHECK: C(const Movable &M, int) : M(M), i(M.a) {}
+  Movable M;
+  int i;
+};
+
+// Test that both declaration and definition are updated
+struct D {
+  D(const Movable &M);
+  // CHECK: D(Movable M);
+  Movable M;
+};
+D::D(const Movable &M) : M(M) {}
+// CHECK: D::D(Movable M) : M(std::move(M)) {}
+
+// Test with default parameter
+struct E {
+  E(const Movable &M = Movable()) : M(M) {}
+  // CHECK: E(Movable M = Movable()) : M(std::move(M)) {}
+  Movable M;
+};
+
+// Test with object that can't be moved
+struct F {
+  F(const NotMovable &NM) : NM(NM) {}
+  // CHECK: F(const NotMovable &NM) : NM(NM) {}
+  NotMovable NM;
+};
+
+// Test unnamed parameter in declaration
+struct G {
+  G(const Movable &);
+  // CHECK: G(Movable );
+  Movable M;
+};
+G::G(const Movable &M) : M(M) {}
+// CHECK: G::G(Movable M) : M(std::move(M)) {}
+
+// Test parameter with and without qualifier
+namespace ns_H {
+typedef ::Movable HMovable;
+}
+struct H {
+  H(const ns_H::HMovable &M);
+  // CHECK: H(ns_H::HMovable M);
+  ns_H::HMovable M;
+};
+using namespace ns_H;
+H::H(const HMovable &M) : M(M) {}
+// CHECK: H(HMovable M) : M(std::move(M)) {}
+
+// Try messing up with macros
+#define MOVABLE_PARAM(Name) const Movable & Name
+// CHECK: #define MOVABLE_PARAM(Name) const Movable & Name
+struct I {
+  I(MOVABLE_PARAM(M)) : M(M) {}
+  // CHECK: I(MOVABLE_PARAM(M)) : M(M) {}
+  Movable M;
+};
+#undef MOVABLE_PARAM
+
+// Test that templates aren't modified
+template  struct J {
+  J(const T &M) : M(M) {}
+  // CHECK: J(const T &M) : M(M) {}
+  T M;
+};
+J j1(Movable());
+J j2(NotMovable());
+
+struct K_Movable {
+  K_Movable() = default;
+  K_Movable(const K_Movable &) = default;
+  K_Movable(K_Movable &&o) { dummy = o.dummy; }
+  int dummy;
+};
+
+// Test with movable type with an user defined move constructor.
+struct K {
+  K(const K_Movable &M) : M(M) {}
+  // CHECK: K(K_Movable M) : M(std::move(M)) {}
+  K_Movable M;
+};
+
+template  struct L {
+  L(const Movable &M) : M(M) {}
+  // CHECK: L(Movable M) : M(std::move(M)) {}
+  Movable M;
+};
+L l(Movable());
+
+// Test with a non-instantiated template class
+template  struct N {
+  N(const Movable &M) : M(M) {}
+  // CHECK: N(Movable M) : M(std::move(M)) {}
+
+  Movable M;
+  T A;
+};
+
+// Test with value parameter
+struct O {
+  O(Movable M) : M(M) {}
+  // CHECK: O(Movable M) : M(std::move(M)) {}
+  Movable M;
+};
+
+// Test with a const-value parameter
+struct P {
+  P(const Movable M) : M(M) {}
+  // CHECK: P(const Movable M) : M(M) {}
+  Movable M;
+};
+
+// Test with multiples parameters where some need to be changed and some don't
+// need to.
+struct Q {
+  Q(const Movable &A, const Movable &B, const Movable &C, double D)
+  : A(A), B(B), C(C), D(D) {}
+  // CHECK:  Q(const Movable &A, Movable B, Movable C, double D)
+  // CHECK-NEXT: : A(A), B(std::move(B)), C(std::move(C)), D(D) {}
+  const Movable &A;
+  Movable B;
+  Movable C;
+  double D;
+};
+
+// 

Re: [PATCH] D11946: Create clang-tidy module modernize. Add pass-by-value check.

2015-08-12 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 31911.
angelgarcia added a comment.

Run clang-format and minor fixes.


http://reviews.llvm.org/D11946

Files:
  CMakeLists.txt
  Makefile
  ModernizeTidyModule.cpp
  PassByValueCheck.cpp
  PassByValueCheck.h
  clang-tidy/CMakeLists.txt
  clang-tidy/Makefile
  clang-tidy/modernize/CMakeLists.txt
  clang-tidy/modernize/Makefile
  clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tidy/modernize/PassByValueCheck.cpp
  clang-tidy/modernize/PassByValueCheck.h
  clang-tidy/tool/CMakeLists.txt
  clang-tidy/tool/ClangTidyMain.cpp
  clang-tidy/tool/Makefile
  test/clang-tidy/modernize-pass-by-value.cpp

Index: PassByValueCheck.h
===
--- PassByValueCheck.h
+++ PassByValueCheck.h
@@ -0,0 +1,38 @@
+//===--- PassByValueCheck.h - clang-tidy-*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_PASS_BY_VALUE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_PASS_BY_VALUE_H
+
+#include "../ClangTidy.h"
+#include "../IncludeInserter.h"
+
+#include 
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+class PassByValueCheck : public ClangTidyCheck {
+public:
+  PassByValueCheck(StringRef Name, ClangTidyContext *Context)
+  : ClangTidyCheck(Name, Context) {}
+  void registerPPCallbacks(clang::CompilerInstance &Compiler) override;
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  std::unique_ptr Inserter;
+};
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_PASS_BY_VALUE_H
Index: PassByValueCheck.cpp
===
--- PassByValueCheck.cpp
+++ PassByValueCheck.cpp
@@ -0,0 +1,212 @@
+//===--- PassByValueCheck.cpp - clang-tidy-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#include "PassByValueCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/Preprocessor.h"
+
+using namespace clang::ast_matchers;
+using namespace llvm;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+/// \brief Matches move constructible classes.
+///
+/// Given
+/// \code
+///   // POD types are trivially move constructible
+///   struct Foo { int a; };
+///
+///   struct Bar {
+/// Bar(Bar &&) = deleted;
+/// int a;
+///   };
+/// \endcode
+/// recordDecl(isMoveConstructible())
+///   matches "Foo".
+AST_MATCHER(CXXRecordDecl, isMoveConstructible) {
+  for (const CXXConstructorDecl *Ctor : Node.ctors()) {
+if (Ctor->isMoveConstructor() && !Ctor->isDeleted())
+  return true;
+  }
+  return false;
+}
+
+/// \brief Matches non-deleted copy constructors.
+///
+/// Given
+/// \code
+///   struct Foo { Foo(const Foo &) = default; };
+///   struct Bar { Bar(const Bar &) = deleted; };
+/// \endcode
+/// constructorDecl(isNonDeletedCopyConstructor())
+///   matches "Foo(const Foo &)".
+AST_MATCHER(CXXConstructorDecl, isNonDeletedCopyConstructor) {
+  return Node.isCopyConstructor() && !Node.isDeleted();
+}
+
+static TypeMatcher constRefType() {
+  return lValueReferenceType(pointee(isConstQualified()));
+}
+
+static TypeMatcher nonConstValueType() {
+  return qualType(unless(anyOf(referenceType(), isConstQualified(;
+}
+
+/// \brief \c clang::RecursiveASTVisitor that checks that the given
+/// \c ParmVarDecl is used exactly one time.
+///
+/// \see ExactlyOneUsageVisitor::hasExactlyOneUsageIn()
+class ExactlyOneUsageVisitor
+: public RecursiveASTVisitor {
+  friend class RecursiveASTVisitor;
+
+public:
+  ExactlyOneUsageVisitor(const ParmVarDecl *ParamDecl) : ParamDecl(ParamDecl) {}
+
+  /// \brief Whether or not the parameter variable is referred only once in the
+  /// given constructor.
+  bool hasExactlyOneUsageIn(const CXXConstructorDecl *Ctor) {
+Count = 0;
+TraverseDecl(const_cast(Ctor));
+return Count == 1;
+  }
+
+private:
+  /// \brief Counts the number of references to a variable.
+  ///
+  /// Stops the AST traversal if more than one usage is found.
+  bool VisitDeclRefExpr(DeclRefExpr *D) {
+if (const ParmVarDecl *To = dyn_cast(D->getDecl()))
+  i

Re: [PATCH] D11946: Create clang-tidy module modernize. Add pass-by-value check.

2015-08-12 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 31948.
angelgarcia marked 20 inline comments as done.
angelgarcia added a comment.

Fix tests and minor issues (auto, punctuation, etc).


http://reviews.llvm.org/D11946

Files:
  clang-tidy/CMakeLists.txt
  clang-tidy/Makefile
  clang-tidy/modernize/CMakeLists.txt
  clang-tidy/modernize/Makefile
  clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tidy/modernize/PassByValueCheck.cpp
  clang-tidy/modernize/PassByValueCheck.h
  clang-tidy/tool/CMakeLists.txt
  clang-tidy/tool/ClangTidyMain.cpp
  clang-tidy/tool/Makefile
  test/clang-tidy/modernize-pass-by-value.cpp

Index: test/clang-tidy/modernize-pass-by-value.cpp
===
--- test/clang-tidy/modernize-pass-by-value.cpp
+++ test/clang-tidy/modernize-pass-by-value.cpp
@@ -0,0 +1,197 @@
+// RUN: $(dirname %s)/check_clang_tidy.sh %s modernize-pass-by-value %t
+// REQUIRES: shell
+
+// CHiECK-FIXES: #include 
+
+namespace {
+// POD types are trivially move constructible.
+struct Movable {
+  int a, b, c;
+};
+
+struct NotMovable {
+  NotMovable() = default;
+  NotMovable(const NotMovable &) = default;
+  NotMovable(NotMovable &&) = delete;
+  int a, b, c;
+};
+}
+
+struct A {
+  A(const Movable &M) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move [modernize-pass-by-value]
+  // CHECK-FIXES: A(Movable M) : M(std::move(M)) {}
+  Movable M;
+};
+
+// Test that we aren't modifying other things than a parameter
+Movable GlobalObj;
+struct B {
+  B(const Movable &M) : M(GlobalObj) {}
+  // CHECK-FIXES: B(const Movable &M) : M(GlobalObj) {}
+  Movable M;
+};
+
+// Test that a parameter with more than one reference to it won't be changed.
+struct C {
+  // Tests extra-reference in body
+  C(const Movable &M) : M(M) { this->i = M.a; }
+  // CHECK-FIXES: C(const Movable &M) : M(M) { this->i = M.a; }
+
+  // Tests extra-reference in init-list
+  C(const Movable &M, int) : M(M), i(M.a) {}
+  // CHECK-FIXES: C(const Movable &M, int) : M(M), i(M.a) {}
+  Movable M;
+  int i;
+};
+
+// Test that both declaration and definition are updated
+struct D {
+  D(const Movable &M);
+  // CHECK-FIXES: D(Movable M);
+  Movable M;
+};
+D::D(const Movable &M) : M(M) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: pass by value and use std::move
+// CHECK-FIXES: D::D(Movable M) : M(std::move(M)) {}
+
+// Test with default parameter
+struct E {
+  E(const Movable &M = Movable()) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+  // CHECK-FIXES: E(Movable M = Movable()) : M(std::move(M)) {}
+  Movable M;
+};
+
+// Test with object that can't be moved
+struct F {
+  F(const NotMovable &NM) : NM(NM) {}
+  // CHECK-FIXES: F(const NotMovable &NM) : NM(NM) {}
+  NotMovable NM;
+};
+
+// Test unnamed parameter in declaration
+struct G {
+  G(const Movable &);
+  // CHECK-FIXES: G(Movable );
+  Movable M;
+};
+G::G(const Movable &M) : M(M) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: pass by value and use std::move
+// CHECK-FIXES: G::G(Movable M) : M(std::move(M)) {}
+
+// Test parameter with and without qualifier
+namespace ns_H {
+typedef ::Movable HMovable;
+}
+struct H {
+  H(const ns_H::HMovable &M);
+  // CHECK-FIXES: H(ns_H::HMovable M);
+  ns_H::HMovable M;
+};
+using namespace ns_H;
+H::H(const HMovable &M) : M(M) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: pass by value and use std::move
+// CHECK-FIXES: H(HMovable M) : M(std::move(M)) {}
+
+// Try messing up with macros
+#define MOVABLE_PARAM(Name) const Movable & Name
+// CHECK-FIXES: #define MOVABLE_PARAM(Name) const Movable & Name
+struct I {
+  I(MOVABLE_PARAM(M)) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+  // CHECK-FIXES: I(MOVABLE_PARAM(M)) : M(M) {}
+  Movable M;
+};
+#undef MOVABLE_PARAM
+
+// Test that templates aren't modified
+template  struct J {
+  J(const T &M) : M(M) {}
+  // CHECK-FIXES: J(const T &M) : M(M) {}
+  T M;
+};
+J j1(Movable());
+J j2(NotMovable());
+
+struct K_Movable {
+  K_Movable() = default;
+  K_Movable(const K_Movable &) = default;
+  K_Movable(K_Movable &&o) { dummy = o.dummy; }
+  int dummy;
+};
+
+// Test with movable type with an user defined move constructor.
+struct K {
+  K(const K_Movable &M) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+  // CHECK-FIXES: K(K_Movable M) : M(std::move(M)) {}
+  K_Movable M;
+};
+
+template  struct L {
+  L(const Movable &M) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+  // CHECK-FIXES: L(Movable M) : M(std::move(M)) {}
+  Movable M;
+};
+L l(Movable());
+
+// Test with a non-instantiated template class
+template  struct N {
+  N(const Movable &M) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+  // CHECK-FIXES: N(Movable M) : M(std::move(M)) {}
+
+  Movable M;
+  T A;
+};
+
+// Test with value pa

Re: [PATCH] D11946: Create clang-tidy module modernize. Add pass-by-value check.

2015-08-13 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 32036.
angelgarcia marked 4 inline comments as done.
angelgarcia added a comment.

Set IncludeStyle as an option. Fix comments.


http://reviews.llvm.org/D11946

Files:
  clang-tidy/CMakeLists.txt
  clang-tidy/Makefile
  clang-tidy/modernize/CMakeLists.txt
  clang-tidy/modernize/Makefile
  clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tidy/modernize/PassByValueCheck.cpp
  clang-tidy/modernize/PassByValueCheck.h
  clang-tidy/tool/CMakeLists.txt
  clang-tidy/tool/ClangTidyMain.cpp
  clang-tidy/tool/Makefile
  test/clang-tidy/modernize-pass-by-value.cpp

Index: test/clang-tidy/modernize-pass-by-value.cpp
===
--- test/clang-tidy/modernize-pass-by-value.cpp
+++ test/clang-tidy/modernize-pass-by-value.cpp
@@ -0,0 +1,197 @@
+// RUN: $(dirname %s)/check_clang_tidy.sh %s modernize-pass-by-value %t
+// REQUIRES: shell
+
+// CHECK-FIXES: #include 
+
+namespace {
+// POD types are trivially move constructible.
+struct Movable {
+  int a, b, c;
+};
+
+struct NotMovable {
+  NotMovable() = default;
+  NotMovable(const NotMovable &) = default;
+  NotMovable(NotMovable &&) = delete;
+  int a, b, c;
+};
+}
+
+struct A {
+  A(const Movable &M) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move [modernize-pass-by-value]
+  // CHECK-FIXES: A(Movable M) : M(std::move(M)) {}
+  Movable M;
+};
+
+// Test that we aren't modifying other things than a parameter.
+Movable GlobalObj;
+struct B {
+  B(const Movable &M) : M(GlobalObj) {}
+  // CHECK-FIXES: B(const Movable &M) : M(GlobalObj) {}
+  Movable M;
+};
+
+// Test that a parameter with more than one reference to it won't be changed.
+struct C {
+  // Tests extra-reference in body.
+  C(const Movable &M) : M(M) { this->i = M.a; }
+  // CHECK-FIXES: C(const Movable &M) : M(M) { this->i = M.a; }
+
+  // Tests extra-reference in init-list.
+  C(const Movable &M, int) : M(M), i(M.a) {}
+  // CHECK-FIXES: C(const Movable &M, int) : M(M), i(M.a) {}
+  Movable M;
+  int i;
+};
+
+// Test that both declaration and definition are updated.
+struct D {
+  D(const Movable &M);
+  // CHECK-FIXES: D(Movable M);
+  Movable M;
+};
+D::D(const Movable &M) : M(M) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: pass by value and use std::move
+// CHECK-FIXES: D::D(Movable M) : M(std::move(M)) {}
+
+// Test with default parameter.
+struct E {
+  E(const Movable &M = Movable()) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+  // CHECK-FIXES: E(Movable M = Movable()) : M(std::move(M)) {}
+  Movable M;
+};
+
+// Test with object that can't be moved.
+struct F {
+  F(const NotMovable &NM) : NM(NM) {}
+  // CHECK-FIXES: F(const NotMovable &NM) : NM(NM) {}
+  NotMovable NM;
+};
+
+// Test unnamed parameter in declaration.
+struct G {
+  G(const Movable &);
+  // CHECK-FIXES: G(Movable );
+  Movable M;
+};
+G::G(const Movable &M) : M(M) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: pass by value and use std::move
+// CHECK-FIXES: G::G(Movable M) : M(std::move(M)) {}
+
+// Test parameter with and without qualifier.
+namespace ns_H {
+typedef ::Movable HMovable;
+}
+struct H {
+  H(const ns_H::HMovable &M);
+  // CHECK-FIXES: H(ns_H::HMovable M);
+  ns_H::HMovable M;
+};
+using namespace ns_H;
+H::H(const HMovable &M) : M(M) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: pass by value and use std::move
+// CHECK-FIXES: H(HMovable M) : M(std::move(M)) {}
+
+// Try messing up with macros.
+#define MOVABLE_PARAM(Name) const Movable & Name
+// CHECK-FIXES: #define MOVABLE_PARAM(Name) const Movable & Name
+struct I {
+  I(MOVABLE_PARAM(M)) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+  // CHECK-FIXES: I(MOVABLE_PARAM(M)) : M(M) {}
+  Movable M;
+};
+#undef MOVABLE_PARAM
+
+// Test that templates aren't modified.
+template  struct J {
+  J(const T &M) : M(M) {}
+  // CHECK-FIXES: J(const T &M) : M(M) {}
+  T M;
+};
+J j1(Movable());
+J j2(NotMovable());
+
+struct K_Movable {
+  K_Movable() = default;
+  K_Movable(const K_Movable &) = default;
+  K_Movable(K_Movable &&o) { dummy = o.dummy; }
+  int dummy;
+};
+
+// Test with movable type with an user defined move constructor.
+struct K {
+  K(const K_Movable &M) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+  // CHECK-FIXES: K(K_Movable M) : M(std::move(M)) {}
+  K_Movable M;
+};
+
+template  struct L {
+  L(const Movable &M) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+  // CHECK-FIXES: L(Movable M) : M(std::move(M)) {}
+  Movable M;
+};
+L l(Movable());
+
+// Test with a non-instantiated template class.
+template  struct N {
+  N(const Movable &M) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+  // CHECK-FIXES: N(Movable M) : M(std::move(M)) {}
+
+  Movable M;
+  T A;
+};
+
+// Test with value p

Re: [PATCH] D11946: Create clang-tidy module modernize. Add pass-by-value check.

2015-08-13 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 32055.
angelgarcia marked 3 inline comments as done.
angelgarcia added a comment.

Make IncludeStyle constant, initialize it with StringSwitch. Fix indentation.


http://reviews.llvm.org/D11946

Files:
  clang-tidy/CMakeLists.txt
  clang-tidy/Makefile
  clang-tidy/modernize/CMakeLists.txt
  clang-tidy/modernize/Makefile
  clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tidy/modernize/PassByValueCheck.cpp
  clang-tidy/modernize/PassByValueCheck.h
  clang-tidy/tool/CMakeLists.txt
  clang-tidy/tool/ClangTidyMain.cpp
  clang-tidy/tool/Makefile
  test/clang-tidy/modernize-pass-by-value.cpp

Index: test/clang-tidy/modernize-pass-by-value.cpp
===
--- test/clang-tidy/modernize-pass-by-value.cpp
+++ test/clang-tidy/modernize-pass-by-value.cpp
@@ -0,0 +1,197 @@
+// RUN: $(dirname %s)/check_clang_tidy.sh %s modernize-pass-by-value %t
+// REQUIRES: shell
+
+// CHECK-FIXES: #include 
+
+namespace {
+// POD types are trivially move constructible.
+struct Movable {
+  int a, b, c;
+};
+
+struct NotMovable {
+  NotMovable() = default;
+  NotMovable(const NotMovable &) = default;
+  NotMovable(NotMovable &&) = delete;
+  int a, b, c;
+};
+}
+
+struct A {
+  A(const Movable &M) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move [modernize-pass-by-value]
+  // CHECK-FIXES: A(Movable M) : M(std::move(M)) {}
+  Movable M;
+};
+
+// Test that we aren't modifying other things than a parameter.
+Movable GlobalObj;
+struct B {
+  B(const Movable &M) : M(GlobalObj) {}
+  // CHECK-FIXES: B(const Movable &M) : M(GlobalObj) {}
+  Movable M;
+};
+
+// Test that a parameter with more than one reference to it won't be changed.
+struct C {
+  // Tests extra-reference in body.
+  C(const Movable &M) : M(M) { this->i = M.a; }
+  // CHECK-FIXES: C(const Movable &M) : M(M) { this->i = M.a; }
+
+  // Tests extra-reference in init-list.
+  C(const Movable &M, int) : M(M), i(M.a) {}
+  // CHECK-FIXES: C(const Movable &M, int) : M(M), i(M.a) {}
+  Movable M;
+  int i;
+};
+
+// Test that both declaration and definition are updated.
+struct D {
+  D(const Movable &M);
+  // CHECK-FIXES: D(Movable M);
+  Movable M;
+};
+D::D(const Movable &M) : M(M) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: pass by value and use std::move
+// CHECK-FIXES: D::D(Movable M) : M(std::move(M)) {}
+
+// Test with default parameter.
+struct E {
+  E(const Movable &M = Movable()) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+  // CHECK-FIXES: E(Movable M = Movable()) : M(std::move(M)) {}
+  Movable M;
+};
+
+// Test with object that can't be moved.
+struct F {
+  F(const NotMovable &NM) : NM(NM) {}
+  // CHECK-FIXES: F(const NotMovable &NM) : NM(NM) {}
+  NotMovable NM;
+};
+
+// Test unnamed parameter in declaration.
+struct G {
+  G(const Movable &);
+  // CHECK-FIXES: G(Movable );
+  Movable M;
+};
+G::G(const Movable &M) : M(M) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: pass by value and use std::move
+// CHECK-FIXES: G::G(Movable M) : M(std::move(M)) {}
+
+// Test parameter with and without qualifier.
+namespace ns_H {
+typedef ::Movable HMovable;
+}
+struct H {
+  H(const ns_H::HMovable &M);
+  // CHECK-FIXES: H(ns_H::HMovable M);
+  ns_H::HMovable M;
+};
+using namespace ns_H;
+H::H(const HMovable &M) : M(M) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: pass by value and use std::move
+// CHECK-FIXES: H(HMovable M) : M(std::move(M)) {}
+
+// Try messing up with macros.
+#define MOVABLE_PARAM(Name) const Movable & Name
+// CHECK-FIXES: #define MOVABLE_PARAM(Name) const Movable & Name
+struct I {
+  I(MOVABLE_PARAM(M)) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+  // CHECK-FIXES: I(MOVABLE_PARAM(M)) : M(M) {}
+  Movable M;
+};
+#undef MOVABLE_PARAM
+
+// Test that templates aren't modified.
+template  struct J {
+  J(const T &M) : M(M) {}
+  // CHECK-FIXES: J(const T &M) : M(M) {}
+  T M;
+};
+J j1(Movable());
+J j2(NotMovable());
+
+struct K_Movable {
+  K_Movable() = default;
+  K_Movable(const K_Movable &) = default;
+  K_Movable(K_Movable &&o) { dummy = o.dummy; }
+  int dummy;
+};
+
+// Test with movable type with an user defined move constructor.
+struct K {
+  K(const K_Movable &M) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+  // CHECK-FIXES: K(K_Movable M) : M(std::move(M)) {}
+  K_Movable M;
+};
+
+template  struct L {
+  L(const Movable &M) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+  // CHECK-FIXES: L(Movable M) : M(std::move(M)) {}
+  Movable M;
+};
+L l(Movable());
+
+// Test with a non-instantiated template class.
+template  struct N {
+  N(const Movable &M) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+  // CHECK-FIXES: N(Movable M) : M(std::move(M)) {}
+
+  Movable M;
+ 

Re: [PATCH] D11946: Create clang-tidy module modernize. Add pass-by-value check.

2015-08-13 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 32059.
angelgarcia added a comment.

Remove StringSwitch.


http://reviews.llvm.org/D11946

Files:
  clang-tidy/CMakeLists.txt
  clang-tidy/Makefile
  clang-tidy/modernize/CMakeLists.txt
  clang-tidy/modernize/Makefile
  clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tidy/modernize/PassByValueCheck.cpp
  clang-tidy/modernize/PassByValueCheck.h
  clang-tidy/tool/CMakeLists.txt
  clang-tidy/tool/ClangTidyMain.cpp
  clang-tidy/tool/Makefile
  test/clang-tidy/modernize-pass-by-value.cpp

Index: test/clang-tidy/modernize-pass-by-value.cpp
===
--- test/clang-tidy/modernize-pass-by-value.cpp
+++ test/clang-tidy/modernize-pass-by-value.cpp
@@ -0,0 +1,197 @@
+// RUN: $(dirname %s)/check_clang_tidy.sh %s modernize-pass-by-value %t
+// REQUIRES: shell
+
+// CHECK-FIXES: #include 
+
+namespace {
+// POD types are trivially move constructible.
+struct Movable {
+  int a, b, c;
+};
+
+struct NotMovable {
+  NotMovable() = default;
+  NotMovable(const NotMovable &) = default;
+  NotMovable(NotMovable &&) = delete;
+  int a, b, c;
+};
+}
+
+struct A {
+  A(const Movable &M) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move [modernize-pass-by-value]
+  // CHECK-FIXES: A(Movable M) : M(std::move(M)) {}
+  Movable M;
+};
+
+// Test that we aren't modifying other things than a parameter.
+Movable GlobalObj;
+struct B {
+  B(const Movable &M) : M(GlobalObj) {}
+  // CHECK-FIXES: B(const Movable &M) : M(GlobalObj) {}
+  Movable M;
+};
+
+// Test that a parameter with more than one reference to it won't be changed.
+struct C {
+  // Tests extra-reference in body.
+  C(const Movable &M) : M(M) { this->i = M.a; }
+  // CHECK-FIXES: C(const Movable &M) : M(M) { this->i = M.a; }
+
+  // Tests extra-reference in init-list.
+  C(const Movable &M, int) : M(M), i(M.a) {}
+  // CHECK-FIXES: C(const Movable &M, int) : M(M), i(M.a) {}
+  Movable M;
+  int i;
+};
+
+// Test that both declaration and definition are updated.
+struct D {
+  D(const Movable &M);
+  // CHECK-FIXES: D(Movable M);
+  Movable M;
+};
+D::D(const Movable &M) : M(M) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: pass by value and use std::move
+// CHECK-FIXES: D::D(Movable M) : M(std::move(M)) {}
+
+// Test with default parameter.
+struct E {
+  E(const Movable &M = Movable()) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+  // CHECK-FIXES: E(Movable M = Movable()) : M(std::move(M)) {}
+  Movable M;
+};
+
+// Test with object that can't be moved.
+struct F {
+  F(const NotMovable &NM) : NM(NM) {}
+  // CHECK-FIXES: F(const NotMovable &NM) : NM(NM) {}
+  NotMovable NM;
+};
+
+// Test unnamed parameter in declaration.
+struct G {
+  G(const Movable &);
+  // CHECK-FIXES: G(Movable );
+  Movable M;
+};
+G::G(const Movable &M) : M(M) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: pass by value and use std::move
+// CHECK-FIXES: G::G(Movable M) : M(std::move(M)) {}
+
+// Test parameter with and without qualifier.
+namespace ns_H {
+typedef ::Movable HMovable;
+}
+struct H {
+  H(const ns_H::HMovable &M);
+  // CHECK-FIXES: H(ns_H::HMovable M);
+  ns_H::HMovable M;
+};
+using namespace ns_H;
+H::H(const HMovable &M) : M(M) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: pass by value and use std::move
+// CHECK-FIXES: H(HMovable M) : M(std::move(M)) {}
+
+// Try messing up with macros.
+#define MOVABLE_PARAM(Name) const Movable & Name
+// CHECK-FIXES: #define MOVABLE_PARAM(Name) const Movable & Name
+struct I {
+  I(MOVABLE_PARAM(M)) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+  // CHECK-FIXES: I(MOVABLE_PARAM(M)) : M(M) {}
+  Movable M;
+};
+#undef MOVABLE_PARAM
+
+// Test that templates aren't modified.
+template  struct J {
+  J(const T &M) : M(M) {}
+  // CHECK-FIXES: J(const T &M) : M(M) {}
+  T M;
+};
+J j1(Movable());
+J j2(NotMovable());
+
+struct K_Movable {
+  K_Movable() = default;
+  K_Movable(const K_Movable &) = default;
+  K_Movable(K_Movable &&o) { dummy = o.dummy; }
+  int dummy;
+};
+
+// Test with movable type with an user defined move constructor.
+struct K {
+  K(const K_Movable &M) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+  // CHECK-FIXES: K(K_Movable M) : M(std::move(M)) {}
+  K_Movable M;
+};
+
+template  struct L {
+  L(const Movable &M) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+  // CHECK-FIXES: L(Movable M) : M(std::move(M)) {}
+  Movable M;
+};
+L l(Movable());
+
+// Test with a non-instantiated template class.
+template  struct N {
+  N(const Movable &M) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+  // CHECK-FIXES: N(Movable M) : M(std::move(M)) {}
+
+  Movable M;
+  T A;
+};
+
+// Test with value parameter.
+struct O {
+  O(Movable M) : M(M) {}
+  // CHECK-MESSAGES: 

Re: [PATCH] D11946: Create clang-tidy module modernize. Add pass-by-value check.

2015-08-13 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 32061.
angelgarcia added a comment.

Remove StringSwitch.


http://reviews.llvm.org/D11946

Files:
  clang-tidy/CMakeLists.txt
  clang-tidy/Makefile
  clang-tidy/modernize/CMakeLists.txt
  clang-tidy/modernize/Makefile
  clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tidy/modernize/PassByValueCheck.cpp
  clang-tidy/modernize/PassByValueCheck.h
  clang-tidy/tool/CMakeLists.txt
  clang-tidy/tool/ClangTidyMain.cpp
  clang-tidy/tool/Makefile
  test/clang-tidy/modernize-pass-by-value.cpp

Index: test/clang-tidy/modernize-pass-by-value.cpp
===
--- test/clang-tidy/modernize-pass-by-value.cpp
+++ test/clang-tidy/modernize-pass-by-value.cpp
@@ -0,0 +1,197 @@
+// RUN: $(dirname %s)/check_clang_tidy.sh %s modernize-pass-by-value %t
+// REQUIRES: shell
+
+// CHECK-FIXES: #include 
+
+namespace {
+// POD types are trivially move constructible.
+struct Movable {
+  int a, b, c;
+};
+
+struct NotMovable {
+  NotMovable() = default;
+  NotMovable(const NotMovable &) = default;
+  NotMovable(NotMovable &&) = delete;
+  int a, b, c;
+};
+}
+
+struct A {
+  A(const Movable &M) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move [modernize-pass-by-value]
+  // CHECK-FIXES: A(Movable M) : M(std::move(M)) {}
+  Movable M;
+};
+
+// Test that we aren't modifying other things than a parameter.
+Movable GlobalObj;
+struct B {
+  B(const Movable &M) : M(GlobalObj) {}
+  // CHECK-FIXES: B(const Movable &M) : M(GlobalObj) {}
+  Movable M;
+};
+
+// Test that a parameter with more than one reference to it won't be changed.
+struct C {
+  // Tests extra-reference in body.
+  C(const Movable &M) : M(M) { this->i = M.a; }
+  // CHECK-FIXES: C(const Movable &M) : M(M) { this->i = M.a; }
+
+  // Tests extra-reference in init-list.
+  C(const Movable &M, int) : M(M), i(M.a) {}
+  // CHECK-FIXES: C(const Movable &M, int) : M(M), i(M.a) {}
+  Movable M;
+  int i;
+};
+
+// Test that both declaration and definition are updated.
+struct D {
+  D(const Movable &M);
+  // CHECK-FIXES: D(Movable M);
+  Movable M;
+};
+D::D(const Movable &M) : M(M) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: pass by value and use std::move
+// CHECK-FIXES: D::D(Movable M) : M(std::move(M)) {}
+
+// Test with default parameter.
+struct E {
+  E(const Movable &M = Movable()) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+  // CHECK-FIXES: E(Movable M = Movable()) : M(std::move(M)) {}
+  Movable M;
+};
+
+// Test with object that can't be moved.
+struct F {
+  F(const NotMovable &NM) : NM(NM) {}
+  // CHECK-FIXES: F(const NotMovable &NM) : NM(NM) {}
+  NotMovable NM;
+};
+
+// Test unnamed parameter in declaration.
+struct G {
+  G(const Movable &);
+  // CHECK-FIXES: G(Movable );
+  Movable M;
+};
+G::G(const Movable &M) : M(M) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: pass by value and use std::move
+// CHECK-FIXES: G::G(Movable M) : M(std::move(M)) {}
+
+// Test parameter with and without qualifier.
+namespace ns_H {
+typedef ::Movable HMovable;
+}
+struct H {
+  H(const ns_H::HMovable &M);
+  // CHECK-FIXES: H(ns_H::HMovable M);
+  ns_H::HMovable M;
+};
+using namespace ns_H;
+H::H(const HMovable &M) : M(M) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: pass by value and use std::move
+// CHECK-FIXES: H(HMovable M) : M(std::move(M)) {}
+
+// Try messing up with macros.
+#define MOVABLE_PARAM(Name) const Movable & Name
+// CHECK-FIXES: #define MOVABLE_PARAM(Name) const Movable & Name
+struct I {
+  I(MOVABLE_PARAM(M)) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+  // CHECK-FIXES: I(MOVABLE_PARAM(M)) : M(M) {}
+  Movable M;
+};
+#undef MOVABLE_PARAM
+
+// Test that templates aren't modified.
+template  struct J {
+  J(const T &M) : M(M) {}
+  // CHECK-FIXES: J(const T &M) : M(M) {}
+  T M;
+};
+J j1(Movable());
+J j2(NotMovable());
+
+struct K_Movable {
+  K_Movable() = default;
+  K_Movable(const K_Movable &) = default;
+  K_Movable(K_Movable &&o) { dummy = o.dummy; }
+  int dummy;
+};
+
+// Test with movable type with an user defined move constructor.
+struct K {
+  K(const K_Movable &M) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+  // CHECK-FIXES: K(K_Movable M) : M(std::move(M)) {}
+  K_Movable M;
+};
+
+template  struct L {
+  L(const Movable &M) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+  // CHECK-FIXES: L(Movable M) : M(std::move(M)) {}
+  Movable M;
+};
+L l(Movable());
+
+// Test with a non-instantiated template class.
+template  struct N {
+  N(const Movable &M) : M(M) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+  // CHECK-FIXES: N(Movable M) : M(std::move(M)) {}
+
+  Movable M;
+  T A;
+};
+
+// Test with value parameter.
+struct O {
+  O(Movable M) : M(M) {}
+  // CHECK-MESSAGES: 

[PATCH] D12017: Fix IncludeInserter/IncludeSorter bug.

2015-08-13 Thread Angel Garcia via cfe-commits
angelgarcia created this revision.
angelgarcia added a reviewer: alexfh.
angelgarcia added subscribers: cfe-commits, klimek.
angelgarcia changed the visibility of this Differential Revision from "Public 
(No Login Required)" to "All Users".

If there weren't any includes in the file, or all of them had 'IncludeKind' 
greater than the desired one, then 'CreateIncludeInsertion' didn't work.

http://reviews.llvm.org/D12017

Files:
  clang-tidy/IncludeInserter.cpp
  clang-tidy/IncludeSorter.cpp
  clang-tidy/IncludeSorter.h

Index: clang-tidy/IncludeSorter.h
===
--- clang-tidy/IncludeSorter.h
+++ clang-tidy/IncludeSorter.h
@@ -21,27 +21,23 @@
 // the necessary commands to sort the inclusions according to the precedence
 // enocded in IncludeKinds.
 class IncludeSorter {
- public:
+public:
   // Supported include styles.
-  enum IncludeStyle {
-IS_LLVM = 0,
-IS_Google = 1
-  };
+  enum IncludeStyle { IS_LLVM = 0, IS_Google = 1 };
 
   // The classifications of inclusions, in the order they should be sorted.
   enum IncludeKinds {
-IK_MainTUInclude = 0, // e.g. #include "foo.h" when editing foo.cc
-IK_CSystemInclude = 1,// e.g. #include 
-IK_CXXSystemInclude = 2,  // e.g. #include 
-IK_NonSystemInclude = 3,  // e.g. #include "bar.h"
-IK_InvalidInclude = 4 // total number of valid IncludeKinds
+IK_MainTUInclude = 0,// e.g. #include "foo.h" when editing foo.cc
+IK_CSystemInclude = 1,   // e.g. #include 
+IK_CXXSystemInclude = 2, // e.g. #include 
+IK_NonSystemInclude = 3, // e.g. #include "bar.h"
+IK_InvalidInclude = 4// total number of valid IncludeKinds
   };
 
   // IncludeSorter constructor; takes the FileID and name of the file to be
   // processed by the sorter.
-  IncludeSorter(const SourceManager* SourceMgr,
-const LangOptions* LangOpts, const FileID FileID,
-StringRef FileName, IncludeStyle Style);
+  IncludeSorter(const SourceManager *SourceMgr, const LangOptions *LangOpts,
+const FileID FileID, StringRef FileName, IncludeStyle Style);
 
   // Returns the SourceManager-specific file ID for the file being handled by
   // the sorter.
@@ -58,18 +54,17 @@
 
   // Creates a quoted inclusion directive in the right sort order. Returns None
   // on error or if header inclusion directive for header already exists.
-  Optional CreateIncludeInsertion(StringRef FileName,
- bool IsAngled);
+  Optional CreateIncludeInsertion(StringRef FileName, bool IsAngled);
 
- private:
+private:
   typedef SmallVector SourceRangeVector;
 
   // Creates a fix-it for the given replacements.
   // Takes the the source location that will be replaced, and the new text.
-  FixItHint CreateFixIt(SourceRange EditRange, const std::string& NewText);
+  FixItHint CreateFixIt(SourceRange EditRange, const std::string &NewText);
 
-  const SourceManager* SourceMgr;
-  const LangOptions* LangOpts;
+  const SourceManager *SourceMgr;
+  const LangOptions *LangOpts;
   const IncludeStyle Style;
   FileID CurrentFileID;
   // The file name stripped of common suffixes.
@@ -82,6 +77,6 @@
   SmallVector IncludeBucket[IK_InvalidInclude];
 };
 
-}  // namespace tidy
-}  // namespace clang
+} // namespace tidy
+} // namespace clang
 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_INCLUDESORTER_H
Index: clang-tidy/IncludeSorter.cpp
===
--- clang-tidy/IncludeSorter.cpp
+++ clang-tidy/IncludeSorter.cpp
@@ -111,14 +111,18 @@
 
 Optional IncludeSorter::CreateIncludeInsertion(StringRef FileName,
   bool IsAngled) {
-  if (SourceLocations.empty()) {
-return None;
-  }
   std::string IncludeStmt =
   IsAngled ? llvm::Twine("#include <" + FileName + ">\n").str()
: llvm::Twine("#include \"" + FileName + "\"\n").str();
+  if (SourceLocations.empty()) {
+// If there are no includes in this file, add it in the first line.
+return FixItHint::CreateInsertion(
+SourceMgr->getLocForStartOfFile(CurrentFileID), IncludeStmt);
+  }
+
   auto IncludeKind =
   DetermineIncludeKind(CanonicalFile, FileName, IsAngled, Style);
+
   if (!IncludeBucket[IncludeKind].empty()) {
 for (const std::string &IncludeEntry : IncludeBucket[IncludeKind]) {
   if (FileName < IncludeEntry) {
@@ -136,7 +140,7 @@
   IncludeStmt);
   }
   IncludeKinds NonEmptyKind = IK_InvalidInclude;
-  for (int i = IncludeKind - 1; i >= 0; --i) {
+  for (int i = IK_InvalidInclude - 1; i >= 0; --i) {
 if (!IncludeBucket[i].empty()) {
   NonEmptyKind = static_cast(i);
   break;
@@ -147,9 +151,8 @@
   }
   const std::string &LastInclude = IncludeBucket[NonEmptyKind].back();
   SourceRange LastIncludeLocation = IncludeLocations[LastInclude].back();
-  IncludeStmt.append("\n");
-  retur

Re: [PATCH] D12017: Fix IncludeInserter/IncludeSorter bug.

2015-08-14 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 32143.
angelgarcia added a comment.

Update tests.


http://reviews.llvm.org/D12017

Files:
  clang-tidy/IncludeInserter.cpp
  clang-tidy/IncludeSorter.cpp
  clang-tidy/IncludeSorter.h
  unittests/clang-tidy/IncludeInserterTest.cpp

Index: unittests/clang-tidy/IncludeInserterTest.cpp
===
--- unittests/clang-tidy/IncludeInserterTest.cpp
+++ unittests/clang-tidy/IncludeInserterTest.cpp
@@ -59,6 +59,13 @@
   bool IsAngledInclude() const override { return false; }
 };
 
+class CSystemIncludeInserterCheck : public IncludeInserterCheckBase {
+public:
+  using IncludeInserterCheckBase::IncludeInserterCheckBase;
+  StringRef HeaderToInclude() const override { return "stdlib.h"; }
+  bool IsAngledInclude() const override { return true; }
+};
+
 class CXXSystemIncludeInserterCheck : public IncludeInserterCheckBase {
 public:
   using IncludeInserterCheckBase::IncludeInserterCheckBase;
@@ -402,6 +409,72 @@
   1));
 }
 
+TEST(IncludeInserterTest, InsertCXXSystemIncludeBeforeNonSystemInclude) {
+  const char *PreCode = R"(
+#include "path/to/a/header.h"
+
+void foo() {
+  int a = 0;
+})";
+  const char *PostCode = R"(
+#include 
+
+#include "path/to/a/header.h"
+
+void foo() {
+  int a = 0;
+})";
+
+  EXPECT_EQ(PostCode, runCheckOnCode(
+  PreCode, "devtools/cymbal/clang_tidy/tests/"
+   "insert_includes_test_header.cc",
+  1));
+}
+
+TEST(IncludeInserterTest, InsertCSystemIncludeBeforeCXXSystemInclude) {
+  const char *PreCode = R"(
+#include 
+
+#include "path/to/a/header.h"
+
+void foo() {
+  int a = 0;
+})";
+  const char *PostCode = R"(
+#include 
+
+#include 
+
+#include "path/to/a/header.h"
+
+void foo() {
+  int a = 0;
+})";
+
+  EXPECT_EQ(PostCode, runCheckOnCode(
+  PreCode, "devtools/cymbal/clang_tidy/tests/"
+   "insert_includes_test_header.cc",
+  1));
+}
+
+TEST(IncludeInserterTest, InsertIncludeIfThereWasNoneBefore) {
+  const char *PreCode = R"(
+void foo() {
+  int a = 0;
+})";
+  const char *PostCode = R"(#include 
+
+
+void foo() {
+  int a = 0;
+})";
+
+  EXPECT_EQ(PostCode, runCheckOnCode(
+  PreCode, "devtools/cymbal/clang_tidy/tests/"
+   "insert_includes_test_header.cc",
+  1));
+}
+
 } // namespace
 } // namespace tidy
 } // namespace clang
Index: clang-tidy/IncludeSorter.h
===
--- clang-tidy/IncludeSorter.h
+++ clang-tidy/IncludeSorter.h
@@ -21,27 +21,23 @@
 // the necessary commands to sort the inclusions according to the precedence
 // enocded in IncludeKinds.
 class IncludeSorter {
- public:
+public:
   // Supported include styles.
-  enum IncludeStyle {
-IS_LLVM = 0,
-IS_Google = 1
-  };
+  enum IncludeStyle { IS_LLVM = 0, IS_Google = 1 };
 
   // The classifications of inclusions, in the order they should be sorted.
   enum IncludeKinds {
-IK_MainTUInclude = 0, // e.g. #include "foo.h" when editing foo.cc
-IK_CSystemInclude = 1,// e.g. #include 
-IK_CXXSystemInclude = 2,  // e.g. #include 
-IK_NonSystemInclude = 3,  // e.g. #include "bar.h"
-IK_InvalidInclude = 4 // total number of valid IncludeKinds
+IK_MainTUInclude = 0,// e.g. #include "foo.h" when editing foo.cc
+IK_CSystemInclude = 1,   // e.g. #include 
+IK_CXXSystemInclude = 2, // e.g. #include 
+IK_NonSystemInclude = 3, // e.g. #include "bar.h"
+IK_InvalidInclude = 4// total number of valid IncludeKinds
   };
 
   // IncludeSorter constructor; takes the FileID and name of the file to be
   // processed by the sorter.
-  IncludeSorter(const SourceManager* SourceMgr,
-const LangOptions* LangOpts, const FileID FileID,
-StringRef FileName, IncludeStyle Style);
+  IncludeSorter(const SourceManager *SourceMgr, const LangOptions *LangOpts,
+const FileID FileID, StringRef FileName, IncludeStyle Style);
 
   // Returns the SourceManager-specific file ID for the file being handled by
   // the sorter.
@@ -58,18 +54,17 @@
 
   // Creates a quoted inclusion directive in the right sort order. Returns None
   // on error or if header inclusion directive for header already exists.
-  Optional CreateIncludeInsertion(StringRef FileName,
- bool IsAngled);
+  Optional CreateIncludeInsertion(StringRef FileName, bool IsAngled);
 
- private:
+private:
   typedef SmallVector SourceRangeVector;
 
   // Creates a fix-it for the given replacements.
   // Takes the the source location that will be replaced, and the new text.
-  FixItHint CreateFixIt(SourceRange EditRange, const std::string& NewText);
+  FixItHint CreateFixIt(SourceRange EditRange, const std::string &NewText)

Re: [PATCH] D12017: Fix IncludeInserter/IncludeSorter bug.

2015-08-14 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 32146.
angelgarcia added a comment.

Add comments.


http://reviews.llvm.org/D12017

Files:
  clang-tidy/IncludeInserter.cpp
  clang-tidy/IncludeSorter.cpp
  clang-tidy/IncludeSorter.h
  unittests/clang-tidy/IncludeInserterTest.cpp

Index: unittests/clang-tidy/IncludeInserterTest.cpp
===
--- unittests/clang-tidy/IncludeInserterTest.cpp
+++ unittests/clang-tidy/IncludeInserterTest.cpp
@@ -59,6 +59,13 @@
   bool IsAngledInclude() const override { return false; }
 };
 
+class CSystemIncludeInserterCheck : public IncludeInserterCheckBase {
+public:
+  using IncludeInserterCheckBase::IncludeInserterCheckBase;
+  StringRef HeaderToInclude() const override { return "stdlib.h"; }
+  bool IsAngledInclude() const override { return true; }
+};
+
 class CXXSystemIncludeInserterCheck : public IncludeInserterCheckBase {
 public:
   using IncludeInserterCheckBase::IncludeInserterCheckBase;
@@ -402,6 +409,72 @@
   1));
 }
 
+TEST(IncludeInserterTest, InsertCXXSystemIncludeBeforeNonSystemInclude) {
+  const char *PreCode = R"(
+#include "path/to/a/header.h"
+
+void foo() {
+  int a = 0;
+})";
+  const char *PostCode = R"(
+#include 
+
+#include "path/to/a/header.h"
+
+void foo() {
+  int a = 0;
+})";
+
+  EXPECT_EQ(PostCode, runCheckOnCode(
+  PreCode, "devtools/cymbal/clang_tidy/tests/"
+   "insert_includes_test_header.cc",
+  1));
+}
+
+TEST(IncludeInserterTest, InsertCSystemIncludeBeforeCXXSystemInclude) {
+  const char *PreCode = R"(
+#include 
+
+#include "path/to/a/header.h"
+
+void foo() {
+  int a = 0;
+})";
+  const char *PostCode = R"(
+#include 
+
+#include 
+
+#include "path/to/a/header.h"
+
+void foo() {
+  int a = 0;
+})";
+
+  EXPECT_EQ(PostCode, runCheckOnCode(
+  PreCode, "devtools/cymbal/clang_tidy/tests/"
+   "insert_includes_test_header.cc",
+  1));
+}
+
+TEST(IncludeInserterTest, InsertIncludeIfThereWasNoneBefore) {
+  const char *PreCode = R"(
+void foo() {
+  int a = 0;
+})";
+  const char *PostCode = R"(#include 
+
+
+void foo() {
+  int a = 0;
+})";
+
+  EXPECT_EQ(PostCode, runCheckOnCode(
+  PreCode, "devtools/cymbal/clang_tidy/tests/"
+   "insert_includes_test_header.cc",
+  1));
+}
+
 } // namespace
 } // namespace tidy
 } // namespace clang
Index: clang-tidy/IncludeSorter.h
===
--- clang-tidy/IncludeSorter.h
+++ clang-tidy/IncludeSorter.h
@@ -21,27 +21,23 @@
 // the necessary commands to sort the inclusions according to the precedence
 // enocded in IncludeKinds.
 class IncludeSorter {
- public:
+public:
   // Supported include styles.
-  enum IncludeStyle {
-IS_LLVM = 0,
-IS_Google = 1
-  };
+  enum IncludeStyle { IS_LLVM = 0, IS_Google = 1 };
 
   // The classifications of inclusions, in the order they should be sorted.
   enum IncludeKinds {
-IK_MainTUInclude = 0, // e.g. #include "foo.h" when editing foo.cc
-IK_CSystemInclude = 1,// e.g. #include 
-IK_CXXSystemInclude = 2,  // e.g. #include 
-IK_NonSystemInclude = 3,  // e.g. #include "bar.h"
-IK_InvalidInclude = 4 // total number of valid IncludeKinds
+IK_MainTUInclude = 0,// e.g. #include "foo.h" when editing foo.cc
+IK_CSystemInclude = 1,   // e.g. #include 
+IK_CXXSystemInclude = 2, // e.g. #include 
+IK_NonSystemInclude = 3, // e.g. #include "bar.h"
+IK_InvalidInclude = 4// total number of valid IncludeKinds
   };
 
   // IncludeSorter constructor; takes the FileID and name of the file to be
   // processed by the sorter.
-  IncludeSorter(const SourceManager* SourceMgr,
-const LangOptions* LangOpts, const FileID FileID,
-StringRef FileName, IncludeStyle Style);
+  IncludeSorter(const SourceManager *SourceMgr, const LangOptions *LangOpts,
+const FileID FileID, StringRef FileName, IncludeStyle Style);
 
   // Returns the SourceManager-specific file ID for the file being handled by
   // the sorter.
@@ -58,18 +54,17 @@
 
   // Creates a quoted inclusion directive in the right sort order. Returns None
   // on error or if header inclusion directive for header already exists.
-  Optional CreateIncludeInsertion(StringRef FileName,
- bool IsAngled);
+  Optional CreateIncludeInsertion(StringRef FileName, bool IsAngled);
 
- private:
+private:
   typedef SmallVector SourceRangeVector;
 
   // Creates a fix-it for the given replacements.
   // Takes the the source location that will be replaced, and the new text.
-  FixItHint CreateFixIt(SourceRange EditRange, const std::string& NewText);
+  FixItHint CreateFixIt(SourceRange EditRange, const std::string &NewText)

[PATCH] D12081: Add use-nullptr check to clang-tidy.

2015-08-17 Thread Angel Garcia via cfe-commits
angelgarcia created this revision.
angelgarcia added a reviewer: alexfh.
angelgarcia added subscribers: klimek, cfe-commits.
angelgarcia changed the visibility of this Differential Revision from "Public 
(No Login Required)" to "All Users".

Move UseNullptr from clang-modernize to modernize module in clang-tidy.

http://reviews.llvm.org/D12081

Files:
  clang-tidy/modernize/CMakeLists.txt
  clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tidy/modernize/UseNullptrCheck.cpp
  clang-tidy/modernize/UseNullptrCheck.h
  test/clang-tidy/modernize-use-nullptr-basic.cpp
  test/clang-tidy/modernize-use-nullptr.cpp

Index: test/clang-tidy/modernize-use-nullptr.cpp
===
--- test/clang-tidy/modernize-use-nullptr.cpp
+++ test/clang-tidy/modernize-use-nullptr.cpp
@@ -0,0 +1,179 @@
+// RUN: $(dirname %s)/check_clang_tidy.sh %s modernize-use-nullptr %t \
+// -config="{CheckOptions: [{key: modernize-use-nullptr.UserNullMacros, value: 'MY_NULL'}]}" \
+// -- -std=c++11
+
+// REQUIRES: shell
+
+#define NULL 0
+
+namespace std {
+
+typedef decltype(nullptr) nullptr_t;
+
+} // namespace std
+
+// Just to make sure make_null() could have side effects.
+void external();
+
+std::nullptr_t make_null() {
+  external();
+  return nullptr;
+}
+
+void func() {
+  void *CallTest = make_null();
+
+  int var = 1;
+  void *CommaTest = (var+=2, make_null());
+
+  int *CastTest = static_cast(make_null());
+}
+
+void dummy(int*) {}
+void side_effect() {}
+
+#define MACRO_EXPANSION_HAS_NULL \
+  void foo() { \
+dummy(0); \
+dummy(NULL); \
+side_effect(); \
+  }
+
+MACRO_EXPANSION_HAS_NULL;
+#undef MACRO_EXPANSION_HAS_NULL
+
+
+void test_macro_expansion1() {
+#define MACRO_EXPANSION_HAS_NULL \
+  dummy(NULL); \
+  side_effect();
+
+  MACRO_EXPANSION_HAS_NULL;
+
+#undef MACRO_EXPANSION_HAS_NULL
+}
+
+// Test macro expansion with cast sequence, PR15572.
+void test_macro_expansion2() {
+#define MACRO_EXPANSION_HAS_NULL \
+  dummy((int*)0); \
+  side_effect();
+
+  MACRO_EXPANSION_HAS_NULL;
+
+#undef MACRO_EXPANSION_HAS_NULL
+}
+
+void test_macro_expansion3() {
+#define MACRO_EXPANSION_HAS_NULL \
+  dummy(NULL); \
+  side_effect();
+
+#define OUTER_MACRO \
+  MACRO_EXPANSION_HAS_NULL; \
+  side_effect();
+
+  OUTER_MACRO;
+
+#undef OUTER_MACRO
+#undef MACRO_EXPANSION_HAS_NULL
+}
+
+void test_macro_expansion4() {
+#define MY_NULL NULL
+  int *p = MY_NULL;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr [modernize-use-nullptr]
+  // CHECK-FIXES: int *p = nullptr;
+#undef MY_NULL
+}
+
+#define IS_EQ(x, y) if (x != y) return;
+void test_macro_args() {
+  int i = 0;
+  int *Ptr;
+
+  IS_EQ(static_cast(0), Ptr);
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use nullptr
+  // CHECK-FIXES: IS_EQ(static_cast(nullptr), Ptr);
+
+  IS_EQ(0, Ptr);// literal
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr
+  // CHECK-FIXES: IS_EQ(nullptr, Ptr);
+
+  IS_EQ(NULL, Ptr); // macro
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr
+  // CHECK-FIXES: IS_EQ(nullptr, Ptr);
+
+  // These are ok since the null literal is not spelled within a macro.
+#define myassert(x) if (!(x)) return;
+  myassert(0 == Ptr);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr
+  // CHECK-FIXES: myassert(nullptr == Ptr);
+
+  myassert(NULL == Ptr);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr
+  // CHECK-FIXES: myassert(nullptr == Ptr);
+
+  // These are bad as the null literal is buried in a macro.
+#define BLAH(X) myassert(0 == (X));
+#define BLAH2(X) myassert(NULL == (X));
+  BLAH(Ptr);
+  BLAH2(Ptr);
+
+  // Same as above but testing extra macro expansion.
+#define EXPECT_NULL(X) IS_EQ(0, X);
+#define EXPECT_NULL2(X) IS_EQ(NULL, X);
+  EXPECT_NULL(Ptr);
+  EXPECT_NULL2(Ptr);
+
+  // Almost the same as above but now null literal is not in a macro so ok
+  // to transform.
+#define EQUALS_PTR(X) IS_EQ(X, Ptr);
+  EQUALS_PTR(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use nullptr
+  // CHECK-FIXES: EQUALS_PTR(nullptr);
+  EQUALS_PTR(NULL);
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use nullptr
+  // CHECK-FIXES: EQUALS_PTR(nullptr);
+
+  // Same as above but testing extra macro expansion.
+#define EQUALS_PTR_I(X) EQUALS_PTR(X)
+  EQUALS_PTR_I(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr
+  // CHECK-FIXES: EQUALS_PTR_I(nullptr);
+  EQUALS_PTR_I(NULL);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr
+  // CHECK-FIXES: EQUALS_PTR_I(nullptr);
+
+  // Ok since null literal not within macro. However, now testing macro
+  // used as arg to another macro.
+#define decorate(EXPR) side_effect(); EXPR;
+  decorate(IS_EQ(NULL, Ptr));
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr
+  // CHECK-FIXES: decorate(IS_EQ(nullptr, Ptr));
+  decorate(IS_EQ(0, Ptr));
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr
+  // CHECK-FIXES: decorate(IS_EQ(nullptr, Ptr));
+
+  // This macro causes a NullToPointer c

Re: [PATCH] D12081: Add use-nullptr check to clang-tidy.

2015-08-17 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 32303.
angelgarcia added a comment.

Previous diff was not the newest one.


http://reviews.llvm.org/D12081

Files:
  clang-tidy/modernize/CMakeLists.txt
  clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tidy/modernize/UseNullptrCheck.cpp
  clang-tidy/modernize/UseNullptrCheck.h
  test/clang-tidy/modernize-use-nullptr-basic.cpp
  test/clang-tidy/modernize-use-nullptr.cpp

Index: test/clang-tidy/modernize-use-nullptr.cpp
===
--- test/clang-tidy/modernize-use-nullptr.cpp
+++ test/clang-tidy/modernize-use-nullptr.cpp
@@ -0,0 +1,179 @@
+// RUN: $(dirname %s)/check_clang_tidy.sh %s modernize-use-nullptr %t \
+// -config="{CheckOptions: [{key: modernize-use-nullptr.UserNullMacros, value: 'MY_NULL'}]}" \
+// -- -std=c++11
+
+// REQUIRES: shell
+
+#define NULL 0
+
+namespace std {
+
+typedef decltype(nullptr) nullptr_t;
+
+} // namespace std
+
+// Just to make sure make_null() could have side effects.
+void external();
+
+std::nullptr_t make_null() {
+  external();
+  return nullptr;
+}
+
+void func() {
+  void *CallTest = make_null();
+
+  int var = 1;
+  void *CommaTest = (var+=2, make_null());
+
+  int *CastTest = static_cast(make_null());
+}
+
+void dummy(int*) {}
+void side_effect() {}
+
+#define MACRO_EXPANSION_HAS_NULL \
+  void foo() { \
+dummy(0); \
+dummy(NULL); \
+side_effect(); \
+  }
+
+MACRO_EXPANSION_HAS_NULL;
+#undef MACRO_EXPANSION_HAS_NULL
+
+
+void test_macro_expansion1() {
+#define MACRO_EXPANSION_HAS_NULL \
+  dummy(NULL); \
+  side_effect();
+
+  MACRO_EXPANSION_HAS_NULL;
+
+#undef MACRO_EXPANSION_HAS_NULL
+}
+
+// Test macro expansion with cast sequence, PR15572.
+void test_macro_expansion2() {
+#define MACRO_EXPANSION_HAS_NULL \
+  dummy((int*)0); \
+  side_effect();
+
+  MACRO_EXPANSION_HAS_NULL;
+
+#undef MACRO_EXPANSION_HAS_NULL
+}
+
+void test_macro_expansion3() {
+#define MACRO_EXPANSION_HAS_NULL \
+  dummy(NULL); \
+  side_effect();
+
+#define OUTER_MACRO \
+  MACRO_EXPANSION_HAS_NULL; \
+  side_effect();
+
+  OUTER_MACRO;
+
+#undef OUTER_MACRO
+#undef MACRO_EXPANSION_HAS_NULL
+}
+
+void test_macro_expansion4() {
+#define MY_NULL NULL
+  int *p = MY_NULL;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr [modernize-use-nullptr]
+  // CHECK-FIXES: int *p = nullptr;
+#undef MY_NULL
+}
+
+#define IS_EQ(x, y) if (x != y) return;
+void test_macro_args() {
+  int i = 0;
+  int *Ptr;
+
+  IS_EQ(static_cast(0), Ptr);
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use nullptr
+  // CHECK-FIXES: IS_EQ(static_cast(nullptr), Ptr);
+
+  IS_EQ(0, Ptr);// literal
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr
+  // CHECK-FIXES: IS_EQ(nullptr, Ptr);
+
+  IS_EQ(NULL, Ptr); // macro
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr
+  // CHECK-FIXES: IS_EQ(nullptr, Ptr);
+
+  // These are ok since the null literal is not spelled within a macro.
+#define myassert(x) if (!(x)) return;
+  myassert(0 == Ptr);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr
+  // CHECK-FIXES: myassert(nullptr == Ptr);
+
+  myassert(NULL == Ptr);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr
+  // CHECK-FIXES: myassert(nullptr == Ptr);
+
+  // These are bad as the null literal is buried in a macro.
+#define BLAH(X) myassert(0 == (X));
+#define BLAH2(X) myassert(NULL == (X));
+  BLAH(Ptr);
+  BLAH2(Ptr);
+
+  // Same as above but testing extra macro expansion.
+#define EXPECT_NULL(X) IS_EQ(0, X);
+#define EXPECT_NULL2(X) IS_EQ(NULL, X);
+  EXPECT_NULL(Ptr);
+  EXPECT_NULL2(Ptr);
+
+  // Almost the same as above but now null literal is not in a macro so ok
+  // to transform.
+#define EQUALS_PTR(X) IS_EQ(X, Ptr);
+  EQUALS_PTR(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use nullptr
+  // CHECK-FIXES: EQUALS_PTR(nullptr);
+  EQUALS_PTR(NULL);
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use nullptr
+  // CHECK-FIXES: EQUALS_PTR(nullptr);
+
+  // Same as above but testing extra macro expansion.
+#define EQUALS_PTR_I(X) EQUALS_PTR(X)
+  EQUALS_PTR_I(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr
+  // CHECK-FIXES: EQUALS_PTR_I(nullptr);
+  EQUALS_PTR_I(NULL);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr
+  // CHECK-FIXES: EQUALS_PTR_I(nullptr);
+
+  // Ok since null literal not within macro. However, now testing macro
+  // used as arg to another macro.
+#define decorate(EXPR) side_effect(); EXPR;
+  decorate(IS_EQ(NULL, Ptr));
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr
+  // CHECK-FIXES: decorate(IS_EQ(nullptr, Ptr));
+  decorate(IS_EQ(0, Ptr));
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr
+  // CHECK-FIXES: decorate(IS_EQ(nullptr, Ptr));
+
+  // This macro causes a NullToPointer cast to happen where 0 is assigned to z
+  // but the 0 literal cannot be replaced because it is also used as an
+  // integer in the comparison.
+#define INT_AND_PTR_USE(X) do { int *z = X; if (X 

Re: [PATCH] D12081: Add use-nullptr check to clang-tidy.

2015-08-17 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 32311.
angelgarcia marked 9 inline comments as done.
angelgarcia added a comment.

Comments fixed.


http://reviews.llvm.org/D12081

Files:
  clang-tidy/modernize/CMakeLists.txt
  clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tidy/modernize/UseNullptrCheck.cpp
  clang-tidy/modernize/UseNullptrCheck.h
  test/clang-tidy/modernize-use-nullptr-basic.cpp
  test/clang-tidy/modernize-use-nullptr.cpp

Index: test/clang-tidy/modernize-use-nullptr.cpp
===
--- test/clang-tidy/modernize-use-nullptr.cpp
+++ test/clang-tidy/modernize-use-nullptr.cpp
@@ -0,0 +1,179 @@
+// RUN:   $(dirname %s)/check_clang_tidy.sh %s modernize-use-nullptr %t \
+// RUN:   -config="{CheckOptions: [{key: modernize-use-nullptr.UserNullMacros, value: 'MY_NULL'}]}" \
+// RUN:   -- -std=c++11
+
+// REQUIRES: shell
+
+#define NULL 0
+
+namespace std {
+
+typedef decltype(nullptr) nullptr_t;
+
+} // namespace std
+
+// Just to make sure make_null() could have side effects.
+void external();
+
+std::nullptr_t make_null() {
+  external();
+  return nullptr;
+}
+
+void func() {
+  void *CallTest = make_null();
+
+  int var = 1;
+  void *CommaTest = (var+=2, make_null());
+
+  int *CastTest = static_cast(make_null());
+}
+
+void dummy(int*) {}
+void side_effect() {}
+
+#define MACRO_EXPANSION_HAS_NULL \
+  void foo() { \
+dummy(0); \
+dummy(NULL); \
+side_effect(); \
+  }
+
+MACRO_EXPANSION_HAS_NULL;
+#undef MACRO_EXPANSION_HAS_NULL
+
+
+void test_macro_expansion1() {
+#define MACRO_EXPANSION_HAS_NULL \
+  dummy(NULL); \
+  side_effect();
+
+  MACRO_EXPANSION_HAS_NULL;
+
+#undef MACRO_EXPANSION_HAS_NULL
+}
+
+// Test macro expansion with cast sequence, PR15572.
+void test_macro_expansion2() {
+#define MACRO_EXPANSION_HAS_NULL \
+  dummy((int*)0); \
+  side_effect();
+
+  MACRO_EXPANSION_HAS_NULL;
+
+#undef MACRO_EXPANSION_HAS_NULL
+}
+
+void test_macro_expansion3() {
+#define MACRO_EXPANSION_HAS_NULL \
+  dummy(NULL); \
+  side_effect();
+
+#define OUTER_MACRO \
+  MACRO_EXPANSION_HAS_NULL; \
+  side_effect();
+
+  OUTER_MACRO;
+
+#undef OUTER_MACRO
+#undef MACRO_EXPANSION_HAS_NULL
+}
+
+void test_macro_expansion4() {
+#define MY_NULL NULL
+  int *p = MY_NULL;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr [modernize-use-nullptr]
+  // CHECK-FIXES: int *p = nullptr;
+#undef MY_NULL
+}
+
+#define IS_EQ(x, y) if (x != y) return;
+void test_macro_args() {
+  int i = 0;
+  int *Ptr;
+
+  IS_EQ(static_cast(0), Ptr);
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use nullptr
+  // CHECK-FIXES: IS_EQ(static_cast(nullptr), Ptr);
+
+  IS_EQ(0, Ptr);// literal
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr
+  // CHECK-FIXES: IS_EQ(nullptr, Ptr);
+
+  IS_EQ(NULL, Ptr); // macro
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr
+  // CHECK-FIXES: IS_EQ(nullptr, Ptr);
+
+  // These are ok since the null literal is not spelled within a macro.
+#define myassert(x) if (!(x)) return;
+  myassert(0 == Ptr);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr
+  // CHECK-FIXES: myassert(nullptr == Ptr);
+
+  myassert(NULL == Ptr);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr
+  // CHECK-FIXES: myassert(nullptr == Ptr);
+
+  // These are bad as the null literal is buried in a macro.
+#define BLAH(X) myassert(0 == (X));
+#define BLAH2(X) myassert(NULL == (X));
+  BLAH(Ptr);
+  BLAH2(Ptr);
+
+  // Same as above but testing extra macro expansion.
+#define EXPECT_NULL(X) IS_EQ(0, X);
+#define EXPECT_NULL2(X) IS_EQ(NULL, X);
+  EXPECT_NULL(Ptr);
+  EXPECT_NULL2(Ptr);
+
+  // Almost the same as above but now null literal is not in a macro so ok
+  // to transform.
+#define EQUALS_PTR(X) IS_EQ(X, Ptr);
+  EQUALS_PTR(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use nullptr
+  // CHECK-FIXES: EQUALS_PTR(nullptr);
+  EQUALS_PTR(NULL);
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use nullptr
+  // CHECK-FIXES: EQUALS_PTR(nullptr);
+
+  // Same as above but testing extra macro expansion.
+#define EQUALS_PTR_I(X) EQUALS_PTR(X)
+  EQUALS_PTR_I(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr
+  // CHECK-FIXES: EQUALS_PTR_I(nullptr);
+  EQUALS_PTR_I(NULL);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr
+  // CHECK-FIXES: EQUALS_PTR_I(nullptr);
+
+  // Ok since null literal not within macro. However, now testing macro
+  // used as arg to another macro.
+#define decorate(EXPR) side_effect(); EXPR;
+  decorate(IS_EQ(NULL, Ptr));
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr
+  // CHECK-FIXES: decorate(IS_EQ(nullptr, Ptr));
+  decorate(IS_EQ(0, Ptr));
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr
+  // CHECK-FIXES: decorate(IS_EQ(nullptr, Ptr));
+
+  // This macro causes a NullToPointer cast to happen where 0 is assigned to z
+  // but the 0 literal cannot be replaced because it is also used as an
+  // integer in the comparison.
+#define IN

Re: [PATCH] D12081: Add use-nullptr check to clang-tidy.

2015-08-19 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 32539.
angelgarcia marked 13 inline comments as done.
angelgarcia added a comment.

Fix comments.


http://reviews.llvm.org/D12081

Files:
  clang-tidy/modernize/CMakeLists.txt
  clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tidy/modernize/UseNullptrCheck.cpp
  clang-tidy/modernize/UseNullptrCheck.h
  test/clang-tidy/modernize-use-nullptr-basic.cpp
  test/clang-tidy/modernize-use-nullptr.cpp

Index: test/clang-tidy/modernize-use-nullptr.cpp
===
--- test/clang-tidy/modernize-use-nullptr.cpp
+++ test/clang-tidy/modernize-use-nullptr.cpp
@@ -0,0 +1,178 @@
+// RUN: $(dirname %s)/check_clang_tidy.sh %s modernize-use-nullptr %t \
+// RUN:   -config="{CheckOptions: [{key: modernize-use-nullptr.UserNullMacros, value: 'MY_NULL'}]}" \
+// RUN:   -- -std=c++11
+// REQUIRES: shell
+
+#define NULL 0
+
+namespace std {
+
+typedef decltype(nullptr) nullptr_t;
+
+} // namespace std
+
+// Just to make sure make_null() could have side effects.
+void external();
+
+std::nullptr_t make_null() {
+  external();
+  return nullptr;
+}
+
+void func() {
+  void *CallTest = make_null();
+
+  int var = 1;
+  void *CommaTest = (var+=2, make_null());
+
+  int *CastTest = static_cast(make_null());
+}
+
+void dummy(int*) {}
+void side_effect() {}
+
+#define MACRO_EXPANSION_HAS_NULL \
+  void foo() { \
+dummy(0); \
+dummy(NULL); \
+side_effect(); \
+  }
+
+MACRO_EXPANSION_HAS_NULL;
+#undef MACRO_EXPANSION_HAS_NULL
+
+
+void test_macro_expansion1() {
+#define MACRO_EXPANSION_HAS_NULL \
+  dummy(NULL); \
+  side_effect();
+
+  MACRO_EXPANSION_HAS_NULL;
+
+#undef MACRO_EXPANSION_HAS_NULL
+}
+
+// Test macro expansion with cast sequence, PR15572.
+void test_macro_expansion2() {
+#define MACRO_EXPANSION_HAS_NULL \
+  dummy((int*)0); \
+  side_effect();
+
+  MACRO_EXPANSION_HAS_NULL;
+
+#undef MACRO_EXPANSION_HAS_NULL
+}
+
+void test_macro_expansion3() {
+#define MACRO_EXPANSION_HAS_NULL \
+  dummy(NULL); \
+  side_effect();
+
+#define OUTER_MACRO \
+  MACRO_EXPANSION_HAS_NULL; \
+  side_effect();
+
+  OUTER_MACRO;
+
+#undef OUTER_MACRO
+#undef MACRO_EXPANSION_HAS_NULL
+}
+
+void test_macro_expansion4() {
+#define MY_NULL NULL
+  int *p = MY_NULL;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr [modernize-use-nullptr]
+  // CHECK-FIXES: int *p = nullptr;
+#undef MY_NULL
+}
+
+#define IS_EQ(x, y) if (x != y) return;
+void test_macro_args() {
+  int i = 0;
+  int *Ptr;
+
+  IS_EQ(static_cast(0), Ptr);
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use nullptr
+  // CHECK-FIXES: IS_EQ(static_cast(nullptr), Ptr);
+
+  IS_EQ(0, Ptr);// literal
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr
+  // CHECK-FIXES: IS_EQ(nullptr, Ptr);
+
+  IS_EQ(NULL, Ptr); // macro
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr
+  // CHECK-FIXES: IS_EQ(nullptr, Ptr);
+
+  // These are ok since the null literal is not spelled within a macro.
+#define myassert(x) if (!(x)) return;
+  myassert(0 == Ptr);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr
+  // CHECK-FIXES: myassert(nullptr == Ptr);
+
+  myassert(NULL == Ptr);
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr
+  // CHECK-FIXES: myassert(nullptr == Ptr);
+
+  // These are bad as the null literal is buried in a macro.
+#define BLAH(X) myassert(0 == (X));
+#define BLAH2(X) myassert(NULL == (X));
+  BLAH(Ptr);
+  BLAH2(Ptr);
+
+  // Same as above but testing extra macro expansion.
+#define EXPECT_NULL(X) IS_EQ(0, X);
+#define EXPECT_NULL2(X) IS_EQ(NULL, X);
+  EXPECT_NULL(Ptr);
+  EXPECT_NULL2(Ptr);
+
+  // Almost the same as above but now null literal is not in a macro so ok
+  // to transform.
+#define EQUALS_PTR(X) IS_EQ(X, Ptr);
+  EQUALS_PTR(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use nullptr
+  // CHECK-FIXES: EQUALS_PTR(nullptr);
+  EQUALS_PTR(NULL);
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use nullptr
+  // CHECK-FIXES: EQUALS_PTR(nullptr);
+
+  // Same as above but testing extra macro expansion.
+#define EQUALS_PTR_I(X) EQUALS_PTR(X)
+  EQUALS_PTR_I(0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr
+  // CHECK-FIXES: EQUALS_PTR_I(nullptr);
+  EQUALS_PTR_I(NULL);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr
+  // CHECK-FIXES: EQUALS_PTR_I(nullptr);
+
+  // Ok since null literal not within macro. However, now testing macro
+  // used as arg to another macro.
+#define decorate(EXPR) side_effect(); EXPR;
+  decorate(IS_EQ(NULL, Ptr));
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr
+  // CHECK-FIXES: decorate(IS_EQ(nullptr, Ptr));
+  decorate(IS_EQ(0, Ptr));
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr
+  // CHECK-FIXES: decorate(IS_EQ(nullptr, Ptr));
+
+  // This macro causes a NullToPointer cast to happen where 0 is assigned to z
+  // but the 0 literal cannot be replaced because it is also used as an
+  // integer in the comparison.
+#define INT_AND

Re: [PATCH] D12081: Add use-nullptr check to clang-tidy.

2015-08-19 Thread Angel Garcia via cfe-commits
angelgarcia added a comment.

Ok, thanks! :)


http://reviews.llvm.org/D12081



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


[PATCH] D12157: Fix LoopConvertCheck bug.

2015-08-19 Thread Angel Garcia via cfe-commits
angelgarcia created this revision.
angelgarcia added a reviewer: alexfh.
angelgarcia added subscribers: klimek, cfe-commits.
angelgarcia changed the visibility of this Differential Revision from "Public 
(No Login Required)" to "All Users".

Fix LoopConvertCheck bug: StringRef to temporaries.

http://reviews.llvm.org/D12157

Files:
  clang-tidy/modernize/LoopConvertCheck.cpp
  clang-tidy/tool/ClangTidyMain.cpp

Index: clang-tidy/tool/ClangTidyMain.cpp
===
--- clang-tidy/tool/ClangTidyMain.cpp
+++ clang-tidy/tool/ClangTidyMain.cpp
@@ -359,7 +359,7 @@
 
 // This anchor is used to force the linker to link the ModernizeModule.
 extern volatile int ModernizeModuleAnchorSource;
-static int ModernizeModuleAnchorDestination = ModernizeModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED ModernizeModuleAnchorDestination = 
ModernizeModuleAnchorSource;
 
 // This anchor is used to force the linker to link the ReadabilityModule.
 extern volatile int ReadabilityModuleAnchorSource;
Index: clang-tidy/modernize/LoopConvertCheck.cpp
===
--- clang-tidy/modernize/LoopConvertCheck.cpp
+++ clang-tidy/modernize/LoopConvertCheck.cpp
@@ -417,7 +417,7 @@
 // First, replace all usages of the array subscript expression with our new
 // variable.
 for (const auto &I : Usages) {
-  StringRef ReplaceText = I.IsArrow ? VarName + "." : VarName;
+  std::string ReplaceText = I.IsArrow ? VarName + "." : VarName;
   TUInfo->getReplacedVars().insert(std::make_pair(TheLoop, IndexVar));
   Diag << FixItHint::CreateReplacement(
   CharSourceRange::getTokenRange(I.Range), ReplaceText);
@@ -446,11 +446,9 @@
   }
 
   StringRef MaybeDereference = ContainerNeedsDereference ? "*" : "";
-  StringRef TypeString = AutoRefType.getAsString();
-  StringRef Range = ("(" + TypeString + " " + VarName + " : " +
- MaybeDereference + ContainerString + ")")
-.str();
-
+  std::string TypeString = AutoRefType.getAsString();
+  std::string Range = ("(" + TypeString + " " + VarName + " : " +
+   MaybeDereference + ContainerString + ")").str();
   Diag << FixItHint::CreateReplacement(
   CharSourceRange::getTokenRange(ParenRange), Range);
   TUInfo->getGeneratedDecls().insert(make_pair(TheLoop, VarName));


Index: clang-tidy/tool/ClangTidyMain.cpp
===
--- clang-tidy/tool/ClangTidyMain.cpp
+++ clang-tidy/tool/ClangTidyMain.cpp
@@ -359,7 +359,7 @@
 
 // This anchor is used to force the linker to link the ModernizeModule.
 extern volatile int ModernizeModuleAnchorSource;
-static int ModernizeModuleAnchorDestination = ModernizeModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED ModernizeModuleAnchorDestination = ModernizeModuleAnchorSource;
 
 // This anchor is used to force the linker to link the ReadabilityModule.
 extern volatile int ReadabilityModuleAnchorSource;
Index: clang-tidy/modernize/LoopConvertCheck.cpp
===
--- clang-tidy/modernize/LoopConvertCheck.cpp
+++ clang-tidy/modernize/LoopConvertCheck.cpp
@@ -417,7 +417,7 @@
 // First, replace all usages of the array subscript expression with our new
 // variable.
 for (const auto &I : Usages) {
-  StringRef ReplaceText = I.IsArrow ? VarName + "." : VarName;
+  std::string ReplaceText = I.IsArrow ? VarName + "." : VarName;
   TUInfo->getReplacedVars().insert(std::make_pair(TheLoop, IndexVar));
   Diag << FixItHint::CreateReplacement(
   CharSourceRange::getTokenRange(I.Range), ReplaceText);
@@ -446,11 +446,9 @@
   }
 
   StringRef MaybeDereference = ContainerNeedsDereference ? "*" : "";
-  StringRef TypeString = AutoRefType.getAsString();
-  StringRef Range = ("(" + TypeString + " " + VarName + " : " +
- MaybeDereference + ContainerString + ")")
-.str();
-
+  std::string TypeString = AutoRefType.getAsString();
+  std::string Range = ("(" + TypeString + " " + VarName + " : " +
+   MaybeDereference + ContainerString + ")").str();
   Diag << FixItHint::CreateReplacement(
   CharSourceRange::getTokenRange(ParenRange), Range);
   TUInfo->getGeneratedDecls().insert(make_pair(TheLoop, VarName));
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D12162: Remove reference.

2015-08-19 Thread Angel Garcia via cfe-commits
angelgarcia created this revision.
angelgarcia added a reviewer: alexfh.
angelgarcia added subscribers: cfe-commits, klimek.
angelgarcia changed the visibility of this Differential Revision from "Public 
(No Login Required)" to "All Users".

Remove a reference where a value was intended (its being initialized with 
std::move).

http://reviews.llvm.org/D12162

Files:
  clang-tidy/modernize/UseNullptrCheck.cpp

Index: clang-tidy/modernize/UseNullptrCheck.cpp
===
--- clang-tidy/modernize/UseNullptrCheck.cpp
+++ clang-tidy/modernize/UseNullptrCheck.cpp
@@ -435,7 +435,7 @@
 private:
   SourceManager &SM;
   ASTContext &Context;
-  const SmallVector &UserNullMacros;
+  const SmallVector UserNullMacros;
   ClangTidyCheck &Check;
   Expr *FirstSubExpr;
   bool PruneSubtree;


Index: clang-tidy/modernize/UseNullptrCheck.cpp
===
--- clang-tidy/modernize/UseNullptrCheck.cpp
+++ clang-tidy/modernize/UseNullptrCheck.cpp
@@ -435,7 +435,7 @@
 private:
   SourceManager &SM;
   ASTContext &Context;
-  const SmallVector &UserNullMacros;
+  const SmallVector UserNullMacros;
   ClangTidyCheck &Check;
   Expr *FirstSubExpr;
   bool PruneSubtree;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D12162: Remove reference.

2015-08-19 Thread Angel Garcia via cfe-commits
angelgarcia changed the visibility of this Differential Revision from "All 
Users" to "Public (No Login Required)".
angelgarcia updated this revision to Diff 32576.
angelgarcia added a comment.

Use ArrayRef.


http://reviews.llvm.org/D12162

Files:
  clang-tidy/modernize/UseNullptrCheck.cpp

Index: clang-tidy/modernize/UseNullptrCheck.cpp
===
--- clang-tidy/modernize/UseNullptrCheck.cpp
+++ clang-tidy/modernize/UseNullptrCheck.cpp
@@ -175,10 +175,10 @@
 class CastSequenceVisitor : public RecursiveASTVisitor {
 public:
   CastSequenceVisitor(ASTContext &Context,
-  SmallVector UserNullMacros,
+  ArrayRef UserNullMacros,
   ClangTidyCheck &check)
   : SM(Context.getSourceManager()), Context(Context),
-UserNullMacros(std::move(UserNullMacros)), Check(check),
+UserNullMacros(UserNullMacros), Check(check),
 FirstSubExpr(nullptr), PruneSubtree(false) {}
 
   bool TraverseStmt(Stmt *S) {
@@ -435,7 +435,7 @@
 private:
   SourceManager &SM;
   ASTContext &Context;
-  const SmallVector &UserNullMacros;
+  ArrayRef UserNullMacros;
   ClangTidyCheck &Check;
   Expr *FirstSubExpr;
   bool PruneSubtree;


Index: clang-tidy/modernize/UseNullptrCheck.cpp
===
--- clang-tidy/modernize/UseNullptrCheck.cpp
+++ clang-tidy/modernize/UseNullptrCheck.cpp
@@ -175,10 +175,10 @@
 class CastSequenceVisitor : public RecursiveASTVisitor {
 public:
   CastSequenceVisitor(ASTContext &Context,
-  SmallVector UserNullMacros,
+  ArrayRef UserNullMacros,
   ClangTidyCheck &check)
   : SM(Context.getSourceManager()), Context(Context),
-UserNullMacros(std::move(UserNullMacros)), Check(check),
+UserNullMacros(UserNullMacros), Check(check),
 FirstSubExpr(nullptr), PruneSubtree(false) {}
 
   bool TraverseStmt(Stmt *S) {
@@ -435,7 +435,7 @@
 private:
   SourceManager &SM;
   ASTContext &Context;
-  const SmallVector &UserNullMacros;
+  ArrayRef UserNullMacros;
   ClangTidyCheck &Check;
   Expr *FirstSubExpr;
   bool PruneSubtree;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D12186: Fix bug in modernize-loop-convert check.

2015-08-20 Thread Angel Garcia via cfe-commits
angelgarcia created this revision.
angelgarcia added a reviewer: alexfh.
angelgarcia added a subscriber: cfe-commits.
angelgarcia changed the visibility of this Differential Revision from "Public 
(No Login Required)" to "All Users".

Remove implicit conversion from nullptr to StringRef.

http://reviews.llvm.org/D12186

Files:
  clang-tidy/modernize/LoopConvertCheck.cpp

Index: clang-tidy/modernize/LoopConvertCheck.cpp
===
--- clang-tidy/modernize/LoopConvertCheck.cpp
+++ clang-tidy/modernize/LoopConvertCheck.cpp
@@ -338,7 +338,7 @@
 SourceRange Range) {
   if (SourceMgr.getFileID(Range.getBegin()) !=
   SourceMgr.getFileID(Range.getEnd()))
-return nullptr;
+return StringRef(nullptr, 0);
 
   return Lexer::getSourceText(CharSourceRange(Range, true), SourceMgr,
   LangOpts);


Index: clang-tidy/modernize/LoopConvertCheck.cpp
===
--- clang-tidy/modernize/LoopConvertCheck.cpp
+++ clang-tidy/modernize/LoopConvertCheck.cpp
@@ -338,7 +338,7 @@
 SourceRange Range) {
   if (SourceMgr.getFileID(Range.getBegin()) !=
   SourceMgr.getFileID(Range.getEnd()))
-return nullptr;
+return StringRef(nullptr, 0);
 
   return Lexer::getSourceText(CharSourceRange(Range, true), SourceMgr,
   LangOpts);
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D12186: Fix bug in modernize-loop-convert check.

2015-08-20 Thread Angel Garcia via cfe-commits
angelgarcia added a comment.

It is allowed as long as you specify that the length is 0.

assert 
https://cs.corp.google.com/#piper///depot/google3/third_party/grte/v4_x86/release/usr/grte/v4/include/assert.h&l=85&ct=xref_jump_to_def&cl=GROK&gsn=assert((data
https://cs.corp.google.com/#piper///depot/google3/third_party/llvm/llvm/include/llvm/ADT/StringRef.h&l=76&ct=xref_jump_to_def&cl=GROK&gsn=data

|  | length 
https://cs.corp.google.com/#piper///depot/google3/third_party/llvm/llvm/include/llvm/ADT/StringRef.h&l=76&ct=xref_jump_to_def&cl=GROK&gsn=length
 |

0) &&"StringRef cannot be built from a NULL argument with
-

non-null length");

I thought that this way it was clear that I was returning an empty
string, but they are both equivalent. I can change it if you think the
default constructor is better.


http://reviews.llvm.org/D12186



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


Re: [PATCH] D12186: Fix bug in modernize-loop-convert check.

2015-08-20 Thread Angel Garcia via cfe-commits
angelgarcia added a comment.

Oooops, copy pasting there was not a good idea. Sorry :(


http://reviews.llvm.org/D12186



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


Re: [PATCH] D12186: Fix bug in modernize-loop-convert check.

2015-08-20 Thread Angel Garcia via cfe-commits
angelgarcia added a comment.

In http://reviews.llvm.org/D12186#228704, @bkramer wrote:

> I meant the code before your change, which calls `StringRef(const char *Str)` 
> and completely disallows nullptr. In other words: this change is missing a 
> regression test.


You are right, the current tests don't cover this line.

> I prefer the default ctor. Using nullptr for the empty string is just an 
> implementation detail, exposing it doesn't add clarity in my opinion.


OK. I'll put the default constructor and try to write a test that covers this 
case. Thank you for your comments!


http://reviews.llvm.org/D12186



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


Re: [PATCH] D12186: Fix bug in modernize-loop-convert check.

2015-08-20 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 32688.
angelgarcia added a comment.

Add a test.


http://reviews.llvm.org/D12186

Files:
  clang-tidy/modernize/LoopConvertCheck.cpp
  test/clang-tidy/Inputs/modernize-loop-convert/structures.h
  test/clang-tidy/modernize-loop-convert-extra.cpp

Index: test/clang-tidy/modernize-loop-convert-extra.cpp
===
--- test/clang-tidy/modernize-loop-convert-extra.cpp
+++ test/clang-tidy/modernize-loop-convert-extra.cpp
@@ -605,4 +605,25 @@
   }
 }
 
+} // namespace SingleIterator
+
+
+namespace Macros {
+
+const int N = 10;
+int arr[N];
+
+void messing_with_macros() {
+  for (int i = 0; i < N; ++i) {
+printf("Value: %d\n", arr[i]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & elem : arr) {
+  // CHECK-FIXES-NEXT:  printf("Value: %d\n", elem);
+
+  for (int i = 0; i < N; ++i) {
+printf("Value: %d\n", CONT arr[i]);
+  }
 }
+
+} // namespace Macros
Index: test/clang-tidy/Inputs/modernize-loop-convert/structures.h
===
--- test/clang-tidy/Inputs/modernize-loop-convert/structures.h
+++ test/clang-tidy/Inputs/modernize-loop-convert/structures.h
@@ -176,4 +176,15 @@
   iterator begin() const;
   iterator end() const;
 };
+
+namespace Macros {
+
+struct MacroStruct {
+  int arr[10];
+};
+static MacroStruct *MacroSt;
+#define CONT MacroSt->
+
+} // namespace Macros
+
 #endif  // STRUCTURES_H
Index: clang-tidy/modernize/LoopConvertCheck.cpp
===
--- clang-tidy/modernize/LoopConvertCheck.cpp
+++ clang-tidy/modernize/LoopConvertCheck.cpp
@@ -337,8 +337,9 @@
 const LangOptions &LangOpts,
 SourceRange Range) {
   if (SourceMgr.getFileID(Range.getBegin()) !=
-  SourceMgr.getFileID(Range.getEnd()))
-return nullptr;
+  SourceMgr.getFileID(Range.getEnd())) {
+return StringRef(); // Empty string.
+  }
 
   return Lexer::getSourceText(CharSourceRange(Range, true), SourceMgr,
   LangOpts);


Index: test/clang-tidy/modernize-loop-convert-extra.cpp
===
--- test/clang-tidy/modernize-loop-convert-extra.cpp
+++ test/clang-tidy/modernize-loop-convert-extra.cpp
@@ -605,4 +605,25 @@
   }
 }
 
+} // namespace SingleIterator
+
+
+namespace Macros {
+
+const int N = 10;
+int arr[N];
+
+void messing_with_macros() {
+  for (int i = 0; i < N; ++i) {
+printf("Value: %d\n", arr[i]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & elem : arr) {
+  // CHECK-FIXES-NEXT:  printf("Value: %d\n", elem);
+
+  for (int i = 0; i < N; ++i) {
+printf("Value: %d\n", CONT arr[i]);
+  }
 }
+
+} // namespace Macros
Index: test/clang-tidy/Inputs/modernize-loop-convert/structures.h
===
--- test/clang-tidy/Inputs/modernize-loop-convert/structures.h
+++ test/clang-tidy/Inputs/modernize-loop-convert/structures.h
@@ -176,4 +176,15 @@
   iterator begin() const;
   iterator end() const;
 };
+
+namespace Macros {
+
+struct MacroStruct {
+  int arr[10];
+};
+static MacroStruct *MacroSt;
+#define CONT MacroSt->
+
+} // namespace Macros
+
 #endif  // STRUCTURES_H
Index: clang-tidy/modernize/LoopConvertCheck.cpp
===
--- clang-tidy/modernize/LoopConvertCheck.cpp
+++ clang-tidy/modernize/LoopConvertCheck.cpp
@@ -337,8 +337,9 @@
 const LangOptions &LangOpts,
 SourceRange Range) {
   if (SourceMgr.getFileID(Range.getBegin()) !=
-  SourceMgr.getFileID(Range.getEnd()))
-return nullptr;
+  SourceMgr.getFileID(Range.getEnd())) {
+return StringRef(); // Empty string.
+  }
 
   return Lexer::getSourceText(CharSourceRange(Range, true), SourceMgr,
   LangOpts);
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D12231: Add use-auto check to modernize module.

2015-08-21 Thread Angel Garcia via cfe-commits
angelgarcia created this revision.
angelgarcia added a reviewer: alexfh.
angelgarcia added subscribers: cfe-commits, klimek.
angelgarcia changed the visibility of this Differential Revision from "Public 
(No Login Required)" to "All Users".

Migrate UseAuto from clang-modernize to clang-tidy.

http://reviews.llvm.org/D12231

Files:
  clang-tidy/modernize/CMakeLists.txt
  clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tidy/modernize/UseAutoCheck.cpp
  clang-tidy/modernize/UseAutoCheck.h
  test/clang-tidy/Inputs/modernize-use-auto/containers.h
  test/clang-tidy/modernize-use-auto-iterator.cpp
  test/clang-tidy/modernize-use-auto-new.cpp

Index: test/clang-tidy/modernize-use-auto-new.cpp
===
--- test/clang-tidy/modernize-use-auto-new.cpp
+++ test/clang-tidy/modernize-use-auto-new.cpp
@@ -0,0 +1,96 @@
+// RUN: %python %S/check_clang_tidy.py %s modernize-use-auto %t
+
+class MyType {};
+
+class MyDerivedType : public MyType {};
+
+// FIXME: the replacement sometimes results in two consecutive spaces after
+// the word 'auto' (due to the presence of spaces at both sides of '*').
+void auto_new() {
+  MyType *a_new = new MyType();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto [modernize-use-auto]
+  // CHECK-FIXES: auto a_new = new MyType();
+
+  static MyType *a_static = new MyType();
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use auto [modernize-use-auto]
+  // CHECK-FIXES: static auto a_static = new MyType();
+
+  MyType *derived = new MyDerivedType();
+
+  void *vd = new MyType();
+
+  // CV-qualifier tests.
+  //
+  // NOTE : the form "type const" is expected here because of a deficiency in
+  // TypeLoc where CV qualifiers are not considered part of the type location
+  // info. That is, all that is being replaced in each case is "MyType *" and
+  // not "MyType * const".
+  static MyType * const d_static = new MyType();
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use auto [modernize-use-auto]
+  // CHECK-FIXES: static auto  const d_static = new MyType();
+
+  MyType * const a_const = new MyType();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto [modernize-use-auto]
+  // CHECK-FIXES: auto  const a_const = new MyType();
+
+  MyType * volatile vol = new MyType();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto [modernize-use-auto]
+  // CHECK-FIXES: auto  volatile vol = new MyType();
+
+  int (**func)(int, int) = new (int(*[5])(int,int));
+
+  int *array = new int[5];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto [modernize-use-auto]
+  // CHECK-FIXES: auto array = new int[5];
+
+  MyType *ptr(new MyType);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto [modernize-use-auto]
+  // CHECK-FIXES: auto ptr(new MyType);
+
+  MyType *ptr2{new MyType};
+
+  {
+// Test for declaration lists.
+MyType *a = new MyType(), *b = new MyType(), *c = new MyType();
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto [modernize-use-auto]
+// CHECK-FIXES: auto a = new MyType(), b = new MyType(), c = new MyType();
+
+// Non-initialized declaration should not be transformed.
+MyType *d = new MyType(), *e;
+
+MyType **f = new MyType*(), **g = new MyType*();
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto [modernize-use-auto]
+// CHECK-FIXES: auto f = new MyType*(), g = new MyType*();
+
+// Mismatching types in declaration lists should not be transformed.
+MyType *h = new MyType(), **i = new MyType*();
+
+// '*' shouldn't be removed in case of mismatching types with multiple
+// declarations.
+MyType *j = new MyType(), *k = new MyType(), **l = new MyType*();
+  }
+
+  {
+// Test for typedefs.
+typedef int * int_p;
+
+int_p a = new int;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto [modernize-use-auto]
+// CHECK-FIXES: auto  a = new int;
+int_p *b = new int*;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto [modernize-use-auto]
+// CHECK-FIXES: auto b = new int*;
+
+// Test for typedefs in declarations lists.
+int_p c = new int, d = new int;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto [modernize-use-auto]
+// CHECK-FIXES: auto  c = new int, d = new int;
+
+// Different types should not be transformed.
+int_p e = new int, *f = new int_p;
+
+int_p *g = new int*, *h = new int_p;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto [modernize-use-auto]
+// CHECK-FIXES: auto g = new int*, h = new int_p;
+  }
+}
Index: test/clang-tidy/modernize-use-auto-iterator.cpp
===
--- test/clang-tidy/modernize-use-auto-iterator.cpp
+++ test/clang-tidy/modernize-use-auto-iterator.cpp
@@ -0,0 +1,320 @@
+// RUN: %python %S/check_clang_tidy.py %s modernize-use-auto %t -- \
+// RUN:   -std=c++11 -I %S/Inputs/modernize-use-auto
+
+#include "containers.h"
+
+void f_array() {
+  std::array C;
+  std::array::iterator I1 = 

Re: [PATCH] D12231: Add use-auto check to modernize module.

2015-08-21 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 32815.
angelgarcia marked 10 inline comments as done.
angelgarcia added a comment.

Fix comments.

I did not include the 'hasDeclaration()" call in the 'standardIterator' 
function because its return type is
internal::PolymorphicMatcherWithParam1< internal::HasDeclarationMatcher, 
internal::Matcher, void(internal::HasDeclarationSupportedTypes)>


http://reviews.llvm.org/D12231

Files:
  clang-tidy/modernize/CMakeLists.txt
  clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tidy/modernize/UseAutoCheck.cpp
  clang-tidy/modernize/UseAutoCheck.h
  test/clang-tidy/Inputs/modernize-use-auto/containers.h
  test/clang-tidy/modernize-use-auto-iterator.cpp
  test/clang-tidy/modernize-use-auto-new.cpp

Index: test/clang-tidy/modernize-use-auto-new.cpp
===
--- test/clang-tidy/modernize-use-auto-new.cpp
+++ test/clang-tidy/modernize-use-auto-new.cpp
@@ -0,0 +1,96 @@
+// RUN: %python %S/check_clang_tidy.py %s modernize-use-auto %t
+
+class MyType {};
+
+class MyDerivedType : public MyType {};
+
+// FIXME: the replacement sometimes results in two consecutive spaces after
+// the word 'auto' (due to the presence of spaces at both sides of '*').
+void auto_new() {
+  MyType *a_new = new MyType();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new [modernize-use-auto]
+  // CHECK-FIXES: auto a_new = new MyType();
+
+  static MyType *a_static = new MyType();
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use auto when initializing with new
+  // CHECK-FIXES: static auto a_static = new MyType();
+
+  MyType *derived = new MyDerivedType();
+
+  void *vd = new MyType();
+
+  // CV-qualifier tests.
+  //
+  // NOTE : the form "type const" is expected here because of a deficiency in
+  // TypeLoc where CV qualifiers are not considered part of the type location
+  // info. That is, all that is being replaced in each case is "MyType *" and
+  // not "MyType * const".
+  static MyType * const d_static = new MyType();
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use auto when initializing with new
+  // CHECK-FIXES: static auto  const d_static = new MyType();
+
+  MyType * const a_const = new MyType();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new
+  // CHECK-FIXES: auto  const a_const = new MyType();
+
+  MyType * volatile vol = new MyType();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new
+  // CHECK-FIXES: auto  volatile vol = new MyType();
+
+  int (**func)(int, int) = new (int(*[5])(int,int));
+
+  int *array = new int[5];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new
+  // CHECK-FIXES: auto array = new int[5];
+
+  MyType *ptr(new MyType);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new
+  // CHECK-FIXES: auto ptr(new MyType);
+
+  MyType *ptr2{new MyType};
+
+  {
+// Test for declaration lists.
+MyType *a = new MyType(), *b = new MyType(), *c = new MyType();
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+// CHECK-FIXES: auto a = new MyType(), b = new MyType(), c = new MyType();
+
+// Non-initialized declaration should not be transformed.
+MyType *d = new MyType(), *e;
+
+MyType **f = new MyType*(), **g = new MyType*();
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+// CHECK-FIXES: auto f = new MyType*(), g = new MyType*();
+
+// Mismatching types in declaration lists should not be transformed.
+MyType *h = new MyType(), **i = new MyType*();
+
+// '*' shouldn't be removed in case of mismatching types with multiple
+// declarations.
+MyType *j = new MyType(), *k = new MyType(), **l = new MyType*();
+  }
+
+  {
+// Test for typedefs.
+typedef int * int_p;
+
+int_p a = new int;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+// CHECK-FIXES: auto  a = new int;
+int_p *b = new int*;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+// CHECK-FIXES: auto b = new int*;
+
+// Test for typedefs in declarations lists.
+int_p c = new int, d = new int;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+// CHECK-FIXES: auto  c = new int, d = new int;
+
+// Different types should not be transformed.
+int_p e = new int, *f = new int_p;
+
+int_p *g = new int*, *h = new int_p;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+// CHECK-FIXES: auto g = new int*, h = new int_p;
+  }
+}
Index: test/clang-tidy/modernize-use-auto-iterator.cpp
===
--- test/clang-tidy/modernize-use-auto-iterator.cpp
+++ test/clang-tidy/modernize-use-auto-iterator.cpp
@@ -0,0 +1,320 @@
+// RUN: %python %S/ch

Re: [PATCH] D12231: Add use-auto check to modernize module.

2015-08-21 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 32816.
angelgarcia added a comment.

Apply clang-format to the code.


http://reviews.llvm.org/D12231

Files:
  clang-tidy/modernize/CMakeLists.txt
  clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tidy/modernize/UseAutoCheck.cpp
  clang-tidy/modernize/UseAutoCheck.h
  test/clang-tidy/Inputs/modernize-use-auto/containers.h
  test/clang-tidy/modernize-use-auto-iterator.cpp
  test/clang-tidy/modernize-use-auto-new.cpp

Index: test/clang-tidy/modernize-use-auto-new.cpp
===
--- test/clang-tidy/modernize-use-auto-new.cpp
+++ test/clang-tidy/modernize-use-auto-new.cpp
@@ -0,0 +1,96 @@
+// RUN: %python %S/check_clang_tidy.py %s modernize-use-auto %t
+
+class MyType {};
+
+class MyDerivedType : public MyType {};
+
+// FIXME: the replacement sometimes results in two consecutive spaces after
+// the word 'auto' (due to the presence of spaces at both sides of '*').
+void auto_new() {
+  MyType *a_new = new MyType();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new [modernize-use-auto]
+  // CHECK-FIXES: auto a_new = new MyType();
+
+  static MyType *a_static = new MyType();
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use auto when initializing with new
+  // CHECK-FIXES: static auto a_static = new MyType();
+
+  MyType *derived = new MyDerivedType();
+
+  void *vd = new MyType();
+
+  // CV-qualifier tests.
+  //
+  // NOTE : the form "type const" is expected here because of a deficiency in
+  // TypeLoc where CV qualifiers are not considered part of the type location
+  // info. That is, all that is being replaced in each case is "MyType *" and
+  // not "MyType * const".
+  static MyType * const d_static = new MyType();
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use auto when initializing with new
+  // CHECK-FIXES: static auto  const d_static = new MyType();
+
+  MyType * const a_const = new MyType();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new
+  // CHECK-FIXES: auto  const a_const = new MyType();
+
+  MyType * volatile vol = new MyType();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new
+  // CHECK-FIXES: auto  volatile vol = new MyType();
+
+  int (**func)(int, int) = new (int(*[5])(int,int));
+
+  int *array = new int[5];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new
+  // CHECK-FIXES: auto array = new int[5];
+
+  MyType *ptr(new MyType);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new
+  // CHECK-FIXES: auto ptr(new MyType);
+
+  MyType *ptr2{new MyType};
+
+  {
+// Test for declaration lists.
+MyType *a = new MyType(), *b = new MyType(), *c = new MyType();
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+// CHECK-FIXES: auto a = new MyType(), b = new MyType(), c = new MyType();
+
+// Non-initialized declaration should not be transformed.
+MyType *d = new MyType(), *e;
+
+MyType **f = new MyType*(), **g = new MyType*();
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+// CHECK-FIXES: auto f = new MyType*(), g = new MyType*();
+
+// Mismatching types in declaration lists should not be transformed.
+MyType *h = new MyType(), **i = new MyType*();
+
+// '*' shouldn't be removed in case of mismatching types with multiple
+// declarations.
+MyType *j = new MyType(), *k = new MyType(), **l = new MyType*();
+  }
+
+  {
+// Test for typedefs.
+typedef int * int_p;
+
+int_p a = new int;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+// CHECK-FIXES: auto  a = new int;
+int_p *b = new int*;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+// CHECK-FIXES: auto b = new int*;
+
+// Test for typedefs in declarations lists.
+int_p c = new int, d = new int;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+// CHECK-FIXES: auto  c = new int, d = new int;
+
+// Different types should not be transformed.
+int_p e = new int, *f = new int_p;
+
+int_p *g = new int*, *h = new int_p;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+// CHECK-FIXES: auto g = new int*, h = new int_p;
+  }
+}
Index: test/clang-tidy/modernize-use-auto-iterator.cpp
===
--- test/clang-tidy/modernize-use-auto-iterator.cpp
+++ test/clang-tidy/modernize-use-auto-iterator.cpp
@@ -0,0 +1,320 @@
+// RUN: %python %S/check_clang_tidy.py %s modernize-use-auto %t -- \
+// RUN:   -std=c++11 -I %S/Inputs/modernize-use-auto
+
+#include "containers.h"
+
+void f_array() {
+  std::array C;
+  std::array::iterator ArrayI1 = C.begin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when declar

Re: [PATCH] D12231: Add use-auto check to modernize module.

2015-08-21 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 32818.
angelgarcia added a comment.

Fix comments: change warning message and minor fixes.


http://reviews.llvm.org/D12231

Files:
  clang-tidy/modernize/CMakeLists.txt
  clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tidy/modernize/UseAutoCheck.cpp
  clang-tidy/modernize/UseAutoCheck.h
  test/clang-tidy/Inputs/modernize-use-auto/containers.h
  test/clang-tidy/modernize-use-auto-iterator.cpp
  test/clang-tidy/modernize-use-auto-new.cpp

Index: test/clang-tidy/modernize-use-auto-new.cpp
===
--- test/clang-tidy/modernize-use-auto-new.cpp
+++ test/clang-tidy/modernize-use-auto-new.cpp
@@ -0,0 +1,96 @@
+// RUN: %python %S/check_clang_tidy.py %s modernize-use-auto %t
+
+class MyType {};
+
+class MyDerivedType : public MyType {};
+
+// FIXME: the replacement sometimes results in two consecutive spaces after
+// the word 'auto' (due to the presence of spaces at both sides of '*').
+void auto_new() {
+  MyType *a_new = new MyType();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new
+  // CHECK-FIXES: auto a_new = new MyType();
+
+  static MyType *a_static = new MyType();
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use auto when initializing with new
+  // CHECK-FIXES: static auto a_static = new MyType();
+
+  MyType *derived = new MyDerivedType();
+
+  void *vd = new MyType();
+
+  // CV-qualifier tests.
+  //
+  // NOTE : the form "type const" is expected here because of a deficiency in
+  // TypeLoc where CV qualifiers are not considered part of the type location
+  // info. That is, all that is being replaced in each case is "MyType *" and
+  // not "MyType * const".
+  static MyType * const d_static = new MyType();
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use auto when initializing with new
+  // CHECK-FIXES: static auto  const d_static = new MyType();
+
+  MyType * const a_const = new MyType();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new
+  // CHECK-FIXES: auto  const a_const = new MyType();
+
+  MyType * volatile vol = new MyType();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new
+  // CHECK-FIXES: auto  volatile vol = new MyType();
+
+  int (**func)(int, int) = new (int(*[5])(int,int));
+
+  int *array = new int[5];
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new
+  // CHECK-FIXES: auto array = new int[5];
+
+  MyType *ptr(new MyType);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with new
+  // CHECK-FIXES: auto ptr(new MyType);
+
+  MyType *ptr2{new MyType};
+
+  {
+// Test for declaration lists.
+MyType *a = new MyType(), *b = new MyType(), *c = new MyType();
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+// CHECK-FIXES: auto a = new MyType(), b = new MyType(), c = new MyType();
+
+// Non-initialized declaration should not be transformed.
+MyType *d = new MyType(), *e;
+
+MyType **f = new MyType*(), **g = new MyType*();
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+// CHECK-FIXES: auto f = new MyType*(), g = new MyType*();
+
+// Mismatching types in declaration lists should not be transformed.
+MyType *h = new MyType(), **i = new MyType*();
+
+// '*' shouldn't be removed in case of mismatching types with multiple
+// declarations.
+MyType *j = new MyType(), *k = new MyType(), **l = new MyType*();
+  }
+
+  {
+// Test for typedefs.
+typedef int * int_p;
+
+int_p a = new int;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+// CHECK-FIXES: auto  a = new int;
+int_p *b = new int*;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+// CHECK-FIXES: auto b = new int*;
+
+// Test for typedefs in declarations lists.
+int_p c = new int, d = new int;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+// CHECK-FIXES: auto  c = new int, d = new int;
+
+// Different types should not be transformed.
+int_p e = new int, *f = new int_p;
+
+int_p *g = new int*, *h = new int_p;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use auto when initializing with new
+// CHECK-FIXES: auto g = new int*, h = new int_p;
+  }
+}
Index: test/clang-tidy/modernize-use-auto-iterator.cpp
===
--- test/clang-tidy/modernize-use-auto-iterator.cpp
+++ test/clang-tidy/modernize-use-auto-iterator.cpp
@@ -0,0 +1,320 @@
+// RUN: %python %S/check_clang_tidy.py %s modernize-use-auto %t -- \
+// RUN:   -std=c++11 -I %S/Inputs/modernize-use-auto
+
+#include "containers.h"
+
+void f_array() {
+  std::array C;
+  std::array::iterator ArrayI1 = C.begin();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when decla

Re: [PATCH] D12231: Add use-auto check to modernize module.

2015-08-21 Thread Angel Garcia via cfe-commits
angelgarcia closed this revision.
angelgarcia added a comment.

Committed revision 245703.


http://reviews.llvm.org/D12231



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


[PATCH] D12281: Tests no longer need the 'REQUIRES: SHELL' line.

2015-08-24 Thread Angel Garcia via cfe-commits
angelgarcia created this revision.
angelgarcia added a reviewer: alexfh.
angelgarcia added subscribers: cfe-commits, klimek.

Update python script, so that it doesn't print that line in new tests.

http://reviews.llvm.org/D12281

Files:
  clang-tidy/add_new_check.py

Index: clang-tidy/add_new_check.py
===
--- clang-tidy/add_new_check.py
+++ clang-tidy/add_new_check.py
@@ -184,7 +184,6 @@
   with open(filename, 'w') as f:
 f.write(
 """// RUN: %%python %%S/check_clang_tidy.py %%s %(check_name_dashes)s %%t
-// REQUIRES: shell
 
 // FIXME: Add something that triggers the check here.
 void f();


Index: clang-tidy/add_new_check.py
===
--- clang-tidy/add_new_check.py
+++ clang-tidy/add_new_check.py
@@ -184,7 +184,6 @@
   with open(filename, 'w') as f:
 f.write(
 """// RUN: %%python %%S/check_clang_tidy.py %%s %(check_name_dashes)s %%t
-// REQUIRES: shell
 
 // FIXME: Add something that triggers the check here.
 void f();
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D12287: Add replace-auto_ptr check.

2015-08-24 Thread Angel Garcia via cfe-commits
angelgarcia created this revision.
angelgarcia added a reviewer: alexfh.
angelgarcia added subscribers: cfe-commits, klimek.

Migrate replace-auto_ptr check from clang-modernize to modernize module in 
clang-tidy.

http://reviews.llvm.org/D12287

Files:
  clang-tidy/modernize/CMakeLists.txt
  clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tidy/modernize/ReplaceAutoPtrCheck.cpp
  clang-tidy/modernize/ReplaceAutoPtrCheck.h
  test/clang-tidy/Inputs/modernize-replace-auto-ptr/
  test/clang-tidy/Inputs/modernize-replace-auto-ptr/memory.h
  test/clang-tidy/modernize-replace-auto-ptr.cpp

Index: test/clang-tidy/modernize-replace-auto-ptr.cpp
===
--- /dev/null
+++ test/clang-tidy/modernize-replace-auto-ptr.cpp
@@ -0,0 +1,304 @@
+// RUN: %python %S/check_clang_tidy.py %s modernize-replace-auto-ptr %t -- \
+// RUN:   -std=c++11 -I %S/Inputs/modernize-replace-auto-ptr
+
+// CHECK-FIXES: #include 
+
+#include "memory.h"
+
+// Instrumentation for auto_ptr_ref test.
+struct Base {};
+struct Derived : Base {};
+std::auto_ptr create_derived_ptr();
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: auto_ptr is deprecated, use unique_ptr instead
+// CHECK-FIXES: std::unique_ptr create_derived_ptr();
+
+
+// Test function return values (declaration)
+std::auto_ptr f_5();
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: auto_ptr is deprecated, use unique_ptr instead
+// CHECK-FIXES: std::unique_ptr f_5()
+
+
+// Test function parameters.
+void f_6(std::auto_ptr);
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: auto_ptr is deprecated, use unique_ptr instead
+// CHECK-FIXES: void f_6(std::unique_ptr);
+void f_7(const std::auto_ptr &);
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: auto_ptr is deprecated, use unique_ptr instead
+// CHECK-FIXES: void f_7(const std::unique_ptr &);
+
+
+// Test on record type fields.
+struct A {
+  std::auto_ptr field;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated, use unique_ptr instead
+  // CHECK-FIXES: std::unique_ptr field;
+
+  typedef std::auto_ptr int_ptr_type;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: auto_ptr is deprecated, use unique_ptr instead
+  // CHECK-FIXES: typedef std::unique_ptr int_ptr_type;
+};
+
+
+// FIXME: Test template WITH instantiation.
+template  struct B {
+  typedef typename std::auto_ptr created_type;
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: auto_ptr is deprecated, use unique_ptr instead
+  // CHECK-FIXES: typedef typename std::unique_ptr created_type;
+
+  created_type create() { return std::auto_ptr(new T()); }
+  // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: auto_ptr is deprecated, use unique_ptr instead
+  // CHECK-FIXES: created_type create() { return std::unique_ptr(new T()); }
+};
+
+
+// Test 'using' in a namespace (declaration)
+namespace ns_1 {
+// Test multiple using declarations.
+  using std::auto_ptr;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: auto_ptr is deprecated, use unique_ptr instead
+  // CHECK-FIXES: using std::unique_ptr;
+  using std::auto_ptr;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: auto_ptr is deprecated, use unique_ptr instead
+  // CHECK-FIXES: using std::unique_ptr;
+}
+
+
+namespace ns_2 {
+template  struct auto_ptr {};
+}
+
+void f_1() {
+  std::auto_ptr a;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated, use unique_ptr instead
+  // CHECK-FIXES: std::unique_ptr a;
+
+  // Check that spaces aren't modified unnecessarily.
+  std:: auto_ptr  b;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: auto_ptr is deprecated, use unique_ptr instead
+  // CHECK-FIXES: std:: unique_ptr  b;
+  std :: auto_ptr < char > c(new char());
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: auto_ptr is deprecated, use unique_ptr instead
+  // CHECK-FIXES: std :: unique_ptr < char > c(new char());
+
+  // Test construction from a temporary.
+  std::auto_ptr d = std::auto_ptr();
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated, use unique_ptr instead
+  // CHECK-MESSAGES: :[[@LINE-2]]:32: warning: auto_ptr is deprecated, use unique_ptr instead
+  // CHECK-FIXES: std::unique_ptr d = std::unique_ptr();
+
+  typedef std::auto_ptr int_ptr_t;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: auto_ptr is deprecated, use unique_ptr instead
+  // CHECK-FIXES: typedef std::unique_ptr int_ptr_t;
+  int_ptr_t e(new int());
+
+  // Test pointers.
+  std::auto_ptr *f;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated, use unique_ptr instead
+  // CHECK-FIXES: std::unique_ptr *f;
+
+  // Test 'static' declarations.
+  static std::auto_ptr g;
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: auto_ptr is deprecated, use unique_ptr instead
+  // CHECK-FIXES: static std::unique_ptr g;
+
+  // Test with cv-qualifiers.
+  const std::auto_ptr h;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: auto_ptr is deprecated, use unique_ptr instead
+  // CHECK-FIXES: const std::unique_ptr h;
+  volatile std::auto_ptr i;
+  // CHECK-ME

Re: [PATCH] D12287: Add replace-auto_ptr check.

2015-08-25 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 33055.
angelgarcia added a comment.

Add check description.


http://reviews.llvm.org/D12287

Files:
  clang-tidy/modernize/CMakeLists.txt
  clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tidy/modernize/ReplaceAutoPtrCheck.cpp
  clang-tidy/modernize/ReplaceAutoPtrCheck.h
  test/clang-tidy/Inputs/modernize-replace-auto-ptr/
  test/clang-tidy/Inputs/modernize-replace-auto-ptr/memory.h
  test/clang-tidy/modernize-replace-auto-ptr.cpp

Index: test/clang-tidy/modernize-replace-auto-ptr.cpp
===
--- /dev/null
+++ test/clang-tidy/modernize-replace-auto-ptr.cpp
@@ -0,0 +1,304 @@
+// RUN: %python %S/check_clang_tidy.py %s modernize-replace-auto-ptr %t -- \
+// RUN:   -std=c++11 -I %S/Inputs/modernize-replace-auto-ptr
+
+// CHECK-FIXES: #include 
+
+#include "memory.h"
+
+// Instrumentation for auto_ptr_ref test.
+struct Base {};
+struct Derived : Base {};
+std::auto_ptr create_derived_ptr();
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: auto_ptr is deprecated, use unique_ptr instead
+// CHECK-FIXES: std::unique_ptr create_derived_ptr();
+
+
+// Test function return values (declaration)
+std::auto_ptr f_5();
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: auto_ptr is deprecated, use unique_ptr instead
+// CHECK-FIXES: std::unique_ptr f_5()
+
+
+// Test function parameters.
+void f_6(std::auto_ptr);
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: auto_ptr is deprecated, use unique_ptr instead
+// CHECK-FIXES: void f_6(std::unique_ptr);
+void f_7(const std::auto_ptr &);
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: auto_ptr is deprecated, use unique_ptr instead
+// CHECK-FIXES: void f_7(const std::unique_ptr &);
+
+
+// Test on record type fields.
+struct A {
+  std::auto_ptr field;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated, use unique_ptr instead
+  // CHECK-FIXES: std::unique_ptr field;
+
+  typedef std::auto_ptr int_ptr_type;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: auto_ptr is deprecated, use unique_ptr instead
+  // CHECK-FIXES: typedef std::unique_ptr int_ptr_type;
+};
+
+
+// FIXME: Test template WITH instantiation.
+template  struct B {
+  typedef typename std::auto_ptr created_type;
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: auto_ptr is deprecated, use unique_ptr instead
+  // CHECK-FIXES: typedef typename std::unique_ptr created_type;
+
+  created_type create() { return std::auto_ptr(new T()); }
+  // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: auto_ptr is deprecated, use unique_ptr instead
+  // CHECK-FIXES: created_type create() { return std::unique_ptr(new T()); }
+};
+
+
+// Test 'using' in a namespace (declaration)
+namespace ns_1 {
+// Test multiple using declarations.
+  using std::auto_ptr;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: auto_ptr is deprecated, use unique_ptr instead
+  // CHECK-FIXES: using std::unique_ptr;
+  using std::auto_ptr;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: auto_ptr is deprecated, use unique_ptr instead
+  // CHECK-FIXES: using std::unique_ptr;
+}
+
+
+namespace ns_2 {
+template  struct auto_ptr {};
+}
+
+void f_1() {
+  std::auto_ptr a;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated, use unique_ptr instead
+  // CHECK-FIXES: std::unique_ptr a;
+
+  // Check that spaces aren't modified unnecessarily.
+  std:: auto_ptr  b;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: auto_ptr is deprecated, use unique_ptr instead
+  // CHECK-FIXES: std:: unique_ptr  b;
+  std :: auto_ptr < char > c(new char());
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: auto_ptr is deprecated, use unique_ptr instead
+  // CHECK-FIXES: std :: unique_ptr < char > c(new char());
+
+  // Test construction from a temporary.
+  std::auto_ptr d = std::auto_ptr();
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated, use unique_ptr instead
+  // CHECK-MESSAGES: :[[@LINE-2]]:32: warning: auto_ptr is deprecated, use unique_ptr instead
+  // CHECK-FIXES: std::unique_ptr d = std::unique_ptr();
+
+  typedef std::auto_ptr int_ptr_t;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: auto_ptr is deprecated, use unique_ptr instead
+  // CHECK-FIXES: typedef std::unique_ptr int_ptr_t;
+  int_ptr_t e(new int());
+
+  // Test pointers.
+  std::auto_ptr *f;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated, use unique_ptr instead
+  // CHECK-FIXES: std::unique_ptr *f;
+
+  // Test 'static' declarations.
+  static std::auto_ptr g;
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: auto_ptr is deprecated, use unique_ptr instead
+  // CHECK-FIXES: static std::unique_ptr g;
+
+  // Test with cv-qualifiers.
+  const std::auto_ptr h;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: auto_ptr is deprecated, use unique_ptr instead
+  // CHECK-FIXES: const std::unique_ptr h;
+  volatile std::auto_ptr i;
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: auto_ptr is deprecated, use unique_ptr instead
+  // CHECK-FIXES: volatile st

Re: [PATCH] D12287: Add replace-auto_ptr check.

2015-08-25 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 33066.
angelgarcia added a comment.

Use the full message once in the test, and truncate all the other patterns.


http://reviews.llvm.org/D12287

Files:
  clang-tidy/modernize/CMakeLists.txt
  clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tidy/modernize/ReplaceAutoPtrCheck.cpp
  clang-tidy/modernize/ReplaceAutoPtrCheck.h
  test/clang-tidy/Inputs/modernize-replace-auto-ptr/
  test/clang-tidy/Inputs/modernize-replace-auto-ptr/memory.h
  test/clang-tidy/modernize-replace-auto-ptr.cpp

Index: test/clang-tidy/modernize-replace-auto-ptr.cpp
===
--- /dev/null
+++ test/clang-tidy/modernize-replace-auto-ptr.cpp
@@ -0,0 +1,304 @@
+// RUN: %python %S/check_clang_tidy.py %s modernize-replace-auto-ptr %t -- \
+// RUN:   -std=c++11 -I %S/Inputs/modernize-replace-auto-ptr
+
+// CHECK-FIXES: #include 
+
+#include "memory.h"
+
+// Instrumentation for auto_ptr_ref test.
+struct Base {};
+struct Derived : Base {};
+std::auto_ptr create_derived_ptr();
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: auto_ptr is deprecated, use unique_ptr instead [modernize-replace-auto-ptr]
+// CHECK-FIXES: std::unique_ptr create_derived_ptr();
+
+
+// Test function return values (declaration)
+std::auto_ptr f_5();
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: auto_ptr is deprecated
+// CHECK-FIXES: std::unique_ptr f_5()
+
+
+// Test function parameters.
+void f_6(std::auto_ptr);
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: auto_ptr is deprecated
+// CHECK-FIXES: void f_6(std::unique_ptr);
+void f_7(const std::auto_ptr &);
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: auto_ptr is deprecated
+// CHECK-FIXES: void f_7(const std::unique_ptr &);
+
+
+// Test on record type fields.
+struct A {
+  std::auto_ptr field;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+  // CHECK-FIXES: std::unique_ptr field;
+
+  typedef std::auto_ptr int_ptr_type;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: auto_ptr is deprecated
+  // CHECK-FIXES: typedef std::unique_ptr int_ptr_type;
+};
+
+
+// FIXME: Test template WITH instantiation.
+template  struct B {
+  typedef typename std::auto_ptr created_type;
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: auto_ptr is deprecated
+  // CHECK-FIXES: typedef typename std::unique_ptr created_type;
+
+  created_type create() { return std::auto_ptr(new T()); }
+  // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: auto_ptr is deprecated
+  // CHECK-FIXES: created_type create() { return std::unique_ptr(new T()); }
+};
+
+
+// Test 'using' in a namespace (declaration)
+namespace ns_1 {
+// Test multiple using declarations.
+  using std::auto_ptr;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: auto_ptr is deprecated
+  // CHECK-FIXES: using std::unique_ptr;
+  using std::auto_ptr;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: auto_ptr is deprecated
+  // CHECK-FIXES: using std::unique_ptr;
+}
+
+
+namespace ns_2 {
+template  struct auto_ptr {};
+}
+
+void f_1() {
+  std::auto_ptr a;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+  // CHECK-FIXES: std::unique_ptr a;
+
+  // Check that spaces aren't modified unnecessarily.
+  std:: auto_ptr  b;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: auto_ptr is deprecated
+  // CHECK-FIXES: std:: unique_ptr  b;
+  std :: auto_ptr < char > c(new char());
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: auto_ptr is deprecated
+  // CHECK-FIXES: std :: unique_ptr < char > c(new char());
+
+  // Test construction from a temporary.
+  std::auto_ptr d = std::auto_ptr();
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+  // CHECK-MESSAGES: :[[@LINE-2]]:32: warning: auto_ptr is deprecated
+  // CHECK-FIXES: std::unique_ptr d = std::unique_ptr();
+
+  typedef std::auto_ptr int_ptr_t;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: auto_ptr is deprecated
+  // CHECK-FIXES: typedef std::unique_ptr int_ptr_t;
+  int_ptr_t e(new int());
+
+  // Test pointers.
+  std::auto_ptr *f;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: auto_ptr is deprecated
+  // CHECK-FIXES: std::unique_ptr *f;
+
+  // Test 'static' declarations.
+  static std::auto_ptr g;
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: auto_ptr is deprecated
+  // CHECK-FIXES: static std::unique_ptr g;
+
+  // Test with cv-qualifiers.
+  const std::auto_ptr h;
+  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: auto_ptr is deprecated
+  // CHECK-FIXES: const std::unique_ptr h;
+  volatile std::auto_ptr i;
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: auto_ptr is deprecated
+  // CHECK-FIXES: volatile std::unique_ptr i;
+  const volatile std::auto_ptr j;
+  // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: auto_ptr is deprecated
+  // CHECK-FIXES: const volatile std::unique_ptr j;
+
+  // Test auto and initializer-list.
+  auto k = std::auto_ptr{};
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: auto_ptr is deprecated
+  // CHECK-FIXES: auto k = std::unique_ptr{};
+  std::aut

[PATCH] D12321: Avoid LoopConvertCheck replacements in template instantiations.

2015-08-25 Thread Angel Garcia via cfe-commits
angelgarcia created this revision.
angelgarcia added a reviewer: alexfh.
angelgarcia added subscribers: cfe-commits, klimek.

Prevent LoopConvertCheck from doing replacements in template instantiations, 
and add a test.

http://reviews.llvm.org/D12321

Files:
  clang-tidy/modernize/LoopConvertCheck.cpp
  test/clang-tidy/modernize-loop-convert-extra.cpp

Index: test/clang-tidy/modernize-loop-convert-extra.cpp
===
--- test/clang-tidy/modernize-loop-convert-extra.cpp
+++ test/clang-tidy/modernize-loop-convert-extra.cpp
@@ -626,3 +626,19 @@
 }
 
 } // namespace Macros
+
+namespace Templates {
+
+template 
+void set_union(Container &container) {
+  for (typename Container::const_iterator SI = container.begin(),
+   SE = container.end(); SI != SE; ++SI) {
+  }
+}
+
+void template_instantiation() {
+  S a;
+  set_union(a);
+}
+
+} // namespace Templates
Index: clang-tidy/modernize/LoopConvertCheck.cpp
===
--- clang-tidy/modernize/LoopConvertCheck.cpp
+++ clang-tidy/modernize/LoopConvertCheck.cpp
@@ -70,6 +70,7 @@
   expr(hasType(isInteger())).bind(ConditionBoundName);
 
   return forStmt(
+ unless(isInTemplateInstantiation()),
  hasLoopInit(declStmt(hasSingleDecl(InitToZeroMatcher))),
  hasCondition(anyOf(
  binaryOperator(hasOperatorName("<"),
@@ -159,6 +160,7 @@
   .bind(DerefByRefResultName)));
 
   return forStmt(
+ unless(isInTemplateInstantiation()),
  hasLoopInit(anyOf(declStmt(declCountIs(2),
 containsDeclaration(0, 
InitDeclMatcher),
 containsDeclaration(1, 
EndDeclMatcher)),
@@ -258,6 +260,7 @@
  EndInitMatcher));
 
   return forStmt(
+ unless(isInTemplateInstantiation()),
  hasLoopInit(
  anyOf(declStmt(declCountIs(2),
 containsDeclaration(0, InitToZeroMatcher),


Index: test/clang-tidy/modernize-loop-convert-extra.cpp
===
--- test/clang-tidy/modernize-loop-convert-extra.cpp
+++ test/clang-tidy/modernize-loop-convert-extra.cpp
@@ -626,3 +626,19 @@
 }
 
 } // namespace Macros
+
+namespace Templates {
+
+template 
+void set_union(Container &container) {
+  for (typename Container::const_iterator SI = container.begin(),
+   SE = container.end(); SI != SE; ++SI) {
+  }
+}
+
+void template_instantiation() {
+  S a;
+  set_union(a);
+}
+
+} // namespace Templates
Index: clang-tidy/modernize/LoopConvertCheck.cpp
===
--- clang-tidy/modernize/LoopConvertCheck.cpp
+++ clang-tidy/modernize/LoopConvertCheck.cpp
@@ -70,6 +70,7 @@
   expr(hasType(isInteger())).bind(ConditionBoundName);
 
   return forStmt(
+ unless(isInTemplateInstantiation()),
  hasLoopInit(declStmt(hasSingleDecl(InitToZeroMatcher))),
  hasCondition(anyOf(
  binaryOperator(hasOperatorName("<"),
@@ -159,6 +160,7 @@
   .bind(DerefByRefResultName)));
 
   return forStmt(
+ unless(isInTemplateInstantiation()),
  hasLoopInit(anyOf(declStmt(declCountIs(2),
 containsDeclaration(0, InitDeclMatcher),
 containsDeclaration(1, EndDeclMatcher)),
@@ -258,6 +260,7 @@
  EndInitMatcher));
 
   return forStmt(
+ unless(isInTemplateInstantiation()),
  hasLoopInit(
  anyOf(declStmt(declCountIs(2),
 containsDeclaration(0, InitToZeroMatcher),
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D12321: Avoid LoopConvertCheck replacements in template instantiations.

2015-08-25 Thread Angel Garcia via cfe-commits
angelgarcia updated this revision to Diff 33081.
angelgarcia added a comment.

Add test.


http://reviews.llvm.org/D12321

Files:
  clang-tidy/modernize/LoopConvertCheck.cpp
  test/clang-tidy/modernize-loop-convert-extra.cpp

Index: test/clang-tidy/modernize-loop-convert-extra.cpp
===
--- test/clang-tidy/modernize-loop-convert-extra.cpp
+++ test/clang-tidy/modernize-loop-convert-extra.cpp
@@ -626,3 +626,24 @@
 }
 
 } // namespace Macros
+
+namespace Templates {
+
+template 
+void set_union(Container &container) {
+  for (typename Container::const_iterator SI = container.begin(),
+   SE = container.end(); SI != SE; ++SI) {
+  }
+  S s;
+  for (S::iterator SI = s.begin(), SE = s.end(); SI != SE; ++SI) {
+  }
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & elem : s) {
+}
+
+void template_instantiation() {
+  S a;
+  set_union(a);
+}
+
+} // namespace Templates
Index: clang-tidy/modernize/LoopConvertCheck.cpp
===
--- clang-tidy/modernize/LoopConvertCheck.cpp
+++ clang-tidy/modernize/LoopConvertCheck.cpp
@@ -70,6 +70,7 @@
   expr(hasType(isInteger())).bind(ConditionBoundName);
 
   return forStmt(
+ unless(isInTemplateInstantiation()),
  hasLoopInit(declStmt(hasSingleDecl(InitToZeroMatcher))),
  hasCondition(anyOf(
  binaryOperator(hasOperatorName("<"),
@@ -159,6 +160,7 @@
   .bind(DerefByRefResultName)));
 
   return forStmt(
+ unless(isInTemplateInstantiation()),
  hasLoopInit(anyOf(declStmt(declCountIs(2),
 containsDeclaration(0, 
InitDeclMatcher),
 containsDeclaration(1, 
EndDeclMatcher)),
@@ -258,6 +260,7 @@
  EndInitMatcher));
 
   return forStmt(
+ unless(isInTemplateInstantiation()),
  hasLoopInit(
  anyOf(declStmt(declCountIs(2),
 containsDeclaration(0, InitToZeroMatcher),


Index: test/clang-tidy/modernize-loop-convert-extra.cpp
===
--- test/clang-tidy/modernize-loop-convert-extra.cpp
+++ test/clang-tidy/modernize-loop-convert-extra.cpp
@@ -626,3 +626,24 @@
 }
 
 } // namespace Macros
+
+namespace Templates {
+
+template 
+void set_union(Container &container) {
+  for (typename Container::const_iterator SI = container.begin(),
+   SE = container.end(); SI != SE; ++SI) {
+  }
+  S s;
+  for (S::iterator SI = s.begin(), SE = s.end(); SI != SE; ++SI) {
+  }
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & elem : s) {
+}
+
+void template_instantiation() {
+  S a;
+  set_union(a);
+}
+
+} // namespace Templates
Index: clang-tidy/modernize/LoopConvertCheck.cpp
===
--- clang-tidy/modernize/LoopConvertCheck.cpp
+++ clang-tidy/modernize/LoopConvertCheck.cpp
@@ -70,6 +70,7 @@
   expr(hasType(isInteger())).bind(ConditionBoundName);
 
   return forStmt(
+ unless(isInTemplateInstantiation()),
  hasLoopInit(declStmt(hasSingleDecl(InitToZeroMatcher))),
  hasCondition(anyOf(
  binaryOperator(hasOperatorName("<"),
@@ -159,6 +160,7 @@
   .bind(DerefByRefResultName)));
 
   return forStmt(
+ unless(isInTemplateInstantiation()),
  hasLoopInit(anyOf(declStmt(declCountIs(2),
 containsDeclaration(0, InitDeclMatcher),
 containsDeclaration(1, EndDeclMatcher)),
@@ -258,6 +260,7 @@
  EndInitMatcher));
 
   return forStmt(
+ unless(isInTemplateInstantiation()),
  hasLoopInit(
  anyOf(declStmt(declCountIs(2),
 containsDeclaration(0, InitToZeroMatcher),
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D12361: LoopConvert no longer take as alias references to other containers.

2015-08-26 Thread Angel Garcia via cfe-commits
angelgarcia created this revision.
angelgarcia added a reviewer: alexfh.
angelgarcia added subscribers: cfe-commits, klimek.

Fix a bug where modernize-loop-convert check would take as alias a reference to 
other containers. Add the pertinent test.

http://reviews.llvm.org/D12361

Files:
  clang-tidy/modernize/LoopConvertUtils.cpp
  test/clang-tidy/modernize-loop-convert-extra.cpp

Index: test/clang-tidy/modernize-loop-convert-extra.cpp
===
--- test/clang-tidy/modernize-loop-convert-extra.cpp
+++ test/clang-tidy/modernize-loop-convert-extra.cpp
@@ -202,6 +202,16 @@
   // CHECK-FIXES-NOT: MutableVal &{{[a-z_]+}} =
   // CHECK-FIXES: {}
   // CHECK-FIXES-NEXT: alias.x = 0;
+
+  dependent dep, other;
+  for (dependent::iterator it = dep.begin(), e = dep.end(); it != e; 
++it) {
+printf("%d\n", *it);
+const int& idx = other[0];
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & elem : dep)
+  // CHECK-FIXES-NEXT: printf("%d\n", elem);
+  // CHECK-FIXES-NEXT: const int& idx = other[0];
 }
 
 } // namespace NamingAlias
Index: clang-tidy/modernize/LoopConvertUtils.cpp
===
--- clang-tidy/modernize/LoopConvertUtils.cpp
+++ clang-tidy/modernize/LoopConvertUtils.cpp
@@ -363,7 +363,7 @@
   return isDereferenceOfOpCall(OpCall, IndexVar);
 if (OpCall->getOperator() == OO_Subscript) {
   assert(OpCall->getNumArgs() == 2);
-  return true;
+  return isIndexInSubscriptExpr(OpCall->getArg(1), IndexVar);
 }
 break;
   }


Index: test/clang-tidy/modernize-loop-convert-extra.cpp
===
--- test/clang-tidy/modernize-loop-convert-extra.cpp
+++ test/clang-tidy/modernize-loop-convert-extra.cpp
@@ -202,6 +202,16 @@
   // CHECK-FIXES-NOT: MutableVal &{{[a-z_]+}} =
   // CHECK-FIXES: {}
   // CHECK-FIXES-NEXT: alias.x = 0;
+
+  dependent dep, other;
+  for (dependent::iterator it = dep.begin(), e = dep.end(); it != e; ++it) {
+printf("%d\n", *it);
+const int& idx = other[0];
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & elem : dep)
+  // CHECK-FIXES-NEXT: printf("%d\n", elem);
+  // CHECK-FIXES-NEXT: const int& idx = other[0];
 }
 
 } // namespace NamingAlias
Index: clang-tidy/modernize/LoopConvertUtils.cpp
===
--- clang-tidy/modernize/LoopConvertUtils.cpp
+++ clang-tidy/modernize/LoopConvertUtils.cpp
@@ -363,7 +363,7 @@
   return isDereferenceOfOpCall(OpCall, IndexVar);
 if (OpCall->getOperator() == OO_Subscript) {
   assert(OpCall->getNumArgs() == 2);
-  return true;
+  return isIndexInSubscriptExpr(OpCall->getArg(1), IndexVar);
 }
 break;
   }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D12370: Fix another LoopConvert fail.

2015-08-26 Thread Angel Garcia via cfe-commits
angelgarcia created this revision.
angelgarcia added a reviewer: alexfh.
angelgarcia added subscribers: cfe-commits, klimek.

Prevent LoopConvert from taking as alias anything that comes from a random 
member function call.

http://reviews.llvm.org/D12370

Files:
  clang-tidy/modernize/LoopConvertUtils.cpp
  test/clang-tidy/modernize-loop-convert-extra.cpp

Index: test/clang-tidy/modernize-loop-convert-extra.cpp
===
--- test/clang-tidy/modernize-loop-convert-extra.cpp
+++ test/clang-tidy/modernize-loop-convert-extra.cpp
@@ -207,11 +207,17 @@
   for (dependent::iterator it = dep.begin(), e = dep.end(); it != e; 
++it) {
 printf("%d\n", *it);
 const int& idx = other[0];
+unsigned othersize = other.size();
   }
-  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & elem : dep)
   // CHECK-FIXES-NEXT: printf("%d\n", elem);
   // CHECK-FIXES-NEXT: const int& idx = other[0];
+  // CHECK-FIXES-NEXT: unsigned othersize = other.size();
+
+  for (int i = 0, e = dep.size(); i != e; ++i) {
+int idx = other.at(i);
+  }
 }
 
 } // namespace NamingAlias
Index: clang-tidy/modernize/LoopConvertUtils.cpp
===
--- clang-tidy/modernize/LoopConvertUtils.cpp
+++ clang-tidy/modernize/LoopConvertUtils.cpp
@@ -368,8 +368,14 @@
 break;
   }
 
-  case Stmt::CXXMemberCallExprClass:
-return true;
+  case Stmt::CXXMemberCallExprClass: {
+const auto *MemCall = cast(Init);
+if (MemCall->getMethodDecl()->getName() == "at") {
+  assert(MemCall->getNumArgs() == 1);
+  return isIndexInSubscriptExpr(MemCall->getArg(0), IndexVar);
+}
+return false;
+  }
 
   default:
 break;


Index: test/clang-tidy/modernize-loop-convert-extra.cpp
===
--- test/clang-tidy/modernize-loop-convert-extra.cpp
+++ test/clang-tidy/modernize-loop-convert-extra.cpp
@@ -207,11 +207,17 @@
   for (dependent::iterator it = dep.begin(), e = dep.end(); it != e; ++it) {
 printf("%d\n", *it);
 const int& idx = other[0];
+unsigned othersize = other.size();
   }
-  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
+  // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
   // CHECK-FIXES: for (auto & elem : dep)
   // CHECK-FIXES-NEXT: printf("%d\n", elem);
   // CHECK-FIXES-NEXT: const int& idx = other[0];
+  // CHECK-FIXES-NEXT: unsigned othersize = other.size();
+
+  for (int i = 0, e = dep.size(); i != e; ++i) {
+int idx = other.at(i);
+  }
 }
 
 } // namespace NamingAlias
Index: clang-tidy/modernize/LoopConvertUtils.cpp
===
--- clang-tidy/modernize/LoopConvertUtils.cpp
+++ clang-tidy/modernize/LoopConvertUtils.cpp
@@ -368,8 +368,14 @@
 break;
   }
 
-  case Stmt::CXXMemberCallExprClass:
-return true;
+  case Stmt::CXXMemberCallExprClass: {
+const auto *MemCall = cast(Init);
+if (MemCall->getMethodDecl()->getName() == "at") {
+  assert(MemCall->getNumArgs() == 1);
+  return isIndexInSubscriptExpr(MemCall->getArg(0), IndexVar);
+}
+return false;
+  }
 
   default:
 break;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D12530: Fix several corner cases for loop-convert check.

2015-09-01 Thread Angel Garcia via cfe-commits
angelgarcia created this revision.
angelgarcia added a reviewer: alexfh.
angelgarcia added subscribers: klimek, cfe-commits.

Reduced the amount of wrong conversions of this check.

http://reviews.llvm.org/D12530

Files:
  clang-tidy/modernize/LoopConvertCheck.cpp
  clang-tidy/modernize/LoopConvertUtils.cpp
  test/clang-tidy/modernize-loop-convert-basic.cpp
  test/clang-tidy/modernize-loop-convert-extra.cpp

Index: test/clang-tidy/modernize-loop-convert-extra.cpp
===
--- test/clang-tidy/modernize-loop-convert-extra.cpp
+++ test/clang-tidy/modernize-loop-convert-extra.cpp
@@ -387,6 +387,14 @@
 
 namespace Nesting {
 
+void g(S::iterator it);
+void const_g(S::const_iterator it);
+class Foo {
+ public:
+  void g(S::iterator it);
+  void const_g(S::const_iterator it);
+};
+
 void f() {
   const int N = 10;
   const int M = 15;
@@ -454,6 +462,48 @@
   // CHECK-FIXES: for (const auto & elem : NestS) {
   // CHECK-FIXES-NEXT: for (S::const_iterator SI = (elem).begin(), SE = (elem).end(); SI != SE; ++SI) {
   // CHECK-FIXES-NEXT: printf("%d", *SI);
+
+  for (Nested::const_iterator I = NestS.begin(), E = NestS.end(); I != E; ++I) {
+const S &s = *I;
+for (S::const_iterator SI = s.begin(), SE = s.end(); SI != SE; ++SI) {
+  printf("%d", *SI);
+  const_g(SI);
+}
+  }
+  // CHECK-MESSAGES: :[[@LINE-7]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (const auto & s : NestS) {
+
+  for (Nested::iterator I = NestS.begin(), E = NestS.end(); I != E; ++I) {
+S &s = *I;
+for (S::iterator SI = s.begin(), SE = s.end(); SI != SE; ++SI) {
+  printf("%d", *SI);
+  g(SI);
+}
+  }
+  // CHECK-MESSAGES: :[[@LINE-7]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & s : NestS) {
+
+  Foo foo;
+  for (Nested::const_iterator I = NestS.begin(), E = NestS.end(); I != E; ++I) {
+const S &s = *I;
+for (S::const_iterator SI = s.begin(), SE = s.end(); SI != SE; ++SI) {
+  printf("%d", *SI);
+  foo.const_g(SI);
+}
+  }
+  // CHECK-MESSAGES: :[[@LINE-7]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (const auto & s : NestS) {
+
+  for (Nested::iterator I = NestS.begin(), E = NestS.end(); I != E; ++I) {
+S &s = *I;
+for (S::iterator SI = s.begin(), SE = s.end(); SI != SE; ++SI) {
+  printf("%d", *SI);
+  foo.g(SI);
+}
+  }
+  // CHECK-MESSAGES: :[[@LINE-7]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (auto & s : NestS) {
+
 }
 
 } // namespace Nesting
Index: test/clang-tidy/modernize-loop-convert-basic.cpp
===
--- test/clang-tidy/modernize-loop-convert-basic.cpp
+++ test/clang-tidy/modernize-loop-convert-basic.cpp
@@ -427,6 +427,27 @@
   }
 };
 
+void foo(S::iterator it) {}
+class Foo {public: void bar(S::iterator it); };
+
+void iterator_used() {
+  S s;
+  Foo fo;
+
+  for (S::iterator it = s.begin(), e = s.end(); it != e; ++it) {
+foo(it);
+  }
+
+  for (S::iterator it = s.begin(), e = s.end(); it != e; ++it) {
+fo.bar(it);
+  }
+
+  S::iterator ret;
+  for (S::iterator it = s.begin(), e = s.end(); it != e; ++it) {
+ret = it;
+  }
+}
+
 } // namespace Iterator
 
 namespace PseudoArray {
@@ -494,12 +515,12 @@
   for (auto i = 0; i < v.size(); ++i) {
   }
   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto & elem : v) {
+  // CHECK-FIXES: for (const auto & elem : v) {
 
   for (auto i = 0; i < v.size(); ++i)
 ;
   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto & elem : v)
+  // CHECK-FIXES: for (const auto & elem : v)
 }
 
 struct NoBeginEnd {
@@ -509,15 +530,15 @@
 struct NoConstBeginEnd {
   NoConstBeginEnd();
   unsigned size() const;
-  unsigned begin();
-  unsigned end();
+  unsigned* begin();
+  unsigned* end();
 };
 
 struct ConstBeginEnd {
   ConstBeginEnd();
   unsigned size() const;
-  unsigned begin() const;
-  unsigned end() const;
+  unsigned* begin() const;
+  unsigned* end() const;
 };
 
 // Shouldn't transform pseudo-array uses if the container doesn't provide
@@ -535,13 +556,32 @@
   for (unsigned i = 0, e = CBE.size(); i < e; ++i) {
   }
   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto & elem : CBE) {
+  // CHECK-FIXES: for (const auto & elem : CBE) {
 
   const ConstBeginEnd const_CBE;
   for (unsigned i = 0, e = const_CBE.size(); i < e; ++i) {
   }
   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (auto & elem : const_CBE) {
+  // CHECK-FIXES: for (const auto & elem : const_CBE) {
+}
+
+struct DerefByValue {
+  DerefByValue();
+  struct iter { unsigned operator*(); };
+  unsigned size() const;
+  iter begin();
+  iter end();
+  unsigned operator[](int);
+};
+
+void DerefByValueTest() {
+ 

Re: [PATCH] D12530: Fix several corner cases for loop-convert check.

2015-09-01 Thread Angel Garcia via cfe-commits
angelgarcia marked 2 inline comments as done.


Comment at: test/clang-tidy/modernize-loop-convert-basic.cpp:448
@@ +447,3 @@
+ret = it;
+  }
+}

klimek wrote:
> This test seems to be missing the it.insert(0) case that was removed from the 
> "unsupported"  comment, if I'm not missing something.
It was in the test 'modernize-loop-convert-negative.cpp'. I moved these ones 
there as well.


Comment at: test/clang-tidy/modernize-loop-convert-basic.cpp:540-541
@@ -518,4 +539,4 @@
   unsigned size() const;
-  unsigned begin() const;
-  unsigned end() const;
+  unsigned* begin() const;
+  unsigned* end() const;
 };

klimek wrote:
> Isn't it important that it's a pointer to an unsigned const, not that the 
> iterator method is const?
The important thing is that the check now adds a "const" whenever it is safe to 
do it. I changed the return type to a pointer just to be more consistent with 
what an iterator is supposed to be. It isn't important at all in this case.


http://reviews.llvm.org/D12530



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


  1   2   >