@@ -1090,16 +1090,6 @@ findGadgets(const Decl *D, const UnsafeBufferUsageHandler &Handler,
1090
1090
}
1091
1091
1092
1092
M.match (*D->getBody (), D->getASTContext ());
1093
-
1094
- // Gadgets "claim" variables they're responsible for. Once this loop finishes,
1095
- // the tracker will only track DREs that weren't claimed by any gadgets,
1096
- // i.e. not understood by the analysis.
1097
- for (const auto &G : CB.FixableGadgets ) {
1098
- for (const auto *DRE : G->getClaimedVarUseSites ()) {
1099
- CB.Tracker .claimUse (DRE);
1100
- }
1101
- }
1102
-
1103
1093
return {std::move (CB.FixableGadgets ), std::move (CB.WarningGadgets ),
1104
1094
std::move (CB.Tracker )};
1105
1095
}
@@ -2250,6 +2240,33 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
2250
2240
return ;
2251
2241
}
2252
2242
2243
+ // If no `WarningGadget`s ever matched, there is no unsafe operations in the
2244
+ // function under the analysis. No need to fix any Fixables.
2245
+ if (!WarningGadgets.empty ()) {
2246
+ // Gadgets "claim" variables they're responsible for. Once this loop
2247
+ // finishes, the tracker will only track DREs that weren't claimed by any
2248
+ // gadgets, i.e. not understood by the analysis.
2249
+ for (const auto &G : FixableGadgets) {
2250
+ for (const auto *DRE : G->getClaimedVarUseSites ()) {
2251
+ Tracker.claimUse (DRE);
2252
+ }
2253
+ }
2254
+ }
2255
+
2256
+ // If no `WarningGadget`s ever matched, there is no unsafe operations in the
2257
+ // function under the analysis. Thus, it early returns here as there is
2258
+ // nothing needs to be fixed.
2259
+ //
2260
+ // Note this claim is based on the assumption that there is no unsafe
2261
+ // variable whose declaration is invisible from the analyzing function.
2262
+ // Otherwise, we need to consider if the uses of those unsafe varuables needs
2263
+ // fix.
2264
+ // So far, we are not fixing any global variables or class members. And,
2265
+ // lambdas will be analyzed along with the enclosing function. So this early
2266
+ // return is correct for now.
2267
+ if (WarningGadgets.empty ())
2268
+ return ;
2269
+
2253
2270
UnsafeOps = groupWarningGadgetsByVar (std::move (WarningGadgets));
2254
2271
FixablesForAllVars = groupFixablesByVar (std::move (FixableGadgets));
2255
2272
@@ -2356,6 +2373,34 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
2356
2373
}
2357
2374
}
2358
2375
2376
+ // Remove a `FixableGadget` if the associated variable is not in the graph
2377
+ // computed above. We do not want to generate fix-its for such variables,
2378
+ // since they are neither warned nor reachable from a warned one.
2379
+ //
2380
+ // Note a variable is not warned if it is not directly used in any unsafe
2381
+ // operation. A variable `v` is NOT reachable from an unsafe variable, if it
2382
+ // does not exist another variable `u` such that `u` is warned and fixing `u`
2383
+ // (transitively) implicates fixing `v`.
2384
+ //
2385
+ // For example,
2386
+ // ```
2387
+ // void f(int * p) {
2388
+ // int * a = p; *p = 0;
2389
+ // }
2390
+ // ```
2391
+ // `*p = 0` is a fixable gadget associated with a variable `p` that is neither
2392
+ // warned nor reachable from a warned one. If we add `a[5] = 0` to the end of
2393
+ // the function above, `p` becomes reachable from a warned variable.
2394
+ for (auto I = FixablesForAllVars.byVar .begin ();
2395
+ I != FixablesForAllVars.byVar .end ();) {
2396
+ // Note `VisitedVars` contain all the variables in the graph:
2397
+ if (VisitedVars.find ((*I).first ) == VisitedVars.end ()) {
2398
+ // no such var in graph:
2399
+ I = FixablesForAllVars.byVar .erase (I);
2400
+ } else
2401
+ ++I;
2402
+ }
2403
+
2359
2404
Strategy NaiveStrategy = getNaiveStrategy (UnsafeVars);
2360
2405
2361
2406
FixItsForVariableGroup =
0 commit comments