@@ -81,22 +81,21 @@ struct State {
81
81
82
82
void initializeAllNonConsumingUses (
83
83
ArrayRef<BranchPropagatedUser> nonConsumingUsers);
84
- bool initializeAllConsumingUses (
84
+ void initializeAllConsumingUses (
85
85
ArrayRef<BranchPropagatedUser> consumingUsers,
86
86
SmallVectorImpl<BrPropUserAndBlockPair> &predsToAddToWorklist);
87
87
88
- // / Initializes state for a consuming use. Returns true if we have not yet
89
- // / seen a consuming use in the same block yet. Returns false if detect such a
90
- // / condition so users know that a use-after-free was detected.
91
- bool initializeConsumingUse (BranchPropagatedUser consumingUser,
88
+ // / Initializes state for a consuming use.
89
+ // /
90
+ // / If we are already tracking a consuming use for the block, this emits a
91
+ // / double consume checker error.
92
+ void initializeConsumingUse (BranchPropagatedUser consumingUser,
92
93
SILBasicBlock *userBlock);
93
94
94
- // / Returns true if the given block contains a non-consuming use that is
95
- // / strictly later in the block than a consuming use. If all
96
- // / non-consuming uses are before the consuming use, the block is
97
- // / removed from the blocksWithNonConsumingUses map to show that the uses
98
- // / were found to properly be post-dominated by a consuming use.
99
- bool checkForSameBlockUseAfterFree (BranchPropagatedUser consumingUser,
95
+ // / Check that this newly initialized consuming user does not have any
96
+ // / non-consuming uses after it. If the checker finds one, it emits a checker
97
+ // / error.
98
+ void checkForSameBlockUseAfterFree (BranchPropagatedUser consumingUser,
100
99
SILBasicBlock *userBlock);
101
100
102
101
// / Once we have marked all of our producing blocks.
@@ -181,27 +180,22 @@ void State::initializeAllNonConsumingUses(
181
180
// Consuming Use Initialization
182
181
// ===----------------------------------------------------------------------===//
183
182
184
- bool State::initializeAllConsumingUses (
183
+ void State::initializeAllConsumingUses (
185
184
ArrayRef<BranchPropagatedUser> consumingUses,
186
185
SmallVectorImpl<std::pair<BranchPropagatedUser, SILBasicBlock *>>
187
186
&predsToAddToWorklist) {
188
- bool noErrors = true ;
189
187
for (BranchPropagatedUser user : consumingUses) {
190
188
SILBasicBlock *userBlock = user.getParent ();
191
189
192
- // First initialize our state for the consuming user. This returns false if
193
- // we found another consuming instruction associated with userBlock and true
194
- // if we successfully associated user with userBlock.
195
- if (!initializeConsumingUse (user, userBlock)) {
196
- // We already handled the error.
197
- noErrors &= handleError ([] {});
198
- }
190
+ // First initialize our state for the consuming user.
191
+ //
192
+ // If we find another consuming instruction associated with userBlock this
193
+ // will emit a checker error.
194
+ initializeConsumingUse (user, userBlock);
199
195
200
- // Then check if the given block has a use after free.
201
- if (checkForSameBlockUseAfterFree (user, userBlock)) {
202
- // We already handled the error.
203
- noErrors &= handleError ([] {});
204
- }
196
+ // Then check if the given block has a use after free and emit an error if
197
+ // we find one.
198
+ checkForSameBlockUseAfterFree (user, userBlock);
205
199
206
200
// If this user is in the same block as the value, do not visit
207
201
// predecessors. We must be extra tolerant here since we allow for
@@ -216,32 +210,30 @@ bool State::initializeAllConsumingUses(
216
210
predsToAddToWorklist.push_back ({user, pred});
217
211
}
218
212
}
219
-
220
- return noErrors;
221
213
}
222
214
223
- bool State::initializeConsumingUse (BranchPropagatedUser consumingUser,
215
+ void State::initializeConsumingUse (BranchPropagatedUser consumingUser,
224
216
SILBasicBlock *userBlock) {
225
217
// Map this user to the block. If we already have a value for the block, then
226
218
// we have a double consume and need to fail.
227
219
if (blocksWithConsumingUses.insert (userBlock).second )
228
- return true ;
220
+ return ;
229
221
230
- return handleError ([&] {
222
+ handleError ([&] {
231
223
llvm::errs () << " Function: '" << value->getFunction ()->getName () << " '\n "
232
224
<< " Found over consume?!\n "
233
225
<< " Value: " << *value << " User: " << *consumingUser
234
226
<< " Block: bb" << userBlock->getDebugID () << " \n\n " ;
235
227
});
236
228
}
237
229
238
- bool State::checkForSameBlockUseAfterFree (BranchPropagatedUser consumingUser,
230
+ void State::checkForSameBlockUseAfterFree (BranchPropagatedUser consumingUser,
239
231
SILBasicBlock *userBlock) {
240
232
// If we do not have any consuming uses in the same block as our
241
233
// consuming user, then we can not have a same block use-after-free.
242
234
auto iter = blocksWithNonConsumingUses.find (userBlock);
243
235
if (iter == blocksWithNonConsumingUses.end ())
244
- return false ;
236
+ return ;
245
237
246
238
BranchPropagatedUser nonConsumingUser = iter->second ;
247
239
@@ -252,14 +244,15 @@ bool State::checkForSameBlockUseAfterFree(BranchPropagatedUser consumingUser,
252
244
// always consider the non-consuming use to be a use after free since
253
245
// the cond branch user is in a previous block. So just bail early.
254
246
if (consumingUser.isCondBranchUser ()) {
255
- return ! handleError ([&]() {
247
+ handleError ([&]() {
256
248
llvm::errs () << " Function: '" << value->getFunction ()->getName () << " '\n "
257
249
<< " Found use after free?!\n "
258
250
<< " Value: " << *value
259
251
<< " Consuming User: " << *consumingUser
260
252
<< " Non Consuming User: " << *iter->second << " Block: bb"
261
253
<< userBlock->getDebugID () << " \n\n " ;
262
254
});
255
+ return ;
263
256
}
264
257
265
258
// Ok. At this point, we know that our consuming user is not a cond branch
@@ -268,7 +261,7 @@ bool State::checkForSameBlockUseAfterFree(BranchPropagatedUser consumingUser,
268
261
// consuming use. and continue.
269
262
if (nonConsumingUser.isCondBranchUser ()) {
270
263
blocksWithNonConsumingUses.erase (iter);
271
- return false ;
264
+ return ;
272
265
}
273
266
274
267
// Otherwise, we know that both of our users are non-cond branch users and
@@ -278,19 +271,20 @@ bool State::checkForSameBlockUseAfterFree(BranchPropagatedUser consumingUser,
278
271
[&nonConsumingUser](const SILInstruction &i) -> bool {
279
272
return nonConsumingUser == &i;
280
273
}) != userBlock->end ()) {
281
- return ! handleError ([&] {
274
+ handleError ([&] {
282
275
llvm::errs () << " Function: '" << value->getFunction ()->getName () << " '\n "
283
276
<< " Found use after free?!\n "
284
277
<< " Value: " << *value
285
278
<< " Consuming User: " << *consumingUser
286
279
<< " Non Consuming User: " << *iter->second << " Block: bb"
287
280
<< userBlock->getDebugID () << " \n\n " ;
288
281
});
282
+ return ;
289
283
}
290
284
291
285
// Erase the use since we know that it is properly joint post-dominated.
292
286
blocksWithNonConsumingUses.erase (iter);
293
- return false ;
287
+ return ;
294
288
}
295
289
296
290
bool State::checkPredsForDoubleConsume (BranchPropagatedUser consumingUser,
0 commit comments