diff options
-rw-r--r-- | clang/lib/Parse/ParseObjc.cpp | 7 | ||||
-rw-r--r-- | clang/test/Parser/objc-at-directive-fixit.m | 28 |
2 files changed, 34 insertions, 1 deletions
diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp index 42081a29ad9..81761bf8d2d 100644 --- a/clang/lib/Parse/ParseObjc.cpp +++ b/clang/lib/Parse/ParseObjc.cpp @@ -2773,6 +2773,7 @@ StmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) { return Actions.ActOnNullStmt(Tok.getLocation()); } + ExprStatementTokLoc = AtLoc; ExprResult Res(ParseExpressionWithLeadingAt(AtLoc)); if (Res.isInvalid()) { // If the expression is invalid, skip ahead to the next semicolon. Not @@ -2869,7 +2870,11 @@ ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) { return ParseAvailabilityCheckExpr(AtLoc); default: { const char *str = nullptr; - if (GetLookAheadToken(1).is(tok::l_brace)) { + // Only provide the @try/@finally/@autoreleasepool fixit when we're sure + // that this is a proper statement where such directives could actually + // occur. + if (GetLookAheadToken(1).is(tok::l_brace) && + ExprStatementTokLoc == AtLoc) { char ch = Tok.getIdentifierInfo()->getNameStart()[0]; str = ch == 't' ? "try" diff --git a/clang/test/Parser/objc-at-directive-fixit.m b/clang/test/Parser/objc-at-directive-fixit.m new file mode 100644 index 00000000000..dcf695d3aaa --- /dev/null +++ b/clang/test/Parser/objc-at-directive-fixit.m @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -triple x86_64-apple-macosx10.10.0 -verify -fobjc-exceptions %s +// RUN: not %clang_cc1 -fsyntax-only -triple x86_64-apple-macosx10.10.0 -fdiagnostics-parseable-fixits -fobjc-exceptions %s 2>&1 | FileCheck %s + +// rdar://19669565 + +void bar(int x); + +void f() { + @try { } + @finally { } + @autoreleasepool { } + + // Provide a fixit when we are parsing a standalone statement + @tr { }; // expected-error {{unexpected '@' in program}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:4-[[@LINE-1]]:6}:"try" + @finaly { }; // expected-error {{unexpected '@' in program}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:4-[[@LINE-1]]:10}:"finally" + @autorelpool { }; // expected-error {{unexpected '@' in program}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:4-[[@LINE-1]]:15}:"autoreleasepool" + + // Ensure that no fixit is given when parsing expressions + // CHECK-NOT: fix-it + id thing = @autoreleasepool { }; // expected-error {{unexpected '@' in program}} + (void)@tr { }; // expected-error {{unexpected '@' in program}} + bar(@final { }); // expected-error {{unexpected '@' in program}} + for(@auto;;) { } // expected-error {{unexpected '@' in program}} + [@try]; // expected-error {{unexpected '@' in program}} +} |