modernc.org/cc@v1.0.1/v2/type.go (about) 1 // Copyright 2017 The CC Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package cc // import "modernc.org/cc/v2" 6 7 // [0]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf 8 9 import ( 10 "bytes" 11 "fmt" 12 "go/token" 13 14 "modernc.org/ir" 15 ) 16 17 var ( 18 _ Type = (*ArrayType)(nil) 19 _ Type = (*EnumType)(nil) 20 _ Type = (*FunctionType)(nil) 21 _ Type = (*NamedType)(nil) 22 _ Type = (*PointerType)(nil) 23 _ Type = (*StructType)(nil) 24 _ Type = (*TaggedStructType)(nil) 25 _ Type = (*TaggedUnionType)(nil) 26 _ Type = (*TaggedEnumType)(nil) 27 _ Type = (*UnionType)(nil) 28 _ Type = TypeKind(0) 29 30 _ fieldFinder = (*StructType)(nil) 31 _ fieldFinder = (*UnionType)(nil) 32 ) 33 34 type fieldFinder interface { 35 findField(int) *FieldProperties 36 } 37 38 // Type represents a C type. 39 type Type interface { 40 Node 41 Equal(Type) bool 42 IsArithmeticType() bool 43 IsCompatible(Type) bool // [0]6.2.7 44 IsIntegerType() bool 45 IsPointerType() bool 46 IsScalarType() bool 47 IsUnsigned() bool 48 IsVoidPointerType() bool 49 Kind() TypeKind 50 String() string 51 assign(ctx *context, n Node, op Operand) Operand 52 } 53 54 // TypeKind represents a particular type kind. 55 type TypeKind int 56 57 func (t TypeKind) Pos() token.Pos { return token.Pos(0) } 58 59 // TypeKind values. 60 const ( 61 _ TypeKind = iota 62 63 Bool 64 Char 65 Int 66 Long 67 LongLong 68 SChar 69 Short 70 UChar 71 UInt 72 ULong 73 ULongLong 74 UShort 75 76 Float 77 Double 78 LongDouble 79 80 FloatComplex 81 DoubleComplex 82 LongDoubleComplex 83 84 FloatImaginary 85 DoubleImaginary 86 LongDoubleImaginary 87 88 Array 89 Enum 90 EnumTag 91 Function 92 Ptr 93 Struct 94 StructTag 95 TypedefName 96 Union 97 UnionTag 98 Void 99 100 maxTypeKind 101 ) 102 103 // IsUnsigned implements Type. 104 func (t TypeKind) IsUnsigned() bool { return t.IsIntegerType() && !isSigned[t] } 105 106 // Kind implements Type. 107 func (t TypeKind) Kind() TypeKind { return t } 108 109 // assign implements Type. 110 func (t TypeKind) assign(ctx *context, n Node, op Operand) Operand { 111 // [0]6.5.16.1 112 switch { 113 // One of the following shall hold: 114 case 115 // the left operand has qualified or unqualified arithmetic 116 // type and the right has arithmetic type; 117 t.IsArithmeticType() && op.Type.IsArithmeticType(): 118 return op.ConvertTo(ctx.model, t) 119 default: 120 panic(fmt.Sprintf("%v: %v <- %v", ctx.position(n), t, op)) 121 } 122 } 123 124 // IsPointerType implements Type. 125 func (t TypeKind) IsPointerType() bool { 126 if t.IsArithmeticType() { 127 return false 128 } 129 130 switch t { 131 case Void: 132 return false 133 default: 134 panic(t) 135 } 136 } 137 138 // IsIntegerType implements Type. 139 func (t TypeKind) IsIntegerType() bool { 140 switch t { 141 case 142 Bool, 143 Char, 144 DoubleImaginary, 145 FloatImaginary, 146 Int, 147 Long, 148 LongDoubleImaginary, 149 LongLong, 150 SChar, 151 Short, 152 UChar, 153 UInt, 154 ULong, 155 ULongLong, 156 UShort: 157 158 return true 159 case 160 Double, 161 DoubleComplex, 162 Float, 163 FloatComplex, 164 LongDouble, 165 LongDoubleComplex, 166 Void: 167 168 return false 169 default: 170 panic(t) 171 } 172 } 173 174 // IsScalarType implements Type. 175 func (t TypeKind) IsScalarType() bool { 176 switch t { 177 case 178 Char, 179 Double, 180 DoubleComplex, 181 Float, 182 FloatComplex, 183 Int, 184 Long, 185 LongDouble, 186 LongDoubleComplex, 187 LongLong, 188 SChar, 189 Short, 190 UChar, 191 UInt, 192 ULong, 193 ULongLong, 194 UShort: 195 196 return true 197 case 198 Bool, 199 Void: 200 201 return false 202 default: 203 panic(t) 204 } 205 } 206 207 // IsVoidPointerType implements Type. 208 func (t TypeKind) IsVoidPointerType() bool { 209 if t != Ptr { 210 return false 211 } 212 213 panic(t) 214 } 215 216 // IsArithmeticType implements Type. 217 func (t TypeKind) IsArithmeticType() bool { return isArithmeticType[t] } 218 219 // IsCompatible implements Type. 220 func (t TypeKind) IsCompatible(u Type) bool { 221 for { 222 switch x := u.(type) { 223 case *PointerType: 224 switch t { 225 case 226 Char, 227 Int: 228 229 return false 230 default: 231 panic(fmt.Errorf("%v %v", t, x)) 232 } 233 case *NamedType: 234 u = x.Type 235 case *EnumType: 236 u = x.Enums[0].Operand.Type 237 case TypeKind: 238 if t.IsIntegerType() && u.IsIntegerType() { 239 return intConvRank[t] == intConvRank[x] && isSigned[t] == isSigned[x] 240 } 241 242 switch x { 243 case 244 Double, 245 DoubleComplex, 246 Float, 247 FloatComplex, 248 LongDouble, 249 LongDoubleComplex: 250 251 return t == x 252 case Void: 253 return t == x 254 default: 255 panic(fmt.Errorf("%v", x)) 256 } 257 default: 258 panic(fmt.Errorf("%v %T", t, x)) 259 } 260 } 261 } 262 263 // Equal implements Type. 264 func (t TypeKind) Equal(u Type) bool { 265 switch x := u.(type) { 266 case 267 *ArrayType, 268 *EnumType, 269 *FunctionType, 270 *PointerType, 271 *StructType, 272 *TaggedEnumType, 273 *TaggedStructType, 274 *TaggedUnionType, 275 *UnionType: 276 277 if t.IsScalarType() || t == Void { 278 return false 279 } 280 281 panic(t) 282 case *NamedType: 283 return t.Equal(x.Type) 284 case TypeKind: 285 switch x { 286 case 287 Bool, 288 Char, 289 Double, 290 DoubleComplex, 291 DoubleImaginary, 292 Float, 293 FloatComplex, 294 FloatImaginary, 295 Int, 296 Long, 297 LongDouble, 298 LongDoubleComplex, 299 LongDoubleImaginary, 300 LongLong, 301 SChar, 302 Short, 303 UChar, 304 UInt, 305 ULong, 306 ULongLong, 307 UShort, 308 Void: 309 310 return t == x 311 default: 312 panic(x) 313 } 314 default: 315 panic(fmt.Errorf("%T", x)) 316 } 317 } 318 319 func (t TypeKind) String() string { 320 switch t { 321 case Bool: 322 return "bool" 323 case Char: 324 return "char" 325 case Int: 326 return "int" 327 case Long: 328 return "long" 329 case LongLong: 330 return "long long" 331 case SChar: 332 return "signed char" 333 case Short: 334 return "short" 335 case UChar: 336 return "unsigned char" 337 case UInt: 338 return "unsigned" 339 case ULong: 340 return "unsigned long" 341 case ULongLong: 342 return "unsigned long long" 343 case UShort: 344 return "unsigned short" 345 case Float: 346 return "float" 347 case Double: 348 return "double" 349 case LongDouble: 350 return "long double" 351 case FloatImaginary: 352 return "float imaginary" 353 case DoubleImaginary: 354 return "double imaginary" 355 case LongDoubleImaginary: 356 return "long double imaginary" 357 case FloatComplex: 358 return "float complex" 359 case DoubleComplex: 360 return "double complex" 361 case LongDoubleComplex: 362 return "long double complex" 363 case Array: 364 return "array" 365 case Enum: 366 return "enum" 367 case EnumTag: 368 return "enum tag" 369 case Function: 370 return "function" 371 case Ptr: 372 return "ptr" 373 case Struct: 374 return "struct" 375 case StructTag: 376 return "struct tag" 377 case TypedefName: 378 return "typedef name" 379 case Union: 380 return "union" 381 case Void: 382 return "void" 383 default: 384 return fmt.Sprintf("TypeKind(%v)", int(t)) 385 } 386 } 387 388 // ArrayType type represents an array type. 389 type ArrayType struct { 390 Item Type 391 Length *Expr 392 Size Operand 393 TypeQualifiers []*TypeQualifier // Eg. double a[restrict 3][5], see 6.7.5.3-21. 394 pos token.Pos 395 } 396 397 func (t *ArrayType) Pos() token.Pos { return t.pos } 398 399 func (t *ArrayType) IsVLA() bool { return t.Length != nil && t.Length.Operand.Value == nil } 400 401 // IsUnsigned implements Type. 402 func (t *ArrayType) IsUnsigned() bool { panic("TODO") } 403 404 // IsVoidPointerType implements Type. 405 func (t *ArrayType) IsVoidPointerType() bool { panic("TODO") } 406 407 // IsArithmeticType implements Type. 408 func (t *ArrayType) IsArithmeticType() bool { return false } 409 410 // IsCompatible implements Type. 411 func (t *ArrayType) IsCompatible(u Type) bool { 412 // [0]6.7.5.2 413 // 414 // 6. For two array types to be compatible, both shall have compatible 415 // element types, and if both size specifiers are present, and are 416 // integer constant expressions, then both size specifiers shall have 417 // the same constant value. If the two array types are used in a 418 // context which requires them to be compatible, it is undefined 419 // behavior if the two size specifiers evaluate to unequal values. 420 switch x := u.(type) { 421 case *ArrayType: 422 if !t.Item.IsCompatible(x.Item) { 423 return false 424 } 425 426 if t.Size.Type != nil && x.Size.Type != nil { 427 return t.Size.Value.(*ir.Int64Value).Value == x.Size.Value.(*ir.Int64Value).Value 428 } 429 430 return true 431 case *NamedType: 432 return x.IsCompatible(t) 433 case *PointerType: 434 return t.Size.Type == nil && t.Item.IsCompatible(x.Item) 435 case TypeKind: 436 if x.IsArithmeticType() { 437 return false 438 } 439 440 panic(fmt.Errorf("%T\n%v\n%v", x, t, u)) 441 default: 442 panic(fmt.Errorf("%T\n%v\n%v", x, t, u)) 443 } 444 } 445 446 // Equal implements Type. 447 func (t *ArrayType) Equal(u Type) bool { 448 if t == u { 449 return true 450 } 451 452 switch x := u.(type) { 453 case *ArrayType: 454 if !t.Item.Equal(x.Item) { 455 return false 456 } 457 458 switch { 459 case t.Size.Type != nil && x.Size.Type != nil: 460 return x.Size.Type != nil && t.Size.Value.(*ir.Int64Value).Value == x.Size.Value.(*ir.Int64Value).Value 461 case t.Size.Type == nil && x.Size.Type == nil: 462 return true 463 default: 464 panic(fmt.Errorf("%v, %v", t, u)) 465 } 466 case *NamedType: 467 return x.Type.Equal(t) 468 case 469 *FunctionType, 470 *PointerType, 471 *StructType, 472 *TaggedStructType: 473 474 return false 475 case TypeKind: 476 if x.IsScalarType() || x == Void { 477 return false 478 } 479 480 panic(x) 481 default: 482 panic(fmt.Errorf("%T %v", x, x)) 483 } 484 } 485 486 // Kind implements Type. 487 func (t *ArrayType) Kind() TypeKind { return Array } 488 489 // assign implements Type. 490 func (t *ArrayType) assign(ctx *context, n Node, op Operand) Operand { 491 switch { 492 case t.Size.Value == nil: 493 return (&PointerType{Item: t.Item}).assign(ctx, n, op) 494 default: 495 panic("TODO") 496 } 497 } 498 499 // IsPointerType implements Type. 500 func (t *ArrayType) IsPointerType() bool { return false } 501 502 // IsIntegerType implements Type. 503 func (t *ArrayType) IsIntegerType() bool { return false } 504 505 // IsScalarType implements Type. 506 func (t *ArrayType) IsScalarType() bool { return false } 507 508 func (t *ArrayType) String() string { 509 switch { 510 case t.Size.Type != nil && t.Size.Value != nil: 511 return fmt.Sprintf("array of %v %v", t.Size.Value, t.Item) 512 default: 513 return fmt.Sprintf("array of %v", t.Item) 514 } 515 } 516 517 // EnumType represents an enum type. 518 type EnumType struct { 519 Tag int 520 Enums []*EnumerationConstant 521 Min int64 522 Max uint64 523 pos token.Pos 524 } 525 526 func (t *EnumType) Pos() token.Pos { return t.pos } 527 528 func (t *EnumType) find(nm int) *EnumerationConstant { 529 for _, v := range t.Enums { 530 if v.Token.Val == nm { 531 return v 532 } 533 } 534 return nil 535 } 536 537 // IsUnsigned implements Type. 538 func (t *EnumType) IsUnsigned() bool { return t.Enums[0].Operand.Type.IsUnsigned() } 539 540 // IsVoidPointerType implements Type. 541 func (t *EnumType) IsVoidPointerType() bool { panic("TODO") } 542 543 // IsArithmeticType implements Type. 544 func (t *EnumType) IsArithmeticType() bool { return true } 545 546 // IsCompatible implements Type. 547 func (t *EnumType) IsCompatible(u Type) bool { 548 switch x := underlyingType(u, true).(type) { 549 case *EnumType: 550 if len(t.Enums) != len(x.Enums) { 551 return false 552 } 553 554 for i, v := range t.Enums { 555 if !v.equal(x.Enums[i]) { 556 return false 557 } 558 } 559 560 return true 561 default: 562 return false 563 } 564 } 565 566 // Equal implements Type. 567 func (t *EnumType) Equal(u Type) bool { 568 if t == u { 569 return true 570 } 571 572 switch x := UnderlyingType(u).(type) { 573 case *EnumType: 574 if t.Tag != x.Tag || len(t.Enums) != len(x.Enums) { 575 return false 576 } 577 578 for i, v := range t.Enums { 579 w := x.Enums[i] 580 if !v.Operand.Type.Equal(w.Operand.Type) || v.Operand.Value.(*ir.Int64Value).Value != w.Operand.Value.(*ir.Int64Value).Value { 581 return false 582 } 583 } 584 585 return true 586 case TypeKind: 587 if x.IsScalarType() { 588 return false 589 } 590 591 panic(fmt.Errorf("%v %T %v", t, x, x)) 592 default: 593 panic(fmt.Errorf("%v %T %v", t, x, x)) 594 } 595 } 596 597 // Kind implements Type. 598 func (t *EnumType) Kind() TypeKind { return Enum } 599 600 // assign implements Type. 601 func (t *EnumType) assign(ctx *context, n Node, op Operand) Operand { 602 return op.ConvertTo(ctx.model, t) 603 } 604 605 // IsPointerType implements Type. 606 func (t *EnumType) IsPointerType() bool { return false } 607 608 // IsIntegerType implements Type. 609 func (t *EnumType) IsIntegerType() bool { return true } 610 611 // IsScalarType implements Type. 612 func (t *EnumType) IsScalarType() bool { return true } 613 614 func (t *EnumType) String() string { 615 return fmt.Sprintf("%s enumeration %s", t.Enums[0].Operand.Type.String(), dict.S(t.Tag)) 616 } 617 618 // Field represents a struct/union field. 619 type Field struct { 620 Bits int 621 Declarator *Declarator 622 Name int 623 PackedType Type // Bits != 0: underlaying struct field type 624 Type Type 625 626 Anonymous bool 627 IsFlexibleArray bool 628 } 629 630 func (f Field) equal(g Field) bool { 631 return f.Name == g.Name && f.Type.Equal(g.Type) && f.Bits == g.Bits 632 } 633 634 func (f Field) isCompatiblel(g Field) bool { 635 return f.Name == g.Name && f.Type.IsCompatible(g.Type) && f.Bits == g.Bits 636 } 637 638 func (f Field) String() string { return fmt.Sprintf("%s %v", dict.S(f.Name), f.Type) } 639 640 // FunctionType represents a function type. 641 type FunctionType struct { 642 Params []Type 643 Result Type 644 Variadic bool 645 params []int 646 pos token.Pos 647 } 648 649 func (t *FunctionType) Pos() token.Pos { return t.pos } 650 651 // IsUnsigned implements Type. 652 func (t *FunctionType) IsUnsigned() bool { panic("TODO") } 653 654 // IsVoidPointerType implements Type. 655 func (t *FunctionType) IsVoidPointerType() bool { panic("TODO") } 656 657 // IsArithmeticType implements Type. 658 func (t *FunctionType) IsArithmeticType() bool { return false } 659 660 // IsCompatible implements Type. 661 func (t *FunctionType) IsCompatible(u Type) bool { 662 switch x := u.(type) { 663 case *FunctionType: 664 if t.Variadic != x.Variadic || !t.Result.IsCompatible(x.Result) { 665 return false 666 } 667 668 if len(t.Params) != len(x.Params) { 669 switch { 670 case len(t.Params) == 1 && len(x.Params) == 0 && t.Params[0].Kind() == Void: 671 return true 672 case len(t.Params) == 0 && len(x.Params) == 1 && x.Params[0].Kind() == Void: 673 return true 674 } 675 return false 676 } 677 678 for i, t := range t.Params { 679 if !t.IsCompatible(x.Params[i]) { 680 return false 681 } 682 } 683 return true 684 case *NamedType: 685 return x.Type.IsCompatible(t) 686 case *PointerType: 687 return x.Item.IsCompatible(t) 688 default: 689 panic(fmt.Errorf("%T", x)) 690 } 691 } 692 693 // Equal implements Type. 694 func (t *FunctionType) Equal(u Type) bool { 695 if t == u { 696 return true 697 } 698 699 switch x := u.(type) { 700 case *FunctionType: 701 if len(t.Params) != len(x.Params) || t.Variadic != x.Variadic || !t.Result.Equal(x.Result) { 702 return false 703 } 704 705 for i, t := range t.Params { 706 if !t.Equal(x.Params[i]) { 707 return false 708 } 709 } 710 return true 711 case 712 *NamedType, 713 *PointerType, 714 *StructType, 715 *TaggedStructType: 716 717 return false 718 case TypeKind: 719 switch x { 720 case 721 Char, 722 Int, 723 Void: 724 725 return false 726 default: 727 panic(x) 728 } 729 default: 730 panic(fmt.Errorf("%T", x)) 731 } 732 } 733 734 // Kind implements Type. 735 func (t *FunctionType) Kind() TypeKind { return Function } 736 737 // assign implements Type. 738 func (t *FunctionType) assign(ctx *context, n Node, op Operand) Operand { 739 switch x := UnderlyingType(op.Type).(type) { 740 case *PointerType: 741 switch y := UnderlyingType(x.Item).(type) { 742 case *FunctionType: 743 if !t.Equal(y) { 744 panic(fmt.Errorf("%v: %v != %v", ctx.position(n), t, y)) 745 } 746 747 return op 748 default: 749 panic(fmt.Errorf("%v: %T", ctx.position(n), y)) 750 } 751 default: 752 panic(fmt.Errorf("%v: %T", ctx.position(n), x)) 753 } 754 } 755 756 // IsPointerType implements Type. 757 func (t *FunctionType) IsPointerType() bool { return false } 758 759 // IsIntegerType implements Type. 760 func (t *FunctionType) IsIntegerType() bool { return false } 761 762 // IsScalarType implements Type. 763 func (t *FunctionType) IsScalarType() bool { return false } 764 765 func (t *FunctionType) String() string { 766 var buf bytes.Buffer 767 buf.WriteString("function (") 768 switch { 769 case len(t.Params) == 1 && t.Params[0].Kind() == Void: 770 // nop 771 default: 772 for i, v := range t.Params { 773 if i != 0 { 774 buf.WriteString(", ") 775 } 776 buf.WriteString(v.String()) 777 } 778 } 779 fmt.Fprintf(&buf, ") returning %v", t.Result) 780 return buf.String() 781 } 782 783 // NamedType represents a type described by a typedef name. 784 type NamedType struct { 785 Name int 786 Type Type // The type Name refers to. 787 pos token.Pos 788 } 789 790 func (t *NamedType) Pos() token.Pos { return t.pos } 791 792 // IsUnsigned implements Type. 793 func (t *NamedType) IsUnsigned() bool { return t.Type.IsUnsigned() } 794 795 // IsVoidPointerType implements Type. 796 func (t *NamedType) IsVoidPointerType() bool { panic("TODO") } 797 798 // IsArithmeticType implements Type. 799 func (t *NamedType) IsArithmeticType() bool { return t.Type.IsArithmeticType() } 800 801 // IsCompatible implements Type. 802 func (t *NamedType) IsCompatible(u Type) (r bool) { 803 return UnderlyingType(t.Type).IsCompatible(UnderlyingType(u)) 804 } 805 806 // Equal implements Type. 807 func (t *NamedType) Equal(u Type) bool { 808 if t == u { 809 return true 810 } 811 812 switch x := u.(type) { 813 case *ArrayType: 814 return x.Equal(t.Type) 815 case *EnumType: 816 return x.Equal(t.Type) 817 case *NamedType: 818 return t.Name == x.Name && t.Type.Equal(x.Type) 819 case 820 *FunctionType, 821 *PointerType: 822 823 return x.Equal(t.Type) 824 case *StructType: 825 return t.Type.Equal(x) 826 case *TaggedEnumType: 827 v := x.getType() 828 return v != x && t.Type.Equal(v) 829 case *TaggedStructType: 830 v := x.getType() 831 return v != x && t.Type.Equal(v) 832 case *TaggedUnionType: 833 v := x.getType() 834 return v != x && t.Type.Equal(v) 835 case TypeKind: 836 switch x { 837 case 838 Bool, 839 Char, 840 Double, 841 Float, 842 Int, 843 Long, 844 LongDouble, 845 LongLong, 846 SChar, 847 Short, 848 UChar, 849 UInt, 850 ULong, 851 ULongLong, 852 UShort, 853 Void: 854 855 return x.Equal(t.Type) 856 default: 857 panic(x) 858 } 859 case *UnionType: 860 return t.Type.Equal(x) 861 default: 862 panic(fmt.Errorf("%T: %v, %v", x, t.Type, u)) 863 } 864 } 865 866 // Kind implements Type. 867 func (t *NamedType) Kind() TypeKind { return t.Type.Kind() } 868 869 // assign implements Type. 870 func (t *NamedType) assign(ctx *context, n Node, op Operand) Operand { return t.Type.assign(ctx, n, op) } 871 872 // IsPointerType implements Type. 873 func (t *NamedType) IsPointerType() bool { return t.Type.IsPointerType() } 874 875 // IsIntegerType implements Type. 876 func (t *NamedType) IsIntegerType() bool { return t.Type.IsIntegerType() } 877 878 // IsScalarType implements Type. 879 func (t *NamedType) IsScalarType() bool { return t.Type.IsScalarType() } 880 881 func (t *NamedType) String() string { return string(dict.S(t.Name)) } 882 883 // PointerType represents a pointer type. 884 type PointerType struct { 885 Item Type 886 pos token.Pos 887 } 888 889 func (t *PointerType) Pos() token.Pos { return t.pos } 890 891 // IsUnsigned implements Type. 892 func (t *PointerType) IsUnsigned() bool { return true } 893 894 // IsVoidPointerType implements Type. 895 func (t *PointerType) IsVoidPointerType() bool { return UnderlyingType(t.Item) == Void } 896 897 // IsArithmeticType implements Type. 898 func (t *PointerType) IsArithmeticType() bool { return false } 899 900 // IsCompatible implements Type. 901 func (t *PointerType) IsCompatible(u Type) bool { 902 if t.Equal(u) { 903 return true 904 } 905 906 var ai Type 907 switch x := UnderlyingType(t.Item).(type) { 908 case *ArrayType: 909 ai = x.Item 910 } 911 912 switch x := UnderlyingType(u).(type) { 913 case *ArrayType: 914 return t.Item.IsCompatible(x.Item) 915 case *NamedType: 916 return t.IsCompatible(x.Type) 917 case *FunctionType: 918 return x.IsCompatible(t) 919 case *PointerType: 920 // [0]6.3.2.3 921 // 922 // 1. A pointer to void may be converted to or from a pointer to any 923 // incomplete or object type. A pointer to any incomplete or object 924 // type may be converted to a pointer to void and back again; the 925 // result shall compare equal to the original pointer. 926 return t.Item == Void || x.Item == Void || 927 ai != nil && ai.IsCompatible(x.Item) || 928 underlyingType(t.Item, true).IsCompatible(underlyingType(x.Item, true)) || 929 Unsigned(t.Item) == Unsigned(x.Item) 930 case *StructType: 931 return false 932 case TypeKind: 933 if u.IsArithmeticType() { 934 return false 935 } 936 937 panic(fmt.Errorf("%T\n%v\n%v", x, t, u)) 938 default: 939 panic(fmt.Errorf("%T\n%v\n%v", x, t, u)) 940 } 941 } 942 943 func Unsigned(t Type) TypeKind { 944 switch k := underlyingType(t, false).Kind(); k { 945 case Char, SChar: 946 return UChar 947 case Short: 948 return UShort 949 case Int: 950 return UInt 951 case Long: 952 return ULong 953 case LongLong: 954 return ULongLong 955 default: 956 return k 957 } 958 } 959 960 // Equal implements Type. 961 func (t *PointerType) Equal(u Type) bool { 962 if t == u { 963 return true 964 } 965 966 switch x := u.(type) { 967 case 968 *ArrayType, 969 *FunctionType, 970 *StructType, 971 *TaggedStructType, 972 *UnionType: 973 974 return false 975 case *NamedType: 976 return t.Equal(x.Type) 977 case *PointerType: 978 return t.Item.Equal(x.Item) 979 case TypeKind: 980 switch x { 981 case 982 Char, 983 Double, 984 Float, 985 Int, 986 Long, 987 LongLong, 988 Short, 989 UChar, 990 UInt, 991 ULong, 992 ULongLong, 993 UShort, 994 Void: 995 996 return false 997 default: 998 panic(x) 999 } 1000 default: 1001 panic(fmt.Errorf("%T", x)) 1002 } 1003 } 1004 1005 // Kind implements Type. 1006 func (t *PointerType) Kind() TypeKind { return Ptr } 1007 1008 // assign implements Type. 1009 func (t *PointerType) assign(ctx *context, n Node, op Operand) (r Operand) { 1010 u := UnderlyingType(t.Item) 1011 var v Type 1012 if op.Type.IsPointerType() { 1013 v = UnderlyingType(UnderlyingType(op.Type).(*PointerType).Item) 1014 } 1015 // [0]6.5.16.1 1016 switch { 1017 // One of the following shall hold: 1018 case ctx.tweaks.EnablePointerCompatibility && op.Type.IsPointerType(): 1019 return op.ConvertTo(ctx.model, t) 1020 case 1021 // both operands are pointers to qualified or unqualified 1022 // versions of compatible types, and the type pointed to by the 1023 // left has all the qualifiers of the type pointed to by the 1024 // right; 1025 op.Type.IsPointerType() && t.IsCompatible(op.Type), 1026 u.IsIntegerType() && v != nil && v.IsIntegerType() && ctx.model.Sizeof(u) == ctx.model.Sizeof(v) && u.IsUnsigned() == v.IsUnsigned(): 1027 1028 return op.ConvertTo(ctx.model, t) 1029 case 1030 // one operand is a pointer to an object or incomplete type and 1031 // the other is a pointer to a qualified or unqualified version 1032 // of void, and the type pointed to by the left has all the 1033 // qualifiers of the type pointed to by the right; 1034 t.IsPointerType() && op.Type.IsVoidPointerType(): 1035 1036 panic("TODO") 1037 case 1038 // the left operand is a pointer and the right is a null 1039 // pointer constant; 1040 op.isNullPtrConst(): 1041 1042 return Operand{Type: t, Value: Null} 1043 default: 1044 panic(fmt.Errorf("%v: lhs type %v <- operand %v, op.IsPointerType %v op.IsCompatible %v", ctx.position(n), t, op, op.Type.IsPointerType(), t.IsCompatible(op.Type))) 1045 } 1046 } 1047 1048 // IsPointerType implements Type. 1049 func (t *PointerType) IsPointerType() bool { return true } 1050 1051 // IsIntegerType implements Type. 1052 func (t *PointerType) IsIntegerType() bool { return false } 1053 1054 // IsScalarType implements Type. 1055 func (t *PointerType) IsScalarType() bool { return true } 1056 1057 func (t *PointerType) String() string { return fmt.Sprintf("pointer to %v", t.Item) } 1058 1059 type structBase struct { 1060 Fields []Field 1061 HasFlexibleArrayMember bool 1062 Tag int 1063 scope *Scope 1064 layout []FieldProperties 1065 } 1066 1067 func (s *structBase) findField(nm int) *FieldProperties { 1068 fps := s.layout 1069 if x, ok := s.scope.Idents[nm].(*Declarator); ok { 1070 r := fps[x.Field] 1071 return &r 1072 } 1073 1074 for _, v := range fps { 1075 if v.Declarator != nil { 1076 continue 1077 } 1078 1079 x, ok := v.Type.(fieldFinder) 1080 if !ok { 1081 continue 1082 } 1083 1084 if fp := x.findField(nm); fp != nil { 1085 r := *fp 1086 r.Offset += v.Offset 1087 return &r 1088 } 1089 } 1090 return nil 1091 } 1092 1093 // StructType represents a struct type. 1094 type StructType struct { 1095 structBase 1096 pos token.Pos 1097 } 1098 1099 func (t *StructType) Pos() token.Pos { return t.pos } 1100 1101 // IsUnsigned implements Type. 1102 func (t *StructType) IsUnsigned() bool { panic("TODO") } 1103 1104 // Field returns the properties of field nm or nil if the field does not exist. 1105 func (t *StructType) Field(nm int) *FieldProperties { 1106 return t.findField(nm) 1107 } 1108 1109 // IsVoidPointerType implements Type. 1110 func (t *StructType) IsVoidPointerType() bool { panic("TODO") } 1111 1112 // IsArithmeticType implements Type. 1113 func (t *StructType) IsArithmeticType() bool { return false } 1114 1115 // IsCompatible implements Type. 1116 func (t *StructType) IsCompatible(u Type) bool { 1117 if t.Equal(u) { 1118 return true 1119 } 1120 1121 // [0]6.2.7.1 1122 // 1123 // Moreover, two structure, union, or enumerated types declared in 1124 // separate translation units are compatible if their tags and members 1125 // satisfy the following requirements: If one is declared with a tag, 1126 // the other shall be declared with the same tag. If both are complete 1127 // types, then the following additional requirements apply: there shall 1128 // be a one-to-one correspondence between their members such that each 1129 // pair of corresponding members are declared with compatible types, 1130 // and such that if one member of a corresponding pair is declared with 1131 // a name, the other member is declared with the same name. For two 1132 // structures, corresponding members shall be declared in the same 1133 // order. For two structures or unions, corresponding bit-fields shall 1134 // have the same widths. 1135 switch x := UnderlyingType(u).(type) { 1136 case *StructType: 1137 //TODO if len(t.Fields) != len(x.Fields) || t.Tag != x.Tag { // Fails in _sqlite/src/test_fs.c 1138 if len(t.Fields) != len(x.Fields) { 1139 return false 1140 } 1141 1142 for i, v := range t.Fields { 1143 if !v.isCompatiblel(x.Fields[i]) { 1144 return false 1145 } 1146 } 1147 1148 return true 1149 default: 1150 return false 1151 } 1152 } 1153 1154 // Equal implements Type. 1155 func (t *StructType) Equal(u Type) bool { 1156 if t == u { 1157 return true 1158 } 1159 1160 switch x := u.(type) { 1161 case *NamedType: 1162 return t.Equal(x.Type) 1163 case 1164 *ArrayType, 1165 *FunctionType, 1166 *PointerType: 1167 1168 return false 1169 case *StructType: 1170 if len(t.Fields) != len(x.Fields) || t.Tag != x.Tag { 1171 return false 1172 } 1173 1174 for i, v := range t.Fields { 1175 if !v.equal(x.Fields[i]) { 1176 return false 1177 } 1178 } 1179 return true 1180 case *TaggedStructType: 1181 v := x.getType() 1182 if v == u { 1183 return false 1184 } 1185 1186 return t.Equal(v) 1187 case TypeKind: 1188 switch x { 1189 case 1190 Char, 1191 Int, 1192 Long, 1193 UChar, 1194 UInt, 1195 UShort, 1196 Void: 1197 1198 return false 1199 default: 1200 panic(x) 1201 } 1202 default: 1203 panic(fmt.Errorf("%T", x)) 1204 } 1205 } 1206 1207 // Kind implements Type. 1208 func (t *StructType) Kind() TypeKind { return Struct } 1209 1210 // assign implements Type. 1211 func (t *StructType) assign(ctx *context, n Node, op Operand) Operand { 1212 switch x := op.Type.(type) { 1213 case *StructType: 1214 if !t.IsCompatible(x) { 1215 panic("TODO") 1216 } 1217 1218 return Operand{Type: t} 1219 case *NamedType: 1220 if !t.IsCompatible(x.Type) { 1221 panic("TODO") 1222 } 1223 1224 return Operand{Type: t} 1225 default: 1226 panic(fmt.Errorf("%v: %T %v", ctx.position(n), x, x)) 1227 } 1228 } 1229 1230 // IsPointerType implements Type. 1231 func (t *StructType) IsPointerType() bool { return false } 1232 1233 // IsIntegerType implements Type. 1234 func (t *StructType) IsIntegerType() bool { return false } 1235 1236 // IsScalarType implements Type. 1237 func (t *StructType) IsScalarType() bool { return false } 1238 1239 func (t *StructType) String() string { 1240 var buf bytes.Buffer 1241 buf.WriteString("struct{") 1242 for i, v := range t.Fields { 1243 if i != 0 { 1244 buf.WriteString("; ") 1245 } 1246 fmt.Fprintf(&buf, "%s %s", dict.S(v.Name), v.Type) 1247 if v.Bits != 0 { 1248 fmt.Fprintf(&buf, ".%d", v.Bits) 1249 } 1250 } 1251 buf.WriteByte('}') 1252 return buf.String() 1253 } 1254 1255 // TaggedEnumType represents an enum type described by a tag name. 1256 type TaggedEnumType struct { 1257 Tag int 1258 Type Type 1259 scope *Scope 1260 pos token.Pos 1261 } 1262 1263 func (t *TaggedEnumType) Pos() token.Pos { return t.pos } 1264 1265 // IsUnsigned implements Type. 1266 func (t *TaggedEnumType) IsUnsigned() bool { return t.Type.IsUnsigned() } 1267 1268 // Equal implements Type. 1269 func (t *TaggedEnumType) Equal(u Type) bool { 1270 switch x := UnderlyingType(u).(type) { 1271 case *EnumType: 1272 switch y := t.getType(); { 1273 case y == t: 1274 panic("TODO") 1275 default: 1276 return y.Equal(u) 1277 } 1278 case *TaggedEnumType: 1279 if t.Tag == x.Tag { 1280 return true 1281 } 1282 1283 panic("TODO") 1284 case TypeKind: 1285 if x.IsScalarType() { 1286 return false 1287 } 1288 1289 panic(fmt.Errorf("%v", x)) 1290 case *PointerType: 1291 return false 1292 default: 1293 panic(fmt.Errorf("%T", x)) 1294 } 1295 } 1296 1297 // IsArithmeticType implements Type. 1298 func (t *TaggedEnumType) IsArithmeticType() bool { return true } 1299 1300 // IsCompatible implements Type. 1301 func (t *TaggedEnumType) IsCompatible(u Type) bool { 1302 switch x := t.getType(); { 1303 case x == t: 1304 panic("TODO") 1305 default: 1306 return underlyingType(x, true).IsCompatible(underlyingType(u, true)) 1307 } 1308 } 1309 1310 // IsIntegerType implements Type. 1311 func (t *TaggedEnumType) IsIntegerType() bool { return true } 1312 1313 // IsPointerType implements Type. 1314 func (t *TaggedEnumType) IsPointerType() bool { return false } 1315 1316 // IsScalarType implements Type. 1317 func (t *TaggedEnumType) IsScalarType() bool { return true } 1318 1319 // IsVoidPointerType implements Type. 1320 func (t *TaggedEnumType) IsVoidPointerType() bool { panic("TODO") } 1321 1322 // Kind implements Type. 1323 func (t *TaggedEnumType) Kind() TypeKind { return Int } 1324 1325 func (t *TaggedEnumType) String() string { return fmt.Sprintf("enum %s", dict.S(t.Tag)) } 1326 1327 // assign implements Type. 1328 func (t *TaggedEnumType) assign(ctx *context, n Node, op Operand) Operand { 1329 switch x := UnderlyingType(op.Type).(type) { 1330 case *EnumType: 1331 //TODO use IsCompatible 1332 op.Type = t 1333 return op 1334 case TypeKind: 1335 if x.IsIntegerType() { 1336 op.Type = t 1337 return op 1338 } 1339 1340 panic(x) 1341 default: 1342 panic(fmt.Errorf("%T", x)) 1343 } 1344 } 1345 1346 func (t *TaggedEnumType) getType() Type { 1347 if t.Type != nil { 1348 return t.Type 1349 } 1350 1351 s := t.scope.lookupEnumTag(t.Tag) 1352 if s == nil { 1353 return t 1354 } 1355 1356 t.Type = s.typ 1357 return t.Type 1358 } 1359 1360 // TaggedStructType represents a struct type described by a tag name. 1361 type TaggedStructType struct { 1362 Tag int 1363 Type Type 1364 scope *Scope 1365 pos token.Pos 1366 } 1367 1368 func (t *TaggedStructType) Pos() token.Pos { return t.pos } 1369 1370 // IsUnsigned implements Type. 1371 func (t *TaggedStructType) IsUnsigned() bool { panic("TODO") } 1372 1373 // IsVoidPointerType implements Type. 1374 func (t *TaggedStructType) IsVoidPointerType() bool { panic("TODO") } 1375 1376 // IsArithmeticType implements Type. 1377 func (t *TaggedStructType) IsArithmeticType() bool { return false } 1378 1379 // IsCompatible implements Type. 1380 func (t *TaggedStructType) IsCompatible(u Type) bool { 1381 if t == u { 1382 return true 1383 } 1384 1385 if x, ok := u.(*TaggedStructType); ok && t.Tag == x.Tag { 1386 return true 1387 } 1388 1389 return false 1390 } 1391 1392 // Equal implements Type. 1393 func (t *TaggedStructType) Equal(u Type) bool { 1394 if t == u { 1395 return true 1396 } 1397 1398 if x, ok := u.(*TaggedStructType); ok && t.Tag == x.Tag { 1399 return true 1400 } 1401 1402 switch x := t.getType().(type) { 1403 case *StructType: 1404 return x.Equal(u) 1405 case *TaggedStructType: 1406 if x == t { 1407 switch y := u.(type) { 1408 case *NamedType: 1409 return t.Equal(y.Type) 1410 case *StructType: 1411 return false 1412 case *TaggedStructType: 1413 return t.Tag == y.Tag 1414 case TypeKind: 1415 switch y { 1416 case Void: 1417 return false 1418 default: 1419 panic(y) 1420 } 1421 default: 1422 panic(fmt.Errorf("%T", y)) 1423 } 1424 } 1425 1426 panic("TODO") 1427 default: 1428 panic(fmt.Errorf("%T", x)) 1429 } 1430 } 1431 1432 func (t *TaggedStructType) getType() Type { 1433 if t.Type != nil { 1434 return t.Type 1435 } 1436 1437 s := t.scope.lookupStructTag(t.Tag) 1438 if s == nil { 1439 return t 1440 } 1441 1442 t.Type = s.typ 1443 return t.Type 1444 } 1445 1446 // Kind implements Type. 1447 func (t *TaggedStructType) Kind() TypeKind { return Struct } 1448 1449 // assign implements Type. 1450 func (t *TaggedStructType) assign(ctx *context, n Node, op Operand) Operand { 1451 switch x := op.Type.(type) { 1452 case *NamedType: 1453 op.Type = x.Type 1454 return t.assign(ctx, n, op) 1455 case *TaggedStructType: 1456 t2 := t.getType() 1457 u2 := x.getType() 1458 if t2 != t && u2 != x { 1459 // [0]6.5.16.1 1460 // 1461 // the left operand has a qualified or unqualified 1462 // version of a structure or union type compatible with 1463 // the type of the right; 1464 if t2.Equal(u2) { 1465 return op 1466 } 1467 1468 panic("TODO") 1469 } 1470 panic("TODO") 1471 case *StructType: 1472 t2 := t.getType() 1473 if t2.Equal(x) { 1474 return op 1475 } 1476 panic(fmt.Errorf("%v: %T %v, %T %v", ctx.position(n), t2, t2, x, x)) 1477 default: 1478 panic(fmt.Errorf("%T", x)) 1479 } 1480 } 1481 1482 // IsPointerType implements Type. 1483 func (t *TaggedStructType) IsPointerType() bool { return false } 1484 1485 // IsIntegerType implements Type. 1486 func (t *TaggedStructType) IsIntegerType() bool { return false } 1487 1488 // IsScalarType implements Type. 1489 func (t *TaggedStructType) IsScalarType() bool { return false } 1490 1491 func (t *TaggedStructType) String() string { return fmt.Sprintf("struct %s", dict.S(t.Tag)) } 1492 1493 // UnionType represents a union type. 1494 type UnionType struct { 1495 structBase 1496 pos token.Pos 1497 } 1498 1499 func (t *UnionType) Pos() token.Pos { return t.pos } 1500 1501 // Field returns the properties of field nm or nil if the field does not exist. 1502 func (t *UnionType) Field(nm int) *FieldProperties { 1503 return t.findField(nm) 1504 } 1505 1506 // IsUnsigned implements Type. 1507 func (t *UnionType) IsUnsigned() bool { panic("TODO") } 1508 1509 // TaggedUnionType represents a struct type described by a tag name. 1510 type TaggedUnionType struct { 1511 Tag int 1512 Type Type 1513 scope *Scope 1514 pos token.Pos 1515 } 1516 1517 func (t *TaggedUnionType) Pos() token.Pos { return t.pos } 1518 1519 // IsUnsigned implements Type. 1520 func (t *TaggedUnionType) IsUnsigned() bool { panic("TODO") } 1521 1522 // IsVoidPointerType implements Type. 1523 func (t *TaggedUnionType) IsVoidPointerType() bool { panic("TODO") } 1524 1525 // IsArithmeticType implements Type. 1526 func (t *TaggedUnionType) IsArithmeticType() bool { return false } 1527 1528 // IsCompatible implements Type. 1529 func (t *TaggedUnionType) IsCompatible(u Type) bool { return t.Equal(u) } 1530 1531 // Equal implements Type. 1532 func (t *TaggedUnionType) Equal(u Type) bool { 1533 if t == u { 1534 return true 1535 } 1536 1537 if x, ok := u.(*TaggedUnionType); ok && t.Tag == x.Tag { 1538 return true 1539 } 1540 1541 switch x := t.getType().(type) { 1542 case *UnionType: 1543 return x.Equal(u) 1544 default: 1545 panic(fmt.Errorf("%T", x)) 1546 } 1547 } 1548 1549 func (t *TaggedUnionType) getType() Type { 1550 if t.Type != nil { 1551 return t.Type 1552 } 1553 1554 s := t.scope.lookupStructTag(t.Tag) 1555 if s == nil { 1556 return t 1557 } 1558 1559 t.Type = s.typ 1560 return t.Type 1561 } 1562 1563 // Kind implements Type. 1564 func (t *TaggedUnionType) Kind() TypeKind { return Union } 1565 1566 // assign implements Type. 1567 func (t *TaggedUnionType) assign(ctx *context, n Node, op Operand) Operand { 1568 switch x := op.Type.(type) { 1569 case *TaggedUnionType: 1570 t2 := t.getType() 1571 u2 := x.getType() 1572 if t2 != t && u2 != x { 1573 // [0]6.5.16.1 1574 // 1575 // the left operand has a qualified or unqualified 1576 // version of a structure or union type compatible with 1577 // the type of the right; 1578 if t2.Equal(u2) { 1579 return op 1580 } 1581 1582 panic("TODO") 1583 } 1584 panic("TODO") 1585 default: 1586 panic(fmt.Errorf("%T", x)) 1587 } 1588 } 1589 1590 // IsPointerType implements Type. 1591 func (t *TaggedUnionType) IsPointerType() bool { return false } 1592 1593 // IsIntegerType implements Type. 1594 func (t *TaggedUnionType) IsIntegerType() bool { return false } 1595 1596 // IsScalarType implements Type. 1597 func (t *TaggedUnionType) IsScalarType() bool { return false } 1598 1599 func (t *TaggedUnionType) String() string { return fmt.Sprintf("union %s", dict.S(t.Tag)) } 1600 1601 // IsVoidPointerType implements Type. 1602 func (t *UnionType) IsVoidPointerType() bool { panic("TODO") } 1603 1604 // IsArithmeticType implements Type. 1605 func (t *UnionType) IsArithmeticType() bool { return false } 1606 1607 // IsCompatible implements Type. 1608 func (t *UnionType) IsCompatible(u Type) bool { 1609 if t.Equal(u) { 1610 return true 1611 } 1612 1613 switch x := UnderlyingType(u).(type) { 1614 case *PointerType: 1615 return false 1616 case TypeKind: 1617 if x.IsScalarType() { 1618 return false 1619 } 1620 panic(fmt.Errorf("%v %T %v", t, x, x)) 1621 default: 1622 panic(fmt.Errorf("%v %T %v", t, x, x)) 1623 } 1624 } 1625 1626 // Equal implements Type. 1627 func (t *UnionType) Equal(u Type) bool { 1628 if t == u { 1629 return true 1630 } 1631 1632 switch x := u.(type) { 1633 case *NamedType: 1634 return t.Equal(x.Type) 1635 case *PointerType: 1636 return false 1637 case *TaggedUnionType: 1638 v := x.Type 1639 if v == x { 1640 panic(x) 1641 } 1642 1643 return t.Equal(v) 1644 case TypeKind: 1645 switch x { 1646 case 1647 Char, 1648 Int, 1649 UInt, 1650 ULongLong, 1651 Void: 1652 1653 return false 1654 default: 1655 panic(x) 1656 } 1657 case *UnionType: 1658 if len(t.Fields) != len(x.Fields) || t.Tag != x.Tag { 1659 return false 1660 } 1661 1662 for i, v := range t.Fields { 1663 if !v.equal(x.Fields[i]) { 1664 return false 1665 } 1666 } 1667 return true 1668 default: 1669 panic(x) 1670 } 1671 } 1672 1673 // Kind implements Type. 1674 func (t *UnionType) Kind() TypeKind { return Union } 1675 1676 // assign implements Type. 1677 func (t *UnionType) assign(ctx *context, n Node, op Operand) Operand { 1678 switch x := op.Type.(type) { 1679 case *NamedType: 1680 if !t.IsCompatible(x.Type) { 1681 panic("TODO") 1682 } 1683 1684 return Operand{Type: t} 1685 case *UnionType: 1686 if !t.IsCompatible(x) { 1687 panic("TODO") 1688 } 1689 1690 return Operand{Type: t} 1691 default: 1692 panic(fmt.Errorf("%v: %T %v", ctx.position(n), x, x)) 1693 } 1694 } 1695 1696 // IsPointerType implements Type. 1697 func (t *UnionType) IsPointerType() bool { return false } 1698 1699 // IsIntegerType implements Type. 1700 func (t *UnionType) IsIntegerType() bool { return false } 1701 1702 // IsScalarType implements Type. 1703 func (t *UnionType) IsScalarType() bool { return false } 1704 1705 func (t *UnionType) String() string { 1706 var buf bytes.Buffer 1707 buf.WriteString("union{") 1708 for i, v := range t.Fields { 1709 if i != 0 { 1710 buf.WriteString("; ") 1711 } 1712 fmt.Fprintf(&buf, "%s %s", dict.S(v.Name), v.Type) 1713 if v.Bits != 0 { 1714 fmt.Fprintf(&buf, ".%d", v.Bits) 1715 } 1716 1717 } 1718 buf.WriteByte('}') 1719 return buf.String() 1720 } 1721 1722 // AdjustedParameterType returns the type of an expression when used as an 1723 // argument of a function, see [0]6.9.1-10. 1724 func AdjustedParameterType(t Type) Type { 1725 u := t 1726 for { 1727 switch x := u.(type) { 1728 case *ArrayType: 1729 return &PointerType{t, t.Pos()} 1730 case *NamedType: 1731 if isVaList(x) { 1732 return x 1733 } 1734 1735 u = x.Type 1736 case 1737 *EnumType, 1738 *PointerType, 1739 *StructType, 1740 *TaggedEnumType, 1741 *TaggedStructType, 1742 *TaggedUnionType, 1743 *UnionType: 1744 1745 return t 1746 case TypeKind: 1747 switch x { 1748 case 1749 Char, 1750 Double, 1751 DoubleComplex, 1752 LongDouble, 1753 Float, 1754 FloatComplex, 1755 Int, 1756 Long, 1757 LongDoubleComplex, 1758 LongLong, 1759 SChar, 1760 Short, 1761 UChar, 1762 UInt, 1763 ULong, 1764 ULongLong, 1765 UShort: 1766 1767 return t 1768 default: 1769 panic(x) 1770 } 1771 default: 1772 panic(fmt.Errorf("%T", x)) 1773 } 1774 } 1775 } 1776 1777 // UnderlyingType returns the concrete type of t, if posible. 1778 func UnderlyingType(t Type) Type { return underlyingType(t, false) } 1779 1780 func underlyingType(t Type, enums bool) Type { 1781 for { 1782 switch x := t.(type) { 1783 case 1784 *ArrayType, 1785 *FunctionType, 1786 *PointerType, 1787 *StructType, 1788 *UnionType: 1789 1790 return x 1791 case *EnumType: 1792 if enums { 1793 return x 1794 } 1795 1796 return x.Enums[0].Operand.Type 1797 case *NamedType: 1798 if x.Type == nil { 1799 return x 1800 } 1801 1802 t = x.Type 1803 case *TaggedEnumType: 1804 if x.Type == nil { 1805 return x 1806 } 1807 1808 t = x.Type 1809 case *TaggedStructType: 1810 if x.Type == nil { 1811 return x 1812 } 1813 1814 t = x.Type 1815 case *TaggedUnionType: 1816 if x.Type == nil { 1817 return x 1818 } 1819 1820 t = x.Type 1821 case TypeKind: 1822 switch x { 1823 case 1824 Bool, 1825 Char, 1826 Double, 1827 DoubleComplex, 1828 DoubleImaginary, 1829 Float, 1830 FloatComplex, 1831 FloatImaginary, 1832 Int, 1833 Long, 1834 LongDouble, 1835 LongDoubleComplex, 1836 LongDoubleImaginary, 1837 LongLong, 1838 Ptr, 1839 SChar, 1840 Short, 1841 UChar, 1842 UInt, 1843 ULong, 1844 ULongLong, 1845 UShort, 1846 Void: 1847 1848 return x 1849 default: 1850 panic(fmt.Errorf("%v", x)) 1851 } 1852 default: 1853 panic(fmt.Errorf("%T", x)) 1854 } 1855 } 1856 }