From: Eli Friedman Date: Mon, 10 Jun 2013 22:04:49 +0000 (+0000) Subject: Make sure we don't emit invalid IR for StmtExprs with complex cleanups. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2ac2fa7726eb2f6fe445e098489e92931c31f7ca;p=clang Make sure we don't emit invalid IR for StmtExprs with complex cleanups. Fixes . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@183699 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp index 36f974a313..643ef91c89 100644 --- a/lib/CodeGen/CGExprComplex.cpp +++ b/lib/CodeGen/CGExprComplex.cpp @@ -358,7 +358,9 @@ ComplexPairTy ComplexExprEmitter::VisitCallExpr(const CallExpr *E) { 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. diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index c1c252d12b..7fb8e87cbd 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -1442,8 +1442,12 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { 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())); + } //===----------------------------------------------------------------------===// diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index 0db31ac49c..f104acb199 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -196,8 +196,8 @@ bool CodeGenFunction::EmitSimpleStmt(const Stmt *S) { /// 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 ('{}')"); @@ -207,17 +207,17 @@ RValue CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast, 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, @@ -230,10 +230,21 @@ RValue CodeGenFunction::EmitCompoundStmtWithoutScope(const CompoundStmt &S, bool EnsureInsertPoint(); - RV = EmitAnyExpr(cast(LastStmt), AggSlot); + QualType ExprTy = cast(LastStmt)->getType(); + if (hasAggregateEvaluationKind(ExprTy)) { + EmitAggExpr(cast(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(LastStmt), RetAlloca, Qualifiers(), + /*IsInit*/false); + } + } - return RV; + return RetAlloca; } void CodeGenFunction::SimplifyForwardingBlocks(llvm::BasicBlock *BB) { diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 41228fa808..81b5d05cf6 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -1767,11 +1767,12 @@ public: /// \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. diff --git a/test/CodeGenCXX/stmtexpr.cpp b/test/CodeGenCXX/stmtexpr.cpp index 1f0e4ac4bf..5d4d6bcce4 100644 --- a/test/CodeGenCXX/stmtexpr.cpp +++ b/test/CodeGenCXX/stmtexpr.cpp @@ -73,3 +73,10 @@ int* foo5() { return (({ a; })); } +// +// 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; +} diff --git a/test/CodeGenObjC/arc.m b/test/CodeGenObjC/arc.m index 7262dc8d7b..21ff43128c 100644 --- a/test/CodeGenObjC/arc.m +++ b/test/CodeGenObjC/arc.m @@ -1115,11 +1115,14 @@ id test52(void) { // 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 @@ -1130,14 +1133,17 @@ void test53(void) { // 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]])