[PATCH] D126481: [analyzer] Handle SymbolCast in SValBuilder

Gabor Marton via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue May 31 23:42:26 PDT 2022


This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
martong marked an inline comment as done.
Closed by commit rG160798ab9be8: [analyzer] Handle SymbolCast in SValBuilder (authored by martong).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D126481

Files:
  clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
  clang/test/Analysis/svalbuilder-casts.cpp


Index: clang/test/Analysis/svalbuilder-casts.cpp
===================================================================
--- /dev/null
+++ clang/test/Analysis/svalbuilder-casts.cpp
@@ -0,0 +1,58 @@
+// RUN: %clang_analyze_cc1 %s \
+// RUN:   -analyzer-checker=core \
+// RUN:   -analyzer-checker=debug.ExprInspection \
+// RUN:   -analyzer-config support-symbolic-integer-casts=true \
+// RUN:   -analyzer-config eagerly-assume=false \
+// RUN:   -triple x86_64-unknown-linux-gnu \
+// RUN:   -verify
+
+// Test that the SValBuilder is able to look up and use a constraint for an
+// operand of a SymbolCast, when the operand is constrained to a const value.
+
+void clang_analyzer_eval(bool);
+
+extern void abort() __attribute__((__noreturn__));
+#define assert(expr) ((expr) ? (void)(0) : abort())
+
+void test(int x) {
+  // Constrain a SymSymExpr to a constant value.
+  assert(x * x == 1);
+  // It is expected to be able to get the constraint for the operand of the
+  // cast.
+  clang_analyzer_eval((char)(x * x) == 1); // expected-warning{{TRUE}}
+  clang_analyzer_eval((long)(x * x) == 1); // expected-warning{{TRUE}}
+}
+
+void test1(int x, int y) {
+  // Even if two lower bytes of `x` equal to zero, it doesn't mean that
+  // the entire `x` is zero. We are not able to know the exact value of x.
+  // It can be one of  65536 possible values like
+  // [0, 65536, -65536, 131072, -131072, ...]. To avoid huge range sets we
+  // still assume `x` in the range [INT_MIN, INT_MAX].
+  assert((short)x == 0); // Lower two bytes are set to 0.
+
+  static_assert((short)65536 == 0, "");
+  static_assert((short)-65536 == 0, "");
+  static_assert((short)131072 == 0, "");
+  static_assert((short)-131072 == 0, "");
+  clang_analyzer_eval(x == 0);       // expected-warning{{UNKNOWN}}
+
+  // These are not truncated to short as zero.
+  static_assert((short)1 != 0, "");
+  clang_analyzer_eval(x == 1);       // expected-warning{{FALSE}}
+  static_assert((short)-1 != 0, "");
+  clang_analyzer_eval(x == -1);      // expected-warning{{FALSE}}
+  static_assert((short)65537 != 0, "");
+  clang_analyzer_eval(x == 65537);   // expected-warning{{FALSE}}
+  static_assert((short)-65537 != 0, "");
+  clang_analyzer_eval(x == -65537);  // expected-warning{{FALSE}}
+  static_assert((short)131073 != 0, "");
+  clang_analyzer_eval(x == 131073);  // expected-warning{{FALSE}}
+  static_assert((short)-131073 != 0, "");
+  clang_analyzer_eval(x == -131073); // expected-warning{{FALSE}}
+
+  // Check for implicit cast.
+  short s = y;
+  assert(s == 0);
+  clang_analyzer_eval(y == 0); // expected-warning{{UNKNOWN}}
+}
Index: clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
+++ clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
@@ -1278,8 +1278,6 @@
       return SVB.makeSymbolVal(S);
     }
 
-    // TODO: Support SymbolCast.
-
     SVal VisitSymIntExpr(const SymIntExpr *S) {
       auto I = Cached.find(S);
       if (I != Cached.end())
@@ -1349,7 +1347,17 @@
           S, SVB.evalBinOp(State, S->getOpcode(), LHS, RHS, S->getType()));
     }
 
-    // FIXME add VisitSymbolCast
+    SVal VisitSymbolCast(const SymbolCast *S) {
+      auto I = Cached.find(S);
+      if (I != Cached.end())
+        return I->second;
+      const SymExpr *OpSym = S->getOperand();
+      SVal OpVal = getConstOrVisit(OpSym);
+      if (isUnchanged(OpSym, OpVal))
+        return skip(S);
+
+      return cache(S, SVB.evalCast(OpVal, S->getType(), OpSym->getType()));
+    }
 
     SVal VisitUnarySymExpr(const UnarySymExpr *S) {
       auto I = Cached.find(S);


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D126481.433298.patch
Type: text/x-patch
Size: 3678 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20220601/ef5f5c36/attachment-0001.bin>


More information about the cfe-commits mailing list