ASDenysPetrov created this revision.
ASDenysPetrov added reviewers: steakhal, NoQ, xazax.hun, vsavchenko, 
Eugene.Zelenko.
ASDenysPetrov added a project: clang.
Herald added subscribers: martong, Charusso, dkrupp, donat.nagy, Szelethus, 
mikhail.ramalho, a.sidorin, rnkovacs, szepet, baloghadamsoftware.
ASDenysPetrov requested review of this revision.
Herald added a subscriber: cfe-commits.

Improve `SValBuilder::evalCast` function in a part of **integer **to **bool 
**cast. Сonvert known `SymbolVal` `RangeSet` to `ConcreteInt` if possible.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D97874

Files:
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
  clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
  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
@@ -870,11 +870,18 @@
   // Symbol to bool.
   if (!OriginalTy.isNull() && CastTy->isBooleanType()) {
     // Non-float to bool.
-    if (Loc::isLocType(OriginalTy) ||
-        OriginalTy->isIntegralOrEnumerationType() ||
-        OriginalTy->isMemberPointerType()) {
+    if (OriginalTy->isIntegralOrEnumerationType()) {
       BasicValueFactory &BVF = getBasicValueFactory();
-      return makeNonLoc(SE, BO_NE, BVF.getValue(0, SE->getType()), CastTy);
+      const llvm::APSInt &Zero = BVF.getValue(0, OriginalTy);
+      bool IsZero, IsNotZero;
+      std::tie(IsZero, IsNotZero) =
+          getStateManager().getConstraintManager().isSymValWithinOrOutsideRange(
+              State, SE, Zero, Zero);
+      // Symbolic pointer, integer to bool.
+      if (IsZero || IsNotZero)
+        return makeTruthVal(IsNotZero, CastTy);
+      // Symbolic integer to bool.
+      return V;
     }
   } else {
     // Symbol to integer.
Index: clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -1278,6 +1278,9 @@
 
   const llvm::APSInt *getSymVal(ProgramStateRef State,
                                 SymbolRef Sym) const override;
+  std::pair<bool, bool>
+  isSymValWithinOrOutsideRange(ProgramStateRef State, SymbolRef Sym,
+                               llvm::APSInt lower, llvm::APSInt upper) override;
 
   ProgramStateRef removeDeadBindings(ProgramStateRef State,
                                      SymbolReaper &SymReaper) override;
@@ -1875,6 +1878,15 @@
   return T ? T->getConcreteValue() : nullptr;
 }
 
+std::pair<bool, bool> RangeConstraintManager::isSymValWithinOrOutsideRange(
+    ProgramStateRef St, SymbolRef Sym, llvm::APSInt lower, llvm::APSInt upper) {
+  if (const RangeSet *T = getConstraint(St, Sym)) {
+    RangeSet RS = T->Intersect(getBasicVals(), F, lower, upper);
+    return {RS == *T, RS.isEmpty()};
+  }
+  return {false, false};
+}
+
 //===----------------------------------------------------------------------===//
 //                Remove dead symbols from existing constraints
 //===----------------------------------------------------------------------===//
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
@@ -153,6 +153,19 @@
     return nullptr;
   }
 
+  /// Return pair of booleans for Within and Outside statuses.
+  /// First bool is `true` when SymbolRef range is within the range.
+  /// Second bool is `true` when SymbolRef range is outside the range.
+  /// Return 'false, false' otherwise.
+  ///
+  /// This function acts as `assumeDual` function
+  /// but it does not create any new states.
+  virtual std::pair<bool, bool>
+  isSymValWithinOrOutsideRange(ProgramStateRef state, SymbolRef sym,
+                               llvm::APSInt lower, llvm::APSInt upper) {
+    return {false, false};
+  }
+
   /// Scan all symbols referenced by the constraints. If the symbol is not
   /// alive, remove it.
   virtual ProgramStateRef removeDeadBindings(ProgramStateRef state,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to