зеркало из https://github.com/microsoft/clang-1.git
Gather cleanups correctly in block return statements.
Thanks to Ted for finding this with magic tools. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@137877 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
6704429557
Коммит
d963c37eb9
|
@ -1741,21 +1741,17 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
|
|||
// pickier with blocks than for normal functions because we don't have GCC
|
||||
// compatibility to worry about here.
|
||||
ReturnStmt *Result = 0;
|
||||
const VarDecl *NRVOCandidate = 0;
|
||||
if (CurBlock->ReturnType->isVoidType()) {
|
||||
if (RetValExp && !RetValExp->isTypeDependent() &&
|
||||
(!getLangOptions().CPlusPlus || !RetValExp->getType()->isVoidType())) {
|
||||
Diag(ReturnLoc, diag::err_return_block_has_expr);
|
||||
RetValExp = 0;
|
||||
}
|
||||
Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, 0);
|
||||
} else if (!RetValExp) {
|
||||
if (!CurBlock->ReturnType->isDependentType())
|
||||
return StmtError(Diag(ReturnLoc, diag::err_block_return_missing_expr));
|
||||
|
||||
Result = new (Context) ReturnStmt(ReturnLoc, 0, 0);
|
||||
} else {
|
||||
const VarDecl *NRVOCandidate = 0;
|
||||
|
||||
if (!FnRetType->isDependentType() && !RetValExp->isTypeDependent()) {
|
||||
// we have a non-void block with an expression, continue checking
|
||||
|
||||
|
@ -1775,20 +1771,19 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
|
|||
// FIXME: Cleanup temporaries here, anyway?
|
||||
return StmtError();
|
||||
}
|
||||
RetValExp = Res.take();
|
||||
|
||||
if (RetValExp) {
|
||||
CheckImplicitConversions(RetValExp, ReturnLoc);
|
||||
RetValExp = MaybeCreateExprWithCleanups(RetValExp);
|
||||
}
|
||||
|
||||
RetValExp = Res.takeAs<Expr>();
|
||||
if (RetValExp)
|
||||
CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc);
|
||||
}
|
||||
|
||||
Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, NRVOCandidate);
|
||||
}
|
||||
|
||||
if (RetValExp) {
|
||||
CheckImplicitConversions(RetValExp, ReturnLoc);
|
||||
RetValExp = MaybeCreateExprWithCleanups(RetValExp);
|
||||
}
|
||||
Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, NRVOCandidate);
|
||||
|
||||
// If we need to check for the named return value optimization, save the
|
||||
// return statement in our scope for later processing.
|
||||
if (getLangOptions().CPlusPlus && FnRetType->isRecordType() &&
|
||||
|
|
|
@ -104,3 +104,29 @@ namespace test3 {
|
|||
consume(^{ (void) b; });
|
||||
}
|
||||
}
|
||||
|
||||
// rdar://problem/9971485
|
||||
namespace test4 {
|
||||
struct A {
|
||||
A();
|
||||
~A();
|
||||
};
|
||||
|
||||
void foo(A a);
|
||||
|
||||
void test() {
|
||||
extern void consume(void(^)());
|
||||
consume(^{ return foo(A()); });
|
||||
}
|
||||
// CHECK: define void @_ZN5test44testEv()
|
||||
// CHECK: define internal void @__test_block_invoke
|
||||
// CHECK: [[TMP:%.*]] = alloca [[A:%.*]], align 1
|
||||
// CHECK-NEXT: alloca i32
|
||||
// CHECK-NEXT: bitcast i8*
|
||||
// CHECK-NEXT: call void @_ZN5test41AC1Ev([[A]]* [[TMP]])
|
||||
// CHECK-NEXT: call void @_ZN5test43fooENS_1AE([[A]]* [[TMP]])
|
||||
// CHECK-NEXT: store i32 1,
|
||||
// CHECK-NEXT: call void @_ZN5test41AD1Ev([[A]]* [[TMP]])
|
||||
// CHECK-NEXT: ret void
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче