@@ -45,10 +45,9 @@ struct State {
45
45
// / The value that we are checking.
46
46
SILValue value;
47
47
48
- // / The behavior of the checker when we detect an error. Can either be
49
- // / returning false, returning false with a message emitted to stderr, or an
50
- // / assert.
51
- ErrorBehaviorKind errorBehavior;
48
+ // / The result error object that use to signal either that no errors were
49
+ // / found or if errors are found the specific type of error that was found.
50
+ LinearLifetimeError error;
52
51
53
52
// / The blocks that we have already visited.
54
53
SmallPtrSetImpl<SILBasicBlock *> &visitedBlocks;
@@ -76,8 +75,8 @@ struct State {
76
75
State (SILValue value, SmallPtrSetImpl<SILBasicBlock *> &visitedBlocks,
77
76
ErrorBehaviorKind errorBehavior,
78
77
SmallVectorImpl<SILBasicBlock *> *leakingBlocks)
79
- : value(value), errorBehavior (errorBehavior),
80
- visitedBlocks (visitedBlocks), leakingBlocks(leakingBlocks) {}
78
+ : value(value), error (errorBehavior), visitedBlocks(visitedBlocks ),
79
+ leakingBlocks (leakingBlocks) {}
81
80
82
81
void initializeAllNonConsumingUses (
83
82
ArrayRef<BranchPropagatedUser> nonConsumingUsers);
@@ -115,17 +114,9 @@ struct State {
115
114
116
115
// / Depending on our initialization, either return false or call Func and
117
116
// / throw an error.
118
- bool handleError (llvm::function_ref<void ()> &&messagePrinterFunc) const {
119
- if (errorBehavior.shouldPrintMessage ()) {
120
- messagePrinterFunc ();
121
- }
122
-
123
- if (errorBehavior.shouldReturnFalse ()) {
124
- return false ;
125
- }
126
-
127
- assert (errorBehavior.shouldAssert () && " At this point, we should assert" );
128
- llvm_unreachable (" triggering standard assertion failure routine" );
117
+ bool handleError (llvm::function_ref<void ()> &&messagePrinterFunc) {
118
+ error.handleError (std::move (messagePrinterFunc));
119
+ return false ;
129
120
}
130
121
};
131
122
@@ -406,20 +397,17 @@ bool State::checkDataflowEndState(DeadEndBlocks &deBlocks) {
406
397
}
407
398
408
399
// If we are supposed to error on leaks, do so now.
409
- if (!errorBehavior.shouldReturnFalseOnLeak ()) {
410
- return handleError ([&] {
411
- llvm::errs () << " Function: '" << value->getFunction ()->getName ()
412
- << " '\n "
413
- << " Error! Found a leak due to a consuming post-dominance "
414
- " failure!\n "
415
- << " Value: " << *value
416
- << " Post Dominating Failure Blocks:\n " ;
417
- for (auto *succBlock : successorBlocksThatMustBeVisited) {
418
- llvm::errs () << " bb" << succBlock->getDebugID ();
419
- }
420
- llvm::errs () << ' \n ' ;
421
- });
422
- }
400
+ error.handleLeakError ([&] {
401
+ llvm::errs () << " Function: '" << value->getFunction ()->getName () << " '\n "
402
+ << " Error! Found a leak due to a consuming post-dominance "
403
+ " failure!\n "
404
+ << " Value: " << *value
405
+ << " Post Dominating Failure Blocks:\n " ;
406
+ for (auto *succBlock : successorBlocksThatMustBeVisited) {
407
+ llvm::errs () << " bb" << succBlock->getDebugID ();
408
+ }
409
+ llvm::errs () << ' \n ' ;
410
+ });
423
411
424
412
// Otherwise... see if we have any other failures. This signals the user
425
413
// wants us to tell it where to insert compensating destroys.
@@ -461,7 +449,7 @@ bool State::checkDataflowEndState(DeadEndBlocks &deBlocks) {
461
449
// Top Level Entrypoints
462
450
// ===----------------------------------------------------------------------===//
463
451
464
- bool swift::valueHasLinearLifetime (
452
+ LinearLifetimeError swift::valueHasLinearLifetime (
465
453
SILValue value, ArrayRef<BranchPropagatedUser> consumingUses,
466
454
ArrayRef<BranchPropagatedUser> nonConsumingUses,
467
455
SmallPtrSetImpl<SILBasicBlock *> &visitedBlocks, DeadEndBlocks &deBlocks,
@@ -496,7 +484,7 @@ bool swift::valueHasLinearLifetime(
496
484
// have been detected by initializing our consuming uses. So we are done.
497
485
if (consumingUses.size () == 1 &&
498
486
consumingUses[0 ].getParent () == value->getParentBlock ()) {
499
- return true ;
487
+ return state. error ;
500
488
}
501
489
502
490
// Ok, we may have multiple consuming uses. Add the user block of each of our
@@ -517,7 +505,7 @@ bool swift::valueHasLinearLifetime(
517
505
// Make sure that the predecessor is not in our blocksWithConsumingUses
518
506
// list.
519
507
if (state.checkPredsForDoubleConsume (user, predBlock)) {
520
- return state.handleError ([] {}) ;
508
+ return state.error ;
521
509
}
522
510
523
511
if (!state.visitedBlocks .insert (predBlock).second )
@@ -528,9 +516,10 @@ bool swift::valueHasLinearLifetime(
528
516
// Now that our algorithm is completely prepared, run the
529
517
// dataflow... If we find a failure, return false.
530
518
if (!state.performDataflow (deBlocks))
531
- return false ;
519
+ return state. error ;
532
520
533
521
// ...and then check that the end state shows that we have a valid linear
534
522
// typed value.
535
- return state.checkDataflowEndState (deBlocks);
523
+ state.checkDataflowEndState (deBlocks);
524
+ return state.error ;
536
525
}
0 commit comments