[PATCH] [StaticAnalyzer]Handle Destructor call generated by C++ delete expr

Jordan Rose jordan_rose at apple.com
Thu Sep 5 17:19:01 PDT 2013


  IIRC, the delete[] case won't actually inline any destructors, but it should still invalidate the entire array. Is that not working?

  You gave me the idea for one more test that probably doesn't work yet:

  ```
  void testDeleteNull() {
    NoReturnDtor *foo = 0;
    delete foo; // should not call destructor, checked below
    clang_analyzer_eval(true); // expected-warning{{TRUE}}
  }

  void testDeleteUnknown(NoReturnDtor *foo) {
    delete foo; // should assume non-null and call noreturn destructor
    clang_analyzer_eval(true); // no-warning
  }
  ```


================
Comment at: test/Analysis/new.cpp:271-285
@@ +270,16 @@
+
+// Invalidate Region even in case of default destructor
+class InvalidateDestTest {
+  public:
+   int x;
+   ~InvalidateDestTest();
+};
+int test_member_invalidation() {
+  InvalidateDestTest* test = new InvalidateDestTest();
+  test->x = 5;
+  int* k = &(test->x);
+  clang_analyzer_eval(*k == 5); // expected-warning{{TRUE}}
+  delete test;
+  clang_analyzer_eval(*k == 5); // expected-warning{{UNKNOWN}}
+  return 0;
+}
----------------
This is backwards; `*k` points into deleted memory. I meant to put the pointer into the class, and have it refer to the stack variable.

================
Comment at: test/Analysis/new.cpp:261-269
@@ +260,11 @@
+
+//Deleting a non class pointer
+void test_dtor_reinterpretCast() {
+  int *v = new int(10);
+  int x = 0;
+  int y = 1;
+  LocalDestTest* test = reinterpret_cast<LocalDestTest*>(v);
+  delete test; // Destructor not called hence should not abort
+  x = y/x;  // expected-warning{{Division by zero}}
+}
+
----------------
The way C++ works is that this *will* actually call the destructor. I haven't tracked down why it doesn't work right, but I'm okay with it not working yet. The test case I wanted was just a plain `delete v`, though.

================
Comment at: test/Analysis/new.cpp:254-259
@@ +253,8 @@
+};
+void test_delte_dtor_LocalVar() {
+  LocalDestTest* arg = 0;
+  LocalDestTest test;
+  delete arg;  // no warn or crash
+  delete &test;
+}
+
----------------
Weird to call this "arg", but okay.

================
Comment at: test/Analysis/new.cpp:227-233
@@ +226,9 @@
+// Test Deleting a value that's passed as an argument.
+class ArgDestTest {
+ public:
+  int x;
+  int y;
+  ArgDestTest() {}
+  ~ArgDestTest() {x = x/y;} //expected-warning{{Division by zero}}
+};
+
----------------
You don't really need to declare this again -- it's the same as DestTest. Just make one type "IntPair" or something (and the same for the "NoReturnDtor" case below).


http://llvm-reviews.chandlerc.com/D1594



More information about the cfe-commits mailing list