Skip to content

Commit 087aee8

Browse files
authored
Merge pull request #85396 from DougGregor/se-0497-export
[SE-0497] Implement @export attribute syntax
2 parents cc8e6fd + f606979 commit 087aee8

Some content is hidden

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

41 files changed

+410
-146
lines changed

include/swift/AST/ASTBridging.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "swift/AST/AttrKind.h"
2222
#include "swift/AST/DiagnosticKind.h"
2323
#include "swift/AST/DiagnosticList.h"
24+
#include "swift/AST/ExportKind.h"
2425
#include "swift/AST/GenericTypeParamKind.h"
2526
#include "swift/AST/Identifier.h"
2627
#include "swift/AST/LayoutConstraintKind.h"
@@ -956,6 +957,12 @@ BridgedImplementsAttr BridgedImplementsAttr_createParsed(
956957
swift::SourceRange range, BridgedTypeRepr cProtocolType,
957958
BridgedDeclNameRef cMemberName, BridgedDeclNameLoc cMemberNameLoc);
958959

960+
SWIFT_NAME("BridgedExportAttr.createParsed(_:atLoc:range:kind:)")
961+
BridgedExportAttr BridgedExportAttr_createParsed(BridgedASTContext cContext,
962+
swift::SourceLoc atLoc,
963+
swift::SourceRange range,
964+
swift::ExportKind kind);
965+
959966
SWIFT_NAME("BridgedInlineAttr.createParsed(_:atLoc:range:kind:)")
960967
BridgedInlineAttr BridgedInlineAttr_createParsed(BridgedASTContext cContext,
961968
swift::SourceLoc atLoc,

include/swift/AST/Attr.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "swift/AST/AvailabilityRange.h"
2424
#include "swift/AST/ConcreteDeclRef.h"
2525
#include "swift/AST/DeclNameLoc.h"
26+
#include "swift/AST/ExportKind.h"
2627
#include "swift/AST/Identifier.h"
2728
#include "swift/AST/KnownProtocols.h"
2829
#include "swift/AST/LifetimeDependence.h"
@@ -2955,6 +2956,35 @@ enum class NonSendableKind : uint8_t {
29552956
Assumed
29562957
};
29572958

2959+
/// Specify whether the declaration should be exported as an interface or
2960+
/// an implementation.
2961+
class ExportAttr : public DeclAttribute {
2962+
public:
2963+
/// How this declaration is exported.
2964+
const ExportKind exportKind;
2965+
2966+
ExportAttr(SourceLoc atLoc, SourceRange range, ExportKind exportKind,
2967+
bool implicit = false)
2968+
: DeclAttribute(DeclAttrKind::Export, atLoc, range, implicit),
2969+
exportKind(exportKind) {}
2970+
2971+
ExportAttr(ExportKind exportKind, bool implicit = false)
2972+
: ExportAttr(SourceLoc(), SourceRange(), exportKind, implicit) { }
2973+
2974+
static bool classof(const DeclAttribute *DA) {
2975+
return DA->getKind() == DeclAttrKind::Export;
2976+
}
2977+
2978+
/// Create a copy of this attribute.
2979+
ExportAttr *clone(ASTContext &ctx) const {
2980+
return new (ctx) ExportAttr(AtLoc, Range, exportKind, isImplicit());
2981+
}
2982+
2983+
bool isEquivalent(const ExportAttr *other, Decl *attachedTo) const {
2984+
return exportKind == other->exportKind;
2985+
}
2986+
};
2987+
29582988
/// Marks a declaration as explicitly non-Sendable.
29592989
class NonSendableAttr : public DeclAttribute {
29602990
public:

include/swift/AST/Decl.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1085,12 +1085,22 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl>, public Swi
10851085
/// behaviors for it and, if it's an extension, its members.
10861086
bool isObjCImplementation() const;
10871087

1088+
/// True if this declaration should always have its implementation made
1089+
/// available to the client, and not have an ABI symbol.
1090+
///
1091+
/// This can be spelled with @export(implementation) or the historical
1092+
/// @_alwaysEmitIntoClient.
1093+
bool isAlwaysEmittedIntoClient() const;
1094+
10881095
/// True if this declaration should never have its implementation made
10891096
/// available to any client. This overrides cross-module optimization and
10901097
/// optimizations that might use the implementation, such that the only
10911098
/// implementation of this function is the one compiled into its owning
10921099
/// module. Practically speaking, this prohibits serialization of the SIL
10931100
/// for this definition.
1101+
///
1102+
/// This can be spelled with @export(interface) or the historical
1103+
/// @_neverEmitIntoClient.
10941104
bool isNeverEmittedIntoClient() const;
10951105

10961106
using AuxiliaryDeclCallback = llvm::function_ref<void(Decl *)>;

include/swift/AST/DeclAttr.def

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -558,7 +558,10 @@ SIMPLE_DECL_ATTR(noDerivative, NoDerivative,
558558
ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove | ForbiddenInABIAttr,
559559
100)
560560

561-
// Unused '101'
561+
DECL_ATTR(export, Export,
562+
OnVar | OnSubscript | OnAbstractFunction,
563+
ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr,
564+
101)
562565

563566
CONTEXTUAL_SIMPLE_DECL_ATTR(actor, Actor,
564567
OnClass,

include/swift/AST/DiagnosticsSema.def

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4170,6 +4170,10 @@ ERROR(final_not_allowed_here,none,
41704170
"'final' may only be applied to classes, properties, methods, and "
41714171
"subscripts", ())
41724172

4173+
ERROR(attr_incompatible_with_attr,none,
4174+
"'%0' cannot be used with '%1'",
4175+
(DeclAttribute, DeclAttribute))
4176+
41734177
ERROR(attr_incompatible_with_non_final,none,
41744178
"'%0' cannot be applied to a non-final %kindonly1",
41754179
(DeclAttribute, const ValueDecl *))
@@ -5369,7 +5373,7 @@ GROUPED_ERROR(opaque_type_unsupported_availability,OpaqueTypeInference,none,
53695373
"a default argument value|" \
53705374
"a property initializer in a '@frozen' type|" \
53715375
"a '@backDeployed' function|" \
5372-
"an embedded function not marked '@_neverEmitIntoClient'}"
5376+
"an embedded function not marked '@export(interface)'}"
53735377

53745378
ERROR(discard_wrong_context_decl,none,
53755379
"'discard' statement cannot appear in %kindonly0",

include/swift/AST/ExportKind.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//===-- AST/ExportKind.h ----------------------------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2025 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_AST_EXPORT_KIND_H
14+
#define SWIFT_AST_EXPORT_KIND_H
15+
16+
/// `ExportKind.h` is imported into Swift. Be *very* careful with what you
17+
/// include here and keep these includes minimal!
18+
///
19+
/// See include guidelines and caveats in `BasicBridging.h`.
20+
#include "swift/Basic/SwiftBridging.h"
21+
22+
namespace swift {
23+
24+
/// How a particular declaration is exported per the @export attribute.
25+
enum class ENUM_EXTENSIBILITY_ATTR(closed) ExportKind {
26+
/// Export only the interface to this declaration (e.g., as a callable symbol)
27+
/// and never it's definition.
28+
Interface SWIFT_NAME("interface"),
29+
30+
/// Export only the implementation of this declaration and do not produce a
31+
/// symbol.
32+
Implementation SWIFT_NAME("implementation"),
33+
};
34+
35+
} // namespace swift
36+
37+
#endif // SWIFT_AST_EXPORT_KIND_H

include/swift/AST/KnownIdentifiers.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,8 @@ IDENTIFIER(always)
332332
IDENTIFIER_(_always)
333333
IDENTIFIER_(assumed)
334334
IDENTIFIER(checked)
335+
IDENTIFIER(interface)
336+
IDENTIFIER(implementation)
335337
IDENTIFIER(never)
336338
IDENTIFIER(none)
337339
IDENTIFIER(safe)

include/swift/SIL/SILFunction.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1421,7 +1421,7 @@ class SILFunction
14211421
return false;
14221422

14231423
auto *V = getLocation().getAsASTNode<ValueDecl>();
1424-
return V && V->getAttrs().hasAttribute<AlwaysEmitIntoClientAttr>();
1424+
return V && V->isAlwaysEmittedIntoClient();
14251425
}
14261426

14271427
/// Return whether this function has attribute @used on it

lib/APIDigester/ModuleAnalyzerNodes.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1764,7 +1764,7 @@ SDKContext::shouldIgnore(Decl *D, const Decl* Parent) const {
17641764
// Exclude decls with @_alwaysEmitIntoClient if we are checking ABI.
17651765
// These decls are considered effectively public because they are usable
17661766
// from inline, so we have to manually exclude them here.
1767-
if (D->getAttrs().hasAttribute<AlwaysEmitIntoClientAttr>())
1767+
if (D->isAlwaysEmittedIntoClient())
17681768
return true;
17691769
} else {
17701770
if (D->isPrivateSystemDecl(false))

lib/AST/ASTDumper.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,15 @@ static StringRef getDumpString(InlineKind kind) {
590590
}
591591
llvm_unreachable("unhandled InlineKind");
592592
}
593+
static StringRef getDumpString(ExportKind kind) {
594+
switch (kind) {
595+
case ExportKind::Interface:
596+
return "interface";
597+
case ExportKind::Implementation:
598+
return "implementation";
599+
}
600+
llvm_unreachable("unhandled ExportKind");
601+
}
593602
static StringRef getDumpString(MacroRole role) {
594603
return getMacroRoleString(role);
595604
}
@@ -5306,6 +5315,11 @@ class PrintAttribute : public AttributeVisitor<PrintAttribute, void, Label>,
53065315
printField(Attr->getKind(), Label::always("kind"));
53075316
printFoot();
53085317
}
5318+
void visitExportAttr(ExportAttr *Attr, Label label) {
5319+
printCommon(Attr, "export_attr", label);
5320+
printField(Attr->exportKind, Label::always("kind"));
5321+
printFoot();
5322+
}
53095323
void visitLifetimeAttr(LifetimeAttr *Attr, Label label) {
53105324
printCommon(Attr, "lifetime_attr", label);
53115325
// FIXME: Improve, more detailed info.

0 commit comments

Comments
 (0)