diff options
author | Ondřej Surý <ondrej@sury.org> | 2012-06-14 13:23:46 +0200 |
---|---|---|
committer | Ondřej Surý <ondrej@sury.org> | 2012-06-14 13:23:46 +0200 |
commit | 917c5fb8ec48e22459d77e3849e6d388f93d3260 (patch) | |
tree | 9c23734a6ffd4d2a8ac99502eda3cc812a8b130b /src/cmd | |
parent | 0003ee229fd33ff46cb5f2fe1e35f5c0284debc4 (diff) | |
download | golang-917c5fb8ec48e22459d77e3849e6d388f93d3260.tar.gz |
Imported Upstream version 1.0.2upstream/1.0.2
Diffstat (limited to 'src/cmd')
-rw-r--r-- | src/cmd/5c/list.c | 4 | ||||
-rw-r--r-- | src/cmd/5g/gobj.c | 3 | ||||
-rw-r--r-- | src/cmd/5g/list.c | 4 | ||||
-rw-r--r-- | src/cmd/5g/reg.c | 4 | ||||
-rw-r--r-- | src/cmd/5l/list.c | 4 | ||||
-rw-r--r-- | src/cmd/6g/gobj.c | 3 | ||||
-rw-r--r-- | src/cmd/6g/reg.c | 4 | ||||
-rw-r--r-- | src/cmd/8g/gobj.c | 3 | ||||
-rw-r--r-- | src/cmd/8g/reg.c | 4 | ||||
-rw-r--r-- | src/cmd/api/goapi.go | 164 | ||||
-rw-r--r-- | src/cmd/cc/scon.c | 5 | ||||
-rw-r--r-- | src/cmd/cgo/main.go | 16 | ||||
-rw-r--r-- | src/cmd/cgo/out.go | 72 | ||||
-rw-r--r-- | src/cmd/dist/build.c | 9 | ||||
-rw-r--r-- | src/cmd/gc/dcl.c | 17 | ||||
-rw-r--r-- | src/cmd/gc/doc.go | 4 | ||||
-rw-r--r-- | src/cmd/gc/gen.c | 3 | ||||
-rw-r--r-- | src/cmd/gc/go.h | 6 | ||||
-rw-r--r-- | src/cmd/gc/inl.c | 43 | ||||
-rw-r--r-- | src/cmd/gc/lex.c | 1 | ||||
-rw-r--r-- | src/cmd/gc/range.c | 11 | ||||
-rw-r--r-- | src/cmd/gc/reflect.c | 2 | ||||
-rw-r--r-- | src/cmd/gc/subr.c | 10 | ||||
-rw-r--r-- | src/cmd/gc/typecheck.c | 119 | ||||
-rw-r--r-- | src/cmd/gc/walk.c | 2 | ||||
-rw-r--r-- | src/cmd/go/build.go | 5 | ||||
-rw-r--r-- | src/cmd/go/doc.go | 17 | ||||
-rw-r--r-- | src/cmd/go/fmt.go | 21 | ||||
-rw-r--r-- | src/cmd/go/help.go | 4 | ||||
-rw-r--r-- | src/cmd/go/main.go | 30 | ||||
-rw-r--r-- | src/cmd/go/run.go | 4 | ||||
-rw-r--r-- | src/cmd/go/vet.go | 9 |
32 files changed, 377 insertions, 230 deletions
diff --git a/src/cmd/5c/list.c b/src/cmd/5c/list.c index ab0fae83c..30b88400f 100644 --- a/src/cmd/5c/list.c +++ b/src/cmd/5c/list.c @@ -140,7 +140,7 @@ Dconv(Fmt *fp) { char str[STRINGSZ]; Adr *a; - char *op; + const char *op; int v; a = va_arg(fp->args, Adr*); @@ -169,7 +169,7 @@ Dconv(Fmt *fp) case D_SHIFT: v = a->offset; - op = "<<>>->@>" + (((v>>5) & 3) << 1); + op = &"<<>>->@>"[(((v>>5) & 3) << 1)]; if(v & (1<<4)) sprint(str, "R%d%c%cR%d", v&15, op[0], op[1], (v>>8)&15); else diff --git a/src/cmd/5g/gobj.c b/src/cmd/5g/gobj.c index b562ba888..2763e7b16 100644 --- a/src/cmd/5g/gobj.c +++ b/src/cmd/5g/gobj.c @@ -198,7 +198,8 @@ dumpfuncs(void) if(isblank(pl->name)) continue; - if(debug['S']) { + // -S prints code; -SS prints code and data + if(debug['S'] && (pl->name || debug['S']>1)) { s = S; if(pl->name != N) s = pl->name->sym; diff --git a/src/cmd/5g/list.c b/src/cmd/5g/list.c index 9bc3a9a9a..f0da24742 100644 --- a/src/cmd/5g/list.c +++ b/src/cmd/5g/list.c @@ -83,7 +83,7 @@ int Dconv(Fmt *fp) { char str[STRINGSZ]; - char *op; + const char *op; Addr *a; int i; int32 v; @@ -119,7 +119,7 @@ Dconv(Fmt *fp) case D_SHIFT: v = a->offset; - op = "<<>>->@>" + (((v>>5) & 3) << 1); + op = &"<<>>->@>"[(((v>>5) & 3) << 1)]; if(v & (1<<4)) sprint(str, "R%d%c%cR%d", v&15, op[0], op[1], (v>>8)&15); else diff --git a/src/cmd/5g/reg.c b/src/cmd/5g/reg.c index 93724d032..393266973 100644 --- a/src/cmd/5g/reg.c +++ b/src/cmd/5g/reg.c @@ -695,8 +695,8 @@ brk: } } } - if(r1 != R) { - r1->link = freer; + if(lastr != R) { + lastr->link = freer; freer = firstr; } diff --git a/src/cmd/5l/list.c b/src/cmd/5l/list.c index 7b623d78a..293fee3c6 100644 --- a/src/cmd/5l/list.c +++ b/src/cmd/5l/list.c @@ -161,7 +161,7 @@ int Dconv(Fmt *fp) { char str[STRINGSZ]; - char *op; + const char *op; Adr *a; int32 v; @@ -191,7 +191,7 @@ Dconv(Fmt *fp) case D_SHIFT: v = a->offset; - op = "<<>>->@>" + (((v>>5) & 3) << 1); + op = &"<<>>->@>"[(((v>>5) & 3) << 1)]; if(v & (1<<4)) snprint(str, sizeof str, "R%d%c%cR%d", v&15, op[0], op[1], (v>>8)&15); else diff --git a/src/cmd/6g/gobj.c b/src/cmd/6g/gobj.c index 80de2f750..8c9208374 100644 --- a/src/cmd/6g/gobj.c +++ b/src/cmd/6g/gobj.c @@ -244,7 +244,8 @@ dumpfuncs(void) if(isblank(pl->name)) continue; - if(debug['S']) { + // -S prints code; -SS prints code and data + if(debug['S'] && (pl->name || debug['S']>1)) { s = S; if(pl->name != N) s = pl->name->sym; diff --git a/src/cmd/6g/reg.c b/src/cmd/6g/reg.c index bed9f8da6..049c63f17 100644 --- a/src/cmd/6g/reg.c +++ b/src/cmd/6g/reg.c @@ -780,8 +780,8 @@ brk: p->to.branch = p->to.branch->link; } - if(r1 != R) { - r1->link = freer; + if(lastr != R) { + lastr->link = freer; freer = firstr; } diff --git a/src/cmd/8g/gobj.c b/src/cmd/8g/gobj.c index d8c8f5ab9..da0055cd9 100644 --- a/src/cmd/8g/gobj.c +++ b/src/cmd/8g/gobj.c @@ -242,7 +242,8 @@ dumpfuncs(void) if(isblank(pl->name)) continue; - if(debug['S']) { + // -S prints code; -SS prints code and data + if(debug['S'] && (pl->name || debug['S']>1)) { s = S; if(pl->name != N) s = pl->name->sym; diff --git a/src/cmd/8g/reg.c b/src/cmd/8g/reg.c index 29270c820..45ffdf96c 100644 --- a/src/cmd/8g/reg.c +++ b/src/cmd/8g/reg.c @@ -677,8 +677,8 @@ brk: p->to.branch = p->to.branch->link; } - if(r1 != R) { - r1->link = freer; + if(lastr != R) { + lastr->link = freer; freer = firstr; } diff --git a/src/cmd/api/goapi.go b/src/cmd/api/goapi.go index 7363f6d82..ad1c6bb8c 100644 --- a/src/cmd/api/goapi.go +++ b/src/cmd/api/goapi.go @@ -28,6 +28,7 @@ import ( "os/exec" "path" "path/filepath" + "runtime" "sort" "strconv" "strings" @@ -35,27 +36,31 @@ import ( // Flags var ( + // TODO(bradfitz): once Go 1.1 comes out, allow the -c flag to take a comma-separated + // list of files, rather than just one. checkFile = flag.String("c", "", "optional filename to check API against") - verbose = flag.Bool("v", false, "Verbose debugging") + allowNew = flag.Bool("allow_new", true, "allow API additions") + nextFile = flag.String("next", "", "optional filename of tentative upcoming API features for the next release. This file can be lazily maintained. It only affects the delta warnings from the -c file printed on success.") + verbose = flag.Bool("v", false, "verbose debugging") + forceCtx = flag.String("contexts", "", "optional comma-separated list of <goos>-<goarch>[-cgo] to override default contexts.") ) +// contexts are the default contexts which are scanned, unless +// overridden by the -contexts flag. var contexts = []*build.Context{ {GOOS: "linux", GOARCH: "386", CgoEnabled: true}, {GOOS: "linux", GOARCH: "386"}, {GOOS: "linux", GOARCH: "amd64", CgoEnabled: true}, {GOOS: "linux", GOARCH: "amd64"}, + {GOOS: "linux", GOARCH: "arm"}, {GOOS: "darwin", GOARCH: "386", CgoEnabled: true}, {GOOS: "darwin", GOARCH: "386"}, {GOOS: "darwin", GOARCH: "amd64", CgoEnabled: true}, {GOOS: "darwin", GOARCH: "amd64"}, {GOOS: "windows", GOARCH: "amd64"}, {GOOS: "windows", GOARCH: "386"}, -} - -func init() { - for _, c := range contexts { - c.Compiler = build.Default.Compiler - } + {GOOS: "freebsd", GOARCH: "amd64"}, + {GOOS: "freebsd", GOARCH: "386"}, } func contextName(c *build.Context) string { @@ -66,9 +71,49 @@ func contextName(c *build.Context) string { return s } +func parseContext(c string) *build.Context { + parts := strings.Split(c, "-") + if len(parts) < 2 { + log.Fatalf("bad context: %q", c) + } + bc := &build.Context{ + GOOS: parts[0], + GOARCH: parts[1], + } + if len(parts) == 3 { + if parts[2] == "cgo" { + bc.CgoEnabled = true + } else { + log.Fatalf("bad context: %q", c) + } + } + return bc +} + +func setContexts() { + contexts = []*build.Context{} + for _, c := range strings.Split(*forceCtx, ",") { + contexts = append(contexts, parseContext(c)) + } +} + func main() { flag.Parse() + if !strings.Contains(runtime.Version(), "weekly") { + if *nextFile != "" { + fmt.Printf("Go version is %q, ignoring -next %s\n", runtime.Version(), *nextFile) + *nextFile = "" + } + } + + if *forceCtx != "" { + setContexts() + } + for _, c := range contexts { + c.Compiler = build.Default.Compiler + } + var pkgs []string if flag.NArg() > 0 { pkgs = flag.Args() @@ -123,45 +168,86 @@ func main() { } sort.Strings(features) + fail := false + defer func() { + if fail { + os.Exit(1) + } + }() + bw := bufio.NewWriter(os.Stdout) defer bw.Flush() - if *checkFile != "" { - bs, err := ioutil.ReadFile(*checkFile) - if err != nil { - log.Fatalf("Error reading file %s: %v", *checkFile, err) - } - v1 := strings.Split(strings.TrimSpace(string(bs)), "\n") - sort.Strings(v1) - v2 := features - take := func(sl *[]string) string { - s := (*sl)[0] - *sl = (*sl)[1:] - return s - } - changes := false - for len(v1) > 0 || len(v2) > 0 { - switch { - case len(v2) == 0 || v1[0] < v2[0]: - fmt.Fprintf(bw, "-%s\n", take(&v1)) - changes = true - case len(v1) == 0 || v1[0] > v2[0]: - fmt.Fprintf(bw, "+%s\n", take(&v2)) - changes = true - default: - take(&v1) - take(&v2) - } - } - if changes { - bw.Flush() - os.Exit(1) - } - } else { + if *checkFile == "" { for _, f := range features { fmt.Fprintf(bw, "%s\n", f) } + return + } + + var required []string + for _, filename := range []string{*checkFile} { + required = append(required, fileFeatures(filename)...) + } + sort.Strings(required) + + var optional = make(map[string]bool) // feature => true + if *nextFile != "" { + for _, feature := range fileFeatures(*nextFile) { + optional[feature] = true + } + } + + take := func(sl *[]string) string { + s := (*sl)[0] + *sl = (*sl)[1:] + return s + } + + for len(required) > 0 || len(features) > 0 { + switch { + case len(features) == 0 || required[0] < features[0]: + fmt.Fprintf(bw, "-%s\n", take(&required)) + fail = true // broke compatibility + case len(required) == 0 || required[0] > features[0]: + newFeature := take(&features) + if optional[newFeature] { + // Known added feature to the upcoming release. + // Delete it from the map so we can detect any upcoming features + // which were never seen. (so we can clean up the nextFile) + delete(optional, newFeature) + } else { + fmt.Fprintf(bw, "+%s\n", newFeature) + if !*allowNew { + fail = true // we're in lock-down mode for next release + } + } + default: + take(&required) + take(&features) + } + } + + var missing []string + for feature := range optional { + missing = append(missing, feature) + } + sort.Strings(missing) + for _, feature := range missing { + fmt.Fprintf(bw, "(in next file, but not in API) -%s\n", feature) + } +} + +func fileFeatures(filename string) []string { + bs, err := ioutil.ReadFile(filename) + if err != nil { + log.Fatalf("Error reading file %s: %v", filename, err) + } + text := strings.TrimSpace(string(bs)) + if text == "" { + return nil } + return strings.Split(text, "\n") } // pkgSymbol represents a symbol in a package diff --git a/src/cmd/cc/scon.c b/src/cmd/cc/scon.c index 193331f77..f6031a5be 100644 --- a/src/cmd/cc/scon.c +++ b/src/cmd/cc/scon.c @@ -175,7 +175,10 @@ evconst(Node *n) break; case OLSHR: - v = (uvlong)l->vconst >> r->vconst; + if(l->type->width != sizeof(uvlong)) + v = ((uvlong)l->vconst & 0xffffffffULL) >> r->vconst; + else + v = (uvlong)l->vconst >> r->vconst; break; case OASHR: diff --git a/src/cmd/cgo/main.go b/src/cmd/cgo/main.go index 7449f04c4..60165961a 100644 --- a/src/cmd/cgo/main.go +++ b/src/cmd/cgo/main.go @@ -22,6 +22,7 @@ import ( "path/filepath" "reflect" "runtime" + "sort" "strings" ) @@ -33,9 +34,8 @@ type Package struct { GccOptions []string CgoFlags map[string]string // #cgo flags (CFLAGS, LDFLAGS) Written map[string]bool - Name map[string]*Name // accumulated Name from Files - Typedef map[string]ast.Expr // accumulated Typedef from Files - ExpFunc []*ExpFunc // accumulated ExpFunc from Files + Name map[string]*Name // accumulated Name from Files + ExpFunc []*ExpFunc // accumulated ExpFunc from Files Decl []ast.Decl GoFiles []string // list of Go files GccFiles []string // list of gcc output files @@ -51,7 +51,15 @@ type File struct { Ref []*Ref // all references to C.xxx in AST ExpFunc []*ExpFunc // exported functions for this file Name map[string]*Name // map from Go name to Name - Typedef map[string]ast.Expr // translations of all necessary types from C +} + +func nameKeys(m map[string]*Name) []string { + var ks []string + for k := range m { + ks = append(ks, k) + } + sort.Strings(ks) + return ks } // A Ref refers to an expression of the form C.xxx in the AST. diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go index 814250c2e..5dfc16a02 100644 --- a/src/cmd/cgo/out.go +++ b/src/cmd/cgo/out.go @@ -71,7 +71,8 @@ func (p *Package) writeDefs() { } cVars := make(map[string]bool) - for _, n := range p.Name { + for _, key := range nameKeys(p.Name) { + n := p.Name[key] if n.Kind != "var" { continue } @@ -94,14 +95,16 @@ func (p *Package) writeDefs() { } fmt.Fprintf(fc, "\n") - for _, n := range p.Name { + for _, key := range nameKeys(p.Name) { + n := p.Name[key] if n.Const != "" { fmt.Fprintf(fgo2, "const _Cconst_%s = %s\n", n.Go, n.Const) } } fmt.Fprintf(fgo2, "\n") - for _, n := range p.Name { + for _, key := range nameKeys(p.Name) { + n := p.Name[key] if n.FuncType != nil { p.writeDefsFunc(fc, fgo2, n) } @@ -372,7 +375,8 @@ func (p *Package) writeOutput(f *File, srcfile string) { fmt.Fprintf(fgcc, "%s\n", f.Preamble) fmt.Fprintf(fgcc, "%s\n", gccProlog) - for _, n := range f.Name { + for _, key := range nameKeys(f.Name) { + n := f.Name[key] if n.FuncType != nil { p.writeOutputFunc(fgcc, n) } @@ -736,25 +740,23 @@ func c(repr string, args ...interface{}) *TypeRepr { // Map predeclared Go types to Type. var goTypes = map[string]*Type{ - "bool": {Size: 1, Align: 1, C: c("uchar")}, - "byte": {Size: 1, Align: 1, C: c("uchar")}, - "int": {Size: 4, Align: 4, C: c("int")}, - "uint": {Size: 4, Align: 4, C: c("uint")}, - "rune": {Size: 4, Align: 4, C: c("int")}, - "int8": {Size: 1, Align: 1, C: c("schar")}, - "uint8": {Size: 1, Align: 1, C: c("uchar")}, - "int16": {Size: 2, Align: 2, C: c("short")}, - "uint16": {Size: 2, Align: 2, C: c("ushort")}, - "int32": {Size: 4, Align: 4, C: c("int")}, - "uint32": {Size: 4, Align: 4, C: c("uint")}, - "int64": {Size: 8, Align: 8, C: c("int64")}, - "uint64": {Size: 8, Align: 8, C: c("uint64")}, - "float": {Size: 4, Align: 4, C: c("float")}, - "float32": {Size: 4, Align: 4, C: c("float")}, - "float64": {Size: 8, Align: 8, C: c("double")}, - "complex": {Size: 8, Align: 8, C: c("__complex float")}, - "complex64": {Size: 8, Align: 8, C: c("__complex float")}, - "complex128": {Size: 16, Align: 16, C: c("__complex double")}, + "bool": {Size: 1, Align: 1, C: c("GoUint8")}, + "byte": {Size: 1, Align: 1, C: c("GoUint8")}, + "int": {Size: 4, Align: 4, C: c("GoInt")}, + "uint": {Size: 4, Align: 4, C: c("GoUint")}, + "rune": {Size: 4, Align: 4, C: c("GoInt32")}, + "int8": {Size: 1, Align: 1, C: c("GoInt8")}, + "uint8": {Size: 1, Align: 1, C: c("GoUint8")}, + "int16": {Size: 2, Align: 2, C: c("GoInt16")}, + "uint16": {Size: 2, Align: 2, C: c("GoUint16")}, + "int32": {Size: 4, Align: 4, C: c("GoInt32")}, + "uint32": {Size: 4, Align: 4, C: c("GoUint32")}, + "int64": {Size: 8, Align: 8, C: c("GoInt64")}, + "uint64": {Size: 8, Align: 8, C: c("GoUint64")}, + "float32": {Size: 4, Align: 4, C: c("GoFloat32")}, + "float64": {Size: 8, Align: 8, C: c("GoFloat64")}, + "complex64": {Size: 8, Align: 8, C: c("GoComplex64")}, + "complex128": {Size: 16, Align: 16, C: c("GoComplex128")}, } // Map an ast type to a Type. @@ -799,7 +801,7 @@ func (p *Package) cgoType(e ast.Expr) *Type { return def } if t.Name == "uintptr" { - return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("uintptr")} + return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoUintptr")} } if t.Name == "string" { return &Type{Size: p.PtrSize + 4, Align: p.PtrSize, C: c("GoString")} @@ -930,13 +932,21 @@ Slice GoBytes(char *p, int n) { ` const gccExportHeaderProlog = ` -typedef unsigned int uint; -typedef signed char schar; -typedef unsigned char uchar; -typedef unsigned short ushort; -typedef long long int64; -typedef unsigned long long uint64; -typedef __SIZE_TYPE__ uintptr; +typedef int GoInt; +typedef unsigned int GoUint; +typedef signed char GoInt8; +typedef unsigned char GoUint8; +typedef short GoInt16; +typedef unsigned short GoUint16; +typedef int GoInt32; +typedef unsigned int GoUint32; +typedef long long GoInt64; +typedef unsigned long long GoUint64; +typedef __SIZE_TYPE__ GoUintptr; +typedef float GoFloat32; +typedef double GoFloat64; +typedef __complex float GoComplex64; +typedef __complex double GoComplex128; typedef struct { char *p; int n; } GoString; typedef void *GoMap; diff --git a/src/cmd/dist/build.c b/src/cmd/dist/build.c index 3ef65f85d..7f9aa7bcd 100644 --- a/src/cmd/dist/build.c +++ b/src/cmd/dist/build.c @@ -1230,6 +1230,15 @@ clean(void) xremove(bpathf(&b, "%s/%s", bstr(&path), cleantab[i]+4)); } + // remove src/pkg/runtime/z* unconditionally + vreset(&dir); + bpathf(&path, "%s/src/pkg/runtime", goroot); + xreaddir(&dir, bstr(&path)); + for(j=0; j<dir.len; j++) { + if(hasprefix(dir.p[j], "z")) + xremove(bpathf(&b, "%s/%s", bstr(&path), dir.p[j])); + } + if(rebuildall) { // Remove object tree. xremoveall(bpathf(&b, "%s/pkg/obj/%s_%s", goroot, gohostos, gohostarch)); diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c index 4121a45ab..32f334b71 100644 --- a/src/cmd/gc/dcl.c +++ b/src/cmd/gc/dcl.c @@ -433,21 +433,6 @@ oldname(Sym *s) } /* - * same for types - */ -Type* -newtype(Sym *s) -{ - Type *t; - - t = typ(TFORW); - t->sym = s; - t->type = T; - return t; -} - - -/* * := declarations */ @@ -1311,7 +1296,7 @@ addmethod(Sym *sf, Type *t, int local) } // Should have picked off all the reasons above, // but just in case, fall back to generic error. - yyerror("invalid receiver type %T", pa); + yyerror("invalid receiver type %T (%lT / %lT)", pa, pa, t); return; } diff --git a/src/cmd/gc/doc.go b/src/cmd/gc/doc.go index 163d3862c..8d8f8967b 100644 --- a/src/cmd/gc/doc.go +++ b/src/cmd/gc/doc.go @@ -47,7 +47,9 @@ Flags: -N disable optimizations -S - write assembly language text to standard output + write assembly language text to standard output (code only) + -SS + write assembly language text to standard output (code and data) -u disallow importing packages not marked as safe -V diff --git a/src/cmd/gc/gen.c b/src/cmd/gc/gen.c index 694a10ab5..96e7b526c 100644 --- a/src/cmd/gc/gen.c +++ b/src/cmd/gc/gen.c @@ -647,6 +647,9 @@ cgen_as(Node *nl, Node *nr) dump("cgen_as = ", nr); } + while(nr != N && nr->op == OCONVNOP) + nr = nr->left; + if(nl == N || isblank(nl)) { cgen_discard(nr); return; diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h index 8c4fff15a..43bd68793 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -182,6 +182,9 @@ struct Type int32 maplineno; // first use of TFORW as map key int32 embedlineno; // first use of TFORW as embedded type + + // for TFORW, where to copy the eventual value to + NodeList *copyto; }; #define T ((Type*)0) @@ -940,7 +943,6 @@ Node* methodname(Node *n, Type *t); Node* methodname1(Node *n, Node *t); Sym* methodsym(Sym *nsym, Type *t0, int iface); Node* newname(Sym *s); -Type* newtype(Sym *s); Node* oldname(Sym *s); void popdcl(void); void poptodcl(void); @@ -1248,9 +1250,7 @@ int islvalue(Node *n); Node* typecheck(Node **np, int top); void typechecklist(NodeList *l, int top); Node* typecheckdef(Node *n); -void resumetypecopy(void); void copytype(Node *n, Type *t); -void defertypecopy(Node *n, Type *t); void queuemethod(Node *n); /* diff --git a/src/cmd/gc/inl.c b/src/cmd/gc/inl.c index efce56057..b2b1faff7 100644 --- a/src/cmd/gc/inl.c +++ b/src/cmd/gc/inl.c @@ -506,6 +506,19 @@ mkinlcall(Node **np, Node *fn) mkinlcall1(np, fn); safemode = save_safemode; } + +static Node* +tinlvar(Type *t) +{ + if(t->nname && !isblank(t->nname)) { + if(!t->nname->inlvar) + fatal("missing inlvar for %N\n", t->nname); + return t->nname->inlvar; + } + typecheck(&nblank, Erv | Easgn); + return nblank; +} + // if *np is a call, and fn is a function with an inlinable body, substitute *np with an OINLCALL. // On return ninit has the parameter assignments, the nbody is the // inlined function body and list, rlist contain the input, output @@ -579,15 +592,12 @@ mkinlcall1(Node **np, Node *fn) fatal("method call without receiver: %+N", n); if(t == T) fatal("method call unknown receiver type: %+N", n); - if(t->nname != N && !isblank(t->nname)) - as = nod(OAS, t->nname->inlvar, n->left->left); - else - as = nod(OAS, temp(t->type), n->left->left); + as = nod(OAS, tinlvar(t), n->left->left); } else { // non-method call to method - if (!n->list) + if(!n->list) fatal("non-method call to method without first arg: %+N", n); - if(t != T && t->nname != N && !isblank(t->nname)) - as = nod(OAS, t->nname->inlvar, n->list->n); + if(t != T) + as = nod(OAS, tinlvar(t), n->list->n); } if(as != N) { @@ -601,27 +611,16 @@ mkinlcall1(Node **np, Node *fn) // TODO check that n->list->n is a call? // TODO: non-method call to T.meth(f()) where f returns t, args... as->rlist = n->list; - for(t = getinargx(fn->type)->type; t; t=t->down) { - if(t->nname && !isblank(t->nname)) { - if(!t->nname->inlvar) - fatal("missing inlvar for %N\n", t->nname); - as->list = list(as->list, t->nname->inlvar); - } else { - as->list = list(as->list, temp(t->type)); - } - } + for(t = getinargx(fn->type)->type; t; t=t->down) + as->list = list(as->list, tinlvar(t)); } else { ll = n->list; if(fn->type->thistuple && n->left->op != ODOTMETH) // non method call to method ll=ll->next; // was handled above in if(thistuple) for(t = getinargx(fn->type)->type; t && ll; t=t->down) { - if(t->nname && !isblank(t->nname)) { - if(!t->nname->inlvar) - fatal("missing inlvar for %N\n", t->nname); - as->list = list(as->list, t->nname->inlvar); - as->rlist = list(as->rlist, ll->n); - } + as->list = list(as->list, tinlvar(t)); + as->rlist = list(as->rlist, ll->n); ll=ll->next; } if(ll || t) diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c index e71fd3848..624dfb0b4 100644 --- a/src/cmd/gc/lex.c +++ b/src/cmd/gc/lex.c @@ -348,7 +348,6 @@ main(int argc, char *argv[]) for(l=xtop; l; l=l->next) if(l->n->op == ODCL || l->n->op == OAS) typecheck(&l->n, Etop); - resumetypecopy(); resumecheckwidth(); // Phase 3: Type check function bodies. diff --git a/src/cmd/gc/range.c b/src/cmd/gc/range.c index 9bcd833a7..d301e4e4f 100644 --- a/src/cmd/gc/range.c +++ b/src/cmd/gc/range.c @@ -152,9 +152,14 @@ walkrange(Node *n) n->ntest = nod(OLT, hv1, hn); n->nincr = nod(OASOP, hv1, nodintconst(1)); n->nincr->etype = OADD; - body = list1(nod(OAS, v1, hv1)); - if(v2) { - body = list(body, nod(OAS, v2, nod(OIND, hp, N))); + if(v2 == N) + body = list1(nod(OAS, v1, hv1)); + else { + a = nod(OAS2, N, N); + a->list = list(list1(v1), v2); + a->rlist = list(list1(hv1), nod(OIND, hp, N)); + body = list1(a); + tmp = nod(OADD, hp, nodintconst(t->type->width)); tmp->type = hp->type; tmp->typecheck = 1; diff --git a/src/cmd/gc/reflect.c b/src/cmd/gc/reflect.c index 07b426508..62759bcba 100644 --- a/src/cmd/gc/reflect.c +++ b/src/cmd/gc/reflect.c @@ -629,6 +629,7 @@ typename(Type *t) n->ullman = 1; n->class = PEXTERN; n->xoffset = 0; + n->typecheck = 1; s->def = n; signatlist = list(signatlist, typenod(t)); @@ -638,6 +639,7 @@ typename(Type *t) n->type = ptrto(s->def->type); n->addable = 1; n->ullman = 2; + n->typecheck = 1; return n; } diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c index 681c023a0..bd53520df 100644 --- a/src/cmd/gc/subr.c +++ b/src/cmd/gc/subr.c @@ -1945,6 +1945,12 @@ safeexpr(Node *n, NodeList **init) if(n == N) return N; + if(n->ninit) { + walkstmtlist(n->ninit); + *init = concat(*init, n->ninit); + n->ninit = nil; + } + switch(n->op) { case ONAME: case OLITERAL: @@ -2673,7 +2679,7 @@ genhash(Sym *sym, Type *t) first = T; for(t1=t->type;; t1=t1->down) { if(t1 != T && (isblanksym(t1->sym) || algtype1(t1->type, nil) == AMEM)) { - if(first == T) + if(first == T && !isblanksym(t1->sym)) first = t1; continue; } @@ -2890,7 +2896,7 @@ geneq(Sym *sym, Type *t) first = T; for(t1=t->type;; t1=t1->down) { if(t1 != T && (isblanksym(t1->sym) || algtype1(t1->type, nil) == AMEM)) { - if(first == T) + if(first == T && !isblanksym(t1->sym)) first = t1; continue; } diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c index e98d53857..cc4faf5a7 100644 --- a/src/cmd/gc/typecheck.c +++ b/src/cmd/gc/typecheck.c @@ -31,7 +31,6 @@ static void checkassign(Node*); static void checkassignlist(NodeList*); static void stringtoarraylit(Node**); static Node* resolve(Node*); -static Type* getforwtype(Node*); static NodeList* typecheckdefstack; @@ -237,7 +236,7 @@ typecheck1(Node **np, int top) Node *n, *l, *r; NodeList *args; int ok, ntop; - Type *t, *tp, *ft, *missing, *have, *badtype; + Type *t, *tp, *missing, *have, *badtype; Val v; char *why; @@ -249,10 +248,6 @@ typecheck1(Node **np, int top) goto error; } - // a dance to handle forward-declared recursive pointer types. - if(n->op == OTYPE && (ft = getforwtype(n->ntype)) != T) - defertypecopy(n, ft); - typecheckdef(n); n->realtype = n->type; if(n->op == ONONAME) @@ -1140,6 +1135,10 @@ reswitch: goto error; n->type = t; if(!isslice(t)) { + if(isconst(args->n, CTNIL)) { + yyerror("first argument to append must be typed slice; have untyped nil", t); + goto error; + } yyerror("first argument to append must be slice; have %lT", t); goto error; } @@ -2612,26 +2611,6 @@ stringtoarraylit(Node **np) *np = nn; } -static Type* -getforwtype(Node *n) -{ - Node *f1, *f2; - - for(f2=n; ; n=n->ntype) { - if((n = resolve(n)) == N || n->op != OTYPE) - return T; - - if(n->type != T && n->type->etype == TFORW) - return n->type; - - // Check for ntype cycle. - if((f2 = resolve(f2)) != N && (f1 = resolve(f2->ntype)) != N) { - f2 = resolve(f1->ntype); - if(f1 == n || f2 == n) - return T; - } - } -} static int ntypecheckdeftype; static NodeList *methodqueue; @@ -2669,49 +2648,24 @@ domethod(Node *n) checkwidth(n->type); } -typedef struct NodeTypeList NodeTypeList; -struct NodeTypeList { - Node *n; - Type *t; - NodeTypeList *next; -}; - -static NodeTypeList *dntq; -static NodeTypeList *dntend; +static NodeList *mapqueue; void -defertypecopy(Node *n, Type *t) +copytype(Node *n, Type *t) { - NodeTypeList *ntl; + int maplineno, embedlineno, lno; + NodeList *l; - if(n == N || t == T) + if(t->etype == TFORW) { + // This type isn't computed yet; when it is, update n. + t->copyto = list(t->copyto, n); return; + } - ntl = mal(sizeof *ntl); - ntl->n = n; - ntl->t = t; - ntl->next = nil; - - if(dntq == nil) - dntq = ntl; - else - dntend->next = ntl; - - dntend = ntl; -} - -void -resumetypecopy(void) -{ - NodeTypeList *l; - - for(l=dntq; l; l=l->next) - copytype(l->n, l->t); -} + maplineno = n->type->maplineno; + embedlineno = n->type->embedlineno; -void -copytype(Node *n, Type *t) -{ + l = n->type->copyto; *n->type = *t; t = n->type; @@ -2724,12 +2678,32 @@ copytype(Node *n, Type *t) t->nod = N; t->printed = 0; t->deferwidth = 0; + t->copyto = nil; + + // Update nodes waiting on this type. + for(; l; l=l->next) + copytype(l->n, t); + + // Double-check use of type as embedded type. + lno = lineno; + if(embedlineno) { + lineno = embedlineno; + if(isptr[t->etype]) + yyerror("embedded type cannot be a pointer"); + } + lineno = lno; + + // Queue check for map until all the types are done settling. + if(maplineno) { + t->maplineno = maplineno; + mapqueue = list(mapqueue, n); + } } static void typecheckdeftype(Node *n) { - int maplineno, embedlineno, lno; + int lno; Type *t; NodeList *l; @@ -2748,26 +2722,12 @@ typecheckdeftype(Node *n) goto ret; } - maplineno = n->type->maplineno; - embedlineno = n->type->embedlineno; - // copy new type and clear fields // that don't come along. // anything zeroed here must be zeroed in // typedcl2 too. copytype(n, t); - // double-check use of type as map key. - if(maplineno) { - lineno = maplineno; - maptype(n->type, types[TBOOL]); - } - if(embedlineno) { - lineno = embedlineno; - if(isptr[t->etype]) - yyerror("embedded type cannot be a pointer"); - } - ret: lineno = lno; @@ -2780,6 +2740,11 @@ ret: for(; l; l=l->next) domethod(l->n); } + for(l=mapqueue; l; l=l->next) { + lineno = l->n->type->maplineno; + maptype(l->n->type, types[TBOOL]); + } + lineno = lno; } ntypecheckdeftype--; } diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c index 7dfd34a7a..a4edc9062 100644 --- a/src/cmd/gc/walk.c +++ b/src/cmd/gc/walk.c @@ -846,11 +846,13 @@ walkexpr(Node **np, NodeList **init) // if range of type cannot exceed static array bound, // disable bounds check if(isfixedarray(n->left->type)) + if(!issigned[n->right->type->etype]) if(n->right->type->width < 4) if((1<<(8*n->right->type->width)) <= n->left->type->bound) n->etype = 1; if(isconst(n->left, CTSTR)) + if(!issigned[n->right->type->etype]) if(n->right->type->width < 4) if((1<<(8*n->right->type->width)) <= n->left->val.u.sval->len) n->etype = 1; diff --git a/src/cmd/go/build.go b/src/cmd/go/build.go index 4bb83f161..767ddfd40 100644 --- a/src/cmd/go/build.go +++ b/src/cmd/go/build.go @@ -152,6 +152,11 @@ func addBuildFlags(cmd *Command) { cmd.Flag.Var(buildCompiler{}, "compiler", "") } +func addBuildFlagsNX(cmd *Command) { + cmd.Flag.BoolVar(&buildN, "n", false, "") + cmd.Flag.BoolVar(&buildX, "x", false, "") +} + type stringsFlag []string func (v *stringsFlag) Set(s string) error { diff --git a/src/cmd/go/doc.go b/src/cmd/go/doc.go index 32ede3964..5e7b10692 100644 --- a/src/cmd/go/doc.go +++ b/src/cmd/go/doc.go @@ -145,7 +145,7 @@ Run godoc on package sources Usage: - go doc [packages] + go doc [-n] [-x] [packages] Doc runs the godoc command on the packages named by the import paths. @@ -153,6 +153,9 @@ import paths. For more about godoc, see 'godoc godoc'. For more about specifying packages, see 'go help packages'. +The -n flag prints commands that would be executed. +The -x flag prints commands as they are executed. + To run godoc with specific options, run godoc itself. See also: go fix, go fmt, go vet. @@ -192,7 +195,7 @@ Run gofmt on package sources Usage: - go fmt [packages] + go fmt [-n] [-x] [packages] Fmt runs the command 'gofmt -l -w' on the packages named by the import paths. It prints the names of the files that are modified. @@ -200,6 +203,9 @@ by the import paths. It prints the names of the files that are modified. For more about gofmt, see 'godoc gofmt'. For more about specifying packages, see 'go help packages'. +The -n flag prints commands that would be executed. +The -x flag prints commands as they are executed. + To run gofmt with specific options, run gofmt itself. See also: go doc, go fix, go vet. @@ -414,7 +420,7 @@ Run go tool vet on packages Usage: - go vet [packages] + go vet [-n] [-x] [packages] Vet runs the Go vet command on the packages named by the import paths. @@ -423,6 +429,9 @@ For more about specifying packages, see 'go help packages'. To run the vet tool with specific options, run 'go tool vet'. +The -n flag prints commands that would be executed. +The -x flag prints commands as they are executed. + See also: go fmt, go fix. @@ -537,7 +546,7 @@ in those files and ignoring any other files in the directory. Remote import path syntax -An import path (see 'go help importpath') denotes a package +An import path (see 'go help packages') denotes a package stored in the local file system. Certain import paths also describe how to obtain the source code for the package using a revision control system. diff --git a/src/cmd/go/fmt.go b/src/cmd/go/fmt.go index cea9b0a51..b1aba32f3 100644 --- a/src/cmd/go/fmt.go +++ b/src/cmd/go/fmt.go @@ -4,9 +4,14 @@ package main +func init() { + addBuildFlagsNX(cmdFmt) + addBuildFlagsNX(cmdDoc) +} + var cmdFmt = &Command{ Run: runFmt, - UsageLine: "fmt [packages]", + UsageLine: "fmt [-n] [-x] [packages]", Short: "run gofmt on package sources", Long: ` Fmt runs the command 'gofmt -l -w' on the packages named @@ -15,6 +20,9 @@ by the import paths. It prints the names of the files that are modified. For more about gofmt, see 'godoc gofmt'. For more about specifying packages, see 'go help packages'. +The -n flag prints commands that would be executed. +The -x flag prints commands as they are executed. + To run gofmt with specific options, run gofmt itself. See also: go doc, go fix, go vet. @@ -32,7 +40,7 @@ func runFmt(cmd *Command, args []string) { var cmdDoc = &Command{ Run: runDoc, - UsageLine: "doc [packages]", + UsageLine: "doc [-n] [-x] [packages]", Short: "run godoc on package sources", Long: ` Doc runs the godoc command on the packages named by the @@ -41,6 +49,9 @@ import paths. For more about godoc, see 'godoc godoc'. For more about specifying packages, see 'go help packages'. +The -n flag prints commands that would be executed. +The -x flag prints commands as they are executed. + To run godoc with specific options, run godoc itself. See also: go fix, go fmt, go vet. @@ -53,6 +64,10 @@ func runDoc(cmd *Command, args []string) { errorf("go doc: cannot use package file list") continue } - run("godoc", pkg.Dir) + if pkg.local { + run("godoc", pkg.Dir) + } else { + run("godoc", pkg.ImportPath) + } } } diff --git a/src/cmd/go/help.go b/src/cmd/go/help.go index 47ea0c711..7539753af 100644 --- a/src/cmd/go/help.go +++ b/src/cmd/go/help.go @@ -61,7 +61,7 @@ var helpRemote = &Command{ Short: "remote import path syntax", Long: ` -An import path (see 'go help importpath') denotes a package +An import path (see 'go help packages') denotes a package stored in the local file system. Certain import paths also describe how to obtain the source code for the package using a revision control system. @@ -138,7 +138,7 @@ The meta tag has the form: <meta name="go-import" content="import-prefix vcs repo-root"> -The import-prefix is the import path correponding to the repository +The import-prefix is the import path corresponding to the repository root. It must be a prefix or an exact match of the package being fetched with "go get". If it's not an exact match, another http request is made at the prefix to verify the <meta> tags match. diff --git a/src/cmd/go/main.go b/src/cmd/go/main.go index 73c2f54a7..20585d1be 100644 --- a/src/cmd/go/main.go +++ b/src/cmd/go/main.go @@ -144,8 +144,9 @@ func main() { } } - fmt.Fprintf(os.Stderr, "Unknown command %#q\n\n", args[0]) - usage() + fmt.Fprintf(os.Stderr, "go: unknown subcommand %q\nRun 'go help' for usage.\n", args[0]) + setExitStatus(2) + exit() } var usageTemplate = `Go is a tool for managing Go source code. @@ -339,6 +340,13 @@ func exitIfErrors() { func run(cmdargs ...interface{}) { cmdline := stringList(cmdargs...) + if buildN || buildV { + fmt.Printf("%s\n", strings.Join(cmdline, " ")) + if buildN { + return + } + } + cmd := exec.Command(cmdline[0], cmdline[1:]...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr @@ -500,13 +508,25 @@ func matchPackagesInFS(pattern string) []string { var pkgs []string filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error { - if err != nil || !fi.IsDir() || path == dir { + if err != nil || !fi.IsDir() { return nil } + if path == dir { + // filepath.Walk starts at dir and recurses. For the recursive case, + // the path is the result of filepath.Join, which calls filepath.Clean. + // The initial case is not Cleaned, though, so we do this explicitly. + // + // This converts a path like "./io/" to "io". Without this step, running + // "cd $GOROOT/src/pkg; go list ./io/..." would incorrectly skip the io + // package, because prepending the prefix "./" to the unclean path would + // result in "././io", and match("././io") returns false. + path = filepath.Clean(path) + } - // Avoid .foo, _foo, and testdata directory trees. + // Avoid .foo, _foo, and testdata directory trees, but do not avoid "." or "..". _, elem := filepath.Split(path) - if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" { + dot := strings.HasPrefix(elem, ".") && elem != "." && elem != ".." + if dot || strings.HasPrefix(elem, "_") || elem == "testdata" { return filepath.SkipDir } diff --git a/src/cmd/go/run.go b/src/cmd/go/run.go index 94cd59296..6043b7e20 100644 --- a/src/cmd/go/run.go +++ b/src/cmd/go/run.go @@ -49,6 +49,10 @@ func runRun(cmd *Command, args []string) { if p.Error != nil { fatalf("%s", p.Error) } + for _, err := range p.DepsErrors { + errorf("%s", err) + } + exitIfErrors() if p.Name != "main" { fatalf("go run: cannot run non-main package") } diff --git a/src/cmd/go/vet.go b/src/cmd/go/vet.go index a672b9910..eb0b89cca 100644 --- a/src/cmd/go/vet.go +++ b/src/cmd/go/vet.go @@ -4,9 +4,13 @@ package main +func init() { + addBuildFlagsNX(cmdVet) +} + var cmdVet = &Command{ Run: runVet, - UsageLine: "vet [packages]", + UsageLine: "vet [-n] [-x] [packages]", Short: "run go tool vet on packages", Long: ` Vet runs the Go vet command on the packages named by the import paths. @@ -16,6 +20,9 @@ For more about specifying packages, see 'go help packages'. To run the vet tool with specific options, run 'go tool vet'. +The -n flag prints commands that would be executed. +The -x flag prints commands as they are executed. + See also: go fmt, go fix. `, } |