|
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 |
|
@@ -5143,18 +5144,34 @@ bool swift::isKeywordPossibleDeclStart(const LangOptions &options,
|
5143 | 5144 | }
|
5144 | 5145 | }
|
5145 | 5146 |
|
5146 |
| -/// Given a current token of 'unowned', check to see if it is followed by a |
5147 |
| -/// "(safe)" or "(unsafe)" specifier. |
5148 |
| -static bool isParenthesizedUnowned(Parser &P) { |
5149 |
| - assert(P.Tok.getText() == "unowned" && P.peekToken().is(tok::l_paren) && |
| 5147 | +static bool |
| 5148 | +isParenthesizedModifier(Parser &P, StringRef name, |
| 5149 | + std::initializer_list<StringRef> allowedArguments) { |
| 5150 | + assert((P.Tok.getText() == name) && P.peekToken().is(tok::l_paren) && |
5150 | 5151 | "Invariant violated");
|
5151 |
| - |
| 5152 | + |
5152 | 5153 | // Look ahead to parse the parenthesized expression.
|
5153 | 5154 | Parser::BacktrackingScope Backtrack(P);
|
5154 | 5155 | P.consumeToken(tok::identifier);
|
5155 | 5156 | P.consumeToken(tok::l_paren);
|
5156 |
| - return P.Tok.is(tok::identifier) && P.peekToken().is(tok::r_paren) && |
5157 |
| - (P.Tok.getText() == "safe" || P.Tok.getText() == "unsafe"); |
| 5157 | + |
| 5158 | + const bool argumentIsAllowed = |
| 5159 | + std::find(allowedArguments.begin(), allowedArguments.end(), |
| 5160 | + P.Tok.getText()) != allowedArguments.end(); |
| 5161 | + return argumentIsAllowed && P.Tok.is(tok::identifier) && |
| 5162 | + P.peekToken().is(tok::r_paren); |
| 5163 | +} |
| 5164 | + |
| 5165 | +/// Given a current token of 'unowned', check to see if it is followed by a |
| 5166 | +/// "(safe)" or "(unsafe)" specifier. |
| 5167 | +static bool isParenthesizedUnowned(Parser &P) { |
| 5168 | + return isParenthesizedModifier(P, "unowned", {"safe", "unsafe"}); |
| 5169 | +} |
| 5170 | + |
| 5171 | +/// Given a current token of 'nonisolated', check to see if it is followed by an |
| 5172 | +/// "(unsafe)" specifier. |
| 5173 | +static bool isParenthesizedNonisolated(Parser &P) { |
| 5174 | + return isParenthesizedModifier(P, "nonisolated", {"unsafe"}); |
5158 | 5175 | }
|
5159 | 5176 |
|
5160 | 5177 | static void skipAttribute(Parser &P) {
|
@@ -5326,6 +5343,19 @@ bool Parser::isStartOfSwiftDecl(bool allowPoundIfAttributes,
|
5326 | 5343 | /*hadAttrsOrModifiers=*/true);
|
5327 | 5344 | }
|
5328 | 5345 |
|
| 5346 | + // If this is 'nonisolated', check to see if it is valid. |
| 5347 | + if (Context.LangOpts.hasFeature(Feature::GlobalConcurrency) && |
| 5348 | + Tok.isContextualKeyword("nonisolated") && Tok2.is(tok::l_paren) && |
| 5349 | + isParenthesizedNonisolated(*this)) { |
| 5350 | + BacktrackingScope backtrack(*this); |
| 5351 | + consumeToken(tok::identifier); |
| 5352 | + consumeToken(tok::l_paren); |
| 5353 | + consumeToken(tok::identifier); |
| 5354 | + consumeToken(tok::r_paren); |
| 5355 | + return isStartOfSwiftDecl(/*allowPoundIfAttributes=*/false, |
| 5356 | + /*hadAttrsOrModifiers=*/true); |
| 5357 | + } |
| 5358 | + |
5329 | 5359 | if (Tok.isContextualKeyword("actor")) {
|
5330 | 5360 | if (Tok2.is(tok::identifier)) // actor Foo {}
|
5331 | 5361 | return true;
|
|
0 commit comments