@@ -3804,26 +3804,41 @@ ParserStatus Parser::parseTypeAttribute(TypeAttributes &Attributes,
38043804 return makeParserSuccess ();
38053805}
38063806
3807+ ParserStatus Parser::parseDeclAttributeList (
3808+ DeclAttributes &Attributes, bool ifConfigsAreDeclAttrs,
3809+ PatternBindingInitializer *initContext) {
3810+ ParserStatus Status;
3811+ while (Tok.isAny (tok::at_sign, tok::pound_if)) {
3812+ if (Tok.is (tok::at_sign)) {
3813+ SyntaxParsingContext AttrCtx (SyntaxContext, SyntaxKind::Attribute);
3814+ SourceLoc AtLoc = consumeToken ();
3815+ Status |= parseDeclAttribute (Attributes, AtLoc, initContext);
3816+ } else {
3817+ if (!ifConfigsAreDeclAttrs && !ifConfigContainsOnlyAttributes ())
3818+ break ;
3819+
3820+ Status |= parseIfConfigDeclAttributes (
3821+ Attributes, ifConfigsAreDeclAttrs, initContext);
3822+ }
3823+ }
3824+ return Status;
3825+ }
3826+
38073827// / \verbatim
38083828// / attribute-list:
38093829// / /*empty*/
38103830// / attribute-list-clause attribute-list
38113831// / attribute-list-clause:
38123832// / '@' attribute
38133833// / \endverbatim
3814- ParserStatus Parser::parseDeclAttributeList (DeclAttributes &Attributes) {
3815- if (Tok.isNot (tok::at_sign))
3834+ ParserStatus Parser::parseDeclAttributeList (
3835+ DeclAttributes &Attributes, bool IfConfigsAreDeclAttrs) {
3836+ if (Tok.isNot (tok::at_sign, tok::pound_if))
38163837 return makeParserSuccess ();
38173838
38183839 PatternBindingInitializer *initContext = nullptr ;
3819- ParserStatus Status;
38203840 SyntaxParsingContext AttrListCtx (SyntaxContext, SyntaxKind::AttributeList);
3821- do {
3822- SyntaxParsingContext AttrCtx (SyntaxContext, SyntaxKind::Attribute);
3823- SourceLoc AtLoc = consumeToken ();
3824- Status |= parseDeclAttribute (Attributes, AtLoc, initContext);
3825- } while (Tok.is (tok::at_sign));
3826- return Status;
3841+ return parseDeclAttributeList (Attributes, IfConfigsAreDeclAttrs, initContext);
38273842}
38283843
38293844// / \verbatim
@@ -3913,7 +3928,8 @@ bool Parser::parseDeclModifierList(DeclAttributes &Attributes,
39133928 BacktrackingScope Scope (*this );
39143929
39153930 consumeToken (); // consume actor
3916- isActorModifier = isStartOfSwiftDecl ();
3931+ isActorModifier = isStartOfSwiftDecl (
3932+ /* allowPoundIfAttributes=*/ false );
39173933 }
39183934
39193935 if (!isActorModifier)
@@ -4284,7 +4300,7 @@ static void skipAttribute(Parser &P) {
42844300 }
42854301}
42864302
4287- bool Parser::isStartOfSwiftDecl () {
4303+ bool Parser::isStartOfSwiftDecl (bool allowPoundIfAttributes ) {
42884304 if (Tok.is (tok::at_sign) && peekToken ().is (tok::kw_rethrows)) {
42894305 // @rethrows does not follow the general rule of @<identifier> so
42904306 // it is needed to short circuit this else there will be an infinite
@@ -4318,7 +4334,7 @@ bool Parser::isStartOfSwiftDecl() {
43184334 // check 'let' and 'var' right now.
43194335 if (Tok.is (tok::kw_try))
43204336 return peekToken ().isAny (tok::kw_let, tok::kw_var);
4321-
4337+
43224338 // Skip an attribute, since it might be a type attribute. This can't
43234339 // happen at the top level of a scope, but we do use isStartOfSwiftDecl()
43244340 // in positions like generic argument lists.
@@ -4329,10 +4345,20 @@ bool Parser::isStartOfSwiftDecl() {
43294345
43304346 // If this attribute is the last element in the block,
43314347 // consider it is a start of incomplete decl.
4332- if (Tok.isAny (tok::r_brace, tok::eof, tok::pound_endif))
4348+ if (Tok.isAny (tok::r_brace, tok::eof) ||
4349+ (Tok.is (tok::pound_endif) && !allowPoundIfAttributes))
43334350 return true ;
43344351
4335- return isStartOfSwiftDecl ();
4352+ return isStartOfSwiftDecl (allowPoundIfAttributes);
4353+ }
4354+
4355+ // Skip a #if that contains only attributes in all branches. These will be
4356+ // parsed as attributes of a declaration, not as separate declarations.
4357+ if (Tok.is (tok::pound_if) && allowPoundIfAttributes) {
4358+ BacktrackingScope backtrack (*this );
4359+ bool sawAnyAttributes = false ;
4360+ return skipIfConfigOfAttributes (sawAnyAttributes) &&
4361+ (Tok.is (tok::eof) || (sawAnyAttributes && isStartOfSwiftDecl ()));
43364362 }
43374363
43384364 // If we have a decl modifying keyword, check if the next token is a valid
@@ -4354,13 +4380,13 @@ bool Parser::isStartOfSwiftDecl() {
43544380 // If we found the start of a decl while trying to skip over the
43554381 // paren, then we have something incomplete like 'private('. Return
43564382 // true for better recovery.
4357- if (isStartOfSwiftDecl ())
4383+ if (isStartOfSwiftDecl (/* allowPoundIfAttributes= */ false ))
43584384 return true ;
43594385
43604386 skipSingle ();
43614387 }
43624388 }
4363- return isStartOfSwiftDecl ();
4389+ return isStartOfSwiftDecl (/* allowPoundIfAttributes= */ false );
43644390 }
43654391 }
43664392
@@ -4387,7 +4413,7 @@ bool Parser::isStartOfSwiftDecl() {
43874413 consumeToken (tok::l_paren);
43884414 consumeToken (tok::identifier);
43894415 consumeToken (tok::r_paren);
4390- return isStartOfSwiftDecl ();
4416+ return isStartOfSwiftDecl (/* allowPoundIfAttributes= */ false );
43914417 }
43924418
43934419 if (Tok.isContextualKeyword (" actor" )) {
@@ -4399,7 +4425,7 @@ bool Parser::isStartOfSwiftDecl() {
43994425 // it's an actor declaration, otherwise, it isn't.
44004426 do {
44014427 consumeToken ();
4402- } while (isStartOfSwiftDecl ());
4428+ } while (isStartOfSwiftDecl (/* allowPoundIfAttributes= */ false ));
44034429 return Tok.is (tok::identifier);
44044430 }
44054431
@@ -4410,7 +4436,7 @@ bool Parser::isStartOfSwiftDecl() {
44104436 // Otherwise, do a recursive parse.
44114437 Parser::BacktrackingScope Backtrack (*this );
44124438 consumeToken (tok::identifier);
4413- return isStartOfSwiftDecl ();
4439+ return isStartOfSwiftDecl (/* allowPoundIfAttributes= */ false );
44144440}
44154441
44164442bool Parser::isStartOfSILDecl () {
@@ -4521,12 +4547,13 @@ setOriginalDeclarationForDifferentiableAttributes(DeclAttributes attrs,
45214547ParserResult<Decl>
45224548Parser::parseDecl (ParseDeclOptions Flags,
45234549 bool IsAtStartOfLineOrPreviousHadSemi,
4550+ bool IfConfigsAreDeclAttrs,
45244551 llvm::function_ref<void (Decl*)> Handler) {
45254552 ParserPosition BeginParserPosition;
45264553 if (isCodeCompletionFirstPass ())
45274554 BeginParserPosition = getParserPosition ();
45284555
4529- if (Tok.is (tok::pound_if)) {
4556+ if (Tok.is (tok::pound_if) && ! ifConfigContainsOnlyAttributes () ) {
45304557 auto IfConfigResult = parseIfConfig (
45314558 [&](SmallVectorImpl<ASTNode> &Decls, bool IsActive) {
45324559 ParserStatus Status;
@@ -4585,7 +4612,8 @@ Parser::parseDecl(ParseDeclOptions Flags,
45854612 DeclAttributes Attributes;
45864613 if (Tok.hasComment ())
45874614 Attributes.add (new (Context) RawDocCommentAttr (Tok.getCommentRange ()));
4588- ParserStatus AttrStatus = parseDeclAttributeList (Attributes);
4615+ ParserStatus AttrStatus = parseDeclAttributeList (
4616+ Attributes, IfConfigsAreDeclAttrs);
45894617
45904618 // Parse modifiers.
45914619 // Keep track of where and whether we see a contextual keyword on the decl.
@@ -5367,7 +5395,9 @@ ParserStatus Parser::parseDeclItem(bool &PreviousHadSemi,
53675395 if (loadCurrentSyntaxNodeFromCache ()) {
53685396 return ParserStatus ();
53695397 }
5370- Result = parseDecl (Options, IsAtStartOfLineOrPreviousHadSemi, handler);
5398+ Result = parseDecl (
5399+ Options, IsAtStartOfLineOrPreviousHadSemi,
5400+ /* IfConfigsAreDeclAttrs=*/ false , handler);
53715401 if (Result.isParseErrorOrHasCompletion ())
53725402 skipUntilDeclRBrace (tok::semi, tok::pound_endif);
53735403 SourceLoc SemiLoc;
@@ -6211,7 +6241,8 @@ void Parser::skipSILUntilSwiftDecl() {
62116241 // Tell the lexer we're about to start lexing SIL.
62126242 Lexer::SILBodyRAII sbr (*L);
62136243
6214- while (!Tok.is (tok::eof) && !isStartOfSwiftDecl ()) {
6244+ while (!Tok.is (tok::eof) &&
6245+ !isStartOfSwiftDecl (/* allowPoundIfAttributes=*/ false )) {
62156246 // SIL pound dotted paths need to be skipped specially as they can contain
62166247 // decl keywords like 'subscript'.
62176248 if (consumeIf (tok::pound)) {
0 commit comments