|
43 | 43 | #include "llvm/Support/Path.h" |
44 | 44 | #include "llvm/Support/SaveAndRestore.h" |
45 | 45 | #include <algorithm> |
| 46 | +#include <initializer_list> |
46 | 47 |
|
47 | 48 | using namespace swift; |
48 | 49 |
|
@@ -5400,18 +5401,34 @@ bool swift::isKeywordPossibleDeclStart(const LangOptions &options, |
5400 | 5401 | } |
5401 | 5402 | } |
5402 | 5403 |
|
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) && |
5407 | 5408 | "Invariant violated"); |
5408 | | - |
| 5409 | + |
5409 | 5410 | // Look ahead to parse the parenthesized expression. |
5410 | 5411 | Parser::BacktrackingScope Backtrack(P); |
5411 | 5412 | P.consumeToken(tok::identifier); |
5412 | 5413 | 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"}); |
5415 | 5432 | } |
5416 | 5433 |
|
5417 | 5434 | static void skipAttribute(Parser &P) { |
@@ -5441,30 +5458,10 @@ static void skipAttribute(Parser &P) { |
5441 | 5458 |
|
5442 | 5459 | bool Parser::isStartOfSwiftDecl(bool allowPoundIfAttributes, |
5443 | 5460 | bool hadAttrsOrModifiers) { |
5444 | | - const bool isTopLevelLibrary = (SF.Kind == SourceFileKind::Library) || |
5445 | | - (SF.Kind == SourceFileKind::Interface) || |
5446 | | - (SF.Kind == SourceFileKind::SIL); |
5447 | 5461 | if (Tok.is(tok::at_sign) && peekToken().is(tok::kw_rethrows)) { |
5448 | 5462 | // @rethrows does not follow the general rule of @<identifier> so |
5449 | 5463 | // it is needed to short circuit this else there will be an infinite |
5450 | 5464 | // 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); |
5468 | 5465 | } else if (!isKeywordPossibleDeclStart(Context.LangOpts, Tok)) { |
5469 | 5466 | // If this is obviously not the start of a decl, then we're done. |
5470 | 5467 | return false; |
@@ -5603,6 +5600,19 @@ bool Parser::isStartOfSwiftDecl(bool allowPoundIfAttributes, |
5603 | 5600 | /*hadAttrsOrModifiers=*/true); |
5604 | 5601 | } |
5605 | 5602 |
|
| 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 | + |
5606 | 5616 | if (Tok.isContextualKeyword("actor")) { |
5607 | 5617 | if (Tok2.is(tok::identifier)) // actor Foo {} |
5608 | 5618 | return true; |
|
0 commit comments