[PATCH] D41250: [analyzer] Model implied cast around operator new().

Artem Dergachev via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Thu Dec 14 11:08:13 PST 2017


NoQ created this revision.
NoQ added reviewers: dcoughlin, xazax.hun, a.sidorin, george.karpenkov, szepet.
Herald added subscribers: cfe-commits, rnkovacs, eraman.

C++ overridable `operator new()` has the following prototype:

  void *operator new(size_t size, user-defined arguments...);

The return value is `void *`. However, before passing it to constructor, we need to make a cast to the respective object pointer type. Hence an implicit cast is present here, which is not represented in the current AST or CFG. Modeling this cast is straightforward though. This is the change i mentioned in https://reviews.llvm.org/D40939.

I also noticed that `evalCast` from `void *` to `T *` is uncomfortable to use because sometimes it transforms `&SymRegion{$x}` into `&element{T, 0S32b, SymRegion{$x}}` even when `$x` is already of type `T *`. The form `&SymRegion{$x}` seems to be the canonical form of this symbolic pointer value in the rest of the analyzer, so i decided to change `evalCast` to preserve it.

The problem of how to represent memregion value casts better still stands - it wouldn't add much to the analyzer's quality, but we just keep running into it over and over again.


Repository:
  rC Clang

https://reviews.llvm.org/D41250

Files:
  lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
  lib/StaticAnalyzer/Core/Store.cpp
  test/Analysis/new-ctor-conservative.cpp
  test/Analysis/new-ctor-inlined.cpp


Index: test/Analysis/new-ctor-inlined.cpp
===================================================================
--- test/Analysis/new-ctor-inlined.cpp
+++ test/Analysis/new-ctor-inlined.cpp
@@ -27,3 +27,12 @@
   // Check that bindings are correct (and also not dying).
   clang_analyzer_eval(s->x == 1); // expected-warning{{TRUE}}
 }
+
+void checkNewPOD() {
+  int *i = new int;
+  clang_analyzer_eval(*i == 0); // expected-warning{{UNKNOWN}}
+  int *j = new int();
+  clang_analyzer_eval(*j == 0); // expected-warning{{TRUE}}
+  int *k = new int(5);
+  clang_analyzer_eval(*k == 5); // expected-warning{{TRUE}}
+}
Index: test/Analysis/new-ctor-conservative.cpp
===================================================================
--- test/Analysis/new-ctor-conservative.cpp
+++ test/Analysis/new-ctor-conservative.cpp
@@ -12,3 +12,12 @@
   S *s = new S;
   clang_analyzer_eval(s->x == 1); // expected-warning{{TRUE}}
 }
+
+void checkNewPOD() {
+  int *i = new int;
+  clang_analyzer_eval(*i == 0); // expected-warning{{UNKNOWN}}
+  int *j = new int();
+  clang_analyzer_eval(*j == 0); // expected-warning{{TRUE}}
+  int *k = new int(5);
+  clang_analyzer_eval(*k == 5); // expected-warning{{TRUE}}
+}
Index: lib/StaticAnalyzer/Core/Store.cpp
===================================================================
--- lib/StaticAnalyzer/Core/Store.cpp
+++ lib/StaticAnalyzer/Core/Store.cpp
@@ -91,13 +91,21 @@
     return R;
 
   // Handle casts from compatible types.
-  if (R->isBoundable())
+  if (R->isBoundable()) {
     if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
       QualType ObjTy = Ctx.getCanonicalType(TR->getValueType());
       if (CanonPointeeTy == ObjTy)
         return R;
     }
 
+    if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) {
+      QualType SymTy =
+          Ctx.getCanonicalType(SR->getSymbol()->getType()->getPointeeType());
+      if (CanonPointeeTy == SymTy)
+        return R;
+    }
+  }
+
   // Process region cast according to the kind of the region being cast.
   switch (R->getKind()) {
     case MemRegion::CXXThisRegionKind:
Index: lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -571,6 +571,10 @@
     SVal PlacementLoc = State->getSVal(CNE->getPlacementArg(0), LCtx);
     Result = svalBuilder.evalCast(PlacementLoc, CNE->getType(),
                                   CNE->getPlacementArg(0)->getType());
+  } else {
+    Result =
+        svalBuilder.evalCast(Result, CNE->getType(),
+                             getContext().getPointerType(getContext().VoidTy));
   }
 
   // Bind the address of the object, then check to see if we cached out.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D41250.126995.patch
Type: text/x-patch
Size: 2778 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20171214/643a0f39/attachment.bin>


More information about the cfe-commits mailing list