Skip to content

Commit bd79424

Browse files
committed
Sema: Move domain-specific @available attr diagnostics to type checking.
Since the domain is now resolved by SemanticAvailableAttrRequest, diagnosing attributes with invalid combinations of fields for a specific domains needs to be delayed.
1 parent a5d60ce commit bd79424

File tree

4 files changed

+57
-65
lines changed

4 files changed

+57
-65
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1579,16 +1579,6 @@ ERROR(attr_availability_expected_equal,none,
15791579
ERROR(attr_availability_expected_version,none,
15801580
"expected version number in '%0' attribute", (StringRef))
15811581

1582-
WARNING(attr_availability_platform_agnostic_expected_option,none,
1583-
"expected 'introduced', 'deprecated', or 'obsoleted' in '%0' attribute "
1584-
"for platform '%1'", (StringRef, StringRef))
1585-
WARNING(attr_availability_platform_agnostic_expected_deprecated_version,none,
1586-
"expected version number with 'deprecated' in '%0' attribute for "
1587-
"platform '%1'", (StringRef, StringRef))
1588-
WARNING(attr_availability_platform_agnostic_infeasible_option,none,
1589-
"'%0' cannot be used in '%1' attribute for platform '%2'",
1590-
(StringRef, StringRef, StringRef))
1591-
15921582
WARNING(attr_availability_nonspecific_platform_unexpected_version,none,
15931583
"unexpected version number in '%0' attribute for non-specific platform "
15941584
"'*'", (StringRef))

include/swift/AST/DiagnosticsSema.def

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6715,6 +6715,16 @@ NOTE(type_eraser_init_spi,none,
67156715
// MARK: @available
67166716
//------------------------------------------------------------------------------
67176717

6718+
WARNING(attr_availability_expected_deprecated_version, none,
6719+
"expected version number with 'deprecated' in '%0' attribute for "
6720+
"platform '%1'", (StringRef, StringRef))
6721+
WARNING(attr_availability_cannot_be_used_for_domain, none,
6722+
"'%0' cannot be used in '%1' attribute for platform '%2'",
6723+
(StringRef, StringRef, StringRef))
6724+
WARNING(attr_availability_expected_version_spec, none,
6725+
"expected 'introduced', 'deprecated', or 'obsoleted' in '%0' attribute "
6726+
"for platform '%1'", (StringRef, StringRef))
6727+
67186728
ERROR(availability_decl_unavailable, none,
67196729
"%0 is unavailable%select{ in %2|}1%select{|: %3}3",
67206730
(const ValueDecl *, bool, StringRef, StringRef))

lib/Parse/ParseDecl.cpp

Lines changed: 6 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -542,62 +542,14 @@ ParserResult<AvailableAttr> Parser::parseExtendedAvailabilitySpecList(
542542
/*isDeclModifier*/ false);
543543
}
544544

545-
auto PlatformKind = platformFromString(Platform);
546-
auto Domain = (PlatformKind && *PlatformKind != PlatformKind::none)
547-
? AvailabilityDomain::forPlatform(*PlatformKind)
548-
: AvailabilityDomain::forUniversal();
549-
550-
// Treat 'swift' as a valid version-qualifying token, when
551-
// at least some versions were mentioned and no other
552-
// platform-agnostic availability spec has been provided.
553-
bool SomeVersion = (!Introduced.empty() ||
554-
!Deprecated.empty() ||
555-
!Obsoleted.empty());
556-
if (!PlatformKind.has_value() &&
557-
(Platform == "swift" || Platform == "_PackageDescription")) {
558-
559-
if (AttrKind == AvailableAttr::Kind::Deprecated) {
560-
diagnose(AttrLoc,
561-
diag::attr_availability_platform_agnostic_expected_deprecated_version,
562-
AttrName, Platform);
563-
return nullptr;
564-
}
565-
if (AttrKind == AvailableAttr::Kind::Unavailable) {
566-
diagnose(AttrLoc, diag::attr_availability_platform_agnostic_infeasible_option,
567-
"unavailable", AttrName, Platform);
568-
return nullptr;
569-
}
570-
assert(AttrKind == AvailableAttr::Kind::Default);
571-
572-
if (!SomeVersion) {
573-
diagnose(AttrLoc, diag::attr_availability_platform_agnostic_expected_option,
574-
AttrName, Platform);
575-
return nullptr;
576-
}
577-
578-
PlatformKind = PlatformKind::none;
579-
Domain = (Platform == "swift")
580-
? AvailabilityDomain::forSwiftLanguage()
581-
: AvailabilityDomain::forPackageDescription();
582-
}
583-
584-
585545
if (AnyArgumentInvalid)
586546
return nullptr;
587-
if (!PlatformKind.has_value()) {
588-
if (auto CorrectedPlatform = closestCorrectedPlatformString(Platform)) {
589-
diagnose(PlatformLoc, diag::attr_availability_suggest_platform, Platform,
590-
AttrName, *CorrectedPlatform)
591-
.fixItReplace(SourceRange(PlatformLoc), *CorrectedPlatform);
592-
} else {
593-
diagnose(AttrLoc, diag::attr_availability_unknown_platform, Platform,
594-
AttrName);
595-
}
596-
return nullptr;
597-
}
598547

599-
// Warn if any version is specified for non-specific platform '*'.
600-
if (Domain.isUniversal() && SomeVersion) {
548+
// Warn if any version is specified with the universal domain ('*').
549+
bool SomeVersion = (!Introduced.empty() ||
550+
!Deprecated.empty() ||
551+
!Obsoleted.empty());
552+
if (Platform == "*" && SomeVersion) {
601553
auto diag = diagnose(AttrLoc,
602554
diag::attr_availability_nonspecific_platform_unexpected_version,
603555
AttrName);
@@ -613,7 +565,7 @@ ParserResult<AvailableAttr> Parser::parseExtendedAvailabilitySpecList(
613565
return nullptr;
614566
}
615567

616-
if (PlatformKind) {
568+
if (auto PlatformKind = platformFromString(Platform)) {
617569
if (!Introduced.empty())
618570
Introduced.Version =
619571
canonicalizePlatformVersion(*PlatformKind, Introduced.Version);

lib/Sema/TypeCheckAttr.cpp

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8273,12 +8273,52 @@ SemanticAvailableAttrRequest::evaluate(swift::Evaluator &evaluator,
82738273
if (attr->hasCachedDomain())
82748274
return SemanticAvailableAttr(attr);
82758275

8276+
auto &diags = decl->getASTContext().Diags;
8277+
auto attrLoc = attr->getLocation();
8278+
auto attrName = attr->getAttrName();
8279+
auto attrKind = attr->getKind();
8280+
auto domainLoc = attr->getDomainLoc();
82768281
auto string = attr->getDomainString();
82778282
ASSERT(string);
82788283

8284+
// Attempt to resolve the domain specified for the attribute and diagnose
8285+
// if no domain is found.
82798286
auto domain = AvailabilityDomain::builtinDomainForString(*string);
8280-
if (!domain)
8287+
if (!domain) {
8288+
if (auto suggestion = closestCorrectedPlatformString(*string)) {
8289+
diags
8290+
.diagnose(domainLoc, diag::attr_availability_suggest_platform,
8291+
*string, attrName, *suggestion)
8292+
.fixItReplace(SourceRange(domainLoc), *suggestion);
8293+
} else {
8294+
diags.diagnose(attrLoc, diag::attr_availability_unknown_platform, *string,
8295+
attrName);
8296+
}
82818297
return std::nullopt;
8298+
}
8299+
8300+
if (domain->isSwiftLanguage() || domain->isPackageDescription()) {
8301+
if (attrKind == AvailableAttr::Kind::Deprecated) {
8302+
diags.diagnose(attrLoc,
8303+
diag::attr_availability_expected_deprecated_version,
8304+
attrName, *string);
8305+
return std::nullopt;
8306+
}
8307+
if (attrKind == AvailableAttr::Kind::Unavailable) {
8308+
diags.diagnose(attrLoc, diag::attr_availability_cannot_be_used_for_domain,
8309+
"unavailable", attrName, *string);
8310+
return std::nullopt;
8311+
}
8312+
assert(attrKind == AvailableAttr::Kind::Default);
8313+
8314+
bool hasVersionSpec = (attr->getRawIntroduced() ||
8315+
attr->getRawDeprecated() || attr->getRawObsoleted());
8316+
if (!hasVersionSpec) {
8317+
diags.diagnose(attrLoc, diag::attr_availability_expected_version_spec,
8318+
attrName, *string);
8319+
return std::nullopt;
8320+
}
8321+
}
82828322

82838323
const_cast<AvailableAttr *>(attr)->setCachedDomain(*domain);
82848324
return SemanticAvailableAttr(attr);

0 commit comments

Comments
 (0)