Skip to content

Disallow spaces between @, attribute name and ( in Swift 6 #71237

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions include/swift/AST/DiagnosticsParse.def
Original file line number Diff line number Diff line change
Expand Up @@ -1510,6 +1510,13 @@ ERROR(type_attribute_applied_to_decl,none,
ERROR(decl_attribute_applied_to_type,none,
"attribute can only be applied to declarations, not types", ())


ERROR(attr_extra_whitespace_after_at,PointsToFirstBadToken,
"extraneous whitespace between '@' and attribute name", ())

ERROR(attr_extra_whitespace_before_lparen,PointsToFirstBadToken,
"extraneous whitespace between attribute name and '('", ())

ERROR(attr_expected_lparen,none,
"expected '(' in '%0' %select{attribute|modifier}1", (StringRef, bool))

Expand Down
14 changes: 14 additions & 0 deletions include/swift/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,18 @@ class Parser {
return true;
}

/// Consume a '('. If it is not directly following the previous token, emit an
/// error (Swift 6) or warning (Swift <6) that attribute name and parentheses
/// must not be separated by a space.
SourceLoc consumeAttributeLParen();

/// If the next token is a '(' that's not on a new line consume it, and error
/// (Swift 6) or warn (Swift <6) that the attribute must not be separted from
/// the '(' by a space.
///
/// If the next token is not '(' or it's on a new line, return false.
bool consumeIfAttributeLParen();

bool consumeIfNotAtStartOfLine(tok K) {
if (Tok.isAtStartOfLine()) return false;
return consumeIf(K);
Expand Down Expand Up @@ -1147,6 +1159,7 @@ class Parser {

/// Parse a specific attribute.
ParserStatus parseDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
SourceLoc AtEndLoc,
PatternBindingInitializer *&initContext,
bool isFromClangAttribute = false);

Expand Down Expand Up @@ -1256,6 +1269,7 @@ class Parser {
bool justChecking);

ParserStatus parseTypeAttribute(TypeOrCustomAttr &result, SourceLoc AtLoc,
SourceLoc AtEndLoc,
PatternBindingInitializer *&initContext,
bool justChecking = false);

Expand Down
13 changes: 8 additions & 5 deletions lib/ClangImporter/ImportDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8055,11 +8055,14 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
parser.consumeTokenWithoutFeedingReceiver();

bool hadError = false;
SourceLoc atLoc;
if (parser.consumeIf(tok::at_sign, atLoc)) {
hadError = parser.parseDeclAttribute(
MappedDecl->getAttrs(), atLoc, initContext,
/*isFromClangAttribute=*/true).isError();
if (parser.Tok.is(tok::at_sign)) {
SourceLoc atEndLoc = parser.Tok.getRange().getEnd();
SourceLoc atLoc = parser.consumeToken(tok::at_sign);
hadError = parser
.parseDeclAttribute(MappedDecl->getAttrs(), atLoc,
atEndLoc, initContext,
/*isFromClangAttribute=*/true)
.isError();
} else {
SourceLoc staticLoc;
StaticSpellingKind staticSpelling;
Expand Down
Loading