]> granicus.if.org Git - clang/commitdiff
[analyzer] Fix operator delete[] array-type-sub-expression handling.
authorArtem Dergachev <artem.dergachev@gmail.com>
Fri, 27 Apr 2018 02:16:03 +0000 (02:16 +0000)
committerArtem Dergachev <artem.dergachev@gmail.com>
Fri, 27 Apr 2018 02:16:03 +0000 (02:16 +0000)
Avoid crash when the sub-expression of operator delete[] is of array type.

This is not the same as simply using a delete[] syntax.

We're still not properly calling destructors in this case in the analyzer.

Differential Revision: https://reviews.llvm.org/D46146

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@331014 91177308-0d34-0410-b5e6-96231b3b80d8

lib/StaticAnalyzer/Core/ExprEngine.cpp
test/Analysis/new.cpp

index 1e0bfcea2d74089e706c70f732e6332bbe095900..d0ebb223e941593a359bc9cf70878350dba82161 100644 (file)
@@ -1086,12 +1086,14 @@ void ExprEngine::ProcessDeleteDtor(const CFGDeleteDtor Dtor,
     // This workaround will just run the first destructor (which will still
     // invalidate the entire array).
     CallOpts.IsArrayCtorOrDtor = true;
+    // Yes, it may even be a multi-dimensional array.
+    while (const auto *AT = getContext().getAsArrayType(DTy))
+      DTy = AT->getElementType();
     if (ArgR)
       ArgR = getStoreManager().GetElementZeroRegion(cast<SubRegion>(ArgR), DTy);
   }
 
-  VisitCXXDestructor(DE->getDestroyedType(), ArgR, DE, /*IsBase=*/false,
-                     Pred, Dst, CallOpts);
+  VisitCXXDestructor(DTy, ArgR, DE, /*IsBase=*/false, Pred, Dst, CallOpts);
 }
 
 void ExprEngine::ProcessBaseDtor(const CFGBaseDtor D,
index 4ae93c612f37c3f31a4be12e6ca38343da3c1922..31f763266c3810f57521ba09fc083c70c207982d 100644 (file)
@@ -274,6 +274,24 @@ void test_var_delete() {
   clang_analyzer_eval(true); // expected-warning{{TRUE}}
 }
 
+void test_array_delete() {
+  class C {
+  public:
+    ~C() {}
+  };
+
+  auto c1 = new C[2][3];
+  delete[] c1; // no-crash // no-warning
+
+  C c2[4];
+  // FIXME: Should warn.
+  delete[] &c2; // no-crash
+
+  C c3[7][6];
+  // FIXME: Should warn.
+  delete[] &c3; // no-crash
+}
+
 void testDeleteNull() {
   NoReturnDtor *foo = 0;
   delete foo; // should not call destructor, checked below