Repository: apple/swift
File: lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp (C++)

Code before:
  // If the self.init() or super.init() call threw an error and
  // we caught it, self is no longer available.
  if (TheMemory.isNonRootClassSelf()) {
    if (getSelfInitializedAtInst(Use.Inst) != DIKind::Yes) {
      auto SelfLiveness =
          getLivenessAtInst(Use.Inst, 0, TheMemory.getNumElements());
      if (SelfLiveness.isAllYes()) {
        if (FailedSelfUse) *FailedSelfUse = true;
        return false;
      }
    }
  }

  return true;
}

//===----------------------------------------------------------------------===//
//                           Top Level Driver
//===----------------------------------------------------------------------===//

static void processMemoryObject(MarkUninitializedInst *I,
                                BlockStates &blockStates) {
  LLVM_DEBUG(llvm::dbgs() << "*** Definite Init looking at: " << *I << "\n");
  DIMemoryObjectInfo MemInfo(I);

  if (I->getType().isTuple() && I->getType().isEmpty(*I->getFunction())) {
    return;
  }

  // Set up the datastructure used to collect the uses of the allocation.
  DIElementUseInfo UseInfo;

  // Walk the use list of the pointer, collecting them into the Uses array.
  collectDIElementUsesFrom(MemInfo, UseInfo);

  LifetimeChecker(MemInfo, UseInfo, blockStates).doIt();
}

/// Check that all memory objects that require initialization before use are
/// properly set and transform the code as required for flow-sensitive
/// properties.
static bool checkDefiniteInitialization(SILFunction &Fn) {
  FrontendStatsTracer StatsTracer(Fn.getModule().getASTContext().Stats,
                                  "definite-init", &Fn);

  LLVM_DEBUG(llvm::dbgs() << "*** Definite Init visiting function: "
                          <<  Fn.getName() << "\n");
  bool Changed = false;

  BlockStates blockStates(&Fn);


Review comment (bug):
I don't think this is right either, because now we'll bail out if you have a two-element tuple where both elements are empty structs, no? I think the right fix is to address the root cause of the crash. DI already explodes tuples recursively, so whatever is making it fall over in the empty case should be fixed at the point where it happens.

Code after:

  // If the self.init() or super.init() call threw an error and
  // we caught it, self is no longer available.
  if (TheMemory.isNonRootClassSelf()) {
    if (getSelfInitializedAtInst(Use.Inst) != DIKind::Yes) {
      auto SelfLiveness =
          getLivenessAtInst(Use.Inst, 0, TheMemory.getNumElements());
      if (SelfLiveness.isAllYes()) {
        if (FailedSelfUse) *FailedSelfUse = true;
        return false;
      }
    }
  }

  return true;
}

//===----------------------------------------------------------------------===//
//                           Top Level Driver
//===----------------------------------------------------------------------===//

static void processMemoryObject(MarkUninitializedInst *I,
                                BlockStates &blockStates) {
  LLVM_DEBUG(llvm::dbgs() << "*** Definite Init looking at: " << *I << "\n");
  DIMemoryObjectInfo MemInfo(I);

  // Set up the datastructure used to collect the uses of the allocation.
  DIElementUseInfo UseInfo;

  // Walk the use list of the pointer, collecting them into the Uses array.
  collectDIElementUsesFrom(MemInfo, UseInfo);

  LifetimeChecker(MemInfo, UseInfo, blockStates).doIt();
}

/// Check that all memory objects that require initialization before use are
/// properly set and transform the code as required for flow-sensitive
/// properties.
static bool checkDefiniteInitialization(SILFunction &Fn) {
  FrontendStatsTracer StatsTracer(Fn.getModule().getASTContext().Stats,
                                  "definite-init", &Fn);

  LLVM_DEBUG(llvm::dbgs() << "*** Definite Init visiting function: "
                          <<  Fn.getName() << "\n");
  bool Changed = false;

  BlockStates blockStates(&Fn);

  for (auto &BB : Fn) {
    for (SILInstruction &inst : BB) {
      if (auto *MUI = dyn_cast<MarkUninitializedInst>(&inst)) {