Skip to content

Commit fa6071d

Browse files
committed
AST/Sema: Look up custom availability domains by name.
Store the domain definitions defined on the command line on the `ModuleDecl` for the main module.
1 parent 7a85bd3 commit fa6071d

File tree

6 files changed

+92
-37
lines changed

6 files changed

+92
-37
lines changed

include/swift/AST/Module.h

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include "swift/AST/AccessNotes.h"
2121
#include "swift/AST/AttrKind.h"
22+
#include "swift/AST/AvailabilityDomain.h"
2223
#include "swift/AST/Decl.h"
2324
#include "swift/AST/DeclContext.h"
2425
#include "swift/AST/Identifier.h"
@@ -41,8 +42,8 @@
4142
#include "llvm/Support/ErrorHandling.h"
4243
#include "llvm/Support/MD5.h"
4344
#include <optional>
44-
#include <unordered_map>
4545
#include <set>
46+
#include <unordered_map>
4647

4748
namespace clang {
4849
class Module;
@@ -51,20 +52,16 @@ namespace clang {
5152
namespace swift {
5253
enum class ArtificialMainKind : uint8_t;
5354
class ASTContext;
54-
class ASTScope;
5555
class ASTWalker;
56-
class AvailabilityScope;
57-
class BraceStmt;
56+
class CustomAvailabilityDomain;
5857
class Decl;
5958
class DeclAttribute;
6059
class TypeDecl;
6160
enum class DeclKind : uint8_t;
62-
class ExtensionDecl;
6361
class DebuggerClient;
6462
class DeclName;
6563
class FileUnit;
6664
class FuncDecl;
67-
class InfixOperatorDecl;
6865
enum class LibraryLevel : uint8_t;
6966
class LinkLibrary;
7067
class ModuleLoader;
@@ -74,20 +71,12 @@ namespace swift {
7471
class PostfixOperatorDecl;
7572
class PrefixOperatorDecl;
7673
class ProtocolConformance;
77-
class ProtocolDecl;
7874
struct PrintOptions;
7975
class SourceLookupCache;
80-
class Token;
81-
class TupleType;
8276
class Type;
8377
class ValueDecl;
84-
class VarDecl;
8578
class VisibleDeclConsumer;
8679

87-
namespace ast_scope {
88-
class ASTSourceFileScope;
89-
}
90-
9180
/// Discriminator for file-units.
9281
enum class FileUnitKind {
9382
/// For a .swift source file.
@@ -361,6 +350,10 @@ class ModuleDecl
361350
/// Used by the debugger to bypass resilient access to fields.
362351
bool BypassResilience = false;
363352

353+
using AvailabilityDomainMap =
354+
llvm::SmallDenseMap<Identifier, CustomAvailabilityDomain *>;
355+
AvailabilityDomainMap AvailabilityDomains;
356+
364357
public:
365358
using PopulateFilesFn = llvm::function_ref<void(
366359
ModuleDecl *, llvm::function_ref<void(FileUnit *)>)>;
@@ -1233,6 +1226,15 @@ class ModuleDecl
12331226
/// An empty `Version` is returned if the information is not available.
12341227
version::Version getLanguageVersionBuiltWith() const;
12351228

1229+
/// Returns the custom availability domain defined by this module with the
1230+
/// given identifier, if one exists.
1231+
std::optional<AvailabilityDomain>
1232+
getAvailabilityDomainForIdentifier(Identifier identifier) const;
1233+
1234+
void setAvailabilityDomains(const AvailabilityDomainMap &&map) {
1235+
AvailabilityDomains = std::move(map);
1236+
}
1237+
12361238
static bool classof(const DeclContext *DC) {
12371239
if (auto D = DC->getAsDecl())
12381240
return classof(D);

include/swift/AST/SourceFile.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@
2525
#include "llvm/ADT/STLExtras.h"
2626

2727
namespace swift {
28-
28+
class ASTScope;
29+
class AvailabilityScope;
2930
class PersistentParserState;
3031
struct SourceFileExtras;
32+
class Token;
3133

3234
/// Kind of import affecting how a decl can be reexported.
3335
///

lib/AST/Module.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4127,3 +4127,12 @@ version::Version ModuleDecl::getLanguageVersionBuiltWith() const {
41274127

41284128
return version::Version();
41294129
}
4130+
4131+
std::optional<AvailabilityDomain>
4132+
ModuleDecl::getAvailabilityDomainForIdentifier(Identifier identifier) const {
4133+
auto iter = AvailabilityDomains.find(identifier);
4134+
if (iter == AvailabilityDomains.end())
4135+
return std::nullopt;
4136+
4137+
return AvailabilityDomain::forCustom(iter->getSecond());
4138+
}

lib/Frontend/Frontend.cpp

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include "swift/Frontend/Frontend.h"
1919
#include "swift/AST/ASTContext.h"
20+
#include "swift/AST/AvailabilityDomain.h"
2021
#include "swift/AST/DiagnosticsFrontend.h"
2122
#include "swift/AST/DiagnosticsSema.h"
2223
#include "swift/AST/FileSystem.h"
@@ -29,24 +30,23 @@
2930
#include "swift/Basic/Platform.h"
3031
#include "swift/Basic/SourceManager.h"
3132
#include "swift/Basic/Statistic.h"
33+
#include "swift/DependencyScan/ModuleDependencyScanner.h"
3234
#include "swift/Frontend/CachingUtils.h"
3335
#include "swift/Frontend/CompileJobCacheKey.h"
3436
#include "swift/Frontend/ModuleInterfaceLoader.h"
3537
#include "swift/Parse/Lexer.h"
3638
#include "swift/SIL/SILModule.h"
3739
#include "swift/SILOptimizer/PassManager/Passes.h"
3840
#include "swift/SILOptimizer/Utils/Generics.h"
41+
#include "swift/Serialization/ScanningLoaders.h"
3942
#include "swift/Serialization/SerializationOptions.h"
4043
#include "swift/Serialization/SerializedModuleLoader.h"
41-
#include "swift/Serialization/ScanningLoaders.h"
42-
#include "swift/DependencyScan/ModuleDependencyScanner.h"
4344
#include "swift/Strings.h"
4445
#include "swift/Subsystems.h"
4546
#include "clang/AST/ASTContext.h"
4647
#include "llvm/ADT/Hashing.h"
4748
#include "llvm/ADT/IntrusiveRefCntPtr.h"
4849
#include "llvm/ADT/SmallVector.h"
49-
#include "llvm/TargetParser/Triple.h"
5050
#include "llvm/CAS/ActionCache.h"
5151
#include "llvm/CAS/BuiltinUnifiedCASDatabases.h"
5252
#include "llvm/CAS/CASFileSystem.h"
@@ -55,8 +55,9 @@
5555
#include "llvm/Support/MemoryBuffer.h"
5656
#include "llvm/Support/Path.h"
5757
#include "llvm/Support/Process.h"
58-
#include "llvm/Support/VirtualOutputBackends.h"
5958
#include "llvm/Support/ThreadPool.h"
59+
#include "llvm/Support/VirtualOutputBackends.h"
60+
#include "llvm/TargetParser/Triple.h"
6061
#include <llvm/ADT/StringExtras.h>
6162

6263
using namespace swift;
@@ -1392,6 +1393,28 @@ bool CompilerInstance::createFilesForMainModule(
13921393
return false;
13931394
}
13941395

1396+
static void configureAvailabilityDomains(const ASTContext &ctx,
1397+
const FrontendOptions &opts,
1398+
ModuleDecl *mainModule) {
1399+
llvm::SmallDenseMap<Identifier, CustomAvailabilityDomain *> domainMap;
1400+
auto createAndInsertDomain = [&](const std::string &name,
1401+
CustomAvailabilityDomain::Kind kind) {
1402+
auto *domain = CustomAvailabilityDomain::create(
1403+
ctx, name, mainModule, CustomAvailabilityDomain::Kind::Enabled);
1404+
bool inserted = domainMap.insert({domain->getName(), domain}).second;
1405+
ASSERT(inserted); // Domains must be unique.
1406+
};
1407+
1408+
for (auto enabled : opts.AvailabilityDomains.EnabledDomains)
1409+
createAndInsertDomain(enabled, CustomAvailabilityDomain::Kind::Enabled);
1410+
for (auto enabled : opts.AvailabilityDomains.DisabledDomains)
1411+
createAndInsertDomain(enabled, CustomAvailabilityDomain::Kind::Disabled);
1412+
for (auto enabled : opts.AvailabilityDomains.DynamicDomains)
1413+
createAndInsertDomain(enabled, CustomAvailabilityDomain::Kind::Dynamic);
1414+
1415+
mainModule->setAvailabilityDomains(std::move(domainMap));
1416+
}
1417+
13951418
ModuleDecl *CompilerInstance::getMainModule() const {
13961419
if (MainModule)
13971420
return MainModule;
@@ -1441,6 +1464,9 @@ ModuleDecl *CompilerInstance::getMainModule() const {
14411464
if (Invocation.getLangOptions().hasFeature(Feature::WarnUnsafe))
14421465
MainModule->setStrictMemorySafety(true);
14431466

1467+
configureAvailabilityDomains(getASTContext(),
1468+
Invocation.getFrontendOptions(), MainModule);
1469+
14441470
if (!Invocation.getFrontendOptions()
14451471
.SwiftInterfaceCompilerVersion.empty()) {
14461472
auto compilerVersion =

lib/Sema/TypeCheckAttr.cpp

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8323,14 +8323,30 @@ ValueDecl *RenamedDeclRequest::evaluate(Evaluator &evaluator,
83238323
return renamedDecl;
83248324
}
83258325

8326+
static std::optional<AvailabilityDomain>
8327+
getAvailabilityDomainForName(StringRef name, const DeclContext *declContext) {
8328+
if (auto builtinDomain =
8329+
AvailabilityDomain::builtinDomainForString(name, declContext))
8330+
return builtinDomain;
8331+
8332+
auto &ctx = declContext->getASTContext();
8333+
auto identifier = ctx.getIdentifier(name);
8334+
if (auto customDomain =
8335+
ctx.MainModule->getAvailabilityDomainForIdentifier(identifier))
8336+
return customDomain;
8337+
8338+
return std::nullopt;
8339+
}
8340+
83268341
std::optional<SemanticAvailableAttr>
83278342
SemanticAvailableAttrRequest::evaluate(swift::Evaluator &evaluator,
83288343
const AvailableAttr *attr,
83298344
const Decl *decl) const {
83308345
if (attr->hasCachedDomain())
83318346
return SemanticAvailableAttr(attr);
83328347

8333-
auto &diags = decl->getASTContext().Diags;
8348+
auto &ctx = decl->getASTContext();
8349+
auto &diags = ctx.Diags;
83348350
auto attrLoc = attr->getLocation();
83358351
auto attrName = attr->getAttrName();
83368352
auto domainLoc = attr->getDomainLoc();
@@ -8341,22 +8357,22 @@ SemanticAvailableAttrRequest::evaluate(swift::Evaluator &evaluator,
83418357
auto domain = attr->getCachedDomain();
83428358

83438359
if (!domain) {
8344-
auto string = attr->getDomainString();
8345-
ASSERT(string);
8360+
auto domainName = attr->getDomainString();
8361+
ASSERT(domainName);
83468362

83478363
// Attempt to resolve the domain specified for the attribute and diagnose
83488364
// if no domain is found.
83498365
auto declContext = decl->getInnermostDeclContext();
8350-
domain = AvailabilityDomain::builtinDomainForString(*string, declContext);
8366+
domain = getAvailabilityDomainForName(*domainName, declContext);
83518367
if (!domain) {
8352-
if (auto suggestion = closestCorrectedPlatformString(*string)) {
8368+
if (auto suggestion = closestCorrectedPlatformString(*domainName)) {
83538369
diags
83548370
.diagnose(domainLoc, diag::attr_availability_suggest_platform,
8355-
*string, attrName, *suggestion)
8371+
*domainName, attrName, *suggestion)
83568372
.fixItReplace(SourceRange(domainLoc), *suggestion);
83578373
} else {
83588374
diags.diagnose(attrLoc, diag::attr_availability_unknown_platform,
8359-
*string, attrName);
8375+
*domainName, attrName);
83608376
}
83618377
return std::nullopt;
83628378
}

test/attr/attr_availability_custom_domains.swift

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,25 @@
88

99
// REQUIRES: swift_feature_CustomAvailability
1010

11-
@available(EnabledDomain) // expected-warning {{unknown platform 'EnabledDomain' for attribute 'available'}}
11+
@available(EnabledDomain)
1212
func availableInEnabledDomain() { }
1313

14-
@available(DisabledDomain, unavailable) // expected-warning {{unknown platform 'DisabledDomain' for attribute 'available'}}
15-
func availableInDisabledDomain() { }
14+
@available(DisabledDomain, unavailable)
15+
func unavailableInDisabledDomain() { } // expected-note {{'unavailableInDisabledDomain()' has been explicitly marked unavailable here}}
1616

17-
@available(RedefinedDomain, deprecated, message: "Use something else") // expected-warning {{unknown platform 'RedefinedDomain' for attribute 'available'}}
18-
func availableInRedefinedDomain() { }
17+
@available(RedefinedDomain, deprecated, message: "Use something else")
18+
func deprecatedInRedefinedDomain() { }
1919

20-
@available(DynamicDomain) // expected-warning {{unknown platform 'DynamicDomain' for attribute 'available'}}
20+
@available(DynamicDomain)
2121
func availableInDynamicDomain() { }
2222

2323
@available(UnknownDomain) // expected-warning {{unknown platform 'UnknownDomain' for attribute 'available'}}
2424
func availableInUnknownDomain() { }
2525

2626
func test() {
27-
availableInEnabledDomain()
28-
availableInDisabledDomain()
29-
availableInRedefinedDomain()
30-
availableInDynamicDomain()
31-
availableInUnknownDomain()
27+
availableInEnabledDomain() // FIXME: [availability] should be diagnosed
28+
unavailableInDisabledDomain() // expected-error {{'unavailableInDisabledDomain()' is unavailable}}
29+
deprecatedInRedefinedDomain() // expected-warning {{'deprecatedInRedefinedDomain()' is deprecated: Use something else}}
30+
availableInDynamicDomain() // FIXME: [availability] should be diagnosed
31+
availableInUnknownDomain() // Ok
3232
}

0 commit comments

Comments
 (0)