summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/Parse/ParseObjc.cpp12
-rw-r--r--clang/test/Parser/objc-at-implementation-eof-crash.m21
-rw-r--r--clang/test/Parser/objc-at-interface-eof-crash.m21
3 files changed, 53 insertions, 1 deletions
diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp
index 77e63efc065..caa6323d320 100644
--- a/clang/lib/Parse/ParseObjc.cpp
+++ b/clang/lib/Parse/ParseObjc.cpp
@@ -3627,6 +3627,14 @@ void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) {
SourceLocation OrigLoc = Tok.getLocation();
assert(!LM.Toks.empty() && "ParseLexedObjCMethodDef - Empty body!");
+ // Store an artificial EOF token to ensure that we don't run off the end of
+ // the method's body when we come to parse it.
+ Token Eof;
+ Eof.startToken();
+ Eof.setKind(tok::eof);
+ Eof.setEofData(MCDecl);
+ Eof.setLocation(OrigLoc);
+ LM.Toks.push_back(Eof);
// Append the current token at the end of the new token stream so that it
// doesn't get lost.
LM.Toks.push_back(Tok);
@@ -3658,7 +3666,7 @@ void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) {
Actions.ActOnDefaultCtorInitializers(MCDecl);
ParseFunctionStatementBody(MCDecl, BodyScope);
}
-
+
if (Tok.getLocation() != OrigLoc) {
// Due to parsing error, we either went over the cached tokens or
// there are still cached tokens left. If it's the latter case skip the
@@ -3670,4 +3678,6 @@ void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) {
while (Tok.getLocation() != OrigLoc && Tok.isNot(tok::eof))
ConsumeAnyToken();
}
+ // Clean up the remaining EOF token.
+ ConsumeAnyToken();
}
diff --git a/clang/test/Parser/objc-at-implementation-eof-crash.m b/clang/test/Parser/objc-at-implementation-eof-crash.m
new file mode 100644
index 00000000000..01469ecb119
--- /dev/null
+++ b/clang/test/Parser/objc-at-implementation-eof-crash.m
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -verify -Wno-objc-root-class %s
+
+@interface ClassA
+
+- (void)fileExistsAtPath:(int)x;
+
+@end
+
+@interface ClassB
+
+@end
+
+@implementation ClassB // expected-note {{implementation started here}}
+
+- (void) method:(ClassA *)mgr { // expected-note {{to match this '{'}}
+ mgr fileExistsAtPath:0
+} // expected-error {{expected ']'}}
+
+@implementation ClassC // expected-error {{missing '@end'}} // expected-error {{expected '}'}} // expected-warning {{cannot find interface declaration for 'ClassC'}}
+
+@end
diff --git a/clang/test/Parser/objc-at-interface-eof-crash.m b/clang/test/Parser/objc-at-interface-eof-crash.m
new file mode 100644
index 00000000000..7776838c9eb
--- /dev/null
+++ b/clang/test/Parser/objc-at-interface-eof-crash.m
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -verify -Wno-objc-root-class %s
+
+@interface ClassA
+
+- (void)fileExistsAtPath:(int)x;
+
+@end
+
+@interface ClassB
+
+@end
+
+@implementation ClassB // expected-note {{implementation started here}}
+
+- (void) method:(ClassA *)mgr { // expected-note {{to match this '{'}}
+ mgr fileExistsAtPath:0
+} // expected-error {{expected ']'}}
+
+@interface ClassC // expected-error {{missing '@end'}} // expected-error {{expected '}'}}
+
+@end
OpenPOWER on IntegriCloud