@@ -1526,6 +1526,15 @@ static void diagRecursivePropertyAccess(const Expr *E, const DeclContext *DC) {
1526
1526
const_cast <Expr *>(E)->walk(walker);
1527
1527
}
1528
1528
1529
+ namespace DiagnosticsContext {
1530
+ // / A mapping of replacement `ValueDecl`s to use in `VarDeclUsageAnalysis`
1531
+ // / instead of the actual `ValueDecl` of the associated `DeclRefExpr`.
1532
+ // / This lets `VarDeclUsageAnalysis` avoid emitting false-positive warnings
1533
+ // / in certain circumstances.
1534
+ static llvm::SmallDenseMap<DeclRefExpr *, ValueDecl *>
1535
+ DeclMappingForUsageAnalysis;
1536
+ }
1537
+
1529
1538
// / Look for any property references in closures that lack a 'self.' qualifier.
1530
1539
// / Within a closure, we require that the source code contain 'self.' explicitly
1531
1540
// / (or that the closure explicitly capture 'self' in the capture list) because
@@ -1650,7 +1659,7 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
1650
1659
// When `VarDeclUsageChecker` checks this DRE, we need to use
1651
1660
// the base we looked up here instead, since otherwise
1652
1661
// we'll emit confusing false-positive warnings.
1653
- DRE-> setDeclForUsageAnalysis ( lookupResult) ;
1662
+ DiagnosticsContext::DeclMappingForUsageAnalysis[ DRE] = lookupResult;
1654
1663
1655
1664
selfDecl = lookupResult;
1656
1665
}
@@ -1677,17 +1686,7 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
1677
1686
1678
1687
if (auto LE = dyn_cast<LoadExpr>(cond.getInitializer ())) {
1679
1688
if (auto selfDRE = dyn_cast<DeclRefExpr>(LE->getSubExpr ())) {
1680
- if (selfDRE->getDecl ()->getName ().isSimpleName (Ctx.Id_self )) {
1681
- // Mark this `OptionalStatementPattern` as enabling implicit
1682
- // self for this weak self capture. This lets us avoid emitting
1683
- // a false-positive warning in `VarDeclUsageChecker` in
1684
- // Swift 5 mode (this is unnecessary in Swift 6).
1685
- if (!Ctx.LangOpts .isSwiftVersionAtLeast (6 )) {
1686
- OSP->setEnablesImplicitSelfForWeakSelfCapture (true );
1687
- }
1688
-
1689
- return true ;
1690
- }
1689
+ return selfDRE->getDecl ()->getName ().isSimpleName (Ctx.Id_self );
1691
1690
}
1692
1691
}
1693
1692
}
@@ -2636,7 +2635,15 @@ class VarDeclUsageChecker : public ASTWalker {
2636
2635
2637
2636
VarDecls[vd] |= Flag;
2638
2637
}
2639
-
2638
+
2639
+ ValueDecl *getDecl (DeclRefExpr *DRE) {
2640
+ if (auto decl = DiagnosticsContext::DeclMappingForUsageAnalysis[DRE]) {
2641
+ return decl;
2642
+ }
2643
+
2644
+ return DRE->getDecl ();
2645
+ }
2646
+
2640
2647
void markBaseOfStorageUse (Expr *E, ConcreteDeclRef decl, unsigned flags);
2641
2648
void markBaseOfStorageUse (Expr *E, bool isMutating);
2642
2649
@@ -3318,19 +3325,6 @@ VarDeclUsageChecker::~VarDeclUsageChecker() {
3318
3325
if (initExpr->getStartLoc ().isValid ()) {
3319
3326
unsigned noParens = initExpr->canAppendPostfixExpression ();
3320
3327
3321
- // Don't emit an "unused value" warning if this is a
3322
- // `let self = self` condition being used to enable
3323
- // implicit self for the remainder of this scope,
3324
- // since it would be a false positive. This is only
3325
- // necessary in Swift 5 mode, because in Swift 6
3326
- // this new self decl is correctly used as the base of
3327
- // implicit self calls for the remainder of the scope.
3328
- auto &ctx = var->getASTContext ();
3329
- if (!ctx.LangOpts .isSwiftVersionAtLeast (6 ) &&
3330
- OSP->getEnablesImplicitSelfForWeakSelfCapture ()) {
3331
- continue ;
3332
- }
3333
-
3334
3328
// If the subexpr is an "as?" cast, we can rewrite it to
3335
3329
// be an "is" test.
3336
3330
ConditionalCheckedCastExpr *CCE = nullptr ;
@@ -3549,7 +3543,7 @@ void VarDeclUsageChecker::markStoredOrInOutExpr(Expr *E, unsigned Flags) {
3549
3543
3550
3544
// If we found a decl that is being assigned to, then mark it.
3551
3545
if (auto *DRE = dyn_cast<DeclRefExpr>(E)) {
3552
- addMark (DRE-> getDeclForUsageAnalysis ( ), Flags);
3546
+ addMark (getDecl (DRE ), Flags);
3553
3547
return ;
3554
3548
}
3555
3549
@@ -3634,10 +3628,10 @@ std::pair<bool, Expr *> VarDeclUsageChecker::walkToExprPre(Expr *E) {
3634
3628
// If this is a DeclRefExpr found in a random place, it is a load of the
3635
3629
// vardecl.
3636
3630
if (auto *DRE = dyn_cast<DeclRefExpr>(E)) {
3637
- addMark (DRE-> getDeclForUsageAnalysis ( ), RK_Read);
3631
+ addMark (getDecl (DRE ), RK_Read);
3638
3632
3639
3633
// If the Expression is a read of a getter, track for diagnostics
3640
- if (auto VD = dyn_cast<VarDecl>(DRE-> getDeclForUsageAnalysis ( ))) {
3634
+ if (auto VD = dyn_cast<VarDecl>(getDecl (DRE ))) {
3641
3635
AssociatedGetterRefExpr.insert (std::make_pair (VD, DRE));
3642
3636
}
3643
3637
}
@@ -3711,7 +3705,7 @@ void VarDeclUsageChecker::handleIfConfig(IfConfigDecl *ICD) {
3711
3705
// conservatively mark it read and written. This will silence "variable
3712
3706
// unused" and "could be marked let" warnings for it.
3713
3707
if (auto *DRE = dyn_cast<DeclRefExpr>(E))
3714
- VDUC.addMark (DRE-> getDeclForUsageAnalysis ( ), RK_Read | RK_Written);
3708
+ VDUC.addMark (VDUC. getDecl (DRE ), RK_Read | RK_Written);
3715
3709
else if (auto *declRef = dyn_cast<UnresolvedDeclRefExpr>(E)) {
3716
3710
auto name = declRef->getName ();
3717
3711
auto loc = declRef->getLoc ();
0 commit comments