Skip to content

Commit 494e597

Browse files
authored
Merge pull request #80641 from tshortli/availability-domain-serialization-6.2
[6.2] Serialization: Encode custom availability domains
2 parents fca7c65 + 38e56fc commit 494e597

21 files changed

+329
-338
lines changed

include/swift/AST/AvailabilityDomain.h

Lines changed: 19 additions & 7 deletions
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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,7 @@ SUPPRESSIBLE_EXPERIMENTAL_FEATURE(ExecutionAttribute, false)
490490
ADOPTABLE_EXPERIMENTAL_FEATURE(AsyncCallerExecution, false)
491491

492492
/// Allow custom availability domains to be defined and referenced.
493-
SUPPRESSIBLE_EXPERIMENTAL_FEATURE(CustomAvailability, true)
493+
EXPERIMENTAL_FEATURE(CustomAvailability, true)
494494

495495
/// Allow public enumerations to be extensible by default
496496
/// regardless of whether the module they are declared in

lib/AST/ASTContext.cpp

Lines changed: 5 additions & 4 deletions
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

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3301,14 +3301,6 @@ suppressingFeatureAddressableTypes(PrintOptions &options,
33013301
action();
33023302
}
33033303

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

lib/AST/AvailabilityDomain.cpp

Lines changed: 62 additions & 6 deletions
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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -468,8 +468,10 @@ static bool usesFeatureCoroutineAccessors(Decl *decl) {
468468
}
469469

470470
static bool usesFeatureCustomAvailability(Decl *decl) {
471-
// FIXME: [availability] Check whether @available attributes for custom
472-
// domains are attached to the decl.
471+
for (auto attr : decl->getSemanticAvailableAttrs()) {
472+
if (attr.getDomain().isCustom())
473+
return true;
474+
}
473475
return false;
474476
}
475477

lib/ClangImporter/ClangImporter.cpp

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4114,35 +4114,29 @@ void ClangModuleUnit::lookupObjCMethods(
41144114

41154115
void ClangModuleUnit::lookupAvailabilityDomains(
41164116
Identifier identifier, SmallVectorImpl<AvailabilityDomain> &results) const {
4117-
auto lookupTable = owner.findLookupTable(clangModule);
4118-
if (!lookupTable)
4117+
auto domainName = identifier.str();
4118+
auto &ctx = getASTContext();
4119+
auto &clangASTContext = getClangASTContext();
4120+
4121+
auto domainInfo = clangASTContext.getFeatureAvailInfo(domainName);
4122+
if (domainInfo.Kind == clang::FeatureAvailKind::None)
41194123
return;
41204124

4121-
auto varDecl = lookupTable->lookupAvailabilityDomainDecl(identifier.str());
4125+
auto *varDecl = dyn_cast_or_null<clang::VarDecl>(domainInfo.Decl);
41224126
if (!varDecl)
41234127
return;
41244128

4125-
auto featureInfo = getClangASTContext().getFeatureAvailInfo(varDecl);
4126-
if (featureInfo.first.empty())
4129+
// The decl that was found may belong to a different Clang module.
4130+
if (varDecl->getOwningModule() != getClangModule())
41274131
return;
41284132

4129-
auto getDomainKind = [](clang::FeatureAvailKind featureAvailKind) {
4130-
switch (featureAvailKind) {
4131-
case clang::FeatureAvailKind::None:
4132-
llvm_unreachable("unexpected kind");
4133-
case clang::FeatureAvailKind::Available:
4134-
return CustomAvailabilityDomain::Kind::Enabled;
4135-
case clang::FeatureAvailKind::Unavailable:
4136-
return CustomAvailabilityDomain::Kind::Disabled;
4137-
case clang::FeatureAvailKind::Dynamic:
4138-
return CustomAvailabilityDomain::Kind::Dynamic;
4139-
}
4140-
};
4133+
auto *imported = ctx.getClangModuleLoader()->importDeclDirectly(varDecl);
4134+
if (!imported)
4135+
return;
41414136

4142-
auto domain = AvailabilityDomain::forCustom(CustomAvailabilityDomain::get(
4143-
featureInfo.first, getParentModule(),
4144-
getDomainKind(featureInfo.second.Kind), getASTContext()));
4145-
results.push_back(domain);
4137+
auto customDomain = AvailabilityDomain::forCustom(imported, ctx);
4138+
ASSERT(customDomain);
4139+
results.push_back(*customDomain);
41464140
}
41474141

41484142
void ClangModuleUnit::collectLinkLibraries(

0 commit comments

Comments
 (0)