github.com/Konstantin8105/c4go@v0.0.0-20240505174241-768bb1c65a51/transpiler/declarations.go (about) 1 // This file contains functions for transpiling declarations of variables and 2 // types. The usage of variables is handled in variables.go. 3 4 package transpiler 5 6 import ( 7 "fmt" 8 goast "go/ast" 9 "go/token" 10 "runtime/debug" 11 "strconv" 12 "strings" 13 14 "github.com/Konstantin8105/c4go/ast" 15 "github.com/Konstantin8105/c4go/program" 16 "github.com/Konstantin8105/c4go/types" 17 "github.com/Konstantin8105/c4go/util" 18 ) 19 20 // Example of AST for union without name inside struct: 21 // -RecordDecl 0x40d41b0 <...> line:453:8 struct EmptyName definition 22 // |-RecordDecl 0x40d4260 <...> line:454:2 union definition 23 // | |-FieldDecl 0x40d4328 <...> col:8 referenced l1 'long' 24 // | `-FieldDecl 0x40d4388 <...> col:8 referenced l2 'long' 25 // |-FieldDecl 0x40d4420 <...> col:2 implicit referenced 'union EmptyName::(anonymous at struct.c:454:2)' 26 // |-IndirectFieldDecl 0x40d4478 <...> col:8 implicit l1 'long' 27 // | |-Field 0x40d4420 '' 'union EmptyName::(anonymous at /struct.c:454:2)' 28 // | `-Field 0x40d4328 'l1' 'long' 29 // `-IndirectFieldDecl 0x40d44c8 <...> col:8 implicit l2 'long' 30 // |-Field 0x40d4420 '' 'union EmptyName::(anonymous at /struct.c:454:2)' 31 // `-Field 0x40d4388 'l2' 'long' 32 33 func newFunctionField(p *program.Program, name, cType string) ( 34 _ *goast.Field, err error) { 35 if name == "" { 36 err = fmt.Errorf("name of function field cannot be empty") 37 return 38 } 39 if !util.IsFunction(cType) { 40 err = fmt.Errorf("cannot create function field for type : %s", cType) 41 return 42 } 43 44 // TODO : add err handling 45 fieldType, _ := types.ResolveType(p, cType) 46 47 return &goast.Field{ 48 Names: []*goast.Ident{util.NewIdent(name)}, 49 Type: goast.NewIdent(fieldType), 50 }, nil 51 } 52 53 func generateNameFieldDecl(t string) string { 54 return "implicit_" + strings.Replace(t, " ", "S", -1) 55 } 56 57 func transpileFieldDecl(p *program.Program, n *ast.FieldDecl) ( 58 field *goast.Field, err error) { 59 defer func() { 60 if field != nil { 61 if field.Type == nil { 62 err = fmt.Errorf("found nil transpileFieldDecl in field Type %v , %v : %v", 63 n, field, err) 64 field.Type = util.NewIdent(n.Type) 65 } 66 if id, ok := field.Type.(*goast.Ident); ok && id.Name == "" { 67 id.Name = "C4GO_FIELD_DECL_NAME_EMPTY" 68 } 69 } 70 }() 71 if util.IsFunction(n.Type) { 72 field, err = newFunctionField(p, n.Name, n.Type) 73 if err == nil { 74 return 75 } 76 } 77 78 if n.Name == "" { 79 //&ast.FieldDecl{Addr:0x3157420, Pos:ast.Position{...}, Position2:"col:2", Name:"", Type:"union EmptyNameDD__at__home_lepricon_go_src_github_com_Konstantin8105_c4go_tests_struct_c_454_2_", Type2:"", Implicit:true, Referenced:true, ChildNodes:[]ast.Node{}} 80 n.Name = generateNameFieldDecl(n.Type) 81 } 82 83 name := n.Name 84 85 fieldType, err := types.ResolveType(p, n.Type) 86 p.AddMessage(p.GenerateWarningMessage(err, n)) 87 88 // TODO: The name of a variable or field cannot be a reserved word 89 // https://github.com/Konstantin8105/c4go/issues/83 90 // Search for this issue in other areas of the codebase. 91 if util.IsGoKeyword(name) { 92 name += "_" 93 } 94 95 arrayType, arraySize := types.GetArrayTypeAndSize(n.Type) 96 if arraySize != -1 { 97 fieldType, err = types.ResolveType(p, arrayType) 98 p.AddMessage(p.GenerateWarningMessage(err, n)) 99 fieldType = fmt.Sprintf("[%d]%s", arraySize, fieldType) 100 } 101 102 return &goast.Field{ 103 Names: []*goast.Ident{util.NewIdent(name)}, 104 Type: util.NewTypeIdent(fieldType), 105 }, nil 106 } 107 108 func transpileRecordDecl(p *program.Program, n *ast.RecordDecl) ( 109 decls []goast.Decl, err error) { 110 111 var addPackageUnsafe bool 112 113 n.Name = util.GenerateCorrectType(n.Name) 114 // |-RecordDecl 0x195a1e0 <line:168:1, line:170:1> line:168:1 struct definition 115 // | `-FieldDecl 0x195a298 <line:169:5, col:9> col:9 referenced aa 'int' 116 // |-VarDecl 0x195a348 <line:168:1, line:170:3> col:3 used mm 'struct (anonymous struct at /home/konstantin/go/src/github.com/K 117 // onstantin8105/c4go/tests/struct.c:168:1)':'struct (anonymous at /home/konstantin/go/src/github.com/Konstantin8105/c4go/tests 118 // /struct.c:168:1)' 119 if n.Name == "" { 120 n.Name = fmt.Sprintf("%s (anonymous %s at %s:%d:%d)", n.Kind, n.Kind, n.Pos.File, n.Pos.Line, n.Pos.Column) 121 } 122 n.Name = util.GenerateCorrectType(n.Name) 123 name := n.Name 124 125 defer func() { 126 if err != nil { 127 err = fmt.Errorf("cannot transpileRecordDecl `%v`. %v", 128 n.Name, err) 129 } else { 130 if addPackageUnsafe { 131 p.AddImports("unsafe") 132 } 133 } 134 }() 135 136 defer func() { 137 if r := recover(); r != nil { 138 err = fmt.Errorf("transpileRecordDecl: error - panic : %#v. %s", r, string(debug.Stack())) 139 } 140 }() 141 142 // ignore if haven`t definition 143 if !n.IsDefinition { 144 return 145 } 146 147 p.DefineType(name) 148 defer func() { 149 if err != nil { 150 p.UndefineType(name) 151 } 152 }() 153 154 var fields []*goast.Field 155 156 // repair name for anonymous RecordDecl 157 for pos := range n.Children() { 158 if rec, ok := n.Children()[pos].(*ast.RecordDecl); ok && rec.Name == "" { 159 if pos < len(n.Children()) { 160 switch v := n.Children()[pos+1].(type) { 161 case *ast.FieldDecl: 162 rec.Name = types.GetBaseType(util.GenerateCorrectType(v.Type)) 163 default: 164 p.AddMessage(p.GenerateWarningMessage( 165 fmt.Errorf("cannot find name for anon RecordDecl: %T", 166 v), n)) 167 rec.Name = "UndefinedNameC2GO" 168 } 169 } 170 } 171 } 172 173 for pos := range n.Children() { 174 switch field := n.Children()[pos].(type) { 175 case *ast.FieldDecl: 176 field.Type = util.GenerateCorrectType(field.Type) 177 field.Type2 = util.GenerateCorrectType(field.Type2) 178 var f *goast.Field 179 f, err = transpileFieldDecl(p, field) 180 if err != nil { 181 err = fmt.Errorf("cannot transpile field. %v", err) 182 p.AddMessage(p.GenerateWarningMessage(err, field)) 183 // TODO ignore error 184 // return 185 err = nil 186 } else { 187 // ignore fields without name 188 if len(f.Names) != 1 { 189 p.AddMessage(p.GenerateWarningMessage( 190 fmt.Errorf("ignore FieldDecl with more then 1 names"+ 191 " in RecordDecl : `%v`", n.Name), n)) 192 continue 193 } 194 if f.Names[0].Name == "" { 195 p.AddMessage(p.GenerateWarningMessage( 196 fmt.Errorf("Ignore FieldDecl without name "+ 197 " in RecordDecl : `%v`", n.Name), n)) 198 continue 199 } 200 // remove duplicates of fields 201 var isDuplicate bool 202 for i := range fields { 203 if fields[i].Names[0].Name == f.Names[0].Name { 204 isDuplicate = true 205 } 206 } 207 if isDuplicate { 208 f.Names[0].Name += strconv.Itoa(pos) 209 } 210 fields = append(fields, f) 211 } 212 213 case *ast.IndirectFieldDecl: 214 // ignore 215 216 case *ast.TransparentUnionAttr: 217 // Don't do anything 218 // Example of AST: 219 // |-RecordDecl 0x3632d78 <...> line:67:9 union definition 220 // | |-TransparentUnionAttr 0x3633050 <...> 221 // | |-FieldDecl 0x3632ed0 <...> col:17 __uptr 'union wait *' 222 // | `-FieldDecl 0x3632f60 <...> col:10 __iptr 'int *' 223 // |-TypedefDecl 0x3633000 <...> col:5 __WAIT_STATUS 'union __WAIT_STATUS':'__WAIT_STATUS' 224 // | `-ElaboratedType 0x3632fb0 'union __WAIT_STATUS' sugar 225 // | `-RecordType 0x3632e00 '__WAIT_STATUS' 226 // | `-Record 0x3632d78 '' 227 228 default: 229 // For case anonymous enum: 230 231 // |-EnumDecl 0x26c3970 <...> line:77:5 232 // | `-EnumConstantDecl 0x26c3a50 <...> col:9 referenced SWE_ENUM_THREE 'int' 233 // | `-IntegerLiteral 0x26c3a30 <...> 'int' 3 234 // |-FieldDecl 0x26c3af0 <...> col:7 EnumThree 'enum (anonymous enum at ... 235 if eDecl, ok := field.(*ast.EnumDecl); ok && eDecl.Name == "" { 236 if pos+1 <= len(n.Children())-1 { 237 if f, ok := n.Children()[pos+1].(*ast.FieldDecl); ok { 238 n.Children()[pos].(*ast.EnumDecl).Name = util.GenerateCorrectType(f.Type) 239 } 240 } 241 } 242 243 // default 244 var declsIn []goast.Decl 245 declsIn, err = transpileToNode(field, p) 246 if err != nil { 247 err = fmt.Errorf("cannot transpile %T : %v", field, err) 248 // p.AddMessage(p.GenerateWarningMessage(err, field)) 249 return 250 } 251 decls = append(decls, declsIn...) 252 } 253 } 254 255 s, err := program.NewStruct(p, n) 256 if err != nil { 257 p.AddMessage(p.GenerateWarningMessage(err, n)) 258 err = nil // ignore error 259 return 260 } 261 switch s.Type { 262 case program.UnionType: 263 if strings.HasPrefix(s.Name, "union ") { 264 p.Structs[s.Name] = s 265 defer func() { 266 if err != nil { 267 delete(p.Structs, s.Name) 268 p.UndefineType(s.Name) 269 } 270 }() 271 } else { 272 p.Unions["union "+s.Name] = s 273 defer func() { 274 if err != nil { 275 delete(p.Structs, "union "+s.Name) 276 p.UndefineType("union " + s.Name) 277 } 278 }() 279 } 280 281 case program.StructType: 282 if strings.HasPrefix(s.Name, "struct ") { 283 p.Structs[s.Name] = s 284 defer func() { 285 if err != nil { 286 delete(p.Structs, s.Name) 287 p.UndefineType(s.Name) 288 } 289 }() 290 } else { 291 p.Structs["struct "+s.Name] = s 292 defer func() { 293 if err != nil { 294 delete(p.Structs, "struct "+s.Name) 295 p.UndefineType("struct " + s.Name) 296 } 297 }() 298 } 299 300 default: 301 err = fmt.Errorf("undefine type of struct : %v", s.Type) 302 return 303 } 304 305 name = strings.TrimPrefix(name, "struct ") 306 name = strings.TrimPrefix(name, "union ") 307 308 var d []goast.Decl 309 switch s.Type { 310 case program.UnionType: 311 // Union size 312 var size int 313 size, err = types.SizeOf(p, "union "+name) 314 315 // In normal case no error is returned, 316 if err != nil { 317 // but if we catch one, send it as a warning 318 err = fmt.Errorf("could not determine the size of type `union %s`"+ 319 " for that reason: %s", name, err) 320 return 321 } 322 // So, we got size, then 323 // Add imports needed 324 addPackageUnsafe = true 325 326 // Declaration for implementing union type 327 d, err = transpileUnion(name, size, fields) 328 if err != nil { 329 return nil, err 330 } 331 332 case program.StructType: 333 d = append(d, &goast.GenDecl{ 334 Tok: token.TYPE, 335 Specs: []goast.Spec{ 336 &goast.TypeSpec{ 337 Name: util.NewIdent(name), 338 Type: &goast.StructType{ 339 Fields: &goast.FieldList{ 340 List: fields, 341 }, 342 }, 343 }, 344 }, 345 }) 346 347 default: 348 err = fmt.Errorf("undefine type of struct : %v", s.Type) 349 return 350 } 351 352 decls = append(decls, d...) 353 354 return 355 } 356 357 func transpileCXXRecordDecl(p *program.Program, n *ast.RecordDecl) ( 358 decls []goast.Decl, err error) { 359 360 n.Name = util.GenerateCorrectType(n.Name) 361 name := n.Name 362 363 defer func() { 364 if err != nil { 365 err = fmt.Errorf("cannot transpileCXXRecordDecl : `%v`. %v", 366 n.Name, err) 367 p.AddMessage(p.GenerateWarningMessage(err, n)) 368 } 369 }() 370 371 defer func() { 372 if r := recover(); r != nil { 373 err = fmt.Errorf("transpileCXXRecordDecl: error - panic : %#v %s", r, string(debug.Stack())) 374 } 375 }() 376 377 // ignore if haven`t definition 378 if !n.IsDefinition { 379 return 380 } 381 382 if name == "" || p.IsTypeAlreadyDefined(name) { 383 err = nil 384 return 385 } 386 387 p.DefineType(n.Kind + " " + name) 388 defer func() { 389 if err != nil { 390 p.UndefineType(n.Kind + " " + name) 391 } 392 }() 393 394 var fields []*goast.Field 395 for _, v := range n.Children() { 396 switch v := v.(type) { 397 case *ast.CXXRecordDecl: 398 // ignore 399 400 case *ast.AccessSpecDecl: 401 // ignore 402 403 case *ast.FieldDecl: 404 var f *goast.Field 405 f, err = transpileFieldDecl(p, v) 406 if err != nil { 407 return 408 } 409 fields = append(fields, f) 410 411 default: 412 p.AddMessage(p.GenerateWarningMessage( 413 fmt.Errorf("cannot transpilation field: %T", v), n)) 414 } 415 } 416 417 return []goast.Decl{&goast.GenDecl{ 418 Tok: token.TYPE, 419 Specs: []goast.Spec{ 420 &goast.TypeSpec{ 421 Name: util.NewIdent(name), 422 Type: &goast.StructType{ 423 Fields: &goast.FieldList{ 424 List: fields, 425 }, 426 }, 427 }, 428 }, 429 }}, nil 430 } 431 432 func transpileTypedefDecl(p *program.Program, n *ast.TypedefDecl) ( 433 decls []goast.Decl, err error) { 434 435 // implicit code from clang at the head of each clang AST tree 436 if n.IsImplicit && n.Pos.File == ast.PositionBuiltIn { 437 return 438 } 439 defer func() { 440 if err != nil { 441 err = fmt.Errorf("cannot transpile Typedef Decl : err = %v", err) 442 } else { 443 if !p.IncludeHeaderIsExists(n.Pos.File) { 444 // no need add struct from C STD 445 decls = nil 446 return 447 } 448 } 449 }() 450 n.Name = util.CleanCType(util.GenerateCorrectType(n.Name)) 451 n.Type = util.CleanCType(util.GenerateCorrectType(n.Type)) 452 n.Type2 = util.CleanCType(util.GenerateCorrectType(n.Type2)) 453 name := n.Name 454 455 if ignoreVaListTypedef(n.Name) { 456 return 457 } 458 459 // |-RecordDecl 0x1b733f0 <line:603:9, line:606:1> line:603:9 struct definition 460 // | |-FieldDecl 0x1b734c0 <line:604:5, col:12> col:12 x 'pointx':'int' 461 // | `-FieldDecl 0x1b73528 <line:605:5, col:9> col:9 y 'int' 462 // |-TypedefDecl 0x1b735d8 <line:603:1, line:606:3> col:3 referenced Point2 'struct Point2':'Point2' 463 // | `-ElaboratedType 0x1b73580 'struct Point2' sugar 464 // | `-RecordType 0x1b73470 'Point2' 465 // | `-Record 0x1b733f0 '' 466 for _, pre := range []string{"struct ", "union "} { 467 if pre+n.Name == n.Type && n.Name == n.Type2 { 468 n.Type = fmt.Sprintf("%s(anonymous %sat %s:%d:%d)", pre, pre, n.Pos.File, n.Pos.Line, n.Pos.Column) 469 n.Type = util.GenerateCorrectType(n.Type) 470 } 471 } 472 473 if "struct "+n.Name == n.Type || "union "+n.Name == n.Type { 474 p.TypedefType[n.Name] = n.Type 475 return 476 } 477 478 if util.IsFunction(n.Type) { 479 var field *goast.Field 480 field, err = newFunctionField(p, n.Name, n.Type) 481 if err != nil { 482 p.AddMessage(p.GenerateWarningMessage(err, n)) 483 } else { 484 // registration type 485 p.TypedefType[n.Name] = n.Type 486 487 decls = append(decls, &goast.GenDecl{ 488 Tok: token.TYPE, 489 Specs: []goast.Spec{ 490 &goast.TypeSpec{ 491 Name: util.NewIdent(name), 492 Assign: 1, 493 Type: field.Type, 494 }, 495 }, 496 }) 497 err = nil 498 return 499 } 500 } 501 502 // added for support "typedef enum {...} dd" with empty name of struct 503 // Result in Go: "type dd int" 504 if strings.Contains(n.Type, "enum ") { 505 // Registration new type in program.Program 506 if !p.IsTypeAlreadyDefined(n.Name) { 507 p.DefineType(n.Name) 508 p.EnumTypedefName[n.Name] = true 509 } 510 decls = append(decls, &goast.GenDecl{ 511 Tok: token.TYPE, 512 Specs: []goast.Spec{ 513 &goast.TypeSpec{ 514 Name: util.NewIdent(name), 515 Assign: 1, 516 Type: util.NewTypeIdent("int32"), 517 }, 518 }, 519 }) 520 err = nil 521 return 522 } 523 524 if p.IsTypeAlreadyDefined(name) { 525 err = nil 526 return 527 } 528 529 p.DefineType(name) 530 531 resolvedType, err := types.ResolveType(p, n.Type) 532 if err != nil { 533 p.AddMessage(p.GenerateWarningMessage(err, n)) 534 err = nil // ignore error 535 } 536 537 // There is a case where the name of the type is also the definition, 538 // like: 539 // 540 // type _RuneEntry _RuneEntry 541 // 542 // This of course is impossible and will cause the Go not to compile. 543 // It itself is caused by lack of understanding (at this time) about 544 // certain scenarios that types are defined as. The above example comes 545 // from: 546 // 547 // typedef struct { 548 // // ... some fields 549 // } _RuneEntry; 550 // 551 // Until which time that we actually need this to work I am going to 552 // suppress these. 553 if name == resolvedType { 554 err = nil 555 return 556 } 557 558 err = nil 559 if resolvedType == "" { 560 resolvedType = "interface{}" 561 } 562 563 p.TypedefType[n.Name] = n.Type 564 565 // 0: *ast.GenDecl { 566 // . Tok: type 567 // . Specs: []ast.Spec (len = 1) { 568 // . . 0: *ast.TypeSpec { 569 // . . . Name: *ast.Ident { 570 // . . . . Name: "R" 571 // . . . } 572 // . . . Assign: 3:8 // <- This is important 573 // . . . Type: *ast.Ident { 574 // . . . . Name: "int" 575 // . . . } 576 // . . } 577 // . } 578 // } 579 decls = append(decls, &goast.GenDecl{ 580 Tok: token.TYPE, 581 Specs: []goast.Spec{ 582 &goast.TypeSpec{ 583 Name: util.NewIdent(name), 584 Assign: 1, 585 Type: util.NewTypeIdent(resolvedType), 586 }, 587 }, 588 }) 589 590 return 591 } 592 593 func transpileVarDecl(p *program.Program, n *ast.VarDecl) ( 594 decls []goast.Decl, theType string, err error) { 595 defer func() { 596 if err != nil { 597 err = fmt.Errorf("cannot transpileVarDecl : err = %v", err) 598 } 599 }() 600 601 n.Name = util.GenerateCorrectType(n.Name) 602 n.Type = util.GenerateCorrectType(n.Type) 603 n.Type2 = util.GenerateCorrectType(n.Type2) 604 605 // Ignore extern as there is no analogy for Go right now. 606 if n.IsExtern && len(n.ChildNodes) == 0 { 607 return 608 } 609 610 if strings.Contains(n.Type, "va_list") && 611 strings.Contains(n.Type2, "va_list_tag") { 612 return VaListInit(p, n.Name), "", nil 613 } 614 615 // Example of DeclStmt for C code: 616 // void * a = NULL; 617 // void(*t)(void) = a; 618 // Example of AST: 619 // `-VarDecl 0x365fea8 <col:3, col:20> col:9 used t 'void (*)(void)' cinit 620 // `-ImplicitCastExpr 0x365ff48 <col:20> 'void (*)(void)' <BitCast> 621 // `-ImplicitCastExpr 0x365ff30 <col:20> 'void *' <LValueToRValue> 622 // `-DeclRefExpr 0x365ff08 <col:20> 'void *' lvalue Var 0x365f8c8 'r' 'void *' 623 624 if len(n.Children()) > 0 { 625 if v, ok := (n.Children()[0]).(*ast.ImplicitCastExpr); ok { 626 if len(v.Type) > 0 { 627 // Is it function ? 628 if util.IsFunction(v.Type) { 629 var prefix string 630 var fields, returns []string 631 prefix, fields, returns, err = types.SeparateFunction(p, v.Type) 632 if err != nil { 633 err = fmt.Errorf("cannot resolve function : %v", err) 634 return 635 } 636 if len(prefix) != 0 { 637 p.AddMessage(p.GenerateWarningMessage( 638 fmt.Errorf("prefix is not used : `%v`", prefix), n)) 639 } 640 functionType := GenerateFuncType(fields, returns) 641 nameVar1 := n.Name 642 643 if vv, ok := v.Children()[0].(*ast.ImplicitCastExpr); ok { 644 if decl, ok := vv.Children()[0].(*ast.DeclRefExpr); ok { 645 nameVar2 := decl.Name 646 647 return []goast.Decl{&goast.GenDecl{ 648 Tok: token.VAR, 649 Specs: []goast.Spec{&goast.ValueSpec{ 650 Names: []*goast.Ident{{Name: nameVar1}}, 651 Type: functionType, 652 Values: []goast.Expr{&goast.TypeAssertExpr{ 653 X: &goast.Ident{Name: nameVar2}, 654 Type: functionType, 655 }}, 656 Doc: p.GetMessageComments(), 657 }, 658 }}}, "", nil 659 } 660 } 661 } 662 } 663 } 664 } 665 666 theType = n.Type 667 668 p.GlobalVariables[n.Name] = theType 669 670 preStmts := []goast.Stmt{} 671 postStmts := []goast.Stmt{} 672 673 defaultValue, _, newPre, newPost, err := getDefaultValueForVar(p, n) 674 if err != nil { 675 p.AddMessage(p.GenerateWarningMessage(err, n)) 676 err = nil // Error is ignored 677 } 678 // for ignore zero value. example: 679 // int i = 0; 680 // transpile to: 681 // var i int // but not "var i int = 0" 682 if len(defaultValue) == 1 && defaultValue[0] != nil { 683 if bl, ok := defaultValue[0].(*goast.BasicLit); ok { 684 if bl.Kind == token.INT && bl.Value == "0" { 685 defaultValue = nil 686 } 687 if bl.Kind == token.FLOAT && bl.Value == "0" { 688 defaultValue = nil 689 } 690 } else if call, ok := defaultValue[0].(*goast.CallExpr); ok { 691 if len(call.Args) == 1 { 692 if bl, ok := call.Args[0].(*goast.BasicLit); ok { 693 if bl.Kind == token.INT && bl.Value == "0" { 694 defaultValue = nil 695 } 696 if bl.Kind == token.FLOAT && bl.Value == "0" { 697 defaultValue = nil 698 } 699 } 700 } 701 } else if ind, ok := defaultValue[0].(*goast.Ident); ok { 702 if ind.Name == "nil" { 703 defaultValue = nil 704 } 705 } 706 } 707 708 preStmts, postStmts = combinePreAndPostStmts(preStmts, postStmts, newPre, newPost) 709 710 // Allocate slice so that it operates like a fixed size array. 711 arrayType, arraySize := types.GetArrayTypeAndSize(n.Type) 712 713 if arraySize != -1 && defaultValue == nil { 714 var goArrayType string 715 goArrayType, err = types.ResolveType(p, arrayType) 716 if err != nil { 717 p.AddMessage(p.GenerateWarningMessage(err, n)) 718 err = nil // Error is ignored 719 } 720 721 defaultValue = []goast.Expr{ 722 util.NewCallExpr( 723 "make", 724 &goast.ArrayType{ 725 Elt: util.NewTypeIdent(goArrayType), 726 }, 727 util.NewIntLit(arraySize), 728 // If len and capacity is same, then 729 // capacity is not need 730 // util.NewIntLit(arraySize), 731 ), 732 } 733 } 734 735 if len(preStmts) != 0 || len(postStmts) != 0 { 736 p.AddMessage(p.GenerateWarningMessage( 737 fmt.Errorf("not acceptable length of Stmt : pre(%d), post(%d)", 738 len(preStmts), len(postStmts)), n)) 739 } 740 741 names := map[string]string{ 742 "ptrdiff_t": "noarch.PtrdiffT", 743 } 744 745 var typeResult goast.Expr 746 747 if n, ok := names[n.Type]; ok { 748 typeResult = util.NewTypeIdent(n) 749 goto ignoreType 750 } 751 752 theType, err = types.ResolveType(p, n.Type) 753 if err != nil { 754 p.AddMessage(p.GenerateWarningMessage( 755 fmt.Errorf("unknown type used C type, because %v", err), n)) 756 err = nil // Error is ignored 757 theType = n.Type 758 } 759 typeResult = util.NewTypeIdent(theType) 760 761 ignoreType: 762 763 return []goast.Decl{&goast.GenDecl{ 764 Tok: token.VAR, 765 Specs: []goast.Spec{ 766 &goast.ValueSpec{ 767 Names: []*goast.Ident{util.NewIdent(n.Name)}, 768 Type: typeResult, 769 Values: defaultValue, 770 Doc: p.GetMessageComments(), 771 }, 772 }, 773 }}, "", nil 774 }