@@ -1176,7 +1176,11 @@ groupWarningGadgetsByVar(const WarningGadgetList &AllUnsafeOperations) {
1176
1176
}
1177
1177
1178
1178
struct FixableGadgetSets {
1179
- std::map<const VarDecl *, std::set<const FixableGadget *>> byVar;
1179
+ std::map<const VarDecl *, std::set<const FixableGadget *>,
1180
+ // To keep keys sorted by their locations in the map so that the
1181
+ // order is deterministic:
1182
+ CompareNode<VarDecl>>
1183
+ byVar;
1180
1184
};
1181
1185
1182
1186
static FixableGadgetSets
@@ -1382,7 +1386,7 @@ static std::optional<StringRef> getRangeText(SourceRange SR,
1382
1386
const SourceManager &SM,
1383
1387
const LangOptions &LangOpts) {
1384
1388
bool Invalid = false ;
1385
- CharSourceRange CSR = CharSourceRange::getCharRange (SR. getBegin (), SR. getEnd () );
1389
+ CharSourceRange CSR = CharSourceRange::getCharRange (SR);
1386
1390
StringRef Text = Lexer::getSourceText (CSR, SM, LangOpts, &Invalid);
1387
1391
1388
1392
if (!Invalid)
@@ -2225,7 +2229,7 @@ getFixIts(FixableGadgetSets &FixablesForAllVars, const Strategy &S,
2225
2229
ASTContext &Ctx,
2226
2230
/* The function decl under analysis */ const Decl *D,
2227
2231
const DeclUseTracker &Tracker, UnsafeBufferUsageHandler &Handler,
2228
- const DefMapTy &VarGrpMap ) {
2232
+ const VariableGroupsManager &VarGrpMgr ) {
2229
2233
std::map<const VarDecl *, FixItList> FixItsForVariable;
2230
2234
for (const auto &[VD, Fixables] : FixablesForAllVars.byVar ) {
2231
2235
FixItsForVariable[VD] =
@@ -2261,9 +2265,10 @@ getFixIts(FixableGadgetSets &FixablesForAllVars, const Strategy &S,
2261
2265
continue ;
2262
2266
}
2263
2267
2264
- const auto VarGroupForVD = VarGrpMap.find (VD);
2265
- if (VarGroupForVD != VarGrpMap.end ()) {
2266
- for (const VarDecl * V : VarGroupForVD->second ) {
2268
+
2269
+ {
2270
+ const auto VarGroupForVD = VarGrpMgr.getGroupOfVar (VD);
2271
+ for (const VarDecl * V : VarGroupForVD) {
2267
2272
if (V == VD) {
2268
2273
continue ;
2269
2274
}
@@ -2275,7 +2280,7 @@ getFixIts(FixableGadgetSets &FixablesForAllVars, const Strategy &S,
2275
2280
2276
2281
if (ImpossibleToFix) {
2277
2282
FixItsForVariable.erase (VD);
2278
- for (const VarDecl * V : VarGroupForVD-> second ) {
2283
+ for (const VarDecl * V : VarGroupForVD) {
2279
2284
FixItsForVariable.erase (V);
2280
2285
}
2281
2286
continue ;
@@ -2293,30 +2298,24 @@ getFixIts(FixableGadgetSets &FixablesForAllVars, const Strategy &S,
2293
2298
}
2294
2299
}
2295
2300
2296
- for (auto VD : FixItsForVariable) {
2297
- const auto VarGroupForVD = VarGrpMap.find (VD.first );
2298
- const Strategy::Kind ReplacementTypeForVD = S.lookup (VD.first );
2299
- if (VarGroupForVD != VarGrpMap.end ()) {
2300
- for (const VarDecl * Var : VarGroupForVD->second ) {
2301
- if (Var == VD.first ) {
2302
- continue ;
2303
- }
2301
+ // The map that maps each variable `v` to fix-its for the whole group where
2302
+ // `v` is in:
2303
+ std::map<const VarDecl *, FixItList> FinalFixItsForVariable{
2304
+ FixItsForVariable};
2304
2305
2305
- FixItList GroupFix;
2306
- if (FixItsForVariable.find (Var) == FixItsForVariable.end ()) {
2307
- GroupFix = fixVariable (Var, ReplacementTypeForVD, D, Tracker,
2308
- Var->getASTContext (), Handler);
2309
- } else {
2310
- GroupFix = FixItsForVariable[Var];
2311
- }
2306
+ for (auto &[Var, Ignore] : FixItsForVariable) {
2307
+ const auto VarGroupForVD = VarGrpMgr.getGroupOfVar (Var);
2312
2308
2313
- for (auto Fix : GroupFix) {
2314
- FixItsForVariable[VD.first ].push_back (Fix);
2315
- }
2316
- }
2309
+ for (const VarDecl *GrpMate : VarGroupForVD) {
2310
+ if (Var == GrpMate)
2311
+ continue ;
2312
+ if (FixItsForVariable.count (GrpMate))
2313
+ FinalFixItsForVariable[Var].insert (FinalFixItsForVariable[Var].end (),
2314
+ FixItsForVariable[GrpMate].begin (),
2315
+ FixItsForVariable[GrpMate].end ());
2317
2316
}
2318
2317
}
2319
- return FixItsForVariable ;
2318
+ return FinalFixItsForVariable ;
2320
2319
}
2321
2320
2322
2321
@@ -2329,6 +2328,24 @@ getNaiveStrategy(const llvm::SmallVectorImpl<const VarDecl *> &UnsafeVars) {
2329
2328
return S;
2330
2329
}
2331
2330
2331
+ // Manages variable groups:
2332
+ class VariableGroupsManagerImpl : public VariableGroupsManager {
2333
+ const std::vector<VarGrpTy> Groups;
2334
+ const std::map<const VarDecl *, unsigned > &VarGrpMap;
2335
+
2336
+ public:
2337
+ VariableGroupsManagerImpl (
2338
+ const std::vector<VarGrpTy> &Groups,
2339
+ const std::map<const VarDecl *, unsigned > &VarGrpMap)
2340
+ : Groups(Groups), VarGrpMap(VarGrpMap) {}
2341
+
2342
+ VarGrpRef getGroupOfVar (const VarDecl *Var) const override {
2343
+ auto I = VarGrpMap.find (Var);
2344
+ assert (I != VarGrpMap.end ());
2345
+ return Groups[I->second ];
2346
+ }
2347
+ };
2348
+
2332
2349
void clang::checkUnsafeBufferUsage (const Decl *D,
2333
2350
UnsafeBufferUsageHandler &Handler,
2334
2351
bool EmitSuggestions) {
@@ -2408,7 +2425,6 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
2408
2425
FixablesForAllVars = groupFixablesByVar (std::move (FixableGadgets));
2409
2426
2410
2427
std::map<const VarDecl *, FixItList> FixItsForVariableGroup;
2411
- DefMapTy VariableGroupsMap{};
2412
2428
2413
2429
// Filter out non-local vars and vars with unclaimed DeclRefExpr-s.
2414
2430
for (auto it = FixablesForAllVars.byVar .cbegin ();
@@ -2451,7 +2467,7 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
2451
2467
UnsafeVars.push_back (VD);
2452
2468
2453
2469
// Fixpoint iteration for pointer assignments
2454
- using DepMapTy = DenseMap<const VarDecl *, std::set <const VarDecl *>>;
2470
+ using DepMapTy = DenseMap<const VarDecl *, llvm::SetVector <const VarDecl *>>;
2455
2471
DepMapTy DependenciesMap{};
2456
2472
DepMapTy PtrAssignmentGraph{};
2457
2473
@@ -2460,7 +2476,7 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
2460
2476
std::optional<std::pair<const VarDecl *, const VarDecl *>> ImplPair =
2461
2477
fixable->getStrategyImplications ();
2462
2478
if (ImplPair) {
2463
- std::pair<const VarDecl *, const VarDecl *> Impl = ImplPair. value ( );
2479
+ std::pair<const VarDecl *, const VarDecl *> Impl = std::move (*ImplPair );
2464
2480
PtrAssignmentGraph[Impl.first ].insert (Impl.second );
2465
2481
}
2466
2482
}
@@ -2505,14 +2521,21 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
2505
2521
}
2506
2522
}
2507
2523
2524
+ // `Groups` stores the set of Connected Components in the graph.
2525
+ std::vector<VarGrpTy> Groups;
2526
+ // `VarGrpMap` maps variables that need fix to the groups (indexes) that the
2527
+ // variables belong to. Group indexes refer to the elements in `Groups`.
2528
+ // `VarGrpMap` is complete in that every variable that needs fix is in it.
2529
+ std::map<const VarDecl *, unsigned > VarGrpMap;
2530
+
2508
2531
// Group Connected Components for Unsafe Vars
2509
2532
// (Dependencies based on pointer assignments)
2510
2533
std::set<const VarDecl *> VisitedVars{};
2511
2534
for (const auto &[Var, ignore] : UnsafeOps.byVar ) {
2512
2535
if (VisitedVars.find (Var) == VisitedVars.end ()) {
2513
- std::vector<const VarDecl *> VarGroup{};
2514
-
2536
+ VarGrpTy &VarGroup = Groups.emplace_back ();
2515
2537
std::queue<const VarDecl*> Queue{};
2538
+
2516
2539
Queue.push (Var);
2517
2540
while (!Queue.empty ()) {
2518
2541
const VarDecl* CurrentVar = Queue.front ();
@@ -2526,10 +2549,10 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
2526
2549
}
2527
2550
}
2528
2551
}
2529
- for ( const VarDecl * V : VarGroup) {
2530
- if (UnsafeOps. byVar . find (V) != UnsafeOps. byVar . end ()) {
2531
- VariableGroupsMap[V] = VarGroup;
2532
- }
2552
+ unsigned GrpIdx = Groups. size () - 1 ;
2553
+
2554
+ for ( const VarDecl *V : VarGroup) {
2555
+ VarGrpMap[V] = GrpIdx;
2533
2556
}
2534
2557
}
2535
2558
}
@@ -2563,20 +2586,19 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
2563
2586
}
2564
2587
2565
2588
Strategy NaiveStrategy = getNaiveStrategy (UnsafeVars);
2589
+ VariableGroupsManagerImpl VarGrpMgr (Groups, VarGrpMap);
2566
2590
2567
2591
FixItsForVariableGroup =
2568
2592
getFixIts (FixablesForAllVars, NaiveStrategy, D->getASTContext (), D,
2569
- Tracker, Handler, VariableGroupsMap);
2570
-
2571
- // FIXME Detect overlapping FixIts.
2593
+ Tracker, Handler, VarGrpMgr);
2572
2594
2573
2595
for (const auto &G : UnsafeOps.noVar ) {
2574
2596
Handler.handleUnsafeOperation (G->getBaseStmt (), /* IsRelatedToDecl=*/ false );
2575
2597
}
2576
2598
2577
2599
for (const auto &[VD, WarningGadgets] : UnsafeOps.byVar ) {
2578
2600
auto FixItsIt = FixItsForVariableGroup.find (VD);
2579
- Handler.handleUnsafeVariableGroup (VD, VariableGroupsMap ,
2601
+ Handler.handleUnsafeVariableGroup (VD, VarGrpMgr ,
2580
2602
FixItsIt != FixItsForVariableGroup.end ()
2581
2603
? std::move (FixItsIt->second )
2582
2604
: FixItList{});
0 commit comments