}
void Sema::ActOnStmtExprError() {
+ // Note that function is also called by TreeTransform when leaving a
+ // StmtExpr scope without rebuilding anything.
+
DiscardCleanupsInEvaluationContext();
PopExpressionEvaluationContext();
}
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformStmtExpr(StmtExpr *E) {
+ SemaRef.ActOnStartStmtExpr();
StmtResult SubStmt
= getDerived().TransformCompoundStmt(E->getSubStmt(), true);
- if (SubStmt.isInvalid())
+ if (SubStmt.isInvalid()) {
+ SemaRef.ActOnStmtExprError();
return ExprError();
+ }
if (!getDerived().AlwaysRebuild() &&
- SubStmt.get() == E->getSubStmt())
+ SubStmt.get() == E->getSubStmt()) {
+ // Calling this an 'error' is unintuitive, but it does the right thing.
+ SemaRef.ActOnStmtExprError();
return SemaRef.MaybeBindToTemporary(E);
+ }
return getDerived().RebuildStmtExpr(E->getLParenLoc(),
SubStmt.get(),
// CHECK: call i8* @objc_autoreleaseReturnValue
template Test37* instantiate_init<int>();
+// Just make sure that the AST invariants hold properly here,
+// i.e. that we don't crash.
+// The block should get bound in the full-expression outside
+// the statement-expression.
+template <class T> class Test38 {
+ void test(T x) {
+ ^{ (void) x; }, ({ x; });
+ }
+};
+// CHECK: define weak_odr void @_ZN6Test38IiE4testEi(
+template class Test38<int>;