[PATCH] [analyzer] Fix crash with temporary destructors

Pavel Labath labath at google.com
Fri Sep 6 02:40:16 PDT 2013


Hi jordan_rose,

It turns out that moving the test out of the loop in makeZeroElementRegion was
not a valid optimization after all, since one of the side effects of the loop is
changing the element type.

To avoid this happening in the future I have changed the function to return the type,
instead of using by-ref parameter.

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

Files:
  lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
  test/Analysis/temporaries.cpp

Index: lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -84,28 +84,24 @@
 
 
 /// Returns a region representing the first element of a (possibly
-/// multi-dimensional) array.
-///
-/// On return, \p Ty will be set to the base type of the array.
+/// multi-dimensional) array and its type.
 ///
 /// If the type is not an array type at all, the original value is returned.
-static SVal makeZeroElementRegion(ProgramStateRef State, SVal LValue,
-                                  QualType &Ty) {
-  // FIXME: This check is just a temporary workaround, because
-  // ProcessTemporaryDtor sends us NULL regions. It will not be necessary once
-  // we can properly process temporary destructors.
-  if (!LValue.getAsRegion())
-    return LValue;
-
+static std::pair<SVal, QualType>
+makeZeroElementRegion(ProgramStateRef State, SVal LValue, QualType Ty) {
   SValBuilder &SVB = State->getStateManager().getSValBuilder();
   ASTContext &Ctx = SVB.getContext();
 
   while (const ArrayType *AT = Ctx.getAsArrayType(Ty)) {
     Ty = AT->getElementType();
-    LValue = State->getLValue(Ty, SVB.makeZeroArrayIndex(), LValue);
+    // FIXME: This check is just a temporary workaround, because
+    // ProcessTemporaryDtor sends us NULL regions. It will not be necessary once
+    // we can properly process temporary destructors.
+    if (LValue.getAsRegion())
+      LValue = State->getLValue(Ty, SVB.makeZeroArrayIndex(), LValue);
   }
 
-  return LValue;
+  return std::make_pair(LValue, Ty);
 }
 
 void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
@@ -135,7 +131,7 @@
             if (Var->getInit()->IgnoreImplicit() == CE) {
               SVal LValue = State->getLValue(Var, LCtx);
               QualType Ty = Var->getType();
-              LValue = makeZeroElementRegion(State, LValue, Ty);
+              LValue = makeZeroElementRegion(State, LValue, Ty).first;
               Target = LValue.getAsRegion();
             }
           }
@@ -163,7 +159,7 @@
         }
 
         QualType Ty = Field->getType();
-        FieldVal = makeZeroElementRegion(State, FieldVal, Ty);
+        FieldVal = makeZeroElementRegion(State, FieldVal, Ty).first;
         Target = FieldVal.getAsRegion();
       }
 
@@ -297,7 +293,8 @@
   // This workaround will just run the first destructor (which will still
   // invalidate the entire array).
   SVal DestVal = loc::MemRegionVal(Dest);
-  DestVal = makeZeroElementRegion(State, DestVal, ObjectType);
+  llvm::tie(DestVal, ObjectType) =
+      makeZeroElementRegion(State, DestVal, ObjectType);
   Dest = DestVal.getAsRegion();
 
   const CXXRecordDecl *RecordDecl = ObjectType->getAsCXXRecordDecl();
Index: test/Analysis/temporaries.cpp
===================================================================
--- test/Analysis/temporaries.cpp
+++ test/Analysis/temporaries.cpp
@@ -1,6 +1,8 @@
 // RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -w -std=c++03 %s
 // RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -w -std=c++11 %s
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -w -analyzer-config cfg-temporary-dtors=true %s -DTEMPORARY_DTORS
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -w -std=c++11 -analyzer-config cfg-temporary-dtors=true %s -DTEMPORARY_DTORS
+
+#include "Inputs/system-header-simulator-cxx.h"
 
 extern bool clang_analyzer_eval(bool);
 
@@ -247,3 +249,16 @@
     clang_analyzer_eval(x == 47); // expected-warning{{TRUE}}
   }
 }
+
+#if __cplusplus >= 201103L
+namespace array_destructors {
+  struct Triple {
+    ~Triple();
+  };
+
+  void f() {
+    Triple triple;
+    std::initializer_list<Triple> a{triple};
+  }
+}
+#endif
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D1615.1.patch
Type: text/x-patch
Size: 3886 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130906/23bb1e70/attachment.bin>


More information about the cfe-commits mailing list