|
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) {
|
@@ -5184,30 +5201,10 @@ static void skipAttribute(Parser &P) {
|
5184 | 5201 |
|
5185 | 5202 | bool Parser::isStartOfSwiftDecl(bool allowPoundIfAttributes,
|
5186 | 5203 | bool hadAttrsOrModifiers) {
|
5187 |
| - const bool isTopLevelLibrary = (SF.Kind == SourceFileKind::Library) || |
5188 |
| - (SF.Kind == SourceFileKind::Interface) || |
5189 |
| - (SF.Kind == SourceFileKind::SIL); |
5190 | 5204 | if (Tok.is(tok::at_sign) && peekToken().is(tok::kw_rethrows)) {
|
5191 | 5205 | // @rethrows does not follow the general rule of @<identifier> so
|
5192 | 5206 | // it is needed to short circuit this else there will be an infinite
|
5193 | 5207 | // loop on invalid attributes of just rethrows
|
5194 |
| - } else if (Context.LangOpts.hasFeature(Feature::GlobalConcurrency) && |
5195 |
| - (Tok.getKind() == tok::identifier) && |
5196 |
| - Tok.getText().equals("nonisolated") && isTopLevelLibrary && |
5197 |
| - !CurDeclContext->isLocalContext()) { |
5198 |
| - // TODO: hack to unblock proposal review by treating top-level nonisolated |
5199 |
| - // contextual keyword like an attribute; more robust implementation pending |
5200 |
| - BacktrackingScope backtrack(*this); |
5201 |
| - skipAttribute(*this); |
5202 |
| - |
5203 |
| - // If this attribute is the last element in the block, |
5204 |
| - // consider it is a start of incomplete decl. |
5205 |
| - if (Tok.isAny(tok::r_brace, tok::eof) || |
5206 |
| - (Tok.is(tok::pound_endif) && !allowPoundIfAttributes)) |
5207 |
| - return true; |
5208 |
| - |
5209 |
| - return isStartOfSwiftDecl(allowPoundIfAttributes, |
5210 |
| - /*hadAttrsOrModifiers=*/true); |
5211 | 5208 | } else if (!isKeywordPossibleDeclStart(Context.LangOpts, Tok)) {
|
5212 | 5209 | // If this is obviously not the start of a decl, then we're done.
|
5213 | 5210 | return false;
|
@@ -5346,6 +5343,19 @@ bool Parser::isStartOfSwiftDecl(bool allowPoundIfAttributes,
|
5346 | 5343 | /*hadAttrsOrModifiers=*/true);
|
5347 | 5344 | }
|
5348 | 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 | + |
5349 | 5359 | if (Tok.isContextualKeyword("actor")) {
|
5350 | 5360 | if (Tok2.is(tok::identifier)) // actor Foo {}
|
5351 | 5361 | return true;
|
|
0 commit comments