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/trunk@214050
91177308-0d34-0410-b5e6-
96231b3b80d8
/// 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 {
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;
}
}
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