@@ -4202,10 +4202,15 @@ ParserResult<CustomAttr> Parser::parseCustomAttribute(
42024202// / Note that various attributes (like mutating, weak, and unowned) are parsed
42034203// / but rejected since they have context-sensitive keywords.
42044204// /
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+
42094214 // If this not an identifier, the attribute is malformed.
42104215 if (Tok.isNot (tok::identifier) &&
42114216 Tok.isNot (tok::kw_in) &&
@@ -4404,8 +4409,10 @@ ParserStatus Parser::parseDeclAttribute(
44044409bool Parser::canParseTypeAttribute () {
44054410 TypeOrCustomAttr result; // ignored
44064411 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 ();
44094416}
44104417
44114418// / Parses the '@differentiable' type attribute argument (no argument list,
@@ -4602,9 +4609,14 @@ bool Parser::parseUUIDString(UUID &uuid, Diag<> diagnostic, bool justChecking) {
46024609// / canParseTypeAttribute; don't emit any diagnostics, and there's
46034610// / no need to actually record the attribute
46044611ParserStatus Parser::parseTypeAttribute (TypeOrCustomAttr &result,
4605- SourceLoc AtLoc,
4612+ SourceLoc AtLoc, SourceLoc AtEndLoc,
46064613 PatternBindingInitializer *&initContext,
46074614 bool justChecking) {
4615+ if (AtEndLoc != Tok.getLoc ()) {
4616+ diagnose (AtEndLoc, diag::attr_extra_whitespace_after_at)
4617+ .warnUntilSwiftVersion (6 );
4618+ }
4619+
46084620 // If this not an identifier, the attribute is malformed.
46094621 if (Tok.isNot (tok::identifier) &&
46104622 // These are keywords that we accept as attribute names.
@@ -5038,8 +5050,9 @@ ParserStatus Parser::parseDeclAttributeList(
50385050 ParserStatus Status;
50395051 while (Tok.isAny (tok::at_sign, tok::pound_if)) {
50405052 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);
50435056 } else {
50445057 if (!ifConfigsAreDeclAttrs && !ifConfigContainsOnlyAttributes ())
50455058 break ;
@@ -5330,8 +5343,9 @@ ParserStatus Parser::ParsedTypeAttributeList::slowParse(Parser &P) {
53305343 return status;
53315344
53325345 TypeOrCustomAttr result;
5346+ SourceLoc AtEndLoc = Tok.getRange ().getEnd ();
53335347 SourceLoc AtLoc = P.consumeToken ();
5334- status |= P.parseTypeAttribute (result, AtLoc, initContext);
5348+ status |= P.parseTypeAttribute (result, AtLoc, AtEndLoc, initContext);
53355349 if (status.isError ())
53365350 return status;
53375351 if (result)
0 commit comments