@@ -4202,10 +4202,15 @@ ParserResult<CustomAttr> Parser::parseCustomAttribute(
4202
4202
// / Note that various attributes (like mutating, weak, and unowned) are parsed
4203
4203
// / but rejected since they have context-sensitive keywords.
4204
4204
// /
4205
- ParserStatus Parser::parseDeclAttribute (
4206
- DeclAttributes &Attributes, SourceLoc AtLoc,
4207
- PatternBindingInitializer *&initContext,
4208
- bool isFromClangAttribute) {
4205
+ ParserStatus Parser::parseDeclAttribute (DeclAttributes &Attributes,
4206
+ SourceLoc AtLoc, SourceLoc AtEndLoc,
4207
+ PatternBindingInitializer *&initContext,
4208
+ bool isFromClangAttribute) {
4209
+ if (AtEndLoc != Tok.getLoc ()) {
4210
+ diagnose (AtEndLoc, diag::attr_extra_whitespace_after_at)
4211
+ .warnUntilSwiftVersion (6 );
4212
+ }
4213
+
4209
4214
// If this not an identifier, the attribute is malformed.
4210
4215
if (Tok.isNot (tok::identifier) &&
4211
4216
Tok.isNot (tok::kw_in) &&
@@ -4404,8 +4409,10 @@ ParserStatus Parser::parseDeclAttribute(
4404
4409
bool Parser::canParseTypeAttribute () {
4405
4410
TypeOrCustomAttr result; // ignored
4406
4411
PatternBindingInitializer *initContext = nullptr ;
4407
- return !parseTypeAttribute (result, /* atLoc=*/ SourceLoc (), initContext,
4408
- /* justChecking*/ true ).isError ();
4412
+ return !parseTypeAttribute (result, /* atLoc=*/ SourceLoc (),
4413
+ /* atEndLoc=*/ SourceLoc (), initContext,
4414
+ /* justChecking*/ true )
4415
+ .isError ();
4409
4416
}
4410
4417
4411
4418
// / Parses the '@differentiable' type attribute argument (no argument list,
@@ -4602,9 +4609,14 @@ bool Parser::parseUUIDString(UUID &uuid, Diag<> diagnostic, bool justChecking) {
4602
4609
// / canParseTypeAttribute; don't emit any diagnostics, and there's
4603
4610
// / no need to actually record the attribute
4604
4611
ParserStatus Parser::parseTypeAttribute (TypeOrCustomAttr &result,
4605
- SourceLoc AtLoc,
4612
+ SourceLoc AtLoc, SourceLoc AtEndLoc,
4606
4613
PatternBindingInitializer *&initContext,
4607
4614
bool justChecking) {
4615
+ if (AtEndLoc != Tok.getLoc ()) {
4616
+ diagnose (AtEndLoc, diag::attr_extra_whitespace_after_at)
4617
+ .warnUntilSwiftVersion (6 );
4618
+ }
4619
+
4608
4620
// If this not an identifier, the attribute is malformed.
4609
4621
if (Tok.isNot (tok::identifier) &&
4610
4622
// These are keywords that we accept as attribute names.
@@ -5038,8 +5050,9 @@ ParserStatus Parser::parseDeclAttributeList(
5038
5050
ParserStatus Status;
5039
5051
while (Tok.isAny (tok::at_sign, tok::pound_if)) {
5040
5052
if (Tok.is (tok::at_sign)) {
5041
- SourceLoc AtLoc = consumeToken ();
5042
- Status |= parseDeclAttribute (Attributes, AtLoc, initContext);
5053
+ SourceLoc AtEndLoc = Tok.getRange ().getEnd ();
5054
+ SourceLoc AtLoc = consumeToken ();
5055
+ Status |= parseDeclAttribute (Attributes, AtLoc, AtEndLoc, initContext);
5043
5056
} else {
5044
5057
if (!ifConfigsAreDeclAttrs && !ifConfigContainsOnlyAttributes ())
5045
5058
break ;
@@ -5330,8 +5343,9 @@ ParserStatus Parser::ParsedTypeAttributeList::slowParse(Parser &P) {
5330
5343
return status;
5331
5344
5332
5345
TypeOrCustomAttr result;
5346
+ SourceLoc AtEndLoc = Tok.getRange ().getEnd ();
5333
5347
SourceLoc AtLoc = P.consumeToken ();
5334
- status |= P.parseTypeAttribute (result, AtLoc, initContext);
5348
+ status |= P.parseTypeAttribute (result, AtLoc, AtEndLoc, initContext);
5335
5349
if (status.isError ())
5336
5350
return status;
5337
5351
if (result)
0 commit comments