@@ -4121,11 +4121,13 @@ static unsigned skipUntilMatchingRBrace(Parser &P,
4121
4121
bool &HasPoundDirective,
4122
4122
bool &HasOperatorDeclarations,
4123
4123
bool &HasNestedClassDeclarations,
4124
- bool &HasNestedTypeDeclarations) {
4124
+ bool &HasNestedTypeDeclarations,
4125
+ bool &HasPotentialRegexLiteral) {
4125
4126
HasPoundDirective = false ;
4126
4127
HasOperatorDeclarations = false ;
4127
4128
HasNestedClassDeclarations = false ;
4128
4129
HasNestedTypeDeclarations = false ;
4130
+ HasPotentialRegexLiteral = false ;
4129
4131
4130
4132
unsigned OpenBraces = 1 ;
4131
4133
@@ -4148,6 +4150,18 @@ static unsigned skipUntilMatchingRBrace(Parser &P,
4148
4150
HasNestedTypeDeclarations |= P.Tok .isAny (tok::kw_class, tok::kw_struct,
4149
4151
tok::kw_enum);
4150
4152
4153
+ // HACK: Bail if we encounter what could potentially be a regex literal.
4154
+ // This is necessary as:
4155
+ // - We might encounter an invalid Swift token that might be valid in a
4156
+ // regex.
4157
+ // - Such a literal could contain a literal `}`, which should not be treated
4158
+ // as an end brace.
4159
+ // FIXME: We should be able to handle `/.../` regex literals in the lexer.
4160
+ if (P.L ->isPotentialUnskippableBareSlashRegexLiteral (P.Tok )) {
4161
+ HasPotentialRegexLiteral = true ;
4162
+ return OpenBraces;
4163
+ }
4164
+
4151
4165
if (P.consumeIf (tok::l_brace)) {
4152
4166
++OpenBraces;
4153
4167
continue ;
@@ -5456,12 +5470,14 @@ bool Parser::canDelayMemberDeclParsing(bool &HasOperatorDeclarations,
5456
5470
CancellableBacktrackingScope BackTrack (*this );
5457
5471
bool HasPoundDirective;
5458
5472
bool HasNestedTypeDeclarations;
5473
+ bool HasPotentialRegexLiteral;
5459
5474
skipUntilMatchingRBrace (*this ,
5460
5475
HasPoundDirective,
5461
5476
HasOperatorDeclarations,
5462
5477
HasNestedClassDeclarations,
5463
- HasNestedTypeDeclarations);
5464
- if (!HasPoundDirective)
5478
+ HasNestedTypeDeclarations,
5479
+ HasPotentialRegexLiteral);
5480
+ if (!HasPoundDirective && !HasPotentialRegexLiteral)
5465
5481
BackTrack.cancelBacktrack ();
5466
5482
return !BackTrack.willBacktrack ();
5467
5483
}
@@ -6137,25 +6153,31 @@ static ParameterList *parseOptionalAccessorArgument(SourceLoc SpecifierLoc,
6137
6153
return ParameterList::create (P.Context , StartLoc, param, EndLoc);
6138
6154
}
6139
6155
6140
- bool Parser::skipBracedBlock (bool &HasNestedTypeDeclarations) {
6156
+ bool Parser::canDelayFunctionBodyParsing (bool &HasNestedTypeDeclarations) {
6157
+ // If explicitly disabled, respect the flag.
6158
+ if (!isDelayedParsingEnabled () && !isCodeCompletionFirstPass ())
6159
+ return false ;
6160
+
6141
6161
SyntaxParsingContext disabled (SyntaxContext);
6142
6162
SyntaxContext->disable ();
6143
- consumeToken (tok::l_brace);
6144
6163
6145
- // We don't care if a skipped function body contained any of these, so
6146
- // just ignore them.
6164
+ // Skip until the matching right curly bracket; If it has a potential regex
6165
+ // literal, we can't skip. We don't care others, so just ignore them;
6166
+ CancellableBacktrackingScope BackTrack (*this );
6167
+ consumeToken (tok::l_brace);
6147
6168
bool HasPoundDirectives;
6148
6169
bool HasOperatorDeclarations;
6149
6170
bool HasNestedClassDeclarations;
6171
+ bool HasPotentialRegexLiteral;
6172
+ skipUntilMatchingRBrace (*this , HasPoundDirectives, HasOperatorDeclarations,
6173
+ HasNestedClassDeclarations, HasNestedTypeDeclarations,
6174
+ HasPotentialRegexLiteral);
6175
+ if (HasPotentialRegexLiteral)
6176
+ return false ;
6150
6177
6151
- unsigned OpenBraces = skipUntilMatchingRBrace (*this ,
6152
- HasPoundDirectives,
6153
- HasOperatorDeclarations,
6154
- HasNestedClassDeclarations,
6155
- HasNestedTypeDeclarations);
6156
- if (consumeIf (tok::r_brace))
6157
- --OpenBraces;
6158
- return OpenBraces != 0 ;
6178
+ BackTrack.cancelBacktrack ();
6179
+ consumeIf (tok::r_brace);
6180
+ return true ;
6159
6181
}
6160
6182
6161
6183
void Parser::skipSILUntilSwiftDecl () {
@@ -7145,30 +7167,6 @@ Parser::parseDeclVar(ParseDeclOptions Flags,
7145
7167
return makeResult (Status);
7146
7168
}
7147
7169
7148
- void Parser::consumeAbstractFunctionBody (AbstractFunctionDecl *AFD,
7149
- const DeclAttributes &Attrs) {
7150
- auto BeginParserPosition = getParserPosition ();
7151
- SourceRange BodyRange;
7152
- BodyRange.Start = Tok.getLoc ();
7153
-
7154
- // Advance the parser to the end of the block; '{' ... '}'.
7155
- bool HasNestedTypeDeclarations;
7156
- skipBracedBlock (HasNestedTypeDeclarations);
7157
-
7158
- BodyRange.End = PreviousLoc;
7159
-
7160
- AFD->setBodyDelayed (BodyRange);
7161
- AFD->setHasNestedTypeDeclarations (HasNestedTypeDeclarations);
7162
-
7163
- if (isCodeCompletionFirstPass () &&
7164
- SourceMgr.rangeContainsCodeCompletionLoc (BodyRange)) {
7165
- State->setCodeCompletionDelayedDeclState (
7166
- SourceMgr, L->getBufferID (),
7167
- CodeCompletionDelayedDeclKind::FunctionBody,
7168
- PD_Default, AFD, BodyRange, BeginParserPosition.PreviousLoc );
7169
- }
7170
- }
7171
-
7172
7170
// / Parse a 'func' declaration, returning null on error. The caller
7173
7171
// / handles this case and does recovery as appropriate.
7174
7172
// /
@@ -7481,12 +7479,41 @@ void Parser::parseAbstractFunctionBody(AbstractFunctionDecl *AFD) {
7481
7479
// If we can delay parsing this body, or this is the first pass of code
7482
7480
// completion, skip until the end. If we encounter a code completion token
7483
7481
// while skipping, we'll make a note of it.
7484
- if (isDelayedParsingEnabled () || isCodeCompletionFirstPass ()) {
7485
- consumeAbstractFunctionBody (AFD, AFD->getAttrs ());
7482
+ auto BodyPreviousLoc = PreviousLoc;
7483
+ SourceRange BodyRange (Tok.getLoc ());
7484
+ auto setCodeCompletionDelayedDeclStateIfNeeded = [&] {
7485
+ if (!isCodeCompletionFirstPass () ||
7486
+ !SourceMgr.rangeContainsCodeCompletionLoc (BodyRange)) {
7487
+ return ;
7488
+ }
7489
+ if (State->hasCodeCompletionDelayedDeclState ())
7490
+ State->takeCodeCompletionDelayedDeclState ();
7491
+ State->setCodeCompletionDelayedDeclState (
7492
+ SourceMgr, L->getBufferID (),
7493
+ CodeCompletionDelayedDeclKind::FunctionBody,
7494
+ PD_Default, AFD, BodyRange, BodyPreviousLoc);
7495
+ };
7496
+
7497
+ bool HasNestedTypeDeclarations;
7498
+ if (canDelayFunctionBodyParsing (HasNestedTypeDeclarations)) {
7499
+ BodyRange.End = PreviousLoc;
7500
+
7501
+ assert (SourceMgr.isBeforeInBuffer (BodyRange.Start , BodyRange.End ) ||
7502
+ BodyRange.Start == BodyRange.End &&
7503
+ " At least '{' should be consumed" );
7504
+
7505
+ AFD->setBodyDelayed (BodyRange);
7506
+ AFD->setHasNestedTypeDeclarations (HasNestedTypeDeclarations);
7507
+
7508
+ setCodeCompletionDelayedDeclStateIfNeeded ();
7486
7509
return ;
7487
7510
}
7488
7511
7489
7512
(void )parseAbstractFunctionBodyImpl (AFD);
7513
+ assert (BodyRange.Start == AFD->getBodySourceRange ().Start &&
7514
+ " The start of the body should be the 'l_brace' token above" );
7515
+ BodyRange = AFD->getBodySourceRange ();
7516
+ setCodeCompletionDelayedDeclStateIfNeeded ();
7490
7517
}
7491
7518
7492
7519
BodyAndFingerprint
0 commit comments