Skip to content

Commit 3d89295

Browse files
Merge pull request swiftlang#69796 from sophiapoirier/nonisolated-unsafe-globals-corrected
corrected implementation of parsing nonisolated(unsafe) as decl contextual keyword in top-level global scope
2 parents b399173 + f65b157 commit 3d89295

File tree

1 file changed

+37
-27
lines changed

1 file changed

+37
-27
lines changed

lib/Parse/ParseDecl.cpp

Lines changed: 37 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#include "llvm/Support/Path.h"
4545
#include "llvm/Support/SaveAndRestore.h"
4646
#include <algorithm>
47+
#include <initializer_list>
4748

4849
using namespace swift;
4950

@@ -5376,18 +5377,34 @@ bool swift::isKeywordPossibleDeclStart(const LangOptions &options,
53765377
}
53775378
}
53785379

5379-
/// Given a current token of 'unowned', check to see if it is followed by a
5380-
/// "(safe)" or "(unsafe)" specifier.
5381-
static bool isParenthesizedUnowned(Parser &P) {
5382-
assert(P.Tok.getText() == "unowned" && P.peekToken().is(tok::l_paren) &&
5380+
static bool
5381+
isParenthesizedModifier(Parser &P, StringRef name,
5382+
std::initializer_list<StringRef> allowedArguments) {
5383+
assert((P.Tok.getText() == name) && P.peekToken().is(tok::l_paren) &&
53835384
"Invariant violated");
5384-
5385+
53855386
// Look ahead to parse the parenthesized expression.
53865387
Parser::BacktrackingScope Backtrack(P);
53875388
P.consumeToken(tok::identifier);
53885389
P.consumeToken(tok::l_paren);
5389-
return P.Tok.is(tok::identifier) && P.peekToken().is(tok::r_paren) &&
5390-
(P.Tok.getText() == "safe" || P.Tok.getText() == "unsafe");
5390+
5391+
const bool argumentIsAllowed =
5392+
std::find(allowedArguments.begin(), allowedArguments.end(),
5393+
P.Tok.getText()) != allowedArguments.end();
5394+
return argumentIsAllowed && P.Tok.is(tok::identifier) &&
5395+
P.peekToken().is(tok::r_paren);
5396+
}
5397+
5398+
/// Given a current token of 'unowned', check to see if it is followed by a
5399+
/// "(safe)" or "(unsafe)" specifier.
5400+
static bool isParenthesizedUnowned(Parser &P) {
5401+
return isParenthesizedModifier(P, "unowned", {"safe", "unsafe"});
5402+
}
5403+
5404+
/// Given a current token of 'nonisolated', check to see if it is followed by an
5405+
/// "(unsafe)" specifier.
5406+
static bool isParenthesizedNonisolated(Parser &P) {
5407+
return isParenthesizedModifier(P, "nonisolated", {"unsafe"});
53915408
}
53925409

53935410
static void skipAttribute(Parser &P) {
@@ -5417,30 +5434,10 @@ static void skipAttribute(Parser &P) {
54175434

54185435
bool Parser::isStartOfSwiftDecl(bool allowPoundIfAttributes,
54195436
bool hadAttrsOrModifiers) {
5420-
const bool isTopLevelLibrary = (SF.Kind == SourceFileKind::Library) ||
5421-
(SF.Kind == SourceFileKind::Interface) ||
5422-
(SF.Kind == SourceFileKind::SIL);
54235437
if (Tok.is(tok::at_sign) && peekToken().is(tok::kw_rethrows)) {
54245438
// @rethrows does not follow the general rule of @<identifier> so
54255439
// it is needed to short circuit this else there will be an infinite
54265440
// loop on invalid attributes of just rethrows
5427-
} else if (Context.LangOpts.hasFeature(Feature::GlobalConcurrency) &&
5428-
(Tok.getKind() == tok::identifier) &&
5429-
Tok.getText().equals("nonisolated") && isTopLevelLibrary &&
5430-
!CurDeclContext->isLocalContext()) {
5431-
// TODO: hack to unblock proposal review by treating top-level nonisolated
5432-
// contextual keyword like an attribute; more robust implementation pending
5433-
BacktrackingScope backtrack(*this);
5434-
skipAttribute(*this);
5435-
5436-
// If this attribute is the last element in the block,
5437-
// consider it is a start of incomplete decl.
5438-
if (Tok.isAny(tok::r_brace, tok::eof) ||
5439-
(Tok.is(tok::pound_endif) && !allowPoundIfAttributes))
5440-
return true;
5441-
5442-
return isStartOfSwiftDecl(allowPoundIfAttributes,
5443-
/*hadAttrsOrModifiers=*/true);
54445441
} else if (!isKeywordPossibleDeclStart(Context.LangOpts, Tok)) {
54455442
// If this is obviously not the start of a decl, then we're done.
54465443
return false;
@@ -5579,6 +5576,19 @@ bool Parser::isStartOfSwiftDecl(bool allowPoundIfAttributes,
55795576
/*hadAttrsOrModifiers=*/true);
55805577
}
55815578

5579+
// If this is 'nonisolated', check to see if it is valid.
5580+
if (Context.LangOpts.hasFeature(Feature::GlobalConcurrency) &&
5581+
Tok.isContextualKeyword("nonisolated") && Tok2.is(tok::l_paren) &&
5582+
isParenthesizedNonisolated(*this)) {
5583+
BacktrackingScope backtrack(*this);
5584+
consumeToken(tok::identifier);
5585+
consumeToken(tok::l_paren);
5586+
consumeToken(tok::identifier);
5587+
consumeToken(tok::r_paren);
5588+
return isStartOfSwiftDecl(/*allowPoundIfAttributes=*/false,
5589+
/*hadAttrsOrModifiers=*/true);
5590+
}
5591+
55825592
if (Tok.isContextualKeyword("actor")) {
55835593
if (Tok2.is(tok::identifier)) // actor Foo {}
55845594
return true;

0 commit comments

Comments
 (0)