Skip to content

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

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

Open
wants to merge 39 commits into
base: release/6.2
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
221a6f0
Sema: Requestify most checks on @_cdecl
xymus Mar 28, 2025
3209730
Parser: Intro @cdecl attribute and gate it behind feature flag CDecl
xymus Apr 1, 2025
2647a8e
Serialization: Read and write the underscored bit for @cdecl
xymus Apr 8, 2025
732918d
Sema: Abstracted service for @cdecl style attributes
xymus Apr 4, 2025
41f126f
Sema: Basic type-checking of @cdecl on global functions
xymus Apr 7, 2025
731826f
Sema: Update other tests for newly more precise diagnostics
xymus Apr 11, 2025
e38fd7f
Sema: Simplify tracking the foreign language of an @objc decl
xymus Apr 17, 2025
fcae4f6
PrintAsObjc Test: Test compatibility headers for C
xymus Apr 10, 2025
8d32818
PrintAsClang: Intro and use getKnownType for C compatibility
xymus Apr 14, 2025
4b7cb77
PrintAsClang: Print @cdecl in their own block in compatibility headers
xymus Apr 1, 2025
8aa538a
PrintAsObjC Test: Don't use -fobjc-arc when targeting the C language
xymus Apr 18, 2025
0db22ef
PrintAsObjC Test: Extract what needs Objective-C out of cdecl-official
xymus Apr 18, 2025
372dfe4
PrintAsClang: Ignore nullability attributes for C clients
xymus Apr 18, 2025
4d7ec58
PrintAsClang: Apply review comments to check on should print of @cdecl
xymus May 5, 2025
3343822
PrintAsObjC Test: Don't use blocks in the @cdecl test
xymus May 5, 2025
9b655df
PrintAsObjC Test: Don't use modules for C compatibility header tests
xymus May 5, 2025
e11afb5
PrintAsObjC Test: Test pointer types with @cdecl
xymus May 6, 2025
0600ddd
Sema: Use ForeignLanguage directly in diagnostic definitions
xymus May 14, 2025
eedc7c2
Sema: Update more diagnostics for @cdecl vs @objc
xymus May 13, 2025
596d925
PrintAsClang: Print `#include` for headers used from `@cdecl` functions
xymus May 6, 2025
9dcbd31
PrintAsObjC Tests: Update users of -emit-clang-header-nonmodular-include
xymus May 13, 2025
2252154
Parser: Accept `@cdecl` with an indentifier for the C name
xymus May 16, 2025
3a0ba5f
Sema: `@cdecl` functions C name defaults to the Swift name
xymus Jun 10, 2025
3b33531
ASTGen: Accept `@cdecl`
xymus May 15, 2025
43ac239
SILGen: Add test for `@cdecl` testing generated code and C name
xymus Jun 6, 2025
83c0667
Sema: Add missing range on notes about representability
xymus May 29, 2025
5c2efac
AST: Begin accepting @cdecl on enums (but not @_cdecl)
xymus Apr 17, 2025
076ae9e
Sema: Reject enums marked with both @cdecl and @objc
xymus Jun 2, 2025
1c5c76f
Sema: Type-check @cdecl enums
xymus Jun 2, 2025
ba4cd11
PrintAsClang: Print @cdecl enums in the compatibility header
xymus Jun 2, 2025
6750320
PrintAsClang: Forward reference enums when used transitively
xymus Jun 4, 2025
b706558
SIL: Fix warning on unused variable
xymus Jun 26, 2025
c128db7
AST: Support `@cdecl` enums without an explicit C name
xymus Jun 10, 2025
1ac5550
AST: Fix crash on references to @cdecl enums at code generation
xymus Jul 1, 2025
3a3abe0
PrintAsObjC: Add visibilty test for @cdecl with app vs library behavior
xymus Jul 1, 2025
12acb5e
Tests: Update all @cdecl tests to use the identifier format
xymus Jul 3, 2025
c0d0cf5
Parser: Reject `@cdecl` attributes with the string format
xymus Jul 3, 2025
9f767b2
Features: Enable the experimental feature CDecl in production
xymus Jul 3, 2025
c4b42d8
PrintAsObjC Test: Ignore poison directories warnings for C
xymus May 5, 2025
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: 3 additions & 2 deletions include/swift/AST/ASTBridging.h
Original file line number Diff line number Diff line change
Expand Up @@ -949,11 +949,12 @@ BridgedBackDeployedAttr BridgedBackDeployedAttr_createParsed(
BridgedSourceRange cRange, BridgedPlatformKind cPlatform,
BridgedVersionTuple cVersion);

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

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

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

/// 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());
return new (ctx) CDeclAttr(Name, AtLoc, Range, isImplicit(),
Underscored);
}

bool isEquivalent(const CDeclAttr *other, Decl *attachedTo) const {
Expand Down
5 changes: 5 additions & 0 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -8172,6 +8172,11 @@ 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: 2 additions & 1 deletion include/swift/AST/DeclAttr.def
Original file line number Diff line number Diff line change
Expand Up @@ -365,9 +365,10 @@ SIMPLE_DECL_ATTR(_show_in_interface, ShowInInterface,
62)

DECL_ATTR(_cdecl, CDecl,
OnFunc | OnAccessor,
OnFunc | OnAccessor | OnEnum,
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: 1 addition & 0 deletions include/swift/AST/DiagnosticsCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ namespace swift {
} // end namespace detail

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

namespace diag {

Expand Down
3 changes: 3 additions & 0 deletions include/swift/AST/DiagnosticsParse.def
Original file line number Diff line number Diff line change
Expand Up @@ -1529,6 +1529,9 @@ 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: 56 additions & 25 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -2051,11 +2051,17 @@ WARNING(wrap_objc_implementation_will_become_error,none,
(DiagnosticInfo *))

ERROR(cdecl_not_at_top_level,none,
"@_cdecl can only be applied to global functions", ())
"%0 can only be applied to global functions", (DeclAttribute))
ERROR(cdecl_empty_name,none,
"@_cdecl symbol name cannot be empty", ())
"%0 symbol name cannot be empty", (DeclAttribute))
ERROR(cdecl_throws,none,
"raising errors from '@_cdecl' functions is not supported", ())
"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'",
())

// @_used and @_section
ERROR(section_linkage_markers_disabled,none,
Expand Down Expand Up @@ -3736,9 +3742,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,
"'@objc' enum must declare an integer raw type", ())
"'%0' enum must declare an integer raw type", (DeclAttribute))
ERROR(objc_enum_raw_type_not_integer,none,
"'@objc' enum raw type %0 is not an integer type", (Type))
"'%0' enum raw type %1 is not an integer type", (DeclAttribute, 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 @@ -5513,10 +5519,14 @@ 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 Objective-C", ())
"'async' function types cannot be represented "
"in %" FOREIGN_LANG_SELECT "0", (ForeignLanguage))
ERROR(actor_isolated_objc,none,
"actor-isolated %kind0 cannot be '@objc'",
(const ValueDecl *))
Expand Down Expand Up @@ -6523,7 +6533,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 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 '@_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 @@ -6556,25 +6566,36 @@ 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 Objective-C", ())
"empty tuple type cannot be represented in %" FOREIGN_LANG_SELECT "0",
(ForeignLanguage))
NOTE(not_objc_non_trivial_cxx_class,none,
"non-trivial C++ classes cannot be represented in Objective-C", ())
"non-trivial C++ classes cannot be represented in "
"%" FOREIGN_LANG_SELECT "0",
(ForeignLanguage))
NOTE(not_objc_tuple,none,
"tuples cannot be represented in Objective-C", ())
"tuples cannot be represented in %" FOREIGN_LANG_SELECT "0",
(ForeignLanguage))
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 Objective-C", ())
"Swift structs cannot be represented in %" FOREIGN_LANG_SELECT "0",
(ForeignLanguage))
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 Objective-C", ())
"generic type parameters cannot be represented in "
"%" FOREIGN_LANG_SELECT "0", (ForeignLanguage))
NOTE(not_objc_function_type_param,none,
"function types cannot be represented in Objective-C unless their "
"parameters and returns can be", ())
"function types cannot be represented in %" FOREIGN_LANG_SELECT "0 "
"unless their parameters and returns can be", (ForeignLanguage))
NOTE(not_objc_function_type_throwing,none,
"throwing function types cannot be represented in Objective-C", ())
"throwing function types cannot be represented in "
"%" FOREIGN_LANG_SELECT "0", (ForeignLanguage))
NOTE(objc_inferring_on_objc_protocol_member,none,
"inferring '@objc' because the declaration is a member of "
"an '@objc' protocol", ())
Expand All @@ -6584,6 +6605,11 @@ 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 @@ -6596,20 +6622,24 @@ 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,
"method cannot be %" OBJC_ATTR_SELECT "0 because it has a variadic "
"parameter", (unsigned))
"%kindonly0 cannot be %" OBJC_ATTR_SELECT "1 because it has a variadic "
"parameter", (const AbstractFunctionDecl*, unsigned))
ERROR(objc_invalid_on_func_inout,none,
"method cannot be %" OBJC_ATTR_SELECT "0 because inout "
"parameters cannot be represented in Objective-C", (unsigned))
"%kindonly0 cannot be %" OBJC_ATTR_SELECT "1 because inout "
"parameters cannot be represented in %" FOREIGN_LANG_SELECT "2",
(const AbstractFunctionDecl*, unsigned, ForeignLanguage))
ERROR(objc_invalid_on_func_param_type,none,
"method cannot be %" OBJC_ATTR_SELECT "1 because the type of the "
"parameter %0 cannot be represented in Objective-C", (unsigned, unsigned))
"%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))
ERROR(objc_invalid_on_func_single_param_type,none,
"method cannot be %" OBJC_ATTR_SELECT "0 because the type of the "
"parameter cannot be represented in Objective-C", (unsigned))
"%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))
ERROR(objc_invalid_on_func_result_type,none,
"method cannot be %" OBJC_ATTR_SELECT "0 because its result type "
"cannot be represented in Objective-C", (unsigned))
"%kindonly0 cannot be %" OBJC_ATTR_SELECT "1 because its result type "
"cannot be represented in %" FOREIGN_LANG_SELECT "2",
(const AbstractFunctionDecl*, unsigned, ForeignLanguage))
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 @@ -6735,6 +6765,7 @@ 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 {
enum class ForeignLanguage : uint8_t {
C,
ObjectiveC,
};
Expand Down
38 changes: 38 additions & 0 deletions include/swift/AST/TypeCheckRequests.h
Original file line number Diff line number Diff line change
Expand Up @@ -4875,6 +4875,44 @@ 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: 6 additions & 0 deletions include/swift/AST/TypeCheckerTypeIDZone.def
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,12 @@ 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: 3 additions & 0 deletions include/swift/Basic/Features.def
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,9 @@ 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: 32 additions & 6 deletions include/swift/PrintAsClang/ClangMacros.def
Original file line number Diff line number Diff line change
Expand Up @@ -176,20 +176,46 @@ CLANG_MACRO_CONDITIONAL("SWIFT_ENUM_ATTR", "(_extensibility)", \
"__attribute__((enum_extensibility(_extensibility)))")

CLANG_MACRO_BODY("SWIFT_ENUM", \
"# define SWIFT_ENUM(_type, _name, _extensibility) " \
"# if (defined(__cplusplus) && __cplusplus >= 201103L) || " \
" (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || " \
" __has_feature(objc_fixed_enum)\n" \
"# 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" \
"# 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" \
"# 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: 3 additions & 1 deletion lib/AST/Attr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1799,7 +1799,9 @@ StringRef DeclAttribute::getAttrName() const {
case DeclAttrKind::Alignment:
return "_alignment";
case DeclAttrKind::CDecl:
return "_cdecl";
if (cast<CDeclAttr>(this)->Underscored)
return "_cdecl";
return "cdecl";
case DeclAttrKind::SwiftNativeObjCRuntimeBase:
return "_swift_native_objc_runtime_base";
case DeclAttrKind::Semantics:
Expand Down
Loading