]> Cypherpunks repositories - gostls13.git/commitdiff
reflect: StructOf set abi.TFlagRegularMemory
authorqiulaidongfeng <2645477756@qq.com>
Sat, 6 Jan 2024 07:25:05 +0000 (07:25 +0000)
committerKeith Randall <khr@golang.org>
Tue, 23 Jan 2024 00:36:00 +0000 (00:36 +0000)
Complete a TODO.

Change-Id: I791d27266ccee69c371524e298120765f5736cf8
GitHub-Last-Rev: 8878003efa2f9f3d8609b88073c982d21ece774b
GitHub-Pull-Request: golang/go#64617
Reviewed-on: https://go-review.googlesource.com/c/go/+/548435
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
src/reflect/export_test.go
src/reflect/type.go
src/reflect/type_test.go

index 1648eb362490ce090d0f694063fc9ab64ec8adad..55eb50a425f6f696e9a618c8804d241ff2826993 100644 (file)
@@ -166,3 +166,5 @@ func SetArgRegs(ints, floats int, floatSize uintptr) (oldInts, oldFloats int, ol
 var MethodValueCallCodePtr = methodValueCallCodePtr
 
 var InternalIsZero = isZero
+
+var IsRegularMemory = isRegularMemory
index 89c50155302346e42b29f2f50aa23dcd3821c960..dfa2ff6ddf61f36e63d9fe3b768ba16c5e7d9d47 100644 (file)
@@ -2152,6 +2152,47 @@ func isValidFieldName(fieldName string) bool {
        return len(fieldName) > 0
 }
 
+// This must match cmd/compile/internal/compare.IsRegularMemory
+func isRegularMemory(t Type) bool {
+       switch t.Kind() {
+       case Array:
+               return isRegularMemory(t.Elem())
+       case Int8, Int16, Int32, Int64, Int, Uint8, Uint16, Uint32, Uint64, Uint, Uintptr, Chan, Pointer, Bool, UnsafePointer:
+               return true
+       case Struct:
+               num := t.NumField()
+               switch num {
+               case 0:
+                       return true
+               case 1:
+                       field := t.Field(0)
+                       if field.Name == "_" {
+                               return false
+                       }
+                       return isRegularMemory(field.Type)
+               default:
+                       for i := range num {
+                               field := t.Field(i)
+                               if field.Name == "_" || !isRegularMemory(field.Type) || isPaddedField(t, i) {
+                                       return false
+                               }
+                       }
+                       return true
+               }
+       }
+       return false
+}
+
+// isPaddedField reports whether the i'th field of struct type t is followed
+// by padding.
+func isPaddedField(t Type, i int) bool {
+       field := t.Field(i)
+       if i+1 < t.NumField() {
+               return field.Offset+field.Type.Size() != t.Field(i+1).Offset
+       }
+       return field.Offset+field.Type.Size() != t.Size()
+}
+
 // StructOf returns the struct type containing fields.
 // The Offset and Index fields are ignored and computed as they would be
 // by the compiler.
@@ -2445,7 +2486,11 @@ func StructOf(fields []StructField) Type {
        }
 
        typ.Str = resolveReflectName(newName(str, "", false, false))
-       typ.TFlag = 0 // TODO: set tflagRegularMemory
+       if isRegularMemory(toType(&typ.Type)) {
+               typ.TFlag = abi.TFlagRegularMemory
+       } else {
+               typ.TFlag = 0
+       }
        typ.Hash = hash
        typ.Size_ = size
        typ.PtrBytes = typeptrdata(&typ.Type)
index 9e124273a2e0b50320e06f27162f941c695b9105..d53bbe553dcc27c250db4c23f04161a386d54e52 100644 (file)
@@ -57,3 +57,46 @@ func TestStructOfEmbeddedIfaceMethodCall(t *testing.T) {
                _ = x.Name()
        })
 }
+
+func TestIsRegularMemory(t *testing.T) {
+       type args struct {
+               t reflect.Type
+       }
+       type S struct {
+               int
+       }
+       tests := []struct {
+               name string
+               args args
+               want bool
+       }{
+               {"struct{i int}", args{reflect.TypeOf(struct{ i int }{})}, true},
+               {"struct{}", args{reflect.TypeOf(struct{}{})}, true},
+               {"struct{i int; s S}", args{reflect.TypeOf(struct {
+                       i int
+                       s S
+               }{})}, true},
+               {"map[int][int]", args{reflect.TypeOf(map[int]int{})}, false},
+               {"[4]chan int", args{reflect.TypeOf([4]chan int{})}, true},
+               {"struct{i int; _ S}", args{reflect.TypeOf(struct {
+                       i int
+                       _ S
+               }{})}, false},
+               {"struct{a int16; b int32}", args{reflect.TypeOf(struct {
+                       a int16
+                       b int32
+               }{})}, false},
+               {"struct {x int32; y int16}", args{reflect.TypeOf(struct {
+                       x int32
+                       y int16
+               }{})}, false},
+               {"struct {_ int32 }", args{reflect.TypeOf(struct{ _ int32 }{})}, false},
+       }
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       if got := reflect.IsRegularMemory(tt.args.t); got != tt.want {
+                               t.Errorf("isRegularMemory() = %v, want %v", got, tt.want)
+                       }
+               })
+       }
+}