Skip to content

Commit 2a1869b

Browse files
authored
[DebugInfo] Shave even more users of DbgVariableIntrinsic from LLVM (#149136)
At this stage I'm just opportunistically deleting any code using debug-intrinsic types, largely adjacent to calls to findDbgUsers. I'll get to deleting that in probably one or more two commits.
1 parent beec840 commit 2a1869b

File tree

13 files changed

+41
-270
lines changed

13 files changed

+41
-270
lines changed

llvm/include/llvm/IR/DebugInfo.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,7 @@ class DebugInfoFinder {
115115
LLVM_ABI void processVariable(DILocalVariable *DVI);
116116
/// Process debug info location.
117117
LLVM_ABI void processLocation(const Module &M, const DILocation *Loc);
118-
/// Process a DbgRecord (e.g, treat a DbgVariableRecord like a
119-
/// DbgVariableIntrinsic).
118+
/// Process a DbgRecord.
120119
LLVM_ABI void processDbgRecord(const Module &M, const DbgRecord &DR);
121120

122121
/// Process subprogram.
@@ -290,8 +289,6 @@ struct VarRecord {
290289
DILocalVariable *Var;
291290
DILocation *DL;
292291

293-
VarRecord(DbgVariableIntrinsic *DVI)
294-
: Var(DVI->getVariable()), DL(getDebugValueLoc(DVI)) {}
295292
VarRecord(DbgVariableRecord *DVR)
296293
: Var(DVR->getVariable()), DL(getDebugValueLoc(DVR)) {}
297294
VarRecord(DILocalVariable *Var, DILocation *DL) : Var(Var), DL(DL) {}

llvm/include/llvm/IR/DebugInfoMetadata.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ namespace dwarf {
6666
enum Tag : uint16_t;
6767
}
6868

69-
class DbgVariableIntrinsic;
7069
class DbgVariableRecord;
7170

7271
LLVM_ABI extern cl::opt<bool> EnableFSDiscriminator;
@@ -4613,7 +4612,6 @@ class DebugVariable {
46134612
LLVM_ABI static const FragmentInfo DefaultFragment;
46144613

46154614
public:
4616-
LLVM_ABI DebugVariable(const DbgVariableIntrinsic *DII);
46174615
LLVM_ABI DebugVariable(const DbgVariableRecord *DVR);
46184616

46194617
DebugVariable(const DILocalVariable *Var,
@@ -4681,7 +4679,6 @@ template <> struct DenseMapInfo<DebugVariable> {
46814679
/// information).
46824680
class DebugVariableAggregate : public DebugVariable {
46834681
public:
4684-
LLVM_ABI DebugVariableAggregate(const DbgVariableIntrinsic *DVI);
46854682
DebugVariableAggregate(const DebugVariable &V)
46864683
: DebugVariable(V.getVariable(), std::nullopt, V.getInlinedAt()) {}
46874684
};

llvm/lib/IR/DebugInfo.cpp

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2288,39 +2288,36 @@ bool AssignmentTrackingPass::runOnFunction(Function &F) {
22882288
// Collect a map of {backing storage : dbg.declares} (currently "backing
22892289
// storage" is limited to Allocas). We'll use this to find dbg.declares to
22902290
// delete after running `trackAssignments`.
2291-
DenseMap<const AllocaInst *, SmallPtrSet<DbgDeclareInst *, 2>> DbgDeclares;
22922291
DenseMap<const AllocaInst *, SmallPtrSet<DbgVariableRecord *, 2>> DVRDeclares;
22932292
// Create another similar map of {storage : variables} that we'll pass to
22942293
// trackAssignments.
22952294
StorageToVarsMap Vars;
2296-
auto ProcessDeclare = [&](auto *Declare, auto &DeclareList) {
2295+
auto ProcessDeclare = [&](DbgVariableRecord &Declare) {
22972296
// FIXME: trackAssignments doesn't let you specify any modifiers to the
22982297
// variable (e.g. fragment) or location (e.g. offset), so we have to
22992298
// leave dbg.declares with non-empty expressions in place.
2300-
if (Declare->getExpression()->getNumElements() != 0)
2299+
if (Declare.getExpression()->getNumElements() != 0)
23012300
return;
2302-
if (!Declare->getAddress())
2301+
if (!Declare.getAddress())
23032302
return;
23042303
if (AllocaInst *Alloca =
2305-
dyn_cast<AllocaInst>(Declare->getAddress()->stripPointerCasts())) {
2304+
dyn_cast<AllocaInst>(Declare.getAddress()->stripPointerCasts())) {
23062305
// FIXME: Skip VLAs for now (let these variables use dbg.declares).
23072306
if (!Alloca->isStaticAlloca())
23082307
return;
23092308
// Similarly, skip scalable vectors (use dbg.declares instead).
23102309
if (auto Sz = Alloca->getAllocationSize(*DL); Sz && Sz->isScalable())
23112310
return;
2312-
DeclareList[Alloca].insert(Declare);
2313-
Vars[Alloca].insert(VarRecord(Declare));
2311+
DVRDeclares[Alloca].insert(&Declare);
2312+
Vars[Alloca].insert(VarRecord(&Declare));
23142313
}
23152314
};
23162315
for (auto &BB : F) {
23172316
for (auto &I : BB) {
23182317
for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) {
23192318
if (DVR.isDbgDeclare())
2320-
ProcessDeclare(&DVR, DVRDeclares);
2319+
ProcessDeclare(DVR);
23212320
}
2322-
if (DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(&I))
2323-
ProcessDeclare(DDI, DbgDeclares);
23242321
}
23252322
}
23262323

@@ -2336,8 +2333,8 @@ bool AssignmentTrackingPass::runOnFunction(Function &F) {
23362333
trackAssignments(F.begin(), F.end(), Vars, *DL);
23372334

23382335
// Delete dbg.declares for variables now tracked with assignment tracking.
2339-
auto DeleteSubsumedDeclare = [&](const auto &Markers, auto &Declares) {
2340-
(void)Markers;
2336+
for (auto &[Insts, Declares] : DVRDeclares) {
2337+
auto Markers = at::getDVRAssignmentMarkers(Insts);
23412338
for (auto *Declare : Declares) {
23422339
// Assert that the alloca that Declare uses is now linked to a dbg.assign
23432340
// describing the same variable (i.e. check that this dbg.declare has
@@ -2356,10 +2353,6 @@ bool AssignmentTrackingPass::runOnFunction(Function &F) {
23562353
Changed = true;
23572354
}
23582355
};
2359-
for (auto &P : DbgDeclares)
2360-
DeleteSubsumedDeclare(at::getAssignmentMarkers(P.first), P.second);
2361-
for (auto &P : DVRDeclares)
2362-
DeleteSubsumedDeclare(at::getDVRAssignmentMarkers(P.first), P.second);
23632356
return Changed;
23642357
}
23652358

llvm/lib/IR/DebugInfoMetadata.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,20 +49,11 @@ uint32_t DIType::getAlignInBits() const {
4949
const DIExpression::FragmentInfo DebugVariable::DefaultFragment = {
5050
std::numeric_limits<uint64_t>::max(), std::numeric_limits<uint64_t>::min()};
5151

52-
DebugVariable::DebugVariable(const DbgVariableIntrinsic *DII)
53-
: Variable(DII->getVariable()),
54-
Fragment(DII->getExpression()->getFragmentInfo()),
55-
InlinedAt(DII->getDebugLoc().getInlinedAt()) {}
56-
5752
DebugVariable::DebugVariable(const DbgVariableRecord *DVR)
5853
: Variable(DVR->getVariable()),
5954
Fragment(DVR->getExpression()->getFragmentInfo()),
6055
InlinedAt(DVR->getDebugLoc().getInlinedAt()) {}
6156

62-
DebugVariableAggregate::DebugVariableAggregate(const DbgVariableIntrinsic *DVI)
63-
: DebugVariable(DVI->getVariable(), std::nullopt,
64-
DVI->getDebugLoc()->getInlinedAt()) {}
65-
6657
DILocation::DILocation(LLVMContext &C, StorageType Storage, unsigned Line,
6758
unsigned Column, uint64_t AtomGroup, uint8_t AtomRank,
6859
ArrayRef<Metadata *> MDs, bool ImplicitCode)

llvm/lib/Transforms/InstCombine/InstCombineInternal.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -825,9 +825,6 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
825825
Value *EvaluateInDifferentType(Value *V, Type *Ty, bool isSigned);
826826

827827
bool tryToSinkInstruction(Instruction *I, BasicBlock *DestBlock);
828-
void tryToSinkInstructionDbgValues(
829-
Instruction *I, BasicBlock::iterator InsertPos, BasicBlock *SrcBlock,
830-
BasicBlock *DestBlock, SmallVectorImpl<DbgVariableIntrinsic *> &DbgUsers);
831828
void tryToSinkInstructionDbgVariableRecords(
832829
Instruction *I, BasicBlock::iterator InsertPos, BasicBlock *SrcBlock,
833830
BasicBlock *DestBlock, SmallVectorImpl<DbgVariableRecord *> &DPUsers);

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 4 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -3575,6 +3575,7 @@ Instruction *InstCombinerImpl::visitAllocSite(Instruction &MI) {
35753575
std::unique_ptr<DIBuilder> DIB;
35763576
if (isa<AllocaInst>(MI)) {
35773577
findDbgUsers(DVIs, &MI, &DVRs);
3578+
assert(DVIs.empty());
35783579
DIB.reset(new DIBuilder(*MI.getModule(), /*AllowUnresolved=*/false));
35793580
}
35803581

@@ -5253,8 +5254,7 @@ bool InstCombinerImpl::tryToSinkInstruction(Instruction *I,
52535254
SmallVector<DbgVariableIntrinsic *, 2> DbgUsers;
52545255
SmallVector<DbgVariableRecord *, 2> DbgVariableRecords;
52555256
findDbgUsers(DbgUsers, I, &DbgVariableRecords);
5256-
if (!DbgUsers.empty())
5257-
tryToSinkInstructionDbgValues(I, InsertPos, SrcBlock, DestBlock, DbgUsers);
5257+
assert(DbgUsers.empty());
52585258
if (!DbgVariableRecords.empty())
52595259
tryToSinkInstructionDbgVariableRecords(I, InsertPos, SrcBlock, DestBlock,
52605260
DbgVariableRecords);
@@ -5271,71 +5271,12 @@ bool InstCombinerImpl::tryToSinkInstruction(Instruction *I,
52715271
return true;
52725272
}
52735273

5274-
void InstCombinerImpl::tryToSinkInstructionDbgValues(
5275-
Instruction *I, BasicBlock::iterator InsertPos, BasicBlock *SrcBlock,
5276-
BasicBlock *DestBlock, SmallVectorImpl<DbgVariableIntrinsic *> &DbgUsers) {
5277-
// For all debug values in the destination block, the sunk instruction
5278-
// will still be available, so they do not need to be dropped.
5279-
SmallVector<DbgVariableIntrinsic *, 2> DbgUsersToSalvage;
5280-
for (auto &DbgUser : DbgUsers)
5281-
if (DbgUser->getParent() != DestBlock)
5282-
DbgUsersToSalvage.push_back(DbgUser);
5283-
5284-
// Process the sinking DbgUsersToSalvage in reverse order, as we only want
5285-
// to clone the last appearing debug intrinsic for each given variable.
5286-
SmallVector<DbgVariableIntrinsic *, 2> DbgUsersToSink;
5287-
for (DbgVariableIntrinsic *DVI : DbgUsersToSalvage)
5288-
if (DVI->getParent() == SrcBlock)
5289-
DbgUsersToSink.push_back(DVI);
5290-
llvm::sort(DbgUsersToSink,
5291-
[](auto *A, auto *B) { return B->comesBefore(A); });
5292-
5293-
SmallVector<DbgVariableIntrinsic *, 2> DIIClones;
5294-
SmallSet<DebugVariable, 4> SunkVariables;
5295-
for (auto *User : DbgUsersToSink) {
5296-
// A dbg.declare instruction should not be cloned, since there can only be
5297-
// one per variable fragment. It should be left in the original place
5298-
// because the sunk instruction is not an alloca (otherwise we could not be
5299-
// here).
5300-
if (isa<DbgDeclareInst>(User))
5301-
continue;
5302-
5303-
DebugVariable DbgUserVariable =
5304-
DebugVariable(User->getVariable(), User->getExpression(),
5305-
User->getDebugLoc()->getInlinedAt());
5306-
5307-
if (!SunkVariables.insert(DbgUserVariable).second)
5308-
continue;
5309-
5310-
// Leave dbg.assign intrinsics in their original positions and there should
5311-
// be no need to insert a clone.
5312-
if (isa<DbgAssignIntrinsic>(User))
5313-
continue;
5314-
5315-
DIIClones.emplace_back(cast<DbgVariableIntrinsic>(User->clone()));
5316-
if (isa<DbgDeclareInst>(User) && isa<CastInst>(I))
5317-
DIIClones.back()->replaceVariableLocationOp(I, I->getOperand(0));
5318-
LLVM_DEBUG(dbgs() << "CLONE: " << *DIIClones.back() << '\n');
5319-
}
5320-
5321-
// Perform salvaging without the clones, then sink the clones.
5322-
if (!DIIClones.empty()) {
5323-
salvageDebugInfoForDbgValues(*I, DbgUsersToSalvage, {});
5324-
// The clones are in reverse order of original appearance, reverse again to
5325-
// maintain the original order.
5326-
for (auto &DIIClone : llvm::reverse(DIIClones)) {
5327-
DIIClone->insertBefore(InsertPos);
5328-
LLVM_DEBUG(dbgs() << "SINK: " << *DIIClone << '\n');
5329-
}
5330-
}
5331-
}
5332-
53335274
void InstCombinerImpl::tryToSinkInstructionDbgVariableRecords(
53345275
Instruction *I, BasicBlock::iterator InsertPos, BasicBlock *SrcBlock,
53355276
BasicBlock *DestBlock,
53365277
SmallVectorImpl<DbgVariableRecord *> &DbgVariableRecords) {
5337-
// Implementation of tryToSinkInstructionDbgValues, but for the
5338-
// DbgVariableRecord of variable assignments rather than dbg.values.
5278+
// For all debug values in the destination block, the sunk instruction
5279+
// will still be available, so they do not need to be dropped.
53395280

53405281
// Fetch all DbgVariableRecords not already in the destination.
53415282
SmallVector<DbgVariableRecord *, 2> DbgVariableRecordsToSalvage;

llvm/lib/Transforms/Scalar/ConstraintElimination.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1489,6 +1489,7 @@ static bool checkAndReplaceCondition(
14891489
SmallVector<DbgVariableIntrinsic *> DbgUsers;
14901490
SmallVector<DbgVariableRecord *> DVRUsers;
14911491
findDbgUsers(DbgUsers, Cmp, &DVRUsers);
1492+
assert(DbgUsers.empty());
14921493

14931494
for (auto *DVR : DVRUsers) {
14941495
auto *DTN = DT.getNode(DVR->getParent());

llvm/lib/Transforms/Utils/CodeExtractor.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1222,9 +1222,7 @@ static void eraseDebugIntrinsicsWithNonLocalRefs(Function &F) {
12221222
SmallVector<DbgVariableIntrinsic *, 4> DbgUsers;
12231223
SmallVector<DbgVariableRecord *, 4> DbgVariableRecords;
12241224
findDbgUsers(DbgUsers, &I, &DbgVariableRecords);
1225-
for (DbgVariableIntrinsic *DVI : DbgUsers)
1226-
if (DVI->getFunction() != &F)
1227-
DVI->eraseFromParent();
1225+
assert(DbgUsers.empty());
12281226
for (DbgVariableRecord *DVR : DbgVariableRecords)
12291227
if (DVR->getFunction() != &F)
12301228
DVR->eraseFromParent();
@@ -1289,14 +1287,12 @@ static void fixupDebugInfoPostExtraction(Function &OldFunc, Function &NewFunc,
12891287
SmallVector<DbgVariableIntrinsic *, 1> DbgUsers;
12901288
SmallVector<DbgVariableRecord *, 1> DPUsers;
12911289
findDbgUsers(DbgUsers, Input, &DPUsers);
1290+
assert(DbgUsers.empty());
12921291
DIExpression *Expr = DIB.createExpression();
12931292

12941293
// Iterate the debud users of the Input values. If they are in the extracted
12951294
// function then update their location with the new value. If they are in
12961295
// the parent function then create a similar debug record.
1297-
for (auto *DVI : DbgUsers)
1298-
UpdateOrInsertDebugRecord(DVI, Input, NewVal, Expr,
1299-
isa<DbgDeclareInst>(DVI));
13001296
for (auto *DVR : DPUsers)
13011297
UpdateOrInsertDebugRecord(DVR, Input, NewVal, Expr, DVR->isDbgDeclare());
13021298
}

llvm/lib/Transforms/Utils/InlineFunction.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1978,14 +1978,13 @@ static at::StorageToVarsMap collectEscapedLocals(const DataLayout &DL,
19781978
continue;
19791979

19801980
// Find all local variables associated with the backing storage.
1981-
auto CollectAssignsForStorage = [&](auto *DbgAssign) {
1981+
auto CollectAssignsForStorage = [&](DbgVariableRecord *DbgAssign) {
19821982
// Skip variables from inlined functions - they are not local variables.
19831983
if (DbgAssign->getDebugLoc().getInlinedAt())
19841984
return;
19851985
LLVM_DEBUG(errs() << " > DEF : " << *DbgAssign << "\n");
19861986
EscapedLocals[Base].insert(at::VarRecord(DbgAssign));
19871987
};
1988-
for_each(at::getAssignmentMarkers(Base), CollectAssignsForStorage);
19891988
for_each(at::getDVRAssignmentMarkers(Base), CollectAssignsForStorage);
19901989
}
19911990
return EscapedLocals;

llvm/lib/Transforms/Utils/Local.cpp

Lines changed: 6 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -613,11 +613,10 @@ bool llvm::replaceDbgUsesWithUndef(Instruction *I) {
613613
SmallVector<DbgVariableIntrinsic *, 1> DbgUsers;
614614
SmallVector<DbgVariableRecord *, 1> DPUsers;
615615
findDbgUsers(DbgUsers, I, &DPUsers);
616-
for (auto *DII : DbgUsers)
617-
DII->setKillLocation();
616+
assert(DbgUsers.empty());
618617
for (auto *DVR : DPUsers)
619618
DVR->setKillLocation();
620-
return !DbgUsers.empty() || !DPUsers.empty();
619+
return !DPUsers.empty();
621620
}
622621

623622
/// areAllUsesEqual - Check whether the uses of a value are all the same.
@@ -2022,6 +2021,7 @@ void llvm::salvageDebugInfo(Instruction &I) {
20222021
SmallVector<DbgVariableIntrinsic *, 1> DbgUsers;
20232022
SmallVector<DbgVariableRecord *, 1> DPUsers;
20242023
findDbgUsers(DbgUsers, &I, &DPUsers);
2024+
assert(DbgUsers.empty());
20252025
salvageDebugInfoForDbgValues(I, DbgUsers, DPUsers);
20262026
}
20272027

@@ -2070,66 +2070,9 @@ void llvm::salvageDebugInfoForDbgValues(
20702070
const unsigned MaxExpressionSize = 128;
20712071
bool Salvaged = false;
20722072

2073-
for (auto *DII : DbgUsers) {
2074-
if (auto *DAI = dyn_cast<DbgAssignIntrinsic>(DII)) {
2075-
if (DAI->getAddress() == &I) {
2076-
salvageDbgAssignAddress(DAI);
2077-
Salvaged = true;
2078-
}
2079-
if (DAI->getValue() != &I)
2080-
continue;
2081-
}
2082-
2083-
// Do not add DW_OP_stack_value for DbgDeclare, because they are implicitly
2084-
// pointing out the value as a DWARF memory location description.
2085-
bool StackValue = isa<DbgValueInst>(DII);
2086-
auto DIILocation = DII->location_ops();
2087-
assert(
2088-
is_contained(DIILocation, &I) &&
2089-
"DbgVariableIntrinsic must use salvaged instruction as its location");
2090-
SmallVector<Value *, 4> AdditionalValues;
2091-
// `I` may appear more than once in DII's location ops, and each use of `I`
2092-
// must be updated in the DIExpression and potentially have additional
2093-
// values added; thus we call salvageDebugInfoImpl for each `I` instance in
2094-
// DIILocation.
2095-
Value *Op0 = nullptr;
2096-
DIExpression *SalvagedExpr = DII->getExpression();
2097-
auto LocItr = find(DIILocation, &I);
2098-
while (SalvagedExpr && LocItr != DIILocation.end()) {
2099-
SmallVector<uint64_t, 16> Ops;
2100-
unsigned LocNo = std::distance(DIILocation.begin(), LocItr);
2101-
uint64_t CurrentLocOps = SalvagedExpr->getNumLocationOperands();
2102-
Op0 = salvageDebugInfoImpl(I, CurrentLocOps, Ops, AdditionalValues);
2103-
if (!Op0)
2104-
break;
2105-
SalvagedExpr =
2106-
DIExpression::appendOpsToArg(SalvagedExpr, Ops, LocNo, StackValue);
2107-
LocItr = std::find(++LocItr, DIILocation.end(), &I);
2108-
}
2109-
// salvageDebugInfoImpl should fail on examining the first element of
2110-
// DbgUsers, or none of them.
2111-
if (!Op0)
2112-
break;
2073+
// We should never see debug intrinsics nowadays.
2074+
assert(DbgUsers.empty());
21132075

2114-
SalvagedExpr = SalvagedExpr->foldConstantMath();
2115-
DII->replaceVariableLocationOp(&I, Op0);
2116-
bool IsValidSalvageExpr = SalvagedExpr->getNumElements() <= MaxExpressionSize;
2117-
if (AdditionalValues.empty() && IsValidSalvageExpr) {
2118-
DII->setExpression(SalvagedExpr);
2119-
} else if (isa<DbgValueInst>(DII) && IsValidSalvageExpr &&
2120-
DII->getNumVariableLocationOps() + AdditionalValues.size() <=
2121-
MaxDebugArgs) {
2122-
DII->addVariableLocationOps(AdditionalValues, SalvagedExpr);
2123-
} else {
2124-
// Do not salvage using DIArgList for dbg.declare, as it is not currently
2125-
// supported in those instructions. Also do not salvage if the resulting
2126-
// DIArgList would contain an unreasonably large number of values.
2127-
DII->setKillLocation();
2128-
}
2129-
LLVM_DEBUG(dbgs() << "SALVAGE: " << *DII << '\n');
2130-
Salvaged = true;
2131-
}
2132-
// Duplicate of above block for DbgVariableRecords.
21332076
for (auto *DVR : DPUsers) {
21342077
if (DVR->isDbgAssign()) {
21352078
if (DVR->getAddress() == &I) {
@@ -2198,9 +2141,6 @@ void llvm::salvageDebugInfoForDbgValues(
21982141
if (Salvaged)
21992142
return;
22002143

2201-
for (auto *DII : DbgUsers)
2202-
DII->setKillLocation();
2203-
22042144
for (auto *DVR : DPUsers)
22052145
DVR->setKillLocation();
22062146
}
@@ -3429,8 +3369,7 @@ void llvm::dropDebugUsers(Instruction &I) {
34293369
SmallVector<DbgVariableIntrinsic *, 1> DbgUsers;
34303370
SmallVector<DbgVariableRecord *, 1> DPUsers;
34313371
findDbgUsers(DbgUsers, &I, &DPUsers);
3432-
for (auto *DII : DbgUsers)
3433-
DII->eraseFromParent();
3372+
assert(DbgUsers.empty());
34343373
for (auto *DVR : DPUsers)
34353374
DVR->eraseFromParent();
34363375
}

0 commit comments

Comments
 (0)