mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-14 03:29:57 +00:00
Make sure we don't emit invalid IR for StmtExprs with complex cleanups.
Fixes <rdar://problem/14074868>. llvm-svn: 183699
This commit is contained in:
parent
8c47bb1a02
commit
4871a46cc3
@ -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.
|
||||
|
@ -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()));
|
||||
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -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<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) {
|
||||
|
@ -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.
|
||||
|
@ -73,3 +73,10 @@ int* foo5() {
|
||||
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;
|
||||
}
|
||||
|
@ -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]])
|
||||
|
Loading…
Reference in New Issue
Block a user