Author: Qiongsi Wu Date: 2024-12-20T09:47:26-08:00 New Revision: 14180185026b8ed793cc7dfd037620e5150ccc35
URL: https://github.com/llvm/llvm-project/commit/14180185026b8ed793cc7dfd037620e5150ccc35 DIFF: https://github.com/llvm/llvm-project/commit/14180185026b8ed793cc7dfd037620e5150ccc35.diff LOG: [clang][ObjectiveC] Fix Parsing the `::` Optional Scope Specifier (#119908) The parser hangs when processing types/variables prefixed by `::` as an optional scope specifier. For example, ``` - (instancetype)init:(::A *) foo; ``` The parser should not hang, and it should emit an error. This PR implements the error check. rdar://140885078 Added: clang/test/Parser/objc-coloncolon.m clang/test/Parser/objcxx-coloncolon.mm Modified: clang/docs/ReleaseNotes.rst clang/lib/Parse/Parser.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index a85ef60b7b58ba..38c35aea3cf220 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -708,6 +708,9 @@ Improvements to Clang's diagnostics - Fix -Wdangling false positives on conditional operators (#120206). +- Fixed a bug where Clang hung on an unsupported optional scope specifier ``::`` when parsing + Objective-C. Clang now emits a diagnostic message instead of hanging. + Improvements to Clang's time-trace ---------------------------------- diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 36e56a92c3092e..8ba6a5dce8a994 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -2222,8 +2222,15 @@ bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec( } } - if (SS.isEmpty()) + if (SS.isEmpty()) { + if (getLangOpts().ObjC && !getLangOpts().CPlusPlus && + Tok.is(tok::coloncolon)) { + // ObjectiveC does not allow :: as as a scope token. + Diag(ConsumeToken(), diag::err_expected_type); + return true; + } return false; + } // A C++ scope specifier that isn't followed by a typename. AnnotateScopeToken(SS, IsNewScope); diff --git a/clang/test/Parser/objc-coloncolon.m b/clang/test/Parser/objc-coloncolon.m new file mode 100644 index 00000000000000..04a24fd81ec08f --- /dev/null +++ b/clang/test/Parser/objc-coloncolon.m @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -x objective-c -fsyntax-only -Wno-objc-root-class -verify %s + +int GV = 42; + +@interface A ++ (int) getGV; +- (instancetype)init:(::A *) foo; // expected-error {{expected a type}} +@end + +@implementation A +- (void)performSelector:(SEL)selector {} +- (void)double:(int)firstArg :(int)secondArg colon:(int)thirdArg {} +- (void)test { + // The `::` below should not trigger an error. + [self performSelector:@selector(double::colon:)]; +} ++ (int) getGV { return ::GV; } // expected-error {{expected a type}} +- (instancetype)init:(::A *) foo { return self; } // expected-error {{expected a type}} +@end diff --git a/clang/test/Parser/objcxx-coloncolon.mm b/clang/test/Parser/objcxx-coloncolon.mm new file mode 100644 index 00000000000000..864a7df8400c1c --- /dev/null +++ b/clang/test/Parser/objcxx-coloncolon.mm @@ -0,0 +1,9 @@ +// Test to make sure the parser does not get stuck on the optional +// scope specifier on the type B. +// RUN: %clang_cc1 -fsyntax-only %s + +class B; + +@interface A +- (void) init:(::B *) foo; +@end _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits