@@ -3793,26 +3793,41 @@ ParserStatus Parser::parseTypeAttribute(TypeAttributes &Attributes,
37933793 return makeParserSuccess ();
37943794}
37953795
3796+ ParserStatus Parser::parseDeclAttributeList (
3797+ DeclAttributes &Attributes, bool ifConfigsAreDeclAttrs,
3798+ PatternBindingInitializer *initContext) {
3799+ ParserStatus Status;
3800+ while (Tok.isAny (tok::at_sign, tok::pound_if)) {
3801+ if (Tok.is (tok::at_sign)) {
3802+ SyntaxParsingContext AttrCtx (SyntaxContext, SyntaxKind::Attribute);
3803+ SourceLoc AtLoc = consumeToken ();
3804+ Status |= parseDeclAttribute (Attributes, AtLoc, initContext);
3805+ } else {
3806+ if (!ifConfigsAreDeclAttrs && !ifConfigContainsOnlyAttributes ())
3807+ break ;
3808+
3809+ Status |= parseIfConfigDeclAttributes (
3810+ Attributes, ifConfigsAreDeclAttrs, initContext);
3811+ }
3812+ }
3813+ return Status;
3814+ }
3815+
37963816// / \verbatim
37973817// / attribute-list:
37983818// / /*empty*/
37993819// / attribute-list-clause attribute-list
38003820// / attribute-list-clause:
38013821// / '@' attribute
38023822// / \endverbatim
3803- ParserStatus Parser::parseDeclAttributeList (DeclAttributes &Attributes) {
3804- if (Tok.isNot (tok::at_sign))
3823+ ParserStatus Parser::parseDeclAttributeList (
3824+ DeclAttributes &Attributes, bool IfConfigsAreDeclAttrs) {
3825+ if (Tok.isNot (tok::at_sign, tok::pound_if))
38053826 return makeParserSuccess ();
38063827
38073828 PatternBindingInitializer *initContext = nullptr ;
3808- ParserStatus Status;
38093829 SyntaxParsingContext AttrListCtx (SyntaxContext, SyntaxKind::AttributeList);
3810- do {
3811- SyntaxParsingContext AttrCtx (SyntaxContext, SyntaxKind::Attribute);
3812- SourceLoc AtLoc = consumeToken ();
3813- Status |= parseDeclAttribute (Attributes, AtLoc, initContext);
3814- } while (Tok.is (tok::at_sign));
3815- return Status;
3830+ return parseDeclAttributeList (Attributes, IfConfigsAreDeclAttrs, initContext);
38163831}
38173832
38183833// / \verbatim
@@ -3902,7 +3917,8 @@ bool Parser::parseDeclModifierList(DeclAttributes &Attributes,
39023917 BacktrackingScope Scope (*this );
39033918
39043919 consumeToken (); // consume actor
3905- isActorModifier = isStartOfSwiftDecl ();
3920+ isActorModifier = isStartOfSwiftDecl (
3921+ /* allowPoundIfAttributes=*/ false );
39063922 }
39073923
39083924 if (!isActorModifier)
@@ -4273,7 +4289,7 @@ static void skipAttribute(Parser &P) {
42734289 }
42744290}
42754291
4276- bool Parser::isStartOfSwiftDecl () {
4292+ bool Parser::isStartOfSwiftDecl (bool allowPoundIfAttributes ) {
42774293 if (Tok.is (tok::at_sign) && peekToken ().is (tok::kw_rethrows)) {
42784294 // @rethrows does not follow the general rule of @<identifier> so
42794295 // it is needed to short circuit this else there will be an infinite
@@ -4307,7 +4323,7 @@ bool Parser::isStartOfSwiftDecl() {
43074323 // check 'let' and 'var' right now.
43084324 if (Tok.is (tok::kw_try))
43094325 return peekToken ().isAny (tok::kw_let, tok::kw_var);
4310-
4326+
43114327 // Skip an attribute, since it might be a type attribute. This can't
43124328 // happen at the top level of a scope, but we do use isStartOfSwiftDecl()
43134329 // in positions like generic argument lists.
@@ -4318,10 +4334,20 @@ bool Parser::isStartOfSwiftDecl() {
43184334
43194335 // If this attribute is the last element in the block,
43204336 // consider it is a start of incomplete decl.
4321- if (Tok.isAny (tok::r_brace, tok::eof, tok::pound_endif))
4337+ if (Tok.isAny (tok::r_brace, tok::eof) ||
4338+ (Tok.is (tok::pound_endif) && !allowPoundIfAttributes))
43224339 return true ;
43234340
4324- return isStartOfSwiftDecl ();
4341+ return isStartOfSwiftDecl (allowPoundIfAttributes);
4342+ }
4343+
4344+ // Skip a #if that contains only attributes in all branches. These will be
4345+ // parsed as attributes of a declaration, not as separate declarations.
4346+ if (Tok.is (tok::pound_if) && allowPoundIfAttributes) {
4347+ BacktrackingScope backtrack (*this );
4348+ bool sawAnyAttributes = false ;
4349+ return skipIfConfigOfAttributes (sawAnyAttributes) && sawAnyAttributes &&
4350+ isStartOfSwiftDecl ();
43254351 }
43264352
43274353 // If we have a decl modifying keyword, check if the next token is a valid
@@ -4343,13 +4369,13 @@ bool Parser::isStartOfSwiftDecl() {
43434369 // If we found the start of a decl while trying to skip over the
43444370 // paren, then we have something incomplete like 'private('. Return
43454371 // true for better recovery.
4346- if (isStartOfSwiftDecl ())
4372+ if (isStartOfSwiftDecl (/* allowPoundIfAttributes= */ false ))
43474373 return true ;
43484374
43494375 skipSingle ();
43504376 }
43514377 }
4352- return isStartOfSwiftDecl ();
4378+ return isStartOfSwiftDecl (/* allowPoundIfAttributes= */ false );
43534379 }
43544380 }
43554381
@@ -4376,7 +4402,7 @@ bool Parser::isStartOfSwiftDecl() {
43764402 consumeToken (tok::l_paren);
43774403 consumeToken (tok::identifier);
43784404 consumeToken (tok::r_paren);
4379- return isStartOfSwiftDecl ();
4405+ return isStartOfSwiftDecl (/* allowPoundIfAttributes= */ false );
43804406 }
43814407
43824408 if (Tok.isContextualKeyword (" actor" )) {
@@ -4388,7 +4414,7 @@ bool Parser::isStartOfSwiftDecl() {
43884414 // it's an actor declaration, otherwise, it isn't.
43894415 do {
43904416 consumeToken ();
4391- } while (isStartOfSwiftDecl ());
4417+ } while (isStartOfSwiftDecl (/* allowPoundIfAttributes= */ false ));
43924418 return Tok.is (tok::identifier);
43934419 }
43944420
@@ -4399,7 +4425,7 @@ bool Parser::isStartOfSwiftDecl() {
43994425 // Otherwise, do a recursive parse.
44004426 Parser::BacktrackingScope Backtrack (*this );
44014427 consumeToken (tok::identifier);
4402- return isStartOfSwiftDecl ();
4428+ return isStartOfSwiftDecl (/* allowPoundIfAttributes= */ false );
44034429}
44044430
44054431bool Parser::isStartOfSILDecl () {
@@ -4510,12 +4536,13 @@ setOriginalDeclarationForDifferentiableAttributes(DeclAttributes attrs,
45104536ParserResult<Decl>
45114537Parser::parseDecl (ParseDeclOptions Flags,
45124538 bool IsAtStartOfLineOrPreviousHadSemi,
4539+ bool IfConfigsAreDeclAttrs,
45134540 llvm::function_ref<void (Decl*)> Handler) {
45144541 ParserPosition BeginParserPosition;
45154542 if (isCodeCompletionFirstPass ())
45164543 BeginParserPosition = getParserPosition ();
45174544
4518- if (Tok.is (tok::pound_if)) {
4545+ if (Tok.is (tok::pound_if) && ! ifConfigContainsOnlyAttributes () ) {
45194546 auto IfConfigResult = parseIfConfig (
45204547 [&](SmallVectorImpl<ASTNode> &Decls, bool IsActive) {
45214548 ParserStatus Status;
@@ -4574,7 +4601,8 @@ Parser::parseDecl(ParseDeclOptions Flags,
45744601 DeclAttributes Attributes;
45754602 if (Tok.hasComment ())
45764603 Attributes.add (new (Context) RawDocCommentAttr (Tok.getCommentRange ()));
4577- ParserStatus AttrStatus = parseDeclAttributeList (Attributes);
4604+ ParserStatus AttrStatus = parseDeclAttributeList (
4605+ Attributes, IfConfigsAreDeclAttrs);
45784606
45794607 // Parse modifiers.
45804608 // Keep track of where and whether we see a contextual keyword on the decl.
@@ -5356,7 +5384,9 @@ ParserStatus Parser::parseDeclItem(bool &PreviousHadSemi,
53565384 if (loadCurrentSyntaxNodeFromCache ()) {
53575385 return ParserStatus ();
53585386 }
5359- Result = parseDecl (Options, IsAtStartOfLineOrPreviousHadSemi, handler);
5387+ Result = parseDecl (
5388+ Options, IsAtStartOfLineOrPreviousHadSemi,
5389+ /* IfConfigsAreDeclAttrs=*/ false , handler);
53605390 if (Result.isParseErrorOrHasCompletion ())
53615391 skipUntilDeclRBrace (tok::semi, tok::pound_endif);
53625392 SourceLoc SemiLoc;
@@ -6200,7 +6230,8 @@ void Parser::skipSILUntilSwiftDecl() {
62006230 // Tell the lexer we're about to start lexing SIL.
62016231 Lexer::SILBodyRAII sbr (*L);
62026232
6203- while (!Tok.is (tok::eof) && !isStartOfSwiftDecl ()) {
6233+ while (!Tok.is (tok::eof) &&
6234+ !isStartOfSwiftDecl (/* allowPoundIfAttributes=*/ false )) {
62046235 // SIL pound dotted paths need to be skipped specially as they can contain
62056236 // decl keywords like 'subscript'.
62066237 if (consumeIf (tok::pound)) {
0 commit comments