]> granicus.if.org Git - clang/commitdiff
Work around missing handling of temporaries bound to default arguments.
authorManuel Klimek <klimek@google.com>
Wed, 13 Aug 2014 15:25:55 +0000 (15:25 +0000)
committerManuel Klimek <klimek@google.com>
Wed, 13 Aug 2014 15:25:55 +0000 (15:25 +0000)
Yet more problems due to the missing CXXBindTemporaryExpr in the CFG for
default arguments.

Unfortunately we cannot just switch off inserting temporaries for the
corresponding default arguments, as that breaks existing tests
(test/SemaCXX/return-noreturn.cpp:245).

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

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

index e837f5b740a551f537531e200e4162bb2fb9e265..4743bd6e602bcacc15023bcf68f9453533acf129 100644 (file)
@@ -681,8 +681,11 @@ void ExprEngine::ProcessTemporaryDtor(const CFGTemporaryDtor D,
   StmtBldr.generateNode(D.getBindTemporaryExpr(), Pred, State);
 
   QualType varType = D.getBindTemporaryExpr()->getSubExpr()->getType();
   StmtBldr.generateNode(D.getBindTemporaryExpr(), Pred, State);
 
   QualType varType = D.getBindTemporaryExpr()->getSubExpr()->getType();
-  assert(CleanDtorState.size() == 1);
-  ExplodedNode *CleanPred = *CleanDtorState.begin();
+  // FIXME: Currently CleanDtorState can be empty here due to temporaries being
+  // bound to default parameters.
+  assert(CleanDtorState.size() <= 1);
+  ExplodedNode *CleanPred =
+      CleanDtorState.empty() ? Pred : *CleanDtorState.begin();
   // FIXME: Inlining of temporary destructors is not supported yet anyway, so
   // we just put a NULL region for now. This will need to be changed later.
   VisitCXXDestructor(varType, nullptr, D.getBindTemporaryExpr(),
   // FIXME: Inlining of temporary destructors is not supported yet anyway, so
   // we just put a NULL region for now. This will need to be changed later.
   VisitCXXDestructor(varType, nullptr, D.getBindTemporaryExpr(),
@@ -718,10 +721,16 @@ void ExprEngine::VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE,
   StmtNodeBuilder StmtBldr(PreVisit, Dst, *currBldrCtx);
   for (ExplodedNode *Node : PreVisit) {
     ProgramStateRef State = Node->getState();
   StmtNodeBuilder StmtBldr(PreVisit, Dst, *currBldrCtx);
   for (ExplodedNode *Node : PreVisit) {
     ProgramStateRef State = Node->getState();
-    assert(!State->contains<InitializedTemporariesSet>(
-        std::make_pair(BTE, Node->getStackFrame())));
-    State = State->add<InitializedTemporariesSet>(
-        std::make_pair(BTE, Node->getStackFrame()));
+
+    if (!State->contains<InitializedTemporariesSet>(
+            std::make_pair(BTE, Node->getStackFrame()))) {
+      // FIXME: Currently the state might already contain the marker due to
+      // incorrect handling of temporaries bound to default parameters; for
+      // those, we currently skip the CXXBindTemporaryExpr but rely on adding
+      // temporary destructor nodes.
+      State = State->add<InitializedTemporariesSet>(
+          std::make_pair(BTE, Node->getStackFrame()));
+    }
     StmtBldr.generateNode(BTE, Node, State);
   }
 }
     StmtBldr.generateNode(BTE, Node, State);
   }
 }
index b1099d1f207e58f63f343917110a675844aa73d5..6e476339cb7735afd141b2c4aa56b2d8664354d4 100644 (file)
@@ -398,6 +398,27 @@ namespace destructors {
   void testDefaultParameters() {
     f();
   }
   void testDefaultParameters() {
     f();
   }
+
+  struct DefaultParam {
+    DefaultParam(int, const Dtor& d = Dtor());
+    ~DefaultParam();
+  };
+  void testDefaultParamConstructorsInLoops() {
+    while (true) {
+      // FIXME: This exact pattern triggers the temporary cleanup logic
+      // to fail when adding a 'clean' state.
+      DefaultParam(42);
+      DefaultParam(42);
+    }
+  }
+  void testDefaultParamConstructorsInTernariesInLoops(bool value) {
+    while (true) {
+      // FIXME: This exact pattern triggers the temporary cleanup logic
+      // to visit the bind-temporary logic with a state that already has that
+      // temporary marked as executed.
+      value ? DefaultParam(42) : DefaultParam(42);
+    }
+  }
 #endif // TEMPORARY_DTORS
 }
 
 #endif // TEMPORARY_DTORS
 }