@@ -2236,10 +2236,11 @@ class VarDeclUsageChecker : public ASTWalker {
2236
2236
DiagnosticEngine &Diags;
2237
2237
// Keep track of some information about a variable.
2238
2238
enum {
2239
- RK_Read = 1 , // /< Whether it was ever read.
2240
- RK_Written = 2 , // /< Whether it was ever written or passed inout.
2239
+ RK_Defined = 1 , // /< Whether it was ever defined in this scope.
2240
+ RK_Read = 2 , // /< Whether it was ever read.
2241
+ RK_Written = 4 , // /< Whether it was ever written or passed inout.
2241
2242
2242
- RK_CaptureList = 4 // /< Var is an entry in a capture list.
2243
+ RK_CaptureList = 8 // /< Var is an entry in a capture list.
2243
2244
};
2244
2245
2245
2246
// / These are all of the variables that we are tracking. VarDecls get added
@@ -2280,7 +2281,7 @@ class VarDeclUsageChecker : public ASTWalker {
2280
2281
if (FD->getAccessorKind () == AccessorKind::Set) {
2281
2282
if (auto getter = dyn_cast<VarDecl>(FD->getStorage ())) {
2282
2283
auto arguments = FD->getParameters ();
2283
- VarDecls[arguments->get (0 )] = 0 ;
2284
+ VarDecls[arguments->get (0 )] = RK_Defined ;
2284
2285
AssociatedGetter = getter;
2285
2286
}
2286
2287
}
@@ -2291,9 +2292,9 @@ class VarDeclUsageChecker : public ASTWalker {
2291
2292
2292
2293
VarDeclUsageChecker (VarDecl *vd) : Diags(vd->getASTContext ().Diags) {
2293
2294
// Track a specific VarDecl
2294
- VarDecls[vd] = 0 ;
2295
+ VarDecls[vd] = RK_Defined ;
2295
2296
if (auto *childVd = vd->getCorrespondingCaseBodyVariable ().getPtrOrNull ()) {
2296
- VarDecls[childVd] = 0 ;
2297
+ VarDecls[childVd] = RK_Defined ;
2297
2298
}
2298
2299
}
2299
2300
@@ -2323,10 +2324,6 @@ class VarDeclUsageChecker : public ASTWalker {
2323
2324
}
2324
2325
return sawMutation;
2325
2326
}
2326
-
2327
- bool isVarDeclEverWritten (VarDecl *VD) {
2328
- return (VarDecls[VD] & RK_Written) != 0 ;
2329
- }
2330
2327
2331
2328
bool shouldTrackVarDecl (VarDecl *VD) {
2332
2329
// If the variable is implicit, ignore it.
@@ -2355,9 +2352,7 @@ class VarDeclUsageChecker : public ASTWalker {
2355
2352
auto *vd = dyn_cast<VarDecl>(D);
2356
2353
if (!vd) return ;
2357
2354
2358
- auto vdi = VarDecls.find (vd);
2359
- if (vdi != VarDecls.end ())
2360
- vdi->second |= Flag;
2355
+ VarDecls[vd] |= Flag;
2361
2356
}
2362
2357
2363
2358
void markBaseOfStorageUse (Expr *E, ConcreteDeclRef decl, unsigned flags);
@@ -2385,17 +2380,17 @@ class VarDeclUsageChecker : public ASTWalker {
2385
2380
// that fact for better diagnostics.
2386
2381
auto parentAsExpr = Parent.getAsExpr ();
2387
2382
if (parentAsExpr && isa<CaptureListExpr>(parentAsExpr))
2388
- return RK_CaptureList;
2383
+ return RK_CaptureList | RK_Defined ;
2389
2384
// Otherwise, return none.
2390
- return 0 ;
2385
+ return RK_Defined ;
2391
2386
}();
2392
2387
2393
2388
if (!vd->isImplicit ()) {
2394
2389
if (auto *childVd =
2395
2390
vd->getCorrespondingCaseBodyVariable ().getPtrOrNull ()) {
2396
2391
// Child vars are never in capture lists.
2397
- assert (defaultFlags == 0 );
2398
- VarDecls[childVd] |= 0 ;
2392
+ assert (defaultFlags == RK_Defined );
2393
+ VarDecls[childVd] |= RK_Defined ;
2399
2394
}
2400
2395
}
2401
2396
VarDecls[vd] |= defaultFlags;
@@ -2437,7 +2432,7 @@ class VarDeclUsageChecker : public ASTWalker {
2437
2432
if (!PBD) continue ;
2438
2433
for (auto idx : range (PBD->getNumPatternEntries ())) {
2439
2434
PBD->getPattern (idx)->forEachVariable ([&](VarDecl *VD) {
2440
- VarDecls[VD] = RK_Read|RK_Written;
2435
+ VarDecls[VD] = RK_Read|RK_Written|RK_Defined ;
2441
2436
});
2442
2437
}
2443
2438
} else if (node.is <Stmt *>()) {
@@ -2448,7 +2443,7 @@ class VarDeclUsageChecker : public ASTWalker {
2448
2443
for (StmtConditionElement SCE : GS->getCond ()) {
2449
2444
if (auto pattern = SCE.getPatternOrNull ()) {
2450
2445
pattern->forEachVariable ([&](VarDecl *VD) {
2451
- VarDecls[VD] = RK_Read|RK_Written;
2446
+ VarDecls[VD] = RK_Read|RK_Written|RK_Defined ;
2452
2447
});
2453
2448
}
2454
2449
}
@@ -2507,7 +2502,7 @@ class VarDeclUsageChecker : public ASTWalker {
2507
2502
// Make sure that we setup our case body variables.
2508
2503
if (auto *caseStmt = dyn_cast<CaseStmt>(S)) {
2509
2504
for (auto *vd : caseStmt->getCaseBodyVariablesOrEmptyArray ()) {
2510
- VarDecls[vd] |= 0 ;
2505
+ VarDecls[vd] |= RK_Defined ;
2511
2506
}
2512
2507
}
2513
2508
@@ -2661,6 +2656,10 @@ VarDeclUsageChecker::~VarDeclUsageChecker() {
2661
2656
unsigned access;
2662
2657
std::tie (var, access) = p;
2663
2658
2659
+ // If the variable was not defined in this scope, we can safely ignore it.
2660
+ if (!(access & RK_Defined))
2661
+ continue ;
2662
+
2664
2663
if (auto *caseStmt =
2665
2664
dyn_cast_or_null<CaseStmt>(var->getRecursiveParentPatternStmt ())) {
2666
2665
// Only diagnose VarDecls from the first CaseLabelItem in CaseStmts, as
0 commit comments