ComplexPairTy ComplexExprEmitter::VisitStmtExpr(const StmtExpr *E) {
CodeGenFunction::StmtExprEvaluation eval(CGF);
- return CGF.EmitCompoundStmt(*E->getSubStmt(), true).getComplexVal();
+ llvm::Value *RetAlloca = CGF.EmitCompoundStmt(*E->getSubStmt(), true);
+ assert(RetAlloca && "Expected complex return value");
+ return EmitLoadOfLValue(CGF.MakeAddrLValue(RetAlloca, E->getType()));
}
/// EmitComplexToComplexCast - Emit a cast from complex value Val to DestType.
Value *ScalarExprEmitter::VisitStmtExpr(const StmtExpr *E) {
CodeGenFunction::StmtExprEvaluation eval(CGF);
- return CGF.EmitCompoundStmt(*E->getSubStmt(), !E->getType()->isVoidType())
- .getScalarVal();
+ llvm::Value *RetAlloca = CGF.EmitCompoundStmt(*E->getSubStmt(),
+ !E->getType()->isVoidType());
+ if (!RetAlloca)
+ return 0;
+ return CGF.EmitLoadOfScalar(CGF.MakeAddrLValue(RetAlloca, E->getType()));
+
}
//===----------------------------------------------------------------------===//
/// EmitCompoundStmt - Emit a compound statement {..} node. If GetLast is true,
/// this captures the expression result of the last sub-statement and returns it
/// (for use by the statement expression extension).
-RValue CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast,
- AggValueSlot AggSlot) {
+llvm::Value* CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast,
+ AggValueSlot AggSlot) {
PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),S.getLBracLoc(),
"LLVM IR generation of compound statement ('{}')");
return EmitCompoundStmtWithoutScope(S, GetLast, AggSlot);
}
-RValue CodeGenFunction::EmitCompoundStmtWithoutScope(const CompoundStmt &S, bool GetLast,
- AggValueSlot AggSlot) {
+llvm::Value*
+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);
- RValue RV;
- if (!GetLast)
- RV = RValue::get(0);
- else {
+ llvm::Value *RetAlloca = 0;
+ 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,
EnsureInsertPoint();
- RV = EmitAnyExpr(cast<Expr>(LastStmt), AggSlot);
+ QualType ExprTy = cast<Expr>(LastStmt)->getType();
+ if (hasAggregateEvaluationKind(ExprTy)) {
+ EmitAggExpr(cast<Expr>(LastStmt), 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(cast<Expr>(LastStmt), RetAlloca, Qualifiers(),
+ /*IsInit*/false);
+ }
+
}
- return RV;
+ return RetAlloca;
}
void CodeGenFunction::SimplifyForwardingBlocks(llvm::BasicBlock *BB) {
/// \return True if the statement was handled.
bool EmitSimpleStmt(const Stmt *S);
- RValue EmitCompoundStmt(const CompoundStmt &S, bool GetLast = false,
- AggValueSlot AVS = AggValueSlot::ignored());
- RValue EmitCompoundStmtWithoutScope(const CompoundStmt &S,
- bool GetLast = false, AggValueSlot AVS =
- AggValueSlot::ignored());
+ llvm::Value *EmitCompoundStmt(const CompoundStmt &S, bool GetLast = false,
+ AggValueSlot AVS = AggValueSlot::ignored());
+ llvm::Value *EmitCompoundStmtWithoutScope(const CompoundStmt &S,
+ bool GetLast = false,
+ AggValueSlot AVS =
+ AggValueSlot::ignored());
/// EmitLabel - Emit the block for the given label. It is legal to call this
/// function even if there is no current insertion point.
return (({ a; }));
}
+// <rdar://problem/14074868>
+// Make sure this doesn't crash.
+int foo5(bool b) {
+ int y = 0;
+ y = ({ A a(1); if (b) goto G; a.i; });
+ G: return y;
+}
// CHECK: define i8* @test52()
// CHECK: [[X:%.*]] = alloca i32
+// CHECK-NEXT: [[TMPALLOCA:%.*]] = alloca i8*
// CHECK-NEXT: store i32 5, i32* [[X]],
// CHECK-NEXT: [[T0:%.*]] = load i32* [[X]],
// CHECK-NEXT: [[T1:%.*]] = call i8* @test52_helper(i32 [[T0]])
-// CHECK-NEXT: [[T2:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[T1]])
-// CHECK-NEXT: ret i8* [[T2]]
+// CHECK-NEXT: store i8* [[T1]], i8** [[TMPALLOCA]]
+// CHECK-NEXT: [[T2:%.*]] = load i8** [[TMPALLOCA]]
+// CHECK-NEXT: [[T3:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[T2]])
+// CHECK-NEXT: ret i8* [[T3]]
}
// rdar://problem/9400644
// CHECK: define void @test53()
// CHECK: [[X:%.*]] = alloca i8*,
// CHECK-NEXT: [[Y:%.*]] = alloca i8*,
+// CHECK-NEXT: [[TMPALLOCA:%.*]] = alloca i8*,
// CHECK-NEXT: [[T0:%.*]] = call i8* @test53_helper()
// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
// CHECK-NEXT: store i8* [[T1]], i8** [[Y]],
// CHECK-NEXT: [[T0:%.*]] = load i8** [[Y]],
// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
+// CHECK-NEXT: store i8* [[T1]], i8** [[TMPALLOCA]]
// CHECK-NEXT: [[T2:%.*]] = load i8** [[Y]]
// CHECK-NEXT: call void @objc_release(i8* [[T2]])
-// CHECK-NEXT: store i8* [[T1]], i8** [[X]],
+// CHECK-NEXT: [[T3:%.*]] = load i8** [[TMPALLOCA]]
+// CHECK-NEXT: store i8* [[T3]], i8** [[X]],
// CHECK-NEXT: load i8** [[X]],
// CHECK-NEXT: [[T0:%.*]] = load i8** [[X]]
// CHECK-NEXT: call void @objc_release(i8* [[T0]])