summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2014-08-04 18:19:14 +0000
committerBill Wendling <isanbard@gmail.com>2014-08-04 18:19:14 +0000
commita2bd2e285cda050126fd9e965ffebdba45997dcc (patch)
treed1bc9b809236adbf9bbac7c78134e03b521489f7
parentb4cc7562d74c3cb8d0539de5783758ddc7a08c72 (diff)
Merging r214050:
------------------------------------------------------------------------ r214050 | rsmith | 2014-07-26 22:12:49 -0700 (Sat, 26 Jul 2014) | 7 lines When looking for temporary dtors while building the CFG, do not walk into lambda expressions (other than their capture initializers) nor blocks. Do walk into default argument expressions and default initializer expressions. These bugs were causing us to produce broken CFGs whenever a lambda expression was used to initialize a libstdc++ std::function object! ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/cfe/branches/release_35@214742 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/ExprCXX.h6
-rw-r--r--lib/Analysis/CFG.cpp27
-rw-r--r--test/SemaCXX/return-noreturn.cpp22
3 files changed, 54 insertions, 1 deletions
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index d883a32e0e..3a43d6dac1 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -1479,6 +1479,12 @@ public:
/// arguments.
typedef Expr **capture_init_iterator;
+ /// \brief Retrieve the initialization expressions for this lambda's captures.
+ llvm::iterator_range<capture_init_iterator> capture_inits() const {
+ return llvm::iterator_range<capture_init_iterator>(capture_init_begin(),
+ capture_init_end());
+ }
+
/// \brief Retrieve the first initialization argument for this
/// lambda expression (which initializes the first capture field).
capture_init_iterator capture_init_begin() const {
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp
index d6361e8767..842a385fbc 100644
--- a/lib/Analysis/CFG.cpp
+++ b/lib/Analysis/CFG.cpp
@@ -3495,10 +3495,35 @@ tryAgain:
case Stmt::ParenExprClass:
E = cast<ParenExpr>(E)->getSubExpr();
goto tryAgain;
-
+
case Stmt::MaterializeTemporaryExprClass:
E = cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr();
goto tryAgain;
+
+ case Stmt::BlockExprClass:
+ // Don't recurse into blocks; their subexpressions don't get evaluated
+ // here.
+ return Block;
+
+ case Stmt::LambdaExprClass: {
+ // For lambda expressions, only recurse into the capture initializers,
+ // and not the body.
+ auto *LE = cast<LambdaExpr>(E);
+ CFGBlock *B = Block;
+ for (Expr *Init : LE->capture_inits()) {
+ if (CFGBlock *R = VisitForTemporaryDtors(Init))
+ B = R;
+ }
+ return B;
+ }
+
+ case Stmt::CXXDefaultArgExprClass:
+ E = cast<CXXDefaultArgExpr>(E)->getExpr();
+ goto tryAgain;
+
+ case Stmt::CXXDefaultInitExprClass:
+ E = cast<CXXDefaultInitExpr>(E)->getExpr();
+ goto tryAgain;
}
}
diff --git a/test/SemaCXX/return-noreturn.cpp b/test/SemaCXX/return-noreturn.cpp
index 16bb86cc21..531dc23995 100644
--- a/test/SemaCXX/return-noreturn.cpp
+++ b/test/SemaCXX/return-noreturn.cpp
@@ -146,3 +146,25 @@ void PR9412_f() {
PR9412_t<PR9412_Exact>(); // expected-note {{in instantiation of function template specialization 'PR9412_t<0>' requested here}}
}
+#if __cplusplus >= 201103L
+namespace LambdaVsTemporaryDtor {
+ struct Y { ~Y(); };
+ struct X { template<typename T> X(T, Y = Y()) {} };
+
+ struct Fatal { ~Fatal() __attribute__((noreturn)); };
+ struct FatalCopy { FatalCopy(); FatalCopy(const FatalCopy&, Fatal F = Fatal()); };
+
+ void foo();
+
+ int bar() {
+ X work([](){ Fatal(); });
+ foo();
+ } // expected-warning {{control reaches end of non-void function}}
+
+ int baz() {
+ FatalCopy fc;
+ X work([fc](){});
+ foo();
+ } // ok, initialization of lambda does not return
+}
+#endif