diff --git a/transform/interface-lowering.go b/transform/interface-lowering.go index d64f2731..6aa3bb13 100644 --- a/transform/interface-lowering.go +++ b/transform/interface-lowering.go @@ -616,10 +616,19 @@ func (p *lowerInterfacesPass) createInterfaceMethodFunc(itf *interfaceInfo, sign // Create entry block. entry := p.ctx.AddBasicBlock(fn, "entry") - // Create default block and make it unreachable (which it is, because all - // possible types are checked). + // Create default block and call runtime.nilPanic. + // The only other possible value remaining is nil for nil interfaces. We + // could panic with a different message here such as "nil interface" but + // that would increase code size and "nil panic" is close enough. Most + // importantly, it avoids undefined behavior when accidentally calling a + // method on a nil interface. defaultBlock := p.ctx.AddBasicBlock(fn, "default") p.builder.SetInsertPointAtEnd(defaultBlock) + nilPanic := p.mod.NamedFunction("runtime.nilPanic") + p.builder.CreateCall(nilPanic, []llvm.Value{ + llvm.Undef(llvm.PointerType(p.ctx.Int8Type(), 0)), + llvm.Undef(llvm.PointerType(p.ctx.Int8Type(), 0)), + }, "") p.builder.CreateUnreachable() // Create type switch in entry block. diff --git a/transform/testdata/interface.ll b/transform/testdata/interface.ll index ee059c95..1e2ce61b 100644 --- a/transform/testdata/interface.ll +++ b/transform/testdata/interface.ll @@ -24,6 +24,7 @@ declare void @runtime.printuint8(i8) declare void @runtime.printint32(i32) declare void @runtime.printptr(i32) declare void @runtime.printnl() +declare void @runtime.nilPanic(i8*, i8*) define void @printInterfaces() { call void @printInterface(i32 ptrtoint (%runtime.typeInInterface* @"typeInInterface:reflect/types.type:basic:int" to i32), i8* inttoptr (i32 5 to i8*)) diff --git a/transform/testdata/interface.out.ll b/transform/testdata/interface.out.ll index 80f71ee4..4bb9ec1b 100644 --- a/transform/testdata/interface.out.ll +++ b/transform/testdata/interface.out.ll @@ -25,6 +25,8 @@ declare void @runtime.printptr(i32) declare void @runtime.printnl() +declare void @runtime.nilPanic(i8*, i8*) + define void @printInterfaces() { call void @printInterface(i32 4, i8* inttoptr (i32 5 to i8*)) call void @printInterface(i32 16, i8* inttoptr (i8 120 to i8*)) @@ -83,6 +85,7 @@ entry: ] default: ; preds = %entry + call void @runtime.nilPanic(i8* undef, i8* undef) unreachable "reflect/types.type:named:Number": ; preds = %entry