@@ -1404,10 +1404,7 @@ const AvailableAttr *TypeChecker::getDeprecated(const Decl *D) {
1404
1404
static bool
1405
1405
someEnclosingDeclMatches (SourceRange ReferenceRange,
1406
1406
const DeclContext *ReferenceDC,
1407
- TypeChecker &TC,
1408
1407
llvm::function_ref<bool (const Decl *)> Pred) {
1409
- ASTContext &Ctx = TC.Context ;
1410
-
1411
1408
// Climb the DeclContext hierarchy to see if any of the containing
1412
1409
// declarations matches the predicate.
1413
1410
const DeclContext *DC = ReferenceDC;
@@ -1446,6 +1443,7 @@ someEnclosingDeclMatches(SourceRange ReferenceRange,
1446
1443
if (ReferenceRange.isInvalid ())
1447
1444
return false ;
1448
1445
1446
+ ASTContext &Ctx = ReferenceDC->getASTContext ();
1449
1447
const Decl *DeclToSearch =
1450
1448
findContainingDeclaration (ReferenceRange, ReferenceDC, Ctx.SourceMgr );
1451
1449
@@ -1474,28 +1472,32 @@ someEnclosingDeclMatches(SourceRange ReferenceRange,
1474
1472
return false ;
1475
1473
}
1476
1474
1477
- bool TypeChecker::isInsideImplicitFunction (SourceRange ReferenceRange,
1478
- const DeclContext *DC) {
1475
+ // / Returns true if the reference or any of its parents is an
1476
+ // / implicit function.
1477
+ static bool isInsideImplicitFunction (SourceRange ReferenceRange,
1478
+ const DeclContext *DC) {
1479
1479
auto IsInsideImplicitFunc = [](const Decl *D) {
1480
1480
auto *AFD = dyn_cast<AbstractFunctionDecl>(D);
1481
1481
return AFD && AFD->isImplicit ();
1482
1482
};
1483
1483
1484
- return someEnclosingDeclMatches (ReferenceRange, DC, *this ,
1485
- IsInsideImplicitFunc);
1484
+ return someEnclosingDeclMatches (ReferenceRange, DC, IsInsideImplicitFunc);
1486
1485
}
1487
1486
1488
- bool TypeChecker::isInsideUnavailableDeclaration (
1489
- SourceRange ReferenceRange, const DeclContext *ReferenceDC) {
1487
+ // / Returns true if the reference or any of its parents is an
1488
+ // / unavailable (or obsoleted) declaration.
1489
+ static bool isInsideUnavailableDeclaration (SourceRange ReferenceRange,
1490
+ const DeclContext *ReferenceDC) {
1490
1491
auto IsUnavailable = [](const Decl *D) {
1491
1492
return D->getAttrs ().getUnavailable (D->getASTContext ());
1492
1493
};
1493
1494
1494
- return someEnclosingDeclMatches (ReferenceRange, ReferenceDC, *this ,
1495
- IsUnavailable);
1495
+ return someEnclosingDeclMatches (ReferenceRange, ReferenceDC, IsUnavailable);
1496
1496
}
1497
1497
1498
- bool TypeChecker::isInsideCompatibleUnavailableDeclaration (
1498
+ // / Returns true if the reference or any of its parents is an
1499
+ // / unconditional unavailable declaration for the same platform.
1500
+ static bool isInsideCompatibleUnavailableDeclaration (
1499
1501
SourceRange ReferenceRange, const DeclContext *ReferenceDC,
1500
1502
const AvailableAttr *attr) {
1501
1503
if (!attr->isUnconditionallyUnavailable ()) {
@@ -1512,18 +1514,18 @@ bool TypeChecker::isInsideCompatibleUnavailableDeclaration(
1512
1514
return EnclosingUnavailable && EnclosingUnavailable->Platform == platform;
1513
1515
};
1514
1516
1515
- return someEnclosingDeclMatches (ReferenceRange, ReferenceDC, *this ,
1516
- IsUnavailable);
1517
+ return someEnclosingDeclMatches (ReferenceRange, ReferenceDC, IsUnavailable);
1517
1518
}
1518
1519
1519
- bool TypeChecker::isInsideDeprecatedDeclaration (SourceRange ReferenceRange,
1520
- const DeclContext *ReferenceDC){
1520
+ // / Returns true if the reference is lexically contained in a declaration
1521
+ // / that is deprecated on all deployment targets.
1522
+ static bool isInsideDeprecatedDeclaration (SourceRange ReferenceRange,
1523
+ const DeclContext *ReferenceDC){
1521
1524
auto IsDeprecated = [](const Decl *D) {
1522
1525
return D->getAttrs ().getDeprecated (D->getASTContext ());
1523
1526
};
1524
1527
1525
- return someEnclosingDeclMatches (ReferenceRange, ReferenceDC, *this ,
1526
- IsDeprecated);
1528
+ return someEnclosingDeclMatches (ReferenceRange, ReferenceDC, IsDeprecated);
1527
1529
}
1528
1530
1529
1531
static void fixItAvailableAttrRename (TypeChecker &TC,
@@ -1930,14 +1932,25 @@ void TypeChecker::diagnoseIfDeprecated(SourceRange ReferenceRange,
1930
1932
}
1931
1933
}
1932
1934
1933
- DeclName Name = DeprecatedDecl->getFullName ();
1935
+ DeclName Name;
1936
+ Optional<unsigned > rawAccessorKind;
1937
+ if (auto *accessor = dyn_cast<AccessorDecl>(DeprecatedDecl)) {
1938
+ Name = accessor->getStorage ()->getFullName ();
1939
+ assert (accessor->isGetterOrSetter ());
1940
+ rawAccessorKind = static_cast <unsigned >(accessor->getAccessorKind ());
1941
+ } else {
1942
+ Name = DeprecatedDecl->getFullName ();
1943
+ }
1944
+
1934
1945
StringRef Platform = Attr->prettyPlatformString ();
1935
1946
clang::VersionTuple DeprecatedVersion;
1936
1947
if (Attr->Deprecated )
1937
1948
DeprecatedVersion = Attr->Deprecated .getValue ();
1938
1949
1950
+ static const unsigned NOT_ACCESSOR_INDEX = 2 ;
1939
1951
if (Attr->Message .empty () && Attr->Rename .empty ()) {
1940
- diagnose (ReferenceRange.Start , diag::availability_deprecated, Name,
1952
+ diagnose (ReferenceRange.Start , diag::availability_deprecated,
1953
+ rawAccessorKind.getValueOr (NOT_ACCESSOR_INDEX), Name,
1941
1954
Attr->hasPlatform (), Platform, Attr->Deprecated .hasValue (),
1942
1955
DeprecatedVersion)
1943
1956
.highlight (Attr->getRange ());
@@ -1951,21 +1964,23 @@ void TypeChecker::diagnoseIfDeprecated(SourceRange ReferenceRange,
1951
1964
1952
1965
if (!Attr->Message .empty ()) {
1953
1966
EncodedDiagnosticMessage EncodedMessage (Attr->Message );
1954
- diagnose (ReferenceRange.Start , diag::availability_deprecated_msg, Name,
1967
+ diagnose (ReferenceRange.Start , diag::availability_deprecated_msg,
1968
+ rawAccessorKind.getValueOr (NOT_ACCESSOR_INDEX), Name,
1955
1969
Attr->hasPlatform (), Platform, Attr->Deprecated .hasValue (),
1956
1970
DeprecatedVersion, EncodedMessage.Message )
1957
1971
.highlight (Attr->getRange ());
1958
1972
} else {
1959
1973
unsigned rawReplaceKind = static_cast <unsigned >(
1960
1974
replacementDeclKind.getValueOr (ReplacementDeclKind::None));
1961
- diagnose (ReferenceRange.Start , diag::availability_deprecated_rename, Name,
1975
+ diagnose (ReferenceRange.Start , diag::availability_deprecated_rename,
1976
+ rawAccessorKind.getValueOr (NOT_ACCESSOR_INDEX), Name,
1962
1977
Attr->hasPlatform (), Platform, Attr->Deprecated .hasValue (),
1963
1978
DeprecatedVersion, replacementDeclKind.hasValue (), rawReplaceKind,
1964
1979
newName)
1965
1980
.highlight (Attr->getRange ());
1966
1981
}
1967
1982
1968
- if (!Attr->Rename .empty ()) {
1983
+ if (!Attr->Rename .empty () && !rawAccessorKind. hasValue () ) {
1969
1984
auto renameDiag = diagnose (ReferenceRange.Start ,
1970
1985
diag::note_deprecated_rename,
1971
1986
newName);
@@ -2232,9 +2247,11 @@ class AvailabilityWalker : public ASTWalker {
2232
2247
return std::make_pair (false , E);
2233
2248
};
2234
2249
2235
- if (auto DR = dyn_cast<DeclRefExpr>(E))
2250
+ if (auto DR = dyn_cast<DeclRefExpr>(E)) {
2236
2251
diagAvailability (DR->getDecl (), DR->getSourceRange (),
2237
2252
getEnclosingApplyExpr ());
2253
+ maybeDiagStorageAccess (DR->getDecl (), DR->getSourceRange (), DC);
2254
+ }
2238
2255
if (auto MR = dyn_cast<MemberRefExpr>(E)) {
2239
2256
walkMemberRef (MR);
2240
2257
return skipChildren ();
@@ -2250,8 +2267,10 @@ class AvailabilityWalker : public ASTWalker {
2250
2267
if (auto DS = dyn_cast<DynamicSubscriptExpr>(E))
2251
2268
diagAvailability (DS->getMember ().getDecl (), DS->getSourceRange ());
2252
2269
if (auto S = dyn_cast<SubscriptExpr>(E)) {
2253
- if (S->hasDecl ())
2270
+ if (S->hasDecl ()) {
2254
2271
diagAvailability (S->getDecl ().getDecl (), S->getSourceRange ());
2272
+ maybeDiagStorageAccess (S->getDecl ().getDecl (), S->getSourceRange (), DC);
2273
+ }
2255
2274
}
2256
2275
if (auto A = dyn_cast<AssignExpr>(E)) {
2257
2276
walkAssignExpr (A);
@@ -2334,20 +2353,17 @@ class AvailabilityWalker : public ASTWalker {
2334
2353
// / Walk a member reference expression, checking for availability.
2335
2354
void walkMemberRef (MemberRefExpr *E) {
2336
2355
// Walk the base in a getter context.
2356
+ // FIXME: We may need to look at the setter too, if we're going to do
2357
+ // writeback. The AST should have this information.
2337
2358
walkInContext (E, E->getBase (), MemberAccessContext::Getter);
2338
2359
2339
2360
ValueDecl *D = E->getMember ().getDecl ();
2340
2361
// Diagnose for the member declaration itself.
2341
2362
if (diagAvailability (D, E->getNameLoc ().getSourceRange ()))
2342
2363
return ;
2343
2364
2344
- if (TC.getLangOpts ().DisableAvailabilityChecking )
2345
- return ;
2346
-
2347
- if (auto *ASD = dyn_cast<AbstractStorageDecl>(D)) {
2348
- // Diagnose for appropriate accessors, given the access context.
2349
- diagStorageAccess (ASD, E->getSourceRange (), DC);
2350
- }
2365
+ // Diagnose for appropriate accessors, given the access context.
2366
+ maybeDiagStorageAccess (D, E->getSourceRange (), DC);
2351
2367
}
2352
2368
2353
2369
// / Walk an inout expression, checking for availability.
@@ -2365,9 +2381,16 @@ class AvailabilityWalker : public ASTWalker {
2365
2381
2366
2382
// / Emit diagnostics, if necessary, for accesses to storage where
2367
2383
// / the accessor for the AccessContext is not available.
2368
- void diagStorageAccess (AbstractStorageDecl *D,
2369
- SourceRange ReferenceRange,
2370
- const DeclContext *ReferenceDC) const {
2384
+ void maybeDiagStorageAccess (const ValueDecl *VD,
2385
+ SourceRange ReferenceRange,
2386
+ const DeclContext *ReferenceDC) const {
2387
+ if (TC.getLangOpts ().DisableAvailabilityChecking )
2388
+ return ;
2389
+
2390
+ auto *D = dyn_cast<AbstractStorageDecl>(VD);
2391
+ if (!D)
2392
+ return ;
2393
+
2371
2394
if (!D->hasAccessorFunctions ()) {
2372
2395
return ;
2373
2396
}
@@ -2395,13 +2418,18 @@ class AvailabilityWalker : public ASTWalker {
2395
2418
}
2396
2419
2397
2420
// / Emit a diagnostic, if necessary for a potentially unavailable accessor.
2398
- // / Returns true if a diagnostic was emitted.
2399
2421
void diagAccessorAvailability (AccessorDecl *D, SourceRange ReferenceRange,
2400
2422
const DeclContext *ReferenceDC,
2401
2423
bool ForInout) const {
2402
2424
if (!D) {
2403
2425
return ;
2404
2426
}
2427
+
2428
+ // Make sure not to diagnose an accessor if we already complained about
2429
+ // the property/subscript.
2430
+ if (!TypeChecker::getDeprecated (D->getStorage ()))
2431
+ TC.diagnoseIfDeprecated (ReferenceRange, ReferenceDC, D, /* call*/ nullptr );
2432
+
2405
2433
auto MaybeUnavail = TC.checkDeclarationAvailability (D, ReferenceRange.Start ,
2406
2434
DC);
2407
2435
if (MaybeUnavail.hasValue ()) {
0 commit comments