mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Parser: Accept @cdecl with an indentifier for the C name
Begin accepting the attribute in the form of `@cdecl(cName)`, using an identifier instead of a string. For ease of landing this change we still accept the string form. We should stop accepting it before making this feature available in production.
This commit is contained in:
@@ -1532,6 +1532,9 @@ ERROR(attr_expected_comma,none,
|
|||||||
ERROR(attr_expected_string_literal,none,
|
ERROR(attr_expected_string_literal,none,
|
||||||
"expected string literal in '%0' attribute", (StringRef))
|
"expected string literal in '%0' attribute", (StringRef))
|
||||||
|
|
||||||
|
ERROR(attr_expected_cname,none,
|
||||||
|
"expected C identifier in '%0' attribute", (StringRef))
|
||||||
|
|
||||||
ERROR(attr_expected_option_such_as,none,
|
ERROR(attr_expected_option_such_as,none,
|
||||||
"expected '%0' option such as '%1'", (StringRef, StringRef))
|
"expected '%0' option such as '%1'", (StringRef, StringRef))
|
||||||
|
|
||||||
|
|||||||
@@ -3014,7 +3014,45 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case DeclAttrKind::CDecl:
|
case DeclAttrKind::CDecl: {
|
||||||
|
if (!AttrName.starts_with("_") &&
|
||||||
|
|
||||||
|
// Backwards support for @cdecl("stringId"). Remove before enabling in
|
||||||
|
// production so we accept only the identifier format.
|
||||||
|
lookahead<bool>(1, [&](CancellableBacktrackingScope &) {
|
||||||
|
return Tok.isNot(tok::string_literal);
|
||||||
|
})) {
|
||||||
|
|
||||||
|
std::optional<StringRef> CName;
|
||||||
|
if (consumeIfAttributeLParen()) {
|
||||||
|
// Custom C name.
|
||||||
|
if (Tok.isNot(tok::identifier)) {
|
||||||
|
diagnose(Loc, diag::attr_expected_cname, AttrName);
|
||||||
|
return makeParserSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
CName = Tok.getText();
|
||||||
|
consumeToken(tok::identifier);
|
||||||
|
AttrRange = SourceRange(Loc, Tok.getRange().getStart());
|
||||||
|
|
||||||
|
if (!consumeIf(tok::r_paren)) {
|
||||||
|
diagnose(Loc, diag::attr_expected_rparen, AttrName,
|
||||||
|
DeclAttribute::isDeclModifier(DK));
|
||||||
|
return makeParserSuccess();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
AttrRange = SourceRange(Loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
Attributes.add(new (Context) CDeclAttr(CName.value_or(StringRef()), AtLoc,
|
||||||
|
AttrRange, /*Implicit=*/false,
|
||||||
|
/*isUnderscored*/false));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Leave legacy @_cdecls to the logic expecting a string.
|
||||||
|
LLVM_FALLTHROUGH;
|
||||||
|
}
|
||||||
case DeclAttrKind::Expose:
|
case DeclAttrKind::Expose:
|
||||||
case DeclAttrKind::SILGenName: {
|
case DeclAttrKind::SILGenName: {
|
||||||
if (!consumeIfAttributeLParen()) {
|
if (!consumeIfAttributeLParen()) {
|
||||||
|
|||||||
@@ -28,8 +28,8 @@
|
|||||||
// CHECK: #endif
|
// CHECK: #endif
|
||||||
|
|
||||||
/// My documentation
|
/// My documentation
|
||||||
@cdecl("simple")
|
@cdecl(simple)
|
||||||
func a_simple(x: Int, bar y: Int) -> Int { return x }
|
func a0_simple(x: Int, bar y: Int) -> Int { return x }
|
||||||
// CHECK-LABEL: // My documentation
|
// CHECK-LABEL: // My documentation
|
||||||
// CHECK-LABEL: SWIFT_EXTERN ptrdiff_t simple(ptrdiff_t x, ptrdiff_t y) SWIFT_NOEXCEPT SWIFT_WARN_UNUSED_RESULT;
|
// CHECK-LABEL: SWIFT_EXTERN ptrdiff_t simple(ptrdiff_t x, ptrdiff_t y) SWIFT_NOEXCEPT SWIFT_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,23 @@
|
|||||||
|
|
||||||
// REQUIRES: swift_feature_CDecl
|
// REQUIRES: swift_feature_CDecl
|
||||||
|
|
||||||
@cdecl("cdecl_foo") func foo(x: Int) -> Int { return x }
|
@cdecl(cdecl_foo) func foo(x: Int) -> Int { return x }
|
||||||
|
|
||||||
|
@cdecl(not an identifier) func invalidName() {}
|
||||||
|
// expected-error @-1 {{expected ')' in 'cdecl' attribute}}
|
||||||
|
// expected-error @-2 {{expected declaration}}
|
||||||
|
|
||||||
|
@cdecl() func emptyParen() {}
|
||||||
|
// expected-error @-1 {{expected C identifier in 'cdecl' attribute}}
|
||||||
|
// expected-error @-2 {{expected declaration}}
|
||||||
|
|
||||||
|
@cdecl(42) func aNumber() {}
|
||||||
|
// expected-error @-1 {{expected C identifier in 'cdecl' attribute}}
|
||||||
|
// expected-error @-2 {{expected declaration}}
|
||||||
|
|
||||||
|
@cdecl(a:selector:) func selectordName() {}
|
||||||
|
// expected-error @-1 {{expected ')' in 'cdecl' attribute}}
|
||||||
|
// expected-error @-2 {{expected declaration}}
|
||||||
|
|
||||||
@cdecl("") // expected-error{{@cdecl symbol name cannot be empty}}
|
@cdecl("") // expected-error{{@cdecl symbol name cannot be empty}}
|
||||||
func emptyName(x: Int) -> Int { return x }
|
func emptyName(x: Int) -> Int { return x }
|
||||||
|
|||||||
Reference in New Issue
Block a user