Skip to content

Commit 94a8526

Browse files
authored
Merge pull request #80616 from tshortli/availability-domain-serialization
Serialization: Encode custom availability domains
2 parents 701c3ff + 10c910e commit 94a8526

21 files changed

+328
-336
lines changed

include/swift/AST/AvailabilityDomain.h

+19-7
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
namespace swift {
3333
class ASTContext;
3434
class CustomAvailabilityDomain;
35+
class Decl;
3536
class DeclContext;
3637
class ModuleDecl;
3738

@@ -148,6 +149,11 @@ class AvailabilityDomain final {
148149
return AvailabilityDomain(Kind::Embedded);
149150
}
150151

152+
/// If `decl` represents an availability domain, returns the corresponding
153+
/// `AvailabilityDomain` value. Otherwise, returns `std::nullopt`.
154+
static std::optional<AvailabilityDomain> forCustom(Decl *decl,
155+
const ASTContext &ctx);
156+
151157
static AvailabilityDomain forCustom(const CustomAvailabilityDomain *domain) {
152158
return AvailabilityDomain(domain);
153159
}
@@ -236,6 +242,10 @@ class AvailabilityDomain final {
236242
/// Returns the string to use when printing an `@available` attribute.
237243
llvm::StringRef getNameForAttributePrinting() const;
238244

245+
/// Returns the decl that represents the domain, or `nullptr` if the domain
246+
/// does not have a decl.
247+
Decl *getDecl() const;
248+
239249
/// Returns the module that the domain belongs to, if it is a custom domain.
240250
ModuleDecl *getModule() const;
241251

@@ -307,24 +317,26 @@ class CustomAvailabilityDomain : public llvm::FoldingSetNode {
307317
Identifier name;
308318
Kind kind;
309319
ModuleDecl *mod;
320+
Decl *decl;
310321

311-
CustomAvailabilityDomain(Identifier name, ModuleDecl *mod, Kind kind);
322+
CustomAvailabilityDomain(Identifier name, Kind kind, ModuleDecl *mod,
323+
Decl *decl);
312324

313325
public:
314-
static const CustomAvailabilityDomain *get(StringRef name, ModuleDecl *mod,
315-
Kind kind, const ASTContext &ctx);
326+
static const CustomAvailabilityDomain *get(StringRef name, Kind kind,
327+
ModuleDecl *mod, Decl *decl,
328+
const ASTContext &ctx);
316329

317330
Identifier getName() const { return name; }
318331
Kind getKind() const { return kind; }
319332
ModuleDecl *getModule() const { return mod; }
333+
Decl *getDecl() const { return decl; }
320334

321335
/// Uniquing for `ASTContext`.
322336
static void Profile(llvm::FoldingSetNodeID &ID, Identifier name,
323-
ModuleDecl *mod, Kind kind);
337+
ModuleDecl *mod);
324338

325-
void Profile(llvm::FoldingSetNodeID &ID) const {
326-
Profile(ID, name, mod, kind);
327-
}
339+
void Profile(llvm::FoldingSetNodeID &ID) const { Profile(ID, name, mod); }
328340
};
329341

330342
/// Represents either a resolved availability domain or an identifier written

include/swift/Basic/Features.def

+1-1
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,7 @@ SUPPRESSIBLE_EXPERIMENTAL_FEATURE(ExecutionAttribute, false)
493493
ADOPTABLE_EXPERIMENTAL_FEATURE(AsyncCallerExecution, false)
494494

495495
/// Allow custom availability domains to be defined and referenced.
496-
SUPPRESSIBLE_EXPERIMENTAL_FEATURE(CustomAvailability, true)
496+
EXPERIMENTAL_FEATURE(CustomAvailability, true)
497497

498498
/// Allow isolated conformances.
499499
EXPERIMENTAL_FEATURE(IsolatedConformances, true)

lib/AST/ASTContext.cpp

+5-4
Original file line numberDiff line numberDiff line change
@@ -5866,11 +5866,11 @@ const AvailabilityContext::Storage *AvailabilityContext::Storage::get(
58665866
}
58675867

58685868
const CustomAvailabilityDomain *
5869-
CustomAvailabilityDomain::get(StringRef name, ModuleDecl *mod, Kind kind,
5870-
const ASTContext &ctx) {
5869+
CustomAvailabilityDomain::get(StringRef name, Kind kind, ModuleDecl *mod,
5870+
Decl *decl, const ASTContext &ctx) {
58715871
auto identifier = ctx.getIdentifier(name);
58725872
llvm::FoldingSetNodeID id;
5873-
CustomAvailabilityDomain::Profile(id, identifier, mod, kind);
5873+
CustomAvailabilityDomain::Profile(id, identifier, mod);
58745874

58755875
auto &foldingSet = ctx.getImpl().CustomAvailabilityDomains;
58765876
void *insertPos;
@@ -5880,7 +5880,8 @@ CustomAvailabilityDomain::get(StringRef name, ModuleDecl *mod, Kind kind,
58805880

58815881
void *mem = ctx.Allocate(sizeof(CustomAvailabilityDomain),
58825882
alignof(CustomAvailabilityDomain));
5883-
auto *newNode = ::new (mem) CustomAvailabilityDomain(identifier, mod, kind);
5883+
auto *newNode =
5884+
::new (mem) CustomAvailabilityDomain(identifier, kind, mod, decl);
58845885
foldingSet.InsertNode(newNode, insertPos);
58855886

58865887
return newNode;

lib/AST/ASTPrinter.cpp

-8
Original file line numberDiff line numberDiff line change
@@ -3302,14 +3302,6 @@ suppressingFeatureAddressableTypes(PrintOptions &options,
33023302
action();
33033303
}
33043304

3305-
static void
3306-
suppressingFeatureCustomAvailability(PrintOptions &options,
3307-
llvm::function_ref<void()> action) {
3308-
// FIXME: [availability] Save and restore a bit controlling whether
3309-
// @available attributes for custom domains are printed.
3310-
action();
3311-
}
3312-
33133305
static void
33143306
suppressingFeatureExecutionAttribute(PrintOptions &options,
33153307
llvm::function_ref<void()> action) {

lib/AST/AvailabilityDomain.cpp

+62-6
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,61 @@
1717
#include "swift/AST/Module.h"
1818
#include "swift/AST/TypeCheckRequests.h"
1919
#include "swift/Basic/Assertions.h"
20+
#include "clang/AST/ASTContext.h"
21+
#include "clang/AST/Decl.h"
2022
#include "llvm/ADT/StringSwitch.h"
2123

2224
using namespace swift;
2325

26+
CustomAvailabilityDomain::Kind
27+
getCustomDomainKind(clang::FeatureAvailKind featureAvailKind) {
28+
switch (featureAvailKind) {
29+
case clang::FeatureAvailKind::None:
30+
llvm_unreachable("unexpected kind");
31+
case clang::FeatureAvailKind::Available:
32+
return CustomAvailabilityDomain::Kind::Enabled;
33+
case clang::FeatureAvailKind::Unavailable:
34+
return CustomAvailabilityDomain::Kind::Disabled;
35+
case clang::FeatureAvailKind::Dynamic:
36+
return CustomAvailabilityDomain::Kind::Dynamic;
37+
}
38+
}
39+
40+
static const CustomAvailabilityDomain *
41+
customDomainForClangDecl(Decl *decl, const ASTContext &ctx) {
42+
auto *clangDecl = decl->getClangDecl();
43+
ASSERT(clangDecl);
44+
45+
auto featureInfo = clangDecl->getASTContext().getFeatureAvailInfo(
46+
const_cast<clang::Decl *>(clangDecl));
47+
48+
// Ensure the decl actually represents an availability domain.
49+
if (featureInfo.first.empty())
50+
return nullptr;
51+
52+
if (featureInfo.second.Kind == clang::FeatureAvailKind::None)
53+
return nullptr;
54+
55+
return CustomAvailabilityDomain::get(
56+
featureInfo.first, getCustomDomainKind(featureInfo.second.Kind),
57+
decl->getModuleContext(), decl, ctx);
58+
}
59+
60+
std::optional<AvailabilityDomain>
61+
AvailabilityDomain::forCustom(Decl *decl, const ASTContext &ctx) {
62+
if (!decl)
63+
return std::nullopt;
64+
65+
if (decl->hasClangNode()) {
66+
if (auto *customDomain = customDomainForClangDecl(decl, ctx))
67+
return AvailabilityDomain::forCustom(customDomain);
68+
} else {
69+
// FIXME: [availability] Handle Swift availability domains decls.
70+
}
71+
72+
return std::nullopt;
73+
}
74+
2475
std::optional<AvailabilityDomain>
2576
AvailabilityDomain::builtinDomainForString(StringRef string,
2677
const DeclContext *declContext) {
@@ -166,6 +217,13 @@ llvm::StringRef AvailabilityDomain::getNameForAttributePrinting() const {
166217
}
167218
}
168219

220+
Decl *AvailabilityDomain::getDecl() const {
221+
if (auto *customDomain = getCustomDomain())
222+
return customDomain->getDecl();
223+
224+
return nullptr;
225+
}
226+
169227
ModuleDecl *AvailabilityDomain::getModule() const {
170228
if (auto customDomain = getCustomDomain())
171229
return customDomain->getModule();
@@ -268,19 +326,17 @@ bool StableAvailabilityDomainComparator::operator()(
268326
}
269327
}
270328

271-
CustomAvailabilityDomain::CustomAvailabilityDomain(Identifier name,
272-
ModuleDecl *mod, Kind kind)
273-
: name(name), kind(kind), mod(mod) {
329+
CustomAvailabilityDomain::CustomAvailabilityDomain(Identifier name, Kind kind,
330+
ModuleDecl *mod, Decl *decl)
331+
: name(name), kind(kind), mod(mod), decl(decl) {
274332
ASSERT(!name.empty());
275333
ASSERT(mod);
276334
}
277335

278336
void CustomAvailabilityDomain::Profile(llvm::FoldingSetNodeID &ID,
279-
Identifier name, ModuleDecl *mod,
280-
Kind kind) {
337+
Identifier name, ModuleDecl *mod) {
281338
ID.AddPointer(name.getAsOpaquePointer());
282339
ID.AddPointer(mod);
283-
ID.AddInteger(static_cast<unsigned>(kind));
284340
}
285341

286342
std::optional<AvailabilityDomain>

lib/AST/FeatureSet.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -490,8 +490,10 @@ static bool usesFeatureCoroutineAccessors(Decl *decl) {
490490
}
491491

492492
static bool usesFeatureCustomAvailability(Decl *decl) {
493-
// FIXME: [availability] Check whether @available attributes for custom
494-
// domains are attached to the decl.
493+
for (auto attr : decl->getSemanticAvailableAttrs()) {
494+
if (attr.getDomain().isCustom())
495+
return true;
496+
}
495497
return false;
496498
}
497499

lib/ClangImporter/ClangImporter.cpp

+15-21
Original file line numberDiff line numberDiff line change
@@ -4090,35 +4090,29 @@ void ClangModuleUnit::lookupObjCMethods(
40904090

40914091
void ClangModuleUnit::lookupAvailabilityDomains(
40924092
Identifier identifier, SmallVectorImpl<AvailabilityDomain> &results) const {
4093-
auto lookupTable = owner.findLookupTable(clangModule);
4094-
if (!lookupTable)
4093+
auto domainName = identifier.str();
4094+
auto &ctx = getASTContext();
4095+
auto &clangASTContext = getClangASTContext();
4096+
4097+
auto domainInfo = clangASTContext.getFeatureAvailInfo(domainName);
4098+
if (domainInfo.Kind == clang::FeatureAvailKind::None)
40954099
return;
40964100

4097-
auto varDecl = lookupTable->lookupAvailabilityDomainDecl(identifier.str());
4101+
auto *varDecl = dyn_cast_or_null<clang::VarDecl>(domainInfo.Decl);
40984102
if (!varDecl)
40994103
return;
41004104

4101-
auto featureInfo = getClangASTContext().getFeatureAvailInfo(varDecl);
4102-
if (featureInfo.first.empty())
4105+
// The decl that was found may belong to a different Clang module.
4106+
if (varDecl->getOwningModule() != getClangModule())
41034107
return;
41044108

4105-
auto getDomainKind = [](clang::FeatureAvailKind featureAvailKind) {
4106-
switch (featureAvailKind) {
4107-
case clang::FeatureAvailKind::None:
4108-
llvm_unreachable("unexpected kind");
4109-
case clang::FeatureAvailKind::Available:
4110-
return CustomAvailabilityDomain::Kind::Enabled;
4111-
case clang::FeatureAvailKind::Unavailable:
4112-
return CustomAvailabilityDomain::Kind::Disabled;
4113-
case clang::FeatureAvailKind::Dynamic:
4114-
return CustomAvailabilityDomain::Kind::Dynamic;
4115-
}
4116-
};
4109+
auto *imported = ctx.getClangModuleLoader()->importDeclDirectly(varDecl);
4110+
if (!imported)
4111+
return;
41174112

4118-
auto domain = AvailabilityDomain::forCustom(CustomAvailabilityDomain::get(
4119-
featureInfo.first, getParentModule(),
4120-
getDomainKind(featureInfo.second.Kind), getASTContext()));
4121-
results.push_back(domain);
4113+
auto customDomain = AvailabilityDomain::forCustom(imported, ctx);
4114+
ASSERT(customDomain);
4115+
results.push_back(*customDomain);
41224116
}
41234117

41244118
void ClangModuleUnit::collectLinkLibraries(

0 commit comments

Comments
 (0)