|
@@ -381,44 +381,48 @@ CodeGenFunction::EmitCompoundStmtWithoutScope(const CompoundStmt &S,
|
|
|
bool GetLast,
|
|
|
AggValueSlot AggSlot) {
|
|
|
|
|
|
- for (CompoundStmt::const_body_iterator I = S.body_begin(),
|
|
|
- E = S.body_end()-GetLast; I != E; ++I)
|
|
|
- EmitStmt(*I);
|
|
|
+ const Stmt *ExprResult = S.getStmtExprResult();
|
|
|
+ assert((!GetLast || (GetLast && ExprResult)) &&
|
|
|
+ "If GetLast is true then the CompoundStmt must have a StmtExprResult");
|
|
|
|
|
|
Address RetAlloca = Address::invalid();
|
|
|
- if (GetLast) {
|
|
|
- // We have to special case labels here. They are statements, but when put
|
|
|
- // at the end of a statement expression, they yield the value of their
|
|
|
- // subexpression. Handle this by walking through all labels we encounter,
|
|
|
- // emitting them before we evaluate the subexpr.
|
|
|
- // Similar issues arise for attributed statements.
|
|
|
- const Stmt *LastStmt = S.body_back();
|
|
|
- while (!isa<Expr>(LastStmt)) {
|
|
|
- if (const auto *LS = dyn_cast<LabelStmt>(LastStmt)) {
|
|
|
- EmitLabel(LS->getDecl());
|
|
|
- LastStmt = LS->getSubStmt();
|
|
|
- } else if (const auto *AS = dyn_cast<AttributedStmt>(LastStmt)) {
|
|
|
- // FIXME: Update this if we ever have attributes that affect the
|
|
|
- // semantics of an expression.
|
|
|
- LastStmt = AS->getSubStmt();
|
|
|
- } else {
|
|
|
- llvm_unreachable("unknown value statement");
|
|
|
+
|
|
|
+ for (auto *CurStmt : S.body()) {
|
|
|
+ if (GetLast && ExprResult == CurStmt) {
|
|
|
+ // We have to special case labels here. They are statements, but when put
|
|
|
+ // at the end of a statement expression, they yield the value of their
|
|
|
+ // subexpression. Handle this by walking through all labels we encounter,
|
|
|
+ // emitting them before we evaluate the subexpr.
|
|
|
+ // Similar issues arise for attributed statements.
|
|
|
+ while (!isa<Expr>(ExprResult)) {
|
|
|
+ if (const auto *LS = dyn_cast<LabelStmt>(ExprResult)) {
|
|
|
+ EmitLabel(LS->getDecl());
|
|
|
+ ExprResult = LS->getSubStmt();
|
|
|
+ } else if (const auto *AS = dyn_cast<AttributedStmt>(ExprResult)) {
|
|
|
+ // FIXME: Update this if we ever have attributes that affect the
|
|
|
+ // semantics of an expression.
|
|
|
+ ExprResult = AS->getSubStmt();
|
|
|
+ } else {
|
|
|
+ llvm_unreachable("unknown value statement");
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- EnsureInsertPoint();
|
|
|
+ EnsureInsertPoint();
|
|
|
|
|
|
- const Expr *E = cast<Expr>(LastStmt);
|
|
|
- QualType ExprTy = E->getType();
|
|
|
- if (hasAggregateEvaluationKind(ExprTy)) {
|
|
|
- EmitAggExpr(E, AggSlot);
|
|
|
+ const Expr *E = cast<Expr>(ExprResult);
|
|
|
+ QualType ExprTy = E->getType();
|
|
|
+ if (hasAggregateEvaluationKind(ExprTy)) {
|
|
|
+ EmitAggExpr(E, AggSlot);
|
|
|
+ } else {
|
|
|
+ // We can't return an RValue here because there might be cleanups at
|
|
|
+ // the end of the StmtExpr. Because of that, we have to emit the result
|
|
|
+ // here into a temporary alloca.
|
|
|
+ RetAlloca = CreateMemTemp(ExprTy);
|
|
|
+ EmitAnyExprToMem(E, RetAlloca, Qualifiers(),
|
|
|
+ /*IsInit*/ false);
|
|
|
+ }
|
|
|
} else {
|
|
|
- // We can't return an RValue here because there might be cleanups at
|
|
|
- // the end of the StmtExpr. Because of that, we have to emit the result
|
|
|
- // here into a temporary alloca.
|
|
|
- RetAlloca = CreateMemTemp(ExprTy);
|
|
|
- EmitAnyExprToMem(E, RetAlloca, Qualifiers(),
|
|
|
- /*IsInit*/ false);
|
|
|
+ EmitStmt(CurStmt);
|
|
|
}
|
|
|
}
|
|
|
|