@@ -4121,11 +4121,13 @@ static unsigned skipUntilMatchingRBrace(Parser &P,
41214121 bool &HasPoundDirective,
41224122 bool &HasOperatorDeclarations,
41234123 bool &HasNestedClassDeclarations,
4124- bool &HasNestedTypeDeclarations) {
4124+ bool &HasNestedTypeDeclarations,
4125+ bool &HasPotentialRegexLiteral) {
41254126 HasPoundDirective = false ;
41264127 HasOperatorDeclarations = false ;
41274128 HasNestedClassDeclarations = false ;
41284129 HasNestedTypeDeclarations = false ;
4130+ HasPotentialRegexLiteral = false ;
41294131
41304132 unsigned OpenBraces = 1 ;
41314133
@@ -4148,6 +4150,18 @@ static unsigned skipUntilMatchingRBrace(Parser &P,
41484150 HasNestedTypeDeclarations |= P.Tok .isAny (tok::kw_class, tok::kw_struct,
41494151 tok::kw_enum);
41504152
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+
41514165 if (P.consumeIf (tok::l_brace)) {
41524166 ++OpenBraces;
41534167 continue ;
@@ -5456,12 +5470,14 @@ bool Parser::canDelayMemberDeclParsing(bool &HasOperatorDeclarations,
54565470 CancellableBacktrackingScope BackTrack (*this );
54575471 bool HasPoundDirective;
54585472 bool HasNestedTypeDeclarations;
5473+ bool HasPotentialRegexLiteral;
54595474 skipUntilMatchingRBrace (*this ,
54605475 HasPoundDirective,
54615476 HasOperatorDeclarations,
54625477 HasNestedClassDeclarations,
5463- HasNestedTypeDeclarations);
5464- if (!HasPoundDirective)
5478+ HasNestedTypeDeclarations,
5479+ HasPotentialRegexLiteral);
5480+ if (!HasPoundDirective && !HasPotentialRegexLiteral)
54655481 BackTrack.cancelBacktrack ();
54665482 return !BackTrack.willBacktrack ();
54675483}
@@ -6137,25 +6153,31 @@ static ParameterList *parseOptionalAccessorArgument(SourceLoc SpecifierLoc,
61376153 return ParameterList::create (P.Context , StartLoc, param, EndLoc);
61386154}
61396155
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+
61416161 SyntaxParsingContext disabled (SyntaxContext);
61426162 SyntaxContext->disable ();
6143- consumeToken (tok::l_brace);
61446163
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);
61476168 bool HasPoundDirectives;
61486169 bool HasOperatorDeclarations;
61496170 bool HasNestedClassDeclarations;
6171+ bool HasPotentialRegexLiteral;
6172+ skipUntilMatchingRBrace (*this , HasPoundDirectives, HasOperatorDeclarations,
6173+ HasNestedClassDeclarations, HasNestedTypeDeclarations,
6174+ HasPotentialRegexLiteral);
6175+ if (HasPotentialRegexLiteral)
6176+ return false ;
61506177
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 ;
61596181}
61606182
61616183void Parser::skipSILUntilSwiftDecl () {
@@ -7145,30 +7167,6 @@ Parser::parseDeclVar(ParseDeclOptions Flags,
71457167 return makeResult (Status);
71467168}
71477169
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-
71727170// / Parse a 'func' declaration, returning null on error. The caller
71737171// / handles this case and does recovery as appropriate.
71747172// /
@@ -7481,12 +7479,41 @@ void Parser::parseAbstractFunctionBody(AbstractFunctionDecl *AFD) {
74817479 // If we can delay parsing this body, or this is the first pass of code
74827480 // completion, skip until the end. If we encounter a code completion token
74837481 // 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 ();
74867509 return ;
74877510 }
74887511
74897512 (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 ();
74907517}
74917518
74927519BodyAndFingerprint
0 commit comments