r331630 - [ASTImporter] Support importing UnresolvedMemberExpr, DependentNameType, DependentScopeDeclRefExpr

2018-05-07 Thread Peter Szecsi via cfe-commits
Author: szepet
Date: Mon May  7 05:08:27 2018
New Revision: 331630

URL: http://llvm.org/viewvc/llvm-project?rev=331630&view=rev
Log:
[ASTImporter] Support importing UnresolvedMemberExpr, DependentNameType, 
DependentScopeDeclRefExpr

The visit callback implementations for the 3 C++ AST Node added to the 
ASTImporter.

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


Modified:
cfe/trunk/lib/AST/ASTImporter.cpp
cfe/trunk/unittests/AST/ASTImporterTest.cpp

Modified: cfe/trunk/lib/AST/ASTImporter.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=331630&r1=331629&r2=331630&view=diff
==
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)
+++ cfe/trunk/lib/AST/ASTImporter.cpp Mon May  7 05:08:27 2018
@@ -121,7 +121,7 @@ namespace clang {
 QualType VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType 
*T);
 QualType VisitTemplateSpecializationType(const TemplateSpecializationType 
*T);
 QualType VisitElaboratedType(const ElaboratedType *T);
-// FIXME: DependentNameType
+QualType VisitDependentNameType(const DependentNameType *T);
 QualType VisitPackExpansionType(const PackExpansionType *T);
 QualType VisitDependentTemplateSpecializationType(
 const DependentTemplateSpecializationType *T);
@@ -347,8 +347,10 @@ namespace clang {
 Expr *VisitCXXConstructExpr(CXXConstructExpr *E);
 Expr *VisitCXXMemberCallExpr(CXXMemberCallExpr *E);
 Expr *VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E);
+Expr *VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E);
 Expr *VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *CE);
 Expr *VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E);
+Expr *VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E);
 Expr *VisitExprWithCleanups(ExprWithCleanups *EWC);
 Expr *VisitCXXThisExpr(CXXThisExpr *E);
 Expr *VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E);
@@ -938,6 +940,25 @@ QualType ASTNodeImporter::VisitDependent
 T->getKeyword(), Qualifier, Name, ToPack);
 }
 
+QualType ASTNodeImporter::VisitDependentNameType(const DependentNameType *T) {
+  NestedNameSpecifier *NNS = Importer.Import(T->getQualifier());
+  if (!NNS && T->getQualifier())
+return QualType();
+
+  IdentifierInfo *Name = Importer.Import(T->getIdentifier());
+  if (!Name && T->getIdentifier())
+return QualType();
+
+  QualType Canon = (T == T->getCanonicalTypeInternal().getTypePtr())
+   ? QualType()
+   : Importer.Import(T->getCanonicalTypeInternal());
+  if (!Canon.isNull())
+Canon = Canon.getCanonicalType();
+
+  return Importer.getToContext().getDependentNameType(T->getKeyword(), NNS,
+  Name, Canon);
+}
+
 QualType ASTNodeImporter::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
   auto *Class =
   dyn_cast_or_null(Importer.Import(T->getDecl()));
@@ -6187,6 +6208,29 @@ Expr *ASTNodeImporter::VisitCXXDependent
   cast_or_null(ToFQ), MemberNameInfo, ResInfo);
 }
 
+Expr *
+ASTNodeImporter::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
+  DeclarationName Name = Importer.Import(E->getDeclName());
+  if (!E->getDeclName().isEmpty() && Name.isEmpty())
+return nullptr;
+
+  DeclarationNameInfo NameInfo(Name, Importer.Import(E->getExprLoc()));
+  ImportDeclarationNameLoc(E->getNameInfo(), NameInfo);
+
+  TemplateArgumentListInfo ToTAInfo(Importer.Import(E->getLAngleLoc()),
+Importer.Import(E->getRAngleLoc()));
+  TemplateArgumentListInfo *ResInfo = nullptr;
+  if (E->hasExplicitTemplateArgs()) {
+if (ImportTemplateArgumentListInfo(E->template_arguments(), ToTAInfo))
+  return nullptr;
+ResInfo = &ToTAInfo;
+  }
+
+  return DependentScopeDeclRefExpr::Create(
+  Importer.getToContext(), Importer.Import(E->getQualifierLoc()),
+  Importer.Import(E->getTemplateKeywordLoc()), NameInfo, ResInfo);
+}
+
 Expr *ASTNodeImporter::VisitCXXUnresolvedConstructExpr(
 CXXUnresolvedConstructExpr *CE) {
   unsigned NumArgs = CE->arg_size();
@@ -6244,6 +6288,47 @@ Expr *ASTNodeImporter::VisitUnresolvedLo
   E->isOverloaded(), ToDecls.begin(), ToDecls.end());
 }
 
+Expr *ASTNodeImporter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) {
+  DeclarationName Name = Importer.Import(E->getName());
+  if (!E->getName().isEmpty() && Name.isEmpty())
+return nullptr;
+  DeclarationNameInfo NameInfo(Name, Importer.Import(E->getNameLoc()));
+  // Import additional name location/type info.
+  ImportDeclarationNameLoc(E->getNameInfo(), NameInfo);
+
+  QualType BaseType = Importer.Import(E->getType());
+  if (!E->getType().isNull() && BaseType.isNull())
+return nullptr;
+
+  UnresolvedSet<8> ToDecls;
+  for (Decl *D : E->decls()) {
+if (NamedDecl *To = cast_or_null(Importer.Import(D)))
+  ToDecls.addDecl(To);

r331344 - [ASTImporter] Fix isa cast assert

2018-05-02 Thread Peter Szecsi via cfe-commits
Author: szepet
Date: Wed May  2 04:52:54 2018
New Revision: 331344

URL: http://llvm.org/viewvc/llvm-project?rev=331344&view=rev
Log:
[ASTImporter] Fix isa cast assert

Do early return if we can't import the found decl for a member expr.
This follows the pre-existing scheme, e.g with E->getMemberDecl().
E->getFoundDecl().getDecl() can be null when a member expression does
not involve lookup. It may involve a lookup in case of a using directive
which refers to a member function in a base class template.

We faced this assert during the CTU analysis of google::protobuf v3.5.2.
We tried hard to synthesize a minimal test example both by hand and by
executing creduce on multiple files. Unfortunately, we were unable to reduce
to such a minimal example, yet. Nevertheless, this fix solved the problem in
protobuf.

To reproduce the error one must execute the analyzer with
-Xclang -analyzer-config -Xclang experimental-enable-naive-ctu-analysis=true 
-Xclang -analyzer-config -Xclang ctu-dir=/path/to/ctu_dir

Patch by Gabor Marton!

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


Modified:
cfe/trunk/lib/AST/ASTImporter.cpp

Modified: cfe/trunk/lib/AST/ASTImporter.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=331344&r1=331343&r2=331344&view=diff
==
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)
+++ cfe/trunk/lib/AST/ASTImporter.cpp Wed May  2 04:52:54 2018
@@ -6089,9 +6089,13 @@ Expr *ASTNodeImporter::VisitMemberExpr(M
   if (!ToMember && E->getMemberDecl())
 return nullptr;
 
-  DeclAccessPair ToFoundDecl = DeclAccessPair::make(
-dyn_cast(Importer.Import(E->getFoundDecl().getDecl())),
-E->getFoundDecl().getAccess());
+  auto *ToDecl =
+  
dyn_cast_or_null(Importer.Import(E->getFoundDecl().getDecl()));
+  if (!ToDecl && E->getFoundDecl().getDecl())
+return nullptr;
+
+  DeclAccessPair ToFoundDecl =
+  DeclAccessPair::make(ToDecl, E->getFoundDecl().getAccess());
 
   DeclarationNameInfo ToMemberNameInfo(
 Importer.Import(E->getMemberNameInfo().getName()),


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


r330847 - [ASTImporter] FriendDecl importing improvements

2018-04-25 Thread Peter Szecsi via cfe-commits
Author: szepet
Date: Wed Apr 25 10:28:03 2018
New Revision: 330847

URL: http://llvm.org/viewvc/llvm-project?rev=330847&view=rev
Log:
[ASTImporter] FriendDecl importing improvements

There are only a few cases of importing a frienddecl which is currently 
supported.
This patch aims to improve the friend import process.
Set FriendObjectKind in case of decls, insert friend into the friend chain
correctly, checks structurally equivalent in a more advanced manner.
Test cases added as well.  


Modified:
cfe/trunk/include/clang/AST/DeclBase.h
cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td
cfe/trunk/lib/AST/ASTImporter.cpp
cfe/trunk/lib/AST/ASTStructuralEquivalence.cpp
cfe/trunk/test/ASTMerge/class/Inputs/class1.cpp
cfe/trunk/test/ASTMerge/class/Inputs/class2.cpp
cfe/trunk/test/ASTMerge/class/test.cpp

Modified: cfe/trunk/include/clang/AST/DeclBase.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=330847&r1=330846&r2=330847&view=diff
==
--- cfe/trunk/include/clang/AST/DeclBase.h (original)
+++ cfe/trunk/include/clang/AST/DeclBase.h Wed Apr 25 10:28:03 2018
@@ -309,6 +309,7 @@ private:
 protected:
   friend class ASTDeclReader;
   friend class ASTDeclWriter;
+  friend class ASTImporter;
   friend class ASTReader;
   friend class CXXClassMemberWrapper;
   friend class LinkageComputer;

Modified: cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td?rev=330847&r1=330846&r2=330847&view=diff
==
--- cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td Wed Apr 25 10:28:03 2018
@@ -273,6 +273,8 @@ def note_odr_objc_synthesize_ivar_here :
   "property is synthesized to ivar %0 here">;
 
 // Importing C++ ASTs
+def note_odr_friend : Note<"friend declared here">;
+def note_odr_missing_friend : Note<"no corresponding friend here">;
 def err_odr_different_num_template_parameters : Error<
   "template parameter lists have a different number of parameters (%0 vs %1)">;
 def note_odr_template_parameter_list : Note<

Modified: cfe/trunk/lib/AST/ASTImporter.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=330847&r1=330846&r2=330847&view=diff
==
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)
+++ cfe/trunk/lib/AST/ASTImporter.cpp Wed Apr 25 10:28:03 2018
@@ -2709,9 +2709,14 @@ Decl *ASTNodeImporter::VisitFriendDecl(F
 
   // Not found. Create it.
   FriendDecl::FriendUnion ToFU;
-  if (NamedDecl *FriendD = D->getFriendDecl())
-ToFU = cast_or_null(Importer.Import(FriendD));
-  else
+  if (NamedDecl *FriendD = D->getFriendDecl()) {
+auto *ToFriendD = cast_or_null(Importer.Import(FriendD));
+if (ToFriendD && FriendD->getFriendObjectKind() != Decl::FOK_None &&
+!(FriendD->isInIdentifierNamespace(Decl::IDNS_NonMemberOperator)))
+  ToFriendD->setObjectOfFriendDecl(false);
+
+ToFU = ToFriendD;
+  }  else // The friend is a type, not a decl.
 ToFU = Importer.Import(D->getFriendType());
   if (!ToFU)
 return nullptr;
@@ -2731,7 +2736,6 @@ Decl *ASTNodeImporter::VisitFriendDecl(F
ToTPLists);
 
   Importer.Imported(D, FrD);
-  RD->pushFriendDecl(FrD);
 
   FrD->setAccess(D->getAccess());
   FrD->setLexicalDeclContext(LexicalDC);
@@ -6596,7 +6600,7 @@ Decl *ASTImporter::Import(Decl *FromD) {
 
   // Record the imported declaration.
   ImportedDecls[FromD] = ToD;
-
+  ToD->IdentifierNamespace = FromD->IdentifierNamespace;
   return ToD;
 }
 

Modified: cfe/trunk/lib/AST/ASTStructuralEquivalence.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTStructuralEquivalence.cpp?rev=330847&r1=330846&r2=330847&view=diff
==
--- cfe/trunk/lib/AST/ASTStructuralEquivalence.cpp (original)
+++ cfe/trunk/lib/AST/ASTStructuralEquivalence.cpp Wed Apr 25 10:28:03 2018
@@ -18,6 +18,7 @@
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclBase.h"
 #include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclFriend.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/NestedNameSpecifier.h"
@@ -942,6 +943,44 @@ static bool IsStructurallyEquivalent(Str
   return false;
 }
   }
+
+  // Check the friends for consistency.
+  CXXRecordDecl::friend_iterator Friend2 = D2CXX->friend_begin(),
+  Friend2End = D2CXX->friend_end();
+  for (CXXRecordDecl::friend_iterator Friend1 = D1CXX->friend_begin(),
+   Friend1End = D1CXX->friend_end();
+   Friend1 != Friend1End; ++Friend1, ++Friend2) {
+if (Friend2 == Friend2End) {

r328906 - [ASTImporter] Add test helper Fixture

2018-03-30 Thread Peter Szecsi via cfe-commits
Author: szepet
Date: Fri Mar 30 15:03:29 2018
New Revision: 328906

URL: http://llvm.org/viewvc/llvm-project?rev=328906&view=rev
Log:
[ASTImporter] Add test helper Fixture

Add a helper test Fixture, so we can add tests which can check internal
attributes of AST nodes like getPreviousDecl(), isVirtual(), etc.
This enables us to check if a redeclaration chain is correctly built during
import, if the virtual flag is preserved during import, etc. We cannot check
such attributes with the existing testImport.
Also, this fixture makes it possible to import from several "From" contexts.

We also added several test cases here, some of them are disabled.
We plan to pass the disabled tests in other patches.

Patch by Gabor Marton!

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


Added:
cfe/trunk/unittests/AST/DeclMatcher.h
Modified:
cfe/trunk/unittests/AST/ASTImporterTest.cpp

Modified: cfe/trunk/unittests/AST/ASTImporterTest.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/ASTImporterTest.cpp?rev=328906&r1=328905&r2=328906&view=diff
==
--- cfe/trunk/unittests/AST/ASTImporterTest.cpp (original)
+++ cfe/trunk/unittests/AST/ASTImporterTest.cpp Fri Mar 30 15:03:29 2018
@@ -17,6 +17,8 @@
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Tooling/Tooling.h"
+
+#include "DeclMatcher.h"
 #include "gtest/gtest.h"
 
 namespace clang {
@@ -29,7 +31,7 @@ static bool isCXX(Language Lang) {
   return Lang == Lang_CXX || Lang == Lang_CXX11;
 }
 
-static RunOptions getRunOptionsForLanguage(Language Lang) {
+static ArgVector getBasicRunOptionsForLanguage(Language Lang) {
   ArgVector BasicArgs;
   // Test with basic arguments.
   switch (Lang) {
@@ -49,6 +51,11 @@ static RunOptions getRunOptionsForLangua
   case Lang_OBJCXX:
 llvm_unreachable("Not implemented yet!");
   }
+  return BasicArgs;
+}
+
+static RunOptions getRunOptionsForLanguage(Language Lang) {
+  ArgVector BasicArgs = getBasicRunOptionsForLanguage(Lang);
 
   // For C++, test with "-fdelayed-template-parsing" enabled to handle MSVC
   // default behaviour.
@@ -61,6 +68,19 @@ static RunOptions getRunOptionsForLangua
   return {BasicArgs};
 }
 
+// Creates a virtual file and assigns that to the context of given AST. If the
+// file already exists then the file will not be created again as a duplicate.
+static void createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
+  const std::string &Code) {
+  assert(ToAST);
+  ASTContext &ToCtx = ToAST->getASTContext();
+  auto *OFS = static_cast(
+  ToCtx.getSourceManager().getFileManager().getVirtualFileSystem().get());
+  auto *MFS =
+  static_cast(OFS->overlays_begin()->get());
+  MFS->addFile(FileName, 0, llvm::MemoryBuffer::getMemBuffer(Code.c_str()));
+}
+
 template
 testing::AssertionResult
 testImport(const std::string &FromCode, const ArgVector &FromArgs,
@@ -79,11 +99,7 @@ testImport(const std::string &FromCode,
 
   // Add input.cc to virtual file system so importer can 'find' it
   // while importing SourceLocations.
-  vfs::OverlayFileSystem *OFS = static_cast(
-
ToCtx.getSourceManager().getFileManager().getVirtualFileSystem().get());
-  vfs::InMemoryFileSystem *MFS = static_cast(
-OFS->overlays_begin()->get());
-  MFS->addFile(InputFileName, 0, llvm::MemoryBuffer::getMemBuffer(FromCode));
+  createVirtualFileIfNeeded(ToAST.get(), InputFileName, FromCode);
 
   ASTImporter Importer(ToCtx, ToAST->getFileManager(),
FromCtx, FromAST->getFileManager(), false);
@@ -133,6 +149,165 @@ void testImport(const std::string &FromC
  Verifier, AMatcher));
 }
 
+const StringRef DeclToImportID = "declToImport";
+
+// This class provides generic methods to write tests which can check internal
+// attributes of AST nodes like getPreviousDecl(), isVirtual(), etc.  Also,
+// this fixture makes it possible to import from several "From" contexts.
+class ASTImporterTestBase : public ::testing::TestWithParam {
+
+  const char *const InputFileName = "input.cc";
+  const char *const OutputFileName = "output.cc";
+
+  // Buffer for the To context, must live in the test scope.
+  std::string ToCode;
+
+  struct TU {
+// Buffer for the context, must live in the test scope.
+std::string Code;
+std::string FileName;
+std::unique_ptr Unit;
+TranslationUnitDecl *TUDecl = nullptr;
+TU(StringRef Code, StringRef FileName, ArgVector Args)
+: Code(Code), FileName(FileName),
+  Unit(tooling::buildASTFromCodeWithArgs(this->Code, Args,
+ this->FileName)),
+  TUDecl(Unit->getASTContext().getTranslationUnitDecl()) {}
+  };
+
+  // We may have several From contexts and related translation units. In each
+  // AST, the buffers for the source are handled via references and are 

r328619 - [analyzer] LoopUnrolling: update the matched assignment operators

2018-03-27 Thread Peter Szecsi via cfe-commits
Author: szepet
Date: Tue Mar 27 05:16:56 2018
New Revision: 328619

URL: http://llvm.org/viewvc/llvm-project?rev=328619&view=rev
Log:
[analyzer] LoopUnrolling: update the matched assignment operators

Extended the matched assignment operators when checking for bound changes in a 
body of the loop by using the freshly added isAssignmentOperator matcher.
This covers all the (current) possible assignments, tests added as well.

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


Modified:
cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
cfe/trunk/test/Analysis/loop-unrolling.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp?rev=328619&r1=328618&r2=328619&view=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp Tue Mar 27 05:16:56 2018
@@ -97,9 +97,7 @@ changeIntBoundNode(internal::Matcherhttp://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/loop-unrolling.cpp?rev=328619&r1=328618&r2=328619&view=diff
==
--- cfe/trunk/test/Analysis/loop-unrolling.cpp (original)
+++ cfe/trunk/test/Analysis/loop-unrolling.cpp Tue Mar 27 05:16:56 2018
@@ -99,13 +99,101 @@ int simple_no_unroll5() {
   return 0;
 }
 
+int no_unroll_assignment() {
+  for (int i = 0; i < 9; i++) {
+i = i + 1;
+clang_analyzer_numTimesReached(); // expected-warning {{4}}
+  }
+  return 0;
+}
+
+int no_unroll_assignment2() {
+  for (int i = 0; i < 9; i++) {
+i *= 2;
+clang_analyzer_numTimesReached(); // expected-warning {{4}}
+  }
+  return 0;
+}
+
+int no_unroll_assignment3() {
+  for (int i = 128; i > 0; i--) {
+i /= 2;
+clang_analyzer_numTimesReached(); // expected-warning {{4}}
+  }
+  return 0;
+}
+
+int no_unroll_assignment4() {
+  for (int i = 0; i < 9; i++) {
+i -= 2;
+clang_analyzer_numTimesReached(); // expected-warning {{4}}
+  }
+  return 0;
+}
+
+int no_unroll_assignment5() {
+  for (int i = 0; i < 9; i++) {
+i += 1;
+clang_analyzer_numTimesReached(); // expected-warning {{4}}
+  }
+  return 0;
+}
+
+int no_unroll_assignment6() {
+  for (int i = 128; i > 0; i--) {
+i >>= 1;
+clang_analyzer_numTimesReached(); // expected-warning {{4}}
+  }
+  return 0;
+}
+
+int no_unroll_assignment7() {
+  for (int i = 0; i < 512; i++) {
+i <<= 1;
+clang_analyzer_numTimesReached(); // expected-warning {{4}}
+  }
+  return 0;
+}
+
+int no_unroll_assignment8() {
+  for (int i = 0; i < 9; i++) {
+i %= 8;
+clang_analyzer_numTimesReached(); // expected-warning {{4}}
+  }
+  return 0;
+}
+
+int no_unroll_assignment9() {
+  for (int i = 0; i < 9; i++) {
+i &= 31;
+clang_analyzer_numTimesReached(); // expected-warning {{4}}
+  }
+  return 0;
+}
+
+int no_unroll_assignment10() {
+  for (int i = 0; i < 9; i++) {
+i |= 2;
+clang_analyzer_numTimesReached(); // expected-warning {{4}}
+  }
+  return 0;
+}
+
+int no_unroll_assignment11() {
+  for (int i = 0; i < 9; i++) {
+i ^= 2;
+clang_analyzer_numTimesReached(); // expected-warning {{4}}
+  }
+  return 0;
+}
+
 int make_new_branches_loop_cached() {
   for (int i = 0; i < 8; i++) {
 clang_analyzer_numTimesReached(); // expected-warning {{4}}
-if(getNum()){
-(void) i; // Since this Stmt does not change the State the analyzer
-  // won't make a new execution path but reuse the earlier 
nodes.
-  }
+if (getNum()) {
+  (void)i; // Since this Stmt does not change the State the analyzer
+   // won't make a new execution path but reuse the earlier nodes.
+}
   }
   clang_analyzer_warnIfReached(); // no-warning
   return 0;
@@ -115,7 +203,7 @@ int make_new_branches_loop_uncached() {
   int l = 2;
   for (int i = 0; i < 8; i++) {
 clang_analyzer_numTimesReached(); // expected-warning {{10}}
-if(getNum()){
+if (getNum()) {
   ++l;
 }
   }
@@ -127,7 +215,7 @@ int make_new_branches_loop_uncached2() {
   int l = 2;
   for (int i = 0; i < 8; i++) {
 clang_analyzer_numTimesReached(); // expected-warning {{10}}
-if(getNum()){
+if (getNum()) {
   ++l;
 }
 (void)&i; // This ensures that the loop won't be unrolled.
@@ -185,7 +273,7 @@ int nested_outer_unrolled() {
 for (j = 0; j < 9; ++j) {
   clang_analyzer_numTimesReached(); // expected-warning {{4}}
   a[j] = 22;
-  (void) &j; // ensures that the inner loop won't be unrolled
+  (void)&j; // ensures that the inner loop won't be unrolled
 }
 a[i] = 42;
   }
@@ -268,8 +356,8 @@ int recursion_unroll1(bool b) {
   int k = 2;
   for (int i = 0; i < 5; i++) {
 clang_analyzer_numTimesReached(); // expected-warning {{13}}
-if(i == 0 && b) // Splits the state in the first iteration but the 
recursion
-  

r328618 - [ASTMatchers] Add isAssignmentOperator matcher

2018-03-27 Thread Peter Szecsi via cfe-commits
Author: szepet
Date: Tue Mar 27 05:11:46 2018
New Revision: 328618

URL: http://llvm.org/viewvc/llvm-project?rev=328618&view=rev
Log:
[ASTMatchers] Add isAssignmentOperator matcher

Adding a matcher for BinaryOperator and cxxOperatorCallExpr to be able to
decide whether it is any kind of assignment operator or not. This would be
useful since allows us to easily detect assignments via matchers for static
analysis (Tidy, SA) purposes.

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


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=328618&r1=328617&r2=328618&view=diff
==
--- cfe/trunk/docs/LibASTMatchersReference.html (original)
+++ cfe/trunk/docs/LibASTMatchersReference.html Tue Mar 27 05:11:46 2018
@@ -1926,6 +1926,19 @@ Example matches a || b (matcher = binary
 
 
 
+MatcherBinaryOperator>isAssignmentOperator
+Matches all 
kinds of assignment operators.
+
+Example 1: matches a += b (matcher = binaryOperator(isAssignmentOperator()))
+  if (a == b)
+a += b;
+
+Example 2: matches s1 = s2 (matcher = 
cxxOperatorCallExpr(isAssignmentOperator()))
+  struct S { S& operator=(const S&); };
+  void x() { S s1, s2; s1 = s2; })
+
+
+
 MatcherCXXBoolLiteralExpr>equalsbool Value
 
 
@@ -2306,6 +2319,19 @@ Usable as: MatcherCXXOperatorCallExpr>isAssignmentOperator
+Matches all 
kinds of assignment operators.
+
+Example 1: matches a += b (matcher = binaryOperator(isAssignmentOperator()))
+  if (a == b)
+a += b;
+
+Example 2: matches s1 = s2 (matcher = 
cxxOperatorCallExpr(isAssignmentOperator()))
+  struct S { S& operator=(const S&); };
+  void x() { S s1, s2; s1 = s2; })
+
+
+
 MatcherCXXRecordDecl>hasDefinition
 Matches a class 
declaration that is defined.
 

Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=328618&r1=328617&r2=328618&view=diff
==
--- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Tue Mar 27 05:11:46 2018
@@ -4003,6 +4003,26 @@ AST_POLYMORPHIC_MATCHER_P(hasOperatorNam
   return Name == Node.getOpcodeStr(Node.getOpcode());
 }
 
+/// \brief Matches on all kinds of assignment operators.
+///
+/// Example 1: matches a += b (matcher = 
binaryOperator(isAssignmentOperator()))
+/// \code
+///   if (a == b)
+/// a += b;
+/// \endcode
+///
+/// Example 2: matches s1 = s2
+///(matcher = cxxOperatorCallExpr(isAssignmentOperator()))
+/// \code
+///   struct S { S& operator=(const S&); };
+///   void x() { S s1, s2; s1 = s2; })
+/// \endcode
+AST_POLYMORPHIC_MATCHER(isAssignmentOperator,
+AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator,
+CXXOperatorCallExpr)) {
+  return Node.isAssignmentOp();
+}
+
 /// \brief Matches the left hand side of binary operator expressions.
 ///
 /// Example matches a (matcher = binaryOperator(hasLHS()))

Modified: cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp?rev=328618&r1=328617&r2=328618&view=diff
==
--- cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp (original)
+++ cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp Tue Mar 27 05:11:46 2018
@@ -322,6 +322,7 @@ RegistryMaps::RegistryMaps() {
   REGISTER_MATCHER(isAnyPointer);
   REGISTER_MATCHER(isArray);
   REGISTER_MATCHER(isArrow);
+  REGISTER_MATCHER(isAssignmentOperator);
   REGISTER_MATCHER(isBaseInitializer);
   REGISTER_MATCHER(isBitField);
   REGISTER_MATCHER(isCatchAll);

Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp?rev=328618&r1=328617&r2=328618&view=diff
==
--- cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp (original)
+++ cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp Tue Mar 27 
05:11:46 2018
@@ -2139,5 +2139,20 @@ TEST(HasTrailingReturn, MatchesLambdaTra
   functionDecl(hasTrailingRetu

r325693 - [analyzer] Prevent AnalyzerStatsChecker from crash

2018-02-21 Thread Peter Szecsi via cfe-commits
Author: szepet
Date: Wed Feb 21 08:06:56 2018
New Revision: 325693

URL: http://llvm.org/viewvc/llvm-project?rev=325693&view=rev
Log:
[analyzer] Prevent AnalyzerStatsChecker from crash

The checker marks the locations where the analyzer creates sinks. However, it
can happen that the sink was created because of a loop which does not contain
condition statement, only breaks in the body. The exhausted block is the block
which should contain the condition but empty, in this case.
This change only emits this marking in order to avoid the undefined behavior.

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


Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp
cfe/trunk/test/Analysis/analyzer-stats.c

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp?rev=325693&r1=325692&r2=325693&view=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp Wed Feb 21 
08:06:56 2018
@@ -122,6 +122,8 @@ void AnalyzerStatsChecker::checkEndAnaly
   E = CE.blocks_exhausted_end(); I != E; ++I) {
 const BlockEdge &BE =  I->first;
 const CFGBlock *Exit = BE.getDst();
+if (Exit->empty())
+  continue;
 const CFGElement &CE = Exit->front();
 if (Optional CS = CE.getAs()) {
   SmallString<128> bufI;

Modified: cfe/trunk/test/Analysis/analyzer-stats.c
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/analyzer-stats.c?rev=325693&r1=325692&r2=325693&view=diff
==
--- cfe/trunk/test/Analysis/analyzer-stats.c (original)
+++ cfe/trunk/test/Analysis/analyzer-stats.c Wed Feb 21 08:06:56 2018
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 
-analyzer-checker=core,deadcode.DeadStores,debug.Stats -verify 
-Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s
+// RUN: %clang_analyze_cc1 
-analyzer-checker=core,deadcode.DeadStores,debug.Stats -verify 
-Wno-unreachable-code -analyzer-opt-analyze-nested-blocks -analyzer-max-loop 4 
%s
 
 int foo();
 
@@ -12,3 +12,19 @@ int test() { // expected-warning-re{{tes
   a /= 4;
   return a;
 }
+
+
+int sink() // expected-warning-re{{sink -> Total CFGBlocks: {{[0-9]+}} | 
Unreachable CFGBlocks: 1 | Exhausted Block: yes | Empty WorkList: yes}}
+{
+  for (int i = 0; i < 10; ++i) // expected-warning {{(sink): The analyzer 
generated a sink at this point}}
+++i;
+
+  return 0;
+}
+
+int emptyConditionLoop() // expected-warning-re{{emptyConditionLoop -> Total 
CFGBlocks: {{[0-9]+}} | Unreachable CFGBlocks: 0 | Exhausted Block: yes | Empty 
WorkList: yes}}
+{
+  int num = 1;
+  for (;;)
+num++;
+}


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


r316852 - [analyzer] MisusedMovedObjectChecker: More precise warning message

2017-10-28 Thread Peter Szecsi via cfe-commits
Author: szepet
Date: Sat Oct 28 16:24:00 2017
New Revision: 316852

URL: http://llvm.org/viewvc/llvm-project?rev=316852&view=rev
Log:
[analyzer] MisusedMovedObjectChecker: More precise warning message

Added new enum in order to differentiate the warning messages on "misusing" into
3 categories: function calls, moving an object, copying an object. (At the
moment the checker gives the same message in case of copying and moving.)

Additional test cases added as well.

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


Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp
cfe/trunk/test/Analysis/MisusedMovedObject.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp?rev=316852&r1=316851&r2=316852&view=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp 
(original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp Sat Oct 
28 16:24:00 2017
@@ -60,6 +60,7 @@ public:
   const char *NL, const char *Sep) const override;
 
 private:
+  enum MisuseKind {MK_FunCall, MK_Copy, MK_Move};
   class MovedBugVisitor : public BugReporterVisitorImpl {
   public:
 MovedBugVisitor(const MemRegion *R) : Region(R), Found(false) {}
@@ -83,7 +84,7 @@ private:
 
   mutable std::unique_ptr BT;
   ExplodedNode *reportBug(const MemRegion *Region, const CallEvent &Call,
-  CheckerContext &C, bool isCopy) const;
+  CheckerContext &C, MisuseKind MK) const;
   bool isInMoveSafeContext(const LocationContext *LC) const;
   bool isStateResetMethod(const CXXMethodDecl *MethodDec) const;
   bool isMoveSafeMethod(const CXXMethodDecl *MethodDec) const;
@@ -179,7 +180,7 @@ const ExplodedNode *MisusedMovedObjectCh
 ExplodedNode *MisusedMovedObjectChecker::reportBug(const MemRegion *Region,
const CallEvent &Call,
CheckerContext &C,
-   bool isCopy = false) const {
+   MisuseKind MK) const {
   if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
 if (!BT)
   BT.reset(new BugType(this, "Usage of a 'moved-from' object",
@@ -195,10 +196,17 @@ ExplodedNode *MisusedMovedObjectChecker:
 
 // Creating the error message.
 std::string ErrorMessage;
-if (isCopy)
-  ErrorMessage = "Copying a 'moved-from' object";
-else
-  ErrorMessage = "Method call on a 'moved-from' object";
+switch(MK) {
+  case MK_FunCall:
+ErrorMessage = "Method call on a 'moved-from' object";
+break;
+  case MK_Copy:
+ErrorMessage = "Copying a 'moved-from' object";
+break;
+  case MK_Move:
+ErrorMessage = "Moving a 'moved-from' object";
+break;
+}
 if (const auto DecReg = Region->getAs()) {
   const auto *RegionDecl = dyn_cast(DecReg->getDecl());
   ErrorMessage += " '" + RegionDecl->getNameAsString() + "'";
@@ -365,7 +373,10 @@ void MisusedMovedObjectChecker::checkPre
   const RegionState *ArgState = State->get(ArgRegion);
   if (ArgState && ArgState->isMoved()) {
 if (!isInMoveSafeContext(LC)) {
-  N = reportBug(ArgRegion, Call, C, /*isCopy=*/true);
+  if(CtorDec->isMoveConstructor())
+N = reportBug(ArgRegion, Call, C, MK_Move);
+  else
+N = reportBug(ArgRegion, Call, C, MK_Copy);
   State = State->set(ArgRegion,
RegionState::getReported());
 }
@@ -405,7 +416,10 @@ void MisusedMovedObjectChecker::checkPre
   State->get(IC->getArgSVal(0).getAsRegion());
   if (ArgState && ArgState->isMoved() && !isInMoveSafeContext(LC)) {
 const MemRegion *ArgRegion = IC->getArgSVal(0).getAsRegion();
-N = reportBug(ArgRegion, Call, C, /*isCopy=*/true);
+if(MethodDecl->isMoveAssignmentOperator())
+  N = reportBug(ArgRegion, Call, C, MK_Move);
+else
+  N = reportBug(ArgRegion, Call, C, MK_Copy);
 State =
 State->set(ArgRegion, 
RegionState::getReported());
   }
@@ -443,7 +457,7 @@ void MisusedMovedObjectChecker::checkPre
   if (isInMoveSafeContext(LC))
 return;
 
-  N = reportBug(ThisRegion, Call, C);
+  N = reportBug(ThisRegion, Call, C, MK_FunCall);
   State = State->set(ThisRegion, RegionState::getReported());
   C.addTransition(State, N);
 }

Modified: cfe/trunk/test/Analysis/MisusedMovedObject.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/MisusedMovedObject.cpp?rev=316852&r1=316851&r2=316852&view=diff
==
--- cfe/trunk/

r316850 - [analyzer] MisusedMovedObjectChecker: Fix false positive on state-resetting, handling method calls on base-class sub-objects

2017-10-28 Thread Peter Szecsi via cfe-commits
Author: szepet
Date: Sat Oct 28 16:09:37 2017
New Revision: 316850

URL: http://llvm.org/viewvc/llvm-project?rev=316850&view=rev
Log:
[analyzer] MisusedMovedObjectChecker: Fix false positive on state-resetting, 
handling method calls on base-class sub-objects

An earlier solution from Artem r315301 solves the reset problem, however, the
reports should be handled the same way in case of method calls. We should not
just report the base class of the object where the method was defined but the
whole object.

Fixed false positive which came from not removing the subobjects in case of a
state-resetting function. (Just replaced the State->remove(...) call to
removeFromState(..) which was defined exactly for that purpose.)

Some minor typos fixed in this patch as well which did not worth a whole new
patch in my opinion, so included them here.

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


Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp
cfe/trunk/test/Analysis/MisusedMovedObject.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp?rev=316850&r1=316849&r2=316850&view=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp 
(original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp Sat Oct 
28 16:09:37 2017
@@ -352,7 +352,7 @@ void MisusedMovedObjectChecker::checkPre
   const LocationContext *LC = C.getLocationContext();
   ExplodedNode *N = nullptr;
 
-  // Remove the MemRegions from the map on which a ctor/dtor call or 
assignement
+  // Remove the MemRegions from the map on which a ctor/dtor call or assignment
   // happened.
 
   // Checking constructor calls.
@@ -380,8 +380,11 @@ void MisusedMovedObjectChecker::checkPre
 return;
   // In case of destructor call we do not track the object anymore.
   const MemRegion *ThisRegion = IC->getCXXThisVal().getAsRegion();
+  if (!ThisRegion)
+return;
+
   if (dyn_cast_or_null(Call.getDecl())) {
-State = removeFromState(State, IC->getCXXThisVal().getAsRegion());
+State = removeFromState(State, ThisRegion);
 C.addTransition(State);
 return;
   }
@@ -412,28 +415,28 @@ void MisusedMovedObjectChecker::checkPre
   }
 
   // The remaining part is check only for method call on a moved-from object.
+
+  // We want to investigate the whole object, not only sub-object of a parent
+  // class in which the encountered method defined.
+  while (const CXXBaseObjectRegion *BR =
+ dyn_cast(ThisRegion))
+ThisRegion = BR->getSuperRegion();
+
   if (isMoveSafeMethod(MethodDecl))
 return;
 
   if (isStateResetMethod(MethodDecl)) {
-// A state reset method resets the whole object, not only sub-object
-// of a parent class in which it is defined.
-const MemRegion *WholeObjectRegion = ThisRegion;
-while (const CXXBaseObjectRegion *BR =
-   dyn_cast(WholeObjectRegion))
-  WholeObjectRegion = BR->getSuperRegion();
-
-State = State->remove(WholeObjectRegion);
+State = removeFromState(State, ThisRegion);
 C.addTransition(State);
 return;
   }
 
-  // If it is already reported then we dont report the bug again.
+  // If it is already reported then we don't report the bug again.
   const RegionState *ThisState = State->get(ThisRegion);
   if (!(ThisState && ThisState->isMoved()))
 return;
 
-  // Dont report it in case if any base region is already reported
+  // Don't report it in case if any base region is already reported
   if (isAnyBaseRegionReported(State, ThisRegion))
 return;
 

Modified: cfe/trunk/test/Analysis/MisusedMovedObject.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/MisusedMovedObject.cpp?rev=316850&r1=316849&r2=316850&view=diff
==
--- cfe/trunk/test/Analysis/MisusedMovedObject.cpp (original)
+++ cfe/trunk/test/Analysis/MisusedMovedObject.cpp Sat Oct 28 16:09:37 2017
@@ -332,6 +332,8 @@ void moveStateResetFunctionsTest() {
 A b = std::move(a);
 a.reset(); // no-warning
 a.foo();   // no-warning
+// Test if resets the state of subregions as well.
+a.b.foo(); // no-warning
   }
   {
 A a;
@@ -344,6 +346,7 @@ void moveStateResetFunctionsTest() {
 A b = std::move(a);
 a.clear(); // no-warning
 a.foo();   // no-warning
+a.b.foo(); // no-warning
   }
 }
 
@@ -444,7 +447,7 @@ void differentBranchesTest(int i) {
   // Same thing, but with a switch statement.
   {
 A a, b;
-switch (i) { // expected-note {{Control jumps to 'case 1:'  at line 448}}
+switch (i) { // expected-note {{Control jumps to 'case 1:'  at line 451}}
 case 1:
   b = std::move(a); // no-warning
   break;// expected-note {{Execution jumps to the 

r316830 - [analyzer] LoopUnrolling: check the bitwidth of the used numbers (pr34943)

2017-10-28 Thread Peter Szecsi via cfe-commits
Author: szepet
Date: Sat Oct 28 05:19:08 2017
New Revision: 316830

URL: http://llvm.org/viewvc/llvm-project?rev=316830&view=rev
Log:
[analyzer] LoopUnrolling: check the bitwidth of the used numbers (pr34943)

The loop unrolling feature aims to track the maximum possible steps a loop can
make. In order to implement this, it investigates the initial value of the 
counter variable and the bound number. (It has to be known.)
These numbers are used as llvm::APInts, however, it was not checked if their
bitwidths are the same which lead to some crashes.
This revision solves this problem by extending the "shorter" one (to the length
of the "longer" one).
For the detailed bug report, see: https://bugs.llvm.org/show_bug.cgi?id=34943

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


Modified:
cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
cfe/trunk/test/Analysis/loop-unrolling.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp?rev=316830&r1=316829&r2=316830&view=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp Sat Oct 28 05:19:08 2017
@@ -208,9 +208,16 @@ bool shouldCompletelyUnroll(const Stmt *
 return false;
 
   auto CounterVar = Matches[0].getNodeAs("initVarName");
-  auto BoundNum = Matches[0].getNodeAs("boundNum")->getValue();
-  auto InitNum = Matches[0].getNodeAs("initNum")->getValue();
+  llvm::APInt BoundNum =
+  Matches[0].getNodeAs("boundNum")->getValue();
+  llvm::APInt InitNum =
+  Matches[0].getNodeAs("initNum")->getValue();
   auto CondOp = Matches[0].getNodeAs("conditionOperator");
+  if (InitNum.getBitWidth() != BoundNum.getBitWidth()) {
+InitNum = InitNum.zextOrSelf(BoundNum.getBitWidth());
+BoundNum = BoundNum.zextOrSelf(InitNum.getBitWidth());
+  }
+
   if (CondOp->getOpcode() == BO_GE || CondOp->getOpcode() == BO_LE)
 maxStep = (BoundNum - InitNum + 1).abs().getZExtValue();
   else

Modified: cfe/trunk/test/Analysis/loop-unrolling.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/loop-unrolling.cpp?rev=316830&r1=316829&r2=316830&view=diff
==
--- cfe/trunk/test/Analysis/loop-unrolling.cpp (original)
+++ cfe/trunk/test/Analysis/loop-unrolling.cpp Sat Oct 28 05:19:08 2017
@@ -373,3 +373,9 @@ int num_steps_over_limit3() {
   return 0;
 }
 
+
+void pr34943() {
+  for (int i = 0; i < 6L; ++i) {
+clang_analyzer_numTimesReached(); // expected-warning {{6}}
+  }
+}


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


[clang-tools-extra] r313016 - [clang-tidy] SuspiciousEnumUsageCheck bugfix

2017-09-12 Thread Peter Szecsi via cfe-commits
Author: szepet
Date: Tue Sep 12 02:40:13 2017
New Revision: 313016

URL: http://llvm.org/viewvc/llvm-project?rev=313016&view=rev
Log:
[clang-tidy] SuspiciousEnumUsageCheck bugfix

iThere is a reported bug on the checker not handling the some APSInt values
correctly: https://bugs.llvm.org/show_bug.cgi?id=34400

This patch aims to fix it.

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



Modified:
clang-tools-extra/trunk/clang-tidy/misc/SuspiciousEnumUsageCheck.cpp
clang-tools-extra/trunk/test/clang-tidy/misc-suspicious-enum-usage.cpp

Modified: clang-tools-extra/trunk/clang-tidy/misc/SuspiciousEnumUsageCheck.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/misc/SuspiciousEnumUsageCheck.cpp?rev=313016&r1=313015&r2=313016&view=diff
==
--- clang-tools-extra/trunk/clang-tidy/misc/SuspiciousEnumUsageCheck.cpp 
(original)
+++ clang-tools-extra/trunk/clang-tidy/misc/SuspiciousEnumUsageCheck.cpp Tue 
Sep 12 02:40:13 2017
@@ -42,7 +42,8 @@ struct ValueRange {
 const auto MinMaxVal = std::minmax_element(
 EnumDec->enumerator_begin(), EnumDec->enumerator_end(),
 [](const EnumConstantDecl *E1, const EnumConstantDecl *E2) {
-  return E1->getInitVal() < E2->getInitVal();
+  return llvm::APSInt::compareValues(E1->getInitVal(),
+ E2->getInitVal()) < 0;
 });
 MinVal = MinMaxVal.first->getInitVal();
 MaxVal = MinMaxVal.second->getInitVal();
@@ -57,7 +58,8 @@ static int enumLength(const EnumDecl *En
 static bool hasDisjointValueRange(const EnumDecl *Enum1,
   const EnumDecl *Enum2) {
   ValueRange Range1(Enum1), Range2(Enum2);
-  return (Range1.MaxVal < Range2.MinVal) || (Range2.MaxVal < Range1.MinVal);
+  return llvm::APSInt::compareValues(Range1.MaxVal, Range2.MinVal) < 0 ||
+ llvm::APSInt::compareValues(Range2.MaxVal, Range1.MinVal) < 0;
 }
 
 static bool isNonPowerOf2NorNullLiteral(const EnumConstantDecl *EnumConst) {

Modified: clang-tools-extra/trunk/test/clang-tidy/misc-suspicious-enum-usage.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/misc-suspicious-enum-usage.cpp?rev=313016&r1=313015&r2=313016&view=diff
==
--- clang-tools-extra/trunk/test/clang-tidy/misc-suspicious-enum-usage.cpp 
(original)
+++ clang-tools-extra/trunk/test/clang-tidy/misc-suspicious-enum-usage.cpp Tue 
Sep 12 02:40:13 2017
@@ -54,7 +54,7 @@ int trigger() {
   int emptytest = EmptyVal | B;
   if (bestDay() | A)
 return 1;
-  // CHECK-MESSAGES: :[[@LINE-2]]:17: warning: enum values are from different 
enum types 
+  // CHECK-MESSAGES: :[[@LINE-2]]:17: warning: enum values are from different 
enum types
   if (I | Y)
 return 1;
   // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: enum values are from different 
enum types
@@ -88,3 +88,9 @@ int dont_trigger() {
 return 1;
   return 42;
 }
+
+namespace PR34400 {
+enum { E1 = 0 };
+enum { E2 = -1 };
+enum { l = E1 | E2 };
+}


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


r311883 - [StaticAnalyzer] LoopUnrolling: Keep track the maximum number of steps for each loop

2017-08-28 Thread Peter Szecsi via cfe-commits
Author: szepet
Date: Mon Aug 28 03:50:28 2017
New Revision: 311883

URL: http://llvm.org/viewvc/llvm-project?rev=311883&view=rev
Log:
[StaticAnalyzer] LoopUnrolling: Keep track the maximum number of steps for each 
loop

This way the unrolling can be restricted for loops which will take at most a
given number of steps. It is defined as 128 in this patch and it seems to have
a good number for that purpose.

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


Modified:
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
cfe/trunk/test/Analysis/loop-unrolling.cpp

Modified: 
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h?rev=311883&r1=311882&r2=311883&view=diff
==
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h 
(original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h 
Mon Aug 28 03:50:28 2017
@@ -38,7 +38,7 @@ bool isUnrolledState(ProgramStateRef Sta
 
 /// Updates the stack of loops contained by the ProgramState.
 ProgramStateRef updateLoopStack(const Stmt *LoopStmt, ASTContext &ASTCtx,
-ExplodedNode* Pred);
+ExplodedNode* Pred, unsigned maxVisitOnPath);
 
 /// Updates the given ProgramState. In current implementation it removes the 
top
 /// element of the stack of loops.

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=311883&r1=311882&r2=311883&view=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Mon Aug 28 03:50:28 2017
@@ -1523,10 +1523,11 @@ void ExprEngine::processCFGBlockEntrance
   // If we reach a loop which has a known bound (and meets
   // other constraints) then consider completely unrolling it.
   if(AMgr.options.shouldUnrollLoops()) {
+unsigned maxBlockVisitOnPath = AMgr.options.maxBlockVisitOnPath;
 const Stmt *Term = nodeBuilder.getContext().getBlock()->getTerminator();
 if (Term) {
   ProgramStateRef NewState = updateLoopStack(Term, AMgr.getASTContext(),
- Pred);
+ Pred, maxBlockVisitOnPath);
   if (NewState != Pred->getState()) {
 ExplodedNode *UpdatedNode = nodeBuilder.generateNode(NewState, Pred);
 if (!UpdatedNode)

Modified: cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp?rev=311883&r1=311882&r2=311883&view=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp Mon Aug 28 03:50:28 2017
@@ -23,22 +23,28 @@ using namespace clang;
 using namespace ento;
 using namespace clang::ast_matchers;
 
+static const int MAXIMUM_STEP_UNROLLED = 128;
+
 struct LoopState {
 private:
   enum Kind { Normal, Unrolled } K;
   const Stmt *LoopStmt;
   const LocationContext *LCtx;
-  LoopState(Kind InK, const Stmt *S, const LocationContext *L)
-  : K(InK), LoopStmt(S), LCtx(L) {}
+  unsigned maxStep;
+  LoopState(Kind InK, const Stmt *S, const LocationContext *L, unsigned N)
+  : K(InK), LoopStmt(S), LCtx(L), maxStep(N) {}
 
 public:
-  static LoopState getNormal(const Stmt *S, const LocationContext *L) {
-return LoopState(Normal, S, L);
+  static LoopState getNormal(const Stmt *S, const LocationContext *L,
+ unsigned N) {
+return LoopState(Normal, S, L, N);
   }
-  static LoopState getUnrolled(const Stmt *S, const LocationContext *L) {
-return LoopState(Unrolled, S, L);
+  static LoopState getUnrolled(const Stmt *S, const LocationContext *L,
+   unsigned N) {
+return LoopState(Unrolled, S, L, N);
   }
   bool isUnrolled() const { return K == Unrolled; }
+  unsigned getMaxStep() const { return maxStep; }
   const Stmt *getLoopStmt() const { return LoopStmt; }
   const LocationContext *getLocationContext() const { return LCtx; }
   bool operator==(const LoopState &X) const {
@@ -48,6 +54,7 @@ public:
 ID.AddInteger(K);
 ID.AddPointer(LoopStmt);
 ID.AddPointer(LCtx);
+ID.AddInteger(maxStep);
   }
 };
 
@@ -74,12 +81,14 @@ ProgramStateRef processLoopEnd(const Stm
 }
 
 static internal::Matcher simpleCondition(StringRef BindName) {
-  return binaryOperator(
-  anyOf(hasOperatorName("<"), hasOperatorName

r311881 - [StaticAnalyzer] LoopUnrolling: Excluding loops which splits the state

2017-08-28 Thread Peter Szecsi via cfe-commits
Author: szepet
Date: Mon Aug 28 03:34:50 2017
New Revision: 311881

URL: http://llvm.org/viewvc/llvm-project?rev=311881&view=rev
Log:
[StaticAnalyzer] LoopUnrolling: Excluding loops which splits the state

Added check if the execution of the last step of the given unrolled loop has
generated more branches. If yes, than treat it as a normal (non-unrolled) loop
in the remaining part of the analysis.

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


Modified:
cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
cfe/trunk/test/Analysis/loop-unrolling.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp?rev=311881&r1=311880&r2=311881&view=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp Mon Aug 28 03:34:50 2017
@@ -204,6 +204,26 @@ bool shouldCompletelyUnroll(const Stmt *
   return !isPossiblyEscaped(CounterVar->getCanonicalDecl(), Pred);
 }
 
+bool madeNewBranch(ExplodedNode* N, const Stmt* LoopStmt) {
+  const Stmt* S = nullptr;
+  while (!N->pred_empty())
+  {
+if (N->succ_size() > 1)
+  return true;
+
+ProgramPoint P = N->getLocation();
+if (Optional BE = P.getAs())
+  S = BE->getBlock()->getTerminator();
+
+if (S == LoopStmt)
+  return false;
+
+N = N->getFirstPred();
+  }
+
+  llvm_unreachable("Reached root without encountering the previous step");
+}
+
 // updateLoopStack is called on every basic block, therefore it needs to be 
fast
 ProgramStateRef updateLoopStack(const Stmt *LoopStmt, ASTContext &ASTCtx,
 ExplodedNode* Pred) {
@@ -215,8 +235,13 @@ ProgramStateRef updateLoopStack(const St
 
   auto LS = State->get();
   if (!LS.isEmpty() && LoopStmt == LS.getHead().getLoopStmt() &&
-  LCtx == LS.getHead().getLocationContext())
+  LCtx == LS.getHead().getLocationContext()) {
+if (LS.getHead().isUnrolled() && madeNewBranch(Pred, LoopStmt)) {
+  State = State->set(LS.getTail());
+  State = State->add(LoopState::getNormal(LoopStmt, LCtx));
+}
 return State;
+  }
 
   if (!shouldCompletelyUnroll(LoopStmt, ASTCtx, Pred)) {
 State = State->add(LoopState::getNormal(LoopStmt, LCtx));

Modified: cfe/trunk/test/Analysis/loop-unrolling.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/loop-unrolling.cpp?rev=311881&r1=311880&r2=311881&view=diff
==
--- cfe/trunk/test/Analysis/loop-unrolling.cpp (original)
+++ cfe/trunk/test/Analysis/loop-unrolling.cpp Mon Aug 28 03:34:50 2017
@@ -1,6 +1,7 @@
 // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection 
-analyzer-config unroll-loops=true,cfg-loopexit=true -verify -std=c++11 %s
 
 void clang_analyzer_numTimesReached();
+void clang_analyzer_warnIfReached();
 
 int getNum();
 void foo(int &);
@@ -62,8 +63,7 @@ int simple_no_unroll2() {
 int simple_no_unroll3() {
   int a[9];
   int k = 42;
-  int i;
-  for (i = 0; i < 9; i++) {
+  for (int i = 0; i < 9; i++) {
 clang_analyzer_numTimesReached(); // expected-warning {{4}}
 a[i] = 42;
 (void)&i;
@@ -98,6 +98,44 @@ int simple_no_unroll5() {
   return 0;
 }
 
+int make_new_branches_loop_cached() {
+  for (int i = 0; i < 8; i++) {
+clang_analyzer_numTimesReached(); // expected-warning {{4}}
+if(getNum()){
+(void) i; // Since this Stmt does not change the State the analyzer
+  // won't make a new execution path but reuse the earlier 
nodes.
+  }
+  }
+  clang_analyzer_warnIfReached(); // no-warning
+  return 0;
+}
+
+int make_new_branches_loop_uncached() {
+  int l = 2;
+  for (int i = 0; i < 8; i++) {
+clang_analyzer_numTimesReached(); // expected-warning {{10}}
+if(getNum()){
+  ++l;
+}
+  }
+  clang_analyzer_warnIfReached(); // no-warning
+  return 0;
+}
+
+int make_new_branches_loop_uncached2() {
+  int l = 2;
+  for (int i = 0; i < 8; i++) {
+clang_analyzer_numTimesReached(); // expected-warning {{10}}
+if(getNum()){
+  ++l;
+}
+(void)&i; // This ensures that the loop won't be unrolled.
+  }
+  clang_analyzer_warnIfReached(); // no-warning
+  return 0;
+}
+
+
 int escape_before_loop_no_unroll1() {
   int a[9];
   int k = 42;
@@ -142,10 +180,11 @@ int nested_outer_unrolled() {
   int k = 42;
   int j = 0;
   for (int i = 0; i < 9; i++) {
-clang_analyzer_numTimesReached(); // expected-warning {{16}}
-for (j = 0; j < getNum(); ++j) {
-  clang_analyzer_numTimesReached(); // expected-warning {{15}}
+clang_analyzer_numTimesReached(); // expected-warning {{1}}
+for (j = 0; j < 9; ++j) {
+  clang_analyzer_numTimesReached(); // expected-warning {{4}}
   a[j] = 22;
+  (void) &j; // ensures that the inner loop won't be unrolled
 }
 a[i]

r311880 - [StaticAnalyzer] LoopUnrolling fixes

2017-08-28 Thread Peter Szecsi via cfe-commits
Author: szepet
Date: Mon Aug 28 03:21:24 2017
New Revision: 311880

URL: http://llvm.org/viewvc/llvm-project?rev=311880&view=rev
Log:
[StaticAnalyzer] LoopUnrolling fixes

1. The LoopUnrolling feature needs the LoopExit included in the CFG so added 
this
dependency via the config options
2. The LoopExit element can be encountered even if we haven't encountered the 
block of the corresponding LoopStmt. So the asserts were not right.
3. If we are caching out the Node then we get a nullptr from generateNode which
case was not handled.


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

Modified:
cfe/trunk/lib/StaticAnalyzer/Core/AnalysisManager.cpp
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
cfe/trunk/test/Analysis/loop-unrolling.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Core/AnalysisManager.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/AnalysisManager.cpp?rev=311880&r1=311879&r2=311880&view=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Core/AnalysisManager.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/AnalysisManager.cpp Mon Aug 28 03:21:24 
2017
@@ -27,7 +27,9 @@ AnalysisManager::AnalysisManager(ASTCont
   /*AddInitializers=*/true,
   Options.includeTemporaryDtorsInCFG(),
Options.includeLifetimeInCFG(),
-  Options.includeLoopExitInCFG(),
+  // Adding LoopExit elements to the CFG is a requirement for loop
+  // unrolling.
+  Options.includeLoopExitInCFG() || Options.shouldUnrollLoops(),
   Options.shouldSynthesizeBodies(),
   Options.shouldConditionalizeStaticInitializers(),
   /*addCXXNewAllocator=*/true,

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=311880&r1=311879&r2=311880&view=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Mon Aug 28 03:21:24 2017
@@ -1527,8 +1527,11 @@ void ExprEngine::processCFGBlockEntrance
 if (Term) {
   ProgramStateRef NewState = updateLoopStack(Term, AMgr.getASTContext(),
  Pred);
-  if (NewState != Pred->getState()){
-Pred = nodeBuilder.generateNode(NewState, Pred);
+  if (NewState != Pred->getState()) {
+ExplodedNode *UpdatedNode = nodeBuilder.generateNode(NewState, Pred);
+if (!UpdatedNode)
+  return;
+Pred = UpdatedNode;
   }
 }
 // Is we are inside an unrolled loop then no need the check the counters.

Modified: cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp?rev=311880&r1=311879&r2=311880&view=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp Mon Aug 28 03:21:24 2017
@@ -13,15 +13,11 @@
 ///
 
//===--===//
 
-#include "clang/Analysis/CFGStmtMap.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
-#include "clang/AST/ParentMap.h"
-#include "clang/AST/StmtVisitor.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h"
-#include "llvm/ADT/Statistic.h"
 
 using namespace clang;
 using namespace ento;
@@ -72,11 +68,8 @@ static bool isLoopStmt(const Stmt *S) {
 
 ProgramStateRef processLoopEnd(const Stmt *LoopStmt, ProgramStateRef State) {
   auto LS = State->get();
-  assert(!LS.isEmpty() && "Loop not added to the stack.");
-  assert(LoopStmt == LS.getHead().getLoopStmt() &&
- "Loop is not on top of the stack.");
-
-  State = State->set(LS.getTail());
+  if (!LS.isEmpty() && LS.getHead().getLoopStmt() == LoopStmt)
+State = State->set(LS.getTail());
   return State;
 }
 

Modified: cfe/trunk/test/Analysis/loop-unrolling.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/loop-unrolling.cpp?rev=311880&r1=311879&r2=311880&view=diff
==
--- cfe/trunk/test/Analysis/loop-unrolling.cpp (original)
+++ cfe/trunk/test/Analysis/loop-unrolling.cpp Mon Aug 28 03:21:24 2017
@@ -272,3 +272,10 @@ int recursion_unroll4(bool b) {
   int a = 22 / k;
   return 0;
 }
+
+int loop_exit_while_empty_loop_stack() {
+  if (getNum())
+for (int i = 1; i < 8; i++)
+  ;
+  return 0;
+}



r311346 - [StaticAnalyzer] LoopUnrolling: Track a LoopStack in order to completely unroll specific loops

2017-08-21 Thread Peter Szecsi via cfe-commits
Author: szepet
Date: Mon Aug 21 09:32:57 2017
New Revision: 311346

URL: http://llvm.org/viewvc/llvm-project?rev=311346&view=rev
Log:
[StaticAnalyzer] LoopUnrolling: Track a LoopStack in order to completely unroll 
specific loops

The LoopExit CFG information provides the opportunity to not mark the loops but
having a stack which tracks if a loop is unrolled or not. So in case of
simulating a loop we just add it and the information if it meets the
requirements to be unrolled to the top of the stack.

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

Modified:
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
cfe/trunk/test/Analysis/loop-unrolling.cpp

Modified: 
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h?rev=311346&r1=311345&r2=311346&view=diff
==
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h 
(original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h 
Mon Aug 21 09:32:57 2017
@@ -8,7 +8,17 @@
 
//===--===//
 ///
 /// This header contains the declarations of functions which are used to decide
-/// which loops should be completely unrolled and mark them.
+/// which loops should be completely unrolled and mark their corresponding
+/// CFGBlocks. It is done by tracking a stack of loops in the ProgramState. 
This
+/// way specific loops can be marked as completely unrolled. For considering a
+/// loop to be completely unrolled it has to fulfill the following 
requirements:
+/// - Currently only forStmts can be considered.
+/// - The bound has to be known.
+/// - The counter variable has not escaped before/in the body of the loop and
+///   changed only in the increment statement corresponding to the loop. It 
also
+///   has to be initialized by a literal in the corresponding initStmt.
+/// - Does not contain goto, switch and returnStmt.
+///
 ///
 
//===--===//
 
@@ -18,17 +28,21 @@
 #include "clang/Analysis/CFG.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
-
 namespace clang {
 namespace ento {
 class AnalysisManager;
 
-ProgramStateRef markLoopAsUnrolled(const Stmt *Term, ProgramStateRef State,
-   const FunctionDecl *FD);
-bool isUnrolledLoopBlock(const CFGBlock *Block, ExplodedNode *Pred,
- AnalysisManager &AMgr);
-bool shouldCompletelyUnroll(const Stmt *LoopStmt, ASTContext &ASTCtx,
-ExplodedNode *Pred);
+/// Returns if the given State indicates that is inside a completely unrolled
+/// loop.
+bool isUnrolledState(ProgramStateRef State);
+
+/// Updates the stack of loops contained by the ProgramState.
+ProgramStateRef updateLoopStack(const Stmt *LoopStmt, ASTContext &ASTCtx,
+ExplodedNode* Pred);
+
+/// Updates the given ProgramState. In current implementation it removes the 
top
+/// element of the stack of loops.
+ProgramStateRef processLoopEnd(const Stmt *LoopStmt, ProgramStateRef State);
 
 } // end namespace ento
 } // end namespace clang

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=311346&r1=311345&r2=311346&view=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Mon Aug 21 09:32:57 2017
@@ -519,10 +519,13 @@ void ExprEngine::ProcessLoopExit(const S
   ExplodedNodeSet Dst;
   Dst.Add(Pred);
   NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
+  ProgramStateRef NewState = Pred->getState();
 
-  LoopExit PP(S, Pred->getLocationContext());
-  Bldr.generateNode(PP, Pred->getState(), Pred);
+  if(AMgr.options.shouldUnrollLoops())
+NewState = processLoopEnd(S, NewState);
 
+  LoopExit PP(S, Pred->getLocationContext());
+  Bldr.generateNode(PP, NewState, Pred);
   // Enqueue the new nodes onto the work list.
   Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
 }
@@ -1519,22 +1522,17 @@ void ExprEngine::processCFGBlockEntrance
   PrettyStackTraceLocationContext CrashInfo(Pred->getLocationContext());
   // If we reach a loop which has a known bound (and meets
   // other constraints) then consider completely unrolling it.
-  if (AMgr.options.shouldUnrollLoops()) {
-const CFGBlock *ActualBlock = nodeBuilder.getContext().getBlock();
-const Stmt *Term = ActualBlock->getTerminato

r311344 - [StaticAnalyzer] Handle LoopExit CFGElement in the analyzer

2017-08-21 Thread Peter Szecsi via cfe-commits
Author: szepet
Date: Mon Aug 21 09:10:19 2017
New Revision: 311344

URL: http://llvm.org/viewvc/llvm-project?rev=311344&view=rev
Log:
[StaticAnalyzer] Handle LoopExit CFGElement in the analyzer

This patch adds handling of the LoopExit CFGElements to the StaticAnalyzer.
This is reached by introducing a new ProgramPoint.
Tests will be added in a following commit.

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

Modified:
cfe/trunk/include/clang/Analysis/ProgramPoint.h
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
cfe/trunk/lib/StaticAnalyzer/Core/CoreEngine.cpp
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp

Modified: cfe/trunk/include/clang/Analysis/ProgramPoint.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/ProgramPoint.h?rev=311344&r1=311343&r2=311344&view=diff
==
--- cfe/trunk/include/clang/Analysis/ProgramPoint.h (original)
+++ cfe/trunk/include/clang/Analysis/ProgramPoint.h Mon Aug 21 09:10:19 2017
@@ -83,6 +83,7 @@ public:
   PostImplicitCallKind,
   MinImplicitCallKind = PreImplicitCallKind,
   MaxImplicitCallKind = PostImplicitCallKind,
+  LoopExitKind,
   EpsilonKind};
 
 private:
@@ -654,6 +655,29 @@ private:
   }
 };
 
+/// Represents a point when we exit a loop.
+/// When this ProgramPoint is encountered we can be sure that the symbolic
+/// execution of the corresponding LoopStmt is finished on the given path.
+/// Note: It is possible to encounter a LoopExit element when we haven't even
+/// encountered the loop itself. At the current state not all loop exits will
+/// result in a LoopExit program point.
+class LoopExit : public ProgramPoint {
+public:
+LoopExit(const Stmt *LoopStmt, const LocationContext *LC)
+: ProgramPoint(LoopStmt, nullptr, LoopExitKind, LC) {}
+
+const Stmt *getLoopStmt() const {
+  return static_cast(getData1());
+}
+
+private:
+friend class ProgramPoint;
+LoopExit() {}
+static bool isKind(const ProgramPoint &Location) {
+  return Location.getKind() == LoopExitKind;
+}
+};
+
 /// This is a meta program point, which should be skipped by all the diagnostic
 /// reasoning etc.
 class EpsilonPoint : public ProgramPoint {

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h?rev=311344&r1=311343&r2=311344&view=diff
==
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h 
(original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h Mon 
Aug 21 09:10:19 2017
@@ -196,6 +196,8 @@ public:
 
   void ProcessStmt(const CFGStmt S, ExplodedNode *Pred);
 
+  void ProcessLoopExit(const Stmt* S, ExplodedNode *Pred);
+
   void ProcessInitializer(const CFGInitializer I, ExplodedNode *Pred);
 
   void ProcessImplicitDtor(const CFGImplicitDtor D, ExplodedNode *Pred);

Modified: cfe/trunk/lib/StaticAnalyzer/Core/CoreEngine.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CoreEngine.cpp?rev=311344&r1=311343&r2=311344&view=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Core/CoreEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CoreEngine.cpp Mon Aug 21 09:10:19 2017
@@ -274,7 +274,8 @@ void CoreEngine::dispatchWorkItem(Explod
   assert(Loc.getAs() ||
  Loc.getAs() ||
  Loc.getAs() ||
- Loc.getAs());
+ Loc.getAs() ||
+ Loc.getAs());
   HandlePostStmt(WU.getBlock(), WU.getIndex(), Pred);
   break;
   }
@@ -566,7 +567,8 @@ void CoreEngine::enqueueStmtNode(Explode
 
   // Do not create extra nodes. Move to the next CFG element.
   if (N->getLocation().getAs() ||
-  N->getLocation().getAs()) {
+  N->getLocation().getAs()||
+  N->getLocation().getAs()) {
 WList->enqueue(N, Block, Idx+1);
 return;
   }

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=311344&r1=311343&r2=311344&view=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Mon Aug 21 09:10:19 2017
@@ -364,8 +364,10 @@ void ExprEngine::processCFGElement(const
 case CFGElement::TemporaryDtor:
   ProcessImplicitDtor(E.castAs(), Pred);
   return;
-case CFGElement::LifetimeEnds:
 case CFGElement::LoopExit:
+  ProcessLoopExit(E.castAs().getLoopStmt(), Pred);
+  return;
+case CFGElement::LifetimeEnds:
   return;
   }
 }
@@ -510,6 +512,21 @@ void

r311235 - [CFG] Add LoopExit information to CFG

2017-08-19 Thread Peter Szecsi via cfe-commits
Author: szepet
Date: Sat Aug 19 04:19:16 2017
New Revision: 311235

URL: http://llvm.org/viewvc/llvm-project?rev=311235&view=rev
Log:
[CFG] Add LoopExit information to CFG

This patch introduces a new CFG element CFGLoopExit that indicate when a loop
ends. It does not deal with returnStmts yet (left it as a TODO).
It hidden behind a new analyzer-config flag called cfg-loopexit (false by
default).
Test cases added.

The main purpose of this patch right know is to make loop unrolling and loop
widening easier and more efficient. However, this information can be useful for
future improvements in the StaticAnalyzer core too.

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


Added:
cfe/trunk/test/Analysis/loopexit-cfg-output.cpp
Modified:
cfe/trunk/include/clang/Analysis/AnalysisContext.h
cfe/trunk/include/clang/Analysis/CFG.h
cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp
cfe/trunk/lib/Analysis/CFG.cpp
cfe/trunk/lib/StaticAnalyzer/Core/AnalysisManager.cpp
cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
cfe/trunk/test/Analysis/analyzer-config.c
cfe/trunk/test/Analysis/analyzer-config.cpp

Modified: cfe/trunk/include/clang/Analysis/AnalysisContext.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/AnalysisContext.h?rev=311235&r1=311234&r2=311235&view=diff
==
--- cfe/trunk/include/clang/Analysis/AnalysisContext.h (original)
+++ cfe/trunk/include/clang/Analysis/AnalysisContext.h Sat Aug 19 04:19:16 2017
@@ -427,6 +427,7 @@ public:
  bool addInitializers = false,
  bool addTemporaryDtors = false,
  bool addLifetime = false,
+ bool addLoopExit = false,
  bool synthesizeBodies = false,
  bool addStaticInitBranches = false,
  bool addCXXNewAllocator = true,

Modified: cfe/trunk/include/clang/Analysis/CFG.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/CFG.h?rev=311235&r1=311234&r2=311235&view=diff
==
--- cfe/trunk/include/clang/Analysis/CFG.h (original)
+++ cfe/trunk/include/clang/Analysis/CFG.h Sat Aug 19 04:19:16 2017
@@ -59,6 +59,7 @@ public:
 Initializer,
 NewAllocator,
 LifetimeEnds,
+LoopExit,
 // dtor kind
 AutomaticObjectDtor,
 DeleteDtor,
@@ -168,6 +169,29 @@ private:
   }
 };
 
+/// Represents the point where a loop ends.
+/// This element is is only produced when building the CFG for the static
+/// analyzer and hidden behind the 'cfg-loopexit' analyzer config flag.
+///
+/// Note: a loop exit element can be reached even when the loop body was never
+/// entered.
+class CFGLoopExit : public CFGElement {
+public:
+explicit CFGLoopExit(const Stmt *stmt)
+: CFGElement(LoopExit, stmt) {}
+
+const Stmt *getLoopStmt() const {
+  return static_cast(Data1.getPointer());
+}
+
+private:
+friend class CFGElement;
+CFGLoopExit() {}
+static bool isKind(const CFGElement &elem) {
+  return elem.getKind() == LoopExit;
+}
+};
+
 /// Represents the point where the lifetime of an automatic object ends
 class CFGLifetimeEnds : public CFGElement {
 public:
@@ -728,6 +752,10 @@ public:
 Elements.push_back(CFGLifetimeEnds(VD, S), C);
   }
 
+  void appendLoopExit(const Stmt *LoopStmt, BumpVectorContext &C) {
+Elements.push_back(CFGLoopExit(LoopStmt), C);
+  }
+
   void appendDeleteDtor(CXXRecordDecl *RD, CXXDeleteExpr *DE, 
BumpVectorContext &C) {
 Elements.push_back(CFGDeleteDtor(RD, DE), C);
   }
@@ -794,6 +822,7 @@ public:
 bool AddInitializers;
 bool AddImplicitDtors;
 bool AddLifetime;
+bool AddLoopExit;
 bool AddTemporaryDtors;
 bool AddStaticInitBranches;
 bool AddCXXNewAllocator;
@@ -818,7 +847,7 @@ public:
 PruneTriviallyFalseEdges(true),
 AddEHEdges(false),
 AddInitializers(false), AddImplicitDtors(false),
-AddLifetime(false),
+AddLifetime(false), AddLoopExit(false),
 AddTemporaryDtors(false), AddStaticInitBranches(false),
 AddCXXNewAllocator(false), AddCXXDefaultInitExprInCtors(false) {}
   };

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=311235&r1=311234&r2=311235&view=diff
==
--- cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h Sat Aug 1

r311234 - [StaticAnalyzer] LoopUnrolling: Exclude cases where the counter is escaped before the loop

2017-08-19 Thread Peter Szecsi via cfe-commits
Author: szepet
Date: Sat Aug 19 03:24:52 2017
New Revision: 311234

URL: http://llvm.org/viewvc/llvm-project?rev=311234&view=rev
Log:
[StaticAnalyzer] LoopUnrolling: Exclude cases where the counter is escaped 
before the loop

Adding escape check for the counter variable of the loop.
It is achieved by jumping back on the ExplodedGraph to its declStmt.

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


Modified:
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
cfe/trunk/test/Analysis/loop-unrolling.cpp

Modified: 
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h?rev=311234&r1=311233&r2=311234&view=diff
==
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h 
(original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h 
Sat Aug 19 03:24:52 2017
@@ -8,8 +8,7 @@
 
//===--===//
 ///
 /// This header contains the declarations of functions which are used to decide
-/// which loops should be completely unrolled and mark their corresponding
-/// CFGBlocks.
+/// which loops should be completely unrolled and mark them.
 ///
 
//===--===//
 
@@ -28,7 +27,8 @@ ProgramStateRef markLoopAsUnrolled(const
const FunctionDecl *FD);
 bool isUnrolledLoopBlock(const CFGBlock *Block, ExplodedNode *Pred,
  AnalysisManager &AMgr);
-bool shouldCompletelyUnroll(const Stmt *LoopStmt, ASTContext &ASTCtx);
+bool shouldCompletelyUnroll(const Stmt *LoopStmt, ASTContext &ASTCtx,
+ExplodedNode *Pred);
 
 } // end namespace ento
 } // end namespace clang

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=311234&r1=311233&r2=311234&view=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Sat Aug 19 03:24:52 2017
@@ -1504,7 +1504,7 @@ void ExprEngine::processCFGBlockEntrance
   if (AMgr.options.shouldUnrollLoops()) {
 const CFGBlock *ActualBlock = nodeBuilder.getContext().getBlock();
 const Stmt *Term = ActualBlock->getTerminator();
-if (Term && shouldCompletelyUnroll(Term, AMgr.getASTContext())) {
+if (Term && shouldCompletelyUnroll(Term, AMgr.getASTContext(), Pred)) {
   ProgramStateRef UnrolledState = markLoopAsUnrolled(
   Term, Pred->getState(),
   cast(Pred->getStackFrame()->getDecl()));

Modified: cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp?rev=311234&r1=311233&r2=311234&view=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp Sat Aug 19 03:24:52 2017
@@ -8,8 +8,9 @@
 
//===--===//
 ///
 /// This file contains functions which are used to decide if a loop worth to be
-/// unrolled. Moreover contains function which mark the CFGBlocks which belongs
-/// to the unrolled loop and store them in ProgramState.
+/// unrolled. Moreover contains function which mark the loops which are 
unrolled
+/// and store them in ProgramState. During the analysis we check the analyzed
+/// blocks if they are part of an unrolled loop or reached from one.
 ///
 
//===--===//
 
@@ -51,47 +52,52 @@ static internal::Matcher simpleCon
   hasEitherOperand(ignoringParenImpCasts(integerLiteral(;
 }
 
-static internal::Matcher changeIntBoundNode(StringRef NodeName) {
-  return anyOf(hasDescendant(unaryOperator(
-   anyOf(hasOperatorName("--"), hasOperatorName("++")),
-   hasUnaryOperand(ignoringParenImpCasts(
-   declRefExpr(to(varDecl(equalsBoundNode(NodeName,
-   hasDescendant(binaryOperator(
-   anyOf(hasOperatorName("="), hasOperatorName("+="),
- hasOperatorName("/="), hasOperatorName("*="),
- hasOperatorName("-=")),
-   hasLHS(ignoringParenImpCasts(
-   
declRefExpr(to(varDecl(equalsBoundNode(NodeName);
-}
-
-static internal::Matcher callByRef(StringRef NodeName) {
-  retur

r309061 - [StaticAnalyzer] LoopUnrolling - Attempt #2 to fix a crash in r309006.

2017-07-25 Thread Peter Szecsi via cfe-commits
Author: szepet
Date: Tue Jul 25 16:49:16 2017
New Revision: 309061

URL: http://llvm.org/viewvc/llvm-project?rev=309061&view=rev
Log:
[StaticAnalyzer] LoopUnrolling - Attempt #2 to fix a crash in r309006.

Modified:
cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp?rev=309061&r1=309060&r2=309061&view=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp Tue Jul 25 16:49:16 2017
@@ -183,9 +183,9 @@ bool isUnrolledLoopBlock(const CFGBlock
 LBV.setBlocksOfLoop(E.first, M);
 // In case of an inlined function call check if any of its callSiteBlock is
 // marked.
-while (BlockSet.find(SearchedBlock) == BlockSet.end() && 
!StackFrame->inTopFrame()) {
+while (BlockSet.find(SearchedBlock) == BlockSet.end() && StackFrame) {
   SearchedBlock = StackFrame->getCallSiteBlock();
-  if(!SearchedBlock)
+  if(!SearchedBlock || StackFrame->inTopFrame())
 break;
   StackFrame = StackFrame->getParent()->getCurrentStackFrame();
 }


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


r309036 - [StaticAnalyzer] LoopUnrolling - Attempt to fix a crash in r309006.

2017-07-25 Thread Peter Szecsi via cfe-commits
Author: szepet
Date: Tue Jul 25 14:54:58 2017
New Revision: 309036

URL: http://llvm.org/viewvc/llvm-project?rev=309036&view=rev
Log:
[StaticAnalyzer] LoopUnrolling - Attempt to fix a crash in r309006.


Modified:
cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp?rev=309036&r1=309035&r2=309036&view=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp Tue Jul 25 14:54:58 2017
@@ -183,8 +183,10 @@ bool isUnrolledLoopBlock(const CFGBlock
 LBV.setBlocksOfLoop(E.first, M);
 // In case of an inlined function call check if any of its callSiteBlock is
 // marked.
-while (SearchedBlock && BlockSet.find(SearchedBlock) == BlockSet.end()) {
+while (BlockSet.find(SearchedBlock) == BlockSet.end() && 
!StackFrame->inTopFrame()) {
   SearchedBlock = StackFrame->getCallSiteBlock();
+  if(!SearchedBlock)
+break;
   StackFrame = StackFrame->getParent()->getCurrentStackFrame();
 }
 delete M;


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


r309006 - [StaticAnalyzer] Completely unrolling specific loops with known bound option

2017-07-25 Thread Peter Szecsi via cfe-commits
Author: szepet
Date: Tue Jul 25 12:23:23 2017
New Revision: 309006

URL: http://llvm.org/viewvc/llvm-project?rev=309006&view=rev
Log:
[StaticAnalyzer] Completely unrolling specific loops with known bound option

This feature allows the analyzer to consider loops to completely unroll.
New requirements/rules (for unrolling) can be added easily via ASTMatchers.

Right now it is hidden behind a flag, the aim is to find the correct heuristic
and create a solution which results higher coverage % and more precise
analysis, thus can be enabled by default.

Right now the blocks which belong to an unrolled loop are marked by the
LoopVisitor which adds them to the ProgramState.
Then whenever we encounter a CFGBlock in the processCFGBlockEntrance which is
marked then we skip its investigating. That means, it won't be considered to
be visited more than the maximal bound for visiting since it won't be checked.

Added:
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h
cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
cfe/trunk/test/Analysis/loop-unrolling.cpp
Modified:
cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
cfe/trunk/lib/StaticAnalyzer/Core/CMakeLists.txt
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
cfe/trunk/test/Analysis/analyzer-config.c
cfe/trunk/test/Analysis/analyzer-config.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=309006&r1=309005&r2=309006&view=diff
==
--- cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h Tue Jul 25 
12:23:23 2017
@@ -275,6 +275,9 @@ private:
   /// \sa shouldWidenLoops
   Optional WidenLoops;
 
+  /// \sa shouldUnrollLoops
+  Optional UnrollLoops;
+
   /// \sa shouldDisplayNotesAsEvents
   Optional DisplayNotesAsEvents;
 
@@ -560,6 +563,10 @@ public:
   /// This is controlled by the 'widen-loops' config option.
   bool shouldWidenLoops();
 
+  /// Returns true if the analysis should try to unroll loops with known 
bounds.
+  /// This is controlled by the 'unroll-loops' config option.
+  bool shouldUnrollLoops();
+
   /// Returns true if the bug reporter should transparently treat extra note
   /// diagnostic pieces as event diagnostic pieces. Useful when the diagnostic
   /// consumer doesn't support the extra note pieces.

Added: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h?rev=309006&view=auto
==
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h 
(added)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h 
Tue Jul 25 12:23:23 2017
@@ -0,0 +1,34 @@
+//===--- LoopUnrolling.h - Unroll loops -*- C++ 
-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+///
+/// This header contains the declarations of functions which are used to decide
+/// which loops should be completely unrolled and mark their corresponding
+/// CFGBlocks.
+///
+//===--===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_LOOPUNROLLING_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_LOOPUNROLLING_H
+
+#include "clang/Analysis/CFG.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
+
+namespace clang {
+namespace ento {
+ProgramStateRef markLoopAsUnrolled(const Stmt *Term, ProgramStateRef State,
+   const FunctionDecl *FD);
+bool isUnrolledLoopBlock(const CFGBlock *Block, ExplodedNode *Pred,
+ AnalysisManager &AMgr);
+bool shouldCompletelyUnroll(const Stmt *LoopStmt, ASTContext &ASTCtx);
+
+} // end namespace ento
+} // end namespace clang
+
+#endif

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp?rev=309006&r1=309005&r2=309006&view=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.

r308592 - Revert "[StaticAnalyzer] Completely unrolling specific loops with known bound option"

2017-07-20 Thread Peter Szecsi via cfe-commits
Author: szepet
Date: Thu Jul 20 00:35:11 2017
New Revision: 308592

URL: http://llvm.org/viewvc/llvm-project?rev=308592&view=rev
Log:
Revert "[StaticAnalyzer] Completely unrolling specific loops with known bound 
option"

Revert r308561 and r308558.

Clang-ppc64be-linux seems to crash while running the test cases.


Removed:
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h
cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
cfe/trunk/test/Analysis/loop-unrolling.cpp
Modified:
cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
cfe/trunk/lib/StaticAnalyzer/Core/CMakeLists.txt
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
cfe/trunk/test/Analysis/analyzer-config.c
cfe/trunk/test/Analysis/analyzer-config.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=308592&r1=308591&r2=308592&view=diff
==
--- cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h Thu Jul 20 
00:35:11 2017
@@ -275,9 +275,6 @@ private:
   /// \sa shouldWidenLoops
   Optional WidenLoops;
 
-  /// \sa shouldUnrollLoops
-  Optional UnrollLoops;
-
   /// \sa shouldDisplayNotesAsEvents
   Optional DisplayNotesAsEvents;
 
@@ -563,11 +560,7 @@ public:
   /// This is controlled by the 'widen-loops' config option.
   bool shouldWidenLoops();
 
-  /// Returns true if the analysis should try to unroll loops with known 
bounds.
-  /// This is controlled by the 'unroll-loops' config option.
-  bool shouldUnrollLoops();
-
-/// Returns true if the bug reporter should transparently treat extra note
+  /// Returns true if the bug reporter should transparently treat extra note
   /// diagnostic pieces as event diagnostic pieces. Useful when the diagnostic
   /// consumer doesn't support the extra note pieces.
   ///

Removed: 
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h?rev=308591&view=auto
==
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h 
(original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h 
(removed)
@@ -1,33 +0,0 @@
-//===--- LoopUnrolling.h - Unroll loops -*- C++ 
-*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===--===//
-///
-/// This header contains the declarations of functions which are used to decide
-/// which loops should be completely unrolled and mark their corresponding
-/// CFGBlocks.
-///
-//===--===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_LOOPUNROLLING_H
-#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_LOOPUNROLLING_H
-
-#include "clang/Analysis/CFG.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
-
-namespace clang {
-namespace ento {
-ProgramStateRef markLoopAsUnrolled(const Stmt *Term, ProgramStateRef State,
-   CFGStmtMap *StmtToBlockMap);
-bool isUnrolledLoopBlock(const CFGBlock *Block, ExplodedNode *Prev);
-bool shouldCompletelyUnroll(const Stmt *LoopStmt, ASTContext &ASTCtx);
-
-} // end namespace ento
-} // end namespace clang
-
-#endif

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp?rev=308592&r1=308591&r2=308592&view=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp Thu Jul 20 
00:35:11 2017
@@ -272,7 +272,6 @@ void ExprInspectionChecker::checkEndAnal
 
 reportBug(llvm::to_string(NumTimesReached), BR, N);
   }
-  ReachedStats.clear();
 }
 
 void ExprInspectionChecker::analyzerCrash(const CallExpr *CE,

Modified: cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp?rev=308592&r1=308591&r2=308592&view=diff
==
--- cfe/trunk/lib/StaticAnaly

r308561 - [StaticAnalyzer] Completely unrolling specific loops with known bound option

2017-07-19 Thread Peter Szecsi via cfe-commits
Author: szepet
Date: Wed Jul 19 17:05:25 2017
New Revision: 308561

URL: http://llvm.org/viewvc/llvm-project?rev=308561&view=rev
Log:
[StaticAnalyzer] Completely unrolling specific loops with known bound option 

Missing files added to rL308558.


Added:
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h
cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
cfe/trunk/test/Analysis/loop-unrolling.cpp

Added: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h?rev=308561&view=auto
==
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h 
(added)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h 
Wed Jul 19 17:05:25 2017
@@ -0,0 +1,33 @@
+//===--- LoopUnrolling.h - Unroll loops -*- C++ 
-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+///
+/// This header contains the declarations of functions which are used to decide
+/// which loops should be completely unrolled and mark their corresponding
+/// CFGBlocks.
+///
+//===--===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_LOOPUNROLLING_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_LOOPUNROLLING_H
+
+#include "clang/Analysis/CFG.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
+
+namespace clang {
+namespace ento {
+ProgramStateRef markLoopAsUnrolled(const Stmt *Term, ProgramStateRef State,
+   CFGStmtMap *StmtToBlockMap);
+bool isUnrolledLoopBlock(const CFGBlock *Block, ExplodedNode *Prev);
+bool shouldCompletelyUnroll(const Stmt *LoopStmt, ASTContext &ASTCtx);
+
+} // end namespace ento
+} // end namespace clang
+
+#endif

Added: cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp?rev=308561&view=auto
==
--- cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp (added)
+++ cfe/trunk/lib/StaticAnalyzer/Core/LoopUnrolling.cpp Wed Jul 19 17:05:25 2017
@@ -0,0 +1,203 @@
+//===--- LoopUnrolling.cpp - Unroll loops ---*- C++ 
-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+///
+/// This file contains functions which are used to decide if a loop worth to be
+/// unrolled. Moreover contains function which mark the CFGBlocks which belongs
+/// to the unrolled loop and store them in ProgramState.
+///
+//===--===//
+
+#include "clang/Analysis/CFGStmtMap.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/AST/ParentMap.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h"
+#include "llvm/ADT/Statistic.h"
+
+using namespace clang;
+using namespace ento;
+using namespace clang::ast_matchers;
+
+#define DEBUG_TYPE "LoopUnrolling"
+
+STATISTIC(NumTimesLoopUnrolled,
+  "The # of times a loop has got completely unrolled");
+
+REGISTER_MAP_WITH_PROGRAMSTATE(UnrolledLoops, const Stmt *, const CFGStmtMap *)
+
+namespace clang {
+namespace ento {
+
+static bool isLoopStmt(const Stmt *S) {
+  return S && (isa(S) || isa(S) || isa(S));
+}
+
+static internal::Matcher simpleCondition(StringRef BindName) {
+  return binaryOperator(
+  anyOf(hasOperatorName("<"), hasOperatorName(">"), hasOperatorName("<="),
+hasOperatorName(">="), hasOperatorName("!=")),
+  hasEitherOperand(ignoringParenImpCasts(
+  declRefExpr(to(varDecl(hasType(isInteger())).bind(BindName),
+  hasEitherOperand(ignoringParenImpCasts(integerLiteral(;
+}
+
+static internal::Matcher changeIntBoundNode(StringRef NodeName) {
+  return anyOf(hasDescendant(unaryOperator(
+   anyOf(hasOperatorName("--"), hasOperatorName("++")),
+   hasUnaryOperand(ignoringParenImpCasts(
+   declRefExpr(to(varDecl(equalsBoundNode(NodeName,
+   hasDescendant(binaryOp

r308558 - This feature allows the analyzer to consider loops to completely unroll. New

2017-07-19 Thread Peter Szecsi via cfe-commits
Author: szepet
Date: Wed Jul 19 16:50:00 2017
New Revision: 308558

URL: http://llvm.org/viewvc/llvm-project?rev=308558&view=rev
Log:
This feature allows the analyzer to consider loops to completely unroll. New
requirements/rules (for unrolling) can be added easily via ASTMatchers.

The current implementation is hidden behind a flag.

Right now the blocks which belong to an unrolled loop are marked by the 
LoopVisitor which adds them to the ProgramState. Then whenever we encounter a
CFGBlock in the processCFGBlockEntrance which is marked then we skip its
investigating. That means, it won't be considered to be visited more than the
maximal bound for visiting since it won't be checked.

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


Modified:
cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
cfe/trunk/lib/StaticAnalyzer/Core/CMakeLists.txt
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
cfe/trunk/test/Analysis/analyzer-config.c
cfe/trunk/test/Analysis/analyzer-config.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=308558&r1=308557&r2=308558&view=diff
==
--- cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h Wed Jul 19 
16:50:00 2017
@@ -275,6 +275,9 @@ private:
   /// \sa shouldWidenLoops
   Optional WidenLoops;
 
+  /// \sa shouldUnrollLoops
+  Optional UnrollLoops;
+
   /// \sa shouldDisplayNotesAsEvents
   Optional DisplayNotesAsEvents;
 
@@ -560,7 +563,11 @@ public:
   /// This is controlled by the 'widen-loops' config option.
   bool shouldWidenLoops();
 
-  /// Returns true if the bug reporter should transparently treat extra note
+  /// Returns true if the analysis should try to unroll loops with known 
bounds.
+  /// This is controlled by the 'unroll-loops' config option.
+  bool shouldUnrollLoops();
+
+/// Returns true if the bug reporter should transparently treat extra note
   /// diagnostic pieces as event diagnostic pieces. Useful when the diagnostic
   /// consumer doesn't support the extra note pieces.
   ///

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp?rev=308558&r1=308557&r2=308558&view=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp Wed Jul 19 
16:50:00 2017
@@ -272,6 +272,7 @@ void ExprInspectionChecker::checkEndAnal
 
 reportBug(llvm::to_string(NumTimesReached), BR, N);
   }
+  ReachedStats.clear();
 }
 
 void ExprInspectionChecker::analyzerCrash(const CallExpr *CE,

Modified: cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp?rev=308558&r1=308557&r2=308558&view=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp Wed Jul 19 16:50:00 
2017
@@ -375,6 +375,12 @@ bool AnalyzerOptions::shouldWidenLoops()
   return WidenLoops.getValue();
 }
 
+bool AnalyzerOptions::shouldUnrollLoops() {
+  if (!UnrollLoops.hasValue())
+UnrollLoops = getBooleanOption("unroll-loops", /*Default=*/false);
+  return UnrollLoops.getValue();
+}
+
 bool AnalyzerOptions::shouldDisplayNotesAsEvents() {
   if (!DisplayNotesAsEvents.hasValue())
 DisplayNotesAsEvents =

Modified: cfe/trunk/lib/StaticAnalyzer/Core/CMakeLists.txt
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CMakeLists.txt?rev=308558&r1=308557&r2=308558&view=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Core/CMakeLists.txt (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CMakeLists.txt Wed Jul 19 16:50:00 2017
@@ -35,6 +35,7 @@ add_clang_library(clangStaticAnalyzerCor
   ExprEngineObjC.cpp
   FunctionSummary.cpp
   HTMLDiagnostics.cpp
+  LoopUnrolling.cpp
   LoopWidening.cpp
   MemRegion.cpp
   PathDiagnostic.cpp
@@ -54,6 +55,7 @@ add_clang_library(clangStaticAnalyzerCor
 
   LINK_LIBS
   clangAST
+  clangASTMatchers
   clangAnalysis
   clangBasic
   clangLex

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=308558&r1=308557&r2=308558&view=diff
===

r303158 - [StaticAnalyzer] Move inline counter increaser to inlineCall function

2017-05-16 Thread Peter Szecsi via cfe-commits
Author: szepet
Date: Tue May 16 06:54:00 2017
New Revision: 303158

URL: http://llvm.org/viewvc/llvm-project?rev=303158&view=rev
Log:
[StaticAnalyzer] Move inline counter increaser to inlineCall function

Even though the shouldInlineCall function returns true, it can happen that the
function is not going to be inlined (as it can be seen at line 913 and below).
Moved the bumpNumTimesInlined(D) (the counter increaser) call to the inlineCall
function where it logically belongs.

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

Modified:
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp?rev=303158&r1=303157&r2=303158&view=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp Tue May 16 
06:54:00 2017
@@ -447,6 +447,7 @@ bool ExprEngine::inlineCall(const CallEv
   Bldr.takeNodes(Pred);
 
   NumInlinedCalls++;
+  Engine.FunctionSummaries->bumpNumTimesInlined(D);
 
   // Mark the decl as visited.
   if (VisitedCallees)
@@ -868,8 +869,6 @@ bool ExprEngine::shouldInlineCall(const
   || IsRecursive))
 return false;
 
-  Engine.FunctionSummaries->bumpNumTimesInlined(D);
-
   return true;
 }
 


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


[PATCH] D23853: Assert in performTrivialCopy - Bug report and a possible solution

2016-10-04 Thread Peter Szecsi via cfe-commits
szepet abandoned this revision.
szepet added a comment.

At first I was not able to reproduce it. Then I realized it was my foul because 
I used the analyzer without the core checkers in this case. Sorry for the false 
positive.


https://reviews.llvm.org/D23853



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


[PATCH] D22507: Clang-tidy - Enum misuse check

2016-10-04 Thread Peter Szecsi via cfe-commits
szepet updated this revision to Diff 73439.
szepet marked an inline comment as done.
szepet added a comment.
Herald added a subscriber: modocache.

Note message checks added to testfiles.


https://reviews.llvm.org/D22507

Files:
  clang-tidy/misc/CMakeLists.txt
  clang-tidy/misc/MiscTidyModule.cpp
  clang-tidy/misc/SuspiciousEnumUsageCheck.cpp
  clang-tidy/misc/SuspiciousEnumUsageCheck.h
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/misc-suspicious-enum-usage.rst
  test/clang-tidy/misc-suspicious-enum-usage-strict.cpp
  test/clang-tidy/misc-suspicious-enum-usage.cpp

Index: test/clang-tidy/misc-suspicious-enum-usage.cpp
===
--- /dev/null
+++ test/clang-tidy/misc-suspicious-enum-usage.cpp
@@ -0,0 +1,90 @@
+// RUN: %check_clang_tidy %s misc-suspicious-enum-usage %t -- -config="{CheckOptions: [{key: misc-suspicious-enum-usage.StrictMode, value: 0}]}" --
+
+enum Empty {
+};
+
+enum A {
+  A = 1,
+  B = 2,
+  C = 4,
+  D = 8,
+  E = 16,
+  F = 32,
+  G = 63
+};
+
+enum X {
+  X = 8,
+  Y = 16,
+  Z = 4
+};
+
+enum {
+  P = 2,
+  Q = 3,
+  R = 4,
+  S = 8,
+  T = 16
+};
+
+enum {
+  H,
+  I,
+  J,
+  K,
+  L
+};
+
+enum Days {
+  Monday,
+  Tuesday,
+  Wednesday,
+  Thursday,
+  Friday,
+  Saturday,
+  Sunday
+};
+
+Days bestDay() {
+  return Friday;
+}
+
+int trigger() {
+  Empty EmptyVal;
+  int emptytest = EmptyVal | B;
+  if (bestDay() | A)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:17: warning: enum values are from different enum types 
+  if (I | Y)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: enum values are from different enum types
+}
+
+int dont_trigger() {
+  unsigned p;
+  p = Q | P;
+
+  if (A + G == E)
+return 1;
+  else if ((Q | R) == T)
+return 1;
+  else
+int k = T | Q;
+
+  Empty EmptyVal;
+  int emptytest = EmptyVal | B;
+
+  int a = 1, b = 5;
+  int c = a + b;
+  int d = c | H, e = b * a;
+  a = B | C;
+  b = X | Z;
+  
+  if (Tuesday != Monday + 1 ||
+  Friday - Thursday != 1 ||
+  Sunday + Wednesday == (Sunday | Wednesday))
+return 1;
+  if (H + I + L == 42)
+return 1;
+  return 42;
+}
Index: test/clang-tidy/misc-suspicious-enum-usage-strict.cpp
===
--- /dev/null
+++ test/clang-tidy/misc-suspicious-enum-usage-strict.cpp
@@ -0,0 +1,94 @@
+// RUN: %check_clang_tidy %s misc-suspicious-enum-usage %t -- -config="{CheckOptions: [{key: misc-suspicious-enum-usage.StrictMode, value: 1}]}" --
+
+enum A {
+  A = 1,
+  B = 2,
+  C = 4,
+  D = 8,
+  E = 16,
+  F = 32,
+  G = 63
+};
+
+enum X {
+  X = 8,
+  Y = 16,
+  Z = 4,
+  ZZ = 3
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: enum type seems like a bitmask (contains mostly power-of-2 literals), but this literal is not a power-of-2 [misc-suspicious-enum-usage]
+// CHECK-MESSAGES: :68:13: note: used here as a bitmask
+};
+// CHECK-MESSAGES: :[[@LINE+2]]:1: warning: enum type seems like a bitmask (contains mostly power-of-2 literals) but some literal(s) are not a power-of-2
+  // CHECK-MESSAGES: :71:8: note: used here as a bitmask
+enum PP {
+  P = 2,
+  Q = 3,
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: enum type seems like a bitmask (contains mostly power-of-2 literals), but this literal is not a power-of-2
+  // CHECK-MESSAGES: :63:7: note: used here as a bitmask
+  R = 4,
+  S = 8,
+  T = 16,
+  U = 31
+};
+
+enum {
+  H,
+  I,
+  J,
+  K,
+  L
+};
+
+enum Days {
+  Monday,
+  Tuesday,
+  Wednesday,
+  Thursday,
+  Friday,
+  Saturday,
+  Sunday
+};
+
+Days bestDay() {
+  return Friday;
+}
+
+int trigger() {
+  if (bestDay() | A)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:17: warning: enum values are from different enum types
+  if (I | Y)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: enum values are from different enum types
+  if (P + Q == R)
+return 1;
+  else if ((Q | R) == T)
+return 1;
+  else
+int k = ZZ | Z;
+  unsigned p = R;
+  PP pp = Q;
+  p |= pp;
+  p = A | G;
+  return 0;
+}
+
+int dont_trigger() {
+  int a = 1, b = 5;
+  int c = a + b;
+  int d = c | H, e = b * a;
+  a = B | C;
+  b = X | Z;
+
+  unsigned bitflag;
+  enum A aa = B;
+  bitflag = aa | C;
+
+  if (Tuesday != Monday + 1 ||
+  Friday - Thursday != 1 ||
+  Sunday + Wednesday == (Sunday | Wednesday))
+return 1;
+  if (H + I + L == 42)
+return 1;
+  return 42;
+}
Index: docs/clang-tidy/checks/misc-suspicious-enum-usage.rst
===
--- /dev/null
+++ docs/clang-tidy/checks/misc-suspicious-enum-usage.rst
@@ -0,0 +1,80 @@
+.. title:: clang-tidy - misc-suspicious-enum-usage
+
+misc-suspicious-enum-usage
+==
+
+The checker detects various cases when an enum is probably misused (as a bitmask
+).
+  
+1. When "ADD" or "bitwise OR" is used between two enum which come from different
+   types and these types value ranges are not disjoint.
+
+The following ca

[PATCH] D22507: Clang-tidy - Enum misuse check

2016-09-30 Thread Peter Szecsi via cfe-commits
szepet added inline comments.


> alexfh wrote in SuspiciousEnumUsageCheck.cpp:155
> Why?

Because the hasDisjointValueRange function could not decide the values 
properly. So in case of an empty Enum it would not make sense. Fortunately we 
know that the empty case should not be reported so used early return on this.

That is why this is needed if we want a deterministic check.

https://reviews.llvm.org/D22507



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


[PATCH] D22507: Clang-tidy - Enum misuse check

2016-09-30 Thread Peter Szecsi via cfe-commits
szepet updated this revision to Diff 73157.
szepet marked 13 inline comments as done.
szepet added a comment.

Updates based on comments (the testfile note comments will be added in the next 
commit)

Some changes in the algorithm/design:
In non-strict mode the checker will only investigate the operations between 
different enum types.
In strict mode we check the suspicious bitmasks too.
(In the previous comments we always talked about only the strict mode 
heuristics and looked on the strict results. )


https://reviews.llvm.org/D22507

Files:
  clang-tidy/misc/CMakeLists.txt
  clang-tidy/misc/MiscTidyModule.cpp
  clang-tidy/misc/SuspiciousEnumUsageCheck.cpp
  clang-tidy/misc/SuspiciousEnumUsageCheck.h
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/misc-suspicious-enum-usage.rst
  test/clang-tidy/misc-suspicious-enum-usage-strict.cpp
  test/clang-tidy/misc-suspicious-enum-usage.cpp

Index: test/clang-tidy/misc-suspicious-enum-usage.cpp
===
--- /dev/null
+++ test/clang-tidy/misc-suspicious-enum-usage.cpp
@@ -0,0 +1,90 @@
+// RUN: %check_clang_tidy %s misc-suspicious-enum-usage %t -- -config="{CheckOptions: [{key: misc-suspicious-enum-usage.StrictMode, value: 0}]}" --
+
+enum Empty {
+};
+
+enum A {
+  A = 1,
+  B = 2,
+  C = 4,
+  D = 8,
+  E = 16,
+  F = 32,
+  G = 63
+};
+
+enum X {
+  X = 8,
+  Y = 16,
+  Z = 4
+};
+
+enum {
+  P = 2,
+  Q = 3,
+  R = 4,
+  S = 8,
+  T = 16
+};
+
+enum {
+  H,
+  I,
+  J,
+  K,
+  L
+};
+
+enum Days {
+  Monday,
+  Tuesday,
+  Wednesday,
+  Thursday,
+  Friday,
+  Saturday,
+  Sunday
+};
+
+Days bestDay() {
+  return Friday;
+}
+
+int trigger() {
+  Empty EmptyVal;
+  int emptytest = EmptyVal | B;
+  if (bestDay() | A)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:17: warning: enum values are from different enum types 
+  if (I | Y)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: enum values are from different enum types
+}
+
+int dont_trigger() {
+  unsigned p;
+  p = Q | P;
+
+  if (A + G == E)
+return 1;
+  else if ((Q | R) == T)
+return 1;
+  else
+int k = T | Q;
+
+  Empty EmptyVal;
+  int emptytest = EmptyVal | B;
+
+  int a = 1, b = 5;
+  int c = a + b;
+  int d = c | H, e = b * a;
+  a = B | C;
+  b = X | Z;
+  
+  if (Tuesday != Monday + 1 ||
+  Friday - Thursday != 1 ||
+  Sunday + Wednesday == (Sunday | Wednesday))
+return 1;
+  if (H + I + L == 42)
+return 1;
+  return 42;
+}
Index: test/clang-tidy/misc-suspicious-enum-usage-strict.cpp
===
--- /dev/null
+++ test/clang-tidy/misc-suspicious-enum-usage-strict.cpp
@@ -0,0 +1,92 @@
+// RUN: %check_clang_tidy %s misc-suspicious-enum-usage %t -- -config="{CheckOptions: [{key: misc-suspicious-enum-usage.StrictMode, value: 1}]}" --
+
+enum A {
+  A = 1,
+  B = 2,
+  C = 4,
+  D = 8,
+  E = 16,
+  F = 32,
+  G = 63
+};
+
+enum X {
+  X = 8,
+  Y = 16,
+  Z = 4,
+  ZZ = 3
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: enum type seems like a bitmask (contains mostly power-of-2 literals), but this literal is not a power-of-2 [misc-suspicious-enum-usage]
+};
+// CHECK-MESSAGES: :[[@LINE+1]]:1: warning: enum type seems like a bitmask (contains mostly power-of-2 literals) but some literal(s) are not a power-of-2
+enum PP {
+  P = 2,
+  Q = 3,
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: enum type seems like a bitmask (contains mostly power-of-2 literals), but this literal is not a power-of-2
+  R = 4,
+  S = 8,
+  T = 16,
+  U = 31
+};
+
+enum {
+  H,
+  I,
+  J,
+  K,
+  L
+};
+
+enum Days {
+  Monday,
+  Tuesday,
+  Wednesday,
+  Thursday,
+  Friday,
+  Saturday,
+  Sunday
+};
+
+Days bestDay() {
+  return Friday;
+}
+
+int trigger() {
+  if (bestDay() | A)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:17: warning: enum values are from different enum types
+  if (I | Y)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: enum values are from different enum types
+  if (P + Q == R)
+return 1;
+  else if ((Q | R) == T)
+return 1;
+  else
+int k = ZZ | Z;
+  unsigned p = R;
+  PP pp = Q;
+  p |= pp;
+  // [LINE-1] triggers the LINE:17 warning
+  p = A | G;
+  return 0;
+}
+
+int dont_trigger() {
+  int a = 1, b = 5;
+  int c = a + b;
+  int d = c | H, e = b * a;
+  a = B | C;
+  b = X | Z;
+
+  unsigned bitflag;
+  enum A aa = B;
+  bitflag = aa | C;
+
+  if (Tuesday != Monday + 1 ||
+  Friday - Thursday != 1 ||
+  Sunday + Wednesday == (Sunday | Wednesday))
+return 1;
+  if (H + I + L == 42)
+return 1;
+  return 42;
+}
Index: docs/clang-tidy/checks/misc-suspicious-enum-usage.rst
===
--- /dev/null
+++ docs/clang-tidy/checks/misc-suspicious-enum-usage.rst
@@ -0,0 +1,80 @@
+.. title:: clang-tidy - misc-suspicious-enum-usage
+
+misc-suspicious-enum-usage
+==
+
+The checker detects various cases when an enum is proba

Re: [PATCH] D22507: Clang-tidy - Enum misuse check

2016-09-20 Thread Peter Szecsi via cfe-commits
szepet updated the summary for this revision.
szepet updated this revision to Diff 71925.
szepet marked 7 inline comments as done.
szepet added a comment.
Herald added subscribers: mgorny, beanz.

In order to decrease false positive rate, the bitmask specific checker part 
investigate only the enumconstans which was initilized by a literal. (If this 
is too strong it can be modified)

Renamed the checker to be more consistent with the checkers used for similar 
purpose.

Documentation code examples updated.


https://reviews.llvm.org/D22507

Files:
  clang-tidy/misc/CMakeLists.txt
  clang-tidy/misc/MiscTidyModule.cpp
  clang-tidy/misc/SuspiciousEnumUsageCheck.cpp
  clang-tidy/misc/SuspiciousEnumUsageCheck.h
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/misc-suspicious-enum-usage.rst
  test/clang-tidy/misc-suspicious-enum-usage-strict.cpp
  test/clang-tidy/misc-suspicious-enum-usage.cpp

Index: test/clang-tidy/misc-suspicious-enum-usage.cpp
===
--- /dev/null
+++ test/clang-tidy/misc-suspicious-enum-usage.cpp
@@ -0,0 +1,85 @@
+// RUN: %check_clang_tidy %s misc-suspicious-enum-usage %t -- -config="{CheckOptions: [{key: misc-suspicious-enum-usage.StrictMode, value: 0}]}" --
+
+enum Empty {
+};
+
+enum A {
+  A = 1,
+  B = 2,
+  C = 4,
+  D = 8,
+  E = 16,
+  F = 32,
+  G = 63
+};
+
+enum X {
+  X = 8,
+  Y = 16,
+  Z = 4
+};
+
+enum {
+  P = 2,
+  Q = 3,
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: enum type seems like a bitmask (contains mostly power-of-2 literals), but this literal is not a power-of-2 [misc-suspicious-enum-usage]
+  R = 4,
+  S = 8,
+  T = 16
+};
+
+enum {
+  H,
+  I,
+  J,
+  K,
+  L
+};
+
+enum Days {
+  Monday,
+  Tuesday,
+  Wednesday,
+  Thursday,
+  Friday,
+  Saturday,
+  Sunday
+};
+
+Days bestDay() {
+  return Friday;
+}
+
+int trigger() {
+  if (bestDay() | A)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:17: warning: enum values are from different enum types 
+  if (I | Y)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: enum values are from different enum types
+  unsigned p;
+  p = Q | P;
+}
+
+int dont_trigger() {
+  if (A + G == E)
+return 1;
+  else if ((Q | R) == T)
+return 1;
+  else
+int k = T | Q;
+  Empty EmptyVal;
+  int emptytest = EmptyVal | B;
+  int a = 1, b = 5;
+  int c = a + b;
+  int d = c | H, e = b * a;
+  a = B | C;
+  b = X | Z;
+  if (Tuesday != Monday + 1 ||
+  Friday - Thursday != 1 ||
+  Sunday + Wednesday == (Sunday | Wednesday))
+return 1;
+  if (H + I + L == 42)
+return 1;
+  return 42;
+}
Index: test/clang-tidy/misc-suspicious-enum-usage-strict.cpp
===
--- /dev/null
+++ test/clang-tidy/misc-suspicious-enum-usage-strict.cpp
@@ -0,0 +1,92 @@
+// RUN: %check_clang_tidy %s misc-suspicious-enum-usage %t -- -config="{CheckOptions: [{key: misc-suspicious-enum-usage.StrictMode, value: 1}]}" --
+
+enum A {
+  A = 1,
+  B = 2,
+  C = 4,
+  D = 8,
+  E = 16,
+  F = 32,
+  G = 63
+};
+
+enum X {
+  X = 8,
+  Y = 16,
+  Z = 4,
+  ZZ = 3
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: enum type seems like a bitmask (contains mostly power-of-2 literals), but this literal is not a power-of-2 [misc-suspicious-enum-usage]
+};
+// CHECK-MESSAGES: :[[@LINE+1]]:1: warning: enum type seems like a bitmask (contains mostly power-of-2 literals) but some literal(s) are not a power-of-2
+enum PP {
+  P = 2,
+  Q = 3,
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: enum type seems like a bitmask (contains mostly power-of-2 literals), but this literal is not a power-of-2
+  R = 4,
+  S = 8,
+  T = 16,
+  U = 31
+};
+
+enum {
+  H,
+  I,
+  J,
+  K,
+  L
+};
+
+enum Days {
+  Monday,
+  Tuesday,
+  Wednesday,
+  Thursday,
+  Friday,
+  Saturday,
+  Sunday
+};
+
+Days bestDay() {
+  return Friday;
+}
+
+int trigger() {
+  if (bestDay() | A)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:17: warning: enum values are from different enum types
+  if (I | Y)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: enum values are from different enum types
+  if (P + Q == R)
+return 1;
+  else if ((Q | R) == T)
+return 1;
+  else
+int k = ZZ | Z;
+  unsigned p = R;
+  PP pp = Q;
+  p |= pp;
+  // [LINE-1] triggers the LINE:17 warning
+  p = A | G;
+  return 0;
+}
+
+int dont_trigger() {
+  int a = 1, b = 5;
+  int c = a + b;
+  int d = c | H, e = b * a;
+  a = B | C;
+  b = X | Z;
+
+  unsigned bitflag;
+  enum A aa = B;
+  bitflag = aa | C;
+
+  if (Tuesday != Monday + 1 ||
+  Friday - Thursday != 1 ||
+  Sunday + Wednesday == (Sunday | Wednesday))
+return 1;
+  if (H + I + L == 42)
+return 1;
+  return 42;
+}
Index: docs/clang-tidy/checks/misc-suspicious-enum-usage.rst
===
--- /dev/null
+++ docs/clang-tidy/checks/misc-suspicious-enum-usage.rst
@@ -0,0 +1,71 @@
+.. title:: clang-tidy - misc-suspicious-en

Re: [PATCH] D22507: Clang-tidy - Enum misuse check

2016-09-05 Thread Peter Szecsi via cfe-commits
szepet updated this revision to Diff 70324.
szepet marked 4 inline comments as done.
szepet added a comment.

cast to dyn-cast change in order to fix a bug, changes based on comments


https://reviews.llvm.org/D22507

Files:
  clang-tidy/misc/CMakeLists.txt
  clang-tidy/misc/EnumMisuseCheck.cpp
  clang-tidy/misc/EnumMisuseCheck.h
  clang-tidy/misc/MiscTidyModule.cpp
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/misc-enum-misuse.rst
  test/clang-tidy/misc-enum-misuse-strict.cpp
  test/clang-tidy/misc-enum-misuse.cpp

Index: test/clang-tidy/misc-enum-misuse.cpp
===
--- /dev/null
+++ test/clang-tidy/misc-enum-misuse.cpp
@@ -0,0 +1,85 @@
+// RUN: %check_clang_tidy %s misc-enum-misuse %t -- -config="{CheckOptions: [{key: misc-enum-misuse.StrictMode, value: 0}]}" --
+
+enum Empty {
+};
+
+enum A {
+  A = 1,
+  B = 2,
+  C = 4,
+  D = 8,
+  E = 16,
+  F = 32,
+  G = 63
+};
+
+enum X {
+  X = 8,
+  Y = 16,
+  Z = 4
+};
+
+enum {
+  P = 2,
+  Q = 3,
+  R = 4,
+  S = 8,
+  T = 16
+};
+
+enum {
+  H,
+  I,
+  J,
+  K,
+  L
+};
+
+enum Days {
+  Monday,
+  Tuesday,
+  Wednesday,
+  Thursday,
+  Friday,
+  Saturday,
+  Sunday
+};
+
+Days bestDay() {
+  return Friday;
+}
+
+int trigger() {
+  if (bestDay() | A)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:17: warning: enum values are from different enum types [misc-enum-misuse]
+  if (I | Y)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: enum values are from different enum types
+  unsigned p;
+  p = Q | P;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: left hand side value is not power-of-2 unlike most other values in the enum type
+}
+
+int dont_trigger() {
+  if (A + G == E)
+return 1;
+  else if ((Q | R) == T)
+return 1;
+  else
+int k = T | Q;
+  Empty EmptyVal;
+  int emptytest = EmptyVal | B;
+  int a = 1, b = 5;
+  int c = a + b;
+  int d = c | H, e = b * a;
+  a = B | C;
+  b = X | Z;
+  if (Tuesday != Monday + 1 ||
+  Friday - Thursday != 1 ||
+  Sunday + Wednesday == (Sunday | Wednesday))
+return 1;
+  if (H + I + L == 42)
+return 1;
+  return 42;
+}
Index: test/clang-tidy/misc-enum-misuse-strict.cpp
===
--- /dev/null
+++ test/clang-tidy/misc-enum-misuse-strict.cpp
@@ -0,0 +1,92 @@
+// RUN: %check_clang_tidy %s misc-enum-misuse %t -- -config="{CheckOptions: [{key: misc-enum-misuse.StrictMode, value: 1}]}" --
+
+enum A {
+  A = 1,
+  B = 2,
+  C = 4,
+  D = 8,
+  E = 16,
+  F = 32,
+  G = 63
+};
+
+enum X {
+  X = 8,
+  Y = 16,
+  Z = 4
+};
+// CHECK-MESSAGES: :[[@LINE+1]]:1: warning: enum type seems like a bitmask but possibly contains misspelled number(s) [misc-enum-misuse]
+enum PP {
+  P = 2,
+  Q = 3,
+  R = 4,
+  S = 8,
+  T = 16,
+  U = 31
+};
+
+enum {
+  H,
+  I,
+  J,
+  K,
+  L
+};
+
+enum Days {
+  Monday,
+  Tuesday,
+  Wednesday,
+  Thursday,
+  Friday,
+  Saturday,
+  Sunday
+};
+
+Days bestDay() {
+  return Friday;
+}
+
+int trigger() {
+  if (bestDay() | A)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:17: warning: enum values are from different enum types
+  if (I | Y)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: enum values are from different enum types
+  if (P + Q == R)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: right hand side value is not power-of-2 unlike most other values in the enum type
+  else if ((Q | R) == T)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:13: warning: left hand side value is not power-of-2 unlike most other values in the enum type
+  else
+int k = T | Q;
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: right hand side value is not power-of-2 unlike most other values in the enum type
+  unsigned p = R;
+  PP pp = Q;
+  p |= pp;
+  // Line 65 triggers the LINE:17 warning
+  p = A | G;
+  return 0;
+}
+
+int dont_trigger() {
+  int a = 1, b = 5;
+  int c = a + b;
+  int d = c | H, e = b * a;
+  a = B | C;
+  b = X | Z;
+
+  unsigned bitflag;
+  enum A aa = B;
+  bitflag = aa | C;
+
+  if (Tuesday != Monday + 1 ||
+  Friday - Thursday != 1 ||
+  Sunday + Wednesday == (Sunday | Wednesday))
+return 1;
+  if (H + I + L == 42)
+return 1;
+  return 42;
+}
Index: docs/clang-tidy/checks/misc-enum-misuse.rst
===
--- /dev/null
+++ docs/clang-tidy/checks/misc-enum-misuse.rst
@@ -0,0 +1,67 @@
+.. title:: clang-tidy - misc-enum-misuse
+
+misc-enum-misuse
+
+
+The checker detects various cases when an enum is probably misused (as a bitmask).
+  
+1. When "ADD" or "bitwise OR" is used between two enum which come from different
+ types and these types value ranges are not disjoint.
+
+In the following cases you can choose either "Strict" or "Weak" option.
+In "Strict" mode we check if the used EnumConstantDecl type contains almost
+only pow-of-2 numbers. 
+We regard the enum as a bitmask if the two cond

Re: [PATCH] D22507: Clang-tidy - Enum misuse check

2016-09-01 Thread Peter Szecsi via cfe-commits
szepet added inline comments.


Comment at: test/clang-tidy/misc-enum-misuse.cpp:3
@@ +2,3 @@
+
+enum Empty {
+};

Could you specify which part of the file seems off? I have run the clang format 
with the same options on testfiles as on the others.


https://reviews.llvm.org/D22507



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


Re: [PATCH] D22507: Clang-tidy - Enum misuse check

2016-09-01 Thread Peter Szecsi via cfe-commits
szepet updated this revision to Diff 70017.
szepet marked 11 inline comments as done.
szepet added a comment.

Changes based on comments, fix a cast to dyn_cast bug, description updated 
(hopefully it became more clear).


https://reviews.llvm.org/D22507

Files:
  clang-tidy/misc/CMakeLists.txt
  clang-tidy/misc/EnumMisuseCheck.cpp
  clang-tidy/misc/EnumMisuseCheck.h
  clang-tidy/misc/MiscTidyModule.cpp
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/misc-argument-comment.rst
  docs/clang-tidy/checks/misc-enum-misuse.rst
  test/clang-tidy/misc-enum-misuse-strict.cpp
  test/clang-tidy/misc-enum-misuse.cpp

Index: test/clang-tidy/misc-enum-misuse.cpp
===
--- /dev/null
+++ test/clang-tidy/misc-enum-misuse.cpp
@@ -0,0 +1,81 @@
+// RUN: %check_clang_tidy %s misc-enum-misuse %t -- -config="{CheckOptions: [{key: misc-enum-misuse.StrictMode, value: 0}]}" --
+
+enum Empty {
+};
+
+enum A { A = 1,
+ B = 2,
+ C = 4,
+ D = 8,
+ E = 16,
+ F = 32,
+ G = 63
+};
+
+enum X { X = 8,
+ Y = 16,
+ Z = 4
+};
+
+enum { P = 2,
+   Q = 3,
+   R = 4,
+   S = 8,
+   T = 16
+};
+
+enum { H,
+   I,
+   J,
+   K,
+   L
+};
+
+enum Days { Monday,
+Tuesday,
+Wednesday,
+Thursday,
+Friday,
+Saturday,
+Sunday
+};
+
+Days bestDay() {
+  return Friday;
+}
+
+int trigger() {
+  if (bestDay() | A)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:17: warning: enum values are from different enum types [misc-enum-misuse]
+  if (I | Y)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: enum values are from different enum types
+  unsigned p;
+  p = Q | P;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: left hand side value is not power-of-2 unlike most other values in the enum type
+}
+
+int dont_trigger() {
+  if (A + G == E)
+return 1;
+  else if ((Q | R) == T)
+return 1;
+  else
+int k = T | Q;
+  return 0;
+  Empty EmptyVal;
+  int emptytest = EmptyVal | B;
+  int a = 1, b = 5;
+  int c = a + b;
+  int d = c | H, e = b * a;
+  a = B | C;
+  b = X | Z;
+  if (Tuesday != Monday + 1 ||
+  Friday - Thursday != 1 ||
+  Sunday + Wednesday == (Sunday | Wednesday))
+return 1;
+  if (H + I + L == 42)
+return 1;
+  return 42;
+}
Index: test/clang-tidy/misc-enum-misuse-strict.cpp
===
--- /dev/null
+++ test/clang-tidy/misc-enum-misuse-strict.cpp
@@ -0,0 +1,87 @@
+// RUN: %check_clang_tidy %s misc-enum-misuse %t -- -config="{CheckOptions: [{key: misc-enum-misuse.StrictMode, value: 1}]}" --
+
+enum A { A = 1,
+ B = 2,
+ C = 4,
+ D = 8,
+ E = 16,
+ F = 32,
+ G = 63
+};
+
+enum X { X = 8,
+ Y = 16,
+ Z = 4
+};
+// CHECK-MESSAGES: :[[@LINE+1]]:1: warning: enum type seems like a bitmask but possibly contains misspelled number(s) [misc-enum-misuse]
+enum PP { P = 2,
+  Q = 3,
+  R = 4,
+  S = 8,
+  T = 16,
+  U = 31
+};
+
+enum { H,
+   I,
+   J,
+   K,
+   L
+};
+
+enum Days { Monday,
+Tuesday,
+Wednesday,
+Thursday,
+Friday,
+Saturday,
+Sunday
+};
+
+Days bestDay() {
+  return Friday;
+}
+
+int trigger() {
+  if (bestDay() | A)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:17: warning: enum values are from different enum types
+  if (I | Y)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: enum values are from different enum types
+  if (P + Q == R)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: right hand side value is not power-of-2 unlike most other values in the enum type
+  else if ((Q | R) == T)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:13: warning: left hand side value is not power-of-2 unlike most other values in the enum type
+  else
+int k = T | Q;
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: right hand side value is not power-of-2 unlike most other values in the enum type
+  unsigned p = R;
+  PP pp = Q;
+  p |= pp;
+  // Line 65 triggers the LINE:17 warning
+  p = A | G;
+  return 0;
+}
+
+int dont_trigger() {
+  int a = 1, b = 5;
+  int c = a + b;
+  int d = c | H, e = b * a;
+  a = B | C;
+  b = X | Z;
+
+  unsigned bitflag;
+  enum A aa = B;
+  bitflag = aa | C;
+
+  if (Tuesday != Monday + 1 ||
+  Friday - Thursday != 1 ||
+  Sunday + Wednesday == (Sunday | Wednesday))
+return 1;
+  if (H + I + L == 42)
+return 1;
+  return 42;
+}
Index: docs/clang-tidy/checks/misc-enum-misuse.rst
===
--- /dev/null
+++ docs/clang-tidy/checks/misc-enum-misuse.rst
@@ -0,0 +1,67 @@
+.. title:: clang-tidy - misc-enum-misuse
+
+misc-enum-misuse
+
+
+The checker detects various cases when an enum is

Re: [PATCH] D22507: Clang-tidy - Enum misuse check

2016-08-23 Thread Peter Szecsi via cfe-commits
szepet added inline comments.


Comment at: clang-tidy/misc/EnumMisuseCheck.cpp:75
@@ +74,3 @@
+// We check if there is at most 2 not power-of-2 value in the enum type and
+// the
+// it contains enough element to make sure it could be a biftield, but we

aaron.ballman wrote:
> The wrapping for this comment is a bit strange, also should be using 
> doxygen-style comments. Also, the grammar is a bit off for the comment. I 
> would recommend:
> ```
> Check if there are two or more enumerators that are not a power of 2 in the 
> enum type, and that the enumeration contains enough elements to reasonably 
> act as a bitmask. Exclude the case where the last enumerator is the sum of 
> the lesser values or when it could contain consecutive values.
> ```
> Also, I would call this `isPossiblyBitMask` instead of using "bit field" 
> because a bit-field is a syntactic construct that is unrelated. Bitmask types 
> are covered in the C++ standard under [bitmask.types] and are slightly 
> different, but more closely related to what this check is looking for.
Thanks for the recommendations! As you can see my grammar and vocabulary is a 
"bit strange" so I really appreciated the correction!


Comment at: clang-tidy/misc/EnumMisuseCheck.cpp:209
@@ +208,3 @@
+if (LhsVar) {
+  diag(EnumDec->getInnerLocStart(), "enum type seems like a bitfield but "
+"possibly contains misspelled "

aaron.ballman wrote:
> I think this diagnostic text is a bit confusing. The enum type shouldn't seem 
> like a bit-field (but more like a bitmask), and I'm not certain what a 
> misspelled number would be. I think the diagnostic is effectively saying that 
> we guess this might be a bitmask, but some of the enumerator values don't 
> make sense for that guess, and so this may be suspicious code -- but I really 
> worry about the false positive rate for such a diagnostic. Have you run this 
> check over a large body of work (like LLVM, Firefox, Chrome, etc)? If so, how 
> do the diagnostics look?
> 
> Perhaps a different way to word the diagnostic is: "enum type used as a 
> bitmask with an enumerator value that is not a power of 2" and place the 
> diagnostic on the enumerator(s) that cause the problem rather than the 
> enumeration as a whole.
Here you can see the results on LLVM. (weak options, less false positive)

{F2319113}

Here I have to mention that the last 4 results could be combined into one, 
because it`s actually the usage of the same enum in different files. If you 
wish I could easily change it.


https://reviews.llvm.org/D22507



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


Re: [PATCH] D22507: Clang-tidy - Enum misuse check

2016-08-23 Thread Peter Szecsi via cfe-commits
szepet updated this revision to Diff 68968.
szepet marked 18 inline comments as done.
szepet added a comment.

Changes based on comments.


https://reviews.llvm.org/D22507

Files:
  clang-tidy/misc/CMakeLists.txt
  clang-tidy/misc/EnumMisuseCheck.cpp
  clang-tidy/misc/EnumMisuseCheck.h
  clang-tidy/misc/MiscTidyModule.cpp
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/misc-enum-misuse.rst
  test/clang-tidy/misc-enum-misuse-weak.cpp
  test/clang-tidy/misc-enum-misuse.cpp

Index: test/clang-tidy/misc-enum-misuse.cpp
===
--- /dev/null
+++ test/clang-tidy/misc-enum-misuse.cpp
@@ -0,0 +1,81 @@
+// RUN: %check_clang_tidy %s misc-enum-misuse %t -- -config="{CheckOptions: [{key: misc-enum-misuse.IsStrict, value: 0}]}" --
+
+enum Empty {
+};
+
+enum A { A = 1,
+ B = 2,
+ C = 4,
+ D = 8,
+ E = 16,
+ F = 32,
+ G = 63
+};
+
+enum X { X = 8,
+ Y = 16,
+ Z = 4
+};
+
+enum { P = 2,
+   Q = 3,
+   R = 4,
+   S = 8,
+   T = 16
+};
+
+enum { H,
+   I,
+   J,
+   K,
+   L
+};
+
+enum Days { Monday,
+Tuesday,
+Wednesday,
+Thursday,
+Friday,
+Saturday,
+Sunday
+};
+
+Days bestDay() {
+  return Friday;
+}
+
+int trigger() {
+  if (bestDay() | A)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:17: warning: enum values are from different enum types [misc-enum-misuse]
+  if (I | Y)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: enum values are from different enum types
+  unsigned p;
+  p = Q | P;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: left hand side value is not power-of-2 unlike most other values in the enum type
+}
+
+int dont_trigger() {
+  if (A + G == E)
+return 1;
+  else if ((Q | R) == T)
+return 1;
+  else
+int k = T | Q;
+  return 0;
+  Empty EmptyVal;
+  int emptytest = EmptyVal | B;
+  int a = 1, b = 5;
+  int c = a + b;
+  int d = c | H, e = b * a;
+  a = B | C;
+  b = X | Z;
+  if (Tuesday != Monday + 1 ||
+  Friday - Thursday != 1 ||
+  Sunday + Wednesday == (Sunday | Wednesday))
+return 1;
+  if (H + I + L == 42)
+return 1;
+  return 42;
+}
Index: test/clang-tidy/misc-enum-misuse-weak.cpp
===
--- /dev/null
+++ test/clang-tidy/misc-enum-misuse-weak.cpp
@@ -0,0 +1,88 @@
+// RUN: %check_clang_tidy %s misc-enum-misuse %t -- -config="{CheckOptions: [{key: misc-enum-misuse.IsStrict, value: 1}]}" --
+
+enum A { A = 1,
+ B = 2,
+ C = 4,
+ D = 8,
+ E = 16,
+ F = 32,
+ G = 63
+};
+
+enum X { X = 8,
+ Y = 16,
+ Z = 4
+};
+// CHECK-MESSAGES: :[[@LINE+1]]:1: warning: enum type seems like a bitfield but possibly contains misspelled number(s) [misc-enum-misuse]
+enum PP { P = 2,
+  Q = 3,
+  R = 4,
+  S = 8,
+  T = 16,
+  U = 31
+};
+
+enum { H,
+   I,
+   J,
+   K,
+   L
+};
+
+enum Days { Monday,
+Tuesday,
+Wednesday,
+Thursday,
+Friday,
+Saturday,
+Sunday
+};
+
+Days bestDay() {
+  return Friday;
+}
+
+int trigger() {
+  if (bestDay() | A)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:17: warning: enum values are from different enum types
+  if (I | Y)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: enum values are from different enum types
+  if (P + Q == R)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: right hand side value is not power-of-2 unlike most other values in the enum type
+  else if ((Q | R) == T)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:13: warning: left hand side value is not power-of-2 unlike most other values in the enum type
+  else
+int k = T | Q;
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: right hand side value is not power-of-2 unlike most other values in the enum type
+  unsigned p = R;
+  PP pp = Q;
+  p |= pp;
+  // Line 60 triggers the LINE:18 warning
+  p = A | G;
+  //p = G | X;
+  return 0;
+}
+
+int dont_trigger() {
+  int a = 1, b = 5;
+  int c = a + b;
+  int d = c | H, e = b * a;
+  a = B | C;
+  b = X | Z;
+
+  unsigned bitflag;
+  enum A aa = B;
+  bitflag = aa | C;
+
+  if (Tuesday != Monday + 1 ||
+  Friday - Thursday != 1 ||
+  Sunday + Wednesday == (Sunday | Wednesday))
+return 1;
+  if (H + I + L == 42)
+return 1;
+  return 42;
+}
Index: docs/clang-tidy/checks/misc-enum-misuse.rst
===
--- /dev/null
+++ docs/clang-tidy/checks/misc-enum-misuse.rst
@@ -0,0 +1,66 @@
+.. title:: clang-tidy - misc-enum-misuse
+
+misc-enum-misuse
+
+
+The checker detects various cases when an enum is probably misused (as a bitfield).
+  1. When "add" or "bitwise or" is used between two enum which come from different
+ ty

Re: [PATCH] D22507: Clang-tidy - Enum misuse check

2016-07-28 Thread Peter Szecsi via cfe-commits
szepet marked 2 inline comments as done.
szepet added a comment.

https://reviews.llvm.org/D22507



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


Re: [PATCH] D22507: Clang-tidy - Enum misuse check

2016-07-28 Thread Peter Szecsi via cfe-commits
szepet updated this revision to Diff 65966.
szepet marked 12 inline comments as done.
szepet added a comment.

updates based on comments, counter and search functions replaced by std 
functions


https://reviews.llvm.org/D22507

Files:
  clang-tidy/misc/CMakeLists.txt
  clang-tidy/misc/EnumMisuseCheck.cpp
  clang-tidy/misc/EnumMisuseCheck.h
  clang-tidy/misc/MiscTidyModule.cpp
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/misc-enum-misuse.rst
  test/clang-tidy/misc-enum-misuse-weak.cpp
  test/clang-tidy/misc-enum-misuse.cpp

Index: test/clang-tidy/misc-enum-misuse.cpp
===
--- /dev/null
+++ test/clang-tidy/misc-enum-misuse.cpp
@@ -0,0 +1,81 @@
+// RUN: %check_clang_tidy %s misc-enum-misuse %t -- -config="{CheckOptions: [{key: misc-enum-misuse.IsStrict, value: 0}]}" --
+
+enum Empty {
+};
+
+enum A { A = 1,
+ B = 2,
+ C = 4,
+ D = 8,
+ E = 16,
+ F = 32,
+ G = 63
+};
+
+enum X { X = 8,
+ Y = 16,
+ Z = 4
+};
+
+enum { P = 2,
+   Q = 3,
+   R = 4,
+   S = 8,
+   T = 16
+};
+
+enum { H,
+   I,
+   J,
+   K,
+   L
+};
+
+enum Days { Monday,
+Tuesday,
+Wednesday,
+Thursday,
+Friday,
+Saturday,
+Sunday
+};
+
+Days bestDay() {
+  return Friday;
+}
+
+int trigger() {
+  if (bestDay() | A)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:17: warning: enum values are from different enum types [misc-enum-misuse]
+  if (I | Y)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: enum values are from different enum types 
+  unsigned p;
+  p = Q | P;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: left hand side value is not power-of-2 unlike most other values in the enum type
+}
+
+int dont_trigger() {
+  if (A + G == E)
+return 1;
+  else if ((Q | R) == T)
+return 1;
+  else
+int k = T | Q;
+  return 0;
+  Empty EmptyVal;
+  int emptytest = EmptyVal | B;
+  int a = 1, b = 5;
+  int c = a + b;
+  int d = c | H, e = b * a;
+  a = B | C;
+  b = X | Z;
+  if (Tuesday != Monday + 1 ||
+  Friday - Thursday != 1 ||
+  Sunday + Wednesday == (Sunday | Wednesday))
+return 1;
+  if (H + I + L == 42)
+return 1;
+  return 42;
+}
Index: test/clang-tidy/misc-enum-misuse-weak.cpp
===
--- /dev/null
+++ test/clang-tidy/misc-enum-misuse-weak.cpp
@@ -0,0 +1,88 @@
+// RUN: %check_clang_tidy %s misc-enum-misuse %t -- -config="{CheckOptions: [{key: misc-enum-misuse.IsStrict, value: 1}]}" --
+
+enum A { A = 1,
+ B = 2,
+ C = 4,
+ D = 8,
+ E = 16,
+ F = 32,
+ G = 63
+};
+
+enum X { X = 8,
+ Y = 16,
+ Z = 4
+};
+// CHECK-MESSAGES: :[[@LINE+1]]:1: warning: enum type seems like a bitfield but possibly contains misspelled number(s) [misc-enum-misuse] 
+enum PP { P = 2,
+  Q = 3,
+  R = 4,
+  S = 8,
+  T = 16,
+  U = 31
+};
+
+enum { H,
+   I,
+   J,
+   K,
+   L
+};
+
+enum Days { Monday,
+Tuesday,
+Wednesday,
+Thursday,
+Friday,
+Saturday,
+Sunday
+};
+
+Days bestDay() {
+  return Friday;
+}
+
+int trigger() {
+  if (bestDay() | A)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:17: warning: enum values are from different enum types 
+  if (I | Y)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: enum values are from different enum types 
+  if (P + Q == R)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: right hand side value is not power-of-2 unlike most other values in the enum type 
+  else if ((Q | R) == T)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:13: warning: left hand side value is not power-of-2 unlike most other values in the enum type 
+  else
+int k = T | Q;
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: right hand side value is not power-of-2 unlike most other values in the enum type 
+  unsigned p = R;
+  PP pp = Q;
+  p |= pp;
+  // Line 60 triggers the LINE:18 warning
+  p = A | G;
+  //p = G | X;
+  return 0;
+}
+
+int dont_trigger() {
+  int a = 1, b = 5;
+  int c = a + b;
+  int d = c | H, e = b * a;
+  a = B | C;
+  b = X | Z;
+
+  unsigned bitflag;
+  enum A aa = B;
+  bitflag = aa | C;
+
+  if (Tuesday != Monday + 1 ||
+  Friday - Thursday != 1 ||
+  Sunday + Wednesday == (Sunday | Wednesday))
+return 1;
+  if (H + I + L == 42)
+return 1;
+  return 42;
+}
Index: docs/clang-tidy/checks/misc-enum-misuse.rst
===
--- /dev/null
+++ docs/clang-tidy/checks/misc-enum-misuse.rst
@@ -0,0 +1,66 @@
+.. title:: clang-tidy - misc-enum-misuse
+
+misc-enum-misuse
+
+
+The checker detects various cases when an enum is probably misused (as a bitfield).
+  1. When "add" or "bitwise 

Re: [PATCH] D22507: Clang-tidy - Enum misuse check

2016-07-25 Thread Peter Szecsi via cfe-commits
szepet updated this revision to Diff 65310.
szepet added a comment.

full diff submitted


https://reviews.llvm.org/D22507

Files:
  clang-tidy/misc/CMakeLists.txt
  clang-tidy/misc/EnumMisuseCheck.cpp
  clang-tidy/misc/EnumMisuseCheck.h
  clang-tidy/misc/MiscTidyModule.cpp
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/misc-enum-misuse.rst
  test/clang-tidy/misc-enum-misuse-weak.cpp
  test/clang-tidy/misc-enum-misuse.cpp

Index: test/clang-tidy/misc-enum-misuse.cpp
===
--- /dev/null
+++ test/clang-tidy/misc-enum-misuse.cpp
@@ -0,0 +1,81 @@
+// RUN: %check_clang_tidy %s misc-enum-misuse %t -- -config="{CheckOptions: [{key: misc-enum-misuse.IsStrict, value: 0}]}" --
+
+enum Empty {
+};
+
+enum A { A = 1,
+ B = 2,
+ C = 4,
+ D = 8,
+ E = 16,
+ F = 32,
+ G = 63
+};
+
+enum X { X = 8,
+ Y = 16,
+ Z = 4
+};
+
+enum { P = 2,
+   Q = 3,
+   R = 4,
+   S = 8,
+   T = 16
+};
+
+enum { H,
+   I,
+   J,
+   K,
+   L
+};
+
+enum Days { Monday,
+Tuesday,
+Wednesday,
+Thursday,
+Friday,
+Saturday,
+Sunday
+};
+
+Days bestDay() {
+  return Friday;
+}
+
+int trigger() {
+  if (bestDay() | A)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:17: warning: enum values are from different enum types [misc-enum-misuse]
+  if (I | Y)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: enum values are from different enum types [misc-enum-misuse]
+  unsigned p;
+  p = Q | P;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: left hand side value is not power-of-2 unlike most other values in the enum type [misc-enum-misuse]
+}
+
+int dont_trigger() {
+  if (A + G == E)
+return 1;
+  else if ((Q | R) == T)
+return 1;
+  else
+int k = T | Q;
+  return 0;
+  Empty EmptyVal;
+  int emptytest = EmptyVal | B;
+  int a = 1, b = 5;
+  int c = a + b;
+  int d = c | H, e = b * a;
+  a = B | C;
+  b = X | Z;
+  if (Tuesday != Monday + 1 ||
+  Friday - Thursday != 1 ||
+  Sunday + Wednesday == (Sunday | Wednesday))
+return 1;
+  if (H + I + L == 42)
+return 1;
+  return 42;
+}
Index: test/clang-tidy/misc-enum-misuse-weak.cpp
===
--- /dev/null
+++ test/clang-tidy/misc-enum-misuse-weak.cpp
@@ -0,0 +1,88 @@
+// RUN: %check_clang_tidy %s misc-enum-misuse %t -- -config="{CheckOptions: [{key: misc-enum-misuse.IsStrict, value: 1}]}" --
+
+enum A { A = 1,
+ B = 2,
+ C = 4,
+ D = 8,
+ E = 16,
+ F = 32,
+ G = 63
+};
+
+enum X { X = 8,
+ Y = 16,
+ Z = 4
+};
+// CHECK-MESSAGES: :[[@LINE+1]]:1: warning: enum type seems like a bitfield but possibly contains misspelled number(s) [misc-enum-misuse]
+enum PP { P = 2,
+  Q = 3,
+  R = 4,
+  S = 8,
+  T = 16,
+  U = 31
+};
+
+enum { H,
+   I,
+   J,
+   K,
+   L
+};
+
+enum Days { Monday,
+Tuesday,
+Wednesday,
+Thursday,
+Friday,
+Saturday,
+Sunday
+};
+
+Days bestDay() {
+  return Friday;
+}
+
+int trigger() {
+  if (bestDay() | A)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:17: warning: enum values are from different enum types [misc-enum-misuse]
+  if (I | Y)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: enum values are from different enum types [misc-enum-misuse]
+  if (P + Q == R)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: right hand side value is not power-of-2 unlike most other values in the enum type [misc-enum-misuse]
+  else if ((Q | R) == T)
+return 1;
+  // CHECK-MESSAGES: :[[@LINE-2]]:13: warning: left hand side value is not power-of-2 unlike most other values in the enum type [misc-enum-misuse]
+  else
+int k = T | Q;
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: right hand side value is not power-of-2 unlike most other values in the enum type [misc-enum-misuse]
+  unsigned p = R;
+  PP pp = Q;
+  p |= pp;
+  // Line 60 triggers the LINE:18 warning
+  p = A | G;
+  //p = G | X;
+  return 0;
+}
+
+int dont_trigger() {
+  int a = 1, b = 5;
+  int c = a + b;
+  int d = c | H, e = b * a;
+  a = B | C;
+  b = X | Z;
+
+  unsigned bitflag;
+  enum A aa = B;
+  bitflag = aa | C;
+
+  if (Tuesday != Monday + 1 ||
+  Friday - Thursday != 1 ||
+  Sunday + Wednesday == (Sunday | Wednesday))
+return 1;
+  if (H + I + L == 42)
+return 1;
+  return 42;
+}
Index: docs/clang-tidy/checks/misc-enum-misuse.rst
===
--- /dev/null
+++ docs/clang-tidy/checks/misc-enum-misuse.rst
@@ -0,0 +1,66 @@
+.. title:: clang-tidy - misc-enum-misuse
+
+misc-enum-misuse
+
+
+The checker detects various cases when an enum is probably misused (as a bitfield).
+  1. Wh

Re: [PATCH] D22507: Clang-tidy - Enum misuse check

2016-07-21 Thread Peter Szecsi via cfe-commits
szepet marked an inline comment as done.
szepet added a comment.

https://reviews.llvm.org/D22507



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


Re: [PATCH] D22507: Clang-tidy - Enum misuse check

2016-07-21 Thread Peter Szecsi via cfe-commits
szepet removed rL LLVM as the repository for this revision.
szepet updated this revision to Diff 64897.
szepet added a comment.

updating patch based on review comments


https://reviews.llvm.org/D22507

Files:
  clang-tidy/misc/EnumMisuseCheck.cpp
  clang-tidy/misc/EnumMisuseCheck.h
  docs/clang-tidy/checks/misc-enum-misuse.rst
  test/clang-tidy/misc-enum-misuse-weak.cpp
  test/clang-tidy/misc-enum-misuse.cpp

Index: test/clang-tidy/misc-enum-misuse.cpp
===
--- test/clang-tidy/misc-enum-misuse.cpp
+++ test/clang-tidy/misc-enum-misuse.cpp
@@ -1,6 +1,7 @@
 // RUN: %check_clang_tidy %s misc-enum-misuse %t -- -config="{CheckOptions: [{key: misc-enum-misuse.IsStrict, value: 0}]}" --
 
-enum Empty {};
+enum Empty {
+};
 
 enum A { A = 1,
  B = 2,
@@ -8,23 +9,27 @@
  D = 8,
  E = 16,
  F = 32,
- G = 63 };
+ G = 63
+};
 
 enum X { X = 8,
  Y = 16,
- Z = 4 };
+ Z = 4
+};
 
-enum {P = 2,
- Q = 3,
- R = 4,
- S = 8,
- T = 16 };
+enum { P = 2,
+   Q = 3,
+   R = 4,
+   S = 8,
+   T = 16
+};
 
 enum { H,
I,
J,
K,
-   L };
+   L
+};
 
 enum Days { Monday,
 Tuesday,
@@ -32,14 +37,14 @@
 Thursday,
 Friday,
 Saturday,
-Sunday };
+Sunday
+};
 
 Days bestDay() {
   return Friday;
 }
 
 int trigger() {
-
   if (bestDay() | A)
 return 1;
   // CHECK-MESSAGES: :[[@LINE-2]]:17: warning: enum values are from different enum types [misc-enum-misuse]
@@ -47,9 +52,8 @@
 return 1;
   // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: enum values are from different enum types [misc-enum-misuse]
   unsigned p;
-  p = Q | P; 
+  p = Q | P;
   // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: left hand side value is not power-of-2 unlike most other values in the enum type [misc-enum-misuse]
-
 }
 
 int dont_trigger() {
@@ -74,4 +78,4 @@
   if (H + I + L == 42)
 return 1;
   return 42;
-};
+}
Index: test/clang-tidy/misc-enum-misuse-weak.cpp
===
--- test/clang-tidy/misc-enum-misuse-weak.cpp
+++ test/clang-tidy/misc-enum-misuse-weak.cpp
@@ -6,24 +6,28 @@
  D = 8,
  E = 16,
  F = 32,
- G = 63 };
+ G = 63
+};
 
 enum X { X = 8,
  Y = 16,
- Z = 4 };
+ Z = 4
+};
 // CHECK-MESSAGES: :[[@LINE+1]]:1: warning: enum type seems like a bitfield but possibly contains misspelled number(s) [misc-enum-misuse]
 enum PP { P = 2,
   Q = 3,
   R = 4,
   S = 8,
   T = 16,
-  U = 31};
+  U = 31
+};
 
 enum { H,
I,
J,
K,
-   L };
+   L
+};
 
 enum Days { Monday,
 Tuesday,
@@ -31,7 +35,8 @@
 Thursday,
 Friday,
 Saturday,
-Sunday };
+Sunday
+};
 
 Days bestDay() {
   return Friday;
@@ -59,7 +64,7 @@
   // Line 60 triggers the LINE:18 warning
   p = A | G;
   //p = G | X;
-return 0;
+  return 0;
 }
 
 int dont_trigger() {
@@ -68,7 +73,7 @@
   int d = c | H, e = b * a;
   a = B | C;
   b = X | Z;
- 
+
   unsigned bitflag;
   enum A aa = B;
   bitflag = aa | C;
@@ -80,5 +85,4 @@
   if (H + I + L == 42)
 return 1;
   return 42;
-};
-
+}
Index: docs/clang-tidy/checks/misc-enum-misuse.rst
===
--- docs/clang-tidy/checks/misc-enum-misuse.rst
+++ docs/clang-tidy/checks/misc-enum-misuse.rst
@@ -23,3 +23,44 @@
  enum val. (only in "Strict")
   4. Check both side of | or + operator where the enum values are from the same
  enum type.
+
+Examples:
+
+.. code:: c++
+
+//1.
+Enum {A, B, C}
+Enum {D, E, F}
+Enum {G = 10, H = 11, I = 12};
+
+unsigned flag;
+flag = A | H; //OK, disjoint value intervalls in the enum types > probably good use
+flag = B | F; //warning, have common values so they are probably misused
+  
+
+
+//2.
+
+Enum Bitfield { A = 0;
+B = 1;
+C = 2;
+D = 4;
+E = 8;
+F = 16;
+G = 31; //OK, real bitfield
+}
+
+Enum AlmostBitfield { AA = 0;
+  BB = 1;
+  CC = 2;
+  DD = 4;
+  EE = 8;
+  FF = 16;
+  GG; //Problem, forgot to initialize
+}
+
+  unsigned flag = 0;
+  flag |= E; //ok
+  flag |= EE; //warning at the decl, and note that it was used here as a bitfield
+
+void f(const string&);  // Good: const is not top level.
Index: clang-tidy/misc/EnumMisuseCheck.h
===
--- clang-tidy/misc/EnumMisuseCheck.h
+++ clang-tidy/misc/EnumMisuseCheck.h
@@ -16,18 +16,20 @@
 namespace tidy {
 namespace misc {
 
-/// FIXME: Write a short description.
-///
+/// The checker det

Re: [PATCH] D22507: Clang-tidy - Enum misuse check

2016-07-21 Thread Peter Szecsi via cfe-commits
szepet marked 18 inline comments as done.
szepet added a comment.

https://reviews.llvm.org/D22507



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