mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge branch 'main' into cdecl-global-function-checking
This commit is contained in:
@@ -3746,19 +3746,20 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes,
|
||||
}
|
||||
case DeclAttrKind::Nonisolated: {
|
||||
AttrRange = Loc;
|
||||
std::optional<bool> isUnsafe(false);
|
||||
std::optional<NonIsolatedModifier> Modifier(NonIsolatedModifier::None);
|
||||
if (EnableParameterizedNonisolated) {
|
||||
isUnsafe =
|
||||
parseSingleAttrOption<bool>(*this, Loc, AttrRange, AttrName, DK,
|
||||
{{Context.Id_unsafe, true}}, *isUnsafe,
|
||||
ParameterizedDeclAttributeKind::Nonisolated);
|
||||
if (!isUnsafe) {
|
||||
Modifier = parseSingleAttrOption<NonIsolatedModifier>(
|
||||
*this, Loc, AttrRange, AttrName, DK,
|
||||
{{Context.Id_unsafe, NonIsolatedModifier::Unsafe},
|
||||
{Context.Id_nonsending, NonIsolatedModifier::NonSending}},
|
||||
*Modifier, ParameterizedDeclAttributeKind::Nonisolated);
|
||||
if (!Modifier) {
|
||||
return makeParserSuccess();
|
||||
}
|
||||
}
|
||||
|
||||
if (!DiscardAttribute) {
|
||||
Attributes.add(new (Context) NonisolatedAttr(AtLoc, AttrRange, *isUnsafe,
|
||||
Attributes.add(new (Context) NonisolatedAttr(AtLoc, AttrRange, *Modifier,
|
||||
/*implicit*/ false));
|
||||
}
|
||||
break;
|
||||
@@ -3948,21 +3949,6 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes,
|
||||
Attributes.add(Attr.get());
|
||||
break;
|
||||
}
|
||||
|
||||
case DeclAttrKind::Execution: {
|
||||
auto behavior = parseSingleAttrOption<ExecutionKind>(
|
||||
*this, Loc, AttrRange, AttrName, DK,
|
||||
{{Context.Id_concurrent, ExecutionKind::Concurrent},
|
||||
{Context.Id_caller, ExecutionKind::Caller}});
|
||||
if (!behavior)
|
||||
return makeParserSuccess();
|
||||
|
||||
if (!DiscardAttribute)
|
||||
Attributes.add(new (Context) ExecutionAttr(AtLoc, AttrRange, *behavior,
|
||||
/*Implicit*/ false));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (DuplicateAttribute) {
|
||||
@@ -4248,10 +4234,6 @@ ParserStatus Parser::parseDeclAttribute(DeclAttributes &Attributes,
|
||||
checkInvalidAttrName("_functionBuilder", "resultBuilder",
|
||||
DeclAttrKind::ResultBuilder, diag::attr_renamed_warning);
|
||||
|
||||
// Historical name for @Sendable.
|
||||
checkInvalidAttrName("concurrent", "Sendable", DeclAttrKind::Sendable,
|
||||
diag::attr_renamed_warning);
|
||||
|
||||
// Historical name for 'nonisolated'.
|
||||
if (!DK && Tok.getText() == "actorIndependent") {
|
||||
diagnose(
|
||||
@@ -4605,23 +4587,6 @@ ParserStatus Parser::parseTypeAttribute(TypeOrCustomAttr &result,
|
||||
// Determine which attribute it is, and diagnose it if unknown.
|
||||
auto optAttr = TypeAttribute::getAttrKindFromString(Tok.getText());
|
||||
|
||||
auto checkInvalidAttrName =
|
||||
[&](StringRef invalidName, StringRef correctName, TypeAttrKind kind,
|
||||
std::optional<Diag<StringRef, StringRef>> diag = std::nullopt) {
|
||||
if (!optAttr && Tok.getText() == invalidName) {
|
||||
optAttr = kind;
|
||||
|
||||
if (diag) {
|
||||
diagnose(Tok, *diag, invalidName, correctName)
|
||||
.fixItReplace(Tok.getLoc(), correctName);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Historical name for @Sendable.
|
||||
checkInvalidAttrName("concurrent", "Sendable", TypeAttrKind::Sendable,
|
||||
diag::attr_renamed_warning);
|
||||
|
||||
if (!optAttr) {
|
||||
auto declAttrID = DeclAttribute::getAttrKindFromString(Tok.getText());
|
||||
if (declAttrID) {
|
||||
@@ -4771,56 +4736,6 @@ ParserStatus Parser::parseTypeAttribute(TypeOrCustomAttr &result,
|
||||
return makeParserSuccess();
|
||||
}
|
||||
|
||||
case TypeAttrKind::Execution: {
|
||||
if (!Context.LangOpts.hasFeature(Feature::ExecutionAttribute)) {
|
||||
diagnose(Tok, diag::requires_experimental_feature, "@execution", false,
|
||||
Feature::ExecutionAttribute.getName());
|
||||
return makeParserError();
|
||||
}
|
||||
|
||||
SourceLoc lpLoc = Tok.getLoc(), behaviorLoc, rpLoc;
|
||||
if (!consumeIfNotAtStartOfLine(tok::l_paren)) {
|
||||
if (!justChecking) {
|
||||
diagnose(Tok, diag::attr_execution_expected_lparen);
|
||||
// TODO: should we suggest removing the `@`?
|
||||
}
|
||||
return makeParserError();
|
||||
}
|
||||
|
||||
bool invalid = false;
|
||||
std::optional<ExecutionKind> behavior;
|
||||
if (isIdentifier(Tok, "concurrent")) {
|
||||
behaviorLoc = consumeToken(tok::identifier);
|
||||
behavior = ExecutionKind::Concurrent;
|
||||
} else if (isIdentifier(Tok, "caller")) {
|
||||
behaviorLoc = consumeToken(tok::identifier);
|
||||
behavior = ExecutionKind::Caller;
|
||||
} else {
|
||||
if (!justChecking) {
|
||||
diagnose(Tok, diag::attr_execution_expected_kind);
|
||||
}
|
||||
invalid = true;
|
||||
consumeIf(tok::identifier);
|
||||
}
|
||||
|
||||
if (justChecking && !Tok.is(tok::r_paren))
|
||||
return makeParserError();
|
||||
if (parseMatchingToken(tok::r_paren, rpLoc,
|
||||
diag::attr_execution_expected_rparen,
|
||||
lpLoc))
|
||||
return makeParserError();
|
||||
|
||||
if (invalid)
|
||||
return makeParserError();
|
||||
assert(behavior);
|
||||
|
||||
if (!justChecking) {
|
||||
result = new (Context) ExecutionTypeAttr(AtLoc, attrLoc, {lpLoc, rpLoc},
|
||||
{*behavior, behaviorLoc});
|
||||
}
|
||||
return makeParserSuccess();
|
||||
}
|
||||
|
||||
case TypeAttrKind::Opened: {
|
||||
// Parse the opened existential ID string in parens
|
||||
SourceLoc beginLoc = Tok.getLoc(), idLoc, endLoc;
|
||||
@@ -5323,6 +5238,7 @@ ParserStatus Parser::parseDeclModifierList(DeclAttributes &Attributes,
|
||||
/// '__shared' attribute-list-clause attribute-list
|
||||
/// '__owned' attribute-list-clause attribute-list
|
||||
/// 'some' attribute-list-clause attribute-list
|
||||
/// 'nonisolated(nonsending)' attribute-list-clause attribute-list
|
||||
/// attribute-list-clause:
|
||||
/// '@' attribute
|
||||
/// '@' attribute attribute-list-clause
|
||||
@@ -5349,6 +5265,43 @@ ParserStatus Parser::ParsedTypeAttributeList::slowParse(Parser &P) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// nonisolated(nonsending)
|
||||
if (Tok.isContextualKeyword("nonisolated")) {
|
||||
Tok.setKind(tok::contextual_keyword);
|
||||
|
||||
auto kwLoc = P.consumeToken();
|
||||
|
||||
if (CallerIsolatedLoc.isValid()) {
|
||||
P.diagnose(kwLoc, diag::nonisolated_nonsending_repeated)
|
||||
.fixItRemove(SpecifierLoc);
|
||||
}
|
||||
|
||||
// '('
|
||||
if (!P.consumeIfAttributeLParen()) {
|
||||
P.diagnose(Tok, diag::nonisolated_nonsending_expected_lparen);
|
||||
status.setIsParseError();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!Tok.isContextualKeyword("nonsending")) {
|
||||
P.diagnose(Tok, diag::nonisolated_nonsending_incorrect_modifier);
|
||||
status.setIsParseError();
|
||||
continue;
|
||||
}
|
||||
|
||||
(void)P.consumeToken();
|
||||
|
||||
// ')'
|
||||
if (!P.consumeIf(tok::r_paren)) {
|
||||
P.diagnose(Tok, diag::nonisolated_nonsending_expected_rparen);
|
||||
status.setIsParseError();
|
||||
continue;
|
||||
}
|
||||
|
||||
CallerIsolatedLoc = kwLoc;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Perform an extra check for 'sending'. Since it is a specifier, we use
|
||||
// the actual parsing logic below.
|
||||
if (Tok.isContextualKeyword("sending")) {
|
||||
@@ -5687,9 +5640,10 @@ static bool consumeIfParenthesizedUnowned(Parser &P) {
|
||||
}
|
||||
|
||||
/// Given a current token of 'nonisolated', check to see if it is followed by an
|
||||
/// "(unsafe)" specifier and consumes if it is.
|
||||
/// "(unsafe)" or "(nonsending)" specifier and consumes if it is.
|
||||
static bool consumeIfParenthesizedNonisolated(Parser &P) {
|
||||
return consumeIfParenthesizedModifier(P, "nonisolated", {"unsafe"});
|
||||
return consumeIfParenthesizedModifier(P, "nonisolated",
|
||||
{"unsafe", "nonsending"});
|
||||
}
|
||||
|
||||
static void skipAttribute(Parser &P) {
|
||||
|
||||
Reference in New Issue
Block a user