[clang] [analyzer] Simplify SVal for simple NonLoc->Loc casts (PR #66463)

Ding Fei via cfe-commits cfe-commits at lists.llvm.org
Thu Sep 14 23:29:35 PDT 2023


https://github.com/danix800 created https://github.com/llvm/llvm-project/pull/66463

NonLoc symbolic SVal to Loc casts are not supported except for nonloc::ConcreteInt.

This change simplifies the source SVals so that the more casts can go through nonloc::ConcreteInt->loc::ConcreteInt path. For example:

```c
  void test_simplified_before_cast_add(long long t1) {
    long long t2 = t1 + 3;
    if (!t2) {
      int *p = (int *) t2;
      clang_analyzer_eval(p == 0); // expected-warning{{TRUE}}
    }
  }
```
If simplified, `t2` is 0, resulting `p` is nullptr, otherwise `p` is unknown.

Fixes #62232

>From e171f8ea4d0fea12dadad6b0ecaffba42ff6ba85 Mon Sep 17 00:00:00 2001
From: dingfei <fding at feysh.com>
Date: Fri, 15 Sep 2023 14:01:26 +0800
Subject: [PATCH] [analyzer] Simplify SVal for simple NonLoc->Loc casts

NonLoc symbolic SVal to Loc casts are not supported except for
nonloc::ConcreteInt.

This change simplifies the source SVals so that the more casts can
go through nonloc::ConcreteInt->loc::ConcreteInt path. For example:

  void test_simplified_before_cast_add(long long t1) {
    long long t2 = t1 + 3;
    if (!t2) {
      int *p = (int *) t2;
      clang_analyzer_eval(p == 0); // expected-warning{{TRUE}}
    }
  }

If simplified, 't2' is 0, resulting 'p' is nullptr, otherwise 'p'
is unknown.

Fixes #62232
---
 clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp |  3 +-
 ...solver-sym-simplification-lvalue-bitcast.c | 31 +++++++++++++++++++
 2 files changed, 33 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/Analysis/solver-sym-simplification-lvalue-bitcast.c

diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 2a47116db55a1ad..7e431f7e598c4cb 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -264,7 +264,8 @@ ProgramStateRef ExprEngine::handleLValueBitCast(
   }
   // Delegate to SValBuilder to process.
   SVal OrigV = state->getSVal(Ex, LCtx);
-  SVal V = svalBuilder.evalCast(OrigV, T, ExTy);
+  SVal SimplifiedOrigV = svalBuilder.simplifySVal(state, OrigV);
+  SVal V = svalBuilder.evalCast(SimplifiedOrigV, T, ExTy);
   // Negate the result if we're treating the boolean as a signed i1
   if (CastE->getCastKind() == CK_BooleanToSignedIntegral && V.isValid())
     V = svalBuilder.evalMinus(V.castAs<NonLoc>());
diff --git a/clang/test/Analysis/solver-sym-simplification-lvalue-bitcast.c b/clang/test/Analysis/solver-sym-simplification-lvalue-bitcast.c
new file mode 100644
index 000000000000000..db8b1456527e523
--- /dev/null
+++ b/clang/test/Analysis/solver-sym-simplification-lvalue-bitcast.c
@@ -0,0 +1,31 @@
+// RUN: %clang_analyze_cc1 %s \
+// RUN:   -analyzer-checker=core \
+// RUN:   -analyzer-checker=debug.ExprInspection \
+// RUN:   -analyzer-config eagerly-assume=false \
+// RUN:   -verify
+
+void clang_analyzer_eval(int);
+
+void test_simplified_before_cast_add(long long t1) {
+  long long t2 = t1 + 3;
+  if (!t2) {
+    int *p = (int *) t2;
+    clang_analyzer_eval(p == 0); // expected-warning{{TRUE}}
+  }
+}
+
+void test_simplified_before_cast_sub(long long t1) {
+  long long t2 = t1 - 3;
+  if (!t2) {
+    int *p = (int *) t2;
+    clang_analyzer_eval(p == 0); // expected-warning{{TRUE}}
+  }
+}
+
+void test_simplified_before_cast_mul(long long t1) {
+  long long t2 = t1 * 3;
+  if (!t2) {
+    int *p = (int *) t2;
+    clang_analyzer_eval(p == 0); // expected-warning{{TRUE}}
+  }
+}



More information about the cfe-commits mailing list