Skip to content

Commit d035caf

Browse files
authored
Merge pull request #15567 from slavapestov/never-fixes
Fix various bogus unreachable code warnings
2 parents bd696c7 + 2c65f5d commit d035caf

File tree

9 files changed

+99
-8
lines changed

9 files changed

+99
-8
lines changed

include/swift/AST/Types.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3981,7 +3981,7 @@ class SILFunctionType final : public TypeBase, public llvm::FoldingSetNode,
39813981
getRepresentation() == SILFunctionTypeRepresentation::Thick;
39823982
}
39833983

3984-
bool isNoReturnFunction(); // Defined in SILType.cpp
3984+
bool isNoReturnFunction() const; // Defined in SILType.cpp
39853985

39863986
class ABICompatibilityCheckResult {
39873987
friend class SILFunctionType;

lib/SIL/SILType.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -442,8 +442,14 @@ bool SILModuleConventions::isPassedIndirectlyInSIL(SILType type, SILModule &M) {
442442
return false;
443443
}
444444

445-
bool SILFunctionType::isNoReturnFunction() {
446-
return getDirectFormalResultsType().getASTType()->isUninhabited();
445+
446+
bool SILFunctionType::isNoReturnFunction() const {
447+
for (unsigned i = 0, e = getNumResults(); i < e; ++i) {
448+
if (getResults()[i].getType()->isUninhabited())
449+
return true;
450+
}
451+
452+
return false;
447453
}
448454

449455
#ifndef NDEBUG

lib/SILGen/SILGenApply.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4272,6 +4272,9 @@ RValue SILGenFunction::emitApply(ResultPlanPtr &&resultPlan,
42724272
// Pop the argument scope.
42734273
argScope.pop();
42744274

4275+
if (substFnType->isNoReturnFunction())
4276+
loc.markAutoGenerated();
4277+
42754278
// Explode the direct results.
42764279
SILFunctionConventions substFnConv(substFnType, SGM.M);
42774280
SmallVector<ManagedValue, 4> directResults;

lib/SILGen/SILGenLValue.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,8 @@ namespace {
433433
ManagedValue base,
434434
MaterializedLValue materialized,
435435
bool isFinal) override {
436+
loc.markAutoGenerated();
437+
436438
assert(base.isLValue());
437439
SGF.B.createEndAccess(loc, base.getValue(), /*abort*/ false);
438440
}
@@ -1566,6 +1568,8 @@ namespace {
15661568
ManagedValue base,
15671569
MaterializedLValue materialized,
15681570
bool isFinal) override {
1571+
loc.markAutoGenerated();
1572+
15691573
// If this is final, we can consume the owner (stored as
15701574
// 'base'). If it isn't, we actually need to retain it, because
15711575
// we've still got a release active.

lib/SILGen/SILGenPoly.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3415,7 +3415,12 @@ void SILGenFunction::emitProtocolWitness(AbstractionPattern reqtOrigTy,
34153415
F.setBare(IsBare);
34163416

34173417
SILLocation loc(witness.getDecl());
3418-
FullExpr scope(Cleanups, CleanupLocation::get(loc));
3418+
loc.markAutoGenerated();
3419+
3420+
CleanupLocation cleanupLoc(witness.getDecl());
3421+
cleanupLoc.markAutoGenerated();
3422+
3423+
FullExpr scope(Cleanups, cleanupLoc);
34193424
FormalEvaluationScope formalEvalScope(*this);
34203425

34213426
auto witnessKind = getWitnessDispatchKind(witness);
@@ -3491,7 +3496,7 @@ void SILGenFunction::emitProtocolWitness(AbstractionPattern reqtOrigTy,
34913496
SILValue reqtResultValue = resultPlanner.execute(witnessResultValue);
34923497

34933498
scope.pop();
3494-
B.createReturn(CleanupLocation::get(loc), reqtResultValue);
3499+
B.createReturn(loc, reqtResultValue);
34953500
}
34963501

34973502
//===----------------------------------------------------------------------===//

lib/SILGen/SILGenStmt.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,9 @@ void StmtEmitter::visitReturnStmt(ReturnStmt *S) {
404404
if (!S->hasResult())
405405
// Void return.
406406
SGF.Cleanups.emitBranchAndCleanups(SGF.ReturnDest, Loc);
407+
else if (S->getResult()->getType()->isUninhabited())
408+
// Never return.
409+
SGF.emitIgnoredExpr(S->getResult());
407410
else
408411
SGF.emitReturnExpr(Loc, S->getResult());
409412
}

lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,20 @@ static SILInstruction *getAsCallToNoReturn(SILInstruction *I) {
423423
if (BI->getModule().isNoReturnBuiltinOrIntrinsic(BI->getName()))
424424
return BI;
425425
}
426+
427+
// These appear in accessors for stored properties with uninhabited
428+
// type. Since a type containing an uninhabited stored property is
429+
// itself uninhabited, we treat these identically to fatalError(), etc.
430+
if (auto *SEI = dyn_cast<StructExtractInst>(I)) {
431+
if (SEI->getType().getASTType()->isUninhabited())
432+
return SEI;
433+
}
434+
435+
if (auto *SEAI = dyn_cast<StructElementAddrInst>(I)) {
436+
if (SEAI->getType().getASTType()->isUninhabited())
437+
return SEAI;
438+
}
439+
426440
return nullptr;
427441
}
428442

test/SILOptimizer/specialize.sil

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -630,9 +630,7 @@ bb0:
630630
%6 = function_ref @action_thunk : $@convention(thin) (@owned @callee_owned () -> (Never, @error Error)) -> (@out Never, @error Error)
631631
%7 = partial_apply %6(%5) : $@convention(thin) (@owned @callee_owned () -> (Never, @error Error)) -> (@out Never, @error Error)
632632
%8 = apply [nothrow] %1<Never>(%2, %7) : $@convention(thin) <τ_0_0> (@owned @callee_owned () -> (@out τ_0_0, @error Error)) -> (@out τ_0_0, @error Error)
633-
dealloc_stack %2 : $*Never
634-
%12 = tuple ()
635-
return %12 : $()
633+
unreachable
636634
} // end sil function 'testGenericClosureSpecialization'
637635

638636
// Test a specialization of a self-recursive generic closure.

test/SILOptimizer/unreachable_code.swift

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,23 +330,81 @@ class FailingClass {
330330
// We should not report unreachable code inside protocol witness thunks
331331

332332
protocol Fooable {
333+
init()
333334
func foo() -> Never
334335
}
335336
struct Foo: Fooable {
337+
init() { // no-warning
338+
fatalError()
339+
}
340+
336341
func foo() -> Never { // no-warning
337342
while true {}
338343
}
339344
}
340345

341346
// We should not report unreachable code inside vtable thunks
342347
class Base {
348+
required init(x: Int) {
349+
fatalError()
350+
}
351+
343352
func foo(x: Int) -> Never {
344353
while true {}
345354
}
346355
}
347356

348357
class Derived : Base {
358+
required init(x: Int?) {
359+
fatalError()
360+
}
361+
349362
override func foo(x: Int?) -> Never {
350363
while true {}
351364
}
352365
}
366+
367+
// Inout writeback
368+
func takesInOut(value: inout SillyStruct) -> Never {
369+
while true {}
370+
}
371+
372+
struct SillyStruct {
373+
mutating func mutatingMethod() -> Never {
374+
takesInOut(value: &self)
375+
}
376+
}
377+
378+
// This triggers various problems
379+
public func genericMightBeNever<R>(
380+
_ body: () -> R) -> R {
381+
while true {}
382+
383+
}
384+
385+
func sillyGenericExample() -> Never {
386+
return genericMightBeNever {
387+
return genericMightBeNever {
388+
return fatalError()
389+
}
390+
}
391+
}
392+
393+
// https://bugs.swift.org/browse/SR-7472
394+
395+
protocol P {
396+
static var theThing: Self { get }
397+
}
398+
399+
extension Never : P {
400+
static var theThing: Never { return fatalError() }
401+
}
402+
403+
func test<T: P>(_ type: T.Type) -> T {
404+
return type.theThing
405+
}
406+
407+
func f(i: Int?) {
408+
guard i != nil else { Never.theThing }
409+
guard i != nil else { test(Never.self) }
410+
}

0 commit comments

Comments
 (0)