summaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2012-06-14 13:23:46 +0200
committerOndřej Surý <ondrej@sury.org>2012-06-14 13:23:46 +0200
commit917c5fb8ec48e22459d77e3849e6d388f93d3260 (patch)
tree9c23734a6ffd4d2a8ac99502eda3cc812a8b130b /src/cmd
parent0003ee229fd33ff46cb5f2fe1e35f5c0284debc4 (diff)
downloadgolang-917c5fb8ec48e22459d77e3849e6d388f93d3260.tar.gz
Imported Upstream version 1.0.2upstream/1.0.2
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/5c/list.c4
-rw-r--r--src/cmd/5g/gobj.c3
-rw-r--r--src/cmd/5g/list.c4
-rw-r--r--src/cmd/5g/reg.c4
-rw-r--r--src/cmd/5l/list.c4
-rw-r--r--src/cmd/6g/gobj.c3
-rw-r--r--src/cmd/6g/reg.c4
-rw-r--r--src/cmd/8g/gobj.c3
-rw-r--r--src/cmd/8g/reg.c4
-rw-r--r--src/cmd/api/goapi.go164
-rw-r--r--src/cmd/cc/scon.c5
-rw-r--r--src/cmd/cgo/main.go16
-rw-r--r--src/cmd/cgo/out.go72
-rw-r--r--src/cmd/dist/build.c9
-rw-r--r--src/cmd/gc/dcl.c17
-rw-r--r--src/cmd/gc/doc.go4
-rw-r--r--src/cmd/gc/gen.c3
-rw-r--r--src/cmd/gc/go.h6
-rw-r--r--src/cmd/gc/inl.c43
-rw-r--r--src/cmd/gc/lex.c1
-rw-r--r--src/cmd/gc/range.c11
-rw-r--r--src/cmd/gc/reflect.c2
-rw-r--r--src/cmd/gc/subr.c10
-rw-r--r--src/cmd/gc/typecheck.c119
-rw-r--r--src/cmd/gc/walk.c2
-rw-r--r--src/cmd/go/build.go5
-rw-r--r--src/cmd/go/doc.go17
-rw-r--r--src/cmd/go/fmt.go21
-rw-r--r--src/cmd/go/help.go4
-rw-r--r--src/cmd/go/main.go30
-rw-r--r--src/cmd/go/run.go4
-rw-r--r--src/cmd/go/vet.go9
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.
`,
}