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

Produce SymbolCast for a pointer-to-integer cast if the
support-symbolic-integer-casts flag is enabled.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D117229

Files:
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
  clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
  clang/test/Analysis/produce-ptr-to-integer-symbolcast.cpp
  clang/test/Analysis/symbol-simplification-mem-region-to-int-cast.cpp

Index: clang/test/Analysis/symbol-simplification-mem-region-to-int-cast.cpp
===================================================================
--- /dev/null
+++ clang/test/Analysis/symbol-simplification-mem-region-to-int-cast.cpp
@@ -0,0 +1,32 @@
+// RUN: %clang_analyze_cc1 %s \
+// RUN:   -analyzer-checker=core \
+// RUN:   -analyzer-checker=debug.ExprInspection \
+// RUN:   -analyzer-config eagerly-assume=false \
+// RUN:   -analyzer-config support-symbolic-integer-casts=true \
+// RUN:   -verify
+
+template <class T>
+void clang_analyzer_dump(T);
+
+void clang_analyzer_eval(bool);
+
+void test_memory_region_to_integer_cast_and_symbol_simplification(int *p) {
+  long p_as_integer = (long)p;
+  if (42 - p_as_integer < 42)
+    return;
+  // 42 - p_as_integer >= 42
+  // p_as_integer <= 0
+
+  if (p)
+    return;
+  clang_analyzer_eval(p == 0);            // expected-warning{{TRUE}}
+  clang_analyzer_eval(p_as_integer == 0); // expected-warning{{UNKNOWN}}
+
+  if (p_as_integer)
+    return;
+  clang_analyzer_eval(p == 0);            // expected-warning{{TRUE}}
+  clang_analyzer_eval(p_as_integer == 0); // expected-warning{{TRUE}}
+
+  (void)p_as_integer;
+  (void)p;
+}
Index: clang/test/Analysis/produce-ptr-to-integer-symbolcast.cpp
===================================================================
--- /dev/null
+++ clang/test/Analysis/produce-ptr-to-integer-symbolcast.cpp
@@ -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:   -analyzer-config support-symbolic-integer-casts=true \
+// RUN:   -triple x86_64-pc-linux-gnu \
+// RUN:   -verify
+
+template <class T>
+void clang_analyzer_dump(T);
+
+void test_memory_region_to_integer_cast(int *p) {
+  long p_int = (long)p;
+  clang_analyzer_dump(p);     // expected-warning{{&SymRegion{reg_$0<int * p>}}}
+  clang_analyzer_dump(p_int); // expected-warning{{(long) (reg_$0<int * p>)}}
+}
+
+void test_label_to_integer_cast(bool coin) {
+  int x = 0;
+p: ++x;
+  if (coin)
+    goto p;
+
+  // FIXME, below we should produce a SymbolCast instead of the LocAsInteger.
+  // However, for that we'd need to be able to store a loc::GotoLabel SVal
+  // inside the SymbolCast. But currently we can put only another SymExpr
+  // inside a SymbolCast.
+
+  // Use of GNU address-of-label extension.
+  clang_analyzer_dump((long)&&p); // expected-warning{{&&p [as 64 bit integer]}}
+}
Index: clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -773,6 +773,16 @@
       //    QualType elemTy = cast<ArrayType>(originalTy)->getElementType();
       //    QualType pointerTy = C.getPointerType(elemTy);
     }
+
+    AnalyzerOptions &Opts =
+        StateMgr.getOwningEngine().getAnalysisManager().getAnalyzerOptions();
+    if (Opts.ShouldSupportSymbolicIntegerCasts) {
+      const MemRegion *R = V.getRegion();
+      if (R && !OriginalTy.isNull())
+        if (const auto *SR = dyn_cast<SymbolicRegion>(R))
+          return simplifySymbolCast(SR->getSymbol(), CastTy);
+    }
+
     const unsigned BitWidth = Context.getIntWidth(CastTy);
     return makeLocAsInteger(Val.castAs<Loc>(), BitWidth);
   }
@@ -1009,6 +1019,40 @@
   return V;
 }
 
+SVal clang::ento::SValBuilder::simplifySymbolCast(SymbolRef SE,
+                                                  QualType CastTy) {
+  QualType T = Context.getCanonicalType(SE->getType());
+  if (!isa<SymbolCast>(SE))
+    return makeNonLoc(SE, T, CastTy);
+
+  SymbolRef RootSym = cast<SymbolCast>(SE)->getOperand();
+  QualType RT = RootSym->getType().getCanonicalType();
+
+  BasicValueFactory &BVF = getBasicValueFactory();
+  APSIntType CTy = BVF.getAPSIntType(CastTy);
+  APSIntType TTy = BVF.getAPSIntType(T);
+
+  const auto WC = CTy.getBitWidth();
+  const auto WT = TTy.getBitWidth();
+
+  if (WC <= WT) {
+    const bool isSameType = (RT == CastTy);
+    if (isSameType)
+      return nonloc::SymbolVal(RootSym);
+    return makeNonLoc(RootSym, RT, CastTy);
+  }
+
+  APSIntType RTy = BVF.getAPSIntType(RT);
+  const auto WR = RTy.getBitWidth();
+  const bool UT = TTy.isUnsigned();
+  const bool UR = RTy.isUnsigned();
+
+  if (((WT > WR) && (UR || !UT)) || ((WT == WR) && (UT == UR)))
+    return makeNonLoc(RootSym, RT, CastTy);
+
+  return makeNonLoc(SE, T, CastTy);
+}
+
 SVal clang::ento::SValBuilder::simplifySymbolCast(nonloc::SymbolVal V,
                                                   QualType CastTy) {
   // We use seven conditions to recognize a simplification case.
@@ -1047,36 +1091,10 @@
   SymbolRef SE = V.getSymbol();
   QualType T = Context.getCanonicalType(SE->getType());
 
-  if (T == CastTy)
-    return V;
-
-  if (!isa<SymbolCast>(SE))
-    return makeNonLoc(SE, T, CastTy);
-
-  SymbolRef RootSym = cast<SymbolCast>(SE)->getOperand();
-  QualType RT = RootSym->getType().getCanonicalType();
-
-  BasicValueFactory &BVF = getBasicValueFactory();
-  APSIntType CTy = BVF.getAPSIntType(CastTy);
-  APSIntType TTy = BVF.getAPSIntType(T);
-
-  const auto WC = CTy.getBitWidth();
-  const auto WT = TTy.getBitWidth();
-
-  if (WC <= WT) {
-    const bool isSameType = (RT == CastTy);
-    if (isSameType)
-      return nonloc::SymbolVal(RootSym);
-    return makeNonLoc(RootSym, RT, CastTy);
+  if (T == CastTy) {
+    auto SV = makeSymbolVal(SE);
+    assert(SV == V);
+    return SV;
   }
-
-  APSIntType RTy = BVF.getAPSIntType(RT);
-  const auto WR = RTy.getBitWidth();
-  const bool UT = TTy.isUnsigned();
-  const bool UR = RTy.isUnsigned();
-
-  if (((WT > WR) && (UR || !UT)) || ((WT == WR) && (UT == UR)))
-    return makeNonLoc(RootSym, RT, CastTy);
-
-  return makeNonLoc(SE, T, CastTy);
+  return simplifySymbolCast(SE, CastTy);
 }
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
@@ -108,6 +108,8 @@
   /// \note: Currently only support integral casts.
   SVal simplifySymbolCast(nonloc::SymbolVal V, QualType CastTy);
 
+  SVal simplifySymbolCast(SymbolRef SE, QualType CastTy);
+
 public:
   SValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context,
               ProgramStateManager &stateMgr);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to