ssa: fix typeAssert for Nil
This commit is contained in:
85
cl/_testgo/ifaceconv/in.go
Normal file
85
cl/_testgo/ifaceconv/in.go
Normal file
@@ -0,0 +1,85 @@
|
||||
package main
|
||||
|
||||
// Tests of interface conversions and type assertions.
|
||||
|
||||
type I0 interface {
|
||||
}
|
||||
type I1 interface {
|
||||
f()
|
||||
}
|
||||
type I2 interface {
|
||||
f()
|
||||
g()
|
||||
}
|
||||
|
||||
type C0 struct{}
|
||||
type C1 struct{}
|
||||
|
||||
func (C1) f() {}
|
||||
|
||||
type C2 struct{}
|
||||
|
||||
func (C2) f() {}
|
||||
func (C2) g() {}
|
||||
|
||||
func main() {
|
||||
var i0 I0
|
||||
var i1 I1
|
||||
var i2 I2
|
||||
|
||||
// Nil always causes a type assertion to fail, even to the
|
||||
// same type.
|
||||
if _, ok := i0.(I0); ok {
|
||||
panic("nil i0.(I0) succeeded")
|
||||
}
|
||||
if _, ok := i1.(I1); ok {
|
||||
panic("nil i1.(I1) succeeded")
|
||||
}
|
||||
if _, ok := i2.(I2); ok {
|
||||
panic("nil i2.(I2) succeeded")
|
||||
}
|
||||
|
||||
// Conversions can't fail, even with nil.
|
||||
_ = I0(i0)
|
||||
|
||||
_ = I0(i1)
|
||||
_ = I1(i1)
|
||||
|
||||
_ = I0(i2)
|
||||
_ = I1(i2)
|
||||
_ = I2(i2)
|
||||
|
||||
// Non-nil type assertions pass or fail based on the concrete type.
|
||||
i1 = C1{}
|
||||
if _, ok := i1.(I0); !ok {
|
||||
panic("C1 i1.(I0) failed")
|
||||
}
|
||||
if _, ok := i1.(I1); !ok {
|
||||
panic("C1 i1.(I1) failed")
|
||||
}
|
||||
if _, ok := i1.(I2); ok {
|
||||
panic("C1 i1.(I2) succeeded")
|
||||
}
|
||||
|
||||
i1 = C2{}
|
||||
if _, ok := i1.(I0); !ok {
|
||||
panic("C2 i1.(I0) failed")
|
||||
}
|
||||
if _, ok := i1.(I1); !ok {
|
||||
panic("C2 i1.(I1) failed")
|
||||
}
|
||||
if _, ok := i1.(I2); !ok {
|
||||
panic("C2 i1.(I2) failed")
|
||||
}
|
||||
|
||||
// Conversions can't fail.
|
||||
i1 = C1{}
|
||||
if I0(i1) == nil {
|
||||
panic("C1 I0(i1) was nil")
|
||||
}
|
||||
if I1(i1) == nil {
|
||||
panic("C1 I1(i1) was nil")
|
||||
}
|
||||
|
||||
println("pass")
|
||||
}
|
||||
1290
cl/_testgo/ifaceconv/out.ll
Normal file
1290
cl/_testgo/ifaceconv/out.ll
Normal file
File diff suppressed because it is too large
Load Diff
60
cl/_testgo/ifaceprom/in.go
Normal file
60
cl/_testgo/ifaceprom/in.go
Normal file
@@ -0,0 +1,60 @@
|
||||
package main
|
||||
|
||||
// Test of promotion of methods of an interface embedded within a
|
||||
// struct. In particular, this test exercises that the correct
|
||||
// method is called.
|
||||
|
||||
type I interface {
|
||||
one() int
|
||||
two() string
|
||||
}
|
||||
|
||||
type S struct {
|
||||
I
|
||||
}
|
||||
|
||||
type impl struct{}
|
||||
|
||||
func (impl) one() int {
|
||||
return 1
|
||||
}
|
||||
|
||||
func (impl) two() string {
|
||||
return "two"
|
||||
}
|
||||
|
||||
func main() {
|
||||
var s S
|
||||
s.I = impl{}
|
||||
if one := s.I.one(); one != 1 {
|
||||
panic(one)
|
||||
}
|
||||
if one := s.one(); one != 1 {
|
||||
panic(one)
|
||||
}
|
||||
closOne := s.I.one
|
||||
if one := closOne(); one != 1 {
|
||||
panic(one)
|
||||
}
|
||||
closOne = s.one
|
||||
if one := closOne(); one != 1 {
|
||||
panic(one)
|
||||
}
|
||||
|
||||
if two := s.I.two(); two != "two" {
|
||||
panic(two)
|
||||
}
|
||||
if two := s.two(); two != "two" {
|
||||
panic(two)
|
||||
}
|
||||
closTwo := s.I.two
|
||||
if two := closTwo(); two != "two" {
|
||||
panic(two)
|
||||
}
|
||||
closTwo = s.two
|
||||
if two := closTwo(); two != "two" {
|
||||
panic(two)
|
||||
}
|
||||
|
||||
println("pass")
|
||||
}
|
||||
1050
cl/_testgo/ifaceprom/out.ll
Normal file
1050
cl/_testgo/ifaceprom/out.ll
Normal file
File diff suppressed because it is too large
Load Diff
@@ -376,90 +376,91 @@ _llgo_1: ; preds = %_llgo_0
|
||||
call void @main.invoke(%"github.com/goplus/llgo/internal/runtime.iface" %118)
|
||||
%119 = extractvalue %"github.com/goplus/llgo/internal/runtime.eface" %108, 0
|
||||
%120 = load ptr, ptr @_llgo_any, align 8
|
||||
br i1 true, label %_llgo_3, label %_llgo_4
|
||||
%121 = call i1 @"github.com/goplus/llgo/internal/runtime.Implements"(ptr %120, ptr %119)
|
||||
br i1 %121, label %_llgo_3, label %_llgo_4
|
||||
|
||||
_llgo_2: ; preds = %_llgo_0
|
||||
%121 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||
%122 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %121, i32 0, i32 0
|
||||
store ptr @32, ptr %122, align 8
|
||||
%123 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %121, i32 0, i32 1
|
||||
store i64 21, ptr %123, align 4
|
||||
%124 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %121, align 8
|
||||
%125 = load ptr, ptr @_llgo_string, align 8
|
||||
%126 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 16)
|
||||
store %"github.com/goplus/llgo/internal/runtime.String" %124, ptr %126, align 8
|
||||
%127 = alloca %"github.com/goplus/llgo/internal/runtime.eface", align 8
|
||||
%128 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %127, i32 0, i32 0
|
||||
store ptr %125, ptr %128, align 8
|
||||
%129 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %127, i32 0, i32 1
|
||||
%122 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||
%123 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %122, i32 0, i32 0
|
||||
store ptr @32, ptr %123, align 8
|
||||
%124 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %122, i32 0, i32 1
|
||||
store i64 21, ptr %124, align 4
|
||||
%125 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %122, align 8
|
||||
%126 = load ptr, ptr @_llgo_string, align 8
|
||||
%127 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 16)
|
||||
store %"github.com/goplus/llgo/internal/runtime.String" %125, ptr %127, align 8
|
||||
%128 = alloca %"github.com/goplus/llgo/internal/runtime.eface", align 8
|
||||
%129 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %128, i32 0, i32 0
|
||||
store ptr %126, ptr %129, align 8
|
||||
%130 = load %"github.com/goplus/llgo/internal/runtime.eface", ptr %127, align 8
|
||||
call void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.eface" %130)
|
||||
%130 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %128, i32 0, i32 1
|
||||
store ptr %127, ptr %130, align 8
|
||||
%131 = load %"github.com/goplus/llgo/internal/runtime.eface", ptr %128, align 8
|
||||
call void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.eface" %131)
|
||||
unreachable
|
||||
|
||||
_llgo_3: ; preds = %_llgo_1
|
||||
%131 = extractvalue %"github.com/goplus/llgo/internal/runtime.eface" %108, 1
|
||||
%132 = alloca %"github.com/goplus/llgo/internal/runtime.eface", align 8
|
||||
%133 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %132, i32 0, i32 0
|
||||
store ptr %119, ptr %133, align 8
|
||||
%134 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %132, i32 0, i32 1
|
||||
store ptr %131, ptr %134, align 8
|
||||
%135 = load %"github.com/goplus/llgo/internal/runtime.eface", ptr %132, align 8
|
||||
%136 = extractvalue %"github.com/goplus/llgo/internal/runtime.eface" %135, 0
|
||||
%137 = load ptr, ptr @"_llgo_iface$uRUteI7wmSy7y7ODhGzk0FdDaxGKMhVSSu6HZEv9aa0", align 8
|
||||
%138 = call i1 @"github.com/goplus/llgo/internal/runtime.Implements"(ptr %137, ptr %136)
|
||||
br i1 %138, label %_llgo_5, label %_llgo_6
|
||||
%132 = extractvalue %"github.com/goplus/llgo/internal/runtime.eface" %108, 1
|
||||
%133 = alloca %"github.com/goplus/llgo/internal/runtime.eface", align 8
|
||||
%134 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %133, i32 0, i32 0
|
||||
store ptr %119, ptr %134, align 8
|
||||
%135 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %133, i32 0, i32 1
|
||||
store ptr %132, ptr %135, align 8
|
||||
%136 = load %"github.com/goplus/llgo/internal/runtime.eface", ptr %133, align 8
|
||||
%137 = extractvalue %"github.com/goplus/llgo/internal/runtime.eface" %136, 0
|
||||
%138 = load ptr, ptr @"_llgo_iface$uRUteI7wmSy7y7ODhGzk0FdDaxGKMhVSSu6HZEv9aa0", align 8
|
||||
%139 = call i1 @"github.com/goplus/llgo/internal/runtime.Implements"(ptr %138, ptr %137)
|
||||
br i1 %139, label %_llgo_5, label %_llgo_6
|
||||
|
||||
_llgo_4: ; preds = %_llgo_1
|
||||
%139 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||
%140 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %139, i32 0, i32 0
|
||||
store ptr @35, ptr %140, align 8
|
||||
%141 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %139, i32 0, i32 1
|
||||
store i64 21, ptr %141, align 4
|
||||
%142 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %139, align 8
|
||||
%143 = load ptr, ptr @_llgo_string, align 8
|
||||
%144 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 16)
|
||||
store %"github.com/goplus/llgo/internal/runtime.String" %142, ptr %144, align 8
|
||||
%145 = alloca %"github.com/goplus/llgo/internal/runtime.eface", align 8
|
||||
%146 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %145, i32 0, i32 0
|
||||
store ptr %143, ptr %146, align 8
|
||||
%147 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %145, i32 0, i32 1
|
||||
%140 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||
%141 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %140, i32 0, i32 0
|
||||
store ptr @35, ptr %141, align 8
|
||||
%142 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %140, i32 0, i32 1
|
||||
store i64 21, ptr %142, align 4
|
||||
%143 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %140, align 8
|
||||
%144 = load ptr, ptr @_llgo_string, align 8
|
||||
%145 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 16)
|
||||
store %"github.com/goplus/llgo/internal/runtime.String" %143, ptr %145, align 8
|
||||
%146 = alloca %"github.com/goplus/llgo/internal/runtime.eface", align 8
|
||||
%147 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %146, i32 0, i32 0
|
||||
store ptr %144, ptr %147, align 8
|
||||
%148 = load %"github.com/goplus/llgo/internal/runtime.eface", ptr %145, align 8
|
||||
call void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.eface" %148)
|
||||
%148 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %146, i32 0, i32 1
|
||||
store ptr %145, ptr %148, align 8
|
||||
%149 = load %"github.com/goplus/llgo/internal/runtime.eface", ptr %146, align 8
|
||||
call void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.eface" %149)
|
||||
unreachable
|
||||
|
||||
_llgo_5: ; preds = %_llgo_3
|
||||
%149 = extractvalue %"github.com/goplus/llgo/internal/runtime.eface" %135, 1
|
||||
%150 = load ptr, ptr @"_llgo_iface$uRUteI7wmSy7y7ODhGzk0FdDaxGKMhVSSu6HZEv9aa0", align 8
|
||||
%151 = call ptr @"github.com/goplus/llgo/internal/runtime.NewItab"(ptr %150, ptr %136)
|
||||
%152 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8
|
||||
%153 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %152, i32 0, i32 0
|
||||
store ptr %151, ptr %153, align 8
|
||||
%154 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %152, i32 0, i32 1
|
||||
store ptr %149, ptr %154, align 8
|
||||
%155 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %152, align 8
|
||||
call void @main.invoke(%"github.com/goplus/llgo/internal/runtime.iface" %155)
|
||||
%150 = extractvalue %"github.com/goplus/llgo/internal/runtime.eface" %136, 1
|
||||
%151 = load ptr, ptr @"_llgo_iface$uRUteI7wmSy7y7ODhGzk0FdDaxGKMhVSSu6HZEv9aa0", align 8
|
||||
%152 = call ptr @"github.com/goplus/llgo/internal/runtime.NewItab"(ptr %151, ptr %137)
|
||||
%153 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8
|
||||
%154 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %153, i32 0, i32 0
|
||||
store ptr %152, ptr %154, align 8
|
||||
%155 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %153, i32 0, i32 1
|
||||
store ptr %150, ptr %155, align 8
|
||||
%156 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %153, align 8
|
||||
call void @main.invoke(%"github.com/goplus/llgo/internal/runtime.iface" %156)
|
||||
call void @main.invoke(%"github.com/goplus/llgo/internal/runtime.iface" zeroinitializer)
|
||||
ret i32 0
|
||||
|
||||
_llgo_6: ; preds = %_llgo_3
|
||||
%156 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||
%157 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %156, i32 0, i32 0
|
||||
store ptr @36, ptr %157, align 8
|
||||
%158 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %156, i32 0, i32 1
|
||||
store i64 21, ptr %158, align 4
|
||||
%159 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %156, align 8
|
||||
%160 = load ptr, ptr @_llgo_string, align 8
|
||||
%161 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 16)
|
||||
store %"github.com/goplus/llgo/internal/runtime.String" %159, ptr %161, align 8
|
||||
%162 = alloca %"github.com/goplus/llgo/internal/runtime.eface", align 8
|
||||
%163 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %162, i32 0, i32 0
|
||||
store ptr %160, ptr %163, align 8
|
||||
%164 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %162, i32 0, i32 1
|
||||
%157 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||
%158 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %157, i32 0, i32 0
|
||||
store ptr @36, ptr %158, align 8
|
||||
%159 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %157, i32 0, i32 1
|
||||
store i64 21, ptr %159, align 4
|
||||
%160 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %157, align 8
|
||||
%161 = load ptr, ptr @_llgo_string, align 8
|
||||
%162 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 16)
|
||||
store %"github.com/goplus/llgo/internal/runtime.String" %160, ptr %162, align 8
|
||||
%163 = alloca %"github.com/goplus/llgo/internal/runtime.eface", align 8
|
||||
%164 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %163, i32 0, i32 0
|
||||
store ptr %161, ptr %164, align 8
|
||||
%165 = load %"github.com/goplus/llgo/internal/runtime.eface", ptr %162, align 8
|
||||
call void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.eface" %165)
|
||||
%165 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %163, i32 0, i32 1
|
||||
store ptr %162, ptr %165, align 8
|
||||
%166 = load %"github.com/goplus/llgo/internal/runtime.eface", ptr %163, align 8
|
||||
call void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.eface" %166)
|
||||
unreachable
|
||||
}
|
||||
|
||||
|
||||
@@ -268,6 +268,9 @@ func IfacePtrData(i iface) unsafe.Pointer {
|
||||
|
||||
// Implements reports whether the type V implements the interface type T.
|
||||
func Implements(T, V *abi.Type) bool {
|
||||
if V == nil {
|
||||
return false
|
||||
}
|
||||
if T.Kind() != abi.Interface {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -238,11 +238,7 @@ func (b Builder) TypeAssert(x Expr, assertedTyp Type, commaOk bool) Expr {
|
||||
var eq Expr
|
||||
var val func() Expr
|
||||
if rawIntf, ok := assertedTyp.raw.Type.Underlying().(*types.Interface); ok {
|
||||
if rawIntf.Empty() {
|
||||
eq = b.Prog.BoolVal(true)
|
||||
} else {
|
||||
eq = b.InlineCall(b.Pkg.rtFunc("Implements"), tabi, tx)
|
||||
}
|
||||
val = func() Expr { return Expr{b.unsafeInterface(rawIntf, tx, b.faceData(x.impl)), assertedTyp} }
|
||||
} else {
|
||||
eq = b.BinOp(token.EQL, tx, tabi)
|
||||
|
||||
Reference in New Issue
Block a user