|
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