Skip to content

Commit ce07ce2

Browse files
committed
frontend: add basic support for @_spi_available
1 parent 91410d8 commit ce07ce2

File tree

12 files changed

+60
-30
lines changed

12 files changed

+60
-30
lines changed

include/swift/AST/Attr.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -632,14 +632,16 @@ class AvailableAttr : public DeclAttribute {
632632
const llvm::VersionTuple &Obsoleted,
633633
SourceRange ObsoletedRange,
634634
PlatformAgnosticAvailabilityKind PlatformAgnostic,
635-
bool Implicit)
635+
bool Implicit,
636+
bool IsSPI)
636637
: DeclAttribute(DAK_Available, AtLoc, Range, Implicit),
637638
Message(Message), Rename(Rename), RenameDecl(RenameDecl),
638639
INIT_VER_TUPLE(Introduced), IntroducedRange(IntroducedRange),
639640
INIT_VER_TUPLE(Deprecated), DeprecatedRange(DeprecatedRange),
640641
INIT_VER_TUPLE(Obsoleted), ObsoletedRange(ObsoletedRange),
641642
PlatformAgnostic(PlatformAgnostic),
642-
Platform(Platform)
643+
Platform(Platform),
644+
IsSPI(IsSPI)
643645
{}
644646

645647
#undef INIT_VER_TUPLE
@@ -685,6 +687,9 @@ class AvailableAttr : public DeclAttribute {
685687
/// The platform of the availability.
686688
const PlatformKind Platform;
687689

690+
/// Whether this is available as SPI.
691+
const bool IsSPI;
692+
688693
/// Whether this is a language-version-specific entity.
689694
bool isLanguageVersionSpecific() const;
690695

include/swift/AST/Availability.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,9 +209,12 @@ class UnavailabilityReason {
209209
/// [lattice]: http://mathworld.wolfram.com/Lattice.html
210210
class AvailabilityContext {
211211
VersionRange OSVersion;
212+
llvm::Optional<bool> SPI;
212213
public:
213214
/// Creates a context that requires certain versions of the target OS.
214-
explicit AvailabilityContext(VersionRange OSVersion) : OSVersion(OSVersion) {}
215+
explicit AvailabilityContext(VersionRange OSVersion,
216+
llvm::Optional<bool> SPI = llvm::None)
217+
: OSVersion(OSVersion), SPI(SPI) {}
215218

216219
/// Creates a context that imposes the constraints of the ASTContext's
217220
/// deployment target.
@@ -291,6 +294,10 @@ class AvailabilityContext {
291294
void unionWith(AvailabilityContext other) {
292295
OSVersion.unionWith(other.getOSVersion());
293296
}
297+
298+
bool isAvailableAsSPI() const {
299+
return SPI && *SPI;
300+
}
294301
};
295302

296303

include/swift/AST/Decl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,6 +1030,8 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
10301030
// an @_spi context.
10311031
bool isSPI() const;
10321032

1033+
bool isAvailableAsSPI() const;
1034+
10331035
// List the SPI groups declared with @_spi or inherited by this decl.
10341036
//
10351037
// SPI groups are inherited from the parent contexts only if the local decl

lib/AST/Attr.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ DeclAttrKind DeclAttribute::getAttrKindFromString(StringRef Str) {
126126
#define DECL_ATTR(X, CLASS, ...) .Case(#X, DAK_##CLASS)
127127
#define DECL_ATTR_ALIAS(X, CLASS) .Case(#X, DAK_##CLASS)
128128
#include "swift/AST/Attr.def"
129+
.Case("_spi_available", DAK_Available)
129130
.Default(DAK_Count);
130131
}
131132

@@ -1599,7 +1600,7 @@ AvailableAttr::createPlatformAgnostic(ASTContext &C,
15991600
NoVersion, SourceRange(),
16001601
NoVersion, SourceRange(),
16011602
Obsoleted, SourceRange(),
1602-
Kind, /* isImplicit */ false);
1603+
Kind, /* isImplicit */ false, /*SPI*/false);
16031604
}
16041605

16051606
AvailableAttr *AvailableAttr::createForAlternative(
@@ -1610,7 +1611,7 @@ AvailableAttr *AvailableAttr::createForAlternative(
16101611
NoVersion, SourceRange(),
16111612
NoVersion, SourceRange(),
16121613
NoVersion, SourceRange(),
1613-
PlatformAgnosticAvailabilityKind::None, /*Implicit=*/true);
1614+
PlatformAgnosticAvailabilityKind::None, /*Implicit=*/true, /*SPI*/false);
16141615
}
16151616

16161617
bool AvailableAttr::isActivePlatform(const ASTContext &ctx) const {
@@ -1628,7 +1629,8 @@ AvailableAttr *AvailableAttr::clone(ASTContext &C, bool implicit) const {
16281629
Obsoleted ? *Obsoleted : llvm::VersionTuple(),
16291630
implicit ? SourceRange() : ObsoletedRange,
16301631
PlatformAgnostic,
1631-
implicit);
1632+
implicit,
1633+
IsSPI);
16321634
}
16331635

16341636
Optional<OriginallyDefinedInAttr::ActiveVersion>

lib/AST/Availability.cpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ struct InferredAvailability {
4141
Optional<llvm::VersionTuple> Introduced;
4242
Optional<llvm::VersionTuple> Deprecated;
4343
Optional<llvm::VersionTuple> Obsoleted;
44+
bool IsSPI = false;
4445
};
4546

4647
/// The type of a function that merges two version tuples.
@@ -51,17 +52,20 @@ typedef const llvm::VersionTuple &(*MergeFunction)(
5152

5253
/// Apply a merge function to two optional versions, returning the result
5354
/// in Inferred.
54-
static void
55+
static bool
5556
mergeIntoInferredVersion(const Optional<llvm::VersionTuple> &Version,
5657
Optional<llvm::VersionTuple> &Inferred,
5758
MergeFunction Merge) {
5859
if (Version.hasValue()) {
5960
if (Inferred.hasValue()) {
6061
Inferred = Merge(Inferred.getValue(), Version.getValue());
62+
return *Inferred == *Version;
6163
} else {
6264
Inferred = Version;
65+
return true;
6366
}
6467
}
68+
return false;
6569
}
6670

6771
/// Merge an attribute's availability with an existing inferred availability
@@ -75,7 +79,9 @@ static void mergeWithInferredAvailability(const AvailableAttr *Attr,
7579
static_cast<unsigned>(Attr->getPlatformAgnosticAvailability())));
7680

7781
// The merge of two introduction versions is the maximum of the two versions.
78-
mergeIntoInferredVersion(Attr->Introduced, Inferred.Introduced, std::max);
82+
if (mergeIntoInferredVersion(Attr->Introduced, Inferred.Introduced, std::max)) {
83+
Inferred.IsSPI = Attr->IsSPI;
84+
}
7985

8086
// The merge of deprecated and obsoleted versions takes the minimum.
8187
mergeIntoInferredVersion(Attr->Deprecated, Inferred.Deprecated, std::min);
@@ -103,7 +109,8 @@ createAvailableAttr(PlatformKind Platform,
103109
Introduced, /*IntroducedRange=*/SourceRange(),
104110
Deprecated, /*DeprecatedRange=*/SourceRange(),
105111
Obsoleted, /*ObsoletedRange=*/SourceRange(),
106-
Inferred.PlatformAgnostic, /*Implicit=*/true);
112+
Inferred.PlatformAgnostic, /*Implicit=*/true,
113+
Inferred.IsSPI);
107114
}
108115

109116
void AvailabilityInference::applyInferredAvailableAttrs(
@@ -173,7 +180,13 @@ AvailabilityInference::annotatedAvailableRange(const Decl *D, ASTContext &Ctx) {
173180
return None;
174181

175182
return AvailabilityContext{
176-
VersionRange::allGTE(bestAvailAttr->Introduced.getValue())};
183+
VersionRange::allGTE(bestAvailAttr->Introduced.getValue()),
184+
bestAvailAttr->IsSPI};
185+
}
186+
187+
bool Decl::isAvailableAsSPI() const {
188+
return AvailabilityInference::availableRange(this, getASTContext())
189+
.isAvailableAsSPI();
177190
}
178191

179192
AvailabilityContext

lib/ClangImporter/ImportDecl.cpp

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1936,7 +1936,8 @@ static void applyAvailableAttribute(Decl *decl, AvailabilityContext &info,
19361936
/*Obsoleted=*/noVersion,
19371937
/*ObsoletedRange*/SourceRange(),
19381938
PlatformAgnosticAvailabilityKind::None,
1939-
/*Implicit=*/false);
1939+
/*Implicit=*/false,
1940+
/*SPI*/false);
19401941

19411942
decl->getAttrs().add(AvAttr);
19421943
}
@@ -2681,7 +2682,8 @@ namespace {
26812682
/*Deprecated*/llvm::VersionTuple(), SourceRange(),
26822683
/*Obsoleted*/llvm::VersionTuple(), SourceRange(),
26832684
PlatformAgnosticAvailabilityKind::SwiftVersionSpecific,
2684-
/*Implicit*/false);
2685+
/*Implicit*/false,
2686+
/*SPI*/false);
26852687
}
26862688
}
26872689

@@ -9013,18 +9015,10 @@ void ClangImporter::Implementation::importAttributes(
90139015
AnyUnavailable = true;
90149016
}
90159017

9016-
if (EnableClangSPI) {
9017-
if (isUsingMacroName(getClangASTContext().getSourceManager(),
9018+
auto IsSPI = isUsingMacroName(getClangASTContext().getSourceManager(),
90189019
avail->getLoc(), "SPI_AVAILABLE") ||
9019-
isUsingMacroName(getClangASTContext().getSourceManager(),
9020-
avail->getLoc(), "__SPI_AVAILABLE")) {
9021-
// The decl has been marked as SPI in the header by using the SPI macro,
9022-
// thus we add the SPI attribute to it with a default group name.
9023-
MappedDecl->getAttrs().add(SPIAccessControlAttr::create(SwiftContext,
9024-
SourceLoc(), SourceRange(),
9025-
SwiftContext.getIdentifier(CLANG_MODULE_DEFUALT_SPI_GROUP_NAME)));
9026-
}
9027-
}
9020+
isUsingMacroName(getClangASTContext().getSourceManager(),
9021+
avail->getLoc(), "__SPI_AVAILABLE");
90289022

90299023
StringRef message = avail->getMessage();
90309024

@@ -9065,7 +9059,8 @@ void ClangImporter::Implementation::importAttributes(
90659059
/*DeprecatedRange=*/SourceRange(),
90669060
obsoleted,
90679061
/*ObsoletedRange=*/SourceRange(),
9068-
PlatformAgnostic, /*Implicit=*/false);
9062+
PlatformAgnostic, /*Implicit=*/false,
9063+
IsSPI);
90699064

90709065
MappedDecl->getAttrs().add(AvAttr);
90719066
}

lib/Parse/ParseDecl.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,8 @@ ParserResult<AvailableAttr> Parser::parseExtendedAvailabilitySpecList(
573573
Deprecated.Version, Deprecated.Range,
574574
Obsoleted.Version, Obsoleted.Range,
575575
PlatformAgnostic,
576-
/*Implicit=*/false);
576+
/*Implicit=*/false,
577+
AttrName == "_spi_available");
577578
return makeParserResult(Attr);
578579

579580
}
@@ -858,7 +859,8 @@ bool Parser::parseAvailability(
858859
/*DeprecatedRange=*/SourceRange(),
859860
/*Obsoleted=*/llvm::VersionTuple(),
860861
/*ObsoletedRange=*/SourceRange(), PlatformAgnostic,
861-
/*Implicit=*/false));
862+
/*Implicit=*/false,
863+
AttrName == "_spi_available"));
862864
}
863865

864866
return true;

lib/Sema/TypeCheckAccess.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1545,7 +1545,7 @@ swift::getDisallowedOriginKind(const Decl *decl,
15451545
}
15461546
// Implementation-only imported, cannot be reexported.
15471547
return DisallowedOriginKind::ImplementationOnly;
1548-
} else if (decl->isSPI() && !where.isSPI()) {
1548+
} else if ((decl->isSPI() || decl->isAvailableAsSPI()) && !where.isSPI()) {
15491549
// SPI can only be exported in SPI.
15501550
return where.getDeclContext()->getParentModule() == M ?
15511551
DisallowedOriginKind::SPILocal :

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4344,6 +4344,7 @@ ProtocolConformance *GetImplicitSendableRequest::evaluate(
43444344
NoVersion, SourceRange(),
43454345
NoVersion, SourceRange(),
43464346
PlatformAgnosticAvailabilityKind::Unavailable,
4347+
false,
43474348
false);
43484349

43494350
// Conformance availability is currently tied to the declaring extension.

lib/Serialization/Deserialization.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4362,6 +4362,7 @@ DeclDeserializer::readAvailable_DECL_ATTR(SmallVectorImpl<uint64_t> &scratch,
43624362
bool isUnavailable;
43634363
bool isDeprecated;
43644364
bool isPackageDescriptionVersionSpecific;
4365+
bool isSPI;
43654366
DEF_VER_TUPLE_PIECES(Introduced);
43664367
DEF_VER_TUPLE_PIECES(Deprecated);
43674368
DEF_VER_TUPLE_PIECES(Obsoleted);
@@ -4371,7 +4372,7 @@ DeclDeserializer::readAvailable_DECL_ATTR(SmallVectorImpl<uint64_t> &scratch,
43714372
// Decode the record, pulling the version tuple information.
43724373
serialization::decls_block::AvailableDeclAttrLayout::readRecord(
43734374
scratch, isImplicit, isUnavailable, isDeprecated,
4374-
isPackageDescriptionVersionSpecific, LIST_VER_TUPLE_PIECES(Introduced),
4375+
isPackageDescriptionVersionSpecific, isSPI, LIST_VER_TUPLE_PIECES(Introduced),
43754376
LIST_VER_TUPLE_PIECES(Deprecated), LIST_VER_TUPLE_PIECES(Obsoleted),
43764377
platform, renameDeclID, messageSize, renameSize);
43774378

@@ -4406,7 +4407,7 @@ DeclDeserializer::readAvailable_DECL_ATTR(SmallVectorImpl<uint64_t> &scratch,
44064407
auto attr = new (ctx) AvailableAttr(
44074408
SourceLoc(), SourceRange(), (PlatformKind)platform, message, rename,
44084409
renameDecl, Introduced, SourceRange(), Deprecated, SourceRange(),
4409-
Obsoleted, SourceRange(), platformAgnostic, isImplicit);
4410+
Obsoleted, SourceRange(), platformAgnostic, isImplicit, isSPI);
44104411
return attr;
44114412
}
44124413

0 commit comments

Comments
 (0)