How to use getTypeDesc method of compiler Package

Best Syzkaller code snippet using compiler.getTypeDesc

check.go

Source:check.go Github

copy

Full Screen

...281 return parentName282}283func (comp *compiler) checkLenType(t0, t *ast.Type, parents []parentDesc,284 checked, warned map[string]bool, isArg bool) {285 desc := comp.getTypeDesc(t)286 if desc == typeStruct {287 s := comp.structs[t.Ident]288 // Prune recursion, can happen even on correct tree via opt pointers.289 if checked[s.Name.Name] {290 return291 }292 checked[s.Name.Name] = true293 fields := s.Fields294 if s.IsUnion {295 fields = nil296 }297 parentName := parentTargetName(s)298 parents = append(parents, parentDesc{name: parentName, fields: fields})299 for _, fld := range s.Fields {300 comp.checkLenType(fld.Type, fld.Type, parents, checked, warned, false)301 }302 warned[parentName] = true303 return304 }305 _, args, _ := comp.getArgsBase(t, isArg)306 for i, arg := range args {307 argDesc := desc.Args[i]308 if argDesc.Type == typeArgLenTarget {309 comp.checkLenTarget(arg, t0, t, parents, warned)310 } else if argDesc.Type == typeArgType {311 comp.checkLenType(t0, arg, parents, checked, warned, argDesc.IsArg)312 }313 }314}315func (comp *compiler) checkLenTarget(arg, t0, t *ast.Type, parents []parentDesc, warned map[string]bool) {316 targets := append([]*ast.Type{arg}, arg.Colon...)317 for i, target := range targets {318 if target.Ident == prog.ParentRef && len(targets) != 1 {319 comp.error(target.Pos, "%v can't be part of path expressions", prog.ParentRef)320 return321 }322 if target.Ident == prog.SyscallRef {323 if i != 0 {324 comp.error(target.Pos, "syscall can't be in the middle of path expressions")325 return326 }327 if len(targets) == 1 {328 comp.error(targets[0].Pos, "no argument name after syscall reference")329 return330 }331 }332 }333 comp.checkLenTargetRec(t0, t, targets, parents, warned)334}335func (comp *compiler) checkLenTargetRec(t0, t *ast.Type, targets []*ast.Type,336 parents []parentDesc, warned map[string]bool) {337 if len(targets) == 0 {338 return339 }340 target := targets[0]341 targets = targets[1:]342 fields := parents[len(parents)-1].fields343 for _, fld := range fields {344 if target.Ident != fld.Name.Name {345 continue346 }347 if fld.Type == t0 {348 comp.error(target.Pos, "%v target %v refers to itself", t.Ident, target.Ident)349 return350 }351 if len(targets) == 0 {352 if t.Ident == "len" {353 typ, desc := comp.derefPointers(fld.Type)354 if desc == typeArray && comp.isVarlen(typ.Args[0]) {355 // We can reach the same struct multiple times starting from different356 // syscall arguments. Warn only once.357 if !warned[parents[len(parents)-1].name] {358 comp.warning(target.Pos, "len target %v refer to an array with"+359 " variable-size elements (do you mean bytesize?)",360 target.Ident)361 }362 }363 }364 return365 }366 typ, desc := comp.derefPointers(fld.Type)367 if desc != typeStruct {368 comp.error(target.Pos, "%v path %v does not refer to a struct", t.Ident, target.Ident)369 return370 }371 s := comp.structs[typ.Ident]372 if s.IsUnion {373 comp.error(target.Pos, "%v path %v does not refer to a struct", t.Ident, target.Ident)374 return375 }376 parents = append(parents, parentDesc{name: parentTargetName(s), fields: s.Fields})377 comp.checkLenTargetRec(t0, t, targets, parents, warned)378 return379 }380 for pi := len(parents) - 1; pi >= 0; pi-- {381 parent := parents[pi]382 if parent.name != "" && (parent.name == target.Ident || target.Ident == prog.ParentRef) ||383 parent.name == "" && target.Ident == prog.SyscallRef {384 if len(targets) == 0 {385 if t.Ident == "offsetof" {386 comp.error(target.Pos, "%v must refer to fields", t.Ident)387 return388 }389 } else {390 parents1 := make([]parentDesc, pi+1)391 copy(parents1, parents[:pi+1])392 comp.checkLenTargetRec(t0, t, targets, parents1, warned)393 }394 return395 }396 }397 comp.error(target.Pos, "%v target %v does not exist", t.Ident, target.Ident)398}399func CollectUnused(desc *ast.Description, target *targets.Target, eh ast.ErrorHandler) ([]ast.Node, error) {400 comp := createCompiler(desc, target, eh)401 comp.typecheck()402 if comp.errors > 0 {403 return nil, errors.New("typecheck failed")404 }405 nodes := comp.collectUnused()406 if comp.errors > 0 {407 return nil, errors.New("collectUnused failed")408 }409 return nodes, nil410}411func (comp *compiler) collectUnused() []ast.Node {412 var unused []ast.Node413 comp.used, _, _ = comp.collectUsed(false)414 structs, flags, strflags := comp.collectUsed(true)415 note := func(n ast.Node) {416 if pos, _, _ := n.Info(); pos.Builtin() {417 return418 }419 unused = append(unused, n)420 }421 for name, n := range comp.intFlags {422 if !flags[name] {423 note(n)424 }425 }426 for name, n := range comp.strFlags {427 if !strflags[name] {428 note(n)429 }430 }431 for name, n := range comp.resources {432 if !structs[name] {433 note(n)434 }435 }436 for name, n := range comp.structs {437 if !structs[name] {438 note(n)439 }440 }441 for name, n := range comp.typedefs {442 if !comp.usedTypedefs[name] {443 note(n)444 }445 }446 return unused447}448func (comp *compiler) collectUsed(all bool) (structs, flags, strflags map[string]bool) {449 structs = make(map[string]bool)450 flags = make(map[string]bool)451 strflags = make(map[string]bool)452 for _, decl := range comp.desc.Nodes {453 switch n := decl.(type) {454 case *ast.Call:455 if !all && n.NR == ^uint64(0) {456 break457 }458 for _, arg := range n.Args {459 comp.collectUsedType(structs, flags, strflags, arg.Type, true)460 }461 if n.Ret != nil {462 comp.collectUsedType(structs, flags, strflags, n.Ret, true)463 }464 }465 }466 return467}468func (comp *compiler) collectUsedType(structs, flags, strflags map[string]bool, t *ast.Type, isArg bool) {469 desc := comp.getTypeDesc(t)470 if desc == typeResource {471 r := comp.resources[t.Ident]472 for r != nil && !structs[r.Name.Name] {473 structs[r.Name.Name] = true474 r = comp.resources[r.Base.Ident]475 }476 return477 }478 if desc == typeStruct {479 if structs[t.Ident] {480 return481 }482 structs[t.Ident] = true483 s := comp.structs[t.Ident]484 for _, fld := range s.Fields {485 comp.collectUsedType(structs, flags, strflags, fld.Type, false)486 }487 return488 }489 if desc == typeFlags {490 flags[t.Args[0].Ident] = true491 return492 }493 if desc == typeString {494 if len(t.Args) != 0 && t.Args[0].Ident != "" {495 strflags[t.Args[0].Ident] = true496 }497 return498 }499 _, args, _ := comp.getArgsBase(t, isArg)500 for i, arg := range args {501 if desc.Args[i].Type == typeArgType {502 comp.collectUsedType(structs, flags, strflags, arg, desc.Args[i].IsArg)503 }504 }505}506func (comp *compiler) checkUnused() {507 for _, n := range comp.collectUnused() {508 pos, typ, name := n.Info()509 comp.error(pos, fmt.Sprintf("unused %v %v", typ, name))510 }511}512type structDir struct {513 Struct string514 Dir prog.Dir515}516func (comp *compiler) checkConstructors() {517 ctors := make(map[string]bool) // resources for which we have ctors518 checked := make(map[structDir]bool)519 for _, decl := range comp.desc.Nodes {520 switch n := decl.(type) {521 case *ast.Call:522 for _, arg := range n.Args {523 comp.checkTypeCtors(arg.Type, prog.DirIn, true, ctors, checked)524 }525 if n.Ret != nil {526 comp.checkTypeCtors(n.Ret, prog.DirOut, true, ctors, checked)527 }528 }529 }530 for _, decl := range comp.desc.Nodes {531 switch n := decl.(type) {532 case *ast.Resource:533 name := n.Name.Name534 if !ctors[name] && comp.used[name] {535 comp.error(n.Pos, "resource %v can't be created"+536 " (never mentioned as a syscall return value or output argument/field)",537 name)538 }539 }540 }541}542func (comp *compiler) checkTypeCtors(t *ast.Type, dir prog.Dir, isArg bool,543 ctors map[string]bool, checked map[structDir]bool) {544 desc := comp.getTypeDesc(t)545 if desc == typeResource {546 // TODO(dvyukov): consider changing this to "dir == prog.DirOut".547 // We have few questionable cases where resources can be created548 // only by inout struct fields. These structs should be split549 // into two different structs: one is in and second is out.550 // But that will require attaching dir to individual fields.551 if dir != prog.DirIn {552 r := comp.resources[t.Ident]553 for r != nil && !ctors[r.Name.Name] {554 ctors[r.Name.Name] = true555 r = comp.resources[r.Base.Ident]556 }557 }558 return559 }560 if desc == typeStruct {561 s := comp.structs[t.Ident]562 name := s.Name.Name563 key := structDir{name, dir}564 if checked[key] {565 return566 }567 checked[key] = true568 for _, fld := range s.Fields {569 comp.checkTypeCtors(fld.Type, dir, false, ctors, checked)570 }571 return572 }573 if desc == typePtr {574 dir = genDir(t.Args[0])575 }576 _, args, _ := comp.getArgsBase(t, isArg)577 for i, arg := range args {578 if desc.Args[i].Type == typeArgType {579 comp.checkTypeCtors(arg, dir, desc.Args[i].IsArg, ctors, checked)580 }581 }582}583func (comp *compiler) checkRecursion() {584 checked := make(map[string]bool)585 for _, decl := range comp.desc.Nodes {586 switch n := decl.(type) {587 case *ast.Resource:588 comp.checkResourceRecursion(n)589 case *ast.Struct:590 var path []pathElem591 comp.checkStructRecursion(checked, n, path)592 }593 }594}595func (comp *compiler) checkResourceRecursion(n *ast.Resource) {596 var seen []string597 for n != nil {598 if arrayContains(seen, n.Name.Name) {599 chain := ""600 for _, r := range seen {601 chain += r + "->"602 }603 chain += n.Name.Name604 comp.error(n.Pos, "recursive resource %v", chain)605 return606 }607 seen = append(seen, n.Name.Name)608 n = comp.resources[n.Base.Ident]609 }610}611type pathElem struct {612 Pos ast.Pos613 Struct string614 Field string615}616func (comp *compiler) checkStructRecursion(checked map[string]bool, n *ast.Struct, path []pathElem) {617 name := n.Name.Name618 if checked[name] {619 return620 }621 for i, elem := range path {622 if elem.Struct != name {623 continue624 }625 path = path[i:]626 str := ""627 for _, elem := range path {628 str += fmt.Sprintf("%v.%v -> ", elem.Struct, elem.Field)629 }630 str += name631 comp.error(path[0].Pos, "recursive declaration: %v (mark some pointers as opt)", str)632 checked[name] = true633 return634 }635 for _, f := range n.Fields {636 path = append(path, pathElem{637 Pos: f.Pos,638 Struct: name,639 Field: f.Name.Name,640 })641 comp.recurseField(checked, f.Type, path)642 path = path[:len(path)-1]643 }644 checked[name] = true645}646func (comp *compiler) recurseField(checked map[string]bool, t *ast.Type, path []pathElem) {647 desc := comp.getTypeDesc(t)648 if desc == typeStruct {649 comp.checkStructRecursion(checked, comp.structs[t.Ident], path)650 return651 }652 _, args, base := comp.getArgsBase(t, false)653 if desc == typePtr && base.IsOptional {654 return // optional pointers prune recursion655 }656 for i, arg := range args {657 if desc.Args[i].Type == typeArgType {658 comp.recurseField(checked, arg, path)659 }660 }661}662func (comp *compiler) checkStruct(ctx checkCtx, n *ast.Struct) {663 var flags checkFlags664 if !n.IsUnion {665 flags |= checkIsStruct666 }667 for _, f := range n.Fields {668 comp.checkType(ctx, f.Type, flags)669 }670 comp.parseAttrs(structOrUnionAttrs(n), n, n.Attrs)671}672func (comp *compiler) checkCall(n *ast.Call) {673 for _, a := range n.Args {674 comp.checkType(checkCtx{}, a.Type, checkIsArg)675 }676 if n.Ret != nil {677 comp.checkType(checkCtx{}, n.Ret, checkIsArg|checkIsRet)678 }679 comp.parseAttrs(callAttrs, n, n.Attrs)680}681type checkFlags int682const (683 checkIsArg checkFlags = 1 << iota // immediate syscall arg type684 checkIsRet // immediate syscall ret type685 checkIsStruct // immediate struct field type686 checkIsResourceBase // immediate resource base type687 checkIsTypedef // immediate type alias/template type688)689type checkCtx struct {690 instantiationStack []string691}692func (comp *compiler) checkType(ctx checkCtx, t *ast.Type, flags checkFlags) {693 if unexpected, _, ok := checkTypeKind(t, kindIdent); !ok {694 comp.error(t.Pos, "unexpected %v, expect type", unexpected)695 return696 }697 desc := comp.getTypeDesc(t)698 if desc == nil {699 comp.error(t.Pos, "unknown type %v", t.Ident)700 return701 }702 if desc == typeTypedef {703 err0 := comp.errors704 // Replace t with type alias/template target type inplace,705 // and check the replaced type recursively.706 comp.replaceTypedef(&ctx, t, flags)707 if err0 == comp.errors {708 comp.checkType(ctx, t, flags)709 }710 return711 }712 err0 := comp.errors713 comp.checkTypeBasic(t, desc, flags)714 if err0 != comp.errors {715 return716 }717 args := comp.checkTypeArgs(t, desc, flags)718 if err0 != comp.errors {719 return720 }721 for i, arg := range args {722 if desc.Args[i].Type == typeArgType {723 var innerFlags checkFlags724 if desc.Args[i].IsArg {725 innerFlags |= checkIsArg726 }727 comp.checkType(ctx, arg, innerFlags)728 } else {729 comp.checkTypeArg(t, arg, desc.Args[i])730 }731 }732 if err0 != comp.errors {733 return734 }735 if desc.Check != nil {736 _, args, base := comp.getArgsBase(t, flags&checkIsArg != 0)737 desc.Check(comp, t, args, base)738 }739}740func (comp *compiler) checkTypeBasic(t *ast.Type, desc *typeDesc, flags checkFlags) {741 for i, col := range t.Colon {742 if i >= desc.MaxColon {743 comp.error(col.Pos, "unexpected ':'")744 return745 }746 if flags&checkIsStruct == 0 {747 comp.error(col.Pos, "unexpected ':', only struct fields can be bitfields")748 return749 }750 }751 if flags&checkIsTypedef != 0 && !desc.CanBeTypedef {752 comp.error(t.Pos, "%v can't be type alias target", t.Ident)753 return754 }755 if flags&checkIsResourceBase != 0 &&756 (desc.CanBeResourceBase == nil || !desc.CanBeResourceBase(comp, t)) {757 comp.error(t.Pos, "%v can't be resource base (int types can)", t.Ident)758 return759 }760 canBeArg, canBeRet := false, false761 if desc.CanBeArgRet != nil {762 canBeArg, canBeRet = desc.CanBeArgRet(comp, t)763 }764 if flags&checkIsRet != 0 && !canBeRet {765 comp.error(t.Pos, "%v can't be syscall return", t.Ident)766 return767 }768 if flags&checkIsArg != 0 && !canBeArg {769 comp.error(t.Pos, "%v can't be syscall argument", t.Ident)770 return771 }772}773func (comp *compiler) checkTypeArgs(t *ast.Type, desc *typeDesc, flags checkFlags) []*ast.Type {774 args, opt := removeOpt(t)775 if opt != nil {776 if len(opt.Args) != 0 {777 comp.error(opt.Pos, "opt can't have arguments")778 }779 if flags&checkIsResourceBase != 0 || desc.CantBeOpt {780 what := "resource base"781 if desc.CantBeOpt {782 what = t.Ident783 }784 comp.error(opt.Pos, "%v can't be marked as opt", what)785 return nil786 }787 }788 addArgs := 0789 needBase := flags&checkIsArg == 0 && desc.NeedBase790 if needBase {791 addArgs++ // last arg must be base type, e.g. const[0, int32]792 }793 if len(args) > len(desc.Args)+addArgs || len(args) < len(desc.Args)-desc.OptArgs+addArgs {794 comp.error(t.Pos, "wrong number of arguments for type %v, expect %v",795 t.Ident, expectedTypeArgs(desc, needBase))796 return nil797 }798 if needBase {799 base := args[len(args)-1]800 args = args[:len(args)-1]801 comp.checkTypeArg(t, base, typeArgBase)802 }803 return args804}805func (comp *compiler) replaceTypedef(ctx *checkCtx, t *ast.Type, flags checkFlags) {806 typedefName := t.Ident807 comp.usedTypedefs[typedefName] = true808 if len(t.Colon) != 0 {809 comp.error(t.Pos, "type alias %v with ':'", t.Ident)810 return811 }812 typedef := comp.typedefs[typedefName]813 // Handling optional BASE argument.814 if len(typedef.Args) > 0 && typedef.Args[len(typedef.Args)-1].Name == argBase {815 if flags&checkIsArg != 0 && len(t.Args) == len(typedef.Args)-1 {816 t.Args = append(t.Args, &ast.Type{817 Pos: t.Pos,818 Ident: "intptr",819 })820 } else if len(t.Args) == len(typedef.Args) {821 comp.checkTypeArg(t, t.Args[len(t.Args)-1], typeArgBase)822 }823 }824 fullTypeName := ast.SerializeNode(t)825 for i, prev := range ctx.instantiationStack {826 if prev == fullTypeName {827 ctx.instantiationStack = append(ctx.instantiationStack, fullTypeName)828 path := ""829 for j := i; j < len(ctx.instantiationStack); j++ {830 if j != i {831 path += " -> "832 }833 path += ctx.instantiationStack[j]834 }835 comp.error(t.Pos, "type instantiation loop: %v", path)836 return837 }838 }839 ctx.instantiationStack = append(ctx.instantiationStack, fullTypeName)840 nargs := len(typedef.Args)841 args := t.Args842 if nargs != len(t.Args) {843 if nargs == 0 {844 comp.error(t.Pos, "type %v is not a template", typedefName)845 } else {846 if flags&checkIsArg != 0 && typedef.Args[len(typedef.Args)-1].Name == argBase {847 nargs--848 }849 comp.error(t.Pos, "template %v needs %v arguments instead of %v",850 typedefName, nargs, len(t.Args))851 }852 return853 }854 pos0 := t.Pos855 if typedef.Type != nil {856 *t = *typedef.Type.Clone().(*ast.Type)857 if !comp.instantiate(t, typedef.Args, args) {858 return859 }860 } else {861 if comp.structs[fullTypeName] == nil {862 inst := typedef.Struct.Clone().(*ast.Struct)863 inst.Name.Name = fullTypeName864 if !comp.instantiate(inst, typedef.Args, args) {865 return866 }867 comp.checkStruct(*ctx, inst)868 comp.desc.Nodes = append(comp.desc.Nodes, inst)869 comp.structs[fullTypeName] = inst870 }871 *t = ast.Type{872 Ident: fullTypeName,873 }874 }875 t.Pos = pos0876 // Remove base type if it's not needed in this context.877 // If desc is nil, will return an error later when we typecheck the result.878 desc := comp.getTypeDesc(t)879 if desc != nil && flags&checkIsArg != 0 && desc.NeedBase {880 baseTypePos := len(t.Args) - 1881 if t.Args[baseTypePos].Ident == "opt" {882 baseTypePos--883 }884 copy(t.Args[baseTypePos:], t.Args[baseTypePos+1:])885 t.Args = t.Args[:len(t.Args)-1]886 }887}888func (comp *compiler) instantiate(templ ast.Node, params []*ast.Ident, args []*ast.Type) bool {889 if len(params) == 0 {890 return true891 }892 argMap := make(map[string]*ast.Type)893 for i, param := range params {894 argMap[param.Name] = args[i]895 }896 argUsed := make(map[string]bool)897 err0 := comp.errors898 ast.PostRecursive(func(n ast.Node) {899 templArg, ok := n.(*ast.Type)900 if !ok {901 return902 }903 if concreteArg := argMap[templArg.Ident]; concreteArg != nil {904 argUsed[templArg.Ident] = true905 origArgs := templArg.Args906 if len(origArgs) != 0 && len(concreteArg.Args) != 0 {907 comp.error(templArg.Pos, "both template parameter %v and its usage"+908 " have sub-arguments", templArg.Ident)909 return910 }911 *templArg = *concreteArg.Clone().(*ast.Type)912 if len(origArgs) != 0 {913 templArg.Args = origArgs914 }915 }916 // TODO(dvyukov): somewhat hacky, but required for int8[0:CONST_ARG]917 // Need more checks here. E.g. that CONST_ARG does not have subargs.918 // And if CONST_ARG is a value, then use concreteArg.Value.919 // Also need to error if CONST_ARG is a string.920 if len(templArg.Colon) != 0 {921 col := templArg.Colon[0]922 if concreteArg := argMap[col.Ident]; concreteArg != nil {923 argUsed[col.Ident] = true924 col.Ident = concreteArg.Ident925 col.Pos = concreteArg.Pos926 }927 }928 })(templ)929 for _, param := range params {930 if !argUsed[param.Name] {931 comp.error(argMap[param.Name].Pos,932 "template argument %v is not used", param.Name)933 }934 }935 return err0 == comp.errors936}937func (comp *compiler) checkTypeArg(t, arg *ast.Type, argDesc namedArg) {938 desc := argDesc.Type939 if len(desc.Names) != 0 {940 if unexpected, _, ok := checkTypeKind(arg, kindIdent); !ok {941 comp.error(arg.Pos, "unexpected %v for %v argument of %v type, expect %+v",942 unexpected, argDesc.Name, t.Ident, desc.Names)943 return944 }945 if !arrayContains(desc.Names, arg.Ident) {946 comp.error(arg.Pos, "unexpected value %v for %v argument of %v type, expect %+v",947 arg.Ident, argDesc.Name, t.Ident, desc.Names)948 return949 }950 } else {951 if unexpected, expect, ok := checkTypeKind(arg, desc.Kind); !ok {952 comp.error(arg.Pos, "unexpected %v for %v argument of %v type, expect %v",953 unexpected, argDesc.Name, t.Ident, expect)954 return955 }956 }957 for i, col := range arg.Colon {958 if i >= desc.MaxColon {959 comp.error(col.Pos, "unexpected ':'")960 return961 }962 if desc.Kind == kindIdent {963 if unexpected, expect, ok := checkTypeKind(col, kindIdent); !ok {964 comp.error(arg.Pos, "unexpected %v after colon, expect %v", unexpected, expect)965 return966 }967 }968 }969 if len(arg.Args) > desc.MaxArgs {970 comp.error(arg.Pos, "%v argument has subargs", argDesc.Name)971 return972 }973 if desc.Check != nil {974 desc.Check(comp, arg)975 }976}977func expectedTypeArgs(desc *typeDesc, needBase bool) string {978 expect := ""979 for i, arg := range desc.Args {980 if expect != "" {981 expect += ", "982 }983 opt := i >= len(desc.Args)-desc.OptArgs984 if opt {985 expect += "["986 }987 expect += arg.Name988 if opt {989 expect += "]"990 }991 }992 if needBase {993 if expect != "" {994 expect += ", "995 }996 expect += typeArgBase.Name997 }998 if !desc.CantBeOpt {999 if expect != "" {1000 expect += ", "1001 }1002 expect += "[opt]"1003 }1004 if expect == "" {1005 expect = "no arguments"1006 }1007 return expect1008}1009func checkTypeKind(t *ast.Type, kind int) (unexpected string, expect string, ok bool) {1010 switch {1011 case kind == kindAny:1012 ok = true1013 case t.HasString:1014 ok = kind == kindString1015 if !ok {1016 unexpected = fmt.Sprintf("string %q", t.String)1017 }1018 case t.Ident != "":1019 ok = kind == kindIdent || kind == kindInt1020 if !ok {1021 unexpected = fmt.Sprintf("identifier %v", t.Ident)1022 }1023 default:1024 ok = kind == kindInt1025 if !ok {1026 unexpected = fmt.Sprintf("int %v", t.Value)1027 }1028 }1029 if !ok {1030 switch kind {1031 case kindString:1032 expect = "string"1033 case kindIdent:1034 expect = "identifier"1035 case kindInt:1036 expect = "int"1037 }1038 }1039 return1040}1041func (comp *compiler) checkVarlens() {1042 for _, decl := range comp.desc.Nodes {1043 switch n := decl.(type) {1044 case *ast.Struct:1045 comp.checkVarlen(n)1046 }1047 }1048}1049func (comp *compiler) isVarlen(t *ast.Type) bool {1050 desc, args, _ := comp.getArgsBase(t, false)1051 return desc.Varlen != nil && desc.Varlen(comp, t, args)1052}1053func (comp *compiler) isZeroSize(t *ast.Type) bool {1054 desc, args, _ := comp.getArgsBase(t, false)1055 return desc.ZeroSize != nil && desc.ZeroSize(comp, t, args)1056}1057func (comp *compiler) checkVarlen(n *ast.Struct) {1058 // Non-varlen unions can't have varlen fields.1059 // Non-packed structs can't have varlen fields in the middle.1060 if n.IsUnion {1061 attrs := comp.parseAttrs(unionAttrs, n, n.Attrs)1062 if attrs[attrVarlen] != 0 {1063 return1064 }1065 } else {1066 attrs := comp.parseAttrs(structAttrs, n, n.Attrs)1067 if attrs[attrPacked] != 0 {1068 return1069 }1070 }1071 for i, f := range n.Fields {1072 if !n.IsUnion && i == len(n.Fields)-1 {1073 break1074 }1075 if comp.isVarlen(f.Type) {1076 if n.IsUnion {1077 comp.error(f.Pos, "variable size field %v in non-varlen union %v",1078 f.Name.Name, n.Name.Name)1079 } else {1080 comp.error(f.Pos, "variable size field %v in the middle of non-packed struct %v",1081 f.Name.Name, n.Name.Name)1082 }1083 }1084 }1085}1086func (comp *compiler) checkDupConsts() {1087 // The idea is to detect copy-paste errors in const arguments, e.g.:1088 // call$FOO(fd fd, arg const[FOO])1089 // call$BAR(fd fd, arg const[FOO])1090 // The second one is meant to be const[BAR],1091 // Unfortunately, this does not fully work as it detects lots of false positives.1092 // But was useful to find real bugs as well. So for now it's disabled, but can be run manually.1093 if true {1094 return1095 }1096 dups := make(map[string]map[string]dupConstArg)1097 for _, decl := range comp.desc.Nodes {1098 switch n := decl.(type) {1099 case *ast.Call:1100 comp.checkDupConstsCall(n, dups)1101 }1102 }1103}1104type dupConstArg struct {1105 pos ast.Pos1106 name string1107}1108func (comp *compiler) checkDupConstsCall(n *ast.Call, dups map[string]map[string]dupConstArg) {1109 if n.NR == ^uint64(0) {1110 return1111 }1112 for dups[n.CallName] == nil {1113 dups[n.CallName] = make(map[string]dupConstArg)1114 }1115 hasConsts := false1116 constArgID := ""1117 for i, arg := range n.Args {1118 desc := comp.getTypeDesc(arg.Type)1119 if desc == typeConst {1120 v := arg.Type.Args[0].Value1121 if v != 0 && v != 18446744073709551516 { // AT_FDCWD1122 constArgID += fmt.Sprintf("(%v-%v)", i, fmt.Sprintf("%v", v))1123 hasConsts = true1124 }1125 } else if desc == typeResource {1126 constArgID += fmt.Sprintf("(%v-%v)", i, arg.Type.Ident)1127 }1128 }1129 if !hasConsts {1130 return1131 }1132 dup, ok := dups[n.CallName][constArgID]...

Full Screen

Full Screen

compiler.go

Source:compiler.go Github

copy

Full Screen

...205 return 0206 }207 return sz.Value208}209func (comp *compiler) getTypeDesc(t *ast.Type) *typeDesc {210 if desc := builtinTypes[t.Ident]; desc != nil {211 return desc212 }213 if comp.resources[t.Ident] != nil {214 return typeResource215 }216 if comp.structs[t.Ident] != nil {217 return typeStruct218 }219 if comp.typedefs[t.Ident] != nil {220 return typeTypedef221 }222 return nil223}224func (comp *compiler) getArgsBase(t *ast.Type, isArg bool) (*typeDesc, []*ast.Type, prog.IntTypeCommon) {225 desc := comp.getTypeDesc(t)226 if desc == nil {227 panic(fmt.Sprintf("no type desc for %#v", *t))228 }229 args, opt := removeOpt(t)230 com := genCommon(t.Ident, sizeUnassigned, opt != nil)231 base := genIntCommon(com, 0, false)232 if desc.NeedBase {233 base.TypeSize = comp.ptrSize234 if !isArg {235 baseType := args[len(args)-1]236 args = args[:len(args)-1]237 base = typeInt.Gen(comp, baseType, nil, base).(*prog.IntType).IntTypeCommon238 }239 }240 return desc, args, base241}242func (comp *compiler) derefPointers(t *ast.Type) (*ast.Type, *typeDesc) {243 for {244 desc := comp.getTypeDesc(t)245 if desc != typePtr {246 return t, desc247 }248 t = t.Args[1]249 }250}251func (comp *compiler) foreachType(n0 ast.Node,252 cb func(*ast.Type, *typeDesc, []*ast.Type, prog.IntTypeCommon)) {253 switch n := n0.(type) {254 case *ast.Call:255 for _, arg := range n.Args {256 comp.foreachSubType(arg.Type, true, cb)257 }258 if n.Ret != nil {...

Full Screen

Full Screen

getTypeDesc

Using AI Code Generation

copy

Full Screen

1import (2func main() {3import "fmt"4func main() {5 fmt.Println(i, f, b, s)6}`7 fset := token.NewFileSet()8 f, err := parser.ParseFile(fset, "2.go", src, 0)9 if err != nil {10 panic(err)11 }12 ast.Print(fset, f)13 typeDesc := f.Scope.Lookup("i").Type().String()14 fmt.Println(typeDesc)15}

Full Screen

Full Screen

getTypeDesc

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 var f [5]int = [5]int{1, 2, 3, 4, 5}4 var g []int = []int{1, 2, 3, 4, 5}5 var h map[string]int = map[string]int{"a": 1, "b": 2}6 var i chan int = make(chan int)7 var j func(a int) int = func(a int) int {8 }9 var k interface{} = 1010 fmt.Println(reflect.TypeOf(a).String())11 fmt.Println(reflect.TypeOf(b).String())12 fmt.Println(reflect.TypeOf(c).String())13 fmt.Println(reflect.TypeOf(d).String())14 fmt.Println(reflect.TypeOf(e).String())15 fmt.Println(reflect.TypeOf(f).String())16 fmt.Println(reflect.TypeOf(g).String())17 fmt.Println(reflect.TypeOf(h).String())18 fmt.Println(reflect.TypeOf(i).String())19 fmt.Println(reflect.TypeOf(j).String())20 fmt.Println(reflect.TypeOf(k).String())21 fmt.Println(reflect.TypeOf(l).String())22}

Full Screen

Full Screen

getTypeDesc

Using AI Code Generation

copy

Full Screen

1import (2func main() {3import "fmt"4func main() {5 fmt.Println("Hello world!")6}7 fmt.Println("src:\n", src)8 l := lexer.New(src)9 p := parser.New(l)10 f := p.ParseFile()11 if f == nil {12 fmt.Println("parse error")13 }14 fmt.Println("parse:\n", f)15 s := scope.NewScope(nil)16 c := compiler.NewCompiler(s, nil)17 c.CompilePackage(f)18 fmt.Println("asm:\n", c.Asm())19 fmt.Println("symbol table:\n", s)20 fmt.Println("type table:\n", c.TypeTable())21 fmt.Println("type of main:", c.GetTypeDesc("main"))22 fmt.Println("type of fmt:", c.GetTypeDesc("fmt"))23 fmt.Println("type of Println:", c.GetTypeDesc("fmt.Println"))24 fmt.Println("type of Hello:", c.GetTypeDesc("Hello"))25 fmt.Println("type of world:", c.GetTypeDesc("world"))26 fmt.Println("type of main():", c.GetTypeDesc("main()"))27 fmt.Println("type of fmt.Println():", c.GetTypeDesc("fmt.Println()"))28 fmt.Println("type of fmt:", c.GetTypeDesc("fmt"))29 fmt.Println("type of fmt.Print:", c.GetTypeDesc("fmt.Print"))30 fmt.Println("type of fmt.Println:", c.GetTypeDesc("fmt.Println"))31 fmt.Println("type of fmt.Scanf:", c.GetTypeDesc("fmt.Scanf"))32 fmt.Println("type of fmt.Sprint:", c.GetTypeDesc("fmt.Sprint"))33 fmt.Println("type of fmt.Sprintln:", c.GetTypeDesc("fmt.Sprintln"))

Full Screen

Full Screen

getTypeDesc

Using AI Code Generation

copy

Full Screen

1import (2type Student struct {3}4func main() {5 t := reflect.TypeOf(s1)6 fmt.Println("Type of s1 is", t)7 fmt.Println("Name of s1 is", t.Name())8 fmt.Println("Kind of s1 is", t.Kind())9 fmt.Println("Underlying type of s1 is", t.Underlying())10}

Full Screen

Full Screen

getTypeDesc

Using AI Code Generation

copy

Full Screen

1import (2type mystruct struct {3}4func main() {5 fmt.Println(reflect.TypeOf(i).Name())6 fmt.Println(reflect.TypeOf(f).Name())7 fmt.Println(reflect.TypeOf(s).Name())8 fmt.Println(reflect.TypeOf(st).Name())9}

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run Syzkaller automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Most used method in

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful