mirror of
				https://github.com/golang/go.git
				synced 2025-10-31 08:40:55 +00:00 
			
		
		
		
	cmd/compile: allow conversion from slice to array ptr
Panic if the slice is too short. Updates #395 Change-Id: I90f4bff2da5d8f3148ba06d2482084f32b25c29a Reviewed-on: https://go-review.googlesource.com/c/go/+/301650 Trust: Josh Bleecher Snyder <josharian@gmail.com> Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
		
							parent
							
								
									1c268431f4
								
							
						
					
					
						commit
						faa4fa1a6e
					
				
					 33 changed files with 380 additions and 141 deletions
				
			
		|  | @ -669,7 +669,10 @@ func (e *escape) exprSkipInit(k hole, n ir.Node) { | ||||||
| 			k = e.spill(k, n) | 			k = e.spill(k, n) | ||||||
| 		} | 		} | ||||||
| 		e.expr(k.note(n, "interface-converted"), n.X) | 		e.expr(k.note(n, "interface-converted"), n.X) | ||||||
| 
 | 	case ir.OSLICE2ARRPTR: | ||||||
|  | 		// the slice pointer flows directly to the result | ||||||
|  | 		n := n.(*ir.ConvExpr) | ||||||
|  | 		e.expr(k, n.X) | ||||||
| 	case ir.ORECV: | 	case ir.ORECV: | ||||||
| 		n := n.(*ir.UnaryExpr) | 		n := n.(*ir.UnaryExpr) | ||||||
| 		e.discard(n.X) | 		e.discard(n.X) | ||||||
|  |  | ||||||
|  | @ -277,7 +277,7 @@ func (n *ConvExpr) SetOp(op Op) { | ||||||
| 	switch op { | 	switch op { | ||||||
| 	default: | 	default: | ||||||
| 		panic(n.no("SetOp " + op.String())) | 		panic(n.no("SetOp " + op.String())) | ||||||
| 	case OCONV, OCONVIFACE, OCONVNOP, OBYTES2STR, OBYTES2STRTMP, ORUNES2STR, OSTR2BYTES, OSTR2BYTESTMP, OSTR2RUNES, ORUNESTR: | 	case OCONV, OCONVIFACE, OCONVNOP, OBYTES2STR, OBYTES2STRTMP, ORUNES2STR, OSTR2BYTES, OSTR2BYTESTMP, OSTR2RUNES, ORUNESTR, OSLICE2ARRPTR: | ||||||
| 		n.op = op | 		n.op = op | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -206,6 +206,7 @@ var OpPrec = []int{ | ||||||
| 	OPRINT:         8, | 	OPRINT:         8, | ||||||
| 	ORUNESTR:       8, | 	ORUNESTR:       8, | ||||||
| 	OSIZEOF:        8, | 	OSIZEOF:        8, | ||||||
|  | 	OSLICE2ARRPTR:  8, | ||||||
| 	OSTR2BYTES:     8, | 	OSTR2BYTES:     8, | ||||||
| 	OSTR2RUNES:     8, | 	OSTR2RUNES:     8, | ||||||
| 	OSTRUCTLIT:     8, | 	OSTRUCTLIT:     8, | ||||||
|  | @ -804,7 +805,8 @@ func exprFmt(n Node, s fmt.State, prec int) { | ||||||
| 		ORUNES2STR, | 		ORUNES2STR, | ||||||
| 		OSTR2BYTES, | 		OSTR2BYTES, | ||||||
| 		OSTR2RUNES, | 		OSTR2RUNES, | ||||||
| 		ORUNESTR: | 		ORUNESTR, | ||||||
|  | 		OSLICE2ARRPTR: | ||||||
| 		n := n.(*ConvExpr) | 		n := n.(*ConvExpr) | ||||||
| 		if n.Type() == nil || n.Type().Sym() == nil { | 		if n.Type() == nil || n.Type().Sym() == nil { | ||||||
| 			fmt.Fprintf(s, "(%v)", n.Type()) | 			fmt.Fprintf(s, "(%v)", n.Type()) | ||||||
|  |  | ||||||
|  | @ -137,6 +137,7 @@ const ( | ||||||
| 	OSTR2BYTES    // Type(Left) (Type is []byte, Left is a string) | 	OSTR2BYTES    // Type(Left) (Type is []byte, Left is a string) | ||||||
| 	OSTR2BYTESTMP // Type(Left) (Type is []byte, Left is a string, ephemeral) | 	OSTR2BYTESTMP // Type(Left) (Type is []byte, Left is a string, ephemeral) | ||||||
| 	OSTR2RUNES    // Type(Left) (Type is []rune, Left is a string) | 	OSTR2RUNES    // Type(Left) (Type is []rune, Left is a string) | ||||||
|  | 	OSLICE2ARRPTR // Type(Left) (Type is *[N]T, Left is a []T) | ||||||
| 	// Left = Right or (if Colas=true) Left := Right | 	// Left = Right or (if Colas=true) Left := Right | ||||||
| 	// If Colas, then Ninit includes a DCL node for Left. | 	// If Colas, then Ninit includes a DCL node for Left. | ||||||
| 	OAS | 	OAS | ||||||
|  |  | ||||||
|  | @ -29,143 +29,144 @@ func _() { | ||||||
| 	_ = x[OSTR2BYTES-18] | 	_ = x[OSTR2BYTES-18] | ||||||
| 	_ = x[OSTR2BYTESTMP-19] | 	_ = x[OSTR2BYTESTMP-19] | ||||||
| 	_ = x[OSTR2RUNES-20] | 	_ = x[OSTR2RUNES-20] | ||||||
| 	_ = x[OAS-21] | 	_ = x[OSLICE2ARRPTR-21] | ||||||
| 	_ = x[OAS2-22] | 	_ = x[OAS-22] | ||||||
| 	_ = x[OAS2DOTTYPE-23] | 	_ = x[OAS2-23] | ||||||
| 	_ = x[OAS2FUNC-24] | 	_ = x[OAS2DOTTYPE-24] | ||||||
| 	_ = x[OAS2MAPR-25] | 	_ = x[OAS2FUNC-25] | ||||||
| 	_ = x[OAS2RECV-26] | 	_ = x[OAS2MAPR-26] | ||||||
| 	_ = x[OASOP-27] | 	_ = x[OAS2RECV-27] | ||||||
| 	_ = x[OCALL-28] | 	_ = x[OASOP-28] | ||||||
| 	_ = x[OCALLFUNC-29] | 	_ = x[OCALL-29] | ||||||
| 	_ = x[OCALLMETH-30] | 	_ = x[OCALLFUNC-30] | ||||||
| 	_ = x[OCALLINTER-31] | 	_ = x[OCALLMETH-31] | ||||||
| 	_ = x[OCALLPART-32] | 	_ = x[OCALLINTER-32] | ||||||
| 	_ = x[OCAP-33] | 	_ = x[OCALLPART-33] | ||||||
| 	_ = x[OCLOSE-34] | 	_ = x[OCAP-34] | ||||||
| 	_ = x[OCLOSURE-35] | 	_ = x[OCLOSE-35] | ||||||
| 	_ = x[OCOMPLIT-36] | 	_ = x[OCLOSURE-36] | ||||||
| 	_ = x[OMAPLIT-37] | 	_ = x[OCOMPLIT-37] | ||||||
| 	_ = x[OSTRUCTLIT-38] | 	_ = x[OMAPLIT-38] | ||||||
| 	_ = x[OARRAYLIT-39] | 	_ = x[OSTRUCTLIT-39] | ||||||
| 	_ = x[OSLICELIT-40] | 	_ = x[OARRAYLIT-40] | ||||||
| 	_ = x[OPTRLIT-41] | 	_ = x[OSLICELIT-41] | ||||||
| 	_ = x[OCONV-42] | 	_ = x[OPTRLIT-42] | ||||||
| 	_ = x[OCONVIFACE-43] | 	_ = x[OCONV-43] | ||||||
| 	_ = x[OCONVNOP-44] | 	_ = x[OCONVIFACE-44] | ||||||
| 	_ = x[OCOPY-45] | 	_ = x[OCONVNOP-45] | ||||||
| 	_ = x[ODCL-46] | 	_ = x[OCOPY-46] | ||||||
| 	_ = x[ODCLFUNC-47] | 	_ = x[ODCL-47] | ||||||
| 	_ = x[ODCLCONST-48] | 	_ = x[ODCLFUNC-48] | ||||||
| 	_ = x[ODCLTYPE-49] | 	_ = x[ODCLCONST-49] | ||||||
| 	_ = x[ODELETE-50] | 	_ = x[ODCLTYPE-50] | ||||||
| 	_ = x[ODOT-51] | 	_ = x[ODELETE-51] | ||||||
| 	_ = x[ODOTPTR-52] | 	_ = x[ODOT-52] | ||||||
| 	_ = x[ODOTMETH-53] | 	_ = x[ODOTPTR-53] | ||||||
| 	_ = x[ODOTINTER-54] | 	_ = x[ODOTMETH-54] | ||||||
| 	_ = x[OXDOT-55] | 	_ = x[ODOTINTER-55] | ||||||
| 	_ = x[ODOTTYPE-56] | 	_ = x[OXDOT-56] | ||||||
| 	_ = x[ODOTTYPE2-57] | 	_ = x[ODOTTYPE-57] | ||||||
| 	_ = x[OEQ-58] | 	_ = x[ODOTTYPE2-58] | ||||||
| 	_ = x[ONE-59] | 	_ = x[OEQ-59] | ||||||
| 	_ = x[OLT-60] | 	_ = x[ONE-60] | ||||||
| 	_ = x[OLE-61] | 	_ = x[OLT-61] | ||||||
| 	_ = x[OGE-62] | 	_ = x[OLE-62] | ||||||
| 	_ = x[OGT-63] | 	_ = x[OGE-63] | ||||||
| 	_ = x[ODEREF-64] | 	_ = x[OGT-64] | ||||||
| 	_ = x[OINDEX-65] | 	_ = x[ODEREF-65] | ||||||
| 	_ = x[OINDEXMAP-66] | 	_ = x[OINDEX-66] | ||||||
| 	_ = x[OKEY-67] | 	_ = x[OINDEXMAP-67] | ||||||
| 	_ = x[OSTRUCTKEY-68] | 	_ = x[OKEY-68] | ||||||
| 	_ = x[OLEN-69] | 	_ = x[OSTRUCTKEY-69] | ||||||
| 	_ = x[OMAKE-70] | 	_ = x[OLEN-70] | ||||||
| 	_ = x[OMAKECHAN-71] | 	_ = x[OMAKE-71] | ||||||
| 	_ = x[OMAKEMAP-72] | 	_ = x[OMAKECHAN-72] | ||||||
| 	_ = x[OMAKESLICE-73] | 	_ = x[OMAKEMAP-73] | ||||||
| 	_ = x[OMAKESLICECOPY-74] | 	_ = x[OMAKESLICE-74] | ||||||
| 	_ = x[OMUL-75] | 	_ = x[OMAKESLICECOPY-75] | ||||||
| 	_ = x[ODIV-76] | 	_ = x[OMUL-76] | ||||||
| 	_ = x[OMOD-77] | 	_ = x[ODIV-77] | ||||||
| 	_ = x[OLSH-78] | 	_ = x[OMOD-78] | ||||||
| 	_ = x[ORSH-79] | 	_ = x[OLSH-79] | ||||||
| 	_ = x[OAND-80] | 	_ = x[ORSH-80] | ||||||
| 	_ = x[OANDNOT-81] | 	_ = x[OAND-81] | ||||||
| 	_ = x[ONEW-82] | 	_ = x[OANDNOT-82] | ||||||
| 	_ = x[ONOT-83] | 	_ = x[ONEW-83] | ||||||
| 	_ = x[OBITNOT-84] | 	_ = x[ONOT-84] | ||||||
| 	_ = x[OPLUS-85] | 	_ = x[OBITNOT-85] | ||||||
| 	_ = x[ONEG-86] | 	_ = x[OPLUS-86] | ||||||
| 	_ = x[OOROR-87] | 	_ = x[ONEG-87] | ||||||
| 	_ = x[OPANIC-88] | 	_ = x[OOROR-88] | ||||||
| 	_ = x[OPRINT-89] | 	_ = x[OPANIC-89] | ||||||
| 	_ = x[OPRINTN-90] | 	_ = x[OPRINT-90] | ||||||
| 	_ = x[OPAREN-91] | 	_ = x[OPRINTN-91] | ||||||
| 	_ = x[OSEND-92] | 	_ = x[OPAREN-92] | ||||||
| 	_ = x[OSLICE-93] | 	_ = x[OSEND-93] | ||||||
| 	_ = x[OSLICEARR-94] | 	_ = x[OSLICE-94] | ||||||
| 	_ = x[OSLICESTR-95] | 	_ = x[OSLICEARR-95] | ||||||
| 	_ = x[OSLICE3-96] | 	_ = x[OSLICESTR-96] | ||||||
| 	_ = x[OSLICE3ARR-97] | 	_ = x[OSLICE3-97] | ||||||
| 	_ = x[OSLICEHEADER-98] | 	_ = x[OSLICE3ARR-98] | ||||||
| 	_ = x[ORECOVER-99] | 	_ = x[OSLICEHEADER-99] | ||||||
| 	_ = x[ORECV-100] | 	_ = x[ORECOVER-100] | ||||||
| 	_ = x[ORUNESTR-101] | 	_ = x[ORECV-101] | ||||||
| 	_ = x[OSELRECV2-102] | 	_ = x[ORUNESTR-102] | ||||||
| 	_ = x[OIOTA-103] | 	_ = x[OSELRECV2-103] | ||||||
| 	_ = x[OREAL-104] | 	_ = x[OIOTA-104] | ||||||
| 	_ = x[OIMAG-105] | 	_ = x[OREAL-105] | ||||||
| 	_ = x[OCOMPLEX-106] | 	_ = x[OIMAG-106] | ||||||
| 	_ = x[OALIGNOF-107] | 	_ = x[OCOMPLEX-107] | ||||||
| 	_ = x[OOFFSETOF-108] | 	_ = x[OALIGNOF-108] | ||||||
| 	_ = x[OSIZEOF-109] | 	_ = x[OOFFSETOF-109] | ||||||
| 	_ = x[OMETHEXPR-110] | 	_ = x[OSIZEOF-110] | ||||||
| 	_ = x[OSTMTEXPR-111] | 	_ = x[OMETHEXPR-111] | ||||||
| 	_ = x[OBLOCK-112] | 	_ = x[OSTMTEXPR-112] | ||||||
| 	_ = x[OBREAK-113] | 	_ = x[OBLOCK-113] | ||||||
| 	_ = x[OCASE-114] | 	_ = x[OBREAK-114] | ||||||
| 	_ = x[OCONTINUE-115] | 	_ = x[OCASE-115] | ||||||
| 	_ = x[ODEFER-116] | 	_ = x[OCONTINUE-116] | ||||||
| 	_ = x[OFALL-117] | 	_ = x[ODEFER-117] | ||||||
| 	_ = x[OFOR-118] | 	_ = x[OFALL-118] | ||||||
| 	_ = x[OFORUNTIL-119] | 	_ = x[OFOR-119] | ||||||
| 	_ = x[OGOTO-120] | 	_ = x[OFORUNTIL-120] | ||||||
| 	_ = x[OIF-121] | 	_ = x[OGOTO-121] | ||||||
| 	_ = x[OLABEL-122] | 	_ = x[OIF-122] | ||||||
| 	_ = x[OGO-123] | 	_ = x[OLABEL-123] | ||||||
| 	_ = x[ORANGE-124] | 	_ = x[OGO-124] | ||||||
| 	_ = x[ORETURN-125] | 	_ = x[ORANGE-125] | ||||||
| 	_ = x[OSELECT-126] | 	_ = x[ORETURN-126] | ||||||
| 	_ = x[OSWITCH-127] | 	_ = x[OSELECT-127] | ||||||
| 	_ = x[OTYPESW-128] | 	_ = x[OSWITCH-128] | ||||||
| 	_ = x[OFUNCINST-129] | 	_ = x[OTYPESW-129] | ||||||
| 	_ = x[OTCHAN-130] | 	_ = x[OFUNCINST-130] | ||||||
| 	_ = x[OTMAP-131] | 	_ = x[OTCHAN-131] | ||||||
| 	_ = x[OTSTRUCT-132] | 	_ = x[OTMAP-132] | ||||||
| 	_ = x[OTINTER-133] | 	_ = x[OTSTRUCT-133] | ||||||
| 	_ = x[OTFUNC-134] | 	_ = x[OTINTER-134] | ||||||
| 	_ = x[OTARRAY-135] | 	_ = x[OTFUNC-135] | ||||||
| 	_ = x[OTSLICE-136] | 	_ = x[OTARRAY-136] | ||||||
| 	_ = x[OINLCALL-137] | 	_ = x[OTSLICE-137] | ||||||
| 	_ = x[OEFACE-138] | 	_ = x[OINLCALL-138] | ||||||
| 	_ = x[OITAB-139] | 	_ = x[OEFACE-139] | ||||||
| 	_ = x[OIDATA-140] | 	_ = x[OITAB-140] | ||||||
| 	_ = x[OSPTR-141] | 	_ = x[OIDATA-141] | ||||||
| 	_ = x[OCFUNC-142] | 	_ = x[OSPTR-142] | ||||||
| 	_ = x[OCHECKNIL-143] | 	_ = x[OCFUNC-143] | ||||||
| 	_ = x[OVARDEF-144] | 	_ = x[OCHECKNIL-144] | ||||||
| 	_ = x[OVARKILL-145] | 	_ = x[OVARDEF-145] | ||||||
| 	_ = x[OVARLIVE-146] | 	_ = x[OVARKILL-146] | ||||||
| 	_ = x[ORESULT-147] | 	_ = x[OVARLIVE-147] | ||||||
| 	_ = x[OINLMARK-148] | 	_ = x[ORESULT-148] | ||||||
| 	_ = x[OLINKSYMOFFSET-149] | 	_ = x[OINLMARK-149] | ||||||
| 	_ = x[OTAILCALL-150] | 	_ = x[OLINKSYMOFFSET-150] | ||||||
| 	_ = x[OGETG-151] | 	_ = x[OTAILCALL-151] | ||||||
| 	_ = x[OEND-152] | 	_ = x[OGETG-152] | ||||||
|  | 	_ = x[OEND-153] | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const _Op_name = "XXXNAMENONAMETYPEPACKLITERALNILADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMAKESLICECOPYMULDIVMODLSHRSHANDANDNOTNEWNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECVRUNESTRSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFMETHEXPRSTMTEXPRBLOCKBREAKCASECONTINUEDEFERFALLFORFORUNTILGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWFUNCINSTTCHANTMAPTSTRUCTTINTERTFUNCTARRAYTSLICEINLCALLEFACEITABIDATASPTRCFUNCCHECKNILVARDEFVARKILLVARLIVERESULTINLMARKLINKSYMOFFSETTAILCALLGETGEND" | const _Op_name = "XXXNAMENONAMETYPEPACKLITERALNILADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESSLICE2ARRPTRASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMAKESLICECOPYMULDIVMODLSHRSHANDANDNOTNEWNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECVRUNESTRSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFMETHEXPRSTMTEXPRBLOCKBREAKCASECONTINUEDEFERFALLFORFORUNTILGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWFUNCINSTTCHANTMAPTSTRUCTTINTERTFUNCTARRAYTSLICEINLCALLEFACEITABIDATASPTRCFUNCCHECKNILVARDEFVARKILLVARLIVERESULTINLMARKLINKSYMOFFSETTAILCALLGETGEND" | ||||||
| 
 | 
 | ||||||
| var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 37, 39, 42, 48, 52, 58, 64, 73, 85, 94, 103, 115, 124, 126, 129, 139, 146, 153, 160, 164, 168, 176, 184, 193, 201, 204, 209, 216, 223, 229, 238, 246, 254, 260, 264, 273, 280, 284, 287, 294, 302, 309, 315, 318, 324, 331, 339, 343, 350, 358, 360, 362, 364, 366, 368, 370, 375, 380, 388, 391, 400, 403, 407, 415, 422, 431, 444, 447, 450, 453, 456, 459, 462, 468, 471, 474, 480, 484, 487, 491, 496, 501, 507, 512, 516, 521, 529, 537, 543, 552, 563, 570, 574, 581, 589, 593, 597, 601, 608, 615, 623, 629, 637, 645, 650, 655, 659, 667, 672, 676, 679, 687, 691, 693, 698, 700, 705, 711, 717, 723, 729, 737, 742, 746, 753, 759, 764, 770, 776, 783, 788, 792, 797, 801, 806, 814, 820, 827, 834, 840, 847, 860, 868, 872, 875} | var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 37, 39, 42, 48, 52, 58, 64, 73, 85, 94, 103, 115, 124, 136, 138, 141, 151, 158, 165, 172, 176, 180, 188, 196, 205, 213, 216, 221, 228, 235, 241, 250, 258, 266, 272, 276, 285, 292, 296, 299, 306, 314, 321, 327, 330, 336, 343, 351, 355, 362, 370, 372, 374, 376, 378, 380, 382, 387, 392, 400, 403, 412, 415, 419, 427, 434, 443, 456, 459, 462, 465, 468, 471, 474, 480, 483, 486, 492, 496, 499, 503, 508, 513, 519, 524, 528, 533, 541, 549, 555, 564, 575, 582, 586, 593, 601, 605, 609, 613, 620, 627, 635, 641, 649, 657, 662, 667, 671, 679, 684, 688, 691, 699, 703, 705, 710, 712, 717, 723, 729, 735, 741, 749, 754, 758, 765, 771, 776, 782, 788, 795, 800, 804, 809, 813, 818, 826, 832, 839, 846, 852, 859, 872, 880, 884, 887} | ||||||
| 
 | 
 | ||||||
| func (i Op) String() string { | func (i Op) String() string { | ||||||
| 	if i >= Op(len(_Op_index)-1) { | 	if i >= Op(len(_Op_index)-1) { | ||||||
|  |  | ||||||
|  | @ -508,7 +508,7 @@ func (x *expandState) rewriteSelect(leaf *Value, selector *Value, offset int64, | ||||||
| 		ls := x.rewriteSelect(leaf, selector.Args[0], offset, regOffset) | 		ls := x.rewriteSelect(leaf, selector.Args[0], offset, regOffset) | ||||||
| 		locs = x.splitSlots(ls, ".ptr", 0, x.typs.BytePtr) | 		locs = x.splitSlots(ls, ".ptr", 0, x.typs.BytePtr) | ||||||
| 
 | 
 | ||||||
| 	case OpSlicePtr: | 	case OpSlicePtr, OpSlicePtrUnchecked: | ||||||
| 		w := selector.Args[0] | 		w := selector.Args[0] | ||||||
| 		ls := x.rewriteSelect(leaf, w, offset, regOffset) | 		ls := x.rewriteSelect(leaf, w, offset, regOffset) | ||||||
| 		locs = x.splitSlots(ls, ".ptr", 0, types.NewPtr(w.Type.Elem())) | 		locs = x.splitSlots(ls, ".ptr", 0, types.NewPtr(w.Type.Elem())) | ||||||
|  | @ -1202,7 +1202,7 @@ func expandCalls(f *Func) { | ||||||
| 			case OpStructSelect, OpArraySelect, | 			case OpStructSelect, OpArraySelect, | ||||||
| 				OpIData, OpITab, | 				OpIData, OpITab, | ||||||
| 				OpStringPtr, OpStringLen, | 				OpStringPtr, OpStringLen, | ||||||
| 				OpSlicePtr, OpSliceLen, OpSliceCap, | 				OpSlicePtr, OpSliceLen, OpSliceCap, OpSlicePtrUnchecked, | ||||||
| 				OpComplexReal, OpComplexImag, | 				OpComplexReal, OpComplexImag, | ||||||
| 				OpInt64Hi, OpInt64Lo: | 				OpInt64Hi, OpInt64Lo: | ||||||
| 				w := v.Args[0] | 				w := v.Args[0] | ||||||
|  |  | ||||||
|  | @ -56,6 +56,7 @@ | ||||||
| (SlicePtr (SliceMake ptr _ _ )) => ptr | (SlicePtr (SliceMake ptr _ _ )) => ptr | ||||||
| (SliceLen (SliceMake _ len _)) => len | (SliceLen (SliceMake _ len _)) => len | ||||||
| (SliceCap (SliceMake _ _ cap)) => cap | (SliceCap (SliceMake _ _ cap)) => cap | ||||||
|  | (SlicePtrUnchecked (SliceMake ptr _ _ )) => ptr | ||||||
| 
 | 
 | ||||||
| (Load <t> ptr mem) && t.IsSlice() => | (Load <t> ptr mem) && t.IsSlice() => | ||||||
|   (SliceMake |   (SliceMake | ||||||
|  |  | ||||||
|  | @ -479,6 +479,10 @@ var genericOps = []opData{ | ||||||
| 	{name: "SlicePtr", argLength: 1, typ: "BytePtr"}, // ptr(arg0) | 	{name: "SlicePtr", argLength: 1, typ: "BytePtr"}, // ptr(arg0) | ||||||
| 	{name: "SliceLen", argLength: 1},                 // len(arg0) | 	{name: "SliceLen", argLength: 1},                 // len(arg0) | ||||||
| 	{name: "SliceCap", argLength: 1},                 // cap(arg0) | 	{name: "SliceCap", argLength: 1},                 // cap(arg0) | ||||||
|  | 	// SlicePtrUnchecked, like SlicePtr, extracts the pointer from a slice. | ||||||
|  | 	// SlicePtr values are assumed non-nil, because they are guarded by bounds checks. | ||||||
|  | 	// SlicePtrUnchecked values can be nil. | ||||||
|  | 	{name: "SlicePtrUnchecked", argLength: 1}, | ||||||
| 
 | 
 | ||||||
| 	// Complex (part/whole) | 	// Complex (part/whole) | ||||||
| 	{name: "ComplexMake", argLength: 2}, // arg0=real, arg1=imag | 	{name: "ComplexMake", argLength: 2}, // arg0=real, arg1=imag | ||||||
|  |  | ||||||
|  | @ -469,6 +469,7 @@ const ( | ||||||
| 	BoundsSlice3BU                      // ... with unsigned high | 	BoundsSlice3BU                      // ... with unsigned high | ||||||
| 	BoundsSlice3C                       // 3-arg slicing operation, 0 <= low <= high failed | 	BoundsSlice3C                       // 3-arg slicing operation, 0 <= low <= high failed | ||||||
| 	BoundsSlice3CU                      // ... with unsigned low | 	BoundsSlice3CU                      // ... with unsigned low | ||||||
|  | 	BoundsConvert                       // conversion to array pointer failed | ||||||
| 	BoundsKindCount | 	BoundsKindCount | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | @ -496,7 +497,8 @@ func boundsABI(b int64) int { | ||||||
| 	case BoundsSlice3Alen, | 	case BoundsSlice3Alen, | ||||||
| 		BoundsSlice3AlenU, | 		BoundsSlice3AlenU, | ||||||
| 		BoundsSlice3Acap, | 		BoundsSlice3Acap, | ||||||
| 		BoundsSlice3AcapU: | 		BoundsSlice3AcapU, | ||||||
|  | 		BoundsConvert: | ||||||
| 		return 0 | 		return 0 | ||||||
| 	case BoundsSliceAlen, | 	case BoundsSliceAlen, | ||||||
| 		BoundsSliceAlenU, | 		BoundsSliceAlenU, | ||||||
|  |  | ||||||
|  | @ -2834,6 +2834,7 @@ const ( | ||||||
| 	OpSlicePtr | 	OpSlicePtr | ||||||
| 	OpSliceLen | 	OpSliceLen | ||||||
| 	OpSliceCap | 	OpSliceCap | ||||||
|  | 	OpSlicePtrUnchecked | ||||||
| 	OpComplexMake | 	OpComplexMake | ||||||
| 	OpComplexReal | 	OpComplexReal | ||||||
| 	OpComplexImag | 	OpComplexImag | ||||||
|  | @ -35898,6 +35899,11 @@ var opcodeTable = [...]opInfo{ | ||||||
| 		argLen:  1, | 		argLen:  1, | ||||||
| 		generic: true, | 		generic: true, | ||||||
| 	}, | 	}, | ||||||
|  | 	{ | ||||||
|  | 		name:    "SlicePtrUnchecked", | ||||||
|  | 		argLen:  1, | ||||||
|  | 		generic: true, | ||||||
|  | 	}, | ||||||
| 	{ | 	{ | ||||||
| 		name:    "ComplexMake", | 		name:    "ComplexMake", | ||||||
| 		argLen:  2, | 		argLen:  2, | ||||||
|  |  | ||||||
|  | @ -23,6 +23,8 @@ func rewriteValuedec(v *Value) bool { | ||||||
| 		return rewriteValuedec_OpSliceLen(v) | 		return rewriteValuedec_OpSliceLen(v) | ||||||
| 	case OpSlicePtr: | 	case OpSlicePtr: | ||||||
| 		return rewriteValuedec_OpSlicePtr(v) | 		return rewriteValuedec_OpSlicePtr(v) | ||||||
|  | 	case OpSlicePtrUnchecked: | ||||||
|  | 		return rewriteValuedec_OpSlicePtrUnchecked(v) | ||||||
| 	case OpStore: | 	case OpStore: | ||||||
| 		return rewriteValuedec_OpStore(v) | 		return rewriteValuedec_OpStore(v) | ||||||
| 	case OpStringLen: | 	case OpStringLen: | ||||||
|  | @ -248,6 +250,20 @@ func rewriteValuedec_OpSlicePtr(v *Value) bool { | ||||||
| 	} | 	} | ||||||
| 	return false | 	return false | ||||||
| } | } | ||||||
|  | func rewriteValuedec_OpSlicePtrUnchecked(v *Value) bool { | ||||||
|  | 	v_0 := v.Args[0] | ||||||
|  | 	// match: (SlicePtrUnchecked (SliceMake ptr _ _ )) | ||||||
|  | 	// result: ptr | ||||||
|  | 	for { | ||||||
|  | 		if v_0.Op != OpSliceMake { | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 		ptr := v_0.Args[0] | ||||||
|  | 		v.copyOf(ptr) | ||||||
|  | 		return true | ||||||
|  | 	} | ||||||
|  | 	return false | ||||||
|  | } | ||||||
| func rewriteValuedec_OpStore(v *Value) bool { | func rewriteValuedec_OpStore(v *Value) bool { | ||||||
| 	v_2 := v.Args[2] | 	v_2 := v.Args[2] | ||||||
| 	v_1 := v.Args[1] | 	v_1 := v.Args[1] | ||||||
|  |  | ||||||
|  | @ -164,6 +164,7 @@ func InitConfig() { | ||||||
| 		BoundsCheckFunc[ssa.BoundsSlice3BU] = typecheck.LookupRuntimeFunc("goPanicSlice3BU") | 		BoundsCheckFunc[ssa.BoundsSlice3BU] = typecheck.LookupRuntimeFunc("goPanicSlice3BU") | ||||||
| 		BoundsCheckFunc[ssa.BoundsSlice3C] = typecheck.LookupRuntimeFunc("goPanicSlice3C") | 		BoundsCheckFunc[ssa.BoundsSlice3C] = typecheck.LookupRuntimeFunc("goPanicSlice3C") | ||||||
| 		BoundsCheckFunc[ssa.BoundsSlice3CU] = typecheck.LookupRuntimeFunc("goPanicSlice3CU") | 		BoundsCheckFunc[ssa.BoundsSlice3CU] = typecheck.LookupRuntimeFunc("goPanicSlice3CU") | ||||||
|  | 		BoundsCheckFunc[ssa.BoundsConvert] = typecheck.LookupRuntimeFunc("goPanicSliceConvert") | ||||||
| 	} else { | 	} else { | ||||||
| 		BoundsCheckFunc[ssa.BoundsIndex] = typecheck.LookupRuntimeFunc("panicIndex") | 		BoundsCheckFunc[ssa.BoundsIndex] = typecheck.LookupRuntimeFunc("panicIndex") | ||||||
| 		BoundsCheckFunc[ssa.BoundsIndexU] = typecheck.LookupRuntimeFunc("panicIndexU") | 		BoundsCheckFunc[ssa.BoundsIndexU] = typecheck.LookupRuntimeFunc("panicIndexU") | ||||||
|  | @ -181,6 +182,7 @@ func InitConfig() { | ||||||
| 		BoundsCheckFunc[ssa.BoundsSlice3BU] = typecheck.LookupRuntimeFunc("panicSlice3BU") | 		BoundsCheckFunc[ssa.BoundsSlice3BU] = typecheck.LookupRuntimeFunc("panicSlice3BU") | ||||||
| 		BoundsCheckFunc[ssa.BoundsSlice3C] = typecheck.LookupRuntimeFunc("panicSlice3C") | 		BoundsCheckFunc[ssa.BoundsSlice3C] = typecheck.LookupRuntimeFunc("panicSlice3C") | ||||||
| 		BoundsCheckFunc[ssa.BoundsSlice3CU] = typecheck.LookupRuntimeFunc("panicSlice3CU") | 		BoundsCheckFunc[ssa.BoundsSlice3CU] = typecheck.LookupRuntimeFunc("panicSlice3CU") | ||||||
|  | 		BoundsCheckFunc[ssa.BoundsConvert] = typecheck.LookupRuntimeFunc("panicSliceConvert") | ||||||
| 	} | 	} | ||||||
| 	if Arch.LinkArch.PtrSize == 4 { | 	if Arch.LinkArch.PtrSize == 4 { | ||||||
| 		ExtendCheckFunc[ssa.BoundsIndex] = typecheck.LookupRuntimeVar("panicExtendIndex") | 		ExtendCheckFunc[ssa.BoundsIndex] = typecheck.LookupRuntimeVar("panicExtendIndex") | ||||||
|  | @ -3148,6 +3150,18 @@ func (s *state) expr(n ir.Node) *ssa.Value { | ||||||
| 		p, l, _ := s.slice(v, i, j, nil, n.Bounded()) | 		p, l, _ := s.slice(v, i, j, nil, n.Bounded()) | ||||||
| 		return s.newValue2(ssa.OpStringMake, n.Type(), p, l) | 		return s.newValue2(ssa.OpStringMake, n.Type(), p, l) | ||||||
| 
 | 
 | ||||||
|  | 	case ir.OSLICE2ARRPTR: | ||||||
|  | 		// if arrlen > slice.len { | ||||||
|  | 		//   panic(...) | ||||||
|  | 		// } | ||||||
|  | 		// slice.ptr | ||||||
|  | 		n := n.(*ir.ConvExpr) | ||||||
|  | 		v := s.expr(n.X) | ||||||
|  | 		arrlen := s.constInt(types.Types[types.TINT], n.Type().Elem().NumElem()) | ||||||
|  | 		cap := s.newValue1(ssa.OpSliceLen, types.Types[types.TINT], v) | ||||||
|  | 		s.boundsCheck(arrlen, cap, ssa.BoundsConvert, false) | ||||||
|  | 		return s.newValue1(ssa.OpSlicePtrUnchecked, types.Types[types.TINT], v) | ||||||
|  | 
 | ||||||
| 	case ir.OCALLFUNC: | 	case ir.OCALLFUNC: | ||||||
| 		n := n.(*ir.CallExpr) | 		n := n.(*ir.CallExpr) | ||||||
| 		if ir.IsIntrinsicCall(n) { | 		if ir.IsIntrinsicCall(n) { | ||||||
|  |  | ||||||
|  | @ -39,6 +39,7 @@ var runtimeDecls = [...]struct { | ||||||
| 	{"goPanicSlice3BU", funcTag, 18}, | 	{"goPanicSlice3BU", funcTag, 18}, | ||||||
| 	{"goPanicSlice3C", funcTag, 16}, | 	{"goPanicSlice3C", funcTag, 16}, | ||||||
| 	{"goPanicSlice3CU", funcTag, 18}, | 	{"goPanicSlice3CU", funcTag, 18}, | ||||||
|  | 	{"goPanicSliceConvert", funcTag, 16}, | ||||||
| 	{"printbool", funcTag, 19}, | 	{"printbool", funcTag, 19}, | ||||||
| 	{"printfloat", funcTag, 21}, | 	{"printfloat", funcTag, 21}, | ||||||
| 	{"printint", funcTag, 23}, | 	{"printint", funcTag, 23}, | ||||||
|  |  | ||||||
|  | @ -46,6 +46,7 @@ func goPanicSlice3B(x int, y int) | ||||||
| func goPanicSlice3BU(x uint, y int) | func goPanicSlice3BU(x uint, y int) | ||||||
| func goPanicSlice3C(x int, y int) | func goPanicSlice3C(x int, y int) | ||||||
| func goPanicSlice3CU(x uint, y int) | func goPanicSlice3CU(x uint, y int) | ||||||
|  | func goPanicSliceConvert(x int, y int) | ||||||
| 
 | 
 | ||||||
| func printbool(bool) | func printbool(bool) | ||||||
| func printfloat(float64) | func printfloat(float64) | ||||||
|  |  | ||||||
|  | @ -574,7 +574,7 @@ func Convertop(srcConstant bool, src, dst *types.Type) (ir.Op, string) { | ||||||
| 		return ir.OCONVNOP, "" | 		return ir.OCONVNOP, "" | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// src is map and dst is a pointer to corresponding hmap. | 	// 10. src is map and dst is a pointer to corresponding hmap. | ||||||
| 	// This rule is needed for the implementation detail that | 	// This rule is needed for the implementation detail that | ||||||
| 	// go gc maps are implemented as a pointer to a hmap struct. | 	// go gc maps are implemented as a pointer to a hmap struct. | ||||||
| 	if src.Kind() == types.TMAP && dst.IsPtr() && | 	if src.Kind() == types.TMAP && dst.IsPtr() && | ||||||
|  | @ -582,6 +582,16 @@ func Convertop(srcConstant bool, src, dst *types.Type) (ir.Op, string) { | ||||||
| 		return ir.OCONVNOP, "" | 		return ir.OCONVNOP, "" | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	// 11. src is a slice and dst is a pointer-to-array. | ||||||
|  | 	// They must have same element type. | ||||||
|  | 	if src.IsSlice() && dst.IsPtr() && dst.Elem().IsArray() && | ||||||
|  | 		types.Identical(src.Elem(), dst.Elem().Elem()) { | ||||||
|  | 		if !types.AllowsGoVersion(curpkg(), 1, 17) { | ||||||
|  | 			return ir.OXXX, ":\n\tconversion of slices to array pointers only supported as of -lang=go1.17" | ||||||
|  | 		} | ||||||
|  | 		return ir.OSLICE2ARRPTR, "" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	return ir.OXXX, "" | 	return ir.OXXX, "" | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1578,6 +1578,9 @@ func TestConvertibleTo(t *testing.T) { | ||||||
| 		{newDefined(new(Struct)), new(Struct), true}, | 		{newDefined(new(Struct)), new(Struct), true}, | ||||||
| 		{newDefined(Typ[Int]), new(Struct), false}, | 		{newDefined(Typ[Int]), new(Struct), false}, | ||||||
| 		{Typ[UntypedInt], Typ[Int], true}, | 		{Typ[UntypedInt], Typ[Int], true}, | ||||||
|  | 		{NewSlice(Typ[Int]), NewPointer(NewArray(Typ[Int], 10)), true}, | ||||||
|  | 		{NewSlice(Typ[Int]), NewArray(Typ[Int], 10), false}, | ||||||
|  | 		{NewSlice(Typ[Int]), NewPointer(NewArray(Typ[Uint], 10)), false}, | ||||||
| 		// Untyped string values are not permitted by the spec, so the below | 		// Untyped string values are not permitted by the spec, so the below | ||||||
| 		// behavior is undefined. | 		// behavior is undefined. | ||||||
| 		{Typ[UntypedString], Typ[String], true}, | 		{Typ[UntypedString], Typ[String], true}, | ||||||
|  |  | ||||||
|  | @ -135,6 +135,18 @@ func (x *operand) convertibleTo(check *Checker, T Type) bool { | ||||||
| 		return true | 		return true | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	// "x is a slice, T is a pointer-to-array type, | ||||||
|  | 	// and the slice and array types have identical element types." | ||||||
|  | 	if s := asSlice(V); s != nil { | ||||||
|  | 		if p := asPointer(T); p != nil { | ||||||
|  | 			if a := asArray(p.Elem()); a != nil { | ||||||
|  | 				if check.identical(s.Elem(), a.Elem()) { | ||||||
|  | 					return true | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	return false | 	return false | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -205,6 +205,11 @@ func walkExpr1(n ir.Node, init *ir.Nodes) ir.Node { | ||||||
| 		n := n.(*ir.ConvExpr) | 		n := n.(*ir.ConvExpr) | ||||||
| 		return walkConv(n, init) | 		return walkConv(n, init) | ||||||
| 
 | 
 | ||||||
|  | 	case ir.OSLICE2ARRPTR: | ||||||
|  | 		n := n.(*ir.ConvExpr) | ||||||
|  | 		n.X = walkExpr(n.X, init) | ||||||
|  | 		return n | ||||||
|  | 
 | ||||||
| 	case ir.ODIV, ir.OMOD: | 	case ir.ODIV, ir.OMOD: | ||||||
| 		n := n.(*ir.BinaryExpr) | 		n := n.(*ir.BinaryExpr) | ||||||
| 		return walkDivMod(n, init) | 		return walkDivMod(n, init) | ||||||
|  |  | ||||||
|  | @ -163,6 +163,10 @@ func TestStdTest(t *testing.T) { | ||||||
| 		"embedfunc.go",   // tests //go:embed | 		"embedfunc.go",   // tests //go:embed | ||||||
| 		"embedvers.go",   // tests //go:embed | 		"embedvers.go",   // tests //go:embed | ||||||
| 		"linkname2.go",   // go/types doesn't check validity of //go:xxx directives | 		"linkname2.go",   // go/types doesn't check validity of //go:xxx directives | ||||||
|  | 
 | ||||||
|  | 		"convert2.go",     // temporary: go/types doesn't know yet about converting from slices to array pointers | ||||||
|  | 		"convert4.go",     // temporary: go/types doesn't know yet about converting from slices to array pointers | ||||||
|  | 		"escape_slice.go", // temporary: go/types doesn't know yet about converting from slices to array pointers | ||||||
| 	) | 	) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1473,6 +1473,10 @@ TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-8 | ||||||
| 	MOVL	AX, x+0(FP) | 	MOVL	AX, x+0(FP) | ||||||
| 	MOVL	CX, y+4(FP) | 	MOVL	CX, y+4(FP) | ||||||
| 	JMP	runtime·goPanicSlice3CU(SB) | 	JMP	runtime·goPanicSlice3CU(SB) | ||||||
|  | TEXT runtime·panicSliceConvert(SB),NOSPLIT,$0-8 | ||||||
|  | 	MOVL	DX, x+0(FP) | ||||||
|  | 	MOVL	BX, y+4(FP) | ||||||
|  | 	JMP	runtime·goPanicSliceConvert(SB) | ||||||
| 
 | 
 | ||||||
| // Extended versions for 64-bit indexes. | // Extended versions for 64-bit indexes. | ||||||
| TEXT runtime·panicExtendIndex(SB),NOSPLIT,$0-12 | TEXT runtime·panicExtendIndex(SB),NOSPLIT,$0-12 | ||||||
|  |  | ||||||
|  | @ -2091,6 +2091,14 @@ TEXT runtime·panicSlice3CU<ABIInternal>(SB),NOSPLIT,$0-16 | ||||||
| 	MOVQ	CX, y+8(FP) | 	MOVQ	CX, y+8(FP) | ||||||
| #endif | #endif | ||||||
| 	JMP	runtime·goPanicSlice3CU<ABIInternal>(SB) | 	JMP	runtime·goPanicSlice3CU<ABIInternal>(SB) | ||||||
|  | TEXT runtime·panicSliceConvert<ABIInternal>(SB),NOSPLIT,$0-16 | ||||||
|  | #ifdef GOEXPERIMENT_regabiargs | ||||||
|  | 	MOVQ	DX, AX | ||||||
|  | #else | ||||||
|  | 	MOVQ	DX, x+0(FP) | ||||||
|  | 	MOVQ	BX, y+8(FP) | ||||||
|  | #endif | ||||||
|  | 	JMP	runtime·goPanicSliceConvert<ABIInternal>(SB) | ||||||
| 
 | 
 | ||||||
| #ifdef GOOS_android | #ifdef GOOS_android | ||||||
| // Use the free TLS_SLOT_APP slot #2 on Android Q. | // Use the free TLS_SLOT_APP slot #2 on Android Q. | ||||||
|  |  | ||||||
|  | @ -992,6 +992,10 @@ TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-8 | ||||||
| 	MOVW	R0, x+0(FP) | 	MOVW	R0, x+0(FP) | ||||||
| 	MOVW	R1, y+4(FP) | 	MOVW	R1, y+4(FP) | ||||||
| 	JMP	runtime·goPanicSlice3CU(SB) | 	JMP	runtime·goPanicSlice3CU(SB) | ||||||
|  | TEXT runtime·panicSliceConvert(SB),NOSPLIT,$0-8 | ||||||
|  | 	MOVW	R2, x+0(FP) | ||||||
|  | 	MOVW	R3, y+4(FP) | ||||||
|  | 	JMP	runtime·goPanicSliceConvert(SB) | ||||||
| 
 | 
 | ||||||
| // Extended versions for 64-bit indexes. | // Extended versions for 64-bit indexes. | ||||||
| TEXT runtime·panicExtendIndex(SB),NOSPLIT,$0-12 | TEXT runtime·panicExtendIndex(SB),NOSPLIT,$0-12 | ||||||
|  |  | ||||||
|  | @ -1314,3 +1314,7 @@ TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-16 | ||||||
| 	MOVD	R0, x+0(FP) | 	MOVD	R0, x+0(FP) | ||||||
| 	MOVD	R1, y+8(FP) | 	MOVD	R1, y+8(FP) | ||||||
| 	JMP	runtime·goPanicSlice3CU(SB) | 	JMP	runtime·goPanicSlice3CU(SB) | ||||||
|  | TEXT runtime·panicSliceConvert(SB),NOSPLIT,$0-16 | ||||||
|  | 	MOVD	R2, x+0(FP) | ||||||
|  | 	MOVD	R3, y+8(FP) | ||||||
|  | 	JMP	runtime·goPanicSliceConvert(SB) | ||||||
|  |  | ||||||
|  | @ -805,3 +805,7 @@ TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-16 | ||||||
| 	MOVV	R1, x+0(FP) | 	MOVV	R1, x+0(FP) | ||||||
| 	MOVV	R2, y+8(FP) | 	MOVV	R2, y+8(FP) | ||||||
| 	JMP	runtime·goPanicSlice3CU(SB) | 	JMP	runtime·goPanicSlice3CU(SB) | ||||||
|  | TEXT runtime·panicSliceConvert(SB),NOSPLIT,$0-16 | ||||||
|  | 	MOVV	R3, x+0(FP) | ||||||
|  | 	MOVV	R4, y+8(FP) | ||||||
|  | 	JMP	runtime·goPanicSliceConvert(SB) | ||||||
|  |  | ||||||
|  | @ -801,6 +801,10 @@ TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-8 | ||||||
| 	MOVW	R1, x+0(FP) | 	MOVW	R1, x+0(FP) | ||||||
| 	MOVW	R2, y+4(FP) | 	MOVW	R2, y+4(FP) | ||||||
| 	JMP	runtime·goPanicSlice3CU(SB) | 	JMP	runtime·goPanicSlice3CU(SB) | ||||||
|  | TEXT runtime·panicSliceConvert(SB),NOSPLIT,$0-8 | ||||||
|  | 	MOVW	R3, x+0(FP) | ||||||
|  | 	MOVW	R4, y+4(FP) | ||||||
|  | 	JMP	runtime·goPanicSliceConvert(SB) | ||||||
| 
 | 
 | ||||||
| // Extended versions for 64-bit indexes. | // Extended versions for 64-bit indexes. | ||||||
| TEXT runtime·panicExtendIndex(SB),NOSPLIT,$0-12 | TEXT runtime·panicExtendIndex(SB),NOSPLIT,$0-12 | ||||||
|  |  | ||||||
|  | @ -1022,3 +1022,7 @@ TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-16 | ||||||
| 	MOVD	R3, x+0(FP) | 	MOVD	R3, x+0(FP) | ||||||
| 	MOVD	R4, y+8(FP) | 	MOVD	R4, y+8(FP) | ||||||
| 	JMP	runtime·goPanicSlice3CU(SB) | 	JMP	runtime·goPanicSlice3CU(SB) | ||||||
|  | TEXT runtime·panicSliceConvert(SB),NOSPLIT,$0-16 | ||||||
|  | 	MOVD	R5, x+0(FP) | ||||||
|  | 	MOVD	R6, y+8(FP) | ||||||
|  | 	JMP	runtime·goPanicSliceConvert(SB) | ||||||
|  |  | ||||||
|  | @ -806,6 +806,10 @@ TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-16 | ||||||
| 	MOV	T0, x+0(FP) | 	MOV	T0, x+0(FP) | ||||||
| 	MOV	T1, y+8(FP) | 	MOV	T1, y+8(FP) | ||||||
| 	JMP	runtime·goPanicSlice3CU(SB) | 	JMP	runtime·goPanicSlice3CU(SB) | ||||||
|  | TEXT runtime·panicSliceConvert(SB),NOSPLIT,$0-16 | ||||||
|  | 	MOV	T2, x+0(FP) | ||||||
|  | 	MOV	T3, y+8(FP) | ||||||
|  | 	JMP	runtime·goPanicSliceConvert(SB) | ||||||
| 
 | 
 | ||||||
| DATA	runtime·mainPC+0(SB)/8,$runtime·main(SB) | DATA	runtime·mainPC+0(SB)/8,$runtime·main(SB) | ||||||
| GLOBL	runtime·mainPC(SB),RODATA,$8 | GLOBL	runtime·mainPC(SB),RODATA,$8 | ||||||
|  |  | ||||||
|  | @ -906,3 +906,7 @@ TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-16 | ||||||
| 	MOVD	R0, x+0(FP) | 	MOVD	R0, x+0(FP) | ||||||
| 	MOVD	R1, y+8(FP) | 	MOVD	R1, y+8(FP) | ||||||
| 	JMP	runtime·goPanicSlice3CU(SB) | 	JMP	runtime·goPanicSlice3CU(SB) | ||||||
|  | TEXT runtime·panicSliceConvert(SB),NOSPLIT,$0-16 | ||||||
|  | 	MOVD	R2, x+0(FP) | ||||||
|  | 	MOVD	R3, y+8(FP) | ||||||
|  | 	JMP	runtime·goPanicSliceConvert(SB) | ||||||
|  |  | ||||||
|  | @ -134,6 +134,7 @@ const ( | ||||||
| 	boundsSlice3B    // s[?:x:y], 0 <= x <= y failed (but boundsSlice3A didn't happen) | 	boundsSlice3B    // s[?:x:y], 0 <= x <= y failed (but boundsSlice3A didn't happen) | ||||||
| 	boundsSlice3C    // s[x:y:?], 0 <= x <= y failed (but boundsSlice3A/B didn't happen) | 	boundsSlice3C    // s[x:y:?], 0 <= x <= y failed (but boundsSlice3A/B didn't happen) | ||||||
| 
 | 
 | ||||||
|  | 	boundsConvert // (*[x]T)(s), 0 <= x <= len(s) failed | ||||||
| 	// Note: in the above, len(s) and cap(s) are stored in y | 	// Note: in the above, len(s) and cap(s) are stored in y | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | @ -149,6 +150,7 @@ var boundsErrorFmts = [...]string{ | ||||||
| 	boundsSlice3Acap: "slice bounds out of range [::%x] with capacity %y", | 	boundsSlice3Acap: "slice bounds out of range [::%x] with capacity %y", | ||||||
| 	boundsSlice3B:    "slice bounds out of range [:%x:%y]", | 	boundsSlice3B:    "slice bounds out of range [:%x:%y]", | ||||||
| 	boundsSlice3C:    "slice bounds out of range [%x:%y:]", | 	boundsSlice3C:    "slice bounds out of range [%x:%y:]", | ||||||
|  | 	boundsConvert:    "cannot convert slice with length %y to pointer to array with length %x", | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // boundsNegErrorFmts are overriding formats if x is negative. In this case there's no need to report y. | // boundsNegErrorFmts are overriding formats if x is negative. In this case there's no need to report y. | ||||||
|  |  | ||||||
|  | @ -160,6 +160,12 @@ func goPanicSlice3CU(x uint, y int) { | ||||||
| 	panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSlice3C}) | 	panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSlice3C}) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // failures in the conversion (*[x]T)s, 0 <= x <= y, x == cap(s) | ||||||
|  | func goPanicSliceConvert(x int, y int) { | ||||||
|  | 	panicCheck1(getcallerpc(), "slice length too short to convert to pointer to array") | ||||||
|  | 	panic(boundsError{x: int64(x), signed: true, y: y, code: boundsConvert}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // Implemented in assembly, as they take arguments in registers. | // Implemented in assembly, as they take arguments in registers. | ||||||
| // Declared here to mark them as ABIInternal. | // Declared here to mark them as ABIInternal. | ||||||
| func panicIndex(x int, y int) | func panicIndex(x int, y int) | ||||||
|  | @ -178,6 +184,7 @@ func panicSlice3B(x int, y int) | ||||||
| func panicSlice3BU(x uint, y int) | func panicSlice3BU(x uint, y int) | ||||||
| func panicSlice3C(x int, y int) | func panicSlice3C(x int, y int) | ||||||
| func panicSlice3CU(x uint, y int) | func panicSlice3CU(x uint, y int) | ||||||
|  | func panicSliceConvert(x int, y int) | ||||||
| 
 | 
 | ||||||
| var shiftError = error(errorString("negative shift amount")) | var shiftError = error(errorString("negative shift amount")) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -313,3 +313,17 @@ func _() { | ||||||
| 	t = u       // ERROR "cannot use .* in assignment|incompatible type" | 	t = u       // ERROR "cannot use .* in assignment|incompatible type" | ||||||
| 	t = (*T)(u) // ERROR "cannot convert" | 	t = (*T)(u) // ERROR "cannot convert" | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func _() { | ||||||
|  | 	var s []byte | ||||||
|  | 	_ = ([4]byte)(s) // ERROR "cannot convert" | ||||||
|  | 	_ = (*[4]byte)(s) | ||||||
|  | 
 | ||||||
|  | 	type A [4]byte | ||||||
|  | 	_ = (A)(s) // ERROR "cannot convert" | ||||||
|  | 	_ = (*A)(s) | ||||||
|  | 
 | ||||||
|  | 	type P *[4]byte | ||||||
|  | 	_ = (P)(s) | ||||||
|  | 	_ = (*P)(s) // ERROR "cannot convert" | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										86
									
								
								test/convert4.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								test/convert4.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,86 @@ | ||||||
|  | // run | ||||||
|  | 
 | ||||||
|  | // Copyright 2020 The Go Authors. All rights reserved. | ||||||
|  | // Use of this source code is governed by a BSD-style | ||||||
|  | // license that can be found in the LICENSE file. | ||||||
|  | 
 | ||||||
|  | // Test conversion from slice to array pointer. | ||||||
|  | 
 | ||||||
|  | package main | ||||||
|  | 
 | ||||||
|  | func wantPanic(fn func(), s string) { | ||||||
|  | 	defer func() { | ||||||
|  | 		err := recover() | ||||||
|  | 		if err == nil { | ||||||
|  | 			panic("expected panic") | ||||||
|  | 		} | ||||||
|  | 		if got := err.(error).Error(); got != s { | ||||||
|  | 			panic("expected panic " + s + " got " + got) | ||||||
|  | 		} | ||||||
|  | 	}() | ||||||
|  | 	fn() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func main() { | ||||||
|  | 	s := make([]byte, 8, 10) | ||||||
|  | 	if p := (*[8]byte)(s); &p[0] != &s[0] { | ||||||
|  | 		panic("*[8]byte conversion failed") | ||||||
|  | 	} | ||||||
|  | 	wantPanic( | ||||||
|  | 		func() { | ||||||
|  | 			_ = (*[9]byte)(s) | ||||||
|  | 		}, | ||||||
|  | 		"runtime error: cannot convert slice with length 8 to pointer to array with length 9", | ||||||
|  | 	) | ||||||
|  | 
 | ||||||
|  | 	var n []byte | ||||||
|  | 	if p := (*[0]byte)(n); p != nil { | ||||||
|  | 		panic("nil slice converted to *[0]byte should be nil") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	z := make([]byte, 0) | ||||||
|  | 	if p := (*[0]byte)(z); p == nil { | ||||||
|  | 		panic("empty slice converted to *[0]byte should be non-nil") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Test with named types | ||||||
|  | 	type Slice []int | ||||||
|  | 	type Int4 [4]int | ||||||
|  | 	type PInt4 *[4]int | ||||||
|  | 	ii := make(Slice, 4) | ||||||
|  | 	if p := (*Int4)(ii); &p[0] != &ii[0] { | ||||||
|  | 		panic("*Int4 conversion failed") | ||||||
|  | 	} | ||||||
|  | 	if p := PInt4(ii); &p[0] != &ii[0] { | ||||||
|  | 		panic("PInt4 conversion failed") | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // test static variable conversion | ||||||
|  | 
 | ||||||
|  | var ( | ||||||
|  | 	ss  = make([]string, 10) | ||||||
|  | 	s5  = (*[5]string)(ss) | ||||||
|  | 	s10 = (*[10]string)(ss) | ||||||
|  | 
 | ||||||
|  | 	ns  []string | ||||||
|  | 	ns0 = (*[0]string)(ns) | ||||||
|  | 
 | ||||||
|  | 	zs  = make([]string, 0) | ||||||
|  | 	zs0 = (*[0]string)(zs) | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func init() { | ||||||
|  | 	if &ss[0] != &s5[0] { | ||||||
|  | 		panic("s5 conversion failed") | ||||||
|  | 	} | ||||||
|  | 	if &ss[0] != &s10[0] { | ||||||
|  | 		panic("s5 conversion failed") | ||||||
|  | 	} | ||||||
|  | 	if ns0 != nil { | ||||||
|  | 		panic("ns0 should be nil") | ||||||
|  | 	} | ||||||
|  | 	if zs0 == nil { | ||||||
|  | 		panic("zs0 should not be nil") | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -101,6 +101,10 @@ func slice11() { | ||||||
| 	_ = s | 	_ = s | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func slice12(x []int) *[1]int { // ERROR "leaking param: x to result ~r1 level=0$" | ||||||
|  | 	return (*[1]int)(x) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func envForDir(dir string) []string { // ERROR "dir does not escape" | func envForDir(dir string) []string { // ERROR "dir does not escape" | ||||||
| 	env := os.Environ() | 	env := os.Environ() | ||||||
| 	return mergeEnvLists([]string{"PWD=" + dir}, env) // ERROR ".PWD=. \+ dir escapes to heap" "\[\]string{...} does not escape" | 	return mergeEnvLists([]string{"PWD=" + dir}, env) // ERROR ".PWD=. \+ dir escapes to heap" "\[\]string{...} does not escape" | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Josh Bleecher Snyder
						Josh Bleecher Snyder