|
44 | 44 | #include "llvm/Support/Path.h"
|
45 | 45 | #include "llvm/Support/SaveAndRestore.h"
|
46 | 46 | #include <algorithm>
|
| 47 | +#include <initializer_list> |
47 | 48 |
|
48 | 49 | using namespace swift;
|
49 | 50 |
|
@@ -5376,18 +5377,34 @@ bool swift::isKeywordPossibleDeclStart(const LangOptions &options,
|
5376 | 5377 | }
|
5377 | 5378 | }
|
5378 | 5379 |
|
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) && |
5383 | 5384 | "Invariant violated");
|
5384 |
| - |
| 5385 | + |
5385 | 5386 | // Look ahead to parse the parenthesized expression.
|
5386 | 5387 | Parser::BacktrackingScope Backtrack(P);
|
5387 | 5388 | P.consumeToken(tok::identifier);
|
5388 | 5389 | 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"}); |
5391 | 5408 | }
|
5392 | 5409 |
|
5393 | 5410 | static void skipAttribute(Parser &P) {
|
@@ -5417,30 +5434,10 @@ static void skipAttribute(Parser &P) {
|
5417 | 5434 |
|
5418 | 5435 | bool Parser::isStartOfSwiftDecl(bool allowPoundIfAttributes,
|
5419 | 5436 | bool hadAttrsOrModifiers) {
|
5420 |
| - const bool isTopLevelLibrary = (SF.Kind == SourceFileKind::Library) || |
5421 |
| - (SF.Kind == SourceFileKind::Interface) || |
5422 |
| - (SF.Kind == SourceFileKind::SIL); |
5423 | 5437 | if (Tok.is(tok::at_sign) && peekToken().is(tok::kw_rethrows)) {
|
5424 | 5438 | // @rethrows does not follow the general rule of @<identifier> so
|
5425 | 5439 | // it is needed to short circuit this else there will be an infinite
|
5426 | 5440 | // 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); |
5444 | 5441 | } else if (!isKeywordPossibleDeclStart(Context.LangOpts, Tok)) {
|
5445 | 5442 | // If this is obviously not the start of a decl, then we're done.
|
5446 | 5443 | return false;
|
@@ -5579,6 +5576,19 @@ bool Parser::isStartOfSwiftDecl(bool allowPoundIfAttributes,
|
5579 | 5576 | /*hadAttrsOrModifiers=*/true);
|
5580 | 5577 | }
|
5581 | 5578 |
|
| 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 | + |
5582 | 5592 | if (Tok.isContextualKeyword("actor")) {
|
5583 | 5593 | if (Tok2.is(tok::identifier)) // actor Foo {}
|
5584 | 5594 | return true;
|
|
0 commit comments