2323#include " swift/AST/ASTWalker.h"
2424#include " swift/AST/AvailabilitySpec.h"
2525#include " swift/AST/ConformanceLookup.h"
26+ #include " swift/AST/DiagnosticsParse.h"
2627#include " swift/AST/DiagnosticsSema.h"
2728#include " swift/AST/ExistentialLayout.h"
2829#include " swift/AST/Expr.h"
@@ -5130,6 +5131,8 @@ static bool diagnoseAvailabilityCondition(PoundAvailableInfo *info,
51305131 StringRef queryName =
51315132 info->isUnavailability () ? " #unavailable" : " #available" ;
51325133
5134+ bool hasValidSpecs = false ;
5135+ bool allValidSpecsArePlatform = true ;
51335136 std::optional<SourceLoc> wildcardLoc;
51345137 llvm::SmallSet<AvailabilityDomain, 8 > seenDomains;
51355138 for (auto spec : info->getSemanticAvailabilitySpecs (DC)) {
@@ -5140,24 +5143,44 @@ static bool diagnoseAvailabilityCondition(PoundAvailableInfo *info,
51405143 }
51415144
51425145 auto domain = spec.getDomain ();
5146+ auto loc = parsedSpec->getStartLoc ();
5147+ bool hasVersion = !spec.getVersion ().empty ();
51435148
5144- if (!domain.isPlatform ()) {
5145- diags.diagnose (
5146- parsedSpec->getStartLoc (),
5147- domain.isSwiftLanguage ()
5148- ? diag::availability_query_swift_not_allowed
5149- : diag::availability_query_package_description_not_allowed,
5150- queryName);
5149+ if (!domain.supportsQueries ()) {
5150+ diags.diagnose (loc, diag::availability_query_not_allowed,
5151+ domain.getNameForDiagnostics (), hasVersion, queryName);
51515152 return true ;
51525153 }
51535154
5154- // Diagnose duplicate platforms.
5155+ if (!domain.isPlatform () && info->getQueries ().size () > 1 ) {
5156+ diags.diagnose (loc, diag::availability_must_occur_alone,
5157+ domain.getNameForDiagnostics (), hasVersion);
5158+ return true ;
5159+ }
5160+
5161+ if (domain.isVersioned ()) {
5162+ if (!hasVersion) {
5163+ diags.diagnose (loc, diag::avail_query_expected_version_number);
5164+ return true ;
5165+ }
5166+ } else if (hasVersion) {
5167+ diags
5168+ .diagnose (loc, diag::availability_unexpected_version,
5169+ domain.getNameForDiagnostics ())
5170+ .highlight (parsedSpec->getVersionSrcRange ());
5171+ return true ;
5172+ }
5173+
5174+ // Diagnose duplicate domains.
51555175 if (!seenDomains.insert (domain).second ) {
5156- diags.diagnose (parsedSpec->getStartLoc (),
5157- diag::availability_query_repeated_platform,
5158- domain.getNameForAttributePrinting ());
5176+ diags.diagnose (loc, diag::availability_query_already_specified,
5177+ domain.isVersioned (), domain.getNameForDiagnostics ());
51595178 return true ;
51605179 }
5180+
5181+ hasValidSpecs = true ;
5182+ if (!domain.isPlatform ())
5183+ allValidSpecsArePlatform = false ;
51615184 }
51625185
51635186 if (info->isUnavailability ()) {
@@ -5167,7 +5190,7 @@ static bool diagnoseAvailabilityCondition(PoundAvailableInfo *info,
51675190 diag::unavailability_query_wildcard_not_required)
51685191 .fixItRemove (*wildcardLoc);
51695192 }
5170- } else if (!wildcardLoc) {
5193+ } else if (!wildcardLoc && hasValidSpecs && allValidSpecsArePlatform ) {
51715194 if (info->getQueries ().size () > 0 ) {
51725195 auto insertLoc = info->getQueries ().back ()->getSourceRange ().End ;
51735196 diags.diagnose (insertLoc, diag::availability_query_wildcard_required)
0 commit comments