@@ -5938,6 +5938,17 @@ bool Parser::isStartOfSwiftDecl(bool allowPoundIfAttributes,
59385938 }
59395939 }
59405940
5941+ // `using @<attribute>` or `using <identifier>`.
5942+ if (Tok.isContextualKeyword (" using" )) {
5943+ // `using` declarations don't support attributes or modifiers.
5944+ if (hadAttrsOrModifiers)
5945+ return false ;
5946+
5947+ return !Tok2.isAtStartOfLine () &&
5948+ (Tok2.is (tok::at_sign) || Tok2.is (tok::identifier) ||
5949+ Tok2.is (tok::code_complete));
5950+ }
5951+
59415952 // If the next token is obviously not the start of a decl, bail early.
59425953 if (!isKeywordPossibleDeclStart (Context.LangOpts , Tok2))
59435954 return false ;
@@ -6292,6 +6303,17 @@ ParserStatus Parser::parseDecl(bool IsAtStartOfLineOrPreviousHadSemi,
62926303 break ;
62936304 }
62946305
6306+ // `using @<attribute>` or `using <identifier>`
6307+ if (Tok.isContextualKeyword (" using" )) {
6308+ auto nextToken = peekToken ();
6309+ if (!nextToken.isAtStartOfLine () &&
6310+ (nextToken.is (tok::at_sign) || nextToken.is (tok::identifier) ||
6311+ nextToken.is (tok::code_complete))) {
6312+ DeclResult = parseDeclUsing (Flags, Attributes);
6313+ break ;
6314+ }
6315+ }
6316+
62956317 if (Flags.contains (PD_HasContainerType) &&
62966318 IsAtStartOfLineOrPreviousHadSemi) {
62976319
@@ -6639,6 +6661,65 @@ ParserResult<ImportDecl> Parser::parseDeclImport(ParseDeclOptions Flags,
66396661 return DCC.fixupParserResult (ID);
66406662}
66416663
6664+ // / Parse an `using` declaration.
6665+ // /
6666+ // / \verbatim
6667+ // / decl-using:
6668+ // / 'using' (@<attribute> | <modifier>)
6669+ // / \endverbatim
6670+ ParserResult<UsingDecl> Parser::parseDeclUsing (ParseDeclOptions Flags,
6671+ DeclAttributes &Attributes) {
6672+ assert (Tok.isContextualKeyword (" using" ));
6673+ DebuggerContextChange DCC (*this );
6674+
6675+ SourceLoc UsingLoc = consumeToken ();
6676+
6677+ if (Tok.is (tok::code_complete)) {
6678+ if (CodeCompletionCallbacks) {
6679+ CodeCompletionCallbacks->completeUsingDecl ();
6680+ }
6681+ return makeParserCodeCompletionStatus ();
6682+ }
6683+
6684+ SourceLoc AtLoc;
6685+ // @<<attribute>>
6686+ if (Tok.is (tok::at_sign))
6687+ AtLoc = consumeToken ();
6688+
6689+ SourceLoc SpecifierLoc;
6690+ Identifier RawSpecifier;
6691+
6692+ if (parseIdentifier (RawSpecifier, SpecifierLoc,
6693+ /* diagnoseDollarPrefix=*/ false ,
6694+ diag::expected_identifier_in_decl, " using" ))
6695+ return nullptr ;
6696+
6697+ std::optional<UsingSpecifier> Specifier =
6698+ llvm::StringSwitch<std::optional<UsingSpecifier>>(RawSpecifier.str ())
6699+ .Case (" MainActor" , UsingSpecifier::MainActor)
6700+ .Case (" nonisolated" , UsingSpecifier::nonisolated)
6701+ .Default (std::nullopt );
6702+
6703+ if (!Specifier) {
6704+ diagnose (SpecifierLoc, diag::using_decl_invalid_specifier, RawSpecifier,
6705+ AtLoc.isValid ());
6706+ return nullptr ;
6707+ }
6708+
6709+ // Complain the `using` not being at top-level only after the specifier
6710+ // has been consumed, otherwise the specifier is going to be interpreted
6711+ // as a start of another declaration.
6712+ if (!CodeCompletionCallbacks && !DCC.movedToTopLevel () &&
6713+ !(Flags & PD_AllowTopLevel)) {
6714+ diagnose (UsingLoc, diag::decl_inner_scope);
6715+ return nullptr ;
6716+ }
6717+
6718+ auto *UD = UsingDecl::create (Context, UsingLoc, AtLoc ? AtLoc : SpecifierLoc,
6719+ *Specifier, CurDeclContext);
6720+ return DCC.fixupParserResult (UD);
6721+ }
6722+
66426723// / Parse an inheritance clause.
66436724// /
66446725// / \verbatim
0 commit comments