@@ -3793,26 +3793,41 @@ ParserStatus Parser::parseTypeAttribute(TypeAttributes &Attributes,
3793
3793
return makeParserSuccess ();
3794
3794
}
3795
3795
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
+
3796
3816
// / \verbatim
3797
3817
// / attribute-list:
3798
3818
// / /*empty*/
3799
3819
// / attribute-list-clause attribute-list
3800
3820
// / attribute-list-clause:
3801
3821
// / '@' attribute
3802
3822
// / \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))
3805
3826
return makeParserSuccess ();
3806
3827
3807
3828
PatternBindingInitializer *initContext = nullptr ;
3808
- ParserStatus Status;
3809
3829
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);
3816
3831
}
3817
3832
3818
3833
// / \verbatim
@@ -3902,7 +3917,8 @@ bool Parser::parseDeclModifierList(DeclAttributes &Attributes,
3902
3917
BacktrackingScope Scope (*this );
3903
3918
3904
3919
consumeToken (); // consume actor
3905
- isActorModifier = isStartOfSwiftDecl ();
3920
+ isActorModifier = isStartOfSwiftDecl (
3921
+ /* allowPoundIfAttributes=*/ false );
3906
3922
}
3907
3923
3908
3924
if (!isActorModifier)
@@ -4273,7 +4289,7 @@ static void skipAttribute(Parser &P) {
4273
4289
}
4274
4290
}
4275
4291
4276
- bool Parser::isStartOfSwiftDecl () {
4292
+ bool Parser::isStartOfSwiftDecl (bool allowPoundIfAttributes ) {
4277
4293
if (Tok.is (tok::at_sign) && peekToken ().is (tok::kw_rethrows)) {
4278
4294
// @rethrows does not follow the general rule of @<identifier> so
4279
4295
// it is needed to short circuit this else there will be an infinite
@@ -4307,7 +4323,7 @@ bool Parser::isStartOfSwiftDecl() {
4307
4323
// check 'let' and 'var' right now.
4308
4324
if (Tok.is (tok::kw_try))
4309
4325
return peekToken ().isAny (tok::kw_let, tok::kw_var);
4310
-
4326
+
4311
4327
// Skip an attribute, since it might be a type attribute. This can't
4312
4328
// happen at the top level of a scope, but we do use isStartOfSwiftDecl()
4313
4329
// in positions like generic argument lists.
@@ -4318,10 +4334,20 @@ bool Parser::isStartOfSwiftDecl() {
4318
4334
4319
4335
// If this attribute is the last element in the block,
4320
4336
// 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))
4322
4339
return true ;
4323
4340
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 ();
4325
4351
}
4326
4352
4327
4353
// If we have a decl modifying keyword, check if the next token is a valid
@@ -4343,13 +4369,13 @@ bool Parser::isStartOfSwiftDecl() {
4343
4369
// If we found the start of a decl while trying to skip over the
4344
4370
// paren, then we have something incomplete like 'private('. Return
4345
4371
// true for better recovery.
4346
- if (isStartOfSwiftDecl ())
4372
+ if (isStartOfSwiftDecl (/* allowPoundIfAttributes= */ false ))
4347
4373
return true ;
4348
4374
4349
4375
skipSingle ();
4350
4376
}
4351
4377
}
4352
- return isStartOfSwiftDecl ();
4378
+ return isStartOfSwiftDecl (/* allowPoundIfAttributes= */ false );
4353
4379
}
4354
4380
}
4355
4381
@@ -4376,7 +4402,7 @@ bool Parser::isStartOfSwiftDecl() {
4376
4402
consumeToken (tok::l_paren);
4377
4403
consumeToken (tok::identifier);
4378
4404
consumeToken (tok::r_paren);
4379
- return isStartOfSwiftDecl ();
4405
+ return isStartOfSwiftDecl (/* allowPoundIfAttributes= */ false );
4380
4406
}
4381
4407
4382
4408
if (Tok.isContextualKeyword (" actor" )) {
@@ -4388,7 +4414,7 @@ bool Parser::isStartOfSwiftDecl() {
4388
4414
// it's an actor declaration, otherwise, it isn't.
4389
4415
do {
4390
4416
consumeToken ();
4391
- } while (isStartOfSwiftDecl ());
4417
+ } while (isStartOfSwiftDecl (/* allowPoundIfAttributes= */ false ));
4392
4418
return Tok.is (tok::identifier);
4393
4419
}
4394
4420
@@ -4399,7 +4425,7 @@ bool Parser::isStartOfSwiftDecl() {
4399
4425
// Otherwise, do a recursive parse.
4400
4426
Parser::BacktrackingScope Backtrack (*this );
4401
4427
consumeToken (tok::identifier);
4402
- return isStartOfSwiftDecl ();
4428
+ return isStartOfSwiftDecl (/* allowPoundIfAttributes= */ false );
4403
4429
}
4404
4430
4405
4431
bool Parser::isStartOfSILDecl () {
@@ -4510,12 +4536,13 @@ setOriginalDeclarationForDifferentiableAttributes(DeclAttributes attrs,
4510
4536
ParserResult<Decl>
4511
4537
Parser::parseDecl (ParseDeclOptions Flags,
4512
4538
bool IsAtStartOfLineOrPreviousHadSemi,
4539
+ bool IfConfigsAreDeclAttrs,
4513
4540
llvm::function_ref<void (Decl*)> Handler) {
4514
4541
ParserPosition BeginParserPosition;
4515
4542
if (isCodeCompletionFirstPass ())
4516
4543
BeginParserPosition = getParserPosition ();
4517
4544
4518
- if (Tok.is (tok::pound_if)) {
4545
+ if (Tok.is (tok::pound_if) && ! ifConfigContainsOnlyAttributes () ) {
4519
4546
auto IfConfigResult = parseIfConfig (
4520
4547
[&](SmallVectorImpl<ASTNode> &Decls, bool IsActive) {
4521
4548
ParserStatus Status;
@@ -4574,7 +4601,8 @@ Parser::parseDecl(ParseDeclOptions Flags,
4574
4601
DeclAttributes Attributes;
4575
4602
if (Tok.hasComment ())
4576
4603
Attributes.add (new (Context) RawDocCommentAttr (Tok.getCommentRange ()));
4577
- ParserStatus AttrStatus = parseDeclAttributeList (Attributes);
4604
+ ParserStatus AttrStatus = parseDeclAttributeList (
4605
+ Attributes, IfConfigsAreDeclAttrs);
4578
4606
4579
4607
// Parse modifiers.
4580
4608
// Keep track of where and whether we see a contextual keyword on the decl.
@@ -5356,7 +5384,9 @@ ParserStatus Parser::parseDeclItem(bool &PreviousHadSemi,
5356
5384
if (loadCurrentSyntaxNodeFromCache ()) {
5357
5385
return ParserStatus ();
5358
5386
}
5359
- Result = parseDecl (Options, IsAtStartOfLineOrPreviousHadSemi, handler);
5387
+ Result = parseDecl (
5388
+ Options, IsAtStartOfLineOrPreviousHadSemi,
5389
+ /* IfConfigsAreDeclAttrs=*/ false , handler);
5360
5390
if (Result.isParseErrorOrHasCompletion ())
5361
5391
skipUntilDeclRBrace (tok::semi, tok::pound_endif);
5362
5392
SourceLoc SemiLoc;
@@ -6200,7 +6230,8 @@ void Parser::skipSILUntilSwiftDecl() {
6200
6230
// Tell the lexer we're about to start lexing SIL.
6201
6231
Lexer::SILBodyRAII sbr (*L);
6202
6232
6203
- while (!Tok.is (tok::eof) && !isStartOfSwiftDecl ()) {
6233
+ while (!Tok.is (tok::eof) &&
6234
+ !isStartOfSwiftDecl (/* allowPoundIfAttributes=*/ false )) {
6204
6235
// SIL pound dotted paths need to be skipped specially as they can contain
6205
6236
// decl keywords like 'subscript'.
6206
6237
if (consumeIf (tok::pound)) {
0 commit comments