Skip to content

Commit 8840ea6

Browse files
committed
Add support for parsing an availability argument in @_specialize
1 parent 7dd295f commit 8840ea6

File tree

11 files changed

+432
-273
lines changed

11 files changed

+432
-273
lines changed

include/swift/AST/Attr.h

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1302,7 +1302,8 @@ class SynthesizedProtocolAttr : public DeclAttribute {
13021302
/// type list.
13031303
class SpecializeAttr final
13041304
: public DeclAttribute,
1305-
private llvm::TrailingObjects<SpecializeAttr, Identifier> {
1305+
private llvm::TrailingObjects<SpecializeAttr, Identifier,
1306+
AvailableAttr *> {
13061307
friend class SpecializeAttrTargetDeclRequest;
13071308
friend TrailingObjects;
13081309

@@ -1321,35 +1322,44 @@ class SpecializeAttr final
13211322
LazyMemberLoader *resolver = nullptr;
13221323
uint64_t resolverContextData;
13231324
size_t numSPIGroups;
1325+
size_t numAvailableAttrs;
13241326

13251327
SpecializeAttr(SourceLoc atLoc, SourceRange Range,
13261328
TrailingWhereClause *clause, bool exported,
13271329
SpecializationKind kind, GenericSignature specializedSignature,
1328-
DeclNameRef targetFunctionName,
1329-
ArrayRef<Identifier> spiGroups);
1330+
DeclNameRef targetFunctionName, ArrayRef<Identifier> spiGroups,
1331+
ArrayRef<AvailableAttr *> availabilityAttrs);
13301332

13311333
public:
1332-
static SpecializeAttr *create(ASTContext &Ctx, SourceLoc atLoc,
1333-
SourceRange Range, TrailingWhereClause *clause,
1334-
bool exported, SpecializationKind kind,
1335-
DeclNameRef targetFunctionName,
1336-
ArrayRef<Identifier> spiGroups,
1337-
GenericSignature specializedSignature
1338-
= nullptr);
1334+
static SpecializeAttr *
1335+
create(ASTContext &Ctx, SourceLoc atLoc, SourceRange Range,
1336+
TrailingWhereClause *clause, bool exported, SpecializationKind kind,
1337+
DeclNameRef targetFunctionName, ArrayRef<Identifier> spiGroups,
1338+
ArrayRef<AvailableAttr *> availabilityAttrs,
1339+
GenericSignature specializedSignature = nullptr);
13391340

13401341
static SpecializeAttr *create(ASTContext &ctx, bool exported,
13411342
SpecializationKind kind,
13421343
ArrayRef<Identifier> spiGroups,
1344+
ArrayRef<AvailableAttr *> availabilityAttrs,
13431345
GenericSignature specializedSignature,
13441346
DeclNameRef replacedFunction);
13451347

13461348
static SpecializeAttr *create(ASTContext &ctx, bool exported,
13471349
SpecializationKind kind,
13481350
ArrayRef<Identifier> spiGroups,
1351+
ArrayRef<AvailableAttr *> availabilityAttrs,
13491352
GenericSignature specializedSignature,
13501353
DeclNameRef replacedFunction,
13511354
LazyMemberLoader *resolver, uint64_t data);
13521355

1356+
size_t numTrailingObjects(OverloadToken<Identifier>) const {
1357+
return numSPIGroups;
1358+
}
1359+
1360+
size_t numTrailingObjects(OverloadToken<AvailableAttr *>) const {
1361+
return numAvailableAttrs;
1362+
}
13531363
/// Name of SPIs declared by the attribute.
13541364
///
13551365
/// Note: A single SPI name per attribute is currently supported but this
@@ -1359,6 +1369,11 @@ class SpecializeAttr final
13591369
numSPIGroups };
13601370
}
13611371

1372+
ArrayRef<AvailableAttr *> getAvailabeAttrs() const {
1373+
return {this->template getTrailingObjects<AvailableAttr *>(),
1374+
numAvailableAttrs};
1375+
}
1376+
13621377
TrailingWhereClause *getTrailingWhereClause() const;
13631378

13641379
GenericSignature getSpecializedSignature() const {

include/swift/AST/DiagnosticsParse.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,6 +1399,9 @@ ERROR(attr_expected_lparen,none,
13991399
ERROR(attr_expected_rparen,none,
14001400
"expected ')' in '%0' %select{attribute|modifier}1", (StringRef, bool))
14011401

1402+
ERROR(attr_expected_semi,none,
1403+
"expected ';' in '%0' %select{attribute|modifier}1", (StringRef, bool))
1404+
14021405
ERROR(attr_expected_comma,none,
14031406
"expected ',' in '%0' %select{attribute|modifier}1", (StringRef, bool))
14041407

include/swift/Parse/Parser.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1061,6 +1061,7 @@ class Parser {
10611061
Optional<SpecializeAttr::SpecializationKind> &Kind,
10621062
TrailingWhereClause *&TrailingWhereClause, DeclNameRef &targetFunction,
10631063
SmallVectorImpl<Identifier> &spiGroups,
1064+
SmallVectorImpl<AvailableAttr *> &availableAttrs,
10641065
llvm::function_ref<bool(Parser &)> parseSILTargetName,
10651066
llvm::function_ref<bool(Parser &)> parseSILSIPModule);
10661067

@@ -1850,7 +1851,11 @@ class Parser {
18501851
parsePlatformVersionConstraintSpec();
18511852
ParserResult<PlatformAgnosticVersionConstraintAvailabilitySpec>
18521853
parsePlatformAgnosticVersionConstraintSpec();
1853-
1854+
bool
1855+
parseAvailability(bool parseAsPartOfSpecializeAttr, StringRef AttrName,
1856+
bool &DiscardAttribute, SourceRange &attrRange,
1857+
SourceLoc AtLoc, SourceLoc Loc,
1858+
llvm::function_ref<void(AvailableAttr *)> addAttribute);
18541859
//===--------------------------------------------------------------------===//
18551860
// Code completion second pass.
18561861

lib/AST/Attr.cpp

Lines changed: 100 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -430,10 +430,11 @@ static bool isShortFormAvailabilityImpliedByOther(const AvailableAttr *Attr,
430430
/// @available(OSX 10.10, iOS 8.0, *)
431431
static void printShortFormAvailable(ArrayRef<const DeclAttribute *> Attrs,
432432
ASTPrinter &Printer,
433-
const PrintOptions &Options) {
433+
const PrintOptions &Options,
434+
bool forAtSpecialize = false) {
434435
assert(!Attrs.empty());
435-
436-
Printer << "@available(";
436+
if (!forAtSpecialize)
437+
Printer << "@available(";
437438
auto FirstAvail = cast<AvailableAttr>(Attrs.front());
438439
if (Attrs.size() == 1 &&
439440
FirstAvail->getPlatformAgnosticAvailability() !=
@@ -445,8 +446,9 @@ static void printShortFormAvailable(ArrayRef<const DeclAttribute *> Attrs,
445446
assert(FirstAvail->isPackageDescriptionVersionSpecific());
446447
Printer << "_PackageDescription ";
447448
}
448-
Printer << FirstAvail->Introduced.getValue().getAsString()
449-
<< ")";
449+
Printer << FirstAvail->Introduced.getValue().getAsString();
450+
if (!forAtSpecialize)
451+
Printer << ")";
450452
} else {
451453
for (auto *DA : Attrs) {
452454
auto *AvailAttr = cast<AvailableAttr>(DA);
@@ -458,9 +460,12 @@ static void printShortFormAvailable(ArrayRef<const DeclAttribute *> Attrs,
458460
Printer << platformString(AvailAttr->Platform) << " "
459461
<< AvailAttr->Introduced.getValue().getAsString() << ", ";
460462
}
461-
Printer << "*)";
463+
Printer << "*";
464+
if (!forAtSpecialize)
465+
Printer << ")";
462466
}
463-
Printer.printNewline();
467+
if (!forAtSpecialize)
468+
Printer.printNewline();
464469
}
465470

466471
/// The kind of a parameter in a `wrt:` differentiation parameters clause:
@@ -745,6 +750,53 @@ SourceLoc DeclAttributes::getStartLoc(bool forModifiers) const {
745750
return lastAttr ? lastAttr->getRangeWithAt().Start : SourceLoc();
746751
}
747752

753+
static void printAvailableAttr(const AvailableAttr *Attr, ASTPrinter &Printer,
754+
const PrintOptions &Options) {
755+
if (Attr->isLanguageVersionSpecific())
756+
Printer << "swift";
757+
else if (Attr->isPackageDescriptionVersionSpecific())
758+
Printer << "_PackageDescription";
759+
else
760+
Printer << Attr->platformString();
761+
762+
if (Attr->isUnconditionallyUnavailable())
763+
Printer << ", unavailable";
764+
else if (Attr->isUnconditionallyDeprecated())
765+
Printer << ", deprecated";
766+
767+
if (Attr->Introduced)
768+
Printer << ", introduced: " << Attr->Introduced.getValue().getAsString();
769+
if (Attr->Deprecated)
770+
Printer << ", deprecated: " << Attr->Deprecated.getValue().getAsString();
771+
if (Attr->Obsoleted)
772+
Printer << ", obsoleted: " << Attr->Obsoleted.getValue().getAsString();
773+
774+
if (!Attr->Rename.empty()) {
775+
Printer << ", renamed: \"" << Attr->Rename << "\"";
776+
} else if (Attr->RenameDecl) {
777+
Printer << ", renamed: \"";
778+
if (auto *Accessor = dyn_cast<AccessorDecl>(Attr->RenameDecl)) {
779+
SmallString<32> Name;
780+
llvm::raw_svector_ostream OS(Name);
781+
Accessor->printUserFacingName(OS);
782+
Printer << Name.str();
783+
} else {
784+
Printer << Attr->RenameDecl->getName();
785+
}
786+
Printer << "\"";
787+
}
788+
789+
// If there's no message, but this is specifically an imported
790+
// "unavailable in Swift" attribute, synthesize a message to look good in
791+
// the generated interface.
792+
if (!Attr->Message.empty()) {
793+
Printer << ", message: ";
794+
Printer.printEscapedStringLiteral(Attr->Message);
795+
} else if (Attr->getPlatformAgnosticAvailability() ==
796+
PlatformAgnosticAvailabilityKind::UnavailableInSwift)
797+
Printer << ", message: \"Not available in Swift\"";
798+
}
799+
748800
bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
749801
const Decl *D) const {
750802

@@ -890,51 +942,7 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
890942
Printer.printAttrName("@available");
891943
Printer << "(";
892944
auto Attr = cast<AvailableAttr>(this);
893-
if (Attr->isLanguageVersionSpecific())
894-
Printer << "swift";
895-
else if (Attr->isPackageDescriptionVersionSpecific())
896-
Printer << "_PackageDescription";
897-
else
898-
Printer << Attr->platformString();
899-
900-
if (Attr->isUnconditionallyUnavailable())
901-
Printer << ", unavailable";
902-
else if (Attr->isUnconditionallyDeprecated())
903-
Printer << ", deprecated";
904-
905-
if (Attr->Introduced)
906-
Printer << ", introduced: " << Attr->Introduced.getValue().getAsString();
907-
if (Attr->Deprecated)
908-
Printer << ", deprecated: " << Attr->Deprecated.getValue().getAsString();
909-
if (Attr->Obsoleted)
910-
Printer << ", obsoleted: " << Attr->Obsoleted.getValue().getAsString();
911-
912-
if (!Attr->Rename.empty()) {
913-
Printer << ", renamed: \"" << Attr->Rename << "\"";
914-
} else if (Attr->RenameDecl) {
915-
Printer << ", renamed: \"";
916-
if (auto *Accessor = dyn_cast<AccessorDecl>(Attr->RenameDecl)) {
917-
SmallString<32> Name;
918-
llvm::raw_svector_ostream OS(Name);
919-
Accessor->printUserFacingName(OS);
920-
Printer << Name.str();
921-
} else {
922-
Printer << Attr->RenameDecl->getName();
923-
}
924-
Printer << "\"";
925-
}
926-
927-
// If there's no message, but this is specifically an imported
928-
// "unavailable in Swift" attribute, synthesize a message to look good in
929-
// the generated interface.
930-
if (!Attr->Message.empty()) {
931-
Printer << ", message: ";
932-
Printer.printEscapedStringLiteral(Attr->Message);
933-
}
934-
else if (Attr->getPlatformAgnosticAvailability()
935-
== PlatformAgnosticAvailabilityKind::UnavailableInSwift)
936-
Printer << ", message: \"Not available in Swift\"";
937-
945+
printAvailableAttr(Attr, Printer, Options);
938946
Printer << ")";
939947
break;
940948
}
@@ -984,6 +992,21 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
984992
Printer << "kind: " << kind << ", ";
985993
if (target)
986994
Printer << "target: " << target << ", ";
995+
auto availAttrs = attr->getAvailabeAttrs();
996+
if (!availAttrs.empty()) {
997+
Printer << "availability: ";
998+
auto numAttrs = availAttrs.size();
999+
if (numAttrs == 1) {
1000+
printAvailableAttr(availAttrs[0], Printer, Options);
1001+
Printer << "; ";
1002+
} else {
1003+
SmallVector<const DeclAttribute *, 8> tmp(availAttrs.begin(),
1004+
availAttrs.end());
1005+
printShortFormAvailable(tmp, Printer, Options,
1006+
true /*forAtSpecialize*/);
1007+
Printer << "; ";
1008+
}
1009+
}
9871010
SmallVector<Requirement, 4> requirementsScratch;
9881011
auto requirements = attr->getSpecializedSignature().getRequirements();
9891012
auto *FnDecl = dyn_cast_or_null<AbstractFunctionDecl>(D);
@@ -1663,13 +1686,18 @@ SpecializeAttr::SpecializeAttr(SourceLoc atLoc, SourceRange range,
16631686
SpecializationKind kind,
16641687
GenericSignature specializedSignature,
16651688
DeclNameRef targetFunctionName,
1666-
ArrayRef<Identifier> spiGroups)
1689+
ArrayRef<Identifier> spiGroups,
1690+
ArrayRef<AvailableAttr *> availableAttrs)
16671691
: DeclAttribute(DAK_Specialize, atLoc, range,
16681692
/*Implicit=*/clause == nullptr),
16691693
trailingWhereClause(clause), specializedSignature(specializedSignature),
1670-
targetFunctionName(targetFunctionName), numSPIGroups(spiGroups.size()) {
1694+
targetFunctionName(targetFunctionName), numSPIGroups(spiGroups.size()),
1695+
numAvailableAttrs(availableAttrs.size()) {
16711696
std::uninitialized_copy(spiGroups.begin(), spiGroups.end(),
16721697
getTrailingObjects<Identifier>());
1698+
std::uninitialized_copy(availableAttrs.begin(), availableAttrs.end(),
1699+
getTrailingObjects<AvailableAttr *>());
1700+
16731701
Bits.SpecializeAttr.exported = exported;
16741702
Bits.SpecializeAttr.kind = unsigned(kind);
16751703
}
@@ -1684,35 +1712,41 @@ SpecializeAttr *SpecializeAttr::create(ASTContext &Ctx, SourceLoc atLoc,
16841712
bool exported, SpecializationKind kind,
16851713
DeclNameRef targetFunctionName,
16861714
ArrayRef<Identifier> spiGroups,
1715+
ArrayRef<AvailableAttr *> availableAttrs,
16871716
GenericSignature specializedSignature) {
1688-
unsigned size = totalSizeToAlloc<Identifier>(spiGroups.size());
1717+
unsigned size = totalSizeToAlloc<Identifier, AvailableAttr *>(
1718+
spiGroups.size(), availableAttrs.size());
16891719
void *mem = Ctx.Allocate(size, alignof(SpecializeAttr));
16901720
return new (mem)
16911721
SpecializeAttr(atLoc, range, clause, exported, kind, specializedSignature,
1692-
targetFunctionName, spiGroups);
1722+
targetFunctionName, spiGroups, availableAttrs);
16931723
}
16941724

16951725
SpecializeAttr *SpecializeAttr::create(ASTContext &ctx, bool exported,
16961726
SpecializationKind kind,
16971727
ArrayRef<Identifier> spiGroups,
1728+
ArrayRef<AvailableAttr *> availableAttrs,
16981729
GenericSignature specializedSignature,
16991730
DeclNameRef targetFunctionName) {
1700-
unsigned size = totalSizeToAlloc<Identifier>(spiGroups.size());
1731+
unsigned size = totalSizeToAlloc<Identifier, AvailableAttr *>(
1732+
spiGroups.size(), availableAttrs.size());
17011733
void *mem = ctx.Allocate(size, alignof(SpecializeAttr));
1702-
return new (mem)
1703-
SpecializeAttr(SourceLoc(), SourceRange(), nullptr, exported, kind,
1704-
specializedSignature, targetFunctionName, spiGroups);
1734+
return new (mem) SpecializeAttr(
1735+
SourceLoc(), SourceRange(), nullptr, exported, kind, specializedSignature,
1736+
targetFunctionName, spiGroups, availableAttrs);
17051737
}
17061738

17071739
SpecializeAttr *SpecializeAttr::create(
17081740
ASTContext &ctx, bool exported, SpecializationKind kind,
1709-
ArrayRef<Identifier> spiGroups, GenericSignature specializedSignature,
1710-
DeclNameRef targetFunctionName, LazyMemberLoader *resolver, uint64_t data) {
1711-
unsigned size = totalSizeToAlloc<Identifier>(spiGroups.size());
1741+
ArrayRef<Identifier> spiGroups, ArrayRef<AvailableAttr *> availableAttrs,
1742+
GenericSignature specializedSignature, DeclNameRef targetFunctionName,
1743+
LazyMemberLoader *resolver, uint64_t data) {
1744+
unsigned size = totalSizeToAlloc<Identifier, AvailableAttr *>(
1745+
spiGroups.size(), availableAttrs.size());
17121746
void *mem = ctx.Allocate(size, alignof(SpecializeAttr));
1713-
auto *attr = new (mem)
1714-
SpecializeAttr(SourceLoc(), SourceRange(), nullptr, exported, kind,
1715-
specializedSignature, targetFunctionName, spiGroups);
1747+
auto *attr = new (mem) SpecializeAttr(
1748+
SourceLoc(), SourceRange(), nullptr, exported, kind, specializedSignature,
1749+
targetFunctionName, spiGroups, availableAttrs);
17161750
attr->resolver = resolver;
17171751
attr->resolverContextData = data;
17181752
return attr;

0 commit comments

Comments
 (0)