[PATCH] D53974: [clang-tidy] new checker: bugprone-too-small-loop-variable

2018-11-01 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas created this revision.
Herald added subscribers: cfe-commits, xazax.hun, mgorny.

The new checker searches for those for loops which has a loop variable
with a "too small" type which means this type can't represent all values
which are part of the iteration range.
For example:

int main() {

  long size = 30;
  for( short int i = 0; i < size; ++i) {}

}

The short type leads to infinite loop here because it can't store all
values in the [0..size] interval. In a real use case, size means a
container's size which depends on the user input. Which means for small
amount of objects the algorithm works, but with a larger user input the
software will freeze.

The idea of the checker comes from the LibreOffice project, where the
same check was implemented as a clang compiler plugin, called
LoopVarTooSmall (LLVM licensed).
The idea is the same behind this check, but the code is different because
of the different framework.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53974

Files:
  clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tidy/bugprone/CMakeLists.txt
  clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
  clang-tidy/bugprone/TooSmallLoopVariableCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/bugprone-too-small-loop-variable.cpp

Index: test/clang-tidy/bugprone-too-small-loop-variable.cpp
===
--- /dev/null
+++ test/clang-tidy/bugprone-too-small-loop-variable.cpp
@@ -0,0 +1,160 @@
+// RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t
+
+long size() { return 294967296l; }
+
+
+void voidBadForLoop() {
+  for (int i = 0; i < size(); ++i) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has a narrower type ('int') than the type ('long') of termination condition [bugprone-too-small-loop-variable]
+}
+
+
+void voidBadForLoop2() {
+  for (int i = 0; i < size() + 10; ++i) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has a narrower type ('int') than the type ('long') of termination condition [bugprone-too-small-loop-variable]
+}
+
+
+void voidBadForLoop3() {
+  for (int i = 0; i <= size() - 1; ++i) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has a narrower type ('int') than the type ('long') of termination condition [bugprone-too-small-loop-variable]
+}
+
+
+void voidBadForLoop4() {
+  for (int i = 0; size() > i; ++i) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: loop variable has a narrower type ('int') than the type ('long') of termination condition [bugprone-too-small-loop-variable]
+}
+
+
+void voidBadForLoop5() {
+  for (int i = 0; size() - 1 >= i; ++i) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: loop variable has a narrower type ('int') than the type ('long') of termination condition [bugprone-too-small-loop-variable]
+}
+
+
+void voidBadForLoop6() {
+  int i = 0;
+  for (; i < size(); ++i) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: loop variable has a narrower type ('int') than the type ('long') of termination condition [bugprone-too-small-loop-variable]
+}
+
+
+void voidForLoopUnsignedCond() {
+  unsigned size = 3147483647;
+  for (int i = 0; i < size; ++i) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has a narrower type ('int') than the type ('unsigned int') of termination condition [bugprone-too-small-loop-variable]
+}
+
+
+// False positive: because of the integer literal, loop condition has int type
+void voidForLoopFalsePositive() {
+  short size = 3;
+  bool cond = false;
+  for (short i = 0; i < (cond ? 0 : size); ++i) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has a narrower type ('short') than the type ('int') of termination condition [bugprone-too-small-loop-variable]
+}
+
+
+// Simple use case when both expressions have the same type
+void voidGoodForLoop() {
+  for (long i = 0; i < size(); ++i) {}  // no warning
+}
+
+
+// Second simple use case when both expressions have the same type
+void voidGoodForLoop2() {
+  short loopCond = 10;
+  for (short i = 0; i < loopCond; ++i) {}  // no warning
+}
+
+
+// Because of the integer literal, the loop condition is int, but we suppress the warning here
+void voidForLoopShortPlusLiteral() {
+  short size = 3;
+  for (short i = 0; i <= (size - 1); ++i) {} // no warning
+}
+
+
+// Additions of two short variable is converted to int, but we suppress this to avoid false positives
+void voidForLoopShortPlusShort() {
+  short size = 256;
+  short increment = 14;
+  for (short i = 0; i < size + increment; ++i) {} // no warning
+}
+
+// Different integer types, but in this case the loop variable is the bigger type
+void voidForLoopReverseCond() {
+  short start = 256;
+  short end = 14;
+  for (int i = start; i >= end; --i) {} // no warning
+}
+
+
+// TODO: handle while loop
+void voidBadWhileLoop() {
+  short i = 0;
+  while (i < size())

[PATCH] D53974: [clang-tidy] new checker: bugprone-too-small-loop-variable

2018-11-01 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas updated this revision to Diff 172113.
ztamas added a comment.

Add a description of the checker with examples to the documentation


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53974

Files:
  clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tidy/bugprone/CMakeLists.txt
  clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
  clang-tidy/bugprone/TooSmallLoopVariableCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/bugprone-too-small-loop-variable.cpp

Index: test/clang-tidy/bugprone-too-small-loop-variable.cpp
===
--- /dev/null
+++ test/clang-tidy/bugprone-too-small-loop-variable.cpp
@@ -0,0 +1,160 @@
+// RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t
+
+long size() { return 294967296l; }
+
+
+void voidBadForLoop() {
+  for (int i = 0; i < size(); ++i) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has a narrower type ('int') than the type ('long') of termination condition [bugprone-too-small-loop-variable]
+}
+
+
+void voidBadForLoop2() {
+  for (int i = 0; i < size() + 10; ++i) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has a narrower type ('int') than the type ('long') of termination condition [bugprone-too-small-loop-variable]
+}
+
+
+void voidBadForLoop3() {
+  for (int i = 0; i <= size() - 1; ++i) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has a narrower type ('int') than the type ('long') of termination condition [bugprone-too-small-loop-variable]
+}
+
+
+void voidBadForLoop4() {
+  for (int i = 0; size() > i; ++i) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: loop variable has a narrower type ('int') than the type ('long') of termination condition [bugprone-too-small-loop-variable]
+}
+
+
+void voidBadForLoop5() {
+  for (int i = 0; size() - 1 >= i; ++i) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: loop variable has a narrower type ('int') than the type ('long') of termination condition [bugprone-too-small-loop-variable]
+}
+
+
+void voidBadForLoop6() {
+  int i = 0;
+  for (; i < size(); ++i) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: loop variable has a narrower type ('int') than the type ('long') of termination condition [bugprone-too-small-loop-variable]
+}
+
+
+void voidForLoopUnsignedCond() {
+  unsigned size = 3147483647;
+  for (int i = 0; i < size; ++i) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has a narrower type ('int') than the type ('unsigned int') of termination condition [bugprone-too-small-loop-variable]
+}
+
+
+// False positive: because of the integer literal, loop condition has int type
+void voidForLoopFalsePositive() {
+  short size = 3;
+  bool cond = false;
+  for (short i = 0; i < (cond ? 0 : size); ++i) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has a narrower type ('short') than the type ('int') of termination condition [bugprone-too-small-loop-variable]
+}
+
+
+// Simple use case when both expressions have the same type
+void voidGoodForLoop() {
+  for (long i = 0; i < size(); ++i) {}  // no warning
+}
+
+
+// Second simple use case when both expressions have the same type
+void voidGoodForLoop2() {
+  short loopCond = 10;
+  for (short i = 0; i < loopCond; ++i) {}  // no warning
+}
+
+
+// Because of the integer literal, the loop condition is int, but we suppress the warning here
+void voidForLoopShortPlusLiteral() {
+  short size = 3;
+  for (short i = 0; i <= (size - 1); ++i) {} // no warning
+}
+
+
+// Additions of two short variable is converted to int, but we suppress this to avoid false positives
+void voidForLoopShortPlusShort() {
+  short size = 256;
+  short increment = 14;
+  for (short i = 0; i < size + increment; ++i) {} // no warning
+}
+
+// Different integer types, but in this case the loop variable is the bigger type
+void voidForLoopReverseCond() {
+  short start = 256;
+  short end = 14;
+  for (int i = start; i >= end; --i) {} // no warning
+}
+
+
+// TODO: handle while loop
+void voidBadWhileLoop() {
+  short i = 0;
+  while (i < size()) {++i;} // missing warning
+}
+
+
+// TODO: handle do-while loop
+void voidBadDoWhileLoop() {
+  short i = 0;
+  do {++i;} while (i < size()); // missing warning
+}
+
+
+// We do not catch this, but other conversion related checks can catch it anyway
+void voidReverseForLoop() {
+  for (short i = size() - 1; i >= 0; --i) {}  // no warning
+}
+
+
+// TODO: handle those cases when the loop condition contains a floating point expression
+void voidDoubleForCond() {
+  double condVar = size();
+  for (short i = 0; i < condVar; ++i) {} // missing warning
+}
+
+
+// TODO: handle complex loop conditions
+void voidComplexForCond() {
+  bool additionalCond = true;
+  for (int i = 0; i < size() && additionalCond; ++i) {} // missing warning
+}
+
+
+// Macro in loop condition
+#define SIZE 125
+#define 

[PATCH] D53974: [clang-tidy] new checker: bugprone-too-small-loop-variable

2018-11-01 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas added a comment.

Just a note. I run the new checker on LibreOffice project. I found ~25 false 
positives, which seems small enough to me. This false positives can be 
supressed easily.
Since the LibreOffice project has a similar check as a compiler plugin the code 
was already cleaned up, however I still found ~30 uncaught issue with the new 
checker:
https://cgit.freedesktop.org/libreoffice/core/commit/?id=26ccd00bc96c585b7065af0dcce246b5bfaae5e1


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53974



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


[PATCH] D53974: [clang-tidy] new checker: bugprone-too-small-loop-variable

2018-11-01 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas added a comment.

In https://reviews.llvm.org/D53974#1283833, @sberg wrote:

> > I run the new checker on LibreOffice project. I found ~25 false positives, 
> > which seems small enough to me. This false positives can be supressed 
> > easily.
>
> Do you have a link to such a false positive and how it got suppressed in the 
> LibreOffice code base?  (If those are included in the referenced 
> https://cgit.freedesktop.org/libreoffice/core/commit/?id=26ccd00bc96c585b7065af0dcce246b5bfaae5e1,
>  I failed to spot them.)


I did not supress anything yet, since this checker is still work in progress. 
The final version might avoid those false postives.
One example in basic/source/runtime/dllmgr-x86.cxx
This line:
for (sal_uInt16 i = 1; i < (arguments == 0 ? 0 : arguments->Count()); ++i)

arguments->Count() returns a sal_uInt16 too, which is unsigned short, however 
"0" is an int literal so the "<>?<>:<>" expression will have an int type.
To supress that you can cast the literal:

for (sal_uInt16 i = 1; i < (arguments == 0 ? (sal_uInt16)0 : 
arguments->Count()); ++i)

Or cast the whole expression:

for (sal_uInt16 i = 1; i < (sal_uInt16)(arguments == 0 ? 0 : 
arguments->Count()); ++i)

Or use int for the loop variable:

for (int i = 1; i < (arguments == 0 ? 0 : arguments->Count()); ++i)


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53974



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


[PATCH] D53974: [clang-tidy] new checker: bugprone-too-small-loop-variable

2018-11-01 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas added a comment.

In https://reviews.llvm.org/D53974#1283759, @ZaMaZaN4iK wrote:

> Hmm, i thought Clang has some warning for this, but I was wrong... Did you 
> think to implement this check as Clang warning?


It did not come in my mind to do that. It might be good idea, I guess. This 
version of the check however might find too much false positives for a clang 
warning.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53974



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


[PATCH] D53974: [clang-tidy] new checker: bugprone-too-small-loop-variable

2018-11-01 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas added a comment.

In https://reviews.llvm.org/D53974#1283833, @sberg wrote:

> > I run the new checker on LibreOffice project. I found ~25 false positives, 
> > which seems small enough to me. This false positives can be supressed 
> > easily.
>
> Do you have a link to such a false positive and how it got suppressed in the 
> LibreOffice code base?  (If those are included in the referenced 
> https://cgit.freedesktop.org/libreoffice/core/commit/?id=26ccd00bc96c585b7065af0dcce246b5bfaae5e1,
>  I failed to spot them.)


I uploaded here the output of the new checker on LibreOffice after my 
referenced commit:
https://gist.github.com/tzolnai/9c2c78323c098e2e09d63c1a1384274b

Search for bugprone-too-small-loop-variable in the log. Not all are false 
positives.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53974



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


[PATCH] D53974: [clang-tidy] new check: bugprone-too-small-loop-variable

2018-11-01 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas added a comment.

In https://reviews.llvm.org/D53974#1284000, @JonasToth wrote:

> For general understanding: Couldn't this check be generalized to comparing 
> integers of different sizes? We tried a 'dont-mix-int-types' check for 
> arithmetic already, its complicated :)
>  But this as a specialization of the category could be done easier (i think).
>
> What do you think?


I don't think so. This comparison is suspicious only inside a loop, not in 
general.
For example see this code:

  long size = 30;
  short index = 100;
  
  if(index < size) {
   // 
  }

You can choose the two values as you want, this comparison will work correctly.
However in a loop condition this comparison means a problem, because the loop 
stops only if the "index" variable gets bigger than the "size" variable.
So the loop context is important here.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53974



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


[PATCH] D53974: [clang-tidy] new check: bugprone-too-small-loop-variable

2018-11-01 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas updated this revision to Diff 172226.
ztamas added a comment.

Run clang-formats on files, remove unneeded empty lines, fix up documentation.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53974

Files:
  clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tidy/bugprone/CMakeLists.txt
  clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
  clang-tidy/bugprone/TooSmallLoopVariableCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/bugprone-too-small-loop-variable.cpp

Index: test/clang-tidy/bugprone-too-small-loop-variable.cpp
===
--- /dev/null
+++ test/clang-tidy/bugprone-too-small-loop-variable.cpp
@@ -0,0 +1,161 @@
+// RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t
+
+long size() { return 294967296l; }
+
+void voidBadForLoop() {
+  for (int i = 0; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has a narrower type ('int') than the type ('long') of termination condition [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop2() {
+  for (int i = 0; i < size() + 10; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has a narrower type ('int') than the type ('long') of termination condition [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop3() {
+  for (int i = 0; i <= size() - 1; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has a narrower type ('int') than the type ('long') of termination condition [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop4() {
+  for (int i = 0; size() > i; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:28: warning: loop variable has a narrower type ('int') than the type ('long') of termination condition [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop5() {
+  for (int i = 0; size() - 1 >= i; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: loop variable has a narrower type ('int') than the type ('long') of termination condition [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop6() {
+  int i = 0;
+  for (; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: loop variable has a narrower type ('int') than the type ('long') of termination condition [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidForLoopUnsignedCond() {
+  unsigned size = 3147483647;
+  for (int i = 0; i < size; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has a narrower type ('int') than the type ('unsigned int') of termination condition [bugprone-too-small-loop-variable]
+  }
+}
+
+// False positive: because of the integer literal, loop condition has int type
+void voidForLoopFalsePositive() {
+  short size = 3;
+  bool cond = false;
+  for (short i = 0; i < (cond ? 0 : size); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has a narrower type ('short') than the type ('int') of termination condition [bugprone-too-small-loop-variable]
+  }
+}
+
+// Simple use case when both expressions have the same type
+void voidGoodForLoop() {
+  for (long i = 0; i < size(); ++i) {
+  } // no warning
+}
+
+// Second simple use case when both expressions have the same type
+void voidGoodForLoop2() {
+  short loopCond = 10;
+  for (short i = 0; i < loopCond; ++i) {
+  } // no warning
+}
+
+// Because of the integer literal, the loop condition is int, but we suppress the warning here
+void voidForLoopShortPlusLiteral() {
+  short size = 3;
+  for (short i = 0; i <= (size - 1); ++i) {
+  } // no warning
+}
+
+// Additions of two short variable is converted to int, but we suppress this to avoid false positives
+void voidForLoopShortPlusShort() {
+  short size = 256;
+  short increment = 14;
+  for (short i = 0; i < size + increment; ++i) {
+  } // no warning
+}
+
+// Different integer types, but in this case the loop variable is the bigger type
+void voidForLoopReverseCond() {
+  short start = 256;
+  short end = 14;
+  for (int i = start; i >= end; --i) {
+  } // no warning
+}
+
+// TODO: handle while loop
+void voidBadWhileLoop() {
+  short i = 0;
+  while (i < size()) {
+++i;
+  } // missing warning
+}
+
+// TODO: handle do-while loop
+void voidBadDoWhileLoop() {
+  short i = 0;
+  do {
+++i;
+  } while (i < size()); // missing warning
+}
+
+// We do not catch this, but other conversion related checks can catch it anyway
+void voidReverseForLoop() {
+  for (short i = size() - 1; i >= 0; --i) {
+  } // no warning
+}
+
+// TODO: handle those cases when the loop condition contains a floating point expression
+void voidDoubleForCond() {
+  double condVar = size();
+  for (short i = 0; i < condVar; ++i) {
+  } // missing warning
+}
+
+// TODO: handle complex loop conditions
+void voidComplexForCond() {
+  bool additionalCond = true;
+  for (int i = 0; i < size() && additionalCond; ++i) {
+  } // miss

[PATCH] D53974: [clang-tidy] new check: bugprone-too-small-loop-variable

2018-11-01 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas marked 30 inline comments as done.
ztamas added a comment.

I fixed up formatting and the docs based on comments.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53974



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


[PATCH] D53974: [clang-tidy] new check: bugprone-too-small-loop-variable

2018-11-02 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas added a comment.

Just to make it clear. I think this check is in a good shape now. I mean it 
catches usefull issues and also does not produce too many false positives, as I 
see.
So my intention here is to get it in as it is now (of course after I fixed 
things reviewers find) and later it can be improved in separate patches (e.g. 
reduce false positives even more, handle other use cases like while loop etc.). 
I think it would be better to have smaller patches than polishing this big one 
until it gets ~prefect.
In the test file I added some TODO comments. They were added as a documentation 
of future possibilities.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53974



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


[PATCH] D53974: [clang-tidy] new check: bugprone-too-small-loop-variable

2018-11-02 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas updated this revision to Diff 172422.
ztamas added a comment.

Update code based on reviewer comments:

- Remove const qualifier
- Fix some comments
- Use isInstantiationDependent() method
- Do not ignore macros
- Mark code-constructs in docs
- Handle the use case when both operands of the binary operator is constant 
inside the condition expression.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53974

Files:
  clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tidy/bugprone/CMakeLists.txt
  clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
  clang-tidy/bugprone/TooSmallLoopVariableCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/bugprone-too-small-loop-variable.cpp

Index: test/clang-tidy/bugprone-too-small-loop-variable.cpp
===
--- /dev/null
+++ test/clang-tidy/bugprone-too-small-loop-variable.cpp
@@ -0,0 +1,154 @@
+// RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t
+
+long size() { return 294967296l; }
+
+void voidBadForLoop() {
+  for (int i = 0; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop2() {
+  for (int i = 0; i < size() + 10; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop3() {
+  for (int i = 0; i <= size() - 1; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop4() {
+  for (int i = 0; size() > i; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:28: warning: loop variable has narrower type 'int' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop5() {
+  for (int i = 0; size() - 1 >= i; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: loop variable has narrower type 'int' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop6() {
+  int i = 0;
+  for (; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: loop variable has narrower type 'int' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidForLoopUnsignedCond() {
+  unsigned size = 3147483647;
+  for (int i = 0; i < size; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than terminating condition 'unsigned int' [bugprone-too-small-loop-variable]
+  }
+}
+
+// False positive: because of the integer literal, loop condition has int type
+void voidForLoopFalsePositive() {
+  short size = 3;
+  bool cond = false;
+  for (short i = 0; i < (cond ? 0 : size); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than terminating condition 'int' [bugprone-too-small-loop-variable]
+  }
+}
+
+// Simple use case when both expressions have the same type
+void voidGoodForLoop() {
+  for (long i = 0; i < size(); ++i) {
+  } // no warning
+}
+
+// Second simple use case when both expressions have the same type
+void voidGoodForLoop2() {
+  short loopCond = 10;
+  for (short i = 0; i < loopCond; ++i) {
+  } // no warning
+}
+
+// Because of the integer literal, the loop condition is int, but we suppress the warning here
+void voidForLoopShortPlusLiteral() {
+  short size = 3;
+  for (short i = 0; i <= (size - 1); ++i) {
+  } // no warning
+}
+
+// Additions of two short variable is converted to int, but we suppress this to avoid false positives
+void voidForLoopShortPlusShort() {
+  short size = 256;
+  short increment = 14;
+  for (short i = 0; i < size + increment; ++i) {
+  } // no warning
+}
+
+// Different integer types, but in this case the loop variable is the bigger type
+void voidForLoopReverseCond() {
+  short start = 256;
+  short end = 14;
+  for (int i = start; i >= end; --i) {
+  } // no warning
+}
+
+// TODO: handle while loop
+void voidBadWhileLoop() {
+  short i = 0;
+  while (i < size()) { // missing warning
+++i;
+  }
+}
+
+// TODO: handle do-while loop
+void voidBadDoWhileLoop() {
+  short i = 0;
+  do {
+++i;
+  } while (i < size()); // missing warning
+}
+
+// We do not catch this, but other conversion related checks can catch it anyway
+void voidReverseForLoop() {
+  for (short i = size() - 1; i >= 0; --i) { // no warning
+  }
+}
+
+// TODO: handle complex loop conditions
+void voidComplexForCond() {
+  bool additionalCond = true;
+  for (int i = 0; i < size() && additionalCond; ++i) { // missing warning
+  }
+}
+
+// Macro in loop condition
+#define SIZE 125
+#define SIZE2 (SIZE + 1)
+void voidForLoopWithMacroCond() {
+  for (short i = 0; i < 

[PATCH] D53974: [clang-tidy] new check: bugprone-too-small-loop-variable

2018-11-02 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas marked 16 inline comments as done.
ztamas added inline comments.



Comment at: clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp:20
+
+static const char LoopName[] = "forLoopName";
+static const char loopVarName[] = "loopVar";

JonasToth wrote:
> Please move these variable in the matcher function and make them `StringRef` 
> instead of `const char[]`.
These variables are used not only inside the matcher function but also in the 
check() function.




Comment at: test/clang-tidy/bugprone-too-small-loop-variable.cpp:6
+void voidBadForLoop() {
+  for (int i = 0; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has a narrower 
type ('int') than the type ('long') of termination condition 
[bugprone-too-small-loop-variable]

JonasToth wrote:
> please add tests where the rhs is a literal.
Do you mean tests like voidForLoopWithLiteralCond()?
Is it worth to add more tests like that?



Comment at: test/clang-tidy/bugprone-too-small-loop-variable.cpp:116
+
+// TODO: handle those cases when the loop condition contains a floating point 
expression
+void voidDoubleForCond() {

whisperity wrote:
> (Misc: You might want to check out D52730 for floats later down the line.)
In the meantime, I thought this float comparison is not a real use case. It 
just came in my mind while I was trying to find out test cases. So I just 
removed it. The referenced conversion check might catch it anyway. 



Comment at: test/clang-tidy/bugprone-too-small-loop-variable.cpp:152
+void voidForLoopWithEnumCond() {
+  for (short i = eSizeType::START; i < eSizeType::END; ++i) {
+  } // no warning

JonasToth wrote:
> It is possible to specify the underlying type of an `enum`.
> For the case `enum eSizeType2 : int;` the problem does occur as well. I think 
> especially this case is tricky to spot manually and should be handled too. 
> What do you think?
Hmm, it can be handled I think. However, I'm not sure how often it is, that an 
enum has an item value bigger than 32767 (short) or 65535 (unsigned short) or 
another even bigger value.
For now, I think it's better to just ignore these cases to avoid false 
positives and keep the first version of the check simple. The scope can be 
extended anytime later I think.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53974



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


[PATCH] D53974: [clang-tidy] new check: bugprone-too-small-loop-variable

2018-11-02 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas updated this revision to Diff 172436.
ztamas added a comment.

- Use StringRef instead of char[]
- Add test cases about big constant / literal / enum values


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53974

Files:
  clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tidy/bugprone/CMakeLists.txt
  clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
  clang-tidy/bugprone/TooSmallLoopVariableCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/bugprone-too-small-loop-variable.cpp

Index: test/clang-tidy/bugprone-too-small-loop-variable.cpp
===
--- /dev/null
+++ test/clang-tidy/bugprone-too-small-loop-variable.cpp
@@ -0,0 +1,184 @@
+// RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t
+
+long size() { return 294967296l; }
+
+void voidBadForLoop() {
+  for (int i = 0; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop2() {
+  for (int i = 0; i < size() + 10; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop3() {
+  for (int i = 0; i <= size() - 1; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop4() {
+  for (int i = 0; size() > i; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:28: warning: loop variable has narrower type 'int' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop5() {
+  for (int i = 0; size() - 1 >= i; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: loop variable has narrower type 'int' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop6() {
+  int i = 0;
+  for (; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: loop variable has narrower type 'int' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidForLoopUnsignedCond() {
+  unsigned size = 3147483647;
+  for (int i = 0; i < size; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than terminating condition 'unsigned int' [bugprone-too-small-loop-variable]
+  }
+}
+
+// False positive: because of the integer literal, loop condition has int type
+void voidForLoopFalsePositive() {
+  short size = 3;
+  bool cond = false;
+  for (short i = 0; i < (cond ? 0 : size); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than terminating condition 'int' [bugprone-too-small-loop-variable]
+  }
+}
+
+// Simple use case when both expressions have the same type
+void voidGoodForLoop() {
+  for (long i = 0; i < size(); ++i) {
+  } // no warning
+}
+
+// Second simple use case when both expressions have the same type
+void voidGoodForLoop2() {
+  short loopCond = 10;
+  for (short i = 0; i < loopCond; ++i) {
+  } // no warning
+}
+
+// Because of the integer literal, the loop condition is int, but we suppress the warning here
+void voidForLoopShortPlusLiteral() {
+  short size = 3;
+  for (short i = 0; i <= (size - 1); ++i) {
+  } // no warning
+}
+
+// Additions of two short variable is converted to int, but we suppress this to avoid false positives
+void voidForLoopShortPlusShort() {
+  short size = 256;
+  short increment = 14;
+  for (short i = 0; i < size + increment; ++i) {
+  } // no warning
+}
+
+// Different integer types, but in this case the loop variable is the bigger type
+void voidForLoopReverseCond() {
+  short start = 256;
+  short end = 14;
+  for (int i = start; i >= end; --i) {
+  } // no warning
+}
+
+// TODO: handle while loop
+void voidBadWhileLoop() {
+  short i = 0;
+  while (i < size()) { // missing warning
+++i;
+  }
+}
+
+// TODO: handle do-while loop
+void voidBadDoWhileLoop() {
+  short i = 0;
+  do {
+++i;
+  } while (i < size()); // missing warning
+}
+
+// Test case with a reverse iteration
+// This is caught by -Wimplicit-int-conversion
+void voidReverseForLoop() {
+  for (short i = size() - 1; i >= 0; --i) { // no warning
+  }
+}
+
+// TODO: handle complex loop conditions
+void voidComplexForCond() {
+  bool additionalCond = true;
+  for (int i = 0; i < size() && additionalCond; ++i) { // missing warning
+  }
+}
+
+// Macro in loop condition
+#define SIZE 125
+#define SIZE2 (SIZE + 1)
+void voidForLoopWithMacroCond() {
+  for (short i = 0; i < SIZE2; ++i) { // no warning
+  }
+}
+
+// Literal in loop condition
+void voidForLoopWithLiteralCond() {
+  for (short i = 0; i < 125; ++i) { // no warning
+  }
+}
+
+// "Big" literal in loop

[PATCH] D53974: [clang-tidy] new check: bugprone-too-small-loop-variable

2018-11-02 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas marked 3 inline comments as done.
ztamas added inline comments.



Comment at: test/clang-tidy/bugprone-too-small-loop-variable.cpp:6
+void voidBadForLoop() {
+  for (int i = 0; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has a narrower 
type ('int') than the type ('long') of termination condition 
[bugprone-too-small-loop-variable]

JonasToth wrote:
> ztamas wrote:
> > JonasToth wrote:
> > > please add tests where the rhs is a literal.
> > Do you mean tests like voidForLoopWithLiteralCond()?
> > Is it worth to add more tests like that?
> I didn't see it. In principle yes, but i would like to see a test with a 
> bigger number then iterateable (maybe there is a frontend warning for that?). 
> If there is no warning, this should definitely be implemented here (possible 
> follow up) or even become a frontend warning.
I added a test case. This kind of test cases are caught by 
-Wtautological-constant-out-of-range-compare, so we are good I think.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53974



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


[PATCH] D53974: [clang-tidy] new check: bugprone-too-small-loop-variable

2018-11-03 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas updated this revision to Diff 172486.
ztamas marked an inline comment as done.
ztamas added a comment.

- Analyze template dependant for loops too (add some test cases)
- Use double backticks for marking code in docs


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53974

Files:
  clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tidy/bugprone/CMakeLists.txt
  clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
  clang-tidy/bugprone/TooSmallLoopVariableCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/bugprone-too-small-loop-variable.cpp

Index: test/clang-tidy/bugprone-too-small-loop-variable.cpp
===
--- /dev/null
+++ test/clang-tidy/bugprone-too-small-loop-variable.cpp
@@ -0,0 +1,204 @@
+// RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t
+
+long size() { return 294967296l; }
+
+void voidBadForLoop() {
+  for (int i = 0; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop2() {
+  for (int i = 0; i < size() + 10; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop3() {
+  for (int i = 0; i <= size() - 1; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop4() {
+  for (int i = 0; size() > i; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:28: warning: loop variable has narrower type 'int' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop5() {
+  for (int i = 0; size() - 1 >= i; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: loop variable has narrower type 'int' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop6() {
+  int i = 0;
+  for (; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: loop variable has narrower type 'int' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidForLoopUnsignedCond() {
+  unsigned size = 3147483647;
+  for (int i = 0; i < size; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than terminating condition 'unsigned int' [bugprone-too-small-loop-variable]
+  }
+}
+
+// False positive: because of the integer literal, loop condition has int type
+void voidForLoopFalsePositive() {
+  short size = 3;
+  bool cond = false;
+  for (short i = 0; i < (cond ? 0 : size); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than terminating condition 'int' [bugprone-too-small-loop-variable]
+  }
+}
+
+// A loop with a template value
+template
+void doSomething() {
+  for (short i = 0; i < size; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+// A loop with a template type
+template
+void doSomething() {
+  for (T i = 0; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: loop variable has narrower type 'short' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidForLoopInstantiation() {
+  doSomething(); // does not trigger the warning
+  doSomething(); // triggers the warning
+}
+
+// Simple use case when both expressions have the same type
+void voidGoodForLoop() {
+  for (long i = 0; i < size(); ++i) {
+  } // no warning
+}
+
+// Second simple use case when both expressions have the same type
+void voidGoodForLoop2() {
+  short loopCond = 10;
+  for (short i = 0; i < loopCond; ++i) {
+  } // no warning
+}
+
+// Because of the integer literal, the loop condition is int, but we suppress the warning here
+void voidForLoopShortPlusLiteral() {
+  short size = 3;
+  for (short i = 0; i <= (size - 1); ++i) {
+  } // no warning
+}
+
+// Additions of two short variable is converted to int, but we suppress this to avoid false positives
+void voidForLoopShortPlusShort() {
+  short size = 256;
+  short increment = 14;
+  for (short i = 0; i < size + increment; ++i) {
+  } // no warning
+}
+
+// Different integer types, but in this case the loop variable is the bigger type
+void voidForLoopReverseCond() {
+  short start = 256;
+  short end = 14;
+  for (int i = start; i >= end; --i) {
+  } // no warning
+}
+
+// TODO: handle while loop
+void voidBadWhileLoop() {
+  short i = 0;
+  while (i < size()) { // missing warning
+++i;
+  }
+}
+
+// TODO: handle do-while loop
+void voidBadDoWhileLoop() {
+  short i = 0;
+  do {
+++i;
+  } while

[PATCH] D53974: [clang-tidy] new check: bugprone-too-small-loop-variable

2018-11-03 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas marked 2 inline comments as done.
ztamas added inline comments.



Comment at: clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp:109
+
+if (RHSE->isInstantiationDependent() || LHSE->isInstantiationDependent())
+  return 0;

Szelethus wrote:
> You seem to have code for handling templates, but I don't see test cases for 
> it.
Thanks for mentioning it. I was overdefensive against false positives. This 
isInstantiationDependent() is not needed here. So I removed and added some test 
cases with templates.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53974



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


[PATCH] D53974: [clang-tidy] new check: bugprone-too-small-loop-variable

2018-11-03 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas updated this revision to Diff 172487.
ztamas marked an inline comment as done.
ztamas added a comment.

Update docs based on reviewer comment


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53974

Files:
  clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tidy/bugprone/CMakeLists.txt
  clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
  clang-tidy/bugprone/TooSmallLoopVariableCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/bugprone-too-small-loop-variable.cpp

Index: test/clang-tidy/bugprone-too-small-loop-variable.cpp
===
--- /dev/null
+++ test/clang-tidy/bugprone-too-small-loop-variable.cpp
@@ -0,0 +1,204 @@
+// RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t
+
+long size() { return 294967296l; }
+
+void voidBadForLoop() {
+  for (int i = 0; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop2() {
+  for (int i = 0; i < size() + 10; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop3() {
+  for (int i = 0; i <= size() - 1; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop4() {
+  for (int i = 0; size() > i; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:28: warning: loop variable has narrower type 'int' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop5() {
+  for (int i = 0; size() - 1 >= i; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: loop variable has narrower type 'int' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop6() {
+  int i = 0;
+  for (; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: loop variable has narrower type 'int' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidForLoopUnsignedCond() {
+  unsigned size = 3147483647;
+  for (int i = 0; i < size; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than terminating condition 'unsigned int' [bugprone-too-small-loop-variable]
+  }
+}
+
+// False positive: because of the integer literal, loop condition has int type
+void voidForLoopFalsePositive() {
+  short size = 3;
+  bool cond = false;
+  for (short i = 0; i < (cond ? 0 : size); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than terminating condition 'int' [bugprone-too-small-loop-variable]
+  }
+}
+
+// A loop with a template value
+template
+void doSomething() {
+  for (short i = 0; i < size; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+// A loop with a template type
+template
+void doSomething() {
+  for (T i = 0; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: loop variable has narrower type 'short' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidForLoopInstantiation() {
+  doSomething(); // does not trigger the warning
+  doSomething(); // triggers the warning
+}
+
+// Simple use case when both expressions have the same type
+void voidGoodForLoop() {
+  for (long i = 0; i < size(); ++i) {
+  } // no warning
+}
+
+// Second simple use case when both expressions have the same type
+void voidGoodForLoop2() {
+  short loopCond = 10;
+  for (short i = 0; i < loopCond; ++i) {
+  } // no warning
+}
+
+// Because of the integer literal, the loop condition is int, but we suppress the warning here
+void voidForLoopShortPlusLiteral() {
+  short size = 3;
+  for (short i = 0; i <= (size - 1); ++i) {
+  } // no warning
+}
+
+// Additions of two short variable is converted to int, but we suppress this to avoid false positives
+void voidForLoopShortPlusShort() {
+  short size = 256;
+  short increment = 14;
+  for (short i = 0; i < size + increment; ++i) {
+  } // no warning
+}
+
+// Different integer types, but in this case the loop variable is the bigger type
+void voidForLoopReverseCond() {
+  short start = 256;
+  short end = 14;
+  for (int i = start; i >= end; --i) {
+  } // no warning
+}
+
+// TODO: handle while loop
+void voidBadWhileLoop() {
+  short i = 0;
+  while (i < size()) { // missing warning
+++i;
+  }
+}
+
+// TODO: handle do-while loop
+void voidBadDoWhileLoop() {
+  short i = 0;
+  do {
+++i;
+  } while (i < size()); // missing warning
+}
+
+// Test case with a reverse iterati

[PATCH] D53974: [clang-tidy] new check: bugprone-too-small-loop-variable

2018-11-03 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas added a comment.

In https://reviews.llvm.org/D53974#1285930, @Szelethus wrote:

> In https://reviews.llvm.org/D53974#1283759, @ZaMaZaN4iK wrote:
>
> > Hmm, i thought Clang has some warning for this, but I was wrong... Did you 
> > think to implement this check as Clang warning?
>
>
> That is an interesting point actually -- maybe it'd be worth doing that, and 
> if more powerful analysis is required, Static Analyzer would be the next 
> step. I haven't actually implemented any 'regular' clang warning, so I'm not 
> sure.


Well, I'm implementing it as a clang-tidy check now. I guess in the future 
anyone can replace it with a clang warning if he/she can implement it 
effectively (e.g. no false positives).

My first impression was that having something accepted as clang static analyzer 
check takes ages and so I expect that implementing something as a clang warning 
takes even more time. My impression is based on bugzilla activity and on some 
read review history. It seems to me it's not rare to have comments like: "Ping, 
let's not abandon this change" or the author says that he/she has no more time 
for further work, etc. However clang-tidy seems more progressive. So I prefer 
to have something as a clang-tidy check (and actually get it in the upstream 
tool) than implementing it as a clang warning (if it can be implemented 
effectively at all), wait for a year of review and most probably abandon the 
change. Of course, it's just a first impression, but why should I take the 
risk. I think this clang-tidy check is powerful, so useful to have it.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53974



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


[PATCH] D53974: [clang-tidy] new check: bugprone-too-small-loop-variable

2018-11-04 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas marked 10 inline comments as done.
ztamas added a comment.

Mark all handled inline comments as Done.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53974



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


[PATCH] D53974: [clang-tidy] new check: bugprone-too-small-loop-variable

2018-11-05 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas added inline comments.



Comment at: clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp:142
+  if (LoopVar->getType() != LoopIncrement->getType())
+return; // We matched the loop variable incorrectly
+

JonasToth wrote:
> Does this try to ensure a precondition? Then it should become an assertion 
> instead.
> Please adjust the comment like above (punctuation, position)
It's not an assumed precondition. This `if` handles the case when 
LoopVarMatcher is not fitted with the actual loop variable. That's why the 
IncrementMatcher is there so we can check whether we found the loop variable.
See voidForLoopReverseCond() test case which hits this `if` branch.
I did not find a solution to handle this check inside the matcher.



Comment at: docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst:10
+
+  .. code-block:: c++
+

JonasToth wrote:
> the `.. code-block:: c++` is usually not indended, only the code itself.
Hmm, I copied this from somewhere. It might be a good idea to make this 
consistent across all the *.rst files. See bugprone-suspicious-semicolon.rst or 
bugprone-use-after-move.rst for example.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53974



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


[PATCH] D53974: [clang-tidy] new check: bugprone-too-small-loop-variable

2018-11-05 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas added inline comments.



Comment at: clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp:45
+
+  // We need to catch only those comparisons which contain any integer cast
+  StatementMatcher LoopVarConversionMatcher =

JonasToth wrote:
> missing full stop.
Sorry, I forgot the punctuation what you've already mentioned.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53974



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


[PATCH] D53974: [clang-tidy] new check: bugprone-too-small-loop-variable

2018-11-05 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas updated this revision to Diff 172635.
ztamas added a comment.

- Add a range-based loop test case
- Restructure test cases a bit
- Fix-up comments, position, punctuation


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53974

Files:
  clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tidy/bugprone/CMakeLists.txt
  clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
  clang-tidy/bugprone/TooSmallLoopVariableCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/bugprone-too-small-loop-variable.cpp

Index: test/clang-tidy/bugprone-too-small-loop-variable.cpp
===
--- /dev/null
+++ test/clang-tidy/bugprone-too-small-loop-variable.cpp
@@ -0,0 +1,227 @@
+// RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t
+
+long size() { return 294967296l; }
+
+
+/// Test cases caught by bugprone-too-small-loop-variable.
+
+void voidBadForLoop() {
+  for (int i = 0; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop2() {
+  for (int i = 0; i < size() + 10; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop3() {
+  for (int i = 0; i <= size() - 1; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop4() {
+  for (int i = 0; size() > i; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:28: warning: loop variable has narrower type 'int' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop5() {
+  for (int i = 0; size() - 1 >= i; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: loop variable has narrower type 'int' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop6() {
+  int i = 0;
+  for (; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: loop variable has narrower type 'int' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidForLoopUnsignedCond() {
+  unsigned size = 3147483647;
+  for (int i = 0; i < size; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than terminating condition 'unsigned int' [bugprone-too-small-loop-variable]
+  }
+}
+
+// Loop's terminating condition has a template dependent value.
+template 
+void doSomething() {
+  for (short i = 0; i < size; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+// Loop's terminating condition has a template dependent type.
+template 
+void doSomething() {
+  for (T i = 0; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: loop variable has narrower type 'short' than terminating condition 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidForLoopInstantiation() {
+  // This line does not trigger the warning.
+  doSomething();
+  // This one triggers the warning.
+  doSomething();
+}
+
+
+/// Test cases where we should not warn.
+
+// A simple use case when both expressions have the same type.
+void voidGoodForLoop() {
+  for (long i = 0; i < size(); ++i) { // no warning
+  }
+}
+
+// Other use case where both expressions have the same type,
+// but short expressions are converted to int by the compare operator.
+void voidGoodForLoop2() {
+  short loopCond = 10;
+  for (short i = 0; i < loopCond; ++i) { // no warning
+  }
+}
+
+// Because of the integer literal, the loop condition is int, but we suppress the warning here.
+void voidForLoopShortPlusLiteral() {
+  short size = 3;
+  for (short i = 0; i <= (size - 1); ++i) { // no warning
+  }
+}
+
+// Addition of two short variables results in an int value, but we suppress this to avoid false positives.
+void voidForLoopShortPlusShort() {
+  short size = 256;
+  short increment = 14;
+  for (short i = 0; i < size + increment; ++i) { // no warning
+  }
+}
+
+// In this test case we have different integer types, but here the loop variable has the bigger type.
+// The terminating condition is cast implicitly, not the loop variable.
+void voidForLoopCondImplicitCast() {
+  short start = 256;
+  short end = 14;
+  for (int i = start; i >= end; --i) { // no warning
+  }
+}
+
+// Range based loop and other iterator based loops are ignored by this check.
+void voidRangeBasedForLoop() {
+  int array[] = 

[PATCH] D53974: [clang-tidy] new check: bugprone-too-small-loop-variable

2018-11-05 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas added inline comments.



Comment at: clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp:142
+  if (LoopVar->getType() != LoopIncrement->getType())
+return; // We matched the loop variable incorrectly
+

ztamas wrote:
> JonasToth wrote:
> > Does this try to ensure a precondition? Then it should become an assertion 
> > instead.
> > Please adjust the comment like above (punctuation, position)
> It's not an assumed precondition. This `if` handles the case when 
> LoopVarMatcher is not fitted with the actual loop variable. That's why the 
> IncrementMatcher is there so we can check whether we found the loop variable.
> See voidForLoopReverseCond() test case which hits this `if` branch.
> I did not find a solution to handle this check inside the matcher.
voidForLoopReverseCond()  was renamed to voidForLoopCondImplicitCast() in the 
mean time.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53974



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


[PATCH] D53974: [clang-tidy] new check: bugprone-too-small-loop-variable

2018-11-07 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas updated this revision to Diff 172938.
ztamas added a comment.

- no `else` after `return`
- `static constexpr llvm::StringLiteral`
- CamelCase variable names
- Remove unneeded isIntegerType() check
- Better terminology: not terminating condition, but iteration's upper bound.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53974

Files:
  clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tidy/bugprone/CMakeLists.txt
  clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
  clang-tidy/bugprone/TooSmallLoopVariableCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/bugprone-too-small-loop-variable.cpp

Index: test/clang-tidy/bugprone-too-small-loop-variable.cpp
===
--- /dev/null
+++ test/clang-tidy/bugprone-too-small-loop-variable.cpp
@@ -0,0 +1,227 @@
+// RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t
+
+long size() { return 294967296l; }
+
+
+/// Test cases correctly caught by bugprone-too-small-loop-variable.
+
+void voidBadForLoop() {
+  for (int i = 0; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop2() {
+  for (int i = 0; i < size() + 10; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop3() {
+  for (int i = 0; i <= size() - 1; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop4() {
+  for (int i = 0; size() > i; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:28: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop5() {
+  for (int i = 0; size() - 1 >= i; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop6() {
+  int i = 0;
+  for (; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidForLoopUnsignedBound() {
+  unsigned size = 3147483647;
+  for (int i = 0; i < size; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than iteration's upper bound 'unsigned int' [bugprone-too-small-loop-variable]
+  }
+}
+
+// The iteration's upper bound has a template dependent value.
+template 
+void doSomething() {
+  for (short i = 0; i < size; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+// The iteration's upper bound has a template dependent type.
+template 
+void doSomething() {
+  for (T i = 0; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: loop variable has narrower type 'short' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidForLoopInstantiation() {
+  // This line does not trigger the warning.
+  doSomething();
+  // This one triggers the warning.
+  doSomething();
+}
+
+
+/// Correct loops: we should not warn here.
+
+// A simple use case when both expressions have the same type.
+void voidGoodForLoop() {
+  for (long i = 0; i < size(); ++i) { // no warning
+  }
+}
+
+// Other use case where both expressions have the same type,
+// but short expressions are converted to int by the compare operator.
+void voidGoodForLoop2() {
+  short loopCond = 10;
+  for (short i = 0; i < loopCond; ++i) { // no warning
+  }
+}
+
+// Because of the integer literal, the iteration's upper bound is int, but we suppress the warning here.
+void voidForLoopShortPlusLiteral() {
+  short size = 3;
+  for (short i = 0; i <= (size - 1); ++i) { // no warning
+  }
+}
+
+// Addition of two short variables results in an int value, but we suppress this to avoid false positives.
+void voidForLoopShortPlusShort() {
+  short size = 256;
+  short increment = 14;
+  for (short i = 0; i < size + increment; ++i) { // no warning
+  }
+}
+
+// In this test case we have different integer types, but here the loop variable has the bigger type.
+// The iteration's bound is cast implicitly, not the loop variable.
+void voidForLoopBoundImplicitCast() {
+  short start = 256;
+  short end = 14;
+  for (int i = start; i >= end; --i) { // no warn

[PATCH] D53974: [clang-tidy] new check: bugprone-too-small-loop-variable

2018-11-09 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas updated this revision to Diff 173372.
ztamas added a comment.

- Make local functions `static`


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53974

Files:
  clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tidy/bugprone/CMakeLists.txt
  clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
  clang-tidy/bugprone/TooSmallLoopVariableCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/bugprone-too-small-loop-variable.cpp

Index: test/clang-tidy/bugprone-too-small-loop-variable.cpp
===
--- /dev/null
+++ test/clang-tidy/bugprone-too-small-loop-variable.cpp
@@ -0,0 +1,227 @@
+// RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t
+
+long size() { return 294967296l; }
+
+
+/// Test cases correctly caught by bugprone-too-small-loop-variable.
+
+void voidBadForLoop() {
+  for (int i = 0; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop2() {
+  for (int i = 0; i < size() + 10; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop3() {
+  for (int i = 0; i <= size() - 1; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop4() {
+  for (int i = 0; size() > i; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:28: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop5() {
+  for (int i = 0; size() - 1 >= i; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop6() {
+  int i = 0;
+  for (; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidForLoopUnsignedBound() {
+  unsigned size = 3147483647;
+  for (int i = 0; i < size; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than iteration's upper bound 'unsigned int' [bugprone-too-small-loop-variable]
+  }
+}
+
+// The iteration's upper bound has a template dependent value.
+template 
+void doSomething() {
+  for (short i = 0; i < size; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+// The iteration's upper bound has a template dependent type.
+template 
+void doSomething() {
+  for (T i = 0; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: loop variable has narrower type 'short' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidForLoopInstantiation() {
+  // This line does not trigger the warning.
+  doSomething();
+  // This one triggers the warning.
+  doSomething();
+}
+
+
+/// Correct loops: we should not warn here.
+
+// A simple use case when both expressions have the same type.
+void voidGoodForLoop() {
+  for (long i = 0; i < size(); ++i) { // no warning
+  }
+}
+
+// Other use case where both expressions have the same type,
+// but short expressions are converted to int by the compare operator.
+void voidGoodForLoop2() {
+  short loopCond = 10;
+  for (short i = 0; i < loopCond; ++i) { // no warning
+  }
+}
+
+// Because of the integer literal, the iteration's upper bound is int, but we suppress the warning here.
+void voidForLoopShortPlusLiteral() {
+  short size = 3;
+  for (short i = 0; i <= (size - 1); ++i) { // no warning
+  }
+}
+
+// Addition of two short variables results in an int value, but we suppress this to avoid false positives.
+void voidForLoopShortPlusShort() {
+  short size = 256;
+  short increment = 14;
+  for (short i = 0; i < size + increment; ++i) { // no warning
+  }
+}
+
+// In this test case we have different integer types, but here the loop variable has the bigger type.
+// The iteration's bound is cast implicitly, not the loop variable.
+void voidForLoopBoundImplicitCast() {
+  short start = 256;
+  short end = 14;
+  for (int i = start; i >= end; --i) { // no warning
+  }
+}
+
+// Range based loop and other iterator based loops are ignored by this check.
+void voidRangeBasedForLoop() {
+  int array[] = {1, 2, 3, 4, 5};
+  for (const int &i :

[PATCH] D53974: [clang-tidy] new check: bugprone-too-small-loop-variable

2018-11-09 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas added a comment.

In https://reviews.llvm.org/D53974#1293268, @JonasToth wrote:

> LGTM.
>  Did you run this check in its final form against a bigger project? These 
> results would be interesting.


I'll run it on LibreOffice code again and we'll see.

> Do you have commit access?

Commit access? This is my first patch.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53974



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


[PATCH] D53974: [clang-tidy] new check: bugprone-too-small-loop-variable

2018-11-10 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas added a comment.

I have the result after running the current version if the check.

Found around 50 new issues were hidden by macros:
https://cgit.freedesktop.org/libreoffice/core/commit/?id=afbfe42e63cdba1a18c292d7eb4875009b0f19c0

Also found some new false positives related to macros. The number of all false 
positives is around 38, which is still seems good to me.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53974



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


[PATCH] D53974: [clang-tidy] new check: bugprone-too-small-loop-variable

2018-11-10 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas added a comment.

I also tested on LLVm code.
The output is here:
https://gist.github.com/tzolnai/fe4f23031d3f9fdbdbf1ee38abda00a4

I found 362 warnings.

Around 95% of these warnings are similar to the next example:

  /home/zolnai/lohome/llvm/lib/Support/Chrono.cpp:64:24: warning: loop variable 
has narrower type 'unsigned int' than iteration's upper bound 'size_t' (aka 
'unsigned long') [bugprone-too-small-loop-variable]
for (unsigned I = 0; I < Style.size(); ++I) {

Where the loop variable has an `unsigned int` type while in the loop condition 
it is compared with a container size which has `size_t` type. The actualy size 
method can be std::string::length() or array_lengthof() too.

An interesting catch related to a template function:

  
/home/zolnai/lohome/llvm/tools/clang/lib/CodeGen/CGNonTrivialStruct.cpp:310:24: 
warning: loop variable has narrower type 'unsigned int' than iteration's upper 
bound 'size_t' (aka 'unsigned long') [bugprone-too-small-loop-variable]
for (unsigned I = 0; I < N; ++I)

Where N is a template value with `size_t` type. If the container function is 
instantiated with a "large" value I expect the function won't work. I guess it 
never actually happens.

An other catch inside a macro:

  /home/zolnai/lohome/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp:157:5: 
warning: loop variable has narrower type 'uint32_t' (aka 'unsigned int') than 
iteration's upper bound 'std::vector::size_type' (aka 'unsigned long') 
[bugprone-too-small-loop-variable]
  IMPLEMENT_VECTOR_INTEGER_ICMP(ne,Ty);
  ^
  
/home/zolnai/lohome/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp:123:24: 
note: expanded from macro 'IMPLEMENT_VECTOR_INTEGER_ICMP'
  for( uint32_t _i=0;_ihttps://reviews.llvm.org/D53974



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


[PATCH] D53974: [clang-tidy] new check: bugprone-too-small-loop-variable

2018-11-11 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas updated this revision to Diff 173559.
ztamas added a comment.

- Add new test cases based on findings in LibreOffice code base


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53974

Files:
  clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tidy/bugprone/CMakeLists.txt
  clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
  clang-tidy/bugprone/TooSmallLoopVariableCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/bugprone-too-small-loop-variable.cpp

Index: test/clang-tidy/bugprone-too-small-loop-variable.cpp
===
--- /dev/null
+++ test/clang-tidy/bugprone-too-small-loop-variable.cpp
@@ -0,0 +1,243 @@
+// RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t
+
+long size() { return 294967296l; }
+
+
+/// Test cases correctly caught by bugprone-too-small-loop-variable.
+
+void voidBadForLoop() {
+  for (int i = 0; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop2() {
+  for (int i = 0; i < size() + 10; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop3() {
+  for (int i = 0; i <= size() - 1; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop4() {
+  for (int i = 0; size() > i; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:28: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop5() {
+  for (int i = 0; size() - 1 >= i; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop6() {
+  int i = 0;
+  for (; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidForLoopUnsignedBound() {
+  unsigned size = 3147483647;
+  for (int i = 0; i < size; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than iteration's upper bound 'unsigned int' [bugprone-too-small-loop-variable]
+  }
+}
+
+// The iteration's upper bound has a template dependent value.
+template 
+void doSomething() {
+  for (short i = 0; i < size; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+// The iteration's upper bound has a template dependent type.
+template 
+void doSomething() {
+  for (T i = 0; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: loop variable has narrower type 'short' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidForLoopInstantiation() {
+  // This line does not trigger the warning.
+  doSomething();
+  // This one triggers the warning.
+  doSomething();
+}
+
+// Suspicious funtcion defined by macro.
+#define SUSPICIOUS_SIZE (size())
+void voidBadForLoopWithMacroBound() {
+  for (short i = 0; i < SUSPICIOUS_SIZE; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+
+/// Correct loops: we should not warn here.
+
+// A simple use case when both expressions have the same type.
+void voidGoodForLoop() {
+  for (long i = 0; i < size(); ++i) { // no warning
+  }
+}
+
+// Other use case where both expressions have the same type,
+// but short expressions are converted to int by the compare operator.
+void voidGoodForLoop2() {
+  short loopCond = 10;
+  for (short i = 0; i < loopCond; ++i) { // no warning
+  }
+}
+
+// Because of the integer literal, the iteration's upper bound is int, but we suppress the warning here.
+void voidForLoopShortPlusLiteral() {
+  short size = 3;
+  for (short i = 0; i <= (size - 1); ++i) { // no warning
+  }
+}
+
+// Addition of two short variables results in an int value, but we suppress this to avoid false positives.
+void voidForLoopShortPlusShort() {
+  short size = 256;
+  short increment = 14;
+  for (short i = 0; i < size + increment; ++i) { // no warning
+  }
+}
+
+// In this test case we have different integer types, but here the loop variable has the bigger type.
+// The itera

[PATCH] D53974: [clang-tidy] new check: bugprone-too-small-loop-variable

2018-11-11 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas added a comment.

>> Also found some new false positives related to macros. The number of all 
>> false positives is around 38, which is still seems good to me.
> 
> I would be very interested why these false positives are created. Is there a 
> way to avoid them and maybe it makes sense to already add `FIXME` at the 
> possible places the check needs improvements.

voidForLoopFalsePositive() and voidForLoopFalsePositive2() test cases covers 
most of the false positives found in LibreOffice.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53974



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


[PATCH] D53974: [clang-tidy] new check: bugprone-too-small-loop-variable

2018-11-11 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas updated this revision to Diff 173560.
ztamas added a comment.

- Fix comment


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53974

Files:
  clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tidy/bugprone/CMakeLists.txt
  clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
  clang-tidy/bugprone/TooSmallLoopVariableCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/bugprone-too-small-loop-variable.cpp

Index: test/clang-tidy/bugprone-too-small-loop-variable.cpp
===
--- /dev/null
+++ test/clang-tidy/bugprone-too-small-loop-variable.cpp
@@ -0,0 +1,243 @@
+// RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t
+
+long size() { return 294967296l; }
+
+
+/// Test cases correctly caught by bugprone-too-small-loop-variable.
+
+void voidBadForLoop() {
+  for (int i = 0; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop2() {
+  for (int i = 0; i < size() + 10; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop3() {
+  for (int i = 0; i <= size() - 1; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop4() {
+  for (int i = 0; size() > i; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:28: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop5() {
+  for (int i = 0; size() - 1 >= i; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop6() {
+  int i = 0;
+  for (; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidForLoopUnsignedBound() {
+  unsigned size = 3147483647;
+  for (int i = 0; i < size; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than iteration's upper bound 'unsigned int' [bugprone-too-small-loop-variable]
+  }
+}
+
+// The iteration's upper bound has a template dependent value.
+template 
+void doSomething() {
+  for (short i = 0; i < size; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+// The iteration's upper bound has a template dependent type.
+template 
+void doSomething() {
+  for (T i = 0; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: loop variable has narrower type 'short' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidForLoopInstantiation() {
+  // This line does not trigger the warning.
+  doSomething();
+  // This one triggers the warning.
+  doSomething();
+}
+
+// A suspicious function used in a macro.
+#define SUSPICIOUS_SIZE (size())
+void voidBadForLoopWithMacroBound() {
+  for (short i = 0; i < SUSPICIOUS_SIZE; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+
+/// Correct loops: we should not warn here.
+
+// A simple use case when both expressions have the same type.
+void voidGoodForLoop() {
+  for (long i = 0; i < size(); ++i) { // no warning
+  }
+}
+
+// Other use case where both expressions have the same type,
+// but short expressions are converted to int by the compare operator.
+void voidGoodForLoop2() {
+  short loopCond = 10;
+  for (short i = 0; i < loopCond; ++i) { // no warning
+  }
+}
+
+// Because of the integer literal, the iteration's upper bound is int, but we suppress the warning here.
+void voidForLoopShortPlusLiteral() {
+  short size = 3;
+  for (short i = 0; i <= (size - 1); ++i) { // no warning
+  }
+}
+
+// Addition of two short variables results in an int value, but we suppress this to avoid false positives.
+void voidForLoopShortPlusShort() {
+  short size = 256;
+  short increment = 14;
+  for (short i = 0; i < size + increment; ++i) { // no warning
+  }
+}
+
+// In this test case we have different integer types, but here the loop variable has the bigger type.
+// The iteration's bound is cast implicitly, not the loop var

[PATCH] D53974: [clang-tidy] new check: bugprone-too-small-loop-variable

2018-11-11 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas added a comment.

In https://reviews.llvm.org/D53974#1294659, @JonasToth wrote:

> >> I would be very interested why these false positives are created. Is there 
> >> a way to avoid them and maybe it makes sense to already add `FIXME` at the 
> >> possible places the check needs improvements.
> > 
> > voidForLoopFalsePositive() and voidForLoopFalsePositive2() test cases 
> > covers most of the false positives found in LibreOffice.
>
> I would not consider them as full false positives, the constants that are 
> created allow to filter more, but type-based the diagnostics are correct. So 
> I think that is fine. If the constants would be a big value, the check does 
> find a real problem.


Yes, that's right, these are not full false positives, but the check's main 
focus is on those loops which are runtime dependent. If a loop's upper bound 
can be calculated in compile time then this loop should be caught by a compiler 
warning based on the actual value of that constant. See 
-Wtautological-constant-out-of-range-compare for example. So I think it's the 
best if we can avoid catching these issues using a type based matching.
Anyway, there is not too many of this kind of false positives, so it's not a 
big issue. In LLVM code I did not find any similar case.
I can't see full false positives where the check works incorrectly. The 
detected type mismatch seems correctly detected in every case.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53974



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


[PATCH] D53974: [clang-tidy] new check: bugprone-too-small-loop-variable

2018-11-11 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas updated this revision to Diff 173573.
ztamas added a comment.

- Add requested test case


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53974

Files:
  clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tidy/bugprone/CMakeLists.txt
  clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
  clang-tidy/bugprone/TooSmallLoopVariableCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/bugprone-too-small-loop-variable.cpp

Index: test/clang-tidy/bugprone-too-small-loop-variable.cpp
===
--- /dev/null
+++ test/clang-tidy/bugprone-too-small-loop-variable.cpp
@@ -0,0 +1,251 @@
+// RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t
+
+long size() { return 294967296l; }
+
+
+/// Test cases correctly caught by bugprone-too-small-loop-variable.
+
+void voidBadForLoop() {
+  for (int i = 0; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop2() {
+  for (int i = 0; i < size() + 10; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop3() {
+  for (int i = 0; i <= size() - 1; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop4() {
+  for (int i = 0; size() > i; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:28: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop5() {
+  for (int i = 0; size() - 1 >= i; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidBadForLoop6() {
+  int i = 0;
+  for (; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidForLoopUnsignedBound() {
+  unsigned size = 3147483647;
+  for (int i = 0; i < size; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than iteration's upper bound 'unsigned int' [bugprone-too-small-loop-variable]
+  }
+}
+
+// The iteration's upper bound has a template dependent value.
+template 
+void doSomething() {
+  for (short i = 0; i < size; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+// The iteration's upper bound has a template dependent type.
+template 
+void doSomething() {
+  for (T i = 0; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: loop variable has narrower type 'short' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidForLoopInstantiation() {
+  // This line does not trigger the warning.
+  doSomething();
+  // This one triggers the warning.
+  doSomething();
+}
+
+// A suspicious function used in a macro.
+#define SUSPICIOUS_SIZE (size())
+void voidBadForLoopWithMacroBound() {
+  for (short i = 0; i < SUSPICIOUS_SIZE; ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
+  }
+}
+
+
+/// Correct loops: we should not warn here.
+
+// A simple use case when both expressions have the same type.
+void voidGoodForLoop() {
+  for (long i = 0; i < size(); ++i) { // no warning
+  }
+}
+
+// Other use case where both expressions have the same type,
+// but short expressions are converted to int by the compare operator.
+void voidGoodForLoop2() {
+  short loopCond = 10;
+  for (short i = 0; i < loopCond; ++i) { // no warning
+  }
+}
+
+// Because of the integer literal, the iteration's upper bound is int, but we suppress the warning here.
+void voidForLoopShortPlusLiteral() {
+  short size = 3;
+  for (short i = 0; i <= (size - 1); ++i) { // no warning
+  }
+}
+
+// Addition of two short variables results in an int value, but we suppress this to avoid false positives.
+void voidForLoopShortPlusShort() {
+  short size = 256;
+  short increment = 14;
+  for (short i = 0; i < size + increment; ++i) { // no warning
+  }
+}
+
+// In this test case we have different integer types, but here the loop variable has the bigger type.
+// The iteration's bound is cast implicitly, not 

[PATCH] D53974: [clang-tidy] new check: bugprone-too-small-loop-variable

2018-11-11 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas added a comment.

> Agree. I think this check is good to go.
> 
> I would commit this check tomorrow if that is ok with you.

Of course, It would be great if this check can get in, Thanks!


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53974



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


[PATCH] D53974: [clang-tidy] new check: bugprone-too-small-loop-variable

2018-11-12 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas added a comment.

> Thank you very much for the patch!

Thank you for reviewing!


Repository:
  rL LLVM

https://reviews.llvm.org/D53974



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


[PATCH] D59870: [clang-tidy] Add MagnitudeBitsUpperLimit option to bugprone-too-small-loop-variable

2019-03-27 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas created this revision.
Herald added subscribers: cfe-commits, jdoerfert, xazax.hun.
Herald added a project: clang.

The bugprone-too-small-loop-variable check often catches loop variables which 
can represent "big enough" values, so we don't actually need to worry about 
that this variable will overflow in a loop when the code iterates through a 
container. For example a 32 bit signed integer type's maximum value is 2 147 
483 647 and a container's size won't reach this maximum value in most of the 
cases.
So the idea of this option to allow the user to specify an upper limit (using 
magnitude bit of the integer type) to filter out those catches which are not 
interesting for the user, so he/she can focus on the more risky integer 
incompatibilities.
Next to the option I replaced the term "positive bits" to "magnitude bits" 
which seems a better naming both in the code and in the name of the new option.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D59870

Files:
  clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
  clang-tidy/bugprone/TooSmallLoopVariableCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
  test/clang-tidy/bugprone-too-small-loop-variable-magniute-bits-upper-limit.cpp

Index: test/clang-tidy/bugprone-too-small-loop-variable-magniute-bits-upper-limit.cpp
===
--- /dev/null
+++ test/clang-tidy/bugprone-too-small-loop-variable-magniute-bits-upper-limit.cpp
@@ -0,0 +1,31 @@
+// RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t -- \
+// RUN:   -config="{CheckOptions: \
+// RUN: [{key: bugprone-too-small-loop-variable.MagnitudeBitsUpperLimit, \
+// RUN:   value: 31}]}" \
+// RUN:   -- --target=x86_64-linux
+
+unsigned long size() { return 294967296l; }
+
+void voidFilteredOutForLoop1() {
+  for (long i = 0; i < size(); ++i) {
+// no warning
+  }
+}
+
+void voidFilteredOutForLoop2() {
+  for (unsigned i = 0; i < size(); ++i) {
+// no warning
+  }
+}
+
+void voidCaughtForLoop1() {
+  for (int i = 0; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than iteration's upper bound 'unsigned long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidCaughtForLoop2() {
+  for (short i = 0; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than iteration's upper bound 'unsigned long' [bugprone-too-small-loop-variable]
+  }
+}
Index: docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
===
--- docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
+++ docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
@@ -27,3 +27,20 @@
 
 This algorithm works for small amount of objects, but will lead to freeze for a
 a larger user input.
+
+.. option:: MagnitudeBitsUpperLimit
+
+  Upper limit for the magnitue bits of the loop variable. If it's set the check
+  filters out those catches in which the loop variable's type has more magnitude
+  bit as the specified upper limit.
+  For example, if the user sets this attribute to 31, then a 32-bit ``unsigend int``
+  is ignored by the check, however a 32-bit ``int`` is not (A 32-bit ``signed int``
+  has 31 magnitude bits).
+
+.. code-block:: c++
+
+  int main() {
+long size = 294967296l;
+for (unsigned i = 0; i < size; ++i) {} // no warning
+for (int i = 0; i < size; ++i) {} // warning
+  }
Index: docs/ReleaseNotes.rst
===
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -119,6 +119,10 @@
   `CommentUserDefiniedLiterals`, `CommentStringLiterals`,
   `CommentCharacterLiterals` & `CommentNullPtrs` options.
 
+- The :bugprone-too-small-loop-variable
+  ` now supports
+  `MagnitudeBitsUpperLimit` option.
+
 - The :doc:`google-runtime-int `
   check has been disabled in Objective-C++.
 
Index: clang-tidy/bugprone/TooSmallLoopVariableCheck.h
===
--- clang-tidy/bugprone/TooSmallLoopVariableCheck.h
+++ clang-tidy/bugprone/TooSmallLoopVariableCheck.h
@@ -29,10 +29,14 @@
 /// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-too-small-loop-variable.html
 class TooSmallLoopVariableCheck : public ClangTidyCheck {
 public:
-  TooSmallLoopVariableCheck(StringRef Name, ClangTidyContext *Context)
-  : ClangTidyCheck(Name, Context) {}
+  TooSmallLoopVariableCheck(StringRef Name, ClangTidyContext *Context);
+
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
   void registerMatchers(ast_matchers::MatchFinder *Finder) override;
   void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  const unsigned MagnitudeBitsUpperLimit;
 };
 
 } // namespace bugprone
Index: clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
=

[PATCH] D59870: [clang-tidy] Add MagnitudeBitsUpperLimit option to bugprone-too-small-loop-variable

2019-03-27 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas added a comment.

I run the check with and without the option on llvm source code. Without the 
option I found 370 catches, while setting MagnitudeBitsUpperLimit to `30` I 
found only two catches:

  
/home/zolnai/libreoffice/clang/llvm-project/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp:390:32:
 warning: loop variable has narrower type 'uint16_t' (aka 'unsigned short') 
than iteration's upper bound 'uint32_t' (aka 'unsigned int') 
[bugprone-too-small-loop-variable]
for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
 ^
  
  
/home/zolnai/libreoffice/clang/llvm-project/llvm/tools/llvm-pdbutil/StreamUtil.cpp:98:32:
 warning: loop variable has narrower type 'uint16_t' (aka 'unsigned short') 
than iteration's upper bound 'uint32_t' (aka 'unsigned int') 
[bugprone-too-small-loop-variable]
for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
 ^


Repository:
  rCTE Clang Tools Extra

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59870/new/

https://reviews.llvm.org/D59870



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


[PATCH] D59870: [clang-tidy] Add MagnitudeBitsUpperLimit option to bugprone-too-small-loop-variable

2019-03-27 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas added a comment.

I found a project where the bugprone-too-small-loop-variable was used:
https://github.com/openMSX/openMSX/commit/55006063daffa90941d4c3f9b0034e494d9cf45a

As the commit message says for 32-bit integers the overflow never happens in 
practice.


Repository:
  rCTE Clang Tools Extra

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59870/new/

https://reviews.llvm.org/D59870



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


[PATCH] D59870: [clang-tidy] Add MagnitudeBitsUpperLimit option to bugprone-too-small-loop-variable

2019-03-27 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas marked an inline comment as done.
ztamas added a comment.

In D59870#1444645 , @JonasToth wrote:

> I think in general this is a good direction. What do you think about other 
> heuristics?
>  E.g. one could say that a vector will not contain more then X GB or similar. 
> That is probably more complicated to figure out though.


Yes, it would be very complicated to find out the memory size of the container 
used in the code, I think. The used size method is not always the size() 
function. In llvm code I see also std::string::length() and array_lengthof(). 
Also a code might use a non-standard container, which might have different 
method for getting the size of the container which makes it hard to create a 
matcher for this and find out which container I need to get it's size.

Also the check can catch loops which are not related to containers, so a 
container related option would have no meening in these cases.

I think it's the easiest way to specify the bits of the ineteger type to limit 
the catches. In real life, I met with this overflow / infinite loop problem 
with 16-bit short type, so I think the real use cases are 8 and 16 bit 
integers. It seems intuitive to me to use the size of the loop variable's type 
to separate those catches which can lead broken functionality in practice from 
those use cases which are just integer incompatibilities.




Comment at: docs/ReleaseNotes.rst:122
 
+- The :bugprone-too-small-loop-variable
+  ` now supports

Eugene.Zelenko wrote:
> :doc prefix and ` is missing. Please also rebase patch from trunk.
I'm a bit confused now about the code repositories, because of the recent 
changes. Which repo should I clone and rebase my commit?
Is this one the trunk?: http://llvm.org/svn/llvm-project/llvm/trunk


Repository:
  rCTE Clang Tools Extra

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59870/new/

https://reviews.llvm.org/D59870



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


[PATCH] D59870: [clang-tidy] Add MagnitudeBitsUpperLimit option to bugprone-too-small-loop-variable

2019-03-28 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas updated this revision to Diff 192582.
ztamas added a comment.

Rebased patch on https://github.com/llvm/llvm-project.git repo.
Updated the docs based on review comments.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59870/new/

https://reviews.llvm.org/D59870

Files:
  clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
  
clang-tools-extra/test/clang-tidy/bugprone-too-small-loop-variable-magniute-bits-upper-limit.cpp

Index: clang-tools-extra/test/clang-tidy/bugprone-too-small-loop-variable-magniute-bits-upper-limit.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/bugprone-too-small-loop-variable-magniute-bits-upper-limit.cpp
@@ -0,0 +1,31 @@
+// RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t -- \
+// RUN:   -config="{CheckOptions: \
+// RUN: [{key: bugprone-too-small-loop-variable.MagnitudeBitsUpperLimit, \
+// RUN:   value: 31}]}" \
+// RUN:   -- --target=x86_64-linux
+
+unsigned long size() { return 294967296l; }
+
+void voidFilteredOutForLoop1() {
+  for (long i = 0; i < size(); ++i) {
+// no warning
+  }
+}
+
+void voidFilteredOutForLoop2() {
+  for (unsigned i = 0; i < size(); ++i) {
+// no warning
+  }
+}
+
+void voidCaughtForLoop1() {
+  for (int i = 0; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than iteration's upper bound 'unsigned long' [bugprone-too-small-loop-variable]
+  }
+}
+
+void voidCaughtForLoop2() {
+  for (short i = 0; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than iteration's upper bound 'unsigned long' [bugprone-too-small-loop-variable]
+  }
+}
Index: clang-tools-extra/docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
+++ clang-tools-extra/docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
@@ -27,3 +27,20 @@
 
 This algorithm works for small amount of objects, but will lead to freeze for a
 a larger user input.
+
+.. option:: MagnitudeBitsUpperLimit
+
+  Upper limit for the magnitue bits of the loop variable. If it's set the check
+  filters out those catches in which the loop variable's type has more magnitude
+  bits as the specified upper limit.
+  For example, if the user sets this option to 31 (bits), then a 32-bit ``unsigend int``
+  is ignored by the check, however a 32-bit ``int`` is not (A 32-bit ``signed int``
+  has 31 magnitude bits).
+
+.. code-block:: c++
+
+  int main() {
+long size = 294967296l;
+for (unsigned i = 0; i < size; ++i) {} // no warning with MagnitudeBitsUpperLimit = 31 on a system where unsigned is 32-bit
+for (int i = 0; i < size; ++i) {} // warning with MagnitudeBitsUpperLimit = 31 on a system where int is 32-bit
+  }
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -119,6 +119,10 @@
   `CommentUserDefiniedLiterals`, `CommentStringLiterals`,
   `CommentCharacterLiterals` & `CommentNullPtrs` options.
 
+- The :doc:`bugprone-too-small-loop-variable
+  ` now supports
+  `MagnitudeBitsUpperLimit` option.
+
 - The :doc:`google-runtime-int `
   check has been disabled in Objective-C++.
 
Index: clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.h
===
--- clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.h
+++ clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.h
@@ -29,10 +29,14 @@
 /// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-too-small-loop-variable.html
 class TooSmallLoopVariableCheck : public ClangTidyCheck {
 public:
-  TooSmallLoopVariableCheck(StringRef Name, ClangTidyContext *Context)
-  : ClangTidyCheck(Name, Context) {}
+  TooSmallLoopVariableCheck(StringRef Name, ClangTidyContext *Context);
+
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
   void registerMatchers(ast_matchers::MatchFinder *Finder) override;
   void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  const unsigned MagnitudeBitsUpperLimit;
 };
 
 } // namespace bugprone
Index: clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
===
--- clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
+++ clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
@@ -27,6 +27,17 @@
 static constexpr llvm::StringLiteral LoopI

[PATCH] D59870: [clang-tidy] Add MagnitudeBitsUpperLimit option to bugprone-too-small-loop-variable

2019-03-31 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas added a comment.

In D59870#1446537 , @JonasToth wrote:

> > I think it's the easiest way to specify the bits of the ineteger type to 
> > limit the catches. In real life, I met with this overflow / infinite loop 
> > problem with 16-bit short type, so I think the real use cases are 8 and 16 
> > bit integers. It seems intuitive to me to use the size of the loop 
> > variable's type to separate those catches which can lead broken 
> > functionality in practice from those use cases which are just integer 
> > incompatibilities.
>
> Given your experience and the false positive rate in some projects, should we 
> maybe default to 16 for that option?


Seems a good idea. I'll update the code accordingly.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59870/new/

https://reviews.llvm.org/D59870



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


[PATCH] D59870: [clang-tidy] Add MagnitudeBitsUpperLimit option to bugprone-too-small-loop-variable

2019-03-31 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas updated this revision to Diff 193017.
ztamas added a comment.

Make 16 the default value of MagnitudeBitsUpperLimit option.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59870/new/

https://reviews.llvm.org/D59870

Files:
  clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
  
clang-tools-extra/test/clang-tidy/bugprone-too-small-loop-variable-magniute-bits-upper-limit.cpp
  clang-tools-extra/test/clang-tidy/bugprone-too-small-loop-variable.cpp

Index: clang-tools-extra/test/clang-tidy/bugprone-too-small-loop-variable.cpp
===
--- clang-tools-extra/test/clang-tidy/bugprone-too-small-loop-variable.cpp
+++ clang-tools-extra/test/clang-tidy/bugprone-too-small-loop-variable.cpp
@@ -1,4 +1,8 @@
-// RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t -- -- --target=x86_64-linux
+// RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t -- \
+// RUN:   -config="{CheckOptions: \
+// RUN: [{key: bugprone-too-small-loop-variable.MagnitudeBitsUpperLimit, \
+// RUN:   value: 1024}]}" \
+// RUN:   -- --target=x86_64-linux
 
 long size() { return 294967296l; }
 
Index: clang-tools-extra/test/clang-tidy/bugprone-too-small-loop-variable-magniute-bits-upper-limit.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/bugprone-too-small-loop-variable-magniute-bits-upper-limit.cpp
@@ -0,0 +1,23 @@
+// RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t -- -- --target=x86_64-linux
+
+// MagnitudeBitsUpperLimit = 16 (default value)
+
+unsigned long size() { return 294967296l; }
+
+void voidFilteredOutForLoop1() {
+  for (long i = 0; i < size(); ++i) {
+// no warning
+  }
+}
+
+void voidCaughtForLoop1() {
+  for (int i = 0; i < size(); ++i) {
+// no warning
+  }
+}
+
+void voidCaughtForLoop2() {
+  for (short i = 0; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than iteration's upper bound 'unsigned long' [bugprone-too-small-loop-variable]
+  }
+}
Index: clang-tools-extra/docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
+++ clang-tools-extra/docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
@@ -27,3 +27,20 @@
 
 This algorithm works for small amount of objects, but will lead to freeze for a
 a larger user input.
+
+.. option:: MagnitudeBitsUpperLimit
+
+  Upper limit for the magnitue bits of the loop variable. If it's set the check
+  filters out those catches in which the loop variable's type has more magnitude
+  bits as the specified upper limit. The default value is 16.
+  For example, if the user sets this option to 31 (bits), then a 32-bit ``unsigend int``
+  is ignored by the check, however a 32-bit ``int`` is not (A 32-bit ``signed int``
+  has 31 magnitude bits).
+
+.. code-block:: c++
+
+  int main() {
+long size = 294967296l;
+for (unsigned i = 0; i < size; ++i) {} // no warning with MagnitudeBitsUpperLimit = 31 on a system where unsigned is 32-bit
+for (int i = 0; i < size; ++i) {} // warning with MagnitudeBitsUpperLimit = 31 on a system where int is 32-bit
+  }
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -119,6 +119,10 @@
   `CommentUserDefiniedLiterals`, `CommentStringLiterals`,
   `CommentCharacterLiterals` & `CommentNullPtrs` options.
 
+- The :doc:`bugprone-too-small-loop-variable
+  ` now supports
+  `MagnitudeBitsUpperLimit` option.
+
 - The :doc:`google-runtime-int `
   check has been disabled in Objective-C++.
 
Index: clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.h
===
--- clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.h
+++ clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.h
@@ -29,10 +29,14 @@
 /// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-too-small-loop-variable.html
 class TooSmallLoopVariableCheck : public ClangTidyCheck {
 public:
-  TooSmallLoopVariableCheck(StringRef Name, ClangTidyContext *Context)
-  : ClangTidyCheck(Name, Context) {}
+  TooSmallLoopVariableCheck(StringRef Name, ClangTidyContext *Context);
+
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
   void registerMatchers(ast_matchers::MatchFinder *Finder) override;
   void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  const unsigned MagnitudeBitsUp

[PATCH] D59870: [clang-tidy] Add MagnitudeBitsUpperLimit option to bugprone-too-small-loop-variable

2019-04-02 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas updated this revision to Diff 193277.
ztamas added a comment.

Fixed typo.
Mentioned the default value in release notes.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59870/new/

https://reviews.llvm.org/D59870

Files:
  clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
  
clang-tools-extra/test/clang-tidy/bugprone-too-small-loop-variable-magniute-bits-upper-limit.cpp
  clang-tools-extra/test/clang-tidy/bugprone-too-small-loop-variable.cpp

Index: clang-tools-extra/test/clang-tidy/bugprone-too-small-loop-variable.cpp
===
--- clang-tools-extra/test/clang-tidy/bugprone-too-small-loop-variable.cpp
+++ clang-tools-extra/test/clang-tidy/bugprone-too-small-loop-variable.cpp
@@ -1,4 +1,8 @@
-// RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t -- -- --target=x86_64-linux
+// RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t -- \
+// RUN:   -config="{CheckOptions: \
+// RUN: [{key: bugprone-too-small-loop-variable.MagnitudeBitsUpperLimit, \
+// RUN:   value: 1024}]}" \
+// RUN:   -- --target=x86_64-linux
 
 long size() { return 294967296l; }
 
Index: clang-tools-extra/test/clang-tidy/bugprone-too-small-loop-variable-magniute-bits-upper-limit.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/bugprone-too-small-loop-variable-magniute-bits-upper-limit.cpp
@@ -0,0 +1,23 @@
+// RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t -- -- --target=x86_64-linux
+
+// MagnitudeBitsUpperLimit = 16 (default value)
+
+unsigned long size() { return 294967296l; }
+
+void voidFilteredOutForLoop1() {
+  for (long i = 0; i < size(); ++i) {
+// no warning
+  }
+}
+
+void voidCaughtForLoop1() {
+  for (int i = 0; i < size(); ++i) {
+// no warning
+  }
+}
+
+void voidCaughtForLoop2() {
+  for (short i = 0; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than iteration's upper bound 'unsigned long' [bugprone-too-small-loop-variable]
+  }
+}
Index: clang-tools-extra/docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
+++ clang-tools-extra/docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
@@ -27,3 +27,20 @@
 
 This algorithm works for small amount of objects, but will lead to freeze for a
 a larger user input.
+
+.. option:: MagnitudeBitsUpperLimit
+
+  Upper limit for the magnitude bits of the loop variable. If it's set the check
+  filters out those catches in which the loop variable's type has more magnitude
+  bits as the specified upper limit. The default value is 16.
+  For example, if the user sets this option to 31 (bits), then a 32-bit ``unsigend int``
+  is ignored by the check, however a 32-bit ``int`` is not (A 32-bit ``signed int``
+  has 31 magnitude bits).
+
+.. code-block:: c++
+
+  int main() {
+long size = 294967296l;
+for (unsigned i = 0; i < size; ++i) {} // no warning with MagnitudeBitsUpperLimit = 31 on a system where unsigned is 32-bit
+for (int i = 0; i < size; ++i) {} // warning with MagnitudeBitsUpperLimit = 31 on a system where int is 32-bit
+  }
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -119,6 +119,12 @@
   `CommentUserDefiniedLiterals`, `CommentStringLiterals`,
   `CommentCharacterLiterals` & `CommentNullPtrs` options.
 
+- The :doc:`bugprone-too-small-loop-variable
+  ` now supports
+  `MagnitudeBitsUpperLimit` option. The default value is to 16,
+  which greatly reduces warnings related to loops which are unlikely to
+  cause an actual functional bug.
+
 - The :doc:`google-runtime-int `
   check has been disabled in Objective-C++.
 
Index: clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.h
===
--- clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.h
+++ clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.h
@@ -29,10 +29,14 @@
 /// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-too-small-loop-variable.html
 class TooSmallLoopVariableCheck : public ClangTidyCheck {
 public:
-  TooSmallLoopVariableCheck(StringRef Name, ClangTidyContext *Context)
-  : ClangTidyCheck(Name, Context) {}
+  TooSmallLoopVariableCheck(StringRef Name, ClangTidyContext *Context);
+
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
   void registerMatchers(ast_matchers::MatchFinder *Finder)

[PATCH] D59870: [clang-tidy] Add MagnitudeBitsUpperLimit option to bugprone-too-small-loop-variable

2019-04-02 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas marked 3 inline comments as done.
ztamas added inline comments.



Comment at: 
clang-tools-extra/docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst:33
+
+  Upper limit for the magnitue bits of the loop variable. If it's set the check
+  filters out those catches in which the loop variable's type has more 
magnitude

JonasToth wrote:
> typo `magnitude`
> 
> The commit you reference to the project fixing the "bugs" stated, that the 
> version without conversions is more efficient (by one instruction :)). I 
> think this might be worth a note, that even though the
> code is not a bug in itself it might still be preferable to remove those code 
> locations in the long run.
Typo is fixed

The referenced commit message mentions 32 bit system, where changing integer 
types was a bit faster. I'm not sure how general this is. I'm not familiar with 
the low level implementation of integer comparison, so I would not mention 
something, that I don't actually understand how it works.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59870/new/

https://reviews.llvm.org/D59870



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


[PATCH] D59870: [clang-tidy] Add MagnitudeBitsUpperLimit option to bugprone-too-small-loop-variable

2019-04-09 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas updated this revision to Diff 194261.
ztamas added a comment.

Fixed a typo in release notes.
Rebased the patch withh git pull -r.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59870/new/

https://reviews.llvm.org/D59870

Files:
  clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
  
clang-tools-extra/test/clang-tidy/bugprone-too-small-loop-variable-magniute-bits-upper-limit.cpp
  clang-tools-extra/test/clang-tidy/bugprone-too-small-loop-variable.cpp

Index: clang-tools-extra/test/clang-tidy/bugprone-too-small-loop-variable.cpp
===
--- clang-tools-extra/test/clang-tidy/bugprone-too-small-loop-variable.cpp
+++ clang-tools-extra/test/clang-tidy/bugprone-too-small-loop-variable.cpp
@@ -1,4 +1,8 @@
-// RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t -- -- --target=x86_64-linux
+// RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t -- \
+// RUN:   -config="{CheckOptions: \
+// RUN: [{key: bugprone-too-small-loop-variable.MagnitudeBitsUpperLimit, \
+// RUN:   value: 1024}]}" \
+// RUN:   -- --target=x86_64-linux
 
 long size() { return 294967296l; }
 
Index: clang-tools-extra/test/clang-tidy/bugprone-too-small-loop-variable-magniute-bits-upper-limit.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/bugprone-too-small-loop-variable-magniute-bits-upper-limit.cpp
@@ -0,0 +1,23 @@
+// RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t -- -- --target=x86_64-linux
+
+// MagnitudeBitsUpperLimit = 16 (default value)
+
+unsigned long size() { return 294967296l; }
+
+void voidFilteredOutForLoop1() {
+  for (long i = 0; i < size(); ++i) {
+// no warning
+  }
+}
+
+void voidCaughtForLoop1() {
+  for (int i = 0; i < size(); ++i) {
+// no warning
+  }
+}
+
+void voidCaughtForLoop2() {
+  for (short i = 0; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than iteration's upper bound 'unsigned long' [bugprone-too-small-loop-variable]
+  }
+}
Index: clang-tools-extra/docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
+++ clang-tools-extra/docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
@@ -27,3 +27,20 @@
 
 This algorithm works for small amount of objects, but will lead to freeze for a
 a larger user input.
+
+.. option:: MagnitudeBitsUpperLimit
+
+  Upper limit for the magnitude bits of the loop variable. If it's set the check
+  filters out those catches in which the loop variable's type has more magnitude
+  bits as the specified upper limit. The default value is 16.
+  For example, if the user sets this option to 31 (bits), then a 32-bit ``unsigend int``
+  is ignored by the check, however a 32-bit ``int`` is not (A 32-bit ``signed int``
+  has 31 magnitude bits).
+
+.. code-block:: c++
+
+  int main() {
+long size = 294967296l;
+for (unsigned i = 0; i < size; ++i) {} // no warning with MagnitudeBitsUpperLimit = 31 on a system where unsigned is 32-bit
+for (int i = 0; i < size; ++i) {} // warning with MagnitudeBitsUpperLimit = 31 on a system where int is 32-bit
+  }
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -119,6 +119,12 @@
   `CommentUserDefiniedLiterals`, `CommentStringLiterals`,
   `CommentCharacterLiterals` & `CommentNullPtrs` options.
 
+- The :doc:`bugprone-too-small-loop-variable
+  ` now supports
+  `MagnitudeBitsUpperLimit` option. The default value was set to 16,
+  which greatly reduces warnings related to loops which are unlikely to
+  cause an actual functional bug.
+
 - The :doc:`google-runtime-int `
   check has been disabled in Objective-C++.
 
Index: clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.h
===
--- clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.h
+++ clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.h
@@ -29,10 +29,14 @@
 /// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-too-small-loop-variable.html
 class TooSmallLoopVariableCheck : public ClangTidyCheck {
 public:
-  TooSmallLoopVariableCheck(StringRef Name, ClangTidyContext *Context)
-  : ClangTidyCheck(Name, Context) {}
+  TooSmallLoopVariableCheck(StringRef Name, ClangTidyContext *Context);
+
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
   void registerMatchers(ast_matchers::Match

[PATCH] D59870: [clang-tidy] Add MagnitudeBitsUpperLimit option to bugprone-too-small-loop-variable

2019-04-09 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas added a comment.

Ok, I just fixed a remaining typo and rebased the patch to have it work with a 
more recent version of the code base, so I guess this patch is ready for commit.
Jonas, can you commit this change for me? I still don't have commit access, I 
just applied for it some days ago.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59870/new/

https://reviews.llvm.org/D59870



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


[PATCH] D60507: [clang-tidy] new check: bugprone-unhandled-self-assignment

2019-04-10 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas created this revision.
Herald added subscribers: cfe-commits, xazax.hun, mgorny.
Herald added a project: clang.

This check searches for copy assignment operators which might not handle 
self-assignment properly. There are three patterns of
handling a self assignment situation: self check, copy-and-swap or the less 
common copy-and-move. The new check warns if none of
these patterns is found in a user defined implementation.

See also:
OOP54-CPP. Gracefully handle self-copy assignment
https://wiki.sei.cmu.edu/confluence/display/cplusplus/OOP54-CPP.+Gracefully+handle+self-copy+assignment


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D60507

Files:
  clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
  clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp

Index: clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp
@@ -0,0 +1,351 @@
+// RUN: %check_clang_tidy %s bugprone-unhandled-self-assignment %t
+
+namespace std {
+
+template 
+void swap(T x, T y) {
+}
+
+template 
+T &&move(T x) {
+}
+
+template 
+class unique_ptr {
+};
+
+template 
+class shared_ptr {
+};
+
+template 
+class weak_ptr {
+};
+
+} // namespace std
+
+void assert(int expression){};
+
+///
+/// Test cases correctly caught by the check.
+
+class PtrField {
+public:
+  PtrField &operator=(const PtrField &object);
+
+private:
+  int *p;
+};
+
+PtrField &PtrField::operator=(const PtrField &object) {
+  // CHECK-MESSAGES: [[@LINE-1]]:21: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+  // ...
+  return *this;
+}
+
+// Class with an inline operator definition.
+class InlineDefinition {
+public:
+  InlineDefinition &operator=(const InlineDefinition &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:21: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  int *p;
+};
+
+class UniquePtrField {
+public:
+  UniquePtrField &operator=(const UniquePtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::unique_ptr p;
+};
+
+class SharedPtrField {
+public:
+  SharedPtrField &operator=(const SharedPtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::shared_ptr p;
+};
+
+class WeakPtrField {
+public:
+  WeakPtrField &operator=(const WeakPtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:17: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::weak_ptr p;
+};
+
+// Class with C array field.
+class CArrayField {
+public:
+  CArrayField &operator=(const CArrayField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:16: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  int array[256];
+};
+
+// Make sure to not ignore cases when the operator definition calls
+// a copy constructor of another class.
+class CopyConstruct {
+public:
+  CopyConstruct &operator=(const CopyConstruct &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:18: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+WeakPtrField a;
+WeakPtrField b(a);
+// ...
+return *this;
+  }
+
+private:
+  int *p;
+};
+
+// Make sure to not ignore cases when the operator definition calls
+// a copy assignment operator of another class.
+class AssignOperator {
+public:
+  AssignOperator &operator=(const AssignOperator &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+a.operator=(object.a);
+// ...
+return *this;
+  }
+
+private:
+  int *p;
+  WeakPtrField a;
+};
+
+///
+/// Test cases correctly ignored by the check.
+
+// Self-assignment is checked using the equality operator.
+class SelfCheck1 {
+public:
+  SelfCheck1 &operator=(const SelfCheck1 &obje

[PATCH] D60507: [clang-tidy] new check: bugprone-unhandled-self-assignment

2019-04-10 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas added a comment.

On llvm source code the check finds three suspicious methods:

  
/home/zolnai/libreoffice/clang/llvm-project/clang/lib/AST/NestedNameSpecifier.cpp:534:1:
 warning: operator=() might not handle self-assignment properly 
[bugprone-unhandled-self-assignment]
  operator=(const NestedNameSpecifierLocBuilder &Other) {
  
  
/home/zolnai/libreoffice/clang/llvm-project/llvm/unittests/ADT/ArrayRefTest.cpp:75:10:
 warning: operator=() might not handle self-assignment properly 
[bugprone-unhandled-self-assignment]
  void operator=(const NonAssignable &RHS) { assert(RHS.Ptr != nullptr); }
  
  
/home/zolnai/libreoffice/clang/llvm-project/llvm/lib/Analysis/TargetLibraryInfo.cpp:594:47:
 warning: operator=() might not handle self-assignment properly 
[bugprone-unhandled-self-assignment]
  TargetLibraryInfoImpl &TargetLibraryInfoImpl::operator=(const 
TargetLibraryInfoImpl &TLI) {

Two of them seems a good catch to me. NestedNameSpecifierLocBuilder and 
TargetLibraryInfoImpl are using `memcpy` without self-check, and using `memcpy` 
on overlapping regions leads to undefined behavior.

The third one is not an actual working copy assignment operator, as I see. It 
is used only for some testing purposes.


Repository:
  rCTE Clang Tools Extra

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D60507/new/

https://reviews.llvm.org/D60507



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


[PATCH] D60507: [clang-tidy] new check: bugprone-unhandled-self-assignment

2019-04-10 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas added a comment.

On LibreOffice source code I found 36 catches with this check.
16 of them was worth to fix because in those cases the object state was changed 
in some way after a self-assignment:
https://cgit.freedesktop.org/libreoffice/core/commit/?id=3a5d78365dd172881c16c03e67f2d170ffc6d7d4

The remaining 20 are false positives. They are working copy assignment 
operators without using any of the three checked patterns.
However, some of these warnings could be suppressed with modernizing the code 
or with removing code duplication:
https://cgit.freedesktop.org/libreoffice/core/commit/?id=adfba503c792fdbd4748d6680c2dd8d8d5bb0d69


Repository:
  rCTE Clang Tools Extra

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D60507/new/

https://reviews.llvm.org/D60507



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


[PATCH] D60507: [clang-tidy] new check: bugprone-unhandled-self-assignment

2019-04-11 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas added a comment.

I'll update the patch based on the comments.
Just a note about the false positive ratio. In LibreOffice we run other static 
analyzers too, that's why there were less positive catches there than false 
positives. For example, PVS studio also catches unprotected copy assignment 
operators. Some of these issues were already fixed before I run this new check 
on the code:
https://cgit.freedesktop.org/libreoffice/core/commit/?id=e5e0cc68f70d35e1849aeaf21c0ce68afd6a1f59


Repository:
  rCTE Clang Tools Extra

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D60507/new/

https://reviews.llvm.org/D60507



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


[PATCH] D60507: [clang-tidy] new check: bugprone-unhandled-self-assignment

2019-04-12 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas updated this revision to Diff 194921.
ztamas added a comment.

Updated the code based on reviewer comments:

- Alphabetical order in `BugproneTidyModule.cpp`
- Handling of `auto_ptr`
- Test cases for template classes (I made the check ignore these case otherwise 
this can lead to false positives)
- Added cert alias
- Simplified the matcher as requested (`hasAnyName()`, 
`has(ignoringParenCasts(cxxThisExpr())`
- Remove empty lines and synchronized the corresponding comment with the 
Release Notes.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D60507/new/

https://reviews.llvm.org/D60507

Files:
  clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
  clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst
  clang-tools-extra/docs/clang-tidy/checks/cert-oop54-cpp.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp

Index: clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp
@@ -0,0 +1,434 @@
+// RUN: %check_clang_tidy %s bugprone-unhandled-self-assignment %t
+
+namespace std {
+
+template 
+void swap(T x, T y) {
+}
+
+template 
+T &&move(T x) {
+}
+
+template 
+class unique_ptr {
+};
+
+template 
+class shared_ptr {
+};
+
+template 
+class weak_ptr {
+};
+
+template 
+class auto_ptr {
+};
+
+} // namespace std
+
+void assert(int expression){};
+
+///
+/// Test cases correctly caught by the check.
+
+class PtrField {
+public:
+  PtrField &operator=(const PtrField &object);
+
+private:
+  int *p;
+};
+
+PtrField &PtrField::operator=(const PtrField &object) {
+  // CHECK-MESSAGES: [[@LINE-1]]:21: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+  // ...
+  return *this;
+}
+
+// Class with an inline operator definition.
+class InlineDefinition {
+public:
+  InlineDefinition &operator=(const InlineDefinition &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:21: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  int *p;
+};
+
+class UniquePtrField {
+public:
+  UniquePtrField &operator=(const UniquePtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::unique_ptr p;
+};
+
+class SharedPtrField {
+public:
+  SharedPtrField &operator=(const SharedPtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::shared_ptr p;
+};
+
+class WeakPtrField {
+public:
+  WeakPtrField &operator=(const WeakPtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:17: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::weak_ptr p;
+};
+
+class AutoPtrField {
+public:
+  AutoPtrField &operator=(const AutoPtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:17: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::auto_ptr p;
+};
+
+// Class with C array field.
+class CArrayField {
+public:
+  CArrayField &operator=(const CArrayField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:16: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  int array[256];
+};
+
+// Make sure to not ignore cases when the operator definition calls
+// a copy constructor of another class.
+class CopyConstruct {
+public:
+  CopyConstruct &operator=(const CopyConstruct &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:18: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+WeakPtrField a;
+WeakPtrField b(a);
+// ...
+return *this;
+  }
+
+private:
+  int *p;
+};
+
+// Make sure to not ignore cases when the operator definition calls
+// a copy assignment operator of another class.
+class AssignOperator {
+public:
+  AssignOperator &operator=(const AssignOperator &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+a.operator=(object.a);
+   

[PATCH] D60507: [clang-tidy] new check: bugprone-unhandled-self-assignment

2019-04-12 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas marked 13 inline comments as done.
ztamas added inline comments.



Comment at: 
clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst:10
+
+This check corresponds to the CERT C++ Coding Standard rule
+`OOP54-CPP. Gracefully handle self-copy assignment

aaron.ballman wrote:
> Eugene.Zelenko wrote:
> > alexfh wrote:
> > > JonasToth wrote:
> > > > It is worth an alias into the cert module. Please add this with this 
> > > > revision already.
> > > Please add a corresponding alias into the cert module.
> > See also other aliased checks for documentation examples.
> I kind of wonder whether we want it as an alias in the CERT module or just 
> move it into the CERT module directly (and maybe provide an alias to 
> bugprone, if we think the fp rate is reasonable enough).
Now, I just added a cert alias. I can move this check to cert module entirely 
if needed. In general, I prefer a meaningful name over a cert number, that's 
why it might be more useful to have also a bugprone prefixed check for this. 
And it seems to me cert checks used to be the aliases.



Comment at: 
clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp:351
+  int *p;
+};

JonasToth wrote:
> Please add tests with templated classes and self-assignment.
I tested with template classes, but TemplateCopyAndSwap test case, for example, 
was wrongly caught by the check. So I just changed the code to ignore template 
classes. I did not find any template class related catch either in LibreOffice 
or LLVM when I run the first version of this check, so we don't lose too much 
with ignoring template classes, I think.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D60507/new/

https://reviews.llvm.org/D60507



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


[PATCH] D60507: [clang-tidy] new check: bugprone-unhandled-self-assignment

2019-04-12 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas updated this revision to Diff 194925.
ztamas marked an inline comment as done.
ztamas added a comment.

Documentation fixes.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D60507/new/

https://reviews.llvm.org/D60507

Files:
  clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
  clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst
  clang-tools-extra/docs/clang-tidy/checks/cert-oop54-cpp.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp

Index: clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp
@@ -0,0 +1,434 @@
+// RUN: %check_clang_tidy %s bugprone-unhandled-self-assignment %t
+
+namespace std {
+
+template 
+void swap(T x, T y) {
+}
+
+template 
+T &&move(T x) {
+}
+
+template 
+class unique_ptr {
+};
+
+template 
+class shared_ptr {
+};
+
+template 
+class weak_ptr {
+};
+
+template 
+class auto_ptr {
+};
+
+} // namespace std
+
+void assert(int expression){};
+
+///
+/// Test cases correctly caught by the check.
+
+class PtrField {
+public:
+  PtrField &operator=(const PtrField &object);
+
+private:
+  int *p;
+};
+
+PtrField &PtrField::operator=(const PtrField &object) {
+  // CHECK-MESSAGES: [[@LINE-1]]:21: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+  // ...
+  return *this;
+}
+
+// Class with an inline operator definition.
+class InlineDefinition {
+public:
+  InlineDefinition &operator=(const InlineDefinition &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:21: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  int *p;
+};
+
+class UniquePtrField {
+public:
+  UniquePtrField &operator=(const UniquePtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::unique_ptr p;
+};
+
+class SharedPtrField {
+public:
+  SharedPtrField &operator=(const SharedPtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::shared_ptr p;
+};
+
+class WeakPtrField {
+public:
+  WeakPtrField &operator=(const WeakPtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:17: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::weak_ptr p;
+};
+
+class AutoPtrField {
+public:
+  AutoPtrField &operator=(const AutoPtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:17: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::auto_ptr p;
+};
+
+// Class with C array field.
+class CArrayField {
+public:
+  CArrayField &operator=(const CArrayField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:16: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  int array[256];
+};
+
+// Make sure to not ignore cases when the operator definition calls
+// a copy constructor of another class.
+class CopyConstruct {
+public:
+  CopyConstruct &operator=(const CopyConstruct &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:18: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+WeakPtrField a;
+WeakPtrField b(a);
+// ...
+return *this;
+  }
+
+private:
+  int *p;
+};
+
+// Make sure to not ignore cases when the operator definition calls
+// a copy assignment operator of another class.
+class AssignOperator {
+public:
+  AssignOperator &operator=(const AssignOperator &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+a.operator=(object.a);
+// ...
+return *this;
+  }
+
+private:
+  int *p;
+  WeakPtrField a;
+};
+
+///
+/// Test cases correctly ignored by the check.
+
+// Self-assignment is checked using the equality operator.
+class SelfCheck1 {
+public:
+  SelfCheck1 &operator=(const SelfCheck1 &object) {
+if (this == &object)
+  ret

[PATCH] D59870: [clang-tidy] Add MagnitudeBitsUpperLimit option to bugprone-too-small-loop-variable

2019-04-13 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas added a comment.

In the meantime, I've got the commit access, so I'll give it a try to push this 
myself.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59870/new/

https://reviews.llvm.org/D59870



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


[PATCH] D59870: [clang-tidy] Add MagnitudeBitsUpperLimit option to bugprone-too-small-loop-variable

2019-04-14 Thread Tamás Zolnai via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL358356: [clang-tidy] Add MagnitudeBitsUpperLimit option to  
bugprone-too-small-loop… (authored by ztamas, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D59870?vs=194261&id=195058#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59870/new/

https://reviews.llvm.org/D59870

Files:
  clang-tools-extra/trunk/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
  clang-tools-extra/trunk/clang-tidy/bugprone/TooSmallLoopVariableCheck.h
  clang-tools-extra/trunk/docs/ReleaseNotes.rst
  
clang-tools-extra/trunk/docs/clang-tidy/checks/bugprone-too-small-loop-variable.rst
  
clang-tools-extra/trunk/test/clang-tidy/bugprone-too-small-loop-variable-magniute-bits-upper-limit.cpp
  clang-tools-extra/trunk/test/clang-tidy/bugprone-too-small-loop-variable.cpp

Index: clang-tools-extra/trunk/test/clang-tidy/bugprone-too-small-loop-variable-magniute-bits-upper-limit.cpp
===
--- clang-tools-extra/trunk/test/clang-tidy/bugprone-too-small-loop-variable-magniute-bits-upper-limit.cpp
+++ clang-tools-extra/trunk/test/clang-tidy/bugprone-too-small-loop-variable-magniute-bits-upper-limit.cpp
@@ -0,0 +1,23 @@
+// RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t -- -- --target=x86_64-linux
+
+// MagnitudeBitsUpperLimit = 16 (default value)
+
+unsigned long size() { return 294967296l; }
+
+void voidFilteredOutForLoop1() {
+  for (long i = 0; i < size(); ++i) {
+// no warning
+  }
+}
+
+void voidCaughtForLoop1() {
+  for (int i = 0; i < size(); ++i) {
+// no warning
+  }
+}
+
+void voidCaughtForLoop2() {
+  for (short i = 0; i < size(); ++i) {
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than iteration's upper bound 'unsigned long' [bugprone-too-small-loop-variable]
+  }
+}
Index: clang-tools-extra/trunk/test/clang-tidy/bugprone-too-small-loop-variable.cpp
===
--- clang-tools-extra/trunk/test/clang-tidy/bugprone-too-small-loop-variable.cpp
+++ clang-tools-extra/trunk/test/clang-tidy/bugprone-too-small-loop-variable.cpp
@@ -1,4 +1,8 @@
-// RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t -- -- --target=x86_64-linux
+// RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t -- \
+// RUN:   -config="{CheckOptions: \
+// RUN: [{key: bugprone-too-small-loop-variable.MagnitudeBitsUpperLimit, \
+// RUN:   value: 1024}]}" \
+// RUN:   -- --target=x86_64-linux
 
 long size() { return 294967296l; }
 
Index: clang-tools-extra/trunk/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
===
--- clang-tools-extra/trunk/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
+++ clang-tools-extra/trunk/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
@@ -27,6 +27,17 @@
 static constexpr llvm::StringLiteral LoopIncrementName =
 llvm::StringLiteral("loopIncrement");
 
+TooSmallLoopVariableCheck::TooSmallLoopVariableCheck(StringRef Name,
+ ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  MagnitudeBitsUpperLimit(Options.get(
+  "MagnitudeBitsUpperLimit", 16)) {}
+
+void TooSmallLoopVariableCheck::storeOptions(
+ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "MagnitudeBitsUpperLimit", MagnitudeBitsUpperLimit);
+}
+
 /// \brief The matcher for loops with suspicious integer loop variable.
 ///
 /// In this general example, assuming 'j' and 'k' are of integral type:
@@ -84,9 +95,9 @@
   this);
 }
 
-/// Returns the positive part of the integer width for an integer type.
-static unsigned calcPositiveBits(const ASTContext &Context,
- const QualType &IntExprType) {
+/// Returns the magnitude bits of an integer type.
+static unsigned calcMagnitudeBits(const ASTContext &Context,
+  const QualType &IntExprType) {
   assert(IntExprType->isIntegerType());
 
   return IntExprType->isUnsignedIntegerType()
@@ -94,13 +105,13 @@
  : Context.getIntWidth(IntExprType) - 1;
 }
 
-/// \brief Calculate the upper bound expression's positive bits, but ignore
+/// \brief Calculate the upper bound expression's magnitude bits, but ignore
 /// constant like values to reduce false positives.
-static unsigned calcUpperBoundPositiveBits(const ASTContext &Context,
-   const Expr *UpperBound,
-   const QualType &UpperBoundType) {
+static unsigned calcUpperBoundMagnitudeBits(const ASTContext &Context,
+const Expr *UpperBound,
+const QualType &

[PATCH] D60507: [clang-tidy] new check: bugprone-unhandled-self-assignment

2019-04-14 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas updated this revision to Diff 195061.
ztamas added a comment.

Missed to syncronize ReleasNotes with the corresponding doc.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D60507/new/

https://reviews.llvm.org/D60507

Files:
  clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
  clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst
  clang-tools-extra/docs/clang-tidy/checks/cert-oop54-cpp.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp

Index: clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp
@@ -0,0 +1,434 @@
+// RUN: %check_clang_tidy %s bugprone-unhandled-self-assignment %t
+
+namespace std {
+
+template 
+void swap(T x, T y) {
+}
+
+template 
+T &&move(T x) {
+}
+
+template 
+class unique_ptr {
+};
+
+template 
+class shared_ptr {
+};
+
+template 
+class weak_ptr {
+};
+
+template 
+class auto_ptr {
+};
+
+} // namespace std
+
+void assert(int expression){};
+
+///
+/// Test cases correctly caught by the check.
+
+class PtrField {
+public:
+  PtrField &operator=(const PtrField &object);
+
+private:
+  int *p;
+};
+
+PtrField &PtrField::operator=(const PtrField &object) {
+  // CHECK-MESSAGES: [[@LINE-1]]:21: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+  // ...
+  return *this;
+}
+
+// Class with an inline operator definition.
+class InlineDefinition {
+public:
+  InlineDefinition &operator=(const InlineDefinition &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:21: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  int *p;
+};
+
+class UniquePtrField {
+public:
+  UniquePtrField &operator=(const UniquePtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::unique_ptr p;
+};
+
+class SharedPtrField {
+public:
+  SharedPtrField &operator=(const SharedPtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::shared_ptr p;
+};
+
+class WeakPtrField {
+public:
+  WeakPtrField &operator=(const WeakPtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:17: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::weak_ptr p;
+};
+
+class AutoPtrField {
+public:
+  AutoPtrField &operator=(const AutoPtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:17: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::auto_ptr p;
+};
+
+// Class with C array field.
+class CArrayField {
+public:
+  CArrayField &operator=(const CArrayField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:16: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  int array[256];
+};
+
+// Make sure to not ignore cases when the operator definition calls
+// a copy constructor of another class.
+class CopyConstruct {
+public:
+  CopyConstruct &operator=(const CopyConstruct &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:18: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+WeakPtrField a;
+WeakPtrField b(a);
+// ...
+return *this;
+  }
+
+private:
+  int *p;
+};
+
+// Make sure to not ignore cases when the operator definition calls
+// a copy assignment operator of another class.
+class AssignOperator {
+public:
+  AssignOperator &operator=(const AssignOperator &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+a.operator=(object.a);
+// ...
+return *this;
+  }
+
+private:
+  int *p;
+  WeakPtrField a;
+};
+
+///
+/// Test cases correctly ignored by the check.
+
+// Self-assignment is checked using the equality operator.
+class SelfCheck1 {
+public:
+  SelfCheck1 &operator=(const SelfCheck1 &object) 

[PATCH] D60507: [clang-tidy] new check: bugprone-unhandled-self-assignment

2019-04-14 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas marked an inline comment as done.
ztamas added inline comments.



Comment at: 
clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp:51
+  // Matcher for standard smart pointers.
+  const auto SmartPointerType = qualType(hasUnqualifiedDesugaredType(
+  recordType(hasDeclaration(classTemplateSpecializationDecl(

xazax.hun wrote:
> JonasToth wrote:
> > what about `auto_ptr`? I am actually not sure if we should care, as its 
> > deprecated and removed already, on the other hand legacy code probably 
> > still has it.
> I am perfectly fine with addressing this in a follow-up patch or even not 
> addressing at all, but I think for some users it might be useful to be able 
> to specify a set of suspicious types as a configuration option such as custom 
> smart pointers, handles and so on. 
Seems a good idea for a follow-up change.
Actually, with an earlier version of this patch I found another vulnerable copy 
assignment operator in llvm code which uses a custom pointer type 
(PointerIntPair):
FunctionInfo &operator=(const FunctionInfo &RHS)


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D60507/new/

https://reviews.llvm.org/D60507



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


[PATCH] D60507: [clang-tidy] new check: bugprone-unhandled-self-assignment

2019-04-16 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas updated this revision to Diff 195382.
ztamas added a comment.

Update patch based on reviewer comments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D60507/new/

https://reviews.llvm.org/D60507

Files:
  clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
  clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst
  clang-tools-extra/docs/clang-tidy/checks/cert-oop54-cpp.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp

Index: clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp
@@ -0,0 +1,434 @@
+// RUN: %check_clang_tidy %s bugprone-unhandled-self-assignment %t
+
+namespace std {
+
+template 
+void swap(T x, T y) {
+}
+
+template 
+T &&move(T x) {
+}
+
+template 
+class unique_ptr {
+};
+
+template 
+class shared_ptr {
+};
+
+template 
+class weak_ptr {
+};
+
+template 
+class auto_ptr {
+};
+
+} // namespace std
+
+void assert(int expression){};
+
+///
+/// Test cases correctly caught by the check.
+
+class PtrField {
+public:
+  PtrField &operator=(const PtrField &object);
+
+private:
+  int *p;
+};
+
+PtrField &PtrField::operator=(const PtrField &object) {
+  // CHECK-MESSAGES: [[@LINE-1]]:21: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+  // ...
+  return *this;
+}
+
+// Class with an inline operator definition.
+class InlineDefinition {
+public:
+  InlineDefinition &operator=(const InlineDefinition &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:21: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  int *p;
+};
+
+class UniquePtrField {
+public:
+  UniquePtrField &operator=(const UniquePtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::unique_ptr p;
+};
+
+class SharedPtrField {
+public:
+  SharedPtrField &operator=(const SharedPtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::shared_ptr p;
+};
+
+class WeakPtrField {
+public:
+  WeakPtrField &operator=(const WeakPtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:17: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::weak_ptr p;
+};
+
+class AutoPtrField {
+public:
+  AutoPtrField &operator=(const AutoPtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:17: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::auto_ptr p;
+};
+
+// Class with C array field.
+class CArrayField {
+public:
+  CArrayField &operator=(const CArrayField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:16: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  int array[256];
+};
+
+// Make sure to not ignore cases when the operator definition calls
+// a copy constructor of another class.
+class CopyConstruct {
+public:
+  CopyConstruct &operator=(const CopyConstruct &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:18: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+WeakPtrField a;
+WeakPtrField b(a);
+// ...
+return *this;
+  }
+
+private:
+  int *p;
+};
+
+// Make sure to not ignore cases when the operator definition calls
+// a copy assignment operator of another class.
+class AssignOperator {
+public:
+  AssignOperator &operator=(const AssignOperator &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+a.operator=(object.a);
+// ...
+return *this;
+  }
+
+private:
+  int *p;
+  WeakPtrField a;
+};
+
+///
+/// Test cases correctly ignored by the check.
+
+// Self-assignment is checked using the equality operator.
+class SelfCheck1 {
+public:
+  SelfCheck1 &operator=(const SelfCheck1 &object) {
+if (this == &

[PATCH] D60507: [clang-tidy] new check: bugprone-unhandled-self-assignment

2019-04-16 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas marked 4 inline comments as done.
ztamas added inline comments.



Comment at: 
clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst:6
+
+`cert-oop54-cpp` redirects here as an alias for this check.
+

aaron.ballman wrote:
> You should add a link to CERT's documentation somewhere around this text.
In an earlier version of this patch, there was a link. I removed it because of 
a reviewer comment. Now I add it back, I hope now are OK.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D60507/new/

https://reviews.llvm.org/D60507



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


[PATCH] D60507: [clang-tidy] new check: bugprone-unhandled-self-assignment

2019-04-16 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas marked 2 inline comments as done.
ztamas added inline comments.



Comment at: 
clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp:351
+  int *p;
+};

aaron.ballman wrote:
> ztamas wrote:
> > JonasToth wrote:
> > > Please add tests with templated classes and self-assignment.
> > I tested with template classes, but TemplateCopyAndSwap test case, for 
> > example, was wrongly caught by the check. So I just changed the code to 
> > ignore template classes. I did not find any template class related catch 
> > either in LibreOffice or LLVM when I run the first version of this check, 
> > so we don't lose too much with ignoring template classes, I think.
> I am not keen on ignoring template classes for the check; that seems like a 
> bug in the check that should be addressed. At a minimum, the test cases 
> should be present with FIXME comments about the unwanted diagnostics.
I don't think it's a good idea to change the check now to catch template 
classes and produce false positives.

First of all the check does not work with template classes because the AST is 
different. Check TemplateCopyAndSwap test case for example. It's expected that 
the definition of operator= contains a CXXConstructExpr, but something is 
different for templates. It might be a lower level problem, how to detect a 
constructor call in a template class or templates just need different matcher. 
So implementing this check with correct template handling might be tricky and 
it might make the checker more complex. I'm not sure it worth the time, because 
as I mentioned I did not see any template related catch in the tested code 
bases. However, it might be a good idea to mention this limitation in the 
documentation.

About the false positives. This template related false positives are different 
from other false positives. In general, check doesn't warn, if the code uses 
one of the three patterns (self-check, copy-and-move, copy-and-swap). However, 
TemplateCopyAndSwap test case was wrongly caught by the check even though it 
uses copy-and-swap method. I would not introduce this kind of false positives. 
So the user of the check can expect that if he / she uses one of the three 
patterns, then there will be no warning in his / her code.

I already added five template related test cases. I think the comments are 
clear about which test case should be ignored by the check and which test cases 
are incorrectly ignored by now.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D60507/new/

https://reviews.llvm.org/D60507



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


[PATCH] D60507: [clang-tidy] new check: bugprone-unhandled-self-assignment

2019-04-22 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas updated this revision to Diff 196066.
ztamas added a comment.

Add false positive test cases.
Added a note about template related limitation to the docs.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D60507/new/

https://reviews.llvm.org/D60507

Files:
  clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
  clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst
  clang-tools-extra/docs/clang-tidy/checks/cert-oop54-cpp.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp

Index: clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp
@@ -0,0 +1,502 @@
+// RUN: %check_clang_tidy %s bugprone-unhandled-self-assignment %t
+
+namespace std {
+
+template 
+void swap(T x, T y) {
+}
+
+template 
+T &&move(T x) {
+}
+
+template 
+class unique_ptr {
+};
+
+template 
+class shared_ptr {
+};
+
+template 
+class weak_ptr {
+};
+
+template 
+class auto_ptr {
+};
+
+} // namespace std
+
+void assert(int expression){};
+
+///
+/// Test cases correctly caught by the check.
+
+class PtrField {
+public:
+  PtrField &operator=(const PtrField &object);
+
+private:
+  int *p;
+};
+
+PtrField &PtrField::operator=(const PtrField &object) {
+  // CHECK-MESSAGES: [[@LINE-1]]:21: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+  // ...
+  return *this;
+}
+
+// Class with an inline operator definition.
+class InlineDefinition {
+public:
+  InlineDefinition &operator=(const InlineDefinition &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:21: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  int *p;
+};
+
+class UniquePtrField {
+public:
+  UniquePtrField &operator=(const UniquePtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::unique_ptr p;
+};
+
+class SharedPtrField {
+public:
+  SharedPtrField &operator=(const SharedPtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::shared_ptr p;
+};
+
+class WeakPtrField {
+public:
+  WeakPtrField &operator=(const WeakPtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:17: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::weak_ptr p;
+};
+
+class AutoPtrField {
+public:
+  AutoPtrField &operator=(const AutoPtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:17: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::auto_ptr p;
+};
+
+// Class with C array field.
+class CArrayField {
+public:
+  CArrayField &operator=(const CArrayField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:16: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  int array[256];
+};
+
+// Make sure to not ignore cases when the operator definition calls
+// a copy constructor of another class.
+class CopyConstruct {
+public:
+  CopyConstruct &operator=(const CopyConstruct &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:18: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+WeakPtrField a;
+WeakPtrField b(a);
+// ...
+return *this;
+  }
+
+private:
+  int *p;
+};
+
+// Make sure to not ignore cases when the operator definition calls
+// a copy assignment operator of another class.
+class AssignOperator {
+public:
+  AssignOperator &operator=(const AssignOperator &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+a.operator=(object.a);
+// ...
+return *this;
+  }
+
+private:
+  int *p;
+  WeakPtrField a;
+};
+
+///
+/// Test cases correctly ignored by the check.
+
+// Self-assignment is checked using the equality operator.
+class SelfCheck1 {
+public:
+  SelfCheck1 &operat

[PATCH] D60507: [clang-tidy] new check: bugprone-unhandled-self-assignment

2019-04-23 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas marked 4 inline comments as done.
ztamas added inline comments.



Comment at: 
clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp:34-36
+  const auto HasNoSelfCheck = cxxMethodDecl(unless(hasDescendant(
+  binaryOperator(anyOf(hasOperatorName("=="), hasOperatorName("!=")),
+ has(ignoringParenCasts(cxxThisExpr()));

aaron.ballman wrote:
> Will this also match code like:
> ```
> Frobble &Frobble::operator=(const Frobble &F) {
>   if (&F == this->whatever())
> return *this;
> }
> ```
> or, more insidiously: 
> ```
> Frobble &Frobble::operator=(const Frobble &F) {
>   if (&F == whatever()) // whatever is a member function of Frobble
> return *this;
> }
> ```
> 
I'll check that case. The original hasLHS(...), hasRHS(...) might work with 
this use case too.



Comment at: 
clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp:54
+  recordType(hasDeclaration(classTemplateSpecializationDecl(
+  hasAnyName("std::shared_ptr", "std::unique_ptr", "std::weak_ptr",
+ "std::auto_ptr"),

aaron.ballman wrote:
> These should be using `::std::whatever` to ensure we only care about names in 
> the global namespace named `std`.
> 
> Should this list be configurable? For instance, boost has a fair number of 
> smart pointers.
> Should this list be configurable? For instance, boost has a fair number of 
> smart pointers.

xazax.hun has the same suggestion. I think it's a good idea for a follow-up 
patch. I actually added a test case with the name CustomPtrField to document 
this future possibility.



Comment at: 
clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp:62-64
+  const auto ThisHasSuspiciousField = cxxMethodDecl(ofClass(cxxRecordDecl(
+  has(fieldDecl(anyOf(hasType(pointerType()), hasType(SmartPointerType),
+  hasType(arrayType(;

aaron.ballman wrote:
> Hmm, while I understand why you're doing this, I'm worried that it will miss 
> some pretty important cases. For instance, improper thread locking could 
> result in deadlocks, improper releasing of non-memory resources could be 
> problematic (such as network connections, file streams, etc), even simple 
> integer assignments could be problematic in theory:
> ```
> Yobble& Yobble::operator=(const Yobble &Y) {
>   superSecretHashVal = 0; // Being secure!
>   ... some code that may early return ...
>   superSecretHashVal = Y.superSecretHashVal;
> }
> ```
> I wonder whether we want an option here to allow users to diagnose regardless 
> of whether we think it's suspicious or not.
> 
> At the very least, this code should not be enabled for the CERT version of 
> the check as it doesn't conform to the CERT requirements.
It's starting to be too much for me.
First, the problem was false positives. If there are too many false positives 
then better to have it in the cert module.
Now your problem is that this is not fit with the CERT requirements, because of 
this matcher which reduces the false positives. Adding this check to the CERT 
module was not my idea in the first place. So I suggest to have it a simple 
bugprone check  (and remove the cert alias) and also we can mention that it is 
related to the corresponding cert rule (but it does not conform with it 
entirely).
This check allows the usage of copy-and-move pattern, which does not conform 
with the cert specification either where only the self-check and copy-and-swap 
is mentioned. So your next suggestion will be to not allow copy-and-move 
because it does not fit with the cert rule? So I think it's better to have this 
not a cert check then, but a bugprone check. I prefer to have a working check 
then implementing a theoretical documentation.

Apart from that cert thing, it actually seems a good idea to add a config 
option to allow the user to get all catches, not just the "suspicious ones".



Comment at: 
clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp:82
+  diag(MatchedDecl->getLocation(),
+   "operator=() might not handle self-assignment properly");
+}

aaron.ballman wrote:
> Hmm, the "might not" seems a bit flat to me. How about: `'operator=()' does 
> not properly test for self-assignment`?
> 
> Also, do we want to have a fix-it to insert a check for self assignment at 
> the start of the function?
I don't think "test for self-assignment" will be good, because it's only one 
way to make the operator self assignment safe. In case of copy-and-swap and 
copy-and-move there is no testing of self assignment, but swaping/moving works 
in all cases without explicit self check.

A fix-it can be a good idea for a follow-up patch.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D60507/new/

https://reviews.llvm.org/D60507




[PATCH] D60507: [clang-tidy] new check: bugprone-unhandled-self-assignment

2019-04-23 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas marked an inline comment as done.
ztamas added inline comments.



Comment at: 
clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp:351
+  int *p;
+};

aaron.ballman wrote:
> ztamas wrote:
> > aaron.ballman wrote:
> > > ztamas wrote:
> > > > JonasToth wrote:
> > > > > Please add tests with templated classes and self-assignment.
> > > > I tested with template classes, but TemplateCopyAndSwap test case, for 
> > > > example, was wrongly caught by the check. So I just changed the code to 
> > > > ignore template classes. I did not find any template class related 
> > > > catch either in LibreOffice or LLVM when I run the first version of 
> > > > this check, so we don't lose too much with ignoring template classes, I 
> > > > think.
> > > I am not keen on ignoring template classes for the check; that seems like 
> > > a bug in the check that should be addressed. At a minimum, the test cases 
> > > should be present with FIXME comments about the unwanted diagnostics.
> > I don't think it's a good idea to change the check now to catch template 
> > classes and produce false positives.
> > 
> > First of all the check does not work with template classes because the AST 
> > is different. Check TemplateCopyAndSwap test case for example. It's 
> > expected that the definition of operator= contains a CXXConstructExpr, but 
> > something is different for templates. It might be a lower level problem, 
> > how to detect a constructor call in a template class or templates just need 
> > different matcher. So implementing this check with correct template 
> > handling might be tricky and it might make the checker more complex. I'm 
> > not sure it worth the time, because as I mentioned I did not see any 
> > template related catch in the tested code bases. However, it might be a 
> > good idea to mention this limitation in the documentation.
> > 
> > About the false positives. This template related false positives are 
> > different from other false positives. In general, check doesn't warn, if 
> > the code uses one of the three patterns (self-check, copy-and-move, 
> > copy-and-swap). However, TemplateCopyAndSwap test case was wrongly caught 
> > by the check even though it uses copy-and-swap method. I would not 
> > introduce this kind of false positives. So the user of the check can expect 
> > that if he / she uses one of the three patterns, then there will be no 
> > warning in his / her code.
> > 
> > I already added five template related test cases. I think the comments are 
> > clear about which test case should be ignored by the check and which test 
> > cases are incorrectly ignored by now.
> > So implementing this check with correct template handling might be tricky 
> > and it might make the checker more complex. 
> 
> I would be surprised if it added that much complexity. You wouldn't be 
> checking the template declarations, but the template instantiations 
> themselves, which should have the same AST representation as similar 
> non-templated code.
> 
> >  I'm not sure it worth the time, because as I mentioned I did not see any 
> > template related catch in the tested code bases.
> 
> It's needed to conform to the CERT coding standard, which has no exceptions 
> for templates here.
> 
> > However, it might be a good idea to mention this limitation in the 
> > documentation.
> 
> My preference is to support it from the start, but if we don't support it, it 
> should definitely be mentioned in the documentation.
I added instatiation of template classes to the test code (locally):

```
template 
class TemplateCopyAndMove {
public:
  TemplateCopyAndMove &operator=(const TemplateCopyAndMove &object) {
TemplateCopyAndMove temp(object);
*this = std::move(temp);
return *this;
  }

private:
  T *p;
};

int instaniateTemplateCopyAndMove() {
TemplateCopyAndMove x;
(void) x;
}
```

However I don't see the expected AST neither in the ClassTemplateDecl or in the 
ClassTemplateSpecializationDecl. So how can I get that AST which is similar to 
non-template case?

```
|-ClassTemplateDecl 0x117ed20  line:342:7 
TemplateCopyAndMove
| |-TemplateTypeParmDecl 0x117ec08  col:17 referenced 
class depth 0 index 0 T
| |-CXXRecordDecl 0x117ec90  line:342:7 class 
TemplateCopyAndMove definition
| | |-DefinitionData standard_layout
| | | |-DefaultConstructor exists trivial needs_implicit
| | | |-CopyConstructor simple trivial has_const_param needs_implicit 
implicit_has_const_param
| | | |-MoveConstructor
| | | |-CopyAssignment non_trivial has_const_param user_declared 
implicit_has_const_param
| | | |-MoveAssignment
| | | `-Destructor simple irrelevant trivial needs_implicit
| | |-CXXRecordDecl 0x117ef70  col:7 implicit class 
TemplateCopyAndMove
| | |-AccessSpecDecl 0x117f000  col:1 public
| | |-CXXMethodDecl 0x117f9d0  line:344:27 operator= 
'TemplateCopyAndMove &(const TemplateCopyAndMove &)'
| | | |-ParmVarDecl 0x117f820  col:67 referenced object 'c

[PATCH] D60507: [clang-tidy] new check: bugprone-unhandled-self-assignment

2019-04-23 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas updated this revision to Diff 196279.
ztamas added a comment.

Added missing fullstop
Added a new test cases making sure that HasNoSelfCheck works correctly
Added template instantiation to tests
Remove the alias from cert module and add the CERT link as a see also


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D60507/new/

https://reviews.llvm.org/D60507

Files:
  clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
  clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp

Index: clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp
@@ -0,0 +1,545 @@
+// RUN: %check_clang_tidy %s bugprone-unhandled-self-assignment %t
+
+namespace std {
+
+template 
+void swap(T x, T y) {
+}
+
+template 
+T &&move(T x) {
+}
+
+template 
+class unique_ptr {
+};
+
+template 
+class shared_ptr {
+};
+
+template 
+class weak_ptr {
+};
+
+template 
+class auto_ptr {
+};
+
+} // namespace std
+
+void assert(int expression){};
+
+///
+/// Test cases correctly caught by the check.
+
+class PtrField {
+public:
+  PtrField &operator=(const PtrField &object);
+
+private:
+  int *p;
+};
+
+PtrField &PtrField::operator=(const PtrField &object) {
+  // CHECK-MESSAGES: [[@LINE-1]]:21: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+  // ...
+  return *this;
+}
+
+// Class with an inline operator definition.
+class InlineDefinition {
+public:
+  InlineDefinition &operator=(const InlineDefinition &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:21: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  int *p;
+};
+
+class UniquePtrField {
+public:
+  UniquePtrField &operator=(const UniquePtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::unique_ptr p;
+};
+
+class SharedPtrField {
+public:
+  SharedPtrField &operator=(const SharedPtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::shared_ptr p;
+};
+
+class WeakPtrField {
+public:
+  WeakPtrField &operator=(const WeakPtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:17: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::weak_ptr p;
+};
+
+class AutoPtrField {
+public:
+  AutoPtrField &operator=(const AutoPtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:17: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::auto_ptr p;
+};
+
+// Class with C array field.
+class CArrayField {
+public:
+  CArrayField &operator=(const CArrayField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:16: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  int array[256];
+};
+
+// Make sure to not ignore cases when the operator definition calls
+// a copy constructor of another class.
+class CopyConstruct {
+public:
+  CopyConstruct &operator=(const CopyConstruct &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:18: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+WeakPtrField a;
+WeakPtrField b(a);
+// ...
+return *this;
+  }
+
+private:
+  int *p;
+};
+
+// Make sure to not ignore cases when the operator definition calls
+// a copy assignment operator of another class.
+class AssignOperator {
+public:
+  AssignOperator &operator=(const AssignOperator &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+a.operator=(object.a);
+// ...
+return *this;
+  }
+
+private:
+  int *p;
+  WeakPtrField a;
+};
+
+class NotSelfCheck {
+public:
+  NotSelfCheck &operator=(const NotSelfCheck &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:17: warning: operator=() might not handle self-assignmen

[PATCH] D60507: [clang-tidy] new check: bugprone-unhandled-self-assignment

2019-04-23 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas marked 5 inline comments as done.
ztamas added inline comments.



Comment at: 
clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp:34-36
+  const auto HasNoSelfCheck = cxxMethodDecl(unless(hasDescendant(
+  binaryOperator(anyOf(hasOperatorName("=="), hasOperatorName("!=")),
+ has(ignoringParenCasts(cxxThisExpr()));

ztamas wrote:
> aaron.ballman wrote:
> > Will this also match code like:
> > ```
> > Frobble &Frobble::operator=(const Frobble &F) {
> >   if (&F == this->whatever())
> > return *this;
> > }
> > ```
> > or, more insidiously: 
> > ```
> > Frobble &Frobble::operator=(const Frobble &F) {
> >   if (&F == whatever()) // whatever is a member function of Frobble
> > return *this;
> > }
> > ```
> > 
> I'll check that case. The original hasLHS(...), hasRHS(...) might work with 
> this use case too.
I added NotSelfCheck test case for this, which works correctly.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D60507/new/

https://reviews.llvm.org/D60507



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


[PATCH] D60507: [clang-tidy] new check: bugprone-unhandled-self-assignment

2019-04-23 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas added a comment.

Ok, so I removed the alias from cert module and added CERT rule link as a "see 
also".
So I think we solved the problem that things do not conform with the CERT 
requirements and can focus on the actual problem.

Summary, templates are still ignored. If there is any idea how to solve this 
for templates easily or there is any sample code for this, then I happy to 
implement template support.
I see a related comment in clang-tidy/modernize/PassByValueCheck.cpp:

  // Clang builds a CXXConstructExpr only when it knows which
  // constructor will be called. In dependent contexts a
  // ParenListExpr is generated instead of a CXXConstructExpr,
  // filtering out templates automatically for us.

So It's not only me who sees that template AST is different.

Also, two good ideas were mentioned about extra options during the review.

1. Allow finding catches not just pointers and arrays
2. Allow configuring list of suspicious field types / pointer types

I think these two options are good ideas for future improvements. For now, the 
check seems useful and produces not many false positives in the current form, I 
think.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D60507/new/

https://reviews.llvm.org/D60507



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


[PATCH] D60507: [clang-tidy] new check: bugprone-unhandled-self-assignment

2019-04-23 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas marked 3 inline comments as done.
ztamas added inline comments.



Comment at: 
clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp:62-64
+  const auto ThisHasSuspiciousField = cxxMethodDecl(ofClass(cxxRecordDecl(
+  has(fieldDecl(anyOf(hasType(pointerType()), hasType(SmartPointerType),
+  hasType(arrayType(;

aaron.ballman wrote:
> ztamas wrote:
> > aaron.ballman wrote:
> > > Hmm, while I understand why you're doing this, I'm worried that it will 
> > > miss some pretty important cases. For instance, improper thread locking 
> > > could result in deadlocks, improper releasing of non-memory resources 
> > > could be problematic (such as network connections, file streams, etc), 
> > > even simple integer assignments could be problematic in theory:
> > > ```
> > > Yobble& Yobble::operator=(const Yobble &Y) {
> > >   superSecretHashVal = 0; // Being secure!
> > >   ... some code that may early return ...
> > >   superSecretHashVal = Y.superSecretHashVal;
> > > }
> > > ```
> > > I wonder whether we want an option here to allow users to diagnose 
> > > regardless of whether we think it's suspicious or not.
> > > 
> > > At the very least, this code should not be enabled for the CERT version 
> > > of the check as it doesn't conform to the CERT requirements.
> > It's starting to be too much for me.
> > First, the problem was false positives. If there are too many false 
> > positives then better to have it in the cert module.
> > Now your problem is that this is not fit with the CERT requirements, 
> > because of this matcher which reduces the false positives. Adding this 
> > check to the CERT module was not my idea in the first place. So I suggest 
> > to have it a simple bugprone check  (and remove the cert alias) and also we 
> > can mention that it is related to the corresponding cert rule (but it does 
> > not conform with it entirely).
> > This check allows the usage of copy-and-move pattern, which does not 
> > conform with the cert specification either where only the self-check and 
> > copy-and-swap is mentioned. So your next suggestion will be to not allow 
> > copy-and-move because it does not fit with the cert rule? So I think it's 
> > better to have this not a cert check then, but a bugprone check. I prefer 
> > to have a working check then implementing a theoretical documentation.
> > 
> > Apart from that cert thing, it actually seems a good idea to add a config 
> > option to allow the user to get all catches, not just the "suspicious ones".
> > It's starting to be too much for me.
> 
> It can be tricky to get this stuff right; I'm sorry the difficulties are 
> aggravating.
> 
> > First, the problem was false positives. If there are too many false 
> > positives then better to have it in the cert module.
> > Now your problem is that this is not fit with the CERT requirements, 
> > because of this matcher which reduces the false positives. 
> > Adding this check to the CERT module was not my idea in the first place. So 
> > I suggest to have it a simple bugprone check (and remove the cert alias) 
> > and also we can mention that it is related to the corresponding cert rule 
> > (but it does not conform with it entirely).
> 
> We typically ask authors to support the various coding standard modules when 
> plausible because of the considerable amount of overlap between the 
> functionalities. I don't particularly like the idea of ignoring the CERT 
> coding standard here given that the solution is almost trivial to implement. 
> However, if you want to remove it from the CERT module and not support it, 
> that's your choice.
> 
> > This check allows the usage of copy-and-move pattern, which does not 
> > conform with the cert specification either where only the self-check and 
> > copy-and-swap is mentioned.
> 
> I don't get that from my reading of the CERT rule, where it says, "A 
> user-provided copy assignment operator must prevent self-copy assignment from 
> leaving the object in an indeterminate state. This can be accomplished by 
> self-assignment tests, copy-and-swap, or other idiomatic design patterns.". 
> Copy-and-move is another idiomatic design pattern for dealing with this, and 
> I'm glad your check incorporates it. (tbh, it would be nice for the CERT rule 
> to have a compliant solution demonstrating it -- I'll recommend it on their 
> rule.)
> 
> > So your next suggestion will be to not allow copy-and-move because it does 
> > not fit with the cert rule? So I think it's better to have this not a cert 
> > check then, but a bugprone check. I prefer to have a working check then 
> > implementing a theoretical documentation.
> 
> Theoretical documentation? The CERT standard is a published standard used in 
> industry that's supported by other analyzers as well as clang-tidy, so it's 
> not really theoretical.
> 
> > Apart from that cert thing, it actually seems a good idea to add a config 
> >

[PATCH] D60507: [clang-tidy] new check: bugprone-unhandled-self-assignment

2019-04-23 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas updated this revision to Diff 196295.
ztamas added a comment.

Make the check to work with templates too


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D60507/new/

https://reviews.llvm.org/D60507

Files:
  clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
  clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp

Index: clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp
@@ -0,0 +1,521 @@
+// RUN: %check_clang_tidy %s bugprone-unhandled-self-assignment %t
+
+namespace std {
+
+template 
+void swap(T x, T y) {
+}
+
+template 
+T &&move(T x) {
+}
+
+template 
+class unique_ptr {
+};
+
+template 
+class shared_ptr {
+};
+
+template 
+class weak_ptr {
+};
+
+template 
+class auto_ptr {
+};
+
+} // namespace std
+
+void assert(int expression){};
+
+///
+/// Test cases correctly caught by the check.
+
+class PtrField {
+public:
+  PtrField &operator=(const PtrField &object);
+
+private:
+  int *p;
+};
+
+PtrField &PtrField::operator=(const PtrField &object) {
+  // CHECK-MESSAGES: [[@LINE-1]]:21: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+  // ...
+  return *this;
+}
+
+// Class with an inline operator definition.
+class InlineDefinition {
+public:
+  InlineDefinition &operator=(const InlineDefinition &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:21: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  int *p;
+};
+
+class UniquePtrField {
+public:
+  UniquePtrField &operator=(const UniquePtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::unique_ptr p;
+};
+
+class SharedPtrField {
+public:
+  SharedPtrField &operator=(const SharedPtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::shared_ptr p;
+};
+
+class WeakPtrField {
+public:
+  WeakPtrField &operator=(const WeakPtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:17: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::weak_ptr p;
+};
+
+class AutoPtrField {
+public:
+  AutoPtrField &operator=(const AutoPtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:17: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::auto_ptr p;
+};
+
+// Class with C array field.
+class CArrayField {
+public:
+  CArrayField &operator=(const CArrayField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:16: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  int array[256];
+};
+
+// Make sure to not ignore cases when the operator definition calls
+// a copy constructor of another class.
+class CopyConstruct {
+public:
+  CopyConstruct &operator=(const CopyConstruct &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:18: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+WeakPtrField a;
+WeakPtrField b(a);
+// ...
+return *this;
+  }
+
+private:
+  int *p;
+};
+
+// Make sure to not ignore cases when the operator definition calls
+// a copy assignment operator of another class.
+class AssignOperator {
+public:
+  AssignOperator &operator=(const AssignOperator &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+a.operator=(object.a);
+// ...
+return *this;
+  }
+
+private:
+  int *p;
+  WeakPtrField a;
+};
+
+class NotSelfCheck {
+public:
+  NotSelfCheck &operator=(const NotSelfCheck &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:17: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+if (&object == this->doSomething()) {
+  // ...
+}
+return *this;
+  }
+
+  void *doSomething()

[PATCH] D60507: [clang-tidy] new check: bugprone-unhandled-self-assignment

2019-04-23 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas added a comment.

I also reformatted the code with clang-format.

So now the templates are handled, however, it's still not fit with the cert 
rule because we not catch all classes, but only those who have suspicious 
fields. I think this one can be added in a follow-up patch and then this check 
can be added to the cert module as an alias.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D60507/new/

https://reviews.llvm.org/D60507



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


[PATCH] D60507: [clang-tidy] new check: bugprone-unhandled-self-assignment

2019-04-23 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas marked 8 inline comments as done.
ztamas added a comment.

Mark some comments Done, which were handled some way.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D60507/new/

https://reviews.llvm.org/D60507



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


[PATCH] D60507: [clang-tidy] new check: bugprone-unhandled-self-assignment

2019-04-24 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas updated this revision to Diff 196410.
ztamas added a comment.

Remove outdated comment from docs.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D60507/new/

https://reviews.llvm.org/D60507

Files:
  clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
  clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp

Index: clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp
@@ -0,0 +1,521 @@
+// RUN: %check_clang_tidy %s bugprone-unhandled-self-assignment %t
+
+namespace std {
+
+template 
+void swap(T x, T y) {
+}
+
+template 
+T &&move(T x) {
+}
+
+template 
+class unique_ptr {
+};
+
+template 
+class shared_ptr {
+};
+
+template 
+class weak_ptr {
+};
+
+template 
+class auto_ptr {
+};
+
+} // namespace std
+
+void assert(int expression){};
+
+///
+/// Test cases correctly caught by the check.
+
+class PtrField {
+public:
+  PtrField &operator=(const PtrField &object);
+
+private:
+  int *p;
+};
+
+PtrField &PtrField::operator=(const PtrField &object) {
+  // CHECK-MESSAGES: [[@LINE-1]]:21: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+  // ...
+  return *this;
+}
+
+// Class with an inline operator definition.
+class InlineDefinition {
+public:
+  InlineDefinition &operator=(const InlineDefinition &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:21: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  int *p;
+};
+
+class UniquePtrField {
+public:
+  UniquePtrField &operator=(const UniquePtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::unique_ptr p;
+};
+
+class SharedPtrField {
+public:
+  SharedPtrField &operator=(const SharedPtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::shared_ptr p;
+};
+
+class WeakPtrField {
+public:
+  WeakPtrField &operator=(const WeakPtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:17: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::weak_ptr p;
+};
+
+class AutoPtrField {
+public:
+  AutoPtrField &operator=(const AutoPtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:17: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::auto_ptr p;
+};
+
+// Class with C array field.
+class CArrayField {
+public:
+  CArrayField &operator=(const CArrayField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:16: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  int array[256];
+};
+
+// Make sure to not ignore cases when the operator definition calls
+// a copy constructor of another class.
+class CopyConstruct {
+public:
+  CopyConstruct &operator=(const CopyConstruct &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:18: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+WeakPtrField a;
+WeakPtrField b(a);
+// ...
+return *this;
+  }
+
+private:
+  int *p;
+};
+
+// Make sure to not ignore cases when the operator definition calls
+// a copy assignment operator of another class.
+class AssignOperator {
+public:
+  AssignOperator &operator=(const AssignOperator &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+a.operator=(object.a);
+// ...
+return *this;
+  }
+
+private:
+  int *p;
+  WeakPtrField a;
+};
+
+class NotSelfCheck {
+public:
+  NotSelfCheck &operator=(const NotSelfCheck &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:17: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+if (&object == this->doSomething()) {
+  // ...
+}
+return *this;
+  }
+
+  void *doSomething() {
+   

[PATCH] D60507: [clang-tidy] new check: bugprone-unhandled-self-assignment

2019-04-25 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas added a comment.

Ok, is there anything else should be included in this patch?
I saw more ideas about how to extend the functionality (custom pointers, 
fix-it, etc). I interpreted these ideas as nice-to-have things for the future.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D60507/new/

https://reviews.llvm.org/D60507



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


[PATCH] D60507: [clang-tidy] new check: bugprone-unhandled-self-assignment

2019-04-28 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas updated this revision to Diff 197014.
ztamas added a comment.

Better handling of template and non-template self-copy


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D60507/new/

https://reviews.llvm.org/D60507

Files:
  clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
  clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp

Index: clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp
@@ -0,0 +1,561 @@
+// RUN: %check_clang_tidy %s bugprone-unhandled-self-assignment %t
+
+namespace std {
+
+template 
+void swap(T x, T y) {
+}
+
+template 
+T &&move(T x) {
+}
+
+template 
+class unique_ptr {
+};
+
+template 
+class shared_ptr {
+};
+
+template 
+class weak_ptr {
+};
+
+template 
+class auto_ptr {
+};
+
+} // namespace std
+
+void assert(int expression){};
+
+///
+/// Test cases correctly caught by the check.
+
+class PtrField {
+public:
+  PtrField &operator=(const PtrField &object);
+
+private:
+  int *p;
+};
+
+PtrField &PtrField::operator=(const PtrField &object) {
+  // CHECK-MESSAGES: [[@LINE-1]]:21: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+  // ...
+  return *this;
+}
+
+// Class with an inline operator definition.
+class InlineDefinition {
+public:
+  InlineDefinition &operator=(const InlineDefinition &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:21: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  int *p;
+};
+
+class UniquePtrField {
+public:
+  UniquePtrField &operator=(const UniquePtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::unique_ptr p;
+};
+
+class SharedPtrField {
+public:
+  SharedPtrField &operator=(const SharedPtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::shared_ptr p;
+};
+
+class WeakPtrField {
+public:
+  WeakPtrField &operator=(const WeakPtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:17: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::weak_ptr p;
+};
+
+class AutoPtrField {
+public:
+  AutoPtrField &operator=(const AutoPtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:17: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::auto_ptr p;
+};
+
+// Class with C array field.
+class CArrayField {
+public:
+  CArrayField &operator=(const CArrayField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:16: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  int array[256];
+};
+
+// Make sure to not ignore cases when the operator definition calls
+// a copy constructor of another class.
+class CopyConstruct {
+public:
+  CopyConstruct &operator=(const CopyConstruct &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:18: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+WeakPtrField a;
+WeakPtrField b(a);
+// ...
+return *this;
+  }
+
+private:
+  int *p;
+};
+
+// Make sure to not ignore cases when the operator definition calls
+// a copy assignment operator of another class.
+class AssignOperator {
+public:
+  AssignOperator &operator=(const AssignOperator &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+a.operator=(object.a);
+// ...
+return *this;
+  }
+
+private:
+  int *p;
+  WeakPtrField a;
+};
+
+class NotSelfCheck {
+public:
+  NotSelfCheck &operator=(const NotSelfCheck &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:17: warning: operator=() might not handle self-assignment properly [bugprone-unhandled-self-assignment]
+if (&object == this->doSomething()) {
+  // ...
+}
+return *this;
+  }
+
+  void *

[PATCH] D60507: [clang-tidy] new check: bugprone-unhandled-self-assignment

2019-05-05 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas added a comment.

Ping.
Is it good to go or is there anything else I need to include in this patch?
Among the lots of idea, I'm not sure which is just brainstorming and which is a 
change request.
The check seems to work (has useful catches and does not produce too many false 
positives), however, it does not conform with the corresponding cert rule. I 
expect that a cert alias with an option can be added in a follow-up patch 
(option to ignore ThisHasSuspiciousField pattern). The bugprone-* check would 
have the same default behavior as it has now in this patch. So adding the cert 
alias would not change this behavior, right? In this case, this code change can 
be added in a separate patch I guess.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D60507/new/

https://reviews.llvm.org/D60507



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


[PATCH] D60507: [clang-tidy] new check: bugprone-unhandled-self-assignment

2019-05-09 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas updated this revision to Diff 198787.
ztamas added a comment.

Changed "might not" to "does not" in the warning message.
Added the requested test case with the swapped template arguments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D60507/new/

https://reviews.llvm.org/D60507

Files:
  clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
  clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp

Index: clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp
@@ -0,0 +1,579 @@
+// RUN: %check_clang_tidy %s bugprone-unhandled-self-assignment %t
+
+namespace std {
+
+template 
+void swap(T x, T y) {
+}
+
+template 
+T &&move(T x) {
+}
+
+template 
+class unique_ptr {
+};
+
+template 
+class shared_ptr {
+};
+
+template 
+class weak_ptr {
+};
+
+template 
+class auto_ptr {
+};
+
+} // namespace std
+
+void assert(int expression){};
+
+///
+/// Test cases correctly caught by the check.
+
+class PtrField {
+public:
+  PtrField &operator=(const PtrField &object);
+
+private:
+  int *p;
+};
+
+PtrField &PtrField::operator=(const PtrField &object) {
+  // CHECK-MESSAGES: [[@LINE-1]]:21: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
+  // ...
+  return *this;
+}
+
+// Class with an inline operator definition.
+class InlineDefinition {
+public:
+  InlineDefinition &operator=(const InlineDefinition &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:21: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  int *p;
+};
+
+class UniquePtrField {
+public:
+  UniquePtrField &operator=(const UniquePtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::unique_ptr p;
+};
+
+class SharedPtrField {
+public:
+  SharedPtrField &operator=(const SharedPtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::shared_ptr p;
+};
+
+class WeakPtrField {
+public:
+  WeakPtrField &operator=(const WeakPtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:17: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::weak_ptr p;
+};
+
+class AutoPtrField {
+public:
+  AutoPtrField &operator=(const AutoPtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:17: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::auto_ptr p;
+};
+
+// Class with C array field.
+class CArrayField {
+public:
+  CArrayField &operator=(const CArrayField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:16: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  int array[256];
+};
+
+// Make sure to not ignore cases when the operator definition calls
+// a copy constructor of another class.
+class CopyConstruct {
+public:
+  CopyConstruct &operator=(const CopyConstruct &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:18: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
+WeakPtrField a;
+WeakPtrField b(a);
+// ...
+return *this;
+  }
+
+private:
+  int *p;
+};
+
+// Make sure to not ignore cases when the operator definition calls
+// a copy assignment operator of another class.
+class AssignOperator {
+public:
+  AssignOperator &operator=(const AssignOperator &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
+a.operator=(object.a);
+// ...
+return *this;
+  }
+
+private:
+  int *p;
+  WeakPtrField a;
+};
+
+class NotSelfCheck {
+public:
+  NotSelfCheck &operator=(const NotSelfCheck &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:17: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
+if (&object == this->doSomething()

[PATCH] D60507: [clang-tidy] new check: bugprone-unhandled-self-assignment

2019-05-09 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas updated this revision to Diff 198789.
ztamas added a comment.

copy operator -> copy assignment operator


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D60507/new/

https://reviews.llvm.org/D60507

Files:
  clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
  clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp

Index: clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment.cpp
@@ -0,0 +1,579 @@
+// RUN: %check_clang_tidy %s bugprone-unhandled-self-assignment %t
+
+namespace std {
+
+template 
+void swap(T x, T y) {
+}
+
+template 
+T &&move(T x) {
+}
+
+template 
+class unique_ptr {
+};
+
+template 
+class shared_ptr {
+};
+
+template 
+class weak_ptr {
+};
+
+template 
+class auto_ptr {
+};
+
+} // namespace std
+
+void assert(int expression){};
+
+///
+/// Test cases correctly caught by the check.
+
+class PtrField {
+public:
+  PtrField &operator=(const PtrField &object);
+
+private:
+  int *p;
+};
+
+PtrField &PtrField::operator=(const PtrField &object) {
+  // CHECK-MESSAGES: [[@LINE-1]]:21: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
+  // ...
+  return *this;
+}
+
+// Class with an inline operator definition.
+class InlineDefinition {
+public:
+  InlineDefinition &operator=(const InlineDefinition &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:21: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  int *p;
+};
+
+class UniquePtrField {
+public:
+  UniquePtrField &operator=(const UniquePtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::unique_ptr p;
+};
+
+class SharedPtrField {
+public:
+  SharedPtrField &operator=(const SharedPtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::shared_ptr p;
+};
+
+class WeakPtrField {
+public:
+  WeakPtrField &operator=(const WeakPtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:17: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::weak_ptr p;
+};
+
+class AutoPtrField {
+public:
+  AutoPtrField &operator=(const AutoPtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:17: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  std::auto_ptr p;
+};
+
+// Class with C array field.
+class CArrayField {
+public:
+  CArrayField &operator=(const CArrayField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:16: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
+// ...
+return *this;
+  }
+
+private:
+  int array[256];
+};
+
+// Make sure to not ignore cases when the operator definition calls
+// a copy constructor of another class.
+class CopyConstruct {
+public:
+  CopyConstruct &operator=(const CopyConstruct &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:18: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
+WeakPtrField a;
+WeakPtrField b(a);
+// ...
+return *this;
+  }
+
+private:
+  int *p;
+};
+
+// Make sure to not ignore cases when the operator definition calls
+// a copy assignment operator of another class.
+class AssignOperator {
+public:
+  AssignOperator &operator=(const AssignOperator &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:19: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
+a.operator=(object.a);
+// ...
+return *this;
+  }
+
+private:
+  int *p;
+  WeakPtrField a;
+};
+
+class NotSelfCheck {
+public:
+  NotSelfCheck &operator=(const NotSelfCheck &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:17: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
+if (&object == this->doSomething()) {
+  // ...
+}
+return *this;
+  }
+
+  void *doSomething() {
+re

[PATCH] D60507: [clang-tidy] new check: bugprone-unhandled-self-assignment

2019-05-09 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas added a comment.

> I definitely want to see the diagnostic text changed away from "might be" -- 
> that's too noncommittal for my tastes. I'd also like to see the additional 
> test case (I suspect it will just work out of the box, but if it doesn't, it 
> would be good to know about it). The CERT alias is a bit more of a grey area 
> -- I'd like to insist on it being added because it's trivial, it improves the 
> behavior of this check by introducing an option some users will want, and 
> checks conforming to coding standards are always more compelling than one-off 
> checks. However, you seem very resistant to that and I don't want to add to 
> your work load if you are opposed to doing it, so I don't insist on the 
> change.

During LibreOffice development, I'm socialized to keep a patch as small as 
possible. Versioning history can be more "clean" with smaller patches. For 
example, it's easier to find and fix regressions
with bisecting. Also smaller patches make the review process faster, etc. 
That's why I'm trying to separate what is absolutely necessary to include and 
what can be cut off from this patch.

I changed the warning message and I added the requested test case. This test 
case is ignored by the check as expected.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D60507/new/

https://reviews.llvm.org/D60507



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


[PATCH] D52936: Add some automatic tests for DivideZero checker

2018-10-05 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas created this revision.
Herald added a subscriber: cfe-commits.

Repository:
  rC Clang

https://reviews.llvm.org/D52936

Files:
  test/Analysis/div-zero.cpp

Index: test/Analysis/div-zero.cpp
===
--- test/Analysis/div-zero.cpp
+++ test/Analysis/div-zero.cpp
@@ -11,3 +11,301 @@
   return (a % (qX-1)); // expected-warning {{Division by zero}}
 
 }
+
+
+void testDiv1() {
+  (void)(42 / 0);
+  // expected-warning@-1 {{division by zero is undefined}}
+  // expected-warning@-2 {{Division by zero}}
+}
+
+
+void testDiv2() {
+  (void)(42 / false);
+  // expected-warning@-1 {{division by zero is undefined}}
+  // expected-warning@-2 {{Division by zero}}
+}
+
+
+void testDiv3() {
+  (void)(42 / !1);
+  // expected-warning@-1 {{division by zero is undefined}}
+  // expected-warning@-2 {{Division by zero}}
+}
+
+
+void testDiv4() {
+  (void)(42 / (1 - 1));
+  // expected-warning@-1 {{division by zero is undefined}}
+  // expected-warning@-2 {{Division by zero}}
+}
+
+
+void testDiv5() {
+  (void)(42 / !(1 + 1));
+  // expected-warning@-1 {{division by zero is undefined}}
+  // expected-warning@-2 {{Division by zero}}
+}
+
+
+void testDiv6a() {
+  (void)(42 / (int)0.0);
+  // expected-warning@-1 {{division by zero is undefined}}
+  // Missing Division by zero warning
+}
+
+
+void testDiv6b() {
+  int x = (int)0.0;
+  (void)(42 / x);
+  // Missing Division by zero warning
+}
+
+
+void testDiv6c() {
+  float y = 0.2;
+  float z = 0.1;
+  int x = (int)(z + y);
+  (void)(42 / x);
+  // Missing Division by zero warning
+}
+
+
+void testDiv7() {
+  (void)(true / 0);
+  // expected-warning@-1 {{division by zero is undefined}}
+  // expected-warning@-2 {{Division by zero}}
+}
+
+
+void testDiv8() {
+  (void)(!1 / 0);
+  // expected-warning@-1 {{division by zero is undefined}}
+  // expected-warning@-2 {{Division by zero}}
+}
+
+
+void testDiv9() {
+  (void)((int)(9.0) / 0);
+  // expected-warning@-1 {{division by zero is undefined}}
+  // expected-warning@-2 {{Division by zero}}
+}
+
+
+void testDiv10() {
+  (void)((10 - 1) / 0);
+  // expected-warning@-1 {{division by zero is undefined}}
+  // expected-warning@-2 {{Division by zero}}
+}
+
+
+void testRem() {
+  (void)(42 % 0);
+  // expected-warning@-1 {{remainder by zero is undefined}}
+  // expected-warning@-2 {{Division by zero}}
+}
+
+
+int testDivAssign(int x) {
+  return (x /= 0);
+  // expected-warning@-1 {{division by zero is undefined}}
+  // expected-warning@-2 {{Division by zero}}
+}
+
+
+int testRemAssign(int x) {
+  return (x %= 0);
+  // expected-warning@-1 {{remainder by zero is undefined}}
+  // expected-warning@-2 {{Division by zero}}
+}
+
+
+void testFloatDiv() {
+  (void)(42.0 / 0);
+  // No warning, the checker handles scalar types only
+}
+
+
+void testDivPath() {
+  int x = 2;
+  int y = 2;
+  int z = 10;
+
+  x = y / z;
+  (void)(42 / x); // expected-warning {{Division by zero}}
+}
+
+
+void testDivPath2() {
+  int x = 2;
+  int y = 0;
+  int z = 10;
+
+  x = y / z;
+  (void)(42 / x); // expected-warning {{Division by zero}}
+}
+
+
+void testRemPath() {
+  int x = 2;
+  int y = 2;
+  int z = 10;
+
+  x = z % y;
+  (void)(42 / x); // expected-warning {{Division by zero}}
+}
+
+
+void testRemPath2() {
+  int x = 2;
+  int y = 2;
+  int z = 0;
+
+  x = z % y;
+  (void)(42 / x); // expected-warning {{Division by zero}}
+}
+
+
+void testAdditionPath() {
+  int x = 2;
+  int y = 2;
+  int z = -2;
+
+  x = z + y;
+  (void)(42 / x); // expected-warning {{Division by zero}}
+}
+
+
+void testSubtractionPath() {
+  int x = 2;
+  int y = 2;
+  int z = 2;
+
+  x = z - y;
+  (void)(42 / x); // expected-warning {{Division by zero}}
+}
+
+
+void testNegationPath() {
+  int x = 2;
+  int y = 2;
+  int z = 2;
+
+  x = - y;
+  x = x + z;
+  (void)(42 / x); // expected-warning {{Division by zero}}
+}
+
+
+void testIfThenPath() {
+  int x = 2;
+  int y = 2;
+  int z = 2;
+
+  if(y > 0)
+x = z - y;
+  (void)(42 / x); // expected-warning {{Division by zero}}
+}
+
+
+void testIfElsePath() {
+  int x = 2;
+  int y = 2;
+  int z = 2;
+
+  if(y < 0) {
+x = z - y + 1;
+  } else {
+x = z - y;
+  }
+  (void)(42 / x); // expected-warning {{Division by zero}}
+}
+
+
+void testSwitchPath() {
+  int x = 2;
+  int y = 2;
+  int z = 2;
+
+  switch(y) {
+case 1: x = y; break;
+case 3: x = z; break;
+default: x %= z; break;
+  }
+
+  (void)(42 / x); // expected-warning {{Division by zero}}
+}
+
+
+void testForLoopPath1() {
+  int x = 5;
+
+  for(int i = 0; i < 5; ++i) {
+x = x - 1;
+  }
+  (void)(42 / x); // Missing warning
+}
+
+
+void testForLoopPath2() {
+  int x = 0;
+
+  for(int i = 0; i < 5; ++i) {}
+  (void)(42 / x); // Missing warning
+}
+
+
+void testForLoopPath3() {
+  int x = 0;
+
+  for(int i = 0; i < 1; ++i) {}
+
+  (void)(42 / x); // expected-warning {{Division by zero}}
+}
+
+
+void testWhileLoopPath() {
+  int x = 0;
+
+  int i = 0;
+  while(i < 5) {
+++i;
+  }
+  (void)(42

[PATCH] D52936: Add some automatic tests for DivideZero checker

2018-10-06 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas added a reviewer: dcoughlin.
ztamas added a comment.

Based on CODE_OWNERS.txt.


Repository:
  rC Clang

https://reviews.llvm.org/D52936



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


[PATCH] D60507: [clang-tidy] new check: bugprone-unhandled-self-assignment

2019-05-12 Thread Tamás Zolnai via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL360540: [clang-tidy] new check: 
bugprone-unhandled-self-assignment (authored by ztamas, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D60507?vs=198789&id=199166#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D60507/new/

https://reviews.llvm.org/D60507

Files:
  clang-tools-extra/trunk/clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tools-extra/trunk/clang-tidy/bugprone/CMakeLists.txt
  clang-tools-extra/trunk/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
  clang-tools-extra/trunk/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.h
  clang-tools-extra/trunk/docs/ReleaseNotes.rst
  
clang-tools-extra/trunk/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst
  clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst
  clang-tools-extra/trunk/test/clang-tidy/bugprone-unhandled-self-assignment.cpp

Index: clang-tools-extra/trunk/clang-tidy/bugprone/BugproneTidyModule.cpp
===
--- clang-tools-extra/trunk/clang-tidy/bugprone/BugproneTidyModule.cpp
+++ clang-tools-extra/trunk/clang-tidy/bugprone/BugproneTidyModule.cpp
@@ -46,6 +46,7 @@
 #include "TooSmallLoopVariableCheck.h"
 #include "UndefinedMemoryManipulationCheck.h"
 #include "UndelegatedConstructorCheck.h"
+#include "UnhandledSelfAssignmentCheck.h"
 #include "UnusedRaiiCheck.h"
 #include "UnusedReturnValueCheck.h"
 #include "UseAfterMoveCheck.h"
@@ -132,6 +133,8 @@
 "bugprone-undefined-memory-manipulation");
 CheckFactories.registerCheck(
 "bugprone-undelegated-constructor");
+CheckFactories.registerCheck(
+"bugprone-unhandled-self-assignment");
 CheckFactories.registerCheck(
 "bugprone-unused-raii");
 CheckFactories.registerCheck(
Index: clang-tools-extra/trunk/clang-tidy/bugprone/CMakeLists.txt
===
--- clang-tools-extra/trunk/clang-tidy/bugprone/CMakeLists.txt
+++ clang-tools-extra/trunk/clang-tidy/bugprone/CMakeLists.txt
@@ -38,6 +38,7 @@
   TooSmallLoopVariableCheck.cpp
   UndefinedMemoryManipulationCheck.cpp
   UndelegatedConstructorCheck.cpp
+  UnhandledSelfAssignmentCheck.cpp
   UnusedRaiiCheck.cpp
   UnusedReturnValueCheck.cpp
   UseAfterMoveCheck.cpp
Index: clang-tools-extra/trunk/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
===
--- clang-tools-extra/trunk/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
+++ clang-tools-extra/trunk/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
@@ -0,0 +1,99 @@
+//===--- UnhandledSelfAssignmentCheck.cpp - clang-tidy ===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "UnhandledSelfAssignmentCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+void UnhandledSelfAssignmentCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+return;
+
+  // We don't care about deleted, default or implicit operator implementations.
+  const auto IsUserDefined = cxxMethodDecl(
+  isDefinition(), unless(anyOf(isDeleted(), isImplicit(), isDefaulted(;
+
+  // We don't need to worry when a copy assignment operator gets the other
+  // object by value.
+  const auto HasReferenceParam =
+  cxxMethodDecl(hasParameter(0, parmVarDecl(hasType(referenceType();
+
+  // Self-check: Code compares something with 'this' pointer. We don't check
+  // whether it is actually the parameter what we compare.
+  const auto HasNoSelfCheck = cxxMethodDecl(unless(hasDescendant(
+  binaryOperator(anyOf(hasOperatorName("=="), hasOperatorName("!=")),
+ has(ignoringParenCasts(cxxThisExpr()));
+
+  // Both copy-and-swap and copy-and-move method creates a copy first and
+  // assign it to 'this' with swap or move.
+  // In the non-template case, we can search for the copy constructor call.
+  const auto HasNonTemplateSelfCopy = cxxMethodDecl(
+  ofClass(cxxRecordDecl(unless(hasAncestor(classTemplateDecl(),
+  hasDescendant(cxxConstructExpr(hasDeclaration(cxxConstructorDecl(
+  isCopyConstructor(), ofClass(equalsBoundNode("class")));
+
+  // In the template case, we need to handle two separate cases: 1) a local
+  // variable is created with the copy, 2) copy is created only as a temporary
+  // object.
+  const auto HasTemplateSelfCopy = cxxMethodDecl(
+  ofClass(c

[PATCH] D62192: [clang-tidy]: Add cert-oop54-cpp alias for bugprone-unhandled-self-assignment

2019-05-21 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas created this revision.
Herald added subscribers: cfe-commits, xazax.hun.
Herald added a project: clang.

Added WarnOnlyIfThisHasSuspiciousField option to allow
to catch any copy assignment operator independently from
the container class's fields.
Added the cert alias using this option.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D62192

Files:
  clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.h
  clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
  
clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst
  clang-tools-extra/docs/clang-tidy/checks/cert-oop54-cpp.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment-warn-only-if-this-has-suspicious-field.cpp
  clang-tools-extra/test/clang-tidy/cert-oop54-cpp.cpp

Index: clang-tools-extra/test/clang-tidy/cert-oop54-cpp.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/cert-oop54-cpp.cpp
@@ -0,0 +1,16 @@
+// RUN: %check_clang_tidy %s cert-oop54-cpp %t
+
+// Test whether bugprone-unhandled-self-assignment.WarnOnlyIfThisHasSuspiciousField option is set correctly.
+class TrivialFields {
+public:
+  TrivialFields &operator=(const TrivialFields &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:18: warning: operator=() does not handle self-assignment properly [cert-oop54-cpp]
+return *this;
+  }
+
+private:
+  int m;
+  float f;
+  double d;
+  bool b;
+};
Index: clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment-warn-only-if-this-has-suspicious-field.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment-warn-only-if-this-has-suspicious-field.cpp
@@ -0,0 +1,41 @@
+// RUN: %check_clang_tidy %s bugprone-unhandled-self-assignment %t -- \
+// RUN:   -config="{CheckOptions: \
+// RUN: [{key: bugprone-unhandled-self-assignment.WarnOnlyIfThisHasSuspiciousField, \
+// RUN:   value: 0}]}"
+
+// Classes with pointer field are still caught.
+class PtrField {
+public:
+  PtrField &operator=(const PtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:13: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
+return *this;
+  }
+
+private:
+  int *p;
+};
+
+// With the option, check catches classes with trivial fields.
+class TrivialFields {
+public:
+  TrivialFields &operator=(const TrivialFields &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:18: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
+return *this;
+  }
+
+private:
+  int m;
+  float f;
+  double d;
+  bool b;
+};
+
+// The check warns also when there is no field at all.
+// In this case, user-defined copy assignment operator is useless anyway.
+class ClassWithoutFields {
+public:
+  ClassWithoutFields &operator=(const ClassWithoutFields &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:23: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
+return *this;
+  }
+};
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -98,6 +98,7 @@
cert-msc50-cpp
cert-msc51-cpp
cert-oop11-cpp (redirects to performance-move-constructor-init) 
+   cert-oop54-cpp (redirects to bugprone-unhandled-self-assignment) 
cppcoreguidelines-avoid-c-arrays (redirects to modernize-avoid-c-arrays) 
cppcoreguidelines-avoid-goto
cppcoreguidelines-avoid-magic-numbers (redirects to readability-magic-numbers) 
Index: clang-tools-extra/docs/clang-tidy/checks/cert-oop54-cpp.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/cert-oop54-cpp.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - cert-oop54-cpp
+.. meta::
+   :http-equiv=refresh: 5;URL=bugprone-unhandled-self-assignment.html
+
+cert-oop54-cpp
+==
+
+The cert-oop54-cpp check is an alias, please see
+`bugprone-unhandled-self-assignment `_
+for more information.
Index: clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst
+++ clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst
@@ -3,11 +3,14 @@
 bugprone-unhandled-self-assignment
 ==
 
+`cert-oop54-cpp` redirects here as an alias for this check. For the cert alias
+WarnOnlyIfThisHasSuspiciousField option is set to `0`.
+
 Finds user-defined copy

[PATCH] D62192: [clang-tidy]: Add cert-oop54-cpp alias for bugprone-unhandled-self-assignment

2019-05-22 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas updated this revision to Diff 200714.
ztamas added a comment.

Fixed docs.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D62192/new/

https://reviews.llvm.org/D62192

Files:
  clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.h
  clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst
  clang-tools-extra/docs/clang-tidy/checks/cert-oop54-cpp.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment-warn-only-if-this-has-suspicious-field.cpp
  clang-tools-extra/test/clang-tidy/cert-oop54-cpp.cpp

Index: clang-tools-extra/test/clang-tidy/cert-oop54-cpp.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/cert-oop54-cpp.cpp
@@ -0,0 +1,16 @@
+// RUN: %check_clang_tidy %s cert-oop54-cpp %t
+
+// Test whether bugprone-unhandled-self-assignment.WarnOnlyIfThisHasSuspiciousField option is set correctly.
+class TrivialFields {
+public:
+  TrivialFields &operator=(const TrivialFields &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:18: warning: operator=() does not handle self-assignment properly [cert-oop54-cpp]
+return *this;
+  }
+
+private:
+  int m;
+  float f;
+  double d;
+  bool b;
+};
Index: clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment-warn-only-if-this-has-suspicious-field.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment-warn-only-if-this-has-suspicious-field.cpp
@@ -0,0 +1,41 @@
+// RUN: %check_clang_tidy %s bugprone-unhandled-self-assignment %t -- \
+// RUN:   -config="{CheckOptions: \
+// RUN: [{key: bugprone-unhandled-self-assignment.WarnOnlyIfThisHasSuspiciousField, \
+// RUN:   value: 0}]}"
+
+// Classes with pointer field are still caught.
+class PtrField {
+public:
+  PtrField &operator=(const PtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:13: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
+return *this;
+  }
+
+private:
+  int *p;
+};
+
+// With the option, check catches classes with trivial fields.
+class TrivialFields {
+public:
+  TrivialFields &operator=(const TrivialFields &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:18: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
+return *this;
+  }
+
+private:
+  int m;
+  float f;
+  double d;
+  bool b;
+};
+
+// The check warns also when there is no field at all.
+// In this case, user-defined copy assignment operator is useless anyway.
+class ClassWithoutFields {
+public:
+  ClassWithoutFields &operator=(const ClassWithoutFields &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:23: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
+return *this;
+  }
+};
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -98,6 +98,7 @@
cert-msc50-cpp
cert-msc51-cpp
cert-oop11-cpp (redirects to performance-move-constructor-init) 
+   cert-oop54-cpp (redirects to bugprone-unhandled-self-assignment) 
cppcoreguidelines-avoid-c-arrays (redirects to modernize-avoid-c-arrays) 
cppcoreguidelines-avoid-goto
cppcoreguidelines-avoid-magic-numbers (redirects to readability-magic-numbers) 
Index: clang-tools-extra/docs/clang-tidy/checks/cert-oop54-cpp.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/cert-oop54-cpp.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - cert-oop54-cpp
+.. meta::
+   :http-equiv=refresh: 5;URL=bugprone-unhandled-self-assignment.html
+
+cert-oop54-cpp
+==
+
+The cert-oop54-cpp check is an alias, please see
+`bugprone-unhandled-self-assignment `_
+for more information.
Index: clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst
+++ clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst
@@ -3,11 +3,14 @@
 bugprone-unhandled-self-assignment
 ==
 
+`cert-oop54-cpp` redirects here as an alias for this check. For the CERT alias,
+the `WarnOnlyIfThisHasSuspiciousField` option is set to `0`.
+
 Finds user-defined copy assignment operators which do not protect the code
 against self-assignment either by checking s

[PATCH] D62192: [clang-tidy]: Add cert-oop54-cpp alias for bugprone-unhandled-self-assignment

2019-05-22 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas updated this revision to Diff 200775.
ztamas added a comment.
Herald added a subscriber: mgorny.

Link burprone module to cert module


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D62192/new/

https://reviews.llvm.org/D62192

Files:
  clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.h
  clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
  clang-tools-extra/clang-tidy/cert/CMakeLists.txt
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst
  clang-tools-extra/docs/clang-tidy/checks/cert-oop54-cpp.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment-warn-only-if-this-has-suspicious-field.cpp
  clang-tools-extra/test/clang-tidy/cert-oop54-cpp.cpp

Index: clang-tools-extra/test/clang-tidy/cert-oop54-cpp.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/cert-oop54-cpp.cpp
@@ -0,0 +1,16 @@
+// RUN: %check_clang_tidy %s cert-oop54-cpp %t
+
+// Test whether bugprone-unhandled-self-assignment.WarnOnlyIfThisHasSuspiciousField option is set correctly.
+class TrivialFields {
+public:
+  TrivialFields &operator=(const TrivialFields &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:18: warning: operator=() does not handle self-assignment properly [cert-oop54-cpp]
+return *this;
+  }
+
+private:
+  int m;
+  float f;
+  double d;
+  bool b;
+};
Index: clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment-warn-only-if-this-has-suspicious-field.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment-warn-only-if-this-has-suspicious-field.cpp
@@ -0,0 +1,41 @@
+// RUN: %check_clang_tidy %s bugprone-unhandled-self-assignment %t -- \
+// RUN:   -config="{CheckOptions: \
+// RUN: [{key: bugprone-unhandled-self-assignment.WarnOnlyIfThisHasSuspiciousField, \
+// RUN:   value: 0}]}"
+
+// Classes with pointer field are still caught.
+class PtrField {
+public:
+  PtrField &operator=(const PtrField &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:13: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
+return *this;
+  }
+
+private:
+  int *p;
+};
+
+// With the option, check catches classes with trivial fields.
+class TrivialFields {
+public:
+  TrivialFields &operator=(const TrivialFields &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:18: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
+return *this;
+  }
+
+private:
+  int m;
+  float f;
+  double d;
+  bool b;
+};
+
+// The check warns also when there is no field at all.
+// In this case, user-defined copy assignment operator is useless anyway.
+class ClassWithoutFields {
+public:
+  ClassWithoutFields &operator=(const ClassWithoutFields &object) {
+// CHECK-MESSAGES: [[@LINE-1]]:23: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
+return *this;
+  }
+};
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -98,6 +98,7 @@
cert-msc50-cpp
cert-msc51-cpp
cert-oop11-cpp (redirects to performance-move-constructor-init) 
+   cert-oop54-cpp (redirects to bugprone-unhandled-self-assignment) 
cppcoreguidelines-avoid-c-arrays (redirects to modernize-avoid-c-arrays) 
cppcoreguidelines-avoid-goto
cppcoreguidelines-avoid-magic-numbers (redirects to readability-magic-numbers) 
Index: clang-tools-extra/docs/clang-tidy/checks/cert-oop54-cpp.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/cert-oop54-cpp.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - cert-oop54-cpp
+.. meta::
+   :http-equiv=refresh: 5;URL=bugprone-unhandled-self-assignment.html
+
+cert-oop54-cpp
+==
+
+The cert-oop54-cpp check is an alias, please see
+`bugprone-unhandled-self-assignment `_
+for more information.
Index: clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst
+++ clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst
@@ -3,11 +3,14 @@
 bugprone-unhandled-self-assignment
 ==
 
+`cert-oop54-cpp` redirects here as an alias for this check. For the CERT alias,
+the `WarnOnlyIfThisHasSuspiciousField` option is set to `0`.
+
 Finds user

[PATCH] D62192: [clang-tidy]: Add cert-oop54-cpp alias for bugprone-unhandled-self-assignment

2019-05-23 Thread Tamás Zolnai via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rCTE361550: [clang-tidy]: Add cert-oop54-cpp alias for 
bugprone-unhandled-self-assignment (authored by ztamas, committed by ).

Changed prior to commit:
  https://reviews.llvm.org/D62192?vs=200775&id=201051#toc

Repository:
  rCTE Clang Tools Extra

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D62192/new/

https://reviews.llvm.org/D62192

Files:
  clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
  clang-tidy/bugprone/UnhandledSelfAssignmentCheck.h
  clang-tidy/cert/CERTTidyModule.cpp
  clang-tidy/cert/CMakeLists.txt
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst
  docs/clang-tidy/checks/cert-oop54-cpp.rst
  docs/clang-tidy/checks/list.rst
  
test/clang-tidy/bugprone-unhandled-self-assignment-warn-only-if-this-has-suspicious-field.cpp
  test/clang-tidy/cert-oop54-cpp.cpp

Index: clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
===
--- clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
+++ clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
@@ -16,6 +16,18 @@
 namespace tidy {
 namespace bugprone {
 
+UnhandledSelfAssignmentCheck::UnhandledSelfAssignmentCheck(
+StringRef Name, ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  WarnOnlyIfThisHasSuspiciousField(
+  Options.get("WarnOnlyIfThisHasSuspiciousField", true)) {}
+
+void UnhandledSelfAssignmentCheck::storeOptions(
+ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "WarnOnlyIfThisHasSuspiciousField",
+WarnOnlyIfThisHasSuspiciousField);
+}
+
 void UnhandledSelfAssignmentCheck::registerMatchers(MatchFinder *Finder) {
   if (!getLangOpts().CPlusPlus)
 return;
@@ -61,29 +73,32 @@
   cxxMethodDecl(unless(hasDescendant(cxxMemberCallExpr(callee(cxxMethodDecl(
   hasName("operator="), ofClass(equalsBoundNode("class";
 
-  // Matcher for standard smart pointers.
-  const auto SmartPointerType = qualType(hasUnqualifiedDesugaredType(
-  recordType(hasDeclaration(classTemplateSpecializationDecl(
-  hasAnyName("::std::shared_ptr", "::std::unique_ptr",
- "::std::weak_ptr", "::std::auto_ptr"),
-  templateArgumentCountIs(1));
-
-  // We will warn only if the class has a pointer or a C array field which
-  // probably causes a problem during self-assignment (e.g. first resetting the
-  // pointer member, then trying to access the object pointed by the pointer, or
-  // memcpy overlapping arrays).
-  const auto ThisHasSuspiciousField = cxxMethodDecl(ofClass(cxxRecordDecl(
-  has(fieldDecl(anyOf(hasType(pointerType()), hasType(SmartPointerType),
-  hasType(arrayType(;
-
-  Finder->addMatcher(
-  cxxMethodDecl(ofClass(cxxRecordDecl().bind("class")),
-isCopyAssignmentOperator(), IsUserDefined,
-HasReferenceParam, HasNoSelfCheck,
-unless(HasNonTemplateSelfCopy), unless(HasTemplateSelfCopy),
-HasNoNestedSelfAssign, ThisHasSuspiciousField)
-  .bind("copyAssignmentOperator"),
-  this);
+  DeclarationMatcher AdditionalMatcher = cxxMethodDecl();
+  if (WarnOnlyIfThisHasSuspiciousField) {
+// Matcher for standard smart pointers.
+const auto SmartPointerType = qualType(hasUnqualifiedDesugaredType(
+recordType(hasDeclaration(classTemplateSpecializationDecl(
+hasAnyName("::std::shared_ptr", "::std::unique_ptr",
+   "::std::weak_ptr", "::std::auto_ptr"),
+templateArgumentCountIs(1));
+
+// We will warn only if the class has a pointer or a C array field which
+// probably causes a problem during self-assignment (e.g. first resetting
+// the pointer member, then trying to access the object pointed by the
+// pointer, or memcpy overlapping arrays).
+AdditionalMatcher = cxxMethodDecl(ofClass(cxxRecordDecl(
+has(fieldDecl(anyOf(hasType(pointerType()), hasType(SmartPointerType),
+hasType(arrayType(;
+  }
+
+  Finder->addMatcher(cxxMethodDecl(ofClass(cxxRecordDecl().bind("class")),
+   isCopyAssignmentOperator(), IsUserDefined,
+   HasReferenceParam, HasNoSelfCheck,
+   unless(HasNonTemplateSelfCopy),
+   unless(HasTemplateSelfCopy),
+   HasNoNestedSelfAssign, AdditionalMatcher)
+ .bind("copyAssignmentOperator"),
+ this);
 }
 
 void UnhandledSelfAssignmentCheck::check(
Index: clang-tidy/bugprone/UnhandledSelfAssignmentCheck.h
===
--- clang-tidy/bugprone/UnhandledSelfAssignmentCheck.h
+++ clang-tidy/bugprone/UnhandledSelfAssignmentCh

[PATCH] D76990: [clang-tidy]: fix false positive of cert-oop54-cpp check.

2020-04-04 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas updated this revision to Diff 255038.
ztamas added a comment.

Add suggested test case and rebase.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D76990/new/

https://reviews.llvm.org/D76990

Files:
  clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
  
clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-self-assignment.cpp


Index: 
clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-self-assignment.cpp
===
--- 
clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-self-assignment.cpp
+++ 
clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-self-assignment.cpp
@@ -212,6 +212,21 @@
   T *p;
 };
 
+// https://bugs.llvm.org/show_bug.cgi?id=44499
+class Foo2;
+template 
+bool operator!=(Foo2 &, Foo2 &) {
+  class Bar2 {
+Bar2 &operator=(const Bar2 &other) {
+  // CHECK-MESSAGES: [[@LINE-1]]:11: warning: operator=() does not handle 
self-assignment properly [bugprone-unhandled-self-assignment]
+  p = other.p;
+  return *this;
+}
+
+int *p;
+  };
+}
+
 ///
 /// Test cases correctly ignored by the check.
 
@@ -283,6 +298,21 @@
   T *p;
 };
 
+// https://bugs.llvm.org/show_bug.cgi?id=44499
+class Foo;
+template 
+bool operator!=(Foo &, Foo &) {
+  class Bar {
+Bar &operator=(const Bar &other) {
+  if (this != &other) {
+  }
+  return *this;
+}
+
+int *p;
+  };
+}
+
 // There is no warning if the copy assignment operator gets the object by 
value.
 class PassedByValue {
 public:
Index: clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
===
--- clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
+++ clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
@@ -40,9 +40,12 @@
 
   // Self-check: Code compares something with 'this' pointer. We don't check
   // whether it is actually the parameter what we compare.
-  const auto HasNoSelfCheck = cxxMethodDecl(unless(
+  const auto HasNoSelfCheck = cxxMethodDecl(unless(anyOf(
   hasDescendant(binaryOperator(hasAnyOperatorName("==", "!="),
-   has(ignoringParenCasts(cxxThisExpr()));
+   has(ignoringParenCasts(cxxThisExpr(),
+  hasDescendant(cxxOperatorCallExpr(
+  hasAnyOverloadedOperatorName("==", "!="), argumentCountIs(2),
+  has(ignoringParenCasts(cxxThisExpr(;
 
   // Both copy-and-swap and copy-and-move method creates a copy first and
   // assign it to 'this' with swap or move.


Index: clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-self-assignment.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-self-assignment.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-self-assignment.cpp
@@ -212,6 +212,21 @@
   T *p;
 };
 
+// https://bugs.llvm.org/show_bug.cgi?id=44499
+class Foo2;
+template 
+bool operator!=(Foo2 &, Foo2 &) {
+  class Bar2 {
+Bar2 &operator=(const Bar2 &other) {
+  // CHECK-MESSAGES: [[@LINE-1]]:11: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
+  p = other.p;
+  return *this;
+}
+
+int *p;
+  };
+}
+
 ///
 /// Test cases correctly ignored by the check.
 
@@ -283,6 +298,21 @@
   T *p;
 };
 
+// https://bugs.llvm.org/show_bug.cgi?id=44499
+class Foo;
+template 
+bool operator!=(Foo &, Foo &) {
+  class Bar {
+Bar &operator=(const Bar &other) {
+  if (this != &other) {
+  }
+  return *this;
+}
+
+int *p;
+  };
+}
+
 // There is no warning if the copy assignment operator gets the object by value.
 class PassedByValue {
 public:
Index: clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
===
--- clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
+++ clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
@@ -40,9 +40,12 @@
 
   // Self-check: Code compares something with 'this' pointer. We don't check
   // whether it is actually the parameter what we compare.
-  const auto HasNoSelfCheck = cxxMethodDecl(unless(
+  const auto HasNoSelfCheck = cxxMethodDecl(unless(anyOf(
   hasDescendant(binaryOperator(hasAnyOperatorName("==", "!="),
-   has(ignoringParenCasts(cxxThisExpr()));
+   has(ignoringParenCasts(cxxThisExpr(),
+  hasDescendant(cxxOperatorCallExpr(
+  hasAnyOverloadedOperatorName("==", "!="), argumentCountIs(2),
+  has(ignoringParenCasts(cxxThisExpr(;

[PATCH] D76990: [clang-tidy]: fix false positive of cert-oop54-cpp check.

2020-04-04 Thread Tamás Zolnai via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG0f9e1e3ae750: [clang-tidy]: fix false positive of 
cert-oop54-cpp check. (authored by ztamas).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D76990/new/

https://reviews.llvm.org/D76990

Files:
  clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
  
clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-self-assignment.cpp


Index: 
clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-self-assignment.cpp
===
--- 
clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-self-assignment.cpp
+++ 
clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-self-assignment.cpp
@@ -212,6 +212,21 @@
   T *p;
 };
 
+// https://bugs.llvm.org/show_bug.cgi?id=44499
+class Foo2;
+template 
+bool operator!=(Foo2 &, Foo2 &) {
+  class Bar2 {
+Bar2 &operator=(const Bar2 &other) {
+  // CHECK-MESSAGES: [[@LINE-1]]:11: warning: operator=() does not handle 
self-assignment properly [bugprone-unhandled-self-assignment]
+  p = other.p;
+  return *this;
+}
+
+int *p;
+  };
+}
+
 ///
 /// Test cases correctly ignored by the check.
 
@@ -283,6 +298,21 @@
   T *p;
 };
 
+// https://bugs.llvm.org/show_bug.cgi?id=44499
+class Foo;
+template 
+bool operator!=(Foo &, Foo &) {
+  class Bar {
+Bar &operator=(const Bar &other) {
+  if (this != &other) {
+  }
+  return *this;
+}
+
+int *p;
+  };
+}
+
 // There is no warning if the copy assignment operator gets the object by 
value.
 class PassedByValue {
 public:
Index: clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
===
--- clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
+++ clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
@@ -40,9 +40,12 @@
 
   // Self-check: Code compares something with 'this' pointer. We don't check
   // whether it is actually the parameter what we compare.
-  const auto HasNoSelfCheck = cxxMethodDecl(unless(
+  const auto HasNoSelfCheck = cxxMethodDecl(unless(anyOf(
   hasDescendant(binaryOperator(hasAnyOperatorName("==", "!="),
-   has(ignoringParenCasts(cxxThisExpr()));
+   has(ignoringParenCasts(cxxThisExpr(),
+  hasDescendant(cxxOperatorCallExpr(
+  hasAnyOverloadedOperatorName("==", "!="), argumentCountIs(2),
+  has(ignoringParenCasts(cxxThisExpr(;
 
   // Both copy-and-swap and copy-and-move method creates a copy first and
   // assign it to 'this' with swap or move.


Index: clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-self-assignment.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-self-assignment.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-self-assignment.cpp
@@ -212,6 +212,21 @@
   T *p;
 };
 
+// https://bugs.llvm.org/show_bug.cgi?id=44499
+class Foo2;
+template 
+bool operator!=(Foo2 &, Foo2 &) {
+  class Bar2 {
+Bar2 &operator=(const Bar2 &other) {
+  // CHECK-MESSAGES: [[@LINE-1]]:11: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
+  p = other.p;
+  return *this;
+}
+
+int *p;
+  };
+}
+
 ///
 /// Test cases correctly ignored by the check.
 
@@ -283,6 +298,21 @@
   T *p;
 };
 
+// https://bugs.llvm.org/show_bug.cgi?id=44499
+class Foo;
+template 
+bool operator!=(Foo &, Foo &) {
+  class Bar {
+Bar &operator=(const Bar &other) {
+  if (this != &other) {
+  }
+  return *this;
+}
+
+int *p;
+  };
+}
+
 // There is no warning if the copy assignment operator gets the object by value.
 class PassedByValue {
 public:
Index: clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
===
--- clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
+++ clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp
@@ -40,9 +40,12 @@
 
   // Self-check: Code compares something with 'this' pointer. We don't check
   // whether it is actually the parameter what we compare.
-  const auto HasNoSelfCheck = cxxMethodDecl(unless(
+  const auto HasNoSelfCheck = cxxMethodDecl(unless(anyOf(
   hasDescendant(binaryOperator(hasAnyOperatorName("==", "!="),
-   has(ignoringParenCasts(cxxThisExpr()));
+   has(ignoringParenCasts(cxxThisExpr(),
+  hasDescendant(cxxOperatorCallExpr(
+  hasAnyOverloadedOperatorName("==", "

[PATCH] D78904: [clang-tidy] extend bugprone-signed-char-misuse check with array subscript case.

2020-04-27 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas added a comment.

I run the check both on LibreOffice and LLVM codebase but did not find any 
catch. I expect that it's not a frequent use case.
I added this extension only to fully cover the CERT rule. If this patch is 
accepted I can add a cert alias for this check.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D78904/new/

https://reviews.llvm.org/D78904



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


[PATCH] D78904: [clang-tidy] extend bugprone-signed-char-misuse check with array subscript case.

2020-04-27 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas created this revision.
Herald added subscribers: cfe-commits, xazax.hun.
Herald added a project: clang.
ztamas added a reviewer: aaron.ballman.
ztamas added a comment.
ztamas updated this revision to Diff 260243.

I run the check both on LibreOffice and LLVM codebase but did not find any 
catch. I expect that it's not a frequent use case.
I added this extension only to fully cover the CERT rule. If this patch is 
accepted I can add a cert alias for this check.


ztamas added a comment.

Fix typo


To cover STR34-C rule's second use case, where ``signed char`` is
used for array subscript after an integer conversion. In the case
of non-ASCII character a ``signed char`` will result in a value
in excess of UCHAR_MAX because of integer promotion.

There is another clang-tidy check which catches these cases.
cppcoreguidelines-pro-bounds-constant-array-index catches any
indexing which is not integer constant. I think this check is
very strict about the index (e.g. constant), so it's still useful
to cover the ``signed char`` use case in this check, so we
can provide a way to catch the SEI cert rule's use cases on a
codebase, where this CPP guideline is not used.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D78904

Files:
  clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp
  clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst
  clang-tools-extra/test/clang-tidy/checkers/bugprone-signed-char-misuse.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/bugprone-signed-char-misuse.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/bugprone-signed-char-misuse.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/bugprone-signed-char-misuse.cpp
@@ -3,6 +3,16 @@
 ///
 /// Test cases correctly caught by the check.
 
+typedef __SIZE_TYPE__ size_t;
+
+namespace std {
+template 
+struct array {
+  T &operator[](size_t n);
+  T &at(size_t n);
+};
+} // namespace std
+
 int SimpleVarDeclaration() {
   signed char CCharacter = -5;
   int NCharacter = CCharacter;
@@ -90,6 +100,16 @@
   return 0;
 }
 
+int SignedCharCArraySubscript(signed char SCharacter) {
+  int Array[3] = {1, 2, 3};
+
+  return Array[static_cast(SCharacter)]; // CHECK-MESSAGES: [[@LINE]]:42: warning: 'signed char' to 'unsigned int' conversion in array subscript; consider casting to 'unsigned char' first. [bugprone-signed-char-misuse]
+}
+
+int SignedCharSTDArraySubscript(std::array Array, signed char SCharacter) {
+  return Array[static_cast(SCharacter)]; // CHECK-MESSAGES: [[@LINE]]:42: warning: 'signed char' to 'unsigned int' conversion in array subscript; consider casting to 'unsigned char' first. [bugprone-signed-char-misuse]
+}
+
 ///
 /// Test cases correctly ignored by the check.
 
@@ -207,3 +227,23 @@
 return 1;
   return 0;
 }
+
+int UnsignedCharCArraySubscript(unsigned char USCharacter) {
+  int Array[3] = {1, 2, 3};
+
+  return Array[static_cast(USCharacter)];
+}
+
+int CastedCArraySubscript(signed char SCharacter) {
+  int Array[3] = {1, 2, 3};
+
+  return Array[static_cast(SCharacter)];
+}
+
+int UnsignedCharSTDArraySubscript(std::array Array, unsigned char USCharacter) {
+  return Array[static_cast(USCharacter)];
+}
+
+int CastedSTDArraySubscript(std::array Array, signed char SCharacter) {
+  return Array[static_cast(SCharacter)];
+}
Index: clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst
+++ clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst
@@ -31,11 +31,10 @@
 by default and so it is caught by this check or not. To change the default behavior
 you can use ``-funsigned-char`` and ``-fsigned-char`` compilation options.
 
-Currently, this check is limited to assignments and variable declarations,
-where a ``signed char`` is assigned to an integer variable and to
-equality/inequality comparisons between ``signed char`` and ``unsigned char``.
-There are other use cases where the unexpected value ranges might lead to
-similar bogus behavior.
+Currently, this check warns in the following cases:
+- ``signed char`` is assigned to an integer variable
+- ``signed char`` and ``unsigned char`` are compared with equality/unequality operator
+- ``signed char`` is converted to integer before array subscript
 
 See also:
 `STR34-C. Cast characters to unsigned char before converting to larger integer sizes
Index: clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp
===
--- clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp
+++ clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp
@@ -102,11 +102,31 @@
   .bind("co

[PATCH] D78904: [clang-tidy] extend bugprone-signed-char-misuse check with array subscript case.

2020-04-27 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas updated this revision to Diff 260243.
ztamas added a comment.

Fix typo


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D78904/new/

https://reviews.llvm.org/D78904

Files:
  clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp
  clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst
  clang-tools-extra/test/clang-tidy/checkers/bugprone-signed-char-misuse.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/bugprone-signed-char-misuse.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/bugprone-signed-char-misuse.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/bugprone-signed-char-misuse.cpp
@@ -3,6 +3,16 @@
 ///
 /// Test cases correctly caught by the check.
 
+typedef __SIZE_TYPE__ size_t;
+
+namespace std {
+template 
+struct array {
+  T &operator[](size_t n);
+  T &at(size_t n);
+};
+} // namespace std
+
 int SimpleVarDeclaration() {
   signed char CCharacter = -5;
   int NCharacter = CCharacter;
@@ -90,6 +100,16 @@
   return 0;
 }
 
+int SignedCharCArraySubscript(signed char SCharacter) {
+  int Array[3] = {1, 2, 3};
+
+  return Array[static_cast(SCharacter)]; // CHECK-MESSAGES: [[@LINE]]:42: warning: 'signed char' to 'unsigned int' conversion in array subscript; consider casting to 'unsigned char' first. [bugprone-signed-char-misuse]
+}
+
+int SignedCharSTDArraySubscript(std::array Array, signed char SCharacter) {
+  return Array[static_cast(SCharacter)]; // CHECK-MESSAGES: [[@LINE]]:42: warning: 'signed char' to 'unsigned int' conversion in array subscript; consider casting to 'unsigned char' first. [bugprone-signed-char-misuse]
+}
+
 ///
 /// Test cases correctly ignored by the check.
 
@@ -207,3 +227,23 @@
 return 1;
   return 0;
 }
+
+int UnsignedCharCArraySubscript(unsigned char USCharacter) {
+  int Array[3] = {1, 2, 3};
+
+  return Array[static_cast(USCharacter)];
+}
+
+int CastedCArraySubscript(signed char SCharacter) {
+  int Array[3] = {1, 2, 3};
+
+  return Array[static_cast(SCharacter)];
+}
+
+int UnsignedCharSTDArraySubscript(std::array Array, unsigned char USCharacter) {
+  return Array[static_cast(USCharacter)];
+}
+
+int CastedSTDArraySubscript(std::array Array, signed char SCharacter) {
+  return Array[static_cast(SCharacter)];
+}
Index: clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst
+++ clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst
@@ -31,11 +31,10 @@
 by default and so it is caught by this check or not. To change the default behavior
 you can use ``-funsigned-char`` and ``-fsigned-char`` compilation options.
 
-Currently, this check is limited to assignments and variable declarations,
-where a ``signed char`` is assigned to an integer variable and to
-equality/inequality comparisons between ``signed char`` and ``unsigned char``.
-There are other use cases where the unexpected value ranges might lead to
-similar bogus behavior.
+Currently, this check warns in the following cases:
+- ``signed char`` is assigned to an integer variable
+- ``signed char`` and ``unsigned char`` are compared with equality/unequality operator
+- ``signed char`` is converted to integer before array subscript
 
 See also:
 `STR34-C. Cast characters to unsigned char before converting to larger integer sizes
Index: clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp
===
--- clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp
+++ clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp
@@ -102,11 +102,31 @@
   .bind("comparison");
 
   Finder->addMatcher(CompareOperator, this);
+
+  // Catch array subscripts with singed char -> integer conversion.
+  // Matcher for C arrays.
+  const auto CArraySubscript =
+  arraySubscriptExpr(hasIndex(SignedCharCastExpr)).bind("arraySubscript");
+
+  Finder->addMatcher(CArraySubscript, this);
+
+  // Matcher for std arrays.
+  const auto STDArraySubscript =
+  cxxOperatorCallExpr(
+  hasOverloadedOperatorName("[]"),
+  hasArgument(0, hasType(cxxRecordDecl(hasName("::std::array",
+  hasArgument(1, SignedCharCastExpr))
+  .bind("arraySubscript");
+
+  Finder->addMatcher(STDArraySubscript, this);
 }
 
 void SignedCharMisuseCheck::check(const MatchFinder::MatchResult &Result) {
   const auto *SignedCastExpression =
   Result.Nodes.getNodeAs("signedCastExpression");
+  const auto *IntegerType = Result.Nodes.getNodeAs("integerType");
+  assert(SignedCastExpression);
+  assert(IntegerType);
 
   // Ignore the match if we know that the signed char's value is n

[PATCH] D78904: [clang-tidy] extend bugprone-signed-char-misuse check with array subscript case.

2020-05-02 Thread Tamás Zolnai via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG030ff901f432: [clang-tidy] extend 
bugprone-signed-char-misuse check with array subscript case. (authored by 
ztamas).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D78904/new/

https://reviews.llvm.org/D78904

Files:
  clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp
  clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst
  clang-tools-extra/test/clang-tidy/checkers/bugprone-signed-char-misuse.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/bugprone-signed-char-misuse.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/bugprone-signed-char-misuse.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/bugprone-signed-char-misuse.cpp
@@ -3,6 +3,16 @@
 ///
 /// Test cases correctly caught by the check.
 
+typedef __SIZE_TYPE__ size_t;
+
+namespace std {
+template 
+struct array {
+  T &operator[](size_t n);
+  T &at(size_t n);
+};
+} // namespace std
+
 int SimpleVarDeclaration() {
   signed char CCharacter = -5;
   int NCharacter = CCharacter;
@@ -90,6 +100,16 @@
   return 0;
 }
 
+int SignedCharCArraySubscript(signed char SCharacter) {
+  int Array[3] = {1, 2, 3};
+
+  return Array[static_cast(SCharacter)]; // CHECK-MESSAGES: [[@LINE]]:42: warning: 'signed char' to 'unsigned int' conversion in array subscript; consider casting to 'unsigned char' first. [bugprone-signed-char-misuse]
+}
+
+int SignedCharSTDArraySubscript(std::array Array, signed char SCharacter) {
+  return Array[static_cast(SCharacter)]; // CHECK-MESSAGES: [[@LINE]]:42: warning: 'signed char' to 'unsigned int' conversion in array subscript; consider casting to 'unsigned char' first. [bugprone-signed-char-misuse]
+}
+
 ///
 /// Test cases correctly ignored by the check.
 
@@ -207,3 +227,23 @@
 return 1;
   return 0;
 }
+
+int UnsignedCharCArraySubscript(unsigned char USCharacter) {
+  int Array[3] = {1, 2, 3};
+
+  return Array[static_cast(USCharacter)];
+}
+
+int CastedCArraySubscript(signed char SCharacter) {
+  int Array[3] = {1, 2, 3};
+
+  return Array[static_cast(SCharacter)];
+}
+
+int UnsignedCharSTDArraySubscript(std::array Array, unsigned char USCharacter) {
+  return Array[static_cast(USCharacter)];
+}
+
+int CastedSTDArraySubscript(std::array Array, signed char SCharacter) {
+  return Array[static_cast(SCharacter)];
+}
Index: clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst
+++ clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst
@@ -31,11 +31,10 @@
 by default and so it is caught by this check or not. To change the default behavior
 you can use ``-funsigned-char`` and ``-fsigned-char`` compilation options.
 
-Currently, this check is limited to assignments and variable declarations,
-where a ``signed char`` is assigned to an integer variable and to
-equality/inequality comparisons between ``signed char`` and ``unsigned char``.
-There are other use cases where the unexpected value ranges might lead to
-similar bogus behavior.
+Currently, this check warns in the following cases:
+- ``signed char`` is assigned to an integer variable
+- ``signed char`` and ``unsigned char`` are compared with equality/inequality operator
+- ``signed char`` is converted to an integer in the array subscript
 
 See also:
 `STR34-C. Cast characters to unsigned char before converting to larger integer sizes
Index: clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp
===
--- clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp
+++ clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp
@@ -102,11 +102,31 @@
   .bind("comparison");
 
   Finder->addMatcher(CompareOperator, this);
+
+  // Catch array subscripts with signed char -> integer conversion.
+  // Matcher for C arrays.
+  const auto CArraySubscript =
+  arraySubscriptExpr(hasIndex(SignedCharCastExpr)).bind("arraySubscript");
+
+  Finder->addMatcher(CArraySubscript, this);
+
+  // Matcher for std arrays.
+  const auto STDArraySubscript =
+  cxxOperatorCallExpr(
+  hasOverloadedOperatorName("[]"),
+  hasArgument(0, hasType(cxxRecordDecl(hasName("::std::array",
+  hasArgument(1, SignedCharCastExpr))
+  .bind("arraySubscript");
+
+  Finder->addMatcher(STDArraySubscript, this);
 }
 
 void SignedCharMisuseCheck::check(const MatchFinder::MatchResult &Result) {
   const auto *SignedCastExpression =
   Result.Nodes.getNodeAs("signedCastExpression");
+  const auto *IntegerType = Result.Nodes.getNodeAs("intege

[PATCH] D78904: [clang-tidy] extend bugprone-signed-char-misuse check with array subscript case.

2020-05-02 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas updated this revision to Diff 261634.
ztamas added a comment.

Spelling / grammar fixes.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D78904/new/

https://reviews.llvm.org/D78904

Files:
  clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp
  clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst
  clang-tools-extra/test/clang-tidy/checkers/bugprone-signed-char-misuse.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/bugprone-signed-char-misuse.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/bugprone-signed-char-misuse.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/bugprone-signed-char-misuse.cpp
@@ -3,6 +3,16 @@
 ///
 /// Test cases correctly caught by the check.
 
+typedef __SIZE_TYPE__ size_t;
+
+namespace std {
+template 
+struct array {
+  T &operator[](size_t n);
+  T &at(size_t n);
+};
+} // namespace std
+
 int SimpleVarDeclaration() {
   signed char CCharacter = -5;
   int NCharacter = CCharacter;
@@ -90,6 +100,16 @@
   return 0;
 }
 
+int SignedCharCArraySubscript(signed char SCharacter) {
+  int Array[3] = {1, 2, 3};
+
+  return Array[static_cast(SCharacter)]; // CHECK-MESSAGES: [[@LINE]]:42: warning: 'signed char' to 'unsigned int' conversion in array subscript; consider casting to 'unsigned char' first. [bugprone-signed-char-misuse]
+}
+
+int SignedCharSTDArraySubscript(std::array Array, signed char SCharacter) {
+  return Array[static_cast(SCharacter)]; // CHECK-MESSAGES: [[@LINE]]:42: warning: 'signed char' to 'unsigned int' conversion in array subscript; consider casting to 'unsigned char' first. [bugprone-signed-char-misuse]
+}
+
 ///
 /// Test cases correctly ignored by the check.
 
@@ -207,3 +227,23 @@
 return 1;
   return 0;
 }
+
+int UnsignedCharCArraySubscript(unsigned char USCharacter) {
+  int Array[3] = {1, 2, 3};
+
+  return Array[static_cast(USCharacter)];
+}
+
+int CastedCArraySubscript(signed char SCharacter) {
+  int Array[3] = {1, 2, 3};
+
+  return Array[static_cast(SCharacter)];
+}
+
+int UnsignedCharSTDArraySubscript(std::array Array, unsigned char USCharacter) {
+  return Array[static_cast(USCharacter)];
+}
+
+int CastedSTDArraySubscript(std::array Array, signed char SCharacter) {
+  return Array[static_cast(SCharacter)];
+}
Index: clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst
+++ clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst
@@ -31,11 +31,10 @@
 by default and so it is caught by this check or not. To change the default behavior
 you can use ``-funsigned-char`` and ``-fsigned-char`` compilation options.
 
-Currently, this check is limited to assignments and variable declarations,
-where a ``signed char`` is assigned to an integer variable and to
-equality/inequality comparisons between ``signed char`` and ``unsigned char``.
-There are other use cases where the unexpected value ranges might lead to
-similar bogus behavior.
+Currently, this check warns in the following cases:
+- ``signed char`` is assigned to an integer variable
+- ``signed char`` and ``unsigned char`` are compared with equality/inequality operator
+- ``signed char`` is converted to an integer in the array subscript
 
 See also:
 `STR34-C. Cast characters to unsigned char before converting to larger integer sizes
Index: clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp
===
--- clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp
+++ clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp
@@ -102,11 +102,31 @@
   .bind("comparison");
 
   Finder->addMatcher(CompareOperator, this);
+
+  // Catch array subscripts with signed char -> integer conversion.
+  // Matcher for C arrays.
+  const auto CArraySubscript =
+  arraySubscriptExpr(hasIndex(SignedCharCastExpr)).bind("arraySubscript");
+
+  Finder->addMatcher(CArraySubscript, this);
+
+  // Matcher for std arrays.
+  const auto STDArraySubscript =
+  cxxOperatorCallExpr(
+  hasOverloadedOperatorName("[]"),
+  hasArgument(0, hasType(cxxRecordDecl(hasName("::std::array",
+  hasArgument(1, SignedCharCastExpr))
+  .bind("arraySubscript");
+
+  Finder->addMatcher(STDArraySubscript, this);
 }
 
 void SignedCharMisuseCheck::check(const MatchFinder::MatchResult &Result) {
   const auto *SignedCastExpression =
   Result.Nodes.getNodeAs("signedCastExpression");
+  const auto *IntegerType = Result.Nodes.getNodeAs("integerType");
+  assert(SignedCastExpression);
+  assert(IntegerType);
 
   // Ignore the match if we know that the sign

[PATCH] D79334: [clang-tidy]: Add cert-str34-c alias for bugprone-signed-char-misuse.

2020-05-04 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas created this revision.
Herald added subscribers: cfe-commits, xazax.hun.
Herald added a project: clang.
ztamas edited the summary of this revision.
ztamas edited the summary of this revision.
ztamas edited the summary of this revision.
ztamas added a reviewer: aaron.ballman.

Added CertSTR34C option to filter out unrelated use cases.
The SEI cert catches explicit integer casts (two use cases),
while in the case of `signed char` \ `unsigned char`
comparison, we have an implicit conversion.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D79334

Files:
  clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.h
  clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst
  clang-tools-extra/docs/clang-tidy/checks/cert-str34-c.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/checkers/cert-str34-c.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/cert-str34-c.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/cert-str34-c.cpp
@@ -0,0 +1,18 @@
+// RUN: %check_clang_tidy %s cert-str34-c %t
+
+// Check whether alias is actually working.
+int SimpleVarDeclaration() {
+  signed char CCharacter = -5;
+  int NCharacter = CCharacter;
+  // CHECK-MESSAGES: [[@LINE-1]]:20: warning: 'signed char' to 'int' conversion; consider casting to 'unsigned char' first. [cert-str34-c]
+
+  return NCharacter;
+}
+
+// Check whether bugprone-signed-char-misuse.CertSTR34C option is set correctly.
+int SignedUnsignedCharEquality(signed char SCharacter) {
+  unsigned char USCharacter = 'a';
+  if (SCharacter == USCharacter) // no warning
+return 1;
+  return 0;
+}
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -320,6 +320,7 @@
`cert-oop11-cpp `_, `performance-move-constructor-init `_, "Yes"
`cert-oop54-cpp `_, `bugprone-unhandled-self-assignment `_,
`cert-pos44-c `_, `bugprone-bad-signal-to-kill-thread `_,
+   `cert-str34-c `_, `bugprone-signed-char-misuse `_,
`clang-analyzer-core.CallAndMessage `_, `Clang Static Analyzer `_,
`clang-analyzer-core.DivideZero `_, `Clang Static Analyzer `_,
`clang-analyzer-core.NonNullParamChecker `_, `Clang Static Analyzer `_,
Index: clang-tools-extra/docs/clang-tidy/checks/cert-str34-c.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/cert-str34-c.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - cert-str34-c
+.. meta::
+   :http-equiv=refresh: 5;URL=bugprone-signed-char-misuse.html
+
+cert-str34-c
+==
+
+The cert-str34-c check is an alias, please see
+`bugprone-signed-char-misuse `_
+for more information.
Index: clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst
+++ clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst
@@ -3,6 +3,9 @@
 bugprone-signed-char-misuse
 ===
 
+`cert-str34-c` redirects here as an alias for this check. For the CERT alias,
+the `CertSTR34C` option is set to `1`.
+
 Finds those ``signed char`` -> integer conversions which might indicate a
 programming error. The basic problem with the ``signed char``, that it might
 store the non-ASCII characters as negative values. This behavior can cause a
@@ -108,3 +111,9 @@
   check. This is useful when a typedef introduces an integer alias like
   ``sal_Int8`` or ``int8_t``. In this case, human misinterpretation is not
   an issue.
+
+.. option:: CertSTR34C
+
+  When non-zero, the check will warn only in the cases described by the
+  STR34-C SEI cert rule. This check covers more use cases, which can be
+  limited with this option.
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -168,6 +168,11 @@
   :doc:`bugprone-reserved-identifier
   ` was added.
 
+- New alias :doc:`cert-str34-c
+  ` to
+  :doc:`bugprone-signed-char-misuse
+  ` was added.
+
 Changes in existing checks
 ^^
 
Index: clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
===
--- clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
+++ clang-tools-

[PATCH] D79334: [clang-tidy]: Add cert-str34-c alias for bugprone-signed-char-misuse.

2020-05-05 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas updated this revision to Diff 262046.
ztamas added a comment.

CertSTR34C -> DiagnoseSignedUnsignedCharComparisons


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D79334/new/

https://reviews.llvm.org/D79334

Files:
  clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.h
  clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst
  clang-tools-extra/docs/clang-tidy/checks/cert-str34-c.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/checkers/cert-str34-c.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/cert-str34-c.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/cert-str34-c.cpp
@@ -0,0 +1,18 @@
+// RUN: %check_clang_tidy %s cert-str34-c %t
+
+// Check whether alias is actually working.
+int SimpleVarDeclaration() {
+  signed char CCharacter = -5;
+  int NCharacter = CCharacter;
+  // CHECK-MESSAGES: [[@LINE-1]]:20: warning: 'signed char' to 'int' conversion; consider casting to 'unsigned char' first. [cert-str34-c]
+
+  return NCharacter;
+}
+
+// Check whether bugprone-signed-char-misuse.DiagnoseSignedUnsignedCharComparisons option is set correctly.
+int SignedUnsignedCharEquality(signed char SCharacter) {
+  unsigned char USCharacter = 'a';
+  if (SCharacter == USCharacter) // no warning
+return 1;
+  return 0;
+}
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -320,6 +320,7 @@
`cert-oop11-cpp `_, `performance-move-constructor-init `_, "Yes"
`cert-oop54-cpp `_, `bugprone-unhandled-self-assignment `_,
`cert-pos44-c `_, `bugprone-bad-signal-to-kill-thread `_,
+   `cert-str34-c `_, `bugprone-signed-char-misuse `_,
`clang-analyzer-core.CallAndMessage `_, `Clang Static Analyzer `_,
`clang-analyzer-core.DivideZero `_, `Clang Static Analyzer `_,
`clang-analyzer-core.NonNullParamChecker `_, `Clang Static Analyzer `_,
Index: clang-tools-extra/docs/clang-tidy/checks/cert-str34-c.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/cert-str34-c.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - cert-str34-c
+.. meta::
+   :http-equiv=refresh: 5;URL=bugprone-signed-char-misuse.html
+
+cert-str34-c
+==
+
+The cert-str34-c check is an alias, please see
+`bugprone-signed-char-misuse `_
+for more information.
Index: clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst
+++ clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst
@@ -3,6 +3,9 @@
 bugprone-signed-char-misuse
 ===
 
+`cert-str34-c` redirects here as an alias for this check. For the CERT alias,
+the `DiagnoseSignedUnsignedCharComparisons` option is set to `0`.
+
 Finds those ``signed char`` -> integer conversions which might indicate a
 programming error. The basic problem with the ``signed char``, that it might
 store the non-ASCII characters as negative values. This behavior can cause a
@@ -108,3 +111,8 @@
   check. This is useful when a typedef introduces an integer alias like
   ``sal_Int8`` or ``int8_t``. In this case, human misinterpretation is not
   an issue.
+
+.. option:: DiagnoseSignedUnsignedCharComparisons
+
+  When non-zero, the check will warn on ``signed char``/``unsigned char`` comparison
+  otherwise this use case is ignored. By default, this option is set to ``1``.
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -168,6 +168,11 @@
   :doc:`bugprone-reserved-identifier
   ` was added.
 
+- New alias :doc:`cert-str34-c
+  ` to
+  :doc:`bugprone-signed-char-misuse
+  ` was added.
+
 Changes in existing checks
 ^^
 
Index: clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
===
--- clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
+++ clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
@@ -11,6 +11,7 @@
 #include "../ClangTidyModuleRegistry.h"
 #include "../bugprone/BadSignalToKillThreadCheck.h"
 #include "../bugprone/ReservedIdentifierCheck.h"
+#include "../bugprone/SignedCharMisus

[PATCH] D79334: [clang-tidy]: Add cert-str34-c alias for bugprone-signed-char-misuse.

2020-05-05 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas marked 3 inline comments as done.
ztamas added inline comments.



Comment at: clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.h:41
   const std::string CharTypdefsToIgnoreList;
+  const bool CertSTR34C;
 };

aaron.ballman wrote:
> I'd prefer a more descriptive name than this -- most people reading the code 
> won't be familiar with that coding standard. How about 
> `DiagnoseSignedUnsignedCharComparisons` or something along those lines?
OK, I updated the code to use this option name.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D79334/new/

https://reviews.llvm.org/D79334



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


[PATCH] D79334: [clang-tidy]: Add cert-str34-c alias for bugprone-signed-char-misuse.

2020-05-06 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas updated this revision to Diff 262316.
ztamas marked an inline comment as done.
ztamas added a comment.

Documentation fixes


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D79334/new/

https://reviews.llvm.org/D79334

Files:
  clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.h
  clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst
  clang-tools-extra/docs/clang-tidy/checks/cert-str34-c.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/checkers/cert-str34-c.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/cert-str34-c.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/cert-str34-c.cpp
@@ -0,0 +1,18 @@
+// RUN: %check_clang_tidy %s cert-str34-c %t
+
+// Check whether alias is actually working.
+int SimpleVarDeclaration() {
+  signed char CCharacter = -5;
+  int NCharacter = CCharacter;
+  // CHECK-MESSAGES: [[@LINE-1]]:20: warning: 'signed char' to 'int' conversion; consider casting to 'unsigned char' first. [cert-str34-c]
+
+  return NCharacter;
+}
+
+// Check whether bugprone-signed-char-misuse.DiagnoseSignedUnsignedCharComparisons option is set correctly.
+int SignedUnsignedCharEquality(signed char SCharacter) {
+  unsigned char USCharacter = 'a';
+  if (SCharacter == USCharacter) // no warning
+return 1;
+  return 0;
+}
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -320,6 +320,7 @@
`cert-oop11-cpp `_, `performance-move-constructor-init `_, "Yes"
`cert-oop54-cpp `_, `bugprone-unhandled-self-assignment `_,
`cert-pos44-c `_, `bugprone-bad-signal-to-kill-thread `_,
+   `cert-str34-c `_, `bugprone-signed-char-misuse `_,
`clang-analyzer-core.CallAndMessage `_, `Clang Static Analyzer `_,
`clang-analyzer-core.DivideZero `_, `Clang Static Analyzer `_,
`clang-analyzer-core.NonNullParamChecker `_, `Clang Static Analyzer `_,
Index: clang-tools-extra/docs/clang-tidy/checks/cert-str34-c.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/cert-str34-c.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - cert-str34-c
+.. meta::
+   :http-equiv=refresh: 5;URL=bugprone-signed-char-misuse.html
+
+cert-str34-c
+
+
+The cert-str34-c check is an alias, please see
+`bugprone-signed-char-misuse `_
+for more information.
Index: clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst
+++ clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst
@@ -3,6 +3,9 @@
 bugprone-signed-char-misuse
 ===
 
+`cert-str34-c` redirects here as an alias for this check. For the CERT alias,
+the `DiagnoseSignedUnsignedCharComparisons` option is set to `0`.
+
 Finds those ``signed char`` -> integer conversions which might indicate a
 programming error. The basic problem with the ``signed char``, that it might
 store the non-ASCII characters as negative values. This behavior can cause a
@@ -108,3 +111,8 @@
   check. This is useful when a typedef introduces an integer alias like
   ``sal_Int8`` or ``int8_t``. In this case, human misinterpretation is not
   an issue.
+
+.. option:: DiagnoseSignedUnsignedCharComparisons
+
+  When nonzero, the check will warn on ``signed char``/``unsigned char`` comparisons,
+  otherwise these comparisons are ignored. By default, this option is set to ``1``.
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -168,6 +168,11 @@
   :doc:`bugprone-reserved-identifier
   ` was added.
 
+- New alias :doc:`cert-str34-c
+  ` to
+  :doc:`bugprone-signed-char-misuse
+  ` was added.
+
 Changes in existing checks
 ^^
 
Index: clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
===
--- clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
+++ clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
@@ -11,6 +11,7 @@
 #include "../ClangTidyModuleRegistry.h"
 #include "../bugprone/BadSignalToKillThreadCheck.h"
 #include "../bugprone/ReservedIdentifierCheck.h"
+#include "../bugprone/Si

[PATCH] D79334: [clang-tidy]: Add cert-str34-c alias for bugprone-signed-char-misuse.

2020-05-06 Thread Tamás Zolnai via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGfedd52682ec7: [clang-tidy]: Add cert-str34-c alias for 
bugprone-signed-char-misuse. (authored by ztamas).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D79334/new/

https://reviews.llvm.org/D79334

Files:
  clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.h
  clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst
  clang-tools-extra/docs/clang-tidy/checks/cert-str34-c.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/checkers/cert-str34-c.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/cert-str34-c.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/cert-str34-c.cpp
@@ -0,0 +1,18 @@
+// RUN: %check_clang_tidy %s cert-str34-c %t
+
+// Check whether alias is actually working.
+int SimpleVarDeclaration() {
+  signed char CCharacter = -5;
+  int NCharacter = CCharacter;
+  // CHECK-MESSAGES: [[@LINE-1]]:20: warning: 'signed char' to 'int' conversion; consider casting to 'unsigned char' first. [cert-str34-c]
+
+  return NCharacter;
+}
+
+// Check whether bugprone-signed-char-misuse.DiagnoseSignedUnsignedCharComparisons option is set correctly.
+int SignedUnsignedCharEquality(signed char SCharacter) {
+  unsigned char USCharacter = 'a';
+  if (SCharacter == USCharacter) // no warning
+return 1;
+  return 0;
+}
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -320,6 +320,7 @@
`cert-oop11-cpp `_, `performance-move-constructor-init `_, "Yes"
`cert-oop54-cpp `_, `bugprone-unhandled-self-assignment `_,
`cert-pos44-c `_, `bugprone-bad-signal-to-kill-thread `_,
+   `cert-str34-c `_, `bugprone-signed-char-misuse `_,
`clang-analyzer-core.CallAndMessage `_, `Clang Static Analyzer `_,
`clang-analyzer-core.DivideZero `_, `Clang Static Analyzer `_,
`clang-analyzer-core.NonNullParamChecker `_, `Clang Static Analyzer `_,
Index: clang-tools-extra/docs/clang-tidy/checks/cert-str34-c.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/cert-str34-c.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - cert-str34-c
+.. meta::
+   :http-equiv=refresh: 5;URL=bugprone-signed-char-misuse.html
+
+cert-str34-c
+
+
+The cert-str34-c check is an alias, please see
+`bugprone-signed-char-misuse `_
+for more information.
Index: clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst
+++ clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst
@@ -3,6 +3,9 @@
 bugprone-signed-char-misuse
 ===
 
+`cert-str34-c` redirects here as an alias for this check. For the CERT alias,
+the `DiagnoseSignedUnsignedCharComparisons` option is set to `0`.
+
 Finds those ``signed char`` -> integer conversions which might indicate a
 programming error. The basic problem with the ``signed char``, that it might
 store the non-ASCII characters as negative values. This behavior can cause a
@@ -108,3 +111,8 @@
   check. This is useful when a typedef introduces an integer alias like
   ``sal_Int8`` or ``int8_t``. In this case, human misinterpretation is not
   an issue.
+
+.. option:: DiagnoseSignedUnsignedCharComparisons
+
+  When nonzero, the check will warn on ``signed char``/``unsigned char`` comparisons,
+  otherwise these comparisons are ignored. By default, this option is set to ``1``.
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -168,6 +168,11 @@
   :doc:`bugprone-reserved-identifier
   ` was added.
 
+- New alias :doc:`cert-str34-c
+  ` to
+  :doc:`bugprone-signed-char-misuse
+  ` was added.
+
 Changes in existing checks
 ^^
 
Index: clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
===
--- clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
+++ clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
@@ -11,6 +11,7 @@
 #include "../ClangTidyModuleRegistry.h"
 #include "../bugprone/BadSignalToKillThreadCheck.h"
 #inclu

[PATCH] D71174: [clang-tidy] new check: bugprone-signed-char-misuse

2019-12-27 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas marked an inline comment as done.
ztamas added inline comments.
Herald added a subscriber: whisperity.



Comment at: 
clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp:43-44
+
+  const auto SignedCharType = expr(hasType(qualType(
+  allOf(isAnyCharacter(), isSignedInteger(), unless(IntTypedef);
+

aaron.ballman wrote:
> Does this properly handle architectures where `char` is signed rather than 
> unsigned? Or does this only handle the case where the user wrote `signed 
> char`?
It catches plain char too. I tested on 64 bit linux where char is signed by 
default.
The funsigned-char and fsigned-char options can be used to override the default 
behavior. Added some new test cases and also extended the documentation to make 
this clear.



Comment at: 
clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp:43-44
+
+  const auto SignedCharType = expr(hasType(qualType(
+  allOf(isAnyCharacter(), isSignedInteger(), unless(IntTypedef);
+

ztamas wrote:
> aaron.ballman wrote:
> > Does this properly handle architectures where `char` is signed rather than 
> > unsigned? Or does this only handle the case where the user wrote `signed 
> > char`?
> It catches plain char too. I tested on 64 bit linux where char is signed by 
> default.
> The funsigned-char and fsigned-char options can be used to override the 
> default behavior. Added some new test cases and also extended the 
> documentation to make this clear.
Most of the catches I found in LibreOffice / LLVM code had `char` type.
I found isSignedCharDefault() method in LLVM code where clang handles platform 
differences, as I see, so I assume clang-tidy works based on that. With the 
compilation options, the char signedness can be controlled anyway, so I think 
this will be OK.
I could test only with a 64 bit linux. There plain char is caught by default, 
as I mentioned, and I could change this behavior with the -funsigned-char 
option.



Comment at: 
clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst:25
+See also:
+`STR34-C. Cast characters to unsigned char before converting to larger integer 
sizes
+`_

aaron.ballman wrote:
> Should this check also be registered in the CERT module?
This check does not cover the whole CERT description. I guess a cert check 
should catch all bugous code related to the CERT issue, right?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D71174/new/

https://reviews.llvm.org/D71174



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


[PATCH] D71174: [clang-tidy] new check: bugprone-signed-char-misuse

2019-12-27 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas added a comment.

I added the above comments two weeks ago, I just forget to push the submit 
button.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D71174/new/

https://reviews.llvm.org/D71174



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


[PATCH] D71174: [clang-tidy] new check: bugprone-signed-char-misuse

2019-12-28 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas marked 2 inline comments as done.
ztamas added inline comments.



Comment at: clang-tools-extra/docs/clang-tidy/checks/list.rst:66
bugprone-posix-return
+   bugprone-signed-char-misuse
bugprone-sizeof-container

sylvestre.ledru wrote:
> list.rst has changed, you should try to rebase your patch!
> 
I rebased the patch. I added medium severity for this check because the CERT 
rule has the same severity.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D71174/new/

https://reviews.llvm.org/D71174



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


[PATCH] D71174: [clang-tidy] new check: bugprone-signed-char-misuse

2019-12-28 Thread Tamás Zolnai via Phabricator via cfe-commits
ztamas updated this revision to Diff 235470.
ztamas added a comment.

Rebase patch.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D71174/new/

https://reviews.llvm.org/D71174

Files:
  clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
  clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/test/clang-tidy/checkers/bugprone-signed-char-misuse-fsigned-char.cpp
  
clang-tools-extra/test/clang-tidy/checkers/bugprone-signed-char-misuse-funsigned-char.cpp
  
clang-tools-extra/test/clang-tidy/checkers/bugprone-signed-char-misuse-with-option.cpp
  clang-tools-extra/test/clang-tidy/checkers/bugprone-signed-char-misuse.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/bugprone-signed-char-misuse.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/bugprone-signed-char-misuse.cpp
@@ -0,0 +1,123 @@
+// RUN: %check_clang_tidy %s bugprone-signed-char-misuse %t
+
+///
+/// Test cases correctly caught by the check.
+
+int SimpleVarDeclaration() {
+  signed char CCharacter = -5;
+  int NCharacter = CCharacter;
+  // CHECK-MESSAGES: [[@LINE-1]]:20: warning: singed char -> integer ('int') conversion; consider to cast to unsigned char first. [bugprone-signed-char-misuse]
+
+  return NCharacter;
+}
+
+int SimpleAssignment() {
+  signed char CCharacter = -5;
+  int NCharacter;
+  NCharacter = CCharacter;
+  // CHECK-MESSAGES: [[@LINE-1]]:16: warning: singed char -> integer ('int') conversion; consider to cast to unsigned char first. [bugprone-signed-char-misuse]
+
+  return NCharacter;
+}
+
+int CStyleCast() {
+  signed char CCharacter = -5;
+  int NCharacter;
+  NCharacter = (int)CCharacter;
+  // CHECK-MESSAGES: [[@LINE-1]]:21: warning: singed char -> integer ('int') conversion; consider to cast to unsigned char first. [bugprone-signed-char-misuse]
+
+  return NCharacter;
+}
+
+int StaticCast() {
+  signed char CCharacter = -5;
+  int NCharacter;
+  NCharacter = static_cast(CCharacter);
+  // CHECK-MESSAGES: [[@LINE-1]]:33: warning: singed char -> integer ('int') conversion; consider to cast to unsigned char first. [bugprone-signed-char-misuse]
+
+  return NCharacter;
+}
+
+int FunctionalCast() {
+  signed char CCharacter = -5;
+  int NCharacter;
+  NCharacter = int(CCharacter);
+  // CHECK-MESSAGES: [[@LINE-1]]:20: warning: singed char -> integer ('int') conversion; consider to cast to unsigned char first. [bugprone-signed-char-misuse]
+
+  return NCharacter;
+}
+
+int NegativeConstValue() {
+  const signed char CCharacter = -5;
+  int NCharacter = CCharacter;
+  // CHECK-MESSAGES: [[@LINE-1]]:20: warning: singed char -> integer ('int') conversion; consider to cast to unsigned char first. [bugprone-signed-char-misuse]
+
+  return NCharacter;
+}
+
+int CharPointer(signed char *CCharacter) {
+  int NCharacter = *CCharacter;
+  // CHECK-MESSAGES: [[@LINE-1]]:20: warning: singed char -> integer ('int') conversion; consider to cast to unsigned char first. [bugprone-signed-char-misuse]
+
+  return NCharacter;
+}
+
+///
+/// Test cases correctly ignored by the check.
+
+int UnsignedCharCast() {
+  unsigned char CCharacter = 'a';
+  int NCharacter = CCharacter;
+
+  return NCharacter;
+}
+
+int PositiveConstValue() {
+  const signed char CCharacter = 5;
+  int NCharacter = CCharacter;
+
+  return NCharacter;
+}
+
+// singed char -> integer cast is not the direct child of declaration expression.
+int DescendantCast() {
+  signed char CCharacter = 'a';
+  int NCharacter = 10 + CCharacter;
+
+  return NCharacter;
+}
+
+// singed char -> integer cast is not the direct child of assignment expression.
+int DescendantCastAssignment() {
+  signed char CCharacter = 'a';
+  int NCharacter;
+  NCharacter = 10 + CCharacter;
+
+  return NCharacter;
+}
+
+// bool is an integer type in clang; make sure to ignore it.
+bool BoolVarDeclaration() {
+  signed char CCharacter = 'a';
+  bool BCharacter = CCharacter == 'b';
+
+  return BCharacter;
+}
+
+// bool is an integer type in clang; make sure to ignore it.
+bool BoolAssignment() {
+  signed char CCharacter = 'a';
+  bool BCharacter;
+  BCharacter = CCharacter == 'b';
+
+  return BCharacter;
+}
+
+// char is an integer type in clang; make sure to ignore it.
+unsigned char CharToCharCast() {
+  signed char SCCharacter = 'a';
+  unsigned char USCharacter;
+  USCharacter = SCCharacter;
+
+  return USCharacter;
+}
Index: clang-tools-extra/test/clang-tidy/checkers/bugprone-signed-char-misuse-with-option.cpp
=

  1   2   >