]> granicus.if.org Git - clang/commitdiff
CFG: Delay creating Dtors for CompoundStmts which end in ReturnStmt
authorMatthias Gehre <M.Gehre@gmx.de>
Sat, 14 Nov 2015 00:36:50 +0000 (00:36 +0000)
committerMatthias Gehre <M.Gehre@gmx.de>
Sat, 14 Nov 2015 00:36:50 +0000 (00:36 +0000)
Summary:
VisitReturnStmt would create a new block with including Dtors, so the Dtors created
in VisitCompoundStmts would be in an unreachable block.

Example:

struct S {
  ~S();
};

void f()
{
  S s;
  return;
}

void g()
{
  S s;
}

Before this patch, f has one additional unreachable block containing just the
destructor of S. With this patch, both f and g have the same blocks.

Reviewers: krememek

Subscribers: cfe-commits

Differential Revision: http://reviews.llvm.org/D13973

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

lib/Analysis/CFG.cpp
test/Analysis/no-unreachable-dtors.cpp [new file with mode: 0644]

index 6cb63f2b175512c4d30b4568051f9829fd925981..fba9a41f232262f0deeab707391ff1d3aee016db 100644 (file)
@@ -1942,7 +1942,15 @@ CFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *C,
 
 
 CFGBlock *CFGBuilder::VisitCompoundStmt(CompoundStmt *C) {
-  addLocalScopeAndDtors(C);
+  LocalScope::const_iterator scopeBeginPos = ScopePos;
+  if (BuildOpts.AddImplicitDtors) {
+    addLocalScopeForStmt(C);
+  }
+  if (!C->body_empty() && !isa<ReturnStmt>(*C->body_rbegin())) {
+    // If the body ends with a ReturnStmt, the dtors will be added in VisitReturnStmt
+    addAutomaticObjDtors(ScopePos, scopeBeginPos, C);
+  }
+
   CFGBlock *LastBlock = Block;
 
   for (CompoundStmt::reverse_body_iterator I=C->body_rbegin(), E=C->body_rend();
diff --git a/test/Analysis/no-unreachable-dtors.cpp b/test/Analysis/no-unreachable-dtors.cpp
new file mode 100644 (file)
index 0000000..e0893b3
--- /dev/null
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=debug.Stats -verify -Wno-unreachable-code %s
+
+struct S {
+  ~S();
+};
+
+// the return at the end of an CompoundStmt does not lead to an unreachable block containing the dtors
+void test() { // expected-warning-re{{test -> Total CFGBlocks: {{[0-9]+}} | Unreachable CFGBlocks: 0 | Exhausted Block: no | Empty WorkList: yes}}
+  S s;
+  return;
+}