diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index 42081a29ad9723dcc7e0495316714081b312ac04..81761bf8d2d89535399793a61527db34d750e5c5 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/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/test/Parser/objc-at-directive-fixit.m b/test/Parser/objc-at-directive-fixit.m new file mode 100644 index 0000000000000000000000000000000000000000..dcf695d3aaa262bb3a9d0defa1184d285f7396dc --- /dev/null +++ b/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}} +}