diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp index d0af98b9106c3..38448a0825617 100644 --- a/clang/lib/Parse/ParseObjc.cpp +++ b/clang/lib/Parse/ParseObjc.cpp @@ -3764,6 +3764,8 @@ void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) { while (Tok.getLocation() != OrigLoc && Tok.isNot(tok::eof)) ConsumeAnyToken(); } - // Clean up the remaining EOF token. - ConsumeAnyToken(); + // Clean up the remaining EOF token, only if it's inserted by us. Otherwise + // this might be code-completion token, which must be propagated to callers. + if (Tok.is(tok::eof) && Tok.getEofData() == MCDecl) + ConsumeAnyToken(); } diff --git a/clang/test/Parser/objc-delayed-method-use-after-free.m b/clang/test/Parser/objc-delayed-method-use-after-free.m new file mode 100644 index 0000000000000..83927b2c70517 --- /dev/null +++ b/clang/test/Parser/objc-delayed-method-use-after-free.m @@ -0,0 +1,13 @@ +// Make sure we don't trigger use-after-free when we encounter a code completion +// token inside a objc method. +@interface Foo +@end + +@implementation Foo +- (void)foo { + +// RUN: %clang_cc1 -fsyntax-only -Wno-objc-root-class -code-completion-at=%s:%(line-1):1 %s | FileCheck %s +// CHECK: COMPLETION: self : [#Foo *#]self + [self foo]; +} +@end