Charusso created this revision.
Charusso added a reviewer: NoQ.
Charusso added a project: clang.
Herald added subscribers: cfe-commits, dkrupp, donat.nagy, Szelethus, 
mikhail.ramalho, a.sidorin, szepet, baloghadamsoftware, xazax.hun.

This patch introduces a new `analyzer-config` configuration:
`-analyzer-config check-bitwise=false`
which could be used to toggle whether the bitwise (and shift) operations
should be checked. It by default set to `false` as we do not model the
bitwise operations enough well.


Repository:
  rC Clang

https://reviews.llvm.org/D66721

Files:
  clang/include/clang/AST/Expr.h
  clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
  clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
  clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
  clang/test/Analysis/analyzer-config.c
  clang/test/Analysis/bitwise-ops.c
  clang/test/Analysis/casts.c
  clang/test/Analysis/diagnostics/track_subexpressions.cpp
  clang/test/Analysis/left-shift-cxx2a.cpp
  clang/test/Analysis/misc-ps-region-store.m

Index: clang/test/Analysis/misc-ps-region-store.m
===================================================================
--- clang/test/Analysis/misc-ps-region-store.m
+++ clang/test/Analysis/misc-ps-region-store.m
@@ -1,5 +1,22 @@
-// RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 -analyzer-checker=core,alpha.core.CastToStruct,alpha.security.ReturnPtrRange,alpha.security.ArrayBound -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks -Wno-objc-root-class %s
-// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 -DTEST_64 -analyzer-checker=core,alpha.core.CastToStruct,alpha.security.ReturnPtrRange,alpha.security.ArrayBound -analyzer-store=region -verify -fblocks   -analyzer-opt-analyze-nested-blocks -Wno-objc-root-class %s
+// RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 \
+// RUN:  -analyzer-checker=core \
+// RUN:  -analyzer-checker=alpha.core.CastToStruct \
+// RUN:  -analyzer-checker=alpha.security.ReturnPtrRange \
+// RUN:  -analyzer-checker=alpha.security.ArrayBound \
+// RUN:  -analyzer-store=region \
+// RUN:  -analyzer-opt-analyze-nested-blocks \
+// RUN:  -analyzer-config check-bitwise=true \
+// RUN:  -Wno-objc-root-class -fblocks -verify %s
+
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 \
+// RUN:  -analyzer-checker=core \
+// RUN:  -analyzer-checker=alpha.core.CastToStruct \
+// RUN:  -analyzer-checker=alpha.security.ReturnPtrRange \
+// RUN:  -analyzer-checker=alpha.security.ArrayBound \
+// RUN:  -analyzer-store=region \
+// RUN:  -analyzer-opt-analyze-nested-blocks \
+// RUN:  -analyzer-config check-bitwise=true \
+// RUN:  -Wno-objc-root-class -fblocks -DTEST_64 -verify %s
 
 typedef long unsigned int size_t;
 void *memcpy(void *, const void *, size_t);
Index: clang/test/Analysis/left-shift-cxx2a.cpp
===================================================================
--- clang/test/Analysis/left-shift-cxx2a.cpp
+++ clang/test/Analysis/left-shift-cxx2a.cpp
@@ -1,5 +1,14 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -triple x86_64-apple-darwin13 -Wno-shift-count-overflow -verify=expected,cxx17 -std=c++17 %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -triple x86_64-apple-darwin13 -Wno-shift-count-overflow -verify=expected,cxx2a -std=c++2a %s
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin13 \
+// RUN:  -analyzer-checker=core,debug.ExprInspection \
+// RUN:  -Wno-shift-count-overflow \
+// RUN:  -analyzer-config check-bitwise=true \
+// RUN:  -std=c++17 -verify=expected,cxx17 %s
+
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin13 \
+// RUN:  -analyzer-checker=core,debug.ExprInspection \
+// RUN:  -Wno-shift-count-overflow \
+// RUN:  -analyzer-config check-bitwise=true \
+// RUN:  -std=c++2a -verify=expected,cxx2a %s
 
 int testNegativeShift(int a) {
   if (a == -5) {
Index: clang/test/Analysis/diagnostics/track_subexpressions.cpp
===================================================================
--- clang/test/Analysis/diagnostics/track_subexpressions.cpp
+++ clang/test/Analysis/diagnostics/track_subexpressions.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_analyze_cc1 -x c++ -analyzer-checker=core -analyzer-output=text -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core \
+// RUN:  -analyzer-config check-bitwise=true \
+// RUN:  -analyzer-output=text -verify %s
 
 typedef unsigned char uint8_t;
 
@@ -38,7 +40,7 @@
 
   for (int i = 0; i < 3; ++i)
     // expected-note@-1 3{{Loop condition is true.  Entering loop body}}
-    // expected-note@-2 {{Loop condition is false. Execution continues on line 43}}
+    // expected-note@-2 {{Loop condition is false. Execution continues on line 45}}
     arr[i] = 0;
   int x = getInt();
   int n = getIndex(x); // expected-note {{Calling 'getIndex'}}
@@ -70,7 +72,7 @@
 
   for (int i = 0; i < 3; ++i)
     // expected-note@-1 3{{Loop condition is true.  Entering loop body}}
-    // expected-note@-2 {{Loop condition is false. Execution continues on line 75}}
+    // expected-note@-2 {{Loop condition is false. Execution continues on line 77}}
     arr[1][i] = 0;
   int x = getInt();
   int n = getIndex(x); // expected-note {{Calling 'getIndex'}}
Index: clang/test/Analysis/casts.c
===================================================================
--- clang/test/Analysis/casts.c
+++ clang/test/Analysis/casts.c
@@ -1,7 +1,23 @@
-// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s
-// RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s
-// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 -analyzer-checker=core,alpha.core,debug.ExprInspection -verify -DEAGERLY_ASSUME=1 -w %s
-// RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 -analyzer-checker=core,alpha.core,debug.ExprInspection -verify -DEAGERLY_ASSUME=1 -DBIT32=1 -w %s
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 \
+// RUN:  -analyzer-checker=core,alpha.core,debug.ExprInspection \
+// RUN:  -analyzer-store=region \
+// RUN:  -analyzer-config eagerly-assume=false \
+// RUN:  -verify %s
+
+// RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 \
+// RUN:  -analyzer-checker=core,alpha.core,debug.ExprInspection \
+// RUN:  -analyzer-store=region \
+// RUN:  -analyzer-config eagerly-assume=false %s \
+// RUN:  -verify %s
+
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 \
+// RUN:  -analyzer-checker=core,alpha.core,debug.ExprInspection \
+// RUN:  -DEAGERLY_ASSUME -w -verify %s
+
+// RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 \
+// RUN:  -analyzer-checker=core,alpha.core,debug.ExprInspection \
+// RUN:  -analyzer-config check-bitwise=true \
+// RUN:  -DEAGERLY_ASSUME -DBIT32 -w -verify %s
 
 extern void clang_analyzer_eval(_Bool);
 
Index: clang/test/Analysis/bitwise-ops.c
===================================================================
--- clang/test/Analysis/bitwise-ops.c
+++ clang/test/Analysis/bitwise-ops.c
@@ -1,4 +1,8 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -triple x86_64-apple-darwin13 -Wno-shift-count-overflow -verify %s
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin13 \
+// RUN:  -analyzer-checker=core,debug.ExprInspection \
+// RUN:  -Wno-shift-count-overflow \
+// RUN:  -analyzer-config check-bitwise=true \
+// RUN:  -verify %s
 
 void clang_analyzer_eval(int);
 #define CHECK(expr) if (!(expr)) return; clang_analyzer_eval(expr)
Index: clang/test/Analysis/analyzer-config.c
===================================================================
--- clang/test/Analysis/analyzer-config.c
+++ clang/test/Analysis/analyzer-config.c
@@ -25,6 +25,7 @@
 // CHECK-NEXT: cfg-rich-constructors = true
 // CHECK-NEXT: cfg-scopes = false
 // CHECK-NEXT: cfg-temporary-dtors = true
+// CHECK-NEXT: check-bitwise = false
 // CHECK-NEXT: cplusplus.Move:WarnOn = KnownsAndLocals
 // CHECK-NEXT: crosscheck-with-z3 = false
 // CHECK-NEXT: ctu-dir = ""
@@ -93,4 +94,4 @@
 // CHECK-NEXT: unroll-loops = false
 // CHECK-NEXT: widen-loops = false
 // CHECK-NEXT: [stats]
-// CHECK-NEXT: num-entries = 90
+// CHECK-NEXT: num-entries = 91
Index: clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
@@ -75,6 +75,9 @@
 void UndefResultChecker::checkPostStmt(const BinaryOperator *B,
                                        CheckerContext &C) const {
   if (C.getSVal(B).isUndef()) {
+    if (B->isBitwiseOrShiftOp() &&
+        !C.getAnalysisManager().getAnalyzerOptions().CheckBitwise)
+      return;
 
     // Do not report assignments of uninitialized values inside swap functions.
     // This should allow to swap partially uninitialized structs
Index: clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
@@ -60,6 +60,11 @@
                                               CheckerContext &Ctx) const {
   SVal X = Ctx.getSVal(Condition);
   if (X.isUndef()) {
+    if (const auto *BO = dyn_cast<BinaryOperator>(Condition))
+      if (BO->isBitwiseOrShiftOp() &&
+          !Ctx.getAnalysisManager().getAnalyzerOptions().CheckBitwise)
+        return;
+
     // Generate a sink node, which implicitly marks both outgoing branches as
     // infeasible.
     ExplodedNode *N = Ctx.generateErrorNode();
Index: clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
+++ clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
@@ -300,6 +300,14 @@
                 "Whether to place an event at each tracked condition.",
                 false)
 
+ANALYZER_OPTION(bool, CheckBitwise, "check-bitwise",
+                "Whether the bitwise (and shift) operations should be checked.",
+                false)
+
+//===----------------------------------------------------------------------===//
+// Unsinged analyzer options.
+//===----------------------------------------------------------------------===//
+
 ANALYZER_OPTION(unsigned, CTUImportThreshold, "ctu-import-threshold",
                 "The maximal amount of translation units that is considered "
                 "for import when inlining functions during CTU analysis. "
@@ -308,10 +316,6 @@
                 "various translation units.",
                 100u)
 
-//===----------------------------------------------------------------------===//
-// Unsinged analyzer options.
-//===----------------------------------------------------------------------===//
-
 ANALYZER_OPTION(
     unsigned, AlwaysInlineSize, "ipa-always-inline-size",
     "The size of the functions (in basic blocks), which should be considered "
Index: clang/include/clang/AST/Expr.h
===================================================================
--- clang/include/clang/AST/Expr.h
+++ clang/include/clang/AST/Expr.h
@@ -3485,6 +3485,11 @@
   static bool isBitwiseOp(Opcode Opc) { return Opc >= BO_And && Opc <= BO_Or; }
   bool isBitwiseOp() const { return isBitwiseOp(getOpcode()); }
 
+  static bool isBitwiseOrShiftOp(Opcode Opc) {
+    return isBitwiseOp(Opc) || isShiftOp(Opc);
+  }
+  bool isBitwiseOrShiftOp() const { return isBitwiseOrShiftOp(getOpcode()); }
+
   static bool isRelationalOp(Opcode Opc) { return Opc >= BO_LT && Opc<=BO_GE; }
   bool isRelationalOp() const { return isRelationalOp(getOpcode()); }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to