From 6c1a9770dc429ba3aa3a56f6ee29626002ed30ed Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Thu, 14 Aug 2025 16:11:39 -0700 Subject: [PATCH 1/4] Sema: Move attached macro availability checking to DeclAvailabilityChecker. This allows the `ExportContext` that is pre-computed for availability checking to be reused when checking attached macro availability. Also, it just makes more sense. NFC. --- lib/Sema/TypeCheckAccess.cpp | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/lib/Sema/TypeCheckAccess.cpp b/lib/Sema/TypeCheckAccess.cpp index b1aae3a489466..0e171f14d93e9 100644 --- a/lib/Sema/TypeCheckAccess.cpp +++ b/lib/Sema/TypeCheckAccess.cpp @@ -573,7 +573,6 @@ class AccessControlChecker : public AccessControlCheckerBase, DeclVisitor::visit(D); checkGlobalActorAccess(D); - checkAttachedMacrosAccess(D); } // Force all kinds to be handled at a lower level. @@ -1314,19 +1313,6 @@ class AccessControlChecker : public AccessControlCheckerBase, noteLimitingImport(MD, minImportLimit, complainRepr); } } - - void checkAttachedMacrosAccess(const Decl *D) { - for (auto customAttrC : D->getExpandedAttrs().getAttributes()) { - auto customAttr = const_cast(customAttrC); - auto *macroDecl = D->getResolvedMacro(customAttr); - if (macroDecl) { - diagnoseDeclAvailability( - macroDecl, customAttr->getTypeRepr()->getSourceRange(), nullptr, - ExportContext::forDeclSignature(const_cast(D)), - std::nullopt); - } - } - } }; class UsableFromInlineChecker : public AccessControlCheckerBase, @@ -2141,9 +2127,22 @@ class DeclAvailabilityChecker : public DeclVisitor { checkType(customAttr->getType(), customAttr->getTypeRepr(), D); } + void checkAttachedMacros(const Decl *D) { + for (auto customAttrC : D->getExpandedAttrs().getAttributes()) { + auto customAttr = const_cast(customAttrC); + auto *macroDecl = D->getResolvedMacro(customAttr); + if (macroDecl) { + diagnoseDeclAvailability(macroDecl, + customAttr->getTypeRepr()->getSourceRange(), + nullptr, Where, std::nullopt); + } + } + } + void visit(Decl *D) { DeclVisitor::visit(D); checkGlobalActor(D); + checkAttachedMacros(D); } // Force all kinds to be handled at a lower level. From 9de88624b28590fcb6fa808a2168e1dfe27d2b89 Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Tue, 19 Aug 2025 18:59:31 -0700 Subject: [PATCH 2/4] Sema: Diagnose availability of availability domains in if #available queries. When emitting statement diagnostics for `if #available` queries, diagnose the availability of the decls representing the referenced availability domains. Among other things, this checks that the domains are sufficiently visible to be used in the containing function body context. --- lib/AST/AvailabilityDomain.cpp | 4 +-- lib/AST/DiagnosticEngine.cpp | 15 ++++++++++ lib/Sema/MiscDiagnostics.cpp | 6 ++++ .../availability_custom_domains_access.swift | 30 +++++++++++++++++++ .../availability-domains/Rivers.h | 4 +++ 5 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 test/ClangImporter/availability_custom_domains_access.swift diff --git a/lib/AST/AvailabilityDomain.cpp b/lib/AST/AvailabilityDomain.cpp index db245ac22f9b2..f4329774b73da 100644 --- a/lib/AST/AvailabilityDomain.cpp +++ b/lib/AST/AvailabilityDomain.cpp @@ -41,9 +41,7 @@ getCustomDomainKind(clang::FeatureAvailKind featureAvailKind) { static const CustomAvailabilityDomain * customDomainForClangDecl(ValueDecl *decl) { auto *clangDecl = decl->getClangDecl(); - ASSERT(clangDecl); - - auto *varDecl = dyn_cast(clangDecl); + auto *varDecl = dyn_cast_or_null(clangDecl); if (!varDecl) return nullptr; diff --git a/lib/AST/DiagnosticEngine.cpp b/lib/AST/DiagnosticEngine.cpp index a26d6eafec562..00daeba9490bc 100644 --- a/lib/AST/DiagnosticEngine.cpp +++ b/lib/AST/DiagnosticEngine.cpp @@ -16,6 +16,7 @@ //===----------------------------------------------------------------------===// #include "swift/AST/DiagnosticEngine.h" +#include "swift/AST/AvailabilityDomain.h" #include "swift/AST/ASTContext.h" #include "swift/AST/ASTPrinter.h" #include "swift/AST/Decl.h" @@ -877,6 +878,20 @@ static void formatDiagnosticArgument(StringRef Modifier, assert(Modifier.empty() && "Improper modifier for ValueDecl argument"); } + // Handle declarations representing an AvailabilityDomain specially. + if (auto VD = dyn_cast(D)) { + if (auto domain = AvailabilityDomain::forCustom(const_cast(VD))) { + Out << "availability domain"; + + if (includeName) { + Out << " " << FormatOpts.OpeningQuotationMark; + Out << domain->getNameForDiagnostics(); + Out << FormatOpts.ClosingQuotationMark; + } + break; + } + } + if (includeName) { if (auto accessor = dyn_cast(D)) { // If it's an accessor, describe that and then switch to discussing its diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp index 368f753388b0b..460f489995a4c 100644 --- a/lib/Sema/MiscDiagnostics.cpp +++ b/lib/Sema/MiscDiagnostics.cpp @@ -5257,6 +5257,12 @@ static bool diagnoseAvailabilityCondition(PoundAvailableInfo *info, return true; } + // Check the availability of the domain decl. + if (auto *domainDecl = spec.getDomain().getDecl()) { + auto where = ExportContext::forFunctionBody(DC, loc); + diagnoseDeclAvailability(domainDecl, loc, nullptr, where); + } + hasValidSpecs = true; if (!domain.isPlatform()) allValidSpecsArePlatform = false; diff --git a/test/ClangImporter/availability_custom_domains_access.swift b/test/ClangImporter/availability_custom_domains_access.swift new file mode 100644 index 0000000000000..625c4990fbb5c --- /dev/null +++ b/test/ClangImporter/availability_custom_domains_access.swift @@ -0,0 +1,30 @@ +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -verify \ +// RUN: -import-objc-header %S/Inputs/availability_domains_bridging_header.h \ +// RUN: -I %S/../Inputs/custom-modules/availability-domains \ +// RUN: -enable-experimental-feature CustomAvailability \ +// RUN: %s + +// REQUIRES: swift_feature_CustomAvailability + +private import Rivers // also re-exported by Oceans +internal import Oceans +// expected-note@-1 {{availability domain 'Arctic' imported as 'internal' from 'Oceans' here}} +// expected-note@-2 {{availability domain 'Colorado' imported as 'internal' from 'Oceans' here}} +// expected-note@-3 {{availability domain 'Grand' imported as 'internal' from 'Oceans' here}} +public import Seas + +@inlinable public func inlinableFunc() { + if #available(Colorado) { } // expected-error {{availability domain 'Colorado' is internal and cannot be referenced from an '@inlinable' function}} + if #available(Grand) { } // expected-error {{availability domain 'Grand' is internal and cannot be referenced from an '@inlinable' function}} + if #available(Arctic) { } // expected-error {{availability domain 'Arctic' is internal and cannot be referenced from an '@inlinable' function}} + if #available(Baltic) { } + if #available(BayBridge) { } +} + +public func nonInlinablePublicFunc() { + if #available(Colorado) { } + if #available(Grand) { } // expected-warning {{availability domain 'Grand' is deprecated: Use Colorado instead}} + if #available(Arctic) { } + if #available(Baltic) { } + if #available(BayBridge) { } +} diff --git a/test/Inputs/custom-modules/availability-domains/Rivers.h b/test/Inputs/custom-modules/availability-domains/Rivers.h index 9b026707be742..9cb0b35b01b20 100644 --- a/test/Inputs/custom-modules/availability-domains/Rivers.h +++ b/test/Inputs/custom-modules/availability-domains/Rivers.h @@ -3,6 +3,10 @@ static struct __AvailabilityDomain colorado_domain __attribute__(( availability_domain(Colorado))) = {__AVAILABILITY_DOMAIN_DISABLED, 0}; +__attribute__((deprecated("Use Colorado instead"))) +static struct __AvailabilityDomain grand_domain __attribute__(( + availability_domain(Grand))) = {__AVAILABILITY_DOMAIN_DISABLED, 0}; + #define AVAIL 0 #define UNAVAIL 1 From 7ac68cecb1cc4609aeb3d7ff4f789d5ed0f334bf Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Mon, 25 Aug 2025 15:59:34 -0700 Subject: [PATCH 3/4] Sema: Check access, availability, and exportability of availability domains. Teach Sema to diagnose the access level, exportability, and availability of availability domains that are referenced by `@available` attributes and `if #available` statements. Resolves rdar://159147207. --- include/swift/AST/DiagnosticsSema.def | 11 + lib/Sema/TypeCheckAccess.cpp | 202 +++++++++-- lib/Sema/TypeCheckAttr.cpp | 3 + lib/Sema/TypeCheckDeclPrimary.cpp | 4 +- ...l-import-availability-custom-domains.swift | 328 ++++++++++++++++++ .../availability_custom_domains_access.swift | 30 -- .../availability-domains/Lakes.h | 13 + .../availability-domains/module.modulemap | 5 + 8 files changed, 530 insertions(+), 66 deletions(-) create mode 100644 test/ClangImporter/access-level-import-availability-custom-domains.swift delete mode 100644 test/ClangImporter/availability_custom_domains_access.swift create mode 100644 test/Inputs/custom-modules/availability-domains/Lakes.h diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 54310001bb7c3..8b04951853c6a 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -6989,6 +6989,17 @@ WARNING(attr_availability_expected_version_spec, none, ERROR(attr_availability_requires_custom_availability, none, "%0 requires '-enable-experimental-feature CustomAvailability'", (AvailabilityDomain)) +ERROR(attr_availability_domain_access, none, + "availability domain '%0' is " + "%select{private|fileprivate|internal|package|%error|%error}1 " + "and cannot be used in '%2' on " + "%select{private|fileprivate|internal|package|public|%error}3 %kind4", + (AvailabilityDomain, AccessLevel, DeclAttribute, AccessLevel, + const Decl *)) +ERROR(attr_availability_domain_not_usable_from_inline, none, + "availability domain '%0' used in '%1' on %kind2 must be " + "'@usableFromInline' or public", + (AvailabilityDomain, DeclAttribute, const Decl *)) ERROR(availability_decl_unavailable, none, "%0 is unavailable%select{ in %2|}1%select{|: %3}3", diff --git a/lib/Sema/TypeCheckAccess.cpp b/lib/Sema/TypeCheckAccess.cpp index 0e171f14d93e9..bafb1de01e054 100644 --- a/lib/Sema/TypeCheckAccess.cpp +++ b/lib/Sema/TypeCheckAccess.cpp @@ -28,6 +28,7 @@ #include "swift/AST/Import.h" #include "swift/AST/ParameterList.h" #include "swift/AST/Pattern.h" +#include "swift/AST/PrettyStackTrace.h" #include "swift/AST/TypeCheckRequests.h" #include "swift/Basic/Assertions.h" #include "clang/AST/DeclCXX.h" @@ -70,10 +71,22 @@ static void forAllRequirementTypes( using CheckTypeAccessCallback = void(AccessScope, const TypeRepr *, DowngradeToWarning, ImportAccessLevel); +using CheckDeclAccessCallback = void(AccessScope, SourceLoc, ImportAccessLevel); + class AccessControlCheckerBase { protected: bool checkUsableFromInline; + bool shouldSkipChecking(const ValueDecl *decl); + + /// Returns true if access checking ought to be skipped for the given + /// `AccessScope`. + bool shouldSkipAccessCheckingInContext(AccessScope contextAccessScope, + const ASTContext &ctx); + + ImportAccessLevel getImportAccessForDecl(const ValueDecl *decl, + const DeclContext *useDC); + void checkTypeAccessImpl( Type type, TypeRepr *typeRepr, AccessScope contextAccessScope, const DeclContext *useDC, bool mayBeInferred, @@ -102,6 +115,12 @@ class AccessControlCheckerBase { }); } + void checkAvailabilityDomains(const Decl *D); + + void checkDeclAccess(SourceLoc loc, const ValueDecl *decl, + AccessScope contextAccessScope, const DeclContext *useDC, + llvm::function_ref diagnose); + AccessControlCheckerBase(bool checkUsableFromInline) : checkUsableFromInline(checkUsableFromInline) {} @@ -117,10 +136,50 @@ class AccessControlCheckerBase { const ValueDecl *ownerDecl); void checkGlobalActorAccess(const Decl *D); + + void checkAvailabilityDomains(const Decl *D, AccessScope accessScope, + AccessLevel contextAccess); }; } // end anonymous namespace +bool AccessControlCheckerBase::shouldSkipChecking(const ValueDecl *decl) { + if (!checkUsableFromInline) + return false; + + if (decl->getFormalAccess() != AccessLevel::Internal && + decl->getFormalAccess() != AccessLevel::Package) + return true; + return !decl->isUsableFromInline(); +} + +bool AccessControlCheckerBase::shouldSkipAccessCheckingInContext( + AccessScope contextAccessScope, const ASTContext &ctx) { + if (ctx.isAccessControlDisabled()) + return true; + + // Don't spend time checking local declarations; this is always valid by the + // time we get to this point. + if (contextAccessScope.isInContext() && + contextAccessScope.getDeclContext()->isLocalContext()) + return true; + + return false; +} + +ImportAccessLevel +AccessControlCheckerBase::getImportAccessForDecl(const ValueDecl *decl, + const DeclContext *useDC) { + auto complainImport = decl->getImportAccessFrom(useDC); + + // Don't complain about an import that doesn't restrict the access + // level of the decl. This can happen with imported `package` decls. + if (complainImport && complainImport->accessLevel >= decl->getFormalAccess()) + return std::nullopt; + + return complainImport; +} + /// Searches the given type representation for a `DeclRefTypeRepr` that is /// bound to a type declaration with the given access scope. The type /// representation is searched in source order. For example, nodes in @@ -201,12 +260,7 @@ void AccessControlCheckerBase::checkTypeAccessImpl( llvm::function_ref diagnose) { auto &Context = useDC->getASTContext(); - if (Context.isAccessControlDisabled()) - return; - // Don't spend time checking local declarations; this is always valid by the - // time we get to this point. - if (contextAccessScope.isInContext() && - contextAccessScope.getDeclContext()->isLocalContext()) + if (shouldSkipAccessCheckingInContext(contextAccessScope, Context)) return; // Report where it was imported from. @@ -229,7 +283,7 @@ void AccessControlCheckerBase::checkTypeAccessImpl( return TypeWalker::Action::Continue; })); } - }; + } AccessScope problematicAccessScope = AccessScope::getPublic(); @@ -307,19 +361,36 @@ void AccessControlCheckerBase::checkTypeAccessImpl( const ValueDecl *VD = complainRepr->getBoundDecl(); assert(VD && "findTypeDeclWithAccessScope should return bound TypeReprs only"); - complainImport = VD->getImportAccessFrom(useDC); - - // Don't complain about an import that doesn't restrict the access - // level of the decl. This can happen with imported `package` decls. - if (complainImport.has_value() && - complainImport->accessLevel >= VD->getFormalAccess()) - complainImport = std::nullopt; + complainImport = getImportAccessForDecl(VD, useDC); } diagnose(problematicAccessScope, complainRepr, downgradeToWarning, complainImport); } +void AccessControlCheckerBase::checkDeclAccess( + SourceLoc loc, const ValueDecl *decl, AccessScope contextAccessScope, + const DeclContext *useDC, + llvm::function_ref diagnose) { + + auto &ctx = useDC->getASTContext(); + if (shouldSkipAccessCheckingInContext(contextAccessScope, ctx)) + return; + + recordRequiredImportAccessLevelForDecl( + decl, useDC, contextAccessScope.accessLevelForDiagnostics(), loc); + + AccessScope declAccessScope = + decl->getFormalAccessScope(useDC, checkUsableFromInline); + if (contextAccessScope.hasEqualDeclContextWith(declAccessScope) || + contextAccessScope.isChildOf(declAccessScope)) + return; + + // The reference to the decl violates the rules of access control. + ImportAccessLevel complainImport = getImportAccessForDecl(decl, useDC); + diagnose(declAccessScope, loc, complainImport); +} + /// Checks if the access scope of the type described by \p TL is valid for the /// type to be the type of \p context. If it isn't, calls \p diagnose with a /// TypeRepr representing the offending part of \p TL. @@ -556,6 +627,50 @@ void AccessControlCheckerBase::checkGlobalActorAccess(const Decl *D) { }); } +void AccessControlCheckerBase::checkAvailabilityDomains( + const Decl *D, AccessScope accessScope, AccessLevel contextAccess) { + auto &ctx = D->getASTContext(); + for (auto attr : D->getSemanticAvailableAttrs()) { + if (auto *domainDecl = attr.getDomain().getDecl()) { + checkDeclAccess( + attr.getParsedAttr()->getDomainLoc(), domainDecl, accessScope, + D->getDeclContext(), + [&](AccessScope domainAccessScope, SourceLoc useLoc, + ImportAccessLevel importLimit) { + // FIXME: [availability] Improve diagnostics by indicating the decl + // that the formal access is implied by. Enum cases, associated + // types, protocol requirements, etc. inherit their access level + // from their context. + + if (checkUsableFromInline) { + ctx.Diags.diagnose( + useLoc, diag::attr_availability_domain_not_usable_from_inline, + attr.getDomain(), attr.getParsedAttr(), D); + noteLimitingImport(nullptr, ctx, importLimit, domainDecl); + return; + } + + ctx.Diags.diagnose(useLoc, diag::attr_availability_domain_access, + attr.getDomain(), + domainAccessScope.accessLevelForDiagnostics(), + attr.getParsedAttr(), contextAccess, D); + noteLimitingImport(nullptr, ctx, importLimit, domainDecl); + }); + } + } +} + +void AccessControlCheckerBase::checkAvailabilityDomains(const Decl *D) { + auto VD = dyn_cast(D->getAbstractSyntaxDeclForAttributes()); + if (!VD || shouldSkipChecking(VD)) + return; + + AccessScope contextAccessScope = + VD->getFormalAccessScope(VD->getDeclContext(), checkUsableFromInline); + + checkAvailabilityDomains(VD, contextAccessScope, VD->getFormalAccess()); +} + namespace { class AccessControlChecker : public AccessControlCheckerBase, public DeclVisitor { @@ -573,6 +688,7 @@ class AccessControlChecker : public AccessControlCheckerBase, DeclVisitor::visit(D); checkGlobalActorAccess(D); + checkAvailabilityDomains(D); } // Force all kinds to be handled at a lower level. @@ -1321,13 +1437,6 @@ class UsableFromInlineChecker : public AccessControlCheckerBase, UsableFromInlineChecker() : AccessControlCheckerBase(/*checkUsableFromInline=*/true) {} - static bool shouldSkipChecking(const ValueDecl *VD) { - if (VD->getFormalAccess() != AccessLevel::Internal && - VD->getFormalAccess() != AccessLevel::Package) - return true; - return !VD->isUsableFromInline(); - }; - void visit(Decl *D) { if (!D->getASTContext().isSwiftVersionAtLeast(4, 2)) return; @@ -1341,6 +1450,7 @@ class UsableFromInlineChecker : public AccessControlCheckerBase, DeclVisitor::visit(D); checkGlobalActorAccess(D); + checkAvailabilityDomains(D); } // Force all kinds to be handled at a lower level. @@ -2139,10 +2249,22 @@ class DeclAvailabilityChecker : public DeclVisitor { } } + void checkAvailabilityDomains(const Decl *D) { + D = D->getAbstractSyntaxDeclForAttributes(); + for (auto attr : D->getSemanticAvailableAttrs()) { + if (auto *domainDecl = attr.getDomain().getDecl()) { + diagnoseDeclAvailability(domainDecl, + attr.getParsedAttr()->getDomainLoc(), nullptr, + Where, std::nullopt); + } + } + } + void visit(Decl *D) { DeclVisitor::visit(D); checkGlobalActor(D); checkAttachedMacros(D); + checkAvailabilityDomains(D); } // Force all kinds to be handled at a lower level. @@ -2372,14 +2494,10 @@ class DeclAvailabilityChecker : public DeclVisitor { } void checkConstrainedExtensionRequirements(ExtensionDecl *ED, - bool hasExportedMembers) { + ExportabilityReason reason) { if (!ED->getTrailingWhereClause()) return; - ExportabilityReason reason = - hasExportedMembers ? ExportabilityReason::ExtensionWithPublicMembers - : ExportabilityReason::ExtensionWithConditionalConformances; - forAllRequirementTypes(ED, [&](Type type, TypeRepr *typeRepr) { checkType(type, typeRepr, ED, reason, DeclAvailabilityFlag::DisableUnsafeChecking); @@ -2423,7 +2541,23 @@ class DeclAvailabilityChecker : public DeclVisitor { // the 'where' clause must only name exported types. Where = wasWhere.withExported(hasExportedMembers || !ED->getInherited().empty()); - checkConstrainedExtensionRequirements(ED, hasExportedMembers); + ExportabilityReason reason = + hasExportedMembers + ? ExportabilityReason::ExtensionWithPublicMembers + : ExportabilityReason::ExtensionWithConditionalConformances; + checkConstrainedExtensionRequirements(ED, reason); + + // Diagnose the exportability of the availability domains referenced by the + // @available attributes attached to the extension. + if (Where.isExported()) { + for (auto availableAttr : ED->getSemanticAvailableAttrs()) { + if (auto *domainDecl = availableAttr.getDomain().getDecl()) { + TypeChecker::diagnoseDeclRefExportability( + availableAttr.getParsedAttr()->getDomainLoc(), domainDecl, + Where.withReason(reason)); + } + } + } // If we haven't already visited the extended nominal visit it here. // This logic is too wide but prevents false reports of an unused public @@ -2491,7 +2625,7 @@ class DeclAvailabilityChecker : public DeclVisitor { } // end anonymous namespace -static void checkExtensionGenericParamAccess(const ExtensionDecl *ED) { +static void checkExtensionAccess(const ExtensionDecl *ED) { auto *AA = ED->getAttrs().getAttribute(); if (!AA) return; @@ -2522,8 +2656,11 @@ static void checkExtensionGenericParamAccess(const ExtensionDecl *ED) { break; } - AccessControlChecker().checkGenericParamAccess( - ED, ED, desiredAccessScope, userSpecifiedAccess); + auto accessChecker = AccessControlChecker(); + accessChecker.checkGenericParamAccess(ED, ED, desiredAccessScope, + userSpecifiedAccess); + accessChecker.checkAvailabilityDomains(ED, desiredAccessScope, + userSpecifiedAccess); } DisallowedOriginKind swift::getDisallowedOriginKind(const Decl *decl, @@ -2659,13 +2796,10 @@ void swift::checkAccessControl(Decl *D) { AccessControlChecker(allowInlineable).visit(D); UsableFromInlineChecker().visit(D); } else if (auto *ED = dyn_cast(D)) { - checkExtensionGenericParamAccess(ED); + checkExtensionAccess(ED); registerPackageAccessForPackageExtendedType(ED); } - if (isa(D)) - return; - auto where = ExportContext::forDeclSignature(D); if (where.isImplicit()) return; diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index 9232601deb7b5..f4a8dae839360 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -563,6 +563,9 @@ void AttributeChecker::visitSensitiveAttr(SensitiveAttr *attr) { } void AttributeChecker::visitTransparentAttr(TransparentAttr *attr) { + if (attr->isImplicit()) + return; + DeclContext *dc = D->getDeclContext(); // Protocol declarations cannot be transparent. if (isa(dc)) diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index a290483e08c72..f213579f07a17 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -3719,11 +3719,11 @@ class DeclChecker : public DeclVisitor { TypeChecker::checkProtocolSelfRequirements(FD); } - checkAccessControl(FD); - TypeChecker::checkParameterList(FD->getParameters(), FD); } + checkAccessControl(FD); + TypeChecker::checkDeclAttributes(FD); TypeChecker::checkDistributedFunc(FD); diff --git a/test/ClangImporter/access-level-import-availability-custom-domains.swift b/test/ClangImporter/access-level-import-availability-custom-domains.swift new file mode 100644 index 0000000000000..6963ed1f1532b --- /dev/null +++ b/test/ClangImporter/access-level-import-availability-custom-domains.swift @@ -0,0 +1,328 @@ +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -verify \ +// RUN: -import-objc-header %S/Inputs/availability_domains_bridging_header.h \ +// RUN: -I %S/../Inputs/custom-modules/availability-domains \ +// RUN: -enable-experimental-feature CustomAvailability \ +// RUN: -experimental-spi-only-imports -parse-as-library -swift-version 4 \ +// RUN: %s + +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -verify \ +// RUN: -import-objc-header %S/Inputs/availability_domains_bridging_header.h \ +// RUN: -I %S/../Inputs/custom-modules/availability-domains \ +// RUN: -enable-experimental-feature CustomAvailability \ +// RUN: -experimental-spi-only-imports -parse-as-library -swift-version 5 \ +// RUN: %s -verify-additional-prefix swift5- + +// REQUIRES: swift_feature_CustomAvailability + +private import Rivers // also re-exported by Oceans +internal import Oceans +// expected-note@-1 22 {{availability domain 'Arctic' imported as 'internal' from 'Oceans' here}} +// expected-swift5-note@-2 2 {{availability domain 'Arctic' imported as 'internal' from 'Oceans' here}} +// expected-note@-3 23 {{availability domain 'Colorado' imported as 'internal' from 'Oceans' here}} +// expected-swift5-note@-4 2 {{availability domain 'Colorado' imported as 'internal' from 'Oceans' here}} +// expected-note@-5 22 {{availability domain 'Grand' imported as 'internal' from 'Oceans' here}} +// expected-swift5-note@-6 2 {{availability domain 'Grand' imported as 'internal' from 'Oceans' here}} +public import Seas +@_spiOnly import Lakes + +@available(Colorado) // expected-error {{availability domain 'Colorado' is internal and cannot be used in '@available' on public global function 'publicFunc()'}} +@available(Grand) // expected-error {{availability domain 'Grand' is internal and cannot be used in '@available' on public global function 'publicFunc()'}} +// expected-warning@-1 {{availability domain 'Grand' is deprecated: Use Colorado instead}} +@available(Arctic) // expected-error {{availability domain 'Arctic' is internal and cannot be used in '@available' on public global function 'publicFunc()'}} +@available(Baltic) +@available(BayBridge) +@available(Salt) // expected-error {{cannot use availability domain 'Salt' here; 'Lakes' was imported for SPI only}} +public func publicFunc() { } + +@available(Colorado) // expected-swift5-error {{availability domain 'Colorado' used in '@available' on global function 'usableFromInlineFunc()' must be '@usableFromInline' or public}} +@available(Grand) // expected-swift5-error {{availability domain 'Grand' used in '@available' on global function 'usableFromInlineFunc()' must be '@usableFromInline' or public}} +// expected-warning@-1 {{availability domain 'Grand' is deprecated: Use Colorado instead}} +@available(Arctic) // expected-swift5-error {{availability domain 'Arctic' used in '@available' on global function 'usableFromInlineFunc()' must be '@usableFromInline' or public}} +@available(Baltic) +@available(BayBridge) +@available(Salt) // expected-error {{cannot use availability domain 'Salt' here; 'Lakes' was imported for SPI only}} +@usableFromInline func usableFromInlineFunc() { } + +@available(Colorado) // expected-error {{availability domain 'Colorado' is internal and cannot be used in '@available' on public global function 'spiFunc()'}} +@available(Grand) // expected-error {{availability domain 'Grand' is internal and cannot be used in '@available' on public global function 'spiFunc()'}} +// expected-warning@-1 {{availability domain 'Grand' is deprecated: Use Colorado instead}} +@available(Arctic) // expected-error {{availability domain 'Arctic' is internal and cannot be used in '@available' on public global function 'spiFunc()'}} +@available(Baltic) +@available(BayBridge) +@available(Salt) +@_spi(Private) public func spiFunc() { } + +@available(Colorado) +@available(Grand) // expected-warning {{availability domain 'Grand' is deprecated: Use Colorado instead}} +@available(Arctic) +@available(Baltic) +@available(BayBridge) +@available(Salt) +func internalFunc() { } + +@available(Colorado) +@available(Grand) // expected-warning {{availability domain 'Grand' is deprecated: Use Colorado instead}} +@available(Arctic) +@available(Baltic) +@available(BayBridge) +@available(Salt) +private func privateFunc() { } + +@available(Colorado) // expected-error {{availability domain 'Colorado' is internal and cannot be used in '@available' on public var 'publicGlobalVar'}} +@available(Grand) // expected-error {{availability domain 'Grand' is internal and cannot be used in '@available' on public var 'publicGlobalVar'}} +// expected-warning@-1 {{availability domain 'Grand' is deprecated: Use Colorado instead}} +@available(Arctic) // expected-error {{availability domain 'Arctic' is internal and cannot be used in '@available' on public var 'publicGlobalVar'}} +@available(Baltic) +@available(BayBridge) +@available(Salt) // expected-error {{cannot use availability domain 'Salt' here; 'Lakes' was imported for SPI only}} +public var publicGlobalVar: Int { + get { 0 } + set { } +} + +@available(Colorado) // expected-error {{availability domain 'Colorado' is internal and cannot be used in '@available' on public struct 'PublicStruct'}} +@available(Grand) // expected-error {{availability domain 'Grand' is internal and cannot be used in '@available' on public struct 'PublicStruct'}} +// expected-warning@-1 {{availability domain 'Grand' is deprecated: Use Colorado instead}} +@available(Arctic) // expected-error {{availability domain 'Arctic' is internal and cannot be used in '@available' on public struct 'PublicStruct'}} +@available(Baltic) +@available(BayBridge) +@available(Salt) // expected-error {{cannot use availability domain 'Salt' here; 'Lakes' was imported for SPI only}} +public struct PublicStruct { } + +public struct PublicGenericStruct { + var value: T + + @available(Colorado) // expected-error {{availability domain 'Colorado' is internal and cannot be used in '@available' on public initializer 'init(value:)'}} + @available(Grand) // expected-error {{availability domain 'Grand' is internal and cannot be used in '@available' on public initializer 'init(value:)'}} + // expected-warning@-1 {{availability domain 'Grand' is deprecated: Use Colorado instead}} + @available(Arctic) // expected-error {{availability domain 'Arctic' is internal and cannot be used in '@available' on public initializer 'init(value:)'}} + @available(Baltic) + @available(BayBridge) + @available(Salt) // expected-error {{cannot use availability domain 'Salt' here; 'Lakes' was imported for SPI only}} + public init(value: T) { + self.value = value + } + + @available(Colorado) // expected-error {{availability domain 'Colorado' is internal and cannot be used in '@available' on public property 'publicProperty'}} + @available(Grand) // expected-error {{availability domain 'Grand' is internal and cannot be used in '@available' on public property 'publicProperty'}} + // expected-warning@-1 {{availability domain 'Grand' is deprecated: Use Colorado instead}} + @available(Arctic) // expected-error {{availability domain 'Arctic' is internal and cannot be used in '@available' on public property 'publicProperty'}} + @available(Baltic) + @available(BayBridge) + @available(Salt) // expected-error {{cannot use availability domain 'Salt' here; 'Lakes' was imported for SPI only}} + public var publicProperty: T { value } + + @available(Colorado) // expected-swift5-error {{availability domain 'Colorado' used in '@available' on property 'usableFromInlineProperty' must be '@usableFromInline' or public}} + @available(Grand) // expected-swift5-error {{availability domain 'Grand' used in '@available' on property 'usableFromInlineProperty' must be '@usableFromInline' or public}} + // expected-warning@-1 {{availability domain 'Grand' is deprecated: Use Colorado instead}} + @available(Arctic) // expected-swift5-error {{availability domain 'Arctic' used in '@available' on property 'usableFromInlineProperty' must be '@usableFromInline' or public}} + @available(Baltic) + @available(BayBridge) + @available(Salt) // expected-error {{cannot use availability domain 'Salt' here; 'Lakes' was imported for SPI only}} + @usableFromInline var usableFromInlineProperty: T { value } + + public var publicPropertyWithSetter: T { + get { value } + + @available(Colorado) // expected-error {{availability domain 'Colorado' is internal and cannot be used in '@available' on public setter for property 'publicPropertyWithSetter'}} + @available(Grand) // expected-error {{availability domain 'Grand' is internal and cannot be used in '@available' on public setter for property 'publicPropertyWithSetter'}} + // expected-warning@-1 {{availability domain 'Grand' is deprecated: Use Colorado instead}} + @available(Arctic) // expected-error {{availability domain 'Arctic' is internal and cannot be used in '@available' on public setter for property 'publicPropertyWithSetter'}} + @available(Baltic) + @available(BayBridge) + @available(Salt) // expected-error {{cannot use availability domain 'Salt' here; 'Lakes' was imported for SPI only}} + set { value = newValue } + } + + @available(Colorado) // expected-error {{availability domain 'Colorado' is internal and cannot be used in '@available' on public instance method 'publicMethod()'}} + @available(Grand) // expected-error {{availability domain 'Grand' is internal and cannot be used in '@available' on public instance method 'publicMethod()'}} + // expected-warning@-1 {{availability domain 'Grand' is deprecated: Use Colorado instead}} + @available(Arctic) // expected-error {{availability domain 'Arctic' is internal and cannot be used in '@available' on public instance method 'publicMethod()'}} + @available(Baltic) + @available(BayBridge) + @available(Salt) // expected-error {{cannot use availability domain 'Salt' here; 'Lakes' was imported for SPI only}} + public func publicMethod() { } + + @available(Colorado) // expected-error {{availability domain 'Colorado' is internal and cannot be used in '@available' on public subscript 'subscript(_:)'}} + @available(Colorado) // expected-error {{availability domain 'Colorado' is internal and cannot be used in '@available' on public subscript 'subscript(_:)'}} + @available(Grand) // expected-error {{availability domain 'Grand' is internal and cannot be used in '@available' on public subscript 'subscript(_:)'}} + // expected-warning@-1 {{availability domain 'Grand' is deprecated: Use Colorado instead}} + @available(Arctic) // expected-error {{availability domain 'Arctic' is internal and cannot be used in '@available' on public subscript 'subscript(_:)'}} + @available(Baltic) + @available(BayBridge) + @available(Salt) // expected-error {{cannot use availability domain 'Salt' here; 'Lakes' was imported for SPI only}} + public subscript(indexForSubscriptInColorado: T) -> T { value } +} + +@available(Colorado) // expected-error {{availability domain 'Colorado' is internal and cannot be used in '@available' on public enum 'PublicEnum'}} +@available(Grand) // expected-error {{availability domain 'Grand' is internal and cannot be used in '@available' on public enum 'PublicEnum'}} +// expected-warning@-1 {{availability domain 'Grand' is deprecated: Use Colorado instead}} +@available(Arctic) // expected-error {{availability domain 'Arctic' is internal and cannot be used in '@available' on public enum 'PublicEnum'}} +@available(Baltic) +@available(BayBridge) +@available(Salt) // expected-error {{cannot use availability domain 'Salt' here; 'Lakes' was imported for SPI only}} +public enum PublicEnum { } + +public enum PublicEnumWithCase { + @available(Colorado) // expected-error {{availability domain 'Colorado' is internal and cannot be used in '@available' on public enum case 'colorado'}} + @available(Grand) // expected-error {{availability domain 'Grand' is internal and cannot be used in '@available' on public enum case 'colorado'}} + // expected-warning@-1 {{availability domain 'Grand' is deprecated: Use Colorado instead}} + @available(Arctic) // expected-error {{availability domain 'Arctic' is internal and cannot be used in '@available' on public enum case 'colorado'}} + @available(Baltic) + @available(BayBridge) + @available(Salt) // expected-error {{cannot use availability domain 'Salt' here; 'Lakes' was imported for SPI only}} + case colorado +} + +@available(Colorado) // expected-error {{availability domain 'Colorado' is internal and cannot be used in '@available' on public class 'PublicClass'}} +@available(Grand) // expected-error {{availability domain 'Grand' is internal and cannot be used in '@available' on public class 'PublicClass'}} +// expected-warning@-1 {{availability domain 'Grand' is deprecated: Use Colorado instead}} +@available(Arctic) // expected-error {{availability domain 'Arctic' is internal and cannot be used in '@available' on public class 'PublicClass'}} +@available(Baltic) +@available(BayBridge) +@available(Salt) // expected-error {{cannot use availability domain 'Salt' here; 'Lakes' was imported for SPI only}} +public class PublicClass { } + +@available(Colorado) // expected-error {{availability domain 'Colorado' is internal and cannot be used in '@available' on public protocol 'PublicProtocol'}} +@available(Grand) // expected-error {{availability domain 'Grand' is internal and cannot be used in '@available' on public protocol 'PublicProtocol'}} +// expected-warning@-1 {{availability domain 'Grand' is deprecated: Use Colorado instead}} +@available(Arctic) // expected-error {{availability domain 'Arctic' is internal and cannot be used in '@available' on public protocol 'PublicProtocol'}} +@available(Baltic) +@available(BayBridge) +@available(Salt) // expected-error {{cannot use availability domain 'Salt' here; 'Lakes' was imported for SPI only}} +public protocol PublicProtocol { } + +public protocol PublicProtocolWithAssociatedType { + @available(Colorado) // expected-error {{availability domain 'Colorado' is internal and cannot be used in '@available' on public associated type 'AssociatedType'}} + @available(Grand) // expected-error {{availability domain 'Grand' is internal and cannot be used in '@available' on public associated type 'AssociatedType'}} + // expected-warning@-1 {{availability domain 'Grand' is deprecated: Use Colorado instead}} + @available(Arctic) // expected-error {{availability domain 'Arctic' is internal and cannot be used in '@available' on public associated type 'AssociatedType'}} + @available(Baltic) + @available(BayBridge) + @available(Salt) // expected-error {{cannot use availability domain 'Salt' here; 'Lakes' was imported for SPI only}} + associatedtype AssociatedType + + @available(Colorado) // expected-error {{availability domain 'Colorado' is internal and cannot be used in '@available' on public instance method 'requirement()'}} + @available(Grand) // expected-error {{availability domain 'Grand' is internal and cannot be used in '@available' on public instance method 'requirement()'}} + // expected-warning@-1 {{availability domain 'Grand' is deprecated: Use Colorado instead}} + @available(Arctic) // expected-error {{availability domain 'Arctic' is internal and cannot be used in '@available' on public instance method 'requirement()'}} + @available(Baltic) + @available(BayBridge) + @available(Salt) // expected-error {{cannot use availability domain 'Salt' here; 'Lakes' was imported for SPI only}} + func requirement() -> AssociatedType +} + +@available(Colorado) // expected-error {{availability domain 'Colorado' is internal and cannot be used in '@available' on public type alias 'PublicTypealias'}} +@available(Grand) // expected-error {{availability domain 'Grand' is internal and cannot be used in '@available' on public type alias 'PublicTypealias'}} +// expected-warning@-1 {{availability domain 'Grand' is deprecated: Use Colorado instead}} +@available(Arctic) // expected-error {{availability domain 'Arctic' is internal and cannot be used in '@available' on public type alias 'PublicTypealias'}} +@available(Baltic) +@available(BayBridge) +@available(Salt) // expected-error {{cannot use availability domain 'Salt' here; 'Lakes' was imported for SPI only}} +public typealias PublicTypealias = Int + +@available(Colorado) +@available(Grand) // expected-warning {{availability domain 'Grand' is deprecated: Use Colorado instead}} +@available(Arctic) +@available(Baltic) +@available(BayBridge) +@available(Salt) +extension PublicGenericStruct { } + +@available(Colorado) // expected-error {{availability domain 'Colorado' is internal and cannot be used in '@available' on public extension of generic struct 'PublicGenericStruct'}} +@available(Grand) // expected-error {{availability domain 'Grand' is internal and cannot be used in '@available' on public extension of generic struct 'PublicGenericStruct'}} +// expected-warning@-1 {{availability domain 'Grand' is deprecated: Use Colorado instead}} +@available(Arctic) // expected-error {{availability domain 'Arctic' is internal and cannot be used in '@available' on public extension of generic struct 'PublicGenericStruct'}} +@available(Baltic) +@available(BayBridge) +@available(Salt) // FIXME: Should be diangosed +public extension PublicGenericStruct { } + +@available(Colorado) +@available(Grand) // expected-warning {{availability domain 'Grand' is deprecated: Use Colorado instead}} +@available(Arctic) +@available(Baltic) +@available(BayBridge) +@available(Salt) +extension PublicGenericStruct { + func internalMethodInExtensionInColorado() { } +} + +@available(Colorado) // expected-error {{cannot use availability domain 'Colorado' in an extension with public or '@usableFromInline' members; 'Rivers' was not imported publicly}} +@available(Grand) // expected-error {{cannot use availability domain 'Grand' in an extension with public or '@usableFromInline' members; 'Rivers' was not imported publicly}} +// expected-warning@-1 {{availability domain 'Grand' is deprecated: Use Colorado instead}} +@available(Arctic) // expected-error {{cannot use availability domain 'Arctic' in an extension with public or '@usableFromInline' members; 'Oceans' was not imported publicly}} +@available(Baltic) +@available(BayBridge) +// FIXME: Duplicate error +@available(Salt) // expected-error {{cannot use availability domain 'Salt' here; 'Lakes' was imported for SPI only}} +// expected-error@-1 {{cannot use availability domain 'Salt' in an extension with public or '@usableFromInline' members; 'Lakes' was imported for SPI only}} +extension PublicGenericStruct { + public func publicMethodInExtensionInColorado() { } +} + +@available(Colorado) +@available(Grand) // expected-warning {{availability domain 'Grand' is deprecated: Use Colorado instead}} +@available(Arctic) +@available(Baltic) +@available(BayBridge) +@available(Salt) +extension PublicGenericStruct where T: PublicProtocolWithAssociatedType { } + +@available(Colorado) // expected-error {{cannot use availability domain 'Colorado' in an extension with conditional conformances; 'Rivers' was not imported publicly}} +@available(Grand) // expected-error {{cannot use availability domain 'Grand' in an extension with conditional conformances; 'Rivers' was not imported publicly}} +// expected-warning@-1 {{availability domain 'Grand' is deprecated: Use Colorado instead}} +@available(Arctic) // expected-error {{cannot use availability domain 'Arctic' in an extension with conditional conformances; 'Oceans' was not imported publicly}} +@available(Baltic) +@available(BayBridge) +// FIXME: Duplicate error +@available(Salt) // expected-error {{cannot use availability domain 'Salt' in an extension with conditional conformances; 'Lakes' was imported for SPI only}} +// expected-error@-1 {{cannot use availability domain 'Salt' here; 'Lakes' was imported for SPI only}} +extension PublicGenericStruct: PublicProtocol {} + +@available(Colorado) // expected-error {{cannot use availability domain 'Colorado' in an extension with public or '@usableFromInline' members; 'Rivers' was not imported publicly}} +@available(Grand) // expected-error {{cannot use availability domain 'Grand' in an extension with public or '@usableFromInline' members; 'Rivers' was not imported publicly}} +// expected-warning@-1 {{availability domain 'Grand' is deprecated: Use Colorado instead}} +@available(Arctic) // expected-error {{cannot use availability domain 'Arctic' in an extension with public or '@usableFromInline' members; 'Oceans' was not imported publicly}} +@available(Baltic) +@available(BayBridge) +// FIXME: Duplicate error +@available(Salt) // expected-error {{cannot use availability domain 'Salt' here; 'Lakes' was imported for SPI only}} +// expected-error@-1 {{cannot use availability domain 'Salt' in an extension with public or '@usableFromInline' members; 'Lakes' was imported for SPI only}} +extension PublicGenericStruct: PublicProtocolWithAssociatedType { + public func requirement() -> Int { 0 } +} + +@inlinable public func inlinableFunc() { + if #available(Colorado) { } // expected-error {{availability domain 'Colorado' is internal and cannot be referenced from an '@inlinable' function}} + if #available(Grand) { } // expected-error {{availability domain 'Grand' is internal and cannot be referenced from an '@inlinable' function}} + if #available(Arctic) { } // expected-error {{availability domain 'Arctic' is internal and cannot be referenced from an '@inlinable' function}} + if #available(Baltic) { } + if #available(BayBridge) { } + if #available(Salt) { } // expected-error {{availability domain 'Salt' cannot be used in an '@inlinable' function because 'Lakes' was imported for SPI only}} + + @available(Colorado) // expected-error {{availability domain 'Colorado' is internal and cannot be referenced from an '@inlinable' function}} + @available(Grand) // expected-error {{availability domain 'Grand' is internal and cannot be referenced from an '@inlinable' function}} + @available(Arctic) // expected-error {{availability domain 'Arctic' is internal and cannot be referenced from an '@inlinable' function}} + @available(Baltic) + @available(BayBridge) + @available(Salt) // expected-error {{availability domain 'Salt' cannot be used in an '@inlinable' function because 'Lakes' was imported for SPI only}} + func nestedFunc() { } +} + +public func nonInlinablePublicFunc() { + if #available(Colorado) { } + if #available(Grand) { } // expected-warning {{availability domain 'Grand' is deprecated: Use Colorado instead}} + if #available(Arctic) { } + if #available(Baltic) { } + if #available(BayBridge) { } + if #available(Salt) { } + + @available(Colorado) + @available(Grand) // expected-warning {{availability domain 'Grand' is deprecated: Use Colorado instead}} + @available(Arctic) + @available(Baltic) + @available(BayBridge) + @available(Salt) + func nestedFunc() { } +} diff --git a/test/ClangImporter/availability_custom_domains_access.swift b/test/ClangImporter/availability_custom_domains_access.swift deleted file mode 100644 index 625c4990fbb5c..0000000000000 --- a/test/ClangImporter/availability_custom_domains_access.swift +++ /dev/null @@ -1,30 +0,0 @@ -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -verify \ -// RUN: -import-objc-header %S/Inputs/availability_domains_bridging_header.h \ -// RUN: -I %S/../Inputs/custom-modules/availability-domains \ -// RUN: -enable-experimental-feature CustomAvailability \ -// RUN: %s - -// REQUIRES: swift_feature_CustomAvailability - -private import Rivers // also re-exported by Oceans -internal import Oceans -// expected-note@-1 {{availability domain 'Arctic' imported as 'internal' from 'Oceans' here}} -// expected-note@-2 {{availability domain 'Colorado' imported as 'internal' from 'Oceans' here}} -// expected-note@-3 {{availability domain 'Grand' imported as 'internal' from 'Oceans' here}} -public import Seas - -@inlinable public func inlinableFunc() { - if #available(Colorado) { } // expected-error {{availability domain 'Colorado' is internal and cannot be referenced from an '@inlinable' function}} - if #available(Grand) { } // expected-error {{availability domain 'Grand' is internal and cannot be referenced from an '@inlinable' function}} - if #available(Arctic) { } // expected-error {{availability domain 'Arctic' is internal and cannot be referenced from an '@inlinable' function}} - if #available(Baltic) { } - if #available(BayBridge) { } -} - -public func nonInlinablePublicFunc() { - if #available(Colorado) { } - if #available(Grand) { } // expected-warning {{availability domain 'Grand' is deprecated: Use Colorado instead}} - if #available(Arctic) { } - if #available(Baltic) { } - if #available(BayBridge) { } -} diff --git a/test/Inputs/custom-modules/availability-domains/Lakes.h b/test/Inputs/custom-modules/availability-domains/Lakes.h new file mode 100644 index 0000000000000..e4c16fec80a6f --- /dev/null +++ b/test/Inputs/custom-modules/availability-domains/Lakes.h @@ -0,0 +1,13 @@ +#include + +static struct __AvailabilityDomain salt_domain __attribute__(( + availability_domain(Salt))) = {__AVAILABILITY_DOMAIN_ENABLED, 0}; + +#define AVAIL 0 +#define UNAVAIL 1 + +__attribute__((availability(domain:Salt, AVAIL))) +void available_in_salt(void); + +#undef UNAVAIL +#undef AVAIL diff --git a/test/Inputs/custom-modules/availability-domains/module.modulemap b/test/Inputs/custom-modules/availability-domains/module.modulemap index 62930e7c437ab..3d9316f279f71 100644 --- a/test/Inputs/custom-modules/availability-domains/module.modulemap +++ b/test/Inputs/custom-modules/availability-domains/module.modulemap @@ -12,3 +12,8 @@ module Seas { header "Seas.h" export * } + +module Lakes { + header "Lakes.h" + export * +} From 0b5d510713bb1b314c28b9a91787486543d392fa Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Fri, 22 Aug 2025 18:52:29 -0700 Subject: [PATCH 4/4] Tests: Adopt Clang availability domain declaration macros. NFC. --- .../availability_domains_bridging_header.h | 12 ++++-------- test/IRGen/Inputs/AvailabilityDomains.h | 14 ++++---------- .../custom-modules/availability-domains/Lakes.h | 5 ++--- .../custom-modules/availability-domains/Oceans.h | 10 +++------- .../custom-modules/availability-domains/Rivers.h | 8 +++----- .../custom-modules/availability-domains/Seas.h | 8 +++----- test/SILGen/Inputs/AvailabilityDomains.h | 16 ++++------------ 7 files changed, 23 insertions(+), 50 deletions(-) diff --git a/test/ClangImporter/Inputs/availability_domains_bridging_header.h b/test/ClangImporter/Inputs/availability_domains_bridging_header.h index 18fdfc79293a5..66f8dcf5cb153 100644 --- a/test/ClangImporter/Inputs/availability_domains_bridging_header.h +++ b/test/ClangImporter/Inputs/availability_domains_bridging_header.h @@ -1,11 +1,7 @@ -#include - -static struct __AvailabilityDomain bay_bridge - __attribute__((availability_domain(BayBridge))) = { - __AVAILABILITY_DOMAIN_ENABLED, 0}; -static struct __AvailabilityDomain golden_gate_bridge - __attribute__((availability_domain(GoldenGateBridge))) = { - __AVAILABILITY_DOMAIN_DISABLED, 0}; +#include + +CLANG_DISABLED_AVAILABILITY_DOMAIN(BayBridge); +CLANG_DISABLED_AVAILABILITY_DOMAIN(GoldenGateBridge); #define AVAIL 0 #define UNAVAIL 1 diff --git a/test/IRGen/Inputs/AvailabilityDomains.h b/test/IRGen/Inputs/AvailabilityDomains.h index 3248ee721e363..ad923bc48a39b 100644 --- a/test/IRGen/Inputs/AvailabilityDomains.h +++ b/test/IRGen/Inputs/AvailabilityDomains.h @@ -1,16 +1,10 @@ -#include - -static struct __AvailabilityDomain __EnabledDomain __attribute__(( - availability_domain(EnabledDomain))) = {__AVAILABILITY_DOMAIN_ENABLED, 0}; - -static struct __AvailabilityDomain __DisabledDomain __attribute__(( - availability_domain(DisabledDomain))) = {__AVAILABILITY_DOMAIN_DISABLED, 0}; +#include int dynamic_domain_pred(); -static struct __AvailabilityDomain __DynamicDomain - __attribute__((availability_domain(DynamicDomain))) = { - __AVAILABILITY_DOMAIN_DYNAMIC, dynamic_domain_pred}; +CLANG_ENABLED_AVAILABILITY_DOMAIN(EnabledDomain); +CLANG_DISABLED_AVAILABILITY_DOMAIN(DisabledDomain); +CLANG_DYNAMIC_AVAILABILITY_DOMAIN(DynamicDomain, dynamic_domain_pred); #define AVAIL 0 #define UNAVAIL 1 diff --git a/test/Inputs/custom-modules/availability-domains/Lakes.h b/test/Inputs/custom-modules/availability-domains/Lakes.h index e4c16fec80a6f..588bd346e965e 100644 --- a/test/Inputs/custom-modules/availability-domains/Lakes.h +++ b/test/Inputs/custom-modules/availability-domains/Lakes.h @@ -1,7 +1,6 @@ -#include +#include -static struct __AvailabilityDomain salt_domain __attribute__(( - availability_domain(Salt))) = {__AVAILABILITY_DOMAIN_ENABLED, 0}; +CLANG_ENABLED_AVAILABILITY_DOMAIN(Salt); #define AVAIL 0 #define UNAVAIL 1 diff --git a/test/Inputs/custom-modules/availability-domains/Oceans.h b/test/Inputs/custom-modules/availability-domains/Oceans.h index d95f5b7d4a18c..57a50b7915a9f 100644 --- a/test/Inputs/custom-modules/availability-domains/Oceans.h +++ b/test/Inputs/custom-modules/availability-domains/Oceans.h @@ -1,15 +1,11 @@ #include -#include +#include int arctic_pred(void); int pacific_pred(void); -static struct __AvailabilityDomain arctic_domain - __attribute__((availability_domain(Arctic))) = { - __AVAILABILITY_DOMAIN_DYNAMIC, arctic_pred}; -static struct __AvailabilityDomain pacific_domain - __attribute__((availability_domain(Pacific))) = { - __AVAILABILITY_DOMAIN_DYNAMIC, pacific_pred}; +CLANG_DYNAMIC_AVAILABILITY_DOMAIN(Arctic, arctic_pred); +CLANG_DYNAMIC_AVAILABILITY_DOMAIN(Pacific, pacific_pred); #define AVAIL 0 #define UNAVAIL 1 diff --git a/test/Inputs/custom-modules/availability-domains/Rivers.h b/test/Inputs/custom-modules/availability-domains/Rivers.h index 9cb0b35b01b20..e36c41d83e001 100644 --- a/test/Inputs/custom-modules/availability-domains/Rivers.h +++ b/test/Inputs/custom-modules/availability-domains/Rivers.h @@ -1,11 +1,9 @@ -#include +#include -static struct __AvailabilityDomain colorado_domain __attribute__(( - availability_domain(Colorado))) = {__AVAILABILITY_DOMAIN_DISABLED, 0}; +CLANG_DISABLED_AVAILABILITY_DOMAIN(Colorado); __attribute__((deprecated("Use Colorado instead"))) -static struct __AvailabilityDomain grand_domain __attribute__(( - availability_domain(Grand))) = {__AVAILABILITY_DOMAIN_DISABLED, 0}; +CLANG_DISABLED_AVAILABILITY_DOMAIN(Grand); #define AVAIL 0 #define UNAVAIL 1 diff --git a/test/Inputs/custom-modules/availability-domains/Seas.h b/test/Inputs/custom-modules/availability-domains/Seas.h index a5795bb07356c..87541fc7794a0 100644 --- a/test/Inputs/custom-modules/availability-domains/Seas.h +++ b/test/Inputs/custom-modules/availability-domains/Seas.h @@ -1,9 +1,7 @@ -#include +#include -static struct __AvailabilityDomain baltic_domain __attribute__(( - availability_domain(Baltic))) = {__AVAILABILITY_DOMAIN_ENABLED, 0}; -static struct __AvailabilityDomain _mediterranean __attribute__(( - availability_domain(Mediterranean))) = {__AVAILABILITY_DOMAIN_ENABLED, 0}; +CLANG_ENABLED_AVAILABILITY_DOMAIN(Baltic); +CLANG_DISABLED_AVAILABILITY_DOMAIN(Mediterranean); #define AVAIL 0 #define UNAVAIL 1 diff --git a/test/SILGen/Inputs/AvailabilityDomains.h b/test/SILGen/Inputs/AvailabilityDomains.h index 213dae3773426..9806517df089d 100644 --- a/test/SILGen/Inputs/AvailabilityDomains.h +++ b/test/SILGen/Inputs/AvailabilityDomains.h @@ -1,18 +1,10 @@ -#include - -static struct __AvailabilityDomain __EnabledDomain - __attribute__((availability_domain(EnabledDomain))) = { - __AVAILABILITY_DOMAIN_ENABLED, 0}; - -static struct __AvailabilityDomain __DisabledDomain - __attribute__((availability_domain(DisabledDomain))) = { - __AVAILABILITY_DOMAIN_DISABLED, 0}; +#include int dynamic_domain_pred(); -static struct __AvailabilityDomain __DynamicDomain - __attribute__((availability_domain(DynamicDomain))) = { - __AVAILABILITY_DOMAIN_DYNAMIC, dynamic_domain_pred}; +CLANG_ENABLED_AVAILABILITY_DOMAIN(EnabledDomain); +CLANG_DISABLED_AVAILABILITY_DOMAIN(DisabledDomain); +CLANG_DYNAMIC_AVAILABILITY_DOMAIN(DynamicDomain, dynamic_domain_pred); #define AVAIL 0 #define UNAVAIL 1