Skip to content

Commit f65b157

Browse files
committed
corrected implementation of parsing nonisolated(unsafe) as decl contextual keyword in top-level global scope (follow up to 5a88257)
1 parent 353d04f commit f65b157

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
@@ -43,6 +43,7 @@
4343
#include "llvm/Support/Path.h"
4444
#include "llvm/Support/SaveAndRestore.h"
4545
#include <algorithm>
46+
#include <initializer_list>
4647

4748
using namespace swift;
4849

@@ -5400,18 +5401,34 @@ bool swift::isKeywordPossibleDeclStart(const LangOptions &options,
54005401
}
54015402
}
54025403

5403-
/// Given a current token of 'unowned', check to see if it is followed by a
5404-
/// "(safe)" or "(unsafe)" specifier.
5405-
static bool isParenthesizedUnowned(Parser &P) {
5406-
assert(P.Tok.getText() == "unowned" && P.peekToken().is(tok::l_paren) &&
5404+
static bool
5405+
isParenthesizedModifier(Parser &P, StringRef name,
5406+
std::initializer_list<StringRef> allowedArguments) {
5407+
assert((P.Tok.getText() == name) && P.peekToken().is(tok::l_paren) &&
54075408
"Invariant violated");
5408-
5409+
54095410
// Look ahead to parse the parenthesized expression.
54105411
Parser::BacktrackingScope Backtrack(P);
54115412
P.consumeToken(tok::identifier);
54125413
P.consumeToken(tok::l_paren);
5413-
return P.Tok.is(tok::identifier) && P.peekToken().is(tok::r_paren) &&
5414-
(P.Tok.getText() == "safe" || P.Tok.getText() == "unsafe");
5414+
5415+
const bool argumentIsAllowed =
5416+
std::find(allowedArguments.begin(), allowedArguments.end(),
5417+
P.Tok.getText()) != allowedArguments.end();
5418+
return argumentIsAllowed && P.Tok.is(tok::identifier) &&
5419+
P.peekToken().is(tok::r_paren);
5420+
}
5421+
5422+
/// Given a current token of 'unowned', check to see if it is followed by a
5423+
/// "(safe)" or "(unsafe)" specifier.
5424+
static bool isParenthesizedUnowned(Parser &P) {
5425+
return isParenthesizedModifier(P, "unowned", {"safe", "unsafe"});
5426+
}
5427+
5428+
/// Given a current token of 'nonisolated', check to see if it is followed by an
5429+
/// "(unsafe)" specifier.
5430+
static bool isParenthesizedNonisolated(Parser &P) {
5431+
return isParenthesizedModifier(P, "nonisolated", {"unsafe"});
54155432
}
54165433

54175434
static void skipAttribute(Parser &P) {
@@ -5441,30 +5458,10 @@ static void skipAttribute(Parser &P) {
54415458

54425459
bool Parser::isStartOfSwiftDecl(bool allowPoundIfAttributes,
54435460
bool hadAttrsOrModifiers) {
5444-
const bool isTopLevelLibrary = (SF.Kind == SourceFileKind::Library) ||
5445-
(SF.Kind == SourceFileKind::Interface) ||
5446-
(SF.Kind == SourceFileKind::SIL);
54475461
if (Tok.is(tok::at_sign) && peekToken().is(tok::kw_rethrows)) {
54485462
// @rethrows does not follow the general rule of @<identifier> so
54495463
// it is needed to short circuit this else there will be an infinite
54505464
// loop on invalid attributes of just rethrows
5451-
} else if (Context.LangOpts.hasFeature(Feature::GlobalConcurrency) &&
5452-
(Tok.getKind() == tok::identifier) &&
5453-
Tok.getText().equals("nonisolated") && isTopLevelLibrary &&
5454-
!CurDeclContext->isLocalContext()) {
5455-
// TODO: hack to unblock proposal review by treating top-level nonisolated
5456-
// contextual keyword like an attribute; more robust implementation pending
5457-
BacktrackingScope backtrack(*this);
5458-
skipAttribute(*this);
5459-
5460-
// If this attribute is the last element in the block,
5461-
// consider it is a start of incomplete decl.
5462-
if (Tok.isAny(tok::r_brace, tok::eof) ||
5463-
(Tok.is(tok::pound_endif) && !allowPoundIfAttributes))
5464-
return true;
5465-
5466-
return isStartOfSwiftDecl(allowPoundIfAttributes,
5467-
/*hadAttrsOrModifiers=*/true);
54685465
} else if (!isKeywordPossibleDeclStart(Context.LangOpts, Tok)) {
54695466
// If this is obviously not the start of a decl, then we're done.
54705467
return false;
@@ -5603,6 +5600,19 @@ bool Parser::isStartOfSwiftDecl(bool allowPoundIfAttributes,
56035600
/*hadAttrsOrModifiers=*/true);
56045601
}
56055602

5603+
// If this is 'nonisolated', check to see if it is valid.
5604+
if (Context.LangOpts.hasFeature(Feature::GlobalConcurrency) &&
5605+
Tok.isContextualKeyword("nonisolated") && Tok2.is(tok::l_paren) &&
5606+
isParenthesizedNonisolated(*this)) {
5607+
BacktrackingScope backtrack(*this);
5608+
consumeToken(tok::identifier);
5609+
consumeToken(tok::l_paren);
5610+
consumeToken(tok::identifier);
5611+
consumeToken(tok::r_paren);
5612+
return isStartOfSwiftDecl(/*allowPoundIfAttributes=*/false,
5613+
/*hadAttrsOrModifiers=*/true);
5614+
}
5615+
56065616
if (Tok.isContextualKeyword("actor")) {
56075617
if (Tok2.is(tok::identifier)) // actor Foo {}
56085618
return true;

0 commit comments

Comments
 (0)