@@ -1570,6 +1570,44 @@ void Parser::parseAllAvailabilityMacroArguments() {
15701570 AvailabilityMacrosComputed = true ;
15711571}
15721572
1573+ static HasAsyncAlternativeAttr *parseAsyncAlternativeAttribute (
1574+ Parser &P, StringRef AttrName, SourceLoc AtLoc, DeclAttrKind DK) {
1575+ SourceLoc Loc = P.PreviousLoc ;
1576+
1577+ // Unnamed @hasAsyncAlternative attribute
1578+ if (P.Tok .isNot (tok::l_paren))
1579+ return new (P.Context ) HasAsyncAlternativeAttr (AtLoc, Loc);
1580+
1581+ P.consumeToken (tok::l_paren);
1582+
1583+ if (!P.Tok .is (tok::string_literal)) {
1584+ P.diagnose (Loc, diag::attr_expected_string_literal, AttrName);
1585+ return nullptr ;
1586+ }
1587+
1588+ auto Value = P.getStringLiteralIfNotInterpolated (
1589+ Loc, (" argument of '" + AttrName + " '" ).str ());
1590+ P.consumeToken (tok::string_literal);
1591+ if (!Value)
1592+ return nullptr ;
1593+
1594+ ParsedDeclName parsedName = parseDeclName (Value.getValue ());
1595+ if (!parsedName || !parsedName.ContextName .empty ()) {
1596+ P.diagnose (AtLoc, diag::has_async_alternative_invalid_name, AttrName);;
1597+ return nullptr ;
1598+ }
1599+
1600+ SourceRange AttrRange = SourceRange (Loc, P.Tok .getRange ().getStart ());
1601+ if (!P.consumeIf (tok::r_paren)) {
1602+ P.diagnose (Loc, diag::attr_expected_rparen, AttrName,
1603+ DeclAttribute::isDeclModifier (DK));
1604+ return nullptr ;
1605+ }
1606+
1607+ return new (P.Context ) HasAsyncAlternativeAttr (
1608+ parsedName.formDeclNameRef (P.Context ), AtLoc, AttrRange);
1609+ }
1610+
15731611bool Parser::parseNewDeclAttribute (DeclAttributes &Attributes, SourceLoc AtLoc,
15741612 DeclAttrKind DK, bool isFromClangAttribute) {
15751613 // Ok, it is a valid attribute, eat it, and then process it.
@@ -2648,6 +2686,22 @@ bool Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
26482686 name, AtLoc, range, /* implicit*/ false ));
26492687 break ;
26502688 }
2689+ case DAK_HasAsyncAlternative: {
2690+ auto *attr = parseAsyncAlternativeAttribute (*this , AttrName, AtLoc, DK);
2691+ if (!attr) {
2692+ skipUntilDeclStmtRBrace (tok::r_paren);
2693+ consumeIf (tok::r_paren);
2694+ return false ;
2695+ }
2696+
2697+ if (!DiscardAttribute) {
2698+ if (Context.LangOpts .EnableExperimentalHasAsyncAlternative )
2699+ Attributes.add (attr);
2700+ else
2701+ diagnose (Loc, diag::requires_has_async_alternative, AttrName);
2702+ }
2703+ break ;
2704+ }
26512705 }
26522706
26532707 if (DuplicateAttribute) {
0 commit comments