mirror of
https://github.com/golang/go.git
synced 2024-09-21 10:28:27 +00:00
cmd/gc: support x[i:j:k]
Design doc at golang.org/s/go12slice. This is an experimental feature and may not be included in the release. R=golang-dev, r CC=golang-dev https://golang.org/cl/10743046
This commit is contained in:
parent
493538adbf
commit
b4e92cee97
@ -34,6 +34,8 @@ cgen(Node *n, Node *res)
|
||||
case OSLICE:
|
||||
case OSLICEARR:
|
||||
case OSLICESTR:
|
||||
case OSLICE3:
|
||||
case OSLICE3ARR:
|
||||
if (res->op != ONAME || !res->addable) {
|
||||
tempname(&n1, n->type);
|
||||
cgen_slice(n, &n1);
|
||||
@ -629,6 +631,8 @@ agen(Node *n, Node *res)
|
||||
case OSLICE:
|
||||
case OSLICEARR:
|
||||
case OSLICESTR:
|
||||
case OSLICE3:
|
||||
case OSLICE3ARR:
|
||||
tempname(&n1, n->type);
|
||||
cgen_slice(n, &n1);
|
||||
agen(&n1, res);
|
||||
|
@ -37,6 +37,8 @@ cgen(Node *n, Node *res)
|
||||
case OSLICE:
|
||||
case OSLICEARR:
|
||||
case OSLICESTR:
|
||||
case OSLICE3:
|
||||
case OSLICE3ARR:
|
||||
if (res->op != ONAME || !res->addable) {
|
||||
tempname(&n1, n->type);
|
||||
cgen_slice(n, &n1);
|
||||
@ -841,6 +843,8 @@ agen(Node *n, Node *res)
|
||||
case OSLICE:
|
||||
case OSLICEARR:
|
||||
case OSLICESTR:
|
||||
case OSLICE3:
|
||||
case OSLICE3ARR:
|
||||
tempname(&n1, n->type);
|
||||
cgen_slice(n, &n1);
|
||||
agen(&n1, res);
|
||||
|
@ -67,6 +67,8 @@ cgen(Node *n, Node *res)
|
||||
case OSLICE:
|
||||
case OSLICEARR:
|
||||
case OSLICESTR:
|
||||
case OSLICE3:
|
||||
case OSLICE3ARR:
|
||||
if (res->op != ONAME || !res->addable) {
|
||||
tempname(&n1, n->type);
|
||||
cgen_slice(n, &n1);
|
||||
@ -547,6 +549,8 @@ agen(Node *n, Node *res)
|
||||
case OSLICE:
|
||||
case OSLICEARR:
|
||||
case OSLICESTR:
|
||||
case OSLICE3:
|
||||
case OSLICE3ARR:
|
||||
tempname(&n1, n->type);
|
||||
cgen_slice(n, &n1);
|
||||
agen(&n1, res);
|
||||
|
@ -749,6 +749,8 @@ escassign(EscState *e, Node *dst, Node *src)
|
||||
case ODOTTYPE2:
|
||||
case OSLICE:
|
||||
case OSLICEARR:
|
||||
case OSLICE3:
|
||||
case OSLICE3ARR:
|
||||
// Conversions, field access, slice all preserve the input value.
|
||||
escassign(e, dst, src->left);
|
||||
break;
|
||||
|
@ -1022,6 +1022,8 @@ static int opprec[] = {
|
||||
[OSLICE] = 8,
|
||||
[OSLICESTR] = 8,
|
||||
[OSLICEARR] = 8,
|
||||
[OSLICE3] = 8,
|
||||
[OSLICE3ARR] = 8,
|
||||
[ODOTINTER] = 8,
|
||||
[ODOTMETH] = 8,
|
||||
[ODOTPTR] = 8,
|
||||
@ -1295,6 +1297,8 @@ exprfmt(Fmt *f, Node *n, int prec)
|
||||
case OSLICE:
|
||||
case OSLICESTR:
|
||||
case OSLICEARR:
|
||||
case OSLICE3:
|
||||
case OSLICE3ARR:
|
||||
exprfmt(f, n->left, nprec);
|
||||
return fmtprint(f, "[%N]", n->right);
|
||||
|
||||
|
@ -520,6 +520,8 @@ enum
|
||||
OSLICE, // v[1:2], typechecking may convert to a more specfic OSLICEXXX.
|
||||
OSLICEARR, // a[1:2]
|
||||
OSLICESTR, // s[1:2]
|
||||
OSLICE3, // v[1:2:3], typechecking may convert to OSLICE3ARR.
|
||||
OSLICE3ARR, // a[1:2:3]
|
||||
ORECOVER, // recover
|
||||
ORECV, // <-c
|
||||
ORUNESTR, // string(i)
|
||||
|
@ -23,6 +23,8 @@
|
||||
#include <libc.h>
|
||||
#include "go.h"
|
||||
|
||||
static int isrelease = -1;
|
||||
|
||||
static void fixlbrace(int);
|
||||
%}
|
||||
%union {
|
||||
@ -950,6 +952,21 @@ pexpr_no_paren:
|
||||
{
|
||||
$$ = nod(OSLICE, $1, nod(OKEY, $3, $5));
|
||||
}
|
||||
| pexpr '[' oexpr ':' oexpr ':' oexpr ']'
|
||||
{
|
||||
// Make sure we don't accidentally release this experimental feature.
|
||||
// http://golang.org/s/go12slice.
|
||||
if(isrelease < 0)
|
||||
isrelease = strstr(getgoversion(), "release") != nil;
|
||||
if(isrelease)
|
||||
yyerror("3-index slice not available in release");
|
||||
|
||||
if($5 == N)
|
||||
yyerror("middle index required in 3-index slice");
|
||||
if($7 == N)
|
||||
yyerror("final index required in 3-index slice");
|
||||
$$ = nod(OSLICE3, $1, nod(OKEY, $3, nod(OKEY, $5, $7)));
|
||||
}
|
||||
| pseudocall
|
||||
| convtype '(' expr ocomma ')'
|
||||
{
|
||||
|
@ -304,6 +304,8 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
|
||||
|
||||
case OSLICE:
|
||||
case OSLICEARR:
|
||||
case OSLICE3:
|
||||
case OSLICE3ARR:
|
||||
// Seems to only lead to double instrumentation.
|
||||
//racewalknode(&n->left, init, 0, 0);
|
||||
goto ret;
|
||||
|
@ -33,6 +33,8 @@ static void stringtoarraylit(Node**);
|
||||
static Node* resolve(Node*);
|
||||
static void checkdefergo(Node*);
|
||||
static int checkmake(Type*, char*, Node*);
|
||||
static int checksliceindex(Node*, Type*);
|
||||
static int checksliceconst(Node*, Node*);
|
||||
|
||||
static NodeList* typecheckdefstack;
|
||||
|
||||
@ -303,7 +305,7 @@ static void
|
||||
typecheck1(Node **np, int top)
|
||||
{
|
||||
int et, aop, op, ptr;
|
||||
Node *n, *l, *r;
|
||||
Node *n, *l, *r, *lo, *mid, *hi;
|
||||
NodeList *args;
|
||||
int ok, ntop;
|
||||
Type *t, *tp, *missing, *have, *badtype;
|
||||
@ -993,54 +995,63 @@ reswitch:
|
||||
yyerror("cannot slice %N (type %T)", l, t);
|
||||
goto error;
|
||||
}
|
||||
if(n->right->left != N) {
|
||||
if((t = n->right->left->type) == T)
|
||||
goto error;
|
||||
if(!isint[t->etype]) {
|
||||
yyerror("invalid slice index %N (type %T)", n->right->left, t);
|
||||
if((lo = n->right->left) != N && checksliceindex(lo, tp) < 0)
|
||||
goto error;
|
||||
if((hi = n->right->right) != N && checksliceindex(hi, tp) < 0)
|
||||
goto error;
|
||||
if(checksliceconst(lo, hi) < 0)
|
||||
goto error;
|
||||
goto ret;
|
||||
|
||||
case OSLICE3:
|
||||
ok |= Erv;
|
||||
typecheck(&n->left, top);
|
||||
typecheck(&n->right->left, Erv);
|
||||
typecheck(&n->right->right->left, Erv);
|
||||
typecheck(&n->right->right->right, Erv);
|
||||
defaultlit(&n->left, T);
|
||||
indexlit(&n->right->left);
|
||||
indexlit(&n->right->right->left);
|
||||
indexlit(&n->right->right->right);
|
||||
l = n->left;
|
||||
if(isfixedarray(l->type)) {
|
||||
if(!islvalue(n->left)) {
|
||||
yyerror("invalid operation %N (slice of unaddressable value)", n);
|
||||
goto error;
|
||||
}
|
||||
if(n->right->left->op == OLITERAL) {
|
||||
if(mpgetfix(n->right->left->val.u.xval) < 0) {
|
||||
yyerror("invalid slice index %N (index must be non-negative)", n->right->left);
|
||||
goto error;
|
||||
} else if(tp != nil && tp->bound > 0 && mpgetfix(n->right->left->val.u.xval) > tp->bound) {
|
||||
yyerror("invalid slice index %N (out of bounds for %d-element array)", n->right->left, tp->bound);
|
||||
goto error;
|
||||
} else if(mpcmpfixfix(n->right->left->val.u.xval, maxintval[TINT]) > 0) {
|
||||
yyerror("invalid slice index %N (index too large)", n->right->left);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
n->left = nod(OADDR, n->left, N);
|
||||
n->left->implicit = 1;
|
||||
typecheck(&n->left, Erv);
|
||||
l = n->left;
|
||||
}
|
||||
if(n->right->right != N) {
|
||||
if((t = n->right->right->type) == T)
|
||||
goto error;
|
||||
if(!isint[t->etype]) {
|
||||
yyerror("invalid slice index %N (type %T)", n->right->right, t);
|
||||
goto error;
|
||||
}
|
||||
if(n->right->right->op == OLITERAL) {
|
||||
if(mpgetfix(n->right->right->val.u.xval) < 0) {
|
||||
yyerror("invalid slice index %N (index must be non-negative)", n->right->right);
|
||||
goto error;
|
||||
} else if(tp != nil && tp->bound > 0 && mpgetfix(n->right->right->val.u.xval) > tp->bound) {
|
||||
yyerror("invalid slice index %N (out of bounds for %d-element array)", n->right->right, tp->bound);
|
||||
goto error;
|
||||
} else if(mpcmpfixfix(n->right->right->val.u.xval, maxintval[TINT]) > 0) {
|
||||
yyerror("invalid slice index %N (index too large)", n->right->right);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(n->right->left != N
|
||||
&& n->right->right != N
|
||||
&& n->right->left->op == OLITERAL
|
||||
&& n->right->right->op == OLITERAL
|
||||
&& mpcmpfixfix(n->right->left->val.u.xval, n->right->right->val.u.xval) > 0) {
|
||||
yyerror("inverted slice index %N > %N", n->right->left, n->right->right);
|
||||
if((t = l->type) == T)
|
||||
goto error;
|
||||
tp = nil;
|
||||
if(istype(t, TSTRING)) {
|
||||
yyerror("invalid operation %N (3-index slice of string)", n);
|
||||
goto error;
|
||||
}
|
||||
if(isptr[t->etype] && isfixedarray(t->type)) {
|
||||
tp = t->type;
|
||||
n->type = typ(TARRAY);
|
||||
n->type->type = tp->type;
|
||||
n->type->bound = -1;
|
||||
dowidth(n->type);
|
||||
n->op = OSLICE3ARR;
|
||||
} else if(isslice(t)) {
|
||||
n->type = t;
|
||||
} else {
|
||||
yyerror("cannot slice %N (type %T)", l, t);
|
||||
goto error;
|
||||
}
|
||||
if((lo = n->right->left) != N && checksliceindex(lo, tp) < 0)
|
||||
goto error;
|
||||
if((mid = n->right->right->left) != N && checksliceindex(mid, tp) < 0)
|
||||
goto error;
|
||||
if((hi = n->right->right->right) != N && checksliceindex(hi, tp) < 0)
|
||||
goto error;
|
||||
if(checksliceconst(lo, hi) < 0 || checksliceconst(lo, mid) < 0 || checksliceconst(mid, hi) < 0)
|
||||
goto error;
|
||||
goto ret;
|
||||
|
||||
/*
|
||||
@ -1757,6 +1768,43 @@ out:
|
||||
*np = n;
|
||||
}
|
||||
|
||||
static int
|
||||
checksliceindex(Node *r, Type *tp)
|
||||
{
|
||||
Type *t;
|
||||
|
||||
if((t = r->type) == T)
|
||||
return -1;
|
||||
if(!isint[t->etype]) {
|
||||
yyerror("invalid slice index %N (type %T)", r, t);
|
||||
return -1;
|
||||
}
|
||||
if(r->op == OLITERAL) {
|
||||
if(mpgetfix(r->val.u.xval) < 0) {
|
||||
yyerror("invalid slice index %N (index must be non-negative)", r);
|
||||
return -1;
|
||||
} else if(tp != nil && tp->bound > 0 && mpgetfix(r->val.u.xval) > tp->bound) {
|
||||
yyerror("invalid slice index %N (out of bounds for %d-element array)", r, tp->bound);
|
||||
return -1;
|
||||
} else if(mpcmpfixfix(r->val.u.xval, maxintval[TINT]) > 0) {
|
||||
yyerror("invalid slice index %N (index too large)", r);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
checksliceconst(Node *lo, Node *hi)
|
||||
{
|
||||
if(lo != N && hi != N && lo->op == OLITERAL && hi->op == OLITERAL
|
||||
&& mpcmpfixfix(lo->val.u.xval, hi->val.u.xval) > 0) {
|
||||
yyerror("invalid slice index: %N > %N", lo, hi);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
checkdefergo(Node *n)
|
||||
{
|
||||
|
@ -1116,6 +1116,27 @@ walkexpr(Node **np, NodeList **init)
|
||||
n->right->right = safeexpr(n->right->right, init);
|
||||
n = sliceany(n, init); // chops n->right, sets n->list
|
||||
goto ret;
|
||||
|
||||
case OSLICE3:
|
||||
case OSLICE3ARR:
|
||||
if(n->right == N) // already processed
|
||||
goto ret;
|
||||
|
||||
walkexpr(&n->left, init);
|
||||
// TODO the OINDEX case is a bug elsewhere that needs to be traced. it causes a crash on ([2][]int{ ... })[1][lo:hi]
|
||||
// TODO the comment on the previous line was copied from case OSLICE. it might not even be true.
|
||||
if(n->left->op == OINDEX)
|
||||
n->left = copyexpr(n->left, n->left->type, init);
|
||||
else
|
||||
n->left = safeexpr(n->left, init);
|
||||
walkexpr(&n->right->left, init);
|
||||
n->right->left = safeexpr(n->right->left, init);
|
||||
walkexpr(&n->right->right->left, init);
|
||||
n->right->right->left = safeexpr(n->right->right->left, init);
|
||||
walkexpr(&n->right->right->right, init);
|
||||
n->right->right->right = safeexpr(n->right->right->right, init);
|
||||
n = sliceany(n, init); // chops n->right, sets n->list
|
||||
goto ret;
|
||||
|
||||
case OADDR:
|
||||
walkexpr(&n->left, init);
|
||||
@ -2575,21 +2596,28 @@ append(Node *n, NodeList **init)
|
||||
}
|
||||
|
||||
|
||||
// Generate frontend part for OSLICE[ARR|STR]
|
||||
// Generate frontend part for OSLICE[3][ARR|STR]
|
||||
//
|
||||
static Node*
|
||||
sliceany(Node* n, NodeList **init)
|
||||
{
|
||||
int bounded;
|
||||
Node *src, *lb, *hb, *bound, *chk, *chk1, *chk2;
|
||||
int64 lbv, hbv, bv, w;
|
||||
int bounded, slice3;
|
||||
Node *src, *lb, *hb, *cb, *bound, *chk, *chk0, *chk1, *chk2;
|
||||
int64 lbv, hbv, cbv, bv, w;
|
||||
Type *bt;
|
||||
|
||||
// print("before sliceany: %+N\n", n);
|
||||
|
||||
src = n->left;
|
||||
lb = n->right->left;
|
||||
hb = n->right->right;
|
||||
slice3 = n->op == OSLICE3 || n->op == OSLICE3ARR;
|
||||
if(slice3) {
|
||||
hb = n->right->right->left;
|
||||
cb = n->right->right->right;
|
||||
} else {
|
||||
hb = n->right->right;
|
||||
cb = hb;
|
||||
}
|
||||
|
||||
bounded = n->etype;
|
||||
|
||||
@ -2610,6 +2638,13 @@ sliceany(Node* n, NodeList **init)
|
||||
bv = mpgetfix(bound->val.u.xval);
|
||||
}
|
||||
|
||||
if(isconst(cb, CTINT)) {
|
||||
cbv = mpgetfix(cb->val.u.xval);
|
||||
if(cbv < 0 || cbv > bv) {
|
||||
yyerror("slice index out of bounds");
|
||||
cbv = -1;
|
||||
}
|
||||
}
|
||||
if(isconst(hb, CTINT)) {
|
||||
hbv = mpgetfix(hb->val.u.xval);
|
||||
if(hbv < 0 || hbv > bv) {
|
||||
@ -2631,10 +2666,13 @@ sliceany(Node* n, NodeList **init)
|
||||
// generate
|
||||
// if hb > bound || lb > hb { panicslice() }
|
||||
chk = N;
|
||||
chk0 = N;
|
||||
chk1 = N;
|
||||
chk2 = N;
|
||||
|
||||
bt = types[simtype[TUINT]];
|
||||
if(cb != N && cb->type->width > 4)
|
||||
bt = types[TUINT64];
|
||||
if(hb != N && hb->type->width > 4)
|
||||
bt = types[TUINT64];
|
||||
if(lb != N && lb->type->width > 4)
|
||||
@ -2642,10 +2680,26 @@ sliceany(Node* n, NodeList **init)
|
||||
|
||||
bound = cheapexpr(conv(bound, bt), init);
|
||||
|
||||
if(cb != N) {
|
||||
cb = cheapexpr(conv(cb, bt), init);
|
||||
if(!bounded)
|
||||
chk0 = nod(OLT, bound, cb);
|
||||
} else if(slice3) {
|
||||
// When we figure out what this means, implement it.
|
||||
fatal("slice3 with cb == N"); // rejected by parser
|
||||
}
|
||||
|
||||
if(hb != N) {
|
||||
hb = cheapexpr(conv(hb, bt), init);
|
||||
if(!bounded)
|
||||
chk1 = nod(OLT, bound, hb);
|
||||
if(!bounded) {
|
||||
if(cb != N)
|
||||
chk1 = nod(OLT, cb, hb);
|
||||
else
|
||||
chk1 = nod(OLT, bound, hb);
|
||||
}
|
||||
} else if(slice3) {
|
||||
// When we figure out what this means, implement it.
|
||||
fatal("slice3 with hb == N"); // rejected by parser
|
||||
} else if(n->op == OSLICEARR) {
|
||||
hb = bound;
|
||||
} else {
|
||||
@ -2661,11 +2715,17 @@ sliceany(Node* n, NodeList **init)
|
||||
chk2 = nod(OLT, hb, lb);
|
||||
}
|
||||
|
||||
if(chk1 != N || chk2 != N) {
|
||||
if(chk0 != N || chk1 != N || chk2 != N) {
|
||||
chk = nod(OIF, N, N);
|
||||
chk->nbody = list1(mkcall("panicslice", T, init));
|
||||
if(chk1 != N)
|
||||
chk->ntest = chk1;
|
||||
if(chk0 != N)
|
||||
chk->ntest = chk0;
|
||||
if(chk1 != N) {
|
||||
if(chk->ntest == N)
|
||||
chk->ntest = chk1;
|
||||
else
|
||||
chk->ntest = nod(OOROR, chk->ntest, chk1);
|
||||
}
|
||||
if(chk2 != N) {
|
||||
if(chk->ntest == N)
|
||||
chk->ntest = chk2;
|
||||
@ -2683,10 +2743,12 @@ sliceany(Node* n, NodeList **init)
|
||||
// cap = bound [ - lo ]
|
||||
n->right = N;
|
||||
n->list = nil;
|
||||
if(!slice3)
|
||||
cb = bound;
|
||||
if(lb == N)
|
||||
bound = conv(bound, types[simtype[TUINT]]);
|
||||
bound = conv(cb, types[simtype[TUINT]]);
|
||||
else
|
||||
bound = nod(OSUB, conv(bound, types[simtype[TUINT]]), conv(lb, types[simtype[TUINT]]));
|
||||
bound = nod(OSUB, conv(cb, types[simtype[TUINT]]), conv(lb, types[simtype[TUINT]]));
|
||||
typecheck(&bound, Erv);
|
||||
walkexpr(&bound, init);
|
||||
n->list = list(n->list, bound);
|
||||
|
2190
src/cmd/gc/y.tab.c
2190
src/cmd/gc/y.tab.c
File diff suppressed because it is too large
Load Diff
@ -74,6 +74,6 @@ static struct {
|
||||
112, LNAME,
|
||||
"nested func not allowed",
|
||||
|
||||
642, ';',
|
||||
644, ';',
|
||||
"else must be followed by if or statement block"
|
||||
};
|
||||
|
@ -9,13 +9,13 @@
|
||||
package p
|
||||
|
||||
func F1(s []byte) []byte {
|
||||
return s[2:1] // ERROR "inverted"
|
||||
return s[2:1] // ERROR "invalid slice index"
|
||||
}
|
||||
|
||||
func F2(a [10]byte) []byte {
|
||||
return a[2:1] // ERROR "inverted"
|
||||
return a[2:1] // ERROR "invalid slice index"
|
||||
}
|
||||
|
||||
func F3(s string) string {
|
||||
return s[2:1] // ERROR "inverted"
|
||||
return s[2:1] // ERROR "invalid slice index"
|
||||
}
|
||||
|
156
test/slice3.go
Normal file
156
test/slice3.go
Normal file
@ -0,0 +1,156 @@
|
||||
// runoutput
|
||||
|
||||
// Copyright 2013 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 run-time behavior of 3-index slice expressions.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
var bout *bufio.Writer
|
||||
|
||||
func main() {
|
||||
bout = bufio.NewWriter(os.Stdout)
|
||||
|
||||
fmt.Fprintf(bout, "%s", programTop)
|
||||
fmt.Fprintf(bout, "func main() {\n")
|
||||
|
||||
index := []string{
|
||||
"0",
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"10",
|
||||
"20",
|
||||
"vminus1",
|
||||
"v0",
|
||||
"v1",
|
||||
"v2",
|
||||
"v3",
|
||||
"v10",
|
||||
"v20",
|
||||
}
|
||||
|
||||
parse := func(s string) (n int, isconst bool) {
|
||||
if s == "vminus1" {
|
||||
return -1, false
|
||||
}
|
||||
isconst = true
|
||||
if s[0] == 'v' {
|
||||
isconst = false
|
||||
s = s[1:]
|
||||
}
|
||||
n, _ = strconv.Atoi(s)
|
||||
return n, isconst
|
||||
}
|
||||
|
||||
const Cap = 10 // cap of slice, array
|
||||
|
||||
for _, base := range []string{"array", "slice"} {
|
||||
for _, i := range index {
|
||||
iv, iconst := parse(i)
|
||||
for _, j := range index {
|
||||
jv, jconst := parse(j)
|
||||
for _, k := range index {
|
||||
kv, kconst := parse(k)
|
||||
// Avoid errors that would make the program not compile.
|
||||
// Those are tested by slice3err.go.
|
||||
switch {
|
||||
case iconst && jconst && iv > jv,
|
||||
jconst && kconst && jv > kv,
|
||||
iconst && kconst && iv > kv,
|
||||
iconst && base == "array" && iv > Cap,
|
||||
jconst && base == "array" && jv > Cap,
|
||||
kconst && base == "array" && kv > Cap:
|
||||
continue
|
||||
}
|
||||
|
||||
expr := base + "[" + i + ":" + j + ":" + k + "]"
|
||||
var xbase, xlen, xcap int
|
||||
if iv > jv || jv > kv || kv > Cap || iv < 0 || jv < 0 || kv < 0 {
|
||||
xbase, xlen, xcap = -1, -1, -1
|
||||
} else {
|
||||
xbase = iv
|
||||
xlen = jv - iv
|
||||
xcap = kv - iv
|
||||
}
|
||||
fmt.Fprintf(bout, "\tcheckSlice(%q, func() []byte { return %s }, %d, %d, %d)\n", expr, expr, xbase, xlen, xcap)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintf(bout, "\tif !ok { os.Exit(1) }\n")
|
||||
fmt.Fprintf(bout, "}\n")
|
||||
bout.Flush()
|
||||
}
|
||||
|
||||
var programTop = `
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var ok = true
|
||||
|
||||
var (
|
||||
array = new([10]byte)
|
||||
slice = array[:]
|
||||
|
||||
vminus1 = -1
|
||||
v0 = 0
|
||||
v1 = 1
|
||||
v2 = 2
|
||||
v3 = 3
|
||||
v4 = 4
|
||||
v5 = 5
|
||||
v10 = 10
|
||||
v20 = 20
|
||||
)
|
||||
|
||||
func notOK() {
|
||||
if ok {
|
||||
println("BUG:")
|
||||
ok = false
|
||||
}
|
||||
}
|
||||
|
||||
func checkSlice(desc string, f func() []byte, xbase, xlen, xcap int) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
if xbase >= 0 {
|
||||
notOK()
|
||||
println(desc, " unexpected panic: ", fmt.Sprint(err))
|
||||
}
|
||||
}
|
||||
// "no panic" is checked below
|
||||
}()
|
||||
|
||||
x := f()
|
||||
|
||||
arrayBase := uintptr(unsafe.Pointer(array))
|
||||
raw := *(*[3]uintptr)(unsafe.Pointer(&x))
|
||||
base, len, cap := raw[0] - arrayBase, raw[1], raw[2]
|
||||
if xbase < 0 {
|
||||
notOK()
|
||||
println(desc, "=", base, len, cap, "want panic")
|
||||
return
|
||||
}
|
||||
if base != uintptr(xbase) || len != uintptr(xlen) || cap != uintptr(xcap) {
|
||||
notOK()
|
||||
println(desc, "=", base, len, cap, "want", xbase, xlen, xcap)
|
||||
}
|
||||
}
|
||||
|
||||
`
|
121
test/slice3err.go
Normal file
121
test/slice3err.go
Normal file
@ -0,0 +1,121 @@
|
||||
// errorcheck
|
||||
|
||||
// Copyright 2013 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.
|
||||
|
||||
package p
|
||||
|
||||
var array *[10]int
|
||||
var slice []int
|
||||
var str string
|
||||
var i, j, k int
|
||||
|
||||
func f() {
|
||||
// check what missing arguments are allowed
|
||||
_ = array[:]
|
||||
_ = array[i:]
|
||||
_ = array[:j]
|
||||
_ = array[i:j]
|
||||
_ = array[::] // ERROR "middle index required in 3-index slice" "final index required in 3-index slice"
|
||||
_ = array[i::] // ERROR "middle index required in 3-index slice" "final index required in 3-index slice"
|
||||
_ = array[:j:] // ERROR "final index required in 3-index slice"
|
||||
_ = array[i:j:] // ERROR "final index required in 3-index slice"
|
||||
_ = array[::k] // ERROR "middle index required in 3-index slice"
|
||||
_ = array[i::k] // ERROR "middle index required in 3-index slice"
|
||||
_ = array[:j:k]
|
||||
_ = array[i:j:k]
|
||||
|
||||
_ = slice[:]
|
||||
_ = slice[i:]
|
||||
_ = slice[:j]
|
||||
_ = slice[i:j]
|
||||
_ = slice[::] // ERROR "middle index required in 3-index slice" "final index required in 3-index slice"
|
||||
_ = slice[i::] // ERROR "middle index required in 3-index slice" "final index required in 3-index slice"
|
||||
_ = slice[:j:] // ERROR "final index required in 3-index slice"
|
||||
_ = slice[i:j:] // ERROR "final index required in 3-index slice"
|
||||
_ = slice[::k] // ERROR "middle index required in 3-index slice"
|
||||
_ = slice[i::k] // ERROR "middle index required in 3-index slice"
|
||||
_ = slice[:j:k]
|
||||
_ = slice[i:j:k]
|
||||
|
||||
_ = str[:]
|
||||
_ = str[i:]
|
||||
_ = str[:j]
|
||||
_ = str[i:j]
|
||||
_ = str[::] // ERROR "3-index slice of string" "middle index required in 3-index slice" "final index required in 3-index slice"
|
||||
_ = str[i::] // ERROR "3-index slice of string" "middle index required in 3-index slice" "final index required in 3-index slice"
|
||||
_ = str[:j:] // ERROR "3-index slice of string" "final index required in 3-index slice"
|
||||
_ = str[i:j:] // ERROR "3-index slice of string" "final index required in 3-index slice"
|
||||
_ = str[::k] // ERROR "3-index slice of string" "middle index required in 3-index slice"
|
||||
_ = str[i::k] // ERROR "3-index slice of string" "middle index required in 3-index slice"
|
||||
_ = str[:j:k] // ERROR "3-index slice of string"
|
||||
_ = str[i:j:k] // ERROR "3-index slice of string"
|
||||
|
||||
// check invalid indices
|
||||
_ = array[1:2]
|
||||
_ = array[2:1] // ERROR "invalid slice index"
|
||||
_ = array[2:2]
|
||||
_ = array[i:1]
|
||||
_ = array[1:j]
|
||||
_ = array[1:2:3]
|
||||
_ = array[1:3:2] // ERROR "invalid slice index"
|
||||
_ = array[2:1:3] // ERROR "invalid slice index"
|
||||
_ = array[2:3:1] // ERROR "invalid slice index"
|
||||
_ = array[3:1:2] // ERROR "invalid slice index"
|
||||
_ = array[3:2:1] // ERROR "invalid slice index"
|
||||
_ = array[i:1:2]
|
||||
_ = array[i:2:1] // ERROR "invalid slice index"
|
||||
_ = array[1:j:2]
|
||||
_ = array[2:j:1] // ERROR "invalid slice index"
|
||||
_ = array[1:2:k]
|
||||
_ = array[2:1:k] // ERROR "invalid slice index"
|
||||
|
||||
_ = slice[1:2]
|
||||
_ = slice[2:1] // ERROR "invalid slice index"
|
||||
_ = slice[2:2]
|
||||
_ = slice[i:1]
|
||||
_ = slice[1:j]
|
||||
_ = slice[1:2:3]
|
||||
_ = slice[1:3:2] // ERROR "invalid slice index"
|
||||
_ = slice[2:1:3] // ERROR "invalid slice index"
|
||||
_ = slice[2:3:1] // ERROR "invalid slice index"
|
||||
_ = slice[3:1:2] // ERROR "invalid slice index"
|
||||
_ = slice[3:2:1] // ERROR "invalid slice index"
|
||||
_ = slice[i:1:2]
|
||||
_ = slice[i:2:1] // ERROR "invalid slice index"
|
||||
_ = slice[1:j:2]
|
||||
_ = slice[2:j:1] // ERROR "invalid slice index"
|
||||
_ = slice[1:2:k]
|
||||
_ = slice[2:1:k] // ERROR "invalid slice index"
|
||||
|
||||
_ = str[1:2]
|
||||
_ = str[2:1] // ERROR "invalid slice index"
|
||||
_ = str[2:2]
|
||||
_ = str[i:1]
|
||||
_ = str[1:j]
|
||||
|
||||
// check out of bounds indices on array
|
||||
_ = array[11:11] // ERROR "out of bounds for 10-element array"
|
||||
_ = array[11:12] // ERROR "out of bounds for 10-element array"
|
||||
_ = array[11:] // ERROR "out of bounds for 10-element array"
|
||||
_ = array[:11] // ERROR "out of bounds for 10-element array"
|
||||
_ = array[1:11] // ERROR "out of bounds for 10-element array"
|
||||
_ = array[1:11:12] // ERROR "out of bounds for 10-element array"
|
||||
_ = array[1:2:11] // ERROR "out of bounds for 10-element array"
|
||||
_ = array[1:11:3] // ERROR "out of bounds for 10-element array"
|
||||
_ = array[11:2:3] // ERROR "out of bounds for 10-element array"
|
||||
_ = array[11:12:13] // ERROR "out of bounds for 10-element array"
|
||||
|
||||
// slice bounds not checked
|
||||
_ = slice[11:11]
|
||||
_ = slice[11:12]
|
||||
_ = slice[11:]
|
||||
_ = slice[:11]
|
||||
_ = slice[1:11]
|
||||
_ = slice[1:11:12]
|
||||
_ = slice[1:2:11]
|
||||
_ = slice[1:11:3] // ERROR "invalid slice index"
|
||||
_ = slice[11:2:3] // ERROR "invalid slice index"
|
||||
_ = slice[11:12:13]
|
||||
}
|
Loading…
Reference in New Issue
Block a user