forked from OSchip/llvm-project
Bug fix, make sure to initialize exception object (to rethrow) even
when there are no @catch blocks. Also, eliminated unneeded alloca for the rethrow object. Also, avoid generating code to rethrow exception if the exception will trivially always be caught. llvm-svn: 56751
This commit is contained in:
parent
da04d7f4ec
commit
b22ff59750
|
@ -1422,19 +1422,17 @@ void CGObjCMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
|
||||||
|
|
||||||
// Emit the "exception in @try" block.
|
// Emit the "exception in @try" block.
|
||||||
CGF.EmitBlock(ExceptionInTryBlock);
|
CGF.EmitBlock(ExceptionInTryBlock);
|
||||||
|
|
||||||
if (const ObjCAtCatchStmt* CatchStmt = S.getCatchStmts()) {
|
// Retrieve the exception object. We may emit multiple blocks but
|
||||||
// Allocate memory for the caught exception and extract it from the
|
// nothing can cross this so the value is already in SSA form.
|
||||||
// exception data.
|
llvm::Value *Caught = CGF.Builder.CreateCall(ObjCTypes.ExceptionExtractFn,
|
||||||
llvm::Value *CaughtPtr = CGF.CreateTempAlloca(ObjCTypes.ObjectPtrTy);
|
ExceptionData,
|
||||||
llvm::Value *Extract = CGF.Builder.CreateCall(ObjCTypes.ExceptionExtractFn,
|
"caught");
|
||||||
ExceptionData);
|
if (const ObjCAtCatchStmt* CatchStmt = S.getCatchStmts()) {
|
||||||
CGF.Builder.CreateStore(Extract, CaughtPtr);
|
// Enter a new exception try block (in case a @catch block throws
|
||||||
|
// an exception).
|
||||||
// Enter a new exception try block
|
|
||||||
// (in case a @catch block throws an exception).
|
|
||||||
CGF.Builder.CreateCall(ObjCTypes.ExceptionTryEnterFn, ExceptionData);
|
CGF.Builder.CreateCall(ObjCTypes.ExceptionTryEnterFn, ExceptionData);
|
||||||
|
|
||||||
llvm::Value *SetJmpResult = CGF.Builder.CreateCall(ObjCTypes.SetJmpFn,
|
llvm::Value *SetJmpResult = CGF.Builder.CreateCall(ObjCTypes.SetJmpFn,
|
||||||
JmpBufPtr, "result");
|
JmpBufPtr, "result");
|
||||||
|
|
||||||
|
@ -1450,29 +1448,31 @@ void CGObjCMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
|
||||||
|
|
||||||
CGF.EmitBlock(CatchBlock);
|
CGF.EmitBlock(CatchBlock);
|
||||||
|
|
||||||
// Handle catch list
|
// Handle catch list. As a special case we check if everything is
|
||||||
|
// matched and avoid generating code for falling off the end if
|
||||||
|
// so.
|
||||||
|
bool AllMatched = false;
|
||||||
for (; CatchStmt; CatchStmt = CatchStmt->getNextCatchStmt()) {
|
for (; CatchStmt; CatchStmt = CatchStmt->getNextCatchStmt()) {
|
||||||
llvm::BasicBlock *NextCatchBlock = llvm::BasicBlock::Create("nextcatch");
|
llvm::BasicBlock *NextCatchBlock = llvm::BasicBlock::Create("nextcatch");
|
||||||
llvm::Value *Caught = CGF.Builder.CreateLoad(CaughtPtr, "caught");
|
|
||||||
|
|
||||||
QualType T;
|
QualType T;
|
||||||
bool MatchesAll = false;
|
|
||||||
const DeclStmt *CatchParam =
|
const DeclStmt *CatchParam =
|
||||||
cast_or_null<DeclStmt>(CatchStmt->getCatchParamStmt());
|
cast_or_null<DeclStmt>(CatchStmt->getCatchParamStmt());
|
||||||
|
const ValueDecl *VD = 0;
|
||||||
|
|
||||||
// catch(...) always matches.
|
// catch(...) always matches.
|
||||||
if (!CatchParam)
|
if (!CatchParam) {
|
||||||
MatchesAll = true;
|
AllMatched = true;
|
||||||
else {
|
} else {
|
||||||
QualType PT = cast<ValueDecl>(CatchParam->getDecl())->getType();
|
VD = cast<ValueDecl>(CatchParam->getDecl());
|
||||||
T = PT->getAsPointerType()->getPointeeType();
|
|
||||||
|
|
||||||
// catch(id e) always matches.
|
// catch(id e) always matches.
|
||||||
if (CGF.getContext().isObjCIdType(T))
|
const PointerType *PT = VD->getType()->getAsPointerType();
|
||||||
MatchesAll = true;
|
if (PT && CGF.getContext().isObjCIdType(PT->getPointeeType()))
|
||||||
|
AllMatched = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MatchesAll) {
|
if (AllMatched) {
|
||||||
if (CatchParam) {
|
if (CatchParam) {
|
||||||
CGF.EmitStmt(CatchParam);
|
CGF.EmitStmt(CatchParam);
|
||||||
|
|
||||||
|
@ -1485,7 +1485,6 @@ void CGObjCMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
|
||||||
|
|
||||||
CGF.EmitStmt(CatchStmt->getCatchBody());
|
CGF.EmitStmt(CatchStmt->getCatchBody());
|
||||||
CGF.Builder.CreateBr(FinallyBlock);
|
CGF.Builder.CreateBr(FinallyBlock);
|
||||||
CGF.EmitBlock(NextCatchBlock);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1523,20 +1522,21 @@ void CGObjCMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
|
||||||
CGF.EmitBlock(NextCatchBlock);
|
CGF.EmitBlock(NextCatchBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
// None of the handlers caught the exception, so store it and rethrow
|
if (!AllMatched) {
|
||||||
// it later.
|
// None of the handlers caught the exception, so store it to be
|
||||||
llvm::Value *Caught = CGF.Builder.CreateLoad(CaughtPtr, "caught");
|
// rethrown at the end of the @finally block.
|
||||||
|
CGF.Builder.CreateStore(Caught, RethrowPtr);
|
||||||
|
CGF.Builder.CreateCall(ObjCTypes.ExceptionTryExitFn, ExceptionData);
|
||||||
|
CGF.Builder.CreateBr(FinallyBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit the exception handler for the @catch blocks.
|
||||||
|
CGF.EmitBlock(ExceptionInCatchBlock);
|
||||||
|
CGF.Builder.CreateStore(CGF.Builder.CreateCall(ObjCTypes.ExceptionExtractFn,
|
||||||
|
ExceptionData),
|
||||||
|
RethrowPtr);
|
||||||
|
} else {
|
||||||
CGF.Builder.CreateStore(Caught, RethrowPtr);
|
CGF.Builder.CreateStore(Caught, RethrowPtr);
|
||||||
CGF.Builder.CreateCall(ObjCTypes.ExceptionTryExitFn,
|
|
||||||
ExceptionData);
|
|
||||||
|
|
||||||
CGF.Builder.CreateBr(FinallyBlock);
|
|
||||||
|
|
||||||
CGF.EmitBlock(ExceptionInCatchBlock);
|
|
||||||
|
|
||||||
Extract = CGF.Builder.CreateCall(ObjCTypes.ExceptionExtractFn,
|
|
||||||
ExceptionData);
|
|
||||||
CGF.Builder.CreateStore(Extract, RethrowPtr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit the @finally block.
|
// Emit the @finally block.
|
||||||
|
|
Loading…
Reference in New Issue