mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
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.
This commit is contained in:
@@ -41,9 +41,7 @@ getCustomDomainKind(clang::FeatureAvailKind featureAvailKind) {
|
||||
static const CustomAvailabilityDomain *
|
||||
customDomainForClangDecl(ValueDecl *decl) {
|
||||
auto *clangDecl = decl->getClangDecl();
|
||||
ASSERT(clangDecl);
|
||||
|
||||
auto *varDecl = dyn_cast<clang::VarDecl>(clangDecl);
|
||||
auto *varDecl = dyn_cast_or_null<clang::VarDecl>(clangDecl);
|
||||
if (!varDecl)
|
||||
return nullptr;
|
||||
|
||||
|
||||
@@ -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<ValueDecl>(D)) {
|
||||
if (auto domain = AvailabilityDomain::forCustom(const_cast<ValueDecl *>(VD))) {
|
||||
Out << "availability domain";
|
||||
|
||||
if (includeName) {
|
||||
Out << " " << FormatOpts.OpeningQuotationMark;
|
||||
Out << domain->getNameForDiagnostics();
|
||||
Out << FormatOpts.ClosingQuotationMark;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (includeName) {
|
||||
if (auto accessor = dyn_cast<AccessorDecl>(D)) {
|
||||
// If it's an accessor, describe that and then switch to discussing its
|
||||
|
||||
@@ -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;
|
||||
|
||||
30
test/ClangImporter/availability_custom_domains_access.swift
Normal file
30
test/ClangImporter/availability_custom_domains_access.swift
Normal file
@@ -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) { }
|
||||
}
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user