Skip to content

Commit 1418018

Browse files
authored
[clang][ObjectiveC] Fix Parsing the :: Optional Scope Specifier (llvm#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
1 parent 0550c32 commit 1418018

File tree

4 files changed

+39
-1
lines changed

4 files changed

+39
-1
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,9 @@ Improvements to Clang's diagnostics
708708
709709
- Fix -Wdangling false positives on conditional operators (#120206).
710710

711+
- Fixed a bug where Clang hung on an unsupported optional scope specifier ``::`` when parsing
712+
Objective-C. Clang now emits a diagnostic message instead of hanging.
713+
711714
Improvements to Clang's time-trace
712715
----------------------------------
713716

clang/lib/Parse/Parser.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2222,8 +2222,15 @@ bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(
22222222
}
22232223
}
22242224

2225-
if (SS.isEmpty())
2225+
if (SS.isEmpty()) {
2226+
if (getLangOpts().ObjC && !getLangOpts().CPlusPlus &&
2227+
Tok.is(tok::coloncolon)) {
2228+
// ObjectiveC does not allow :: as as a scope token.
2229+
Diag(ConsumeToken(), diag::err_expected_type);
2230+
return true;
2231+
}
22262232
return false;
2233+
}
22272234

22282235
// A C++ scope specifier that isn't followed by a typename.
22292236
AnnotateScopeToken(SS, IsNewScope);

clang/test/Parser/objc-coloncolon.m

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %clang_cc1 -x objective-c -fsyntax-only -Wno-objc-root-class -verify %s
2+
3+
int GV = 42;
4+
5+
@interface A
6+
+ (int) getGV;
7+
- (instancetype)init:(::A *) foo; // expected-error {{expected a type}}
8+
@end
9+
10+
@implementation A
11+
- (void)performSelector:(SEL)selector {}
12+
- (void)double:(int)firstArg :(int)secondArg colon:(int)thirdArg {}
13+
- (void)test {
14+
// The `::` below should not trigger an error.
15+
[self performSelector:@selector(double::colon:)];
16+
}
17+
+ (int) getGV { return ::GV; } // expected-error {{expected a type}}
18+
- (instancetype)init:(::A *) foo { return self; } // expected-error {{expected a type}}
19+
@end
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Test to make sure the parser does not get stuck on the optional
2+
// scope specifier on the type B.
3+
// RUN: %clang_cc1 -fsyntax-only %s
4+
5+
class B;
6+
7+
@interface A
8+
- (void) init:(::B *) foo;
9+
@end

0 commit comments

Comments
 (0)