Skip to content

Commit ed65bb9

Browse files
authored
Merge pull request #82791 from xymus/cdecl-6.2
[6.2] Accept `@cdecl` global functions and enums, behind experimental feature flags
2 parents b84b357 + 6f4d55a commit ed65bb9

File tree

63 files changed

+1698
-215
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+1698
-215
lines changed

include/swift/AST/ASTBridging.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -949,11 +949,12 @@ BridgedBackDeployedAttr BridgedBackDeployedAttr_createParsed(
949949
BridgedSourceRange cRange, BridgedPlatformKind cPlatform,
950950
BridgedVersionTuple cVersion);
951951

952-
SWIFT_NAME("BridgedCDeclAttr.createParsed(_:atLoc:range:name:)")
952+
SWIFT_NAME("BridgedCDeclAttr.createParsed(_:atLoc:range:name:underscored:)")
953953
BridgedCDeclAttr BridgedCDeclAttr_createParsed(BridgedASTContext cContext,
954954
BridgedSourceLoc cAtLoc,
955955
BridgedSourceRange cRange,
956-
BridgedStringRef cName);
956+
BridgedStringRef cName,
957+
bool underscored);
957958

958959
SWIFT_NAME(
959960
"BridgedCustomAttr.createParsed(_:atLoc:type:initContext:argumentList:)")

include/swift/AST/Attr.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -691,22 +691,29 @@ class SectionAttr : public DeclAttribute {
691691
/// Defines the @_cdecl attribute.
692692
class CDeclAttr : public DeclAttribute {
693693
public:
694-
CDeclAttr(StringRef Name, SourceLoc AtLoc, SourceRange Range, bool Implicit)
695-
: DeclAttribute(DeclAttrKind::CDecl, AtLoc, Range, Implicit), Name(Name) {
694+
CDeclAttr(StringRef Name, SourceLoc AtLoc, SourceRange Range, bool Implicit,
695+
bool Underscored)
696+
: DeclAttribute(DeclAttrKind::CDecl, AtLoc, Range, Implicit),
697+
Name(Name), Underscored(Underscored) {
696698
}
697699

698-
CDeclAttr(StringRef Name, bool Implicit)
699-
: CDeclAttr(Name, SourceLoc(), SourceRange(), Implicit) {}
700+
CDeclAttr(StringRef Name, bool Implicit, bool Underscored)
701+
: CDeclAttr(Name, SourceLoc(), SourceRange(), Implicit, Underscored) {}
700702

701703
/// The symbol name.
702704
const StringRef Name;
703705

706+
/// Is this the version of the attribute that's underscored?
707+
/// Used to preserve retro compatibility with early adopters.
708+
const bool Underscored;
709+
704710
static bool classof(const DeclAttribute *DA) {
705711
return DA->getKind() == DeclAttrKind::CDecl;
706712
}
707713

708714
CDeclAttr *clone(ASTContext &ctx) const {
709-
return new (ctx) CDeclAttr(Name, AtLoc, Range, isImplicit());
715+
return new (ctx) CDeclAttr(Name, AtLoc, Range, isImplicit(),
716+
Underscored);
710717
}
711718

712719
bool isEquivalent(const CDeclAttr *other, Decl *attachedTo) const {

include/swift/AST/Decl.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8172,6 +8172,11 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
81728172
/// instance method.
81738173
bool isObjCInstanceMethod() const;
81748174

8175+
/// Get the foreign language targeted by a @cdecl-style attribute, if any.
8176+
/// Used to abstract away the change in meaning of @cdecl vs @_cdecl while
8177+
/// formalizing the attribute.
8178+
std::optional<ForeignLanguage> getCDeclKind() const;
8179+
81758180
/// Determine whether the name of an argument is an API name by default
81768181
/// depending on the function context.
81778182
bool argumentNameIsAPIByDefault() const;

include/swift/AST/DeclAttr.def

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,9 +365,10 @@ SIMPLE_DECL_ATTR(_show_in_interface, ShowInInterface,
365365
62)
366366

367367
DECL_ATTR(_cdecl, CDecl,
368-
OnFunc | OnAccessor,
368+
OnFunc | OnAccessor | OnEnum,
369369
LongAttribute | UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr,
370370
63)
371+
DECL_ATTR_ALIAS(cdecl, CDecl)
371372

372373
SIMPLE_DECL_ATTR(usableFromInline, UsableFromInline,
373374
OnAbstractFunction | OnVar | OnSubscript | OnNominalType | OnTypeAlias,

include/swift/AST/DiagnosticsCommon.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ namespace swift {
4848
} // end namespace detail
4949

5050
enum class StaticSpellingKind : uint8_t;
51+
enum class ForeignLanguage : uint8_t;
5152

5253
namespace diag {
5354

include/swift/AST/DiagnosticsParse.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1529,6 +1529,9 @@ ERROR(attr_expected_comma,none,
15291529
ERROR(attr_expected_string_literal,none,
15301530
"expected string literal in '%0' attribute", (StringRef))
15311531

1532+
ERROR(attr_expected_cname,none,
1533+
"expected C identifier in '%0' attribute", (StringRef))
1534+
15321535
ERROR(attr_expected_option_such_as,none,
15331536
"expected '%0' option such as '%1'", (StringRef, StringRef))
15341537

include/swift/AST/DiagnosticsSema.def

Lines changed: 56 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2051,11 +2051,17 @@ WARNING(wrap_objc_implementation_will_become_error,none,
20512051
(DiagnosticInfo *))
20522052

20532053
ERROR(cdecl_not_at_top_level,none,
2054-
"@_cdecl can only be applied to global functions", ())
2054+
"%0 can only be applied to global functions", (DeclAttribute))
20552055
ERROR(cdecl_empty_name,none,
2056-
"@_cdecl symbol name cannot be empty", ())
2056+
"%0 symbol name cannot be empty", (DeclAttribute))
20572057
ERROR(cdecl_throws,none,
2058-
"raising errors from '@_cdecl' functions is not supported", ())
2058+
"raising errors from %0 functions is not supported", (DeclAttribute))
2059+
ERROR(cdecl_incompatible_with_objc,none,
2060+
"cannot apply both '@cdecl' and '@objc' to %kindonly0",
2061+
(const Decl *))
2062+
ERROR(cdecl_feature_required,none,
2063+
"@cdecl requires '-enable-experimental-feature CDecl'",
2064+
())
20592065

20602066
// @_used and @_section
20612067
ERROR(section_linkage_markers_disabled,none,
@@ -3736,9 +3742,9 @@ ERROR(enum_with_raw_type_case_with_argument,none,
37363742
NOTE(enum_raw_type_here,none,
37373743
"declared raw type %0 here", (Type))
37383744
ERROR(objc_enum_no_raw_type,none,
3739-
"'@objc' enum must declare an integer raw type", ())
3745+
"'%0' enum must declare an integer raw type", (DeclAttribute))
37403746
ERROR(objc_enum_raw_type_not_integer,none,
3741-
"'@objc' enum raw type %0 is not an integer type", (Type))
3747+
"'%0' enum raw type %1 is not an integer type", (DeclAttribute, Type))
37423748
ERROR(enum_non_integer_raw_value_auto_increment,none,
37433749
"enum case must declare a raw value when the preceding raw value is not an integer", ())
37443750
ERROR(enum_non_integer_convertible_raw_type_no_value,none,
@@ -5513,10 +5519,14 @@ FIXIT(insert_globalactor_attr, "@%0 ", (Type))
55135519
ERROR(main_function_must_be_mainActor,none,
55145520
"main() must be '@MainActor'", ())
55155521

5522+
// Keep aligned with enum ForeignLanguage
5523+
#define FOREIGN_LANG_SELECT "select{C|Objective-C}"
5524+
55165525
ERROR(not_objc_function_async,none,
55175526
"'async' %0 cannot be represented in Objective-C", (DescriptiveDeclKind))
55185527
NOTE(not_objc_function_type_async,none,
5519-
"'async' function types cannot be represented in Objective-C", ())
5528+
"'async' function types cannot be represented "
5529+
"in %" FOREIGN_LANG_SELECT "0", (ForeignLanguage))
55205530
ERROR(actor_isolated_objc,none,
55215531
"actor-isolated %kind0 cannot be '@objc'",
55225532
(const ValueDecl *))
@@ -6523,7 +6533,7 @@ ERROR(objc_cannot_infer_name_raw_identifier,none,
65236533
(DescriptiveDeclKind))
65246534

65256535
// If you change this, also change enum ObjCReason
6526-
#define OBJC_ATTR_SELECT "select{marked '@_cdecl'|marked dynamic|marked '@objc'|marked '@objcMembers'|marked '@IBOutlet'|marked '@IBAction'|marked '@IBSegueAction'|marked '@NSManaged'|a member of an '@objc' protocol|implicitly '@objc'|an '@objc' override|an implementation of an '@objc' requirement|marked '@IBInspectable'|marked '@GKInspectable'|in an '@objc' extension of a class (without '@nonobjc')|in an '@objc @implementation' extension of a class (without final or '@nonobjc')|marked '@objc' by an access note}"
6536+
#define OBJC_ATTR_SELECT "select{marked '@cdecl'|marked '@_cdecl'|marked dynamic|marked '@objc'|marked '@objcMembers'|marked '@IBOutlet'|marked '@IBAction'|marked '@IBSegueAction'|marked '@NSManaged'|a member of an '@objc' protocol|implicitly '@objc'|an '@objc' override|an implementation of an '@objc' requirement|marked '@IBInspectable'|marked '@GKInspectable'|in an '@objc' extension of a class (without '@nonobjc')|in an '@objc @implementation' extension of a class (without final or '@nonobjc')|marked '@objc' by an access note}"
65276537

65286538
ERROR(objc_invalid_on_var,none,
65296539
"property cannot be %" OBJC_ATTR_SELECT "0 "
@@ -6556,25 +6566,36 @@ NOTE(not_objc_error_protocol_composition,none,
65566566
"protocol-constrained type containing 'Error' cannot be represented "
65576567
"in Objective-C", ())
65586568
NOTE(not_objc_empty_tuple,none,
6559-
"empty tuple type cannot be represented in Objective-C", ())
6569+
"empty tuple type cannot be represented in %" FOREIGN_LANG_SELECT "0",
6570+
(ForeignLanguage))
65606571
NOTE(not_objc_non_trivial_cxx_class,none,
6561-
"non-trivial C++ classes cannot be represented in Objective-C", ())
6572+
"non-trivial C++ classes cannot be represented in "
6573+
"%" FOREIGN_LANG_SELECT "0",
6574+
(ForeignLanguage))
65626575
NOTE(not_objc_tuple,none,
6563-
"tuples cannot be represented in Objective-C", ())
6576+
"tuples cannot be represented in %" FOREIGN_LANG_SELECT "0",
6577+
(ForeignLanguage))
65646578
NOTE(not_objc_swift_class,none,
65656579
"classes not annotated with '@objc' cannot be represented "
65666580
"in Objective-C", ())
65676581
NOTE(not_objc_swift_struct,none,
6568-
"Swift structs cannot be represented in Objective-C", ())
6582+
"Swift structs cannot be represented in %" FOREIGN_LANG_SELECT "0",
6583+
(ForeignLanguage))
65696584
NOTE(not_objc_swift_enum,none,
65706585
"non-'@objc' enums cannot be represented in Objective-C", ())
6586+
NOTE(not_cdecl_or_objc_swift_enum,none,
6587+
"Swift enums not marked '@cdecl'%select{| or '@objc'}0 cannot be "
6588+
"represented in %" FOREIGN_LANG_SELECT "0",
6589+
(ForeignLanguage))
65716590
NOTE(not_objc_generic_type_param,none,
6572-
"generic type parameters cannot be represented in Objective-C", ())
6591+
"generic type parameters cannot be represented in "
6592+
"%" FOREIGN_LANG_SELECT "0", (ForeignLanguage))
65736593
NOTE(not_objc_function_type_param,none,
6574-
"function types cannot be represented in Objective-C unless their "
6575-
"parameters and returns can be", ())
6594+
"function types cannot be represented in %" FOREIGN_LANG_SELECT "0 "
6595+
"unless their parameters and returns can be", (ForeignLanguage))
65766596
NOTE(not_objc_function_type_throwing,none,
6577-
"throwing function types cannot be represented in Objective-C", ())
6597+
"throwing function types cannot be represented in "
6598+
"%" FOREIGN_LANG_SELECT "0", (ForeignLanguage))
65786599
NOTE(objc_inferring_on_objc_protocol_member,none,
65796600
"inferring '@objc' because the declaration is a member of "
65806601
"an '@objc' protocol", ())
@@ -6584,6 +6605,11 @@ NOTE(objc_witness_objc_requirement,none,
65846605
"satisfying requirement for %kind0 in protocol %1",
65856606
(const ValueDecl *, const ProtocolDecl *))
65866607

6608+
NOTE(cdecl_incompatible_with_protocols,none,
6609+
"protocols cannot be represented in C", ())
6610+
NOTE(cdecl_incompatible_with_classes,none,
6611+
"classes cannot be represented in C", ())
6612+
65876613
ERROR(no_opaque_return_type_of,none,
65886614
"unable to resolve type for _opaqueReturnTypeOf attribute", ())
65896615

@@ -6596,20 +6622,24 @@ ERROR(objc_addressor, none,
65966622
ERROR(objc_coroutine_accessor, none,
65976623
"'read' and 'modify' accessors are not allowed to be marked '@objc'", ())
65986624
ERROR(objc_invalid_on_func_variadic,none,
6599-
"method cannot be %" OBJC_ATTR_SELECT "0 because it has a variadic "
6600-
"parameter", (unsigned))
6625+
"%kindonly0 cannot be %" OBJC_ATTR_SELECT "1 because it has a variadic "
6626+
"parameter", (const AbstractFunctionDecl*, unsigned))
66016627
ERROR(objc_invalid_on_func_inout,none,
6602-
"method cannot be %" OBJC_ATTR_SELECT "0 because inout "
6603-
"parameters cannot be represented in Objective-C", (unsigned))
6628+
"%kindonly0 cannot be %" OBJC_ATTR_SELECT "1 because inout "
6629+
"parameters cannot be represented in %" FOREIGN_LANG_SELECT "2",
6630+
(const AbstractFunctionDecl*, unsigned, ForeignLanguage))
66046631
ERROR(objc_invalid_on_func_param_type,none,
6605-
"method cannot be %" OBJC_ATTR_SELECT "1 because the type of the "
6606-
"parameter %0 cannot be represented in Objective-C", (unsigned, unsigned))
6632+
"%kindonly0 cannot be %" OBJC_ATTR_SELECT "2 because the type of the "
6633+
"parameter %1 cannot be represented in %" FOREIGN_LANG_SELECT "3",
6634+
(const AbstractFunctionDecl*, unsigned, unsigned, ForeignLanguage))
66076635
ERROR(objc_invalid_on_func_single_param_type,none,
6608-
"method cannot be %" OBJC_ATTR_SELECT "0 because the type of the "
6609-
"parameter cannot be represented in Objective-C", (unsigned))
6636+
"%kindonly0 cannot be %" OBJC_ATTR_SELECT "1 because the type of the "
6637+
"parameter cannot be represented in %" FOREIGN_LANG_SELECT "2",
6638+
(const AbstractFunctionDecl*, unsigned, ForeignLanguage))
66106639
ERROR(objc_invalid_on_func_result_type,none,
6611-
"method cannot be %" OBJC_ATTR_SELECT "0 because its result type "
6612-
"cannot be represented in Objective-C", (unsigned))
6640+
"%kindonly0 cannot be %" OBJC_ATTR_SELECT "1 because its result type "
6641+
"cannot be represented in %" FOREIGN_LANG_SELECT "2",
6642+
(const AbstractFunctionDecl*, unsigned, ForeignLanguage))
66136643
ERROR(objc_invalid_on_foreign_class,none,
66146644
"method cannot be %" OBJC_ATTR_SELECT "0 because Core Foundation "
66156645
"types are not classes in Objective-C", (unsigned))
@@ -6735,6 +6765,7 @@ ERROR(nonobjc_not_allowed,none,
67356765
#undef OBJC_DIAG_SELECT_2
67366766
#undef OBJC_DIAG_SELECT
67376767
#undef OBJC_ATTR_SELECT
6768+
#undef FOREIGN_LANG_SELECT
67386769

67396770
//------------------------------------------------------------------------------
67406771
// MARK: @exclusivity

include/swift/AST/Type.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ inline SubstOptions operator|(SubstFlags lhs, SubstFlags rhs) {
161161

162162
/// Enumeration describing foreign languages to which Swift may be
163163
/// bridged.
164-
enum class ForeignLanguage {
164+
enum class ForeignLanguage : uint8_t {
165165
C,
166166
ObjectiveC,
167167
};

include/swift/AST/TypeCheckRequests.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4875,6 +4875,44 @@ class TypeCheckObjCImplementationRequest
48754875
bool isCached() const { return true; }
48764876
};
48774877

4878+
/// Check @cdecl functions for compatibility with the foreign language.
4879+
class TypeCheckCDeclFunctionRequest
4880+
: public SimpleRequest<TypeCheckCDeclFunctionRequest,
4881+
evaluator::SideEffect(FuncDecl *FD,
4882+
CDeclAttr *attr),
4883+
RequestFlags::Cached> {
4884+
public:
4885+
using SimpleRequest::SimpleRequest;
4886+
4887+
private:
4888+
friend SimpleRequest;
4889+
4890+
evaluator::SideEffect
4891+
evaluate(Evaluator &evaluator, FuncDecl *FD, CDeclAttr *attr) const;
4892+
4893+
public:
4894+
bool isCached() const { return true; }
4895+
};
4896+
4897+
/// Check @cdecl enums for compatibility with C.
4898+
class TypeCheckCDeclEnumRequest
4899+
: public SimpleRequest<TypeCheckCDeclEnumRequest,
4900+
evaluator::SideEffect(EnumDecl *ED,
4901+
CDeclAttr *attr),
4902+
RequestFlags::Cached> {
4903+
public:
4904+
using SimpleRequest::SimpleRequest;
4905+
4906+
private:
4907+
friend SimpleRequest;
4908+
4909+
evaluator::SideEffect
4910+
evaluate(Evaluator &evaluator, EnumDecl *ED, CDeclAttr *attr) const;
4911+
4912+
public:
4913+
bool isCached() const { return true; }
4914+
};
4915+
48784916
void simple_display(llvm::raw_ostream &out, ASTNode node);
48794917
void simple_display(llvm::raw_ostream &out, Type value);
48804918
void simple_display(llvm::raw_ostream &out, const TypeRepr *TyR);

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,12 @@ SWIFT_REQUEST(TypeChecker, IsNonUserModuleRequest,
554554
SWIFT_REQUEST(TypeChecker, TypeCheckObjCImplementationRequest,
555555
unsigned(ExtensionDecl *),
556556
Cached, NoLocationInfo)
557+
SWIFT_REQUEST(TypeChecker, TypeCheckCDeclFunctionRequest,
558+
evaluator::SideEffect(FunctionDecl *, CDeclAttr *),
559+
Cached, NoLocationInfo)
560+
SWIFT_REQUEST(TypeChecker, TypeCheckCDeclEnumRequest,
561+
evaluator::SideEffect(EnumDecl *, CDeclAttr *),
562+
Cached, NoLocationInfo)
557563
SWIFT_REQUEST(TypeChecker, HasInitAccessorRequest,
558564
bool(AbstractStorageDecl *), Cached,
559565
NoLocationInfo)

0 commit comments

Comments
 (0)