作者:pombredann
项目:go.tool
// isValuePreserving returns true if a conversion from ut_src to
// ut_dst is value-preserving, i.e. just a change of type.
// Precondition: neither argument is a named type.
//
func isValuePreserving(ut_src, ut_dst types.Type) bool {
// Identical underlying types?
if types.IsIdentical(ut_dst, ut_src) {
return true
}
switch ut_dst.(type) {
case *types.Chan:
// Conversion between channel types?
_, ok := ut_src.(*types.Chan)
return ok
case *types.Pointer:
// Conversion between pointers with identical base types?
_, ok := ut_src.(*types.Pointer)
return ok
case *types.Signature:
// Conversion between f(T) function and (T) func f() method?
// TODO(adonovan): is this sound? Discuss with gri.
_, ok := ut_src.(*types.Signature)
return ok
}
return false
}
作者:nagyistg
项目:hm-workspac
func checkVarValue(t *testing.T, prog *ssa.Program, pkg *ssa.Package, ref []ast.Node, obj *types.Var, expKind string, wantAddr bool) {
// The prefix of all assertions messages.
prefix := fmt.Sprintf("VarValue(%s @ L%d)",
obj, prog.Fset.Position(ref[0].Pos()).Line)
v := prog.VarValue(obj, pkg, ref)
// Kind is the concrete type of the ssa Value.
gotKind := "nil"
if v != nil {
gotKind = fmt.Sprintf("%T", v)[len("*ssa."):]
}
// fmt.Printf("%s = %v (kind %q; expect %q) addr=%t\n", prefix, v, gotKind, expKind, wantAddr) // debugging
// Check the kinds match.
// "nil" indicates expected failure (e.g. optimized away).
if expKind != gotKind {
t.Errorf("%s concrete type == %s, want %s", prefix, gotKind, expKind)
}
// Check the types match.
// If wantAddr, the expected type is the object's address.
if v != nil {
expType := obj.Type()
if wantAddr {
expType = types.NewPointer(expType)
}
if !types.IsIdentical(v.Type(), expType) {
t.Errorf("%s.Type() == %s, want %s", prefix, v.Type(), expType)
}
}
}
作者:amulya
项目:bosh-cloudstack-cp
// Set sets the map entry for key to val,
// and returns the previous entry, if any.
func (m *M) Set(key types.Type, value interface{}) (prev interface{}) {
if m.table != nil {
hash := m.hasher.Hash(key)
bucket := m.table[hash]
var hole *entry
for i, e := range bucket {
if e.key == nil {
hole = &bucket[i]
} else if types.IsIdentical(key, e.key) {
prev = e.value
bucket[i].value = value
return
}
}
if hole != nil {
*hole = entry{key, value} // overwrite deleted entry
} else {
m.table[hash] = append(bucket, entry{key, value})
}
} else {
if m.hasher.memo == nil {
m.hasher = MakeHasher()
}
hash := m.hasher.Hash(key)
m.table = map[uint32][]entry{hash: {entry{key, value}}}
}
m.length++
return
}
作者:Bosh-for-Cp
项目:bosh-260
// typeAssert checks whether dynamic type of itf is instr.AssertedType.
// It returns the extracted value on success, and panics on failure,
// unless instr.CommaOk, in which case it always returns a "value,ok" tuple.
//
func typeAssert(i *interpreter, instr *ssa.TypeAssert, itf iface) value {
var v value
err := ""
if itf.t == nil {
err = fmt.Sprintf("interface conversion: interface is nil, not %s", instr.AssertedType)
} else if idst, ok := instr.AssertedType.Underlying().(*types.Interface); ok {
v = itf
err = checkInterface(i, idst, itf)
} else if types.IsIdentical(itf.t, instr.AssertedType) {
v = copyVal(itf.v) // extract value
} else {
err = fmt.Sprintf("interface conversion: interface is %s, not %s", itf.t, instr.AssertedType)
}
if err != "" {
if !instr.CommaOk {
panic(err)
}
return tuple{zero(instr.AssertedType), false}
}
if instr.CommaOk {
return tuple{v, true}
}
return v
}
作者:nagyistg
项目:hm-workspac
func (c *typeAssertConstraint) solve(a *analysis, n *node, delta nodeset) {
tIface, _ := c.typ.Underlying().(*types.Interface)
for ifaceObj := range delta {
tDyn, v, indirect := a.taggedValue(ifaceObj)
if tDyn == nil {
panic("not a tagged value")
}
if indirect {
// TODO(adonovan): we'll need to implement this
// when we start creating indirect tagged objects.
panic("indirect tagged object")
}
if tIface != nil {
if types.IsAssignableTo(tDyn, tIface) {
if a.addLabel(c.dst, ifaceObj) {
a.addWork(c.dst)
}
}
} else {
if types.IsIdentical(tDyn, c.typ) {
// Copy entire payload to dst.
//
// TODO(adonovan): opt: if tConc is
// nonpointerlike we can skip this
// entire constraint, perhaps. We
// only care about pointers among the
// fields.
a.onlineCopyN(c.dst, v, a.sizeof(tDyn))
}
}
}
}
作者:pombredann
项目:go.tool
// emitConv emits to f code to convert Value val to exactly type typ,
// and returns the converted value. Implicit conversions are required
// by language assignability rules in assignments, parameter passing,
// etc.
//
func emitConv(f *Function, val Value, typ types.Type) Value {
t_src := val.Type()
// Identical types? Conversion is a no-op.
if types.IsIdentical(t_src, typ) {
return val
}
ut_dst := typ.Underlying()
ut_src := t_src.Underlying()
// Just a change of type, but not value or representation?
if isValuePreserving(ut_src, ut_dst) {
c := &ChangeType{X: val}
c.setType(typ)
return f.emit(c)
}
// Conversion to, or construction of a value of, an interface type?
if _, ok := ut_dst.(*types.Interface); ok {
// Assignment from one interface type to another?
if _, ok := ut_src.(*types.Interface); ok {
return emitTypeAssert(f, val, typ)
}
// Untyped nil literal? Return interface-typed nil literal.
if ut_src == tUntypedNil {
return nilLiteral(typ)
}
// Convert (non-nil) "untyped" literals to their default type.
// TODO(gri): expose types.isUntyped().
if t, ok := ut_src.(*types.Basic); ok && t.Info()&types.IsUntyped != 0 {
val = emitConv(f, val, DefaultType(ut_src))
}
mi := &MakeInterface{
X: val,
Methods: f.Prog.MethodSet(t_src),
}
mi.setType(typ)
return f.emit(mi)
}
// Conversion of a literal to a non-interface type results in
// a new literal of the destination type and (initially) the
// same abstract value. We don't compute the representation
// change yet; this defers the point at which the number of
// possible representations explodes.
if l, ok := val.(*Literal); ok {
return newLiteral(l.Value, typ)
}
// A representation-changing conversion.
c := &Convert{X: val}
c.setType(typ)
return f.emit(c)
}
作者:Bosh-for-Cp
项目:bosh-260
func checkEqualButNotIdentical(t *testing.T, x, y types.Type, comment string) {
if !types.IsIdentical(x, y) {
t.Errorf("%s: not equal: %s, %s", comment, x, y)
}
if x == y {
t.Errorf("%s: identical: %p, %p", comment, x, y)
}
}
作者:amulya
项目:bosh-cloudstack-cp
// At returns the map entry for the given key.
// The result is nil if the entry is not present.
//
func (m *M) At(key types.Type) interface{} {
if m != nil && m.table != nil {
for _, e := range m.table[m.hasher.Hash(key)] {
if e.key != nil && types.IsIdentical(key, e.key) {
return e.value
}
}
}
return nil
}
作者:nagyistg
项目:hm-workspac
// testMainSlice emits to fn code to construct a slice of type slice
// (one of []testing.Internal{Test,Benchmark,Example}) for all
// functions in this package whose name starts with prefix (one of
// "Test", "Benchmark" or "Example") and whose type is appropriate.
// It returns the slice value.
//
func testMainSlice(fn *Function, prefix string, slice types.Type) Value {
tElem := slice.(*types.Slice).Elem()
tFunc := tElem.Underlying().(*types.Struct).Field(1).Type()
var testfuncs []*Function
for name, mem := range fn.Pkg.Members {
if fn, ok := mem.(*Function); ok && isTest(name, prefix) && types.IsIdentical(fn.Signature, tFunc) {
testfuncs = append(testfuncs, fn)
}
}
if testfuncs == nil {
return nilConst(slice)
}
tString := types.Typ[types.String]
tPtrString := types.NewPointer(tString)
tPtrElem := types.NewPointer(tElem)
tPtrFunc := types.NewPointer(tFunc)
// Emit: array = new [n]testing.InternalTest
tArray := types.NewArray(tElem, int64(len(testfuncs)))
array := emitNew(fn, tArray, token.NoPos)
array.Comment = "test main"
for i, testfunc := range testfuncs {
// Emit: pitem = &array[i]
ia := &IndexAddr{X: array, Index: intConst(int64(i))}
ia.setType(tPtrElem)
pitem := fn.emit(ia)
// Emit: pname = &pitem.Name
fa := &FieldAddr{X: pitem, Field: 0} // .Name
fa.setType(tPtrString)
pname := fn.emit(fa)
// Emit: *pname = "testfunc"
emitStore(fn, pname, NewConst(exact.MakeString(testfunc.Name()), tString))
// Emit: pfunc = &pitem.F
fa = &FieldAddr{X: pitem, Field: 1} // .F
fa.setType(tPtrFunc)
pfunc := fn.emit(fa)
// Emit: *pfunc = testfunc
emitStore(fn, pfunc, testfunc)
}
// Emit: slice array[:]
sl := &Slice{X: array}
sl.setType(slice)
return fn.emit(sl)
}
作者:amulya
项目:bosh-cloudstack-cp
// Delete removes the entry with the given key, if any.
// It returns true if the entry was found.
//
func (m *M) Delete(key types.Type) bool {
if m != nil && m.table != nil {
hash := m.hasher.Hash(key)
bucket := m.table[hash]
for i, e := range bucket {
if e.key != nil && types.IsIdentical(key, e.key) {
// We can't compact the bucket as it
// would disturb iterators.
bucket[i] = entry{}
m.length--
return true
}
}
}
return false
}
作者:amulya
项目:bosh-cloudstack-cp
func checkFuncValue(t *testing.T, prog *ssa.Program, obj *types.Func) {
fn := prog.FuncValue(obj)
// fmt.Printf("FuncValue(%s) = %s\n", obj, fn) // debugging
if fn == nil {
t.Errorf("FuncValue(%s) == nil", obj)
return
}
if fnobj := fn.Object(); fnobj != obj {
t.Errorf("FuncValue(%s).Object() == %s; value was %s",
obj, fnobj, fn.Name())
return
}
if !types.IsIdentical(fn.Type(), obj.Type()) {
t.Errorf("FuncValue(%s).Type() == %s", obj, fn.Type())
return
}
}
作者:ufo2294026
项目:two-server-other
func (c *rVSetBytesConstraint) solve(a *analysis, _ *node, delta nodeset) {
for vObj := range delta {
tDyn, slice, indirect := a.taggedValue(vObj)
if indirect {
// TODO(adonovan): we'll need to implement this
// when we start creating indirect tagged objects.
panic("indirect tagged object")
}
tSlice, ok := tDyn.Underlying().(*types.Slice)
if ok && types.IsIdentical(tSlice.Elem(), types.Typ[types.Uint8]) {
if a.onlineCopy(slice, c.x) {
a.addWork(slice)
}
}
}
}
作者:pombredann
项目:go.tool
// emitTypeAssert emits to f a type assertion value := x.(t) and
// returns the value. x.Type() must be an interface.
//
func emitTypeAssert(f *Function, x Value, t types.Type) Value {
// Simplify infallible assertions.
txi := x.Type().Underlying().(*types.Interface)
if ti, ok := t.Underlying().(*types.Interface); ok {
if types.IsIdentical(ti, txi) {
return x
}
if isSuperinterface(ti, txi) {
c := &ChangeInterface{X: x}
c.setType(t)
return f.emit(c)
}
}
a := &TypeAssert{X: x, AssertedType: t}
a.setType(t)
return f.emit(a)
}
作者:ufo2294026
项目:two-server-other
// isErrorMethodCall reports whether the call is of a method with signature
// func Error() string
// where "string" is the universe's string type. We know the method is called "Error".
func (f *File) isErrorMethodCall(call *ast.CallExpr) bool {
typ := f.pkg.types[call]
if typ != nil {
// We know it's called "Error", so just check the function signature.
return types.IsIdentical(f.pkg.types[call.Fun], stringerMethodType)
}
// Without types, we can still check by hand.
// Is it a selector expression? Otherwise it's a function call, not a method call.
sel, ok := call.Fun.(*ast.SelectorExpr)
if !ok {
return false
}
// The package is type-checked, so if there are no arguments, we're done.
if len(call.Args) > 0 {
return false
}
// Check the type of the method declaration
typ = f.pkg.types[sel]
if typ == nil {
return false
}
// The type must be a signature, but be sure for safety.
sig, ok := typ.(*types.Signature)
if !ok {
return false
}
// There must be a receiver for it to be a method call. Otherwise it is
// a function, not something that satisfies the error interface.
if sig.Recv() == nil {
return false
}
// There must be no arguments. Already verified by type checking, but be thorough.
if sig.Params().Len() > 0 {
return false
}
// Finally the real questions.
// There must be one result.
if sig.Results().Len() != 1 {
return false
}
// It must have return type "string" from the universe.
return sig.Results().At(0).Type() == types.Typ[types.String]
}
作者:amulya
项目:bosh-cloudstack-cp
func checkConstValue(t *testing.T, prog *ssa.Program, obj *types.Const) {
c := prog.ConstValue(obj)
// fmt.Printf("ConstValue(%s) = %s\n", obj, c) // debugging
if c == nil {
t.Errorf("ConstValue(%s) == nil", obj)
return
}
if !types.IsIdentical(c.Type(), obj.Type()) {
t.Errorf("ConstValue(%s).Type() == %s", obj, c.Type())
return
}
if obj.Name() != "nil" {
if !exact.Compare(c.Value, token.EQL, obj.Val()) {
t.Errorf("ConstValue(%s).Value (%s) != %s",
obj, c.Value, obj.Val())
return
}
}
}
作者:pombredann
项目:go.tool
// isSuperinterface returns true if x is a superinterface of y,
// i.e. x's methods are a subset of y's.
//
func isSuperinterface(x, y *types.Interface) bool {
if y.NumMethods() < x.NumMethods() {
return false
}
// TODO(adonovan): opt: this is quadratic.
outer:
for i, n := 0, x.NumMethods(); i < n; i++ {
xm := x.Method(i)
for j, m := 0, y.NumMethods(); j < m; j++ {
ym := y.Method(j)
if MakeId(xm.Name(), xm.Pkg()) == MakeId(ym.Name(), ym.Pkg()) {
if !types.IsIdentical(xm.Type(), ym.Type()) {
return false // common name but conflicting types
}
continue outer
}
}
return false // y doesn't have this method
}
return true
}
作者:nagyistg
项目:hm-workspac
// emitCompare emits to f code compute the boolean result of
// comparison comparison 'x op y'.
//
func emitCompare(f *Function, op token.Token, x, y Value, pos token.Pos) Value {
xt := x.Type().Underlying()
yt := y.Type().Underlying()
// Special case to optimise a tagless SwitchStmt so that
// these are equivalent
// switch { case e: ...}
// switch true { case e: ... }
// if e==true { ... }
// even in the case when e's type is an interface.
// TODO(adonovan): opt: generalise to x==true, false!=y, etc.
if x == vTrue && op == token.EQL {
if yt, ok := yt.(*types.Basic); ok && yt.Info()&types.IsBoolean != 0 {
return y
}
}
if types.IsIdentical(xt, yt) {
// no conversion necessary
} else if _, ok := xt.(*types.Interface); ok {
y = emitConv(f, y, x.Type())
} else if _, ok := yt.(*types.Interface); ok {
x = emitConv(f, x, y.Type())
} else if _, ok := x.(*Const); ok {
x = emitConv(f, x, y.Type())
} else if _, ok := y.(*Const); ok {
y = emitConv(f, y, x.Type())
} else {
// other cases, e.g. channels. No-op.
}
v := &BinOp{
Op: op,
X: x,
Y: y,
}
v.setPos(pos)
v.setType(tBool)
return f.emit(v)
}
作者:Bosh-for-Cp
项目:bosh-260
// checkShadowing checks whether the identifier shadows an identifier in an outer scope.
func (f *File) checkShadowing(ident *ast.Ident) {
obj := f.pkg.idents[ident]
if obj == nil {
return
}
// obj.Parent.Parent is the surrounding scope. If we can find another declaration
// starting from there, we have a shadowed variable.
shadowed := obj.Parent().Parent().LookupParent(obj.Name())
if shadowed == nil {
return
}
// Don't complain if it's shadowing a universe-declared variable; that's fine.
if shadowed.Parent() == types.Universe {
return
}
if *strictShadowing {
// The shadowed variable must appear before this one to be an instance of shadowing.
if shadowed.Pos() > ident.Pos() {
return
}
} else {
// Don't complain if the span of validity of the shadowed variable doesn't include
// the shadowing variable.
span, ok := f.pkg.spans[shadowed]
if !ok {
f.Badf(ident.Pos(), "internal error: no range for %s", ident.Name)
return
}
if !span.contains(ident.Pos()) {
return
}
}
// Don't complain if the types differ: that implies the programmer really wants two variables.
if types.IsIdentical(obj.Type(), shadowed.Type()) {
f.Badf(ident.Pos(), "declaration of %s shadows declaration at %s", obj.Name(), f.loc(shadowed.Pos()))
}
}
作者:qioixi
项目:llg
func (v *LLVMValue) Convert(dsttyp types.Type) Value {
b := v.compiler.builder
// If it's a stack allocated value, we'll want to compare the
// value type, not the pointer type.
srctyp := v.typ
// Get the underlying type, if any.
origdsttyp := dsttyp
dsttyp = dsttyp.Underlying()
srctyp = srctyp.Underlying()
// Identical (underlying) types? Just swap in the destination type.
if types.IsIdentical(srctyp, dsttyp) {
// A method converted to a function type without the
// receiver is where we convert a "method value" into a
// function.
if srctyp, ok := srctyp.(*types.Signature); ok && srctyp.Recv() != nil {
if dsttyp, ok := dsttyp.(*types.Signature); ok && dsttyp.Recv() == nil {
return v.convertMethodValue(origdsttyp)
}
}
// TODO avoid load here by reusing pointer value, if exists.
return v.compiler.NewValue(v.LLVMValue(), origdsttyp)
}
// Both pointer types with identical underlying types? Same as above.
if srctyp, ok := srctyp.(*types.Pointer); ok {
if dsttyp, ok := dsttyp.(*types.Pointer); ok {
srctyp := srctyp.Elem().Underlying()
dsttyp := dsttyp.Elem().Underlying()
if types.IsIdentical(srctyp, dsttyp) {
return v.compiler.NewValue(v.LLVMValue(), origdsttyp)
}
}
}
// Convert from an interface type.
if _, isinterface := srctyp.(*types.Interface); isinterface {
if interface_, isinterface := dsttyp.(*types.Interface); isinterface {
return v.mustConvertI2I(interface_)
} else {
return v.mustConvertI2V(origdsttyp)
}
}
// Converting to an interface type.
if interface_, isinterface := dsttyp.(*types.Interface); isinterface {
return v.convertV2I(interface_)
}
byteslice := types.NewSlice(types.Typ[types.Byte])
runeslice := types.NewSlice(types.Typ[types.Rune])
// string ->
if isString(srctyp) {
// (untyped) string -> string
// XXX should untyped strings be able to escape go/types?
if isString(dsttyp) {
return v.compiler.NewValue(v.LLVMValue(), origdsttyp)
}
// string -> []byte
if types.IsIdentical(dsttyp, byteslice) {
c := v.compiler
value := v.LLVMValue()
strdata := c.builder.CreateExtractValue(value, 0, "")
strlen := c.builder.CreateExtractValue(value, 1, "")
// Data must be copied, to prevent changes in
// the byte slice from mutating the string.
newdata := c.builder.CreateArrayMalloc(strdata.Type().ElementType(), strlen, "")
memcpy := c.NamedFunction("runtime.memcpy", "func(uintptr, uintptr, uintptr)")
c.builder.CreateCall(memcpy, []llvm.Value{
c.builder.CreatePtrToInt(newdata, c.target.IntPtrType(), ""),
c.builder.CreatePtrToInt(strdata, c.target.IntPtrType(), ""),
strlen,
}, "")
strdata = newdata
struct_ := llvm.Undef(c.types.ToLLVM(byteslice))
struct_ = c.builder.CreateInsertValue(struct_, strdata, 0, "")
struct_ = c.builder.CreateInsertValue(struct_, strlen, 1, "")
struct_ = c.builder.CreateInsertValue(struct_, strlen, 2, "")
return c.NewValue(struct_, byteslice)
}
// string -> []rune
if types.IsIdentical(dsttyp, runeslice) {
return v.stringToRuneSlice()
}
}
// []byte -> string
if types.IsIdentical(srctyp, byteslice) && isString(dsttyp) {
c := v.compiler
value := v.LLVMValue()
data := c.builder.CreateExtractValue(value, 0, "")
len := c.builder.CreateExtractValue(value, 1, "")
//.........这里部分代码省略.........
作者:amulya
项目:bosh-cloudstack-cp
// nil-tolerant variant of types.IsIdentical.
func sameType(x, y types.Type) bool {
if x == nil {
return y == nil
}
return y != nil && types.IsIdentical(x, y)
}