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