Skip to content

Commit 4153928

Browse files
authored
Merge pull request #6924 from graydon/rdar-28815071-fixit-to-narrow-availability-check
2 parents da41a13 + cdeb038 commit 4153928

13 files changed

+310
-31
lines changed

include/swift/AST/Attr.h

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -589,15 +589,18 @@ class AvailableAttr : public DeclAttribute {
589589
PlatformKind Platform,
590590
StringRef Message, StringRef Rename,
591591
const clang::VersionTuple &Introduced,
592+
SourceRange IntroducedRange,
592593
const clang::VersionTuple &Deprecated,
594+
SourceRange DeprecatedRange,
593595
const clang::VersionTuple &Obsoleted,
596+
SourceRange ObsoletedRange,
594597
PlatformAgnosticAvailabilityKind PlatformAgnostic,
595598
bool Implicit)
596599
: DeclAttribute(DAK_Available, AtLoc, Range, Implicit),
597600
Message(Message), Rename(Rename),
598-
INIT_VER_TUPLE(Introduced),
599-
INIT_VER_TUPLE(Deprecated),
600-
INIT_VER_TUPLE(Obsoleted),
601+
INIT_VER_TUPLE(Introduced), IntroducedRange(IntroducedRange),
602+
INIT_VER_TUPLE(Deprecated), DeprecatedRange(DeprecatedRange),
603+
INIT_VER_TUPLE(Obsoleted), ObsoletedRange(ObsoletedRange),
601604
PlatformAgnostic(PlatformAgnostic),
602605
Platform(Platform)
603606
{}
@@ -618,12 +621,21 @@ class AvailableAttr : public DeclAttribute {
618621
/// Indicates when the symbol was introduced.
619622
const Optional<clang::VersionTuple> Introduced;
620623

624+
/// Indicates where the Introduced version was specified.
625+
const SourceRange IntroducedRange;
626+
621627
/// Indicates when the symbol was deprecated.
622628
const Optional<clang::VersionTuple> Deprecated;
623629

630+
/// Indicates where the Deprecated version was specified.
631+
const SourceRange DeprecatedRange;
632+
624633
/// Indicates when the symbol was obsoleted.
625634
const Optional<clang::VersionTuple> Obsoleted;
626635

636+
/// Indicates where the Obsoleted version was specified.
637+
const SourceRange ObsoletedRange;
638+
627639
/// Indicates if the declaration has platform-agnostic availability.
628640
const PlatformAgnosticAvailabilityKind PlatformAgnostic;
629641

include/swift/AST/TypeRefinementContext.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,16 @@ class TypeRefinementContext {
225225
/// or an invalid location if the context reflects the minimum deployment
226226
// target.
227227
SourceLoc getIntroductionLoc() const;
228-
228+
229+
/// Returns the source range covering a _single_ decl-attribute or statement
230+
/// condition that introduced the refinement context for a given platform
231+
/// version; if zero or multiple such responsible attributes or statements
232+
/// exist, returns an invalid SourceRange.
233+
SourceRange
234+
getAvailabilityConditionVersionSourceRange(
235+
PlatformKind Platform,
236+
const clang::VersionTuple &Version) const;
237+
229238
/// Returns the source range on which this context refines types.
230239
SourceRange getSourceRange() const { return SrcRange; }
231240

lib/AST/Attr.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -715,7 +715,10 @@ AvailableAttr::createPlatformAgnostic(ASTContext &C,
715715
}
716716
return new (C) AvailableAttr(
717717
SourceLoc(), SourceRange(), PlatformKind::none, Message, Rename,
718-
NoVersion, NoVersion, Obsoleted, Kind, /* isImplicit */ false);
718+
NoVersion, SourceRange(),
719+
NoVersion, SourceRange(),
720+
Obsoleted, SourceRange(),
721+
Kind, /* isImplicit */ false);
719722
}
720723

721724
bool AvailableAttr::isActivePlatform(const ASTContext &ctx) const {

lib/AST/Availability.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,10 @@ createAvailableAttr(PlatformKind Platform,
9191
return new (Context) AvailableAttr(
9292
SourceLoc(), SourceRange(), Platform,
9393
/*Message=*/StringRef(),
94-
/*Rename=*/StringRef(), Introduced, Deprecated, Obsoleted,
94+
/*Rename=*/StringRef(),
95+
Introduced, /*IntroducedRange=*/SourceRange(),
96+
Deprecated, /*DeprecatedRange=*/SourceRange(),
97+
Obsoleted, /*ObsoletedRange=*/SourceRange(),
9598
Inferred.PlatformAgnostic, /*Implicit=*/true);
9699
}
97100

lib/AST/TypeRefinementContext.cpp

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,99 @@ SourceLoc TypeRefinementContext::getIntroductionLoc() const {
194194
llvm_unreachable("Unhandled Reason in switch.");
195195
}
196196

197+
static SourceRange
198+
getAvailabilityConditionVersionSourceRange(const PoundAvailableInfo *PAI,
199+
PlatformKind Platform,
200+
const clang::VersionTuple &Version) {
201+
SourceRange Range;
202+
for (auto *S : PAI->getQueries()) {
203+
if (auto *V = dyn_cast<PlatformVersionConstraintAvailabilitySpec>(S)) {
204+
if (V->getPlatform() == Platform && V->getVersion() == Version) {
205+
// More than one: return invalid range, no unique choice.
206+
if (Range.isValid())
207+
return SourceRange();
208+
else
209+
Range = V->getVersionSrcRange();
210+
}
211+
}
212+
}
213+
return Range;
214+
}
215+
216+
static SourceRange
217+
getAvailabilityConditionVersionSourceRange(
218+
const MutableArrayRef<StmtConditionElement> &Conds,
219+
PlatformKind Platform,
220+
const clang::VersionTuple &Version) {
221+
SourceRange Range;
222+
for (auto const& C : Conds) {
223+
if (C.getKind() == StmtConditionElement::CK_Availability) {
224+
SourceRange R = getAvailabilityConditionVersionSourceRange(
225+
C.getAvailability(), Platform, Version);
226+
// More than one: return invalid range.
227+
if (Range.isValid())
228+
return SourceRange();
229+
else
230+
Range = R;
231+
}
232+
}
233+
return Range;
234+
}
235+
236+
static SourceRange
237+
getAvailabilityConditionVersionSourceRange(const DeclAttributes &DeclAttrs,
238+
PlatformKind Platform,
239+
const clang::VersionTuple &Version) {
240+
SourceRange Range;
241+
for (auto *Attr : DeclAttrs) {
242+
if (auto *AA = dyn_cast<AvailableAttr>(Attr)) {
243+
if (AA->Introduced.hasValue() &&
244+
AA->Introduced.getValue() == Version &&
245+
AA->Platform == Platform) {
246+
247+
// More than one: return invalid range.
248+
if (Range.isValid())
249+
return SourceRange();
250+
else
251+
Range = AA->IntroducedRange;
252+
}
253+
}
254+
}
255+
return Range;
256+
}
257+
258+
SourceRange
259+
TypeRefinementContext::getAvailabilityConditionVersionSourceRange(
260+
PlatformKind Platform,
261+
const clang::VersionTuple &Version) const {
262+
switch (getReason()) {
263+
case Reason::Decl:
264+
return ::getAvailabilityConditionVersionSourceRange(
265+
Node.getAsDecl()->getAttrs(), Platform, Version);
266+
267+
case Reason::IfStmtThenBranch:
268+
case Reason::IfStmtElseBranch:
269+
return ::getAvailabilityConditionVersionSourceRange(
270+
Node.getAsIfStmt()->getCond(), Platform, Version);
271+
272+
case Reason::ConditionFollowingAvailabilityQuery:
273+
return ::getAvailabilityConditionVersionSourceRange(
274+
Node.getAsPoundAvailableInfo(), Platform, Version);
275+
276+
case Reason::GuardStmtFallthrough:
277+
case Reason::GuardStmtElseBranch:
278+
return ::getAvailabilityConditionVersionSourceRange(
279+
Node.getAsGuardStmt()->getCond(), Platform, Version);
280+
281+
case Reason::WhileStmtBody:
282+
return ::getAvailabilityConditionVersionSourceRange(
283+
Node.getAsWhileStmt()->getCond(), Platform, Version);
284+
285+
case Reason::Root:
286+
return SourceRange();
287+
}
288+
}
289+
197290
void TypeRefinementContext::print(raw_ostream &OS, SourceManager &SrcMgr,
198291
unsigned Indent) const {
199292
OS.indent(Indent);

lib/ClangImporter/ImportDecl.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1557,8 +1557,11 @@ static void applyAvailableAttribute(Decl *decl, AvailabilityContext &info,
15571557
/*Message=*/StringRef(),
15581558
/*Rename=*/StringRef(),
15591559
info.getOSVersion().getLowerEndpoint(),
1560+
/*IntroducedRange*/SourceRange(),
15601561
/*Deprecated=*/noVersion,
1562+
/*DeprecatedRange*/SourceRange(),
15611563
/*Obsoleted=*/noVersion,
1564+
/*ObsoletedRange*/SourceRange(),
15621565
PlatformAgnosticAvailabilityKind::None,
15631566
/*Implicit=*/false);
15641567

@@ -6572,7 +6575,12 @@ void ClangImporter::Implementation::importAttributes(
65726575
auto AvAttr = new (C) AvailableAttr(SourceLoc(), SourceRange(),
65736576
platformK.getValue(),
65746577
message, swiftReplacement,
6575-
introduced, deprecated, obsoleted,
6578+
introduced,
6579+
/*IntroducedRange=*/SourceRange(),
6580+
deprecated,
6581+
/*DeprecatedRange=*/SourceRange(),
6582+
obsoleted,
6583+
/*ObsoletedRange=*/SourceRange(),
65766584
PlatformAgnostic, /*Implicit=*/false);
65776585

65786586
MappedDecl->getAttrs().add(AvAttr);

lib/Parse/ParseDecl.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -897,18 +897,21 @@ bool Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
897897
for (auto *Spec : Specs) {
898898
PlatformKind Platform;
899899
clang::VersionTuple Version;
900+
SourceRange VersionRange;
900901
PlatformAgnosticAvailabilityKind PlatformAgnostic;
901902

902903
if (auto *PlatformVersionSpec =
903904
dyn_cast<PlatformVersionConstraintAvailabilitySpec>(Spec)) {
904905
Platform = PlatformVersionSpec->getPlatform();
905906
Version = PlatformVersionSpec->getVersion();
907+
VersionRange = PlatformVersionSpec->getVersionSrcRange();
906908
PlatformAgnostic = PlatformAgnosticAvailabilityKind::None;
907909

908910
} else if (auto *LanguageVersionSpec =
909911
dyn_cast<LanguageVersionConstraintAvailabilitySpec>(Spec)) {
910912
Platform = PlatformKind::none;
911913
Version = LanguageVersionSpec->getVersion();
914+
VersionRange = LanguageVersionSpec->getVersionSrcRange();
912915
PlatformAgnostic =
913916
PlatformAgnosticAvailabilityKind::SwiftVersionSpecific;
914917

@@ -922,8 +925,11 @@ bool Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
922925
/*Message=*/StringRef(),
923926
/*Rename=*/StringRef(),
924927
/*Introduced=*/Version,
928+
/*IntroducedRange=*/VersionRange,
925929
/*Deprecated=*/clang::VersionTuple(),
930+
/*DeprecatedRange=*/SourceRange(),
926931
/*Obsoleted=*/clang::VersionTuple(),
932+
/*ObsoletedRange=*/SourceRange(),
927933
PlatformAgnostic,
928934
/*Implicit=*/true));
929935
}
@@ -941,6 +947,7 @@ bool Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
941947

942948
StringRef Message, Renamed;
943949
clang::VersionTuple Introduced, Deprecated, Obsoleted;
950+
SourceRange IntroducedRange, DeprecatedRange, ObsoletedRange;
944951
auto PlatformAgnostic = PlatformAgnosticAvailabilityKind::None;
945952
bool AnyAnnotations = false;
946953
int ParamIndex = 0;
@@ -1060,8 +1067,10 @@ bool Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
10601067
(ArgumentKind == IsDeprecated) ? Deprecated :
10611068
Obsoleted;
10621069

1063-
SourceRange VersionRange;
1064-
1070+
auto &VersionRange = (ArgumentKind == IsIntroduced) ? IntroducedRange :
1071+
(ArgumentKind == IsDeprecated) ? DeprecatedRange :
1072+
ObsoletedRange;
1073+
10651074
if (parseVersionTuple(
10661075
VersionArg, VersionRange,
10671076
Diagnostic(diag::attr_availability_expected_version,
@@ -1127,9 +1136,9 @@ bool Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
11271136
AvailableAttr(AtLoc, AttrRange,
11281137
PlatformKind.getValue(),
11291138
Message, Renamed,
1130-
Introduced,
1131-
Deprecated,
1132-
Obsoleted,
1139+
Introduced, IntroducedRange,
1140+
Deprecated, DeprecatedRange,
1141+
Obsoleted, ObsoletedRange,
11331142
PlatformAgnostic,
11341143
/*Implicit=*/false));
11351144
} else {

0 commit comments

Comments
 (0)