r325286 - [analyzer] Suppress temporary destructors for temporary arrays.

Artem Dergachev via cfe-commits cfe-commits at lists.llvm.org
Thu Feb 15 11:34:19 PST 2018


Author: dergachev
Date: Thu Feb 15 11:34:19 2018
New Revision: 325286

URL: http://llvm.org/viewvc/llvm-project?rev=325286&view=rev
Log:
[analyzer] Suppress temporary destructors for temporary arrays.

Array destructors, like constructors, need to be called for each element of the
array separately. We do not have any mechanisms to do this in the analyzer,
so for now all we do is evaluate a single constructor or destructor
conservatively and give up. It automatically causes the necessary invalidation
and pointer escape for the whole array, because this is how RegionStore works.

Implement this conservative behavior for temporary destructors. This fixes the
crash on the provided test.

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

Modified:
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
    cfe/trunk/test/Analysis/temporaries.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=325286&r1=325285&r2=325286&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Thu Feb 15 11:34:19 2018
@@ -957,7 +957,7 @@ void ExprEngine::ProcessTemporaryDtor(co
   }
   StmtBldr.generateNode(D.getBindTemporaryExpr(), Pred, State);
 
-  QualType varType = D.getBindTemporaryExpr()->getSubExpr()->getType();
+  QualType T = D.getBindTemporaryExpr()->getSubExpr()->getType();
   // FIXME: Currently CleanDtorState can be empty here due to temporaries being
   // bound to default parameters.
   assert(CleanDtorState.size() <= 1);
@@ -966,9 +966,22 @@ void ExprEngine::ProcessTemporaryDtor(co
 
   EvalCallOptions CallOpts;
   CallOpts.IsTemporaryCtorOrDtor = true;
-  if (!MR)
+  if (!MR) {
     CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion = true;
-  VisitCXXDestructor(varType, MR, D.getBindTemporaryExpr(),
+
+    // If we have no MR, we still need to unwrap the array to avoid destroying
+    // the whole array at once. Regardless, we'd eventually need to model array
+    // destructors properly, element-by-element.
+    while (const ArrayType *AT = getContext().getAsArrayType(T)) {
+      T = AT->getElementType();
+      CallOpts.IsArrayCtorOrDtor = true;
+    }
+  } else {
+    // We'd eventually need to makeZeroElementRegion() trick here,
+    // but for now we don't have the respective construction contexts,
+    // so MR would always be null in this case. Do nothing for now.
+  }
+  VisitCXXDestructor(T, MR, D.getBindTemporaryExpr(),
                      /*IsBase=*/false, CleanPred, Dst, CallOpts);
 }
 

Modified: cfe/trunk/test/Analysis/temporaries.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/temporaries.cpp?rev=325286&r1=325285&r2=325286&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/temporaries.cpp (original)
+++ cfe/trunk/test/Analysis/temporaries.cpp Thu Feb 15 11:34:19 2018
@@ -6,6 +6,8 @@ extern bool clang_analyzer_eval(bool);
 extern bool clang_analyzer_warnIfReached();
 void clang_analyzer_checkInlined(bool);
 
+#include "Inputs/system-header-simulator-cxx.h";
+
 struct Trivial {
   Trivial(int x) : value(x) {}
   int value;
@@ -892,3 +894,17 @@ void test_ternary_temporary_with_copy(in
   }
 }
 } // namespace test_match_constructors_and_destructors
+
+#if __cplusplus >= 201103L
+namespace temporary_list_crash {
+class C {
+public:
+  C() {}
+  ~C() {}
+};
+
+void test() {
+  std::initializer_list<C>{C(), C()}; // no-crash
+}
+} // namespace temporary_list_crash
+#endif // C++11




More information about the cfe-commits mailing list