@@ -418,11 +418,8 @@ void DeclAttributes::dump(const Decl *D) const {
418418// / introduction version and does not support deprecation, obsoletion, or
419419// / messages.
420420LLVM_READONLY
421- static bool isShortAvailable (const DeclAttribute *DA) {
422- auto *AvailAttr = dyn_cast<AvailableAttr>(DA);
423- if (!AvailAttr)
424- return false ;
425-
421+ static bool isShortAvailable (const SemanticAvailableAttr &semanticAttr) {
422+ auto *AvailAttr = semanticAttr.getParsedAttr ();
426423 if (AvailAttr->isSPI ())
427424 return false ;
428425
@@ -462,20 +459,21 @@ static bool isShortAvailable(const DeclAttribute *DA) {
462459// / For example, iOS availability implies macCatalyst availability so if attributes for
463460// / both are present and they have the same 'introduced' version, we can skip printing an
464461// / explicit availability for macCatalyst.
465- static bool isShortFormAvailabilityImpliedByOther (const AvailableAttr *Attr,
466- ArrayRef<const DeclAttribute *> Others) {
462+ static bool
463+ isShortFormAvailabilityImpliedByOther (SemanticAvailableAttr Attr,
464+ ArrayRef<SemanticAvailableAttr> Others) {
467465 assert (isShortAvailable (Attr));
468466
469- for (auto *DA : Others) {
470- auto *Other = cast<AvailableAttr>(DA);
471- if (Attr->getPlatform () == Other->getPlatform ())
467+ auto platform = Attr.getDomain ().getPlatformKind ();
468+ for (auto other : Others) {
469+ auto otherPlatform = other.getDomain ().getPlatformKind ();
470+ if (platform == otherPlatform)
472471 continue ;
473472
474- if (!inheritsAvailabilityFromPlatform (Attr->getPlatform (),
475- Other->getPlatform ()))
473+ if (!inheritsAvailabilityFromPlatform (platform, otherPlatform))
476474 continue ;
477475
478- if (Attr->Introduced == Other ->Introduced )
476+ if (Attr. getParsedAttr () ->Introduced == other. getParsedAttr () ->Introduced )
479477 return true ;
480478 }
481479 return false ;
@@ -489,39 +487,43 @@ static bool isShortFormAvailabilityImpliedByOther(const AvailableAttr *Attr,
489487// / this will print:
490488// / @available(OSX 10.10, iOS 8.0, *)
491489static void printShortFormAvailable (const Decl *D,
492- ArrayRef<const DeclAttribute * > Attrs,
490+ ArrayRef<SemanticAvailableAttr > Attrs,
493491 ASTPrinter &Printer,
494492 const PrintOptions &Options,
495493 bool forAtSpecialize = false ) {
496494 assert (!Attrs.empty ());
497495 if (!forAtSpecialize)
498496 Printer << " @available(" ;
499- auto FirstAvail = cast<AvailableAttr>(Attrs.front ());
500- auto FirstAvailDomain = D->getDomainForAvailableAttr (FirstAvail);
501- if (Attrs.size () == 1 && !FirstAvailDomain.isPlatform ()) {
502- assert (FirstAvail->Introduced .has_value ());
503- Printer << FirstAvailDomain.getNameForAttributePrinting () << " " ;
504- Printer << FirstAvail->Introduced .value ().getAsString ();
505- if (!forAtSpecialize)
506- Printer << " )" ;
507- } else {
508- for (auto *DA : Attrs) {
509- auto *AvailAttr = cast<AvailableAttr>(DA);
510- auto AvailAttrDomain = D->getDomainForAvailableAttr (AvailAttr);
511- assert (AvailAttr->Introduced .has_value ());
512- // Avoid omitting available attribute when we are printing module interface.
513- if (!Options.IsForSwiftInterface &&
514- isShortFormAvailabilityImpliedByOther (AvailAttr, Attrs))
515- continue ;
516- Printer << AvailAttrDomain.getNameForAttributePrinting () << " "
517- << AvailAttr->Introduced .value ().getAsString () << " , " ;
518- }
519- Printer << " *" ;
520- if (!forAtSpecialize)
521- Printer << " )" ;
497+
498+ bool isFirst = true ;
499+ bool isPlatformAvailability = false ;
500+ for (auto semanticAttr : Attrs) {
501+ auto *availAttr = semanticAttr.getParsedAttr ();
502+ auto domain = semanticAttr.getDomain ();
503+ assert (availAttr->Introduced .has_value ());
504+
505+ // Avoid omitting available attribute when we are printing module interface.
506+ if (!Options.IsForSwiftInterface &&
507+ isShortFormAvailabilityImpliedByOther (semanticAttr, Attrs))
508+ continue ;
509+
510+ Printer << (isFirst ? " " : " , " );
511+ isFirst = false ;
512+
513+ if (domain.isPlatform ())
514+ isPlatformAvailability = true ;
515+
516+ Printer << domain.getNameForAttributePrinting () << " "
517+ << availAttr->Introduced .value ().getAsString ();
522518 }
523- if (!forAtSpecialize)
519+
520+ if (isPlatformAvailability)
521+ Printer << " , *" ;
522+
523+ if (!forAtSpecialize) {
524+ Printer << " )" ;
524525 Printer.printNewline ();
526+ }
525527}
526528
527529static void printShortFormBackDeployed (ArrayRef<const DeclAttribute *> Attrs,
@@ -775,9 +777,9 @@ void DeclAttributes::print(ASTPrinter &Printer, const PrintOptions &Options,
775777 using AttributeVector = SmallVector<const DeclAttribute *, 8 >;
776778
777779 // Process attributes in passes.
778- AttributeVector shortAvailableAttributes;
779- const DeclAttribute * swiftVersionAvailableAttribute = nullptr ;
780- const DeclAttribute * packageDescriptionVersionAvailableAttribute = nullptr ;
780+ SmallVector<SemanticAvailableAttr, 8 > shortAvailableAttributes;
781+ std::optional<SemanticAvailableAttr> swiftVersionAvailableAttribute;
782+ std::optional<SemanticAvailableAttr> packageDescriptionVersionAvailableAttribute;
781783 AttributeVector backDeployedAttributes;
782784 AttributeVector longAttributes;
783785 AttributeVector attributes;
@@ -824,30 +826,31 @@ void DeclAttributes::print(ASTPrinter &Printer, const PrintOptions &Options,
824826 // Be careful not to coalesce `@available(swift 5)` with other short
825827 // `available' attributes.
826828 if (auto *availableAttr = dyn_cast<AvailableAttr>(DA)) {
827- if (availableAttr->isLanguageVersionSpecific () &&
828- isShortAvailable (availableAttr)) {
829- swiftVersionAvailableAttribute = availableAttr;
830- continue ;
831- }
832- if (availableAttr->isPackageDescriptionVersionSpecific () &&
833- isShortAvailable (availableAttr)) {
834- packageDescriptionVersionAvailableAttribute = availableAttr;
829+ auto domain = D->getDomainForAvailableAttr (availableAttr);
830+ auto semanticAttr = SemanticAvailableAttr (availableAttr, domain);
831+ if (isShortAvailable (semanticAttr)) {
832+ if (domain.isSwiftLanguage ())
833+ swiftVersionAvailableAttribute.emplace (semanticAttr);
834+ else if (domain.isPackageDescription ())
835+ packageDescriptionVersionAvailableAttribute.emplace (semanticAttr);
836+ else
837+ shortAvailableAttributes.push_back (semanticAttr);
838+
835839 continue ;
836840 }
837841 }
838842
839843 AttributeVector &which = DA->isDeclModifier () ? modifiers :
840844 isa<BackDeployedAttr>(DA) ? backDeployedAttributes :
841- isShortAvailable (DA) ? shortAvailableAttributes :
842845 DA->isLongAttribute () ? longAttributes :
843846 attributes;
844847 which.push_back (DA);
845848 }
846849
847850 if (swiftVersionAvailableAttribute)
848- printShortFormAvailable (D, swiftVersionAvailableAttribute, Printer, Options);
851+ printShortFormAvailable (D, * swiftVersionAvailableAttribute, Printer, Options);
849852 if (packageDescriptionVersionAvailableAttribute)
850- printShortFormAvailable (D, packageDescriptionVersionAvailableAttribute, Printer, Options);
853+ printShortFormAvailable (D, * packageDescriptionVersionAvailableAttribute, Printer, Options);
851854 if (!shortAvailableAttributes.empty ())
852855 printShortFormAvailable (D, shortAvailableAttributes, Printer, Options);
853856 if (!backDeployedAttributes.empty ())
@@ -926,10 +929,12 @@ SemanticAvailableAttributes::Filter::operator()(
926929 return SemanticAvailableAttr (availableAttr, domain);
927930}
928931
929- static void printAvailableAttr (const Decl *D, const AvailableAttr *Attr,
932+ static void printAvailableAttr (const Decl *D,
933+ const SemanticAvailableAttr &SemanticAttr,
930934 ASTPrinter &Printer,
931935 const PrintOptions &Options) {
932- auto Domain = D->getDomainForAvailableAttr (Attr);
936+ auto Attr = SemanticAttr.getParsedAttr ();
937+ auto Domain = SemanticAttr.getDomain ();
933938
934939 // The parser rejects `@available(swift, unavailable)`, so when printing
935940 // attributes that are universally unavailable in Swift, we must print them
@@ -1159,6 +1164,9 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
11591164
11601165 case DeclAttrKind::Available: {
11611166 auto Attr = cast<AvailableAttr>(this );
1167+ auto Domain = D->getDomainForAvailableAttr (Attr);
1168+ auto SemanticAttr = SemanticAvailableAttr (Attr, Domain);
1169+
11621170 if (Options.printPublicInterface () && Attr->isSPI ()) {
11631171 assert (Attr->hasPlatform ());
11641172 assert (Attr->Introduced .has_value ());
@@ -1182,7 +1190,7 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
11821190 Printer.printAttrName (" @available" );
11831191 }
11841192 Printer << " (" ;
1185- printAvailableAttr (D, Attr , Printer, Options);
1193+ printAvailableAttr (D, SemanticAttr , Printer, Options);
11861194 Printer << " )" ;
11871195 break ;
11881196 }
@@ -1276,17 +1284,19 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
12761284 Printer << " kind: " << kind << " , " ;
12771285 if (target)
12781286 Printer << " target: " << target << " , " ;
1279- auto availAttrs = attr->getAvailableAttrs ();
1280- if (!availAttrs.empty ()) {
1287+ SmallVector<SemanticAvailableAttr, 8 > semanticAvailAttrs;
1288+ for (auto availAttr : attr->getAvailableAttrs ()) {
1289+ auto domain = D->getDomainForAvailableAttr (availAttr);
1290+ semanticAvailAttrs.push_back (SemanticAvailableAttr (availAttr, domain));
1291+ }
1292+
1293+ if (!semanticAvailAttrs.empty ()) {
12811294 Printer << " availability: " ;
1282- auto numAttrs = availAttrs.size ();
1283- if (numAttrs == 1 ) {
1284- printAvailableAttr (D, availAttrs[0 ], Printer, Options);
1295+ if (semanticAvailAttrs.size () == 1 ) {
1296+ printAvailableAttr (D, semanticAvailAttrs[0 ], Printer, Options);
12851297 Printer << " ; " ;
12861298 } else {
1287- SmallVector<const DeclAttribute *, 8 > tmp (availAttrs.begin (),
1288- availAttrs.end ());
1289- printShortFormAvailable (D, tmp, Printer, Options,
1299+ printShortFormAvailable (D, semanticAvailAttrs, Printer, Options,
12901300 true /* forAtSpecialize*/ );
12911301 Printer << " ; " ;
12921302 }
0 commit comments