[PATCH] D97874: [analyzer] Improve SVal cast from integer to bool using known RangeSet

Denys Petrov via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Mar 9 03:39:52 PST 2021


ASDenysPetrov updated this revision to Diff 329282.
ASDenysPetrov added a comment.

Updated due to discussion.


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

https://reviews.llvm.org/D97874

Files:
  clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
  clang/test/Analysis/cast_symbolic_ints_to_bool.cpp


Index: clang/test/Analysis/cast_symbolic_ints_to_bool.cpp
===================================================================
--- /dev/null
+++ clang/test/Analysis/cast_symbolic_ints_to_bool.cpp
@@ -0,0 +1,67 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s
+
+template <typename T>
+void clang_analyzer_dump(T);
+
+void test_int_to_bool(bool b, int x) {
+  clang_analyzer_dump(b); // expected-warning{{reg_$0<_Bool b>}}
+  b = x;
+  clang_analyzer_dump(b); // expected-warning{{reg_$1<int x>}}
+  if (x < 0) {
+    b = x;
+    clang_analyzer_dump(b); // expected-warning{{1 U1b}}
+  } else if (x > 0) {
+    b = x;
+    clang_analyzer_dump(b); // expected-warning{{1 U1b}}
+  } else {
+    b = x;
+    clang_analyzer_dump(b); // expected-warning{{0 U1b}}
+  }
+}
+
+void test_char_to_bool(char x) {
+  bool b = x;
+  clang_analyzer_dump(b); // expected-warning{{reg_$0<char x>}}
+  if (x < 0) {
+    bool b = x;
+    clang_analyzer_dump(b); // expected-warning{{1 U1b}}
+  } else if (x > 0) {
+    bool b = x;
+    clang_analyzer_dump(b); // expected-warning{{1 U1b}}
+  } else {
+    bool b = x;
+    clang_analyzer_dump(b); // expected-warning{{0 U1b}}
+  }
+}
+
+void test_unsigned_to_bool(bool b, unsigned x) {
+  clang_analyzer_dump(b); // expected-warning{{reg_$0<_Bool b>}}
+  b = x;
+  clang_analyzer_dump(b); // expected-warning{{reg_$1<unsigned int x>}}
+  if (x) {
+    b = x;
+    clang_analyzer_dump(b); // expected-warning{{1 U1b}}
+  } else {
+    b = x;
+    clang_analyzer_dump(b); // expected-warning{{0 U1b}}
+  }
+}
+
+void test_unsigned_to_bool(unsigned char x) {
+  bool b = x;
+  clang_analyzer_dump(b); // expected-warning{{reg_$0<unsigned char x>}}
+  if (x < 42) {
+    b = x;
+    clang_analyzer_dump(b); // expected-warning{{reg_$0<unsigned char x>}}
+    if (x) {
+      b = x;
+      clang_analyzer_dump(b); // expected-warning{{1 U1b}}
+    } else {
+      b = x;
+      clang_analyzer_dump(b); // expected-warning{{0 U1b}}
+    }
+  } else {
+    b = x;
+    clang_analyzer_dump(b); // expected-warning{{1 U1b}}
+  }
+}
Index: clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -871,12 +871,16 @@
 
   // Symbol to bool.
   if (!OriginalTy.isNull() && CastTy->isBooleanType()) {
-    // Non-float to bool.
-    if (Loc::isLocType(OriginalTy) ||
-        OriginalTy->isIntegralOrEnumerationType() ||
-        OriginalTy->isMemberPointerType()) {
-      BasicValueFactory &BVF = getBasicValueFactory();
-      return makeNonLoc(SE, BO_NE, BVF.getValue(0, SE->getType()), CastTy);
+    // Symbolic integer to bool.
+    if (OriginalTy->isIntegralOrEnumerationType()) {
+
+      // Integer is known to be non-zero or zero only.
+      auto truth = State->isNonNull(V);
+      if (truth.isConstrained())
+        return makeTruthVal(truth.isConstrainedTrue(), CastTy);
+
+      // Unconstrained integer to bool.
+      return V;
     }
   } else {
     // Symbol to integer.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D97874.329282.patch
Type: text/x-patch
Size: 3106 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20210309/c24096c5/attachment-0001.bin>


More information about the cfe-commits mailing list