@@ -3804,26 +3804,41 @@ ParserStatus Parser::parseTypeAttribute(TypeAttributes &Attributes,
3804
3804
return makeParserSuccess ();
3805
3805
}
3806
3806
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
+
3807
3827
// / \verbatim
3808
3828
// / attribute-list:
3809
3829
// / /*empty*/
3810
3830
// / attribute-list-clause attribute-list
3811
3831
// / attribute-list-clause:
3812
3832
// / '@' attribute
3813
3833
// / \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))
3816
3837
return makeParserSuccess ();
3817
3838
3818
3839
PatternBindingInitializer *initContext = nullptr ;
3819
- ParserStatus Status;
3820
3840
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);
3827
3842
}
3828
3843
3829
3844
// / \verbatim
@@ -3913,7 +3928,8 @@ bool Parser::parseDeclModifierList(DeclAttributes &Attributes,
3913
3928
BacktrackingScope Scope (*this );
3914
3929
3915
3930
consumeToken (); // consume actor
3916
- isActorModifier = isStartOfSwiftDecl ();
3931
+ isActorModifier = isStartOfSwiftDecl (
3932
+ /* allowPoundIfAttributes=*/ false );
3917
3933
}
3918
3934
3919
3935
if (!isActorModifier)
@@ -4284,7 +4300,7 @@ static void skipAttribute(Parser &P) {
4284
4300
}
4285
4301
}
4286
4302
4287
- bool Parser::isStartOfSwiftDecl () {
4303
+ bool Parser::isStartOfSwiftDecl (bool allowPoundIfAttributes ) {
4288
4304
if (Tok.is (tok::at_sign) && peekToken ().is (tok::kw_rethrows)) {
4289
4305
// @rethrows does not follow the general rule of @<identifier> so
4290
4306
// it is needed to short circuit this else there will be an infinite
@@ -4318,7 +4334,7 @@ bool Parser::isStartOfSwiftDecl() {
4318
4334
// check 'let' and 'var' right now.
4319
4335
if (Tok.is (tok::kw_try))
4320
4336
return peekToken ().isAny (tok::kw_let, tok::kw_var);
4321
-
4337
+
4322
4338
// Skip an attribute, since it might be a type attribute. This can't
4323
4339
// happen at the top level of a scope, but we do use isStartOfSwiftDecl()
4324
4340
// in positions like generic argument lists.
@@ -4329,10 +4345,20 @@ bool Parser::isStartOfSwiftDecl() {
4329
4345
4330
4346
// If this attribute is the last element in the block,
4331
4347
// 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))
4333
4350
return true ;
4334
4351
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 ()));
4336
4362
}
4337
4363
4338
4364
// If we have a decl modifying keyword, check if the next token is a valid
@@ -4354,13 +4380,13 @@ bool Parser::isStartOfSwiftDecl() {
4354
4380
// If we found the start of a decl while trying to skip over the
4355
4381
// paren, then we have something incomplete like 'private('. Return
4356
4382
// true for better recovery.
4357
- if (isStartOfSwiftDecl ())
4383
+ if (isStartOfSwiftDecl (/* allowPoundIfAttributes= */ false ))
4358
4384
return true ;
4359
4385
4360
4386
skipSingle ();
4361
4387
}
4362
4388
}
4363
- return isStartOfSwiftDecl ();
4389
+ return isStartOfSwiftDecl (/* allowPoundIfAttributes= */ false );
4364
4390
}
4365
4391
}
4366
4392
@@ -4387,7 +4413,7 @@ bool Parser::isStartOfSwiftDecl() {
4387
4413
consumeToken (tok::l_paren);
4388
4414
consumeToken (tok::identifier);
4389
4415
consumeToken (tok::r_paren);
4390
- return isStartOfSwiftDecl ();
4416
+ return isStartOfSwiftDecl (/* allowPoundIfAttributes= */ false );
4391
4417
}
4392
4418
4393
4419
if (Tok.isContextualKeyword (" actor" )) {
@@ -4399,7 +4425,7 @@ bool Parser::isStartOfSwiftDecl() {
4399
4425
// it's an actor declaration, otherwise, it isn't.
4400
4426
do {
4401
4427
consumeToken ();
4402
- } while (isStartOfSwiftDecl ());
4428
+ } while (isStartOfSwiftDecl (/* allowPoundIfAttributes= */ false ));
4403
4429
return Tok.is (tok::identifier);
4404
4430
}
4405
4431
@@ -4410,7 +4436,7 @@ bool Parser::isStartOfSwiftDecl() {
4410
4436
// Otherwise, do a recursive parse.
4411
4437
Parser::BacktrackingScope Backtrack (*this );
4412
4438
consumeToken (tok::identifier);
4413
- return isStartOfSwiftDecl ();
4439
+ return isStartOfSwiftDecl (/* allowPoundIfAttributes= */ false );
4414
4440
}
4415
4441
4416
4442
bool Parser::isStartOfSILDecl () {
@@ -4521,12 +4547,13 @@ setOriginalDeclarationForDifferentiableAttributes(DeclAttributes attrs,
4521
4547
ParserResult<Decl>
4522
4548
Parser::parseDecl (ParseDeclOptions Flags,
4523
4549
bool IsAtStartOfLineOrPreviousHadSemi,
4550
+ bool IfConfigsAreDeclAttrs,
4524
4551
llvm::function_ref<void (Decl*)> Handler) {
4525
4552
ParserPosition BeginParserPosition;
4526
4553
if (isCodeCompletionFirstPass ())
4527
4554
BeginParserPosition = getParserPosition ();
4528
4555
4529
- if (Tok.is (tok::pound_if)) {
4556
+ if (Tok.is (tok::pound_if) && ! ifConfigContainsOnlyAttributes () ) {
4530
4557
auto IfConfigResult = parseIfConfig (
4531
4558
[&](SmallVectorImpl<ASTNode> &Decls, bool IsActive) {
4532
4559
ParserStatus Status;
@@ -4585,7 +4612,8 @@ Parser::parseDecl(ParseDeclOptions Flags,
4585
4612
DeclAttributes Attributes;
4586
4613
if (Tok.hasComment ())
4587
4614
Attributes.add (new (Context) RawDocCommentAttr (Tok.getCommentRange ()));
4588
- ParserStatus AttrStatus = parseDeclAttributeList (Attributes);
4615
+ ParserStatus AttrStatus = parseDeclAttributeList (
4616
+ Attributes, IfConfigsAreDeclAttrs);
4589
4617
4590
4618
// Parse modifiers.
4591
4619
// Keep track of where and whether we see a contextual keyword on the decl.
@@ -5367,7 +5395,9 @@ ParserStatus Parser::parseDeclItem(bool &PreviousHadSemi,
5367
5395
if (loadCurrentSyntaxNodeFromCache ()) {
5368
5396
return ParserStatus ();
5369
5397
}
5370
- Result = parseDecl (Options, IsAtStartOfLineOrPreviousHadSemi, handler);
5398
+ Result = parseDecl (
5399
+ Options, IsAtStartOfLineOrPreviousHadSemi,
5400
+ /* IfConfigsAreDeclAttrs=*/ false , handler);
5371
5401
if (Result.isParseErrorOrHasCompletion ())
5372
5402
skipUntilDeclRBrace (tok::semi, tok::pound_endif);
5373
5403
SourceLoc SemiLoc;
@@ -6211,7 +6241,8 @@ void Parser::skipSILUntilSwiftDecl() {
6211
6241
// Tell the lexer we're about to start lexing SIL.
6212
6242
Lexer::SILBodyRAII sbr (*L);
6213
6243
6214
- while (!Tok.is (tok::eof) && !isStartOfSwiftDecl ()) {
6244
+ while (!Tok.is (tok::eof) &&
6245
+ !isStartOfSwiftDecl (/* allowPoundIfAttributes=*/ false )) {
6215
6246
// SIL pound dotted paths need to be skipped specially as they can contain
6216
6247
// decl keywords like 'subscript'.
6217
6248
if (consumeIf (tok::pound)) {
0 commit comments