]> granicus.if.org Git - clang/commitdiff
[analyzer] Handle caching out while evaluating a C++ new expression.
authorJordan Rose <jordan_rose@apple.com>
Sat, 30 Mar 2013 01:31:42 +0000 (01:31 +0000)
committerJordan Rose <jordan_rose@apple.com>
Sat, 30 Mar 2013 01:31:42 +0000 (01:31 +0000)
Evaluating a C++ new expression now includes generating an intermediate
ExplodedNode, and this node could very well represent a previously-
reachable state in the ExplodedGraph. If so, we can short-circuit the
rest of the evaluation.

Caught by the assertion a few lines later.

<rdar://problem/13510065>

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

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

index c1dd6b2220965f8986e336f73d7bdfb8a08326a2..64c361d4d8eacc78d5a99c893f6bc866a3065a9e 100644 (file)
@@ -351,15 +351,16 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
     State = State->BindExpr(CNE, LCtx, symVal);
   }
 
-  Bldr.generateNode(CNE, Pred, State);  
+  ExplodedNode *NewN = Bldr.generateNode(CNE, Pred, State);
+  if (!NewN)
+    return;
 
   // If the type is not a record, we won't have a CXXConstructExpr as an
   // initializer. Copy the value over.
   if (const Expr *Init = CNE->getInitializer()) {
     if (!isa<CXXConstructExpr>(Init)) {
       assert(Bldr.getResults().size() == 1);
-      ExplodedNode *TmpN = *Bldr.getResults().begin();
-      Bldr.takeNodes(TmpN);
+      Bldr.takeNodes(NewN);
 
       assert(!CNE->getType()->getPointeeCXXRecordDecl());
 
index 004a05ef94f66559f24ae876a09cb7fc795ab089..44ae9802f81f55fdb25e464177a05a04b876c0c1 100644 (file)
@@ -94,6 +94,14 @@ void testNewInvalidationScalarPlacement(int **p) {
   new (p) (int *)(static_cast<int *>(malloc(4))); // no-warning
 }
 
+void testCacheOut(PtrWrapper w) {
+  extern bool coin();
+  if (coin())
+    w.x = 0;
+  new (&w.x) (int*)(0); // we cache out here; don't crash
+}
+
+
 //--------------------------------------------------------------------
 // Check for intersection with other checkers from MallocChecker.cpp 
 // bounded with unix.Malloc