forked from OSchip/llvm-project
Fixed <rdar://problem/6213808> clang ObjC rewriter: @finally is not always executed
llvm-svn: 60593
This commit is contained in:
parent
994faaf218
commit
6d6da255fb
|
@ -41,6 +41,7 @@ namespace {
|
||||||
Diagnostic &Diags;
|
Diagnostic &Diags;
|
||||||
const LangOptions &LangOpts;
|
const LangOptions &LangOpts;
|
||||||
unsigned RewriteFailedDiag;
|
unsigned RewriteFailedDiag;
|
||||||
|
unsigned TryFinallyContainsReturnDiag;
|
||||||
|
|
||||||
ASTContext *Context;
|
ASTContext *Context;
|
||||||
SourceManager *SM;
|
SourceManager *SM;
|
||||||
|
@ -216,6 +217,7 @@ namespace {
|
||||||
Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
|
Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
|
||||||
Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp);
|
Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp);
|
||||||
Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp);
|
Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp);
|
||||||
|
void WarnAboutReturnGotoContinueOrBreakStmts(Stmt *S);
|
||||||
Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S);
|
Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S);
|
||||||
Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S);
|
Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S);
|
||||||
Stmt *RewriteObjCCatchStmt(ObjCAtCatchStmt *S);
|
Stmt *RewriteObjCCatchStmt(ObjCAtCatchStmt *S);
|
||||||
|
@ -368,6 +370,8 @@ RewriteObjC::RewriteObjC(std::string inFile, std::string outFile,
|
||||||
OutFileName = outFile;
|
OutFileName = outFile;
|
||||||
RewriteFailedDiag = Diags.getCustomDiagID(Diagnostic::Warning,
|
RewriteFailedDiag = Diags.getCustomDiagID(Diagnostic::Warning,
|
||||||
"rewriting sub-expression within a macro (may not be correct)");
|
"rewriting sub-expression within a macro (may not be correct)");
|
||||||
|
TryFinallyContainsReturnDiag = Diags.getCustomDiagID(Diagnostic::Warning,
|
||||||
|
"rewriter doesn't support user-specified control flow semantics for @try/@finally (code may not execute properly)");
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTConsumer *clang::CreateCodeRewriterTest(const std::string& InFile,
|
ASTConsumer *clang::CreateCodeRewriterTest(const std::string& InFile,
|
||||||
|
@ -1420,6 +1424,21 @@ Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RewriteObjC::WarnAboutReturnGotoContinueOrBreakStmts(Stmt *S) {
|
||||||
|
// Perform a bottom up traversal of all children.
|
||||||
|
for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
|
||||||
|
CI != E; ++CI)
|
||||||
|
if (*CI)
|
||||||
|
WarnAboutReturnGotoContinueOrBreakStmts(*CI);
|
||||||
|
|
||||||
|
if (isa<ReturnStmt>(S) || isa<ContinueStmt>(S) ||
|
||||||
|
isa<BreakStmt>(S) || isa<GotoStmt>(S)) {
|
||||||
|
Diags.Report(Context->getFullLoc(S->getLocStart()),
|
||||||
|
TryFinallyContainsReturnDiag);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
|
Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
|
||||||
// Get the start location and compute the semi location.
|
// Get the start location and compute the semi location.
|
||||||
SourceLocation startLoc = S->getLocStart();
|
SourceLocation startLoc = S->getLocStart();
|
||||||
|
@ -1570,6 +1589,9 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
|
||||||
|
|
||||||
// Set lastCurlyLoc
|
// Set lastCurlyLoc
|
||||||
lastCurlyLoc = body->getLocEnd();
|
lastCurlyLoc = body->getLocEnd();
|
||||||
|
|
||||||
|
// Now check for any return/continue/go statements within the @try.
|
||||||
|
WarnAboutReturnGotoContinueOrBreakStmts(S->getTryBody());
|
||||||
} else { /* no finally clause - make sure we synthesize an implicit one */
|
} else { /* no finally clause - make sure we synthesize an implicit one */
|
||||||
buf = "{ /* implicit finally clause */\n";
|
buf = "{ /* implicit finally clause */\n";
|
||||||
buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n";
|
buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n";
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
// RUN: clang -rewrite-objc -verify %s -o -
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
@try {
|
||||||
|
printf("executing try");
|
||||||
|
return(0); // expected-warning{{rewriter doesn't support user-specified control flow semantics for @try/@finally (code may not execute properly)}}
|
||||||
|
} @finally {
|
||||||
|
printf("executing finally");
|
||||||
|
}
|
||||||
|
while (1) {
|
||||||
|
@try {
|
||||||
|
printf("executing try");
|
||||||
|
break; // expected-warning{{rewriter doesn't support user-specified control flow semantics for @try/@finally (code may not execute properly)}}
|
||||||
|
} @finally {
|
||||||
|
printf("executing finally");
|
||||||
|
}
|
||||||
|
printf("executing after finally block");
|
||||||
|
}
|
||||||
|
@try {
|
||||||
|
printf("executing try");
|
||||||
|
} @finally {
|
||||||
|
printf("executing finally");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue