[clang-tools-extra] r318906 - [clang-tidy] Misplaced Operator in Strlen in Alloc

2017-11-23 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Thu Nov 23 04:26:28 2017
New Revision: 318906

URL: http://llvm.org/viewvc/llvm-project?rev=318906=rev
Log:
[clang-tidy] Misplaced Operator in Strlen in Alloc

A possible error is to write `malloc(strlen(s+1))` instead of
`malloc(strlen(s)+1)`. Unfortunately the former is also valid syntactically,
but allocates less memory by two bytes (if s` is at least one character long,
undefined behavior otherwise) which may result in overflow cases. This check
detects such cases and also suggests the fix for them.


Modified:
clang-tools-extra/trunk/clang-tidy/bugprone/BugproneTidyModule.cpp
clang-tools-extra/trunk/clang-tidy/bugprone/CMakeLists.txt
clang-tools-extra/trunk/docs/ReleaseNotes.rst
clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst

Modified: clang-tools-extra/trunk/clang-tidy/bugprone/BugproneTidyModule.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/bugprone/BugproneTidyModule.cpp?rev=318906=318905=318906=diff
==
--- clang-tools-extra/trunk/clang-tidy/bugprone/BugproneTidyModule.cpp 
(original)
+++ clang-tools-extra/trunk/clang-tidy/bugprone/BugproneTidyModule.cpp Thu Nov 
23 04:26:28 2017
@@ -12,6 +12,7 @@
 #include "../ClangTidyModuleRegistry.h"
 #include "CopyConstructorInitCheck.h"
 #include "IntegerDivisionCheck.h"
+#include "MisplacedOperatorInStrlenInAllocCheck.h"
 #include "SuspiciousMemsetUsageCheck.h"
 #include "UndefinedMemoryManipulationCheck.h"
 
@@ -26,6 +27,8 @@ public:
 "bugprone-copy-constructor-init");
 CheckFactories.registerCheck(
 "bugprone-integer-division");
+CheckFactories.registerCheck(
+"bugprone-misplaced-operator-in-strlen-in-alloc");
 CheckFactories.registerCheck(
 "bugprone-suspicious-memset-usage");
 CheckFactories.registerCheck(

Modified: clang-tools-extra/trunk/clang-tidy/bugprone/CMakeLists.txt
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/bugprone/CMakeLists.txt?rev=318906=318905=318906=diff
==
--- clang-tools-extra/trunk/clang-tidy/bugprone/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clang-tidy/bugprone/CMakeLists.txt Thu Nov 23 
04:26:28 2017
@@ -4,6 +4,7 @@ add_clang_library(clangTidyBugproneModul
   BugproneTidyModule.cpp
   CopyConstructorInitCheck.cpp
   IntegerDivisionCheck.cpp
+  MisplacedOperatorInStrlenInAllocCheck.cpp
   SuspiciousMemsetUsageCheck.cpp
   UndefinedMemoryManipulationCheck.cpp
 

Modified: clang-tools-extra/trunk/docs/ReleaseNotes.rst
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/ReleaseNotes.rst?rev=318906=318905=318906=diff
==
--- clang-tools-extra/trunk/docs/ReleaseNotes.rst (original)
+++ clang-tools-extra/trunk/docs/ReleaseNotes.rst Thu Nov 23 04:26:28 2017
@@ -85,6 +85,15 @@ Improvements to clang-tidy
   not intended to be subclassed. Includes a list of classes from Foundation
   and UIKit which are documented as not supporting subclassing.
 
+- New `bugprone-misplaced-operator-in-strlen-in-alloc
+  
`_
 check
+
+  Finds cases where ``1`` is added to the string in the argument to
+  ``strlen()``, ``strnlen()``, ``strnlen_s()``, ``wcslen()``, ``wcsnlen()``, 
and
+  ``wcsnlen_s()`` instead of the result and the value is used as an argument to
+  a memory allocation function (``malloc()``, ``calloc()``, ``realloc()``,
+  ``alloca()``).
+
 - Renamed checks to use correct term "implicit conversion" instead of "implicit
   cast" and modified messages and option names accordingly:
 

Modified: clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst?rev=318906=318905=318906=diff
==
--- clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst (original)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst Thu Nov 23 04:26:28 
2017
@@ -19,6 +19,7 @@ Clang-Tidy Checks
boost-use-to-string
bugprone-copy-constructor-init
bugprone-integer-division
+   bugprone-misplaced-operator-in-strlen-in-alloc
bugprone-suspicious-memset-usage
bugprone-undefined-memory-manipulation
cert-dcl03-c (redirects to misc-static-assert) 


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


r318909 - [ASTMatchers] Matchers for new[] operators

2017-11-23 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Thu Nov 23 04:43:20 2017
New Revision: 318909

URL: http://llvm.org/viewvc/llvm-project?rev=318909=rev
Log:
[ASTMatchers] Matchers for new[] operators

Two new matchers for `CXXNewExpr` are added which may be useful e.g. in
`clang-tidy` checkers. One of them is `isArray` which matches `new[]` but not
plain `new`. The other one, `hasArraySize` matches `new[]` for a given size.


Modified:
cfe/trunk/docs/LibASTMatchersReference.html
cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp
cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp

Modified: cfe/trunk/docs/LibASTMatchersReference.html
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LibASTMatchersReference.html?rev=318909=318908=318909=diff
==
--- cfe/trunk/docs/LibASTMatchersReference.html (original)
+++ cfe/trunk/docs/LibASTMatchersReference.html Thu Nov 23 04:43:20 2017
@@ -2276,6 +2276,16 @@ Given
 
 
 
+Matcherhttp://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html;>CXXNewExprisArray
+Matches array new 
expressions.
+
+Given:
+  MyClass *p1 = new MyClass[10];
+cxxNewExpr(isArray())
+  matches the expression 'new MyClass[10]'.
+
+
+
 Matcherhttp://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html;>CXXOperatorCallExprhasOverloadedOperatorNameStringRef
 Name
 Matches 
overloaded operator names.
 
@@ -4476,6 +4486,16 @@ Example matches A() in the last line
 
 
 
+Matcherhttp://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html;>CXXNewExprhasArraySizeMatcherhttp://clang.llvm.org/doxygen/classclang_1_1Expr.html;>Expr 
InnerMatcher
+Matches array new 
expressions with a given array size.
+
+Given:
+  MyClass *p1 = new MyClass[10];
+cxxNewExpr(hasArraySize(intgerLiteral(equals(10
+  matches the expression 'new MyClass[10]'.
+
+
+
 Matcherhttp://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html;>CXXNewExprhasDeclarationMatcherhttp://clang.llvm.org/doxygen/classclang_1_1Decl.html;>Decl  
InnerMatcher
 Matches a node if 
the declaration associated with that node
 matches the given matcher.

Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=318909=318908=318909=diff
==
--- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Thu Nov 23 04:43:20 2017
@@ -5828,6 +5828,31 @@ AST_MATCHER(ParmVarDecl, hasDefaultArgum
   return Node.hasDefaultArg(); 
 }
 
+/// \brief Matches array new expressions.
+///
+/// Given:
+/// \code
+///   MyClass *p1 = new MyClass[10];
+/// \endcode
+/// cxxNewExpr(isArray())
+///   matches the expression 'new MyClass[10]'.
+AST_MATCHER(CXXNewExpr, isArray) {
+  return Node.isArray();
+}
+
+/// \brief Matches array new expressions with a given array size.
+///
+/// Given:
+/// \code
+///   MyClass *p1 = new MyClass[10];
+/// \endcode
+/// cxxNewExpr(hasArraySize(intgerLiteral(equals(10
+///   matches the expression 'new MyClass[10]'.
+AST_MATCHER_P(CXXNewExpr, hasArraySize, internal::Matcher, InnerMatcher) 
{
+  return Node.isArray() &&
+InnerMatcher.matches(*Node.getArraySize(), Finder, Builder);
+}
+
 } // namespace ast_matchers
 } // namespace clang
 

Modified: cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp?rev=318909=318908=318909=diff
==
--- cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp (original)
+++ cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp Thu Nov 23 04:43:20 2017
@@ -234,6 +234,7 @@ RegistryMaps::RegistryMaps() {
   REGISTER_MATCHER(hasAnyUsingShadowDecl);
   REGISTER_MATCHER(hasArgument);
   REGISTER_MATCHER(hasArgumentOfType);
+  REGISTER_MATCHER(hasArraySize);
   REGISTER_MATCHER(hasAttr);
   REGISTER_MATCHER(hasAutomaticStorageDuration);
   REGISTER_MATCHER(hasBase);
@@ -317,6 +318,7 @@ RegistryMaps::RegistryMaps() {
   REGISTER_MATCHER(isAnonymous);
   REGISTER_MATCHER(isAnyCharacter);
   REGISTER_MATCHER(isAnyPointer);
+  REGISTER_MATCHER(isArray);
   REGISTER_MATCHER(isArrow);
   REGISTER_MATCHER(isBaseInitializer);
   REGISTER_MATCHER(isBitField);

Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp?rev=318909=318908=318909=diff
==
--- cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp (original)
+++ cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp Thu Nov 23 
04:43:20 2017
@@ -1998,5 +1998,15 @@ TEST(HasDefaultArgument, Basic) {
   

[clang-tools-extra] r318912 - [clang-tidy] Add support for operator new[] in check bugprone-misplaced-operator-in-strlen-in-alloc

2017-11-23 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Thu Nov 23 04:56:23 2017
New Revision: 318912

URL: http://llvm.org/viewvc/llvm-project?rev=318912=rev
Log:
[clang-tidy] Add support for operator new[] in check 
bugprone-misplaced-operator-in-strlen-in-alloc

The check now recognizes error cases like `new char[strlen(s + 1)]` and suggests
a fix in the format `new char[strlen(s) + 1]`.


Modified:

clang-tools-extra/trunk/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp
clang-tools-extra/trunk/docs/ReleaseNotes.rst

clang-tools-extra/trunk/docs/clang-tidy/checks/bugprone-misplaced-operator-in-strlen-in-alloc.rst

clang-tools-extra/trunk/test/clang-tidy/bugprone-misplaced-operator-in-strlen-in-alloc.cpp

Modified: 
clang-tools-extra/trunk/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp?rev=318912=318911=318912=diff
==
--- 
clang-tools-extra/trunk/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp
 (original)
+++ 
clang-tools-extra/trunk/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp
 Thu Nov 23 04:56:23 2017
@@ -53,21 +53,28 @@ void MisplacedOperatorInStrlenInAllocChe
   callExpr(callee(Alloc0Func), hasArgument(0, BadArg)).bind("Alloc"), 
this);
   Finder->addMatcher(
   callExpr(callee(Alloc1Func), hasArgument(1, BadArg)).bind("Alloc"), 
this);
+  Finder->addMatcher(
+  cxxNewExpr(isArray(), hasArraySize(BadArg)).bind("Alloc"), this);
 }
 
 void MisplacedOperatorInStrlenInAllocCheck::check(
 const MatchFinder::MatchResult ) {
-  const auto *Alloc = Result.Nodes.getNodeAs("Alloc");
+  const Expr *Alloc = Result.Nodes.getNodeAs("Alloc");
+  if (!Alloc)
+Alloc = Result.Nodes.getNodeAs("Alloc");
+  assert(Alloc && "Matched node bound by 'Alloc' shoud be either 'CallExpr'"
+ " or 'CXXNewExpr'");
+
   const auto *StrLen = Result.Nodes.getNodeAs("StrLen");
   const auto *BinOp = Result.Nodes.getNodeAs("BinOp");
 
   const StringRef StrLenText = Lexer::getSourceText(
   CharSourceRange::getTokenRange(StrLen->getSourceRange()),
   *Result.SourceManager, getLangOpts());
-  const StringRef StrLenBegin = StrLenText.substr(0, StrLenText.find('(') + 1);
   const StringRef Arg0Text = Lexer::getSourceText(
   CharSourceRange::getTokenRange(StrLen->getArg(0)->getSourceRange()),
   *Result.SourceManager, getLangOpts());
+  const StringRef StrLenBegin = StrLenText.substr(0, 
StrLenText.find(Arg0Text));
   const StringRef StrLenEnd = StrLenText.substr(
   StrLenText.find(Arg0Text) + Arg0Text.size(), StrLenText.size());
 

Modified: clang-tools-extra/trunk/docs/ReleaseNotes.rst
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/ReleaseNotes.rst?rev=318912=318911=318912=diff
==
--- clang-tools-extra/trunk/docs/ReleaseNotes.rst (original)
+++ clang-tools-extra/trunk/docs/ReleaseNotes.rst Thu Nov 23 04:56:23 2017
@@ -92,7 +92,7 @@ Improvements to clang-tidy
   ``strlen()``, ``strnlen()``, ``strnlen_s()``, ``wcslen()``, ``wcsnlen()``, 
and
   ``wcsnlen_s()`` instead of the result and the value is used as an argument to
   a memory allocation function (``malloc()``, ``calloc()``, ``realloc()``,
-  ``alloca()``).
+  ``alloca()``) or the ``new[]`` operator in `C++`.
 
 - Renamed checks to use correct term "implicit conversion" instead of "implicit
   cast" and modified messages and option names accordingly:

Modified: 
clang-tools-extra/trunk/docs/clang-tidy/checks/bugprone-misplaced-operator-in-strlen-in-alloc.rst
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/bugprone-misplaced-operator-in-strlen-in-alloc.rst?rev=318912=318911=318912=diff
==
--- 
clang-tools-extra/trunk/docs/clang-tidy/checks/bugprone-misplaced-operator-in-strlen-in-alloc.rst
 (original)
+++ 
clang-tools-extra/trunk/docs/clang-tidy/checks/bugprone-misplaced-operator-in-strlen-in-alloc.rst
 Thu Nov 23 04:56:23 2017
@@ -6,12 +6,12 @@ bugprone-misplaced-operator-in-strlen-in
 Finds cases where ``1`` is added to the string in the argument to ``strlen()``,
 ``strnlen()``, ``strnlen_s()``, ``wcslen()``, ``wcsnlen()``, and 
``wcsnlen_s()``
 instead of the result and the value is used as an argument to a memory
-allocation function (``malloc()``, ``calloc()``, ``realloc()``, ``alloca()``).
-Cases where ``1`` is added both to the parameter and the result of the
-``strlen()``-like function are ignored, as are cases where the whole addition 
is
-surrounded by extra parentheses.
+allocation function (``malloc()``, ``calloc()``, ``realloc()``, ``alloca()``) 
or
+the ``new[]`` operator in `C++`. Cases where ``1`` is added both to the
+parameter and the result of the 

[clang-tools-extra] r318907 - [clang-tidy] Misplaced Operator in Strlen in Alloc

2017-11-23 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Thu Nov 23 04:33:12 2017
New Revision: 318907

URL: http://llvm.org/viewvc/llvm-project?rev=318907=rev
Log:
[clang-tidy] Misplaced Operator in Strlen in Alloc

A possible error is to write `malloc(strlen(s+1))` instead of
`malloc(strlen(s)+1)`. Unfortunately the former is also valid syntactically,
but allocates less memory by two bytes (if `s` is at least one character long,
undefined behavior otherwise) which may result in overflow cases. This check
detects such cases and also suggests the fix for them.

Fix for r318906, forgot to add new files.


Added:

clang-tools-extra/trunk/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp

clang-tools-extra/trunk/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.h

clang-tools-extra/trunk/docs/clang-tidy/checks/bugprone-misplaced-operator-in-strlen-in-alloc.rst

clang-tools-extra/trunk/test/clang-tidy/bugprone-misplaced-operator-in-strlen-in-alloc.c

clang-tools-extra/trunk/test/clang-tidy/bugprone-misplaced-operator-in-strlen-in-alloc.cpp

Added: 
clang-tools-extra/trunk/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp?rev=318907=auto
==
--- 
clang-tools-extra/trunk/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp
 (added)
+++ 
clang-tools-extra/trunk/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp
 Thu Nov 23 04:33:12 2017
@@ -0,0 +1,92 @@
+//===--- MisplacedOperatorInStrlenInAllocCheck.cpp - 
clang-tidy===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#include "MisplacedOperatorInStrlenInAllocCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+void MisplacedOperatorInStrlenInAllocCheck::registerMatchers(
+MatchFinder *Finder) {
+  const auto StrLenFunc = functionDecl(anyOf(
+  hasName("::strlen"), hasName("::std::strlen"), hasName("::strnlen"),
+  hasName("::std::strnlen"), hasName("::strnlen_s"),
+  hasName("::std::strnlen_s"), hasName("::wcslen"),
+  hasName("::std::wcslen"), hasName("::wcsnlen"), 
hasName("::std::wcsnlen"),
+  hasName("::wcsnlen_s"), hasName("std::wcsnlen_s")));
+
+  const auto BadUse =
+  callExpr(callee(StrLenFunc),
+   hasAnyArgument(ignoringImpCasts(
+   binaryOperator(allOf(hasOperatorName("+"),
+hasRHS(ignoringParenImpCasts(
+integerLiteral(equals(1))
+   .bind("BinOp"
+  .bind("StrLen");
+
+  const auto BadArg = anyOf(
+  allOf(hasDescendant(BadUse),
+unless(binaryOperator(allOf(
+hasOperatorName("+"), hasLHS(BadUse),
+hasRHS(ignoringParenImpCasts(integerLiteral(equals(1,
+  BadUse);
+
+  const auto Alloc0Func =
+  functionDecl(anyOf(hasName("::malloc"), hasName("std::malloc"),
+ hasName("::alloca"), hasName("std::alloca")));
+  const auto Alloc1Func =
+  functionDecl(anyOf(hasName("::calloc"), hasName("std::calloc"),
+ hasName("::realloc"), hasName("std::realloc")));
+
+  Finder->addMatcher(
+  callExpr(callee(Alloc0Func), hasArgument(0, BadArg)).bind("Alloc"), 
this);
+  Finder->addMatcher(
+  callExpr(callee(Alloc1Func), hasArgument(1, BadArg)).bind("Alloc"), 
this);
+}
+
+void MisplacedOperatorInStrlenInAllocCheck::check(
+const MatchFinder::MatchResult ) {
+  const auto *Alloc = Result.Nodes.getNodeAs("Alloc");
+  const auto *StrLen = Result.Nodes.getNodeAs("StrLen");
+  const auto *BinOp = Result.Nodes.getNodeAs("BinOp");
+
+  const StringRef StrLenText = Lexer::getSourceText(
+  CharSourceRange::getTokenRange(StrLen->getSourceRange()),
+  *Result.SourceManager, getLangOpts());
+  const StringRef StrLenBegin = StrLenText.substr(0, StrLenText.find('(') + 1);
+  const StringRef Arg0Text = Lexer::getSourceText(
+  CharSourceRange::getTokenRange(StrLen->getArg(0)->getSourceRange()),
+  *Result.SourceManager, getLangOpts());
+  const StringRef StrLenEnd = StrLenText.substr(
+  StrLenText.find(Arg0Text) + Arg0Text.size(), StrLenText.size());
+
+  const StringRef LHSText = Lexer::getSourceText(
+  CharSourceRange::getTokenRange(BinOp->getLHS()->getSourceRange()),
+  *Result.SourceManager, getLangOpts());
+  const StringRef RHSText = Lexer::getSourceText(
+  CharSourceRange::getTokenRange(BinOp->getRHS()->getSourceRange()),

[clang-tools-extra] r318913 - [clang-tidy] Detect bugs in bugprone-misplaced-operator-in-strlen-in-alloc even in the case the allocation function is called using a constant function pointer

2017-11-23 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Thu Nov 23 05:12:25 2017
New Revision: 318913

URL: http://llvm.org/viewvc/llvm-project?rev=318913=rev
Log:
[clang-tidy] Detect bugs in bugprone-misplaced-operator-in-strlen-in-alloc even 
in the case the allocation function is called using a constant function pointer

Detect bugs even if a function of the malloc() family is called using a 
constant pointer.


Modified:

clang-tools-extra/trunk/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp

clang-tools-extra/trunk/docs/clang-tidy/checks/bugprone-misplaced-operator-in-strlen-in-alloc.rst

clang-tools-extra/trunk/test/clang-tidy/bugprone-misplaced-operator-in-strlen-in-alloc.c

Modified: 
clang-tools-extra/trunk/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp?rev=318913=318912=318913=diff
==
--- 
clang-tools-extra/trunk/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp
 (original)
+++ 
clang-tools-extra/trunk/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp
 Thu Nov 23 05:12:25 2017
@@ -49,10 +49,23 @@ void MisplacedOperatorInStrlenInAllocChe
   functionDecl(anyOf(hasName("::calloc"), hasName("std::calloc"),
  hasName("::realloc"), hasName("std::realloc")));
 
-  Finder->addMatcher(
-  callExpr(callee(Alloc0Func), hasArgument(0, BadArg)).bind("Alloc"), 
this);
-  Finder->addMatcher(
-  callExpr(callee(Alloc1Func), hasArgument(1, BadArg)).bind("Alloc"), 
this);
+  const auto Alloc0FuncPtr =
+  varDecl(hasType(isConstQualified()),
+  hasInitializer(ignoringParenImpCasts(
+  declRefExpr(hasDeclaration(Alloc0Func);
+  const auto Alloc1FuncPtr =
+  varDecl(hasType(isConstQualified()),
+  hasInitializer(ignoringParenImpCasts(
+  declRefExpr(hasDeclaration(Alloc1Func);
+
+  Finder->addMatcher(callExpr(callee(decl(anyOf(Alloc0Func, Alloc0FuncPtr))),
+  hasArgument(0, BadArg))
+ .bind("Alloc"),
+ this);
+  Finder->addMatcher(callExpr(callee(decl(anyOf(Alloc1Func, Alloc1FuncPtr))),
+  hasArgument(1, BadArg))
+ .bind("Alloc"),
+ this);
   Finder->addMatcher(
   cxxNewExpr(isArray(), hasArraySize(BadArg)).bind("Alloc"), this);
 }

Modified: 
clang-tools-extra/trunk/docs/clang-tidy/checks/bugprone-misplaced-operator-in-strlen-in-alloc.rst
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/bugprone-misplaced-operator-in-strlen-in-alloc.rst?rev=318913=318912=318913=diff
==
--- 
clang-tools-extra/trunk/docs/clang-tidy/checks/bugprone-misplaced-operator-in-strlen-in-alloc.rst
 (original)
+++ 
clang-tools-extra/trunk/docs/clang-tidy/checks/bugprone-misplaced-operator-in-strlen-in-alloc.rst
 Thu Nov 23 05:12:25 2017
@@ -7,9 +7,11 @@ Finds cases where ``1`` is added to the
 ``strnlen()``, ``strnlen_s()``, ``wcslen()``, ``wcsnlen()``, and 
``wcsnlen_s()``
 instead of the result and the value is used as an argument to a memory
 allocation function (``malloc()``, ``calloc()``, ``realloc()``, ``alloca()``) 
or
-the ``new[]`` operator in `C++`. Cases where ``1`` is added both to the
-parameter and the result of the ``strlen()``-like function are ignored, as are
-cases where the whole addition is surrounded by extra parentheses.
+the ``new[]`` operator in `C++`. The check detects error cases even if one of
+these functions (except the ``new[]`` operator) is called by a constant 
function
+pointer.  Cases where ``1`` is added both to the parameter and the result of 
the
+``strlen()``-like function are ignored, as are cases where the whole addition 
is
+surrounded by extra parentheses.
 
 `C` example code:
 

Modified: 
clang-tools-extra/trunk/test/clang-tidy/bugprone-misplaced-operator-in-strlen-in-alloc.c
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/bugprone-misplaced-operator-in-strlen-in-alloc.c?rev=318913=318912=318913=diff
==
--- 
clang-tools-extra/trunk/test/clang-tidy/bugprone-misplaced-operator-in-strlen-in-alloc.c
 (original)
+++ 
clang-tools-extra/trunk/test/clang-tidy/bugprone-misplaced-operator-in-strlen-in-alloc.c
 Thu Nov 23 05:12:25 2017
@@ -75,3 +75,11 @@ void intentional3(char *name) {
   // CHECK-MESSAGES-NOT: :[[@LINE-1]]:28: warning: addition operator is 
applied to the argument of strlen
   // If expression is in extra parentheses, consider it as intentional
 }
+
+void (*(*const alloc_ptr)(size_t)) = malloc;
+
+void bad_indirect_alloc(char *name) {
+  char *new_name = (char 

r334804 - [ASTImporter] Corrected diagnostic client handling in tests.

2018-06-15 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Thu Jun 14 23:45:39 2018
New Revision: 334804

URL: http://llvm.org/viewvc/llvm-project?rev=334804=rev
Log:
[ASTImporter] Corrected diagnostic client handling in tests.

ASTImporter tests may produce source file related warnings, the diagnostic
client should be in correct state to handle it. Added 'beginSourceFile' to set
the client state.

Patch by: Balázs Kéri

Differential Revision: https://reviews.llvm.org/D47445


Modified:
cfe/trunk/include/clang/Frontend/ASTUnit.h
cfe/trunk/lib/Frontend/ASTUnit.cpp
cfe/trunk/unittests/AST/ASTImporterTest.cpp

Modified: cfe/trunk/include/clang/Frontend/ASTUnit.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/ASTUnit.h?rev=334804=334803=334804=diff
==
--- cfe/trunk/include/clang/Frontend/ASTUnit.h (original)
+++ cfe/trunk/include/clang/Frontend/ASTUnit.h Thu Jun 14 23:45:39 2018
@@ -438,6 +438,15 @@ public:
   void setASTContext(ASTContext *ctx) { Ctx = ctx; }
   void setPreprocessor(std::shared_ptr pp);
 
+  /// Enable source-range based diagnostic messages.
+  ///
+  /// If diagnostic messages with source-range information are to be expected
+  /// and AST comes not from file (e.g. after LoadFromCompilerInvocation) this
+  /// function has to be called.
+  /// The function is to be called only once and the AST should be associated
+  /// with the same source file afterwards.
+  void enableSourceFileDiagnostics();
+
   bool hasSema() const { return (bool)TheSema; }
 
   Sema () const { 

Modified: cfe/trunk/lib/Frontend/ASTUnit.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/ASTUnit.cpp?rev=334804=334803=334804=diff
==
--- cfe/trunk/lib/Frontend/ASTUnit.cpp (original)
+++ cfe/trunk/lib/Frontend/ASTUnit.cpp Thu Jun 14 23:45:39 2018
@@ -275,6 +275,12 @@ void ASTUnit::setPreprocessor(std::share
   this->PP = std::move(PP);
 }
 
+void ASTUnit::enableSourceFileDiagnostics() {
+  assert(getDiagnostics().getClient() && Ctx &&
+  "Bad context for source file");
+  getDiagnostics().getClient()->BeginSourceFile(Ctx->getLangOpts(), PP.get());
+}
+
 /// Determine the set of code-completion contexts in which this
 /// declaration should be shown.
 static unsigned getDeclShowContexts(const NamedDecl *ND,

Modified: cfe/trunk/unittests/AST/ASTImporterTest.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/ASTImporterTest.cpp?rev=334804=334803=334804=diff
==
--- cfe/trunk/unittests/AST/ASTImporterTest.cpp (original)
+++ cfe/trunk/unittests/AST/ASTImporterTest.cpp Thu Jun 14 23:45:39 2018
@@ -98,6 +98,9 @@ testImport(const std::string ,
   ASTContext  = FromAST->getASTContext(),
= ToAST->getASTContext();
 
+  FromAST->enableSourceFileDiagnostics();
+  ToAST->enableSourceFileDiagnostics();
+
   ASTImporter Importer(ToCtx, ToAST->getFileManager(),
FromCtx, FromAST->getFileManager(), false);
 
@@ -172,7 +175,9 @@ class ASTImporterTestBase : public ::tes
 : Code(Code), FileName(FileName),
   Unit(tooling::buildASTFromCodeWithArgs(this->Code, Args,
  this->FileName)),
-  TUDecl(Unit->getASTContext().getTranslationUnitDecl()) {}
+  TUDecl(Unit->getASTContext().getTranslationUnitDecl()) {
+  Unit->enableSourceFileDiagnostics();
+}
   };
 
   // We may have several From contexts and related translation units. In each
@@ -214,6 +219,7 @@ public:
 ToCode = ToSrcCode;
 assert(!ToAST);
 ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
+ToAST->enableSourceFileDiagnostics();
 
 ASTContext  = FromTU.Unit->getASTContext(),
 = ToAST->getASTContext();
@@ -261,6 +267,7 @@ public:
 ToCode = ToSrcCode;
 assert(!ToAST);
 ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
+ToAST->enableSourceFileDiagnostics();
 
 return ToAST->getASTContext().getTranslationUnitDecl();
   }
@@ -274,6 +281,7 @@ public:
   // Build the AST from an empty file.
   ToAST =
   tooling::buildASTFromCodeWithArgs(/*Code=*/"", ToArgs, "empty.cc");
+  ToAST->enableSourceFileDiagnostics();
 }
 
 // Create a virtual file in the To Ctx which corresponds to the file from


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


r338234 - [Analyzer] Iterator Checker Hotfix: Defer deletion of container data until its last iterator is cleaned up

2018-07-30 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Mon Jul 30 01:52:21 2018
New Revision: 338234

URL: http://llvm.org/viewvc/llvm-project?rev=338234=rev
Log:
[Analyzer] Iterator Checker Hotfix: Defer deletion of container data until its 
last iterator is cleaned up

The analyzer may consider a container region as dead while it still has live
iterators. We must defer deletion of the data belonging to such containers
until all its iterators are dead as well to be able to compare the iterator
to the begin and the end of the container which is stored in the container
data.

Differential Revision: https://reviews.llvm.org/D48427


Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp?rev=338234=338233=338234=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp Mon Jul 30 
01:52:21 2018
@@ -291,6 +291,7 @@ const ContainerData *getContainerData(Pr
   const MemRegion *Cont);
 ProgramStateRef setContainerData(ProgramStateRef State, const MemRegion *Cont,
  const ContainerData );
+bool hasLiveIterators(ProgramStateRef State, const MemRegion *Cont);
 bool isOutOfRange(ProgramStateRef State, const IteratorPosition );
 bool isZero(ProgramStateRef State, const NonLoc );
 } // namespace
@@ -536,7 +537,11 @@ void IteratorChecker::checkDeadSymbols(S
   auto ContMap = State->get();
   for (const auto Cont : ContMap) {
 if (!SR.isLiveRegion(Cont.first)) {
-  State = State->remove(Cont.first);
+  // We must keep the container data while it has live iterators to be able
+  // to compare them to the begin and the end of the container.
+  if (!hasLiveIterators(State, Cont.first)) {
+State = State->remove(Cont.first);
+  }
 }
   }
 
@@ -1188,6 +1193,22 @@ ProgramStateRef relateIteratorPositions(
   return NewState;
 }
 
+bool hasLiveIterators(ProgramStateRef State, const MemRegion *Cont) {
+  auto RegionMap = State->get();
+  for (const auto Reg : RegionMap) {
+if (Reg.second.getContainer() == Cont)
+  return true;
+  }
+
+  auto SymbolMap = State->get();
+  for (const auto Sym : SymbolMap) {
+if (Sym.second.getContainer() == Cont)
+  return true;
+  }
+
+  return false;
+}
+
 bool isZero(ProgramStateRef State, const NonLoc ) {
   auto  = State->getBasicVals();
   return compare(State, Val,


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


r340805 - [Analyzer] Iterator Checker - Part 3: Invalidation check, first for (copy) assignments

2018-08-28 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Tue Aug 28 01:41:15 2018
New Revision: 340805

URL: http://llvm.org/viewvc/llvm-project?rev=340805=rev
Log:
[Analyzer] Iterator Checker - Part 3: Invalidation check, first for (copy) 
assignments

We add check for invalidation of iterators. The only operation we handle here
is the (copy) assignment.

Differential Revision: https://reviews.llvm.org/D32747


Added:
cfe/trunk/test/Analysis/invalidated-iterator.cpp
Modified:
cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td
cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h
cfe/trunk/test/Analysis/diagnostics/explicit-suppression.cpp

Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td?rev=340805=340804=340805=diff
==
--- cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td Tue Aug 28 
01:41:15 2018
@@ -313,6 +313,10 @@ def IteratorRangeChecker : Checker<"Iter
   HelpText<"Check for iterators used outside their valid ranges">,
   DescFile<"IteratorChecker.cpp">;
 
+def InvalidatedIteratorChecker : Checker<"InvalidatedIterator">,
+  HelpText<"Check for use of invalidated iterators">,
+  DescFile<"IteratorChecker.cpp">;
+
 def MisusedMovedObjectChecker: Checker<"MisusedMovedObject">,
  HelpText<"Method calls on a moved-from object and copying a moved-from "
   "object will be reported">,

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp?rev=340805=340804=340805=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp Tue Aug 28 
01:41:15 2018
@@ -67,11 +67,14 @@
 // a constraint which we later retrieve when doing an actual comparison.
 
 #include "ClangSACheckers.h"
+#include "clang/AST/DeclTemplate.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
 #include "clang/StaticAnalyzer/Core/Checker.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
 
+#include 
+
 using namespace clang;
 using namespace ento;
 
@@ -85,34 +88,43 @@ private:
   // Container the iterator belongs to
   const MemRegion *Cont;
 
+  // Whether iterator is valid
+  const bool Valid;
+
   // Abstract offset
   const SymbolRef Offset;
 
-  IteratorPosition(const MemRegion *C, SymbolRef Of)
-  : Cont(C), Offset(Of) {}
+  IteratorPosition(const MemRegion *C, bool V, SymbolRef Of)
+  : Cont(C), Valid(V), Offset(Of) {}
 
 public:
   const MemRegion *getContainer() const { return Cont; }
+  bool isValid() const { return Valid; }
   SymbolRef getOffset() const { return Offset; }
 
+  IteratorPosition invalidate() const {
+return IteratorPosition(Cont, false, Offset);
+  }
+
   static IteratorPosition getPosition(const MemRegion *C, SymbolRef Of) {
-return IteratorPosition(C, Of);
+return IteratorPosition(C, true, Of);
   }
 
   IteratorPosition setTo(SymbolRef NewOf) const {
-return IteratorPosition(Cont, NewOf);
+return IteratorPosition(Cont, Valid, NewOf);
   }
 
   bool operator==(const IteratorPosition ) const {
-return Cont == X.Cont && Offset == X.Offset;
+return Cont == X.Cont && Valid == X.Valid && Offset == X.Offset;
   }
 
   bool operator!=(const IteratorPosition ) const {
-return Cont != X.Cont || Offset != X.Offset;
+return Cont != X.Cont || Valid != X.Valid || Offset != X.Offset;
   }
 
   void Profile(llvm::FoldingSetNodeID ) const {
 ID.AddPointer(Cont);
+ID.AddInteger(Valid);
 ID.Add(Offset);
   }
 };
@@ -181,15 +193,16 @@ public:
 
 class IteratorChecker
 : public Checker,
  check::PostStmt,
  check::LiveSymbols, check::DeadSymbols,
  eval::Assume> {
 
   std::unique_ptr OutOfRangeBugType;
+  std::unique_ptr InvalidatedBugType;
 
   void handleComparison(CheckerContext , const SVal , const SVal 
,
 const SVal , OverloadedOperatorKind Op) const;
+  void verifyAccess(CheckerContext , const SVal ) const;
   void verifyDereference(CheckerContext , const SVal ) const;
   void handleIncrement(CheckerContext , const SVal , const SVal ,
bool Postfix) const;
@@ -204,17 +217,21 @@ class IteratorChecker
  const SVal ) const;
   void assignToContainer(CheckerContext , const Expr *CE, const SVal ,
  const MemRegion *Cont) const;
+  void handleAssign(CheckerContext , const SVal ) const;
   void 

r337151 - [Analyzer] Mark `SymbolData` parts of iterator position as live in program state maps

2018-07-16 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Mon Jul 16 02:27:27 2018
New Revision: 337151

URL: http://llvm.org/viewvc/llvm-project?rev=337151=rev
Log:
[Analyzer] Mark `SymbolData` parts of iterator position as live in program 
state maps

Marking a symbolic expression as live is non-recursive. In our checkers we
either use conjured symbols or conjured symbols plus/minus integers to
represent abstract position of iterators, so in this latter case we also
must mark the `SymbolData` part of these symbolic expressions as live to
prevent them from getting reaped.

Differential Revision: https://reviews.llvm.org/D48764


Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp?rev=337151=337150=337151=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp Mon Jul 16 
02:27:27 2018
@@ -488,14 +488,18 @@ void IteratorChecker::checkLiveSymbols(P
   // alive
   auto RegionMap = State->get();
   for (const auto Reg : RegionMap) {
-const auto Pos = Reg.second;
-SR.markLive(Pos.getOffset());
+const auto Offset = Reg.second.getOffset();
+for (auto i = Offset->symbol_begin(); i != Offset->symbol_end(); ++i)
+  if (isa(*i))
+SR.markLive(*i);
   }
 
   auto SymbolMap = State->get();
   for (const auto Sym : SymbolMap) {
-const auto Pos = Sym.second;
-SR.markLive(Pos.getOffset());
+const auto Offset = Sym.second.getOffset();
+for (auto i = Offset->symbol_begin(); i != Offset->symbol_end(); ++i)
+  if (isa(*i))
+SR.markLive(*i);
   }
 
   auto ContMap = State->get();
@@ -1157,21 +1161,31 @@ ProgramStateRef relateIteratorPositions(
 const IteratorPosition ,
 bool Equal) {
   auto  = State->getStateManager().getSValBuilder();
+
+  // FIXME: This code should be reworked as follows:
+  // 1. Subtract the operands using evalBinOp().
+  // 2. Assume that the result doesn't overflow.
+  // 3. Compare the result to 0.
+  // 4. Assume the result of the comparison.
   const auto comparison =
   SVB.evalBinOp(State, BO_EQ, nonloc::SymbolVal(Pos1.getOffset()),
-nonloc::SymbolVal(Pos2.getOffset()), 
SVB.getConditionType())
-  .getAs();
+nonloc::SymbolVal(Pos2.getOffset()),
+SVB.getConditionType());
 
-  if (comparison) {
-auto NewState = State->assume(*comparison, Equal);
-if (const auto CompSym = comparison->getAsSymbol()) {
-  return assumeNoOverflow(NewState, cast(CompSym)->getLHS(), 
2);
-}
+  assert(comparison.getAs() &&
+"Symbol comparison must be a `DefinedSVal`");
 
-return NewState;
+  auto NewState = State->assume(comparison.castAs(), Equal);
+  if (const auto CompSym = comparison.getAsSymbol()) {
+assert(isa(CompSym) &&
+   "Symbol comparison must be a `SymIntExpr`");
+assert(BinaryOperator::isComparisonOp(
+   cast(CompSym)->getOpcode()) &&
+   "Symbol comparison must be a comparison");
+return assumeNoOverflow(NewState, cast(CompSym)->getLHS(), 2);
   }
 
-  return State;
+  return NewState;
 }
 
 bool isZero(ProgramStateRef State, const NonLoc ) {
@@ -1225,14 +1239,12 @@ bool compare(ProgramStateRef State, NonL
   auto  = State->getStateManager().getSValBuilder();
 
   const auto comparison =
-  SVB.evalBinOp(State, Opc, NL1, NL2, SVB.getConditionType())
-  .getAs();
+SVB.evalBinOp(State, Opc, NL1, NL2, SVB.getConditionType());
 
-  if (comparison) {
-return !State->assume(*comparison, false);
-  }
+  assert(comparison.getAs() &&
+"Symbol comparison must be a `DefinedSVal`");
 
-  return false;
+  return !State->assume(comparison.castAs(), false);
 }
 
 } // namespace


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


r337678 - [Analyzer] Quick Fix for exponential execution time when simpilifying complex additive expressions

2018-07-23 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Mon Jul 23 03:50:20 2018
New Revision: 337678

URL: http://llvm.org/viewvc/llvm-project?rev=337678=rev
Log:
[Analyzer] Quick Fix for exponential execution time when simpilifying complex 
additive expressions

Patch https://reviews.llvm.org/rC329780 not only rearranges comparisons but
also binary expressions. This latter behavior is not protected by the analyzer
option. Hower, since no complexity threshold is enforced to the symbols this
may result in exponential execution time if the expressions are too complex:
https://bugs.llvm.org/show_bug.cgi?id=38208. For a quick fix we extended the
analyzer option to also cover the additive cases.

This is only a temporary fix, the final solution should be enforcing the
complexity threshold to the symbols.

Differential Revision: https://reviews.llvm.org/D49536


Modified:
cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
cfe/trunk/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
cfe/trunk/test/Analysis/constraint_manager_negate_difference.c
cfe/trunk/test/Analysis/iterator-range.cpp
cfe/trunk/test/Analysis/plist-macros.cpp
cfe/trunk/test/Analysis/svalbuilder-rearrange-comparisons.c

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h?rev=337678=337677=337678=diff
==
--- cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h Mon Jul 23 
03:50:20 2018
@@ -318,8 +318,8 @@ private:
   /// \sa shouldDisplayNotesAsEvents
   Optional DisplayNotesAsEvents;
 
-  /// \sa shouldAggressivelySimplifyRelationalComparison
-  Optional AggressiveRelationalComparisonSimplification;
+  /// \sa shouldAggressivelySimplifyBinaryOperation
+  Optional AggressiveBinaryOperationSimplification;
 
   /// \sa getCTUDir
   Optional CTUDir;
@@ -690,19 +690,19 @@ public:
   /// to false when unset.
   bool shouldDisplayNotesAsEvents();
 
-  /// Returns true if SValBuilder should rearrange comparisons of symbolic
-  /// expressions which consist of a sum of a symbol and a concrete integer
-  /// into the format where symbols are on the left-hand side and the integer
-  /// is on the right. This is only done if both symbols and both concrete
-  /// integers are signed, greater than or equal to the quarter of the minimum
-  /// value of the type and less than or equal to the quarter of the maximum
-  /// value of that type.
-  ///
-  /// A + n  B + m becomes A - B  m - n, where A and B symbolic,
-  /// n and m are integers.  is any of '==', '!=', '<', '<=', '>' or '>='.
-  /// The rearrangement also happens with '-' instead of '+' on either or both
-  /// side and also if any or both integers are missing.
-  bool shouldAggressivelySimplifyRelationalComparison();
+  /// Returns true if SValBuilder should rearrange comparisons and additive
+  /// operations of symbolic expressions which consist of a sum of a symbol and
+  /// a concrete integer into the format where symbols are on the left-hand
+  /// side and the integer is on the right. This is only done if both symbols
+  /// and both concrete integers are signed, greater than or equal to the
+  /// quarter of the minimum value of the type and less than or equal to the
+  /// quarter of the maximum value of that type.
+  ///
+  /// A + n  B + m becomes A - B  m - n, where A and B symbolic,
+  /// n and m are integers.  is any of '==', '!=', '<', '<=', '>', '>=',
+  /// '+' or '-'. The rearrangement also happens with '-' instead of '+' on
+  // either or both side and also if any or both integers are missing.
+  bool shouldAggressivelySimplifyBinaryOperation();
 
   /// Returns the directory containing the CTU related files.
   StringRef getCTUDir();

Modified: cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp?rev=337678=337677=337678=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp Mon Jul 23 03:50:20 
2018
@@ -463,12 +463,12 @@ bool AnalyzerOptions::shouldDisplayNotes
   return DisplayNotesAsEvents.getValue();
 }
 
-bool AnalyzerOptions::shouldAggressivelySimplifyRelationalComparison() {
-  if (!AggressiveRelationalComparisonSimplification.hasValue())
-AggressiveRelationalComparisonSimplification =
-  getBooleanOption("aggressive-relational-comparison-simplification",
+bool AnalyzerOptions::shouldAggressivelySimplifyBinaryOperation() {
+  if (!AggressiveBinaryOperationSimplification.hasValue())
+AggressiveBinaryOperationSimplification =
+  

r337679 - Fix for last commit: adding new test file forgotten.

2018-07-23 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Mon Jul 23 03:53:02 2018
New Revision: 337679

URL: http://llvm.org/viewvc/llvm-project?rev=337679=rev
Log:
Fix for last commit: adding new test file forgotten.


Added:
cfe/trunk/test/Analysis/PR38208.c

Added: cfe/trunk/test/Analysis/PR38208.c
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/PR38208.c?rev=337679=auto
==
--- cfe/trunk/test/Analysis/PR38208.c (added)
+++ cfe/trunk/test/Analysis/PR38208.c Mon Jul 23 03:53:02 2018
@@ -0,0 +1,43 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s
+
+// expected-no-diagnostics
+
+int foo(int a, int b) {
+  a += b; b -= a;
+  a += b; b -= a;
+  a += b; b -= a;
+  a += b; b -= a;
+  a += b; b -= a;
+  a += b; b -= a;
+  a += b; b -= a;
+  a += b; b -= a;
+  a += b; b -= a;
+  a += b; b -= a;
+  a += b; b -= a;
+  a += b; b -= a;
+  a += b; b -= a;
+  a += b; b -= a;
+  a += b; b -= a;
+  a += b; b -= a;
+  a += b; b -= a;
+  a += b; b -= a;
+  a += b; b -= a;
+  a += b; b -= a;
+  a += b; b -= a;
+  a += b; b -= a;
+  a += b; b -= a;
+  a += b; b -= a;
+  a += b; b -= a;
+  a += b; b -= a;
+  a += b; b -= a;
+  a += b; b -= a;
+  a += b; b -= a;
+  a += b; b -= a;
+  a += b; b -= a;
+  a += b; b -= a;
+  a += b; b -= a;
+  a += b; b -= a;
+  a += b; b -= a;
+  a += b; b -= a;
+  return a + b;
+}


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


r341791 - [Analyzer] Iterator Checker - Part 5: Move Assignment of Containers

2018-09-10 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Mon Sep 10 02:04:27 2018
New Revision: 341791

URL: http://llvm.org/viewvc/llvm-project?rev=341791=rev
Log:
[Analyzer] Iterator Checker - Part 5: Move Assignment of Containers

If a container is moved by its move assignment operator, according to the 
standard all their iterators except the past-end iterators remain valid but 
refer to the new container. This patch introduces support for this case in the 
iterator checkers.

Differential Revision: https://reviews.llvm.org/D32859


Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp?rev=341791=341790=341791=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp Mon Sep 10 
02:04:27 2018
@@ -114,6 +114,10 @@ public:
 return IteratorPosition(Cont, Valid, NewOf);
   }
 
+  IteratorPosition reAssign(const MemRegion *NewCont) const {
+return IteratorPosition(NewCont, Valid, Offset);
+  }
+
   bool operator==(const IteratorPosition ) const {
 return Cont == X.Cont && Valid == X.Valid && Offset == X.Offset;
   }
@@ -218,7 +222,9 @@ class IteratorChecker
  const SVal ) const;
   void assignToContainer(CheckerContext , const Expr *CE, const SVal ,
  const MemRegion *Cont) const;
-  void handleAssign(CheckerContext , const SVal ) const;
+  void handleAssign(CheckerContext , const SVal ,
+const Expr *CE = nullptr,
+const SVal  = UndefinedVal()) const;
   void verifyRandomIncrOrDecr(CheckerContext , OverloadedOperatorKind Op,
   const SVal , const SVal ,
   const SVal ) const;
@@ -315,6 +321,17 @@ ProgramStateRef relateIteratorPositions(
 bool Equal);
 ProgramStateRef invalidateAllIteratorPositions(ProgramStateRef State,
const MemRegion *Cont);
+ProgramStateRef reassignAllIteratorPositions(ProgramStateRef State,
+ const MemRegion *Cont,
+ const MemRegion *NewCont);
+ProgramStateRef reassignAllIteratorPositionsUnless(ProgramStateRef State,
+   const MemRegion *Cont,
+   const MemRegion *NewCont,
+   SymbolRef Offset,
+   BinaryOperator::Opcode Opc);
+ProgramStateRef rebaseSymbolInIteratorPositionsIf(
+ProgramStateRef State, SValBuilder , SymbolRef OldSym,
+SymbolRef NewSym, SymbolRef CondSym, BinaryOperator::Opcode Opc);
 const ContainerData *getContainerData(ProgramStateRef State,
   const MemRegion *Cont);
 ProgramStateRef setContainerData(ProgramStateRef State, const MemRegion *Cont,
@@ -454,7 +471,12 @@ void IteratorChecker::checkPostCall(cons
 const auto Op = Func->getOverloadedOperator();
 if (isAssignmentOperator(Op)) {
   const auto *InstCall = dyn_cast();
-  handleAssign(C, InstCall->getCXXThisVal());
+  if (Func->getParamDecl(0)->getType()->isRValueReferenceType()) {
+handleAssign(C, InstCall->getCXXThisVal(), Call.getOriginExpr(),
+ Call.getArgSVal(0));
+  } else {
+handleAssign(C, InstCall->getCXXThisVal());
+  }
 } else if (isSimpleComparisonOperator(Op)) {
   if (const auto *InstCall = dyn_cast()) {
 handleComparison(C, Call.getReturnValue(), InstCall->getCXXThisVal(),
@@ -503,9 +525,6 @@ void IteratorChecker::checkPostCall(cons
   return;
 
 auto State = C.getState();
-// Already bound to container?
-if (getIteratorPosition(State, Call.getReturnValue()))
-  return;
 
 if (const auto *InstCall = dyn_cast()) {
   if (isBeginCall(Func)) {
@@ -520,6 +539,10 @@ void IteratorChecker::checkPostCall(cons
   }
 }
 
+// Already bound to container?
+if (getIteratorPosition(State, Call.getReturnValue()))
+  return;
+
 // Copy-like and move constructors
 if (isa() && Call.getNumArgs() == 1) {
   if (const auto *Pos = getIteratorPosition(State, Call.getArgSVal(0))) {
@@ -981,7 +1004,8 @@ void IteratorChecker::assignToContainer(
   C.addTransition(State);
 }
 
-void IteratorChecker::handleAssign(CheckerContext , const SVal ) const {
+void IteratorChecker::handleAssign(CheckerContext , const SVal ,
+   const Expr *CE, const SVal ) const {
   const auto *ContReg = Cont.getAsRegion();
   if (!ContReg)
 return;
@@ -998,6 +1022,65 @@ void IteratorChecker::handleAssign(Check

r341793 - [Analyzer] Iterator Checker - Part 7: Support for push and pop operations

2018-09-10 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Mon Sep 10 02:06:31 2018
New Revision: 341793

URL: http://llvm.org/viewvc/llvm-project?rev=341793=rev
Log:
[Analyzer] Iterator Checker - Part 7: Support for push and pop operations

This patch adds support for the following operations in the iterator checkers: 
push_back, push_front, emplace_back, emplace_front, pop_back and pop_front. 
This affects iterator range checks (range is extended after push and emplace 
and reduced after pop operations) and invalidation checks (according to the 
standard).

Differential Revision: https://reviews.llvm.org/D32902


Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h
cfe/trunk/test/Analysis/diagnostics/explicit-suppression.cpp
cfe/trunk/test/Analysis/invalidated-iterator.cpp
cfe/trunk/test/Analysis/iterator-range.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp?rev=341793=341792=341793=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp Mon Sep 10 
02:06:31 2018
@@ -72,6 +72,7 @@
 #include "clang/StaticAnalyzer/Core/Checker.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h"
 
 #include 
 
@@ -225,6 +226,10 @@ class IteratorChecker
   void handleAssign(CheckerContext , const SVal ,
 const Expr *CE = nullptr,
 const SVal  = UndefinedVal()) const;
+  void handlePushBack(CheckerContext , const SVal ) const;
+  void handlePopBack(CheckerContext , const SVal ) const;
+  void handlePushFront(CheckerContext , const SVal ) const;
+  void handlePopFront(CheckerContext , const SVal ) const;
   void verifyRandomIncrOrDecr(CheckerContext , OverloadedOperatorKind Op,
   const SVal , const SVal ,
   const SVal ) const;
@@ -282,6 +287,12 @@ bool isIterator(const CXXRecordDecl *CRD
 bool isComparisonOperator(OverloadedOperatorKind OK);
 bool isBeginCall(const FunctionDecl *Func);
 bool isEndCall(const FunctionDecl *Func);
+bool isPushBackCall(const FunctionDecl *Func);
+bool isEmplaceBackCall(const FunctionDecl *Func);
+bool isPopBackCall(const FunctionDecl *Func);
+bool isPushFrontCall(const FunctionDecl *Func);
+bool isEmplaceFrontCall(const FunctionDecl *Func);
+bool isPopFrontCall(const FunctionDecl *Func);
 bool isAssignmentOperator(OverloadedOperatorKind OK);
 bool isSimpleComparisonOperator(OverloadedOperatorKind OK);
 bool isAccessOperator(OverloadedOperatorKind OK);
@@ -289,6 +300,9 @@ bool isDereferenceOperator(OverloadedOpe
 bool isIncrementOperator(OverloadedOperatorKind OK);
 bool isDecrementOperator(OverloadedOperatorKind OK);
 bool isRandomIncrOrDecrOperator(OverloadedOperatorKind OK);
+bool hasSubscriptOperator(ProgramStateRef State, const MemRegion *Reg);
+bool frontModifiable(ProgramStateRef State, const MemRegion *Reg);
+bool backModifiable(ProgramStateRef State, const MemRegion *Reg);
 BinaryOperator::Opcode getOpcode(const SymExpr *SE);
 const RegionOrSymbol getRegionOrSymbol(const SVal );
 const ProgramStateRef processComparison(ProgramStateRef State,
@@ -325,6 +339,9 @@ ProgramStateRef relateIteratorPositions(
 bool Equal);
 ProgramStateRef invalidateAllIteratorPositions(ProgramStateRef State,
const MemRegion *Cont);
+ProgramStateRef invalidateIteratorPositions(ProgramStateRef State,
+SymbolRef Offset,
+BinaryOperator::Opcode Opc);
 ProgramStateRef reassignAllIteratorPositions(ProgramStateRef State,
  const MemRegion *Cont,
  const MemRegion *NewCont);
@@ -561,6 +578,18 @@ void IteratorChecker::checkPostCall(cons
   }
 }
   } else {
+if (const auto *InstCall = dyn_cast()) {
+  if (isPushBackCall(Func) || isEmplaceBackCall(Func)) {
+handlePushBack(C, InstCall->getCXXThisVal());
+  } else if (isPopBackCall(Func)) {
+handlePopBack(C, InstCall->getCXXThisVal());
+  } else if (isPushFrontCall(Func) || isEmplaceFrontCall(Func)) {
+handlePushFront(C, InstCall->getCXXThisVal());
+  } else if (isPopFrontCall(Func)) {
+handlePopFront(C, InstCall->getCXXThisVal());
+  }
+}
+
 const auto *OrigExpr = Call.getOriginExpr();
 if (!OrigExpr)
   return;
@@ -653,9 +682,13 @@ void IteratorChecker::checkLiveSymbols(P
 const auto CData = Cont.second;
 if (CData.getBegin()) {
  

r341794 - [Analyzer] Iterator Checker - Part 8: Support for assign, clear, insert, emplace and erase operations

2018-09-10 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Mon Sep 10 02:07:47 2018
New Revision: 341794

URL: http://llvm.org/viewvc/llvm-project?rev=341794=rev
Log:
[Analyzer] Iterator Checker - Part 8: Support for assign, clear, insert, 
emplace and erase operations

This patch adds support for the following operations in the iterator checkers: 
assign, clear, insert, insert_after, emplace, emplace_after, erase and 
erase_after. This affects mismatched iterator checks ("this" and parameter must 
match) and invalidation checks (according to the standard).

Differential Revision: https://reviews.llvm.org/D32904


Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h
cfe/trunk/test/Analysis/diagnostics/explicit-suppression.cpp
cfe/trunk/test/Analysis/invalidated-iterator.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp?rev=341794=341793=341794=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp Mon Sep 10 
02:07:47 2018
@@ -198,7 +198,7 @@ public:
 
 class IteratorChecker
 : public Checker,
+ check::PostStmt, check::Bind,
  check::LiveSymbols, check::DeadSymbols,
  eval::Assume> {
 
@@ -226,13 +226,23 @@ class IteratorChecker
   void handleAssign(CheckerContext , const SVal ,
 const Expr *CE = nullptr,
 const SVal  = UndefinedVal()) const;
+  void handleClear(CheckerContext , const SVal ) const;
   void handlePushBack(CheckerContext , const SVal ) const;
   void handlePopBack(CheckerContext , const SVal ) const;
   void handlePushFront(CheckerContext , const SVal ) const;
   void handlePopFront(CheckerContext , const SVal ) const;
+  void handleInsert(CheckerContext , const SVal ) const;
+  void handleErase(CheckerContext , const SVal ) const;
+  void handleErase(CheckerContext , const SVal ,
+   const SVal ) const;
+  void handleEraseAfter(CheckerContext , const SVal ) const;
+  void handleEraseAfter(CheckerContext , const SVal ,
+const SVal ) const;
   void verifyRandomIncrOrDecr(CheckerContext , OverloadedOperatorKind Op,
   const SVal , const SVal ,
   const SVal ) const;
+  void verifyMatch(CheckerContext , const SVal ,
+   const MemRegion *Cont) const;
   void verifyMatch(CheckerContext , const SVal ,
const SVal ) const;
 
@@ -262,6 +272,9 @@ public:
 
   void checkPreCall(const CallEvent , CheckerContext ) const;
   void checkPostCall(const CallEvent , CheckerContext ) const;
+  void checkBind(SVal Loc, SVal Val, const Stmt *S, CheckerContext ) const;
+  void checkPostStmt(const CXXConstructExpr *CCE, CheckerContext ) const;
+  void checkPostStmt(const DeclStmt *DS, CheckerContext ) const;
   void checkPostStmt(const MaterializeTemporaryExpr *MTE,
  CheckerContext ) const;
   void checkLiveSymbols(ProgramStateRef State, SymbolReaper ) const;
@@ -287,12 +300,18 @@ bool isIterator(const CXXRecordDecl *CRD
 bool isComparisonOperator(OverloadedOperatorKind OK);
 bool isBeginCall(const FunctionDecl *Func);
 bool isEndCall(const FunctionDecl *Func);
+bool isAssignCall(const FunctionDecl *Func);
+bool isClearCall(const FunctionDecl *Func);
 bool isPushBackCall(const FunctionDecl *Func);
 bool isEmplaceBackCall(const FunctionDecl *Func);
 bool isPopBackCall(const FunctionDecl *Func);
 bool isPushFrontCall(const FunctionDecl *Func);
 bool isEmplaceFrontCall(const FunctionDecl *Func);
 bool isPopFrontCall(const FunctionDecl *Func);
+bool isInsertCall(const FunctionDecl *Func);
+bool isEraseCall(const FunctionDecl *Func);
+bool isEraseAfterCall(const FunctionDecl *Func);
+bool isEmplaceCall(const FunctionDecl *Func);
 bool isAssignmentOperator(OverloadedOperatorKind OK);
 bool isSimpleComparisonOperator(OverloadedOperatorKind OK);
 bool isAccessOperator(OverloadedOperatorKind OK);
@@ -339,9 +358,18 @@ ProgramStateRef relateIteratorPositions(
 bool Equal);
 ProgramStateRef invalidateAllIteratorPositions(ProgramStateRef State,
const MemRegion *Cont);
+ProgramStateRef
+invalidateAllIteratorPositionsExcept(ProgramStateRef State,
+ const MemRegion *Cont, SymbolRef Offset,
+ BinaryOperator::Opcode Opc);
 ProgramStateRef invalidateIteratorPositions(ProgramStateRef State,
 SymbolRef Offset,
 BinaryOperator::Opcode Opc);
+ProgramStateRef 

r341792 - [Analyzer] Iterator Checker - Part 6: Mismatched iterator checker for constructors and comparisons

2018-09-10 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Mon Sep 10 02:05:31 2018
New Revision: 341792

URL: http://llvm.org/viewvc/llvm-project?rev=341792=rev
Log:
[Analyzer] Iterator Checker - Part 6: Mismatched iterator checker for 
constructors and comparisons

Extension of the mismatched iterator checker for constructors taking range of 
first..last (first and last must be iterators of the same container) and also 
for comparisons of iterators of different containers (one does not compare 
iterators of different containers, since the set of iterators is partially 
ordered, there are no relations between iterators of different containers, 
except that they are always non-equal).

Differential Revision: https://reviews.llvm.org/D32860


Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp?rev=341792=341791=341792=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp Mon Sep 10 
02:05:31 2018
@@ -236,6 +236,9 @@ class IteratorChecker
   void reportMismatchedBug(const StringRef , const SVal ,
const SVal , CheckerContext ,
ExplodedNode *ErrNode) const;
+  void reportMismatchedBug(const StringRef , const SVal ,
+   const MemRegion *Reg, CheckerContext ,
+   ExplodedNode *ErrNode) const;
   void reportInvalidatedBug(const StringRef , const SVal ,
 CheckerContext , ExplodedNode *ErrNode) const;
 
@@ -276,6 +279,7 @@ namespace {
 
 bool isIteratorType(const QualType );
 bool isIterator(const CXXRecordDecl *CRD);
+bool isComparisonOperator(OverloadedOperatorKind OK);
 bool isBeginCall(const FunctionDecl *Func);
 bool isEndCall(const FunctionDecl *Func);
 bool isAssignmentOperator(OverloadedOperatorKind OK);
@@ -397,8 +401,48 @@ void IteratorChecker::checkPreCall(const
   } else {
 verifyDereference(C, Call.getArgSVal(0));
   }
+} else if (ChecksEnabled[CK_MismatchedIteratorChecker] &&
+   isComparisonOperator(Func->getOverloadedOperator())) {
+  // Check for comparisons of iterators of different containers
+  if (const auto *InstCall = dyn_cast()) {
+if (Call.getNumArgs() < 1)
+  return;
+
+if (!isIteratorType(InstCall->getCXXThisExpr()->getType()) ||
+!isIteratorType(Call.getArgExpr(0)->getType()))
+  return;
+
+verifyMatch(C, InstCall->getCXXThisVal(), Call.getArgSVal(0));
+  } else {
+if (Call.getNumArgs() < 2)
+  return;
+
+if (!isIteratorType(Call.getArgExpr(0)->getType()) ||
+!isIteratorType(Call.getArgExpr(1)->getType()))
+  return;
+
+verifyMatch(C, Call.getArgSVal(0), Call.getArgSVal(1));
+  }
 }
-  } else if (!isa()) {
+  } else if (isa()) {
+// Check match of first-last iterator pair in a constructor of a container
+if (Call.getNumArgs() < 2)
+  return;
+
+const auto *Ctr = cast(Call.getDecl());
+if (Ctr->getNumParams() < 2)
+  return;
+
+if (Ctr->getParamDecl(0)->getName() != "first" ||
+Ctr->getParamDecl(1)->getName() != "last")
+  return;
+
+if (!isIteratorType(Call.getArgExpr(0)->getType()) ||
+!isIteratorType(Call.getArgExpr(1)->getType()))
+  return;
+
+verifyMatch(C, Call.getArgSVal(0), Call.getArgSVal(1));
+  } else {
 // The main purpose of iterators is to abstract away from different
 // containers and provide a (maybe limited) uniform access to them.
 // This implies that any correctly written template function that
@@ -1102,6 +1146,16 @@ void IteratorChecker::reportMismatchedBu
   C.emitReport(std::move(R));
 }
 
+void IteratorChecker::reportMismatchedBug(const StringRef ,
+  const SVal , const MemRegion 
*Reg,
+  CheckerContext ,
+  ExplodedNode *ErrNode) const {
+  auto R = llvm::make_unique(*MismatchedBugType, Message, ErrNode);
+  R->markInteresting(Val);
+  R->markInteresting(Reg);
+  C.emitReport(std::move(R));
+}
+
 void IteratorChecker::reportInvalidatedBug(const StringRef ,
const SVal , CheckerContext ,
ExplodedNode *ErrNode) const {
@@ -1173,6 +1227,11 @@ bool isIterator(const CXXRecordDecl *CRD
  HasPostIncrOp && HasDerefOp;
 }
 
+bool isComparisonOperator(OverloadedOperatorKind OK) {
+  return OK == OO_EqualEqual || OK == OO_ExclaimEqual || OK == OO_Less ||
+ OK == OO_LessEqual || OK == OO_Greater || OK == OO_GreaterEqual;
+}
+
 bool isBeginCall(const FunctionDecl *Func) {
   

r341795 - [Analyzer] Commit fix for rL341790/rC341790

2018-09-10 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Mon Sep 10 02:19:54 2018
New Revision: 341795

URL: http://llvm.org/viewvc/llvm-project?rev=341795=rev
Log:
[Analyzer] Commit fix for rL341790/rC341790

Test file was accidentally not added for rL341790/rC341790 and subsequant 
patches.


Added:
cfe/trunk/test/Analysis/mismatched-iterator.cpp

Added: cfe/trunk/test/Analysis/mismatched-iterator.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/mismatched-iterator.cpp?rev=341795=auto
==
--- cfe/trunk/test/Analysis/mismatched-iterator.cpp (added)
+++ cfe/trunk/test/Analysis/mismatched-iterator.cpp Mon Sep 10 02:19:54 2018
@@ -0,0 +1,175 @@
+// RUN: %clang_analyze_cc1 -std=c++11 
-analyzer-checker=core,cplusplus,alpha.cplusplus.MismatchedIterator 
-analyzer-config aggressive-binary-operation-simplification=true 
-analyzer-config c++-container-inlining=false %s -verify
+// RUN: %clang_analyze_cc1 -std=c++11 
-analyzer-checker=core,cplusplus,alpha.cplusplus.MismatchedIterator 
-analyzer-config aggressive-binary-operation-simplification=true 
-analyzer-config c++-container-inlining=true -DINLINE=1 %s -verify
+
+#include "Inputs/system-header-simulator-cxx.h"
+
+void good_insert1(std::vector , int n) {
+  v.insert(v.cbegin(), n); // no-warning
+}
+
+
+void good_insert2(std::vector , int len, int n) {
+  v.insert(v.cbegin(), len, n); // no-warning
+}
+
+void good_insert3(std::vector , std::vector ) {
+  v1.insert(v1.cbegin(), v2.cbegin(), v2.cend()); // no-warning
+}
+
+void good_insert4(std::vector , int len, int n) {
+  v.insert(v.cbegin(), {n-1, n, n+1}); // no-warning
+}
+
+void good_insert_find(std::vector , int n, int m) {
+  auto i = std::find(v.cbegin(), v.cend(), n);
+  v.insert(i, m); // no-warning
+}
+
+void good_erase1(std::vector ) {
+  v.erase(v.cbegin()); // no-warning
+}
+
+void good_erase2(std::vector ) {
+  v.erase(v.cbegin(), v.cend()); // no-warning
+}
+
+void good_emplace(std::vector , int n) {
+  v.emplace(v.cbegin(), n); // no-warning
+}
+
+void good_ctor(std::vector ) {
+  std::vector new_v(v.cbegin(), v.cend()); // no-warning
+}
+
+void good_find(std::vector , int n) {
+  std::find(v.cbegin(), v.cend(), n); // no-warning
+}
+
+void good_find_first_of(std::vector , std::vector ) {
+  std::find_first_of(v1.cbegin(), v1.cend(), v2.cbegin(), v2.cend()); // 
no-warning
+}
+
+void good_copy(std::vector , std::vector , int n) {
+  std::copy(v1.cbegin(), v1.cend(), v2.begin()); // no-warning
+}
+
+void good_move_find1(std::vector , std::vector , int n) {
+  auto i0 = v2.cbegin();
+  v1 = std::move(v2);
+  std::find(i0, v1.cend(), n); // no-warning
+}
+
+void bad_insert1(std::vector , std::vector , int n) {
+  v2.insert(v1.cbegin(), n); // expected-warning{{Container accessed using 
foreign iterator argument}}
+}
+
+void bad_insert2(std::vector , std::vector , int len, int n) {
+  v2.insert(v1.cbegin(), len, n); // expected-warning{{Container accessed 
using foreign iterator argument}}
+}
+
+void bad_insert3(std::vector , std::vector ) {
+  v2.insert(v1.cbegin(), v2.cbegin(), v2.cend()); // 
expected-warning{{Container accessed using foreign iterator argument}}
+  v1.insert(v1.cbegin(), v1.cbegin(), v2.cend()); // 
expected-warning{{Iterators of different containers used where the same 
container is expected}}
+  v1.insert(v1.cbegin(), v2.cbegin(), v1.cend()); // 
expected-warning{{Iterators of different containers used where the same 
container is expected}}
+}
+
+void bad_insert4(std::vector , std::vector , int len, int n) {
+  v2.insert(v1.cbegin(), {n-1, n, n+1}); // expected-warning{{Container 
accessed using foreign iterator argument}}
+}
+
+void bad_erase1(std::vector , std::vector ) {
+  v2.erase(v1.cbegin()); // expected-warning{{Container accessed using foreign 
iterator argument}}
+}
+
+void bad_erase2(std::vector , std::vector ) {
+  v2.erase(v2.cbegin(), v1.cend()); // expected-warning{{Container accessed 
using foreign iterator argument}}
+  v2.erase(v1.cbegin(), v2.cend()); // expected-warning{{Container accessed 
using foreign iterator argument}}
+  v2.erase(v1.cbegin(), v1.cend()); // expected-warning{{Container accessed 
using foreign iterator argument}}
+}
+
+void bad_emplace(std::vector , std::vector , int n) {
+  v2.emplace(v1.cbegin(), n); // expected-warning{{Container accessed using 
foreign iterator argument}}
+}
+
+void good_move_find2(std::vector , std::vector , int n) {
+  auto i0 = --v2.cend();
+  v1 = std::move(v2);
+  std::find(i0, v1.cend(), n); // no-warning
+}
+
+void good_move_find3(std::vector , std::vector , int n) {
+  auto i0 = v2.cend();
+  v1 = std::move(v2);
+  v2.push_back(n);
+  std::find(v2.cbegin(), i0, n); // no-warning
+}
+
+void good_comparison(std::vector ) {
+  if (v.cbegin() == v.cend()) {} // no-warning
+}
+
+void bad_ctor(std::vector , std::vector ) {
+  std::vector new_v(v1.cbegin(), v2.cend()); // 
expected-warning{{Iterators of different containers used where 

r341790 - [Analyzer] Iterator Checker - Part 4: Mismatched iterator checker for function parameters

2018-09-10 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Mon Sep 10 02:03:22 2018
New Revision: 341790

URL: http://llvm.org/viewvc/llvm-project?rev=341790=rev
Log:
[Analyzer] Iterator Checker - Part 4: Mismatched iterator checker for function 
parameters

New check added to the checker which checks whether iterator parameters of 
template functions typed by the same template parameter refer to the same 
container.

Differential Revision: https://reviews.llvm.org/D32845


Modified:
cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td
cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h
cfe/trunk/test/Analysis/invalidated-iterator.cpp

Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td?rev=341790=341789=341790=diff
==
--- cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td Mon Sep 10 
02:03:22 2018
@@ -309,12 +309,16 @@ def DeleteWithNonVirtualDtorChecker : Ch
"destructor in their base class">,
   DescFile<"DeleteWithNonVirtualDtorChecker.cpp">;
 
+def InvalidatedIteratorChecker : Checker<"InvalidatedIterator">,
+  HelpText<"Check for use of invalidated iterators">,
+  DescFile<"IteratorChecker.cpp">;
+
 def IteratorRangeChecker : Checker<"IteratorRange">,
   HelpText<"Check for iterators used outside their valid ranges">,
   DescFile<"IteratorChecker.cpp">;
 
-def InvalidatedIteratorChecker : Checker<"InvalidatedIterator">,
-  HelpText<"Check for use of invalidated iterators">,
+def MismatchedIteratorChecker : Checker<"MismatchedIterator">,
+  HelpText<"Check for use of iterators of different containers where iterators 
of the same container are expected">,
   DescFile<"IteratorChecker.cpp">;
 
 def MisusedMovedObjectChecker: Checker<"MisusedMovedObject">,

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp?rev=341790=341789=341790=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp Mon Sep 10 
02:03:22 2018
@@ -198,6 +198,7 @@ class IteratorChecker
  eval::Assume> {
 
   std::unique_ptr OutOfRangeBugType;
+  std::unique_ptr MismatchedBugType;
   std::unique_ptr InvalidatedBugType;
 
   void handleComparison(CheckerContext , const SVal , const SVal 
,
@@ -221,8 +222,14 @@ class IteratorChecker
   void verifyRandomIncrOrDecr(CheckerContext , OverloadedOperatorKind Op,
   const SVal , const SVal ,
   const SVal ) const;
+  void verifyMatch(CheckerContext , const SVal ,
+   const SVal ) const;
+
   void reportOutOfRangeBug(const StringRef , const SVal ,
CheckerContext , ExplodedNode *ErrNode) const;
+  void reportMismatchedBug(const StringRef , const SVal ,
+   const SVal , CheckerContext ,
+   ExplodedNode *ErrNode) const;
   void reportInvalidatedBug(const StringRef , const SVal ,
 CheckerContext , ExplodedNode *ErrNode) const;
 
@@ -231,6 +238,7 @@ public:
 
   enum CheckKind {
 CK_IteratorRangeChecker,
+CK_MismatchedIteratorChecker,
 CK_InvalidatedIteratorChecker,
 CK_NumCheckKinds
   };
@@ -312,6 +320,8 @@ const ContainerData *getContainerData(Pr
 ProgramStateRef setContainerData(ProgramStateRef State, const MemRegion *Cont,
  const ContainerData );
 bool hasLiveIterators(ProgramStateRef State, const MemRegion *Cont);
+bool isBoundThroughLazyCompoundVal(const Environment ,
+   const MemRegion *Reg);
 bool isOutOfRange(ProgramStateRef State, const IteratorPosition );
 bool isZero(ProgramStateRef State, const NonLoc );
 } // namespace
@@ -320,6 +330,9 @@ IteratorChecker::IteratorChecker() {
   OutOfRangeBugType.reset(
   new BugType(this, "Iterator out of range", "Misuse of STL APIs"));
   OutOfRangeBugType->setSuppressOnSink(true);
+  MismatchedBugType.reset(
+  new BugType(this, "Iterator(s) mismatched", "Misuse of STL APIs"));
+  MismatchedBugType->setSuppressOnSink(true);
   InvalidatedBugType.reset(
   new BugType(this, "Iterator invalidated", "Misuse of STL APIs"));
   InvalidatedBugType->setSuppressOnSink(true);
@@ -368,6 +381,65 @@ void IteratorChecker::checkPreCall(const
 verifyDereference(C, Call.getArgSVal(0));
   }
 }
+  } else if (!isa()) {
+// The main purpose of iterators is to abstract away from different
+// containers and provide a (maybe limited) 

[clang-tools-extra] r336997 - [clang-tidy] Exception Escape Checker

2018-07-13 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Fri Jul 13 06:09:40 2018
New Revision: 336997

URL: http://llvm.org/viewvc/llvm-project?rev=336997=rev
Log:
[clang-tidy] Exception Escape Checker

Finds functions which may throw an exception directly or indirectly, but they
should not: Destructors, move constructors, move assignment operators, the
main() function, swap() functions, functions marked with throw() or noexcept
and functions given as option to the checker.

Differential Revision: https://reviews.llvm.org/D33537


Added:
clang-tools-extra/trunk/clang-tidy/bugprone/ExceptionEscapeCheck.cpp
clang-tools-extra/trunk/clang-tidy/bugprone/ExceptionEscapeCheck.h
clang-tools-extra/trunk/docs/clang-tidy/checks/bugprone-exception-escape.rst
clang-tools-extra/trunk/test/clang-tidy/bugprone-exception-escape.cpp
Modified:
clang-tools-extra/trunk/clang-tidy/bugprone/BugproneTidyModule.cpp
clang-tools-extra/trunk/clang-tidy/bugprone/CMakeLists.txt
clang-tools-extra/trunk/docs/ReleaseNotes.rst
clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst

Modified: clang-tools-extra/trunk/clang-tidy/bugprone/BugproneTidyModule.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/bugprone/BugproneTidyModule.cpp?rev=336997=336996=336997=diff
==
--- clang-tools-extra/trunk/clang-tidy/bugprone/BugproneTidyModule.cpp 
(original)
+++ clang-tools-extra/trunk/clang-tidy/bugprone/BugproneTidyModule.cpp Fri Jul 
13 06:09:40 2018
@@ -16,6 +16,7 @@
 #include "BoolPointerImplicitConversionCheck.h"
 #include "CopyConstructorInitCheck.h"
 #include "DanglingHandleCheck.h"
+#include "ExceptionEscapeCheck.h"
 #include "FoldInitTypeCheck.h"
 #include "ForwardDeclarationNamespaceCheck.h"
 #include "ForwardingReferenceOverloadCheck.h"
@@ -67,6 +68,8 @@ public:
 "bugprone-copy-constructor-init");
 CheckFactories.registerCheck(
 "bugprone-dangling-handle");
+CheckFactories.registerCheck(
+"bugprone-exception-escape");
 CheckFactories.registerCheck(
 "bugprone-fold-init-type");
 CheckFactories.registerCheck(

Modified: clang-tools-extra/trunk/clang-tidy/bugprone/CMakeLists.txt
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/bugprone/CMakeLists.txt?rev=336997=336996=336997=diff
==
--- clang-tools-extra/trunk/clang-tidy/bugprone/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clang-tidy/bugprone/CMakeLists.txt Fri Jul 13 
06:09:40 2018
@@ -7,6 +7,7 @@ add_clang_library(clangTidyBugproneModul
   BugproneTidyModule.cpp
   CopyConstructorInitCheck.cpp
   DanglingHandleCheck.cpp
+  ExceptionEscapeCheck.cpp
   FoldInitTypeCheck.cpp
   ForwardDeclarationNamespaceCheck.cpp
   ForwardingReferenceOverloadCheck.cpp

Added: clang-tools-extra/trunk/clang-tidy/bugprone/ExceptionEscapeCheck.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/bugprone/ExceptionEscapeCheck.cpp?rev=336997=auto
==
--- clang-tools-extra/trunk/clang-tidy/bugprone/ExceptionEscapeCheck.cpp (added)
+++ clang-tools-extra/trunk/clang-tidy/bugprone/ExceptionEscapeCheck.cpp Fri 
Jul 13 06:09:40 2018
@@ -0,0 +1,214 @@
+//===--- ExceptionEscapeCheck.cpp - 
clang-tidy-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#include "ExceptionEscapeCheck.h"
+
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/StringSet.h"
+
+using namespace clang::ast_matchers;
+
+namespace {
+typedef llvm::SmallVector TypeVec;
+} // namespace
+
+namespace clang {
+
+static bool isBaseOf(const Type *DerivedType, const Type *BaseType) {
+  const auto *DerivedClass = DerivedType->getAsCXXRecordDecl();
+  const auto *BaseClass = BaseType->getAsCXXRecordDecl();
+  if (!DerivedClass || !BaseClass)
+return false;
+
+  return !DerivedClass->forallBases(
+  [BaseClass](const CXXRecordDecl *Cur) { return Cur != BaseClass; });
+}
+
+static const TypeVec
+throwsException(const Stmt *St, const TypeVec ,
+llvm::SmallSet );
+
+static const TypeVec
+throwsException(const FunctionDecl *Func,
+llvm::SmallSet ) {
+  if (CallStack.count(Func))
+return TypeVec();
+
+  if (const Stmt *Body = Func->getBody()) {
+CallStack.insert(Func);
+const TypeVec Result = throwsException(Body, TypeVec(), CallStack);
+CallStack.erase(Func);
+return Result;
+  }
+
+  TypeVec Result;
+  if (const auto *FPT = Func->getType()->getAs()) {
+for (const QualType Ex : 

r337000 - [Analyzer] alpha.unix.cstring.OutOfBounds checker enable/disable fix

2018-07-13 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Fri Jul 13 06:44:44 2018
New Revision: 337000

URL: http://llvm.org/viewvc/llvm-project?rev=337000=rev
Log:
[Analyzer] alpha.unix.cstring.OutOfBounds checker enable/disable fix

It was not possible to disable alpha.unix.cstring.OutOfBounds checker's reports
since unix.Malloc checker always implicitly enabled the filter. Moreover if the
checker was disabled from command line (-analyzer-disable-checker ..) the out
of bounds warnings were nevertheless emitted under different checker names such
as unix.cstring.NullArg, or unix.Malloc.

This patch fixes the case sot that Malloc checker only enables implicitly the
underlying modeling of strcpy, memcpy etc. but not the warning messages that
would have been emmitted by alpha.unix.cstring.OutOfBounds

Patch by: Dániel Krupp

Differential Revision: https://reviews.llvm.org/D48831


Added:
cfe/trunk/test/Analysis/cstring-plist.c
Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
cfe/trunk/test/Analysis/malloc.c
cfe/trunk/test/Analysis/string.c

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp?rev=337000=336999=337000=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp Fri Jul 13 
06:44:44 2018
@@ -305,10 +305,10 @@ ProgramStateRef CStringChecker::CheckLoc
   ProgramStateRef StOutBound = state->assumeInBound(Idx, Size, false);
   if (StOutBound && !StInBound) {
 // These checks are either enabled by the CString out-of-bounds checker
-// explicitly or the "basic" CStringNullArg checker support that Malloc
-// checker enables.
-assert(Filter.CheckCStringOutOfBounds || Filter.CheckCStringNullArg);
-
+// explicitly or implicitly by the Malloc checker.
+// In the latter case we only do modeling but do not emit warning.
+if (!Filter.CheckCStringOutOfBounds)
+  return nullptr;
 // Emit a bug report.
 if (warningMsg) {
   emitOutOfBoundsBug(C, StOutBound, S, warningMsg);
@@ -1039,7 +1039,7 @@ bool CStringChecker::memsetAux(const Exp
 std::tie(StateWholeReg, StateNotWholeReg) =
 State->assume(svalBuilder.evalEQ(State, Extent, *SizeNL));
 
-// With the semantic of 'memset()', we should convert the CharVal to 
+// With the semantic of 'memset()', we should convert the CharVal to
 // unsigned char.
 CharVal = svalBuilder.evalCast(CharVal, Ctx.UnsignedCharTy, Ctx.IntTy);
 
@@ -2418,5 +2418,5 @@ void CStringChecker::checkDeadSymbols(Sy
 REGISTER_CHECKER(CStringNotNullTerm)
 
   void ento::registerCStringCheckerBasic(CheckerManager ) {
-registerCStringNullArg(Mgr);
+Mgr.registerChecker();
   }

Added: cfe/trunk/test/Analysis/cstring-plist.c
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/cstring-plist.c?rev=337000=auto
==
--- cfe/trunk/test/Analysis/cstring-plist.c (added)
+++ cfe/trunk/test/Analysis/cstring-plist.c Fri Jul 13 06:44:44 2018
@@ -0,0 +1,22 @@
+// RUN: rm -f %t
+// RUN: %clang_analyze_cc1 -fblocks 
-analyzer-checker=core,unix.Malloc,unix.cstring.NullArg 
-analyzer-disable-checker=alpha.unix.cstring.OutOfBounds -analyzer-output=plist 
-analyzer-config path-diagnostics-alternate=false -o %t %s
+// RUN: FileCheck -input-file %t %s
+
+typedef __typeof(sizeof(int)) size_t;
+void *malloc(size_t);
+void free(void *);
+char *strncpy(char *restrict s1, const char *restrict s2, size_t n);
+
+
+
+void cstringchecker_bounds_nocrash() {
+  char *p = malloc(2);
+  strncpy(p, "AAA", sizeof("AAA")); // we don't expect warning as the checker 
is disabled
+  free(p);
+}
+
+// CHECK: diagnostics
+// CHECK-NEXT: 
+// CHECK-NEXT: 
+// CHECK-NEXT: 
+// CHECK-NEXT: 

Modified: cfe/trunk/test/Analysis/malloc.c
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc.c?rev=337000=336999=337000=diff
==
--- cfe/trunk/test/Analysis/malloc.c (original)
+++ cfe/trunk/test/Analysis/malloc.c Fri Jul 13 06:44:44 2018
@@ -375,7 +375,7 @@ void CheckUseZeroReallocatedPathWarn(_Bo
 // or inter-procedural analysis, this is a conservative answer.
 int *f3() {
   static int *p = 0;
-  p = malloc(12); 
+  p = malloc(12);
   return p; // no-warning
 }
 
@@ -384,7 +384,7 @@ int *f3() {
 // functions or inter-procedural analysis, this is a conservative answer.
 static int *p_f4 = 0;
 int *f4() {
-  p_f4 = malloc(12); 
+  p_f4 = malloc(12);
   return p_f4; // no-warning
 }
 
@@ -1232,7 +1232,7 @@ void radar10978247(int myValueSize) {
 
   if (myValueSize <= sizeof(stackBuffer))
 buffer = stackBuffer;
-  else 
+  else
 buffer = malloc(myValueSize);
 
   // do stuff with the buffer
@@ -1246,7 +1246,7 @@ 

r330064 - [Analyzer] Fix for SValBuilder expressions rearrangement

2018-04-13 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Fri Apr 13 13:23:02 2018
New Revision: 330064

URL: http://llvm.org/viewvc/llvm-project?rev=330064=rev
Log:
[Analyzer] Fix for SValBuilder expressions rearrangement

Expression rearrangement in SValBuilder (see rL329780) crashes with an assert 
if the type of the integer is different from the type of the symbol. This fix 
adds a check that prevents rearrangement in such cases.

Differential Revision: https://reviews.llvm.org/D45557


Modified:
cfe/trunk/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
cfe/trunk/test/Analysis/svalbuilder-rearrange-comparisons.c

Modified: cfe/trunk/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp?rev=330064=330063=330064=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp Fri Apr 13 13:23:02 
2018
@@ -469,6 +469,8 @@ static Optional tryRearrange(Pro
 // Initialize SingleTy later with a symbol's type.
   } else if (BinaryOperator::isAdditiveOp(Op)) {
 SingleTy = ResultTy;
+if (LSym->getType() != SingleTy)
+  return None;
 // Substracting unsigned integers is a nightmare.
 if (!SingleTy->isSignedIntegerOrEnumerationType())
   return None;

Modified: cfe/trunk/test/Analysis/svalbuilder-rearrange-comparisons.c
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/svalbuilder-rearrange-comparisons.c?rev=330064=330063=330064=diff
==
--- cfe/trunk/test/Analysis/svalbuilder-rearrange-comparisons.c (original)
+++ cfe/trunk/test/Analysis/svalbuilder-rearrange-comparisons.c Fri Apr 13 
13:23:02 2018
@@ -929,3 +929,8 @@ void overflow(signed char n, signed char
 clang_analyzer_eval(n - 126 == m + 3); // expected-warning{{UNKNOWN}}
   }
 }
+
+int mixed_integer_types(int x, int y) {
+  short a = x - 1U;
+  return a - y;
+}


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


r329780 - [Analyzer] SValBuilder Comparison Rearrangement (with Restrictions and Analyzer Option)

2018-04-11 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Tue Apr 10 23:21:12 2018
New Revision: 329780

URL: http://llvm.org/viewvc/llvm-project?rev=329780=rev
Log:
[Analyzer] SValBuilder Comparison Rearrangement (with Restrictions and Analyzer 
Option)

Since the range-based constraint manager (default) is weak in handling 
comparisons where symbols are on both sides it is wise to rearrange them to 
have symbols only on the left side. Thus e.g. A + n >= B + m becomes A - B >= m 
- n which enables the constraint manager to store a range m - n .. MAX_VALUE 
for the symbolic expression A - B. This can be used later to check whether e.g. 
A + k == B + l can be true, which is also rearranged to A - B == l - k so the 
constraint manager can check whether l - k is in the range (thus greater than 
or equal to m - n).

The restriction in this version is the the rearrangement happens only if both 
the symbols and the concrete integers are within the range [min/4 .. max/4] 
where min and max are the minimal and maximal values of their type.

The rearrangement is not enabled by default. It has to be enabled by using 
-analyzer-config aggressive-relational-comparison-simplification=true.

Co-author of this patch is Artem Dergachev (NoQ).

Differential Revision: https://reviews.llvm.org/D41938


Added:
cfe/trunk/test/Analysis/svalbuilder-rearrange-comparisons.c
Modified:
cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
cfe/trunk/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
cfe/trunk/test/Analysis/conditional-path-notes.c
cfe/trunk/test/Analysis/explain-svals.cpp

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h?rev=329780=329779=329780=diff
==
--- cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h Tue Apr 10 
23:21:12 2018
@@ -312,6 +312,9 @@ private:
   /// \sa shouldDisplayNotesAsEvents
   Optional DisplayNotesAsEvents;
 
+  /// \sa shouldAggressivelySimplifyRelationalComparison
+  Optional AggressiveRelationalComparisonSimplification;
+
   /// \sa getCTUDir
   Optional CTUDir;
 
@@ -666,6 +669,20 @@ public:
   /// to false when unset.
   bool shouldDisplayNotesAsEvents();
 
+  /// Returns true if SValBuilder should rearrange comparisons of symbolic
+  /// expressions which consist of a sum of a symbol and a concrete integer
+  /// into the format where symbols are on the left-hand side and the integer
+  /// is on the right. This is only done if both symbols and both concrete
+  /// integers are signed, greater than or equal to the quarter of the minimum
+  /// value of the type and less than or equal to the quarter of the maximum
+  /// value of that type.
+  ///
+  /// A + n  B + m becomes A - B  m - n, where A and B symbolic,
+  /// n and m are integers.  is any of '==', '!=', '<', '<=', '>' or '>='.
+  /// The rearrangement also happens with '-' instead of '+' on either or both
+  /// side and also if any or both integers are missing.
+  bool shouldAggressivelySimplifyRelationalComparison();
+
   /// Returns the directory containing the CTU related files.
   StringRef getCTUDir();
 

Modified: cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp?rev=329780=329779=329780=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp Tue Apr 10 23:21:12 
2018
@@ -445,6 +445,14 @@ bool AnalyzerOptions::shouldDisplayNotes
   return DisplayNotesAsEvents.getValue();
 }
 
+bool AnalyzerOptions::shouldAggressivelySimplifyRelationalComparison() {
+  if (!AggressiveRelationalComparisonSimplification.hasValue())
+AggressiveRelationalComparisonSimplification =
+  getBooleanOption("aggressive-relational-comparison-simplification",
+   /*Default=*/false);
+  return AggressiveRelationalComparisonSimplification.getValue();
+}
+
 StringRef AnalyzerOptions::getCTUDir() {
   if (!CTUDir.hasValue()) {
 CTUDir = getOptionAsString("ctu-dir", "");

Modified: cfe/trunk/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp?rev=329780=329779=329780=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp Tue Apr 10 23:21:12 
2018
@@ -12,8 +12,10 @@
 
//===--===//
 
 #include 

r335835 - [Analyzer] Iterator Checker - Part 2: Increment, decrement operators and ahead-of-begin checks

2018-06-28 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Thu Jun 28 03:58:53 2018
New Revision: 335835

URL: http://llvm.org/viewvc/llvm-project?rev=335835=rev
Log:
[Analyzer] Iterator Checker - Part 2: Increment, decrement operators and 
ahead-of-begin checks

Add handling of the begin() funcion of containers to the iterator checkers,
together with the pre- and postfix ++ and -- operators of the iterators. This
makes possible the checking of iterators dereferenced ahead of the begin of the
container.

Differential Revision: https://reviews.llvm.org/D32642


Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h
cfe/trunk/test/Analysis/diagnostics/explicit-suppression.cpp
cfe/trunk/test/Analysis/iterator-range.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp?rev=335835=335834=335835=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp Thu Jun 28 
03:58:53 2018
@@ -46,19 +46,25 @@
 // use setter and getters functions which separate the three cases. To store
 // them we use a pointer union of symbol and memory region.
 //
-// The checker works the following way: We record the past-end iterator for
-// all containers whenever their `.end()` is called. Since the Constraint
-// Manager cannot handle SVals we need to take over its role. We post-check
-// equality and non-equality comparisons and propagate the position of the
-// iterator to the other side of the comparison if it is past-end and we are in
-// the 'equal' branch (true-branch for `==` and false-branch for `!=`).
+// The checker works the following way: We record the begin and the
+// past-end iterator for all containers whenever their `.begin()` and `.end()`
+// are called. Since the Constraint Manager cannot handle such SVals we need
+// to take over its role. We post-check equality and non-equality comparisons
+// and record that the two sides are equal if we are in the 'equal' branch
+// (true-branch for `==` and false-branch for `!=`).
 //
 // In case of type-I or type-II iterators we get a concrete integer as a result
 // of the comparison (1 or 0) but in case of type-III we only get a Symbol. In
 // this latter case we record the symbol and reload it in evalAssume() and do
 // the propagation there. We also handle (maybe double) negated comparisons
-// which are represented in the form of (x == 0 or x !=0 ) where x is the
+// which are represented in the form of (x == 0 or x != 0) where x is the
 // comparison itself.
+//
+// Since `SimpleConstraintManager` cannot handle complex symbolic expressions
+// we only use expressions of the format S, S+n or S-n for iterator positions
+// where S is a conjured symbol and n is an unsigned concrete integer. When
+// making an assumption e.g. `S1 + n == S2 + m` we store `S1 - S2 == m - n` as
+// a constraint which we later retrieve when doing an actual comparison.
 
 #include "ClangSACheckers.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
@@ -80,7 +86,7 @@ private:
   const MemRegion *Cont;
 
   // Abstract offset
-  SymbolRef Offset;
+  const SymbolRef Offset;
 
   IteratorPosition(const MemRegion *C, SymbolRef Of)
   : Cont(C), Offset(Of) {}
@@ -113,31 +119,39 @@ public:
 
 typedef llvm::PointerUnion RegionOrSymbol;
 
-// Structure to record the symbolic end position of a container
+// Structure to record the symbolic begin and end position of a container
 struct ContainerData {
 private:
-  SymbolRef End;
+  const SymbolRef Begin, End;
 
-  ContainerData(SymbolRef E) : End(E) {}
+  ContainerData(SymbolRef B, SymbolRef E) : Begin(B), End(E) {}
 
 public:
+  static ContainerData fromBegin(SymbolRef B) {
+return ContainerData(B, nullptr);
+  }
+
   static ContainerData fromEnd(SymbolRef E) {
-return ContainerData(E);
+return ContainerData(nullptr, E);
   }
 
+  SymbolRef getBegin() const { return Begin; }
   SymbolRef getEnd() const { return End; }
 
-  ContainerData newEnd(SymbolRef E) const { return ContainerData(E); }
+  ContainerData newBegin(SymbolRef B) const { return ContainerData(B, End); }
+
+  ContainerData newEnd(SymbolRef E) const { return ContainerData(Begin, E); }
 
   bool operator==(const ContainerData ) const {
-return End == X.End;
+return Begin == X.Begin && End == X.End;
   }
 
   bool operator!=(const ContainerData ) const {
-return End != X.End;
+return Begin != X.Begin || End != X.End;
   }
 
   void Profile(llvm::FoldingSetNodeID ) const {
+ID.Add(Begin);
 ID.Add(End);
   }
 };
@@ -167,8 +181,9 @@ public:
 
 class IteratorChecker
 : public Checker,
  check::PostStmt,
- check::DeadSymbols,
+ check::LiveSymbols, 

r335814 - [Analyzer] Constraint Manager Negates Difference

2018-06-28 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Thu Jun 28 00:35:23 2018
New Revision: 335814

URL: http://llvm.org/viewvc/llvm-project?rev=335814=rev
Log:
[Analyzer] Constraint Manager Negates Difference

If range [m .. n] is stored for symbolic expression A - B, then we can deduce 
the range for B - A which is [-n .. -m]. This is only true for signed types, 
unless the range is [0 .. 0].

Differential Revision: https://reviews.llvm.org/D35110


Added:
cfe/trunk/test/Analysis/constraint_manager_negate_difference.c
Modified:

cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h
cfe/trunk/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
cfe/trunk/test/Analysis/ptr-arith.c

Modified: 
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h?rev=335814=335813=335814=diff
==
--- 
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h
 (original)
+++ 
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h
 Thu Jun 28 00:35:23 2018
@@ -115,6 +115,8 @@ public:
   RangeSet Intersect(BasicValueFactory , Factory , llvm::APSInt Lower,
  llvm::APSInt Upper) const;
 
+  RangeSet Negate(BasicValueFactory , Factory ) const;
+
   void print(raw_ostream ) const;
 
   bool operator==(const RangeSet ) const {

Modified: cfe/trunk/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp?rev=335814=335813=335814=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp Thu Jun 28 
00:35:23 2018
@@ -174,6 +174,38 @@ RangeSet RangeSet::Intersect(BasicValueF
   return newRanges;
 }
 
+// Turn all [A, B] ranges to [-B, -A]. Ranges [MIN, B] are turned to range set
+// [MIN, MIN] U [-B, MAX], when MIN and MAX are the minimal and the maximal
+// signed values of the type.
+RangeSet RangeSet::Negate(BasicValueFactory , Factory ) const {
+  PrimRangeSet newRanges = F.getEmptySet();
+
+  for (iterator i = begin(), e = end(); i != e; ++i) {
+const llvm::APSInt  = i->From(),  = i->To();
+const llvm::APSInt  = (from.isMinSignedValue() ?
+ BV.getMaxValue(from) :
+ BV.getValue(- from));
+if (to.isMaxSignedValue() && !newRanges.isEmpty() &&
+newRanges.begin()->From().isMinSignedValue()) {
+  assert(newRanges.begin()->To().isMinSignedValue() &&
+ "Ranges should not overlap");
+  assert(!from.isMinSignedValue() && "Ranges should not overlap");
+  const llvm::APSInt  = newRanges.begin()->From();
+  newRanges =
+F.add(F.remove(newRanges, *newRanges.begin()), Range(newFrom, newTo));
+} else if (!to.isMinSignedValue()) {
+  const llvm::APSInt  = BV.getValue(- to);
+  newRanges = F.add(newRanges, Range(newFrom, newTo));
+}
+if (from.isMinSignedValue()) {
+  newRanges = F.add(newRanges, Range(BV.getMinValue(from),
+ BV.getMinValue(from)));
+}
+  }
+
+  return newRanges;
+}
+
 void RangeSet::print(raw_ostream ) const {
   bool isFirst = true;
   os << "{ ";
@@ -252,6 +284,8 @@ private:
   RangeSet::Factory F;
 
   RangeSet getRange(ProgramStateRef State, SymbolRef Sym);
+  const RangeSet* getRangeForMinusSymbol(ProgramStateRef State,
+ SymbolRef Sym);
 
   RangeSet getSymLTRange(ProgramStateRef St, SymbolRef Sym,
  const llvm::APSInt ,
@@ -268,6 +302,7 @@ private:
   RangeSet getSymGERange(ProgramStateRef St, SymbolRef Sym,
  const llvm::APSInt ,
  const llvm::APSInt );
+
 };
 
 } // end anonymous namespace
@@ -423,9 +458,15 @@ RangeSet RangeConstraintManager::getRang
   if (ConstraintRangeTy::data_type *V = State->get(Sym))
 return *V;
 
+  BasicValueFactory  = getBasicVals();
+
+  // If Sym is a difference of symbols A - B, then maybe we have range set
+  // stored for B - A.
+  if (const RangeSet *R = getRangeForMinusSymbol(State, Sym))
+return R->Negate(BV, F);
+
   // Lazily generate a new RangeSet representing all possible values for the
   // given symbol type.
-  BasicValueFactory  = getBasicVals();
   QualType T = Sym->getType();
 
   RangeSet Result(F, BV.getMinValue(T), BV.getMaxValue(T));
@@ -441,6 +482,32 @@ RangeSet RangeConstraintManager::getRang
   return Result;
 }
 
+// FIXME: Once SValBuilder supports unary minus, we should use SValBuilder to
+//obtain the negated symbolic expression instead of constructing the
+//symbol 

[clang-tools-extra] r344445 - [clang-tidy] Fix for typos in the tests for `bugprone-exception-escape`

2018-10-13 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Sat Oct 13 04:17:59 2018
New Revision: 35

URL: http://llvm.org/viewvc/llvm-project?rev=35=rev
Log:
[clang-tidy] Fix for typos in the tests for `bugprone-exception-escape`


Modified:
clang-tools-extra/trunk/test/clang-tidy/bugprone-exception-escape.cpp

Modified: clang-tools-extra/trunk/test/clang-tidy/bugprone-exception-escape.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/bugprone-exception-escape.cpp?rev=35=34=35=diff
==
--- clang-tools-extra/trunk/test/clang-tidy/bugprone-exception-escape.cpp 
(original)
+++ clang-tools-extra/trunk/test/clang-tidy/bugprone-exception-escape.cpp Sat 
Oct 13 04:17:59 2018
@@ -263,21 +263,21 @@ void thrower(int n) {
 }
 
 int directly_recursive(int n) noexcept {
-  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in 
funcion 'directly_recursive' which should not throw exceptions
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in 
function 'directly_recursive' which should not throw exceptions
   if (n == 0)
 thrower(n);
   return directly_recursive(n);
 }
 
 int indirectly_recursive(int n) noexcept;
-// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in 
functin 'indirectly_recursive' which should not throw exceptions
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in 
function 'indirectly_recursive' which should not throw exceptions
 
 int recursion_helper(int n) {
   indirectly_recursive(n);
 }
 
 int indirectly_recursive(int n) noexcept {
-  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in 
funcion 'indirectly_recursive' which should not throw exceptions
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in 
function 'indirectly_recursive' which should not throw exceptions
   if (n == 0)
 thrower(n);
   return recursion_helper(n);


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


r344443 - [Analyzer] Iterator Checker - Part 10: Tests for iterators passed as parameter

2018-10-13 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Sat Oct 13 03:24:48 2018
New Revision: 33

URL: http://llvm.org/viewvc/llvm-project?rev=33=rev
Log:
[Analyzer] Iterator Checker - Part 10: Tests for iterators passed as parameter

In earlier Clang Static Analyzer versions `check::Bind() was not invoked for
parameter passing, so we needed a trick which is not needed anymore. However
add the tests to ensure its working.

Differential Revision: https::/reviews.llvm.org/D32906


Modified:
cfe/trunk/test/Analysis/iterator-range.cpp
cfe/trunk/test/Analysis/mismatched-iterator.cpp

Modified: cfe/trunk/test/Analysis/iterator-range.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/iterator-range.cpp?rev=33=32=33=diff
==
--- cfe/trunk/test/Analysis/iterator-range.cpp (original)
+++ cfe/trunk/test/Analysis/iterator-range.cpp Sat Oct 13 03:24:48 2018
@@ -97,6 +97,28 @@ void copy_and_increase3(const std::vecto
 *i2; // expected-warning{{Iterator accessed outside of its range}}
 }
 
+template 
+InputIterator nonStdFind(InputIterator first, InputIterator last,
+ const T ) {
+  for (auto i = first; i != last; ++i) {
+if (*i == val) {
+  return i;
+}
+  }
+  return last;
+}
+
+void good_non_std_find(std::vector , int e) {
+  auto first = nonStdFind(V.begin(), V.end(), e);
+  if (V.end() != first)
+*first; // no-warning
+}
+
+void bad_non_std_find(std::vector , int e) {
+  auto first = nonStdFind(V.begin(), V.end(), e);
+  *first; // expected-warning{{Iterator accessed outside of its range}}
+}
+
 void tricky(std::vector , int e) {
   const auto first = V.begin();
   const auto comp1 = (first != V.end()), comp2 = (first == V.end());

Modified: cfe/trunk/test/Analysis/mismatched-iterator.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/mismatched-iterator.cpp?rev=33=32=33=diff
==
--- cfe/trunk/test/Analysis/mismatched-iterator.cpp (original)
+++ cfe/trunk/test/Analysis/mismatched-iterator.cpp Sat Oct 13 03:24:48 2018
@@ -144,6 +144,19 @@ void bad_overwrite(std::vector ,
   v1.insert(i, n); // expected-warning{{Container accessed using foreign 
iterator argument}}
 }
 
+template
+bool is_cend(Container cont, Iterator it) {
+  return it == cont.cend();
+}
+
+void good_empty(std::vector ) {
+  is_cend(v, v.cbegin()); // no-warning
+}
+
+void bad_empty(std::vector , std::vector ) {
+  is_cend(v1, v2.cbegin()); // expected-warning@-8{{Iterators of different 
containers used where the same container is expected}}
+}
+
 void good_move(std::vector , std::vector ) {
   const auto i0 = ++v2.cbegin();
   v1 = std::move(v2);


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


[clang-tools-extra] r344444 - [clang-tidy] Optimize query in bugprone-exception-escape

2018-10-13 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Sat Oct 13 03:34:52 2018
New Revision: 34

URL: http://llvm.org/viewvc/llvm-project?rev=34=rev
Log:
[clang-tidy] Optimize query in bugprone-exception-escape

Checking whether a functions throws indirectly may be very expensive because it
needs to visit its whole call graph. Therefore we should first check whether the
function is forbidden to throw and only check whether it throws afterward. This
also seems to solve bug https://bugs.llvm.org/show_bug.cgi?id=39167 where the
execution time is so long that it seems to hang.

Differential Revision: https://reviews.llvm.org/D53187


Modified:
clang-tools-extra/trunk/clang-tidy/bugprone/ExceptionEscapeCheck.cpp
clang-tools-extra/trunk/docs/clang-tidy/checks/bugprone-exception-escape.rst
clang-tools-extra/trunk/test/clang-tidy/bugprone-exception-escape.cpp

Modified: clang-tools-extra/trunk/clang-tidy/bugprone/ExceptionEscapeCheck.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/bugprone/ExceptionEscapeCheck.cpp?rev=34=33=34=diff
==
--- clang-tools-extra/trunk/clang-tidy/bugprone/ExceptionEscapeCheck.cpp 
(original)
+++ clang-tools-extra/trunk/clang-tidy/bugprone/ExceptionEscapeCheck.cpp Sat 
Oct 13 03:34:52 2018
@@ -190,12 +190,12 @@ void ExceptionEscapeCheck::registerMatch
 return;
 
   Finder->addMatcher(
-  functionDecl(allOf(throws(unless(isIgnored(IgnoredExceptions))),
- anyOf(isNoThrow(), cxxDestructorDecl(),
+  functionDecl(allOf(anyOf(isNoThrow(), cxxDestructorDecl(),
cxxConstructorDecl(isMoveConstructor()),
cxxMethodDecl(isMoveAssignmentOperator()),
hasName("main"), hasName("swap"),
-   isEnabled(FunctionsThatShouldNotThrow
+   isEnabled(FunctionsThatShouldNotThrow)),
+ throws(unless(isIgnored(IgnoredExceptions)
   .bind("thrower"),
   this);
 }

Modified: 
clang-tools-extra/trunk/docs/clang-tidy/checks/bugprone-exception-escape.rst
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/bugprone-exception-escape.rst?rev=34=33=34=diff
==
--- 
clang-tools-extra/trunk/docs/clang-tidy/checks/bugprone-exception-escape.rst 
(original)
+++ 
clang-tools-extra/trunk/docs/clang-tidy/checks/bugprone-exception-escape.rst 
Sat Oct 13 03:34:52 2018
@@ -21,6 +21,8 @@ are always possible to implement in a no
 operations are also used to create move operations. A throwing ``main()``
 function also results in unexpected termination.
 
+WARNING! This check may be expensive on large source files.
+
 Options
 ---
 

Modified: clang-tools-extra/trunk/test/clang-tidy/bugprone-exception-escape.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/bugprone-exception-escape.cpp?rev=34=33=34=diff
==
--- clang-tools-extra/trunk/test/clang-tidy/bugprone-exception-escape.cpp 
(original)
+++ clang-tools-extra/trunk/test/clang-tidy/bugprone-exception-escape.cpp Sat 
Oct 13 03:34:52 2018
@@ -258,6 +258,31 @@ void this_counts(int n) noexcept {
   throw ignored1();
 }
 
+void thrower(int n) {
+  throw n;
+}
+
+int directly_recursive(int n) noexcept {
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in 
funcion 'directly_recursive' which should not throw exceptions
+  if (n == 0)
+thrower(n);
+  return directly_recursive(n);
+}
+
+int indirectly_recursive(int n) noexcept;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in 
functin 'indirectly_recursive' which should not throw exceptions
+
+int recursion_helper(int n) {
+  indirectly_recursive(n);
+}
+
+int indirectly_recursive(int n) noexcept {
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in 
funcion 'indirectly_recursive' which should not throw exceptions
+  if (n == 0)
+thrower(n);
+  return recursion_helper(n);
+}
+
 int main() {
   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in 
function 'main' which should not throw exceptions
   throw 1;


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


[clang-tools-extra] r344340 - [clang-tidy] White List Option for performance-unnecessary-value-param, performance-unnecessary-copy-initialization and performance-for-range-copy

2018-10-12 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Fri Oct 12 06:05:21 2018
New Revision: 344340

URL: http://llvm.org/viewvc/llvm-project?rev=344340=rev
Log:
[clang-tidy] White List Option for performance-unnecessary-value-param, 
performance-unnecessary-copy-initialization and performance-for-range-copy

New option added to these three checks to be able to silence false positives on
types that are intentionally passed by value or copied. Such types are e.g.
intrusive reference counting pointer types like llvm::IntrusiveRefCntPtr. The
new option is named WhiteListTypes and can contain a semicolon-separated list of
names of these types. Regular expressions are allowed. Default is empty.

Differential Revision: https://reviews.llvm.org/D52727


Added:

clang-tools-extra/trunk/test/clang-tidy/performance-for-range-copy-allowed-types.cpp

clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-copy-initialization-allowed-types.cpp

clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param-allowed-types.cpp
Modified:
clang-tools-extra/trunk/clang-tidy/performance/ForRangeCopyCheck.cpp
clang-tools-extra/trunk/clang-tidy/performance/ForRangeCopyCheck.h

clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryCopyInitialization.cpp

clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryCopyInitialization.h

clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp
clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.h
clang-tools-extra/trunk/clang-tidy/utils/Matchers.h

clang-tools-extra/trunk/docs/clang-tidy/checks/performance-for-range-copy.rst

clang-tools-extra/trunk/docs/clang-tidy/checks/performance-unnecessary-copy-initialization.rst

clang-tools-extra/trunk/docs/clang-tidy/checks/performance-unnecessary-value-param.rst

Modified: clang-tools-extra/trunk/clang-tidy/performance/ForRangeCopyCheck.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/performance/ForRangeCopyCheck.cpp?rev=344340=344339=344340=diff
==
--- clang-tools-extra/trunk/clang-tidy/performance/ForRangeCopyCheck.cpp 
(original)
+++ clang-tools-extra/trunk/clang-tidy/performance/ForRangeCopyCheck.cpp Fri 
Oct 12 06:05:21 2018
@@ -10,6 +10,8 @@
 #include "ForRangeCopyCheck.h"
 #include "../utils/DeclRefExprUtils.h"
 #include "../utils/FixItHintUtils.h"
+#include "../utils/Matchers.h"
+#include "../utils/OptionsUtils.h"
 #include "../utils/TypeTraits.h"
 #include "clang/Analysis/Analyses/ExprMutationAnalyzer.h"
 
@@ -21,10 +23,14 @@ namespace performance {
 
 ForRangeCopyCheck::ForRangeCopyCheck(StringRef Name, ClangTidyContext *Context)
 : ClangTidyCheck(Name, Context),
-  WarnOnAllAutoCopies(Options.get("WarnOnAllAutoCopies", 0)) {}
+  WarnOnAllAutoCopies(Options.get("WarnOnAllAutoCopies", 0)),
+  AllowedTypes(
+  utils::options::parseStringList(Options.get("AllowedTypes", ""))) {}
 
 void ForRangeCopyCheck::storeOptions(ClangTidyOptions::OptionMap ) {
   Options.store(Opts, "WarnOnAllAutoCopies", WarnOnAllAutoCopies);
+  Options.store(Opts, "AllowedTypes",
+utils::options::serializeStringList(AllowedTypes));
 }
 
 void ForRangeCopyCheck::registerMatchers(MatchFinder *Finder) {
@@ -32,7 +38,10 @@ void ForRangeCopyCheck::registerMatchers
   // initialized through MaterializeTemporaryExpr which indicates a type
   // conversion.
   auto LoopVar = varDecl(
-  hasType(hasCanonicalType(unless(anyOf(referenceType(), pointerType(),
+  hasType(qualType(
+  unless(anyOf(hasCanonicalType(anyOf(referenceType(), pointerType())),
+   hasDeclaration(namedDecl(
+   matchers::matchesAnyListedName(AllowedTypes))),
   unless(hasInitializer(expr(hasDescendant(materializeTemporaryExpr());
   Finder->addMatcher(cxxForRangeStmt(hasLoopVariable(LoopVar.bind("loopVar")))
  .bind("forRange"),
@@ -41,6 +50,7 @@ void ForRangeCopyCheck::registerMatchers
 
 void ForRangeCopyCheck::check(const MatchFinder::MatchResult ) {
   const auto *Var = Result.Nodes.getNodeAs("loopVar");
+
   // Ignore code in macros since we can't place the fixes correctly.
   if (Var->getBeginLoc().isMacroID())
 return;

Modified: clang-tools-extra/trunk/clang-tidy/performance/ForRangeCopyCheck.h
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/performance/ForRangeCopyCheck.h?rev=344340=344339=344340=diff
==
--- clang-tools-extra/trunk/clang-tidy/performance/ForRangeCopyCheck.h 
(original)
+++ clang-tools-extra/trunk/clang-tidy/performance/ForRangeCopyCheck.h Fri Oct 
12 06:05:21 2018
@@ -40,6 +40,7 @@ private:
ASTContext );
 
   const bool WarnOnAllAutoCopies;
+  const std::vector AllowedTypes;
 };
 
 } 

r351746 - [Analyzer] Remove extra blank line from Iterator Checker (test commit)

2019-01-21 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Mon Jan 21 07:31:23 2019
New Revision: 351746

URL: http://llvm.org/viewvc/llvm-project?rev=351746=rev
Log:
[Analyzer] Remove extra blank line from Iterator Checker (test commit)


Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp?rev=351746=351745=351746=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp Mon Jan 21 
07:31:23 2019
@@ -2378,7 +2378,6 @@ bool compare(ProgramStateRef State, Symb
   return compare(State, nonloc::SymbolVal(Sym1), nonloc::SymbolVal(Sym2), Opc);
 }
 
-
 bool compare(ProgramStateRef State, NonLoc NL1, NonLoc NL2,
  BinaryOperator::Opcode Opc) {
   auto  = State->getStateManager().getSValBuilder();


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


r348245 - [Analyzer] Iterator Checker - Forbid decrements past the begin() and increments past the end() of containers

2018-12-04 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Tue Dec  4 02:27:27 2018
New Revision: 348245

URL: http://llvm.org/viewvc/llvm-project?rev=348245=rev
Log:
[Analyzer] Iterator Checker - Forbid decrements past the begin() and increments 
past the end() of containers

Previously, the iterator range checker only warned upon dereferencing of
iterators outside their valid range as well as increments and decrements of
out-of-range iterators where the result remains out-of-range. However, the C++
standard is more strict than this: decrementing begin() or incrementing end()
results in undefined behaviour even if the iterator is not dereferenced
afterwards. Coming back to the range once out-of-range is also undefined.

This patch corrects the behaviour of the iterator range checker: warnings are
given for any operation whose result is ahead of begin() or past the end()
(which is the past-end iterator itself, thus now we are speaking of past
past-the-end).

Differential Revision: https://reviews.llvm.org/D53812


Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
cfe/trunk/test/Analysis/iterator-range.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp?rev=348245=348244=348245=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp Tue Dec  4 
02:27:27 2018
@@ -238,14 +238,17 @@ class IteratorChecker
   void handleEraseAfter(CheckerContext , const SVal ) const;
   void handleEraseAfter(CheckerContext , const SVal ,
 const SVal ) const;
+  void verifyIncrement(CheckerContext , const SVal ) const;
+  void verifyDecrement(CheckerContext , const SVal ) const;
   void verifyRandomIncrOrDecr(CheckerContext , OverloadedOperatorKind Op,
-  const SVal , const SVal ,
-  const SVal ) const;
+  const SVal , const SVal ) const;
   void verifyMatch(CheckerContext , const SVal ,
const MemRegion *Cont) const;
   void verifyMatch(CheckerContext , const SVal ,
const SVal ) const;
-
+  IteratorPosition advancePosition(CheckerContext , OverloadedOperatorKind 
Op,
+   const IteratorPosition ,
+   const SVal ) const;
   void reportOutOfRangeBug(const StringRef , const SVal ,
CheckerContext , ExplodedNode *ErrNode) const;
   void reportMismatchedBug(const StringRef , const SVal ,
@@ -388,7 +391,9 @@ ProgramStateRef setContainerData(Program
 bool hasLiveIterators(ProgramStateRef State, const MemRegion *Cont);
 bool isBoundThroughLazyCompoundVal(const Environment ,
const MemRegion *Reg);
-bool isOutOfRange(ProgramStateRef State, const IteratorPosition );
+bool isPastTheEnd(ProgramStateRef State, const IteratorPosition );
+bool isAheadOfRange(ProgramStateRef State, const IteratorPosition );
+bool isBehindPastTheEnd(ProgramStateRef State, const IteratorPosition );
 bool isZero(ProgramStateRef State, const NonLoc );
 } // namespace
 
@@ -422,29 +427,46 @@ void IteratorChecker::checkPreCall(const
 verifyAccess(C, Call.getArgSVal(0));
   }
 }
-if (ChecksEnabled[CK_IteratorRangeChecker] &&
-isRandomIncrOrDecrOperator(Func->getOverloadedOperator())) {
-  if (const auto *InstCall = dyn_cast()) {
-// Check for out-of-range incrementions and decrementions
-if (Call.getNumArgs() >= 1) {
-  verifyRandomIncrOrDecr(C, Func->getOverloadedOperator(),
- Call.getReturnValue(),
- InstCall->getCXXThisVal(), 
Call.getArgSVal(0));
+if (ChecksEnabled[CK_IteratorRangeChecker]) {
+  if (isIncrementOperator(Func->getOverloadedOperator())) {
+// Check for out-of-range incrementions
+if (const auto *InstCall = dyn_cast()) {
+  verifyIncrement(C, InstCall->getCXXThisVal());
+} else {
+  if (Call.getNumArgs() >= 1) {
+verifyIncrement(C, Call.getArgSVal(0));
+  }
 }
-  } else {
-if (Call.getNumArgs() >= 2) {
-  verifyRandomIncrOrDecr(C, Func->getOverloadedOperator(),
- Call.getReturnValue(), Call.getArgSVal(0),
- Call.getArgSVal(1));
+  } else if (isDecrementOperator(Func->getOverloadedOperator())) {
+// Check for out-of-range decrementions
+if (const auto *InstCall = dyn_cast()) {
+  verifyDecrement(C, InstCall->getCXXThisVal());
+} else {
+  if (Call.getNumArgs() >= 1) {
+verifyDecrement(C, Call.getArgSVal(0));
+  }
+}
+  } else if 

r348244 - [Analyzer] Iterator Checkers - Use the region of the topmost base class for iterators stored in a region

2018-12-04 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Tue Dec  4 02:22:28 2018
New Revision: 348244

URL: http://llvm.org/viewvc/llvm-project?rev=348244=rev
Log:
[Analyzer] Iterator Checkers - Use the region of the topmost base class for 
iterators stored in a region

If an iterator is represented by a derived C++ class but its comparison operator
is for its base the iterator checkers cannot recognize the iterators compared.
This results in false positives in very straightforward cases (range error when
dereferencing an iterator after disclosing that it is equal to the past-the-end
iterator).

To overcome this problem we always use the region of the topmost base class for
iterators stored in a region. A new method called getMostDerivedObjectRegion()
was added to the MemRegion class to get this region.

Differential Revision: https://reviews.llvm.org/D54466


Modified:
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp
cfe/trunk/test/Analysis/iterator-range.cpp

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h?rev=348244=348243=348244=diff
==
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h 
(original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h Tue 
Dec  4 02:22:28 2018
@@ -118,6 +118,10 @@ public:
 
   const MemRegion *getBaseRegion() const;
 
+  /// Recursively retrieve the region of the most derived class instance of
+  /// regions of C++ base class instances.
+  const MemRegion *getMostDerivedObjectRegion() const;
+
   /// Check if the region is a subregion of the given region.
   /// Each region is a subregion of itself.
   virtual bool isSubRegionOf(const MemRegion *R) const;

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp?rev=348244=348243=348244=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp Tue Dec  4 
02:22:28 2018
@@ -1089,9 +1089,7 @@ void IteratorChecker::verifyRandomIncrOr
 void IteratorChecker::verifyMatch(CheckerContext , const SVal ,
   const MemRegion *Cont) const {
   // Verify match between a container and the container of an iterator
-  while (const auto *CBOR = Cont->getAs()) {
-Cont = CBOR->getSuperRegion();
-  }
+  Cont = Cont->getMostDerivedObjectRegion();
 
   auto State = C.getState();
   const auto *Pos = getIteratorPosition(State, Iter);
@@ -1125,9 +1123,7 @@ void IteratorChecker::handleBegin(Checke
   if (!ContReg)
 return;
 
-  while (const auto *CBOR = ContReg->getAs()) {
-ContReg = CBOR->getSuperRegion();
-  }
+  ContReg = ContReg->getMostDerivedObjectRegion();
 
   // If the container already has a begin symbol then use it. Otherwise first
   // create a new one.
@@ -1151,9 +1147,7 @@ void IteratorChecker::handleEnd(CheckerC
   if (!ContReg)
 return;
 
-  while (const auto *CBOR = ContReg->getAs()) {
-ContReg = CBOR->getSuperRegion();
-  }
+  ContReg = ContReg->getMostDerivedObjectRegion();
 
   // If the container already has an end symbol then use it. Otherwise first
   // create a new one.
@@ -1174,9 +1168,7 @@ void IteratorChecker::handleEnd(CheckerC
 void IteratorChecker::assignToContainer(CheckerContext , const Expr *CE,
 const SVal ,
 const MemRegion *Cont) const {
-  while (const auto *CBOR = Cont->getAs()) {
-Cont = CBOR->getSuperRegion();
-  }
+  Cont = Cont->getMostDerivedObjectRegion();
 
   auto State = C.getState();
   auto  = C.getSymbolManager();
@@ -1194,9 +1186,7 @@ void IteratorChecker::handleAssign(Check
   if (!ContReg)
 return;
 
-  while (const auto *CBOR = ContReg->getAs()) {
-ContReg = CBOR->getSuperRegion();
-  }
+  ContReg = ContReg->getMostDerivedObjectRegion();
 
   // Assignment of a new value to a container always invalidates all its
   // iterators
@@ -1211,9 +1201,7 @@ void IteratorChecker::handleAssign(Check
   if (!OldCont.isUndef()) {
 const auto *OldContReg = OldCont.getAsRegion();
 if (OldContReg) {
-  while (const auto *CBOR = OldContReg->getAs()) {
-OldContReg = CBOR->getSuperRegion();
-  }
+  OldContReg = OldContReg->getMostDerivedObjectRegion();
   const auto OldCData = getContainerData(State, OldContReg);
   if (OldCData) {
 if (const auto OldEndSym = OldCData->getEnd()) {
@@ -1273,9 +1261,7 @@ void IteratorChecker::handleClear(Checke
   if (!ContReg)
 return;
 
-  

r347981 - lyzer] [HOTFIX!] SValBuilder crash when `aggressive-binary-operation-simplification` enabled

2018-11-30 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Fri Nov 30 02:37:44 2018
New Revision: 347981

URL: http://llvm.org/viewvc/llvm-project?rev=347981=rev
Log:
lyzer] [HOTFIX!] SValBuilder crash when 
`aggressive-binary-operation-simplification` enabled

During the review of D41938 a condition check with an early exit accidentally
slipped into a branch, leaving the other branch unprotected. This may result in
an assertion later on. This hotfix moves this contition check outside of the
branch.

Differential Revision: https://reviews.llvm.org/D55051


Modified:
cfe/trunk/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
cfe/trunk/test/Analysis/svalbuilder-rearrange-comparisons.c

Modified: cfe/trunk/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp?rev=347981=347980=347981=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp Fri Nov 30 02:37:44 
2018
@@ -475,9 +475,6 @@ static Optional tryRearrange(Pro
 SingleTy = ResultTy;
 if (LSym->getType() != SingleTy)
   return None;
-// Substracting unsigned integers is a nightmare.
-if (!SingleTy->isSignedIntegerOrEnumerationType())
-  return None;
   } else {
 // Don't rearrange other operations.
 return None;
@@ -485,6 +482,10 @@ static Optional tryRearrange(Pro
 
   assert(!SingleTy.isNull() && "We should have figured out the type by now!");
 
+  // Rearrange signed symbolic expressions only
+  if (!SingleTy->isSignedIntegerOrEnumerationType())
+return None;
+
   SymbolRef RSym = Rhs.getAsSymbol();
   if (!RSym || RSym->getType() != SingleTy)
 return None;

Modified: cfe/trunk/test/Analysis/svalbuilder-rearrange-comparisons.c
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/svalbuilder-rearrange-comparisons.c?rev=347981=347980=347981=diff
==
--- cfe/trunk/test/Analysis/svalbuilder-rearrange-comparisons.c (original)
+++ cfe/trunk/test/Analysis/svalbuilder-rearrange-comparisons.c Fri Nov 30 
02:37:44 2018
@@ -979,3 +979,20 @@ int mixed_integer_types(int x, int y) {
   short a = x - 1U;
   return a - y;
 }
+
+unsigned gu();
+unsigned fu() {
+  unsigned x = gu();
+  // Assert that no overflows occur in this test file.
+  // Assuming that concrete integers are also within that range.
+  assert(x <= ((unsigned)UINT_MAX / 4));
+  return x;
+}
+
+void unsigned_concrete_int_no_crash() {
+  unsigned x = fu() + 1U, y = fu() + 1U;
+  clang_analyzer_denote(x - 1U, "$x");
+  clang_analyzer_denote(y - 1U, "$y");
+  clang_analyzer_express(y); // expected-warning {{$y}}
+  clang_analyzer_express(x == y); // expected-warning {{$x + 1U == $y + 1U}}
+}


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


r357167 - [Analyzer] Constraint Manager - Calculate Effective Range for Differences

2019-03-28 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Thu Mar 28 06:05:59 2019
New Revision: 357167

URL: http://llvm.org/viewvc/llvm-project?rev=357167=rev
Log:
[Analyzer] Constraint Manager - Calculate Effective Range for Differences

Since rL335814, if the constraint manager cannot find a range set for `A - B`
(where `A` and `B` are symbols) it looks for a range for `B - A` and returns
it negated if it exists. However, if a range set for both `A - B` and `B - A`
is stored then it only returns the first one. If we both use `A - B` and
`B - A`, these expressions behave as two totally unrelated symbols. This way
we miss some useful deductions which may lead to false negatives or false
positives.

This tiny patch changes this behavior: if the symbolic expression the
constraint manager is looking for is a difference `A - B`, it tries to
retrieve the range for both `A - B` and `B - A` and if both exists it returns
the intersection of range `A - B` and the negated range of `B - A`. This way
every time a checker applies new constraints to the symbolic difference or to
its negated it always affects both the original difference and its negated.

Differential Revision: https://reviews.llvm.org/D55007


Modified:

cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h
cfe/trunk/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
cfe/trunk/test/Analysis/constraint_manager_negate_difference.c

Modified: 
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h?rev=357167=357166=357167=diff
==
--- 
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h
 (original)
+++ 
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h
 Thu Mar 28 06:05:59 2019
@@ -113,7 +113,8 @@ private:
 public:
   RangeSet Intersect(BasicValueFactory , Factory , llvm::APSInt Lower,
  llvm::APSInt Upper) const;
-
+  RangeSet Intersect(BasicValueFactory , Factory ,
+ const RangeSet ) const;
   RangeSet Negate(BasicValueFactory , Factory ) const;
 
   void print(raw_ostream ) const;

Modified: cfe/trunk/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp?rev=357167=357166=357167=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp Thu Mar 28 
06:05:59 2019
@@ -173,6 +173,22 @@ RangeSet RangeSet::Intersect(BasicValueF
   return newRanges;
 }
 
+// Returns a set containing the values in the receiving set, intersected with
+// the range set passed as parameter.
+RangeSet RangeSet::Intersect(BasicValueFactory , Factory ,
+ const RangeSet ) const {
+  PrimRangeSet newRanges = F.getEmptySet();
+
+  for (iterator i = Other.begin(), e = Other.end(); i != e; ++i) {
+RangeSet newPiece = Intersect(BV, F, i->From(), i->To());
+for (iterator j = newPiece.begin(), ee = newPiece.end(); j != ee; ++j) {
+  newRanges = F.add(newRanges, *j);
+}
+  }
+
+  return newRanges;
+}
+
 // Turn all [A, B] ranges to [-B, -A]. Ranges [MIN, B] are turned to range set
 // [MIN, MIN] U [-B, MAX], when MIN and MAX are the minimal and the maximal
 // signed values of the type.
@@ -461,14 +477,21 @@ static RangeSet applyBitwiseConstraints(
 
 RangeSet RangeConstraintManager::getRange(ProgramStateRef State,
   SymbolRef Sym) {
-  if (ConstraintRangeTy::data_type *V = State->get(Sym))
-return *V;
-
-  BasicValueFactory  = getBasicVals();
+  ConstraintRangeTy::data_type *V = State->get(Sym);
 
   // If Sym is a difference of symbols A - B, then maybe we have range set
   // stored for B - A.
-  if (const RangeSet *R = getRangeForMinusSymbol(State, Sym))
+  BasicValueFactory  = getBasicVals();
+  const RangeSet *R = getRangeForMinusSymbol(State, Sym);
+
+  // If we have range set stored for both A - B and B - A then calculate the
+  // effective range set by intersecting the range set for A - B and the
+  // negated range set of B - A.
+  if (V && R)
+return V->Intersect(BV, F, R->Negate(BV, F));
+  if (V)
+return *V;
+  if (R)
 return R->Negate(BV, F);
 
   // Lazily generate a new RangeSet representing all possible values for the

Modified: cfe/trunk/test/Analysis/constraint_manager_negate_difference.c
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/constraint_manager_negate_difference.c?rev=357167=357166=357167=diff
==
--- 

r356049 - [Analyzer] Skip symbolic regions based on conjured symbols in comparison of the containers of iterators

2019-03-13 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Wed Mar 13 06:55:11 2019
New Revision: 356049

URL: http://llvm.org/viewvc/llvm-project?rev=356049=rev
Log:
[Analyzer] Skip symbolic regions based on conjured symbols in comparison of the 
containers of iterators

Checking whether two regions are the same is a partially decidable problem:
either we know for sure that they are the same or we cannot decide. A typical
case for this are the symbolic regions based on conjured symbols. Two
different conjured symbols are either the same or they are different. Since
we cannot decide this and want to reduce false positives as much as possible
we exclude these regions whenever checking whether two containers are the
same at iterator mismatch check.

Differential Revision: https://reviews.llvm.org/D53754


Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
cfe/trunk/test/Analysis/mismatched-iterator.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp?rev=356049=356048=356049=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp Wed Mar 13 
06:55:11 2019
@@ -1098,14 +1098,34 @@ void IteratorChecker::verifyMatch(Checke
   // Verify match between a container and the container of an iterator
   Cont = Cont->getMostDerivedObjectRegion();
 
+  if (const auto *ContSym = Cont->getSymbolicBase()) {
+if (isa(ContSym->getSymbol()))
+  return;
+  }
+
   auto State = C.getState();
   const auto *Pos = getIteratorPosition(State, Iter);
-  if (Pos && Pos->getContainer() != Cont) {
+  if (!Pos)
+return;
+
+  const auto *IterCont = Pos->getContainer();
+
+  // Skip symbolic regions based on conjured symbols. Two conjured symbols
+  // may or may not be the same. For example, the same function can return
+  // the same or a different container but we get different conjured symbols
+  // for each call. This may cause false positives so omit them from the check.
+  if (const auto *ContSym = IterCont->getSymbolicBase()) {
+if (isa(ContSym->getSymbol()))
+  return;
+  }
+
+  if (IterCont != Cont) {
 auto *N = C.generateNonFatalErrorNode(State);
 if (!N) {
   return;
 }
-reportMismatchedBug("Container accessed using foreign iterator argument.", 
Iter, Cont, C, N);
+reportMismatchedBug("Container accessed using foreign iterator argument.",
+Iter, Cont, C, N);
   }
 }
 
@@ -1114,8 +1134,31 @@ void IteratorChecker::verifyMatch(Checke
   // Verify match between the containers of two iterators
   auto State = C.getState();
   const auto *Pos1 = getIteratorPosition(State, Iter1);
+  if (!Pos1)
+return;
+
+  const auto *IterCont1 = Pos1->getContainer();
+
+  // Skip symbolic regions based on conjured symbols. Two conjured symbols
+  // may or may not be the same. For example, the same function can return
+  // the same or a different container but we get different conjured symbols
+  // for each call. This may cause false positives so omit them from the check.
+  if (const auto *ContSym = IterCont1->getSymbolicBase()) {
+if (isa(ContSym->getSymbol()))
+  return;
+  }
+
   const auto *Pos2 = getIteratorPosition(State, Iter2);
-  if (Pos1 && Pos2 && Pos1->getContainer() != Pos2->getContainer()) {
+  if (!Pos2)
+return;
+
+  const auto *IterCont2 = Pos2->getContainer();
+  if (const auto *ContSym = IterCont2->getSymbolicBase()) {
+if (isa(ContSym->getSymbol()))
+  return;
+  }
+
+  if (IterCont1 != IterCont2) {
 auto *N = C.generateNonFatalErrorNode(State);
 if (!N)
   return;

Modified: cfe/trunk/test/Analysis/mismatched-iterator.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/mismatched-iterator.cpp?rev=356049=356048=356049=diff
==
--- cfe/trunk/test/Analysis/mismatched-iterator.cpp (original)
+++ cfe/trunk/test/Analysis/mismatched-iterator.cpp Wed Mar 13 06:55:11 2019
@@ -189,3 +189,17 @@ void bad_comparison(std::vector 
 *v1.cbegin();
   }
 }
+
+std::vector _vector_ref();
+
+void ignore_conjured1() {
+  std::vector  = return_vector_ref(),  = return_vector_ref();
+
+  v2.erase(v1.cbegin()); // no-warning
+}
+
+void ignore_conjured2() {
+  std::vector  = return_vector_ref(),  = return_vector_ref();
+
+  if (v1.cbegin() == v2.cbegin()) {} //no-warning
+}


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


r353943 - [Analyzer] Crash fix for FindLastStoreBRVisitor

2019-02-13 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Wed Feb 13 04:25:47 2019
New Revision: 353943

URL: http://llvm.org/viewvc/llvm-project?rev=353943=rev
Log:
[Analyzer] Crash fix for FindLastStoreBRVisitor

FindLastStoreBRVisitor tries to find the first node in the exploded graph where
the current value was assigned to a region. This node is called the "store
site". It is identified by a pair of Pred and Succ nodes where Succ already has
the binding for the value while Pred does not have it. However the visitor
mistakenly identifies a node pair as the store site where the value is a
`LazyCompoundVal` and `Pred` does not have a store yet but `Succ` has it. In
this case the `LazyCompoundVal` is different in the `Pred` node because it also
contains the store which is different in the two nodes. This error may lead to
crashes (a declaration is cast to a parameter declaration without check) or
misleading bug path notes.

In this patch we fix this problem by checking for unequal `LazyCompoundVals`: if
their region is equal, and their store is the same as the store of their nodes
we consider them as equal when looking for the "store site". This is an
approximation because we do not check for differences of the subvalues
(structure members or array elements) in the stores.

Differential Revision: https://reviews.llvm.org/D58067


Added:
cfe/trunk/test/Analysis/PR40625.cpp
Modified:
cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
cfe/trunk/test/Analysis/uninit-vals.m

Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp?rev=353943=353942=353943=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp Wed Feb 13 
04:25:47 2019
@@ -153,6 +153,32 @@ const Expr *bugreporter::getDerefExpr(co
   return E;
 }
 
+/// Comparing internal representations of symbolic values (via
+/// SVal::operator==()) is a valid way to check if the value was updated,
+/// unless it's a LazyCompoundVal that may have a different internal
+/// representation every time it is loaded from the state. In this function we
+/// do an approximate comparison for lazy compound values, checking that they
+/// are the immediate snapshots of the tracked region's bindings within the
+/// node's respective states but not really checking that these snapshots
+/// actually contain the same set of bindings.
+bool hasVisibleUpdate(const ExplodedNode *LeftNode, SVal LeftVal,
+  const ExplodedNode *RightNode, SVal RightVal) {
+  if (LeftVal == RightVal)
+return true;
+
+  const auto LLCV = LeftVal.getAs();
+  if (!LLCV)
+return false;
+
+  const auto RLCV = RightVal.getAs();
+  if (!RLCV)
+return false;
+
+  return LLCV->getRegion() == RLCV->getRegion() &&
+LLCV->getStore() == LeftNode->getState()->getStore() &&
+RLCV->getStore() == RightNode->getState()->getStore();
+}
+
 
//===--===//
 // Definitions for bug reporter visitors.
 
//===--===//
@@ -1177,7 +1203,7 @@ FindLastStoreBRVisitor::VisitNode(const
 if (Succ->getState()->getSVal(R) != V)
   return nullptr;
 
-if (Pred->getState()->getSVal(R) == V) {
+if (hasVisibleUpdate(Pred, Pred->getState()->getSVal(R), Succ, V)) {
   Optional PS = Succ->getLocationAs();
   if (!PS || PS->getLocationValue() != R)
 return nullptr;
@@ -1198,6 +1224,7 @@ FindLastStoreBRVisitor::VisitNode(const
 // UndefinedVal.)
 if (Optional CE = Succ->getLocationAs()) {
   if (const auto *VR = dyn_cast(R)) {
+
 const auto *Param = cast(VR->getDecl());
 
 ProgramStateManager  = BRC.getStateManager();

Added: cfe/trunk/test/Analysis/PR40625.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/PR40625.cpp?rev=353943=auto
==
--- cfe/trunk/test/Analysis/PR40625.cpp (added)
+++ cfe/trunk/test/Analysis/PR40625.cpp Wed Feb 13 04:25:47 2019
@@ -0,0 +1,16 @@
+// RUN: %clang_analyze_cc1 -std=c++11 
-analyzer-checker=core,alpha.core.CallAndMessageUnInitRefArg  %s -verify
+
+void f(const int *end);
+
+void g(const int ()[10]) {
+  f(arrr+sizeof(arrr)); // expected-warning{{1st function call argument is a 
pointer to uninitialized value}}
+  // FIXME: This is a false positive that should be fixed. Until then this
+  //tests the crash fix in FindLastStoreBRVisitor (beside
+  //uninit-vals.m).
+}
+
+void h() {
+  int arr[10];
+
+  g(arr);
+}

Modified: cfe/trunk/test/Analysis/uninit-vals.m
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/uninit-vals.m?rev=353943=353942=353943=diff

r354127 - [Analyzer] Fix for test file of bug 40625

2019-02-15 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Fri Feb 15 04:33:42 2019
New Revision: 354127

URL: http://llvm.org/viewvc/llvm-project?rev=354127=rev
Log:
[Analyzer] Fix for test file of bug 40625

Test fixed and changed to true positive, FIXME about false positive removed.


Modified:
cfe/trunk/test/Analysis/PR40625.cpp

Modified: cfe/trunk/test/Analysis/PR40625.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/PR40625.cpp?rev=354127=354126=354127=diff
==
--- cfe/trunk/test/Analysis/PR40625.cpp (original)
+++ cfe/trunk/test/Analysis/PR40625.cpp Fri Feb 15 04:33:42 2019
@@ -3,10 +3,7 @@
 void f(const int *end);
 
 void g(const int ()[10]) {
-  f(arrr+sizeof(arrr)); // expected-warning{{1st function call argument is a 
pointer to uninitialized value}}
-  // FIXME: This is a false positive that should be fixed. Until then this
-  //tests the crash fix in FindLastStoreBRVisitor (beside
-  //uninit-vals.m).
+  f(arrr); // expected-warning{{1st function call argument is a pointer to 
uninitialized value}}
 }
 
 void h() {


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


r361818 - [Analyzer] Replace `CXXSelfAssignmentBRVisitor` with `NoteTags`

2019-05-28 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Tue May 28 06:07:09 2019
New Revision: 361818

URL: http://llvm.org/viewvc/llvm-project?rev=361818=rev
Log:
[Analyzer] Replace `CXXSelfAssignmentBRVisitor` with `NoteTags`

The `cplusplus.SelfAssignment` checker has a visitor that is added
to every `BugReport` to mark the to branch of the self assignment
operator with e.g. `rhs == *this` and `rhs != *this`. With the new
`NoteTag` feature this visitor is not needed anymore. Instead the
checker itself marks the two branches using the `NoteTag`s.

Differential Revision: https://reviews.llvm.org/D62479


Modified:

cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h
cfe/trunk/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp
cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp
cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp

Modified: 
cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h?rev=361818=361817=361818=diff
==
--- 
cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h 
(original)
+++ 
cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h 
Tue May 28 06:07:09 2019
@@ -294,20 +294,6 @@ public:
  BugReport ) override;
 };
 
-class CXXSelfAssignmentBRVisitor final : public BugReporterVisitor {
-  bool Satisfied = false;
-
-public:
-  CXXSelfAssignmentBRVisitor() = default;
-
-  void Profile(llvm::FoldingSetNodeID ) const override {}
-
-  std::shared_ptr VisitNode(const ExplodedNode *Succ,
- BugReporterContext ,
- BugReport ) override;
-};
-
-
 /// The bug visitor will walk all the nodes in a path and collect all the
 /// constraints. When it reaches the root node, will create a refutation
 /// manager and check if the constraints are satisfiable

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp?rev=361818=361817=361818=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp 
(original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp Tue May 
28 06:07:09 2019
@@ -50,10 +50,26 @@ void CXXSelfAssignmentChecker::checkBegi
   State->getSVal(SVB.getCXXThis(MD, LCtx->getStackFrame()));
   auto Param = SVB.makeLoc(State->getRegion(MD->getParamDecl(0), LCtx));
   auto ParamVal = State->getSVal(Param);
+
   ProgramStateRef SelfAssignState = State->bindLoc(Param, ThisVal, LCtx);
-  C.addTransition(SelfAssignState);
+  const NoteTag *SelfAssignTag =
+C.getNoteTag([MD](BugReport ) -> std::string {
+SmallString<256> Msg;
+llvm::raw_svector_ostream Out(Msg);
+Out << "Assuming " << MD->getParamDecl(0)->getName() << " == *this";
+return Out.str();
+  });
+  C.addTransition(SelfAssignState, SelfAssignTag);
+
   ProgramStateRef NonSelfAssignState = State->bindLoc(Param, ParamVal, LCtx);
-  C.addTransition(NonSelfAssignState);
+  const NoteTag *NonSelfAssignTag =
+C.getNoteTag([MD](BugReport ) -> std::string {
+SmallString<256> Msg;
+llvm::raw_svector_ostream Out(Msg);
+Out << "Assuming " << MD->getParamDecl(0)->getName() << " != *this";
+return Out.str();
+  });
+  C.addTransition(NonSelfAssignState, NonSelfAssignTag);
 }
 
 void ento::registerCXXSelfAssignmentChecker(CheckerManager ) {

Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp?rev=361818=361817=361818=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp Tue May 28 06:07:09 2019
@@ -2610,7 +2610,6 @@ std::pairaddVisitor(llvm::make_unique());
 R->addVisitor(llvm::make_unique());
-R->addVisitor(llvm::make_unique());
 R->addVisitor(llvm::make_unique());
 
 BugReporterContext BRC(Reporter, ErrorGraph.BackMap);

Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp?rev=361818=361817=361818=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp Tue May 28 
06:07:09 2019
@@ -2371,59 +2371,6 @@ 

[clang-tools-extra] r361225 - [clang-tidy] New option for misc-throw-by-value-catch-by-reference

2019-05-21 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Tue May 21 00:25:06 2019
New Revision: 361225

URL: http://llvm.org/viewvc/llvm-project?rev=361225=rev
Log:
[clang-tidy] New option for misc-throw-by-value-catch-by-reference

Catching trivial objects by value is not dangerous but may be
inefficient if they are too large. This patch adds an option
`WarnOnLargeObject` to the checker to also warn if such an object
is caught by value. An object is considered as "large" if its
size is greater than `MaxSize` which is another option. Default
value is the machine word of the architecture (size of the type
`size_t`).

Differential Revision: https://reviews.llvm.org/D61851


Modified:

clang-tools-extra/trunk/clang-tidy/misc/ThrowByValueCatchByReferenceCheck.cpp
clang-tools-extra/trunk/clang-tidy/misc/ThrowByValueCatchByReferenceCheck.h
clang-tools-extra/trunk/docs/ReleaseNotes.rst

clang-tools-extra/trunk/docs/clang-tidy/checks/misc-throw-by-value-catch-by-reference.rst

Modified: 
clang-tools-extra/trunk/clang-tidy/misc/ThrowByValueCatchByReferenceCheck.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/misc/ThrowByValueCatchByReferenceCheck.cpp?rev=361225=361224=361225=diff
==
--- 
clang-tools-extra/trunk/clang-tidy/misc/ThrowByValueCatchByReferenceCheck.cpp 
(original)
+++ 
clang-tools-extra/trunk/clang-tidy/misc/ThrowByValueCatchByReferenceCheck.cpp 
Tue May 21 00:25:06 2019
@@ -20,7 +20,10 @@ namespace misc {
 ThrowByValueCatchByReferenceCheck::ThrowByValueCatchByReferenceCheck(
 StringRef Name, ClangTidyContext *Context)
 : ClangTidyCheck(Name, Context),
-  CheckAnonymousTemporaries(Options.get("CheckThrowTemporaries", true)) {}
+  CheckAnonymousTemporaries(Options.get("CheckThrowTemporaries", true)),
+  WarnOnLargeObject(Options.get("WarnOnLargeObject", false)),
+  // Cannot access `ASTContext` from here so set it to an extremal value.
+  MaxSize(Options.get("MaxSize", std::numeric_limits::max())) {}
 
 void ThrowByValueCatchByReferenceCheck::registerMatchers(MatchFinder *Finder) {
   // This is a C++ only check thus we register the matchers only for C++
@@ -150,8 +153,19 @@ void ThrowByValueCatchByReferenceCheck::
 // If it's not a pointer and not a reference then it must be caught "by
 // value". In this case we should emit a diagnosis message unless the type
 // is trivial.
-if (!caughtType.isTrivialType(context))
+if (!caughtType.isTrivialType(context)) {
   diag(varDecl->getBeginLoc(), diagMsgCatchReference);
+} else if (WarnOnLargeObject) {
+  // If the type is trivial, then catching it by reference is not 
dangerous.
+  // However, catching large objects by value decreases the performance.
+
+  // We can now access `ASTContext` so if `MaxSize` is an extremal value
+  // then set it to the size of `size_t`.
+  if (MaxSize == std::numeric_limits::max())
+MaxSize = context.getTypeSize(context.getSizeType());
+  if (context.getTypeSize(caughtType) > MaxSize)
+diag(varDecl->getBeginLoc(), diagMsgCatchReference);
+}
   }
 }
 

Modified: 
clang-tools-extra/trunk/clang-tidy/misc/ThrowByValueCatchByReferenceCheck.h
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/misc/ThrowByValueCatchByReferenceCheck.h?rev=361225=361224=361225=diff
==
--- clang-tools-extra/trunk/clang-tidy/misc/ThrowByValueCatchByReferenceCheck.h 
(original)
+++ clang-tools-extra/trunk/clang-tidy/misc/ThrowByValueCatchByReferenceCheck.h 
Tue May 21 00:25:06 2019
@@ -41,6 +41,8 @@ private:
   bool isCatchVariable(const DeclRefExpr *declRefExpr);
   bool isFunctionOrCatchVar(const DeclRefExpr *declRefExpr);
   const bool CheckAnonymousTemporaries;
+  const bool WarnOnLargeObject;
+  uint64_t MaxSize; // No `const` because we have to set it in two steps.
 };
 
 } // namespace misc

Modified: clang-tools-extra/trunk/docs/ReleaseNotes.rst
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/ReleaseNotes.rst?rev=361225=361224=361225=diff
==
--- clang-tools-extra/trunk/docs/ReleaseNotes.rst (original)
+++ clang-tools-extra/trunk/docs/ReleaseNotes.rst Tue May 21 00:25:06 2019
@@ -170,6 +170,11 @@ Improvements to clang-tidy
 
   Rewrites function signatures to use a trailing return type.
 
+- The :doc:`misc-throw-by-value-catch-by-reference
+  ` now supports
+  `WarnOnLargeObject` and `MaxSize` options to warn on any large trivial
+  object caught by value.
+
 Improvements to include-fixer
 -
 

Modified: 
clang-tools-extra/trunk/docs/clang-tidy/checks/misc-throw-by-value-catch-by-reference.rst
URL: 

r361141 - [Analyzer] Refactor begin and end symbol creation

2019-05-20 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Mon May 20 04:04:27 2019
New Revision: 361141

URL: http://llvm.org/viewvc/llvm-project?rev=361141=rev
Log:
[Analyzer] Refactor begin and end symbol creation

This patch refactors begin and end symbol creation by moving symbol
conjuration into the `create...` functions. This way the functions'
responsibilities are clearer and makes possible to add more functions
handling these symbols (e.g. functions for handling the container's
size) without code multiplication.

Differential Revision: https://reviews.llvm.org/D61136


Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp?rev=361141=361140=361141=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp Mon May 20 
04:04:27 2019
@@ -300,10 +300,13 @@ bool backModifiable(ProgramStateRef Stat
 SymbolRef getContainerBegin(ProgramStateRef State, const MemRegion *Cont);
 SymbolRef getContainerEnd(ProgramStateRef State, const MemRegion *Cont);
 ProgramStateRef createContainerBegin(ProgramStateRef State,
- const MemRegion *Cont,
- const SymbolRef Sym);
+ const MemRegion *Cont, const Expr *E,
+ QualType T, const LocationContext *LCtx,
+ unsigned BlockCount);
 ProgramStateRef createContainerEnd(ProgramStateRef State, const MemRegion 
*Cont,
-   const SymbolRef Sym);
+   const Expr *E, QualType T,
+   const LocationContext *LCtx,
+   unsigned BlockCount);
 const IteratorPosition *getIteratorPosition(ProgramStateRef State,
 const SVal );
 ProgramStateRef setIteratorPosition(ProgramStateRef State, const SVal ,
@@ -1142,11 +1145,9 @@ void IteratorChecker::handleBegin(Checke
   auto State = C.getState();
   auto BeginSym = getContainerBegin(State, ContReg);
   if (!BeginSym) {
-auto  = C.getSymbolManager();
-BeginSym = SymMgr.conjureSymbol(CE, C.getLocationContext(),
-C.getASTContext().LongTy, C.blockCount());
-State = assumeNoOverflow(State, BeginSym, 4);
-State = createContainerBegin(State, ContReg, BeginSym);
+State = createContainerBegin(State, ContReg, CE, C.getASTContext().LongTy,
+ C.getLocationContext(), C.blockCount());
+BeginSym = getContainerBegin(State, ContReg);
   }
   State = setIteratorPosition(State, RetVal,
   IteratorPosition::getPosition(ContReg, 
BeginSym));
@@ -1166,11 +1167,9 @@ void IteratorChecker::handleEnd(CheckerC
   auto State = C.getState();
   auto EndSym = getContainerEnd(State, ContReg);
   if (!EndSym) {
-auto  = C.getSymbolManager();
-EndSym = SymMgr.conjureSymbol(CE, C.getLocationContext(),
-  C.getASTContext().LongTy, C.blockCount());
-State = assumeNoOverflow(State, EndSym, 4);
-State = createContainerEnd(State, ContReg, EndSym);
+State = createContainerEnd(State, ContReg, CE, C.getASTContext().LongTy,
+   C.getLocationContext(), C.blockCount());
+EndSym = getContainerEnd(State, ContReg);
   }
   State = setIteratorPosition(State, RetVal,
   IteratorPosition::getPosition(ContReg, EndSym));
@@ -1934,32 +1933,47 @@ SymbolRef getContainerEnd(ProgramStateRe
 }
 
 ProgramStateRef createContainerBegin(ProgramStateRef State,
- const MemRegion *Cont,
- const SymbolRef Sym) {
+ const MemRegion *Cont, const Expr *E,
+ QualType T, const LocationContext *LCtx,
+ unsigned BlockCount) {
   // Only create if it does not exist
   const auto *CDataPtr = getContainerData(State, Cont);
+  if (CDataPtr && CDataPtr->getBegin())
+return State;
+
+  auto  = State->getSymbolManager();
+  const SymbolConjured *Sym = SymMgr.conjureSymbol(E, LCtx, T, BlockCount,
+   "begin");
+  State = assumeNoOverflow(State, Sym, 4);
+
   if (CDataPtr) {
-if (CDataPtr->getBegin()) {
-  return State;
-}
 const auto CData = CDataPtr->newBegin(Sym);
 return setContainerData(State, Cont, CData);
   }
+
   const auto CData = ContainerData::fromBegin(Sym);
   return setContainerData(State, Cont, CData);
 }
 
 ProgramStateRef createContainerEnd(ProgramStateRef State, const MemRegion 

[clang-tools-extra] r360114 - [clang-tidy] Extend bugprone-sizeof-expression to check sizeof(pointers to structures)

2019-05-07 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Mon May  6 23:16:02 2019
New Revision: 360114

URL: http://llvm.org/viewvc/llvm-project?rev=360114=rev
Log:
[clang-tidy] Extend bugprone-sizeof-expression to check sizeof(pointers to 
structures)

Accidentally taking the size of a struct-pointer type or a value of this type
is more common than explicitly using the & operator for the value. This patch
extends the check to include these cases.

Differential Revision: https://reviews.llvm.org/D61260


Modified:
clang-tools-extra/trunk/clang-tidy/bugprone/SizeofExpressionCheck.cpp
clang-tools-extra/trunk/test/clang-tidy/bugprone-sizeof-expression.cpp

Modified: clang-tools-extra/trunk/clang-tidy/bugprone/SizeofExpressionCheck.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/bugprone/SizeofExpressionCheck.cpp?rev=360114=360113=360114=diff
==
--- clang-tools-extra/trunk/clang-tidy/bugprone/SizeofExpressionCheck.cpp 
(original)
+++ clang-tools-extra/trunk/clang-tidy/bugprone/SizeofExpressionCheck.cpp Mon 
May  6 23:16:02 2019
@@ -145,10 +145,17 @@ void SizeofExpressionCheck::registerMatc
   unaryOperator(hasOperatorName("&"),
 hasUnaryOperand(ignoringParenImpCasts(expr(
 hasType(qualType(hasCanonicalType(recordType(;
+  const auto PointerToStructType = type(hasUnqualifiedDesugaredType(
+  pointerType(pointee(recordType();
+  const auto PointerToStructExpr = expr(ignoringParenImpCasts(expr(
+  hasType(qualType(hasCanonicalType(PointerToStructType))),
+  unless(cxxThisExpr();
 
   Finder->addMatcher(
-  expr(sizeOfExpr(has(expr(ignoringParenImpCasts(
-   anyOf(ArrayCastExpr, PointerToArrayExpr, StructAddrOfExpr))
+  expr(anyOf(sizeOfExpr(has(expr(ignoringParenImpCasts(
+   anyOf(ArrayCastExpr, PointerToArrayExpr, StructAddrOfExpr,
+ PointerToStructExpr),
+sizeOfExpr(has(PointerToStructType
   .bind("sizeof-pointer-to-aggregate"),
   this);
 

Modified: clang-tools-extra/trunk/test/clang-tidy/bugprone-sizeof-expression.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/bugprone-sizeof-expression.cpp?rev=360114=360113=360114=diff
==
--- clang-tools-extra/trunk/test/clang-tidy/bugprone-sizeof-expression.cpp 
(original)
+++ clang-tools-extra/trunk/test/clang-tidy/bugprone-sizeof-expression.cpp Mon 
May  6 23:16:02 2019
@@ -193,11 +193,15 @@ int Test5() {
 Array10* ptr;
   };
   typedef const MyStruct TMyStruct;
+  typedef const MyStruct *PMyStruct;
+  typedef TMyStruct *PMyStruct2;
 
   static TMyStruct kGlocalMyStruct = {};
   static TMyStruct volatile * kGlocalMyStructPtr = 
 
   MyStruct S;
+  PMyStruct PS;
+  PMyStruct2 PS2;
   Array10 A10;
 
   int sum = 0;
@@ -225,6 +229,14 @@ int Test5() {
   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 
'sizeof(A*)'; pointer to aggregate
   sum += sizeof();
   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 
'sizeof(A*)'; pointer to aggregate
+  sum += sizeof(MyStruct*);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 
'sizeof(A*)'; pointer to aggregate
+  sum += sizeof(PMyStruct);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 
'sizeof(A*)'; pointer to aggregate
+  sum += sizeof(PS);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 
'sizeof(A*)'; pointer to aggregate
+  sum += sizeof(PS2);
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 
'sizeof(A*)'; pointer to aggregate
   sum += sizeof();
   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 
'sizeof(A*)'; pointer to aggregate
 


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


[clang-tools-extra] r360032 - [clang-tidy] Extend bugprone-sizeof-expression check to detect sizeof misuse in pointer arithmetic

2019-05-06 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Mon May  6 03:41:37 2019
New Revision: 360032

URL: http://llvm.org/viewvc/llvm-project?rev=360032=rev
Log:
[clang-tidy] Extend bugprone-sizeof-expression check to detect sizeof misuse in 
pointer arithmetic

Some programmers tend to forget that subtracting two pointers results in the
difference between them in number of elements of the pointee type instead of
bytes. This leads to codes such as `size_t size = (p - q) / sizeof(int)` where
`p` and `q` are of type `int*`. Or similarily, `if (p - q < buffer_size *
sizeof(int)) { ... }`. This patch extends `bugprone-sizeof-expression` to
detect such cases.

Differential Revision: https://reviews.llvm.org/D61422


Modified:
clang-tools-extra/trunk/clang-tidy/bugprone/SizeofExpressionCheck.cpp
clang-tools-extra/trunk/test/clang-tidy/bugprone-sizeof-expression.cpp

Modified: clang-tools-extra/trunk/clang-tidy/bugprone/SizeofExpressionCheck.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/bugprone/SizeofExpressionCheck.cpp?rev=360032=360031=360032=diff
==
--- clang-tools-extra/trunk/clang-tidy/bugprone/SizeofExpressionCheck.cpp 
(original)
+++ clang-tools-extra/trunk/clang-tidy/bugprone/SizeofExpressionCheck.cpp Mon 
May  6 03:41:37 2019
@@ -84,8 +84,11 @@ void SizeofExpressionCheck::registerMatc
   const auto IntegerCallExpr = expr(ignoringParenImpCasts(
   callExpr(anyOf(hasType(isInteger()), hasType(enumType())),
unless(isInTemplateInstantiation();
-  const auto SizeOfExpr =
-  expr(anyOf(sizeOfExpr(has(type())), sizeOfExpr(has(expr();
+  const auto SizeOfExpr = expr(anyOf(
+  sizeOfExpr(
+  has(hasUnqualifiedDesugaredType(type().bind("sizeof-arg-type",
+  sizeOfExpr(has(expr(hasType(
+  hasUnqualifiedDesugaredType(type().bind("sizeof-arg-type";
   const auto SizeOfZero = expr(
   sizeOfExpr(has(ignoringParenImpCasts(expr(integerLiteral(equals(0)));
 
@@ -209,6 +212,36 @@ void SizeofExpressionCheck::registerMatc
hasSizeOfDescendant(8, expr(SizeOfExpr, 
unless(SizeOfZero
   .bind("sizeof-sizeof-expr"),
   this);
+
+  // Detect sizeof in pointer aritmetic like: N * sizeof(S) == P1 - P2 or
+  // (P1 - P2) / sizeof(S) where P1 and P2 are pointers to type S.
+  const auto PtrDiffExpr = binaryOperator(
+  hasOperatorName("-"),
+  hasLHS(expr(hasType(hasUnqualifiedDesugaredType(pointerType(pointee(
+  hasUnqualifiedDesugaredType(type().bind("left-ptr-type",
+  hasRHS(expr(hasType(hasUnqualifiedDesugaredType(pointerType(pointee(
+  hasUnqualifiedDesugaredType(type().bind("right-ptr-type");
+
+  Finder->addMatcher(
+  binaryOperator(
+  anyOf(hasOperatorName("=="), hasOperatorName("!="),
+hasOperatorName("<"), hasOperatorName("<="),
+hasOperatorName(">"), hasOperatorName(">="),
+hasOperatorName("+"), hasOperatorName("-")),
+  hasEitherOperand(expr(anyOf(
+  ignoringParenImpCasts(SizeOfExpr),
+  ignoringParenImpCasts(binaryOperator(
+  hasOperatorName("*"),
+  hasEitherOperand(ignoringParenImpCasts(SizeOfExpr))),
+  hasEitherOperand(ignoringParenImpCasts(PtrDiffExpr)))
+  .bind("sizeof-in-ptr-arithmetic-mul"),
+  this);
+
+  Finder->addMatcher(binaryOperator(hasOperatorName("/"),
+hasLHS(ignoringParenImpCasts(PtrDiffExpr)),
+hasRHS(ignoringParenImpCasts(SizeOfExpr)))
+ .bind("sizeof-in-ptr-arithmetic-div"),
+ this);
 }
 
 void SizeofExpressionCheck::check(const MatchFinder::MatchResult ) {
@@ -275,6 +308,26 @@ void SizeofExpressionCheck::check(const
   } else if (const auto *E =
  Result.Nodes.getNodeAs("sizeof-multiply-sizeof")) {
 diag(E->getBeginLoc(), "suspicious 'sizeof' by 'sizeof' multiplication");
+  } else if (const auto *E =
+ Result.Nodes.getNodeAs("sizeof-in-ptr-arithmetic-mul")) 
{
+const auto *LPtrTy = Result.Nodes.getNodeAs("left-ptr-type");
+const auto *RPtrTy = Result.Nodes.getNodeAs("right-ptr-type");
+const auto *SizeofArgTy = Result.Nodes.getNodeAs("sizeof-arg-type");
+
+if ((LPtrTy == RPtrTy) && (LPtrTy == SizeofArgTy)) {
+  diag(E->getBeginLoc(), "suspicious usage of 'sizeof(...)' in "
+  "pointer arithmetic");
+}
+  } else if (const auto *E =
+ Result.Nodes.getNodeAs("sizeof-in-ptr-arithmetic-div")) 
{
+const auto *LPtrTy = Result.Nodes.getNodeAs("left-ptr-type");
+const auto *RPtrTy = Result.Nodes.getNodeAs("right-ptr-type");
+const auto *SizeofArgTy = Result.Nodes.getNodeAs("sizeof-arg-type");
+
+if ((LPtrTy == RPtrTy) && (LPtrTy == SizeofArgTy)) {
+  

r358955 - [Analyzer] Fix for previous commit

2019-04-23 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Tue Apr 23 00:45:10 2019
New Revision: 358955

URL: http://llvm.org/viewvc/llvm-project?rev=358955=rev
Log:
[Analyzer] Fix for previous commit

A compilation warning was in my previous commit which broke the buildbot
because it is using `-Werror` for compilation. This patch fixes this
issue.


Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp?rev=358955=358954=358955=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp Tue Apr 23 
00:45:10 2019
@@ -848,9 +848,9 @@ void IteratorChecker::processComparison(
 SymbolRef Sym2, const SVal ,
 OverloadedOperatorKind Op) const {
   if (const auto TruthVal = RetVal.getAs()) {
-if (State = relateSymbols(State, Sym1, Sym2,
+if ((State = relateSymbols(State, Sym1, Sym2,
   (Op == OO_EqualEqual) ==
-  (TruthVal->getValue() != 0))) {
+   (TruthVal->getValue() != 0 {
   C.addTransition(State);
 } else {
   C.generateSink(State, C.getPredecessor());


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


r358951 - [Analyzer] Instead of recording comparisons in interator checkers do an eager state split

2019-04-23 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Tue Apr 23 00:15:55 2019
New Revision: 358951

URL: http://llvm.org/viewvc/llvm-project?rev=358951=rev
Log:
[Analyzer] Instead of recording comparisons in interator checkers do an eager 
state split

Currently iterator checkers record comparison of iterator positions
and process them for keeping track the distance between them (e.g.
whether a position is the same as the end position). However this
makes some processing unnecessarily complex and it is not needed at
all: we only need to keep track between the abstract symbols stored
in these iterator positions. This patch changes this and opens the
path to comparisons to the begin() and end() symbols between the
container (e.g. size, emptiness) which are stored as symbols, not
iterator positions. The functionality of the checker is unchanged.

Differential Revision: https://reviews.llvm.org/D53701


Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp?rev=358951=358950=358951=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp Tue Apr 23 
00:15:55 2019
@@ -133,8 +133,6 @@ public:
   }
 };
 
-typedef llvm::PointerUnion RegionOrSymbol;
-
 // Structure to record the symbolic begin and end position of a container
 struct ContainerData {
 private:
@@ -172,41 +170,21 @@ public:
   }
 };
 
-// Structure fo recording iterator comparisons. We needed to retrieve the
-// original comparison expression in assumptions.
-struct IteratorComparison {
-private:
-  RegionOrSymbol Left, Right;
-  bool Equality;
-
-public:
-  IteratorComparison(RegionOrSymbol L, RegionOrSymbol R, bool Eq)
-  : Left(L), Right(R), Equality(Eq) {}
-
-  RegionOrSymbol getLeft() const { return Left; }
-  RegionOrSymbol getRight() const { return Right; }
-  bool isEquality() const { return Equality; }
-  bool operator==(const IteratorComparison ) const {
-return Left == X.Left && Right == X.Right && Equality == X.Equality;
-  }
-  bool operator!=(const IteratorComparison ) const {
-return Left != X.Left || Right != X.Right || Equality != X.Equality;
-  }
-  void Profile(llvm::FoldingSetNodeID ) const { ID.AddInteger(Equality); }
-};
-
 class IteratorChecker
 : public Checker, check::Bind,
- check::LiveSymbols, check::DeadSymbols,
- eval::Assume> {
+ check::LiveSymbols, check::DeadSymbols> {
 
   std::unique_ptr OutOfRangeBugType;
   std::unique_ptr MismatchedBugType;
   std::unique_ptr InvalidatedBugType;
 
-  void handleComparison(CheckerContext , const SVal , const SVal 
,
-const SVal , OverloadedOperatorKind Op) const;
+  void handleComparison(CheckerContext , const Expr *CE, const SVal ,
+const SVal , const SVal ,
+OverloadedOperatorKind Op) const;
+  void processComparison(CheckerContext , ProgramStateRef State,
+ SymbolRef Sym1, SymbolRef Sym2, const SVal ,
+ OverloadedOperatorKind Op) const;
   void verifyAccess(CheckerContext , const SVal ) const;
   void verifyDereference(CheckerContext , const SVal ) const;
   void handleIncrement(CheckerContext , const SVal , const SVal ,
@@ -281,8 +259,6 @@ public:
  CheckerContext ) const;
   void checkLiveSymbols(ProgramStateRef State, SymbolReaper ) const;
   void checkDeadSymbols(SymbolReaper , CheckerContext ) const;
-  ProgramStateRef evalAssume(ProgramStateRef State, SVal Cond,
- bool Assumption) const;
 };
 } // namespace
 
@@ -292,9 +268,6 @@ REGISTER_MAP_WITH_PROGRAMSTATE(IteratorR
 
 REGISTER_MAP_WITH_PROGRAMSTATE(ContainerMap, const MemRegion *, ContainerData)
 
-REGISTER_MAP_WITH_PROGRAMSTATE(IteratorComparisonMap, const SymExpr *,
-   IteratorComparison)
-
 namespace {
 
 bool isIteratorType(const QualType );
@@ -324,16 +297,6 @@ bool isRandomIncrOrDecrOperator(Overload
 bool hasSubscriptOperator(ProgramStateRef State, const MemRegion *Reg);
 bool frontModifiable(ProgramStateRef State, const MemRegion *Reg);
 bool backModifiable(ProgramStateRef State, const MemRegion *Reg);
-BinaryOperator::Opcode getOpcode(const SymExpr *SE);
-const RegionOrSymbol getRegionOrSymbol(const SVal );
-const ProgramStateRef processComparison(ProgramStateRef State,
-RegionOrSymbol LVal,
-RegionOrSymbol RVal, bool Equal);
-const ProgramStateRef saveComparison(ProgramStateRef State,
- const SymExpr *Condition, const SVal 
,
- const SVal , bool Eq);
-const 

r358971 - [Analyzer] Second fix for last commit for IteratorChecker

2019-04-23 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Tue Apr 23 04:18:50 2019
New Revision: 358971

URL: http://llvm.org/viewvc/llvm-project?rev=358971=rev
Log:
[Analyzer] Second fix for last commit for IteratorChecker

A variable was redeclared instead of assigned in an internal
block, leaving the original uninitialized. This is fixed now.


Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp?rev=358971=358970=358971=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp Tue Apr 23 
04:18:50 2019
@@ -825,7 +825,7 @@ void IteratorChecker::handleComparison(C
   SymbolRef Sym;
   if (!LPos || !RPos) {
 auto  = C.getSymbolManager();
-auto Sym = SymMgr.conjureSymbol(CE, C.getLocationContext(),
+Sym = SymMgr.conjureSymbol(CE, C.getLocationContext(),
C.getASTContext().LongTy, C.blockCount());
 State = assumeNoOverflow(State, Sym, 4);
   }


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


r359283 - [Analyzer] Iterator Checkers - Do an early return after handling calls

2019-04-26 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Fri Apr 26 00:30:07 2019
New Revision: 359283

URL: http://llvm.org/viewvc/llvm-project?rev=359283=rev
Log:
[Analyzer] Iterator Checkers - Do an early return after handling calls

This patch is more of a fix than a real improvement: in checkPostCall()
we should return immediately after finding the right call and handling
it. This both saves unnecessary processing and double-handling calls by
mistake.

Differential Revision: https://reviews.llvm.org/D61134


Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp?rev=359283=359282=359283=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp Fri Apr 26 
00:30:07 2019
@@ -563,12 +563,14 @@ void IteratorChecker::checkPostCall(cons
 const auto Op = Func->getOverloadedOperator();
 if (isAssignmentOperator(Op)) {
   const auto *InstCall = dyn_cast();
-  if (Func->getParamDecl(0)->getType()->isRValueReferenceType()) {
+  if (cast(Func)->isMoveAssignmentOperator()) {
 handleAssign(C, InstCall->getCXXThisVal(), Call.getOriginExpr(),
  Call.getArgSVal(0));
-  } else {
-handleAssign(C, InstCall->getCXXThisVal());
+return;
   }
+
+  handleAssign(C, InstCall->getCXXThisVal());
+  return;
 } else if (isSimpleComparisonOperator(Op)) {
   const auto *OrigExpr = Call.getOriginExpr();
   if (!OrigExpr)
@@ -577,68 +579,107 @@ void IteratorChecker::checkPostCall(cons
   if (const auto *InstCall = dyn_cast()) {
 handleComparison(C, OrigExpr, Call.getReturnValue(),
  InstCall->getCXXThisVal(), Call.getArgSVal(0), Op);
-  } else {
-handleComparison(C, OrigExpr, Call.getReturnValue(), 
Call.getArgSVal(0),
- Call.getArgSVal(1), Op);
+return;
   }
+
+  handleComparison(C, OrigExpr, Call.getReturnValue(), Call.getArgSVal(0),
+ Call.getArgSVal(1), Op);
+  return;
 } else if (isRandomIncrOrDecrOperator(Func->getOverloadedOperator())) {
   if (const auto *InstCall = dyn_cast()) {
 if (Call.getNumArgs() >= 1) {
   handleRandomIncrOrDecr(C, Func->getOverloadedOperator(),
  Call.getReturnValue(),
  InstCall->getCXXThisVal(), 
Call.getArgSVal(0));
+  return;
 }
   } else {
 if (Call.getNumArgs() >= 2) {
   handleRandomIncrOrDecr(C, Func->getOverloadedOperator(),
  Call.getReturnValue(), Call.getArgSVal(0),
  Call.getArgSVal(1));
+  return;
 }
   }
 } else if (isIncrementOperator(Func->getOverloadedOperator())) {
   if (const auto *InstCall = dyn_cast()) {
 handleIncrement(C, Call.getReturnValue(), InstCall->getCXXThisVal(),
 Call.getNumArgs());
-  } else {
-handleIncrement(C, Call.getReturnValue(), Call.getArgSVal(0),
-Call.getNumArgs());
+return;
   }
+
+  handleIncrement(C, Call.getReturnValue(), Call.getArgSVal(0),
+  Call.getNumArgs());
+  return;
 } else if (isDecrementOperator(Func->getOverloadedOperator())) {
   if (const auto *InstCall = dyn_cast()) {
 handleDecrement(C, Call.getReturnValue(), InstCall->getCXXThisVal(),
 Call.getNumArgs());
-  } else {
-handleDecrement(C, Call.getReturnValue(), Call.getArgSVal(0),
-Call.getNumArgs());
+return;
   }
+
+  handleDecrement(C, Call.getReturnValue(), Call.getArgSVal(0),
+Call.getNumArgs());
+  return;
 }
   } else {
 if (const auto *InstCall = dyn_cast()) {
   if (isAssignCall(Func)) {
 handleAssign(C, InstCall->getCXXThisVal());
-  } else if (isClearCall(Func)) {
+return;
+  }
+
+  if (isClearCall(Func)) {
 handleClear(C, InstCall->getCXXThisVal());
-  } else if (isPushBackCall(Func) || isEmplaceBackCall(Func)) {
+return;
+  }
+
+  if (isPushBackCall(Func) || isEmplaceBackCall(Func)) {
 handlePushBack(C, InstCall->getCXXThisVal());
-  } else if (isPopBackCall(Func)) {
+return;
+  }
+
+  if (isPopBackCall(Func)) {
 handlePopBack(C, InstCall->getCXXThisVal());
-  } else if (isPushFrontCall(Func) || isEmplaceFrontCall(Func)) {
+return;
+  }
+
+  if (isPushFrontCall(Func) || isEmplaceFrontCall(Func)) {
 handlePushFront(C, InstCall->getCXXThisVal());
-  } else if (isPopFrontCall(Func)) {
+ 

r370314 - [Analyzer] Iterator Checkers - Make range errors and invalidated access fatal

2019-08-29 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Thu Aug 29 02:35:47 2019
New Revision: 370314

URL: http://llvm.org/viewvc/llvm-project?rev=370314=rev
Log:
[Analyzer] Iterator Checkers - Make range errors and invalidated access fatal

Range errors (dereferencing or incrementing the past-the-end iterator or
decrementing the iterator of the first element of the range) and access of
invalidated iterators lead to undefined behavior. There is no point to
continue the analysis after such an error on the same execution path, but
terminate it by a sink node (fatal error). This also improves the
performance and helps avoiding double reports (e.g. in case of nested
iterators).

Differential Revision: https://reviews.llvm.org/D62893


Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h
cfe/trunk/test/Analysis/diagnostics/explicit-suppression.cpp
cfe/trunk/test/Analysis/invalidated-iterator.cpp
cfe/trunk/test/Analysis/iterator-range.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp?rev=370314=370313=370314=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp Thu Aug 29 
02:35:47 2019
@@ -356,14 +356,12 @@ bool isZero(ProgramStateRef State, const
 
 IteratorChecker::IteratorChecker() {
   OutOfRangeBugType.reset(
-  new BugType(this, "Iterator out of range", "Misuse of STL APIs",
-  /*SuppressOnSink=*/true));
+  new BugType(this, "Iterator out of range", "Misuse of STL APIs"));
   MismatchedBugType.reset(
   new BugType(this, "Iterator(s) mismatched", "Misuse of STL APIs",
   /*SuppressOnSink=*/true));
   InvalidatedBugType.reset(
-  new BugType(this, "Iterator invalidated", "Misuse of STL APIs",
-  /*SuppressOnSink=*/true));
+  new BugType(this, "Iterator invalidated", "Misuse of STL APIs"));
 }
 
 void IteratorChecker::checkPreCall(const CallEvent ,
@@ -928,7 +926,7 @@ void IteratorChecker::verifyDereference(
   auto State = C.getState();
   const auto *Pos = getIteratorPosition(State, Val);
   if (Pos && isPastTheEnd(State, *Pos)) {
-auto *N = C.generateNonFatalErrorNode(State);
+auto *N = C.generateErrorNode(State);
 if (!N)
   return;
 reportOutOfRangeBug("Past-the-end iterator dereferenced.", Val, C, N);
@@ -940,7 +938,7 @@ void IteratorChecker::verifyAccess(Check
   auto State = C.getState();
   const auto *Pos = getIteratorPosition(State, Val);
   if (Pos && !Pos->isValid()) {
-auto *N = C.generateNonFatalErrorNode(State);
+auto *N = C.generateErrorNode(State);
 if (!N) {
   return;
 }
@@ -1048,14 +1046,14 @@ void IteratorChecker::verifyRandomIncrOr
   // The result may be the past-end iterator of the container, but any other
   // out of range position is undefined behaviour
   if (isAheadOfRange(State, advancePosition(C, Op, *Pos, Value))) {
-auto *N = C.generateNonFatalErrorNode(State);
+auto *N = C.generateErrorNode(State);
 if (!N)
   return;
 reportOutOfRangeBug("Iterator decremented ahead of its valid range.", LHS,
 C, N);
   }
   if (isBehindPastTheEnd(State, advancePosition(C, Op, *Pos, Value))) {
-auto *N = C.generateNonFatalErrorNode(State);
+auto *N = C.generateErrorNode(State);
 if (!N)
   return;
 reportOutOfRangeBug("Iterator incremented behind the past-the-end "

Modified: cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h?rev=370314=370313=370314=diff
==
--- cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h (original)
+++ cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h Thu Aug 29 
02:35:47 2019
@@ -150,7 +150,7 @@ template  operator++() { item = item->next; return *this; 
}
   __list_iterator operator++(int) {
 auto tmp = *this;
@@ -175,6 +175,9 @@ template 
+  friend struct __list_iterator;
+
 private:
   T* item;
 };
@@ -190,7 +193,7 @@ template  operator++() { item = item->next; return *this; 
}
   __fwdl_iterator operator++(int) {
 auto tmp = *this;
@@ -208,6 +211,9 @@ template 
+  friend struct __fwdl_iterator;
+
 private:
   T* item;
 };

Modified: cfe/trunk/test/Analysis/diagnostics/explicit-suppression.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/diagnostics/explicit-suppression.cpp?rev=370314=370313=370314=diff
==
--- cfe/trunk/test/Analysis/diagnostics/explicit-suppression.cpp (original)
+++ 

r367802 - [Analyzer] Iterator Checkers - Fix for Crash on Iterator Differences

2019-08-05 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Sun Aug  4 23:45:41 2019
New Revision: 367802

URL: http://llvm.org/viewvc/llvm-project?rev=367802=rev
Log:
[Analyzer] Iterator Checkers - Fix for Crash on Iterator Differences

Iterators differences were mistakenly handled as random decrements which
causes an assertion. This patch fixes this.


Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h
cfe/trunk/test/Analysis/diagnostics/explicit-suppression.cpp
cfe/trunk/test/Analysis/iterator-range.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp?rev=367802=367801=367802=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp Sun Aug  4 
23:45:41 2019
@@ -406,13 +406,15 @@ void IteratorChecker::checkPreCall(const
   } else if (isRandomIncrOrDecrOperator(Func->getOverloadedOperator())) {
 if (const auto *InstCall = dyn_cast()) {
   // Check for out-of-range incrementions and decrementions
-  if (Call.getNumArgs() >= 1) {
+  if (Call.getNumArgs() >= 1 &&
+  Call.getArgExpr(0)->getType()->isIntegralOrEnumerationType()) {
 verifyRandomIncrOrDecr(C, Func->getOverloadedOperator(),
InstCall->getCXXThisVal(),
Call.getArgSVal(0));
   }
 } else {
-  if (Call.getNumArgs() >= 2) {
+  if (Call.getNumArgs() >= 2 &&
+  Call.getArgExpr(1)->getType()->isIntegralOrEnumerationType()) {
 verifyRandomIncrOrDecr(C, Func->getOverloadedOperator(),
Call.getArgSVal(0), Call.getArgSVal(1));
   }
@@ -590,14 +592,16 @@ void IteratorChecker::checkPostCall(cons
   return;
 } else if (isRandomIncrOrDecrOperator(Func->getOverloadedOperator())) {
   if (const auto *InstCall = dyn_cast()) {
-if (Call.getNumArgs() >= 1) {
+if (Call.getNumArgs() >= 1 &&
+  Call.getArgExpr(0)->getType()->isIntegralOrEnumerationType()) {
   handleRandomIncrOrDecr(C, Func->getOverloadedOperator(),
  Call.getReturnValue(),
  InstCall->getCXXThisVal(), 
Call.getArgSVal(0));
   return;
 }
   } else {
-if (Call.getNumArgs() >= 2) {
+if (Call.getNumArgs() >= 2 &&
+  Call.getArgExpr(1)->getType()->isIntegralOrEnumerationType()) {
   handleRandomIncrOrDecr(C, Func->getOverloadedOperator(),
  Call.getReturnValue(), Call.getArgSVal(0),
  Call.getArgSVal(1));

Modified: cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h?rev=367802=367801=367802=diff
==
--- cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h (original)
+++ cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h Sun Aug  4 
23:45:41 2019
@@ -70,6 +70,9 @@ template 
+  difference_type operator-(const __vector_iterator );
+
   Ref operator*() const { return *ptr; }
   Ptr operator->() const { return *ptr; }
 

Modified: cfe/trunk/test/Analysis/diagnostics/explicit-suppression.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/diagnostics/explicit-suppression.cpp?rev=367802=367801=367802=diff
==
--- cfe/trunk/test/Analysis/diagnostics/explicit-suppression.cpp (original)
+++ cfe/trunk/test/Analysis/diagnostics/explicit-suppression.cpp Sun Aug  4 
23:45:41 2019
@@ -19,6 +19,6 @@ class C {
 void testCopyNull(C *I, C *E) {
   std::copy(I, E, (C *)0);
 #ifndef SUPPRESSED
-  // expected-warning@../Inputs/system-header-simulator-cxx.h:677 {{Called C++ 
object pointer is null}}
+  // expected-warning@../Inputs/system-header-simulator-cxx.h:680 {{Called C++ 
object pointer is null}}
 #endif
 }

Modified: cfe/trunk/test/Analysis/iterator-range.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/iterator-range.cpp?rev=367802=367801=367802=diff
==
--- cfe/trunk/test/Analysis/iterator-range.cpp (original)
+++ cfe/trunk/test/Analysis/iterator-range.cpp Sun Aug  4 23:45:41 2019
@@ -236,3 +236,8 @@ void good_derived(simple_container c) {
 *i0; // no-warning
   }
 }
+
+void iter_diff(std::vector ) {
+  auto i0 = V.begin(), i1 = V.end();
+  ptrdiff_t len = i1 - i0; // no-crash
+}


___

[clang-tools-extra] r372693 - [clang-tidy] New bugprone-infinite-loop check for detecting obvious infinite loops

2019-09-24 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Tue Sep 24 00:43:26 2019
New Revision: 372693

URL: http://llvm.org/viewvc/llvm-project?rev=372693=rev
Log:
[clang-tidy] New bugprone-infinite-loop check for detecting obvious infinite 
loops

Finding infinite loops is well-known to be impossible (halting problem).
However, it is possible to detect some obvious infinite loops, for example,
if the loop condition is not changed. Detecting such loops is beneficial
since the tests will hang on programs containing infinite loops so
testing-time detection may be costly in large systems. Obvious cases are
where the programmer forgets to increment/decrement the counter or
increments/decrements the wrong variable.

Differential Revision: https://reviews.llvm.org/D64736


Modified:
clang-tools-extra/trunk/clang-tidy/bugprone/BugproneTidyModule.cpp
clang-tools-extra/trunk/clang-tidy/bugprone/CMakeLists.txt
clang-tools-extra/trunk/docs/ReleaseNotes.rst
clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst

Modified: clang-tools-extra/trunk/clang-tidy/bugprone/BugproneTidyModule.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/bugprone/BugproneTidyModule.cpp?rev=372693=372692=372693=diff
==
--- clang-tools-extra/trunk/clang-tidy/bugprone/BugproneTidyModule.cpp 
(original)
+++ clang-tools-extra/trunk/clang-tidy/bugprone/BugproneTidyModule.cpp Tue Sep 
24 00:43:26 2019
@@ -23,6 +23,7 @@
 #include "ForwardingReferenceOverloadCheck.h"
 #include "InaccurateEraseCheck.h"
 #include "IncorrectRoundingsCheck.h"
+#include "InfiniteLoopCheck.h"
 #include "IntegerDivisionCheck.h"
 #include "LambdaFunctionNameCheck.h"
 #include "MacroParenthesesCheck.h"
@@ -88,6 +89,8 @@ public:
 "bugprone-inaccurate-erase");
 CheckFactories.registerCheck(
 "bugprone-incorrect-roundings");
+CheckFactories.registerCheck(
+"bugprone-infinite-loop");
 CheckFactories.registerCheck(
 "bugprone-integer-division");
 CheckFactories.registerCheck(

Modified: clang-tools-extra/trunk/clang-tidy/bugprone/CMakeLists.txt
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/bugprone/CMakeLists.txt?rev=372693=372692=372693=diff
==
--- clang-tools-extra/trunk/clang-tidy/bugprone/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clang-tidy/bugprone/CMakeLists.txt Tue Sep 24 
00:43:26 2019
@@ -15,6 +15,7 @@ add_clang_library(clangTidyBugproneModul
   ForwardingReferenceOverloadCheck.cpp
   InaccurateEraseCheck.cpp
   IncorrectRoundingsCheck.cpp
+  InfiniteLoopCheck.cpp
   IntegerDivisionCheck.cpp
   LambdaFunctionNameCheck.cpp
   MacroParenthesesCheck.cpp

Modified: clang-tools-extra/trunk/docs/ReleaseNotes.rst
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/ReleaseNotes.rst?rev=372693=372692=372693=diff
==
--- clang-tools-extra/trunk/docs/ReleaseNotes.rst (original)
+++ clang-tools-extra/trunk/docs/ReleaseNotes.rst Tue Sep 24 00:43:26 2019
@@ -70,6 +70,86 @@ Improvements to clang-tidy
 - New :doc:`bugprone-dynamic-static-initializers
   ` check.
 
+- New OpenMP module.
+
+  For checks specific to `OpenMP `_ API.
+
+- New :doc:`abseil-duration-addition
+  ` check.
+
+  Checks for cases where addition should be performed in the ``absl::Time``
+  domain.
+
+- New :doc:`abseil-duration-conversion-cast
+  ` check.
+
+  Checks for casts of ``absl::Duration`` conversion functions, and recommends
+  the right conversion function instead.
+
+- New :doc:`abseil-duration-unnecessary-conversion
+  ` check.
+
+  Finds and fixes cases where ``absl::Duration`` values are being converted to
+  numeric types and back again.
+
+- New :doc:`abseil-time-comparison
+  ` check.
+
+  Prefer comparisons in the ``absl::Time`` domain instead of the integer
+  domain.
+
+- New :doc:`abseil-time-subtraction
+  ` check.
+
+  Finds and fixes ``absl::Time`` subtraction expressions to do subtraction
+  in the Time domain instead of the numeric domain.
+
+- New :doc:`android-cloexec-pipe
+  ` check.
+
+  This check detects usage of ``pipe()``.
+
+- New :doc:`android-cloexec-pipe2
+  ` check.
+
+  This checks ensures that ``pipe2()`` is called with the O_CLOEXEC flag.
+
+- New :doc:`bugprone-infinite-loop
+  ` check.
+
+  Finds obvious infinite loops (loops where the condition variable is not
+  changed at all).
+
+- New :doc:`bugprone-unhandled-self-assignment
+  ` check.
+
+  Finds user-defined copy assignment operators which do not protect the code
+  against self-assignment either by checking self-assignment explicitly or
+  using the copy-and-swap or the copy-and-move method.
+
+- New :doc:`bugprone-branch-clone
+  ` check.
+
+  Checks for repeated branches in ``if/else if/else`` chains, consecutive
+  repeated 

[clang-tools-extra] r373428 - [clang-tidy] Fix for commits rL372706 and rL372711

2019-10-02 Thread Adam Balogh via cfe-commits
Author: baloghadamsoftware
Date: Wed Oct  2 00:14:11 2019
New Revision: 373428

URL: http://llvm.org/viewvc/llvm-project?rev=373428=rev
Log:
[clang-tidy] Fix for commits rL372706 and rL372711

The patch committed was not the accepted version but the
previous one. This commit fixes this issue.

Differential Revision: https://reviews.llvm.org/D64736


Modified:
clang-tools-extra/trunk/clang-tidy/bugprone/InfiniteLoopCheck.cpp
clang-tools-extra/trunk/docs/clang-tidy/checks/bugprone-infinite-loop.rst
clang-tools-extra/trunk/test/clang-tidy/bugprone-infinite-loop.cpp

Modified: clang-tools-extra/trunk/clang-tidy/bugprone/InfiniteLoopCheck.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/bugprone/InfiniteLoopCheck.cpp?rev=373428=373427=373428=diff
==
--- clang-tools-extra/trunk/clang-tidy/bugprone/InfiniteLoopCheck.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/bugprone/InfiniteLoopCheck.cpp Wed Oct  
2 00:14:11 2019
@@ -24,7 +24,7 @@ loopEndingStmt(internal::Matcher I
 callExpr(Internal, callee(functionDecl(isNoReturn());
 }
 
-/// \brief Return whether `S` is a reference to the declaration of `Var`.
+/// Return whether `S` is a reference to the declaration of `Var`.
 static bool isAccessForVar(const Stmt *S, const VarDecl *Var) {
   if (const auto *DRE = dyn_cast(S))
 return DRE->getDecl() == Var;
@@ -32,7 +32,7 @@ static bool isAccessForVar(const Stmt *S
   return false;
 }
 
-/// \brief Return whether `Var` has a pointer of reference in `S`.
+/// Return whether `Var` has a pointer or reference in `S`.
 static bool isPtrOrReferenceForVar(const Stmt *S, const VarDecl *Var) {
   if (const auto *DS = dyn_cast(S)) {
 for (const Decl *D : DS->getDeclGroup()) {
@@ -50,7 +50,7 @@ static bool isPtrOrReferenceForVar(const
   return false;
 }
 
-/// \brief Return whether `Var` has a pointer of reference in `S`.
+/// Return whether `Var` has a pointer or reference in `S`.
 static bool hasPtrOrReferenceInStmt(const Stmt *S, const VarDecl *Var) {
   if (isPtrOrReferenceForVar(S, Var))
 return true;
@@ -66,13 +66,13 @@ static bool hasPtrOrReferenceInStmt(cons
   return false;
 }
 
-/// \brief Return whether `Var` has a pointer of reference in `Func`.
+/// Return whether `Var` has a pointer or reference in `Func`.
 static bool hasPtrOrReferenceInFunc(const FunctionDecl *Func,
 const VarDecl *Var) {
   return hasPtrOrReferenceInStmt(Func->getBody(), Var);
 }
 
-/// \brief Return whether `Var` was changed in `LoopStmt`.
+/// Return whether `Var` was changed in `LoopStmt`.
 static bool isChanged(const Stmt *LoopStmt, const VarDecl *Var,
   ASTContext *Context) {
   if (const auto *ForLoop = dyn_cast(LoopStmt))
@@ -88,8 +88,7 @@ static bool isChanged(const Stmt *LoopSt
   return ExprMutationAnalyzer(*LoopStmt, *Context).isMutated(Var);
 }
 
-/// \brief Return whether `Cond` is a variable that is possibly changed in
-/// `LoopStmt`.
+/// Return whether `Cond` is a variable that is possibly changed in `LoopStmt`.
 static bool isVarThatIsPossiblyChanged(const FunctionDecl *Func,
const Stmt *LoopStmt, const Stmt *Cond,
ASTContext *Context) {
@@ -116,7 +115,7 @@ static bool isVarThatIsPossiblyChanged(c
   return false;
 }
 
-/// \brief Return whether at least one variable of `Cond` changed in 
`LoopStmt`.
+/// Return whether at least one variable of `Cond` changed in `LoopStmt`.
 static bool isAtLeastOneCondVarChanged(const FunctionDecl *Func,
const Stmt *LoopStmt, const Stmt *Cond,
ASTContext *Context) {
@@ -133,7 +132,7 @@ static bool isAtLeastOneCondVarChanged(c
   return false;
 }
 
-/// \brief Return the variable names in `Cond`.
+/// Return the variable names in `Cond`.
 static std::string getCondVarNames(const Stmt *Cond) {
   if (const auto *DRE = dyn_cast(Cond)) {
 if (const auto *Var = dyn_cast(DRE->getDecl()))

Modified: 
clang-tools-extra/trunk/docs/clang-tidy/checks/bugprone-infinite-loop.rst
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/bugprone-infinite-loop.rst?rev=373428=373427=373428=diff
==
--- clang-tools-extra/trunk/docs/clang-tidy/checks/bugprone-infinite-loop.rst 
(original)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/bugprone-infinite-loop.rst 
Wed Oct  2 00:14:11 2019
@@ -15,7 +15,7 @@ considered infinite if it does not have
 the condition:
 
 - It is a local variable.
-- It has no reference or pointer aliases
+- It has no reference or pointer aliases.
 - It is not a structure or class member.
 
 Furthermore, the condition must not contain a function call to consider the 
loop

Modified: 

[clang] 0f88cae - [Analyzer] Checker for Debugging Iterator Checkers

2019-11-07 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2019-11-08T08:59:50+01:00
New Revision: 0f88caeef8f2d4708f442d03db7723396712a143

URL: 
https://github.com/llvm/llvm-project/commit/0f88caeef8f2d4708f442d03db7723396712a143
DIFF: 
https://github.com/llvm/llvm-project/commit/0f88caeef8f2d4708f442d03db7723396712a143.diff

LOG: [Analyzer] Checker for Debugging Iterator Checkers

For white-box testing correct container and iterator modelling it is essential
to access the internal data structures stored for container and iterators. This
patch introduces a simple debug checkers called debug.IteratorDebugging to
achieve this.

Differential Revision: https://reviews.llvm.org/D67156

Added: 
clang/test/Analysis/debug-iterator-modeling.cpp

Modified: 
clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp

Removed: 




diff  --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td 
b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index 4d52655045b3..be455ae14f57 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -1343,6 +1343,11 @@ def ReportStmts : Checker<"ReportStmts">,
   HelpText<"Emits a warning for every statement.">,
   Documentation;
 
+def DebugIteratorModeling : Checker<"DebugIteratorModeling">,
+  HelpText<"Check the analyzer's understanding of C++ iterators">,
+  Dependencies<[IteratorModeling]>,
+  Documentation;
+
 } // end "debug"
 
 

diff  --git a/clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
index 97ace68569ef..a84327f07a52 100644
--- a/clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
@@ -173,11 +173,12 @@ struct ContainerData {
 class IteratorChecker
 : public Checker, check::Bind,
- check::LiveSymbols, check::DeadSymbols> {
+ check::LiveSymbols, check::DeadSymbols, eval::Call> {
 
   std::unique_ptr OutOfRangeBugType;
   std::unique_ptr MismatchedBugType;
   std::unique_ptr InvalidatedBugType;
+  std::unique_ptr DebugMsgBugType;
 
   void handleComparison(CheckerContext , const Expr *CE, const SVal ,
 const SVal , const SVal ,
@@ -236,7 +237,35 @@ class IteratorChecker
ExplodedNode *ErrNode) const;
   void reportInvalidatedBug(const StringRef , const SVal ,
 CheckerContext , ExplodedNode *ErrNode) const;
-
+  template 
+  void analyzerContainerDataField(const CallExpr *CE, CheckerContext ,
+  Getter get) const;
+  void analyzerContainerBegin(const CallExpr *CE, CheckerContext ) const;
+  void analyzerContainerEnd(const CallExpr *CE, CheckerContext ) const;
+  template 
+  void analyzerIteratorDataField(const CallExpr *CE, CheckerContext ,
+ Getter get, SVal Default) const;
+  void analyzerIteratorPosition(const CallExpr *CE, CheckerContext ) const;
+  void analyzerIteratorContainer(const CallExpr *CE, CheckerContext ) const;
+  void analyzerIteratorValidity(const CallExpr *CE, CheckerContext ) const;
+  ExplodedNode *reportDebugMsg(llvm::StringRef Msg, CheckerContext ) const;
+
+  typedef void (IteratorChecker::*FnCheck)(const CallExpr *,
+   CheckerContext &) const;
+
+  CallDescriptionMap Callbacks = {
+{{0, "clang_analyzer_container_begin", 1},
+ ::analyzerContainerBegin},
+{{0, "clang_analyzer_container_end", 1},
+ ::analyzerContainerEnd},
+{{0, "clang_analyzer_iterator_position", 1},
+ ::analyzerIteratorPosition},
+{{0, "clang_analyzer_iterator_container", 1},
+ ::analyzerIteratorContainer},
+{{0, "clang_analyzer_iterator_validity", 1},
+ ::analyzerIteratorValidity},
+  };
+  
 public:
   IteratorChecker();
 
@@ -244,6 +273,7 @@ class IteratorChecker
 CK_IteratorRangeChecker,
 CK_MismatchedIteratorChecker,
 CK_InvalidatedIteratorChecker,
+CK_DebugIteratorModeling,
 CK_NumCheckKinds
   };
 
@@ -259,6 +289,7 @@ class IteratorChecker
  CheckerContext ) const;
   void checkLiveSymbols(ProgramStateRef State, SymbolReaper ) const;
   void checkDeadSymbols(SymbolReaper , CheckerContext ) const;
+  bool evalCall(const CallEvent , CheckerContext ) const;
 };
 } // namespace
 
@@ -362,6 +393,9 @@ IteratorChecker::IteratorChecker() {
   /*SuppressOnSink=*/true));
   InvalidatedBugType.reset(
   new BugType(this, "Iterator invalidated", "Misuse of STL APIs"));
+  DebugMsgBugType.reset(
+  new BugType(this, "Checking analyzer assumptions", "debug",
+  /*SuppressOnSink=*/true));
 }
 
 void IteratorChecker::checkPreCall(const CallEvent ,
@@ -1627,6 +1661,124 @@ void IteratorChecker::reportInvalidatedBug(const 

[clang] 6e9c589 - [Analyzer] Iterator Modeling: Print Container Data and Iterator Positions when printing the Program State

2019-12-11 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2019-12-11T14:20:17+01:00
New Revision: 6e9c58946bfe8eed7308a3b57611e225ad67

URL: 
https://github.com/llvm/llvm-project/commit/6e9c58946bfe8eed7308a3b57611e225ad67
DIFF: 
https://github.com/llvm/llvm-project/commit/6e9c58946bfe8eed7308a3b57611e225ad67.diff

LOG: [Analyzer] Iterator Modeling: Print Container Data and Iterator Positions 
when printing the Program State

Debugging the Iterator Modeling checker or any of the iterator checkers
is difficult without being able to see the relations between the
iterator variables and their abstract positions, as well as the abstract
symbols denoting the begin and the end of the container.

This patch adds the checker-specific part of the Program State printing
to the Iterator Modeling checker.

Added: 


Modified: 
clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
clang/test/Analysis/iterator-modelling.cpp

Removed: 




diff  --git a/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp 
b/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
index 9730de0e4cd3..0a7015e85e93 100644
--- a/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
@@ -121,6 +121,9 @@ class IteratorModeling
   void handleEraseAfter(CheckerContext , const SVal ) const;
   void handleEraseAfter(CheckerContext , const SVal ,
 const SVal ) const;
+  void printState(raw_ostream , ProgramStateRef State, const char *NL,
+  const char *Sep) const override;
+
 public:
   IteratorModeling() {}
 
@@ -1080,6 +1083,58 @@ void IteratorModeling::handleEraseAfter(CheckerContext 
, const SVal ,
   C.addTransition(State);
 }
 
+void IteratorModeling::printState(raw_ostream , ProgramStateRef State,
+  const char *NL, const char *Sep) const {
+
+  auto ContMap = State->get();
+
+  if (!ContMap.isEmpty()) {
+Out << Sep << "Container Data :" << NL;
+for (const auto Cont : ContMap) {
+  Cont.first->dumpToStream(Out);
+  Out << " : [ ";
+  const auto CData = Cont.second;
+  if (CData.getBegin())
+CData.getBegin()->dumpToStream(Out);
+  else
+Out << "";
+  Out << " .. ";
+  if (CData.getEnd())
+CData.getEnd()->dumpToStream(Out);
+  else
+Out << "";
+  Out << " ]" << NL;
+}
+  }
+
+  auto SymbolMap = State->get();
+  auto RegionMap = State->get();
+
+  if (!SymbolMap.isEmpty() || !RegionMap.isEmpty()) {
+Out << Sep << "Iterator Positions :" << NL;
+for (const auto Sym : SymbolMap) {
+  Sym.first->dumpToStream(Out);
+  Out << " : ";
+  const auto Pos = Sym.second;
+  Out << (Pos.isValid() ? "Valid" : "Invalid") << " ; Container == ";
+  Pos.getContainer()->dumpToStream(Out);
+  Out<<" ; Offset == ";
+  Pos.getOffset()->dumpToStream(Out);
+}
+
+for (const auto Reg : RegionMap) {
+  Reg.first->dumpToStream(Out);
+  Out << " : ";
+  const auto Pos = Reg.second;
+  Out << (Pos.isValid() ? "Valid" : "Invalid") << " ; Container == ";
+  Pos.getContainer()->dumpToStream(Out);
+  Out<<" ; Offset == ";
+  Pos.getOffset()->dumpToStream(Out);
+}
+  }
+}
+
+
 namespace {
 
 const CXXRecordDecl *getCXXRecordDecl(ProgramStateRef State,

diff  --git a/clang/test/Analysis/iterator-modelling.cpp 
b/clang/test/Analysis/iterator-modelling.cpp
index 92427528e7c0..2cd7b349be81 100644
--- a/clang/test/Analysis/iterator-modelling.cpp
+++ b/clang/test/Analysis/iterator-modelling.cpp
@@ -1,6 +1,9 @@
 // RUN: %clang_analyze_cc1 -std=c++11 
-analyzer-checker=core,cplusplus,debug.DebugIteratorModeling,debug.ExprInspection
 -analyzer-config aggressive-binary-operation-simplification=true 
-analyzer-config c++-container-inlining=false %s -verify
+
 // RUN: %clang_analyze_cc1 -std=c++11 
-analyzer-checker=core,cplusplus,debug.DebugIteratorModeling,debug.ExprInspection
 -analyzer-config aggressive-binary-operation-simplification=true 
-analyzer-config c++-container-inlining=true -DINLINE=1 %s -verify
 
+// RUN: %clang_analyze_cc1 -std=c++11 
-analyzer-checker=core,cplusplus,alpha.cplusplus.IteratorModeling,debug.ExprInspection
 -analyzer-config aggressive-binary-operation-simplification=true %s 2>&1 | 
FileCheck %s
+
 #include "Inputs/system-header-simulator-cxx.h"
 
 template 
@@ -1970,3 +1973,29 @@ void non_std_find(std::vector , int e) {
 clang_analyzer_iterator_position(first)); // 
expected-warning@-1{{FALSE}} expected-warning@-1 0-1{{TRUE}} FIXME: should only 
expect FALSE in every case
   }
 }
+
+void clang_analyzer_printState();
+
+void print_state(std::vector ) {
+  const auto i0 = V.cbegin();
+  clang_analyzer_printState();
+
+// CHECK:  "checker_messages": [
+// CHECK-NEXT:   { "checker": "alpha.cplusplus.IteratorModeling", "messages": [
+// CHECK-NEXT: "Container Data :",
+// 

[clang-tools-extra] 170ee64 - [clang-tidy] Link shared library clangTidyOpenMPModule to library LLVMFrontendOpenMP

2019-12-11 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2019-12-11T12:37:22+01:00
New Revision: 170ee645f4d147103f93927c37a304c759c669dd

URL: 
https://github.com/llvm/llvm-project/commit/170ee645f4d147103f93927c37a304c759c669dd
DIFF: 
https://github.com/llvm/llvm-project/commit/170ee645f4d147103f93927c37a304c759c669dd.diff

LOG: [clang-tidy] Link shared library clangTidyOpenMPModule to library 
LLVMFrontendOpenMP

Building shared libs was broken, it is fixed now.

Added: 


Modified: 
clang-tools-extra/clang-tidy/openmp/CMakeLists.txt

Removed: 




diff  --git a/clang-tools-extra/clang-tidy/openmp/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/openmp/CMakeLists.txt
index bbd65f290364..c3c691bfb53d 100644
--- a/clang-tools-extra/clang-tidy/openmp/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/openmp/CMakeLists.txt
@@ -11,4 +11,5 @@ add_clang_library(clangTidyOpenMPModule
   clangBasic
   clangTidy
   clangTidyUtils
+  LLVMFrontendOpenMP
   )



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


[clang] 855d21a - [Analyzer] Iterator Checkers: Replace `UnknownVal` in comparison result by a conjured value

2019-12-11 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2019-12-11T15:24:06+01:00
New Revision: 855d21a03ae841b7c6c980e92f67bd5b65287fa6

URL: 
https://github.com/llvm/llvm-project/commit/855d21a03ae841b7c6c980e92f67bd5b65287fa6
DIFF: 
https://github.com/llvm/llvm-project/commit/855d21a03ae841b7c6c980e92f67bd5b65287fa6.diff

LOG: [Analyzer] Iterator Checkers: Replace `UnknownVal` in comparison result by 
a conjured value

Sometimes the return value of a comparison operator call is
`UnkownVal`. Since no assumptions can be made on `UnknownVal`,
this leeds to keeping impossible execution paths in the
exploded graph resulting in poor performance and false
positives. To overcome this we replace unknown results of
iterator comparisons by conjured symbols.

Differential Revision: https://reviews.llvm.org/D70244

Added: 


Modified: 
clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
clang/test/Analysis/invalidated-iterator.cpp
clang/test/Analysis/iterator-modelling.cpp

Removed: 




diff  --git a/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp 
b/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
index 0a7015e85e93..ab4e8112d677 100644
--- a/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
@@ -87,7 +87,7 @@ class IteratorModeling
 : public Checker,
  check::Bind, check::LiveSymbols, check::DeadSymbols> {
 
-  void handleComparison(CheckerContext , const Expr *CE, const SVal ,
+  void handleComparison(CheckerContext , const Expr *CE, SVal RetVal,
 const SVal , const SVal ,
 OverloadedOperatorKind Op) const;
   void processComparison(CheckerContext , ProgramStateRef State,
@@ -499,9 +499,9 @@ void IteratorModeling::checkDeadSymbols(SymbolReaper ,
 }
 
 void IteratorModeling::handleComparison(CheckerContext , const Expr *CE,
-const SVal , const SVal ,
-const SVal ,
-OverloadedOperatorKind Op) const {
+   SVal RetVal, const SVal ,
+   const SVal ,
+   OverloadedOperatorKind Op) const {
   // Record the operands and the operator of the comparison for the next
   // evalAssume, if the result is a symbolic expression. If it is a concrete
   // value (only one branch is possible), then transfer the state between
@@ -538,6 +538,16 @@ void IteratorModeling::handleComparison(CheckerContext , 
const Expr *CE,
 RPos = getIteratorPosition(State, RVal);
   }
 
+  // We cannot make assumpotions on `UnknownVal`. Let us conjure a symbol
+  // instead.
+  if (RetVal.isUnknown()) {
+auto  = C.getSymbolManager();
+auto *LCtx = C.getLocationContext();
+RetVal = nonloc::SymbolVal(SymMgr.conjureSymbol(
+CE, LCtx, C.getASTContext().BoolTy, C.blockCount()));
+State = State->BindExpr(CE, LCtx, RetVal);
+  }
+
   processComparison(C, State, LPos->getOffset(), RPos->getOffset(), RetVal, 
Op);
 }
 
@@ -559,7 +569,7 @@ void IteratorModeling::processComparison(CheckerContext ,
   const auto ConditionVal = RetVal.getAs();
   if (!ConditionVal)
 return;
-  
+
   if (auto StateTrue = relateSymbols(State, Sym1, Sym2, Op == OO_EqualEqual)) {
 StateTrue = StateTrue->assume(*ConditionVal, true);
 C.addTransition(StateTrue);

diff  --git a/clang/test/Analysis/invalidated-iterator.cpp 
b/clang/test/Analysis/invalidated-iterator.cpp
index 4505aedd4e36..a9ccc3b75834 100644
--- a/clang/test/Analysis/invalidated-iterator.cpp
+++ b/clang/test/Analysis/invalidated-iterator.cpp
@@ -120,4 +120,3 @@ void assignment(std::vector ) {
   V.erase(i);
   auto j = V.cbegin(); // no-warning
 }
-

diff  --git a/clang/test/Analysis/iterator-modelling.cpp 
b/clang/test/Analysis/iterator-modelling.cpp
index 2cd7b349be81..3c981b27bbbf 100644
--- a/clang/test/Analysis/iterator-modelling.cpp
+++ b/clang/test/Analysis/iterator-modelling.cpp
@@ -1969,8 +1969,8 @@ void non_std_find(std::vector , int e) {
   clang_analyzer_eval(clang_analyzer_container_end(V) ==
   clang_analyzer_iterator_position(first)); // 
expected-warning@-1{{FALSE}} expected-warning@-1{{TRUE}}
   if (V.end() != first) {
-  clang_analyzer_eval(clang_analyzer_container_end(V) ==
-clang_analyzer_iterator_position(first)); // 
expected-warning@-1{{FALSE}} expected-warning@-1 0-1{{TRUE}} FIXME: should only 
expect FALSE in every case
+clang_analyzer_eval(clang_analyzer_container_end(V) ==
+clang_analyzer_iterator_position(first)); // 
expected-warning@-1{{FALSE}}
   }
 }
 



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


[clang-tools-extra] 497a754 - [Clang-Tidy] Quick fix for bug in bugprone-macro-parentheses 43804

2019-12-01 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2019-12-02T08:50:51+01:00
New Revision: 497a754adeca67196c12a936d09c12d6803f99de

URL: 
https://github.com/llvm/llvm-project/commit/497a754adeca67196c12a936d09c12d6803f99de
DIFF: 
https://github.com/llvm/llvm-project/commit/497a754adeca67196c12a936d09c12d6803f99de.diff

LOG: [Clang-Tidy] Quick fix for bug in bugprone-macro-parentheses 43804

Applying parentheses for statement leads to compilation error. Bug
[[ 43804 | https://bugs.llvm.org/show_bug.cgi?id=43804 ]] is a
compilation error suggested by a wrong fix of this checker. This
patch is a quick fix for this issue.

Differential Revision: https://reviews.llvm.org/D70850

Added: 


Modified: 
clang-tools-extra/clang-tidy/bugprone/MacroParenthesesCheck.cpp
clang-tools-extra/test/clang-tidy/checkers/bugprone-macro-parentheses.cpp

Removed: 




diff  --git a/clang-tools-extra/clang-tidy/bugprone/MacroParenthesesCheck.cpp 
b/clang-tools-extra/clang-tidy/bugprone/MacroParenthesesCheck.cpp
index 7ca5c1e3454b..8d4366b51a3e 100644
--- a/clang-tools-extra/clang-tidy/bugprone/MacroParenthesesCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/MacroParenthesesCheck.cpp
@@ -54,7 +54,7 @@ static bool isSurroundedRight(const Token ) {
 /// Is given TokenKind a keyword?
 static bool isKeyword(const Token ) {
   // FIXME: better matching of keywords to avoid false positives.
-  return T.isOneOf(tok::kw_case, tok::kw_const, tok::kw_struct);
+  return T.isOneOf(tok::kw_if, tok::kw_case, tok::kw_const, tok::kw_struct);
 }
 
 /// Warning is written when one of these operators are not within parentheses.

diff  --git 
a/clang-tools-extra/test/clang-tidy/checkers/bugprone-macro-parentheses.cpp 
b/clang-tools-extra/test/clang-tidy/checkers/bugprone-macro-parentheses.cpp
index 2cc45e83b203..8d128352e789 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone-macro-parentheses.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone-macro-parentheses.cpp
@@ -43,6 +43,7 @@
 #define GOOD30(args...)   std::cout << args;
 #define GOOD31(X) A*X=2
 #define GOOD32(X) std::vector
+#define GOOD33(x) if (!a__##x) a_##x = (#x)
 
 // These are allowed for now..
 #define MAYBE1*12.34



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


[clang-tools-extra] fccd0da - [clang-tidy] New check: bugprone-misplaced-pointer-arithmetic-in-alloc

2020-01-21 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-01-21T14:38:15+01:00
New Revision: fccd0da5ee6f4e337395f287edcf824a009e1b7e

URL: 
https://github.com/llvm/llvm-project/commit/fccd0da5ee6f4e337395f287edcf824a009e1b7e
DIFF: 
https://github.com/llvm/llvm-project/commit/fccd0da5ee6f4e337395f287edcf824a009e1b7e.diff

LOG: [clang-tidy] New check: bugprone-misplaced-pointer-arithmetic-in-alloc

Finds cases where an integer expression is added to the result
of a memory allocation function instead of its argument.

Differential Revision: https://reviews.llvm.org/D71001

Added: 

clang-tools-extra/clang-tidy/bugprone/MisplacedPointerArithmeticInAllocCheck.cpp

clang-tools-extra/clang-tidy/bugprone/MisplacedPointerArithmeticInAllocCheck.h

clang-tools-extra/docs/clang-tidy/checks/bugprone-misplaced-pointer-arithmetic-in-alloc.rst

clang-tools-extra/test/clang-tidy/checkers/bugprone-misplaced-pointer-arithmetic-in-alloc.c

clang-tools-extra/test/clang-tidy/checkers/bugprone-misplaced-pointer-arithmetic-in-alloc.cpp

Modified: 
clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
clang-tools-extra/docs/ReleaseNotes.rst
clang-tools-extra/docs/clang-tidy/checks/list.rst

Removed: 




diff  --git a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp 
b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
index 831f5f4e3b62..86936c678562 100644
--- a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
@@ -30,6 +30,7 @@
 #include "MacroParenthesesCheck.h"
 #include "MacroRepeatedSideEffectsCheck.h"
 #include "MisplacedOperatorInStrlenInAllocCheck.h"
+#include "MisplacedPointerArithmeticInAllocCheck.h"
 #include "MisplacedWideningCastCheck.h"
 #include "MoveForwardingReferenceCheck.h"
 #include "MultipleStatementMacroCheck.h"
@@ -107,6 +108,8 @@ class BugproneModule : public ClangTidyModule {
 "bugprone-macro-repeated-side-effects");
 CheckFactories.registerCheck(
 "bugprone-misplaced-operator-in-strlen-in-alloc");
+CheckFactories.registerCheck(
+"bugprone-misplaced-pointer-arithmetic-in-alloc");
 CheckFactories.registerCheck(
 "bugprone-misplaced-widening-cast");
 CheckFactories.registerCheck(

diff  --git a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
index efb97a5318bb..c9078ed390d1 100644
--- a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
@@ -22,6 +22,7 @@ add_clang_library(clangTidyBugproneModule
   MacroParenthesesCheck.cpp
   MacroRepeatedSideEffectsCheck.cpp
   MisplacedOperatorInStrlenInAllocCheck.cpp
+  MisplacedPointerArithmeticInAllocCheck.cpp
   MisplacedWideningCastCheck.cpp
   MoveForwardingReferenceCheck.cpp
   MultipleStatementMacroCheck.cpp

diff  --git 
a/clang-tools-extra/clang-tidy/bugprone/MisplacedPointerArithmeticInAllocCheck.cpp
 
b/clang-tools-extra/clang-tidy/bugprone/MisplacedPointerArithmeticInAllocCheck.cpp
new file mode 100644
index ..c6dc78622851
--- /dev/null
+++ 
b/clang-tools-extra/clang-tidy/bugprone/MisplacedPointerArithmeticInAllocCheck.cpp
@@ -0,0 +1,105 @@
+//===--- MisplacedPointerArithmeticInAllocCheck.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 "MisplacedPointerArithmeticInAllocCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+void MisplacedPointerArithmeticInAllocCheck::registerMatchers(
+MatchFinder *Finder) {
+  const auto AllocFunc = functionDecl(
+  anyOf(hasName("::malloc"), hasName("std::malloc"), hasName("::alloca"),
+hasName("::calloc"), hasName("std::calloc"), hasName("::realloc"),
+hasName("std::realloc")));
+
+  const auto AllocFuncPtr =
+  varDecl(hasType(isConstQualified()),
+  hasInitializer(ignoringParenImpCasts(
+  declRefExpr(hasDeclaration(AllocFunc);
+
+  const auto AdditiveOperator =
+  binaryOperator(anyOf(hasOperatorName("+"), hasOperatorName("-")));
+
+  const auto IntExpr = expr(hasType(isInteger()));
+
+  const auto AllocCall = callExpr(callee(decl(anyOf(AllocFunc, 
AllocFuncPtr;
+
+  Finder->addMatcher(
+  binaryOperator(
+  AdditiveOperator,
+  hasLHS(anyOf(AllocCall, castExpr(hasSourceExpression(AllocCall,
+  hasRHS(IntExpr))
+  .bind("PtrArith"),
+  this);
+
+ 

[clang] 770ad9f - [Analyzer] Fix for iterator modeling and checkers: handle negative numbers correctly

2020-02-25 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-02-25T14:57:34+01:00
New Revision: 770ad9f55e660e0ec89f61d5579dfafad17ab5f5

URL: 
https://github.com/llvm/llvm-project/commit/770ad9f55e660e0ec89f61d5579dfafad17ab5f5
DIFF: 
https://github.com/llvm/llvm-project/commit/770ad9f55e660e0ec89f61d5579dfafad17ab5f5.diff

LOG: [Analyzer] Fix for iterator modeling and checkers: handle negative numbers 
correctly

Currently, using negative numbers in iterator operations (additions and
subractions) results in advancements with huge positive numbers due to
an error. This patch fixes it.

Differential Revision: https://reviews.llvm.org/D74760

Added: 


Modified: 
clang/lib/StaticAnalyzer/Checkers/Iterator.cpp
clang/test/Analysis/iterator-modelling.cpp

Removed: 




diff  --git a/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp 
b/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp
index 64daf358fbe5..e80d8bc32dec 100644
--- a/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp
@@ -200,22 +200,29 @@ ProgramStateRef advancePosition(ProgramStateRef State, 
const SVal ,
 
   auto  = State->getStateManager().getSymbolManager();
   auto  = State->getStateManager().getSValBuilder();
+  auto  = State->getStateManager().getBasicVals();
 
   assert ((Op == OO_Plus || Op == OO_PlusEqual ||
Op == OO_Minus || Op == OO_MinusEqual) &&
   "Advance operator must be one of +, -, += and -=.");
   auto BinOp = (Op == OO_Plus || Op == OO_PlusEqual) ? BO_Add : BO_Sub;
-  if (const auto IntDist = Distance.getAs()) {
-// For concrete integers we can calculate the new position
-const auto NewPos =
-  Pos->setTo(SVB.evalBinOp(State, BinOp,
-   nonloc::SymbolVal(Pos->getOffset()),
-   *IntDist, SymMgr.getType(Pos->getOffset()))
- .getAsSymbol());
-return setIteratorPosition(State, Iter, NewPos);
-  }
+  const auto IntDistOp = Distance.getAs();
+  if (!IntDistOp)
+return nullptr;
 
-  return nullptr;
+  // For concrete integers we can calculate the new position
+  nonloc::ConcreteInt IntDist = *IntDistOp;
+
+  if (IntDist.getValue().isNegative()) {
+IntDist = nonloc::ConcreteInt(BVF.getValue(-IntDist.getValue()));
+BinOp = (BinOp == BO_Add) ? BO_Sub : BO_Add;
+  }
+  const auto NewPos =
+Pos->setTo(SVB.evalBinOp(State, BinOp,
+ nonloc::SymbolVal(Pos->getOffset()),
+ IntDist, SymMgr.getType(Pos->getOffset()))
+   .getAsSymbol());
+  return setIteratorPosition(State, Iter, NewPos);
 }
 
 // This function tells the analyzer's engine that symbols produced by our

diff  --git a/clang/test/Analysis/iterator-modelling.cpp 
b/clang/test/Analysis/iterator-modelling.cpp
index b2551939986a..4e40319cedc1 100644
--- a/clang/test/Analysis/iterator-modelling.cpp
+++ b/clang/test/Analysis/iterator-modelling.cpp
@@ -100,6 +100,16 @@ void plus_equal(const std::vector ) {
   clang_analyzer_express(clang_analyzer_iterator_position(i)); 
//expected-warning{{$v.begin() + 2}}
 }
 
+void plus_equal_negative(const std::vector ) {
+  auto i = v.end();
+
+  clang_analyzer_denote(clang_analyzer_container_end(v), "$v.end()");
+
+  i += -2;
+
+  clang_analyzer_express(clang_analyzer_iterator_position(i)); 
//expected-warning{{$v.end() - 2}}
+}
+
 void minus_equal(const std::vector ) {
   auto i = v.end();
 
@@ -110,6 +120,16 @@ void minus_equal(const std::vector ) {
   clang_analyzer_express(clang_analyzer_iterator_position(i)); 
//expected-warning{{$v.end() - 2}}
 }
 
+void minus_equal_negative(const std::vector ) {
+  auto i = v.begin();
+
+  clang_analyzer_denote(clang_analyzer_container_begin(v), "$v.begin()");
+
+  i -= -2;
+
+  clang_analyzer_express(clang_analyzer_iterator_position(i)); 
//expected-warning{{$v.begin() + 2}}
+}
+
 void copy(const std::vector ) {
   auto i1 = v.end();
 
@@ -132,6 +152,17 @@ void plus(const std::vector ) {
   clang_analyzer_express(clang_analyzer_iterator_position(i2)); 
//expected-warning{{$v.begin() + 2}}
 }
 
+void plus_negative(const std::vector ) {
+  auto i1 = v.end();
+
+  clang_analyzer_denote(clang_analyzer_container_end(v), "$v.end()");
+
+  auto i2 = i1 + (-2);
+
+  clang_analyzer_eval(clang_analyzer_iterator_container(i2) == ); // 
expected-warning{{TRUE}}
+  clang_analyzer_express(clang_analyzer_iterator_position(i2)); 
//expected-warning{{$v.end() - 2}}
+}
+
 void minus(const std::vector ) {
   auto i1 = v.end();
 
@@ -143,6 +174,17 @@ void minus(const std::vector ) {
   clang_analyzer_express(clang_analyzer_iterator_position(i2)); 
//expected-warning{{$v.end() - 2}}
 }
 
+void minus_negative(const std::vector ) {
+  auto i1 = v.begin();
+
+  clang_analyzer_denote(clang_analyzer_container_begin(v), "$v.begin()");
+
+  auto i2 = i1 - (-2);
+
+  clang_analyzer_eval(clang_analyzer_iterator_container(i2) == ); // 

[clang-tools-extra] 70f4c6e - [clan-tidy] Fix false positive in bugprone-infinite-loop

2020-01-27 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-01-27T10:13:55+01:00
New Revision: 70f4c6e7b14f225f9628fbdab3620ce037613351

URL: 
https://github.com/llvm/llvm-project/commit/70f4c6e7b14f225f9628fbdab3620ce037613351
DIFF: 
https://github.com/llvm/llvm-project/commit/70f4c6e7b14f225f9628fbdab3620ce037613351.diff

LOG: [clan-tidy] Fix false positive in bugprone-infinite-loop

The checker bugprone-infinite-loop does not track changes of
variables in the initialization expression of a variable
declared inside the condition of the while statement. This
leads to false positives, similarly to the one in the bug
report https://bugs.llvm.org/show_bug.cgi?id=44618. This
patch fixes this issue by enabling tracking of the variables
of this expression as well.

Differential Revision: https://reviews.llvm.org/D73270

Added: 


Modified: 
clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp
clang-tools-extra/test/clang-tidy/checkers/bugprone-infinite-loop.cpp

Removed: 




diff  --git a/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp 
b/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp
index 81ae45a00896..c771ba81b250 100644
--- a/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp
@@ -170,17 +170,33 @@ void InfiniteLoopCheck::check(const 
MatchFinder::MatchResult ) {
   const auto *LoopStmt = Result.Nodes.getNodeAs("loop-stmt");
   const auto *Func = Result.Nodes.getNodeAs("func");
 
+  bool ShouldHaveConditionVariables = true;
+  if (const auto *While = dyn_cast(LoopStmt)) {
+if (const VarDecl *LoopVarDecl = While->getConditionVariable()) {
+  if (const Expr *Init = LoopVarDecl->getInit()) {
+ShouldHaveConditionVariables = false;
+Cond = Init;
+  }
+}
+  }
+
   if (isAtLeastOneCondVarChanged(Func, LoopStmt, Cond, Result.Context))
 return;
 
   std::string CondVarNames = getCondVarNames(Cond);
-  if (CondVarNames.empty())
+  if (ShouldHaveConditionVariables && CondVarNames.empty())
 return;
 
-  diag(LoopStmt->getBeginLoc(),
-   "this loop is infinite; none of its condition variables (%0)"
-   " are updated in the loop body")
+  if (CondVarNames.empty()) {
+diag(LoopStmt->getBeginLoc(),
+ "this loop is infinite; it does not check any variables in the"
+ " condition");
+  } else {
+diag(LoopStmt->getBeginLoc(),
+ "this loop is infinite; none of its condition variables (%0)"
+ " are updated in the loop body")
   << CondVarNames;
+  }
 }
 
 } // namespace bugprone

diff  --git 
a/clang-tools-extra/test/clang-tidy/checkers/bugprone-infinite-loop.cpp 
b/clang-tools-extra/test/clang-tidy/checkers/bugprone-infinite-loop.cpp
index 33d94820b0f6..d89bdadf0212 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone-infinite-loop.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone-infinite-loop.cpp
@@ -4,10 +4,20 @@ void simple_infinite_loop1() {
   int i = 0;
   int j = 0;
   while (i < 10) {
-// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of 
its condition variables (i) are updated in the loop body 
[bugprone-infinite-loop]
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of 
its condition variables (i) are updated in the loop body 
[bugprone-infinite-loop]
 j++;
   }
 
+  while (int k = 10) {
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; it does 
not check any variables in the condition [bugprone-infinite-loop]
+j--;
+  }
+
+  while (int k = 10) {
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; it does 
not check any variables in the condition [bugprone-infinite-loop]
+k--;
+  }
+
   do {
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of 
its condition variables (i) are updated in the loop body 
[bugprone-infinite-loop]
 j++;
@@ -27,6 +37,16 @@ void simple_infinite_loop2() {
 j++;
   }
 
+  while (int k = Limit) {
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of 
its condition variables (Limit) are updated in the loop body 
[bugprone-infinite-loop]
+j--;
+  }
+
+  while (int k = Limit) {
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of 
its condition variables (Limit) are updated in the loop body 
[bugprone-infinite-loop]
+k--;
+  }
+
   do {
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of 
its condition variables (i, Limit) are updated in the loop body 
[bugprone-infinite-loop]
 j++;
@@ -44,6 +64,22 @@ void simple_not_infinite1() {
 // Not an error since 'Limit' is updated.
 Limit--;
   }
+
+  while (Limit--) {
+// Not an error since 'Limit' is updated.
+i++;
+  }
+
+  while (int k = Limit) {
+// Not an error since 'Limit' is updated.
+Limit--;
+  }
+
+  while 

[clang] b198f16 - [Analyzer] Model STL Algoirthms to improve the iterator checkers

2020-02-05 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-02-05T17:59:08+01:00
New Revision: b198f16e1e1c8ee849008c1b886199eae5bc2e01

URL: 
https://github.com/llvm/llvm-project/commit/b198f16e1e1c8ee849008c1b886199eae5bc2e01
DIFF: 
https://github.com/llvm/llvm-project/commit/b198f16e1e1c8ee849008c1b886199eae5bc2e01.diff

LOG: [Analyzer] Model STL Algoirthms to improve the iterator checkers

STL Algorithms are usually implemented in a tricky for performance
reasons which is too complicated for the analyzer. Furthermore inlining
them is costly. Instead of inlining we should model their behavior
according to the specifications.

This patch is the first step towards STL Algorithm modeling. It models
all the `find()`-like functions in a simple way: the result is either
found or not. In the future it can be extended to only return success if
container modeling is also extended in a way the it keeps track of
trivial insertions and deletions.

Differential Revision: https://reviews.llvm.org/D70818

Added: 
clang/lib/StaticAnalyzer/Checkers/STLAlgorithmModeling.cpp
clang/test/Analysis/stl-algorithm-modeling-aggressive-std-find-modeling.cpp
clang/test/Analysis/stl-algorithm-modeling.cpp

Modified: 
clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
clang/lib/StaticAnalyzer/Checkers/Iterator.cpp
clang/lib/StaticAnalyzer/Checkers/Iterator.h
clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
clang/test/Analysis/Inputs/system-header-simulator-cxx.h
clang/test/Analysis/analyzer-config.c

Removed: 




diff  --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td 
b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index 6a7fbfe83041..50610de6843e 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -622,6 +622,19 @@ def IteratorModeling : Checker<"IteratorModeling">,
   Documentation,
   Hidden;
 
+def STLAlgorithmModeling : Checker<"STLAlgorithmModeling">,
+  HelpText<"Models the algorithm library of the C++ STL.">,
+  CheckerOptions<[
+CmdLineOption
+  ]>,
+  Dependencies<[ContainerModeling]>,
+  Documentation;
+
 def InvalidatedIteratorChecker : Checker<"InvalidatedIterator">,
   HelpText<"Check for use of invalidated iterators">,
   Dependencies<[IteratorModeling]>,

diff  --git a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt 
b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
index b6af13d4e97f..765c2f3e4530 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -99,6 +99,7 @@ add_clang_library(clangStaticAnalyzerCheckers
   SmartPtrModeling.cpp
   StackAddrEscapeChecker.cpp
   StdLibraryFunctionsChecker.cpp
+  STLAlgorithmModeling.cpp
   StreamChecker.cpp
   Taint.cpp
   TaintTesterChecker.cpp

diff  --git a/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp 
b/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp
index 612d3050babd..64daf358fbe5 100644
--- a/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp
@@ -177,6 +177,20 @@ ProgramStateRef setIteratorPosition(ProgramStateRef State, 
const SVal ,
   return nullptr;
 }
 
+ProgramStateRef createIteratorPosition(ProgramStateRef State, const SVal ,
+   const MemRegion *Cont, const Stmt* S,
+   const LocationContext *LCtx,
+   unsigned blockCount) {
+  auto  = State->getStateManager();
+  auto  = StateMgr.getSymbolManager();
+  auto  = StateMgr.getContext();
+
+  auto Sym = SymMgr.conjureSymbol(S, LCtx, ACtx.LongTy, blockCount);
+  State = assumeNoOverflow(State, Sym, 4);
+  return setIteratorPosition(State, Val,
+ IteratorPosition::getPosition(Cont, Sym));
+}
+
 ProgramStateRef advancePosition(ProgramStateRef State, const SVal ,
 OverloadedOperatorKind Op,
 const SVal ) {

diff  --git a/clang/lib/StaticAnalyzer/Checkers/Iterator.h 
b/clang/lib/StaticAnalyzer/Checkers/Iterator.h
index a1a24732794b..d5c6cb96ebc6 100644
--- a/clang/lib/StaticAnalyzer/Checkers/Iterator.h
+++ b/clang/lib/StaticAnalyzer/Checkers/Iterator.h
@@ -159,6 +159,10 @@ const IteratorPosition 
*getIteratorPosition(ProgramStateRef State,
 const SVal );
 ProgramStateRef setIteratorPosition(ProgramStateRef State, const SVal ,
 const IteratorPosition );
+ProgramStateRef createIteratorPosition(ProgramStateRef State, const SVal ,
+   const MemRegion *Cont, const Stmt* S,
+   const LocationContext *LCtx,
+   unsigned blockCount);
 ProgramStateRef 

[clang] 20a3d64 - [Analyzer][NFC] Change parameter of NoteTag lambdas to PathSensitiveBugReport

2020-03-10 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-03-10T11:30:28+01:00
New Revision: 20a3d64c8883c8be550f0759525b1550b7c2d35f

URL: 
https://github.com/llvm/llvm-project/commit/20a3d64c8883c8be550f0759525b1550b7c2d35f
DIFF: 
https://github.com/llvm/llvm-project/commit/20a3d64c8883c8be550f0759525b1550b7c2d35f.diff

LOG: [Analyzer][NFC] Change parameter of NoteTag lambdas to 
PathSensitiveBugReport

Lambdas creating path notes using NoteTags still take BugReport as their
parameter. Since path notes obviously only appear in PathSensitiveBugReports
it is straightforward that lambdas of NoteTags take PathSensitiveBugReport
as their parameter.

Differential Revision: https://reviews.llvm.org/D75898

Added: 


Modified: 
clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
clang/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp
clang/lib/StaticAnalyzer/Checkers/FuchsiaHandleChecker.cpp
clang/lib/StaticAnalyzer/Checkers/MIGChecker.cpp
clang/lib/StaticAnalyzer/Checkers/ReturnValueChecker.cpp
clang/lib/StaticAnalyzer/Core/CoreEngine.cpp

Removed: 




diff  --git a/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h 
b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
index 1b39cdf12c80..d45c4b71e780 100644
--- a/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
+++ b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
@@ -726,7 +726,8 @@ class BugReporterContext {
 class NoteTag : public ProgramPointTag {
 public:
   using Callback =
-  std::function;
+  std::function;
 
 private:
   static int Kind;
@@ -743,7 +744,7 @@ class NoteTag : public ProgramPointTag {
   }
 
   Optional generateMessage(BugReporterContext ,
-BugReport ) const {
+PathSensitiveBugReport ) const {
 std::string Msg = Cb(BRC, R);
 if (Msg.empty())
   return None;

diff  --git 
a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
index aee26db95fd1..2b5d37b6cc41 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
@@ -258,10 +258,12 @@ class CheckerContext {
   /// @param IsPrunable Whether the note is prunable. It allows BugReporter
   ///to omit the note from the report if it would make the displayed
   ///bug path significantly shorter.
-  const NoteTag *getNoteTag(std::function &,
-bool IsPrunable = false) {
+  const NoteTag
+  *getNoteTag(std::function &,
+  bool IsPrunable = false) {
 return getNoteTag(
-[Cb](BugReporterContext &, BugReport ) { return Cb(BR); },
+[Cb](BugReporterContext &,
+ PathSensitiveBugReport ) { return Cb(BR); },
 IsPrunable);
   }
 
@@ -274,7 +276,8 @@ class CheckerContext {
   ///bug path significantly shorter.
   const NoteTag *getNoteTag(std::function &,
 bool IsPrunable = false) {
-return getNoteTag([Cb](BugReporterContext &, BugReport &) { return Cb(); },
+return getNoteTag([Cb](BugReporterContext &,
+   PathSensitiveBugReport &) { return Cb(); },
   IsPrunable);
   }
 
@@ -286,7 +289,8 @@ class CheckerContext {
   ///bug path significantly shorter.
   const NoteTag *getNoteTag(StringRef Note, bool IsPrunable = false) {
 return getNoteTag(
-[Note](BugReporterContext &, BugReport &) { return std::string(Note); 
},
+[Note](BugReporterContext &,
+   PathSensitiveBugReport &) { return std::string(Note); },
 IsPrunable);
   }
 

diff  --git a/clang/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp
index f7cee71ef0a1..aada05db2cbc 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp
@@ -53,7 +53,7 @@ void 
CXXSelfAssignmentChecker::checkBeginFunction(CheckerContext ) const {
 
   ProgramStateRef SelfAssignState = State->bindLoc(Param, ThisVal, LCtx);
   const NoteTag *SelfAssignTag =
-C.getNoteTag([MD](BugReport ) -> std::string {
+C.getNoteTag([MD](PathSensitiveBugReport ) -> std::string {
 SmallString<256> Msg;
 llvm::raw_svector_ostream Out(Msg);
 Out << "Assuming " << MD->getParamDecl(0)->getName() << " == *this";
@@ -63,7 +63,7 @@ void 
CXXSelfAssignmentChecker::checkBeginFunction(CheckerContext ) const {
 
   ProgramStateRef NonSelfAssignState = State->bindLoc(Param, ParamVal, LCtx);
   const NoteTag *NonSelfAssignTag =
-

[clang] 57f70d1 - [Analyzer] Mark constant member functions const in CheckerManager

2020-03-09 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-03-09T14:11:30+01:00
New Revision: 57f70d187706f572227b74c82c7446a3096f862f

URL: 
https://github.com/llvm/llvm-project/commit/57f70d187706f572227b74c82c7446a3096f862f
DIFF: 
https://github.com/llvm/llvm-project/commit/57f70d187706f572227b74c82c7446a3096f862f.diff

LOG: [Analyzer] Mark constant member functions const in CheckerManager

Most of the getter functions (and a reporter function) in
`CheckerManager` are constant but not marked as `const`. This prevents
functions having only a constant reference to `CheckerManager` using
these member functions. This patch fixes this issue.

Differential Revision: https://reviews.llvm.org/D75839

Added: 


Modified: 
clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
clang/lib/StaticAnalyzer/Core/CheckerManager.cpp

Removed: 




diff  --git a/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h 
b/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
index 246ff8f90d35..4454d7603b27 100644
--- a/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
+++ b/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
@@ -140,14 +140,14 @@ class CheckerManager {
   void finishedCheckerRegistration();
 
   const LangOptions () const { return LangOpts; }
-  AnalyzerOptions () { return AOptions; }
-  ASTContext () { return Context; }
+  AnalyzerOptions () const { return AOptions; }
+  ASTContext () const { return Context; }
 
   /// Emits an error through a DiagnosticsEngine about an invalid user supplied
   /// checker option value.
   void reportInvalidCheckerOptionValue(const CheckerBase *C,
StringRef OptionName,
-   StringRef ExpectedValueDesc);
+   StringRef ExpectedValueDesc) const;
 
   using CheckerRef = CheckerBase *;
   using CheckerTag = const void *;
@@ -620,7 +620,7 @@ class CheckerManager {
   /// Returns the checkers that have registered for callbacks of the
   /// given \p Kind.
   const std::vector &
-  getObjCMessageCheckers(ObjCMessageVisitKind Kind);
+  getObjCMessageCheckers(ObjCMessageVisitKind Kind) const;
 
   std::vector PreObjCMessageCheckers;
   std::vector PostObjCMessageCheckers;

diff  --git a/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp 
b/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
index a9361837cf68..ce5e4a46d3e2 100644
--- a/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -61,7 +61,8 @@ void CheckerManager::finishedCheckerRegistration() {
 }
 
 void CheckerManager::reportInvalidCheckerOptionValue(
-const CheckerBase *C, StringRef OptionName, StringRef ExpectedValueDesc) {
+const CheckerBase *C, StringRef OptionName,
+StringRef ExpectedValueDesc) const {
 
   Context.getDiagnostics()
   .Report(diag::err_analyzer_checker_option_invalid_input)
@@ -249,7 +250,7 @@ void 
CheckerManager::runCheckersForObjCMessage(ObjCMessageVisitKind visitKind,
 }
 
 const std::vector &
-CheckerManager::getObjCMessageCheckers(ObjCMessageVisitKind Kind) {
+CheckerManager::getObjCMessageCheckers(ObjCMessageVisitKind Kind) const {
   switch (Kind) {
   case ObjCMessageVisitKind::Pre:
 return PreObjCMessageCheckers;



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


[clang] eb90692 - [Analyzer] Rename test `iterator-modelling.cpp` to `iterator-modeling.cpp`

2020-03-30 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-03-30T09:23:35+02:00
New Revision: eb90692d8a660bb3172c9c2cc5adb3864c626d96

URL: 
https://github.com/llvm/llvm-project/commit/eb90692d8a660bb3172c9c2cc5adb3864c626d96
DIFF: 
https://github.com/llvm/llvm-project/commit/eb90692d8a660bb3172c9c2cc5adb3864c626d96.diff

LOG: [Analyzer] Rename test `iterator-modelling.cpp` to `iterator-modeling.cpp`

Typo fix.

Added: 
clang/test/Analysis/iterator-modeling.cpp

Modified: 


Removed: 
clang/test/Analysis/iterator-modelling.cpp



diff  --git a/clang/test/Analysis/iterator-modelling.cpp 
b/clang/test/Analysis/iterator-modeling.cpp
similarity index 100%
rename from clang/test/Analysis/iterator-modelling.cpp
rename to clang/test/Analysis/iterator-modeling.cpp



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


[clang] afcb77c - [Analyzer] Fix for incorrect use of container and iterator checkers

2020-03-30 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-03-30T09:14:45+02:00
New Revision: afcb77cc88a2ed489bbd383774c54daa82340761

URL: 
https://github.com/llvm/llvm-project/commit/afcb77cc88a2ed489bbd383774c54daa82340761
DIFF: 
https://github.com/llvm/llvm-project/commit/afcb77cc88a2ed489bbd383774c54daa82340761.diff

LOG: [Analyzer] Fix for incorrect use of container and iterator checkers

Iterator checkers (and planned container checkers) need the option
aggressive-binary-operation-simplification to be enabled. Without this
option they may cause assertions. To prevent such misuse, this patch adds
a preventive check which issues a warning and denies the registartion of
the checker if this option is disabled.

Differential Revision: https://reviews.llvm.org/D75171

Added: 

clang/test/Analysis/container-modeling-no-aggressive-binary-operation-simplification-warn.cpp

clang/test/Analysis/iterator-modeling-no-aggressive-binary-operation-simplification-no-crash.cpp

Modified: 
clang/include/clang/Basic/DiagnosticDriverKinds.td
clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
clang/test/Analysis/loop-widening-notes.cpp

Removed: 




diff  --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td 
b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 5a3249215189..27ffd562c6de 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -344,6 +344,8 @@ def err_analyzer_checker_option_unknown : Error<
   "checker '%0' has no option called '%1'">;
 def err_analyzer_checker_option_invalid_input : Error<
   "invalid input for checker option '%0', that expects %1">;
+def err_analyzer_checker_incompatible_analyzer_option : Error<
+  "checker cannot be enabled with analyzer option '%0' == %1">;
 
 def err_drv_invalid_hvx_length : Error<
   "-mhvx-length is not supported without a -mhvx/-mhvx= flag">;

diff  --git a/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp 
b/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
index 0af10cec9378..73c6517fd0eb 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
@@ -12,6 +12,7 @@
 
 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
 #include "clang/AST/DeclTemplate.h"
+#include "clang/Driver/DriverDiagnostic.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
 #include "clang/StaticAnalyzer/Core/Checker.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
@@ -1068,5 +1069,15 @@ void ento::registerContainerModeling(CheckerManager 
) {
 }
 
 bool ento::shouldRegisterContainerModeling(const CheckerManager ) {
+  if (!mgr.getLangOpts().CPlusPlus)
+return false;
+
+  if (!mgr.getAnalyzerOptions().ShouldAggressivelySimplifyBinaryOperation) {
+mgr.getASTContext().getDiagnostics().Report(
+diag::err_analyzer_checker_incompatible_analyzer_option)
+  << "aggressive-binary-operation-simplification" << "false";
+return false;
+  }
+
   return true;
 }

diff  --git 
a/clang/test/Analysis/container-modeling-no-aggressive-binary-operation-simplification-warn.cpp
 
b/clang/test/Analysis/container-modeling-no-aggressive-binary-operation-simplification-warn.cpp
new file mode 100644
index ..1a55e878f9ef
--- /dev/null
+++ 
b/clang/test/Analysis/container-modeling-no-aggressive-binary-operation-simplification-warn.cpp
@@ -0,0 +1,7 @@
+// RUN: %clang_analyze_cc1 -std=c++11\
+// RUN: -analyzer-checker=core,cplusplus,alpha.cplusplus.ContainerModeling\
+// RUN: %s 2>&1 | FileCheck %s
+
+// XFAIL: *
+
+// CHECK: checker cannot be enabled with analyzer option 
'aggressive-binary-operation-simplification' == false

diff  --git 
a/clang/test/Analysis/iterator-modeling-no-aggressive-binary-operation-simplification-no-crash.cpp
 
b/clang/test/Analysis/iterator-modeling-no-aggressive-binary-operation-simplification-no-crash.cpp
new file mode 100644
index ..4b7c52db5462
--- /dev/null
+++ 
b/clang/test/Analysis/iterator-modeling-no-aggressive-binary-operation-simplification-no-crash.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_analyze_cc1 -std=c++11\
+// RUN: 
-analyzer-checker=core,cplusplus,debug.DebugIteratorModeling,debug.ExprInspection\
+// RUN: %s 2>&1 | FileCheck %s
+
+// XFAIL: *
+
+// CHECK: checker cannot be enabled with analyzer option 
'aggressive-binary-operation-simplification' == false
+
+#include "Inputs/system-header-simulator-cxx.h"
+
+void clang_analyzer_eval(bool);
+
+void comparison(std::vector ) {
+  clang_analyzer_eval(V.begin() == V.end()); // no-crash
+}

diff  --git a/clang/test/Analysis/loop-widening-notes.cpp 
b/clang/test/Analysis/loop-widening-notes.cpp
index 2c26a1490e5c..0ba71d030d05 100644
--- a/clang/test/Analysis/loop-widening-notes.cpp
+++ b/clang/test/Analysis/loop-widening-notes.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 

[clang] a3f4d17 - [Analyzer] Use note tags to track container begin and and changes

2020-03-26 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-03-26T07:56:28+01:00
New Revision: a3f4d17a1a53c4144a5bb7c14620a5d2790f36ea

URL: 
https://github.com/llvm/llvm-project/commit/a3f4d17a1a53c4144a5bb7c14620a5d2790f36ea
DIFF: 
https://github.com/llvm/llvm-project/commit/a3f4d17a1a53c4144a5bb7c14620a5d2790f36ea.diff

LOG: [Analyzer] Use note tags to track container begin and and changes

Container operations such as `push_back()`, `pop_front()`
etc. increment and decrement the abstract begin and end
symbols of containers. This patch introduces note tags
to `ContainerModeling` to track these changes. This helps
the user to better identify the source of errors related
to containers and iterators.

Differential Revision: https://reviews.llvm.org/D73720

Added: 


Modified: 
clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
clang/lib/StaticAnalyzer/Checkers/IteratorRangeChecker.cpp
clang/test/Analysis/container-modeling.cpp
clang/test/Analysis/iterator-range.cpp

Removed: 




diff  --git a/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp 
b/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
index 7d8dc8b8a0ab..b225a61db439 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
@@ -31,47 +31,43 @@ namespace {
 class ContainerModeling
   : public Checker {
 
-  void handleBegin(CheckerContext , const Expr *CE, const SVal ,
-   const SVal ) const;
-  void handleEnd(CheckerContext , const Expr *CE, const SVal ,
- const SVal ) const;
-  void handleAssignment(CheckerContext , const SVal ,
-const Expr *CE = nullptr,
-const SVal  = UndefinedVal()) const;
-  void handleAssign(CheckerContext , const SVal ) const;
-  void handleClear(CheckerContext , const SVal ) const;
-  void handlePushBack(CheckerContext , const SVal ) const;
-  void handlePopBack(CheckerContext , const SVal ) const;
-  void handlePushFront(CheckerContext , const SVal ) const;
-  void handlePopFront(CheckerContext , const SVal ) const;
-  void handleInsert(CheckerContext , const SVal ,
-const SVal ) const;
-  void handleErase(CheckerContext , const SVal , const SVal ) 
const;
-  void handleErase(CheckerContext , const SVal , const SVal ,
-   const SVal ) const;
-  void handleEraseAfter(CheckerContext , const SVal ,
-const SVal ) const;
-  void handleEraseAfter(CheckerContext , const SVal , const SVal ,
-const SVal ) const;
+  void handleBegin(CheckerContext , const Expr *CE, SVal RetVal,
+   SVal Cont) const;
+  void handleEnd(CheckerContext , const Expr *CE, SVal RetVal,
+ SVal Cont) const;
+  void handleAssignment(CheckerContext , SVal Cont, const Expr *CE = nullptr,
+SVal OldCont = UndefinedVal()) const;
+  void handleAssign(CheckerContext , SVal Cont, const Expr *ContE) const;
+  void handleClear(CheckerContext , SVal Cont, const Expr *ContE) const;
+  void handlePushBack(CheckerContext , SVal Cont, const Expr *ContE) const;
+  void handlePopBack(CheckerContext , SVal Cont, const Expr *ContE) const;
+  void handlePushFront(CheckerContext , SVal Cont, const Expr *ContE) const;
+  void handlePopFront(CheckerContext , SVal Cont, const Expr *ContE) const;
+  void handleInsert(CheckerContext , SVal Cont, SVal Iter) const;
+  void handleErase(CheckerContext , SVal Cont, SVal Iter) const;
+  void handleErase(CheckerContext , SVal Cont, SVal Iter1, SVal Iter2) const;
+  void handleEraseAfter(CheckerContext , SVal Cont, SVal Iter) const;
+  void handleEraseAfter(CheckerContext , SVal Cont, SVal Iter1,
+SVal Iter2) const;
+  const NoteTag *getChangeTag(CheckerContext , StringRef Text,
+  const MemRegion *ContReg,
+  const Expr *ContE) const;
   void printState(raw_ostream , ProgramStateRef State, const char *NL,
   const char *Sep) const override;
 
 public:
-  ContainerModeling() {}
+  ContainerModeling() = default;
 
   void checkPostCall(const CallEvent , CheckerContext ) const;
   void checkLiveSymbols(ProgramStateRef State, SymbolReaper ) const;
   void checkDeadSymbols(SymbolReaper , CheckerContext ) const;
 
-  typedef void (ContainerModeling::*NoItParamFn)(CheckerContext &,
- const SVal &) const;
-  typedef void (ContainerModeling::*OneItParamFn)(CheckerContext &,
-  const SVal &,
-  const SVal &) const;
-  typedef void (ContainerModeling::*TwoItParamFn)(CheckerContext &,
-  const SVal &,
-  const SVal &,
-   

[clang] 1a27d63 - [Analyzer] Only add container note tags to the operations of the affected container

2020-03-26 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-03-26T09:44:16+01:00
New Revision: 1a27d63a8891076ad9176f1a70f372003bc55c2f

URL: 
https://github.com/llvm/llvm-project/commit/1a27d63a8891076ad9176f1a70f372003bc55c2f
DIFF: 
https://github.com/llvm/llvm-project/commit/1a27d63a8891076ad9176f1a70f372003bc55c2f.diff

LOG: [Analyzer] Only add container note tags to the operations of the affected 
container

If an error happens which is related to a container the Container
Modeling checker adds note tags to all the container operations along
the bug path. This may be disturbing if there are other containers
beside the one which is affected by the bug. This patch restricts the
note tags to only the affected container and adjust the debug checkers
to be able to test this change.

Differential Revision: https://reviews.llvm.org/D75514

Added: 


Modified: 
clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
clang/lib/StaticAnalyzer/Checkers/DebugContainerModeling.cpp
clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
clang/test/Analysis/container-modeling.cpp

Removed: 




diff  --git a/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp 
b/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
index b225a61db439..8126fe8260c8 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
@@ -721,6 +721,9 @@ const NoteTag 
*ContainerModeling::getChangeTag(CheckerContext ,
 
   return C.getNoteTag(
   [Text, Name, ContReg](PathSensitiveBugReport ) -> std::string {
+if (!BR.isInteresting(ContReg))
+  return "";
+
 SmallString<256> Msg;
 llvm::raw_svector_ostream Out(Msg);
 Out << "Container " << (!Name.empty() ? ("'" + Name.str() + "' ") : "" 
)

diff  --git a/clang/lib/StaticAnalyzer/Checkers/DebugContainerModeling.cpp 
b/clang/lib/StaticAnalyzer/Checkers/DebugContainerModeling.cpp
index 8d0572723991..ce8dccb22333 100644
--- a/clang/lib/StaticAnalyzer/Checkers/DebugContainerModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/DebugContainerModeling.cpp
@@ -92,7 +92,19 @@ void 
DebugContainerModeling::analyzerContainerDataField(const CallExpr *CE,
   if (Field) {
 State = State->BindExpr(CE, C.getLocationContext(),
 nonloc::SymbolVal(Field));
-C.addTransition(State);
+
+// Progpagate interestingness from the container's data (marked
+// interesting by an `ExprInspection` debug call to the container
+// itself.
+const NoteTag *InterestingTag =
+  C.getNoteTag(
+  [Cont, Field](PathSensitiveBugReport ) -> std::string {
+if (BR.isInteresting(Field)) {
+  BR.markInteresting(Cont);
+}
+return "";
+  });
+C.addTransition(State, InterestingTag);
 return;
   }
 }

diff  --git a/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
index 10b27831d89f..97e287e7a221 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
@@ -52,9 +52,12 @@ class ExprInspectionChecker : public Checker ExprVal = None) const;
   ExplodedNode *reportBug(llvm::StringRef Msg, BugReporter ,
-  ExplodedNode *N) const;
+  ExplodedNode *N,
+  Optional ExprVal = None) const;
 
 public:
   bool evalCall(const CallEvent , CheckerContext ) const;
@@ -144,22 +147,28 @@ static const char *getArgumentValueString(const CallExpr 
*CE,
 }
 
 ExplodedNode *ExprInspectionChecker::reportBug(llvm::StringRef Msg,
-   CheckerContext ) const {
+   CheckerContext ,
+   Optional ExprVal) const {
   ExplodedNode *N = C.generateNonFatalErrorNode();
-  reportBug(Msg, C.getBugReporter(), N);
+  reportBug(Msg, C.getBugReporter(), N, ExprVal);
   return N;
 }
 
 ExplodedNode *ExprInspectionChecker::reportBug(llvm::StringRef Msg,
BugReporter ,
-   ExplodedNode *N) const {
+   ExplodedNode *N,
+   Optional ExprVal) const {
   if (!N)
 return nullptr;
 
   if (!BT)
 BT.reset(new BugType(this, "Checking analyzer assumptions", "debug"));
 
-  BR.emitReport(std::make_unique(*BT, Msg, N));
+  auto R = std::make_unique(*BT, Msg, N);
+  if (ExprVal) {
+R->markInteresting(*ExprVal);
+  }
+  BR.emitReport(std::move(R));
   return N;
 }
 
@@ -406,7 +415,8 @@ void ExprInspectionChecker::analyzerExpress(const CallExpr 
*CE,
 return;
   

[clang] 6cff2e9 - [Analyzer] Bugfix for CheckerRegistry

2020-03-19 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-03-19T16:06:42+01:00
New Revision: 6cff2e9f7884690d480b961f78806cbb91773b34

URL: 
https://github.com/llvm/llvm-project/commit/6cff2e9f7884690d480b961f78806cbb91773b34
DIFF: 
https://github.com/llvm/llvm-project/commit/6cff2e9f7884690d480b961f78806cbb91773b34.diff

LOG: [Analyzer] Bugfix for CheckerRegistry

`CheckerRegistry` registers a checker either if it is excplicitly
enabled or it is a dependency of an explicitly enabled checker and is
not explicitly disabled. In both cases it is also important that the
checker should be registered (`shoudRegister`//XXX//`()` returns true).

Currently there is a bug here: if the dependenct checker is not
explicitly disabled it is registered regardless of whether it should
be registered. This patch fixes this bug.

Differential Revision: https://reviews.llvm.org/D75842

Added: 


Modified: 
clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h
clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp

Removed: 




diff  --git a/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h 
b/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h
index 8f0c7edc58b4..8830542f27d8 100644
--- a/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h
+++ b/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h
@@ -167,7 +167,7 @@ class CheckerRegistry {
 }
 
 bool isDisabled(const LangOptions ) const {
-  return State == StateFromCmdLine::State_Disabled && ShouldRegister(LO);
+  return State == StateFromCmdLine::State_Disabled || !ShouldRegister(LO);
 }
 
 // Since each checker must have a 
diff erent full name, we can identify

diff  --git a/clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp 
b/clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp
index d0cf291eb2b8..8027d3338b69 100644
--- a/clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp
+++ b/clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp
@@ -81,6 +81,66 @@ TEST(RegisterCustomCheckers, CheckLocationIncDec) {
   runCheckerOnCode("void f() { int *p; (*p)++; }"));
 }
 
+//===--===//
+// Unsatisfied checker dependency
+//===--===//
+
+class PrerequisiteChecker : public Checker {
+public:
+  void checkASTCodeBody(const Decl *D, AnalysisManager ,
+BugReporter ) const {
+BR.EmitBasicReport(D, this, "Prerequisite", categories::LogicError,
+   "This is the prerequisite checker",
+   PathDiagnosticLocation(D, Mgr.getSourceManager()), {});
+  }
+};
+
+void registerPrerequisiteChecker(CheckerManager ) {
+  mgr.registerChecker();
+}
+
+bool shouldRegisterPrerequisiteChecker(const LangOptions ) {
+  return false;
+}
+
+class DependentChecker : public Checker {
+public:
+  void checkASTCodeBody(const Decl *D, AnalysisManager ,
+BugReporter ) const {
+BR.EmitBasicReport(D, this, "Dependent", categories::LogicError,
+   "This is the Dependent Checker",
+   PathDiagnosticLocation(D, Mgr.getSourceManager()), {});
+  }
+};
+
+void registerDependentChecker(CheckerManager ) {
+  mgr.registerChecker();
+}
+
+bool shouldRegisterDependentChecker(const LangOptions ) {
+  return true;
+}
+
+void addDependentChecker(AnalysisASTConsumer ,
+ AnalyzerOptions ) {
+  AnOpts.CheckersAndPackages = {{"custom.Dependent", true}};
+  AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry ) {
+ Registry.addChecker(registerPrerequisiteChecker,
+ shouldRegisterPrerequisiteChecker,
+ "custom.Prerequisite", "Description", "", false);
+ Registry.addChecker(registerDependentChecker,
+ shouldRegisterDependentChecker,
+ "custom.Dependent", "Description", "", false);
+ Registry.addDependency("custom.Dependent", "custom.Prerequisite");
+});
+}
+
+TEST(RegisterDependentCheckers, RegisterChecker) {
+  std::string Diags;
+  EXPECT_TRUE(runCheckerOnCode("void f() {;}", Diags));
+  EXPECT_EQ(Diags, "");
+}
+
 } // namespace
 } // namespace ento
 } // namespace clang



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


[clang] 60bad94 - [Analyzer] Iterator Modeling - Model `std::advance()`, `std::prev()` and `std::next()`

2020-03-23 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-03-23T15:29:55+01:00
New Revision: 60bad941a1c1b745f570da8251f2ba9ee8b7d06e

URL: 
https://github.com/llvm/llvm-project/commit/60bad941a1c1b745f570da8251f2ba9ee8b7d06e
DIFF: 
https://github.com/llvm/llvm-project/commit/60bad941a1c1b745f570da8251f2ba9ee8b7d06e.diff

LOG: [Analyzer] Iterator Modeling - Model `std::advance()`, `std::prev()` and 
`std::next()`

Whenever the analyzer budget runs out just at the point where
`std::advance()`, `std::prev()` or `std::next()` is invoked the function
are not inlined. This results in strange behavior such as
`std::prev(v.end())` equals `v.end()`. To prevent this model these
functions if they were not inlined. It may also happend that although
`std::advance()` is inlined but a function it calls inside (e.g.
`__advance()` in some implementations) is not. This case is also handled
in this patch.

Differential Revision: https://reviews.llvm.org/D76361

Added: 


Modified: 
clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
clang/test/Analysis/Inputs/system-header-simulator-cxx.h
clang/test/Analysis/iterator-modelling.cpp

Removed: 




diff  --git a/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp 
b/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
index 955a40b0d4b7..9a813b0a1a45 100644
--- a/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
@@ -86,6 +86,15 @@ class IteratorModeling
 : public Checker,
  check::Bind, check::LiveSymbols, check::DeadSymbols> {
 
+  using AdvanceFn = void (IteratorModeling::*)(CheckerContext &, const Expr *,
+   SVal, SVal, SVal) const;
+
+  void handleOverloadedOperator(CheckerContext , const CallEvent ,
+OverloadedOperatorKind Op) const;
+  void handleAdvanceLikeFunction(CheckerContext , const CallEvent ,
+ const Expr *OrigExpr,
+ const AdvanceFn *Handler) const;
+
   void handleComparison(CheckerContext , const Expr *CE, SVal RetVal,
 const SVal , const SVal ,
 OverloadedOperatorKind Op) const;
@@ -99,13 +108,39 @@ class IteratorModeling
   void handleRandomIncrOrDecr(CheckerContext , const Expr *CE,
   OverloadedOperatorKind Op, const SVal ,
   const SVal , const SVal ) const;
+  void handleAdvance(CheckerContext , const Expr *CE, SVal RetVal, SVal Iter,
+ SVal Amount) const;
+  void handlePrev(CheckerContext , const Expr *CE, SVal RetVal, SVal Iter,
+  SVal Amount) const;
+  void handleNext(CheckerContext , const Expr *CE, SVal RetVal, SVal Iter,
+  SVal Amount) const;
   void assignToContainer(CheckerContext , const Expr *CE, const SVal ,
  const MemRegion *Cont) const;
+  bool noChangeInAdvance(CheckerContext , SVal Iter, const Expr *CE) const;
   void printState(raw_ostream , ProgramStateRef State, const char *NL,
   const char *Sep) const override;
 
+  // std::advance, std::prev & std::next
+  CallDescriptionMap AdvanceLikeFunctions = {
+  // template
+  // void advance(InputIt& it, Distance n);
+  {{{"std", "advance"}, 2}, ::handleAdvance},
+
+  // template
+  // BidirIt prev(
+  //   BidirIt it,
+  //   typename std::iterator_traits::
diff erence_type n = 1);
+  {{{"std", "prev"}, 2}, ::handlePrev},
+
+  // template
+  // ForwardIt next(
+  //   ForwardIt it,
+  //   typename std::iterator_traits::
diff erence_type n = 1);
+  {{{"std", "next"}, 2}, ::handleNext},
+  };
+
 public:
-  IteratorModeling() {}
+  IteratorModeling() = default;
 
   void checkPostCall(const CallEvent , CheckerContext ) const;
   void checkBind(SVal Loc, SVal Val, const Stmt *S, CheckerContext ) const;
@@ -123,6 +158,7 @@ ProgramStateRef relateSymbols(ProgramStateRef State, 
SymbolRef Sym1,
   SymbolRef Sym2, bool Equal);
 bool isBoundThroughLazyCompoundVal(const Environment ,
const MemRegion *Reg);
+const ExplodedNode *findCallEnter(const ExplodedNode *Node, const Expr *Call);
 
 } // namespace
 
@@ -135,101 +171,52 @@ void IteratorModeling::checkPostCall(const CallEvent 
,
 
   if (Func->isOverloadedOperator()) {
 const auto Op = Func->getOverloadedOperator();
-if (isSimpleComparisonOperator(Op)) {
-  const auto *OrigExpr = Call.getOriginExpr();
-  if (!OrigExpr)
-return;
-
-  if (const auto *InstCall = dyn_cast()) {
-handleComparison(C, OrigExpr, Call.getReturnValue(),
- InstCall->getCXXThisVal(), Call.getArgSVal(0), Op);
-return;
-  }
-
-  handleComparison(C, OrigExpr, Call.getReturnValue(), 

[clang] ccc0d35 - [Analyzer] IteratorRangeChecker verify `std::advance()`, `std::prev()` and `std::next()`

2020-03-23 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-03-23T17:33:26+01:00
New Revision: ccc0d351817bedf3a979144238ffb8e2797285d4

URL: 
https://github.com/llvm/llvm-project/commit/ccc0d351817bedf3a979144238ffb8e2797285d4
DIFF: 
https://github.com/llvm/llvm-project/commit/ccc0d351817bedf3a979144238ffb8e2797285d4.diff

LOG: [Analyzer] IteratorRangeChecker verify `std::advance()`, `std::prev()` and 
`std::next()`

Upon calling one of the functions `std::advance()`, `std::prev()` and
`std::next()` iterators could get out of their valid range which leads
to undefined behavior. If all these funcions are inlined together with
the functions they call internally (e.g. `__advance()` called by
`std::advance()` in some implementations) the error is detected by
`IteratorRangeChecker` but the bug location is inside the STL
implementation. Even worse, if the budget runs out and one of the calls
is not inlined the bug remains undetected. This patch fixes this
behavior: all the bugs are detected at the point of the STL function
invocation.

Differential Revision: https://reviews.llvm.org/D76379

Added: 


Modified: 
clang/lib/StaticAnalyzer/Checkers/IteratorRangeChecker.cpp
clang/test/Analysis/iterator-range.cpp

Removed: 




diff  --git a/clang/lib/StaticAnalyzer/Checkers/IteratorRangeChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/IteratorRangeChecker.cpp
index bd8b84d464b6..f9b493bf9bb0 100644
--- a/clang/lib/StaticAnalyzer/Checkers/IteratorRangeChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/IteratorRangeChecker.cpp
@@ -31,18 +31,30 @@ class IteratorRangeChecker
 
   std::unique_ptr OutOfRangeBugType;
 
-  void verifyDereference(CheckerContext , const SVal ) const;
-  void verifyIncrement(CheckerContext , const SVal ) const;
-  void verifyDecrement(CheckerContext , const SVal ) const;
+  void verifyDereference(CheckerContext , SVal Val) const;
+  void verifyIncrement(CheckerContext , SVal Iter) const;
+  void verifyDecrement(CheckerContext , SVal Iter) const;
   void verifyRandomIncrOrDecr(CheckerContext , OverloadedOperatorKind Op,
-  const SVal , const SVal ) const;
-  void reportBug(const StringRef , const SVal ,
- CheckerContext , ExplodedNode *ErrNode) const;
+  SVal LHS, SVal RHS) const;
+  void verifyAdvance(CheckerContext , SVal LHS, SVal RHS) const;
+  void verifyPrev(CheckerContext , SVal LHS, SVal RHS) const;
+  void verifyNext(CheckerContext , SVal LHS, SVal RHS) const;
+  void reportBug(const StringRef , SVal Val, CheckerContext ,
+ ExplodedNode *ErrNode) const;
+
 public:
   IteratorRangeChecker();
 
   void checkPreCall(const CallEvent , CheckerContext ) const;
 
+  using AdvanceFn = void (IteratorRangeChecker::*)(CheckerContext &, SVal,
+   SVal) const;
+
+  CallDescriptionMap AdvanceFunctions = {
+  {{{"std", "advance"}, 2}, ::verifyAdvance},
+  {{{"std", "prev"}, 2}, ::verifyPrev},
+  {{{"std", "next"}, 2}, ::verifyNext},
+  };
 };
 
 bool isPastTheEnd(ProgramStateRef State, const IteratorPosition );
@@ -107,11 +119,23 @@ void IteratorRangeChecker::checkPreCall(const CallEvent 
,
 verifyDereference(C, Call.getArgSVal(0));
   }
 }
+  } else {
+const AdvanceFn *Verifier = AdvanceFunctions.lookup(Call);
+if (Verifier) {
+  if (Call.getNumArgs() > 1) {
+(this->**Verifier)(C, Call.getArgSVal(0), Call.getArgSVal(1));
+  } else {
+auto  = C.getSValBuilder().getBasicValueFactory();
+(this->**Verifier)(
+C, Call.getArgSVal(0),
+nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(1;
+  }
+}
   }
 }
 
 void IteratorRangeChecker::verifyDereference(CheckerContext ,
- const SVal ) const {
+ SVal Val) const {
   auto State = C.getState();
   const auto *Pos = getIteratorPosition(State, Val);
   if (Pos && isPastTheEnd(State, *Pos)) {
@@ -123,24 +147,21 @@ void 
IteratorRangeChecker::verifyDereference(CheckerContext ,
   }
 }
 
-void IteratorRangeChecker::verifyIncrement(CheckerContext ,
-  const SVal ) const {
+void IteratorRangeChecker::verifyIncrement(CheckerContext , SVal Iter) const 
{
   auto  = C.getSValBuilder().getBasicValueFactory();
   verifyRandomIncrOrDecr(C, OO_Plus, Iter,
  nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(1;
 }
 
-void IteratorRangeChecker::verifyDecrement(CheckerContext ,
-  const SVal ) const {
+void IteratorRangeChecker::verifyDecrement(CheckerContext , SVal Iter) const 
{
   auto  = C.getSValBuilder().getBasicValueFactory();
   verifyRandomIncrOrDecr(C, OO_Minus, Iter,
  nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(1;
 }
 
 void 

[clang-tools-extra] 22808d6 - [clang-tidy] Buildbot failure fix for commit rGf5fd7486d6c0

2020-08-31 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-08-31T16:32:10+02:00
New Revision: 22808d693ef7f8cf61ceff506a320249a0bdb5ef

URL: 
https://github.com/llvm/llvm-project/commit/22808d693ef7f8cf61ceff506a320249a0bdb5ef
DIFF: 
https://github.com/llvm/llvm-project/commit/22808d693ef7f8cf61ceff506a320249a0bdb5ef.diff

LOG: [clang-tidy] Buildbot failure fix for commit rGf5fd7486d6c0

Commit `rGf5fd7486d6c0` caused a buildbot failure because exceptions are
disabled by default on one of the buildbots. This patch forcibly enables
exceptions for the affected test.

Added: 


Modified: 

clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-prefer-member-initializer.cpp

Removed: 




diff  --git 
a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-prefer-member-initializer.cpp
 
b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-prefer-member-initializer.cpp
index c65b6374ace2..a55a7d8208a6 100644
--- 
a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-prefer-member-initializer.cpp
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-prefer-member-initializer.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy %s cppcoreguidelines-prefer-member-initializer %t
+// RUN: %check_clang_tidy %s cppcoreguidelines-prefer-member-initializer %t -- 
-- -fcxx-exceptions
 
 class Simple1 {
   int n;



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


[clang-tools-extra] f5fd748 - [clang-tidy] New check readability-prefer-member-initializer

2020-08-31 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-08-31T15:59:29+02:00
New Revision: f5fd7486d6c0debb465de3e927fcc31884874280

URL: 
https://github.com/llvm/llvm-project/commit/f5fd7486d6c0debb465de3e927fcc31884874280
DIFF: 
https://github.com/llvm/llvm-project/commit/f5fd7486d6c0debb465de3e927fcc31884874280.diff

LOG: [clang-tidy] New check readability-prefer-member-initializer

Finds member initializations in the constructor body which can
be placed to the member initializers of the constructor instead.
This does not only improves the readability of the code but also
affects positively its performance. Class-member assignments
inside a control statement or following the first control
statement are ignored.

Differential Revision: https://reviews.llvm.org/D71199

Added: 

clang-tools-extra/clang-tidy/cppcoreguidelines/PreferMemberInitializerCheck.cpp

clang-tools-extra/clang-tidy/cppcoreguidelines/PreferMemberInitializerCheck.h

clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-prefer-member-initializer.rst

clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-prefer-member-initializer-modernize-use-default-member-init-assignment.cpp

clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-prefer-member-initializer-modernize-use-default-member-init.cpp

clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-prefer-member-initializer.cpp

Modified: 
clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt

clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
clang-tools-extra/docs/ReleaseNotes.rst
clang-tools-extra/docs/clang-tidy/checks/list.rst

Removed: 




diff  --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
index 39c2c552eb73..a9f5b3e0c15b 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
@@ -13,6 +13,7 @@ add_clang_library(clangTidyCppCoreGuidelinesModule
   NarrowingConversionsCheck.cpp
   NoMallocCheck.cpp
   OwningMemoryCheck.cpp
+  PreferMemberInitializerCheck.cpp
   ProBoundsArrayToPointerDecayCheck.cpp
   ProBoundsConstantArrayIndexCheck.cpp
   ProBoundsPointerArithmeticCheck.cpp

diff  --git 
a/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
 
b/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
index 4cb5022888d3..bf613109f0eb 100644
--- 
a/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
+++ 
b/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
@@ -22,6 +22,7 @@
 #include "NarrowingConversionsCheck.h"
 #include "NoMallocCheck.h"
 #include "OwningMemoryCheck.h"
+#include "PreferMemberInitializerCheck.h"
 #include "ProBoundsArrayToPointerDecayCheck.h"
 #include "ProBoundsConstantArrayIndexCheck.h"
 #include "ProBoundsPointerArithmeticCheck.h"
@@ -66,6 +67,8 @@ class CppCoreGuidelinesModule : public ClangTidyModule {
 "cppcoreguidelines-non-private-member-variables-in-classes");
 CheckFactories.registerCheck(
 "cppcoreguidelines-owning-memory");
+CheckFactories.registerCheck(
+"cppcoreguidelines-prefer-member-initializer");
 CheckFactories.registerCheck(
 "cppcoreguidelines-pro-bounds-array-to-pointer-decay");
 CheckFactories.registerCheck(

diff  --git 
a/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferMemberInitializerCheck.cpp
 
b/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferMemberInitializerCheck.cpp
new file mode 100644
index ..97ae586f9fdb
--- /dev/null
+++ 
b/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferMemberInitializerCheck.cpp
@@ -0,0 +1,233 @@
+//===--- PreferMemberInitializerCheck.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 "PreferMemberInitializerCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+static bool isControlStatement(const Stmt *S) {
+  return isa(S) || isa(S) || isa(S) ||
+ isa(S) || isa(S) || isa(S) ||
+ isa(S) || isa(S) || isa(S);
+}
+
+static bool isNoReturnCallStatement(const Stmt *S) {
+  const auto *Call = dyn_cast(S);
+  if (!Call)
+return false;
+
+  const FunctionDecl *Func = Call->getDirectCallee();
+  if (!Func)
+return false;
+
+  return Func->isNoReturn();
+}
+
+static bool isLiteral(const Expr *E) {
+  return isa(E) || 

[clang-tools-extra] 14dd073 - [Clang-Tidy] New check `bugprone-redundant-branch-condition`

2020-08-31 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-08-31T16:00:59+02:00
New Revision: 14dd0737822ba476803320a2ff37a1012174d312

URL: 
https://github.com/llvm/llvm-project/commit/14dd0737822ba476803320a2ff37a1012174d312
DIFF: 
https://github.com/llvm/llvm-project/commit/14dd0737822ba476803320a2ff37a1012174d312.diff

LOG: [Clang-Tidy] New check `bugprone-redundant-branch-condition`

Checking the same condition again in a nested `if` usually make no sense,
except if the value of the expression could have been changed between
the two checks. Although compilers may optimize this out, such code is
suspicious: the programmer may have meant to check something else.
Therefore it is worth to find such places in the code and notify the
user about the problem.

This patch implements a basic check for this problem. Currently it
only detects redundant conditions where the condition is a variable of
integral type. It also detects the possible bug if the variable is in an
//or// or //and// logical expression in the inner if and/or the variable
is in an //and// logical expression in the outer if statement. Negated
cases are not handled yet.

Differential Revision: https://reviews.llvm.org/D81272

Added: 
clang-tools-extra/clang-tidy/bugprone/RedundantBranchConditionCheck.cpp
clang-tools-extra/clang-tidy/bugprone/RedundantBranchConditionCheck.h

clang-tools-extra/docs/clang-tidy/checks/bugprone-redundant-branch-condition.rst

clang-tools-extra/test/clang-tidy/checkers/bugprone-redundant-branch-condition.cpp

Modified: 
clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
clang-tools-extra/docs/ReleaseNotes.rst
clang-tools-extra/docs/clang-tidy/checks/list.rst

Removed: 




diff  --git a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp 
b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
index 3f735a8484d8..1556a2924f59 100644
--- a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
@@ -38,6 +38,7 @@
 #include "NotNullTerminatedResultCheck.h"
 #include "ParentVirtualCallCheck.h"
 #include "PosixReturnCheck.h"
+#include "RedundantBranchConditionCheck.h"
 #include "ReservedIdentifierCheck.h"
 #include "SignedCharMisuseCheck.h"
 #include "SizeofContainerCheck.h"
@@ -119,6 +120,8 @@ class BugproneModule : public ClangTidyModule {
 "bugprone-move-forwarding-reference");
 CheckFactories.registerCheck(
 "bugprone-multiple-statement-macro");
+CheckFactories.registerCheck(
+"bugprone-redundant-branch-condition");
 CheckFactories.registerCheck(
 "bugprone-narrowing-conversions");
 CheckFactories.registerCheck("bugprone-no-escape");

diff  --git a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
index 6e7a94928a5a..169e0529d872 100644
--- a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
@@ -33,6 +33,7 @@ add_clang_library(clangTidyBugproneModule
   NotNullTerminatedResultCheck.cpp
   ParentVirtualCallCheck.cpp
   PosixReturnCheck.cpp
+  RedundantBranchConditionCheck.cpp
   ReservedIdentifierCheck.cpp
   SignedCharMisuseCheck.cpp
   SizeofContainerCheck.cpp

diff  --git 
a/clang-tools-extra/clang-tidy/bugprone/RedundantBranchConditionCheck.cpp 
b/clang-tools-extra/clang-tidy/bugprone/RedundantBranchConditionCheck.cpp
new file mode 100644
index ..137356acbdba
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/RedundantBranchConditionCheck.cpp
@@ -0,0 +1,153 @@
+//===--- RedundantBranchConditionCheck.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 "RedundantBranchConditionCheck.h"
+#include "../utils/Aliasing.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Analysis/Analyses/ExprMutationAnalyzer.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+using clang::tidy::utils::hasPtrOrReferenceInFunc;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+static const char CondVarStr[] = "cond_var";
+static const char OuterIfStr[] = "outer_if";
+static const char InnerIfStr[] = "inner_if";
+static const char FuncStr[] = "func";
+
+/// Returns whether `Var` is changed in `S` before `NextS`.
+static bool isChangedBefore(const Stmt *S, const Stmt *NextS,
+const VarDecl *Var, ASTContext *Context) {
+  ExprMutationAnalyzer MutAn(*S, *Context);
+  const auto  = Context->getSourceManager();
+  

[clang-tools-extra] d6c9dc3 - [clang-tidy] Remove obsolete checker google-runtime-references

2020-10-06 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-10-06T14:03:55+02:00
New Revision: d6c9dc3c17e444e007758c01507bb5280532c9f8

URL: 
https://github.com/llvm/llvm-project/commit/d6c9dc3c17e444e007758c01507bb5280532c9f8
DIFF: 
https://github.com/llvm/llvm-project/commit/d6c9dc3c17e444e007758c01507bb5280532c9f8.diff

LOG: [clang-tidy] Remove obsolete checker google-runtime-references

The rules which is the base of this checker is removed from the
//Google C++ Style Guide// in May:
[[ https://github.com/google/styleguide/pull/553 | Update C++ styleguide ]].
Now this checker became obsolete.

Differential Revision: https://reviews.llvm.org/D88831

Added: 


Modified: 
clang-tools-extra/clang-tidy/google/CMakeLists.txt
clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp
clang-tools-extra/docs/ReleaseNotes.rst

Removed: 
clang-tools-extra/clang-tidy/google/NonConstReferences.cpp
clang-tools-extra/clang-tidy/google/NonConstReferences.h
clang-tools-extra/docs/clang-tidy/checks/google-runtime-references.rst
clang-tools-extra/test/clang-tidy/checkers/google-runtime-references.cpp



diff  --git a/clang-tools-extra/clang-tidy/google/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/google/CMakeLists.txt
index e38ba8abb78d..e1e5fc7a85a7 100644
--- a/clang-tools-extra/clang-tidy/google/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/google/CMakeLists.txt
@@ -16,7 +16,6 @@ add_clang_library(clangTidyGoogleModule
   GlobalVariableDeclarationCheck.cpp
   GoogleTidyModule.cpp
   IntegerTypesCheck.cpp
-  NonConstReferences.cpp
   OverloadedUnaryAndCheck.cpp
   TodoCommentCheck.cpp
   UnnamedNamespaceInHeaderCheck.cpp

diff  --git a/clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp 
b/clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp
index 4c6b791f8cdd..d8fcf3fed94f 100644
--- a/clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp
@@ -23,7 +23,6 @@
 #include "GlobalNamesInHeadersCheck.h"
 #include "GlobalVariableDeclarationCheck.h"
 #include "IntegerTypesCheck.h"
-#include "NonConstReferences.h"
 #include "OverloadedUnaryAndCheck.h"
 #include "TodoCommentCheck.h"
 #include "UnnamedNamespaceInHeaderCheck.h"
@@ -63,8 +62,6 @@ class GoogleModule : public ClangTidyModule {
 "google-runtime-int");
 CheckFactories.registerCheck(
 "google-runtime-operator");
-CheckFactories.registerCheck(
-"google-runtime-references");
 CheckFactories
 .registerCheck(
 "google-readability-avoid-underscore-in-googletest-name");

diff  --git a/clang-tools-extra/clang-tidy/google/NonConstReferences.cpp 
b/clang-tools-extra/clang-tidy/google/NonConstReferences.cpp
deleted file mode 100644
index e0fb614dfe8b..
--- a/clang-tools-extra/clang-tidy/google/NonConstReferences.cpp
+++ /dev/null
@@ -1,148 +0,0 @@
-//===--- NonConstReferences.cpp - clang-tidy *- C++ 
-*-===//
-//
-// 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 "NonConstReferences.h"
-#include "../utils/OptionsUtils.h"
-#include "clang/AST/DeclBase.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
-#include "clang/ASTMatchers/ASTMatchers.h"
-
-using namespace clang::ast_matchers;
-
-namespace clang {
-namespace tidy {
-namespace google {
-namespace runtime {
-
-NonConstReferences::NonConstReferences(StringRef Name,
-   ClangTidyContext *Context)
-: ClangTidyCheck(Name, Context),
-  IncludedTypes(
-  utils::options::parseStringList(Options.get("IncludedTypes", ""))) {}
-
-void NonConstReferences::storeOptions(ClangTidyOptions::OptionMap ) {
-  Options.store(Opts, "IncludedTypes",
-utils::options::serializeStringList(IncludedTypes));
-}
-
-void NonConstReferences::registerMatchers(MatchFinder *Finder) {
-  Finder->addMatcher(
-  parmVarDecl(
-  unless(isInstantiated()),
-  hasType(references(
-  qualType(unless(isConstQualified())).bind("referenced_type"))),
-  unless(hasType(rValueReferenceType(
-  .bind("param"),
-  this);
-}
-
-void NonConstReferences::check(const MatchFinder::MatchResult ) {
-  const auto *Parameter = Result.Nodes.getNodeAs("param");
-  const auto *Function =
-  dyn_cast_or_null(Parameter->getParentFunctionOrMethod());
-
-  if (Function == nullptr || Function->isImplicit())
-return;
-
-  if (Function->getLocation().isMacroID())
-return;
-
-  if (!Function->isCanonicalDecl())
-return;
-
-  if (const auto *Method = dyn_cast(Function)) {
-// Don't warn on implementations of an interface using references.
-if 

[clang] facad21 - [Analyzer] Fix for `ExprEngine::computeObjectUnderConstruction()` for base and delegating consturctor initializers

2020-09-25 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-09-25T13:28:22+02:00
New Revision: facad21b29839a08fdf448eb4dd5a4e31e293b9b

URL: 
https://github.com/llvm/llvm-project/commit/facad21b29839a08fdf448eb4dd5a4e31e293b9b
DIFF: 
https://github.com/llvm/llvm-project/commit/facad21b29839a08fdf448eb4dd5a4e31e293b9b.diff

LOG: [Analyzer] Fix for `ExprEngine::computeObjectUnderConstruction()` for base 
and delegating consturctor initializers

For /C++/ constructor initializers `ExprEngine:computeUnderConstruction()`
asserts that they are all member initializers. This is not neccessarily
true when this function is used to get the return value for the
construction context thus attempts to fetch return values of base and
delegating constructor initializers result in assertions. This small
patch fixes this issue.

Differential Revision: https://reviews.llvm.org/D85351

Added: 


Modified: 
clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
clang/unittests/StaticAnalyzer/TestReturnValueUnderConstruction.cpp

Removed: 




diff  --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index 802bc934cfb06..953a8ef58b447 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -132,10 +132,20 @@ SVal ExprEngine::computeObjectUnderConstruction(
 case ConstructionContext::SimpleConstructorInitializerKind: {
   const auto *ICC = cast(CC);
   const auto *Init = ICC->getCXXCtorInitializer();
-  assert(Init->isAnyMemberInitializer());
   const CXXMethodDecl *CurCtor = cast(LCtx->getDecl());
   Loc ThisPtr = SVB.getCXXThis(CurCtor, LCtx->getStackFrame());
   SVal ThisVal = State->getSVal(ThisPtr);
+  if (Init->isBaseInitializer()) {
+const auto *ThisReg = cast(ThisVal.getAsRegion());
+const CXXRecordDecl *BaseClass =
+  Init->getBaseClass()->getAsCXXRecordDecl();
+const auto *BaseReg =
+  MRMgr.getCXXBaseObjectRegion(BaseClass, ThisReg,
+   Init->isBaseVirtual());
+return SVB.makeLoc(BaseReg);
+  }
+  if (Init->isDelegatingInitializer())
+return ThisVal;
 
   const ValueDecl *Field;
   SVal FieldVal;
@@ -364,6 +374,11 @@ ProgramStateRef ExprEngine::updateObjectsUnderConstruction(
 case ConstructionContext::CXX17ElidedCopyConstructorInitializerKind:
 case ConstructionContext::SimpleConstructorInitializerKind: {
   const auto *ICC = cast(CC);
+  const auto *Init = ICC->getCXXCtorInitializer();
+  // Base and delegating initializers handled above
+  assert(Init->isAnyMemberInitializer() &&
+ "Base and delegating initializers should have been handled by"
+ "computeObjectUnderConstruction()");
   return addObjectUnderConstruction(State, ICC->getCXXCtorInitializer(),
 LCtx, V);
 }

diff  --git 
a/clang/unittests/StaticAnalyzer/TestReturnValueUnderConstruction.cpp 
b/clang/unittests/StaticAnalyzer/TestReturnValueUnderConstruction.cpp
index 5750d5918db32..eb0ee6c1fd8a0 100644
--- a/clang/unittests/StaticAnalyzer/TestReturnValueUnderConstruction.cpp
+++ b/clang/unittests/StaticAnalyzer/TestReturnValueUnderConstruction.cpp
@@ -23,8 +23,8 @@ class TestReturnValueUnderConstructionChecker
   : public Checker {
 public:
   void checkPostCall(const CallEvent , CheckerContext ) const {
-// Only calls with origin expression are checked. These are `returnC()`
-// and C::C().
+// Only calls with origin expression are checked. These are `returnC()`,
+// `returnD()`, C::C() and D::D().
 if (!Call.getOriginExpr())
   return;
 
@@ -35,6 +35,10 @@ class TestReturnValueUnderConstructionChecker
 Optional RetVal = Call.getReturnValueUnderConstruction();
 ASSERT_TRUE(RetVal);
 ASSERT_TRUE(RetVal->getAsRegion());
+
+const auto *RetReg = cast(RetVal->getAsRegion());
+const Expr *OrigExpr = Call.getOriginExpr();
+ASSERT_EQ(OrigExpr->getType(), RetReg->getValueType());
   }
 };
 
@@ -51,22 +55,65 @@ void addTestReturnValueUnderConstructionChecker(
 TEST(TestReturnValueUnderConstructionChecker,
  ReturnValueUnderConstructionChecker) {
   EXPECT_TRUE(runCheckerOnCode(
-  R"(class C {
- public:
-   C(int nn): n(nn) {}
-   virtual ~C() {}
- private:
-   int n;
- };
-
- C returnC(int m) {
-   C c(m);
-   return c;
- }
-
- void foo() {
-   C c = returnC(1); 
- })"));
+  R"(class C {
+ public:
+   C(int nn): n(nn) {}
+   virtual ~C() {}
+ private:
+   int n;
+ };
+
+ C 

[clang-tools-extra] dbd45b2 - [ASTMatchers] Fix `hasBody` for the descendants of `FunctionDecl`

2020-09-16 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-09-16T13:16:51+02:00
New Revision: dbd45b2db8e0c396fa20d4c72734c4f31f54af96

URL: 
https://github.com/llvm/llvm-project/commit/dbd45b2db8e0c396fa20d4c72734c4f31f54af96
DIFF: 
https://github.com/llvm/llvm-project/commit/dbd45b2db8e0c396fa20d4c72734c4f31f54af96.diff

LOG: [ASTMatchers] Fix `hasBody` for the descendants of `FunctionDecl`

//AST Matcher// `hasBody` is a polymorphic matcher that behaves
differently for loop statements and function declarations. The main
difference is the for functions declarations it does not only call
`FunctionDecl::getBody()` but first checks whether the declaration in
question is that specific declaration which has the body by calling
`FunctionDecl::doesThisDeclarationHaveABody()`. This is achieved by
specialization of the template `GetBodyMatcher`. Unfortunately template
specializations do not catch the descendants of the class for which the
template is specialized. Therefore it does not work correcly for the
descendants of `FunctionDecl`, such as `CXXMethodDecl`,
`CXXConstructorDecl`, `CXXDestructorDecl` etc. This patch fixes this
issue by using a template metaprogram.

The patch also introduces a new matcher `hasAnyBody` which matches
declarations which have a body present in the AST but not necessarily
belonging to that particular declaration.

Differential Revision: https://reviews.llvm.org/D87527

Added: 


Modified: 
clang-tools-extra/clang-tidy/modernize/UseEqualsDeleteCheck.cpp
clang/include/clang/ASTMatchers/ASTMatchers.h
clang/include/clang/ASTMatchers/ASTMatchersInternal.h
clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp

Removed: 




diff  --git a/clang-tools-extra/clang-tidy/modernize/UseEqualsDeleteCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/UseEqualsDeleteCheck.cpp
index ea4bf91b0d438..7d5ae89551731 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseEqualsDeleteCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseEqualsDeleteCheck.cpp
@@ -36,12 +36,12 @@ void UseEqualsDeleteCheck::registerMatchers(MatchFinder 
*Finder) {
   Finder->addMatcher(
   cxxMethodDecl(
   PrivateSpecialFn,
-  unless(anyOf(hasBody(stmt()), isDefaulted(), isDeleted(),
+  unless(anyOf(hasAnyBody(stmt()), isDefaulted(), isDeleted(),
ast_matchers::isTemplateInstantiation(),
// Ensure that all methods except private special member
// functions are defined.
hasParent(cxxRecordDecl(hasMethod(unless(
-   anyOf(PrivateSpecialFn, hasBody(stmt()), isPure(),
+   anyOf(PrivateSpecialFn, hasAnyBody(stmt()), 
isPure(),
  isDefaulted(), isDeleted()
   .bind(SpecialFunction),
   this);

diff  --git a/clang/include/clang/ASTMatchers/ASTMatchers.h 
b/clang/include/clang/ASTMatchers/ASTMatchers.h
index e670459fe8a2f..bd89906eadb0f 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -4879,7 +4879,9 @@ AST_MATCHER_P(ArraySubscriptExpr, hasBase,
 }
 
 /// Matches a 'for', 'while', 'do while' statement or a function
-/// definition that has a given body.
+/// definition that has a given body. Note that in case of functions
+/// this matcher only matches the definition itself and not the other
+/// declarations of the same function.
 ///
 /// Given
 /// \code
@@ -4889,6 +4891,18 @@ AST_MATCHER_P(ArraySubscriptExpr, hasBase,
 ///   matches 'for (;;) {}'
 /// with compoundStmt()
 ///   matching '{}'
+///
+/// Given
+/// \code
+///   void f();
+///   void f() {}
+/// \endcode
+/// hasBody(functionDecl())
+///   matches 'void f() {}'
+/// with compoundStmt()
+///   matching '{}'
+///   but does not match 'void f();'
+
 AST_POLYMORPHIC_MATCHER_P(hasBody,
   AST_POLYMORPHIC_SUPPORTED_TYPES(DoStmt, ForStmt,
   WhileStmt,
@@ -4900,6 +4914,30 @@ AST_POLYMORPHIC_MATCHER_P(hasBody,
   InnerMatcher.matches(*Statement, Finder, Builder));
 }
 
+/// Matches a function declaration that has a given body present in the AST.
+/// Note that this matcher matches all the declarations of a function whose
+/// body is present in the AST.
+///
+/// Given
+/// \code
+///   void f();
+///   void f() {}
+///   void g();
+/// \endcode
+/// hasAnyBody(functionDecl())
+///   matches both 'void f();'
+///   and 'void f() {}'
+/// with compoundStmt()
+///   matching '{}'
+///   but does not match 'void g();'
+AST_MATCHER_P(FunctionDecl, hasAnyBody,
+  internal::Matcher, InnerMatcher) {
+  const Stmt *const Statement = Node.getBody();
+  return (Statement != nullptr &&
+  InnerMatcher.matches(*Statement, Finder, Builder));
+}
+
+
 /// Matches compound statements where at least one substatement 

[clang-tools-extra] 779a2a2 - [clang-tidy] Crash fix for bugprone-misplaced-pointer-arithmetic-in-alloc

2020-09-16 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-09-16T13:16:44+02:00
New Revision: 779a2a2edcea89ad5f5bf99eeac90516542159d9

URL: 
https://github.com/llvm/llvm-project/commit/779a2a2edcea89ad5f5bf99eeac90516542159d9
DIFF: 
https://github.com/llvm/llvm-project/commit/779a2a2edcea89ad5f5bf99eeac90516542159d9.diff

LOG: [clang-tidy] Crash fix for bugprone-misplaced-pointer-arithmetic-in-alloc

Placement new operators on non-object types cause crash in
`bugprone-misplaced-pointer-arithmetic-in-alloc`. This patch fixes this
issue.

Differential Revision: https://reviews.llvm.org/D87683

Added: 


Modified: 

clang-tools-extra/clang-tidy/bugprone/MisplacedPointerArithmeticInAllocCheck.cpp

clang-tools-extra/test/clang-tidy/checkers/bugprone-misplaced-pointer-arithmetic-in-alloc.cpp

Removed: 




diff  --git 
a/clang-tools-extra/clang-tidy/bugprone/MisplacedPointerArithmeticInAllocCheck.cpp
 
b/clang-tools-extra/clang-tidy/bugprone/MisplacedPointerArithmeticInAllocCheck.cpp
index 2a6a0ae53a4f3..6208cb5cfc9dc 100644
--- 
a/clang-tools-extra/clang-tidy/bugprone/MisplacedPointerArithmeticInAllocCheck.cpp
+++ 
b/clang-tools-extra/clang-tidy/bugprone/MisplacedPointerArithmeticInAllocCheck.cpp
@@ -77,9 +77,9 @@ void MisplacedPointerArithmeticInAllocCheck::check(
   CallName = "operator new[]";
 } else {
   const auto *CtrE = New->getConstructExpr();
-  if (!CtrE->getArg(CtrE->getNumArgs() - 1)
-   ->getType()
-   ->isIntegralOrEnumerationType())
+  if (!CtrE || !CtrE->getArg(CtrE->getNumArgs() - 1)
+ ->getType()
+ ->isIntegralOrEnumerationType())
 return;
   CallName = "operator new";
 }

diff  --git 
a/clang-tools-extra/test/clang-tidy/checkers/bugprone-misplaced-pointer-arithmetic-in-alloc.cpp
 
b/clang-tools-extra/test/clang-tidy/checkers/bugprone-misplaced-pointer-arithmetic-in-alloc.cpp
index 42250da2610df..00d12891cde88 100644
--- 
a/clang-tools-extra/test/clang-tidy/checkers/bugprone-misplaced-pointer-arithmetic-in-alloc.cpp
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/bugprone-misplaced-pointer-arithmetic-in-alloc.cpp
@@ -51,3 +51,14 @@ void bad_new_array(int n, int m) {
   // CHECK-FIXES: p = new char[n - m] + 10;
   // FIXME: should be p = new char[n - m + 10];
 }
+
+namespace std {
+typedef decltype(sizeof(void*)) size_t;
+}
+
+void* operator new(std::size_t, void*);
+
+void placement_new_ptr(void *buf, C *old) {
+  C **p = new (buf) C*(old) + 1;
+  // CHECK-MESSAGES-NOT: :[[@LINE-1]]:11: warning: arithmetic operation is 
applied to the result of operator new() instead of its size-like argument
+}



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


[clang] d70ec36 - [Analyzer][NFC] Remove the SubEngine interface

2020-05-26 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-05-26T19:56:55+02:00
New Revision: d70ec366c91b2a5fc6334e6f6ca9c4d9a6785c5e

URL: 
https://github.com/llvm/llvm-project/commit/d70ec366c91b2a5fc6334e6f6ca9c4d9a6785c5e
DIFF: 
https://github.com/llvm/llvm-project/commit/d70ec366c91b2a5fc6334e6f6ca9c4d9a6785c5e.diff

LOG: [Analyzer][NFC] Remove the SubEngine interface

The `SubEngine` interface is an interface with only one implementation
`EpxrEngine`. Adding other implementations are difficult and very
unlikely in the near future. Currently, if anything from `ExprEngine` is
to be exposed to other classes it is moved to `SubEngine` which
restricts the alternative implementations. The virtual methods are have
a slight perofrmance impact. Furthermore, instead of the `LLVM`-style
inheritance a native inheritance is used here, which renders `LLVM`
functions like e.g. `cast()` unusable here. This patch removes this
interface and allows usage of `ExprEngine` directly.

Differential Revision: https://reviews.llvm.org/D80548

Added: 


Modified: 
clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h

clang/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h
clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h

clang/include/clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h
clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
clang/lib/StaticAnalyzer/Core/CMakeLists.txt
clang/lib/StaticAnalyzer/Core/CallEvent.cpp
clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
clang/lib/StaticAnalyzer/Core/ProgramState.cpp
clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
clang/lib/StaticAnalyzer/Core/RegionStore.cpp
clang/lib/StaticAnalyzer/Core/SMTConstraintManager.cpp
clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp
clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp

Removed: 
clang/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
clang/lib/StaticAnalyzer/Core/SubEngine.cpp



diff  --git 
a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
index 935b2bb7b937..335536b6a310 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
@@ -32,7 +32,7 @@ namespace clang {
 namespace ento {
 
 class ProgramStateManager;
-class SubEngine;
+class ExprEngine;
 class SymbolReaper;
 
 class ConditionTruthVal {
@@ -193,10 +193,11 @@ class ConstraintManager {
 
 std::unique_ptr
 CreateRangeConstraintManager(ProgramStateManager ,
- SubEngine *subengine);
+ ExprEngine *exprengine);
 
 std::unique_ptr
-CreateZ3ConstraintManager(ProgramStateManager , SubEngine *subengine);
+CreateZ3ConstraintManager(ProgramStateManager ,
+  ExprEngine *exprengine);
 
 } // namespace ento
 } // namespace clang

diff  --git 
a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
index 278193ef99ed..2aca2c99ef4f 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
@@ -41,7 +41,7 @@ class LabelDecl;
 namespace ento {
 
 class FunctionSummariesTy;
-class SubEngine;
+class ExprEngine;
 
 
//===--===//
 /// CoreEngine - Implements the core logic of the graph-reachability
@@ -69,7 +69,7 @@ class CoreEngine {
   std::vector>;
 
 private:
-  SubEngine 
+  ExprEngine 
 
   /// G - The simulation graph.  Each node is a (location,state) pair.
   mutable ExplodedGraph G;
@@ -129,7 +129,7 @@ class CoreEngine {
 
 public:
   /// Construct a CoreEngine object to analyze the provided CFG.
-  CoreEngine(SubEngine ,
+  CoreEngine(ExprEngine ,
  FunctionSummariesTy *FS,
  AnalyzerOptions );
 

diff  --git 
a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index c66c54116a0c..a94c847f35ee 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -21,6 +21,7 @@
 #include "clang/Analysis/DomainSpecific/ObjCNoReturn.h"
 #include "clang/Analysis/ProgramPoint.h"
 #include "clang/Basic/LLVM.h"
+#include 

[clang] 12dbdc2 - [Analyzer] Fix buildbot failure of commit rGd70ec366c91b

2020-05-26 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-05-26T20:43:37+02:00
New Revision: 12dbdc2a6b68162f7370e9754bdb0e1edd65bf3c

URL: 
https://github.com/llvm/llvm-project/commit/12dbdc2a6b68162f7370e9754bdb0e1edd65bf3c
DIFF: 
https://github.com/llvm/llvm-project/commit/12dbdc2a6b68162f7370e9754bdb0e1edd65bf3c.diff

LOG: [Analyzer] Fix buildbot failure of commit rGd70ec366c91b

Added: 


Modified: 
clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h

Removed: 




diff  --git 
a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index b32302cfc337..3611979c6191 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -97,7 +97,7 @@ class SymbolManager;
 class SwitchNodeBuilder;
 
 class ExprEngine {
-  virtual void anchor();
+  void anchor();
 public:
   /// The modes of inlining, which override the default analysis-wide settings.
   enum InliningModes {



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


[clang-tools-extra] 4fc0214 - [clang-tidy] New check cppcoreguidelines-prefer-member-initializer

2020-09-21 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-09-21T14:42:58+02:00
New Revision: 4fc0214a10140fa77449677e8094ea22d3d17701

URL: 
https://github.com/llvm/llvm-project/commit/4fc0214a10140fa77449677e8094ea22d3d17701
DIFF: 
https://github.com/llvm/llvm-project/commit/4fc0214a10140fa77449677e8094ea22d3d17701.diff

LOG: [clang-tidy] New check cppcoreguidelines-prefer-member-initializer

Finds member initializations in the constructor body which can be placed
into the initialization list instead. This does not only improves the
readability of the code but also affects positively its performance.
Class-member assignments inside a control statement or following the
first control statement are ignored.

Differential Revision: https://reviews.llvm.org/D71199

Added: 

clang-tools-extra/clang-tidy/cppcoreguidelines/PreferMemberInitializerCheck.cpp

clang-tools-extra/clang-tidy/cppcoreguidelines/PreferMemberInitializerCheck.h

clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-prefer-member-initializer.rst

clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-prefer-member-initializer-modernize-use-default-member-init-assignment.cpp

clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-prefer-member-initializer-modernize-use-default-member-init.cpp

clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-prefer-member-initializer.cpp

Modified: 
clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt

clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
clang-tools-extra/docs/ReleaseNotes.rst

Removed: 




diff  --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
index 39c2c552eb73..a9f5b3e0c15b 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
@@ -13,6 +13,7 @@ add_clang_library(clangTidyCppCoreGuidelinesModule
   NarrowingConversionsCheck.cpp
   NoMallocCheck.cpp
   OwningMemoryCheck.cpp
+  PreferMemberInitializerCheck.cpp
   ProBoundsArrayToPointerDecayCheck.cpp
   ProBoundsConstantArrayIndexCheck.cpp
   ProBoundsPointerArithmeticCheck.cpp

diff  --git 
a/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
 
b/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
index 4cb5022888d3..bf613109f0eb 100644
--- 
a/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
+++ 
b/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
@@ -22,6 +22,7 @@
 #include "NarrowingConversionsCheck.h"
 #include "NoMallocCheck.h"
 #include "OwningMemoryCheck.h"
+#include "PreferMemberInitializerCheck.h"
 #include "ProBoundsArrayToPointerDecayCheck.h"
 #include "ProBoundsConstantArrayIndexCheck.h"
 #include "ProBoundsPointerArithmeticCheck.h"
@@ -66,6 +67,8 @@ class CppCoreGuidelinesModule : public ClangTidyModule {
 "cppcoreguidelines-non-private-member-variables-in-classes");
 CheckFactories.registerCheck(
 "cppcoreguidelines-owning-memory");
+CheckFactories.registerCheck(
+"cppcoreguidelines-prefer-member-initializer");
 CheckFactories.registerCheck(
 "cppcoreguidelines-pro-bounds-array-to-pointer-decay");
 CheckFactories.registerCheck(

diff  --git 
a/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferMemberInitializerCheck.cpp
 
b/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferMemberInitializerCheck.cpp
new file mode 100644
index ..bc0a3b98ac7a
--- /dev/null
+++ 
b/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferMemberInitializerCheck.cpp
@@ -0,0 +1,246 @@
+//===--- PreferMemberInitializerCheck.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 "PreferMemberInitializerCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+static bool isControlStatement(const Stmt *S) {
+  return isa(S);
+}
+
+static bool isNoReturnCallStatement(const Stmt *S) {
+  const auto *Call = dyn_cast(S);
+  if (!Call)
+return false;
+
+  const FunctionDecl *Func = Call->getDirectCallee();
+  if (!Func)
+return false;
+
+  return Func->isNoReturn();
+}
+
+static bool isLiteral(const Expr *E) {
+  return isa(E);
+}
+
+static bool isUnaryExprOfLiteral(const Expr *E) {
+  if (const auto *UnOp = dyn_cast(E))
+return isLiteral(UnOp->getSubExpr());
+  return false;
+}
+
+static 

[clang] c79745e - [Analyzer] Quick fix for broken tests on Windows

2020-07-01 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-07-01T12:52:47+02:00
New Revision: c79745ed48f3e22e9c5fdfa070bceecf7590896c

URL: 
https://github.com/llvm/llvm-project/commit/c79745ed48f3e22e9c5fdfa070bceecf7590896c
DIFF: 
https://github.com/llvm/llvm-project/commit/c79745ed48f3e22e9c5fdfa070bceecf7590896c.diff

LOG: [Analyzer] Quick fix for broken tests on Windows

Added: 


Modified: 
clang/test/Analysis/iterator-modeling.cpp

Removed: 




diff  --git a/clang/test/Analysis/iterator-modeling.cpp 
b/clang/test/Analysis/iterator-modeling.cpp
index f522dded37a6..f19848b8dc93 100644
--- a/clang/test/Analysis/iterator-modeling.cpp
+++ b/clang/test/Analysis/iterator-modeling.cpp
@@ -1976,26 +1976,23 @@ void clang_analyzer_printState();
 
 void print_state(std::vector ) {
   const auto i0 = V.cbegin();
-  const auto i1 = V.cbegin() + 1;
   clang_analyzer_printState();
 
   // CHECK:  "checker_messages": [
   // CHECK:   { "checker": "alpha.cplusplus.IteratorModeling", "messages": [
   // CHECK-NEXT: "Iterator Positions :",
   // CHECK-NEXT: "i0 : Valid ; Container == 
SymRegion{reg_$[[#]] & V>} ; Offset == conj_$[[#]]{long, 
LC[[#]], S[[#]], #[[#]]}"
-  // CHECK-NEXT: "i1 : Valid ; Container == 
SymRegion{reg_$[[#]] & V>} ; Offset == (conj_$[[#]]{long, 
LC[[#]], S[[#]], #[[#]]}) + 1"
   // CHECK-NEXT:   ]}
 
   *i0;
-  *i1;
-  const auto i2 = V.cend();
+  const auto i1 = V.cend();
   clang_analyzer_printState();
 
   // CHECK:  "checker_messages": [
   // CHECK:   { "checker": "alpha.cplusplus.IteratorModeling", "messages": [
   // CHECK-NEXT: "Iterator Positions :",
-  // CHECK-NEXT: "i2 : Valid ; Container == 
SymRegion{reg_$[[#]] & V>} ; Offset == conj_$[[#]]{long, 
LC[[#]], S[[#]], #[[#]]}"
+  // CHECK-NEXT: "i1 : Valid ; Container == 
SymRegion{reg_$[[#]] & V>} ; Offset == conj_$[[#]]{long, 
LC[[#]], S[[#]], #[[#]]}"
   // CHECK-NEXT:   ]}
 
-  *i2;
+  *i1;
 }



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


[clang] 40c50bd - [Sema][NFC] Remove Redundant Condition

2020-07-01 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-07-01T09:04:27+02:00
New Revision: 40c50bdee443dd48424ac7d724ced8874c40ee33

URL: 
https://github.com/llvm/llvm-project/commit/40c50bdee443dd48424ac7d724ced8874c40ee33
DIFF: 
https://github.com/llvm/llvm-project/commit/40c50bdee443dd48424ac7d724ced8874c40ee33.diff

LOG: [Sema][NFC] Remove Redundant Condition

Condition `TypeQuals` is checked both in an outer and in an inner `if`
statement in static function `ConvertDeclSpecToType()` in file
`SemaType.cpp`. This patch removes the redundant inner check.

The issue was found using `clang-tidy` check under review
`misc-redundant-condition`. See https://reviews.llvm.org/D81272.

Differential Revision: https://reviews.llvm.org/D82563

Added: 


Modified: 
clang/lib/Sema/SemaType.cpp

Removed: 




diff  --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 52fe292ce113..b8a787f010d6 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -1759,7 +1759,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState 
) {
 //   The effect of a cv-qualifier-seq in a function declarator is not the
 //   same as adding cv-qualification on top of the function type. In the
 //   latter case, the cv-qualifiers are ignored.
-if (TypeQuals && Result->isFunctionType()) {
+if (Result->isFunctionType()) {
   diagnoseAndRemoveTypeQualifiers(
   S, DS, TypeQuals, Result, DeclSpec::TQ_const | DeclSpec::TQ_volatile,
   S.getLangOpts().CPlusPlus



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


[clang] ea563da - [Analyzer] Fix errors in iterator modeling

2020-07-01 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-07-01T09:04:28+02:00
New Revision: ea563daae5232a03e08e43e68da813f76548f36a

URL: 
https://github.com/llvm/llvm-project/commit/ea563daae5232a03e08e43e68da813f76548f36a
DIFF: 
https://github.com/llvm/llvm-project/commit/ea563daae5232a03e08e43e68da813f76548f36a.diff

LOG: [Analyzer] Fix errors in iterator modeling

There is major a bug found in iterator modeling: upon adding a value
to or subtracting a value from an iterator the position of the original
iterator is also changed beside the result. This patch fixes this bug.

To catch such bugs in the future we also changed the tests to look for
regular expressions including an end-of-line symbol (`$`) so we can
prevent false matches where only the tested prefix matches.

Another minor bug is that when printing the state, all the iterator
positions are printed in a single line. This patch also fixes this.

Differential Revision: https://reviews.llvm.org/D82385

Added: 


Modified: 
clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
clang/test/Analysis/iterator-modeling.cpp

Removed: 




diff  --git a/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp 
b/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
index e35918edbf89..c4f71da421c6 100644
--- a/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
@@ -458,7 +458,7 @@ void IteratorModeling::processComparison(CheckerContext ,
 StateTrue = StateTrue->assume(*ConditionVal, true);
 C.addTransition(StateTrue);
   }
-  
+
   if (auto StateFalse = relateSymbols(State, Sym1, Sym2, Op != OO_EqualEqual)) 
{
 StateFalse = StateFalse->assume(*ConditionVal, false);
 C.addTransition(StateFalse);
@@ -540,14 +540,16 @@ void 
IteratorModeling::handleRandomIncrOrDecr(CheckerContext ,
 
   auto  = (Op == OO_PlusEqual || Op == OO_MinusEqual) ? LHS : RetVal;
 
-  auto NewState =
-advancePosition(State, LHS, Op, *value);
-  if (NewState) {
-const auto *NewPos = getIteratorPosition(NewState, LHS);
+  // `AdvancedState` is a state where the position of `LHS` is advanced. We
+  // only need this state to retrieve the new position, but we do not want
+  // to change the position of `LHS` (in every case).
+  auto AdvancedState = advancePosition(State, LHS, Op, *value);
+  if (AdvancedState) {
+const auto *NewPos = getIteratorPosition(AdvancedState, LHS);
 assert(NewPos &&
"Iterator should have position after successful advancement");
 
-State = setIteratorPosition(NewState, TgtVal, *NewPos);
+State = setIteratorPosition(State, TgtVal, *NewPos);
 C.addTransition(State);
   } else {
 assignToContainer(C, CE, TgtVal, Pos->getContainer());
@@ -611,10 +613,15 @@ void IteratorModeling::printState(raw_ostream , 
ProgramStateRef State,
   const char *NL, const char *Sep) const {
   auto SymbolMap = State->get();
   auto RegionMap = State->get();
+  // Use a counter to add newlines before every line except the first one.
+  unsigned Count = 0;
 
   if (!SymbolMap.isEmpty() || !RegionMap.isEmpty()) {
 Out << Sep << "Iterator Positions :" << NL;
 for (const auto  : SymbolMap) {
+  if (Count++)
+Out << NL;
+
   Sym.first->dumpToStream(Out);
   Out << " : ";
   const auto Pos = Sym.second;
@@ -625,6 +632,9 @@ void IteratorModeling::printState(raw_ostream , 
ProgramStateRef State,
 }
 
 for (const auto  : RegionMap) {
+  if (Count++)
+Out << NL;
+
   Reg.first->dumpToStream(Out);
   Out << " : ";
   const auto Pos = Reg.second;

diff  --git a/clang/test/Analysis/iterator-modeling.cpp 
b/clang/test/Analysis/iterator-modeling.cpp
index bb37a7565ca1..a2a67b58259a 100644
--- a/clang/test/Analysis/iterator-modeling.cpp
+++ b/clang/test/Analysis/iterator-modeling.cpp
@@ -1,12 +1,12 @@
-// RUN: %clang_analyze_cc1 -std=c++11 
-analyzer-checker=core,cplusplus,debug.DebugIteratorModeling,debug.ExprInspection
 -analyzer-config aggressive-binary-operation-simplification=true 
-analyzer-config c++-container-inlining=false %s -verify
+// RUN: %clang_analyze_cc1 -std=c++11 
-analyzer-checker=core,cplusplus,debug.DebugIteratorModeling,debug.ExprInspection
 -analyzer-config aggressive-binary-operation-simplification=true 
-analyzer-config c++-container-inlining=false %s -verify -analyzer-config 
display-checker-name=false
 
-// RUN: %clang_analyze_cc1 -std=c++11 
-analyzer-checker=core,cplusplus,debug.DebugIteratorModeling,debug.ExprInspection
 -analyzer-config aggressive-binary-operation-simplification=true 
-analyzer-config c++-container-inlining=true -DINLINE=1 %s -verify
+// RUN: %clang_analyze_cc1 -std=c++11 
-analyzer-checker=core,cplusplus,debug.DebugIteratorModeling,debug.ExprInspection
 -analyzer-config aggressive-binary-operation-simplification=true 
-analyzer-config c++-container-inlining=true 

[clang] 9e63b19 - [Analyzer] Handle pointer implemented as iterators in iterator checkers

2020-07-01 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-07-01T09:04:28+02:00
New Revision: 9e63b190af76c798b06b1e3b75216abfdeb1bce3

URL: 
https://github.com/llvm/llvm-project/commit/9e63b190af76c798b06b1e3b75216abfdeb1bce3
DIFF: 
https://github.com/llvm/llvm-project/commit/9e63b190af76c798b06b1e3b75216abfdeb1bce3.diff

LOG: [Analyzer] Handle pointer implemented as iterators in iterator checkers

Iterators are an abstraction of pointers and in some data structures
iterators may be implemented by pointers. This patch adds support for
iterators implemented as pointers in all the iterator checkers
(including iterator modeling).

Differential Revision: https://reviews.llvm.org/D82185

Added: 


Modified: 
clang/lib/StaticAnalyzer/Checkers/InvalidatedIteratorChecker.cpp
clang/lib/StaticAnalyzer/Checkers/Iterator.cpp
clang/lib/StaticAnalyzer/Checkers/Iterator.h
clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
clang/lib/StaticAnalyzer/Checkers/IteratorRangeChecker.cpp
clang/lib/StaticAnalyzer/Checkers/MismatchedIteratorChecker.cpp
clang/test/Analysis/invalidated-iterator.cpp
clang/test/Analysis/iterator-modeling.cpp
clang/test/Analysis/iterator-range.cpp
clang/test/Analysis/mismatched-iterator.cpp

Removed: 




diff  --git a/clang/lib/StaticAnalyzer/Checkers/InvalidatedIteratorChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/InvalidatedIteratorChecker.cpp
index c6cd11b09a4c..6955ba11a28f 100644
--- a/clang/lib/StaticAnalyzer/Checkers/InvalidatedIteratorChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/InvalidatedIteratorChecker.cpp
@@ -26,7 +26,10 @@ using namespace iterator;
 namespace {
 
 class InvalidatedIteratorChecker
-  : public Checker {
+  : public Checker,
+   check::PreStmt,
+   check::PreStmt,
+   check::PreStmt> {
 
   std::unique_ptr InvalidatedBugType;
 
@@ -37,6 +40,10 @@ class InvalidatedIteratorChecker
   InvalidatedIteratorChecker();
 
   void checkPreCall(const CallEvent , CheckerContext ) const;
+  void checkPreStmt(const UnaryOperator *UO, CheckerContext ) const;
+  void checkPreStmt(const BinaryOperator *BO, CheckerContext ) const;
+  void checkPreStmt(const ArraySubscriptExpr *ASE, CheckerContext ) const;
+  void checkPreStmt(const MemberExpr *ME, CheckerContext ) const;
 
 };
 
@@ -65,6 +72,48 @@ void InvalidatedIteratorChecker::checkPreCall(const 
CallEvent ,
   }
 }
 
+void InvalidatedIteratorChecker::checkPreStmt(const UnaryOperator *UO,
+  CheckerContext ) const {
+  if (isa(UO->getSubExpr()))
+return;
+
+  ProgramStateRef State = C.getState();
+  UnaryOperatorKind OK = UO->getOpcode();
+  SVal SubVal = State->getSVal(UO->getSubExpr(), C.getLocationContext());
+
+  if (isAccessOperator(OK)) {
+verifyAccess(C, SubVal);
+  }
+}
+
+void InvalidatedIteratorChecker::checkPreStmt(const BinaryOperator *BO,
+  CheckerContext ) const {
+  ProgramStateRef State = C.getState();
+  BinaryOperatorKind OK = BO->getOpcode();
+  SVal LVal = State->getSVal(BO->getLHS(), C.getLocationContext());
+
+  if (isAccessOperator(OK)) {
+verifyAccess(C, LVal);
+  }
+}
+
+void InvalidatedIteratorChecker::checkPreStmt(const ArraySubscriptExpr *ASE,
+  CheckerContext ) const {
+  ProgramStateRef State = C.getState();
+  SVal LVal = State->getSVal(ASE->getLHS(), C.getLocationContext());
+  verifyAccess(C, LVal);
+}
+
+void InvalidatedIteratorChecker::checkPreStmt(const MemberExpr *ME,
+  CheckerContext ) const {
+  if (!ME->isArrow() || ME->isImplicitAccess())
+return;
+
+  ProgramStateRef State = C.getState();
+  SVal BaseVal = State->getSVal(ME->getBase(), C.getLocationContext());
+  verifyAccess(C, BaseVal);
+}
+
 void InvalidatedIteratorChecker::verifyAccess(CheckerContext , const SVal 
) const {
   auto State = C.getState();
   const auto *Pos = getIteratorPosition(State, Val);

diff  --git a/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp 
b/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp
index e80d8bc32dec..ac0f24603dd9 100644
--- a/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp
@@ -128,24 +128,54 @@ bool isAccessOperator(OverloadedOperatorKind OK) {
  isDecrementOperator(OK) || isRandomIncrOrDecrOperator(OK);
 }
 
+bool isAccessOperator(UnaryOperatorKind OK) {
+  return isDereferenceOperator(OK) || isIncrementOperator(OK) ||
+ isDecrementOperator(OK);
+}
+
+bool isAccessOperator(BinaryOperatorKind OK) {
+  return isDereferenceOperator(OK) || isRandomIncrOrDecrOperator(OK);
+}
+
 bool isDereferenceOperator(OverloadedOperatorKind OK) {
   return OK == OO_Star || OK == OO_Arrow || OK == OO_ArrowStar ||
  OK == OO_Subscript;
 }
 
+bool isDereferenceOperator(UnaryOperatorKind OK) {
+  return 

[clang-tools-extra] 4da65c2 - [clang-tidy] New util `Aliasing` factored out from `bugprone-infinite-loop`

2020-07-01 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-07-01T09:04:27+02:00
New Revision: 4da65c2920b68a1cf47054a7d655cc2a19a4aa28

URL: 
https://github.com/llvm/llvm-project/commit/4da65c2920b68a1cf47054a7d655cc2a19a4aa28
DIFF: 
https://github.com/llvm/llvm-project/commit/4da65c2920b68a1cf47054a7d655cc2a19a4aa28.diff

LOG: [clang-tidy] New util `Aliasing` factored out from `bugprone-infinite-loop`

Function `hasPtrOrReferenceInfFunc()` of `bugprone-infinite-loop` is a
generic function which could be reused in another checks. This patch
moves this function into a newly created utility module.

Differential Revision: https://reviews.llvm.org/D81396

Added: 
clang-tools-extra/clang-tidy/utils/Aliasing.cpp
clang-tools-extra/clang-tidy/utils/Aliasing.h

Modified: 
clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp
clang-tools-extra/clang-tidy/utils/CMakeLists.txt

Removed: 




diff  --git a/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp 
b/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp
index c9dd47ef0cf9..310fbec72a50 100644
--- a/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp
@@ -10,8 +10,10 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/Analysis/Analyses/ExprMutationAnalyzer.h"
+#include "../utils/Aliasing.h"
 
 using namespace clang::ast_matchers;
+using clang::tidy::utils::hasPtrOrReferenceInFunc;
 
 namespace clang {
 namespace tidy {
@@ -24,54 +26,6 @@ loopEndingStmt(internal::Matcher Internal) {
 callExpr(Internal, callee(functionDecl(isNoReturn());
 }
 
-/// Return whether `S` is a reference to the declaration of `Var`.
-static bool isAccessForVar(const Stmt *S, const VarDecl *Var) {
-  if (const auto *DRE = dyn_cast(S))
-return DRE->getDecl() == Var;
-
-  return false;
-}
-
-/// Return whether `Var` has a pointer or reference in `S`.
-static bool isPtrOrReferenceForVar(const Stmt *S, const VarDecl *Var) {
-  if (const auto *DS = dyn_cast(S)) {
-for (const Decl *D : DS->getDeclGroup()) {
-  if (const auto *LeftVar = dyn_cast(D)) {
-if (LeftVar->hasInit() && LeftVar->getType()->isReferenceType()) {
-  return isAccessForVar(LeftVar->getInit(), Var);
-}
-  }
-}
-  } else if (const auto *UnOp = dyn_cast(S)) {
-if (UnOp->getOpcode() == UO_AddrOf)
-  return isAccessForVar(UnOp->getSubExpr(), Var);
-  }
-
-  return false;
-}
-
-/// Return whether `Var` has a pointer or reference in `S`.
-static bool hasPtrOrReferenceInStmt(const Stmt *S, const VarDecl *Var) {
-  if (isPtrOrReferenceForVar(S, Var))
-return true;
-
-  for (const Stmt *Child : S->children()) {
-if (!Child)
-  continue;
-
-if (hasPtrOrReferenceInStmt(Child, Var))
-  return true;
-  }
-
-  return false;
-}
-
-/// Return whether `Var` has a pointer or reference in `Func`.
-static bool hasPtrOrReferenceInFunc(const FunctionDecl *Func,
-const VarDecl *Var) {
-  return hasPtrOrReferenceInStmt(Func->getBody(), Var);
-}
-
 /// Return whether `Var` was changed in `LoopStmt`.
 static bool isChanged(const Stmt *LoopStmt, const VarDecl *Var,
   ASTContext *Context) {

diff  --git a/clang-tools-extra/clang-tidy/utils/Aliasing.cpp 
b/clang-tools-extra/clang-tidy/utils/Aliasing.cpp
new file mode 100644
index ..3a88126a9ee6
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/utils/Aliasing.cpp
@@ -0,0 +1,65 @@
+//===- Aliasing.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 "Aliasing.h"
+
+#include "clang/AST/Expr.h"
+
+namespace clang {
+namespace tidy {
+namespace utils {
+
+/// Return whether \p S is a reference to the declaration of \p Var.
+static bool isAccessForVar(const Stmt *S, const VarDecl *Var) {
+  if (const auto *DRE = dyn_cast(S))
+return DRE->getDecl() == Var;
+
+  return false;
+}
+
+/// Return whether \p Var has a pointer or reference in \p S.
+static bool isPtrOrReferenceForVar(const Stmt *S, const VarDecl *Var) {
+  if (const auto *DS = dyn_cast(S)) {
+for (const Decl *D : DS->getDeclGroup()) {
+  if (const auto *LeftVar = dyn_cast(D)) {
+if (LeftVar->hasInit() && LeftVar->getType()->isReferenceType()) {
+  return isAccessForVar(LeftVar->getInit(), Var);
+}
+  }
+}
+  } else if (const auto *UnOp = dyn_cast(S)) {
+if (UnOp->getOpcode() == UO_AddrOf)
+  return isAccessForVar(UnOp->getSubExpr(), Var);
+  }
+
+  return false;
+}
+
+/// Return whether \p Var has a pointer or 

[clang] e22ace8 - [Analyzer] Fix buildbot failure caused by commit `rG813734dad7e8b526c39806d1a88820b1f0706fb1`

2020-06-09 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-06-09T14:50:27+02:00
New Revision: e22ace8ba2b060e983d7cc2a76d00d6ef3816177

URL: 
https://github.com/llvm/llvm-project/commit/e22ace8ba2b060e983d7cc2a76d00d6ef3816177
DIFF: 
https://github.com/llvm/llvm-project/commit/e22ace8ba2b060e983d7cc2a76d00d6ef3816177.diff

LOG: [Analyzer] Fix buildbot failure caused by commit 
`rG813734dad7e8b526c39806d1a88820b1f0706fb1`

Added: 


Modified: 
clang/unittests/StaticAnalyzer/TestReturnValueUnderConstruction.cpp

Removed: 




diff  --git 
a/clang/unittests/StaticAnalyzer/TestReturnValueUnderConstruction.cpp 
b/clang/unittests/StaticAnalyzer/TestReturnValueUnderConstruction.cpp
index 7532d5491390..a329b37d2767 100644
--- a/clang/unittests/StaticAnalyzer/TestReturnValueUnderConstruction.cpp
+++ b/clang/unittests/StaticAnalyzer/TestReturnValueUnderConstruction.cpp
@@ -26,7 +26,9 @@ class TestReturnValueUnderConstructionChecker
 // We are checking the invocation of `returnC` which returns an object
 // by value.
 const IdentifierInfo *ID = Call.getCalleeIdentifier();
-if (ID->getName() != "returnC")
+// Only calls with origin expression are checked. These are `returnC()`
+// and C::C().
+if (!Call.getOriginExpr())
   return;
 
 // Since `returnC` returns an object by value, the invocation results



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


[clang] 53298b8 - [Analyzer] Remove warning caused by commit `rG98db1f990fc2`

2020-06-09 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-06-09T15:40:42+02:00
New Revision: 53298b8c8d74d0064c673db18addfe973b544dbb

URL: 
https://github.com/llvm/llvm-project/commit/53298b8c8d74d0064c673db18addfe973b544dbb
DIFF: 
https://github.com/llvm/llvm-project/commit/53298b8c8d74d0064c673db18addfe973b544dbb.diff

LOG: [Analyzer] Remove warning caused by commit `rG98db1f990fc2`

Added: 


Modified: 
clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h

Removed: 




diff  --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
index b0391bd042a8..9f85347db5df 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
@@ -1099,7 +1099,7 @@ class ObjCIvarRegion : public DeclRegion {
 const MemRegion* superRegion);
 
 public:
-  const ObjCIvarDecl *getDecl() const;
+  const ObjCIvarDecl *getDecl() const override;
 
   void Profile(llvm::FoldingSetNodeID& ID) const override;
 



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


[clang] 54f9ddd - [Analyzer] Remove warning caused by commit `rGe22ace8ba2b0`

2020-06-09 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-06-09T15:46:15+02:00
New Revision: 54f9ddd8064125c0343980433546709e7dbf4593

URL: 
https://github.com/llvm/llvm-project/commit/54f9ddd8064125c0343980433546709e7dbf4593
DIFF: 
https://github.com/llvm/llvm-project/commit/54f9ddd8064125c0343980433546709e7dbf4593.diff

LOG: [Analyzer] Remove warning caused by commit `rGe22ace8ba2b0`

Added: 


Modified: 
clang/unittests/StaticAnalyzer/TestReturnValueUnderConstruction.cpp

Removed: 




diff  --git 
a/clang/unittests/StaticAnalyzer/TestReturnValueUnderConstruction.cpp 
b/clang/unittests/StaticAnalyzer/TestReturnValueUnderConstruction.cpp
index a329b37d2767..5750d5918db3 100644
--- a/clang/unittests/StaticAnalyzer/TestReturnValueUnderConstruction.cpp
+++ b/clang/unittests/StaticAnalyzer/TestReturnValueUnderConstruction.cpp
@@ -23,9 +23,6 @@ class TestReturnValueUnderConstructionChecker
   : public Checker {
 public:
   void checkPostCall(const CallEvent , CheckerContext ) const {
-// We are checking the invocation of `returnC` which returns an object
-// by value.
-const IdentifierInfo *ID = Call.getCalleeIdentifier();
 // Only calls with origin expression are checked. These are `returnC()`
 // and C::C().
 if (!Call.getOriginExpr())



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


[clang] b2a37cf - [Analyzer] Replace `assert` with `ASSERT_TRUE` in a unit test to silence warnings

2020-06-12 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-06-12T17:09:34+02:00
New Revision: b2a37cfe2bda0bc8c4d2e981922b5ac59c429bdc

URL: 
https://github.com/llvm/llvm-project/commit/b2a37cfe2bda0bc8c4d2e981922b5ac59c429bdc
DIFF: 
https://github.com/llvm/llvm-project/commit/b2a37cfe2bda0bc8c4d2e981922b5ac59c429bdc.diff

LOG: [Analyzer] Replace `assert` with `ASSERT_TRUE` in a unit test to silence 
warnings

Added: 


Modified: 
clang/unittests/StaticAnalyzer/ParamRegionTest.cpp

Removed: 




diff  --git a/clang/unittests/StaticAnalyzer/ParamRegionTest.cpp 
b/clang/unittests/StaticAnalyzer/ParamRegionTest.cpp
index 7ec032a7beae..3dbbc7ba1578 100644
--- a/clang/unittests/StaticAnalyzer/ParamRegionTest.cpp
+++ b/clang/unittests/StaticAnalyzer/ParamRegionTest.cpp
@@ -19,7 +19,7 @@ class ParamRegionTestConsumer : public ExprEngineConsumer {
   void checkForSameParamRegions(MemRegionManager ,
 const StackFrameContext *SFC,
 const ParmVarDecl *PVD) {
-assert(llvm::all_of(PVD->redecls(), [&](const clang::VarDecl *D2) {
+ASSERT_TRUE(llvm::all_of(PVD->redecls(), [&](const clang::VarDecl *D2) {
   return MRMgr.getVarRegion(PVD, SFC) ==
  MRMgr.getVarRegion(cast(D2), SFC);
 }));



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


[clang] 813734d - [Analyzer] Add `getReturnValueUnderConstruction()` to `CallEvent`

2020-06-09 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-06-09T12:08:56+02:00
New Revision: 813734dad7e8b526c39806d1a88820b1f0706fb1

URL: 
https://github.com/llvm/llvm-project/commit/813734dad7e8b526c39806d1a88820b1f0706fb1
DIFF: 
https://github.com/llvm/llvm-project/commit/813734dad7e8b526c39806d1a88820b1f0706fb1.diff

LOG: [Analyzer] Add `getReturnValueUnderConstruction()` to `CallEvent`

Checkers should be able to get the return value under construction for a
`CallEvenet`. This patch adds a function to achieve this which retrieves
the return value from the construction context of the call.

Differential Revision: https://reviews.llvm.org/D80366

Added: 
clang/unittests/StaticAnalyzer/TestReturnValueUnderConstruction.cpp

Modified: 
clang/include/clang/Analysis/AnalysisDeclContext.h
clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
clang/lib/StaticAnalyzer/Core/CallEvent.cpp
clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
clang/unittests/StaticAnalyzer/CMakeLists.txt

Removed: 




diff  --git a/clang/include/clang/Analysis/AnalysisDeclContext.h 
b/clang/include/clang/Analysis/AnalysisDeclContext.h
index 6fe1e27bda75..d12582f4f329 100644
--- a/clang/include/clang/Analysis/AnalysisDeclContext.h
+++ b/clang/include/clang/Analysis/AnalysisDeclContext.h
@@ -324,6 +324,8 @@ class StackFrameContext : public LocationContext {
 
   unsigned getIndex() const { return Index; }
 
+  CFGElement getCallSiteCFGElement() const { return (*Block)[Index]; }
+  
   void Profile(llvm::FoldingSetNodeID ) override;
 
   static void Profile(llvm::FoldingSetNodeID , AnalysisDeclContext *ADC,

diff  --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
index 8b84b79651bd..2dd75fa23e2f 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
@@ -434,6 +434,15 @@ class CallEvent {
 return CallArgumentIndex;
   }
 
+  /// Returns the construction context of the call, if it is a C++ constructor
+  /// call or a call of a function returning a C++ class instance. Otherwise
+  /// return nullptr.
+  const ConstructionContext *getConstructionContext() const;
+
+  /// If the call returns a C++ record type then the region of its return value
+  /// can be retrieved from its construction context.
+  Optional getReturnValueUnderConstruction() const;
+
   // Iterator access to formal parameters and their types.
 private:
   struct GetTypeFn {

diff  --git 
a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index 3611979c6191..baa3a94adb64 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -126,6 +126,13 @@ class ExprEngine {
 /// for example 'A { const C  }; A a = { C() };'
 bool IsTemporaryLifetimeExtendedViaAggregate = false;
 
+/// This call is a pre-C++17 elidable constructor that we failed to elide
+/// because we failed to compute the target region into which
+/// this constructor would have been ultimately elided. Analysis that
+/// we perform in this case is still correct but it behaves 
diff erently,
+/// as if copy elision is disabled.
+bool IsElidableCtorThatHasNotBeenElided = false;
+
 EvalCallOptions() {}
   };
 
@@ -709,6 +716,35 @@ class ExprEngine {
const CallEvent ,
const EvalCallOptions  = {});
 
+  /// Find location of the object that is being constructed by a given
+  /// constructor. This should ideally always succeed but due to not being
+  /// fully implemented it sometimes indicates that it failed via its
+  /// out-parameter CallOpts; in such cases a fake temporary region is
+  /// returned, which is better than nothing but does not represent
+  /// the actual behavior of the program.
+  SVal computeObjectUnderConstruction(
+  const Expr *E, ProgramStateRef State, const LocationContext *LCtx,
+  const ConstructionContext *CC, EvalCallOptions );
+
+  /// Update the program state with all the path-sensitive information
+  /// that's necessary to perform construction of an object with a given
+  /// syntactic construction context. V and CallOpts have to be obtained from
+  /// computeObjectUnderConstruction() invoked with the same set of
+  /// the remaining arguments (E, State, LCtx, CC).
+  ProgramStateRef updateObjectsUnderConstruction(
+  SVal V, const Expr *E, ProgramStateRef State, const LocationContext 
*LCtx,
+  const ConstructionContext *CC, const EvalCallOptions );
+
+  /// A convenient wrapper around computeObjectUnderConstruction
+  /// and 

[clang] 98db1f9 - [Analyzer] [NFC] Parameter Regions

2020-06-09 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-06-09T12:08:56+02:00
New Revision: 98db1f990fc273adc1ae36d4ce97ce66fd27ac30

URL: 
https://github.com/llvm/llvm-project/commit/98db1f990fc273adc1ae36d4ce97ce66fd27ac30
DIFF: 
https://github.com/llvm/llvm-project/commit/98db1f990fc273adc1ae36d4ce97ce66fd27ac30.diff

LOG: [Analyzer] [NFC] Parameter Regions

Currently, parameters of functions without their definition present cannot
be represented as regions because it would be difficult to ensure that the
same declaration is used in every case. To overcome this, we split
`VarRegion` to two subclasses: `NonParamVarRegion` and `ParamVarRegion`.
The latter does not store the `Decl` of the parameter variable. Instead it
stores the index of the parameter which enables retrieving the actual
`Decl` every time using the function declaration of the stack frame. To
achieve this we also removed storing of `Decl` from `DeclRegion` and made
`getDecl()` pure virtual. The individual `Decl`s are stored in the
appropriate subclasses, such as `FieldRegion`, `ObjCIvarRegion` and the
newly introduced `NonParamVarRegion`.

Differential Revision: https://reviews.llvm.org/D80522

Added: 
clang/unittests/StaticAnalyzer/ParamRegionTest.cpp

Modified: 
clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
clang/include/clang/StaticAnalyzer/Core/PathSensitive/Regions.def
clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
clang/lib/StaticAnalyzer/Core/CallEvent.cpp
clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
clang/lib/StaticAnalyzer/Core/MemRegion.cpp
clang/lib/StaticAnalyzer/Core/Store.cpp
clang/test/Analysis/explain-svals.c
clang/test/Analysis/explain-svals.cpp
clang/test/Analysis/explain-svals.m
clang/unittests/StaticAnalyzer/CMakeLists.txt

Removed: 




diff  --git a/clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h 
b/clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
index f7bd5b58aab5..0f33909daec0 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
+++ b/clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
@@ -18,6 +18,7 @@
 #include "clang/AST/Attr.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h"
+#include "llvm/ADT/StringExtras.h"
 
 namespace clang {
 
@@ -179,7 +180,7 @@ class SValExplainer : public FullSValVisitor {
 return OS.str();
   }
 
-  std::string VisitVarRegion(const VarRegion *R) {
+  std::string VisitNonParamVarRegion(const NonParamVarRegion *R) {
 const VarDecl *VD = R->getDecl();
 std::string Name = VD->getQualifiedNameAsString();
 if (isa(VD))
@@ -216,6 +217,39 @@ class SValExplainer : public 
FullSValVisitor {
"' inside " + Visit(R->getSuperRegion());
   }
 
+  std::string VisitParamVarRegion(const ParamVarRegion *R) {
+std::string Str;
+llvm::raw_string_ostream OS(Str);
+
+const ParmVarDecl *PVD = R->getDecl();
+std::string Name = PVD->getQualifiedNameAsString();
+if (!Name.empty()) {
+  OS << "parameter '" << Name << "'";
+  return std::string(OS.str());
+}
+
+unsigned Index = R->getIndex() + 1;
+OS << Index << llvm::getOrdinalSuffix(Index) << " parameter of ";
+const Decl *Parent = R->getStackFrame()->getDecl();
+if (const auto *FD = dyn_cast(Parent))
+  OS << "function '" << FD->getQualifiedNameAsString() << "()'";
+else if (const auto *CD = dyn_cast(Parent))
+  OS << "C++ constructor '" << CD->getQualifiedNameAsString() << "()'";
+else if (const auto *MD = dyn_cast(Parent)) {
+  if (MD->isClassMethod())
+OS << "Objective-C method '+" << MD->getQualifiedNameAsString() << "'";
+  else
+OS << "Objective-C method '-" << MD->getQualifiedNameAsString() << "'";
+} else if (isa(Parent)) {
+  if (cast(Parent)->isConversionFromLambda())
+OS << "lambda";
+  else
+OS << "block";
+}
+
+return std::string(OS.str());
+  }
+
   std::string VisitSVal(SVal V) {
 std::string Str;
 llvm::raw_string_ostream OS(Str);

diff  --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
index 2dd75fa23e2f..a71469e90ea2 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
@@ -402,9 +402,10 @@ class CallEvent {
   const StackFrameContext *getCalleeStackFrame(unsigned BlockCount) const;
 
   /// Returns memory location for a parameter variable within the callee stack
-  /// frame. May fail; returns null on failure.
-  

[clang] 5419a31 - [Analyzer] Allow creation of stack frame for functions without definition

2020-06-09 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-06-09T12:08:57+02:00
New Revision: 5419a3121522fe1251d52c7f1fb790d68581e549

URL: 
https://github.com/llvm/llvm-project/commit/5419a3121522fe1251d52c7f1fb790d68581e549
DIFF: 
https://github.com/llvm/llvm-project/commit/5419a3121522fe1251d52c7f1fb790d68581e549.diff

LOG: [Analyzer] Allow creation of stack frame for functions without definition

Retrieving the parameter location of functions was disabled because it
may causes crashes due to the fact that functions may have multiple
declarations and without definition it is difficult to ensure that
always the same declration is used. Now parameters are stored in
`ParamRegions` which are independent of the declaration of the function,
therefore the same parameters always have the same regions,
independently of the function declaration used actually. This allows us
to remove the limitation described above.

Differential Revision: https://reviews.llvm.org/D80286

Added: 


Modified: 
clang/lib/StaticAnalyzer/Core/CallEvent.cpp
clang/test/Analysis/explain-svals.cpp
clang/test/Analysis/temporaries.cpp
clang/unittests/StaticAnalyzer/ParamRegionTest.cpp

Removed: 




diff  --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp 
b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
index dd6f78e7143f..cb8693f3c34c 100644
--- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -172,23 +172,9 @@ AnalysisDeclContext 
*CallEvent::getCalleeAnalysisDeclContext() const {
   if (!D)
 return nullptr;
 
-  // TODO: For now we skip functions without definitions, even if we have
-  // our own getDecl(), because it's hard to find out which re-declaration
-  // is going to be used, and usually clients don't really care about this
-  // situation because there's a loss of precision anyway because we cannot
-  // inline the call.
-  RuntimeDefinition RD = getRuntimeDefinition();
-  if (!RD.getDecl())
-return nullptr;
-
   AnalysisDeclContext *ADC =
   LCtx->getAnalysisDeclContext()->getManager()->getContext(D);
 
-  // TODO: For now we skip virtual functions, because this also rises
-  // the problem of which decl to use, but now it's across 
diff erent classes.
-  if (RD.mayHaveOtherDefinitions() || RD.getDecl() != ADC->getDecl())
-return nullptr;
-
   return ADC;
 }
 

diff  --git a/clang/test/Analysis/explain-svals.cpp 
b/clang/test/Analysis/explain-svals.cpp
index 0510e4156f51..c33373f00de2 100644
--- a/clang/test/Analysis/explain-svals.cpp
+++ b/clang/test/Analysis/explain-svals.cpp
@@ -98,7 +98,7 @@ class C {
 } // end of anonymous namespace
 
 void test_6() {
-  clang_analyzer_explain(conjure_S()); // expected-warning-re^lazily 
frozen compound value of temporary object constructed at statement 
'conjure_S\(\)'$
+  clang_analyzer_explain(conjure_S()); // expected-warning-re^lazily 
frozen compound value of 1st parameter of function 
'clang_analyzer_explain\(\)'$
   clang_analyzer_explain(conjure_S().z); // expected-warning-re^value 
derived from \(symbol of type 'int' conjured at statement 'conjure_S\(\)'\) for 
field 'z' of temporary object constructed at statement 'conjure_S\(\)'$
 }
 

diff  --git a/clang/test/Analysis/temporaries.cpp 
b/clang/test/Analysis/temporaries.cpp
index 325b689c0deb..1c0ac38160c2 100644
--- a/clang/test/Analysis/temporaries.cpp
+++ b/clang/test/Analysis/temporaries.cpp
@@ -890,12 +890,9 @@ class C {
 public:
   ~C() {
 glob = 1;
-// FIXME: Why is destructor not inlined in C++17
 clang_analyzer_checkInlined(true);
 #ifdef TEMPORARY_DTORS
-#if __cplusplus < 201703L
-// expected-warning@-3{{TRUE}}
-#endif
+// expected-warning@-2{{TRUE}}
 #endif
   }
 };
@@ -914,16 +911,11 @@ void test(int coin) {
   // temporaries returned from functions, so we took the wrong branch.
   coin && is(get()); // no-crash
   if (coin) {
-// FIXME: Why is destructor not inlined in C++17
 clang_analyzer_eval(glob);
 #ifdef TEMPORARY_DTORS
-#if __cplusplus < 201703L
-// expected-warning@-3{{TRUE}}
-#else
-// expected-warning@-5{{UNKNOWN}}
-#endif
+// expected-warning@-2{{TRUE}}
 #else
-// expected-warning@-8{{UNKNOWN}}
+// expected-warning@-4{{UNKNOWN}}
 #endif
   } else {
 // The destructor is not called on this branch.

diff  --git a/clang/unittests/StaticAnalyzer/ParamRegionTest.cpp 
b/clang/unittests/StaticAnalyzer/ParamRegionTest.cpp
index 9a666f7fb615..c58af3f851c4 100644
--- a/clang/unittests/StaticAnalyzer/ParamRegionTest.cpp
+++ b/clang/unittests/StaticAnalyzer/ParamRegionTest.cpp
@@ -16,6 +16,15 @@ namespace ento {
 namespace {
 
 class ParamRegionTestConsumer : public ExprEngineConsumer {
+  void checkForSameParamRegions(MemRegionManager ,
+const StackFrameContext *SFC,
+const ParmVarDecl *PVD) {
+for (const auto *D2: PVD->redecls()) {

[clang] a59d4ae - [Analyzer] Hotfix for various crashes in iterator checkers

2020-07-16 Thread Adam Balogh via cfe-commits

Author: Adam Balogh
Date: 2020-07-16T20:49:33+02:00
New Revision: a59d4ae4313c0a961c50d14c0616b49220c5a469

URL: 
https://github.com/llvm/llvm-project/commit/a59d4ae4313c0a961c50d14c0616b49220c5a469
DIFF: 
https://github.com/llvm/llvm-project/commit/a59d4ae4313c0a961c50d14c0616b49220c5a469.diff

LOG: [Analyzer] Hotfix for various crashes in iterator checkers

The patch that introduces handling iterators implemented as pointers may
cause crash in some projects because pointer difference is mistakenly
handled as pointer decrement. (Similair case for iterators implemented
as class instances are already handled correctly.) This patch fixes this
issue.

The second case that causes crash is comparison of an iterator
implemented as pointer and a null-pointer. This patch contains a fix for
this issue as well.

The third case which causes crash is that the checker mistakenly
considers all integers as nonloc::ConcreteInt when handling an increment
or decrement of an iterator implemented as pointers. This patch adds a
fix for this too.

The last case where crashes were detected is when checking for success
of an std::advance() operation. Since the modeling of iterators
implemented as pointers is still incomplete this may result in an
assertion. This patch replaces the assertion with an early exit and
adds a FIXME there.

Differential Revision: https://reviews.llvm.org/D83295

Added: 


Modified: 
clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
clang/lib/StaticAnalyzer/Checkers/IteratorRangeChecker.cpp
clang/test/Analysis/iterator-modeling.cpp
clang/test/Analysis/iterator-range.cpp

Removed: 




diff  --git a/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp 
b/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
index fd8cbd694b24..632de9e5dc83 100644
--- a/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
@@ -272,6 +272,8 @@ void IteratorModeling::checkPostStmt(const BinaryOperator 
*BO,
 handleComparison(C, BO, Result, LVal, RVal,
  BinaryOperator::getOverloadedOperator(OK));
   } else if (isRandomIncrOrDecrOperator(OK)) {
+if (!BO->getRHS()->getType()->isIntegralOrEnumerationType())
+  return;
 handlePtrIncrOrDecr(C, BO->getLHS(),
 BinaryOperator::getOverloadedOperator(OK), RVal);
   }
@@ -461,6 +463,12 @@ void IteratorModeling::handleComparison(CheckerContext , 
const Expr *CE,
 RPos = getIteratorPosition(State, RVal);
   }
 
+  // If the value for which we just tried to set a new iterator position is
+  // an `SVal`for which no iterator position can be set then the setting was
+  // unsuccessful. We cannot handle the comparison in this case.
+  if (!LPos || !RPos)
+return;
+
   // We cannot make assumptions on `UnknownVal`. Let us conjure a symbol
   // instead.
   if (RetVal.isUnknown()) {
@@ -599,6 +607,9 @@ void IteratorModeling::handlePtrIncrOrDecr(CheckerContext 
,
const Expr *Iterator,
OverloadedOperatorKind OK,
SVal Offset) const {
+  if (!Offset.getAs())
+return;
+
   QualType PtrType = Iterator->getType();
   if (!PtrType->isPointerType())
 return;
@@ -612,13 +623,11 @@ void IteratorModeling::handlePtrIncrOrDecr(CheckerContext 
,
 return;
 
   SVal NewVal;
-  if (OK == OO_Plus || OK == OO_PlusEqual)
+  if (OK == OO_Plus || OK == OO_PlusEqual) {
 NewVal = State->getLValue(ElementType, Offset, OldVal);
-  else {
-const llvm::APSInt  =
-  Offset.castAs().getValue();
-auto  = C.getSymbolManager().getBasicVals();
-SVal NegatedOffset = nonloc::ConcreteInt(BVF.getValue(-OffsetInt));
+  } else {
+auto  = C.getSValBuilder();
+SVal NegatedOffset = SVB.evalMinus(Offset.castAs());
 NewVal = State->getLValue(ElementType, NegatedOffset, OldVal);
   }
 
@@ -684,9 +693,14 @@ bool IteratorModeling::noChangeInAdvance(CheckerContext 
, SVal Iter,
 
   const auto StateBefore = N->getState();
   const auto *PosBefore = getIteratorPosition(StateBefore, Iter);
-
-  assert(PosBefore && "`std::advance() should not create new iterator "
- "position but change existing ones");
+  // FIXME: `std::advance()` should not create a new iterator position but
+  //change existing ones. However, in case of iterators implemented as
+  //pointers the handling of parameters in `std::advance()`-like
+  //functions is still incomplete which may result in cases where
+  //the new position is assigned to the wrong pointer. This causes
+  //crash if we use an assertion here.
+  if (!PosBefore)
+return false;
 
   return PosBefore->getOffset() == PosAfter->getOffset();
 }

diff  --git a/clang/lib/StaticAnalyzer/Checkers/IteratorRangeChecker.cpp