arphaman created this revision. This patch fixes a Clang crash that happens when an Objective-C source code contains an `@interface`/`@implementation` declaration that follows unterminated `@implementation` declaration that contains a method with a message send that doesn't have the ']'. The crash happens because the `@interface`/`@implementation` parsing methods encounter an unexpected EOF that is caused by parser's attempt to recover from the missing ']' by skipping to the next ']'/';' (it reaches EOF instead since these tokens are not present).
Repository: rL LLVM https://reviews.llvm.org/D34185 Files: lib/Parse/ParseObjc.cpp test/Parser/objc-at-implementation-eof-crash.m test/Parser/objc-at-interface-eof-crash.m Index: test/Parser/objc-at-interface-eof-crash.m =================================================================== --- /dev/null +++ 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'}} + +@end // expected-error {{expected '}'}} Index: test/Parser/objc-at-implementation-eof-crash.m =================================================================== --- /dev/null +++ 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'}} + +@end // expected-error {{expected '}'}} Index: lib/Parse/ParseObjc.cpp =================================================================== --- lib/Parse/ParseObjc.cpp +++ lib/Parse/ParseObjc.cpp @@ -217,6 +217,8 @@ assert(Tok.isObjCAtKeyword(tok::objc_interface) && "ParseObjCAtInterfaceDeclaration(): Expected @interface"); CheckNestedObjCContexts(AtLoc); + if (isEofOrEom()) + return nullptr; ConsumeToken(); // the "interface" identifier // Code completion after '@interface'. @@ -2101,6 +2103,8 @@ assert(Tok.isObjCAtKeyword(tok::objc_implementation) && "ParseObjCAtImplementationDeclaration(): Expected @implementation"); CheckNestedObjCContexts(AtLoc); + if (isEofOrEom()) + return nullptr; ConsumeToken(); // the "implementation" identifier // Code completion after '@implementation'.
Index: test/Parser/objc-at-interface-eof-crash.m =================================================================== --- /dev/null +++ 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'}} + +@end // expected-error {{expected '}'}} Index: test/Parser/objc-at-implementation-eof-crash.m =================================================================== --- /dev/null +++ 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'}} + +@end // expected-error {{expected '}'}} Index: lib/Parse/ParseObjc.cpp =================================================================== --- lib/Parse/ParseObjc.cpp +++ lib/Parse/ParseObjc.cpp @@ -217,6 +217,8 @@ assert(Tok.isObjCAtKeyword(tok::objc_interface) && "ParseObjCAtInterfaceDeclaration(): Expected @interface"); CheckNestedObjCContexts(AtLoc); + if (isEofOrEom()) + return nullptr; ConsumeToken(); // the "interface" identifier // Code completion after '@interface'. @@ -2101,6 +2103,8 @@ assert(Tok.isObjCAtKeyword(tok::objc_implementation) && "ParseObjCAtImplementationDeclaration(): Expected @implementation"); CheckNestedObjCContexts(AtLoc); + if (isEofOrEom()) + return nullptr; ConsumeToken(); // the "implementation" identifier // Code completion after '@implementation'.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits