summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2012-07-09 16:54:53 +0000
committerJordan Rose <jordan_rose@apple.com>2012-07-09 16:54:53 +0000
commit12e730c6e37e7f4c31e8007902be9e3f8fc85893 (patch)
treea0525eee37afe37bc8669ce346521842c9063d38 /clang/lib
parente04395e2f4a7a2a1e03b59cc687ac56f0854381b (diff)
downloadbcm5719-llvm-12e730c6e37e7f4c31e8007902be9e3f8fc85893.tar.gz
bcm5719-llvm-12e730c6e37e7f4c31e8007902be9e3f8fc85893.zip
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). llvm-svn: 159941
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Parse/ParseDecl.cpp26
-rw-r--r--clang/lib/Parse/Parser.cpp2
2 files changed, 23 insertions, 5 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index d91457c0d69..05d44a5af0c 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/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;
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index 07031338499..d0c988d1dbf 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -49,7 +49,7 @@ Parser::Parser(Preprocessor &pp, Sema &actions, bool SkipFunctionBodies)
: PP(pp), Actions(actions), Diags(PP.getDiagnostics()),
GreaterThanIsOperator(true), ColonIsSacred(false),
InMessageExpression(false), TemplateParameterDepth(0),
- SkipFunctionBodies(SkipFunctionBodies) {
+ ParsingInObjCContainer(false), SkipFunctionBodies(SkipFunctionBodies) {
Tok.setKind(tok::eof);
Actions.CurScope = 0;
NumCachedScopes = 0;
OpenPOWER on IntegriCloud