diff options
author | Jordan Rose <jordan_rose@apple.com> | 2012-07-09 16:54:53 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2012-07-09 16:54:53 +0000 |
commit | 94f29f4bf5d6b49dd1b7fc16cfa1521adc0c71c0 (patch) | |
tree | 2ace396d6886f3b5b0f6611c21e625c763a78770 /lib/Parse/ParseDecl.cpp | |
parent | ee158bc29bc12ce544996f7cdfde14aba63acf4d (diff) |
Better parser recovery in Objective-C containers.
Previously it was possible to get an infinite-loop-on-invalid with a namespace
decl within @interface. Since 'namespace' is normally a safe place to retry
top-level parsing, we just didn't consume the token.
This adds a flag that tracks whether we have temporarily left Objective-C
scope to parse a C-like declaration, and uses that to better recover from
parse problems by stopping at possible method declarations and at @end. To
fix the original problem, we do /not/ stop at 'namespace' when in an
Objective-C @interface or @protocol context (but still do in @implementation).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@159941 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse/ParseDecl.cpp')
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index d91457c0d6..05d44a5af0 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -1270,15 +1270,33 @@ void Parser::SkipMalformedDecl() { case tok::kw_inline: // 'inline namespace' at the start of a line is almost certainly - // a good place to pick back up parsing. - if (Tok.isAtStartOfLine() && NextToken().is(tok::kw_namespace)) + // a good place to pick back up parsing, except in an Objective-C + // @interface context. + if (Tok.isAtStartOfLine() && NextToken().is(tok::kw_namespace) && + (!ParsingInObjCContainer || CurParsedObjCImpl)) return; break; case tok::kw_namespace: // 'namespace' at the start of a line is almost certainly a good - // place to pick back up parsing. - if (Tok.isAtStartOfLine()) + // place to pick back up parsing, except in an Objective-C + // @interface context. + if (Tok.isAtStartOfLine() && + (!ParsingInObjCContainer || CurParsedObjCImpl)) + return; + break; + + case tok::at: + // @end is very much like } in Objective-C contexts. + if (NextToken().isObjCAtKeyword(tok::objc_end) && + ParsingInObjCContainer) + return; + break; + + case tok::minus: + case tok::plus: + // - and + probably start new method declarations in Objective-C contexts. + if (Tok.isAtStartOfLine() && ParsingInObjCContainer) return; break; |