mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Check deprecation for getters and setters
This handles the case where just one accessor is deprecated but not the other, which does come up sometimes in Apple's frameworks. rdar://problem/18633725
This commit is contained in:
@@ -3590,22 +3590,23 @@ NOTE(availability_obsoleted, none,
|
|||||||
(DeclName, StringRef, clang::VersionTuple))
|
(DeclName, StringRef, clang::VersionTuple))
|
||||||
|
|
||||||
WARNING(availability_deprecated, none,
|
WARNING(availability_deprecated, none,
|
||||||
"%0 %select{is|%select{is|was}3}1 deprecated"
|
"%select{getter for |setter for |}0%1 %select{is|%select{is|was}4}2 "
|
||||||
"%select{| %select{on|in}3 %2%select{| %4}3}1",
|
"deprecated%select{| %select{on|in}4 %3%select{| %5}4}2",
|
||||||
(DeclName, bool, StringRef, bool, clang::VersionTuple))
|
(unsigned, DeclName, bool, StringRef, bool, clang::VersionTuple))
|
||||||
|
|
||||||
WARNING(availability_deprecated_msg, none,
|
WARNING(availability_deprecated_msg, none,
|
||||||
"%0 %select{is|%select{is|was}3}1 deprecated"
|
"%select{getter for |setter for |}0%1 %select{is|%select{is|was}4}2 "
|
||||||
"%select{| %select{on|in}3 %2%select{| %4}3}1: %5",
|
"deprecated%select{| %select{on|in}4 %3%select{| %5}4}2: %6",
|
||||||
(DeclName, bool, StringRef, bool, clang::VersionTuple, StringRef))
|
(unsigned, DeclName, bool, StringRef, bool, clang::VersionTuple,
|
||||||
|
StringRef))
|
||||||
|
|
||||||
WARNING(availability_deprecated_rename, none,
|
WARNING(availability_deprecated_rename, none,
|
||||||
"%0 %select{is|%select{is|was}3}1 deprecated"
|
"%select{getter for |setter for |}0%1 %select{is|%select{is|was}4}2 "
|
||||||
"%select{| %select{on|in}3 %2%select{| %4}3}1: "
|
"deprecated%select{| %select{on|in}4 %3%select{| %5}4}2: "
|
||||||
"%select{renamed to|replaced by}5%" REPLACEMENT_DECL_KIND_SELECT "6 "
|
"%select{renamed to|replaced by}6%" REPLACEMENT_DECL_KIND_SELECT "7 "
|
||||||
"'%7'",
|
"'%8'",
|
||||||
(DeclName, bool, StringRef, bool, clang::VersionTuple, bool, unsigned,
|
(unsigned, DeclName, bool, StringRef, bool, clang::VersionTuple, bool,
|
||||||
StringRef))
|
unsigned, StringRef))
|
||||||
#undef REPLACEMENT_DECL_KIND_SELECT
|
#undef REPLACEMENT_DECL_KIND_SELECT
|
||||||
|
|
||||||
NOTE(note_deprecated_rename, none,
|
NOTE(note_deprecated_rename, none,
|
||||||
|
|||||||
@@ -1932,14 +1932,25 @@ void TypeChecker::diagnoseIfDeprecated(SourceRange ReferenceRange,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DeclName Name = DeprecatedDecl->getFullName();
|
DeclName Name;
|
||||||
|
Optional<unsigned> rawAccessorKind;
|
||||||
|
if (auto *accessor = dyn_cast<AccessorDecl>(DeprecatedDecl)) {
|
||||||
|
Name = accessor->getStorage()->getFullName();
|
||||||
|
assert(accessor->isGetterOrSetter());
|
||||||
|
rawAccessorKind = static_cast<unsigned>(accessor->getAccessorKind());
|
||||||
|
} else {
|
||||||
|
Name = DeprecatedDecl->getFullName();
|
||||||
|
}
|
||||||
|
|
||||||
StringRef Platform = Attr->prettyPlatformString();
|
StringRef Platform = Attr->prettyPlatformString();
|
||||||
clang::VersionTuple DeprecatedVersion;
|
clang::VersionTuple DeprecatedVersion;
|
||||||
if (Attr->Deprecated)
|
if (Attr->Deprecated)
|
||||||
DeprecatedVersion = Attr->Deprecated.getValue();
|
DeprecatedVersion = Attr->Deprecated.getValue();
|
||||||
|
|
||||||
|
static const unsigned NOT_ACCESSOR_INDEX = 2;
|
||||||
if (Attr->Message.empty() && Attr->Rename.empty()) {
|
if (Attr->Message.empty() && Attr->Rename.empty()) {
|
||||||
diagnose(ReferenceRange.Start, diag::availability_deprecated, Name,
|
diagnose(ReferenceRange.Start, diag::availability_deprecated,
|
||||||
|
rawAccessorKind.getValueOr(NOT_ACCESSOR_INDEX), Name,
|
||||||
Attr->hasPlatform(), Platform, Attr->Deprecated.hasValue(),
|
Attr->hasPlatform(), Platform, Attr->Deprecated.hasValue(),
|
||||||
DeprecatedVersion)
|
DeprecatedVersion)
|
||||||
.highlight(Attr->getRange());
|
.highlight(Attr->getRange());
|
||||||
@@ -1953,21 +1964,23 @@ void TypeChecker::diagnoseIfDeprecated(SourceRange ReferenceRange,
|
|||||||
|
|
||||||
if (!Attr->Message.empty()) {
|
if (!Attr->Message.empty()) {
|
||||||
EncodedDiagnosticMessage EncodedMessage(Attr->Message);
|
EncodedDiagnosticMessage EncodedMessage(Attr->Message);
|
||||||
diagnose(ReferenceRange.Start, diag::availability_deprecated_msg, Name,
|
diagnose(ReferenceRange.Start, diag::availability_deprecated_msg,
|
||||||
|
rawAccessorKind.getValueOr(NOT_ACCESSOR_INDEX), Name,
|
||||||
Attr->hasPlatform(), Platform, Attr->Deprecated.hasValue(),
|
Attr->hasPlatform(), Platform, Attr->Deprecated.hasValue(),
|
||||||
DeprecatedVersion, EncodedMessage.Message)
|
DeprecatedVersion, EncodedMessage.Message)
|
||||||
.highlight(Attr->getRange());
|
.highlight(Attr->getRange());
|
||||||
} else {
|
} else {
|
||||||
unsigned rawReplaceKind = static_cast<unsigned>(
|
unsigned rawReplaceKind = static_cast<unsigned>(
|
||||||
replacementDeclKind.getValueOr(ReplacementDeclKind::None));
|
replacementDeclKind.getValueOr(ReplacementDeclKind::None));
|
||||||
diagnose(ReferenceRange.Start, diag::availability_deprecated_rename, Name,
|
diagnose(ReferenceRange.Start, diag::availability_deprecated_rename,
|
||||||
|
rawAccessorKind.getValueOr(NOT_ACCESSOR_INDEX), Name,
|
||||||
Attr->hasPlatform(), Platform, Attr->Deprecated.hasValue(),
|
Attr->hasPlatform(), Platform, Attr->Deprecated.hasValue(),
|
||||||
DeprecatedVersion, replacementDeclKind.hasValue(), rawReplaceKind,
|
DeprecatedVersion, replacementDeclKind.hasValue(), rawReplaceKind,
|
||||||
newName)
|
newName)
|
||||||
.highlight(Attr->getRange());
|
.highlight(Attr->getRange());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Attr->Rename.empty()) {
|
if (!Attr->Rename.empty() && !rawAccessorKind.hasValue()) {
|
||||||
auto renameDiag = diagnose(ReferenceRange.Start,
|
auto renameDiag = diagnose(ReferenceRange.Start,
|
||||||
diag::note_deprecated_rename,
|
diag::note_deprecated_rename,
|
||||||
newName);
|
newName);
|
||||||
@@ -2234,9 +2247,11 @@ public:
|
|||||||
return std::make_pair(false, E);
|
return std::make_pair(false, E);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (auto DR = dyn_cast<DeclRefExpr>(E))
|
if (auto DR = dyn_cast<DeclRefExpr>(E)) {
|
||||||
diagAvailability(DR->getDecl(), DR->getSourceRange(),
|
diagAvailability(DR->getDecl(), DR->getSourceRange(),
|
||||||
getEnclosingApplyExpr());
|
getEnclosingApplyExpr());
|
||||||
|
maybeDiagStorageAccess(DR->getDecl(), DR->getSourceRange(), DC);
|
||||||
|
}
|
||||||
if (auto MR = dyn_cast<MemberRefExpr>(E)) {
|
if (auto MR = dyn_cast<MemberRefExpr>(E)) {
|
||||||
walkMemberRef(MR);
|
walkMemberRef(MR);
|
||||||
return skipChildren();
|
return skipChildren();
|
||||||
@@ -2252,8 +2267,10 @@ public:
|
|||||||
if (auto DS = dyn_cast<DynamicSubscriptExpr>(E))
|
if (auto DS = dyn_cast<DynamicSubscriptExpr>(E))
|
||||||
diagAvailability(DS->getMember().getDecl(), DS->getSourceRange());
|
diagAvailability(DS->getMember().getDecl(), DS->getSourceRange());
|
||||||
if (auto S = dyn_cast<SubscriptExpr>(E)) {
|
if (auto S = dyn_cast<SubscriptExpr>(E)) {
|
||||||
if (S->hasDecl())
|
if (S->hasDecl()) {
|
||||||
diagAvailability(S->getDecl().getDecl(), S->getSourceRange());
|
diagAvailability(S->getDecl().getDecl(), S->getSourceRange());
|
||||||
|
maybeDiagStorageAccess(S->getDecl().getDecl(), S->getSourceRange(), DC);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (auto A = dyn_cast<AssignExpr>(E)) {
|
if (auto A = dyn_cast<AssignExpr>(E)) {
|
||||||
walkAssignExpr(A);
|
walkAssignExpr(A);
|
||||||
@@ -2336,6 +2353,8 @@ private:
|
|||||||
/// Walk a member reference expression, checking for availability.
|
/// Walk a member reference expression, checking for availability.
|
||||||
void walkMemberRef(MemberRefExpr *E) {
|
void walkMemberRef(MemberRefExpr *E) {
|
||||||
// Walk the base in a getter context.
|
// Walk the base in a getter context.
|
||||||
|
// FIXME: We may need to look at the setter too, if we're going to do
|
||||||
|
// writeback. The AST should have this information.
|
||||||
walkInContext(E, E->getBase(), MemberAccessContext::Getter);
|
walkInContext(E, E->getBase(), MemberAccessContext::Getter);
|
||||||
|
|
||||||
ValueDecl *D = E->getMember().getDecl();
|
ValueDecl *D = E->getMember().getDecl();
|
||||||
@@ -2343,13 +2362,8 @@ private:
|
|||||||
if (diagAvailability(D, E->getNameLoc().getSourceRange()))
|
if (diagAvailability(D, E->getNameLoc().getSourceRange()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (TC.getLangOpts().DisableAvailabilityChecking)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (auto *ASD = dyn_cast<AbstractStorageDecl>(D)) {
|
|
||||||
// Diagnose for appropriate accessors, given the access context.
|
// Diagnose for appropriate accessors, given the access context.
|
||||||
diagStorageAccess(ASD, E->getSourceRange(), DC);
|
maybeDiagStorageAccess(D, E->getSourceRange(), DC);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Walk an inout expression, checking for availability.
|
/// Walk an inout expression, checking for availability.
|
||||||
@@ -2367,9 +2381,16 @@ private:
|
|||||||
|
|
||||||
/// Emit diagnostics, if necessary, for accesses to storage where
|
/// Emit diagnostics, if necessary, for accesses to storage where
|
||||||
/// the accessor for the AccessContext is not available.
|
/// the accessor for the AccessContext is not available.
|
||||||
void diagStorageAccess(AbstractStorageDecl *D,
|
void maybeDiagStorageAccess(const ValueDecl *VD,
|
||||||
SourceRange ReferenceRange,
|
SourceRange ReferenceRange,
|
||||||
const DeclContext *ReferenceDC) const {
|
const DeclContext *ReferenceDC) const {
|
||||||
|
if (TC.getLangOpts().DisableAvailabilityChecking)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto *D = dyn_cast<AbstractStorageDecl>(VD);
|
||||||
|
if (!D)
|
||||||
|
return;
|
||||||
|
|
||||||
if (!D->hasAccessorFunctions()) {
|
if (!D->hasAccessorFunctions()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2397,13 +2418,18 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Emit a diagnostic, if necessary for a potentially unavailable accessor.
|
/// Emit a diagnostic, if necessary for a potentially unavailable accessor.
|
||||||
/// Returns true if a diagnostic was emitted.
|
|
||||||
void diagAccessorAvailability(AccessorDecl *D, SourceRange ReferenceRange,
|
void diagAccessorAvailability(AccessorDecl *D, SourceRange ReferenceRange,
|
||||||
const DeclContext *ReferenceDC,
|
const DeclContext *ReferenceDC,
|
||||||
bool ForInout) const {
|
bool ForInout) const {
|
||||||
if (!D) {
|
if (!D) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure not to diagnose an accessor if we already complained about
|
||||||
|
// the property/subscript.
|
||||||
|
if (!TypeChecker::getDeprecated(D->getStorage()))
|
||||||
|
TC.diagnoseIfDeprecated(ReferenceRange, ReferenceDC, D, /*call*/nullptr);
|
||||||
|
|
||||||
auto MaybeUnavail = TC.checkDeclarationAvailability(D, ReferenceRange.Start,
|
auto MaybeUnavail = TC.checkDeclarationAvailability(D, ReferenceRange.Start,
|
||||||
DC);
|
DC);
|
||||||
if (MaybeUnavail.hasValue()) {
|
if (MaybeUnavail.hasValue()) {
|
||||||
|
|||||||
@@ -93,3 +93,17 @@ typedef NS_ENUM(NSInteger, NSEnumAddedCasesIn2017) {
|
|||||||
NSEnumAddedCasesIn2017ExistingCaseThree,
|
NSEnumAddedCasesIn2017ExistingCaseThree,
|
||||||
NSEnumAddedCasesIn2017NewCaseOne __attribute__((availability(macosx,introduced=10.13))) __attribute__((availability(ios,introduced=11.0))) __attribute__((availability(tvos,introduced=11.0))) __attribute__((availability(watchos,introduced=4.0)))
|
NSEnumAddedCasesIn2017NewCaseOne __attribute__((availability(macosx,introduced=10.13))) __attribute__((availability(ios,introduced=11.0))) __attribute__((availability(tvos,introduced=11.0))) __attribute__((availability(watchos,introduced=4.0)))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@interface AccessorDeprecations: NSObject
|
||||||
|
@property int fullyDeprecated __attribute__((deprecated));
|
||||||
|
|
||||||
|
@property int getterDeprecated;
|
||||||
|
- (int)getterDeprecated __attribute__((deprecated));
|
||||||
|
@property (class) int getterDeprecatedClass;
|
||||||
|
+ (int)getterDeprecatedClass __attribute__((deprecated));
|
||||||
|
|
||||||
|
@property int setterDeprecated;
|
||||||
|
- (void)setSetterDeprecated:(int)setterDeprecated __attribute__((deprecated));
|
||||||
|
@property (class) int setterDeprecatedClass;
|
||||||
|
+ (void)setSetterDeprecatedClass:(int)setterDeprecated __attribute__((deprecated));
|
||||||
|
@end
|
||||||
|
|||||||
@@ -25,8 +25,28 @@ func test_unavailable_func(_ x : NSObject) {
|
|||||||
NSDeallocateObject(x) // expected-error {{'NSDeallocateObject' is unavailable}}
|
NSDeallocateObject(x) // expected-error {{'NSDeallocateObject' is unavailable}}
|
||||||
}
|
}
|
||||||
|
|
||||||
func test_deprecated_imported_as_unavailable(_ s:UnsafeMutablePointer<CChar>) {
|
func test_deprecated(_ s:UnsafeMutablePointer<CChar>, _ obj: AccessorDeprecations) {
|
||||||
_ = tmpnam(s) // expected-warning {{'tmpnam' is deprecated: Due to security concerns inherent in the design of tmpnam(3), it is highly recommended that you use mkstemp(3) instead.}}
|
_ = tmpnam(s) // expected-warning {{'tmpnam' is deprecated: Due to security concerns inherent in the design of tmpnam(3), it is highly recommended that you use mkstemp(3) instead.}}
|
||||||
|
|
||||||
|
_ = obj.fullyDeprecated // expected-warning {{'fullyDeprecated' is deprecated}}
|
||||||
|
obj.fullyDeprecated = 0 // expected-warning {{'fullyDeprecated' is deprecated}}
|
||||||
|
obj.fullyDeprecated += 1 // expected-warning {{'fullyDeprecated' is deprecated}}
|
||||||
|
|
||||||
|
_ = obj.getterDeprecated // expected-warning {{getter for 'getterDeprecated' is deprecated}}
|
||||||
|
obj.getterDeprecated = 0
|
||||||
|
obj.getterDeprecated += 1 // expected-warning {{getter for 'getterDeprecated' is deprecated}}
|
||||||
|
|
||||||
|
_ = AccessorDeprecations.getterDeprecatedClass // expected-warning {{getter for 'getterDeprecatedClass' is deprecated}}
|
||||||
|
AccessorDeprecations.getterDeprecatedClass = 0
|
||||||
|
AccessorDeprecations.getterDeprecatedClass += 1 // expected-warning {{getter for 'getterDeprecatedClass' is deprecated}}
|
||||||
|
|
||||||
|
_ = obj.setterDeprecated
|
||||||
|
obj.setterDeprecated = 0 // expected-warning {{setter for 'setterDeprecated' is deprecated}}
|
||||||
|
obj.setterDeprecated += 1 // expected-warning {{setter for 'setterDeprecated' is deprecated}}
|
||||||
|
|
||||||
|
_ = AccessorDeprecations.setterDeprecatedClass
|
||||||
|
AccessorDeprecations.setterDeprecatedClass = 0 // expected-warning {{setter for 'setterDeprecatedClass' is deprecated}}
|
||||||
|
AccessorDeprecations.setterDeprecatedClass += 1 // expected-warning {{setter for 'setterDeprecatedClass' is deprecated}}
|
||||||
}
|
}
|
||||||
|
|
||||||
func test_NSInvocation(_ x: NSInvocation, // expected-error {{'NSInvocation' is unavailable}}
|
func test_NSInvocation(_ x: NSInvocation, // expected-error {{'NSInvocation' is unavailable}}
|
||||||
|
|||||||
@@ -808,8 +808,120 @@ func rdar32526620_3(a: Int, b: E_32526620, c: String) {} // expected-note {{here
|
|||||||
rdar32526620_3(a: 42, b: .bar, c: "question")
|
rdar32526620_3(a: 42, b: .bar, c: "question")
|
||||||
// expected-error@-1 {{'rdar32526620_3(a:b:c:)' has been replaced by instance method 'E_32526620.set(a:c:)'}} {{1-15=E_32526620.bar.set}} {{23-32=}}
|
// expected-error@-1 {{'rdar32526620_3(a:b:c:)' has been replaced by instance method 'E_32526620.set(a:c:)'}} {{1-15=E_32526620.bar.set}} {{23-32=}}
|
||||||
|
|
||||||
|
|
||||||
@available(*, unavailable) // expected-warning {{'@available' without an OS is ignored on extensions; apply the attribute to each member instead}} {{1-28=}}
|
@available(*, unavailable) // expected-warning {{'@available' without an OS is ignored on extensions; apply the attribute to each member instead}} {{1-28=}}
|
||||||
extension DummyType {}
|
extension DummyType {}
|
||||||
|
|
||||||
@available(*, deprecated) // expected-warning {{'@available' without an OS is ignored on extensions; apply the attribute to each member instead}} {{1-27=}}
|
@available(*, deprecated) // expected-warning {{'@available' without an OS is ignored on extensions; apply the attribute to each member instead}} {{1-27=}}
|
||||||
extension DummyType {}
|
extension DummyType {}
|
||||||
|
|
||||||
|
|
||||||
|
var deprecatedGetter: Int {
|
||||||
|
@available(*, deprecated) get { return 0 }
|
||||||
|
set {}
|
||||||
|
}
|
||||||
|
var deprecatedGetterOnly: Int {
|
||||||
|
@available(*, deprecated) get { return 0 }
|
||||||
|
}
|
||||||
|
var deprecatedSetter: Int {
|
||||||
|
get { return 0 }
|
||||||
|
@available(*, deprecated) set {}
|
||||||
|
}
|
||||||
|
var deprecatedBoth: Int {
|
||||||
|
@available(*, deprecated) get { return 0 }
|
||||||
|
@available(*, deprecated) set {}
|
||||||
|
}
|
||||||
|
var deprecatedMessage: Int {
|
||||||
|
@available(*, deprecated, message: "bad getter") get { return 0 }
|
||||||
|
@available(*, deprecated, message: "bad setter") set {}
|
||||||
|
}
|
||||||
|
var deprecatedRename: Int {
|
||||||
|
@available(*, deprecated, renamed: "betterThing()") get { return 0 }
|
||||||
|
@available(*, deprecated, renamed: "setBetterThing(_:)") set {}
|
||||||
|
}
|
||||||
|
@available(*, deprecated, message: "bad variable")
|
||||||
|
var deprecatedProperty: Int {
|
||||||
|
@available(*, deprecated, message: "bad getter") get { return 0 }
|
||||||
|
@available(*, deprecated, message: "bad setter") set {}
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = deprecatedGetter // expected-warning {{getter for 'deprecatedGetter' is deprecated}} {{none}}
|
||||||
|
deprecatedGetter = 0
|
||||||
|
deprecatedGetter += 1 // expected-warning {{getter for 'deprecatedGetter' is deprecated}} {{none}}
|
||||||
|
|
||||||
|
_ = deprecatedGetterOnly // expected-warning {{getter for 'deprecatedGetterOnly' is deprecated}} {{none}}
|
||||||
|
|
||||||
|
_ = deprecatedSetter
|
||||||
|
deprecatedSetter = 0 // expected-warning {{setter for 'deprecatedSetter' is deprecated}} {{none}}
|
||||||
|
deprecatedSetter += 1 // expected-warning {{setter for 'deprecatedSetter' is deprecated}} {{none}}
|
||||||
|
|
||||||
|
_ = deprecatedBoth // expected-warning {{getter for 'deprecatedBoth' is deprecated}} {{none}}
|
||||||
|
deprecatedBoth = 0 // expected-warning {{setter for 'deprecatedBoth' is deprecated}} {{none}}
|
||||||
|
deprecatedBoth += 1 // expected-warning {{getter for 'deprecatedBoth' is deprecated}} {{none}} expected-warning {{setter for 'deprecatedBoth' is deprecated}} {{none}}
|
||||||
|
|
||||||
|
_ = deprecatedMessage // expected-warning {{getter for 'deprecatedMessage' is deprecated: bad getter}} {{none}}
|
||||||
|
deprecatedMessage = 0 // expected-warning {{setter for 'deprecatedMessage' is deprecated: bad setter}} {{none}}
|
||||||
|
deprecatedMessage += 1 // expected-warning {{getter for 'deprecatedMessage' is deprecated: bad getter}} {{none}} expected-warning {{setter for 'deprecatedMessage' is deprecated: bad setter}} {{none}}
|
||||||
|
|
||||||
|
_ = deprecatedRename // expected-warning {{getter for 'deprecatedRename' is deprecated: renamed to 'betterThing()'}} {{none}}
|
||||||
|
deprecatedRename = 0 // expected-warning {{setter for 'deprecatedRename' is deprecated: renamed to 'setBetterThing(_:)'}} {{none}}
|
||||||
|
deprecatedRename += 1 // expected-warning {{getter for 'deprecatedRename' is deprecated: renamed to 'betterThing()'}} {{none}} expected-warning {{setter for 'deprecatedRename' is deprecated: renamed to 'setBetterThing(_:)'}} {{none}}
|
||||||
|
|
||||||
|
_ = deprecatedProperty // expected-warning {{'deprecatedProperty' is deprecated: bad variable}} {{none}}
|
||||||
|
deprecatedProperty = 0 // expected-warning {{'deprecatedProperty' is deprecated: bad variable}} {{none}}
|
||||||
|
deprecatedProperty += 1 // expected-warning {{'deprecatedProperty' is deprecated: bad variable}} {{none}}
|
||||||
|
|
||||||
|
struct DeprecatedAccessors {
|
||||||
|
var deprecatedMessage: Int {
|
||||||
|
@available(*, deprecated, message: "bad getter") get { return 0 }
|
||||||
|
@available(*, deprecated, message: "bad setter") set {}
|
||||||
|
}
|
||||||
|
|
||||||
|
static var staticDeprecated: Int {
|
||||||
|
@available(*, deprecated, message: "bad getter") get { return 0 }
|
||||||
|
@available(*, deprecated, message: "bad setter") set {}
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(*, deprecated, message: "bad property")
|
||||||
|
var deprecatedProperty: Int {
|
||||||
|
@available(*, deprecated, message: "bad getter") get { return 0 }
|
||||||
|
@available(*, deprecated, message: "bad setter") set {}
|
||||||
|
}
|
||||||
|
|
||||||
|
subscript(_: Int) -> Int {
|
||||||
|
@available(*, deprecated, message: "bad subscript getter") get { return 0 }
|
||||||
|
@available(*, deprecated, message: "bad subscript setter") set {}
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(*, deprecated, message: "bad subscript!")
|
||||||
|
subscript(alsoDeprecated _: Int) -> Int {
|
||||||
|
@available(*, deprecated, message: "bad subscript getter") get { return 0 }
|
||||||
|
@available(*, deprecated, message: "bad subscript setter") set {}
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func testAccessors(other: inout DeprecatedAccessors) {
|
||||||
|
_ = deprecatedMessage // expected-warning {{getter for 'deprecatedMessage' is deprecated: bad getter}} {{none}}
|
||||||
|
deprecatedMessage = 0 // expected-warning {{setter for 'deprecatedMessage' is deprecated: bad setter}} {{none}}
|
||||||
|
deprecatedMessage += 1 // expected-warning {{getter for 'deprecatedMessage' is deprecated: bad getter}} {{none}} expected-warning {{setter for 'deprecatedMessage' is deprecated: bad setter}} {{none}}
|
||||||
|
|
||||||
|
_ = other.deprecatedMessage // expected-warning {{getter for 'deprecatedMessage' is deprecated: bad getter}} {{none}}
|
||||||
|
other.deprecatedMessage = 0 // expected-warning {{setter for 'deprecatedMessage' is deprecated: bad setter}} {{none}}
|
||||||
|
other.deprecatedMessage += 1 // expected-warning {{getter for 'deprecatedMessage' is deprecated: bad getter}} {{none}} expected-warning {{setter for 'deprecatedMessage' is deprecated: bad setter}} {{none}}
|
||||||
|
|
||||||
|
_ = other.deprecatedProperty // expected-warning {{'deprecatedProperty' is deprecated: bad property}} {{none}}
|
||||||
|
other.deprecatedProperty = 0 // expected-warning {{'deprecatedProperty' is deprecated: bad property}} {{none}}
|
||||||
|
other.deprecatedProperty += 1 // expected-warning {{'deprecatedProperty' is deprecated: bad property}} {{none}}
|
||||||
|
|
||||||
|
_ = DeprecatedAccessors.staticDeprecated // expected-warning {{getter for 'staticDeprecated' is deprecated: bad getter}} {{none}}
|
||||||
|
DeprecatedAccessors.staticDeprecated = 0 // expected-warning {{setter for 'staticDeprecated' is deprecated: bad setter}} {{none}}
|
||||||
|
DeprecatedAccessors.staticDeprecated += 1 // expected-warning {{getter for 'staticDeprecated' is deprecated: bad getter}} {{none}} expected-warning {{setter for 'staticDeprecated' is deprecated: bad setter}} {{none}}
|
||||||
|
|
||||||
|
_ = other[0] // expected-warning {{getter for 'subscript' is deprecated: bad subscript getter}} {{none}}
|
||||||
|
other[0] = 0 // expected-warning {{setter for 'subscript' is deprecated: bad subscript setter}} {{none}}
|
||||||
|
other[0] += 1 // expected-warning {{getter for 'subscript' is deprecated: bad subscript getter}} {{none}} expected-warning {{setter for 'subscript' is deprecated: bad subscript setter}} {{none}}
|
||||||
|
|
||||||
|
_ = other[alsoDeprecated: 0] // expected-warning {{'subscript(alsoDeprecated:)' is deprecated: bad subscript!}} {{none}}
|
||||||
|
other[alsoDeprecated: 0] = 0 // expected-warning {{'subscript(alsoDeprecated:)' is deprecated: bad subscript!}} {{none}}
|
||||||
|
other[alsoDeprecated: 0] += 1 // expected-warning {{'subscript(alsoDeprecated:)' is deprecated: bad subscript!}} {{none}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user