Skip to content

Revert "[6.2] Accept @cdecl global functions and enums, behind experimental feature flags" #83103

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 1 commit into from
Jul 17, 2025
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
5 changes: 2 additions & 3 deletions include/swift/AST/ASTBridging.h
Original file line number Diff line number Diff line change
Expand Up @@ -949,12 +949,11 @@ BridgedBackDeployedAttr BridgedBackDeployedAttr_createParsed(
BridgedSourceRange cRange, BridgedPlatformKind cPlatform,
BridgedVersionTuple cVersion);

SWIFT_NAME("BridgedCDeclAttr.createParsed(_:atLoc:range:name:underscored:)")
SWIFT_NAME("BridgedCDeclAttr.createParsed(_:atLoc:range:name:)")
BridgedCDeclAttr BridgedCDeclAttr_createParsed(BridgedASTContext cContext,
BridgedSourceLoc cAtLoc,
BridgedSourceRange cRange,
BridgedStringRef cName,
bool underscored);
BridgedStringRef cName);

SWIFT_NAME(
"BridgedCustomAttr.createParsed(_:atLoc:type:initContext:argumentList:)")
Expand Down
17 changes: 5 additions & 12 deletions include/swift/AST/Attr.h
Original file line number Diff line number Diff line change
Expand Up @@ -691,29 +691,22 @@ class SectionAttr : public DeclAttribute {
/// Defines the @_cdecl attribute.
class CDeclAttr : public DeclAttribute {
public:
CDeclAttr(StringRef Name, SourceLoc AtLoc, SourceRange Range, bool Implicit,
bool Underscored)
: DeclAttribute(DeclAttrKind::CDecl, AtLoc, Range, Implicit),
Name(Name), Underscored(Underscored) {
CDeclAttr(StringRef Name, SourceLoc AtLoc, SourceRange Range, bool Implicit)
: DeclAttribute(DeclAttrKind::CDecl, AtLoc, Range, Implicit), Name(Name) {
}

CDeclAttr(StringRef Name, bool Implicit, bool Underscored)
: CDeclAttr(Name, SourceLoc(), SourceRange(), Implicit, Underscored) {}
CDeclAttr(StringRef Name, bool Implicit)
: CDeclAttr(Name, SourceLoc(), SourceRange(), Implicit) {}

/// The symbol name.
const StringRef Name;

/// Is this the version of the attribute that's underscored?
/// Used to preserve retro compatibility with early adopters.
const bool Underscored;

static bool classof(const DeclAttribute *DA) {
return DA->getKind() == DeclAttrKind::CDecl;
}

CDeclAttr *clone(ASTContext &ctx) const {
return new (ctx) CDeclAttr(Name, AtLoc, Range, isImplicit(),
Underscored);
return new (ctx) CDeclAttr(Name, AtLoc, Range, isImplicit());
}

bool isEquivalent(const CDeclAttr *other, Decl *attachedTo) const {
Expand Down
5 changes: 0 additions & 5 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -8172,11 +8172,6 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
/// instance method.
bool isObjCInstanceMethod() const;

/// Get the foreign language targeted by a @cdecl-style attribute, if any.
/// Used to abstract away the change in meaning of @cdecl vs @_cdecl while
/// formalizing the attribute.
std::optional<ForeignLanguage> getCDeclKind() const;

/// Determine whether the name of an argument is an API name by default
/// depending on the function context.
bool argumentNameIsAPIByDefault() const;
Expand Down
3 changes: 1 addition & 2 deletions include/swift/AST/DeclAttr.def
Original file line number Diff line number Diff line change
Expand Up @@ -365,10 +365,9 @@ SIMPLE_DECL_ATTR(_show_in_interface, ShowInInterface,
62)

DECL_ATTR(_cdecl, CDecl,
OnFunc | OnAccessor | OnEnum,
OnFunc | OnAccessor,
LongAttribute | UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr,
63)
DECL_ATTR_ALIAS(cdecl, CDecl)

SIMPLE_DECL_ATTR(usableFromInline, UsableFromInline,
OnAbstractFunction | OnVar | OnSubscript | OnNominalType | OnTypeAlias,
Expand Down
1 change: 0 additions & 1 deletion include/swift/AST/DiagnosticsCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ namespace swift {
} // end namespace detail

enum class StaticSpellingKind : uint8_t;
enum class ForeignLanguage : uint8_t;

namespace diag {

Expand Down
3 changes: 0 additions & 3 deletions include/swift/AST/DiagnosticsParse.def
Original file line number Diff line number Diff line change
Expand Up @@ -1529,9 +1529,6 @@ ERROR(attr_expected_comma,none,
ERROR(attr_expected_string_literal,none,
"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,
"expected '%0' option such as '%1'", (StringRef, StringRef))

Expand Down
81 changes: 25 additions & 56 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -2051,17 +2051,11 @@ WARNING(wrap_objc_implementation_will_become_error,none,
(DiagnosticInfo *))

ERROR(cdecl_not_at_top_level,none,
"%0 can only be applied to global functions", (DeclAttribute))
"@_cdecl can only be applied to global functions", ())
ERROR(cdecl_empty_name,none,
"%0 symbol name cannot be empty", (DeclAttribute))
"@_cdecl symbol name cannot be empty", ())
ERROR(cdecl_throws,none,
"raising errors from %0 functions is not supported", (DeclAttribute))
ERROR(cdecl_incompatible_with_objc,none,
"cannot apply both '@cdecl' and '@objc' to %kindonly0",
(const Decl *))
ERROR(cdecl_feature_required,none,
"@cdecl requires '-enable-experimental-feature CDecl'",
())
"raising errors from '@_cdecl' functions is not supported", ())

// @_used and @_section
ERROR(section_linkage_markers_disabled,none,
Expand Down Expand Up @@ -3742,9 +3736,9 @@ ERROR(enum_with_raw_type_case_with_argument,none,
NOTE(enum_raw_type_here,none,
"declared raw type %0 here", (Type))
ERROR(objc_enum_no_raw_type,none,
"'%0' enum must declare an integer raw type", (DeclAttribute))
"'@objc' enum must declare an integer raw type", ())
ERROR(objc_enum_raw_type_not_integer,none,
"'%0' enum raw type %1 is not an integer type", (DeclAttribute, Type))
"'@objc' enum raw type %0 is not an integer type", (Type))
ERROR(enum_non_integer_raw_value_auto_increment,none,
"enum case must declare a raw value when the preceding raw value is not an integer", ())
ERROR(enum_non_integer_convertible_raw_type_no_value,none,
Expand Down Expand Up @@ -5519,14 +5513,10 @@ FIXIT(insert_globalactor_attr, "@%0 ", (Type))
ERROR(main_function_must_be_mainActor,none,
"main() must be '@MainActor'", ())

// Keep aligned with enum ForeignLanguage
#define FOREIGN_LANG_SELECT "select{C|Objective-C}"

ERROR(not_objc_function_async,none,
"'async' %0 cannot be represented in Objective-C", (DescriptiveDeclKind))
NOTE(not_objc_function_type_async,none,
"'async' function types cannot be represented "
"in %" FOREIGN_LANG_SELECT "0", (ForeignLanguage))
"'async' function types cannot be represented in Objective-C", ())
ERROR(actor_isolated_objc,none,
"actor-isolated %kind0 cannot be '@objc'",
(const ValueDecl *))
Expand Down Expand Up @@ -6533,7 +6523,7 @@ ERROR(objc_cannot_infer_name_raw_identifier,none,
(DescriptiveDeclKind))

// If you change this, also change enum ObjCReason
#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}"
#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}"

ERROR(objc_invalid_on_var,none,
"property cannot be %" OBJC_ATTR_SELECT "0 "
Expand Down Expand Up @@ -6566,36 +6556,25 @@ NOTE(not_objc_error_protocol_composition,none,
"protocol-constrained type containing 'Error' cannot be represented "
"in Objective-C", ())
NOTE(not_objc_empty_tuple,none,
"empty tuple type cannot be represented in %" FOREIGN_LANG_SELECT "0",
(ForeignLanguage))
"empty tuple type cannot be represented in Objective-C", ())
NOTE(not_objc_non_trivial_cxx_class,none,
"non-trivial C++ classes cannot be represented in "
"%" FOREIGN_LANG_SELECT "0",
(ForeignLanguage))
"non-trivial C++ classes cannot be represented in Objective-C", ())
NOTE(not_objc_tuple,none,
"tuples cannot be represented in %" FOREIGN_LANG_SELECT "0",
(ForeignLanguage))
"tuples cannot be represented in Objective-C", ())
NOTE(not_objc_swift_class,none,
"classes not annotated with '@objc' cannot be represented "
"in Objective-C", ())
NOTE(not_objc_swift_struct,none,
"Swift structs cannot be represented in %" FOREIGN_LANG_SELECT "0",
(ForeignLanguage))
"Swift structs cannot be represented in Objective-C", ())
NOTE(not_objc_swift_enum,none,
"non-'@objc' enums cannot be represented in Objective-C", ())
NOTE(not_cdecl_or_objc_swift_enum,none,
"Swift enums not marked '@cdecl'%select{| or '@objc'}0 cannot be "
"represented in %" FOREIGN_LANG_SELECT "0",
(ForeignLanguage))
NOTE(not_objc_generic_type_param,none,
"generic type parameters cannot be represented in "
"%" FOREIGN_LANG_SELECT "0", (ForeignLanguage))
"generic type parameters cannot be represented in Objective-C", ())
NOTE(not_objc_function_type_param,none,
"function types cannot be represented in %" FOREIGN_LANG_SELECT "0 "
"unless their parameters and returns can be", (ForeignLanguage))
"function types cannot be represented in Objective-C unless their "
"parameters and returns can be", ())
NOTE(not_objc_function_type_throwing,none,
"throwing function types cannot be represented in "
"%" FOREIGN_LANG_SELECT "0", (ForeignLanguage))
"throwing function types cannot be represented in Objective-C", ())
NOTE(objc_inferring_on_objc_protocol_member,none,
"inferring '@objc' because the declaration is a member of "
"an '@objc' protocol", ())
Expand All @@ -6605,11 +6584,6 @@ NOTE(objc_witness_objc_requirement,none,
"satisfying requirement for %kind0 in protocol %1",
(const ValueDecl *, const ProtocolDecl *))

NOTE(cdecl_incompatible_with_protocols,none,
"protocols cannot be represented in C", ())
NOTE(cdecl_incompatible_with_classes,none,
"classes cannot be represented in C", ())

ERROR(no_opaque_return_type_of,none,
"unable to resolve type for _opaqueReturnTypeOf attribute", ())

Expand All @@ -6622,24 +6596,20 @@ ERROR(objc_addressor, none,
ERROR(objc_coroutine_accessor, none,
"'read' and 'modify' accessors are not allowed to be marked '@objc'", ())
ERROR(objc_invalid_on_func_variadic,none,
"%kindonly0 cannot be %" OBJC_ATTR_SELECT "1 because it has a variadic "
"parameter", (const AbstractFunctionDecl*, unsigned))
"method cannot be %" OBJC_ATTR_SELECT "0 because it has a variadic "
"parameter", (unsigned))
ERROR(objc_invalid_on_func_inout,none,
"%kindonly0 cannot be %" OBJC_ATTR_SELECT "1 because inout "
"parameters cannot be represented in %" FOREIGN_LANG_SELECT "2",
(const AbstractFunctionDecl*, unsigned, ForeignLanguage))
"method cannot be %" OBJC_ATTR_SELECT "0 because inout "
"parameters cannot be represented in Objective-C", (unsigned))
ERROR(objc_invalid_on_func_param_type,none,
"%kindonly0 cannot be %" OBJC_ATTR_SELECT "2 because the type of the "
"parameter %1 cannot be represented in %" FOREIGN_LANG_SELECT "3",
(const AbstractFunctionDecl*, unsigned, unsigned, ForeignLanguage))
"method cannot be %" OBJC_ATTR_SELECT "1 because the type of the "
"parameter %0 cannot be represented in Objective-C", (unsigned, unsigned))
ERROR(objc_invalid_on_func_single_param_type,none,
"%kindonly0 cannot be %" OBJC_ATTR_SELECT "1 because the type of the "
"parameter cannot be represented in %" FOREIGN_LANG_SELECT "2",
(const AbstractFunctionDecl*, unsigned, ForeignLanguage))
"method cannot be %" OBJC_ATTR_SELECT "0 because the type of the "
"parameter cannot be represented in Objective-C", (unsigned))
ERROR(objc_invalid_on_func_result_type,none,
"%kindonly0 cannot be %" OBJC_ATTR_SELECT "1 because its result type "
"cannot be represented in %" FOREIGN_LANG_SELECT "2",
(const AbstractFunctionDecl*, unsigned, ForeignLanguage))
"method cannot be %" OBJC_ATTR_SELECT "0 because its result type "
"cannot be represented in Objective-C", (unsigned))
ERROR(objc_invalid_on_foreign_class,none,
"method cannot be %" OBJC_ATTR_SELECT "0 because Core Foundation "
"types are not classes in Objective-C", (unsigned))
Expand Down Expand Up @@ -6765,7 +6735,6 @@ ERROR(nonobjc_not_allowed,none,
#undef OBJC_DIAG_SELECT_2
#undef OBJC_DIAG_SELECT
#undef OBJC_ATTR_SELECT
#undef FOREIGN_LANG_SELECT

//------------------------------------------------------------------------------
// MARK: @exclusivity
Expand Down
2 changes: 1 addition & 1 deletion include/swift/AST/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ inline SubstOptions operator|(SubstFlags lhs, SubstFlags rhs) {

/// Enumeration describing foreign languages to which Swift may be
/// bridged.
enum class ForeignLanguage : uint8_t {
enum class ForeignLanguage {
C,
ObjectiveC,
};
Expand Down
38 changes: 0 additions & 38 deletions include/swift/AST/TypeCheckRequests.h
Original file line number Diff line number Diff line change
Expand Up @@ -4875,44 +4875,6 @@ class TypeCheckObjCImplementationRequest
bool isCached() const { return true; }
};

/// Check @cdecl functions for compatibility with the foreign language.
class TypeCheckCDeclFunctionRequest
: public SimpleRequest<TypeCheckCDeclFunctionRequest,
evaluator::SideEffect(FuncDecl *FD,
CDeclAttr *attr),
RequestFlags::Cached> {
public:
using SimpleRequest::SimpleRequest;

private:
friend SimpleRequest;

evaluator::SideEffect
evaluate(Evaluator &evaluator, FuncDecl *FD, CDeclAttr *attr) const;

public:
bool isCached() const { return true; }
};

/// Check @cdecl enums for compatibility with C.
class TypeCheckCDeclEnumRequest
: public SimpleRequest<TypeCheckCDeclEnumRequest,
evaluator::SideEffect(EnumDecl *ED,
CDeclAttr *attr),
RequestFlags::Cached> {
public:
using SimpleRequest::SimpleRequest;

private:
friend SimpleRequest;

evaluator::SideEffect
evaluate(Evaluator &evaluator, EnumDecl *ED, CDeclAttr *attr) const;

public:
bool isCached() const { return true; }
};

void simple_display(llvm::raw_ostream &out, ASTNode node);
void simple_display(llvm::raw_ostream &out, Type value);
void simple_display(llvm::raw_ostream &out, const TypeRepr *TyR);
Expand Down
6 changes: 0 additions & 6 deletions include/swift/AST/TypeCheckerTypeIDZone.def
Original file line number Diff line number Diff line change
Expand Up @@ -554,12 +554,6 @@ SWIFT_REQUEST(TypeChecker, IsNonUserModuleRequest,
SWIFT_REQUEST(TypeChecker, TypeCheckObjCImplementationRequest,
unsigned(ExtensionDecl *),
Cached, NoLocationInfo)
SWIFT_REQUEST(TypeChecker, TypeCheckCDeclFunctionRequest,
evaluator::SideEffect(FunctionDecl *, CDeclAttr *),
Cached, NoLocationInfo)
SWIFT_REQUEST(TypeChecker, TypeCheckCDeclEnumRequest,
evaluator::SideEffect(EnumDecl *, CDeclAttr *),
Cached, NoLocationInfo)
SWIFT_REQUEST(TypeChecker, HasInitAccessorRequest,
bool(AbstractStorageDecl *), Cached,
NoLocationInfo)
Expand Down
3 changes: 0 additions & 3 deletions include/swift/Basic/Features.def
Original file line number Diff line number Diff line change
Expand Up @@ -520,9 +520,6 @@ EXPERIMENTAL_FEATURE(ClosureBodyMacro, true)
/// Allow declarations of Swift runtime symbols using @_silgen_name.
EXPERIMENTAL_FEATURE(AllowRuntimeSymbolDeclarations, true)

/// Allow use of `@cdecl`
EXPERIMENTAL_FEATURE(CDecl, true)

/// Optimize copies of ObjectiveC blocks.
EXPERIMENTAL_FEATURE(CopyBlockOptimization, true)

Expand Down
38 changes: 6 additions & 32 deletions include/swift/PrintAsClang/ClangMacros.def
Original file line number Diff line number Diff line change
Expand Up @@ -176,46 +176,20 @@ CLANG_MACRO_CONDITIONAL("SWIFT_ENUM_ATTR", "(_extensibility)", \
"__attribute__((enum_extensibility(_extensibility)))")

CLANG_MACRO_BODY("SWIFT_ENUM", \
"# if (defined(__cplusplus) && __cplusplus >= 201103L) || " \
" (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || " \
" __has_feature(objc_fixed_enum)\n" \
"# define SWIFT_ENUM(_type, _name, _extensibility) " \
"# define SWIFT_ENUM(_type, _name, _extensibility) " \
"enum _name : _type _name; " \
"enum SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type\n" \
"# if __has_feature(generalized_swift_name)\n" \
"# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) " \
"enum _name : _type _name SWIFT_COMPILE_NAME(SWIFT_NAME); " \
"enum SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_ENUM_ATTR(_extensibility) " \
"SWIFT_ENUM_EXTRA _name : _type\n" \
"# else\n" \
"# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) " \
"SWIFT_ENUM(_type, _name, _extensibility)\n" \
"# endif\n" \
"# if __has_feature(generalized_swift_name)\n" \
"# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) " \
"enum _name : _type _name SWIFT_COMPILE_NAME(SWIFT_NAME); " \
"enum SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_ENUM_ATTR(_extensibility) " \
"SWIFT_ENUM_EXTRA _name : _type\n" \
"# else\n" \
"# define SWIFT_ENUM(_type, _name, _extensibility) _type _name; enum \n" \
"# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) " \
"SWIFT_ENUM(_type, _name, _extensibility)\n" \
"# endif")
CLANG_MACRO_DEFINED("SWIFT_ENUM_NAMED")

CLANG_MACRO_BODY("SWIFT_ENUM_TAG", \
"# if (defined(__cplusplus) && __cplusplus >= 201103L) || " \
" (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || " \
" __has_feature(objc_fixed_enum)\n" \
"# define SWIFT_ENUM_TAG enum\n" \
"# else\n" \
"# define SWIFT_ENUM_TAG\n" \
"# endif")

CLANG_MACRO_BODY("SWIFT_ENUM_FWD_DECL", \
"# if (defined(__cplusplus) && __cplusplus >= 201103L) || " \
" (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || " \
" __has_feature(objc_fixed_enum)\n" \
"# define SWIFT_ENUM_FWD_DECL(_type, _name) enum _name : _type _name;\n" \
"# else\n" \
"# define SWIFT_ENUM_FWD_DECL(_type, _name) _type _name;\n" \
"# endif")

CLANG_MACRO("SWIFT_UNAVAILABLE", , "__attribute__((unavailable))")
CLANG_MACRO("SWIFT_UNAVAILABLE_MSG", "(msg)", "__attribute__((unavailable(msg)))")

Expand Down
4 changes: 1 addition & 3 deletions lib/AST/Attr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1799,9 +1799,7 @@ StringRef DeclAttribute::getAttrName() const {
case DeclAttrKind::Alignment:
return "_alignment";
case DeclAttrKind::CDecl:
if (cast<CDeclAttr>(this)->Underscored)
return "_cdecl";
return "cdecl";
return "_cdecl";
case DeclAttrKind::SwiftNativeObjCRuntimeBase:
return "_swift_native_objc_runtime_base";
case DeclAttrKind::Semantics:
Expand Down
Loading