Merge "golang.org/x/tools: Update to release branch of Go 1.6"
diff --git a/go/src/golang.org/x/tools/README.google b/go/src/golang.org/x/tools/README.google
index 11e6893..daf3b49 100644
--- a/go/src/golang.org/x/tools/README.google
+++ b/go/src/golang.org/x/tools/README.google
@@ -1,5 +1,5 @@
-URL: https://go.googlesource.com/tools/+archive/b60a44a905945100f46b6fc9184df866dbccf955.tar.gz
-Version: b60a44a905945100f46b6fc9184df866dbccf955
+URL: https://go.googlesource.com/tools/+archive/c887be1b2ebd11663d4bf2fbca508c449172339e.tar.gz
+Version: c887be1b2ebd11663d4bf2fbca508c449172339e
 License: New BSD
 License File: LICENSE
 
@@ -7,6 +7,4 @@
 Packages and tools supporting the Go programming language.
 
 Local Modifications:
-Whitelisting Vanadium named slice types for go vet checks.
-Removed two test cases from go/vcs/vcs_test.go that fail now that
-code.google.com is in archive mode.
+- Applied https://go-review.googlesource.com/#/c/19189/
diff --git a/go/src/golang.org/x/tools/cmd/bundle/main.go b/go/src/golang.org/x/tools/cmd/bundle/main.go
new file mode 100644
index 0000000..f0051fe
--- /dev/null
+++ b/go/src/golang.org/x/tools/cmd/bundle/main.go
@@ -0,0 +1,222 @@
+// Copyright 2015 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.
+
+// +build go1.5
+
+// The bundle command concatenates the source files of a package,
+// renaming package-level names by adding a prefix and renaming
+// identifiers as needed to preserve referential integrity.
+//
+// Example:
+// 	$ bundle golang.org/x/net/http2 net/http http2
+//
+// The command above prints a single file containing the code of
+// golang.org/x/net/http2, suitable for inclusion in package net/http,
+// in which toplevel names have been prefixed with "http2".
+//
+// Assumptions:
+// - no file in the package imports "C", that is, uses cgo.
+// - no file in the package has GOOS or GOARCH build tags or file names.
+// - comments associated with the package or import declarations,
+//   may be discarded, as may comments associated with no top-level
+//   declaration at all.
+// - neither the original package nor the destination package contains
+//   any identifiers starting with the designated prefix.
+//   (This allows us to avoid various conflict checks.)
+// - there are no renaming imports.
+// - test files are ignored.
+// - none of the renamed identifiers is significant
+//   to reflection-based logic.
+//
+// Only package-level var, func, const, and type objects are renamed,
+// and embedded fields of renamed types.  No methods are renamed, so we
+// needn't worry about preserving interface satisfaction.
+//
+package main
+
+import (
+	"bytes"
+	"flag"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/format"
+	"go/parser"
+	"go/token"
+	"go/types"
+	"io"
+	"log"
+	"os"
+	"path/filepath"
+	"strings"
+
+	"golang.org/x/tools/go/loader"
+)
+
+func main() {
+	log.SetPrefix("bundle: ")
+	log.SetFlags(0)
+
+	flag.Parse()
+	args := flag.Args()
+	if len(args) != 3 {
+		log.Fatal(`Usage: bundle package dest prefix
+
+Arguments:
+ package is the import path of the package to concatenate.
+ dest is the import path of the package in which the resulting file will reside.
+ prefix is the string to attach to all renamed identifiers.
+`)
+	}
+	initialPkg, dest, prefix := args[0], args[1], args[2]
+
+	if err := bundle(os.Stdout, initialPkg, dest, prefix); err != nil {
+		log.Fatal(err)
+	}
+}
+
+var ctxt = &build.Default
+
+func bundle(w io.Writer, initialPkg, dest, prefix string) error {
+	// Load the initial package.
+	conf := loader.Config{ParserMode: parser.ParseComments, Build: ctxt}
+	conf.TypeCheckFuncBodies = func(p string) bool { return p == initialPkg }
+	conf.Import(initialPkg)
+
+	lprog, err := conf.Load()
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	info := lprog.Package(initialPkg)
+
+	objsToUpdate := make(map[types.Object]bool)
+	var rename func(from types.Object)
+	rename = func(from types.Object) {
+		if !objsToUpdate[from] {
+			objsToUpdate[from] = true
+
+			// Renaming a type that is used as an embedded field
+			// requires renaming the field too. e.g.
+			// 	type T int // if we rename this to U..
+			// 	var s struct {T}
+			// 	print(s.T) // ...this must change too
+			if _, ok := from.(*types.TypeName); ok {
+				for id, obj := range info.Uses {
+					if obj == from {
+						if field := info.Defs[id]; field != nil {
+							rename(field)
+						}
+					}
+				}
+			}
+		}
+	}
+
+	// Rename each package-level object.
+	scope := info.Pkg.Scope()
+	for _, name := range scope.Names() {
+		rename(scope.Lookup(name))
+	}
+
+	var out bytes.Buffer
+
+	fmt.Fprintf(&out, "// Code generated by golang.org/x/tools/cmd/bundle command:\n")
+	fmt.Fprintf(&out, "//   $ bundle %s %s %s\n\n", initialPkg, dest, prefix)
+
+	// Concatenate package comments from all files...
+	for _, f := range info.Files {
+		if doc := f.Doc.Text(); strings.TrimSpace(doc) != "" {
+			for _, line := range strings.Split(doc, "\n") {
+				fmt.Fprintf(&out, "// %s\n", line)
+			}
+		}
+	}
+	// ...but don't let them become the actual package comment.
+	fmt.Fprintln(&out)
+
+	// TODO(adonovan): don't assume pkg.name == basename(pkg.path).
+	fmt.Fprintf(&out, "package %s\n\n", filepath.Base(dest))
+
+	// Print a single declaration that imports all necessary packages.
+	// TODO(adonovan):
+	// - support renaming imports.
+	// - preserve comments from the original import declarations.
+	for _, f := range info.Files {
+		for _, imp := range f.Imports {
+			if imp.Name != nil {
+				log.Fatalf("%s: renaming imports not supported",
+					lprog.Fset.Position(imp.Pos()))
+			}
+		}
+	}
+	fmt.Fprintln(&out, "import (")
+	for _, p := range info.Pkg.Imports() {
+		if p.Path() == dest {
+			continue
+		}
+		fmt.Fprintf(&out, "\t%q\n", p.Path())
+	}
+	fmt.Fprintln(&out, ")\n")
+
+	// Modify and print each file.
+	for _, f := range info.Files {
+		// Update renamed identifiers.
+		for id, obj := range info.Defs {
+			if objsToUpdate[obj] {
+				id.Name = prefix + obj.Name()
+			}
+		}
+		for id, obj := range info.Uses {
+			if objsToUpdate[obj] {
+				id.Name = prefix + obj.Name()
+			}
+		}
+
+		// For each qualified identifier that refers to the
+		// destination package, remove the qualifier.
+		// The "@@@." strings are removed in postprocessing.
+		ast.Inspect(f, func(n ast.Node) bool {
+			if sel, ok := n.(*ast.SelectorExpr); ok {
+				if id, ok := sel.X.(*ast.Ident); ok {
+					if obj, ok := info.Uses[id].(*types.PkgName); ok {
+						if obj.Imported().Path() == dest {
+							id.Name = "@@@"
+						}
+					}
+				}
+			}
+			return true
+		})
+
+		// Pretty-print package-level declarations.
+		// but no package or import declarations.
+		//
+		// TODO(adonovan): this may cause loss of comments
+		// preceding or associated with the package or import
+		// declarations or not associated with any declaration.
+		// Check.
+		var buf bytes.Buffer
+		for _, decl := range f.Decls {
+			if decl, ok := decl.(*ast.GenDecl); ok && decl.Tok == token.IMPORT {
+				continue
+			}
+			buf.Reset()
+			format.Node(&buf, lprog.Fset, decl)
+			// Remove each "@@@." in the output.
+			// TODO(adonovan): not hygienic.
+			out.Write(bytes.Replace(buf.Bytes(), []byte("@@@."), nil, -1))
+			out.WriteString("\n\n")
+		}
+	}
+
+	// Now format the entire thing.
+	result, err := format.Source(out.Bytes())
+	if err != nil {
+		log.Fatalf("formatting failed: %v", err)
+	}
+
+	_, err = w.Write(result)
+	return err
+}
diff --git a/go/src/golang.org/x/tools/cmd/bundle/main_test.go b/go/src/golang.org/x/tools/cmd/bundle/main_test.go
new file mode 100644
index 0000000..b4d0810
--- /dev/null
+++ b/go/src/golang.org/x/tools/cmd/bundle/main_test.go
@@ -0,0 +1,66 @@
+// Copyright 2015 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 main
+
+import (
+	"bytes"
+	"io/ioutil"
+	"os/exec"
+	"runtime"
+	"testing"
+
+	"golang.org/x/tools/go/buildutil"
+)
+
+func TestBundle(t *testing.T) {
+	load := func(name string) string {
+		data, err := ioutil.ReadFile(name)
+		if err != nil {
+			t.Fatal(err)
+		}
+		return string(data)
+	}
+
+	ctxt = buildutil.FakeContext(map[string]map[string]string{
+		"initial": {
+			"a.go": load("testdata/src/initial/a.go"),
+			"b.go": load("testdata/src/initial/b.go"),
+		},
+		"fmt": {
+			"print.go": `package fmt; func Println(...interface{})`,
+		},
+	})
+
+	var out bytes.Buffer
+	if err := bundle(&out, "initial", "dest", "prefix"); err != nil {
+		t.Fatal(err)
+	}
+	if got, want := out.String(), load("testdata/out.golden"); got != want {
+		t.Errorf("-- got --\n%s\n-- want --\n%s\n-- diff --", got, want)
+
+		if err := ioutil.WriteFile("testdata/out.got", out.Bytes(), 0644); err != nil {
+			t.Fatal(err)
+		}
+		t.Log(diff("testdata/out.got", "testdata/out.golden"))
+	}
+}
+
+func diff(a, b string) string {
+	var cmd *exec.Cmd
+	switch runtime.GOOS {
+	case "plan9":
+		cmd = exec.Command("/bin/diff", "-c", a, b)
+	default:
+		cmd = exec.Command("/usr/bin/diff", "-u", a, b)
+	}
+	var out bytes.Buffer
+	cmd.Stdout = &out
+	cmd.Stderr = &out
+	cmd.Run() // nonzero exit is expected
+	if out.Len() == 0 {
+		return "(failed to compute diff)"
+	}
+	return out.String()
+}
diff --git a/go/src/golang.org/x/tools/cmd/bundle/testdata/out.golden b/go/src/golang.org/x/tools/cmd/bundle/testdata/out.golden
new file mode 100644
index 0000000..5153d3f
--- /dev/null
+++ b/go/src/golang.org/x/tools/cmd/bundle/testdata/out.golden
@@ -0,0 +1,31 @@
+// Code generated by golang.org/x/tools/cmd/bundle command:
+//   $ bundle initial dest prefix
+
+// The package doc comment
+//
+
+package dest
+
+import (
+	"fmt"
+)
+
+// init functions are not renamed
+func init() { prefixfoo() }
+
+// Type S.
+type prefixS struct {
+	prefixt
+	u int
+}
+
+// Function bar.
+func prefixbar(s *prefixS) { fmt.Println(s.prefixt, s.u) }
+
+type prefixt int
+
+const prefixc = 1
+
+func prefixfoo() {
+	fmt.Println()
+}
diff --git a/go/src/golang.org/x/tools/cmd/bundle/testdata/src/initial/a.go b/go/src/golang.org/x/tools/cmd/bundle/testdata/src/initial/a.go
new file mode 100644
index 0000000..99cd145
--- /dev/null
+++ b/go/src/golang.org/x/tools/cmd/bundle/testdata/src/initial/a.go
@@ -0,0 +1,15 @@
+package initial
+
+import "fmt"
+
+// init functions are not renamed
+func init() { foo() }
+
+// Type S.
+type S struct {
+	t
+	u int
+}
+
+// Function bar.
+func bar(s *S) { fmt.Println(s.t, s.u) }
diff --git a/go/src/golang.org/x/tools/cmd/bundle/testdata/src/initial/b.go b/go/src/golang.org/x/tools/cmd/bundle/testdata/src/initial/b.go
new file mode 100644
index 0000000..399b6ed
--- /dev/null
+++ b/go/src/golang.org/x/tools/cmd/bundle/testdata/src/initial/b.go
@@ -0,0 +1,12 @@
+// The package doc comment
+package initial
+
+import "fmt"
+
+type t int
+
+const c = 1
+
+func foo() {
+	fmt.Println()
+}
diff --git a/go/src/golang.org/x/tools/cmd/callgraph/main.go b/go/src/golang.org/x/tools/cmd/callgraph/main.go
index 29179dd..eed92aa 100644
--- a/go/src/golang.org/x/tools/cmd/callgraph/main.go
+++ b/go/src/golang.org/x/tools/cmd/callgraph/main.go
@@ -20,12 +20,14 @@
 //     callee file/line/col
 
 import (
+	"bufio"
 	"bytes"
 	"flag"
 	"fmt"
 	"go/build"
 	"go/token"
 	"io"
+	"log"
 	"os"
 	"runtime"
 	"text/template"
@@ -41,15 +43,21 @@
 	"golang.org/x/tools/go/ssa/ssautil"
 )
 
-var algoFlag = flag.String("algo", "rta",
-	`Call graph construction algorithm (static, cha, rta, pta)`)
+// flags
+var (
+	algoFlag = flag.String("algo", "rta",
+		`Call graph construction algorithm (static, cha, rta, pta)`)
 
-var testFlag = flag.Bool("test", false,
-	"Loads test code (*_test.go) for imported packages")
+	testFlag = flag.Bool("test", false,
+		"Loads test code (*_test.go) for imported packages")
 
-var formatFlag = flag.String("format",
-	"{{.Caller}}\t--{{.Dynamic}}-{{.Line}}:{{.Column}}-->\t{{.Callee}}",
-	"A template expression specifying how to format an edge")
+	formatFlag = flag.String("format",
+		"{{.Caller}}\t--{{.Dynamic}}-{{.Line}}:{{.Column}}-->\t{{.Callee}}",
+		"A template expression specifying how to format an edge")
+
+	ptalogFlag = flag.String("ptalog", "",
+		"Location of the points-to analysis log file, or empty to disable logging.")
+)
 
 func init() {
 	flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsFlagDoc)
@@ -180,7 +188,7 @@
 
 	// Create and build SSA-form program representation.
 	prog := ssautil.CreateProgram(iprog, 0)
-	prog.BuildAll()
+	prog.Build()
 
 	// -- call graph construction ------------------------------------------
 
@@ -194,6 +202,25 @@
 		cg = cha.CallGraph(prog)
 
 	case "pta":
+		// Set up points-to analysis log file.
+		var ptalog io.Writer
+		if *ptalogFlag != "" {
+			if f, err := os.Create(*ptalogFlag); err != nil {
+				log.Fatalf("Failed to create PTA log file: %s", err)
+			} else {
+				buf := bufio.NewWriter(f)
+				ptalog = buf
+				defer func() {
+					if err := buf.Flush(); err != nil {
+						log.Printf("flush: %s", err)
+					}
+					if err := f.Close(); err != nil {
+						log.Printf("close: %s", err)
+					}
+				}()
+			}
+		}
+
 		main, err := mainPackage(prog, tests)
 		if err != nil {
 			return err
@@ -201,6 +228,7 @@
 		config := &pointer.Config{
 			Mains:          []*ssa.Package{main},
 			BuildCallGraph: true,
+			Log:            ptalog,
 		}
 		ptares, err := pointer.Analyze(config)
 		if err != nil {
@@ -295,7 +323,7 @@
 
 	// Otherwise, use the first package named main.
 	for _, pkg := range pkgs {
-		if pkg.Object.Name() == "main" {
+		if pkg.Pkg.Name() == "main" {
 			if pkg.Func("main") == nil {
 				return nil, fmt.Errorf("no func main() in main package")
 			}
diff --git a/go/src/golang.org/x/tools/cmd/eg/eg.go b/go/src/golang.org/x/tools/cmd/eg/eg.go
index 5970c1a..c3cee7d 100644
--- a/go/src/golang.org/x/tools/cmd/eg/eg.go
+++ b/go/src/golang.org/x/tools/cmd/eg/eg.go
@@ -90,7 +90,7 @@
 
 	// Analyze the template.
 	template := iprog.Created[0]
-	xform, err := eg.NewTransformer(iprog.Fset, template, *verboseFlag)
+	xform, err := eg.NewTransformer(iprog.Fset, template.Pkg, template.Files[0], &template.Info, *verboseFlag)
 	if err != nil {
 		return err
 	}
diff --git a/go/src/golang.org/x/tools/cmd/fiximports/main.go b/go/src/golang.org/x/tools/cmd/fiximports/main.go
index 86ae777..365a261 100644
--- a/go/src/golang.org/x/tools/cmd/fiximports/main.go
+++ b/go/src/golang.org/x/tools/cmd/fiximports/main.go
@@ -96,6 +96,8 @@
 	dryrun     = flag.Bool("n", false, "dry run: show changes, but don't apply them")
 	badDomains = flag.String("baddomains", "code.google.com",
 		"a comma-separated list of domains from which packages should not be imported")
+	replaceFlag = flag.String("replace", "",
+		"a comma-separated list of noncanonical=canonical pairs of package paths.  If both items in a pair end with '...', they are treated as path prefixes.")
 )
 
 // seams for testing
@@ -132,6 +134,8 @@
 	}
 }
 
+type canonicalName struct{ path, name string }
+
 // fiximports fixes imports in the specified packages.
 // Invariant: a false result implies an error was already printed.
 func fiximports(packages ...string) bool {
@@ -158,13 +162,41 @@
 		return false
 	}
 
-	// noncanonical maps each non-canonical package path to
-	// its canonical name.
+	// packageName maps each package's path to its name.
+	packageName := make(map[string]string)
+	for _, p := range pkgs {
+		packageName[p.ImportPath] = p.Package.Name
+	}
+
+	// canonical maps each non-canonical package path to
+	// its canonical path and name.
 	// A present nil value indicates that the canonical package
 	// is unknown: hosted on a bad domain with no redirect.
-	noncanonical := make(map[string]*build.Package)
+	canonical := make(map[string]canonicalName)
 	domains := strings.Split(*badDomains, ",")
 
+	type replaceItem struct {
+		old, new    string
+		matchPrefix bool
+	}
+	var replace []replaceItem
+	for _, pair := range strings.Split(*replaceFlag, ",") {
+		if pair == "" {
+			continue
+		}
+		words := strings.Split(pair, "=")
+		if len(words) != 2 {
+			fmt.Fprintf(stderr, "importfix: -replace: %q is not of the form \"canonical=noncanonical\".\n", pair)
+			return false
+		}
+		replace = append(replace, replaceItem{
+			old: strings.TrimSuffix(words[0], "..."),
+			new: strings.TrimSuffix(words[1], "..."),
+			matchPrefix: strings.HasSuffix(words[0], "...") &&
+				strings.HasSuffix(words[1], "..."),
+		})
+	}
+
 	// Find non-canonical packages and populate importedBy graph.
 	for _, p := range pkgs {
 		if p.Error != nil {
@@ -187,11 +219,41 @@
 			addEdge(&p.Package, imp)
 		}
 
+		// Does package have an explicit import comment?
 		if p.ImportComment != "" {
 			if p.ImportComment != p.ImportPath {
-				noncanonical[p.ImportPath] = &p.Package
+				canonical[p.ImportPath] = canonicalName{
+					path: p.Package.ImportComment,
+					name: p.Package.Name,
+				}
 			}
 		} else {
+			// Is package matched by a -replace item?
+			var newPath string
+			for _, item := range replace {
+				if item.matchPrefix {
+					if strings.HasPrefix(p.ImportPath, item.old) {
+						newPath = item.new + p.ImportPath[len(item.old):]
+						break
+					}
+				} else if p.ImportPath == item.old {
+					newPath = item.new
+					break
+				}
+			}
+			if newPath != "" {
+				newName := packageName[newPath]
+				if newName == "" {
+					newName = filepath.Base(newPath) // a guess
+				}
+				canonical[p.ImportPath] = canonicalName{
+					path: newPath,
+					name: newName,
+				}
+				continue
+			}
+
+			// Is package matched by a -baddomains item?
 			for _, domain := range domains {
 				slash := strings.Index(p.ImportPath, "/")
 				if slash < 0 {
@@ -200,7 +262,7 @@
 				if p.ImportPath[:slash] == domain {
 					// Package comes from bad domain and has no import comment.
 					// Report an error each time this package is imported.
-					noncanonical[p.ImportPath] = nil
+					canonical[p.ImportPath] = canonicalName{}
 
 					// TODO(adonovan): should we make an HTTP request to
 					// see if there's an HTTP redirect, a "go-import" meta tag,
@@ -212,10 +274,10 @@
 		}
 	}
 
-	// Find all clients (direct importers) of noncanonical packages.
+	// Find all clients (direct importers) of canonical packages.
 	// These are the packages that need fixing up.
 	clients := make(map[*build.Package]bool)
-	for path := range noncanonical {
+	for path := range canonical {
 		for client := range importedBy[path] {
 			clients[client] = true
 		}
@@ -244,7 +306,7 @@
 	// Rewrite selected client packages.
 	ok := true
 	for client := range clients {
-		if !rewritePackage(client, noncanonical) {
+		if !rewritePackage(client, canonical) {
 			ok = false
 
 			// There were errors.
@@ -291,7 +353,7 @@
 }
 
 // Invariant: false result => error already printed.
-func rewritePackage(client *build.Package, noncanonical map[string]*build.Package) bool {
+func rewritePackage(client *build.Package, canonical map[string]canonicalName) bool {
 	ok := true
 
 	used := make(map[string]bool)
@@ -305,7 +367,7 @@
 			first = true
 			fmt.Fprintf(stderr, "%s\n", client.ImportPath)
 		}
-		err := rewriteFile(filepath.Join(client.Dir, filename), noncanonical, used)
+		err := rewriteFile(filepath.Join(client.Dir, filename), canonical, used)
 		if err != nil {
 			fmt.Fprintf(stderr, "\tERROR: %v\n", err)
 			ok = false
@@ -319,8 +381,8 @@
 	}
 	sort.Strings(keys)
 	for _, key := range keys {
-		if p := noncanonical[key]; p != nil {
-			fmt.Fprintf(stderr, "\tfixed: %s -> %s\n", key, p.ImportComment)
+		if p := canonical[key]; p.path != "" {
+			fmt.Fprintf(stderr, "\tfixed: %s -> %s\n", key, p.path)
 		} else {
 			fmt.Fprintf(stderr, "\tERROR: %s has no import comment\n", key)
 			ok = false
@@ -331,10 +393,10 @@
 }
 
 // rewrite reads, modifies, and writes filename, replacing all imports
-// of packages P in noncanonical by noncanonical[P].
-// It records in used which noncanonical packages were imported.
+// of packages P in canonical by canonical[P].
+// It records in used which canonical packages were imported.
 // used[P]=="" indicates that P was imported but its canonical path is unknown.
-func rewriteFile(filename string, noncanonical map[string]*build.Package, used map[string]bool) error {
+func rewriteFile(filename string, canonical map[string]canonicalName, used map[string]bool) error {
 	fset := token.NewFileSet()
 	f, err := parser.ParseFile(fset, filename, nil, parser.ParseComments)
 	if err != nil {
@@ -348,15 +410,15 @@
 				fset.Position(imp.Pos()), imp.Path.Value, err)
 			continue
 		}
-		p, ok := noncanonical[impPath]
+		canon, ok := canonical[impPath]
 		if !ok {
 			continue // import path is canonical
 		}
 
 		used[impPath] = true
 
-		if p == nil {
-			// The canonical path is unknown.
+		if canon.path == "" {
+			// The canonical path is unknown (a -baddomain).
 			// Show the offending import.
 			// TODO(adonovan): should we show the actual source text?
 			fmt.Fprintf(stderr, "\t%s:%d: import %q\n",
@@ -367,18 +429,16 @@
 
 		changed = true
 
-		imp.Path.Value = strconv.Quote(p.ImportComment)
+		imp.Path.Value = strconv.Quote(canon.path)
 
 		// Add a renaming import if necessary.
 		//
 		// This is a guess at best.  We can't see whether a 'go
 		// get' of the canonical import path would have the same
 		// name or not.  Assume it's the last segment.
-		//
-		// TODO(adonovan): should we make an HTTP request?
-		newBase := path.Base(p.ImportComment)
-		if imp.Name == nil && newBase != p.Name {
-			imp.Name = &ast.Ident{Name: p.Name}
+		newBase := path.Base(canon.path)
+		if imp.Name == nil && newBase != canon.name {
+			imp.Name = &ast.Ident{Name: canon.name}
 		}
 	}
 
diff --git a/go/src/golang.org/x/tools/cmd/fiximports/main_test.go b/go/src/golang.org/x/tools/cmd/fiximports/main_test.go
index c8f7bc3..e6be110 100644
--- a/go/src/golang.org/x/tools/cmd/fiximports/main_test.go
+++ b/go/src/golang.org/x/tools/cmd/fiximports/main_test.go
@@ -40,11 +40,13 @@
 	defer func() {
 		stderr = os.Stderr
 		*badDomains = "code.google.com"
+		*replaceFlag = ""
 	}()
 
 	for i, test := range []struct {
 		packages    []string // packages to rewrite, "go list" syntax
 		badDomains  string   // -baddomains flag
+		replaceFlag string   // -replace flag
 		wantOK      bool
 		wantStderr  string
 		wantRewrite map[string]string
@@ -106,8 +108,77 @@
 )`,
 			},
 		},
+		// #3. The -replace flag lets user supply missing import comments.
+		{
+			packages:    []string{"all"},
+			replaceFlag: "titanic.biz/foo=new.com/foo",
+			wantOK:      true,
+			wantStderr: `
+testdata/src/old.com/bad/bad.go:2:43: expected 'package', found 'EOF'
+fruit.io/banana
+	fixed: old.com/one -> new.com/one
+	fixed: titanic.biz/bar -> new.com/bar
+	fixed: titanic.biz/foo -> new.com/foo
+`,
+			wantRewrite: map[string]string{
+				"$GOPATH/src/fruit.io/banana/banana.go": `package banana
+
+import (
+	_ "new.com/bar"
+	_ "new.com/foo"
+	_ "new.com/one"
+)`,
+			},
+		},
+		// #4. The -replace flag supports wildcards.
+		//     An explicit import comment takes precedence.
+		{
+			packages:    []string{"all"},
+			replaceFlag: "titanic.biz/...=new.com/...",
+			wantOK:      true,
+			wantStderr: `
+testdata/src/old.com/bad/bad.go:2:43: expected 'package', found 'EOF'
+fruit.io/banana
+	fixed: old.com/one -> new.com/one
+	fixed: titanic.biz/bar -> new.com/bar
+	fixed: titanic.biz/foo -> new.com/foo
+`,
+			wantRewrite: map[string]string{
+				"$GOPATH/src/fruit.io/banana/banana.go": `package banana
+
+import (
+	_ "new.com/bar"
+	_ "new.com/foo"
+	_ "new.com/one"
+)`,
+			},
+		},
+		// #5. The -replace flag trumps -baddomains.
+		{
+			packages:    []string{"all"},
+			badDomains:  "titanic.biz",
+			replaceFlag: "titanic.biz/foo=new.com/foo",
+			wantOK:      true,
+			wantStderr: `
+testdata/src/old.com/bad/bad.go:2:43: expected 'package', found 'EOF'
+fruit.io/banana
+	fixed: old.com/one -> new.com/one
+	fixed: titanic.biz/bar -> new.com/bar
+	fixed: titanic.biz/foo -> new.com/foo
+`,
+			wantRewrite: map[string]string{
+				"$GOPATH/src/fruit.io/banana/banana.go": `package banana
+
+import (
+	_ "new.com/bar"
+	_ "new.com/foo"
+	_ "new.com/one"
+)`,
+			},
+		},
 	} {
 		*badDomains = test.badDomains
+		*replaceFlag = test.replaceFlag
 
 		stderr = new(bytes.Buffer)
 		gotRewrite := make(map[string]string)
diff --git a/go/src/golang.org/x/tools/cmd/godex/gc.go b/go/src/golang.org/x/tools/cmd/godex/gc.go
index 85335b9..e252900 100644
--- a/go/src/golang.org/x/tools/cmd/godex/gc.go
+++ b/go/src/golang.org/x/tools/cmd/godex/gc.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 // This file implements access to gc-generated export data.
 
 package main
diff --git a/go/src/golang.org/x/tools/cmd/godex/gc14.go b/go/src/golang.org/x/tools/cmd/godex/gc14.go
new file mode 100644
index 0000000..40c433d
--- /dev/null
+++ b/go/src/golang.org/x/tools/cmd/godex/gc14.go
@@ -0,0 +1,17 @@
+// Copyright 2014 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.
+
+// +build !go1.5
+
+// This file implements access to gc-generated export data.
+
+package main
+
+import (
+	"golang.org/x/tools/go/gcimporter"
+)
+
+func init() {
+	register("gc", gcimporter.Import)
+}
diff --git a/go/src/golang.org/x/tools/cmd/godex/gccgo.go b/go/src/golang.org/x/tools/cmd/godex/gccgo.go
index aee2d8e..2f2168d 100644
--- a/go/src/golang.org/x/tools/cmd/godex/gccgo.go
+++ b/go/src/golang.org/x/tools/cmd/godex/gccgo.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 // This file implements access to gccgo-generated export data.
 
 package main
diff --git a/go/src/golang.org/x/tools/cmd/godex/gccgo14.go b/go/src/golang.org/x/tools/cmd/godex/gccgo14.go
new file mode 100644
index 0000000..1317527
--- /dev/null
+++ b/go/src/golang.org/x/tools/cmd/godex/gccgo14.go
@@ -0,0 +1,42 @@
+// Copyright 2014 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.
+
+// +build !go1.5
+
+// This file implements access to gccgo-generated export data.
+
+package main
+
+import (
+	"golang.org/x/tools/go/gccgoimporter"
+	"golang.org/x/tools/go/types"
+)
+
+var (
+	initmap = make(map[*types.Package]gccgoimporter.InitData)
+)
+
+func init() {
+	incpaths := []string{"/"}
+
+	// importer for default gccgo
+	var inst gccgoimporter.GccgoInstallation
+	inst.InitFromDriver("gccgo")
+	register("gccgo", inst.GetImporter(incpaths, initmap))
+}
+
+// Print the extra gccgo compiler data for this package, if it exists.
+func (p *printer) printGccgoExtra(pkg *types.Package) {
+	if initdata, ok := initmap[pkg]; ok {
+		p.printf("/*\npriority %d\n", initdata.Priority)
+
+		p.printDecl("init", len(initdata.Inits), func() {
+			for _, init := range initdata.Inits {
+				p.printf("%s %s %d\n", init.Name, init.InitFunc, init.Priority)
+			}
+		})
+
+		p.print("*/\n")
+	}
+}
diff --git a/go/src/golang.org/x/tools/cmd/godex/godex.go b/go/src/golang.org/x/tools/cmd/godex/godex.go
index dee0990..3cdca2e 100644
--- a/go/src/golang.org/x/tools/cmd/godex/godex.go
+++ b/go/src/golang.org/x/tools/cmd/godex/godex.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package main
 
 import (
diff --git a/go/src/golang.org/x/tools/cmd/godex/godex14.go b/go/src/golang.org/x/tools/cmd/godex/godex14.go
new file mode 100644
index 0000000..c193bad
--- /dev/null
+++ b/go/src/golang.org/x/tools/cmd/godex/godex14.go
@@ -0,0 +1,209 @@
+// Copyright 2014 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.
+
+// +build !go1.5
+
+package main
+
+import (
+	"errors"
+	"flag"
+	"fmt"
+	"go/build"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"strings"
+
+	"golang.org/x/tools/go/types"
+)
+
+var (
+	source  = flag.String("s", "", "only consider packages from src, where src is one of the supported compilers")
+	verbose = flag.Bool("v", false, "verbose mode")
+)
+
+// lists of registered sources and corresponding importers
+var (
+	sources      []string
+	importers    []types.Importer
+	importFailed = errors.New("import failed")
+)
+
+// map of imported packages
+var packages = make(map[string]*types.Package)
+
+func usage() {
+	fmt.Fprintln(os.Stderr, "usage: godex [flags] {path|qualifiedIdent}")
+	flag.PrintDefaults()
+	os.Exit(2)
+}
+
+func report(msg string) {
+	fmt.Fprintln(os.Stderr, "error: "+msg)
+	os.Exit(2)
+}
+
+func main() {
+	flag.Usage = usage
+	flag.Parse()
+
+	if flag.NArg() == 0 {
+		report("no package name, path, or file provided")
+	}
+
+	imp := tryImports
+	if *source != "" {
+		imp = lookup(*source)
+		if imp == nil {
+			report("source (-s argument) must be one of: " + strings.Join(sources, ", "))
+		}
+	}
+
+	for _, arg := range flag.Args() {
+		path, name := splitPathIdent(arg)
+		logf("\tprocessing %q: path = %q, name = %s\n", arg, path, name)
+
+		// generate possible package path prefixes
+		// (at the moment we do this for each argument - should probably cache the generated prefixes)
+		prefixes := make(chan string)
+		go genPrefixes(prefixes, !filepath.IsAbs(path) && !build.IsLocalImport(path))
+
+		// import package
+		pkg, err := tryPrefixes(packages, prefixes, path, imp)
+		if err != nil {
+			logf("\t=> ignoring %q: %s\n", path, err)
+			continue
+		}
+
+		// filter objects if needed
+		var filter func(types.Object) bool
+		if name != "" {
+			filter = func(obj types.Object) bool {
+				// TODO(gri) perhaps use regular expression matching here?
+				return obj.Name() == name
+			}
+		}
+
+		// print contents
+		print(os.Stdout, pkg, filter)
+	}
+}
+
+func logf(format string, args ...interface{}) {
+	if *verbose {
+		fmt.Fprintf(os.Stderr, format, args...)
+	}
+}
+
+// splitPathIdent splits a path.name argument into its components.
+// All but the last path element may contain dots.
+func splitPathIdent(arg string) (path, name string) {
+	if i := strings.LastIndex(arg, "."); i >= 0 {
+		if j := strings.LastIndex(arg, "/"); j < i {
+			// '.' is not part of path
+			path = arg[:i]
+			name = arg[i+1:]
+			return
+		}
+	}
+	path = arg
+	return
+}
+
+// tryPrefixes tries to import the package given by (the possibly partial) path using the given importer imp
+// by prepending all possible prefixes to path. It returns with the first package that it could import, or
+// with an error.
+func tryPrefixes(packages map[string]*types.Package, prefixes chan string, path string, imp types.Importer) (pkg *types.Package, err error) {
+	for prefix := range prefixes {
+		actual := path
+		if prefix == "" {
+			// don't use filepath.Join as it will sanitize the path and remove
+			// a leading dot and then the path is not recognized as a relative
+			// package path by the importers anymore
+			logf("\ttrying no prefix\n")
+		} else {
+			actual = filepath.Join(prefix, path)
+			logf("\ttrying prefix %q\n", prefix)
+		}
+		pkg, err = imp(packages, actual)
+		if err == nil {
+			break
+		}
+		logf("\t=> importing %q failed: %s\n", actual, err)
+	}
+	return
+}
+
+// tryImports is an importer that tries all registered importers
+// successively until one of them succeeds or all of them failed.
+func tryImports(packages map[string]*types.Package, path string) (pkg *types.Package, err error) {
+	for i, imp := range importers {
+		logf("\t\ttrying %s import\n", sources[i])
+		pkg, err = imp(packages, path)
+		if err == nil {
+			break
+		}
+		logf("\t\t=> %s import failed: %s\n", sources[i], err)
+	}
+	return
+}
+
+// protect protects an importer imp from panics and returns the protected importer.
+func protect(imp types.Importer) types.Importer {
+	return func(packages map[string]*types.Package, path string) (pkg *types.Package, err error) {
+		defer func() {
+			if recover() != nil {
+				pkg = nil
+				err = importFailed
+			}
+		}()
+		return imp(packages, path)
+	}
+}
+
+// register registers an importer imp for a given source src.
+func register(src string, imp types.Importer) {
+	if lookup(src) != nil {
+		panic(src + " importer already registered")
+	}
+	sources = append(sources, src)
+	importers = append(importers, protect(imp))
+}
+
+// lookup returns the importer imp for a given source src.
+func lookup(src string) types.Importer {
+	for i, s := range sources {
+		if s == src {
+			return importers[i]
+		}
+	}
+	return nil
+}
+
+func genPrefixes(out chan string, all bool) {
+	out <- ""
+	if all {
+		platform := build.Default.GOOS + "_" + build.Default.GOARCH
+		dirnames := append([]string{build.Default.GOROOT}, filepath.SplitList(build.Default.GOPATH)...)
+		for _, dirname := range dirnames {
+			walkDir(filepath.Join(dirname, "pkg", platform), "", out)
+		}
+	}
+	close(out)
+}
+
+func walkDir(dirname, prefix string, out chan string) {
+	fiList, err := ioutil.ReadDir(dirname)
+	if err != nil {
+		return
+	}
+	for _, fi := range fiList {
+		if fi.IsDir() && !strings.HasPrefix(fi.Name(), ".") {
+			prefix := filepath.Join(prefix, fi.Name())
+			out <- prefix
+			walkDir(filepath.Join(dirname, fi.Name()), prefix, out)
+		}
+	}
+}
diff --git a/go/src/golang.org/x/tools/cmd/godex/print.go b/go/src/golang.org/x/tools/cmd/godex/print.go
index e519f41..d411afd 100644
--- a/go/src/golang.org/x/tools/cmd/godex/print.go
+++ b/go/src/golang.org/x/tools/cmd/godex/print.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package main
 
 import (
diff --git a/go/src/golang.org/x/tools/cmd/godex/print14.go b/go/src/golang.org/x/tools/cmd/godex/print14.go
new file mode 100644
index 0000000..55d7c5b
--- /dev/null
+++ b/go/src/golang.org/x/tools/cmd/godex/print14.go
@@ -0,0 +1,370 @@
+// Copyright 2014 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.
+
+// +build !go1.5
+
+package main
+
+import (
+	"bytes"
+	"fmt"
+	"go/token"
+	"io"
+	"math/big"
+
+	"golang.org/x/tools/go/exact"
+	"golang.org/x/tools/go/types"
+)
+
+// TODO(gri) use tabwriter for alignment?
+
+func print(w io.Writer, pkg *types.Package, filter func(types.Object) bool) {
+	var p printer
+	p.pkg = pkg
+	p.printPackage(pkg, filter)
+	p.printGccgoExtra(pkg)
+	io.Copy(w, &p.buf)
+}
+
+type printer struct {
+	pkg    *types.Package
+	buf    bytes.Buffer
+	indent int  // current indentation level
+	last   byte // last byte written
+}
+
+func (p *printer) print(s string) {
+	// Write the string one byte at a time. We care about the presence of
+	// newlines for indentation which we will see even in the presence of
+	// (non-corrupted) Unicode; no need to read one rune at a time.
+	for i := 0; i < len(s); i++ {
+		ch := s[i]
+		if ch != '\n' && p.last == '\n' {
+			// Note: This could lead to a range overflow for very large
+			// indentations, but it's extremely unlikely to happen for
+			// non-pathological code.
+			p.buf.WriteString("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"[:p.indent])
+		}
+		p.buf.WriteByte(ch)
+		p.last = ch
+	}
+}
+
+func (p *printer) printf(format string, args ...interface{}) {
+	p.print(fmt.Sprintf(format, args...))
+}
+
+// methodsFor returns the named type and corresponding methods if the type
+// denoted by obj is not an interface and has methods. Otherwise it returns
+// the zero value.
+func methodsFor(obj *types.TypeName) (*types.Named, []*types.Selection) {
+	named, _ := obj.Type().(*types.Named)
+	if named == nil {
+		// A type name's type can also be the
+		// exported basic type unsafe.Pointer.
+		return nil, nil
+	}
+	if _, ok := named.Underlying().(*types.Interface); ok {
+		// ignore interfaces
+		return nil, nil
+	}
+	methods := combinedMethodSet(named)
+	if len(methods) == 0 {
+		return nil, nil
+	}
+	return named, methods
+}
+
+func (p *printer) printPackage(pkg *types.Package, filter func(types.Object) bool) {
+	// collect objects by kind
+	var (
+		consts   []*types.Const
+		typem    []*types.Named    // non-interface types with methods
+		typez    []*types.TypeName // interfaces or types without methods
+		vars     []*types.Var
+		funcs    []*types.Func
+		builtins []*types.Builtin
+		methods  = make(map[*types.Named][]*types.Selection) // method sets for named types
+	)
+	scope := pkg.Scope()
+	for _, name := range scope.Names() {
+		obj := scope.Lookup(name)
+		if obj.Exported() {
+			// collect top-level exported and possibly filtered objects
+			if filter == nil || filter(obj) {
+				switch obj := obj.(type) {
+				case *types.Const:
+					consts = append(consts, obj)
+				case *types.TypeName:
+					// group into types with methods and types without
+					if named, m := methodsFor(obj); named != nil {
+						typem = append(typem, named)
+						methods[named] = m
+					} else {
+						typez = append(typez, obj)
+					}
+				case *types.Var:
+					vars = append(vars, obj)
+				case *types.Func:
+					funcs = append(funcs, obj)
+				case *types.Builtin:
+					// for unsafe.Sizeof, etc.
+					builtins = append(builtins, obj)
+				}
+			}
+		} else if filter == nil {
+			// no filtering: collect top-level unexported types with methods
+			if obj, _ := obj.(*types.TypeName); obj != nil {
+				// see case *types.TypeName above
+				if named, m := methodsFor(obj); named != nil {
+					typem = append(typem, named)
+					methods[named] = m
+				}
+			}
+		}
+	}
+
+	p.printf("package %s  // %q\n", pkg.Name(), pkg.Path())
+
+	p.printDecl("const", len(consts), func() {
+		for _, obj := range consts {
+			p.printObj(obj)
+			p.print("\n")
+		}
+	})
+
+	p.printDecl("var", len(vars), func() {
+		for _, obj := range vars {
+			p.printObj(obj)
+			p.print("\n")
+		}
+	})
+
+	p.printDecl("type", len(typez), func() {
+		for _, obj := range typez {
+			p.printf("%s ", obj.Name())
+			p.writeType(p.pkg, obj.Type().Underlying())
+			p.print("\n")
+		}
+	})
+
+	// non-interface types with methods
+	for _, named := range typem {
+		first := true
+		if obj := named.Obj(); obj.Exported() {
+			if first {
+				p.print("\n")
+				first = false
+			}
+			p.printf("type %s ", obj.Name())
+			p.writeType(p.pkg, named.Underlying())
+			p.print("\n")
+		}
+		for _, m := range methods[named] {
+			if obj := m.Obj(); obj.Exported() {
+				if first {
+					p.print("\n")
+					first = false
+				}
+				p.printFunc(m.Recv(), obj.(*types.Func))
+				p.print("\n")
+			}
+		}
+	}
+
+	if len(funcs) > 0 {
+		p.print("\n")
+		for _, obj := range funcs {
+			p.printFunc(nil, obj)
+			p.print("\n")
+		}
+	}
+
+	// TODO(gri) better handling of builtins (package unsafe only)
+	if len(builtins) > 0 {
+		p.print("\n")
+		for _, obj := range builtins {
+			p.printf("func %s() // builtin\n", obj.Name())
+		}
+	}
+
+	p.print("\n")
+}
+
+func (p *printer) printDecl(keyword string, n int, printGroup func()) {
+	switch n {
+	case 0:
+		// nothing to do
+	case 1:
+		p.printf("\n%s ", keyword)
+		printGroup()
+	default:
+		p.printf("\n%s (\n", keyword)
+		p.indent++
+		printGroup()
+		p.indent--
+		p.print(")\n")
+	}
+}
+
+// absInt returns the absolute value of v as a *big.Int.
+// v must be a numeric value.
+func absInt(v exact.Value) *big.Int {
+	// compute big-endian representation of v
+	b := exact.Bytes(v) // little-endian
+	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
+		b[i], b[j] = b[j], b[i]
+	}
+	return new(big.Int).SetBytes(b)
+}
+
+var (
+	one = big.NewRat(1, 1)
+	ten = big.NewRat(10, 1)
+)
+
+// floatString returns the string representation for a
+// numeric value v in normalized floating-point format.
+func floatString(v exact.Value) string {
+	if exact.Sign(v) == 0 {
+		return "0.0"
+	}
+	// x != 0
+
+	// convert |v| into a big.Rat x
+	x := new(big.Rat).SetFrac(absInt(exact.Num(v)), absInt(exact.Denom(v)))
+
+	// normalize x and determine exponent e
+	// (This is not very efficient, but also not speed-critical.)
+	var e int
+	for x.Cmp(ten) >= 0 {
+		x.Quo(x, ten)
+		e++
+	}
+	for x.Cmp(one) < 0 {
+		x.Mul(x, ten)
+		e--
+	}
+
+	// TODO(gri) Values such as 1/2 are easier to read in form 0.5
+	// rather than 5.0e-1. Similarly, 1.0e1 is easier to read as
+	// 10.0. Fine-tune best exponent range for readability.
+
+	s := x.FloatString(100) // good-enough precision
+
+	// trim trailing 0's
+	i := len(s)
+	for i > 0 && s[i-1] == '0' {
+		i--
+	}
+	s = s[:i]
+
+	// add a 0 if the number ends in decimal point
+	if len(s) > 0 && s[len(s)-1] == '.' {
+		s += "0"
+	}
+
+	// add exponent and sign
+	if e != 0 {
+		s += fmt.Sprintf("e%+d", e)
+	}
+	if exact.Sign(v) < 0 {
+		s = "-" + s
+	}
+
+	// TODO(gri) If v is a "small" fraction (i.e., numerator and denominator
+	// are just a small number of decimal digits), add the exact fraction as
+	// a comment. For instance: 3.3333...e-1 /* = 1/3 */
+
+	return s
+}
+
+// valString returns the string representation for the value v.
+// Setting floatFmt forces an integer value to be formatted in
+// normalized floating-point format.
+// TODO(gri) Move this code into package exact.
+func valString(v exact.Value, floatFmt bool) string {
+	switch v.Kind() {
+	case exact.Int:
+		if floatFmt {
+			return floatString(v)
+		}
+	case exact.Float:
+		return floatString(v)
+	case exact.Complex:
+		re := exact.Real(v)
+		im := exact.Imag(v)
+		var s string
+		if exact.Sign(re) != 0 {
+			s = floatString(re)
+			if exact.Sign(im) >= 0 {
+				s += " + "
+			} else {
+				s += " - "
+				im = exact.UnaryOp(token.SUB, im, 0) // negate im
+			}
+		}
+		// im != 0, otherwise v would be exact.Int or exact.Float
+		return s + floatString(im) + "i"
+	}
+	return v.String()
+}
+
+func (p *printer) printObj(obj types.Object) {
+	p.print(obj.Name())
+
+	typ, basic := obj.Type().Underlying().(*types.Basic)
+	if basic && typ.Info()&types.IsUntyped != 0 {
+		// don't write untyped types
+	} else {
+		p.print(" ")
+		p.writeType(p.pkg, obj.Type())
+	}
+
+	if obj, ok := obj.(*types.Const); ok {
+		floatFmt := basic && typ.Info()&(types.IsFloat|types.IsComplex) != 0
+		p.print(" = ")
+		p.print(valString(obj.Val(), floatFmt))
+	}
+}
+
+func (p *printer) printFunc(recvType types.Type, obj *types.Func) {
+	p.print("func ")
+	sig := obj.Type().(*types.Signature)
+	if recvType != nil {
+		p.print("(")
+		p.writeType(p.pkg, recvType)
+		p.print(") ")
+	}
+	p.print(obj.Name())
+	p.writeSignature(p.pkg, sig)
+}
+
+// combinedMethodSet returns the method set for a named type T
+// merged with all the methods of *T that have different names than
+// the methods of T.
+//
+// combinedMethodSet is analogous to types/typeutil.IntuitiveMethodSet
+// but doesn't require a MethodSetCache.
+// TODO(gri) If this functionality doesn't change over time, consider
+// just calling IntuitiveMethodSet eventually.
+func combinedMethodSet(T *types.Named) []*types.Selection {
+	// method set for T
+	mset := types.NewMethodSet(T)
+	var res []*types.Selection
+	for i, n := 0, mset.Len(); i < n; i++ {
+		res = append(res, mset.At(i))
+	}
+
+	// add all *T methods with names different from T methods
+	pmset := types.NewMethodSet(types.NewPointer(T))
+	for i, n := 0, pmset.Len(); i < n; i++ {
+		pm := pmset.At(i)
+		if obj := pm.Obj(); mset.Lookup(obj.Pkg(), obj.Name()) == nil {
+			res = append(res, pm)
+		}
+	}
+
+	return res
+}
diff --git a/go/src/golang.org/x/tools/cmd/godex/source.go b/go/src/golang.org/x/tools/cmd/godex/source.go
index 22d7813..a86031a 100644
--- a/go/src/golang.org/x/tools/cmd/godex/source.go
+++ b/go/src/golang.org/x/tools/cmd/godex/source.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 // This file implements access to export data from source.
 
 package main
diff --git a/go/src/golang.org/x/tools/cmd/godex/source14.go b/go/src/golang.org/x/tools/cmd/godex/source14.go
new file mode 100644
index 0000000..620a9b3
--- /dev/null
+++ b/go/src/golang.org/x/tools/cmd/godex/source14.go
@@ -0,0 +1,21 @@
+// Copyright 2014 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.
+
+// +build !go1.5
+
+// This file implements access to export data from source.
+
+package main
+
+import (
+	"golang.org/x/tools/go/types"
+)
+
+func init() {
+	register("source", sourceImporter)
+}
+
+func sourceImporter(packages map[string]*types.Package, path string) (*types.Package, error) {
+	panic("unimplemented")
+}
diff --git a/go/src/golang.org/x/tools/cmd/godex/writetype.go b/go/src/golang.org/x/tools/cmd/godex/writetype.go
index 10c8e65..c079855 100644
--- a/go/src/golang.org/x/tools/cmd/godex/writetype.go
+++ b/go/src/golang.org/x/tools/cmd/godex/writetype.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 // This file implements writing of types. The functionality is lifted
 // directly from go/types, but now contains various modifications for
 // nicer output.
diff --git a/go/src/golang.org/x/tools/cmd/godex/writetype14.go b/go/src/golang.org/x/tools/cmd/godex/writetype14.go
new file mode 100644
index 0000000..ea009b4
--- /dev/null
+++ b/go/src/golang.org/x/tools/cmd/godex/writetype14.go
@@ -0,0 +1,244 @@
+// Copyright 2014 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.
+
+// +build !go1.5
+
+// This file implements writing of types. The functionality is lifted
+// directly from go/types, but now contains various modifications for
+// nicer output.
+//
+// TODO(gri) back-port once we have a fixed interface and once the
+// go/types API is not frozen anymore for the 1.3 release; and remove
+// this implementation if possible.
+
+package main
+
+import "golang.org/x/tools/go/types"
+
+func (p *printer) writeType(this *types.Package, typ types.Type) {
+	p.writeTypeInternal(this, typ, make([]types.Type, 8))
+}
+
+// From go/types - leave for now to ease back-porting this code.
+const GcCompatibilityMode = false
+
+func (p *printer) writeTypeInternal(this *types.Package, typ types.Type, visited []types.Type) {
+	// Theoretically, this is a quadratic lookup algorithm, but in
+	// practice deeply nested composite types with unnamed component
+	// types are uncommon. This code is likely more efficient than
+	// using a map.
+	for _, t := range visited {
+		if t == typ {
+			p.printf("â—‹%T", typ) // cycle to typ
+			return
+		}
+	}
+	visited = append(visited, typ)
+
+	switch t := typ.(type) {
+	case nil:
+		p.print("<nil>")
+
+	case *types.Basic:
+		if t.Kind() == types.UnsafePointer {
+			p.print("unsafe.")
+		}
+		if GcCompatibilityMode {
+			// forget the alias names
+			switch t.Kind() {
+			case types.Byte:
+				t = types.Typ[types.Uint8]
+			case types.Rune:
+				t = types.Typ[types.Int32]
+			}
+		}
+		p.print(t.Name())
+
+	case *types.Array:
+		p.printf("[%d]", t.Len())
+		p.writeTypeInternal(this, t.Elem(), visited)
+
+	case *types.Slice:
+		p.print("[]")
+		p.writeTypeInternal(this, t.Elem(), visited)
+
+	case *types.Struct:
+		n := t.NumFields()
+		if n == 0 {
+			p.print("struct{}")
+			return
+		}
+
+		p.print("struct {\n")
+		p.indent++
+		for i := 0; i < n; i++ {
+			f := t.Field(i)
+			if !f.Anonymous() {
+				p.printf("%s ", f.Name())
+			}
+			p.writeTypeInternal(this, f.Type(), visited)
+			if tag := t.Tag(i); tag != "" {
+				p.printf(" %q", tag)
+			}
+			p.print("\n")
+		}
+		p.indent--
+		p.print("}")
+
+	case *types.Pointer:
+		p.print("*")
+		p.writeTypeInternal(this, t.Elem(), visited)
+
+	case *types.Tuple:
+		p.writeTuple(this, t, false, visited)
+
+	case *types.Signature:
+		p.print("func")
+		p.writeSignatureInternal(this, t, visited)
+
+	case *types.Interface:
+		// We write the source-level methods and embedded types rather
+		// than the actual method set since resolved method signatures
+		// may have non-printable cycles if parameters have anonymous
+		// interface types that (directly or indirectly) embed the
+		// current interface. For instance, consider the result type
+		// of m:
+		//
+		//     type T interface{
+		//         m() interface{ T }
+		//     }
+		//
+		n := t.NumMethods()
+		if n == 0 {
+			p.print("interface{}")
+			return
+		}
+
+		p.print("interface {\n")
+		p.indent++
+		if GcCompatibilityMode {
+			// print flattened interface
+			// (useful to compare against gc-generated interfaces)
+			for i := 0; i < n; i++ {
+				m := t.Method(i)
+				p.print(m.Name())
+				p.writeSignatureInternal(this, m.Type().(*types.Signature), visited)
+				p.print("\n")
+			}
+		} else {
+			// print explicit interface methods and embedded types
+			for i, n := 0, t.NumExplicitMethods(); i < n; i++ {
+				m := t.ExplicitMethod(i)
+				p.print(m.Name())
+				p.writeSignatureInternal(this, m.Type().(*types.Signature), visited)
+				p.print("\n")
+			}
+			for i, n := 0, t.NumEmbeddeds(); i < n; i++ {
+				typ := t.Embedded(i)
+				p.writeTypeInternal(this, typ, visited)
+				p.print("\n")
+			}
+		}
+		p.indent--
+		p.print("}")
+
+	case *types.Map:
+		p.print("map[")
+		p.writeTypeInternal(this, t.Key(), visited)
+		p.print("]")
+		p.writeTypeInternal(this, t.Elem(), visited)
+
+	case *types.Chan:
+		var s string
+		var parens bool
+		switch t.Dir() {
+		case types.SendRecv:
+			s = "chan "
+			// chan (<-chan T) requires parentheses
+			if c, _ := t.Elem().(*types.Chan); c != nil && c.Dir() == types.RecvOnly {
+				parens = true
+			}
+		case types.SendOnly:
+			s = "chan<- "
+		case types.RecvOnly:
+			s = "<-chan "
+		default:
+			panic("unreachable")
+		}
+		p.print(s)
+		if parens {
+			p.print("(")
+		}
+		p.writeTypeInternal(this, t.Elem(), visited)
+		if parens {
+			p.print(")")
+		}
+
+	case *types.Named:
+		s := "<Named w/o object>"
+		if obj := t.Obj(); obj != nil {
+			if pkg := obj.Pkg(); pkg != nil {
+				if pkg != this {
+					p.print(pkg.Path())
+					p.print(".")
+				}
+				// TODO(gri): function-local named types should be displayed
+				// differently from named types at package level to avoid
+				// ambiguity.
+			}
+			s = obj.Name()
+		}
+		p.print(s)
+
+	default:
+		// For externally defined implementations of Type.
+		p.print(t.String())
+	}
+}
+
+func (p *printer) writeTuple(this *types.Package, tup *types.Tuple, variadic bool, visited []types.Type) {
+	p.print("(")
+	for i, n := 0, tup.Len(); i < n; i++ {
+		if i > 0 {
+			p.print(", ")
+		}
+		v := tup.At(i)
+		if name := v.Name(); name != "" {
+			p.print(name)
+			p.print(" ")
+		}
+		typ := v.Type()
+		if variadic && i == n-1 {
+			p.print("...")
+			typ = typ.(*types.Slice).Elem()
+		}
+		p.writeTypeInternal(this, typ, visited)
+	}
+	p.print(")")
+}
+
+func (p *printer) writeSignature(this *types.Package, sig *types.Signature) {
+	p.writeSignatureInternal(this, sig, make([]types.Type, 8))
+}
+
+func (p *printer) writeSignatureInternal(this *types.Package, sig *types.Signature, visited []types.Type) {
+	p.writeTuple(this, sig.Params(), sig.Variadic(), visited)
+
+	res := sig.Results()
+	n := res.Len()
+	if n == 0 {
+		// no result
+		return
+	}
+
+	p.print(" ")
+	if n == 1 && res.At(0).Name() == "" {
+		// single unnamed result
+		p.writeTypeInternal(this, res.At(0).Type(), visited)
+		return
+	}
+
+	// multiple or named result(s)
+	p.writeTuple(this, res, false, visited)
+}
diff --git a/go/src/golang.org/x/tools/cmd/godoc/appinit.go b/go/src/golang.org/x/tools/cmd/godoc/appinit.go
index 3d6a921..0c83df9 100644
--- a/go/src/golang.org/x/tools/cmd/godoc/appinit.go
+++ b/go/src/golang.org/x/tools/cmd/godoc/appinit.go
@@ -12,17 +12,24 @@
 import (
 	"archive/zip"
 	"log"
+	"net/http"
 	"path"
 	"regexp"
 
 	"golang.org/x/tools/godoc"
+	"golang.org/x/tools/godoc/dl"
+	"golang.org/x/tools/godoc/proxy"
+	"golang.org/x/tools/godoc/short"
 	"golang.org/x/tools/godoc/static"
 	"golang.org/x/tools/godoc/vfs"
 	"golang.org/x/tools/godoc/vfs/mapfs"
 	"golang.org/x/tools/godoc/vfs/zipfs"
+
+	"google.golang.org/appengine"
 )
 
 func init() {
+	enforceHosts = !appengine.IsDevAppServer()
 	playEnabled = true
 
 	log.Println("initializing godoc ...")
@@ -61,7 +68,15 @@
 	pres.NotesRx = regexp.MustCompile("BUG")
 
 	readTemplates(pres, true)
-	registerHandlers(pres)
+
+	mux := registerHandlers(pres)
+	dl.RegisterHandlers(mux)
+	short.RegisterHandlers(mux)
+
+	// Register /compile and /share handlers against the default serve mux
+	// so that other app modules can make plain HTTP requests to those
+	// hosts. (For reasons, HTTPS communication between modules is broken.)
+	proxy.RegisterHandlers(http.DefaultServeMux)
 
 	log.Println("godoc initialization complete")
 }
diff --git a/go/src/golang.org/x/tools/cmd/godoc/dl.go b/go/src/golang.org/x/tools/cmd/godoc/dl.go
index bd73831..40e6658 100644
--- a/go/src/golang.org/x/tools/cmd/godoc/dl.go
+++ b/go/src/golang.org/x/tools/cmd/godoc/dl.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build !appengine
+
 package main
 
 import "net/http"
@@ -10,5 +12,5 @@
 // This file will not be included when deploying godoc to golang.org.
 
 func init() {
-	http.Handle("/dl/", http.RedirectHandler("http://golang.org/dl/", http.StatusFound))
+	http.Handle("/dl/", http.RedirectHandler("https://golang.org/dl/", http.StatusFound))
 }
diff --git a/go/src/golang.org/x/tools/cmd/godoc/godoc_test.go b/go/src/golang.org/x/tools/cmd/godoc/godoc_test.go
index a228fae..e4ab12f 100644
--- a/go/src/golang.org/x/tools/cmd/godoc/godoc_test.go
+++ b/go/src/golang.org/x/tools/cmd/godoc/godoc_test.go
@@ -44,7 +44,9 @@
 	{
 		args: []string{"nonexistingpkg"},
 		matches: []string{
-			`no such file or directory|does not exist|cannot find the file`,
+			// The last pattern (does not e) is for plan9:
+			// http://build.golang.org/log/2d8e5e14ed365bfa434b37ec0338cd9e6f8dd9bf
+			`no such file or directory|does not exist|cannot find the file|(?:' does not e)`,
 		},
 	},
 	{
@@ -266,6 +268,18 @@
 			},
 			needIndex: true,
 		},
+		{
+			path: "/pkg/strings/",
+			match: []string{
+				`href="/src/strings/strings.go"`,
+			},
+		},
+		{
+			path: "/cmd/compile/internal/amd64/",
+			match: []string{
+				`href="/src/cmd/compile/internal/amd64/reg.go"`,
+			},
+		},
 	}
 	for _, test := range tests {
 		if test.needIndex && !withIndex {
diff --git a/go/src/golang.org/x/tools/cmd/godoc/handlers.go b/go/src/golang.org/x/tools/cmd/godoc/handlers.go
index 1f79d80..dda1bb8 100644
--- a/go/src/golang.org/x/tools/cmd/godoc/handlers.go
+++ b/go/src/golang.org/x/tools/cmd/godoc/handlers.go
@@ -13,8 +13,11 @@
 package main
 
 import (
+	"encoding/json"
+	"go/format"
 	"log"
 	"net/http"
+	"strings"
 	"text/template"
 
 	"golang.org/x/tools/godoc"
@@ -27,16 +30,57 @@
 	fs   = vfs.NameSpace{}
 )
 
-func registerHandlers(pres *godoc.Presentation) {
+var enforceHosts = false // set true in production on app engine
+
+// hostEnforcerHandler redirects requests to "http://foo.golang.org/bar"
+// to "https://golang.org/bar".
+// It permits requests to the host "godoc-test.golang.org" for testing.
+type hostEnforcerHandler struct {
+	h http.Handler
+}
+
+func (h hostEnforcerHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	if !enforceHosts {
+		h.h.ServeHTTP(w, r)
+		return
+	}
+	if r.TLS == nil || !h.validHost(r.Host) {
+		r.URL.Scheme = "https"
+		if h.validHost(r.Host) {
+			r.URL.Host = r.Host
+		} else {
+			r.URL.Host = "golang.org"
+		}
+		http.Redirect(w, r, r.URL.String(), http.StatusFound)
+		return
+	}
+	h.h.ServeHTTP(w, r)
+}
+
+func (h hostEnforcerHandler) validHost(host string) bool {
+	switch strings.ToLower(host) {
+	case "golang.org", "godoc-test.golang.org":
+		return true
+	}
+	return false
+}
+
+func registerHandlers(pres *godoc.Presentation) *http.ServeMux {
 	if pres == nil {
 		panic("nil Presentation")
 	}
-	http.HandleFunc("/doc/codewalk/", codewalk)
-	http.Handle("/doc/play/", pres.FileServer())
-	http.Handle("/robots.txt", pres.FileServer())
-	http.Handle("/", pres)
-	http.Handle("/pkg/C/", redirect.Handler("/cmd/cgo/"))
-	redirect.Register(nil)
+	mux := http.NewServeMux()
+	mux.HandleFunc("/doc/codewalk/", codewalk)
+	mux.Handle("/doc/play/", pres.FileServer())
+	mux.Handle("/robots.txt", pres.FileServer())
+	mux.Handle("/", pres)
+	mux.Handle("/pkg/C/", redirect.Handler("/cmd/cgo/"))
+	mux.HandleFunc("/fmt", fmtHandler)
+	redirect.Register(mux)
+
+	http.Handle("/", hostEnforcerHandler{mux})
+
+	return mux
 }
 
 func readTemplate(name string) *template.Template {
@@ -81,3 +125,22 @@
 		p.SearchDescXML = readTemplate("opensearch.xml")
 	}
 }
+
+type fmtResponse struct {
+	Body  string
+	Error string
+}
+
+// fmtHandler takes a Go program in its "body" form value, formats it with
+// standard gofmt formatting, and writes a fmtResponse as a JSON object.
+func fmtHandler(w http.ResponseWriter, r *http.Request) {
+	resp := new(fmtResponse)
+	body, err := format.Source([]byte(r.FormValue("body")))
+	if err != nil {
+		resp.Error = err.Error()
+	} else {
+		resp.Body = string(body)
+	}
+	w.Header().Set("Content-type", "application/json; charset=utf-8")
+	json.NewEncoder(w).Encode(resp)
+}
diff --git a/go/src/golang.org/x/tools/cmd/godoc/play.go b/go/src/golang.org/x/tools/cmd/godoc/play.go
index a56ffe2..02f477d 100644
--- a/go/src/golang.org/x/tools/cmd/godoc/play.go
+++ b/go/src/golang.org/x/tools/cmd/godoc/play.go
@@ -2,43 +2,10 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build !appengine
+
 package main
 
-import (
-	"encoding/json"
-	"fmt"
-	"go/format"
-	"net/http"
-
-	// This package registers "/compile" and "/share" handlers
-	// that redirect to the golang.org playground.
-	_ "golang.org/x/tools/playground"
-)
-
-func init() {
-	http.HandleFunc("/fmt", fmtHandler)
-}
-
-type fmtResponse struct {
-	Body  string
-	Error string
-}
-
-// fmtHandler takes a Go program in its "body" form value, formats it with
-// standard gofmt formatting, and writes a fmtResponse as a JSON object.
-func fmtHandler(w http.ResponseWriter, r *http.Request) {
-	resp := new(fmtResponse)
-	body, err := format.Source([]byte(r.FormValue("body")))
-	if err != nil {
-		resp.Error = err.Error()
-	} else {
-		resp.Body = string(body)
-	}
-	json.NewEncoder(w).Encode(resp)
-}
-
-// disabledHandler serves a 501 "Not Implemented" response.
-func disabledHandler(w http.ResponseWriter, r *http.Request) {
-	w.WriteHeader(http.StatusNotImplemented)
-	fmt.Fprint(w, "This functionality is not available via local godoc.")
-}
+// This package registers "/compile" and "/share" handlers
+// that redirect to the golang.org playground.
+import _ "golang.org/x/tools/playground"
diff --git a/go/src/golang.org/x/tools/cmd/godoc/setup-godoc-app.bash b/go/src/golang.org/x/tools/cmd/godoc/setup-godoc-app.bash
index 9d82cd7..a462ebe 100755
--- a/go/src/golang.org/x/tools/cmd/godoc/setup-godoc-app.bash
+++ b/go/src/golang.org/x/tools/cmd/godoc/setup-godoc-app.bash
@@ -67,7 +67,7 @@
 	go=$APPENGINE_SDK/goapp
 	$go get -d -tags appengine $GODOC
 	mkdir -p $APPDIR/$GODOC
-	cp $(find $($go list -f '{{.Dir}}' $GODOC) -type f -depth 1) $APPDIR/$GODOC/
+	cp $(find $($go list -f '{{.Dir}}' $GODOC) -mindepth 1 -maxdepth 1 -type f) $APPDIR/$GODOC/
 }
 
 makeAppYaml() {
diff --git a/go/src/golang.org/x/tools/cmd/godoc/x.go b/go/src/golang.org/x/tools/cmd/godoc/x.go
index b4af41a..d6ee745 100644
--- a/go/src/golang.org/x/tools/cmd/godoc/x.go
+++ b/go/src/golang.org/x/tools/cmd/godoc/x.go
@@ -24,6 +24,7 @@
 var xMap = map[string]xRepo{
 	"codereview": {"https://code.google.com/p/go.codereview", "hg"},
 
+	"arch":       {"https://go.googlesource.com/arch", "git"},
 	"benchmarks": {"https://go.googlesource.com/benchmarks", "git"},
 	"blog":       {"https://go.googlesource.com/blog", "git"},
 	"build":      {"https://go.googlesource.com/build", "git"},
@@ -36,9 +37,12 @@
 	"oauth2":     {"https://go.googlesource.com/oauth2", "git"},
 	"playground": {"https://go.googlesource.com/playground", "git"},
 	"review":     {"https://go.googlesource.com/review", "git"},
+	"sync":       {"https://go.googlesource.com/sync", "git"},
 	"sys":        {"https://go.googlesource.com/sys", "git"},
 	"talks":      {"https://go.googlesource.com/talks", "git"},
+	"term":       {"https://go.googlesource.com/term", "git"},
 	"text":       {"https://go.googlesource.com/text", "git"},
+	"time":       {"https://go.googlesource.com/time", "git"},
 	"tools":      {"https://go.googlesource.com/tools", "git"},
 	"tour":       {"https://go.googlesource.com/tour", "git"},
 }
diff --git a/go/src/golang.org/x/tools/cmd/gorename/main.go b/go/src/golang.org/x/tools/cmd/gorename/main.go
index 922dc0c..b1b895c 100644
--- a/go/src/golang.org/x/tools/cmd/gorename/main.go
+++ b/go/src/golang.org/x/tools/cmd/gorename/main.go
@@ -11,8 +11,8 @@
 	"flag"
 	"fmt"
 	"go/build"
+	"log"
 	"os"
-	"runtime"
 
 	"golang.org/x/tools/go/buildutil"
 	"golang.org/x/tools/refactor/rename"
@@ -28,25 +28,17 @@
 func init() {
 	flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsFlagDoc)
 	flag.BoolVar(&rename.Force, "force", false, "proceed, even if conflicts were reported")
-	flag.BoolVar(&rename.DryRun, "dryrun", false, "show the change, but do not apply it")
 	flag.BoolVar(&rename.Verbose, "v", false, "print verbose information")
-
-	// If $GOMAXPROCS isn't set, use the full capacity of the machine.
-	// For small machines, use at least 4 threads.
-	if os.Getenv("GOMAXPROCS") == "" {
-		n := runtime.NumCPU()
-		if n < 4 {
-			n = 4
-		}
-		runtime.GOMAXPROCS(n)
-	}
+	flag.BoolVar(&rename.Diff, "d", false, "display diffs instead of rewriting files")
+	flag.StringVar(&rename.DiffCmd, "diffcmd", "diff", "diff command invoked when using -d")
 }
 
 func main() {
+	log.SetPrefix("gorename: ")
+	log.SetFlags(0)
 	flag.Parse()
 	if len(flag.Args()) > 0 {
-		fmt.Fprintln(os.Stderr, "gorename: surplus arguments.")
-		os.Exit(1)
+		log.Fatal("surplus arguments")
 	}
 
 	if *helpFlag || (*offsetFlag == "" && *fromFlag == "" && *toFlag == "") {
@@ -56,7 +48,7 @@
 
 	if err := rename.Main(&build.Default, *offsetFlag, *fromFlag, *toFlag); err != nil {
 		if err != rename.ConflictError {
-			fmt.Fprintf(os.Stderr, "gorename: %s\n", err)
+			log.Fatal(err)
 		}
 		os.Exit(1)
 	}
diff --git a/go/src/golang.org/x/tools/cmd/gotype/gotype.go b/go/src/golang.org/x/tools/cmd/gotype/gotype.go
index 4a5c7de..bd3721f 100644
--- a/go/src/golang.org/x/tools/cmd/gotype/gotype.go
+++ b/go/src/golang.org/x/tools/cmd/gotype/gotype.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package main
 
 import (
@@ -9,18 +11,15 @@
 	"fmt"
 	"go/ast"
 	"go/build"
+	"go/importer"
 	"go/parser"
 	"go/scanner"
 	"go/token"
+	"go/types"
 	"io/ioutil"
 	"os"
 	"path/filepath"
-	"runtime"
 	"time"
-
-	"golang.org/x/tools/go/gccgoimporter"
-	_ "golang.org/x/tools/go/gcimporter"
-	"golang.org/x/tools/go/types"
 )
 
 var (
@@ -186,6 +185,10 @@
 }
 
 func checkPkgFiles(files []*ast.File) {
+	compiler := "gc"
+	if *gccgo {
+		compiler = "gccgo"
+	}
 	type bailout struct{}
 	conf := types.Config{
 		FakeImportC: true,
@@ -195,12 +198,8 @@
 			}
 			report(err)
 		},
-		Sizes: sizes,
-	}
-	if *gccgo {
-		var inst gccgoimporter.GccgoInstallation
-		inst.InitFromDriver("gccgo")
-		conf.Import = inst.GetImporter(nil, nil)
+		Importer: importer.For(compiler, nil),
+		Sizes:    sizes,
 	}
 
 	defer func() {
@@ -233,8 +232,6 @@
 }
 
 func main() {
-	runtime.GOMAXPROCS(runtime.NumCPU()) // remove this once runtime is smarter
-
 	flag.Usage = usage
 	flag.Parse()
 	if *printAST || *printTrace {
diff --git a/go/src/golang.org/x/tools/cmd/gotype/gotype14.go b/go/src/golang.org/x/tools/cmd/gotype/gotype14.go
new file mode 100644
index 0000000..92d089e
--- /dev/null
+++ b/go/src/golang.org/x/tools/cmd/gotype/gotype14.go
@@ -0,0 +1,268 @@
+// Copyright 2011 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.
+
+// +build !go1.5
+
+// This is a 1:1 copy of gotype.go but for the changes required to build
+// against Go1.4 and before.
+// TODO(gri) Decide long-term fate of gotype (issue #12303).
+
+package main
+
+import (
+	"flag"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/parser"
+	"go/scanner"
+	"go/token"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"runtime"
+	"time"
+
+	"golang.org/x/tools/go/gccgoimporter"
+	_ "golang.org/x/tools/go/gcimporter"
+	"golang.org/x/tools/go/types"
+)
+
+var (
+	// main operation modes
+	allFiles  = flag.Bool("a", false, "use all (incl. _test.go) files when processing a directory")
+	allErrors = flag.Bool("e", false, "report all errors (not just the first 10)")
+	verbose   = flag.Bool("v", false, "verbose mode")
+	gccgo     = flag.Bool("gccgo", false, "use gccgoimporter instead of gcimporter")
+
+	// debugging support
+	sequential    = flag.Bool("seq", false, "parse sequentially, rather than in parallel")
+	printAST      = flag.Bool("ast", false, "print AST (forces -seq)")
+	printTrace    = flag.Bool("trace", false, "print parse trace (forces -seq)")
+	parseComments = flag.Bool("comments", false, "parse comments (ignored unless -ast or -trace is provided)")
+)
+
+var (
+	fset       = token.NewFileSet()
+	errorCount = 0
+	parserMode parser.Mode
+	sizes      types.Sizes
+)
+
+func initParserMode() {
+	if *allErrors {
+		parserMode |= parser.AllErrors
+	}
+	if *printTrace {
+		parserMode |= parser.Trace
+	}
+	if *parseComments && (*printAST || *printTrace) {
+		parserMode |= parser.ParseComments
+	}
+}
+
+func initSizes() {
+	wordSize := 8
+	maxAlign := 8
+	switch build.Default.GOARCH {
+	case "386", "arm":
+		wordSize = 4
+		maxAlign = 4
+		// add more cases as needed
+	}
+	sizes = &types.StdSizes{WordSize: int64(wordSize), MaxAlign: int64(maxAlign)}
+}
+
+func usage() {
+	fmt.Fprintln(os.Stderr, "usage: gotype [flags] [path ...]")
+	flag.PrintDefaults()
+	os.Exit(2)
+}
+
+func report(err error) {
+	scanner.PrintError(os.Stderr, err)
+	if list, ok := err.(scanner.ErrorList); ok {
+		errorCount += len(list)
+		return
+	}
+	errorCount++
+}
+
+// parse may be called concurrently
+func parse(filename string, src interface{}) (*ast.File, error) {
+	if *verbose {
+		fmt.Println(filename)
+	}
+	file, err := parser.ParseFile(fset, filename, src, parserMode) // ok to access fset concurrently
+	if *printAST {
+		ast.Print(fset, file)
+	}
+	return file, err
+}
+
+func parseStdin() (*ast.File, error) {
+	src, err := ioutil.ReadAll(os.Stdin)
+	if err != nil {
+		return nil, err
+	}
+	return parse("<standard input>", src)
+}
+
+func parseFiles(filenames []string) ([]*ast.File, error) {
+	files := make([]*ast.File, len(filenames))
+
+	if *sequential {
+		for i, filename := range filenames {
+			var err error
+			files[i], err = parse(filename, nil)
+			if err != nil {
+				return nil, err // leave unfinished goroutines hanging
+			}
+		}
+	} else {
+		type parseResult struct {
+			file *ast.File
+			err  error
+		}
+
+		out := make(chan parseResult)
+		for _, filename := range filenames {
+			go func(filename string) {
+				file, err := parse(filename, nil)
+				out <- parseResult{file, err}
+			}(filename)
+		}
+
+		for i := range filenames {
+			res := <-out
+			if res.err != nil {
+				return nil, res.err // leave unfinished goroutines hanging
+			}
+			files[i] = res.file
+		}
+	}
+
+	return files, nil
+}
+
+func parseDir(dirname string) ([]*ast.File, error) {
+	ctxt := build.Default
+	pkginfo, err := ctxt.ImportDir(dirname, 0)
+	if _, nogo := err.(*build.NoGoError); err != nil && !nogo {
+		return nil, err
+	}
+	filenames := append(pkginfo.GoFiles, pkginfo.CgoFiles...)
+	if *allFiles {
+		filenames = append(filenames, pkginfo.TestGoFiles...)
+	}
+
+	// complete file names
+	for i, filename := range filenames {
+		filenames[i] = filepath.Join(dirname, filename)
+	}
+
+	return parseFiles(filenames)
+}
+
+func getPkgFiles(args []string) ([]*ast.File, error) {
+	if len(args) == 0 {
+		// stdin
+		file, err := parseStdin()
+		if err != nil {
+			return nil, err
+		}
+		return []*ast.File{file}, nil
+	}
+
+	if len(args) == 1 {
+		// possibly a directory
+		path := args[0]
+		info, err := os.Stat(path)
+		if err != nil {
+			return nil, err
+		}
+		if info.IsDir() {
+			return parseDir(path)
+		}
+	}
+
+	// list of files
+	return parseFiles(args)
+}
+
+func checkPkgFiles(files []*ast.File) {
+	type bailout struct{}
+	conf := types.Config{
+		FakeImportC: true,
+		Error: func(err error) {
+			if !*allErrors && errorCount >= 10 {
+				panic(bailout{})
+			}
+			report(err)
+		},
+		Sizes: sizes,
+	}
+	if *gccgo {
+		var inst gccgoimporter.GccgoInstallation
+		inst.InitFromDriver("gccgo")
+		conf.Import = inst.GetImporter(nil, nil)
+	}
+
+	defer func() {
+		switch p := recover().(type) {
+		case nil, bailout:
+			// normal return or early exit
+		default:
+			// re-panic
+			panic(p)
+		}
+	}()
+
+	const path = "pkg" // any non-empty string will do for now
+	conf.Check(path, fset, files, nil)
+}
+
+func printStats(d time.Duration) {
+	fileCount := 0
+	lineCount := 0
+	fset.Iterate(func(f *token.File) bool {
+		fileCount++
+		lineCount += f.LineCount()
+		return true
+	})
+
+	fmt.Printf(
+		"%s (%d files, %d lines, %d lines/s)\n",
+		d, fileCount, lineCount, int64(float64(lineCount)/d.Seconds()),
+	)
+}
+
+func main() {
+	runtime.GOMAXPROCS(runtime.NumCPU()) // not needed for go1.5
+
+	flag.Usage = usage
+	flag.Parse()
+	if *printAST || *printTrace {
+		*sequential = true
+	}
+	initParserMode()
+	initSizes()
+
+	start := time.Now()
+
+	files, err := getPkgFiles(flag.Args())
+	if err != nil {
+		report(err)
+		os.Exit(2)
+	}
+
+	checkPkgFiles(files)
+	if errorCount > 0 {
+		os.Exit(2)
+	}
+
+	if *verbose {
+		printStats(time.Since(start))
+	}
+}
diff --git a/go/src/golang.org/x/tools/cmd/oracle/main.go b/go/src/golang.org/x/tools/cmd/oracle/main.go
index a7a1661..7b23b15 100644
--- a/go/src/golang.org/x/tools/cmd/oracle/main.go
+++ b/go/src/golang.org/x/tools/cmd/oracle/main.go
@@ -78,7 +78,7 @@
    golang.org/x/tools/cmd/oracle
 
 Print the callgraph of the trivial web-server in JSON format:
-% oracle -format=json $GOROOT/src/net/http/triv.go callgraph
+% oracle -format=json callstack $GOROOT/src/net/http/triv.go
 ` + loader.FromArgsUsage
 
 var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
diff --git a/go/src/golang.org/x/tools/cmd/present/appengine.go b/go/src/golang.org/x/tools/cmd/present/appengine.go
index 7df536c..1e39ce1 100644
--- a/go/src/golang.org/x/tools/cmd/present/appengine.go
+++ b/go/src/golang.org/x/tools/cmd/present/appengine.go
@@ -10,21 +10,13 @@
 	"mime"
 
 	"golang.org/x/tools/present"
-
-	_ "golang.org/x/tools/playground"
 )
 
-var basePath = "./present/"
-
 func init() {
-	initTemplates(basePath)
-	playScript(basePath, "HTTPTransport")
+	initTemplates("./present/")
 	present.PlayEnabled = true
+	initPlayground("./present/", nil)
 
 	// App Engine has no /etc/mime.types
 	mime.AddExtensionType(".svg", "image/svg+xml")
 }
-
-func playable(c present.Code) bool {
-	return present.PlayEnabled && c.Play && c.Ext == ".go"
-}
diff --git a/go/src/golang.org/x/tools/cmd/present/doc.go b/go/src/golang.org/x/tools/cmd/present/doc.go
index fafcefe..7c32696 100644
--- a/go/src/golang.org/x/tools/cmd/present/doc.go
+++ b/go/src/golang.org/x/tools/cmd/present/doc.go
@@ -7,8 +7,6 @@
 presents slide and article files from the current directory.
 
 It may be run as a stand-alone command or an App Engine app.
-Instructions for deployment to App Engine are in the README of the
-golang.org/x/tools repository.
 
 Usage of present:
   -base="": base path for slide template and static resources
@@ -20,6 +18,33 @@
 The setup of the Go version of NaCl is documented at:
 https://golang.org/wiki/NativeClient
 
+To use with App Engine, copy the tools/cmd/present directory to the root of
+your application and create an app.yaml file similar to this:
+
+    application: [application]
+    version: [version]
+    runtime: go
+    api_version: go1
+
+    handlers:
+    - url: /favicon.ico
+      static_files: present/static/favicon.ico
+      upload: present/static/favicon.ico
+    - url: /static
+      static_dir: present/static
+      application_readable: true
+    - url: /.*
+      script: _go_app
+
+    # nobuild_files is a regexp that identifies which files to not build.  It
+    # is useful for embedding static assets like code snippets and preventing
+    # them from producing build errors for your project.
+    nobuild_files: [path regexp for talk materials]
+
+Present then can be tested in a local App Engine environment with
+
+    goapp serve
+
 Input files are named foo.extension, where "extension" defines the format of
 the generated output. The supported formats are:
 	.slide        // HTML5 slide presentation
diff --git a/go/src/golang.org/x/tools/cmd/present/local.go b/go/src/golang.org/x/tools/cmd/present/local.go
index d91dcc2..d968553 100644
--- a/go/src/golang.org/x/tools/cmd/present/local.go
+++ b/go/src/golang.org/x/tools/cmd/present/local.go
@@ -15,35 +15,34 @@
 	"net/http"
 	"net/url"
 	"os"
-	"runtime"
 	"strings"
 
-	"golang.org/x/tools/playground/socket"
 	"golang.org/x/tools/present"
 )
 
 const basePkg = "golang.org/x/tools/cmd/present"
 
-var basePath string
+var (
+	httpAddr     = flag.String("http", "127.0.0.1:3999", "HTTP service address (e.g., '127.0.0.1:3999')")
+	originHost   = flag.String("orighost", "", "host component of web origin URL (e.g., 'localhost')")
+	basePath     = flag.String("base", "", "base path for slide template and static resources")
+	nativeClient = flag.Bool("nacl", false, "use Native Client environment playground (prevents non-Go code execution)")
+)
 
 func main() {
-	httpAddr := flag.String("http", "127.0.0.1:3999", "HTTP service address (e.g., '127.0.0.1:3999')")
-	originHost := flag.String("orighost", "", "host component of web origin URL (e.g., 'localhost')")
-	flag.StringVar(&basePath, "base", "", "base path for slide template and static resources")
 	flag.BoolVar(&present.PlayEnabled, "play", true, "enable playground (permit execution of arbitrary user code)")
-	nativeClient := flag.Bool("nacl", false, "use Native Client environment playground (prevents non-Go code execution)")
 	flag.Parse()
 
-	if basePath == "" {
+	if *basePath == "" {
 		p, err := build.Default.Import(basePkg, "", build.FindOnly)
 		if err != nil {
 			fmt.Fprintf(os.Stderr, "Couldn't find gopresent files: %v\n", err)
 			fmt.Fprintf(os.Stderr, basePathMessage, basePkg)
 			os.Exit(1)
 		}
-		basePath = p.Dir
+		*basePath = p.Dir
 	}
-	err := initTemplates(basePath)
+	err := initTemplates(*basePath)
 	if err != nil {
 		log.Fatalf("Failed to parse templates: %v", err)
 	}
@@ -58,6 +57,7 @@
 	if err != nil {
 		log.Fatal(err)
 	}
+
 	origin := &url.URL{Scheme: "http"}
 	if *originHost != "" {
 		origin.Host = net.JoinHostPort(*originHost, port)
@@ -76,20 +76,8 @@
 		}
 	}
 
-	if present.PlayEnabled {
-		if *nativeClient {
-			socket.RunScripts = false
-			socket.Environ = func() []string {
-				if runtime.GOARCH == "amd64" {
-					return environ("GOOS=nacl", "GOARCH=amd64p32")
-				}
-				return environ("GOOS=nacl")
-			}
-		}
-		playScript(basePath, "SocketTransport")
-		http.Handle("/socket", socket.NewHandler(origin))
-	}
-	http.Handle("/static/", http.FileServer(http.Dir(basePath)))
+	initPlayground(*basePath, origin)
+	http.Handle("/static/", http.FileServer(http.Dir(*basePath)))
 
 	if !ln.Addr().(*net.TCPAddr).IP.IsLoopback() &&
 		present.PlayEnabled && !*nativeClient {
@@ -100,10 +88,6 @@
 	log.Fatal(http.Serve(ln, nil))
 }
 
-func playable(c present.Code) bool {
-	return present.PlayEnabled && c.Play
-}
-
 func environ(vars ...string) []string {
 	env := os.Environ()
 	for _, r := range vars {
diff --git a/go/src/golang.org/x/tools/cmd/present/play_http.go b/go/src/golang.org/x/tools/cmd/present/play_http.go
new file mode 100644
index 0000000..02e7314
--- /dev/null
+++ b/go/src/golang.org/x/tools/cmd/present/play_http.go
@@ -0,0 +1,23 @@
+// Copyright 2015 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.
+
+// +build appengine appenginevm
+
+package main
+
+import (
+	"net/url"
+
+	"golang.org/x/tools/present"
+
+	_ "golang.org/x/tools/playground"
+)
+
+func initPlayground(basepath string, origin *url.URL) {
+	playScript(basepath, "HTTPTransport")
+}
+
+func playable(c present.Code) bool {
+	return present.PlayEnabled && c.Play && c.Ext == ".go"
+}
diff --git a/go/src/golang.org/x/tools/cmd/present/play_socket.go b/go/src/golang.org/x/tools/cmd/present/play_socket.go
new file mode 100644
index 0000000..df63eda
--- /dev/null
+++ b/go/src/golang.org/x/tools/cmd/present/play_socket.go
@@ -0,0 +1,36 @@
+// Copyright 2015 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.
+
+// +build !appengine,!appenginevm
+
+package main
+
+import (
+	"net/http"
+	"net/url"
+	"runtime"
+
+	"golang.org/x/tools/playground/socket"
+	"golang.org/x/tools/present"
+)
+
+func initPlayground(basepath string, origin *url.URL) {
+	if present.PlayEnabled {
+		if *nativeClient {
+			socket.RunScripts = false
+			socket.Environ = func() []string {
+				if runtime.GOARCH == "amd64" {
+					return environ("GOOS=nacl", "GOARCH=amd64p32")
+				}
+				return environ("GOOS=nacl")
+			}
+		}
+		playScript(basepath, "SocketTransport")
+		http.Handle("/socket", socket.NewHandler(origin))
+	}
+}
+
+func playable(c present.Code) bool {
+	return present.PlayEnabled && c.Play
+}
diff --git a/go/src/golang.org/x/tools/cmd/present/static/styles.css b/go/src/golang.org/x/tools/cmd/present/static/styles.css
index 5cb2953..688127f 100644
--- a/go/src/golang.org/x/tools/cmd/present/static/styles.css
+++ b/go/src/golang.org/x/tools/cmd/present/static/styles.css
@@ -379,11 +379,26 @@
   color: black;
 }
 
-article > .image {
+article > .image,
+article > .video {
   text-align: center;
   margin-top: 40px;
 }
 
+article > .background {
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  z-index: -1;
+}
+
+article > .background > img {
+  max-height: 100%;
+  max-width: 100%;
+}
+
 table {
   width: 100%;
   border-collapse: collapse;
diff --git a/go/src/golang.org/x/tools/cmd/present/templates/action.tmpl b/go/src/golang.org/x/tools/cmd/present/templates/action.tmpl
index 2893058..1eae3b7 100644
--- a/go/src/golang.org/x/tools/cmd/present/templates/action.tmpl
+++ b/go/src/golang.org/x/tools/cmd/present/templates/action.tmpl
@@ -37,6 +37,20 @@
 </div>
 {{end}}
 
+{{define "video"}}
+<div class="video">
+  <video {{with .Height}} height="{{.}}"{{end}}{{with .Width}} width="{{.}}"{{end}} controls>
+    <source src="{{.URL}}" type="{{.SourceType}}">
+  </video>
+</div>
+{{end}}
+
+{{define "background"}}
+<div class="background">
+  <img src="{{.URL}}">
+</div>
+{{end}}
+
 {{define "iframe"}}
 <iframe src="{{.URL}}"{{with .Height}} height="{{.}}"{{end}}{{with .Width}} width="{{.}}"{{end}}></iframe>
 {{end}}
@@ -45,4 +59,4 @@
 
 {{define "html"}}{{.HTML}}{{end}}
 
-{{define "caption"}}<figcaption>{{style .Text}}</figcaption>{{end}}
\ No newline at end of file
+{{define "caption"}}<figcaption>{{style .Text}}</figcaption>{{end}}
diff --git a/go/src/golang.org/x/tools/cmd/present/templates/article.tmpl b/go/src/golang.org/x/tools/cmd/present/templates/article.tmpl
index 40d1c93..411f00b 100644
--- a/go/src/golang.org/x/tools/cmd/present/templates/article.tmpl
+++ b/go/src/golang.org/x/tools/cmd/present/templates/article.tmpl
@@ -7,6 +7,23 @@
     <title>{{.Title}}</title>
     <link type="text/css" rel="stylesheet" href="/static/article.css">
     <meta charset='utf-8'>
+    <script>
+      // Initialize Google Analytics tracking code on production site only.
+      if (window["location"] && window["location"]["hostname"] == "talks.golang.org") {
+        var _gaq = _gaq || [];
+        _gaq.push(["_setAccount", "UA-11222381-6"]);
+        _gaq.push(["b._setAccount", "UA-49880327-6"]);
+        window.trackPageview = function() {
+          _gaq.push(["_trackPageview", location.pathname+location.hash]);
+          _gaq.push(["b._trackPageview", location.pathname+location.hash]);
+        };
+        window.trackPageview();
+        window.trackEvent = function(category, action, opt_label, opt_value, opt_noninteraction) {
+          _gaq.push(["_trackEvent", category, action, opt_label, opt_value, opt_noninteraction]);
+          _gaq.push(["b._trackEvent", category, action, opt_label, opt_value, opt_noninteraction]);
+        };
+      }
+    </script>
   </head>
 
   <body>
@@ -39,7 +56,21 @@
         {{end}}
       </div>
     </div>
+
+    {{if .PlayEnabled}}
     <script src='/play.js'></script>
+    {{end}}
+
+    <script>
+      (function() {
+        // Load Google Analytics tracking code on production site only.
+        if (window["location"] && window["location"]["hostname"] == "talks.golang.org") {
+          var ga = document.createElement("script"); ga.type = "text/javascript"; ga.async = true;
+          ga.src = ("https:" == document.location.protocol ? "https://ssl" : "http://www") + ".google-analytics.com/ga.js";
+          var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(ga, s);
+        }
+      })();
+    </script>
   </body>
 </html>
 {{end}}
diff --git a/go/src/golang.org/x/tools/cmd/present/templates/dir.tmpl b/go/src/golang.org/x/tools/cmd/present/templates/dir.tmpl
index 15cf97f..1732623 100644
--- a/go/src/golang.org/x/tools/cmd/present/templates/dir.tmpl
+++ b/go/src/golang.org/x/tools/cmd/present/templates/dir.tmpl
@@ -1,10 +1,27 @@
 <!DOCTYPE html>
 <html>
 <head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
   <title>Talks - The Go Programming Language</title>
   <link type="text/css" rel="stylesheet" href="/static/dir.css">
   <script src="/static/dir.js"></script>
+  <script>
+    // Initialize Google Analytics tracking code on production site only.
+    if (window["location"] && window["location"]["hostname"] == "talks.golang.org") {
+      var _gaq = _gaq || [];
+      _gaq.push(["_setAccount", "UA-11222381-6"]);
+      _gaq.push(["b._setAccount", "UA-49880327-6"]);
+      window.trackPageview = function() {
+        _gaq.push(["_trackPageview", location.pathname+location.hash]);
+        _gaq.push(["b._trackPageview", location.pathname+location.hash]);
+      };
+      window.trackPageview();
+      window.trackEvent = function(category, action, opt_label, opt_value, opt_noninteraction) {
+        _gaq.push(["_trackEvent", category, action, opt_label, opt_value, opt_noninteraction]);
+        _gaq.push(["b._trackEvent", category, action, opt_label, opt_value, opt_noninteraction]);
+      };
+    }
+  </script>
 </head>
 <body>
 
@@ -77,5 +94,15 @@
 <a href="http://www.google.com/intl/en/policies/privacy/">Privacy Policy</a>
 </div>
 
+<script>
+  (function() {
+    // Load Google Analytics tracking code on production site only.
+    if (window["location"] && window["location"]["hostname"] == "talks.golang.org") {
+      var ga = document.createElement("script"); ga.type = "text/javascript"; ga.async = true;
+      ga.src = ("https:" == document.location.protocol ? "https://ssl" : "http://www") + ".google-analytics.com/ga.js";
+      var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(ga, s);
+    }
+  })();
+</script>
 </body>
 </html>
diff --git a/go/src/golang.org/x/tools/cmd/present/templates/slides.tmpl b/go/src/golang.org/x/tools/cmd/present/templates/slides.tmpl
index 11070d2..2b4ec98 100644
--- a/go/src/golang.org/x/tools/cmd/present/templates/slides.tmpl
+++ b/go/src/golang.org/x/tools/cmd/present/templates/slides.tmpl
@@ -7,6 +7,23 @@
     <title>{{.Title}}</title>
     <meta charset='utf-8'>
     <script src='/static/slides.js'></script>
+    <script>
+      // Initialize Google Analytics tracking code on production site only.
+      if (window["location"] && window["location"]["hostname"] == "talks.golang.org") {
+        var _gaq = _gaq || [];
+        _gaq.push(["_setAccount", "UA-11222381-6"]);
+        _gaq.push(["b._setAccount", "UA-49880327-6"]);
+        window.trackPageview = function() {
+          _gaq.push(["_trackPageview", location.pathname+location.hash]);
+          _gaq.push(["b._trackPageview", location.pathname+location.hash]);
+        };
+        window.trackPageview();
+        window.trackEvent = function(category, action, opt_label, opt_value, opt_noninteraction) {
+          _gaq.push(["_trackEvent", category, action, opt_label, opt_value, opt_noninteraction]);
+          _gaq.push(["b._trackEvent", category, action, opt_label, opt_value, opt_noninteraction]);
+        };
+      }
+    </script>
   </head>
 
   <body style='display: none'>
@@ -54,10 +71,21 @@
       (Press 'H' or navigate to hide this message.)
     </div>
 
+    {{if .PlayEnabled}}
+    <script src='/play.js'></script>
+    {{end}}
+
+    <script>
+      (function() {
+        // Load Google Analytics tracking code on production site only.
+        if (window["location"] && window["location"]["hostname"] == "talks.golang.org") {
+          var ga = document.createElement("script"); ga.type = "text/javascript"; ga.async = true;
+          ga.src = ("https:" == document.location.protocol ? "https://ssl" : "http://www") + ".google-analytics.com/ga.js";
+          var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(ga, s);
+        }
+      })();
+    </script>
   </body>
-  {{if .PlayEnabled}}
-  <script src='/play.js'></script>
-  {{end}}
 </html>
 {{end}}
 
diff --git a/go/src/golang.org/x/tools/cmd/ssadump/main.go b/go/src/golang.org/x/tools/cmd/ssadump/main.go
index 75f1601..bdc4d0a 100644
--- a/go/src/golang.org/x/tools/cmd/ssadump/main.go
+++ b/go/src/golang.org/x/tools/cmd/ssadump/main.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 // ssadump: a tool for displaying and interpreting the SSA form of Go programs.
 package main // import "golang.org/x/tools/cmd/ssadump"
 
@@ -9,6 +11,7 @@
 	"flag"
 	"fmt"
 	"go/build"
+	"go/types"
 	"os"
 	"runtime"
 	"runtime/pprof"
@@ -18,7 +21,6 @@
 	"golang.org/x/tools/go/ssa"
 	"golang.org/x/tools/go/ssa/interp"
 	"golang.org/x/tools/go/ssa/ssautil"
-	"golang.org/x/tools/go/types"
 )
 
 var (
@@ -147,7 +149,7 @@
 
 	// Run the interpreter.
 	if *runFlag {
-		prog.BuildAll()
+		prog.Build()
 
 		var main *ssa.Package
 		pkgs := prog.AllPackages()
@@ -162,7 +164,7 @@
 		} else {
 			// Otherwise, run main.main.
 			for _, pkg := range pkgs {
-				if pkg.Object.Name() == "main" {
+				if pkg.Pkg.Name() == "main" {
 					main = pkg
 					if main.Func("main") == nil {
 						return fmt.Errorf("no func main() in main package")
@@ -180,7 +182,7 @@
 				build.Default.GOARCH, runtime.GOARCH)
 		}
 
-		interp.Interpret(main, interpMode, conf.TypeChecker.Sizes, main.Object.Path(), args)
+		interp.Interpret(main, interpMode, conf.TypeChecker.Sizes, main.Pkg.Path(), args)
 	}
 	return nil
 }
diff --git a/go/src/golang.org/x/tools/cmd/ssadump/main14.go b/go/src/golang.org/x/tools/cmd/ssadump/main14.go
new file mode 100644
index 0000000..201ea81
--- /dev/null
+++ b/go/src/golang.org/x/tools/cmd/ssadump/main14.go
@@ -0,0 +1,188 @@
+// 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.
+
+// +build !go1.5
+
+// ssadump: a tool for displaying and interpreting the SSA form of Go programs.
+package main // import "golang.org/x/tools/cmd/ssadump"
+
+import (
+	"flag"
+	"fmt"
+	"go/build"
+	"os"
+	"runtime"
+	"runtime/pprof"
+
+	"golang.org/x/tools/go/buildutil"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/ssa/interp"
+	"golang.org/x/tools/go/ssa/ssautil"
+	"golang.org/x/tools/go/types"
+)
+
+var (
+	modeFlag = ssa.BuilderModeFlag(flag.CommandLine, "build", 0)
+
+	testFlag = flag.Bool("test", false, "Loads test code (*_test.go) for imported packages.")
+
+	runFlag = flag.Bool("run", false, "Invokes the SSA interpreter on the program.")
+
+	interpFlag = flag.String("interp", "", `Options controlling the SSA test interpreter.
+The value is a sequence of zero or more more of these letters:
+R	disable [R]ecover() from panic; show interpreter crash instead.
+T	[T]race execution of the program.  Best for single-threaded programs!
+`)
+)
+
+const usage = `SSA builder and interpreter.
+Usage: ssadump [<flag> ...] <args> ...
+Use -help flag to display options.
+
+Examples:
+% ssadump -build=F hello.go              # dump SSA form of a single package
+% ssadump -run -interp=T hello.go        # interpret a program, with tracing
+% ssadump -run -test unicode -- -test.v  # interpret the unicode package's tests, verbosely
+` + loader.FromArgsUsage +
+	`
+When -run is specified, ssadump will run the program.
+The entry point depends on the -test flag:
+if clear, it runs the first package named main.
+if set, it runs the tests of each package.
+`
+
+var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
+
+func init() {
+	flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsFlagDoc)
+
+	// If $GOMAXPROCS isn't set, use the full capacity of the machine.
+	// For small machines, use at least 4 threads.
+	if os.Getenv("GOMAXPROCS") == "" {
+		n := runtime.NumCPU()
+		if n < 4 {
+			n = 4
+		}
+		runtime.GOMAXPROCS(n)
+	}
+}
+
+func main() {
+	if err := doMain(); err != nil {
+		fmt.Fprintf(os.Stderr, "ssadump: %s\n", err)
+		os.Exit(1)
+	}
+}
+
+func doMain() error {
+	flag.Parse()
+	args := flag.Args()
+
+	conf := loader.Config{Build: &build.Default}
+
+	// Choose types.Sizes from conf.Build.
+	var wordSize int64 = 8
+	switch conf.Build.GOARCH {
+	case "386", "arm":
+		wordSize = 4
+	}
+	conf.TypeChecker.Sizes = &types.StdSizes{
+		MaxAlign: 8,
+		WordSize: wordSize,
+	}
+
+	var interpMode interp.Mode
+	for _, c := range *interpFlag {
+		switch c {
+		case 'T':
+			interpMode |= interp.EnableTracing
+		case 'R':
+			interpMode |= interp.DisableRecover
+		default:
+			return fmt.Errorf("unknown -interp option: '%c'", c)
+		}
+	}
+
+	if len(args) == 0 {
+		fmt.Fprint(os.Stderr, usage)
+		os.Exit(1)
+	}
+
+	// Profiling support.
+	if *cpuprofile != "" {
+		f, err := os.Create(*cpuprofile)
+		if err != nil {
+			fmt.Fprintln(os.Stderr, err)
+			os.Exit(1)
+		}
+		pprof.StartCPUProfile(f)
+		defer pprof.StopCPUProfile()
+	}
+
+	// Use the initial packages from the command line.
+	args, err := conf.FromArgs(args, *testFlag)
+	if err != nil {
+		return err
+	}
+
+	// The interpreter needs the runtime package.
+	if *runFlag {
+		conf.Import("runtime")
+	}
+
+	// Load, parse and type-check the whole program.
+	iprog, err := conf.Load()
+	if err != nil {
+		return err
+	}
+
+	// Create and build SSA-form program representation.
+	prog := ssautil.CreateProgram(iprog, *modeFlag)
+
+	// Build and display only the initial packages
+	// (and synthetic wrappers), unless -run is specified.
+	for _, info := range iprog.InitialPackages() {
+		prog.Package(info.Pkg).Build()
+	}
+
+	// Run the interpreter.
+	if *runFlag {
+		prog.Build()
+
+		var main *ssa.Package
+		pkgs := prog.AllPackages()
+		if *testFlag {
+			// If -test, run all packages' tests.
+			if len(pkgs) > 0 {
+				main = prog.CreateTestMainPackage(pkgs...)
+			}
+			if main == nil {
+				return fmt.Errorf("no tests")
+			}
+		} else {
+			// Otherwise, run main.main.
+			for _, pkg := range pkgs {
+				if pkg.Pkg.Name() == "main" {
+					main = pkg
+					if main.Func("main") == nil {
+						return fmt.Errorf("no func main() in main package")
+					}
+					break
+				}
+			}
+			if main == nil {
+				return fmt.Errorf("no main package")
+			}
+		}
+
+		if runtime.GOARCH != build.Default.GOARCH {
+			return fmt.Errorf("cross-interpretation is not supported (target has GOARCH %s, interpreter has %s)",
+				build.Default.GOARCH, runtime.GOARCH)
+		}
+
+		interp.Interpret(main, interpMode, conf.TypeChecker.Sizes, main.Pkg.Path(), args)
+	}
+	return nil
+}
diff --git a/go/src/golang.org/x/tools/cmd/stress/stress.go b/go/src/golang.org/x/tools/cmd/stress/stress.go
index e0ff6b4..470d261 100644
--- a/go/src/golang.org/x/tools/cmd/stress/stress.go
+++ b/go/src/golang.org/x/tools/cmd/stress/stress.go
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// TODO: syscall.SIGABRT is not defined for Plan 9 (issue #11975)
-
 // +build !plan9
 
 // The stress utility is intended for catching of episodic failures.
diff --git a/go/src/golang.org/x/tools/cmd/stringer/stringer.go b/go/src/golang.org/x/tools/cmd/stringer/stringer.go
index be87dec..992125a 100644
--- a/go/src/golang.org/x/tools/cmd/stringer/stringer.go
+++ b/go/src/golang.org/x/tools/cmd/stringer/stringer.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 // Stringer is a tool to automate the creation of methods that satisfy the fmt.Stringer
 // interface. Given the name of a (signed or unsigned) integer type T that has constants
 // defined, stringer will create a new self-contained Go source file implementing
@@ -64,20 +66,18 @@
 	"fmt"
 	"go/ast"
 	"go/build"
+	exact "go/constant"
 	"go/format"
+	"go/importer"
 	"go/parser"
 	"go/token"
+	"go/types"
 	"io/ioutil"
 	"log"
 	"os"
 	"path/filepath"
 	"sort"
 	"strings"
-
-	"golang.org/x/tools/go/exact"
-	"golang.org/x/tools/go/types"
-
-	_ "golang.org/x/tools/go/gcimporter"
 )
 
 var (
@@ -128,7 +128,7 @@
 	}
 
 	// Print the header and package clause.
-	g.Printf("// generated by stringer %s; DO NOT EDIT\n", strings.Join(os.Args[1:], " "))
+	g.Printf("// Code generated by \"stringer %s\"; DO NOT EDIT\n", strings.Join(os.Args[1:], " "))
 	g.Printf("\n")
 	g.Printf("package %s", g.pkg.name)
 	g.Printf("\n")
@@ -260,7 +260,7 @@
 // check type-checks the package. The package must be OK to proceed.
 func (pkg *Package) check(fs *token.FileSet, astFiles []*ast.File) {
 	pkg.defs = make(map[*ast.Ident]types.Object)
-	config := types.Config{FakeImportC: true}
+	config := types.Config{Importer: importer.Default(), FakeImportC: true}
 	info := &types.Info{
 		Defs: pkg.defs,
 	}
diff --git a/go/src/golang.org/x/tools/cmd/stringer/stringer14.go b/go/src/golang.org/x/tools/cmd/stringer/stringer14.go
new file mode 100644
index 0000000..e0962e3
--- /dev/null
+++ b/go/src/golang.org/x/tools/cmd/stringer/stringer14.go
@@ -0,0 +1,640 @@
+// Copyright 2014 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.
+
+// +build !go1.5
+
+// Stringer is a tool to automate the creation of methods that satisfy the fmt.Stringer
+// interface. Given the name of a (signed or unsigned) integer type T that has constants
+// defined, stringer will create a new self-contained Go source file implementing
+//	func (t T) String() string
+// The file is created in the same package and directory as the package that defines T.
+// It has helpful defaults designed for use with go generate.
+//
+// Stringer works best with constants that are consecutive values such as created using iota,
+// but creates good code regardless. In the future it might also provide custom support for
+// constant sets that are bit patterns.
+//
+// For example, given this snippet,
+//
+//	package painkiller
+//
+//	type Pill int
+//
+//	const (
+//		Placebo Pill = iota
+//		Aspirin
+//		Ibuprofen
+//		Paracetamol
+//		Acetaminophen = Paracetamol
+//	)
+//
+// running this command
+//
+//	stringer -type=Pill
+//
+// in the same directory will create the file pill_string.go, in package painkiller,
+// containing a definition of
+//
+//	func (Pill) String() string
+//
+// That method will translate the value of a Pill constant to the string representation
+// of the respective constant name, so that the call fmt.Print(painkiller.Aspirin) will
+// print the string "Aspirin".
+//
+// Typically this process would be run using go generate, like this:
+//
+//	//go:generate stringer -type=Pill
+//
+// If multiple constants have the same value, the lexically first matching name will
+// be used (in the example, Acetaminophen will print as "Paracetamol").
+//
+// With no arguments, it processes the package in the current directory.
+// Otherwise, the arguments must name a single directory holding a Go package
+// or a set of Go source files that represent a single Go package.
+//
+// The -type flag accepts a comma-separated list of types so a single run can
+// generate methods for multiple types. The default output file is t_string.go,
+// where t is the lower-cased name of the first type listed. It can be overridden
+// with the -output flag.
+//
+package main // import "golang.org/x/tools/cmd/stringer"
+
+import (
+	"bytes"
+	"flag"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/format"
+	"go/parser"
+	"go/token"
+	"io/ioutil"
+	"log"
+	"os"
+	"path/filepath"
+	"sort"
+	"strings"
+
+	"golang.org/x/tools/go/exact"
+	"golang.org/x/tools/go/types"
+
+	_ "golang.org/x/tools/go/gcimporter"
+)
+
+var (
+	typeNames = flag.String("type", "", "comma-separated list of type names; must be set")
+	output    = flag.String("output", "", "output file name; default srcdir/<type>_string.go")
+)
+
+// Usage is a replacement usage function for the flags package.
+func Usage() {
+	fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
+	fmt.Fprintf(os.Stderr, "\tstringer [flags] -type T [directory]\n")
+	fmt.Fprintf(os.Stderr, "\tstringer [flags[ -type T files... # Must be a single package\n")
+	fmt.Fprintf(os.Stderr, "For more information, see:\n")
+	fmt.Fprintf(os.Stderr, "\thttp://godoc.org/golang.org/x/tools/cmd/stringer\n")
+	fmt.Fprintf(os.Stderr, "Flags:\n")
+	flag.PrintDefaults()
+}
+
+func main() {
+	log.SetFlags(0)
+	log.SetPrefix("stringer: ")
+	flag.Usage = Usage
+	flag.Parse()
+	if len(*typeNames) == 0 {
+		flag.Usage()
+		os.Exit(2)
+	}
+	types := strings.Split(*typeNames, ",")
+
+	// We accept either one directory or a list of files. Which do we have?
+	args := flag.Args()
+	if len(args) == 0 {
+		// Default: process whole package in current directory.
+		args = []string{"."}
+	}
+
+	// Parse the package once.
+	var (
+		dir string
+		g   Generator
+	)
+	if len(args) == 1 && isDirectory(args[0]) {
+		dir = args[0]
+		g.parsePackageDir(args[0])
+	} else {
+		dir = filepath.Dir(args[0])
+		g.parsePackageFiles(args)
+	}
+
+	// Print the header and package clause.
+	g.Printf("// Code generated by \"stringer %s\"; DO NOT EDIT\n", strings.Join(os.Args[1:], " "))
+	g.Printf("\n")
+	g.Printf("package %s", g.pkg.name)
+	g.Printf("\n")
+	g.Printf("import \"fmt\"\n") // Used by all methods.
+
+	// Run generate for each type.
+	for _, typeName := range types {
+		g.generate(typeName)
+	}
+
+	// Format the output.
+	src := g.format()
+
+	// Write to file.
+	outputName := *output
+	if outputName == "" {
+		baseName := fmt.Sprintf("%s_string.go", types[0])
+		outputName = filepath.Join(dir, strings.ToLower(baseName))
+	}
+	err := ioutil.WriteFile(outputName, src, 0644)
+	if err != nil {
+		log.Fatalf("writing output: %s", err)
+	}
+}
+
+// isDirectory reports whether the named file is a directory.
+func isDirectory(name string) bool {
+	info, err := os.Stat(name)
+	if err != nil {
+		log.Fatal(err)
+	}
+	return info.IsDir()
+}
+
+// Generator holds the state of the analysis. Primarily used to buffer
+// the output for format.Source.
+type Generator struct {
+	buf bytes.Buffer // Accumulated output.
+	pkg *Package     // Package we are scanning.
+}
+
+func (g *Generator) Printf(format string, args ...interface{}) {
+	fmt.Fprintf(&g.buf, format, args...)
+}
+
+// File holds a single parsed file and associated data.
+type File struct {
+	pkg  *Package  // Package to which this file belongs.
+	file *ast.File // Parsed AST.
+	// These fields are reset for each type being generated.
+	typeName string  // Name of the constant type.
+	values   []Value // Accumulator for constant values of that type.
+}
+
+type Package struct {
+	dir      string
+	name     string
+	defs     map[*ast.Ident]types.Object
+	files    []*File
+	typesPkg *types.Package
+}
+
+// parsePackageDir parses the package residing in the directory.
+func (g *Generator) parsePackageDir(directory string) {
+	pkg, err := build.Default.ImportDir(directory, 0)
+	if err != nil {
+		log.Fatalf("cannot process directory %s: %s", directory, err)
+	}
+	var names []string
+	names = append(names, pkg.GoFiles...)
+	names = append(names, pkg.CgoFiles...)
+	// TODO: Need to think about constants in test files. Maybe write type_string_test.go
+	// in a separate pass? For later.
+	// names = append(names, pkg.TestGoFiles...) // These are also in the "foo" package.
+	names = append(names, pkg.SFiles...)
+	names = prefixDirectory(directory, names)
+	g.parsePackage(directory, names, nil)
+}
+
+// parsePackageFiles parses the package occupying the named files.
+func (g *Generator) parsePackageFiles(names []string) {
+	g.parsePackage(".", names, nil)
+}
+
+// prefixDirectory places the directory name on the beginning of each name in the list.
+func prefixDirectory(directory string, names []string) []string {
+	if directory == "." {
+		return names
+	}
+	ret := make([]string, len(names))
+	for i, name := range names {
+		ret[i] = filepath.Join(directory, name)
+	}
+	return ret
+}
+
+// parsePackage analyzes the single package constructed from the named files.
+// If text is non-nil, it is a string to be used instead of the content of the file,
+// to be used for testing. parsePackage exits if there is an error.
+func (g *Generator) parsePackage(directory string, names []string, text interface{}) {
+	var files []*File
+	var astFiles []*ast.File
+	g.pkg = new(Package)
+	fs := token.NewFileSet()
+	for _, name := range names {
+		if !strings.HasSuffix(name, ".go") {
+			continue
+		}
+		parsedFile, err := parser.ParseFile(fs, name, text, 0)
+		if err != nil {
+			log.Fatalf("parsing package: %s: %s", name, err)
+		}
+		astFiles = append(astFiles, parsedFile)
+		files = append(files, &File{
+			file: parsedFile,
+			pkg:  g.pkg,
+		})
+	}
+	if len(astFiles) == 0 {
+		log.Fatalf("%s: no buildable Go files", directory)
+	}
+	g.pkg.name = astFiles[0].Name.Name
+	g.pkg.files = files
+	g.pkg.dir = directory
+	// Type check the package.
+	g.pkg.check(fs, astFiles)
+}
+
+// check type-checks the package. The package must be OK to proceed.
+func (pkg *Package) check(fs *token.FileSet, astFiles []*ast.File) {
+	pkg.defs = make(map[*ast.Ident]types.Object)
+	config := types.Config{FakeImportC: true}
+	info := &types.Info{
+		Defs: pkg.defs,
+	}
+	typesPkg, err := config.Check(pkg.dir, fs, astFiles, info)
+	if err != nil {
+		log.Fatalf("checking package: %s", err)
+	}
+	pkg.typesPkg = typesPkg
+}
+
+// generate produces the String method for the named type.
+func (g *Generator) generate(typeName string) {
+	values := make([]Value, 0, 100)
+	for _, file := range g.pkg.files {
+		// Set the state for this run of the walker.
+		file.typeName = typeName
+		file.values = nil
+		if file.file != nil {
+			ast.Inspect(file.file, file.genDecl)
+			values = append(values, file.values...)
+		}
+	}
+
+	if len(values) == 0 {
+		log.Fatalf("no values defined for type %s", typeName)
+	}
+	runs := splitIntoRuns(values)
+	// The decision of which pattern to use depends on the number of
+	// runs in the numbers. If there's only one, it's easy. For more than
+	// one, there's a tradeoff between complexity and size of the data
+	// and code vs. the simplicity of a map. A map takes more space,
+	// but so does the code. The decision here (crossover at 10) is
+	// arbitrary, but considers that for large numbers of runs the cost
+	// of the linear scan in the switch might become important, and
+	// rather than use yet another algorithm such as binary search,
+	// we punt and use a map. In any case, the likelihood of a map
+	// being necessary for any realistic example other than bitmasks
+	// is very low. And bitmasks probably deserve their own analysis,
+	// to be done some other day.
+	switch {
+	case len(runs) == 1:
+		g.buildOneRun(runs, typeName)
+	case len(runs) <= 10:
+		g.buildMultipleRuns(runs, typeName)
+	default:
+		g.buildMap(runs, typeName)
+	}
+}
+
+// splitIntoRuns breaks the values into runs of contiguous sequences.
+// For example, given 1,2,3,5,6,7 it returns {1,2,3},{5,6,7}.
+// The input slice is known to be non-empty.
+func splitIntoRuns(values []Value) [][]Value {
+	// We use stable sort so the lexically first name is chosen for equal elements.
+	sort.Stable(byValue(values))
+	// Remove duplicates. Stable sort has put the one we want to print first,
+	// so use that one. The String method won't care about which named constant
+	// was the argument, so the first name for the given value is the only one to keep.
+	// We need to do this because identical values would cause the switch or map
+	// to fail to compile.
+	j := 1
+	for i := 1; i < len(values); i++ {
+		if values[i].value != values[i-1].value {
+			values[j] = values[i]
+			j++
+		}
+	}
+	values = values[:j]
+	runs := make([][]Value, 0, 10)
+	for len(values) > 0 {
+		// One contiguous sequence per outer loop.
+		i := 1
+		for i < len(values) && values[i].value == values[i-1].value+1 {
+			i++
+		}
+		runs = append(runs, values[:i])
+		values = values[i:]
+	}
+	return runs
+}
+
+// format returns the gofmt-ed contents of the Generator's buffer.
+func (g *Generator) format() []byte {
+	src, err := format.Source(g.buf.Bytes())
+	if err != nil {
+		// Should never happen, but can arise when developing this code.
+		// The user can compile the output to see the error.
+		log.Printf("warning: internal error: invalid Go generated: %s", err)
+		log.Printf("warning: compile the package to analyze the error")
+		return g.buf.Bytes()
+	}
+	return src
+}
+
+// Value represents a declared constant.
+type Value struct {
+	name string // The name of the constant.
+	// The value is stored as a bit pattern alone. The boolean tells us
+	// whether to interpret it as an int64 or a uint64; the only place
+	// this matters is when sorting.
+	// Much of the time the str field is all we need; it is printed
+	// by Value.String.
+	value  uint64 // Will be converted to int64 when needed.
+	signed bool   // Whether the constant is a signed type.
+	str    string // The string representation given by the "go/exact" package.
+}
+
+func (v *Value) String() string {
+	return v.str
+}
+
+// byValue lets us sort the constants into increasing order.
+// We take care in the Less method to sort in signed or unsigned order,
+// as appropriate.
+type byValue []Value
+
+func (b byValue) Len() int      { return len(b) }
+func (b byValue) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
+func (b byValue) Less(i, j int) bool {
+	if b[i].signed {
+		return int64(b[i].value) < int64(b[j].value)
+	}
+	return b[i].value < b[j].value
+}
+
+// genDecl processes one declaration clause.
+func (f *File) genDecl(node ast.Node) bool {
+	decl, ok := node.(*ast.GenDecl)
+	if !ok || decl.Tok != token.CONST {
+		// We only care about const declarations.
+		return true
+	}
+	// The name of the type of the constants we are declaring.
+	// Can change if this is a multi-element declaration.
+	typ := ""
+	// Loop over the elements of the declaration. Each element is a ValueSpec:
+	// a list of names possibly followed by a type, possibly followed by values.
+	// If the type and value are both missing, we carry down the type (and value,
+	// but the "go/types" package takes care of that).
+	for _, spec := range decl.Specs {
+		vspec := spec.(*ast.ValueSpec) // Guaranteed to succeed as this is CONST.
+		if vspec.Type == nil && len(vspec.Values) > 0 {
+			// "X = 1". With no type but a value, the constant is untyped.
+			// Skip this vspec and reset the remembered type.
+			typ = ""
+			continue
+		}
+		if vspec.Type != nil {
+			// "X T". We have a type. Remember it.
+			ident, ok := vspec.Type.(*ast.Ident)
+			if !ok {
+				continue
+			}
+			typ = ident.Name
+		}
+		if typ != f.typeName {
+			// This is not the type we're looking for.
+			continue
+		}
+		// We now have a list of names (from one line of source code) all being
+		// declared with the desired type.
+		// Grab their names and actual values and store them in f.values.
+		for _, name := range vspec.Names {
+			if name.Name == "_" {
+				continue
+			}
+			// This dance lets the type checker find the values for us. It's a
+			// bit tricky: look up the object declared by the name, find its
+			// types.Const, and extract its value.
+			obj, ok := f.pkg.defs[name]
+			if !ok {
+				log.Fatalf("no value for constant %s", name)
+			}
+			info := obj.Type().Underlying().(*types.Basic).Info()
+			if info&types.IsInteger == 0 {
+				log.Fatalf("can't handle non-integer constant type %s", typ)
+			}
+			value := obj.(*types.Const).Val() // Guaranteed to succeed as this is CONST.
+			if value.Kind() != exact.Int {
+				log.Fatalf("can't happen: constant is not an integer %s", name)
+			}
+			i64, isInt := exact.Int64Val(value)
+			u64, isUint := exact.Uint64Val(value)
+			if !isInt && !isUint {
+				log.Fatalf("internal error: value of %s is not an integer: %s", name, value.String())
+			}
+			if !isInt {
+				u64 = uint64(i64)
+			}
+			v := Value{
+				name:   name.Name,
+				value:  u64,
+				signed: info&types.IsUnsigned == 0,
+				str:    value.String(),
+			}
+			f.values = append(f.values, v)
+		}
+	}
+	return false
+}
+
+// Helpers
+
+// usize returns the number of bits of the smallest unsigned integer
+// type that will hold n. Used to create the smallest possible slice of
+// integers to use as indexes into the concatenated strings.
+func usize(n int) int {
+	switch {
+	case n < 1<<8:
+		return 8
+	case n < 1<<16:
+		return 16
+	default:
+		// 2^32 is enough constants for anyone.
+		return 32
+	}
+}
+
+// declareIndexAndNameVars declares the index slices and concatenated names
+// strings representing the runs of values.
+func (g *Generator) declareIndexAndNameVars(runs [][]Value, typeName string) {
+	var indexes, names []string
+	for i, run := range runs {
+		index, name := g.createIndexAndNameDecl(run, typeName, fmt.Sprintf("_%d", i))
+		indexes = append(indexes, index)
+		names = append(names, name)
+	}
+	g.Printf("const (\n")
+	for _, name := range names {
+		g.Printf("\t%s\n", name)
+	}
+	g.Printf(")\n\n")
+	g.Printf("var (")
+	for _, index := range indexes {
+		g.Printf("\t%s\n", index)
+	}
+	g.Printf(")\n\n")
+}
+
+// declareIndexAndNameVar is the single-run version of declareIndexAndNameVars
+func (g *Generator) declareIndexAndNameVar(run []Value, typeName string) {
+	index, name := g.createIndexAndNameDecl(run, typeName, "")
+	g.Printf("const %s\n", name)
+	g.Printf("var %s\n", index)
+}
+
+// createIndexAndNameDecl returns the pair of declarations for the run. The caller will add "const" and "var".
+func (g *Generator) createIndexAndNameDecl(run []Value, typeName string, suffix string) (string, string) {
+	b := new(bytes.Buffer)
+	indexes := make([]int, len(run))
+	for i := range run {
+		b.WriteString(run[i].name)
+		indexes[i] = b.Len()
+	}
+	nameConst := fmt.Sprintf("_%s_name%s = %q", typeName, suffix, b.String())
+	nameLen := b.Len()
+	b.Reset()
+	fmt.Fprintf(b, "_%s_index%s = [...]uint%d{0, ", typeName, suffix, usize(nameLen))
+	for i, v := range indexes {
+		if i > 0 {
+			fmt.Fprintf(b, ", ")
+		}
+		fmt.Fprintf(b, "%d", v)
+	}
+	fmt.Fprintf(b, "}")
+	return b.String(), nameConst
+}
+
+// declareNameVars declares the concatenated names string representing all the values in the runs.
+func (g *Generator) declareNameVars(runs [][]Value, typeName string, suffix string) {
+	g.Printf("const _%s_name%s = \"", typeName, suffix)
+	for _, run := range runs {
+		for i := range run {
+			g.Printf("%s", run[i].name)
+		}
+	}
+	g.Printf("\"\n")
+}
+
+// buildOneRun generates the variables and String method for a single run of contiguous values.
+func (g *Generator) buildOneRun(runs [][]Value, typeName string) {
+	values := runs[0]
+	g.Printf("\n")
+	g.declareIndexAndNameVar(values, typeName)
+	// The generated code is simple enough to write as a Printf format.
+	lessThanZero := ""
+	if values[0].signed {
+		lessThanZero = "i < 0 || "
+	}
+	if values[0].value == 0 { // Signed or unsigned, 0 is still 0.
+		g.Printf(stringOneRun, typeName, usize(len(values)), lessThanZero)
+	} else {
+		g.Printf(stringOneRunWithOffset, typeName, values[0].String(), usize(len(values)), lessThanZero)
+	}
+}
+
+// Arguments to format are:
+//	[1]: type name
+//	[2]: size of index element (8 for uint8 etc.)
+//	[3]: less than zero check (for signed types)
+const stringOneRun = `func (i %[1]s) String() string {
+	if %[3]si >= %[1]s(len(_%[1]s_index)-1) {
+		return fmt.Sprintf("%[1]s(%%d)", i)
+	}
+	return _%[1]s_name[_%[1]s_index[i]:_%[1]s_index[i+1]]
+}
+`
+
+// Arguments to format are:
+//	[1]: type name
+//	[2]: lowest defined value for type, as a string
+//	[3]: size of index element (8 for uint8 etc.)
+//	[4]: less than zero check (for signed types)
+/*
+ */
+const stringOneRunWithOffset = `func (i %[1]s) String() string {
+	i -= %[2]s
+	if %[4]si >= %[1]s(len(_%[1]s_index)-1) {
+		return fmt.Sprintf("%[1]s(%%d)", i + %[2]s)
+	}
+	return _%[1]s_name[_%[1]s_index[i] : _%[1]s_index[i+1]]
+}
+`
+
+// buildMultipleRuns generates the variables and String method for multiple runs of contiguous values.
+// For this pattern, a single Printf format won't do.
+func (g *Generator) buildMultipleRuns(runs [][]Value, typeName string) {
+	g.Printf("\n")
+	g.declareIndexAndNameVars(runs, typeName)
+	g.Printf("func (i %s) String() string {\n", typeName)
+	g.Printf("\tswitch {\n")
+	for i, values := range runs {
+		if len(values) == 1 {
+			g.Printf("\tcase i == %s:\n", &values[0])
+			g.Printf("\t\treturn _%s_name_%d\n", typeName, i)
+			continue
+		}
+		g.Printf("\tcase %s <= i && i <= %s:\n", &values[0], &values[len(values)-1])
+		if values[0].value != 0 {
+			g.Printf("\t\ti -= %s\n", &values[0])
+		}
+		g.Printf("\t\treturn _%s_name_%d[_%s_index_%d[i]:_%s_index_%d[i+1]]\n",
+			typeName, i, typeName, i, typeName, i)
+	}
+	g.Printf("\tdefault:\n")
+	g.Printf("\t\treturn fmt.Sprintf(\"%s(%%d)\", i)\n", typeName)
+	g.Printf("\t}\n")
+	g.Printf("}\n")
+}
+
+// buildMap handles the case where the space is so sparse a map is a reasonable fallback.
+// It's a rare situation but has simple code.
+func (g *Generator) buildMap(runs [][]Value, typeName string) {
+	g.Printf("\n")
+	g.declareNameVars(runs, typeName, "")
+	g.Printf("\nvar _%s_map = map[%s]string{\n", typeName, typeName)
+	n := 0
+	for _, values := range runs {
+		for _, value := range values {
+			g.Printf("\t%s: _%s_name[%d:%d],\n", &value, typeName, n, n+len(value.name))
+			n += len(value.name)
+		}
+	}
+	g.Printf("}\n\n")
+	g.Printf(stringMap, typeName)
+}
+
+// Argument to format is the type name.
+const stringMap = `func (i %[1]s) String() string {
+	if str, ok := _%[1]s_map[i]; ok {
+		return str
+	}
+	return fmt.Sprintf("%[1]s(%%d)", i)
+}
+`
diff --git a/go/src/golang.org/x/tools/cmd/tipgodoc/Dockerfile b/go/src/golang.org/x/tools/cmd/tip/Dockerfile
similarity index 63%
rename from go/src/golang.org/x/tools/cmd/tipgodoc/Dockerfile
rename to go/src/golang.org/x/tools/cmd/tip/Dockerfile
index 760ca0b..8364cdb 100644
--- a/go/src/golang.org/x/tools/cmd/tipgodoc/Dockerfile
+++ b/go/src/golang.org/x/tools/cmd/tip/Dockerfile
@@ -1,13 +1,13 @@
-FROM golang:1.4.2
+FROM golang:1.5
 
 RUN apt-get update && apt-get install --no-install-recommends -y -q build-essential git
 
 # golang puts its go install here (weird but true)
-ENV GOROOT_BOOTSTRAP /usr/src/go
+ENV GOROOT_BOOTSTRAP /usr/local/go
 
 # golang sets GOPATH=/go
-ADD . /go/src/tipgodoc
-RUN go install tipgodoc
-ENTRYPOINT ["/go/bin/tipgodoc"]
+ADD . /go/src/tip
+RUN go install tip
+ENTRYPOINT ["/go/bin/tip"]
 # Kubernetes expects us to listen on port 8080
 EXPOSE 8080 
diff --git a/go/src/golang.org/x/tools/cmd/tip/README b/go/src/golang.org/x/tools/cmd/tip/README
new file mode 100644
index 0000000..5fe1cfe
--- /dev/null
+++ b/go/src/golang.org/x/tools/cmd/tip/README
@@ -0,0 +1,14 @@
+1. Deploy the app.
+
+   To deploy tip.golang.org:
+       $ gcloud --project golang-org preview app deploy --no-promote godoc.yaml
+
+   To deploy talks.golang.org:
+       $ gcloud --project golang-org preview app deploy --no-promote talks.yaml
+
+2. Wait until the deployed version is serving requests.
+
+3. Go to the developer console and upgrade the default version.
+   https://console.developers.google.com/appengine/versions?project=golang-org&moduleId=tip
+
+4. Clean up any old versions (they continue to use at least one instance).
diff --git a/go/src/golang.org/x/tools/cmd/tip/godoc.go b/go/src/golang.org/x/tools/cmd/tip/godoc.go
new file mode 100644
index 0000000..ab3c3d2
--- /dev/null
+++ b/go/src/golang.org/x/tools/cmd/tip/godoc.go
@@ -0,0 +1,72 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by the Apache 2.0
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"os"
+	"os/exec"
+	"path/filepath"
+)
+
+type godocBuilder struct {
+}
+
+func (b godocBuilder) Signature(heads map[string]string) string {
+	return heads["go"] + "-" + heads["tools"]
+}
+
+func (b godocBuilder) Init(dir, hostport string, heads map[string]string) (*exec.Cmd, error) {
+	goDir := filepath.Join(dir, "go")
+	toolsDir := filepath.Join(dir, "gopath/src/golang.org/x/tools")
+	if err := checkout(repoURL+"go", heads["go"], goDir); err != nil {
+		return nil, err
+	}
+	if err := checkout(repoURL+"tools", heads["tools"], toolsDir); err != nil {
+		return nil, err
+	}
+
+	make := exec.Command(filepath.Join(goDir, "src/make.bash"))
+	make.Dir = filepath.Join(goDir, "src")
+	if err := runErr(make); err != nil {
+		return nil, err
+	}
+	goBin := filepath.Join(goDir, "bin/go")
+	install := exec.Command(goBin, "install", "golang.org/x/tools/cmd/godoc")
+	install.Env = []string{
+		"GOROOT=" + goDir,
+		"GOPATH=" + filepath.Join(dir, "gopath"),
+		"GOROOT_BOOTSTRAP=" + os.Getenv("GOROOT_BOOTSTRAP"),
+	}
+	if err := runErr(install); err != nil {
+		return nil, err
+	}
+
+	godocBin := filepath.Join(goDir, "bin/godoc")
+	godoc := exec.Command(godocBin, "-http="+hostport, "-index", "-index_interval=-1s")
+	godoc.Env = []string{"GOROOT=" + goDir}
+	// TODO(adg): log this somewhere useful
+	godoc.Stdout = os.Stdout
+	godoc.Stderr = os.Stderr
+	if err := godoc.Start(); err != nil {
+		return nil, err
+	}
+	return godoc, nil
+}
+
+var indexingMsg = []byte("Indexing in progress: result may be inaccurate")
+
+func (b godocBuilder) HealthCheck(hostport string) error {
+	body, err := getOK(fmt.Sprintf("http://%v/search?q=FALLTHROUGH", hostport))
+	if err != nil {
+		return err
+	}
+	if bytes.Contains(body, indexingMsg) {
+		return errors.New("still indexing")
+	}
+	return nil
+}
diff --git a/go/src/golang.org/x/tools/cmd/tip/godoc.yaml b/go/src/golang.org/x/tools/cmd/tip/godoc.yaml
new file mode 100644
index 0000000..5f6d9dc
--- /dev/null
+++ b/go/src/golang.org/x/tools/cmd/tip/godoc.yaml
@@ -0,0 +1,18 @@
+module: tip
+runtime: custom
+vm: true
+
+automatic_scaling:
+  min_num_instances: 1
+  max_num_instances: 2
+
+env_variables:
+  TIP_BUILDER: 'godoc'
+
+health_check:
+  enable_health_check: True
+  check_interval_sec: 5
+  timeout_sec: 4
+  unhealthy_threshold: 2
+  healthy_threshold: 2
+  restart_threshold: 240
diff --git a/go/src/golang.org/x/tools/cmd/tip/talks.go b/go/src/golang.org/x/tools/cmd/tip/talks.go
new file mode 100644
index 0000000..15167e1
--- /dev/null
+++ b/go/src/golang.org/x/tools/cmd/tip/talks.go
@@ -0,0 +1,73 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by the Apache 2.0
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"runtime"
+)
+
+type talksBuilder struct {
+}
+
+func (b talksBuilder) Signature(heads map[string]string) string {
+	return heads["talks"]
+}
+
+const talksToolsRev = "ac6d9c1d842f9b6482f39f7a172e0251a0f7cbc0"
+
+func (b talksBuilder) Init(dir, hostport string, heads map[string]string) (*exec.Cmd, error) {
+	toolsDir := filepath.Join(dir, "gopath/src/golang.org/x/tools")
+	if err := checkout(repoURL+"tools", talksToolsRev, toolsDir); err != nil {
+		return nil, err
+	}
+	talksDir := filepath.Join(dir, "gopath/src/golang.org/x/talks")
+	if err := checkout(repoURL+"talks", heads["talks"], talksDir); err != nil {
+		return nil, err
+	}
+
+	goDir := os.Getenv("GOROOT_BOOTSTRAP")
+	if goDir == "" {
+		goDir = runtime.GOROOT()
+	}
+	goBin := filepath.Join(goDir, "bin/go")
+	goPath := filepath.Join(dir, "gopath")
+	presentPath := "golang.org/x/tools/cmd/present"
+	install := exec.Command(goBin, "install", "-tags=appenginevm", presentPath)
+	install.Env = []string{"GOROOT=" + goDir, "GOPATH=" + goPath}
+	if err := runErr(install); err != nil {
+		return nil, err
+	}
+
+	talksBin := filepath.Join(goPath, "bin/present")
+	presentSrc := filepath.Join(goPath, "src", presentPath)
+	present := exec.Command(talksBin, "-http="+hostport, "-base="+presentSrc)
+	present.Dir = talksDir
+	// TODO(adg): log this somewhere useful
+	present.Stdout = os.Stdout
+	present.Stderr = os.Stderr
+	if err := present.Start(); err != nil {
+		return nil, err
+	}
+	return present, nil
+}
+
+var talksMsg = []byte("Talks - The Go Programming Language")
+
+func (b talksBuilder) HealthCheck(hostport string) error {
+	body, err := getOK(fmt.Sprintf("http://%v/", hostport))
+	if err != nil {
+		return err
+	}
+	if !bytes.Contains(body, talksMsg) {
+		return errors.New("couldn't match string")
+	}
+	return nil
+}
diff --git a/go/src/golang.org/x/tools/cmd/tip/talks.yaml b/go/src/golang.org/x/tools/cmd/tip/talks.yaml
new file mode 100644
index 0000000..edc90a5
--- /dev/null
+++ b/go/src/golang.org/x/tools/cmd/tip/talks.yaml
@@ -0,0 +1,18 @@
+module: talks
+runtime: custom
+vm: true
+
+automatic_scaling:
+  min_num_instances: 1
+  max_num_instances: 5
+
+env_variables:
+  TIP_BUILDER: 'talks'
+
+health_check:
+  enable_health_check: True
+  check_interval_sec: 5
+  timeout_sec: 4
+  unhealthy_threshold: 2
+  healthy_threshold: 2
+  restart_threshold: 240
diff --git a/go/src/golang.org/x/tools/cmd/tipgodoc/tip.go b/go/src/golang.org/x/tools/cmd/tip/tip.go
similarity index 65%
rename from go/src/golang.org/x/tools/cmd/tipgodoc/tip.go
rename to go/src/golang.org/x/tools/cmd/tip/tip.go
index ab3b8e6..099b75e 100644
--- a/go/src/golang.org/x/tools/cmd/tipgodoc/tip.go
+++ b/go/src/golang.org/x/tools/cmd/tip/tip.go
@@ -8,8 +8,8 @@
 
 import (
 	"bufio"
-	"bytes"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"io"
 	"io/ioutil"
@@ -30,12 +30,24 @@
 	startTimeout = 5 * time.Minute
 )
 
-var indexingMsg = []byte("Indexing in progress: result may be inaccurate")
-
 func main() {
-	p := new(Proxy)
+	const k = "TIP_BUILDER"
+	var b Builder
+	switch os.Getenv(k) {
+	case "godoc":
+		b = godocBuilder{}
+	case "talks":
+		b = talksBuilder{}
+	default:
+		log.Fatalf("Unknown %v value: %q", k, os.Getenv(k))
+	}
+
+	p := &Proxy{builder: b}
 	go p.run()
 	http.Handle("/", p)
+	http.HandleFunc("/_ah/health", p.serveHealthCheck)
+
+	log.Print("Starting up")
 
 	if err := http.ListenAndServe(":8080", nil); err != nil {
 		p.stop()
@@ -46,12 +58,21 @@
 // Proxy implements the tip.golang.org server: a reverse-proxy
 // that builds and runs godoc instances showing the latest docs.
 type Proxy struct {
-	mu    sync.Mutex // protects the followin'
-	proxy http.Handler
-	cur   string    // signature of gorepo+toolsrepo
-	cmd   *exec.Cmd // live godoc instance, or nil for none
-	side  string
-	err   error
+	builder Builder
+
+	mu       sync.Mutex // protects the followin'
+	proxy    http.Handler
+	cur      string    // signature of gorepo+toolsrepo
+	cmd      *exec.Cmd // live godoc instance, or nil for none
+	side     string
+	hostport string // host and port of the live instance
+	err      error
+}
+
+type Builder interface {
+	Signature(heads map[string]string) string
+	Init(dir, hostport string, heads map[string]string) (*exec.Cmd, error)
+	HealthCheck(hostport string) error
 }
 
 func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
@@ -64,7 +85,7 @@
 	err := p.err
 	p.mu.Unlock()
 	if proxy == nil {
-		s := "tip.golang.org is starting up"
+		s := "starting up"
 		if err != nil {
 			s = err.Error()
 		}
@@ -80,6 +101,25 @@
 	fmt.Fprintf(w, "side=%v\ncurrent=%v\nerror=%v\n", p.side, p.cur, p.err)
 }
 
+func (p *Proxy) serveHealthCheck(w http.ResponseWriter, r *http.Request) {
+	p.mu.Lock()
+	defer p.mu.Unlock()
+	// NOTE: Status 502, 503, 504 are the only status codes that signify an unhealthy app.
+	// So long as this handler returns one of those codes, this instance will not be sent any requests.
+	if p.proxy == nil {
+		log.Printf("Health check: not ready")
+		http.Error(w, "Not ready", http.StatusServiceUnavailable)
+		return
+	}
+
+	if err := p.builder.HealthCheck(p.hostport); err != nil {
+		log.Printf("Health check failed: %v", err)
+		http.Error(w, "Health check failed", http.StatusServiceUnavailable)
+		return
+	}
+	io.WriteString(w, "ok")
+}
+
 // run runs in its own goroutine.
 func (p *Proxy) run() {
 	p.side = "a"
@@ -104,7 +144,7 @@
 		return
 	}
 
-	sig := heads["go"] + "-" + heads["tools"]
+	sig := p.builder.Signature(heads)
 
 	p.mu.Lock()
 	changes := sig != p.cur
@@ -121,7 +161,25 @@
 		newSide = "a"
 	}
 
-	cmd, hostport, err := initSide(newSide, heads["go"], heads["tools"])
+	dir := filepath.Join(os.TempDir(), "tip", newSide)
+	if err := os.MkdirAll(dir, 0755); err != nil {
+		p.err = err
+		return
+	}
+	hostport := "localhost:8081"
+	if newSide == "b" {
+		hostport = "localhost:8082"
+	}
+	cmd, err := p.builder.Init(dir, hostport, heads)
+	if err == nil {
+		go func() {
+			// TODO(adg,bradfitz): be smarter about dead processes
+			if err := cmd.Wait(); err != nil {
+				log.Printf("process in %v exited: %v", dir, err)
+			}
+		}()
+		err = waitReady(p.builder, hostport)
+	}
 
 	p.mu.Lock()
 	defer p.mu.Unlock()
@@ -139,80 +197,23 @@
 	}
 	p.proxy = httputil.NewSingleHostReverseProxy(u)
 	p.side = newSide
+	p.hostport = hostport
 	if p.cmd != nil {
 		p.cmd.Process.Kill()
 	}
 	p.cmd = cmd
 }
 
-func initSide(side, goHash, toolsHash string) (godoc *exec.Cmd, hostport string, err error) {
-	dir := filepath.Join(os.TempDir(), "tipgodoc", side)
-	if err := os.MkdirAll(dir, 0755); err != nil {
-		return nil, "", err
-	}
-
-	goDir := filepath.Join(dir, "go")
-	toolsDir := filepath.Join(dir, "gopath/src/golang.org/x/tools")
-	if err := checkout(repoURL+"go", goHash, goDir); err != nil {
-		return nil, "", err
-	}
-	if err := checkout(repoURL+"tools", toolsHash, toolsDir); err != nil {
-		return nil, "", err
-	}
-
-	make := exec.Command(filepath.Join(goDir, "src/make.bash"))
-	make.Dir = filepath.Join(goDir, "src")
-	if err := runErr(make); err != nil {
-		return nil, "", err
-	}
-	goBin := filepath.Join(goDir, "bin/go")
-	install := exec.Command(goBin, "install", "golang.org/x/tools/cmd/godoc")
-	install.Env = []string{
-		"GOROOT=" + goDir,
-		"GOPATH=" + filepath.Join(dir, "gopath"),
-		"GOROOT_BOOTSTRAP=" + os.Getenv("GOROOT_BOOTSTRAP"),
-	}
-	if err := runErr(install); err != nil {
-		return nil, "", err
-	}
-
-	godocBin := filepath.Join(goDir, "bin/godoc")
-	hostport = "localhost:8081"
-	if side == "b" {
-		hostport = "localhost:8082"
-	}
-	godoc = exec.Command(godocBin, "-http="+hostport, "-index", "-index_interval=-1s")
-	godoc.Env = []string{"GOROOT=" + goDir}
-	// TODO(adg): log this somewhere useful
-	godoc.Stdout = os.Stdout
-	godoc.Stderr = os.Stderr
-	if err := godoc.Start(); err != nil {
-		return nil, "", err
-	}
-	go func() {
-		// TODO(bradfitz): tell the proxy that this side is dead
-		if err := godoc.Wait(); err != nil {
-			log.Printf("side %v exited: %v", side, err)
-		}
-	}()
-
+func waitReady(b Builder, hostport string) error {
+	var err error
 	deadline := time.Now().Add(startTimeout)
 	for time.Now().Before(deadline) {
+		if err = b.HealthCheck(hostport); err == nil {
+			return nil
+		}
 		time.Sleep(time.Second)
-		var res *http.Response
-		res, err = http.Get(fmt.Sprintf("http://%v/search?q=FALLTHROUGH", hostport))
-		if err != nil {
-			continue
-		}
-		rbody, err := ioutil.ReadAll(res.Body)
-		res.Body.Close()
-		if err == nil && res.StatusCode == http.StatusOK &&
-			!bytes.Contains(rbody, indexingMsg) {
-			return godoc, hostport, nil
-		}
 	}
-	godoc.Process.Kill()
-	return nil, "", fmt.Errorf("timed out waiting for side %v at %v (%v)", side, hostport, err)
+	return fmt.Errorf("timed out waiting for process at %v: %v", hostport, err)
 }
 
 func runErr(cmd *exec.Cmd) error {
@@ -296,3 +297,19 @@
 	}
 	return m
 }
+
+func getOK(url string) (body []byte, err error) {
+	res, err := http.Get(url)
+	if err != nil {
+		return nil, err
+	}
+	body, err = ioutil.ReadAll(res.Body)
+	res.Body.Close()
+	if err != nil {
+		return nil, err
+	}
+	if res.StatusCode != http.StatusOK {
+		return nil, errors.New(res.Status)
+	}
+	return body, nil
+}
diff --git a/go/src/golang.org/x/tools/cmd/tipgodoc/README b/go/src/golang.org/x/tools/cmd/tipgodoc/README
deleted file mode 100644
index 602e546..0000000
--- a/go/src/golang.org/x/tools/cmd/tipgodoc/README
+++ /dev/null
@@ -1,3 +0,0 @@
-To deploy as an App Engine Manged VM, use gcloud:
-
-	$ gcloud --project golang-org preview app deploy .
diff --git a/go/src/golang.org/x/tools/cmd/tipgodoc/app.yaml b/go/src/golang.org/x/tools/cmd/tipgodoc/app.yaml
deleted file mode 100644
index 59e5a06..0000000
--- a/go/src/golang.org/x/tools/cmd/tipgodoc/app.yaml
+++ /dev/null
@@ -1,15 +0,0 @@
-application: golang-org
-version: tip
-runtime: custom
-api_version: go1
-vm: true
-
-manual_scaling:
-  instances: 1
-
-handlers:
-- url: /.*
-  script: _go_app
-
-health_check:
-  enable_health_check: False
diff --git a/go/src/golang.org/x/tools/cmd/vet/doc.go b/go/src/golang.org/x/tools/cmd/vet/doc.go
index a19de3f..012f88b 100644
--- a/go/src/golang.org/x/tools/cmd/vet/doc.go
+++ b/go/src/golang.org/x/tools/cmd/vet/doc.go
@@ -37,49 +37,6 @@
 
 Available checks:
 
-Printf family
-
-Flag: -printf
-
-Suspicious calls to functions in the Printf family, including any functions
-with these names, disregarding case:
-	Print Printf Println
-	Fprint Fprintf Fprintln
-	Sprint Sprintf Sprintln
-	Error Errorf
-	Fatal Fatalf
-	Log Logf
-	Panic Panicf Panicln
-If the function name ends with an 'f', the function is assumed to take
-a format descriptor string in the manner of fmt.Printf. If not, vet
-complains about arguments that look like format descriptor strings.
-
-It also checks for errors such as using a Writer as the first argument of
-Printf.
-
-Methods
-
-Flag: -methods
-
-Non-standard signatures for methods with familiar names, including:
-	Format GobEncode GobDecode MarshalJSON MarshalXML
-	Peek ReadByte ReadFrom ReadRune Scan Seek
-	UnmarshalJSON UnreadByte UnreadRune WriteByte
-	WriteTo
-
-Struct tags
-
-Flag: -structtags
-
-Struct tags that do not follow the format understood by reflect.StructTag.Get.
-Well-known encoding struct tags (json, xml) used with unexported fields.
-
-Unkeyed composite literals
-
-Flag: -composites
-
-Composite struct literals that do not use the field-keyed syntax.
-
 Assembly declarations
 
 Flag: -asmdecl
@@ -110,36 +67,92 @@
 
 Badly formed or misplaced +build tags.
 
+Unkeyed composite literals
+
+Flag: -composites
+
+Composite struct literals that do not use the field-keyed syntax.
+
 Copying locks
 
 Flag: -copylocks
 
 Locks that are erroneously passed by value.
 
+Documentation examples
+
+Flag: -example
+
+Mistakes involving example tests, including examples with incorrect names or
+function signatures, or that document identifiers not in the package.
+
+Methods
+
+Flag: -methods
+
+Non-standard signatures for methods with familiar names, including:
+	Format GobEncode GobDecode MarshalJSON MarshalXML
+	Peek ReadByte ReadFrom ReadRune Scan Seek
+	UnmarshalJSON UnreadByte UnreadRune WriteByte
+	WriteTo
+
 Nil function comparison
 
 Flag: -nilfunc
 
 Comparisons between functions and nil.
 
+Printf family
+
+Flag: -printf
+
+Suspicious calls to functions in the Printf family, including any functions
+with these names, disregarding case:
+	Print Printf Println
+	Fprint Fprintf Fprintln
+	Sprint Sprintf Sprintln
+	Error Errorf
+	Fatal Fatalf
+	Log Logf
+	Panic Panicf Panicln
+If the function name ends with an 'f', the function is assumed to take
+a format descriptor string in the manner of fmt.Printf. If not, vet
+complains about arguments that look like format descriptor strings.
+
+It also checks for errors such as using a Writer as the first argument of
+Printf.
+
 Range loop variables
 
 Flag: -rangeloops
 
 Incorrect uses of range loop variables in closures.
 
-Unreachable code
-
-Flag: -unreachable
-
-Unreachable code.
-
 Shadowed variables
 
 Flag: -shadow=false (experimental; must be set explicitly)
 
 Variables that may have been unintentionally shadowed.
 
+Shifts
+
+Flag: -shift
+
+Shifts equal to or longer than the variable's length.
+
+Struct tags
+
+Flag: -structtags
+
+Struct tags that do not follow the format understood by reflect.StructTag.Get.
+Well-known encoding struct tags (json, xml) used with unexported fields.
+
+Unreachable code
+
+Flag: -unreachable
+
+Unreachable code.
+
 Misuse of unsafe Pointers
 
 Flag: -unsafeptr
@@ -159,12 +172,6 @@
 fmt.Sprintf and methods like String and Error. The flags -unusedfuncs
 and -unusedstringmethods control the set.
 
-Shifts
-
-Flag: -shift
-
-Shifts equal to or longer than the variable's length.
-
 Other flags
 
 These flags configure the behavior of vet:
diff --git a/go/src/golang.org/x/tools/cmd/vet/example.go b/go/src/golang.org/x/tools/cmd/vet/example.go
new file mode 100644
index 0000000..585d388
--- /dev/null
+++ b/go/src/golang.org/x/tools/cmd/vet/example.go
@@ -0,0 +1,125 @@
+// Copyright 2015 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 main
+
+import (
+	"go/ast"
+	"strings"
+	"unicode"
+	"unicode/utf8"
+
+	"golang.org/x/tools/go/types"
+)
+
+func init() {
+	register("example",
+		"check for common mistaken usages of documentation examples",
+		checkExample,
+		funcDecl)
+}
+
+func isExampleSuffix(s string) bool {
+	r, size := utf8.DecodeRuneInString(s)
+	return size > 0 && unicode.IsLower(r)
+}
+
+// checkExample walks the documentation example functions checking for common
+// mistakes of misnamed functions, failure to map functions to existing
+// identifiers, etc.
+func checkExample(f *File, node ast.Node) {
+	if !strings.HasSuffix(f.name, "_test.go") {
+		return
+	}
+	var (
+		pkg     = f.pkg
+		pkgName = pkg.typesPkg.Name()
+		scopes  = []*types.Scope{pkg.typesPkg.Scope()}
+		lookup  = func(name string) types.Object {
+			for _, scope := range scopes {
+				if o := scope.Lookup(name); o != nil {
+					return o
+				}
+			}
+			return nil
+		}
+	)
+	if strings.HasSuffix(pkgName, "_test") {
+		// Treat 'package foo_test' as an alias for 'package foo'.
+		var (
+			basePkg = strings.TrimSuffix(pkgName, "_test")
+			pkg     = f.pkg
+		)
+		for _, p := range pkg.typesPkg.Imports() {
+			if p.Name() == basePkg {
+				scopes = append(scopes, p.Scope())
+				break
+			}
+		}
+	}
+	fn, ok := node.(*ast.FuncDecl)
+	if !ok {
+		// Ignore non-functions.
+		return
+	}
+	var (
+		fnName = fn.Name.Name
+		report = func(format string, args ...interface{}) { f.Badf(node.Pos(), format, args...) }
+	)
+	if fn.Recv != nil || !strings.HasPrefix(fnName, "Example") {
+		// Ignore methods and types not named "Example".
+		return
+	}
+	if params := fn.Type.Params; len(params.List) != 0 {
+		report("%s should be niladic", fnName)
+	}
+	if results := fn.Type.Results; results != nil && len(results.List) != 0 {
+		report("%s should return nothing", fnName)
+	}
+	if fnName == "Example" {
+		// Nothing more to do.
+		return
+	}
+	if filesRun && !includesNonTest {
+		// The coherence checks between a test and the package it tests
+		// will report false positives if no non-test files have
+		// been provided.
+		return
+	}
+	var (
+		exName = strings.TrimPrefix(fnName, "Example")
+		elems  = strings.SplitN(exName, "_", 3)
+		ident  = elems[0]
+		obj    = lookup(ident)
+	)
+	if ident != "" && obj == nil {
+		// Check ExampleFoo and ExampleBadFoo.
+		report("%s refers to unknown identifier: %s", fnName, ident)
+		// Abort since obj is absent and no subsequent checks can be performed.
+		return
+	}
+	if elemCnt := strings.Count(exName, "_"); elemCnt == 0 {
+		// Nothing more to do.
+		return
+	}
+	mmbr := elems[1]
+	if ident == "" {
+		// Check Example_suffix and Example_BadSuffix.
+		if residual := strings.TrimPrefix(exName, "_"); !isExampleSuffix(residual) {
+			report("%s has malformed example suffix: %s", fnName, residual)
+		}
+		return
+	}
+	if !isExampleSuffix(mmbr) {
+		// Check ExampleFoo_Method and ExampleFoo_BadMethod.
+		if obj, _, _ := types.LookupFieldOrMethod(obj.Type(), true, obj.Pkg(), mmbr); obj == nil {
+			report("%s refers to unknown field or method: %s.%s", fnName, ident, mmbr)
+		}
+	}
+	if len(elems) == 3 && !isExampleSuffix(elems[2]) {
+		// Check ExampleFoo_Method_suffix and ExampleFoo_Method_Badsuffix.
+		report("%s has malformed example suffix: %s", fnName, elems[2])
+	}
+	return
+}
diff --git a/go/src/golang.org/x/tools/cmd/vet/main.go b/go/src/golang.org/x/tools/cmd/vet/main.go
index e4b6877..c86e13c 100644
--- a/go/src/golang.org/x/tools/cmd/vet/main.go
+++ b/go/src/golang.org/x/tools/cmd/vet/main.go
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// NOTE: This version of vet is retired. Bug fixes only.
+// Vet now lives in the core repository.
+
 // Vet is a simple checker for static errors in Go source code.
 // See doc.go for more information.
 package main
@@ -53,6 +56,14 @@
 // setTrueCount record how many flags are explicitly set to true.
 var setTrueCount int
 
+// dirsRun and filesRun indicate whether the vet is applied to directory or
+// file targets. The distinction affects which checks are run.
+var dirsRun, filesRun bool
+
+// includesNonTest indicates whether the vet is applied to non-test targets.
+// Certain checks are relevant only if they touch both test and non-test files.
+var includesNonTest bool
+
 // A triState is a boolean that knows whether it has been set to either true or false.
 // It is used to identify if a flag appears; the standard boolean flag cannot
 // distinguish missing from unset. It also satisfies flag.Value.
@@ -209,8 +220,6 @@
 	if flag.NArg() == 0 {
 		Usage()
 	}
-	dirs := false
-	files := false
 	for _, name := range flag.Args() {
 		// Is it a directory?
 		fi, err := os.Stat(name)
@@ -219,15 +228,18 @@
 			continue
 		}
 		if fi.IsDir() {
-			dirs = true
+			dirsRun = true
 		} else {
-			files = true
+			filesRun = true
+			if !strings.HasSuffix(name, "_test.go") {
+				includesNonTest = true
+			}
 		}
 	}
-	if dirs && files {
+	if dirsRun && filesRun {
 		Usage()
 	}
-	if dirs {
+	if dirsRun {
 		for _, name := range flag.Args() {
 			walkDir(name)
 		}
diff --git a/go/src/golang.org/x/tools/cmd/vet/testdata/divergent/buf.go b/go/src/golang.org/x/tools/cmd/vet/testdata/divergent/buf.go
new file mode 100644
index 0000000..0efe0f8
--- /dev/null
+++ b/go/src/golang.org/x/tools/cmd/vet/testdata/divergent/buf.go
@@ -0,0 +1,17 @@
+// Test of examples with divergent packages.
+
+// Package buf ...
+package buf
+
+// Buf is a ...
+type Buf []byte
+
+// Append ...
+func (*Buf) Append([]byte) {}
+
+func (Buf) Reset() {}
+
+func (Buf) Len() int { return 0 }
+
+// DefaultBuf is a ...
+var DefaultBuf Buf
diff --git a/go/src/golang.org/x/tools/cmd/vet/testdata/divergent/buf_test.go b/go/src/golang.org/x/tools/cmd/vet/testdata/divergent/buf_test.go
new file mode 100644
index 0000000..6b9cba3
--- /dev/null
+++ b/go/src/golang.org/x/tools/cmd/vet/testdata/divergent/buf_test.go
@@ -0,0 +1,35 @@
+// Test of examples with divergent packages.
+
+package buf_test
+
+func Example() {} // OK because is package-level.
+
+func Example_suffix() // OK because refers to suffix annotation.
+
+func Example_BadSuffix() // ERROR "Example_BadSuffix has malformed example suffix: BadSuffix"
+
+func ExampleBuf() // OK because refers to known top-level type.
+
+func ExampleBuf_Append() {} // OK because refers to known method.
+
+func ExampleBuf_Clear() {} // ERROR "ExampleBuf_Clear refers to unknown field or method: Buf.Clear"
+
+func ExampleBuf_suffix() {} // OK because refers to suffix annotation.
+
+func ExampleBuf_Append_Bad() {} // ERROR "ExampleBuf_Append_Bad has malformed example suffix: Bad"
+
+func ExampleBuf_Append_suffix() {} // OK because refers to known method with valid suffix.
+
+func ExampleDefaultBuf() {} // OK because refers to top-level identifier.
+
+func ExampleBuf_Reset() bool { return true } // ERROR "ExampleBuf_Reset should return nothing"
+
+func ExampleBuf_Len(i int) {} // ERROR "ExampleBuf_Len should be niladic"
+
+// "Puffer" is German for "Buffer".
+
+func ExamplePuffer() // ERROR "ExamplePuffer refers to unknown identifier: Puffer"
+
+func ExamplePuffer_Append() // ERROR "ExamplePuffer_Append refers to unknown identifier: Puffer"
+
+func ExamplePuffer_suffix() // ERROR "ExamplePuffer_suffix refers to unknown identifier: Puffer"
diff --git a/go/src/golang.org/x/tools/cmd/vet/testdata/examples_test.go b/go/src/golang.org/x/tools/cmd/vet/testdata/examples_test.go
new file mode 100644
index 0000000..9c53672
--- /dev/null
+++ b/go/src/golang.org/x/tools/cmd/vet/testdata/examples_test.go
@@ -0,0 +1,48 @@
+// Test of examples.
+
+package testdata
+
+// Buf is a ...
+type Buf []byte
+
+// Append ...
+func (*Buf) Append([]byte) {}
+
+func (Buf) Reset() {}
+
+func (Buf) Len() int { return 0 }
+
+// DefaultBuf is a ...
+var DefaultBuf Buf
+
+func Example() {} // OK because is package-level.
+
+func Example_goodSuffix() // OK because refers to suffix annotation.
+
+func Example_BadSuffix() // ERROR "Example_BadSuffix has malformed example suffix: BadSuffix"
+
+func ExampleBuf() // OK because refers to known top-level type.
+
+func ExampleBuf_Append() {} // OK because refers to known method.
+
+func ExampleBuf_Clear() {} // ERROR "ExampleBuf_Clear refers to unknown field or method: Buf.Clear"
+
+func ExampleBuf_suffix() {} // OK because refers to suffix annotation.
+
+func ExampleBuf_Append_Bad() {} // ERROR "ExampleBuf_Append_Bad has malformed example suffix: Bad"
+
+func ExampleBuf_Append_suffix() {} // OK because refers to known method with valid suffix.
+
+func ExampleDefaultBuf() {} // OK because refers to top-level identifier.
+
+func ExampleBuf_Reset() bool { return true } // ERROR "ExampleBuf_Reset should return nothing"
+
+func ExampleBuf_Len(i int) {} // ERROR "ExampleBuf_Len should be niladic"
+
+// "Puffer" is German for "Buffer".
+
+func ExamplePuffer() // ERROR "ExamplePuffer refers to unknown identifier: Puffer"
+
+func ExamplePuffer_Append() // ERROR "ExamplePuffer_Append refers to unknown identifier: Puffer"
+
+func ExamplePuffer_suffix() // ERROR "ExamplePuffer_suffix refers to unknown identifier: Puffer"
diff --git a/go/src/golang.org/x/tools/cmd/vet/testdata/incomplete/examples_test.go b/go/src/golang.org/x/tools/cmd/vet/testdata/incomplete/examples_test.go
new file mode 100644
index 0000000..445502b
--- /dev/null
+++ b/go/src/golang.org/x/tools/cmd/vet/testdata/incomplete/examples_test.go
@@ -0,0 +1,33 @@
+// Test of examples.
+
+package testdata
+
+func Example() {} // OK because is package-level.
+
+func Example_suffix() // OK because refers to suffix annotation.
+
+func Example_BadSuffix() // OK because non-test package was excluded.  No false positives wanted.
+
+func ExampleBuf() // OK because non-test package was excluded.  No false positives wanted.
+
+func ExampleBuf_Append() {} // OK because non-test package was excluded.  No false positives wanted.
+
+func ExampleBuf_Clear() {} // OK because non-test package was excluded.  No false positives wanted.
+
+func ExampleBuf_suffix() {} // OK because refers to suffix annotation.
+
+func ExampleBuf_Append_Bad() {} // OK because non-test package was excluded.  No false positives wanted.
+
+func ExampleBuf_Append_suffix() {} // OK because refers to known method with valid suffix.
+
+func ExampleBuf_Reset() bool { return true } // ERROR "ExampleBuf_Reset should return nothing"
+
+func ExampleBuf_Len(i int) {} // ERROR "ExampleBuf_Len should be niladic"
+
+// "Puffer" is German for "Buffer".
+
+func ExamplePuffer() // OK because non-test package was excluded.  No false positives wanted.
+
+func ExamplePuffer_Append() // OK because non-test package was excluded.  No false positives wanted.
+
+func ExamplePuffer_suffix() // OK because non-test package was excluded.  No false positives wanted.
diff --git a/go/src/golang.org/x/tools/cmd/vet/vet_test.go b/go/src/golang.org/x/tools/cmd/vet/vet_test.go
index 6a09e3d..7508193 100644
--- a/go/src/golang.org/x/tools/cmd/vet/vet_test.go
+++ b/go/src/golang.org/x/tools/cmd/vet/vet_test.go
@@ -22,23 +22,46 @@
 	binary  = "testvet.exe"
 )
 
+func CanRun(t *testing.T) bool {
+	// Plan 9 and Windows systems can't be guaranteed to have Perl and so can't run errchk.
+	switch runtime.GOOS {
+	case "plan9", "windows":
+		t.Skip("skipping test; no Perl on %q", runtime.GOOS)
+		return false
+	}
+	return true
+}
+
+func Build(t *testing.T) {
+	// go build
+	cmd := exec.Command("go", "build", "-o", binary)
+	run(cmd, t)
+}
+
+func Vet(t *testing.T, files []string) {
+	errchk := filepath.Join(runtime.GOROOT(), "test", "errchk")
+	flags := []string{
+		"./" + binary,
+		"-printfuncs=Warn:1,Warnf:1",
+		"-test", // TODO: Delete once -shadow is part of -all.
+	}
+	cmd := exec.Command(errchk, append(flags, files...)...)
+	if !run(cmd, t) {
+		t.Fatal("vet command failed")
+	}
+}
+
 // Run this shell script, but do it in Go so it can be run by "go test".
 // 	go build -o testvet
 // 	$(GOROOT)/test/errchk ./testvet -shadow -printfuncs='Warn:1,Warnf:1' testdata/*.go testdata/*.s
 // 	rm testvet
 //
+
 func TestVet(t *testing.T) {
-	// Plan 9 and Windows systems can't be guaranteed to have Perl and so can't run errchk.
-	switch runtime.GOOS {
-	case "plan9", "windows":
-		t.Skip("skipping test; no Perl on %q", runtime.GOOS)
+	if !CanRun(t) {
+		t.Skip("cannot run on this environment")
 	}
-
-	// go build
-	cmd := exec.Command("go", "build", "-o", binary)
-	run(cmd, t)
-
-	// defer removal of vet
+	Build(t)
 	defer os.Remove(binary)
 
 	// errchk ./testvet
@@ -51,16 +74,29 @@
 		t.Fatal(err)
 	}
 	files := append(gos, asms...)
-	errchk := filepath.Join(runtime.GOROOT(), "test", "errchk")
-	flags := []string{
-		"./" + binary,
-		"-printfuncs=Warn:1,Warnf:1",
-		"-test", // TODO: Delete once -shadow is part of -all.
+	Vet(t, files)
+}
+
+func TestDivergentPackagesExamples(t *testing.T) {
+	if !CanRun(t) {
+		t.Skip("cannot run on this environment")
 	}
-	cmd = exec.Command(errchk, append(flags, files...)...)
-	if !run(cmd, t) {
-		t.Fatal("vet command failed")
+	Build(t)
+	defer os.Remove(binary)
+
+	// errchk ./testvet
+	Vet(t, []string{"testdata/divergent/buf.go", "testdata/divergent/buf_test.go"})
+}
+
+func TestIncompleteExamples(t *testing.T) {
+	if !CanRun(t) {
+		t.Skip("cannot run on this environment")
 	}
+	Build(t)
+	defer os.Remove(binary)
+
+	// errchk ./testvet
+	Vet(t, []string{"testdata/incomplete/examples_test.go"})
 }
 
 func run(c *exec.Cmd, t *testing.T) bool {
@@ -83,7 +119,6 @@
 	cmd := exec.Command("go", "build", "-o", binary)
 	run(cmd, t)
 
-	// defer removal of vet
 	defer os.Remove(binary)
 
 	args := []string{
diff --git a/go/src/golang.org/x/tools/cmd/vet/whitelist/whitelist.go b/go/src/golang.org/x/tools/cmd/vet/whitelist/whitelist.go
index 76a3198..d6f0dce 100644
--- a/go/src/golang.org/x/tools/cmd/vet/whitelist/whitelist.go
+++ b/go/src/golang.org/x/tools/cmd/vet/whitelist/whitelist.go
@@ -50,11 +50,4 @@
 	"image.Point":         true,
 	"image.Rectangle":     true,
 	"image.Uniform":       true,
-
-	// Vanadium named slice types.
-	//
-	// NOTE: These types were added to avoid spurious go vet warnings.
-	// Make sure to add them back if you update the source.
-	"v.io/v23/uniqueid.Id":     true,
-	"v.io/v23/rpc.ListenAddrs": true,
 }
diff --git a/go/src/golang.org/x/tools/container/intsets/popcnt_amd64.go b/go/src/golang.org/x/tools/container/intsets/popcnt_amd64.go
new file mode 100644
index 0000000..99ea813
--- /dev/null
+++ b/go/src/golang.org/x/tools/container/intsets/popcnt_amd64.go
@@ -0,0 +1,20 @@
+// Copyright 2015 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.
+
+// +build amd64,!appengine,!gccgo
+
+package intsets
+
+func popcnt(x word) int
+func havePOPCNT() bool
+
+var hasPOPCNT = havePOPCNT()
+
+// popcount returns the population count (number of set bits) of x.
+func popcount(x word) int {
+	if hasPOPCNT {
+		return popcnt(x)
+	}
+	return popcountTable(x) // faster than Hacker's Delight
+}
diff --git a/go/src/golang.org/x/tools/container/intsets/popcnt_amd64.s b/go/src/golang.org/x/tools/container/intsets/popcnt_amd64.s
new file mode 100644
index 0000000..05c3d6f
--- /dev/null
+++ b/go/src/golang.org/x/tools/container/intsets/popcnt_amd64.s
@@ -0,0 +1,30 @@
+// Copyright 2015 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.
+
+// +build amd64,!appengine,!gccgo
+
+#include "textflag.h"
+
+// func havePOPCNT() bool
+TEXT ·havePOPCNT(SB),4,$0
+	MOVQ	$1, AX
+	CPUID
+	SHRQ	$23, CX
+	ANDQ	$1, CX
+	MOVB	CX, ret+0(FP)
+	RET
+
+// func popcnt(word) int
+TEXT ·popcnt(SB),NOSPLIT,$0-8
+	XORQ	AX, AX
+	MOVQ	x+0(FP), SI
+	// POPCNT (SI), AX is not recognized by Go assembler,
+	// so we assemble it ourselves.
+	BYTE	$0xf3
+	BYTE	$0x48
+	BYTE	$0x0f
+	BYTE	$0xb8
+	BYTE	$0xc6
+	MOVQ	AX, ret+8(FP)
+	RET
diff --git a/go/src/golang.org/x/tools/container/intsets/popcnt_gccgo.go b/go/src/golang.org/x/tools/container/intsets/popcnt_gccgo.go
new file mode 100644
index 0000000..82a8875
--- /dev/null
+++ b/go/src/golang.org/x/tools/container/intsets/popcnt_gccgo.go
@@ -0,0 +1,9 @@
+// Copyright 2015 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.
+
+// +build gccgo
+
+package intsets
+
+func popcount(x word) int
diff --git a/go/src/golang.org/x/tools/container/intsets/popcnt_gccgo_c.c b/go/src/golang.org/x/tools/container/intsets/popcnt_gccgo_c.c
new file mode 100644
index 0000000..08abb32
--- /dev/null
+++ b/go/src/golang.org/x/tools/container/intsets/popcnt_gccgo_c.c
@@ -0,0 +1,19 @@
+// Copyright 2015 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.
+
+// +build gccgo
+
+#include <errno.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#define _STRINGIFY2_(x) #x
+#define _STRINGIFY_(x) _STRINGIFY2_(x)
+#define GOSYM_PREFIX _STRINGIFY_(__USER_LABEL_PREFIX__)
+
+extern intptr_t popcount(uintptr_t x) __asm__(GOSYM_PREFIX GOPKGPATH ".popcount");
+
+intptr_t popcount(uintptr_t x) {
+	return __builtin_popcountl((unsigned long)(x));
+}
diff --git a/go/src/golang.org/x/tools/container/intsets/popcnt_generic.go b/go/src/golang.org/x/tools/container/intsets/popcnt_generic.go
new file mode 100644
index 0000000..3985a1d
--- /dev/null
+++ b/go/src/golang.org/x/tools/container/intsets/popcnt_generic.go
@@ -0,0 +1,33 @@
+// Copyright 2015 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.
+
+// +build !amd64 appengine
+// +build !gccgo
+
+package intsets
+
+import "runtime"
+
+// We compared three algorithms---Hacker's Delight, table lookup,
+// and AMD64's SSE4.1 hardware POPCNT---on a 2.67GHz Xeon X5550.
+//
+// % GOARCH=amd64 go test -run=NONE -bench=Popcount
+// POPCNT               5.12 ns/op
+// Table                8.53 ns/op
+// HackersDelight       9.96 ns/op
+//
+// % GOARCH=386 go test -run=NONE -bench=Popcount
+// Table               10.4  ns/op
+// HackersDelight       5.23 ns/op
+//
+// (AMD64's ABM1 hardware supports ntz and nlz too,
+// but they aren't critical.)
+
+// popcount returns the population count (number of set bits) of x.
+func popcount(x word) int {
+	if runtime.GOARCH == "386" {
+		return popcountHD(uint32(x))
+	}
+	return popcountTable(x)
+}
diff --git a/go/src/golang.org/x/tools/container/intsets/util.go b/go/src/golang.org/x/tools/container/intsets/util.go
index 76e682c..dd1db86 100644
--- a/go/src/golang.org/x/tools/container/intsets/util.go
+++ b/go/src/golang.org/x/tools/container/intsets/util.go
@@ -4,6 +4,16 @@
 
 package intsets
 
+// From Hacker's Delight, fig 5.2.
+func popcountHD(x uint32) int {
+	x -= (x >> 1) & 0x55555555
+	x = (x & 0x33333333) + ((x >> 2) & 0x33333333)
+	x = (x + (x >> 4)) & 0x0f0f0f0f
+	x = x + (x >> 8)
+	x = x + (x >> 16)
+	return int(x & 0x0000003f)
+}
+
 var a [1 << 8]byte
 
 func init() {
@@ -18,8 +28,7 @@
 	}
 }
 
-// popcount returns the population count (number of set bits) of x.
-func popcount(x word) int {
+func popcountTable(x word) int {
 	return int(a[byte(x>>(0*8))] +
 		a[byte(x>>(1*8))] +
 		a[byte(x>>(2*8))] +
diff --git a/go/src/golang.org/x/tools/container/intsets/util_test.go b/go/src/golang.org/x/tools/container/intsets/util_test.go
index 92a4bc5..e4cc659 100644
--- a/go/src/golang.org/x/tools/container/intsets/util_test.go
+++ b/go/src/golang.org/x/tools/container/intsets/util_test.go
@@ -4,7 +4,10 @@
 
 package intsets
 
-import "testing"
+import (
+	"math/rand"
+	"testing"
+)
 
 func TestNLZ(t *testing.T) {
 	// Test the platform-specific edge case.
@@ -23,3 +26,33 @@
 
 // Backdoor for testing.
 func (s *Sparse) Check() error { return s.check() }
+
+func dumbPopcount(x word) int {
+	var popcnt int
+	for i := uint(0); i < bitsPerWord; i++ {
+		if x&(1<<i) != 0 {
+			popcnt++
+		}
+	}
+	return popcnt
+}
+
+func TestPopcount(t *testing.T) {
+	for i := 0; i < 1e5; i++ {
+		x := word(rand.Uint32())
+		if bitsPerWord == 64 {
+			x = x | (word(rand.Uint32()) << 32)
+		}
+		want := dumbPopcount(x)
+		got := popcount(x)
+		if got != want {
+			t.Errorf("popcount(%d) = %d, want %d", x, got, want)
+		}
+	}
+}
+
+func BenchmarkPopcount(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		popcount(word(i))
+	}
+}
diff --git a/go/src/golang.org/x/tools/go/buildutil/allpackages.go b/go/src/golang.org/x/tools/go/buildutil/allpackages.go
index 0f909ee..bee5fc1 100644
--- a/go/src/golang.org/x/tools/go/buildutil/allpackages.go
+++ b/go/src/golang.org/x/tools/go/buildutil/allpackages.go
@@ -18,9 +18,10 @@
 	"sync"
 )
 
-// AllPackages returns the import path of each Go package in any source
+// AllPackages returns the package path of each Go package in any source
 // directory of the specified build context (e.g. $GOROOT or an element
 // of $GOPATH).  Errors are ignored.  The results are sorted.
+// All package paths are canonical, and thus may contain "/vendor/".
 //
 // The result may include import paths for directories that contain no
 // *.go files, such as "archive" (in $GOROOT/src).
@@ -37,9 +38,10 @@
 	return list
 }
 
-// ForEachPackage calls the found function with the import path of
+// ForEachPackage calls the found function with the package path of
 // each Go package it finds in any source directory of the specified
 // build context (e.g. $GOROOT or an element of $GOPATH).
+// All package paths are canonical, and thus may contain "/vendor/".
 //
 // If the package directory exists but could not be read, the second
 // argument to the found function provides the error.
@@ -48,10 +50,6 @@
 // which must be concurrency-safe.
 //
 func ForEachPackage(ctxt *build.Context, found func(importPath string, err error)) {
-	// We use a counting semaphore to limit
-	// the number of parallel calls to ReadDir.
-	sema := make(chan bool, 20)
-
 	ch := make(chan item)
 
 	var wg sync.WaitGroup
@@ -59,7 +57,7 @@
 		root := root
 		wg.Add(1)
 		go func() {
-			allPackages(ctxt, sema, root, ch)
+			allPackages(ctxt, root, ch)
 			wg.Done()
 		}()
 	}
@@ -79,7 +77,11 @@
 	err        error // (optional)
 }
 
-func allPackages(ctxt *build.Context, sema chan bool, root string, ch chan<- item) {
+// We use a process-wide counting semaphore to limit
+// the number of parallel calls to ReadDir.
+var ioLimit = make(chan bool, 20)
+
+func allPackages(ctxt *build.Context, root string, ch chan<- item) {
 	root = filepath.Clean(root) + string(os.PathSeparator)
 
 	var wg sync.WaitGroup
@@ -100,9 +102,9 @@
 			return
 		}
 
-		sema <- true
+		ioLimit <- true
 		files, err := ReadDir(ctxt, dir)
-		<-sema
+		<-ioLimit
 		if pkg != "" || err != nil {
 			ch <- item{pkg, err}
 		}
diff --git a/go/src/golang.org/x/tools/go/buildutil/tags.go b/go/src/golang.org/x/tools/go/buildutil/tags.go
index 9735094..525ecb6 100644
--- a/go/src/golang.org/x/tools/go/buildutil/tags.go
+++ b/go/src/golang.org/x/tools/go/buildutil/tags.go
@@ -16,7 +16,7 @@
 // See $GOROOT/src/cmd/go/doc.go for description of 'go build -tags' flag.
 //
 // Example:
-//	flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsDoc)
+// 	flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsFlagDoc)
 type TagsFlag []string
 
 func (v *TagsFlag) Set(s string) error {
diff --git a/go/src/golang.org/x/tools/go/buildutil/util.go b/go/src/golang.org/x/tools/go/buildutil/util.go
index 60eeae2..0e093fc 100644
--- a/go/src/golang.org/x/tools/go/buildutil/util.go
+++ b/go/src/golang.org/x/tools/go/buildutil/util.go
@@ -15,6 +15,7 @@
 	"os"
 	"path"
 	"path/filepath"
+	"runtime"
 	"strings"
 )
 
@@ -72,7 +73,7 @@
 	// We assume that no source root (GOPATH[i] or GOROOT) contains any other.
 	for _, srcdir := range ctxt.SrcDirs() {
 		srcdirSlash := filepath.ToSlash(srcdir) + "/"
-		if strings.HasPrefix(dirSlash, srcdirSlash) {
+		if dirHasPrefix(dirSlash, srcdirSlash) {
 			importPath := dirSlash[len(srcdirSlash) : len(dirSlash)-len("/")]
 			return ctxt.Import(importPath, dir, build.FindOnly)
 		}
@@ -81,6 +82,14 @@
 	return nil, fmt.Errorf("can't find package containing %s", filename)
 }
 
+// dirHasPrefix tests whether the directory dir begins with prefix.
+func dirHasPrefix(dir, prefix string) bool {
+	if runtime.GOOS != "windows" {
+		return strings.HasPrefix(dir, prefix)
+	}
+	return len(dir) >= len(prefix) && strings.EqualFold(dir[:len(prefix)], prefix)
+}
+
 // -- Effective methods of file system interface -------------------------
 
 // (go/build.Context defines these as methods, but does not export them.)
diff --git a/go/src/golang.org/x/tools/go/buildutil/util_test.go b/go/src/golang.org/x/tools/go/buildutil/util_test.go
index 10dae17..dd55533 100644
--- a/go/src/golang.org/x/tools/go/buildutil/util_test.go
+++ b/go/src/golang.org/x/tools/go/buildutil/util_test.go
@@ -23,13 +23,14 @@
 	goroot := runtime.GOROOT()
 	gopath := filepath.SplitList(os.Getenv("GOPATH"))[0]
 
-	for _, test := range [][2]string{
+	tests := [][2]string{
 		{goroot + "/src/fmt/print.go", "fmt"},
 		{goroot + "/src/encoding/json/foo.go", "encoding/json"},
 		{goroot + "/src/encoding/missing/foo.go", "(not found)"},
 		{gopath + "/src/golang.org/x/tools/go/buildutil/util_test.go",
 			"golang.org/x/tools/go/buildutil"},
-	} {
+	}
+	for _, test := range tests {
 		file, want := test[0], test[1]
 		bp, err := buildutil.ContainingPackage(&build.Default, ".", file)
 		got := bp.ImportPath
diff --git a/go/src/golang.org/x/tools/go/buildutil/util_windows_test.go b/go/src/golang.org/x/tools/go/buildutil/util_windows_test.go
new file mode 100644
index 0000000..86fe9c7
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/buildutil/util_windows_test.go
@@ -0,0 +1,48 @@
+// Copyright 2015 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 buildutil_test
+
+import (
+	"fmt"
+	"go/build"
+	"path/filepath"
+	"runtime"
+	"strings"
+	"testing"
+
+	"golang.org/x/tools/go/buildutil"
+)
+
+func testContainingPackageCaseFold(file, want string) error {
+	bp, err := buildutil.ContainingPackage(&build.Default, ".", file)
+	if err != nil {
+		return err
+	}
+	if got := bp.ImportPath; got != want {
+		return fmt.Errorf("ContainingPackage(%q) = %s, want %s", file, got, want)
+	}
+	return nil
+}
+
+func TestContainingPackageCaseFold(t *testing.T) {
+	path := filepath.Join(runtime.GOROOT(), `src\fmt\print.go`)
+	err := testContainingPackageCaseFold(path, "fmt")
+	if err != nil {
+		t.Error(err)
+	}
+	vol := filepath.VolumeName(path)
+	if len(vol) != 2 || vol[1] != ':' {
+		t.Fatalf("GOROOT path has unexpected volume name: %v", vol)
+	}
+	rest := path[len(vol):]
+	err = testContainingPackageCaseFold(strings.ToUpper(vol)+rest, "fmt")
+	if err != nil {
+		t.Error(err)
+	}
+	err = testContainingPackageCaseFold(strings.ToLower(vol)+rest, "fmt")
+	if err != nil {
+		t.Error(err)
+	}
+}
diff --git a/go/src/golang.org/x/tools/go/callgraph/cha/cha.go b/go/src/golang.org/x/tools/go/callgraph/cha/cha.go
index fcdf686..e016649 100644
--- a/go/src/golang.org/x/tools/go/callgraph/cha/cha.go
+++ b/go/src/golang.org/x/tools/go/callgraph/cha/cha.go
@@ -1,3 +1,9 @@
+// Copyright 2014 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.
+
+// +build go1.5
+
 // Package cha computes the call graph of a Go program using the Class
 // Hierarchy Analysis (CHA) algorithm.
 //
@@ -20,10 +26,11 @@
 package cha // import "golang.org/x/tools/go/callgraph/cha"
 
 import (
+	"go/types"
+
 	"golang.org/x/tools/go/callgraph"
 	"golang.org/x/tools/go/ssa"
 	"golang.org/x/tools/go/ssa/ssautil"
-	"golang.org/x/tools/go/types"
 	"golang.org/x/tools/go/types/typeutil"
 )
 
diff --git a/go/src/golang.org/x/tools/go/callgraph/cha/cha14.go b/go/src/golang.org/x/tools/go/callgraph/cha/cha14.go
new file mode 100644
index 0000000..5a20c8b
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/callgraph/cha/cha14.go
@@ -0,0 +1,126 @@
+// Copyright 2014 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.
+
+// +build !go1.5
+
+// Package cha computes the call graph of a Go program using the Class
+// Hierarchy Analysis (CHA) algorithm.
+//
+// CHA was first described in "Optimization of Object-Oriented Programs
+// Using Static Class Hierarchy Analysis", Jeffrey Dean, David Grove,
+// and Craig Chambers, ECOOP'95.
+//
+// CHA is related to RTA (see go/callgraph/rta); the difference is that
+// CHA conservatively computes the entire "implements" relation between
+// interfaces and concrete types ahead of time, whereas RTA uses dynamic
+// programming to construct it on the fly as it encounters new functions
+// reachable from main.  CHA may thus include spurious call edges for
+// types that haven't been instantiated yet, or types that are never
+// instantiated.
+//
+// Since CHA conservatively assumes that all functions are address-taken
+// and all concrete types are put into interfaces, it is sound to run on
+// partial programs, such as libraries without a main or test function.
+//
+package cha // import "golang.org/x/tools/go/callgraph/cha"
+
+import (
+	"golang.org/x/tools/go/callgraph"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/ssa/ssautil"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/go/types/typeutil"
+)
+
+// CallGraph computes the call graph of the specified program using the
+// Class Hierarchy Analysis algorithm.
+//
+func CallGraph(prog *ssa.Program) *callgraph.Graph {
+	cg := callgraph.New(nil) // TODO(adonovan) eliminate concept of rooted callgraph
+
+	allFuncs := ssautil.AllFunctions(prog)
+
+	// funcsBySig contains all functions, keyed by signature.  It is
+	// the effective set of address-taken functions used to resolve
+	// a dynamic call of a particular signature.
+	var funcsBySig typeutil.Map // value is []*ssa.Function
+
+	// methodsByName contains all methods,
+	// grouped by name for efficient lookup.
+	methodsByName := make(map[string][]*ssa.Function)
+
+	// methodsMemo records, for every abstract method call call I.f on
+	// interface type I, the set of concrete methods C.f of all
+	// types C that satisfy interface I.
+	methodsMemo := make(map[*types.Func][]*ssa.Function)
+	lookupMethods := func(m *types.Func) []*ssa.Function {
+		methods, ok := methodsMemo[m]
+		if !ok {
+			I := m.Type().(*types.Signature).Recv().Type().Underlying().(*types.Interface)
+			for _, f := range methodsByName[m.Name()] {
+				C := f.Signature.Recv().Type() // named or *named
+				if types.Implements(C, I) {
+					methods = append(methods, f)
+				}
+			}
+			methodsMemo[m] = methods
+		}
+		return methods
+	}
+
+	for f := range allFuncs {
+		if f.Signature.Recv() == nil {
+			// Package initializers can never be address-taken.
+			if f.Name() == "init" && f.Synthetic == "package initializer" {
+				continue
+			}
+			funcs, _ := funcsBySig.At(f.Signature).([]*ssa.Function)
+			funcs = append(funcs, f)
+			funcsBySig.Set(f.Signature, funcs)
+		} else {
+			methodsByName[f.Name()] = append(methodsByName[f.Name()], f)
+		}
+	}
+
+	addEdge := func(fnode *callgraph.Node, site ssa.CallInstruction, g *ssa.Function) {
+		gnode := cg.CreateNode(g)
+		callgraph.AddEdge(fnode, site, gnode)
+	}
+
+	addEdges := func(fnode *callgraph.Node, site ssa.CallInstruction, callees []*ssa.Function) {
+		// Because every call to a highly polymorphic and
+		// frequently used abstract method such as
+		// (io.Writer).Write is assumed to call every concrete
+		// Write method in the program, the call graph can
+		// contain a lot of duplication.
+		//
+		// TODO(adonovan): opt: consider factoring the callgraph
+		// API so that the Callers component of each edge is a
+		// slice of nodes, not a singleton.
+		for _, g := range callees {
+			addEdge(fnode, site, g)
+		}
+	}
+
+	for f := range allFuncs {
+		fnode := cg.CreateNode(f)
+		for _, b := range f.Blocks {
+			for _, instr := range b.Instrs {
+				if site, ok := instr.(ssa.CallInstruction); ok {
+					call := site.Common()
+					if call.IsInvoke() {
+						addEdges(fnode, site, lookupMethods(call.Method))
+					} else if g := call.StaticCallee(); g != nil {
+						addEdge(fnode, site, g)
+					} else if _, ok := call.Value.(*ssa.Builtin); !ok {
+						callees, _ := funcsBySig.At(call.Signature()).([]*ssa.Function)
+						addEdges(fnode, site, callees)
+					}
+				}
+			}
+		}
+	}
+
+	return cg
+}
diff --git a/go/src/golang.org/x/tools/go/callgraph/cha/cha14_test.go b/go/src/golang.org/x/tools/go/callgraph/cha/cha14_test.go
new file mode 100644
index 0000000..7f0aeeb
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/callgraph/cha/cha14_test.go
@@ -0,0 +1,112 @@
+// Copyright 2014 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.
+
+// +build !go1.5
+
+// No testdata on Android.
+
+// +build !android
+
+package cha_test
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"io/ioutil"
+	"sort"
+	"strings"
+	"testing"
+
+	"golang.org/x/tools/go/callgraph"
+	"golang.org/x/tools/go/callgraph/cha"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/ssa/ssautil"
+	"golang.org/x/tools/go/types"
+)
+
+var inputs = []string{
+	"testdata/func.go",
+	"testdata/iface.go",
+	"testdata/recv.go",
+}
+
+func expectation(f *ast.File) (string, token.Pos) {
+	for _, c := range f.Comments {
+		text := strings.TrimSpace(c.Text())
+		if t := strings.TrimPrefix(text, "WANT:\n"); t != text {
+			return t, c.Pos()
+		}
+	}
+	return "", token.NoPos
+}
+
+// TestCHA runs CHA on each file in inputs, prints the dynamic edges of
+// the call graph, and compares it with the golden results embedded in
+// the WANT comment at the end of the file.
+//
+func TestCHA(t *testing.T) {
+	for _, filename := range inputs {
+		content, err := ioutil.ReadFile(filename)
+		if err != nil {
+			t.Errorf("couldn't read file '%s': %s", filename, err)
+			continue
+		}
+
+		conf := loader.Config{
+			ParserMode: parser.ParseComments,
+		}
+		f, err := conf.ParseFile(filename, content)
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+
+		want, pos := expectation(f)
+		if pos == token.NoPos {
+			t.Errorf("No WANT: comment in %s", filename)
+			continue
+		}
+
+		conf.CreateFromFiles("main", f)
+		iprog, err := conf.Load()
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+
+		prog := ssautil.CreateProgram(iprog, 0)
+		mainPkg := prog.Package(iprog.Created[0].Pkg)
+		prog.Build()
+
+		cg := cha.CallGraph(prog)
+
+		if got := printGraph(cg, mainPkg.Pkg); got != want {
+			t.Errorf("%s: got:\n%s\nwant:\n%s",
+				prog.Fset.Position(pos), got, want)
+		}
+	}
+}
+
+func printGraph(cg *callgraph.Graph, from *types.Package) string {
+	var edges []string
+	callgraph.GraphVisitEdges(cg, func(e *callgraph.Edge) error {
+		if strings.Contains(e.Description(), "dynamic") {
+			edges = append(edges, fmt.Sprintf("%s --> %s",
+				e.Caller.Func.RelString(from),
+				e.Callee.Func.RelString(from)))
+		}
+		return nil
+	})
+	sort.Strings(edges)
+
+	var buf bytes.Buffer
+	buf.WriteString("Dynamic calls\n")
+	for _, edge := range edges {
+		fmt.Fprintf(&buf, "  %s\n", edge)
+	}
+	return strings.TrimSpace(buf.String())
+}
diff --git a/go/src/golang.org/x/tools/go/callgraph/cha/cha_test.go b/go/src/golang.org/x/tools/go/callgraph/cha/cha_test.go
index 38348c0..332758c 100644
--- a/go/src/golang.org/x/tools/go/callgraph/cha/cha_test.go
+++ b/go/src/golang.org/x/tools/go/callgraph/cha/cha_test.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 // No testdata on Android.
 
 // +build !android
@@ -14,6 +16,7 @@
 	"go/ast"
 	"go/parser"
 	"go/token"
+	"go/types"
 	"io/ioutil"
 	"sort"
 	"strings"
@@ -23,7 +26,6 @@
 	"golang.org/x/tools/go/callgraph/cha"
 	"golang.org/x/tools/go/loader"
 	"golang.org/x/tools/go/ssa/ssautil"
-	"golang.org/x/tools/go/types"
 )
 
 var inputs = []string{
@@ -78,11 +80,11 @@
 
 		prog := ssautil.CreateProgram(iprog, 0)
 		mainPkg := prog.Package(iprog.Created[0].Pkg)
-		prog.BuildAll()
+		prog.Build()
 
 		cg := cha.CallGraph(prog)
 
-		if got := printGraph(cg, mainPkg.Object); got != want {
+		if got := printGraph(cg, mainPkg.Pkg); got != want {
 			t.Errorf("%s: got:\n%s\nwant:\n%s",
 				prog.Fset.Position(pos), got, want)
 		}
diff --git a/go/src/golang.org/x/tools/go/callgraph/rta/rta.go b/go/src/golang.org/x/tools/go/callgraph/rta/rta.go
index 8d22da6..7c9379d 100644
--- a/go/src/golang.org/x/tools/go/callgraph/rta/rta.go
+++ b/go/src/golang.org/x/tools/go/callgraph/rta/rta.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 // This package provides Rapid Type Analysis (RTA) for Go, a fast
 // algorithm for call graph construction and discovery of reachable code
 // (and hence dead code) and runtime types.  The algorithm was first
@@ -48,10 +50,10 @@
 
 import (
 	"fmt"
+	"go/types"
 
 	"golang.org/x/tools/go/callgraph"
 	"golang.org/x/tools/go/ssa"
-	"golang.org/x/tools/go/types"
 	"golang.org/x/tools/go/types/typeutil"
 )
 
@@ -197,7 +199,7 @@
 func (r *rta) addInvokeEdge(site ssa.CallInstruction, C types.Type) {
 	// Ascertain the concrete method of C to be called.
 	imethod := site.Common().Method
-	cmethod := r.prog.Method(r.prog.MethodSets.MethodSet(C).Lookup(imethod.Pkg(), imethod.Name()))
+	cmethod := r.prog.MethodValue(r.prog.MethodSets.MethodSet(C).Lookup(imethod.Pkg(), imethod.Name()))
 	r.addEdge(site, cmethod, true)
 }
 
@@ -361,7 +363,7 @@
 
 			if m.Exported() {
 				// Exported methods are always potentially callable via reflection.
-				r.addReachable(r.prog.Method(sel), true)
+				r.addReachable(r.prog.MethodValue(sel), true)
 			}
 		}
 
diff --git a/go/src/golang.org/x/tools/go/callgraph/rta/rta14.go b/go/src/golang.org/x/tools/go/callgraph/rta/rta14.go
new file mode 100644
index 0000000..33956ad
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/callgraph/rta/rta14.go
@@ -0,0 +1,461 @@
+// 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.
+
+// +build !go1.5
+
+// This package provides Rapid Type Analysis (RTA) for Go, a fast
+// algorithm for call graph construction and discovery of reachable code
+// (and hence dead code) and runtime types.  The algorithm was first
+// described in:
+//
+// David F. Bacon and Peter F. Sweeney. 1996.
+// Fast static analysis of C++ virtual function calls. (OOPSLA '96)
+// http://doi.acm.org/10.1145/236337.236371
+//
+// The algorithm uses dynamic programming to tabulate the cross-product
+// of the set of known "address taken" functions with the set of known
+// dynamic calls of the same type.  As each new address-taken function
+// is discovered, call graph edges are added from each known callsite,
+// and as each new call site is discovered, call graph edges are added
+// from it to each known address-taken function.
+//
+// A similar approach is used for dynamic calls via interfaces: it
+// tabulates the cross-product of the set of known "runtime types",
+// i.e. types that may appear in an interface value, or be derived from
+// one via reflection, with the set of known "invoke"-mode dynamic
+// calls.  As each new "runtime type" is discovered, call edges are
+// added from the known call sites, and as each new call site is
+// discovered, call graph edges are added to each compatible
+// method.
+//
+// In addition, we must consider all exported methods of any runtime type
+// as reachable, since they may be called via reflection.
+//
+// Each time a newly added call edge causes a new function to become
+// reachable, the code of that function is analyzed for more call sites,
+// address-taken functions, and runtime types.  The process continues
+// until a fixed point is achieved.
+//
+// The resulting call graph is less precise than one produced by pointer
+// analysis, but the algorithm is much faster.  For example, running the
+// cmd/callgraph tool on its own source takes ~2.1s for RTA and ~5.4s
+// for points-to analysis.
+//
+package rta // import "golang.org/x/tools/go/callgraph/rta"
+
+// TODO(adonovan): test it by connecting it to the interpreter and
+// replacing all "unreachable" functions by a special intrinsic, and
+// ensure that that intrinsic is never called.
+
+import (
+	"fmt"
+
+	"golang.org/x/tools/go/callgraph"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/go/types/typeutil"
+)
+
+// A Result holds the results of Rapid Type Analysis, which includes the
+// set of reachable functions/methods, runtime types, and the call graph.
+//
+type Result struct {
+	// CallGraph is the discovered callgraph.
+	// It does not include edges for calls made via reflection.
+	CallGraph *callgraph.Graph
+
+	// Reachable contains the set of reachable functions and methods.
+	// This includes exported methods of runtime types, since
+	// they may be accessed via reflection.
+	// The value indicates whether the function is address-taken.
+	//
+	// (We wrap the bool in a struct to avoid inadvertent use of
+	// "if Reachable[f] {" to test for set membership.)
+	Reachable map[*ssa.Function]struct{ AddrTaken bool }
+
+	// RuntimeTypes contains the set of types that are needed at
+	// runtime, for interfaces or reflection.
+	//
+	// The value indicates whether the type is inaccessible to reflection.
+	// Consider:
+	// 	type A struct{B}
+	// 	fmt.Println(new(A))
+	// Types *A, A and B are accessible to reflection, but the unnamed
+	// type struct{B} is not.
+	RuntimeTypes typeutil.Map
+}
+
+// Working state of the RTA algorithm.
+type rta struct {
+	result *Result
+
+	prog *ssa.Program
+
+	worklist []*ssa.Function // list of functions to visit
+
+	// addrTakenFuncsBySig contains all address-taken *Functions, grouped by signature.
+	// Keys are *types.Signature, values are map[*ssa.Function]bool sets.
+	addrTakenFuncsBySig typeutil.Map
+
+	// dynCallSites contains all dynamic "call"-mode call sites, grouped by signature.
+	// Keys are *types.Signature, values are unordered []ssa.CallInstruction.
+	dynCallSites typeutil.Map
+
+	// invokeSites contains all "invoke"-mode call sites, grouped by interface.
+	// Keys are *types.Interface (never *types.Named),
+	// Values are unordered []ssa.CallInstruction sets.
+	invokeSites typeutil.Map
+
+	// The following two maps together define the subset of the
+	// m:n "implements" relation needed by the algorithm.
+
+	// concreteTypes maps each concrete type to the set of interfaces that it implements.
+	// Keys are types.Type, values are unordered []*types.Interface.
+	// Only concrete types used as MakeInterface operands are included.
+	concreteTypes typeutil.Map
+
+	// interfaceTypes maps each interface type to
+	// the set of concrete types that implement it.
+	// Keys are *types.Interface, values are unordered []types.Type.
+	// Only interfaces used in "invoke"-mode CallInstructions are included.
+	interfaceTypes typeutil.Map
+}
+
+// addReachable marks a function as potentially callable at run-time,
+// and ensures that it gets processed.
+func (r *rta) addReachable(f *ssa.Function, addrTaken bool) {
+	reachable := r.result.Reachable
+	n := len(reachable)
+	v := reachable[f]
+	if addrTaken {
+		v.AddrTaken = true
+	}
+	reachable[f] = v
+	if len(reachable) > n {
+		// First time seeing f.  Add it to the worklist.
+		r.worklist = append(r.worklist, f)
+	}
+}
+
+// addEdge adds the specified call graph edge, and marks it reachable.
+// addrTaken indicates whether to mark the callee as "address-taken".
+func (r *rta) addEdge(site ssa.CallInstruction, callee *ssa.Function, addrTaken bool) {
+	r.addReachable(callee, addrTaken)
+
+	if g := r.result.CallGraph; g != nil {
+		if site.Parent() == nil {
+			panic(site)
+		}
+		from := g.CreateNode(site.Parent())
+		to := g.CreateNode(callee)
+		callgraph.AddEdge(from, site, to)
+	}
+}
+
+// ---------- addrTakenFuncs × dynCallSites ----------
+
+// visitAddrTakenFunc is called each time we encounter an address-taken function f.
+func (r *rta) visitAddrTakenFunc(f *ssa.Function) {
+	// Create two-level map (Signature -> Function -> bool).
+	S := f.Signature
+	funcs, _ := r.addrTakenFuncsBySig.At(S).(map[*ssa.Function]bool)
+	if funcs == nil {
+		funcs = make(map[*ssa.Function]bool)
+		r.addrTakenFuncsBySig.Set(S, funcs)
+	}
+	if !funcs[f] {
+		// First time seeing f.
+		funcs[f] = true
+
+		// If we've seen any dyncalls of this type, mark it reachable,
+		// and add call graph edges.
+		sites, _ := r.dynCallSites.At(S).([]ssa.CallInstruction)
+		for _, site := range sites {
+			r.addEdge(site, f, true)
+		}
+	}
+}
+
+// visitDynCall is called each time we encounter a dynamic "call"-mode call.
+func (r *rta) visitDynCall(site ssa.CallInstruction) {
+	S := site.Common().Signature()
+
+	// Record the call site.
+	sites, _ := r.dynCallSites.At(S).([]ssa.CallInstruction)
+	r.dynCallSites.Set(S, append(sites, site))
+
+	// For each function of signature S that we know is address-taken,
+	// mark it reachable.  We'll add the callgraph edges later.
+	funcs, _ := r.addrTakenFuncsBySig.At(S).(map[*ssa.Function]bool)
+	for g := range funcs {
+		r.addEdge(site, g, true)
+	}
+}
+
+// ---------- concrete types × invoke sites ----------
+
+// addInvokeEdge is called for each new pair (site, C) in the matrix.
+func (r *rta) addInvokeEdge(site ssa.CallInstruction, C types.Type) {
+	// Ascertain the concrete method of C to be called.
+	imethod := site.Common().Method
+	cmethod := r.prog.MethodValue(r.prog.MethodSets.MethodSet(C).Lookup(imethod.Pkg(), imethod.Name()))
+	r.addEdge(site, cmethod, true)
+}
+
+// visitInvoke is called each time the algorithm encounters an "invoke"-mode call.
+func (r *rta) visitInvoke(site ssa.CallInstruction) {
+	I := site.Common().Value.Type().Underlying().(*types.Interface)
+
+	// Record the invoke site.
+	sites, _ := r.invokeSites.At(I).([]ssa.CallInstruction)
+	r.invokeSites.Set(I, append(sites, site))
+
+	// Add callgraph edge for each existing
+	// address-taken concrete type implementing I.
+	for _, C := range r.implementations(I) {
+		r.addInvokeEdge(site, C)
+	}
+}
+
+// ---------- main algorithm ----------
+
+// visitFunc processes function f.
+func (r *rta) visitFunc(f *ssa.Function) {
+	var space [32]*ssa.Value // preallocate space for common case
+
+	for _, b := range f.Blocks {
+		for _, instr := range b.Instrs {
+			rands := instr.Operands(space[:0])
+
+			switch instr := instr.(type) {
+			case ssa.CallInstruction:
+				call := instr.Common()
+				if call.IsInvoke() {
+					r.visitInvoke(instr)
+				} else if g := call.StaticCallee(); g != nil {
+					r.addEdge(instr, g, false)
+				} else if _, ok := call.Value.(*ssa.Builtin); !ok {
+					r.visitDynCall(instr)
+				}
+
+				// Ignore the call-position operand when
+				// looking for address-taken Functions.
+				// Hack: assume this is rands[0].
+				rands = rands[1:]
+
+			case *ssa.MakeInterface:
+				r.addRuntimeType(instr.X.Type(), false)
+			}
+
+			// Process all address-taken functions.
+			for _, op := range rands {
+				if g, ok := (*op).(*ssa.Function); ok {
+					r.visitAddrTakenFunc(g)
+				}
+			}
+		}
+	}
+}
+
+// Analyze performs Rapid Type Analysis, starting at the specified root
+// functions.  It returns nil if no roots were specified.
+//
+// If buildCallGraph is true, Result.CallGraph will contain a call
+// graph; otherwise, only the other fields (reachable functions) are
+// populated.
+//
+func Analyze(roots []*ssa.Function, buildCallGraph bool) *Result {
+	if len(roots) == 0 {
+		return nil
+	}
+
+	r := &rta{
+		result: &Result{Reachable: make(map[*ssa.Function]struct{ AddrTaken bool })},
+		prog:   roots[0].Prog,
+	}
+
+	if buildCallGraph {
+		// TODO(adonovan): change callgraph API to eliminate the
+		// notion of a distinguished root node.  Some callgraphs
+		// have many roots, or none.
+		r.result.CallGraph = callgraph.New(roots[0])
+	}
+
+	hasher := typeutil.MakeHasher()
+	r.result.RuntimeTypes.SetHasher(hasher)
+	r.addrTakenFuncsBySig.SetHasher(hasher)
+	r.dynCallSites.SetHasher(hasher)
+	r.invokeSites.SetHasher(hasher)
+	r.concreteTypes.SetHasher(hasher)
+	r.interfaceTypes.SetHasher(hasher)
+
+	// Visit functions, processing their instructions, and adding
+	// new functions to the worklist, until a fixed point is
+	// reached.
+	var shadow []*ssa.Function // for efficiency, we double-buffer the worklist
+	r.worklist = append(r.worklist, roots...)
+	for len(r.worklist) > 0 {
+		shadow, r.worklist = r.worklist, shadow[:0]
+		for _, f := range shadow {
+			r.visitFunc(f)
+		}
+	}
+	return r.result
+}
+
+// interfaces(C) returns all currently known interfaces implemented by C.
+func (r *rta) interfaces(C types.Type) []*types.Interface {
+	// Ascertain set of interfaces C implements
+	// and update 'implements' relation.
+	var ifaces []*types.Interface
+	r.interfaceTypes.Iterate(func(I types.Type, concs interface{}) {
+		if I := I.(*types.Interface); types.Implements(C, I) {
+			concs, _ := concs.([]types.Type)
+			r.interfaceTypes.Set(I, append(concs, C))
+			ifaces = append(ifaces, I)
+		}
+	})
+	r.concreteTypes.Set(C, ifaces)
+	return ifaces
+}
+
+// implementations(I) returns all currently known concrete types that implement I.
+func (r *rta) implementations(I *types.Interface) []types.Type {
+	var concs []types.Type
+	if v := r.interfaceTypes.At(I); v != nil {
+		concs = v.([]types.Type)
+	} else {
+		// First time seeing this interface.
+		// Update the 'implements' relation.
+		r.concreteTypes.Iterate(func(C types.Type, ifaces interface{}) {
+			if types.Implements(C, I) {
+				ifaces, _ := ifaces.([]*types.Interface)
+				r.concreteTypes.Set(C, append(ifaces, I))
+				concs = append(concs, C)
+			}
+		})
+		r.interfaceTypes.Set(I, concs)
+	}
+	return concs
+}
+
+// addRuntimeType is called for each concrete type that can be the
+// dynamic type of some interface or reflect.Value.
+// Adapted from needMethods in go/ssa/builder.go
+//
+func (r *rta) addRuntimeType(T types.Type, skip bool) {
+	if prev, ok := r.result.RuntimeTypes.At(T).(bool); ok {
+		if skip && !prev {
+			r.result.RuntimeTypes.Set(T, skip)
+		}
+		return
+	}
+	r.result.RuntimeTypes.Set(T, skip)
+
+	mset := r.prog.MethodSets.MethodSet(T)
+
+	if _, ok := T.Underlying().(*types.Interface); !ok {
+		// T is a new concrete type.
+		for i, n := 0, mset.Len(); i < n; i++ {
+			sel := mset.At(i)
+			m := sel.Obj()
+
+			if m.Exported() {
+				// Exported methods are always potentially callable via reflection.
+				r.addReachable(r.prog.MethodValue(sel), true)
+			}
+		}
+
+		// Add callgraph edge for each existing dynamic
+		// "invoke"-mode call via that interface.
+		for _, I := range r.interfaces(T) {
+			sites, _ := r.invokeSites.At(I).([]ssa.CallInstruction)
+			for _, site := range sites {
+				r.addInvokeEdge(site, T)
+			}
+		}
+	}
+
+	// Precondition: T is not a method signature (*Signature with Recv()!=nil).
+	// Recursive case: skip => don't call makeMethods(T).
+	// Each package maintains its own set of types it has visited.
+
+	var n *types.Named
+	switch T := T.(type) {
+	case *types.Named:
+		n = T
+	case *types.Pointer:
+		n, _ = T.Elem().(*types.Named)
+	}
+	if n != nil {
+		owner := n.Obj().Pkg()
+		if owner == nil {
+			return // built-in error type
+		}
+	}
+
+	// Recursion over signatures of each exported method.
+	for i := 0; i < mset.Len(); i++ {
+		if mset.At(i).Obj().Exported() {
+			sig := mset.At(i).Type().(*types.Signature)
+			r.addRuntimeType(sig.Params(), true)  // skip the Tuple itself
+			r.addRuntimeType(sig.Results(), true) // skip the Tuple itself
+		}
+	}
+
+	switch t := T.(type) {
+	case *types.Basic:
+		// nop
+
+	case *types.Interface:
+		// nop---handled by recursion over method set.
+
+	case *types.Pointer:
+		r.addRuntimeType(t.Elem(), false)
+
+	case *types.Slice:
+		r.addRuntimeType(t.Elem(), false)
+
+	case *types.Chan:
+		r.addRuntimeType(t.Elem(), false)
+
+	case *types.Map:
+		r.addRuntimeType(t.Key(), false)
+		r.addRuntimeType(t.Elem(), false)
+
+	case *types.Signature:
+		if t.Recv() != nil {
+			panic(fmt.Sprintf("Signature %s has Recv %s", t, t.Recv()))
+		}
+		r.addRuntimeType(t.Params(), true)  // skip the Tuple itself
+		r.addRuntimeType(t.Results(), true) // skip the Tuple itself
+
+	case *types.Named:
+		// A pointer-to-named type can be derived from a named
+		// type via reflection.  It may have methods too.
+		r.addRuntimeType(types.NewPointer(T), false)
+
+		// Consider 'type T struct{S}' where S has methods.
+		// Reflection provides no way to get from T to struct{S},
+		// only to S, so the method set of struct{S} is unwanted,
+		// so set 'skip' flag during recursion.
+		r.addRuntimeType(t.Underlying(), true)
+
+	case *types.Array:
+		r.addRuntimeType(t.Elem(), false)
+
+	case *types.Struct:
+		for i, n := 0, t.NumFields(); i < n; i++ {
+			r.addRuntimeType(t.Field(i).Type(), false)
+		}
+
+	case *types.Tuple:
+		for i, n := 0, t.Len(); i < n; i++ {
+			r.addRuntimeType(t.At(i).Type(), false)
+		}
+
+	default:
+		panic(T)
+	}
+}
diff --git a/go/src/golang.org/x/tools/go/callgraph/rta/rta14_test.go b/go/src/golang.org/x/tools/go/callgraph/rta/rta14_test.go
new file mode 100644
index 0000000..fd0c71d
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/callgraph/rta/rta14_test.go
@@ -0,0 +1,141 @@
+// Copyright 2014 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.
+
+// +build !go1.5
+
+// No testdata on Android.
+
+// +build !android
+
+package rta_test
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"io/ioutil"
+	"sort"
+	"strings"
+	"testing"
+
+	"golang.org/x/tools/go/callgraph"
+	"golang.org/x/tools/go/callgraph/rta"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/ssa/ssautil"
+	"golang.org/x/tools/go/types"
+)
+
+var inputs = []string{
+	"testdata/func.go",
+	"testdata/rtype.go",
+	"testdata/iface.go",
+}
+
+func expectation(f *ast.File) (string, token.Pos) {
+	for _, c := range f.Comments {
+		text := strings.TrimSpace(c.Text())
+		if t := strings.TrimPrefix(text, "WANT:\n"); t != text {
+			return t, c.Pos()
+		}
+	}
+	return "", token.NoPos
+}
+
+// TestRTA runs RTA on each file in inputs, prints the results, and
+// compares it with the golden results embedded in the WANT comment at
+// the end of the file.
+//
+// The results string consists of two parts: the set of dynamic call
+// edges, "f --> g", one per line, and the set of reachable functions,
+// one per line.  Each set is sorted.
+//
+func TestRTA(t *testing.T) {
+	for _, filename := range inputs {
+		content, err := ioutil.ReadFile(filename)
+		if err != nil {
+			t.Errorf("couldn't read file '%s': %s", filename, err)
+			continue
+		}
+
+		conf := loader.Config{
+			ParserMode: parser.ParseComments,
+		}
+		f, err := conf.ParseFile(filename, content)
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+
+		want, pos := expectation(f)
+		if pos == token.NoPos {
+			t.Errorf("No WANT: comment in %s", filename)
+			continue
+		}
+
+		conf.CreateFromFiles("main", f)
+		iprog, err := conf.Load()
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+
+		prog := ssautil.CreateProgram(iprog, 0)
+		mainPkg := prog.Package(iprog.Created[0].Pkg)
+		prog.Build()
+
+		res := rta.Analyze([]*ssa.Function{
+			mainPkg.Func("main"),
+			mainPkg.Func("init"),
+		}, true)
+
+		if got := printResult(res, mainPkg.Pkg); got != want {
+			t.Errorf("%s: got:\n%s\nwant:\n%s",
+				prog.Fset.Position(pos), got, want)
+		}
+	}
+}
+
+func printResult(res *rta.Result, from *types.Package) string {
+	var buf bytes.Buffer
+
+	writeSorted := func(ss []string) {
+		sort.Strings(ss)
+		for _, s := range ss {
+			fmt.Fprintf(&buf, "  %s\n", s)
+		}
+	}
+
+	buf.WriteString("Dynamic calls\n")
+	var edges []string
+	callgraph.GraphVisitEdges(res.CallGraph, func(e *callgraph.Edge) error {
+		if strings.Contains(e.Description(), "dynamic") {
+			edges = append(edges, fmt.Sprintf("%s --> %s",
+				e.Caller.Func.RelString(from),
+				e.Callee.Func.RelString(from)))
+		}
+		return nil
+	})
+	writeSorted(edges)
+
+	buf.WriteString("Reachable functions\n")
+	var reachable []string
+	for f := range res.Reachable {
+		reachable = append(reachable, f.RelString(from))
+	}
+	writeSorted(reachable)
+
+	buf.WriteString("Reflect types\n")
+	var rtypes []string
+	res.RuntimeTypes.Iterate(func(key types.Type, value interface{}) {
+		if value == false { // accessible to reflection
+			rtypes = append(rtypes, types.TypeString(key, types.RelativeTo(from)))
+		}
+	})
+	writeSorted(rtypes)
+
+	return strings.TrimSpace(buf.String())
+}
diff --git a/go/src/golang.org/x/tools/go/callgraph/rta/rta_test.go b/go/src/golang.org/x/tools/go/callgraph/rta/rta_test.go
index e5aa846..5046521 100644
--- a/go/src/golang.org/x/tools/go/callgraph/rta/rta_test.go
+++ b/go/src/golang.org/x/tools/go/callgraph/rta/rta_test.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 // No testdata on Android.
 
 // +build !android
@@ -14,6 +16,7 @@
 	"go/ast"
 	"go/parser"
 	"go/token"
+	"go/types"
 	"io/ioutil"
 	"sort"
 	"strings"
@@ -24,7 +27,6 @@
 	"golang.org/x/tools/go/loader"
 	"golang.org/x/tools/go/ssa"
 	"golang.org/x/tools/go/ssa/ssautil"
-	"golang.org/x/tools/go/types"
 )
 
 var inputs = []string{
@@ -83,14 +85,14 @@
 
 		prog := ssautil.CreateProgram(iprog, 0)
 		mainPkg := prog.Package(iprog.Created[0].Pkg)
-		prog.BuildAll()
+		prog.Build()
 
 		res := rta.Analyze([]*ssa.Function{
 			mainPkg.Func("main"),
 			mainPkg.Func("init"),
 		}, true)
 
-		if got := printResult(res, mainPkg.Object); got != want {
+		if got := printResult(res, mainPkg.Pkg); got != want {
 			t.Errorf("%s: got:\n%s\nwant:\n%s",
 				prog.Fset.Position(pos), got, want)
 		}
diff --git a/go/src/golang.org/x/tools/go/callgraph/static/static_test.go b/go/src/golang.org/x/tools/go/callgraph/static/static_test.go
index 62297f7..e1bfcd7 100644
--- a/go/src/golang.org/x/tools/go/callgraph/static/static_test.go
+++ b/go/src/golang.org/x/tools/go/callgraph/static/static_test.go
@@ -63,7 +63,7 @@
 	P := iprog.Created[0].Pkg
 
 	prog := ssautil.CreateProgram(iprog, 0)
-	prog.BuildAll()
+	prog.Build()
 
 	cg := static.CallGraph(prog)
 
diff --git a/go/src/golang.org/x/tools/go/gcimporter15/bimport.go b/go/src/golang.org/x/tools/go/gcimporter15/bimport.go
new file mode 100644
index 0000000..525e12b
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/gcimporter15/bimport.go
@@ -0,0 +1,685 @@
+// Copyright 2015 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.
+
+// +build go1.5
+
+// This file is a copy of $GOROOT/src/go/internal/gcimporter/bimport.go, tagged for go1.5.
+
+package gcimporter
+
+import (
+	"encoding/binary"
+	"fmt"
+	"go/constant"
+	"go/token"
+	"go/types"
+	"sort"
+	"unicode"
+	"unicode/utf8"
+)
+
+// BImportData imports a package from the serialized package data
+// and returns the number of bytes consumed and a reference to the package.
+// If data is obviously malformed, an error is returned but in
+// general it is not recommended to call BImportData on untrusted data.
+func BImportData(imports map[string]*types.Package, data []byte, path string) (int, *types.Package, error) {
+	p := importer{
+		imports: imports,
+		data:    data,
+	}
+	p.buf = p.bufarray[:]
+
+	// read low-level encoding format
+	switch format := p.byte(); format {
+	case 'c':
+		// compact format - nothing to do
+	case 'd':
+		p.debugFormat = true
+	default:
+		return p.read, nil, fmt.Errorf("invalid encoding format in export data: got %q; want 'c' or 'd'", format)
+	}
+
+	// --- generic export data ---
+
+	if v := p.string(); v != "v0" {
+		return p.read, nil, fmt.Errorf("unknown version: %s", v)
+	}
+
+	// populate typList with predeclared "known" types
+	p.typList = append(p.typList, predeclared...)
+
+	// read package data
+	// TODO(gri) clean this up
+	i := p.tagOrIndex()
+	if i != packageTag {
+		panic(fmt.Sprintf("package tag expected, got %d", i))
+	}
+	name := p.string()
+	if s := p.string(); s != "" {
+		panic(fmt.Sprintf("empty path expected, got %s", s))
+	}
+	pkg := p.imports[path]
+	if pkg == nil {
+		pkg = types.NewPackage(path, name)
+		p.imports[path] = pkg
+	}
+	p.pkgList = append(p.pkgList, pkg)
+
+	if debug && p.pkgList[0] != pkg {
+		panic("imported packaged not found in pkgList[0]")
+	}
+
+	// read compiler-specific flags
+	p.string() // discard
+
+	// read consts
+	for i := p.int(); i > 0; i-- {
+		name := p.string()
+		typ := p.typ(nil)
+		val := p.value()
+		p.declare(types.NewConst(token.NoPos, pkg, name, typ, val))
+	}
+
+	// read vars
+	for i := p.int(); i > 0; i-- {
+		name := p.string()
+		typ := p.typ(nil)
+		p.declare(types.NewVar(token.NoPos, pkg, name, typ))
+	}
+
+	// read funcs
+	for i := p.int(); i > 0; i-- {
+		name := p.string()
+		sig := p.typ(nil).(*types.Signature)
+		p.int() // read and discard index of inlined function body
+		p.declare(types.NewFunc(token.NoPos, pkg, name, sig))
+	}
+
+	// read types
+	for i := p.int(); i > 0; i-- {
+		// name is parsed as part of named type and the
+		// type object is added to scope via respective
+		// named type
+		_ = p.typ(nil).(*types.Named)
+	}
+
+	// ignore compiler-specific import data
+
+	// complete interfaces
+	for _, typ := range p.typList {
+		if it, ok := typ.(*types.Interface); ok {
+			it.Complete()
+		}
+	}
+
+	// record all referenced packages as imports
+	list := append(([]*types.Package)(nil), p.pkgList[1:]...)
+	sort.Sort(byPath(list))
+	pkg.SetImports(list)
+
+	// package was imported completely and without errors
+	pkg.MarkComplete()
+
+	return p.read, pkg, nil
+}
+
+type importer struct {
+	imports  map[string]*types.Package
+	data     []byte
+	buf      []byte   // for reading strings
+	bufarray [64]byte // initial underlying array for buf, large enough to avoid allocation when compiling std lib
+	pkgList  []*types.Package
+	typList  []types.Type
+
+	debugFormat bool
+	read        int // bytes read
+}
+
+func (p *importer) declare(obj types.Object) {
+	if alt := p.pkgList[0].Scope().Insert(obj); alt != nil {
+		// This can only happen if we import a package a second time.
+		panic(fmt.Sprintf("%s already declared", alt.Name()))
+	}
+}
+
+func (p *importer) pkg() *types.Package {
+	// if the package was seen before, i is its index (>= 0)
+	i := p.tagOrIndex()
+	if i >= 0 {
+		return p.pkgList[i]
+	}
+
+	// otherwise, i is the package tag (< 0)
+	if i != packageTag {
+		panic(fmt.Sprintf("unexpected package tag %d", i))
+	}
+
+	// read package data
+	name := p.string()
+	path := p.string()
+
+	// we should never see an empty package name
+	if name == "" {
+		panic("empty package name in import")
+	}
+
+	// we should never see an empty import path
+	if path == "" {
+		panic("empty import path")
+	}
+
+	// if the package was imported before, use that one; otherwise create a new one
+	pkg := p.imports[path]
+	if pkg == nil {
+		pkg = types.NewPackage(path, name)
+		p.imports[path] = pkg
+	}
+	p.pkgList = append(p.pkgList, pkg)
+
+	return pkg
+}
+
+func (p *importer) record(t types.Type) {
+	p.typList = append(p.typList, t)
+}
+
+// A dddSlice is a types.Type representing ...T parameters.
+// It only appears for parameter types and does not escape
+// the importer.
+type dddSlice struct {
+	elem types.Type
+}
+
+func (t *dddSlice) Underlying() types.Type { return t }
+func (t *dddSlice) String() string         { return "..." + t.elem.String() }
+
+// parent is the package which declared the type; parent == nil means
+// the package currently imported. The parent package is needed for
+// exported struct fields and interface methods which don't contain
+// explicit package information in the export data.
+func (p *importer) typ(parent *types.Package) types.Type {
+	// if the type was seen before, i is its index (>= 0)
+	i := p.tagOrIndex()
+	if i >= 0 {
+		return p.typList[i]
+	}
+
+	// otherwise, i is the type tag (< 0)
+	switch i {
+	case namedTag:
+		// read type object
+		name := p.string()
+		parent = p.pkg()
+		scope := parent.Scope()
+		obj := scope.Lookup(name)
+
+		// if the object doesn't exist yet, create and insert it
+		if obj == nil {
+			obj = types.NewTypeName(token.NoPos, parent, name, nil)
+			scope.Insert(obj)
+		}
+
+		if _, ok := obj.(*types.TypeName); !ok {
+			panic(fmt.Sprintf("pkg = %s, name = %s => %s", parent, name, obj))
+		}
+
+		// associate new named type with obj if it doesn't exist yet
+		t0 := types.NewNamed(obj.(*types.TypeName), nil, nil)
+
+		// but record the existing type, if any
+		t := obj.Type().(*types.Named)
+		p.record(t)
+
+		// read underlying type
+		t0.SetUnderlying(p.typ(parent))
+
+		// interfaces don't have associated methods
+		if _, ok := t0.Underlying().(*types.Interface); ok {
+			return t
+		}
+
+		// read associated methods
+		for i := p.int(); i > 0; i-- {
+			name := p.string()
+			recv, _ := p.paramList() // TODO(gri) do we need a full param list for the receiver?
+			params, isddd := p.paramList()
+			result, _ := p.paramList()
+			p.int() // read and discard index of inlined function body
+			sig := types.NewSignature(recv.At(0), params, result, isddd)
+			t0.AddMethod(types.NewFunc(token.NoPos, parent, name, sig))
+		}
+
+		return t
+
+	case arrayTag:
+		t := new(types.Array)
+		p.record(t)
+
+		n := p.int64()
+		*t = *types.NewArray(p.typ(parent), n)
+		return t
+
+	case sliceTag:
+		t := new(types.Slice)
+		p.record(t)
+
+		*t = *types.NewSlice(p.typ(parent))
+		return t
+
+	case dddTag:
+		t := new(dddSlice)
+		p.record(t)
+
+		t.elem = p.typ(parent)
+		return t
+
+	case structTag:
+		t := new(types.Struct)
+		p.record(t)
+
+		n := p.int()
+		fields := make([]*types.Var, n)
+		tags := make([]string, n)
+		for i := range fields {
+			fields[i] = p.field(parent)
+			tags[i] = p.string()
+		}
+		*t = *types.NewStruct(fields, tags)
+		return t
+
+	case pointerTag:
+		t := new(types.Pointer)
+		p.record(t)
+
+		*t = *types.NewPointer(p.typ(parent))
+		return t
+
+	case signatureTag:
+		t := new(types.Signature)
+		p.record(t)
+
+		params, isddd := p.paramList()
+		result, _ := p.paramList()
+		*t = *types.NewSignature(nil, params, result, isddd)
+		return t
+
+	case interfaceTag:
+		// Create a dummy entry in the type list. This is safe because we
+		// cannot expect the interface type to appear in a cycle, as any
+		// such cycle must contain a named type which would have been
+		// first defined earlier.
+		n := len(p.typList)
+		p.record(nil)
+
+		// no embedded interfaces with gc compiler
+		if p.int() != 0 {
+			panic("unexpected embedded interface")
+		}
+
+		// read methods
+		methods := make([]*types.Func, p.int())
+		for i := range methods {
+			pkg, name := p.fieldName(parent)
+			params, isddd := p.paramList()
+			result, _ := p.paramList()
+			sig := types.NewSignature(nil, params, result, isddd)
+			methods[i] = types.NewFunc(token.NoPos, pkg, name, sig)
+		}
+
+		t := types.NewInterface(methods, nil)
+		p.typList[n] = t
+		return t
+
+	case mapTag:
+		t := new(types.Map)
+		p.record(t)
+
+		key := p.typ(parent)
+		val := p.typ(parent)
+		*t = *types.NewMap(key, val)
+		return t
+
+	case chanTag:
+		t := new(types.Chan)
+		p.record(t)
+
+		var dir types.ChanDir
+		// tag values must match the constants in cmd/compile/internal/gc/go.go
+		switch d := p.int(); d {
+		case 1 /* Crecv */ :
+			dir = types.RecvOnly
+		case 2 /* Csend */ :
+			dir = types.SendOnly
+		case 3 /* Cboth */ :
+			dir = types.SendRecv
+		default:
+			panic(fmt.Sprintf("unexpected channel dir %d", d))
+		}
+		val := p.typ(parent)
+		*t = *types.NewChan(dir, val)
+		return t
+
+	default:
+		panic(fmt.Sprintf("unexpected type tag %d", i))
+	}
+}
+
+func (p *importer) field(parent *types.Package) *types.Var {
+	pkg, name := p.fieldName(parent)
+	typ := p.typ(parent)
+
+	anonymous := false
+	if name == "" {
+		// anonymous field - typ must be T or *T and T must be a type name
+		switch typ := deref(typ).(type) {
+		case *types.Basic: // basic types are named types
+			pkg = nil // // objects defined in Universe scope have no package
+			name = typ.Name()
+		case *types.Named:
+			name = typ.Obj().Name()
+		default:
+			panic("anonymous field expected")
+		}
+		anonymous = true
+	}
+
+	return types.NewField(token.NoPos, pkg, name, typ, anonymous)
+}
+
+func (p *importer) fieldName(parent *types.Package) (*types.Package, string) {
+	pkg := parent
+	if pkg == nil {
+		// use the imported package instead
+		pkg = p.pkgList[0]
+	}
+	name := p.string()
+	if name == "" {
+		return pkg, "" // anonymous
+	}
+	if name == "?" || name != "_" && !exported(name) {
+		// explicitly qualified field
+		if name == "?" {
+			name = "" // anonymous
+		}
+		pkg = p.pkg()
+	}
+	return pkg, name
+}
+
+func (p *importer) paramList() (*types.Tuple, bool) {
+	n := p.int()
+	if n == 0 {
+		return nil, false
+	}
+	// negative length indicates unnamed parameters
+	named := true
+	if n < 0 {
+		n = -n
+		named = false
+	}
+	// n > 0
+	params := make([]*types.Var, n)
+	isddd := false
+	for i := range params {
+		params[i], isddd = p.param(named)
+	}
+	return types.NewTuple(params...), isddd
+}
+
+func (p *importer) param(named bool) (*types.Var, bool) {
+	t := p.typ(nil)
+	td, isddd := t.(*dddSlice)
+	if isddd {
+		t = types.NewSlice(td.elem)
+	}
+
+	var name string
+	if named {
+		name = p.string()
+		if name == "" {
+			panic("expected named parameter")
+		}
+	}
+
+	// read and discard compiler-specific info
+	p.string()
+
+	return types.NewVar(token.NoPos, nil, name, t), isddd
+}
+
+func exported(name string) bool {
+	ch, _ := utf8.DecodeRuneInString(name)
+	return unicode.IsUpper(ch)
+}
+
+func (p *importer) value() constant.Value {
+	switch tag := p.tagOrIndex(); tag {
+	case falseTag:
+		return constant.MakeBool(false)
+	case trueTag:
+		return constant.MakeBool(true)
+	case int64Tag:
+		return constant.MakeInt64(p.int64())
+	case floatTag:
+		return p.float()
+	case complexTag:
+		re := p.float()
+		im := p.float()
+		return constant.BinaryOp(re, token.ADD, constant.MakeImag(im))
+	case stringTag:
+		return constant.MakeString(p.string())
+	default:
+		panic(fmt.Sprintf("unexpected value tag %d", tag))
+	}
+}
+
+func (p *importer) float() constant.Value {
+	sign := p.int()
+	if sign == 0 {
+		return constant.MakeInt64(0)
+	}
+
+	exp := p.int()
+	mant := []byte(p.string()) // big endian
+
+	// remove leading 0's if any
+	for len(mant) > 0 && mant[0] == 0 {
+		mant = mant[1:]
+	}
+
+	// convert to little endian
+	// TODO(gri) go/constant should have a more direct conversion function
+	//           (e.g., once it supports a big.Float based implementation)
+	for i, j := 0, len(mant)-1; i < j; i, j = i+1, j-1 {
+		mant[i], mant[j] = mant[j], mant[i]
+	}
+
+	// adjust exponent (constant.MakeFromBytes creates an integer value,
+	// but mant represents the mantissa bits such that 0.5 <= mant < 1.0)
+	exp -= len(mant) << 3
+	if len(mant) > 0 {
+		for msd := mant[len(mant)-1]; msd&0x80 == 0; msd <<= 1 {
+			exp++
+		}
+	}
+
+	x := constant.MakeFromBytes(mant)
+	switch {
+	case exp < 0:
+		d := constant.Shift(constant.MakeInt64(1), token.SHL, uint(-exp))
+		x = constant.BinaryOp(x, token.QUO, d)
+	case exp > 0:
+		x = constant.Shift(x, token.SHL, uint(exp))
+	}
+
+	if sign < 0 {
+		x = constant.UnaryOp(token.SUB, x, 0)
+	}
+	return x
+}
+
+// ----------------------------------------------------------------------------
+// Low-level decoders
+
+func (p *importer) tagOrIndex() int {
+	if p.debugFormat {
+		p.marker('t')
+	}
+
+	return int(p.rawInt64())
+}
+
+func (p *importer) int() int {
+	x := p.int64()
+	if int64(int(x)) != x {
+		panic("exported integer too large")
+	}
+	return int(x)
+}
+
+func (p *importer) int64() int64 {
+	if p.debugFormat {
+		p.marker('i')
+	}
+
+	return p.rawInt64()
+}
+
+func (p *importer) string() string {
+	if p.debugFormat {
+		p.marker('s')
+	}
+
+	if n := int(p.rawInt64()); n > 0 {
+		if cap(p.buf) < n {
+			p.buf = make([]byte, n)
+		} else {
+			p.buf = p.buf[:n]
+		}
+		for i := 0; i < n; i++ {
+			p.buf[i] = p.byte()
+		}
+		return string(p.buf)
+	}
+
+	return ""
+}
+
+func (p *importer) marker(want byte) {
+	if got := p.byte(); got != want {
+		panic(fmt.Sprintf("incorrect marker: got %c; want %c (pos = %d)", got, want, p.read))
+	}
+
+	pos := p.read
+	if n := int(p.rawInt64()); n != pos {
+		panic(fmt.Sprintf("incorrect position: got %d; want %d", n, pos))
+	}
+}
+
+// rawInt64 should only be used by low-level decoders
+func (p *importer) rawInt64() int64 {
+	i, err := binary.ReadVarint(p)
+	if err != nil {
+		panic(fmt.Sprintf("read error: %v", err))
+	}
+	return i
+}
+
+// needed for binary.ReadVarint in rawInt64
+func (p *importer) ReadByte() (byte, error) {
+	return p.byte(), nil
+}
+
+// byte is the bottleneck interface for reading p.data.
+// It unescapes '|' 'S' to '$' and '|' '|' to '|'.
+func (p *importer) byte() byte {
+	b := p.data[0]
+	r := 1
+	if b == '|' {
+		b = p.data[1]
+		r = 2
+		switch b {
+		case 'S':
+			b = '$'
+		case '|':
+			// nothing to do
+		default:
+			panic("unexpected escape sequence in export data")
+		}
+	}
+	p.data = p.data[r:]
+	p.read += r
+	return b
+
+}
+
+// ----------------------------------------------------------------------------
+// Export format
+
+// Tags. Must be < 0.
+const (
+	// Packages
+	packageTag = -(iota + 1)
+
+	// Types
+	namedTag
+	arrayTag
+	sliceTag
+	dddTag
+	structTag
+	pointerTag
+	signatureTag
+	interfaceTag
+	mapTag
+	chanTag
+
+	// Values
+	falseTag
+	trueTag
+	int64Tag
+	floatTag
+	fractionTag // not used by gc
+	complexTag
+	stringTag
+)
+
+var predeclared = []types.Type{
+	// basic types
+	types.Typ[types.Bool],
+	types.Typ[types.Int],
+	types.Typ[types.Int8],
+	types.Typ[types.Int16],
+	types.Typ[types.Int32],
+	types.Typ[types.Int64],
+	types.Typ[types.Uint],
+	types.Typ[types.Uint8],
+	types.Typ[types.Uint16],
+	types.Typ[types.Uint32],
+	types.Typ[types.Uint64],
+	types.Typ[types.Uintptr],
+	types.Typ[types.Float32],
+	types.Typ[types.Float64],
+	types.Typ[types.Complex64],
+	types.Typ[types.Complex128],
+	types.Typ[types.String],
+
+	// aliases
+	types.Universe.Lookup("byte").Type(),
+	types.Universe.Lookup("rune").Type(),
+
+	// error
+	types.Universe.Lookup("error").Type(),
+
+	// untyped types
+	types.Typ[types.UntypedBool],
+	types.Typ[types.UntypedInt],
+	types.Typ[types.UntypedRune],
+	types.Typ[types.UntypedFloat],
+	types.Typ[types.UntypedComplex],
+	types.Typ[types.UntypedString],
+	types.Typ[types.UntypedNil],
+
+	// package unsafe
+	types.Typ[types.UnsafePointer],
+}
diff --git a/go/src/golang.org/x/tools/go/gcimporter15/exportdata.go b/go/src/golang.org/x/tools/go/gcimporter15/exportdata.go
new file mode 100644
index 0000000..4e1d1e4
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/gcimporter15/exportdata.go
@@ -0,0 +1,115 @@
+// Copyright 2011 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.
+
+// +build go1.5
+
+// This file is a copy of $GOROOT/src/go/internal/gcimporter/exportdata.go, tagged for go1.5.
+
+// This file implements FindExportData.
+
+package gcimporter
+
+import (
+	"bufio"
+	"errors"
+	"fmt"
+	"io"
+	"strconv"
+	"strings"
+)
+
+func readGopackHeader(r *bufio.Reader) (name string, size int, err error) {
+	// See $GOROOT/include/ar.h.
+	hdr := make([]byte, 16+12+6+6+8+10+2)
+	_, err = io.ReadFull(r, hdr)
+	if err != nil {
+		return
+	}
+	// leave for debugging
+	if false {
+		fmt.Printf("header: %s", hdr)
+	}
+	s := strings.TrimSpace(string(hdr[16+12+6+6+8:][:10]))
+	size, err = strconv.Atoi(s)
+	if err != nil || hdr[len(hdr)-2] != '`' || hdr[len(hdr)-1] != '\n' {
+		err = errors.New("invalid archive header")
+		return
+	}
+	name = strings.TrimSpace(string(hdr[:16]))
+	return
+}
+
+// FindExportData positions the reader r at the beginning of the
+// export data section of an underlying GC-created object/archive
+// file by reading from it. The reader must be positioned at the
+// start of the file before calling this function. The hdr result
+// is the string before the export data, either "$$" or "$$B".
+//
+func FindExportData(r *bufio.Reader) (hdr string, err error) {
+	// Read first line to make sure this is an object file.
+	line, err := r.ReadSlice('\n')
+	if err != nil {
+		return
+	}
+
+	if string(line) == "!<arch>\n" {
+		// Archive file. Scan to __.PKGDEF.
+		var name string
+		var size int
+		if name, size, err = readGopackHeader(r); err != nil {
+			return
+		}
+
+		// Optional leading __.GOSYMDEF or __.SYMDEF.
+		// Read and discard.
+		if name == "__.SYMDEF" || name == "__.GOSYMDEF" {
+			const block = 4096
+			tmp := make([]byte, block)
+			for size > 0 {
+				n := size
+				if n > block {
+					n = block
+				}
+				if _, err = io.ReadFull(r, tmp[:n]); err != nil {
+					return
+				}
+				size -= n
+			}
+
+			if name, _, err = readGopackHeader(r); err != nil {
+				return
+			}
+		}
+
+		// First real entry should be __.PKGDEF.
+		if name != "__.PKGDEF" {
+			err = errors.New("go archive is missing __.PKGDEF")
+			return
+		}
+
+		// Read first line of __.PKGDEF data, so that line
+		// is once again the first line of the input.
+		if line, err = r.ReadSlice('\n'); err != nil {
+			return
+		}
+	}
+
+	// Now at __.PKGDEF in archive or still at beginning of file.
+	// Either way, line should begin with "go object ".
+	if !strings.HasPrefix(string(line), "go object ") {
+		err = errors.New("not a go object file")
+		return
+	}
+
+	// Skip over object header to export data.
+	// Begins after first line starting with $$.
+	for line[0] != '$' {
+		if line, err = r.ReadSlice('\n'); err != nil {
+			return
+		}
+	}
+	hdr = string(line)
+
+	return
+}
diff --git a/go/src/golang.org/x/tools/go/gcimporter15/gcimporter.go b/go/src/golang.org/x/tools/go/gcimporter15/gcimporter.go
new file mode 100644
index 0000000..5bc5696
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/gcimporter15/gcimporter.go
@@ -0,0 +1,1025 @@
+// Copyright 2011 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.
+
+// +build go1.5
+
+// This file is a copy of $GOROOT/src/go/internal/gcimporter/gcimporter.go, tagged for go1.5,
+// and minimally adjusted to make it build.
+
+// Package gcimporter15 provides various functions for reading
+// gc-generated object files that can be used to implement the
+// Importer interface defined by the Go 1.5 standard library package.
+//
+// This package serves as a stop-gap for missing features in the
+// standard library's go/importer package, specifically customizable
+// package data lookup. This package should be deleted once that
+// functionality becomes available in the standard library.
+package gcimporter // import "golang.org/x/tools/go/gcimporter15"
+
+import (
+	"bufio"
+	"errors"
+	"fmt"
+	"go/build"
+	exact "go/constant"
+	"go/token"
+	"go/types"
+	"io"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"sort"
+	"strconv"
+	"strings"
+	"text/scanner"
+)
+
+// debugging/development support
+const debug = false
+
+var pkgExts = [...]string{".a", ".o"}
+
+// FindPkg returns the filename and unique package id for an import
+// path based on package information provided by build.Import (using
+// the build.Default build.Context).
+// If no file was found, an empty filename is returned.
+//
+func FindPkg(path, srcDir string) (filename, id string) {
+	if path == "" {
+		return
+	}
+
+	var noext string
+	switch {
+	default:
+		// "x" -> "$GOPATH/pkg/$GOOS_$GOARCH/x.ext", "x"
+		// Don't require the source files to be present.
+		bp, _ := build.Import(path, srcDir, build.FindOnly|build.AllowBinary)
+		if bp.PkgObj == "" {
+			return
+		}
+		noext = strings.TrimSuffix(bp.PkgObj, ".a")
+		id = bp.ImportPath
+
+	case build.IsLocalImport(path):
+		// "./x" -> "/this/directory/x.ext", "/this/directory/x"
+		noext = filepath.Join(srcDir, path)
+		id = noext
+
+	case filepath.IsAbs(path):
+		// for completeness only - go/build.Import
+		// does not support absolute imports
+		// "/x" -> "/x.ext", "/x"
+		noext = path
+		id = path
+	}
+
+	if false { // for debugging
+		if path != id {
+			fmt.Printf("%s -> %s\n", path, id)
+		}
+	}
+
+	// try extensions
+	for _, ext := range pkgExts {
+		filename = noext + ext
+		if f, err := os.Stat(filename); err == nil && !f.IsDir() {
+			return
+		}
+	}
+
+	filename = "" // not found
+	return
+}
+
+// ImportData imports a package by reading the gc-generated export data,
+// adds the corresponding package object to the packages map indexed by id,
+// and returns the object.
+//
+// The packages map must contains all packages already imported. The data
+// reader position must be the beginning of the export data section. The
+// filename is only used in error messages.
+//
+// If packages[id] contains the completely imported package, that package
+// can be used directly, and there is no need to call this function (but
+// there is also no harm but for extra time used).
+//
+func ImportData(packages map[string]*types.Package, filename, id string, data io.Reader) (pkg *types.Package, err error) {
+	// support for parser error handling
+	defer func() {
+		switch r := recover().(type) {
+		case nil:
+			// nothing to do
+		case importError:
+			err = r
+		default:
+			panic(r) // internal error
+		}
+	}()
+
+	var p parser
+	p.init(filename, id, data, packages)
+	pkg = p.parseExport()
+
+	return
+}
+
+// Import imports a gc-generated package given its import path and srcDir, adds
+// the corresponding package object to the packages map, and returns the object.
+// The packages map must contain all packages already imported.
+//
+func Import(packages map[string]*types.Package, path, srcDir string) (pkg *types.Package, err error) {
+	filename, id := FindPkg(path, srcDir)
+	if filename == "" {
+		if path == "unsafe" {
+			return types.Unsafe, nil
+		}
+		err = fmt.Errorf("can't find import: %s", id)
+		return
+	}
+
+	// no need to re-import if the package was imported completely before
+	if pkg = packages[id]; pkg != nil && pkg.Complete() {
+		return
+	}
+
+	// open file
+	f, err := os.Open(filename)
+	if err != nil {
+		return
+	}
+	defer func() {
+		f.Close()
+		if err != nil {
+			// add file name to error
+			err = fmt.Errorf("reading export data: %s: %v", filename, err)
+		}
+	}()
+
+	var hdr string
+	buf := bufio.NewReader(f)
+	if hdr, err = FindExportData(buf); err != nil {
+		return
+	}
+
+	switch hdr {
+	case "$$\n":
+		return ImportData(packages, filename, id, buf)
+	case "$$B\n":
+		var data []byte
+		data, err = ioutil.ReadAll(buf)
+		if err == nil {
+			_, pkg, err = BImportData(packages, data, path)
+			return
+		}
+	default:
+		err = fmt.Errorf("unknown export data header: %q", hdr)
+	}
+
+	return
+}
+
+// ----------------------------------------------------------------------------
+// Parser
+
+// TODO(gri) Imported objects don't have position information.
+//           Ideally use the debug table line info; alternatively
+//           create some fake position (or the position of the
+//           import). That way error messages referring to imported
+//           objects can print meaningful information.
+
+// parser parses the exports inside a gc compiler-produced
+// object/archive file and populates its scope with the results.
+type parser struct {
+	scanner    scanner.Scanner
+	tok        rune                      // current token
+	lit        string                    // literal string; only valid for Ident, Int, String tokens
+	id         string                    // package id of imported package
+	sharedPkgs map[string]*types.Package // package id -> package object (across importer)
+	localPkgs  map[string]*types.Package // package id -> package object (just this package)
+}
+
+func (p *parser) init(filename, id string, src io.Reader, packages map[string]*types.Package) {
+	p.scanner.Init(src)
+	p.scanner.Error = func(_ *scanner.Scanner, msg string) { p.error(msg) }
+	p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanChars | scanner.ScanStrings | scanner.ScanComments | scanner.SkipComments
+	p.scanner.Whitespace = 1<<'\t' | 1<<' '
+	p.scanner.Filename = filename // for good error messages
+	p.next()
+	p.id = id
+	p.sharedPkgs = packages
+	if debug {
+		// check consistency of packages map
+		for _, pkg := range packages {
+			if pkg.Name() == "" {
+				fmt.Printf("no package name for %s\n", pkg.Path())
+			}
+		}
+	}
+}
+
+func (p *parser) next() {
+	p.tok = p.scanner.Scan()
+	switch p.tok {
+	case scanner.Ident, scanner.Int, scanner.Char, scanner.String, '·':
+		p.lit = p.scanner.TokenText()
+	default:
+		p.lit = ""
+	}
+	if debug {
+		fmt.Printf("%s: %q -> %q\n", scanner.TokenString(p.tok), p.scanner.TokenText(), p.lit)
+	}
+}
+
+func declTypeName(pkg *types.Package, name string) *types.TypeName {
+	scope := pkg.Scope()
+	if obj := scope.Lookup(name); obj != nil {
+		return obj.(*types.TypeName)
+	}
+	obj := types.NewTypeName(token.NoPos, pkg, name, nil)
+	// a named type may be referred to before the underlying type
+	// is known - set it up
+	types.NewNamed(obj, nil, nil)
+	scope.Insert(obj)
+	return obj
+}
+
+// ----------------------------------------------------------------------------
+// Error handling
+
+// Internal errors are boxed as importErrors.
+type importError struct {
+	pos scanner.Position
+	err error
+}
+
+func (e importError) Error() string {
+	return fmt.Sprintf("import error %s (byte offset = %d): %s", e.pos, e.pos.Offset, e.err)
+}
+
+func (p *parser) error(err interface{}) {
+	if s, ok := err.(string); ok {
+		err = errors.New(s)
+	}
+	// panic with a runtime.Error if err is not an error
+	panic(importError{p.scanner.Pos(), err.(error)})
+}
+
+func (p *parser) errorf(format string, args ...interface{}) {
+	p.error(fmt.Sprintf(format, args...))
+}
+
+func (p *parser) expect(tok rune) string {
+	lit := p.lit
+	if p.tok != tok {
+		p.errorf("expected %s, got %s (%s)", scanner.TokenString(tok), scanner.TokenString(p.tok), lit)
+	}
+	p.next()
+	return lit
+}
+
+func (p *parser) expectSpecial(tok string) {
+	sep := 'x' // not white space
+	i := 0
+	for i < len(tok) && p.tok == rune(tok[i]) && sep > ' ' {
+		sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token
+		p.next()
+		i++
+	}
+	if i < len(tok) {
+		p.errorf("expected %q, got %q", tok, tok[0:i])
+	}
+}
+
+func (p *parser) expectKeyword(keyword string) {
+	lit := p.expect(scanner.Ident)
+	if lit != keyword {
+		p.errorf("expected keyword %s, got %q", keyword, lit)
+	}
+}
+
+// ----------------------------------------------------------------------------
+// Qualified and unqualified names
+
+// PackageId = string_lit .
+//
+func (p *parser) parsePackageId() string {
+	id, err := strconv.Unquote(p.expect(scanner.String))
+	if err != nil {
+		p.error(err)
+	}
+	// id == "" stands for the imported package id
+	// (only known at time of package installation)
+	if id == "" {
+		id = p.id
+	}
+	return id
+}
+
+// PackageName = ident .
+//
+func (p *parser) parsePackageName() string {
+	return p.expect(scanner.Ident)
+}
+
+// dotIdentifier = ( ident | '·' ) { ident | int | '·' } .
+func (p *parser) parseDotIdent() string {
+	ident := ""
+	if p.tok != scanner.Int {
+		sep := 'x' // not white space
+		for (p.tok == scanner.Ident || p.tok == scanner.Int || p.tok == '·') && sep > ' ' {
+			ident += p.lit
+			sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token
+			p.next()
+		}
+	}
+	if ident == "" {
+		p.expect(scanner.Ident) // use expect() for error handling
+	}
+	return ident
+}
+
+// QualifiedName = "@" PackageId "." ( "?" | dotIdentifier ) .
+//
+func (p *parser) parseQualifiedName() (id, name string) {
+	p.expect('@')
+	id = p.parsePackageId()
+	p.expect('.')
+	// Per rev f280b8a485fd (10/2/2013), qualified names may be used for anonymous fields.
+	if p.tok == '?' {
+		p.next()
+	} else {
+		name = p.parseDotIdent()
+	}
+	return
+}
+
+// getPkg returns the package for a given id. If the package is
+// not found, create the package and add it to the p.localPkgs
+// and p.sharedPkgs maps. name is the (expected) name of the
+// package. If name == "", the package name is expected to be
+// set later via an import clause in the export data.
+//
+// id identifies a package, usually by a canonical package path like
+// "encoding/json" but possibly by a non-canonical import path like
+// "./json".
+//
+func (p *parser) getPkg(id, name string) *types.Package {
+	// package unsafe is not in the packages maps - handle explicitly
+	if id == "unsafe" {
+		return types.Unsafe
+	}
+
+	pkg := p.localPkgs[id]
+	if pkg == nil {
+		// first import of id from this package
+		pkg = p.sharedPkgs[id]
+		if pkg == nil {
+			// first import of id by this importer;
+			// add (possibly unnamed) pkg to shared packages
+			pkg = types.NewPackage(id, name)
+			p.sharedPkgs[id] = pkg
+		}
+		// add (possibly unnamed) pkg to local packages
+		if p.localPkgs == nil {
+			p.localPkgs = make(map[string]*types.Package)
+		}
+		p.localPkgs[id] = pkg
+	} else if name != "" {
+		// package exists already and we have an expected package name;
+		// make sure names match or set package name if necessary
+		if pname := pkg.Name(); pname == "" {
+			setName(pkg, name)
+		} else if pname != name {
+			p.errorf("%s package name mismatch: %s (given) vs %s (expected)", pname, name)
+		}
+	}
+	return pkg
+}
+
+// parseExportedName is like parseQualifiedName, but
+// the package id is resolved to an imported *types.Package.
+//
+func (p *parser) parseExportedName() (pkg *types.Package, name string) {
+	id, name := p.parseQualifiedName()
+	pkg = p.getPkg(id, "")
+	return
+}
+
+// ----------------------------------------------------------------------------
+// Types
+
+// BasicType = identifier .
+//
+func (p *parser) parseBasicType() types.Type {
+	id := p.expect(scanner.Ident)
+	obj := types.Universe.Lookup(id)
+	if obj, ok := obj.(*types.TypeName); ok {
+		return obj.Type()
+	}
+	p.errorf("not a basic type: %s", id)
+	return nil
+}
+
+// ArrayType = "[" int_lit "]" Type .
+//
+func (p *parser) parseArrayType(parent *types.Package) types.Type {
+	// "[" already consumed and lookahead known not to be "]"
+	lit := p.expect(scanner.Int)
+	p.expect(']')
+	elem := p.parseType(parent)
+	n, err := strconv.ParseInt(lit, 10, 64)
+	if err != nil {
+		p.error(err)
+	}
+	return types.NewArray(elem, n)
+}
+
+// MapType = "map" "[" Type "]" Type .
+//
+func (p *parser) parseMapType(parent *types.Package) types.Type {
+	p.expectKeyword("map")
+	p.expect('[')
+	key := p.parseType(parent)
+	p.expect(']')
+	elem := p.parseType(parent)
+	return types.NewMap(key, elem)
+}
+
+// Name = identifier | "?" | QualifiedName .
+//
+// For unqualified and anonymous names, the returned package is the parent
+// package unless parent == nil, in which case the returned package is the
+// package being imported. (The parent package is not nil if the the name
+// is an unqualified struct field or interface method name belonging to a
+// type declared in another package.)
+//
+// For qualified names, the returned package is nil (and not created if
+// it doesn't exist yet) unless materializePkg is set (which creates an
+// unnamed package with valid package path). In the latter case, a
+// subequent import clause is expected to provide a name for the package.
+//
+func (p *parser) parseName(parent *types.Package, materializePkg bool) (pkg *types.Package, name string) {
+	pkg = parent
+	if pkg == nil {
+		pkg = p.sharedPkgs[p.id]
+	}
+	switch p.tok {
+	case scanner.Ident:
+		name = p.lit
+		p.next()
+	case '?':
+		// anonymous
+		p.next()
+	case '@':
+		// exported name prefixed with package path
+		pkg = nil
+		var id string
+		id, name = p.parseQualifiedName()
+		if materializePkg {
+			pkg = p.getPkg(id, "")
+		}
+	default:
+		p.error("name expected")
+	}
+	return
+}
+
+func deref(typ types.Type) types.Type {
+	if p, _ := typ.(*types.Pointer); p != nil {
+		return p.Elem()
+	}
+	return typ
+}
+
+// Field = Name Type [ string_lit ] .
+//
+func (p *parser) parseField(parent *types.Package) (*types.Var, string) {
+	pkg, name := p.parseName(parent, true)
+	typ := p.parseType(parent)
+	anonymous := false
+	if name == "" {
+		// anonymous field - typ must be T or *T and T must be a type name
+		switch typ := deref(typ).(type) {
+		case *types.Basic: // basic types are named types
+			pkg = nil // objects defined in Universe scope have no package
+			name = typ.Name()
+		case *types.Named:
+			name = typ.Obj().Name()
+		default:
+			p.errorf("anonymous field expected")
+		}
+		anonymous = true
+	}
+	tag := ""
+	if p.tok == scanner.String {
+		s := p.expect(scanner.String)
+		var err error
+		tag, err = strconv.Unquote(s)
+		if err != nil {
+			p.errorf("invalid struct tag %s: %s", s, err)
+		}
+	}
+	return types.NewField(token.NoPos, pkg, name, typ, anonymous), tag
+}
+
+// StructType = "struct" "{" [ FieldList ] "}" .
+// FieldList  = Field { ";" Field } .
+//
+func (p *parser) parseStructType(parent *types.Package) types.Type {
+	var fields []*types.Var
+	var tags []string
+
+	p.expectKeyword("struct")
+	p.expect('{')
+	for i := 0; p.tok != '}' && p.tok != scanner.EOF; i++ {
+		if i > 0 {
+			p.expect(';')
+		}
+		fld, tag := p.parseField(parent)
+		if tag != "" && tags == nil {
+			tags = make([]string, i)
+		}
+		if tags != nil {
+			tags = append(tags, tag)
+		}
+		fields = append(fields, fld)
+	}
+	p.expect('}')
+
+	return types.NewStruct(fields, tags)
+}
+
+// Parameter = ( identifier | "?" ) [ "..." ] Type [ string_lit ] .
+//
+func (p *parser) parseParameter() (par *types.Var, isVariadic bool) {
+	_, name := p.parseName(nil, false)
+	// remove gc-specific parameter numbering
+	if i := strings.Index(name, "·"); i >= 0 {
+		name = name[:i]
+	}
+	if p.tok == '.' {
+		p.expectSpecial("...")
+		isVariadic = true
+	}
+	typ := p.parseType(nil)
+	if isVariadic {
+		typ = types.NewSlice(typ)
+	}
+	// ignore argument tag (e.g. "noescape")
+	if p.tok == scanner.String {
+		p.next()
+	}
+	// TODO(gri) should we provide a package?
+	par = types.NewVar(token.NoPos, nil, name, typ)
+	return
+}
+
+// Parameters    = "(" [ ParameterList ] ")" .
+// ParameterList = { Parameter "," } Parameter .
+//
+func (p *parser) parseParameters() (list []*types.Var, isVariadic bool) {
+	p.expect('(')
+	for p.tok != ')' && p.tok != scanner.EOF {
+		if len(list) > 0 {
+			p.expect(',')
+		}
+		par, variadic := p.parseParameter()
+		list = append(list, par)
+		if variadic {
+			if isVariadic {
+				p.error("... not on final argument")
+			}
+			isVariadic = true
+		}
+	}
+	p.expect(')')
+
+	return
+}
+
+// Signature = Parameters [ Result ] .
+// Result    = Type | Parameters .
+//
+func (p *parser) parseSignature(recv *types.Var) *types.Signature {
+	params, isVariadic := p.parseParameters()
+
+	// optional result type
+	var results []*types.Var
+	if p.tok == '(' {
+		var variadic bool
+		results, variadic = p.parseParameters()
+		if variadic {
+			p.error("... not permitted on result type")
+		}
+	}
+
+	return types.NewSignature(recv, types.NewTuple(params...), types.NewTuple(results...), isVariadic)
+}
+
+// InterfaceType = "interface" "{" [ MethodList ] "}" .
+// MethodList    = Method { ";" Method } .
+// Method        = Name Signature .
+//
+// The methods of embedded interfaces are always "inlined"
+// by the compiler and thus embedded interfaces are never
+// visible in the export data.
+//
+func (p *parser) parseInterfaceType(parent *types.Package) types.Type {
+	var methods []*types.Func
+
+	p.expectKeyword("interface")
+	p.expect('{')
+	for i := 0; p.tok != '}' && p.tok != scanner.EOF; i++ {
+		if i > 0 {
+			p.expect(';')
+		}
+		pkg, name := p.parseName(parent, true)
+		sig := p.parseSignature(nil)
+		methods = append(methods, types.NewFunc(token.NoPos, pkg, name, sig))
+	}
+	p.expect('}')
+
+	// Complete requires the type's embedded interfaces to be fully defined,
+	// but we do not define any
+	return types.NewInterface(methods, nil).Complete()
+}
+
+// ChanType = ( "chan" [ "<-" ] | "<-" "chan" ) Type .
+//
+func (p *parser) parseChanType(parent *types.Package) types.Type {
+	dir := types.SendRecv
+	if p.tok == scanner.Ident {
+		p.expectKeyword("chan")
+		if p.tok == '<' {
+			p.expectSpecial("<-")
+			dir = types.SendOnly
+		}
+	} else {
+		p.expectSpecial("<-")
+		p.expectKeyword("chan")
+		dir = types.RecvOnly
+	}
+	elem := p.parseType(parent)
+	return types.NewChan(dir, elem)
+}
+
+// Type =
+//	BasicType | TypeName | ArrayType | SliceType | StructType |
+//      PointerType | FuncType | InterfaceType | MapType | ChanType |
+//      "(" Type ")" .
+//
+// BasicType   = ident .
+// TypeName    = ExportedName .
+// SliceType   = "[" "]" Type .
+// PointerType = "*" Type .
+// FuncType    = "func" Signature .
+//
+func (p *parser) parseType(parent *types.Package) types.Type {
+	switch p.tok {
+	case scanner.Ident:
+		switch p.lit {
+		default:
+			return p.parseBasicType()
+		case "struct":
+			return p.parseStructType(parent)
+		case "func":
+			// FuncType
+			p.next()
+			return p.parseSignature(nil)
+		case "interface":
+			return p.parseInterfaceType(parent)
+		case "map":
+			return p.parseMapType(parent)
+		case "chan":
+			return p.parseChanType(parent)
+		}
+	case '@':
+		// TypeName
+		pkg, name := p.parseExportedName()
+		return declTypeName(pkg, name).Type()
+	case '[':
+		p.next() // look ahead
+		if p.tok == ']' {
+			// SliceType
+			p.next()
+			return types.NewSlice(p.parseType(parent))
+		}
+		return p.parseArrayType(parent)
+	case '*':
+		// PointerType
+		p.next()
+		return types.NewPointer(p.parseType(parent))
+	case '<':
+		return p.parseChanType(parent)
+	case '(':
+		// "(" Type ")"
+		p.next()
+		typ := p.parseType(parent)
+		p.expect(')')
+		return typ
+	}
+	p.errorf("expected type, got %s (%q)", scanner.TokenString(p.tok), p.lit)
+	return nil
+}
+
+// ----------------------------------------------------------------------------
+// Declarations
+
+// ImportDecl = "import" PackageName PackageId .
+//
+func (p *parser) parseImportDecl() {
+	p.expectKeyword("import")
+	name := p.parsePackageName()
+	p.getPkg(p.parsePackageId(), name)
+}
+
+// int_lit = [ "+" | "-" ] { "0" ... "9" } .
+//
+func (p *parser) parseInt() string {
+	s := ""
+	switch p.tok {
+	case '-':
+		s = "-"
+		p.next()
+	case '+':
+		p.next()
+	}
+	return s + p.expect(scanner.Int)
+}
+
+// number = int_lit [ "p" int_lit ] .
+//
+func (p *parser) parseNumber() (typ *types.Basic, val exact.Value) {
+	// mantissa
+	mant := exact.MakeFromLiteral(p.parseInt(), token.INT, 0)
+	if mant == nil {
+		panic("invalid mantissa")
+	}
+
+	if p.lit == "p" {
+		// exponent (base 2)
+		p.next()
+		exp, err := strconv.ParseInt(p.parseInt(), 10, 0)
+		if err != nil {
+			p.error(err)
+		}
+		if exp < 0 {
+			denom := exact.MakeInt64(1)
+			denom = exact.Shift(denom, token.SHL, uint(-exp))
+			typ = types.Typ[types.UntypedFloat]
+			val = exact.BinaryOp(mant, token.QUO, denom)
+			return
+		}
+		if exp > 0 {
+			mant = exact.Shift(mant, token.SHL, uint(exp))
+		}
+		typ = types.Typ[types.UntypedFloat]
+		val = mant
+		return
+	}
+
+	typ = types.Typ[types.UntypedInt]
+	val = mant
+	return
+}
+
+// ConstDecl   = "const" ExportedName [ Type ] "=" Literal .
+// Literal     = bool_lit | int_lit | float_lit | complex_lit | rune_lit | string_lit .
+// bool_lit    = "true" | "false" .
+// complex_lit = "(" float_lit "+" float_lit "i" ")" .
+// rune_lit    = "(" int_lit "+" int_lit ")" .
+// string_lit  = `"` { unicode_char } `"` .
+//
+func (p *parser) parseConstDecl() {
+	p.expectKeyword("const")
+	pkg, name := p.parseExportedName()
+
+	var typ0 types.Type
+	if p.tok != '=' {
+		// constant types are never structured - no need for parent type
+		typ0 = p.parseType(nil)
+	}
+
+	p.expect('=')
+	var typ types.Type
+	var val exact.Value
+	switch p.tok {
+	case scanner.Ident:
+		// bool_lit
+		if p.lit != "true" && p.lit != "false" {
+			p.error("expected true or false")
+		}
+		typ = types.Typ[types.UntypedBool]
+		val = exact.MakeBool(p.lit == "true")
+		p.next()
+
+	case '-', scanner.Int:
+		// int_lit
+		typ, val = p.parseNumber()
+
+	case '(':
+		// complex_lit or rune_lit
+		p.next()
+		if p.tok == scanner.Char {
+			p.next()
+			p.expect('+')
+			typ = types.Typ[types.UntypedRune]
+			_, val = p.parseNumber()
+			p.expect(')')
+			break
+		}
+		_, re := p.parseNumber()
+		p.expect('+')
+		_, im := p.parseNumber()
+		p.expectKeyword("i")
+		p.expect(')')
+		typ = types.Typ[types.UntypedComplex]
+		val = exact.BinaryOp(re, token.ADD, exact.MakeImag(im))
+
+	case scanner.Char:
+		// rune_lit
+		typ = types.Typ[types.UntypedRune]
+		val = exact.MakeFromLiteral(p.lit, token.CHAR, 0)
+		p.next()
+
+	case scanner.String:
+		// string_lit
+		typ = types.Typ[types.UntypedString]
+		val = exact.MakeFromLiteral(p.lit, token.STRING, 0)
+		p.next()
+
+	default:
+		p.errorf("expected literal got %s", scanner.TokenString(p.tok))
+	}
+
+	if typ0 == nil {
+		typ0 = typ
+	}
+
+	pkg.Scope().Insert(types.NewConst(token.NoPos, pkg, name, typ0, val))
+}
+
+// TypeDecl = "type" ExportedName Type .
+//
+func (p *parser) parseTypeDecl() {
+	p.expectKeyword("type")
+	pkg, name := p.parseExportedName()
+	obj := declTypeName(pkg, name)
+
+	// The type object may have been imported before and thus already
+	// have a type associated with it. We still need to parse the type
+	// structure, but throw it away if the object already has a type.
+	// This ensures that all imports refer to the same type object for
+	// a given type declaration.
+	typ := p.parseType(pkg)
+
+	if name := obj.Type().(*types.Named); name.Underlying() == nil {
+		name.SetUnderlying(typ)
+	}
+}
+
+// VarDecl = "var" ExportedName Type .
+//
+func (p *parser) parseVarDecl() {
+	p.expectKeyword("var")
+	pkg, name := p.parseExportedName()
+	typ := p.parseType(pkg)
+	pkg.Scope().Insert(types.NewVar(token.NoPos, pkg, name, typ))
+}
+
+// Func = Signature [ Body ] .
+// Body = "{" ... "}" .
+//
+func (p *parser) parseFunc(recv *types.Var) *types.Signature {
+	sig := p.parseSignature(recv)
+	if p.tok == '{' {
+		p.next()
+		for i := 1; i > 0; p.next() {
+			switch p.tok {
+			case '{':
+				i++
+			case '}':
+				i--
+			}
+		}
+	}
+	return sig
+}
+
+// MethodDecl = "func" Receiver Name Func .
+// Receiver   = "(" ( identifier | "?" ) [ "*" ] ExportedName ")" .
+//
+func (p *parser) parseMethodDecl() {
+	// "func" already consumed
+	p.expect('(')
+	recv, _ := p.parseParameter() // receiver
+	p.expect(')')
+
+	// determine receiver base type object
+	base := deref(recv.Type()).(*types.Named)
+
+	// parse method name, signature, and possibly inlined body
+	_, name := p.parseName(nil, false)
+	sig := p.parseFunc(recv)
+
+	// methods always belong to the same package as the base type object
+	pkg := base.Obj().Pkg()
+
+	// add method to type unless type was imported before
+	// and method exists already
+	// TODO(gri) This leads to a quadratic algorithm - ok for now because method counts are small.
+	base.AddMethod(types.NewFunc(token.NoPos, pkg, name, sig))
+}
+
+// FuncDecl = "func" ExportedName Func .
+//
+func (p *parser) parseFuncDecl() {
+	// "func" already consumed
+	pkg, name := p.parseExportedName()
+	typ := p.parseFunc(nil)
+	pkg.Scope().Insert(types.NewFunc(token.NoPos, pkg, name, typ))
+}
+
+// Decl = [ ImportDecl | ConstDecl | TypeDecl | VarDecl | FuncDecl | MethodDecl ] "\n" .
+//
+func (p *parser) parseDecl() {
+	if p.tok == scanner.Ident {
+		switch p.lit {
+		case "import":
+			p.parseImportDecl()
+		case "const":
+			p.parseConstDecl()
+		case "type":
+			p.parseTypeDecl()
+		case "var":
+			p.parseVarDecl()
+		case "func":
+			p.next() // look ahead
+			if p.tok == '(' {
+				p.parseMethodDecl()
+			} else {
+				p.parseFuncDecl()
+			}
+		}
+	}
+	p.expect('\n')
+}
+
+// ----------------------------------------------------------------------------
+// Export
+
+// Export        = "PackageClause { Decl } "$$" .
+// PackageClause = "package" PackageName [ "safe" ] "\n" .
+//
+func (p *parser) parseExport() *types.Package {
+	p.expectKeyword("package")
+	name := p.parsePackageName()
+	if p.tok == scanner.Ident && p.lit == "safe" {
+		// package was compiled with -u option - ignore
+		p.next()
+	}
+	p.expect('\n')
+
+	pkg := p.getPkg(p.id, name)
+
+	for p.tok != '$' && p.tok != scanner.EOF {
+		p.parseDecl()
+	}
+
+	if ch := p.scanner.Peek(); p.tok != '$' || ch != '$' {
+		// don't call next()/expect() since reading past the
+		// export data may cause scanner errors (e.g. NUL chars)
+		p.errorf("expected '$$', got %s %c", scanner.TokenString(p.tok), ch)
+	}
+
+	if n := p.scanner.ErrorCount; n != 0 {
+		p.errorf("expected no scanner errors, got %d", n)
+	}
+
+	// Record all locally referenced packages as imports.
+	var imports []*types.Package
+	for id, pkg2 := range p.localPkgs {
+		if pkg2.Name() == "" {
+			p.errorf("%s package has no name", id)
+		}
+		if id == p.id {
+			continue // avoid self-edge
+		}
+		imports = append(imports, pkg2)
+	}
+	sort.Sort(byPath(imports))
+	pkg.SetImports(imports)
+
+	// package was imported completely and without errors
+	pkg.MarkComplete()
+
+	return pkg
+}
+
+type byPath []*types.Package
+
+func (a byPath) Len() int           { return len(a) }
+func (a byPath) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+func (a byPath) Less(i, j int) bool { return a[i].Path() < a[j].Path() }
diff --git a/go/src/golang.org/x/tools/go/gcimporter15/gcimporter16_test.go b/go/src/golang.org/x/tools/go/gcimporter15/gcimporter16_test.go
new file mode 100644
index 0000000..ac94d99
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/gcimporter15/gcimporter16_test.go
@@ -0,0 +1,55 @@
+// Copyright 2011 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.
+
+// +build go1.6
+
+package gcimporter
+
+import (
+	"fmt"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"runtime"
+	"testing"
+)
+
+// TODO(gri) Remove this function once we switched to new export format by default.
+func compileNewExport(t *testing.T, dirname, filename string) string {
+	/* testenv. */ MustHaveGoBuild(t)
+	cmd := exec.Command("go", "tool", "compile", "-newexport", filename)
+	cmd.Dir = dirname
+	out, err := cmd.CombinedOutput()
+	if err != nil {
+		t.Logf("%s", out)
+		t.Fatalf("go tool compile %s failed: %s", filename, err)
+	}
+	// filename should end with ".go"
+	return filepath.Join(dirname, filename[:len(filename)-2]+"o")
+}
+
+// TODO(gri) Remove this function once we switched to new export format by default
+//           (and update the comment and want list in TestImportTestdata).
+func TestImportTestdataNewExport(t *testing.T) {
+	// This package only handles gc export data.
+	if runtime.Compiler != "gc" {
+		t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
+		return
+	}
+
+	if outFn := compileNewExport(t, "testdata", "exports.go"); outFn != "" {
+		defer os.Remove(outFn)
+	}
+
+	if pkg := testPath(t, "./testdata/exports", "."); pkg != nil {
+		// The package's Imports list must include all packages
+		// explicitly imported by exports.go, plus all packages
+		// referenced indirectly via exported objects in exports.go.
+		want := `[package ast ("go/ast") package token ("go/token")]`
+		got := fmt.Sprint(pkg.Imports())
+		if got != want {
+			t.Errorf(`Package("exports").Imports() = %s, want %s`, got, want)
+		}
+	}
+}
diff --git a/go/src/golang.org/x/tools/go/gcimporter15/gcimporter_test.go b/go/src/golang.org/x/tools/go/gcimporter15/gcimporter_test.go
new file mode 100644
index 0000000..873ef46
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/gcimporter15/gcimporter_test.go
@@ -0,0 +1,365 @@
+// Copyright 2011 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.
+
+// +build go1.5
+
+// This file is a copy of $GOROOT/src/go/internal/gcimporter/gcimporter_test.go, tagged for go1.5,
+// and minimally adjusted to make it build with code from (std lib) internal/testenv copied.
+
+package gcimporter
+
+import (
+	"fmt"
+	"go/types"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"runtime"
+	"strings"
+	"testing"
+	"time"
+)
+
+// ----------------------------------------------------------------------------
+// The following three functions (Builder, HasGoBuild, MustHaveGoBuild) were
+// copied from $GOROOT/src/internal/testenv since that package is not available
+// in x/tools.
+
+// Builder reports the name of the builder running this test
+// (for example, "linux-amd64" or "windows-386-gce").
+// If the test is not running on the build infrastructure,
+// Builder returns the empty string.
+func Builder() string {
+	return os.Getenv("GO_BUILDER_NAME")
+}
+
+// HasGoBuild reports whether the current system can build programs with ``go build''
+// and then run them with os.StartProcess or exec.Command.
+func HasGoBuild() bool {
+	switch runtime.GOOS {
+	case "android", "nacl":
+		return false
+	case "darwin":
+		if strings.HasPrefix(runtime.GOARCH, "arm") {
+			return false
+		}
+	}
+	return true
+}
+
+// MustHaveGoBuild checks that the current system can build programs with ``go build''
+// and then run them with os.StartProcess or exec.Command.
+// If not, MustHaveGoBuild calls t.Skip with an explanation.
+func MustHaveGoBuild(t *testing.T) {
+	if !HasGoBuild() {
+		t.Skipf("skipping test: 'go build' not available on %s/%s", runtime.GOOS, runtime.GOARCH)
+	}
+}
+
+// ----------------------------------------------------------------------------
+
+// skipSpecialPlatforms causes the test to be skipped for platforms where
+// builders (build.golang.org) don't have access to compiled packages for
+// import.
+func skipSpecialPlatforms(t *testing.T) {
+	switch platform := runtime.GOOS + "-" + runtime.GOARCH; platform {
+	case "nacl-amd64p32",
+		"nacl-386",
+		"nacl-arm",
+		"darwin-arm",
+		"darwin-arm64":
+		t.Skipf("no compiled packages available for import on %s", platform)
+	}
+}
+
+func compile(t *testing.T, dirname, filename string) string {
+	/* testenv. */ MustHaveGoBuild(t)
+	cmd := exec.Command("go", "tool", "compile", filename)
+	cmd.Dir = dirname
+	out, err := cmd.CombinedOutput()
+	if err != nil {
+		t.Logf("%s", out)
+		t.Fatalf("go tool compile %s failed: %s", filename, err)
+	}
+	// filename should end with ".go"
+	return filepath.Join(dirname, filename[:len(filename)-2]+"o")
+}
+
+func testPath(t *testing.T, path, srcDir string) *types.Package {
+	t0 := time.Now()
+	pkg, err := Import(make(map[string]*types.Package), path, srcDir)
+	if err != nil {
+		t.Errorf("testPath(%s): %s", path, err)
+		return nil
+	}
+	t.Logf("testPath(%s): %v", path, time.Since(t0))
+	return pkg
+}
+
+const maxTime = 30 * time.Second
+
+func testDir(t *testing.T, dir string, endTime time.Time) (nimports int) {
+	dirname := filepath.Join(runtime.GOROOT(), "pkg", runtime.GOOS+"_"+runtime.GOARCH, dir)
+	list, err := ioutil.ReadDir(dirname)
+	if err != nil {
+		t.Fatalf("testDir(%s): %s", dirname, err)
+	}
+	for _, f := range list {
+		if time.Now().After(endTime) {
+			t.Log("testing time used up")
+			return
+		}
+		switch {
+		case !f.IsDir():
+			// try extensions
+			for _, ext := range pkgExts {
+				if strings.HasSuffix(f.Name(), ext) {
+					name := f.Name()[0 : len(f.Name())-len(ext)] // remove extension
+					if testPath(t, filepath.Join(dir, name), dir) != nil {
+						nimports++
+					}
+				}
+			}
+		case f.IsDir():
+			nimports += testDir(t, filepath.Join(dir, f.Name()), endTime)
+		}
+	}
+	return
+}
+
+func TestImportTestdata(t *testing.T) {
+	// This package only handles gc export data.
+	if runtime.Compiler != "gc" {
+		t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
+		return
+	}
+
+	if outFn := compile(t, "testdata", "exports.go"); outFn != "" {
+		defer os.Remove(outFn)
+	}
+
+	if pkg := testPath(t, "./testdata/exports", "."); pkg != nil {
+		// The package's Imports list must include all packages
+		// explicitly imported by exports.go, plus all packages
+		// referenced indirectly via exported objects in exports.go.
+		// With the textual export format, the list may also include
+		// additional packages that are not strictly required for
+		// import processing alone (they are exported to err "on
+		// the safe side").
+		got := fmt.Sprint(pkg.Imports())
+		for _, want := range []string{"go/ast", "go/token"} {
+			if !strings.Contains(got, want) {
+				t.Errorf(`Package("exports").Imports() = %s, does not contain %s`, got, want)
+			}
+		}
+	}
+}
+
+func TestImportStdLib(t *testing.T) {
+	skipSpecialPlatforms(t)
+
+	// This package only handles gc export data.
+	if runtime.Compiler != "gc" {
+		t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
+		return
+	}
+
+	dt := maxTime
+	if testing.Short() && /* testenv. */ Builder() == "" {
+		dt = 10 * time.Millisecond
+	}
+	nimports := testDir(t, "", time.Now().Add(dt)) // installed packages
+	t.Logf("tested %d imports", nimports)
+}
+
+var importedObjectTests = []struct {
+	name string
+	want string
+}{
+	{"math.Pi", "const Pi untyped float"},
+	{"io.Reader", "type Reader interface{Read(p []byte) (n int, err error)}"},
+	{"io.ReadWriter", "type ReadWriter interface{Read(p []byte) (n int, err error); Write(p []byte) (n int, err error)}"},
+	{"math.Sin", "func Sin(x float64) float64"},
+	// TODO(gri) add more tests
+}
+
+func TestImportedTypes(t *testing.T) {
+	skipSpecialPlatforms(t)
+
+	// This package only handles gc export data.
+	if runtime.Compiler != "gc" {
+		t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
+		return
+	}
+
+	for _, test := range importedObjectTests {
+		s := strings.Split(test.name, ".")
+		if len(s) != 2 {
+			t.Fatal("inconsistent test data")
+		}
+		importPath := s[0]
+		objName := s[1]
+
+		pkg, err := Import(make(map[string]*types.Package), importPath, ".")
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+
+		obj := pkg.Scope().Lookup(objName)
+		if obj == nil {
+			t.Errorf("%s: object not found", test.name)
+			continue
+		}
+
+		got := types.ObjectString(obj, types.RelativeTo(pkg))
+		if got != test.want {
+			t.Errorf("%s: got %q; want %q", test.name, got, test.want)
+		}
+	}
+}
+
+func TestIssue5815(t *testing.T) {
+	skipSpecialPlatforms(t)
+
+	// This package only handles gc export data.
+	if runtime.Compiler != "gc" {
+		t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
+		return
+	}
+
+	pkg, err := Import(make(map[string]*types.Package), "strings", ".")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	scope := pkg.Scope()
+	for _, name := range scope.Names() {
+		obj := scope.Lookup(name)
+		if obj.Pkg() == nil {
+			t.Errorf("no pkg for %s", obj)
+		}
+		if tname, _ := obj.(*types.TypeName); tname != nil {
+			named := tname.Type().(*types.Named)
+			for i := 0; i < named.NumMethods(); i++ {
+				m := named.Method(i)
+				if m.Pkg() == nil {
+					t.Errorf("no pkg for %s", m)
+				}
+			}
+		}
+	}
+}
+
+// Smoke test to ensure that imported methods get the correct package.
+func TestCorrectMethodPackage(t *testing.T) {
+	skipSpecialPlatforms(t)
+
+	// This package only handles gc export data.
+	if runtime.Compiler != "gc" {
+		t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
+		return
+	}
+
+	imports := make(map[string]*types.Package)
+	_, err := Import(imports, "net/http", ".")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	mutex := imports["sync"].Scope().Lookup("Mutex").(*types.TypeName).Type()
+	mset := types.NewMethodSet(types.NewPointer(mutex)) // methods of *sync.Mutex
+	sel := mset.Lookup(nil, "Lock")
+	lock := sel.Obj().(*types.Func)
+	if got, want := lock.Pkg().Path(), "sync"; got != want {
+		t.Errorf("got package path %q; want %q", got, want)
+	}
+}
+
+func TestIssue13566(t *testing.T) {
+	skipSpecialPlatforms(t)
+
+	// This package only handles gc export data.
+	if runtime.Compiler != "gc" {
+		t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
+		return
+	}
+
+	// On windows, we have to set the -D option for the compiler to avoid having a drive
+	// letter and an illegal ':' in the import path - just skip it (see also issue #3483).
+	if runtime.GOOS == "windows" {
+		t.Skip("avoid dealing with relative paths/drive letters on windows")
+	}
+
+	if f := compile(t, "testdata", "a.go"); f != "" {
+		defer os.Remove(f)
+	}
+	if f := compile(t, "testdata", "b.go"); f != "" {
+		defer os.Remove(f)
+	}
+
+	// import must succeed (test for issue at hand)
+	pkg, err := Import(make(map[string]*types.Package), "./testdata/b", ".")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// make sure all indirectly imported packages have names
+	for _, imp := range pkg.Imports() {
+		if imp.Name() == "" {
+			t.Errorf("no name for %s package", imp.Path())
+		}
+	}
+}
+
+func TestIssue13898(t *testing.T) {
+	skipSpecialPlatforms(t)
+
+	// This package only handles gc export data.
+	if runtime.Compiler != "gc" {
+		t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
+		return
+	}
+
+	// import go/internal/gcimporter which imports go/types partially
+	imports := make(map[string]*types.Package)
+	_, err := Import(imports, "go/internal/gcimporter", ".")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// look for go/types package
+	var goTypesPkg *types.Package
+	for path, pkg := range imports {
+		if path == "go/types" {
+			goTypesPkg = pkg
+			break
+		}
+	}
+	if goTypesPkg == nil {
+		t.Fatal("go/types not found")
+	}
+
+	// look for go/types.Object type
+	obj := goTypesPkg.Scope().Lookup("Object")
+	if obj == nil {
+		t.Fatal("go/types.Object not found")
+	}
+	typ, ok := obj.Type().(*types.Named)
+	if !ok {
+		t.Fatalf("go/types.Object type is %v; wanted named type", typ)
+	}
+
+	// lookup go/types.Object.Pkg method
+	m, _, _ := types.LookupFieldOrMethod(typ, false, nil, "Pkg")
+	if m == nil {
+		t.Fatal("go/types.Object.Pkg not found")
+	}
+
+	// the method must belong to go/types
+	if m.Pkg().Path() != "go/types" {
+		t.Fatalf("found %v; want go/types", m.Pkg())
+	}
+}
diff --git a/go/src/golang.org/x/tools/go/gcimporter15/setname15.go b/go/src/golang.org/x/tools/go/gcimporter15/setname15.go
new file mode 100644
index 0000000..8f78f54
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/gcimporter15/setname15.go
@@ -0,0 +1,31 @@
+// Copyright 2016 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.
+
+// +build go1.5,!go1.6
+
+package gcimporter
+
+import (
+	"go/types"
+	"unsafe"
+)
+
+func setName(pkg *types.Package, name string) {
+	(*types_Package)(unsafe.Pointer(pkg)).name = name
+}
+
+// The underlying type of types_Package is identical to
+// the underlying type of types.Package. We use it with
+// package unsafe to set the name field since 1.5 does
+// not have the Package.SetName method.
+// TestSetName verifies that the layout with respect to
+// the name field is correct.
+type types_Package struct {
+	path     string
+	name     string
+	scope    *types.Scope
+	complete bool
+	imports  []*types.Package
+	fake     bool
+}
diff --git a/go/src/golang.org/x/tools/go/gcimporter15/setname16.go b/go/src/golang.org/x/tools/go/gcimporter15/setname16.go
new file mode 100644
index 0000000..d318e7c
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/gcimporter15/setname16.go
@@ -0,0 +1,13 @@
+// Copyright 2016 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.
+
+// +build go1.6
+
+package gcimporter
+
+import "go/types"
+
+func setName(pkg *types.Package, name string) {
+	pkg.SetName(name)
+}
diff --git a/go/src/golang.org/x/tools/go/gcimporter15/setname_test.go b/go/src/golang.org/x/tools/go/gcimporter15/setname_test.go
new file mode 100644
index 0000000..a8a33f7
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/gcimporter15/setname_test.go
@@ -0,0 +1,28 @@
+// Copyright 2016 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.
+
+// +build go1.5
+
+package gcimporter
+
+import (
+	"go/types"
+	"testing"
+)
+
+func TestSetName(t *testing.T) {
+	pkg := types.NewPackage("path", "foo")
+	scope := pkg.Scope()
+
+	// verify setName
+	setName(pkg, "bar")
+	if name := pkg.Name(); name != "bar" {
+		t.Fatalf(`got package name %q; want "bar"`, name)
+	}
+
+	// verify no other fields are changed
+	if pkg.Path() != "path" || pkg.Scope() != scope || pkg.Complete() || pkg.Imports() != nil {
+		t.Fatalf("setName changed other fields")
+	}
+}
diff --git a/go/src/golang.org/x/tools/go/gcimporter15/testdata/a.go b/go/src/golang.org/x/tools/go/gcimporter15/testdata/a.go
new file mode 100644
index 0000000..56e4292
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/gcimporter15/testdata/a.go
@@ -0,0 +1,14 @@
+// Copyright 2016 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.
+
+// Input for TestIssue13566
+
+package a
+
+import "encoding/json"
+
+type A struct {
+	a    *A
+	json json.RawMessage
+}
diff --git a/go/src/golang.org/x/tools/go/gcimporter15/testdata/b.go b/go/src/golang.org/x/tools/go/gcimporter15/testdata/b.go
new file mode 100644
index 0000000..4196678
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/gcimporter15/testdata/b.go
@@ -0,0 +1,11 @@
+// Copyright 2016 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.
+
+// Input for TestIssue13566
+
+package b
+
+import "./a"
+
+type A a.A
diff --git a/go/src/golang.org/x/tools/go/gcimporter15/testdata/exports.go b/go/src/golang.org/x/tools/go/gcimporter15/testdata/exports.go
new file mode 100644
index 0000000..8ee28b0
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/gcimporter15/testdata/exports.go
@@ -0,0 +1,89 @@
+// Copyright 2011 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.
+
+// This file is used to generate an object file which
+// serves as test file for gcimporter_test.go.
+
+package exports
+
+import (
+	"go/ast"
+)
+
+// Issue 3682: Correctly read dotted identifiers from export data.
+const init1 = 0
+
+func init() {}
+
+const (
+	C0 int = 0
+	C1     = 3.14159265
+	C2     = 2.718281828i
+	C3     = -123.456e-789
+	C4     = +123.456E+789
+	C5     = 1234i
+	C6     = "foo\n"
+	C7     = `bar\n`
+)
+
+type (
+	T1  int
+	T2  [10]int
+	T3  []int
+	T4  *int
+	T5  chan int
+	T6a chan<- int
+	T6b chan (<-chan int)
+	T6c chan<- (chan int)
+	T7  <-chan *ast.File
+	T8  struct{}
+	T9  struct {
+		a    int
+		b, c float32
+		d    []string `go:"tag"`
+	}
+	T10 struct {
+		T8
+		T9
+		_ *T10
+	}
+	T11 map[int]string
+	T12 interface{}
+	T13 interface {
+		m1()
+		m2(int) float32
+	}
+	T14 interface {
+		T12
+		T13
+		m3(x ...struct{}) []T9
+	}
+	T15 func()
+	T16 func(int)
+	T17 func(x int)
+	T18 func() float32
+	T19 func() (x float32)
+	T20 func(...interface{})
+	T21 struct{ next *T21 }
+	T22 struct{ link *T23 }
+	T23 struct{ link *T22 }
+	T24 *T24
+	T25 *T26
+	T26 *T27
+	T27 *T25
+	T28 func(T28) T28
+)
+
+var (
+	V0 int
+	V1 = -991.0
+)
+
+func F1()         {}
+func F2(x int)    {}
+func F3() int     { return 0 }
+func F4() float32 { return 0 }
+func F5(a, b, c int, u, v, w struct{ x, y T1 }, more ...interface{}) (p, q, r chan<- T10)
+
+func (p *T1) M1()
diff --git a/go/src/golang.org/x/tools/go/importer/import_test.go b/go/src/golang.org/x/tools/go/importer/import_test.go
index 3a2560c..95c373d 100644
--- a/go/src/golang.org/x/tools/go/importer/import_test.go
+++ b/go/src/golang.org/x/tools/go/importer/import_test.go
@@ -119,6 +119,11 @@
 		if testing.Short() && time.Since(start) >= 750*time.Millisecond {
 			return
 		}
+		if lib == "cmd/internal/objfile" || lib == "net/http" {
+			// gcimporter doesn't support vendored imports.
+			// TODO(gri): fix.
+			continue
+		}
 
 		pkg, err := pkgForPath(lib)
 		switch err := err.(type) {
diff --git a/go/src/golang.org/x/tools/go/loader/cgo.go b/go/src/golang.org/x/tools/go/loader/cgo.go
index fb39e53..f698197 100644
--- a/go/src/golang.org/x/tools/go/loader/cgo.go
+++ b/go/src/golang.org/x/tools/go/loader/cgo.go
@@ -1,3 +1,9 @@
+// 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.
+
+// +build go1.5
+
 package loader
 
 // This file handles cgo preprocessing of files containing `import "C"`.
diff --git a/go/src/golang.org/x/tools/go/loader/cgo14.go b/go/src/golang.org/x/tools/go/loader/cgo14.go
new file mode 100644
index 0000000..1dac420
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/loader/cgo14.go
@@ -0,0 +1,205 @@
+// 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.
+
+// +build !go1.5
+
+package loader
+
+// This file handles cgo preprocessing of files containing `import "C"`.
+//
+// DESIGN
+//
+// The approach taken is to run the cgo processor on the package's
+// CgoFiles and parse the output, faking the filenames of the
+// resulting ASTs so that the synthetic file containing the C types is
+// called "C" (e.g. "~/go/src/net/C") and the preprocessed files
+// have their original names (e.g. "~/go/src/net/cgo_unix.go"),
+// not the names of the actual temporary files.
+//
+// The advantage of this approach is its fidelity to 'go build'.  The
+// downside is that the token.Position.Offset for each AST node is
+// incorrect, being an offset within the temporary file.  Line numbers
+// should still be correct because of the //line comments.
+//
+// The logic of this file is mostly plundered from the 'go build'
+// tool, which also invokes the cgo preprocessor.
+//
+//
+// REJECTED ALTERNATIVE
+//
+// An alternative approach that we explored is to extend go/types'
+// Importer mechanism to provide the identity of the importing package
+// so that each time `import "C"` appears it resolves to a different
+// synthetic package containing just the objects needed in that case.
+// The loader would invoke cgo but parse only the cgo_types.go file
+// defining the package-level objects, discarding the other files
+// resulting from preprocessing.
+//
+// The benefit of this approach would have been that source-level
+// syntax information would correspond exactly to the original cgo
+// file, with no preprocessing involved, making source tools like
+// godoc, oracle, and eg happy.  However, the approach was rejected
+// due to the additional complexity it would impose on go/types.  (It
+// made for a beautiful demo, though.)
+//
+// cgo files, despite their *.go extension, are not legal Go source
+// files per the specification since they may refer to unexported
+// members of package "C" such as C.int.  Also, a function such as
+// C.getpwent has in effect two types, one matching its C type and one
+// which additionally returns (errno C.int).  The cgo preprocessor
+// uses name mangling to distinguish these two functions in the
+// processed code, but go/types would need to duplicate this logic in
+// its handling of function calls, analogous to the treatment of map
+// lookups in which y=m[k] and y,ok=m[k] are both legal.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/parser"
+	"go/token"
+	"io/ioutil"
+	"log"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"regexp"
+	"strings"
+)
+
+// processCgoFiles invokes the cgo preprocessor on bp.CgoFiles, parses
+// the output and returns the resulting ASTs.
+//
+func processCgoFiles(bp *build.Package, fset *token.FileSet, DisplayPath func(path string) string, mode parser.Mode) ([]*ast.File, error) {
+	tmpdir, err := ioutil.TempDir("", strings.Replace(bp.ImportPath, "/", "_", -1)+"_C")
+	if err != nil {
+		return nil, err
+	}
+	defer os.RemoveAll(tmpdir)
+
+	pkgdir := bp.Dir
+	if DisplayPath != nil {
+		pkgdir = DisplayPath(pkgdir)
+	}
+
+	cgoFiles, cgoDisplayFiles, err := runCgo(bp, pkgdir, tmpdir)
+	if err != nil {
+		return nil, err
+	}
+	var files []*ast.File
+	for i := range cgoFiles {
+		rd, err := os.Open(cgoFiles[i])
+		if err != nil {
+			return nil, err
+		}
+		display := filepath.Join(bp.Dir, cgoDisplayFiles[i])
+		f, err := parser.ParseFile(fset, display, rd, mode)
+		rd.Close()
+		if err != nil {
+			return nil, err
+		}
+		files = append(files, f)
+	}
+	return files, nil
+}
+
+var cgoRe = regexp.MustCompile(`[/\\:]`)
+
+// runCgo invokes the cgo preprocessor on bp.CgoFiles and returns two
+// lists of files: the resulting processed files (in temporary
+// directory tmpdir) and the corresponding names of the unprocessed files.
+//
+// runCgo is adapted from (*builder).cgo in
+// $GOROOT/src/cmd/go/build.go, but these features are unsupported:
+// pkg-config, Objective C, CGOPKGPATH, CGO_FLAGS.
+//
+func runCgo(bp *build.Package, pkgdir, tmpdir string) (files, displayFiles []string, err error) {
+	cgoCPPFLAGS, _, _, _ := cflags(bp, true)
+	_, cgoexeCFLAGS, _, _ := cflags(bp, false)
+
+	if len(bp.CgoPkgConfig) > 0 {
+		return nil, nil, fmt.Errorf("cgo pkg-config not supported")
+	}
+
+	// Allows including _cgo_export.h from .[ch] files in the package.
+	cgoCPPFLAGS = append(cgoCPPFLAGS, "-I", tmpdir)
+
+	// _cgo_gotypes.go (displayed "C") contains the type definitions.
+	files = append(files, filepath.Join(tmpdir, "_cgo_gotypes.go"))
+	displayFiles = append(displayFiles, "C")
+	for _, fn := range bp.CgoFiles {
+		// "foo.cgo1.go" (displayed "foo.go") is the processed Go source.
+		f := cgoRe.ReplaceAllString(fn[:len(fn)-len("go")], "_")
+		files = append(files, filepath.Join(tmpdir, f+"cgo1.go"))
+		displayFiles = append(displayFiles, fn)
+	}
+
+	var cgoflags []string
+	if bp.Goroot && bp.ImportPath == "runtime/cgo" {
+		cgoflags = append(cgoflags, "-import_runtime_cgo=false")
+	}
+	if bp.Goroot && bp.ImportPath == "runtime/race" || bp.ImportPath == "runtime/cgo" {
+		cgoflags = append(cgoflags, "-import_syscall=false")
+	}
+
+	args := stringList(
+		"go", "tool", "cgo", "-objdir", tmpdir, cgoflags, "--",
+		cgoCPPFLAGS, cgoexeCFLAGS, bp.CgoFiles,
+	)
+	if false {
+		log.Printf("Running cgo for package %q: %s (dir=%s)", bp.ImportPath, args, pkgdir)
+	}
+	cmd := exec.Command(args[0], args[1:]...)
+	cmd.Dir = pkgdir
+	cmd.Stdout = os.Stderr
+	cmd.Stderr = os.Stderr
+	if err := cmd.Run(); err != nil {
+		return nil, nil, fmt.Errorf("cgo failed: %s: %s", args, err)
+	}
+
+	return files, displayFiles, nil
+}
+
+// -- unmodified from 'go build' ---------------------------------------
+
+// Return the flags to use when invoking the C or C++ compilers, or cgo.
+func cflags(p *build.Package, def bool) (cppflags, cflags, cxxflags, ldflags []string) {
+	var defaults string
+	if def {
+		defaults = "-g -O2"
+	}
+
+	cppflags = stringList(envList("CGO_CPPFLAGS", ""), p.CgoCPPFLAGS)
+	cflags = stringList(envList("CGO_CFLAGS", defaults), p.CgoCFLAGS)
+	cxxflags = stringList(envList("CGO_CXXFLAGS", defaults), p.CgoCXXFLAGS)
+	ldflags = stringList(envList("CGO_LDFLAGS", defaults), p.CgoLDFLAGS)
+	return
+}
+
+// envList returns the value of the given environment variable broken
+// into fields, using the default value when the variable is empty.
+func envList(key, def string) []string {
+	v := os.Getenv(key)
+	if v == "" {
+		v = def
+	}
+	return strings.Fields(v)
+}
+
+// stringList's arguments should be a sequence of string or []string values.
+// stringList flattens them into a single []string.
+func stringList(args ...interface{}) []string {
+	var x []string
+	for _, arg := range args {
+		switch arg := arg.(type) {
+		case []string:
+			x = append(x, arg...)
+		case string:
+			x = append(x, arg)
+		default:
+			panic("stringList: invalid argument")
+		}
+	}
+	return x
+}
diff --git a/go/src/golang.org/x/tools/go/loader/doc.go b/go/src/golang.org/x/tools/go/loader/doc.go
index 1ff4b15..600cd1a 100644
--- a/go/src/golang.org/x/tools/go/loader/doc.go
+++ b/go/src/golang.org/x/tools/go/loader/doc.go
@@ -50,6 +50,11 @@
 //
 // CONCEPTS AND TERMINOLOGY
 //
+// The WORKSPACE is the set of packages accessible to the loader.  The
+// workspace is defined by Config.Build, a *build.Context.  The
+// default context treats subdirectories of $GOROOT and $GOPATH as
+// packages, but this behavior may be overridden.
+//
 // An AD HOC package is one specified as a set of source files on the
 // command line.  In the simplest case, it may consist of a single file
 // such as $GOROOT/src/net/http/triv.go.
@@ -59,14 +64,25 @@
 // same directory.  (go/build.Package calls these files XTestFiles.)
 //
 // An IMPORTABLE package is one that can be referred to by some import
-// spec.  The Path() of each importable package is unique within a
-// Program.
+// spec.  Every importable package is uniquely identified by its
+// PACKAGE PATH or just PATH, a string such as "fmt", "encoding/json",
+// or "cmd/vendor/golang.org/x/arch/x86/x86asm".  A package path
+// typically denotes a subdirectory of the workspace.
+//
+// An import declaration uses an IMPORT PATH to refer to a package.
+// Most import declarations use the package path as the import path.
+//
+// Due to VENDORING (https://golang.org/s/go15vendor), the
+// interpretation of an import path may depend on the directory in which
+// it appears.  To resolve an import path to a package path, go/build
+// must search the enclosing directories for a subdirectory named
+// "vendor".
 //
 // ad hoc packages and external test packages are NON-IMPORTABLE.  The
-// Path() of an ad hoc package is inferred from the package
+// path of an ad hoc package is inferred from the package
 // declarations of its files and is therefore not a unique package key.
 // For example, Config.CreatePkgs may specify two initial ad hoc
-// packages both called "main".
+// packages, both with path "main".
 //
 // An AUGMENTED package is an importable package P plus all the
 // *_test.go files with same 'package foo' declaration as P.
@@ -125,7 +141,7 @@
 // Let us define the import dependency graph as follows.  Each node is a
 // list of files passed to (Checker).Files at once.  Many of these lists
 // are the production code of an importable Go package, so those nodes
-// are labelled by the package's import path.  The remaining nodes are
+// are labelled by the package's path.  The remaining nodes are
 // ad hoc packages and lists of in-package *_test.go files that augment
 // an importable package; those nodes have no label.
 //
diff --git a/go/src/golang.org/x/tools/go/loader/example14_test.go b/go/src/golang.org/x/tools/go/loader/example14_test.go
index 76d5ea6..67dbefa 100644
--- a/go/src/golang.org/x/tools/go/loader/example14_test.go
+++ b/go/src/golang.org/x/tools/go/loader/example14_test.go
@@ -83,7 +83,7 @@
 	// created: []
 	// imported: [errors runtime unicode/utf8]
 	// initial: [errors runtime unicode/utf8]
-	// all: [errors runtime unicode/utf8]
+	// all: [errors runtime unicode/utf8 unsafe]
 }
 
 // This example creates and type-checks a single package (without tests)
@@ -139,7 +139,7 @@
 	// created: [hello]
 	// imported: []
 	// initial: [hello]
-	// all: [errors fmt hello io math os reflect runtime strconv sync sync/atomic syscall time unicode/utf8]
+	// all: [errors fmt hello io math os reflect runtime strconv sync sync/atomic syscall time unicode/utf8 unsafe]
 	// strconv.Files: [atob.go atof.go atoi.go decimal.go extfloat.go ftoa.go isprint.go itoa.go quote.go]
 }
 
@@ -167,7 +167,7 @@
 	// created: [strconv_test]
 	// imported: [errors strconv unicode/utf8]
 	// initial: [errors strconv strconv_test unicode/utf8]
-	// all: [bufio bytes errors flag fmt io math math/rand os reflect runtime runtime/pprof sort strconv strconv_test strings sync sync/atomic syscall testing text/tabwriter time unicode unicode/utf8]
+	// all: [bufio bytes errors flag fmt io math math/rand os reflect runtime runtime/pprof sort strconv strconv_test strings sync sync/atomic syscall testing text/tabwriter time unicode unicode/utf8 unsafe]
 	// strconv.Files: [atob.go atof.go atoi.go decimal.go extfloat.go ftoa.go isprint.go itoa.go quote.go internal_test.go]
 	// strconv_test.Files: [atob_test.go atof_test.go atoi_test.go decimal_test.go fp_test.go ftoa_test.go itoa_test.go quote_example_test.go quote_test.go strconv_test.go]
 }
diff --git a/go/src/golang.org/x/tools/go/loader/example15_test.go b/go/src/golang.org/x/tools/go/loader/example15_test.go
new file mode 100644
index 0000000..5cf365b
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/loader/example15_test.go
@@ -0,0 +1,177 @@
+// Copyright 2015 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.
+
+// +build go1.5,!go1.6
+// +build !windows
+
+package loader_test
+
+import (
+	"fmt"
+	"go/token"
+	"log"
+	"path/filepath"
+	"runtime"
+	"sort"
+	"strings"
+
+	"golang.org/x/tools/go/loader"
+)
+
+func printProgram(prog *loader.Program) {
+	// Created packages are the initial packages specified by a call
+	// to CreateFromFilenames or CreateFromFiles.
+	var names []string
+	for _, info := range prog.Created {
+		names = append(names, info.Pkg.Path())
+	}
+	fmt.Printf("created: %s\n", names)
+
+	// Imported packages are the initial packages specified by a
+	// call to Import or ImportWithTests.
+	names = nil
+	for _, info := range prog.Imported {
+		if strings.Contains(info.Pkg.Path(), "internal") {
+			continue // skip, to reduce fragility
+		}
+		names = append(names, info.Pkg.Path())
+	}
+	sort.Strings(names)
+	fmt.Printf("imported: %s\n", names)
+
+	// InitialPackages contains the union of created and imported.
+	names = nil
+	for _, info := range prog.InitialPackages() {
+		names = append(names, info.Pkg.Path())
+	}
+	sort.Strings(names)
+	fmt.Printf("initial: %s\n", names)
+
+	// AllPackages contains all initial packages and their dependencies.
+	names = nil
+	for pkg := range prog.AllPackages {
+		names = append(names, pkg.Path())
+	}
+	sort.Strings(names)
+	fmt.Printf("all: %s\n", names)
+}
+
+func printFilenames(fset *token.FileSet, info *loader.PackageInfo) {
+	var names []string
+	for _, f := range info.Files {
+		names = append(names, filepath.Base(fset.File(f.Pos()).Name()))
+	}
+	fmt.Printf("%s.Files: %s\n", info.Pkg.Path(), names)
+}
+
+// This example loads a set of packages and all of their dependencies
+// from a typical command-line.  FromArgs parses a command line and
+// makes calls to the other methods of Config shown in the examples that
+// follow.
+func ExampleConfig_FromArgs() {
+	args := []string{"mytool", "unicode/utf8", "errors", "runtime", "--", "foo", "bar"}
+	const wantTests = false
+
+	var conf loader.Config
+	rest, err := conf.FromArgs(args[1:], wantTests)
+	prog, err := conf.Load()
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	fmt.Printf("rest: %s\n", rest)
+	printProgram(prog)
+	// Output:
+	// rest: [foo bar]
+	// created: []
+	// imported: [errors runtime unicode/utf8]
+	// initial: [errors runtime unicode/utf8]
+	// all: [errors runtime unicode/utf8 unsafe]
+}
+
+// This example creates and type-checks a single package (without tests)
+// from a list of filenames, and loads all of its dependencies.
+func ExampleConfig_CreateFromFilenames() {
+	var conf loader.Config
+	filename := filepath.Join(runtime.GOROOT(), "src/container/heap/heap.go")
+	conf.CreateFromFilenames("container/heap", filename)
+	prog, err := conf.Load()
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	printProgram(prog)
+	// Output:
+	// created: [container/heap]
+	// imported: []
+	// initial: [container/heap]
+	// all: [container/heap sort]
+}
+
+// In the examples below, for stability, the chosen packages are
+// relatively small, platform-independent, and low-level (and thus
+// infrequently changing).
+// The strconv package has internal and external tests.
+
+const hello = `package main
+
+import "fmt"
+
+func main() {
+	fmt.Println("Hello, world.")
+}
+`
+
+// This example creates and type-checks a package from a list of
+// already-parsed files, and loads all its dependencies.
+func ExampleConfig_CreateFromFiles() {
+	var conf loader.Config
+	f, err := conf.ParseFile("hello.go", hello)
+	if err != nil {
+		log.Fatal(err)
+	}
+	conf.CreateFromFiles("hello", f)
+	prog, err := conf.Load()
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	printProgram(prog)
+	printFilenames(prog.Fset, prog.Package("strconv"))
+	// Output:
+	// created: [hello]
+	// imported: []
+	// initial: [hello]
+	// all: [errors fmt hello io math os reflect runtime strconv sync sync/atomic syscall time unicode/utf8 unsafe]
+	// strconv.Files: [atob.go atof.go atoi.go decimal.go doc.go extfloat.go ftoa.go isprint.go itoa.go quote.go]
+}
+
+// This example imports three packages, including the tests for one of
+// them, and loads all their dependencies.
+func ExampleConfig_Import() {
+	// ImportWithTest("strconv") causes strconv to include
+	// internal_test.go, and creates an external test package,
+	// strconv_test.
+	// (Compare with the example of CreateFromFiles.)
+
+	var conf loader.Config
+	conf.Import("unicode/utf8")
+	conf.Import("errors")
+	conf.ImportWithTests("strconv")
+	prog, err := conf.Load()
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	printProgram(prog)
+	printFilenames(prog.Fset, prog.Package("strconv"))
+	printFilenames(prog.Fset, prog.Package("strconv_test"))
+	// Output:
+	// created: [strconv_test]
+	// imported: [errors strconv unicode/utf8]
+	// initial: [errors strconv strconv_test unicode/utf8]
+	// all: [bufio bytes errors flag fmt io log math math/rand os reflect runtime runtime/pprof runtime/trace sort strconv strconv_test strings sync sync/atomic syscall testing text/tabwriter time unicode unicode/utf8 unsafe]
+	// strconv.Files: [atob.go atof.go atoi.go decimal.go doc.go extfloat.go ftoa.go isprint.go itoa.go quote.go internal_test.go]
+	// strconv_test.Files: [atob_test.go atof_test.go atoi_test.go decimal_test.go example_test.go fp_test.go ftoa_test.go itoa_test.go quote_test.go strconv_test.go]
+}
diff --git a/go/src/golang.org/x/tools/go/loader/example_test.go b/go/src/golang.org/x/tools/go/loader/example_test.go
index ce5afdb..66ddb92 100644
--- a/go/src/golang.org/x/tools/go/loader/example_test.go
+++ b/go/src/golang.org/x/tools/go/loader/example_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build go1.5
+// +build go1.6
 // +build !windows
 
 package loader_test
@@ -14,6 +14,7 @@
 	"path/filepath"
 	"runtime"
 	"sort"
+	"strings"
 
 	"golang.org/x/tools/go/loader"
 )
@@ -31,6 +32,9 @@
 	// call to Import or ImportWithTests.
 	names = nil
 	for _, info := range prog.Imported {
+		if strings.Contains(info.Pkg.Path(), "internal") {
+			continue // skip, to reduce fragility
+		}
 		names = append(names, info.Pkg.Path())
 	}
 	sort.Strings(names)
@@ -83,7 +87,7 @@
 	// created: []
 	// imported: [errors runtime unicode/utf8]
 	// initial: [errors runtime unicode/utf8]
-	// all: [errors runtime unicode/utf8]
+	// all: [errors runtime runtime/internal/atomic runtime/internal/sys unicode/utf8 unsafe]
 }
 
 // This example creates and type-checks a single package (without tests)
@@ -139,7 +143,7 @@
 	// created: [hello]
 	// imported: []
 	// initial: [hello]
-	// all: [errors fmt hello io math os reflect runtime strconv sync sync/atomic syscall time unicode/utf8]
+	// all: [errors fmt hello internal/race io math os reflect runtime runtime/internal/atomic runtime/internal/sys strconv sync sync/atomic syscall time unicode/utf8 unsafe]
 	// strconv.Files: [atob.go atof.go atoi.go decimal.go doc.go extfloat.go ftoa.go isprint.go itoa.go quote.go]
 }
 
@@ -167,7 +171,7 @@
 	// created: [strconv_test]
 	// imported: [errors strconv unicode/utf8]
 	// initial: [errors strconv strconv_test unicode/utf8]
-	// all: [bufio bytes errors flag fmt io log math math/rand os reflect runtime runtime/pprof runtime/trace sort strconv strconv_test strings sync sync/atomic syscall testing text/tabwriter time unicode unicode/utf8]
+	// all: [bufio bytes errors flag fmt internal/race io log math math/rand os reflect runtime runtime/debug runtime/internal/atomic runtime/internal/sys runtime/pprof runtime/trace sort strconv strconv_test strings sync sync/atomic syscall testing text/tabwriter time unicode unicode/utf8 unsafe]
 	// strconv.Files: [atob.go atof.go atoi.go decimal.go doc.go extfloat.go ftoa.go isprint.go itoa.go quote.go internal_test.go]
 	// strconv_test.Files: [atob_test.go atof_test.go atoi_test.go decimal_test.go example_test.go fp_test.go ftoa_test.go itoa_test.go quote_test.go strconv_test.go]
 }
diff --git a/go/src/golang.org/x/tools/go/loader/go16.go b/go/src/golang.org/x/tools/go/loader/go16.go
new file mode 100644
index 0000000..c0ed50f
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/loader/go16.go
@@ -0,0 +1,13 @@
+// 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.
+
+// +build go1.6
+
+package loader
+
+import "go/build"
+
+func init() {
+	ignoreVendor = build.IgnoreVendor
+}
diff --git a/go/src/golang.org/x/tools/go/loader/go16_test.go b/go/src/golang.org/x/tools/go/loader/go16_test.go
new file mode 100644
index 0000000..71f89b2
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/loader/go16_test.go
@@ -0,0 +1,12 @@
+// 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.
+
+// +build go1.6
+// +build !android
+
+package loader_test
+
+func init() {
+	go16 = true
+}
diff --git a/go/src/golang.org/x/tools/go/loader/loader.go b/go/src/golang.org/x/tools/go/loader/loader.go
index 1d3ead0..b0f8336 100644
--- a/go/src/golang.org/x/tools/go/loader/loader.go
+++ b/go/src/golang.org/x/tools/go/loader/loader.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package loader
 
 // See doc.go for package documentation and implementation notes.
@@ -13,6 +15,7 @@
 	"go/build"
 	"go/parser"
 	"go/token"
+	"go/types"
 	"os"
 	"sort"
 	"strings"
@@ -20,9 +23,10 @@
 	"time"
 
 	"golang.org/x/tools/go/ast/astutil"
-	"golang.org/x/tools/go/types"
 )
 
+var ignoreVendor build.ImportMode
+
 const trace = false // show timing info for type-checking
 
 // Config specifies the configuration for loading a whole program from
@@ -45,13 +49,13 @@
 	// The supplied Import function is not used either.
 	TypeChecker types.Config
 
-	// TypeCheckFuncBodies is a predicate over package import
-	// paths.  A package for which the predicate is false will
+	// TypeCheckFuncBodies is a predicate over package paths.
+	// A package for which the predicate is false will
 	// have its package-level declarations type checked, but not
 	// its function bodies; this can be used to quickly load
 	// dependencies from source.  If nil, all func bodies are type
 	// checked.
-	TypeCheckFuncBodies func(string) bool
+	TypeCheckFuncBodies func(path string) bool
 
 	// If Build is non-nil, it is used to locate source packages.
 	// Otherwise &build.Default is used.
@@ -84,9 +88,8 @@
 	// the corresponding elements of the Program.Created slice.
 	CreatePkgs []PkgSpec
 
-	// ImportPkgs specifies a set of initial packages to load from
-	// source.  The map keys are package import paths, used to
-	// locate the package relative to $GOROOT.
+	// ImportPkgs specifies a set of initial packages to load.
+	// The map keys are package paths.
 	//
 	// The map value indicates whether to load tests.  If true, Load
 	// will add and type-check two lists of files to the package:
@@ -96,13 +99,14 @@
 	ImportPkgs map[string]bool
 
 	// FindPackage is called during Load to create the build.Package
-	// for a given import path.  If nil, a default implementation
-	// based on ctxt.Import is used.  A client may use this hook to
-	// adapt to a proprietary build system that does not follow the
-	// "go build" layout conventions, for example.
+	// for a given import path from a given directory.
+	// If FindPackage is nil, (*build.Context).Import is used.
+	// A client may use this hook to adapt to a proprietary build
+	// system that does not follow the "go build" layout
+	// conventions, for example.
 	//
 	// It must be safe to call concurrently from multiple goroutines.
-	FindPackage func(ctxt *build.Context, importPath string) (*build.Package, error)
+	FindPackage func(ctxt *build.Context, fromDir, importPath string, mode build.ImportMode) (*build.Package, error)
 }
 
 // A PkgSpec specifies a non-importable package to be created by Load.
@@ -110,7 +114,7 @@
 // Filenames is provided.  The path needn't be globally unique.
 //
 type PkgSpec struct {
-	Path      string      // import path ("" => use package declaration)
+	Path      string      // package path ("" => use package declaration)
 	Files     []*ast.File // ASTs of already-parsed files
 	Filenames []string    // names of files to be parsed
 }
@@ -123,6 +127,15 @@
 	// filenames were supplied by Config.CreatePkgs[i], followed by
 	// the external test package, if any, of each package in
 	// Config.ImportPkgs ordered by ImportPath.
+	//
+	// NOTE: these files must not import "C".  Cgo preprocessing is
+	// only performed on imported packages, not ad hoc packages.
+	//
+	// TODO(adonovan): we need to copy and adapt the logic of
+	// goFilesPackage (from $GOROOT/src/cmd/go/build.go) and make
+	// Config.Import and Config.Create methods return the same kind
+	// of entity, essentially a build.Package.
+	// Perhaps we can even reuse that type directly.
 	Created []*PackageInfo
 
 	// Imported contains the initially imported packages,
@@ -134,7 +147,7 @@
 	// dependencies, including incomplete ones.
 	AllPackages map[*types.Package]*PackageInfo
 
-	// importMap is the canonical mapping of import paths to
+	// importMap is the canonical mapping of package paths to
 	// packages.  It contains all Imported initial packages, but not
 	// Created ones, and all imported dependencies.
 	importMap map[string]*types.Package
@@ -152,6 +165,7 @@
 	Files                 []*ast.File // syntax trees for the package's files
 	Errors                []error     // non-nil if the package had errors
 	types.Info                        // type-checker deductions.
+	dir                   string      // package directory
 
 	checker   *types.Checker // transient type-checker state
 	errorFunc func(error)
@@ -294,7 +308,7 @@
 func (conf *Config) Import(path string) { conf.addImport(path, false) }
 
 func (conf *Config) addImport(path string, tests bool) {
-	if path == "C" || path == "unsafe" {
+	if path == "C" {
 		return // ignore; not a real package
 	}
 	if conf.ImportPkgs == nil {
@@ -366,6 +380,10 @@
 	progMu sync.Mutex // guards prog
 	prog   *Program   // the resulting program
 
+	// findpkg is a memoization of FindPackage.
+	findpkgMu sync.Mutex // guards findpkg
+	findpkg   map[findpkgKey]*findpkgValue
+
 	importedMu sync.Mutex             // guards imported
 	imported   map[string]*importInfo // all imported packages (incl. failures) by import path
 
@@ -378,6 +396,18 @@
 	graph   map[string]map[string]bool
 }
 
+type findpkgKey struct {
+	importPath string
+	fromDir    string
+	mode       build.ImportMode
+}
+
+type findpkgValue struct {
+	ready chan struct{} // closed to broadcast readiness
+	bp    *build.Package
+	err   error
+}
+
 // importInfo tracks the success or failure of a single import.
 //
 // Upon completion, exactly one of info and err is non-nil:
@@ -385,35 +415,30 @@
 // A successful package may still contain type errors.
 //
 type importInfo struct {
-	path     string       // import path
-	mu       sync.Mutex   // guards the following fields prior to completion
-	info     *PackageInfo // results of typechecking (including errors)
-	err      error        // reason for failure to create a package
-	complete sync.Cond    // complete condition is that one of info, err is non-nil.
+	path     string        // import path
+	info     *PackageInfo  // results of typechecking (including errors)
+	complete chan struct{} // closed to broadcast that info is set.
 }
 
 // awaitCompletion blocks until ii is complete,
-// i.e. the info and err fields are safe to inspect without a lock.
-// It is concurrency-safe and idempotent.
+// i.e. the info field is safe to inspect.
 func (ii *importInfo) awaitCompletion() {
-	ii.mu.Lock()
-	for ii.info == nil && ii.err == nil {
-		ii.complete.Wait()
-	}
-	ii.mu.Unlock()
+	<-ii.complete // wait for close
 }
 
 // Complete marks ii as complete.
 // Its info and err fields will not be subsequently updated.
-func (ii *importInfo) Complete(info *PackageInfo, err error) {
-	if info == nil && err == nil {
-		panic("Complete(nil, nil)")
+func (ii *importInfo) Complete(info *PackageInfo) {
+	if info == nil {
+		panic("info == nil")
 	}
-	ii.mu.Lock()
 	ii.info = info
-	ii.err = err
-	ii.complete.Broadcast()
-	ii.mu.Unlock()
+	close(ii.complete)
+}
+
+type importError struct {
+	path string // import path
+	err  error  // reason for failure to create a package
 }
 
 // Load creates the initial packages specified by conf.{Create,Import}Pkgs,
@@ -446,17 +471,7 @@
 
 	// Install default FindPackage hook using go/build logic.
 	if conf.FindPackage == nil {
-		conf.FindPackage = func(ctxt *build.Context, path string) (*build.Package, error) {
-			// TODO(adonovan): cache calls to build.Import
-			// so we don't do it three times per test package.
-			ioLimit <- true
-			bp, err := ctxt.Import(path, conf.Cwd, 0)
-			<-ioLimit
-			if _, ok := err.(*build.NoGoError); ok {
-				return bp, nil // empty directory is not an error
-			}
-			return bp, err
-		}
+		conf.FindPackage = (*build.Context).Import
 	}
 
 	prog := &Program{
@@ -469,6 +484,7 @@
 	imp := importer{
 		conf:     conf,
 		prog:     prog,
+		findpkg:  make(map[findpkgKey]*findpkgValue),
 		imported: make(map[string]*importInfo),
 		start:    time.Now(),
 		graph:    make(map[string]map[string]bool),
@@ -480,24 +496,26 @@
 
 	// Load the initially imported packages and their dependencies,
 	// in parallel.
-	for _, ii := range imp.loadAll("", conf.ImportPkgs) {
-		if ii.err != nil {
-			conf.TypeChecker.Error(ii.err) // failed to create package
-			errpkgs = append(errpkgs, ii.path)
-			continue
-		}
-		prog.Imported[ii.info.Pkg.Path()] = ii.info
+	// No vendor check on packages imported from the command line.
+	infos, importErrors := imp.importAll("", conf.Cwd, conf.ImportPkgs, ignoreVendor)
+	for _, ie := range importErrors {
+		conf.TypeChecker.Error(ie.err) // failed to create package
+		errpkgs = append(errpkgs, ie.path)
+	}
+	for _, info := range infos {
+		prog.Imported[info.Pkg.Path()] = info
 	}
 
 	// Augment the designated initial packages by their tests.
 	// Dependencies are loaded in parallel.
 	var xtestPkgs []*build.Package
-	for path, augment := range conf.ImportPkgs {
+	for importPath, augment := range conf.ImportPkgs {
 		if !augment {
 			continue
 		}
 
-		bp, err := conf.FindPackage(conf.build(), path)
+		// No vendor check on packages imported from command line.
+		bp, err := imp.findPackage(importPath, conf.Cwd, ignoreVendor)
 		if err != nil {
 			// Package not found, or can't even parse package declaration.
 			// Already reported by previous loop; ignore it.
@@ -509,12 +527,14 @@
 			xtestPkgs = append(xtestPkgs, bp)
 		}
 
+		// Consult the cache using the canonical package path.
+		path := bp.ImportPath
 		imp.importedMu.Lock() // (unnecessary, we're sequential here)
 		ii, ok := imp.imported[path]
 		// Paranoid checks added due to issue #11012.
 		if !ok {
 			// Unreachable.
-			// The previous loop called loadAll and thus
+			// The previous loop called importAll and thus
 			// startLoad for each path in ImportPkgs, which
 			// populates imp.imported[path] with a non-zero value.
 			panic(fmt.Sprintf("imported[%q] not found", path))
@@ -526,19 +546,10 @@
 			// that at least one of ii.err and ii.info is non-nil.
 			panic(fmt.Sprintf("imported[%q] == nil", path))
 		}
-		if ii.err != nil {
-			// The sole possible cause is failure of the
-			// FindPackage call in (*importer).load,
-			// but we rechecked that condition above.
-			// Perhaps the state of the file system changed
-			// in between?  Seems unlikely.
-			panic(fmt.Sprintf("imported[%q].err = %v", path, ii.err))
-		}
 		if ii.info == nil {
 			// Unreachable.
-			// Complete has this postcondition:
-			// 	ii.err != nil || ii.info != nil
-			// and we know that ii.err == nil here.
+			// awaitCompletion has the postcondition
+			// ii.info != nil.
 			panic(fmt.Sprintf("imported[%q].info = nil", path))
 		}
 		info := ii.info
@@ -557,7 +568,8 @@
 	}
 
 	createPkg := func(path string, files []*ast.File, errs []error) {
-		info := imp.newPackageInfo(path)
+		// TODO(adonovan): fix: use dirname of files, not cwd.
+		info := imp.newPackageInfo(path, conf.Cwd)
 		for _, err := range errs {
 			info.appendError(err)
 		}
@@ -699,6 +711,9 @@
 //    'x': include external *_test.go source files. (XTestGoFiles)
 //
 func (conf *Config) parsePackageFiles(bp *build.Package, which rune) ([]*ast.File, []error) {
+	if bp.Goroot && bp.ImportPath == "unsafe" {
+		return nil, nil
+	}
 	var filenames []string
 	switch which {
 	case 'g':
@@ -729,8 +744,6 @@
 // doImport imports the package denoted by path.
 // It implements the types.Importer signature.
 //
-// imports is the type-checker's package canonicalization map.
-//
 // It returns an error if a package could not be created
 // (e.g. go/build or parse error), but type errors are reported via
 // the types.Config.Error callback (the first of which is also saved
@@ -739,11 +752,6 @@
 // Idempotent.
 //
 func (imp *importer) doImport(from *PackageInfo, to string) (*types.Package, error) {
-	// Package unsafe is handled specially, and has no PackageInfo.
-	// TODO(adonovan): move this check into go/types?
-	if to == "unsafe" {
-		return types.Unsafe, nil
-	}
 	if to == "C" {
 		// This should be unreachable, but ad hoc packages are
 		// not currently subject to cgo preprocessing.
@@ -752,14 +760,24 @@
 			from.Pkg.Path())
 	}
 
+	bp, err := imp.findPackage(to, from.dir, 0)
+	if err != nil {
+		return nil, err
+	}
+
+	// The standard unsafe package is handled specially,
+	// and has no PackageInfo.
+	if bp.Goroot && bp.ImportPath == "unsafe" {
+		return types.Unsafe, nil
+	}
+
+	// Look for the package in the cache using its canonical path.
+	path := bp.ImportPath
 	imp.importedMu.Lock()
-	ii := imp.imported[to]
+	ii := imp.imported[path]
 	imp.importedMu.Unlock()
 	if ii == nil {
-		panic("internal error: unexpected import: " + to)
-	}
-	if ii.err != nil {
-		return nil, ii.err
+		panic("internal error: unexpected import: " + path)
 	}
 	if ii.info != nil {
 		return ii.info.Pkg, nil
@@ -767,7 +785,7 @@
 
 	// Import of incomplete package: this indicates a cycle.
 	fromPath := from.Pkg.Path()
-	if cycle := imp.findPath(to, fromPath); cycle != nil {
+	if cycle := imp.findPath(path, fromPath); cycle != nil {
 		cycle = append([]string{fromPath}, cycle...)
 		return nil, fmt.Errorf("import cycle: %s", strings.Join(cycle, " -> "))
 	}
@@ -775,16 +793,62 @@
 	panic("internal error: import of incomplete (yet acyclic) package: " + fromPath)
 }
 
-// loadAll loads, parses, and type-checks the specified packages in
+// findPackage locates the package denoted by the importPath in the
+// specified directory.
+func (imp *importer) findPackage(importPath, fromDir string, mode build.ImportMode) (*build.Package, error) {
+	// We use a non-blocking duplicate-suppressing cache (gopl.io §9.7)
+	// to avoid holding the lock around FindPackage.
+	key := findpkgKey{importPath, fromDir, mode}
+	imp.findpkgMu.Lock()
+	v, ok := imp.findpkg[key]
+	if ok {
+		// cache hit
+		imp.findpkgMu.Unlock()
+
+		<-v.ready // wait for entry to become ready
+	} else {
+		// Cache miss: this goroutine becomes responsible for
+		// populating the map entry and broadcasting its readiness.
+		v = &findpkgValue{ready: make(chan struct{})}
+		imp.findpkg[key] = v
+		imp.findpkgMu.Unlock()
+
+		ioLimit <- true
+		v.bp, v.err = imp.conf.FindPackage(imp.conf.build(), importPath, fromDir, mode)
+		<-ioLimit
+
+		if _, ok := v.err.(*build.NoGoError); ok {
+			v.err = nil // empty directory is not an error
+		}
+
+		close(v.ready) // broadcast ready condition
+	}
+	return v.bp, v.err
+}
+
+// importAll loads, parses, and type-checks the specified packages in
 // parallel and returns their completed importInfos in unspecified order.
 //
-// fromPath is the import path of the importing package, if it is
+// fromPath is the package path of the importing package, if it is
 // importable, "" otherwise.  It is used for cycle detection.
 //
-func (imp *importer) loadAll(fromPath string, paths map[string]bool) []*importInfo {
-	result := make([]*importInfo, 0, len(paths))
-	for path := range paths {
-		result = append(result, imp.startLoad(path))
+// fromDir is the directory containing the import declaration that
+// caused these imports.
+//
+func (imp *importer) importAll(fromPath, fromDir string, imports map[string]bool, mode build.ImportMode) (infos []*PackageInfo, errors []importError) {
+	// TODO(adonovan): opt: do the loop in parallel once
+	// findPackage is non-blocking.
+	var pending []*importInfo
+	for importPath := range imports {
+		bp, err := imp.findPackage(importPath, fromDir, mode)
+		if err != nil {
+			errors = append(errors, importError{
+				path: importPath,
+				err:  err,
+			})
+			continue
+		}
+		pending = append(pending, imp.startLoad(bp))
 	}
 
 	if fromPath != "" {
@@ -798,13 +862,13 @@
 			deps = make(map[string]bool)
 			imp.graph[fromPath] = deps
 		}
-		for path := range paths {
-			deps[path] = true
+		for _, ii := range pending {
+			deps[ii.path] = true
 		}
 		imp.graphMu.Unlock()
 	}
 
-	for _, ii := range result {
+	for _, ii := range pending {
 		if fromPath != "" {
 			if cycle := imp.findPath(ii.path, fromPath); cycle != nil {
 				// Cycle-forming import: we must not await its
@@ -822,8 +886,10 @@
 			}
 		}
 		ii.awaitCompletion()
+		infos = append(infos, ii.info)
 	}
-	return result
+
+	return infos, errors
 }
 
 // findPath returns an arbitrary path from 'from' to 'to' in the import
@@ -856,20 +922,20 @@
 // specified package and its dependencies, if it has not already begun.
 //
 // It returns an importInfo, not necessarily in a completed state.  The
-// caller must call awaitCompletion() before accessing its info and err
-// fields.
+// caller must call awaitCompletion() before accessing its info field.
 //
 // startLoad is concurrency-safe and idempotent.
 //
-func (imp *importer) startLoad(path string) *importInfo {
+func (imp *importer) startLoad(bp *build.Package) *importInfo {
+	path := bp.ImportPath
 	imp.importedMu.Lock()
 	ii, ok := imp.imported[path]
 	if !ok {
-		ii = &importInfo{path: path}
-		ii.complete.L = &ii.mu
+		ii = &importInfo{path: path, complete: make(chan struct{})}
 		imp.imported[path] = ii
 		go func() {
-			ii.Complete(imp.load(path))
+			info := imp.load(bp)
+			ii.Complete(info)
 		}()
 	}
 	imp.importedMu.Unlock()
@@ -879,13 +945,8 @@
 
 // load implements package loading by parsing Go source files
 // located by go/build.
-//
-func (imp *importer) load(path string) (*PackageInfo, error) {
-	bp, err := imp.conf.FindPackage(imp.conf.build(), path)
-	if err != nil {
-		return nil, err // package not found
-	}
-	info := imp.newPackageInfo(bp.ImportPath)
+func (imp *importer) load(bp *build.Package) *PackageInfo {
+	info := imp.newPackageInfo(bp.ImportPath, bp.Dir)
 	info.Importable = true
 	files, errs := imp.conf.parsePackageFiles(bp, 'g')
 	for _, err := range errs {
@@ -895,10 +956,10 @@
 	imp.addFiles(info, files, true)
 
 	imp.progMu.Lock()
-	imp.prog.importMap[path] = info.Pkg
+	imp.prog.importMap[bp.ImportPath] = info.Pkg
 	imp.progMu.Unlock()
 
-	return info, nil
+	return info
 }
 
 // addFiles adds and type-checks the specified files to info, loading
@@ -917,7 +978,9 @@
 	if cycleCheck {
 		fromPath = info.Pkg.Path()
 	}
-	imp.loadAll(fromPath, scanImports(files))
+	// TODO(adonovan): opt: make the caller do scanImports.
+	// Callers with a build.Package can skip it.
+	imp.importAll(fromPath, info.dir, scanImports(files), 0)
 
 	if trace {
 		fmt.Fprintf(os.Stderr, "%s: start %q (%d)\n",
@@ -934,7 +997,7 @@
 	}
 }
 
-func (imp *importer) newPackageInfo(path string) *PackageInfo {
+func (imp *importer) newPackageInfo(path, dir string) *PackageInfo {
 	pkg := types.NewPackage(path, "")
 	info := &PackageInfo{
 		Pkg: pkg,
@@ -947,6 +1010,7 @@
 			Selections: make(map[*ast.SelectorExpr]*types.Selection),
 		},
 		errorFunc: imp.conf.TypeChecker.Error,
+		dir:       dir,
 	}
 
 	// Copy the types.Config so we can vary it across PackageInfos.
@@ -955,9 +1019,7 @@
 	if f := imp.conf.TypeCheckFuncBodies; f != nil {
 		tc.IgnoreFuncBodies = !f(path)
 	}
-	tc.Import = func(_ map[string]*types.Package, to string) (*types.Package, error) {
-		return imp.doImport(info, to)
-	}
+	tc.Importer = closure{imp, info}
 	tc.Error = info.appendError // appendError wraps the user's Error function
 
 	info.checker = types.NewChecker(&tc, imp.conf.fset(), pkg, &info.Info)
@@ -966,3 +1028,10 @@
 	imp.progMu.Unlock()
 	return info
 }
+
+type closure struct {
+	imp  *importer
+	info *PackageInfo
+}
+
+func (c closure) Import(to string) (*types.Package, error) { return c.imp.doImport(c.info, to) }
diff --git a/go/src/golang.org/x/tools/go/loader/loader14.go b/go/src/golang.org/x/tools/go/loader/loader14.go
new file mode 100644
index 0000000..d3fb157
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/loader/loader14.go
@@ -0,0 +1,1019 @@
+// 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.
+
+// +build !go1.5
+
+package loader
+
+// See doc.go for package documentation and implementation notes.
+
+import (
+	"errors"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/parser"
+	"go/token"
+	"os"
+	"sort"
+	"strings"
+	"sync"
+	"time"
+
+	"golang.org/x/tools/go/ast/astutil"
+	"golang.org/x/tools/go/types"
+)
+
+const trace = false // show timing info for type-checking
+
+// Config specifies the configuration for loading a whole program from
+// Go source code.
+// The zero value for Config is a ready-to-use default configuration.
+type Config struct {
+	// Fset is the file set for the parser to use when loading the
+	// program.  If nil, it may be lazily initialized by any
+	// method of Config.
+	Fset *token.FileSet
+
+	// ParserMode specifies the mode to be used by the parser when
+	// loading source packages.
+	ParserMode parser.Mode
+
+	// TypeChecker contains options relating to the type checker.
+	//
+	// The supplied IgnoreFuncBodies is not used; the effective
+	// value comes from the TypeCheckFuncBodies func below.
+	// The supplied Import function is not used either.
+	TypeChecker types.Config
+
+	// TypeCheckFuncBodies is a predicate over package paths.
+	// A package for which the predicate is false will
+	// have its package-level declarations type checked, but not
+	// its function bodies; this can be used to quickly load
+	// dependencies from source.  If nil, all func bodies are type
+	// checked.
+	TypeCheckFuncBodies func(path string) bool
+
+	// If Build is non-nil, it is used to locate source packages.
+	// Otherwise &build.Default is used.
+	//
+	// By default, cgo is invoked to preprocess Go files that
+	// import the fake package "C".  This behaviour can be
+	// disabled by setting CGO_ENABLED=0 in the environment prior
+	// to startup, or by setting Build.CgoEnabled=false.
+	Build *build.Context
+
+	// The current directory, used for resolving relative package
+	// references such as "./go/loader".  If empty, os.Getwd will be
+	// used instead.
+	Cwd string
+
+	// If DisplayPath is non-nil, it is used to transform each
+	// file name obtained from Build.Import().  This can be used
+	// to prevent a virtualized build.Config's file names from
+	// leaking into the user interface.
+	DisplayPath func(path string) string
+
+	// If AllowErrors is true, Load will return a Program even
+	// if some of the its packages contained I/O, parser or type
+	// errors; such errors are accessible via PackageInfo.Errors.  If
+	// false, Load will fail if any package had an error.
+	AllowErrors bool
+
+	// CreatePkgs specifies a list of non-importable initial
+	// packages to create.  The resulting packages will appear in
+	// the corresponding elements of the Program.Created slice.
+	CreatePkgs []PkgSpec
+
+	// ImportPkgs specifies a set of initial packages to load.
+	// The map keys are package paths.
+	//
+	// The map value indicates whether to load tests.  If true, Load
+	// will add and type-check two lists of files to the package:
+	// non-test files followed by in-package *_test.go files.  In
+	// addition, it will append the external test package (if any)
+	// to Program.Created.
+	ImportPkgs map[string]bool
+
+	// FindPackage is called during Load to create the build.Package
+	// for a given import path from a given directory.
+	// If FindPackage is nil, a default implementation
+	// based on ctxt.Import is used.  A client may use this hook to
+	// adapt to a proprietary build system that does not follow the
+	// "go build" layout conventions, for example.
+	//
+	// It must be safe to call concurrently from multiple goroutines.
+	FindPackage func(ctxt *build.Context, fromDir, importPath string, mode build.ImportMode) (*build.Package, error)
+}
+
+// A PkgSpec specifies a non-importable package to be created by Load.
+// Files are processed first, but typically only one of Files and
+// Filenames is provided.  The path needn't be globally unique.
+//
+type PkgSpec struct {
+	Path      string      // package path ("" => use package declaration)
+	Files     []*ast.File // ASTs of already-parsed files
+	Filenames []string    // names of files to be parsed
+}
+
+// A Program is a Go program loaded from source as specified by a Config.
+type Program struct {
+	Fset *token.FileSet // the file set for this program
+
+	// Created[i] contains the initial package whose ASTs or
+	// filenames were supplied by Config.CreatePkgs[i], followed by
+	// the external test package, if any, of each package in
+	// Config.ImportPkgs ordered by ImportPath.
+	//
+	// NOTE: these files must not import "C".  Cgo preprocessing is
+	// only performed on imported packages, not ad hoc packages.
+	//
+	// TODO(adonovan): we need to copy and adapt the logic of
+	// goFilesPackage (from $GOROOT/src/cmd/go/build.go) and make
+	// Config.Import and Config.Create methods return the same kind
+	// of entity, essentially a build.Package.
+	// Perhaps we can even reuse that type directly.
+	Created []*PackageInfo
+
+	// Imported contains the initially imported packages,
+	// as specified by Config.ImportPkgs.
+	Imported map[string]*PackageInfo
+
+	// AllPackages contains the PackageInfo of every package
+	// encountered by Load: all initial packages and all
+	// dependencies, including incomplete ones.
+	AllPackages map[*types.Package]*PackageInfo
+
+	// importMap is the canonical mapping of package paths to
+	// packages.  It contains all Imported initial packages, but not
+	// Created ones, and all imported dependencies.
+	importMap map[string]*types.Package
+}
+
+// PackageInfo holds the ASTs and facts derived by the type-checker
+// for a single package.
+//
+// Not mutated once exposed via the API.
+//
+type PackageInfo struct {
+	Pkg                   *types.Package
+	Importable            bool        // true if 'import "Pkg.Path()"' would resolve to this
+	TransitivelyErrorFree bool        // true if Pkg and all its dependencies are free of errors
+	Files                 []*ast.File // syntax trees for the package's files
+	Errors                []error     // non-nil if the package had errors
+	types.Info                        // type-checker deductions.
+	dir                   string      // package directory
+
+	checker   *types.Checker // transient type-checker state
+	errorFunc func(error)
+}
+
+func (info *PackageInfo) String() string { return info.Pkg.Path() }
+
+func (info *PackageInfo) appendError(err error) {
+	if info.errorFunc != nil {
+		info.errorFunc(err)
+	} else {
+		fmt.Fprintln(os.Stderr, err)
+	}
+	info.Errors = append(info.Errors, err)
+}
+
+func (conf *Config) fset() *token.FileSet {
+	if conf.Fset == nil {
+		conf.Fset = token.NewFileSet()
+	}
+	return conf.Fset
+}
+
+// ParseFile is a convenience function (intended for testing) that invokes
+// the parser using the Config's FileSet, which is initialized if nil.
+//
+// src specifies the parser input as a string, []byte, or io.Reader, and
+// filename is its apparent name.  If src is nil, the contents of
+// filename are read from the file system.
+//
+func (conf *Config) ParseFile(filename string, src interface{}) (*ast.File, error) {
+	// TODO(adonovan): use conf.build() etc like parseFiles does.
+	return parser.ParseFile(conf.fset(), filename, src, conf.ParserMode)
+}
+
+// FromArgsUsage is a partial usage message that applications calling
+// FromArgs may wish to include in their -help output.
+const FromArgsUsage = `
+<args> is a list of arguments denoting a set of initial packages.
+It may take one of two forms:
+
+1. A list of *.go source files.
+
+   All of the specified files are loaded, parsed and type-checked
+   as a single package.  All the files must belong to the same directory.
+
+2. A list of import paths, each denoting a package.
+
+   The package's directory is found relative to the $GOROOT and
+   $GOPATH using similar logic to 'go build', and the *.go files in
+   that directory are loaded, parsed and type-checked as a single
+   package.
+
+   In addition, all *_test.go files in the directory are then loaded
+   and parsed.  Those files whose package declaration equals that of
+   the non-*_test.go files are included in the primary package.  Test
+   files whose package declaration ends with "_test" are type-checked
+   as another package, the 'external' test package, so that a single
+   import path may denote two packages.  (Whether this behaviour is
+   enabled is tool-specific, and may depend on additional flags.)
+
+A '--' argument terminates the list of packages.
+`
+
+// FromArgs interprets args as a set of initial packages to load from
+// source and updates the configuration.  It returns the list of
+// unconsumed arguments.
+//
+// It is intended for use in command-line interfaces that require a
+// set of initial packages to be specified; see FromArgsUsage message
+// for details.
+//
+// Only superficial errors are reported at this stage; errors dependent
+// on I/O are detected during Load.
+//
+func (conf *Config) FromArgs(args []string, xtest bool) ([]string, error) {
+	var rest []string
+	for i, arg := range args {
+		if arg == "--" {
+			rest = args[i+1:]
+			args = args[:i]
+			break // consume "--" and return the remaining args
+		}
+	}
+
+	if len(args) > 0 && strings.HasSuffix(args[0], ".go") {
+		// Assume args is a list of a *.go files
+		// denoting a single ad hoc package.
+		for _, arg := range args {
+			if !strings.HasSuffix(arg, ".go") {
+				return nil, fmt.Errorf("named files must be .go files: %s", arg)
+			}
+		}
+		conf.CreateFromFilenames("", args...)
+	} else {
+		// Assume args are directories each denoting a
+		// package and (perhaps) an external test, iff xtest.
+		for _, arg := range args {
+			if xtest {
+				conf.ImportWithTests(arg)
+			} else {
+				conf.Import(arg)
+			}
+		}
+	}
+
+	return rest, nil
+}
+
+// CreateFromFilenames is a convenience function that adds
+// a conf.CreatePkgs entry to create a package of the specified *.go
+// files.
+//
+func (conf *Config) CreateFromFilenames(path string, filenames ...string) {
+	conf.CreatePkgs = append(conf.CreatePkgs, PkgSpec{Path: path, Filenames: filenames})
+}
+
+// CreateFromFiles is a convenience function that adds a conf.CreatePkgs
+// entry to create package of the specified path and parsed files.
+//
+func (conf *Config) CreateFromFiles(path string, files ...*ast.File) {
+	conf.CreatePkgs = append(conf.CreatePkgs, PkgSpec{Path: path, Files: files})
+}
+
+// ImportWithTests is a convenience function that adds path to
+// ImportPkgs, the set of initial source packages located relative to
+// $GOPATH.  The package will be augmented by any *_test.go files in
+// its directory that contain a "package x" (not "package x_test")
+// declaration.
+//
+// In addition, if any *_test.go files contain a "package x_test"
+// declaration, an additional package comprising just those files will
+// be added to CreatePkgs.
+//
+func (conf *Config) ImportWithTests(path string) { conf.addImport(path, true) }
+
+// Import is a convenience function that adds path to ImportPkgs, the
+// set of initial packages that will be imported from source.
+//
+func (conf *Config) Import(path string) { conf.addImport(path, false) }
+
+func (conf *Config) addImport(path string, tests bool) {
+	if path == "C" {
+		return // ignore; not a real package
+	}
+	if conf.ImportPkgs == nil {
+		conf.ImportPkgs = make(map[string]bool)
+	}
+	conf.ImportPkgs[path] = conf.ImportPkgs[path] || tests
+}
+
+// PathEnclosingInterval returns the PackageInfo and ast.Node that
+// contain source interval [start, end), and all the node's ancestors
+// up to the AST root.  It searches all ast.Files of all packages in prog.
+// exact is defined as for astutil.PathEnclosingInterval.
+//
+// The zero value is returned if not found.
+//
+func (prog *Program) PathEnclosingInterval(start, end token.Pos) (pkg *PackageInfo, path []ast.Node, exact bool) {
+	for _, info := range prog.AllPackages {
+		for _, f := range info.Files {
+			if f.Pos() == token.NoPos {
+				// This can happen if the parser saw
+				// too many errors and bailed out.
+				// (Use parser.AllErrors to prevent that.)
+				continue
+			}
+			if !tokenFileContainsPos(prog.Fset.File(f.Pos()), start) {
+				continue
+			}
+			if path, exact := astutil.PathEnclosingInterval(f, start, end); path != nil {
+				return info, path, exact
+			}
+		}
+	}
+	return nil, nil, false
+}
+
+// InitialPackages returns a new slice containing the set of initial
+// packages (Created + Imported) in unspecified order.
+//
+func (prog *Program) InitialPackages() []*PackageInfo {
+	infos := make([]*PackageInfo, 0, len(prog.Created)+len(prog.Imported))
+	infos = append(infos, prog.Created...)
+	for _, info := range prog.Imported {
+		infos = append(infos, info)
+	}
+	return infos
+}
+
+// Package returns the ASTs and results of type checking for the
+// specified package.
+func (prog *Program) Package(path string) *PackageInfo {
+	if info, ok := prog.AllPackages[prog.importMap[path]]; ok {
+		return info
+	}
+	for _, info := range prog.Created {
+		if path == info.Pkg.Path() {
+			return info
+		}
+	}
+	return nil
+}
+
+// ---------- Implementation ----------
+
+// importer holds the working state of the algorithm.
+type importer struct {
+	conf  *Config   // the client configuration
+	start time.Time // for logging
+
+	progMu sync.Mutex // guards prog
+	prog   *Program   // the resulting program
+
+	// findpkg is a memoization of FindPackage.
+	findpkgMu sync.Mutex // guards findpkg
+	findpkg   map[findpkgKey]findpkgValue
+
+	importedMu sync.Mutex             // guards imported
+	imported   map[string]*importInfo // all imported packages (incl. failures) by import path
+
+	// import dependency graph: graph[x][y] => x imports y
+	//
+	// Since non-importable packages cannot be cyclic, we ignore
+	// their imports, thus we only need the subgraph over importable
+	// packages.  Nodes are identified by their import paths.
+	graphMu sync.Mutex
+	graph   map[string]map[string]bool
+}
+
+type findpkgKey struct {
+	importPath string
+	fromDir    string
+	mode       build.ImportMode
+}
+
+type findpkgValue struct {
+	bp  *build.Package
+	err error
+}
+
+// importInfo tracks the success or failure of a single import.
+//
+// Upon completion, exactly one of info and err is non-nil:
+// info on successful creation of a package, err otherwise.
+// A successful package may still contain type errors.
+//
+type importInfo struct {
+	path     string        // import path
+	info     *PackageInfo  // results of typechecking (including errors)
+	complete chan struct{} // closed to broadcast that info is set.
+}
+
+// awaitCompletion blocks until ii is complete,
+// i.e. the info field is safe to inspect.
+func (ii *importInfo) awaitCompletion() {
+	<-ii.complete // wait for close
+}
+
+// Complete marks ii as complete.
+// Its info and err fields will not be subsequently updated.
+func (ii *importInfo) Complete(info *PackageInfo) {
+	if info == nil {
+		panic("info == nil")
+	}
+	ii.info = info
+	close(ii.complete)
+}
+
+type importError struct {
+	path string // import path
+	err  error  // reason for failure to create a package
+}
+
+// Load creates the initial packages specified by conf.{Create,Import}Pkgs,
+// loading their dependencies packages as needed.
+//
+// On success, Load returns a Program containing a PackageInfo for
+// each package.  On failure, it returns an error.
+//
+// If AllowErrors is true, Load will return a Program even if some
+// packages contained I/O, parser or type errors, or if dependencies
+// were missing.  (Such errors are accessible via PackageInfo.Errors.  If
+// false, Load will fail if any package had an error.
+//
+// It is an error if no packages were loaded.
+//
+func (conf *Config) Load() (*Program, error) {
+	// Create a simple default error handler for parse/type errors.
+	if conf.TypeChecker.Error == nil {
+		conf.TypeChecker.Error = func(e error) { fmt.Fprintln(os.Stderr, e) }
+	}
+
+	// Set default working directory for relative package references.
+	if conf.Cwd == "" {
+		var err error
+		conf.Cwd, err = os.Getwd()
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	// Install default FindPackage hook using go/build logic.
+	if conf.FindPackage == nil {
+		conf.FindPackage = func(ctxt *build.Context, path, fromDir string, mode build.ImportMode) (*build.Package, error) {
+			ioLimit <- true
+			bp, err := ctxt.Import(path, fromDir, mode)
+			<-ioLimit
+			if _, ok := err.(*build.NoGoError); ok {
+				return bp, nil // empty directory is not an error
+			}
+			return bp, err
+		}
+	}
+
+	prog := &Program{
+		Fset:        conf.fset(),
+		Imported:    make(map[string]*PackageInfo),
+		importMap:   make(map[string]*types.Package),
+		AllPackages: make(map[*types.Package]*PackageInfo),
+	}
+
+	imp := importer{
+		conf:     conf,
+		prog:     prog,
+		findpkg:  make(map[findpkgKey]findpkgValue),
+		imported: make(map[string]*importInfo),
+		start:    time.Now(),
+		graph:    make(map[string]map[string]bool),
+	}
+
+	// -- loading proper (concurrent phase) --------------------------------
+
+	var errpkgs []string // packages that contained errors
+
+	// Load the initially imported packages and their dependencies,
+	// in parallel.
+	infos, importErrors := imp.importAll("", conf.Cwd, conf.ImportPkgs, 0)
+	for _, ie := range importErrors {
+		conf.TypeChecker.Error(ie.err) // failed to create package
+		errpkgs = append(errpkgs, ie.path)
+	}
+	for _, info := range infos {
+		prog.Imported[info.Pkg.Path()] = info
+	}
+
+	// Augment the designated initial packages by their tests.
+	// Dependencies are loaded in parallel.
+	var xtestPkgs []*build.Package
+	for importPath, augment := range conf.ImportPkgs {
+		if !augment {
+			continue
+		}
+
+		bp, err := imp.findPackage(importPath, conf.Cwd, 0)
+		if err != nil {
+			// Package not found, or can't even parse package declaration.
+			// Already reported by previous loop; ignore it.
+			continue
+		}
+
+		// Needs external test package?
+		if len(bp.XTestGoFiles) > 0 {
+			xtestPkgs = append(xtestPkgs, bp)
+		}
+
+		// Consult the cache using the canonical package path.
+		path := bp.ImportPath
+		imp.importedMu.Lock() // (unnecessary, we're sequential here)
+		ii, ok := imp.imported[path]
+		// Paranoid checks added due to issue #11012.
+		if !ok {
+			// Unreachable.
+			// The previous loop called importAll and thus
+			// startLoad for each path in ImportPkgs, which
+			// populates imp.imported[path] with a non-zero value.
+			panic(fmt.Sprintf("imported[%q] not found", path))
+		}
+		if ii == nil {
+			// Unreachable.
+			// The ii values in this loop are the same as in
+			// the previous loop, which enforced the invariant
+			// that at least one of ii.err and ii.info is non-nil.
+			panic(fmt.Sprintf("imported[%q] == nil", path))
+		}
+		if ii.info == nil {
+			// Unreachable.
+			// awaitCompletion has the postcondition
+			// ii.info != nil.
+			panic(fmt.Sprintf("imported[%q].info = nil", path))
+		}
+		info := ii.info
+		imp.importedMu.Unlock()
+
+		// Parse the in-package test files.
+		files, errs := imp.conf.parsePackageFiles(bp, 't')
+		for _, err := range errs {
+			info.appendError(err)
+		}
+
+		// The test files augmenting package P cannot be imported,
+		// but may import packages that import P,
+		// so we must disable the cycle check.
+		imp.addFiles(info, files, false)
+	}
+
+	createPkg := func(path string, files []*ast.File, errs []error) {
+		// TODO(adonovan): fix: use dirname of files, not cwd.
+		info := imp.newPackageInfo(path, conf.Cwd)
+		for _, err := range errs {
+			info.appendError(err)
+		}
+
+		// Ad hoc packages are non-importable,
+		// so no cycle check is needed.
+		// addFiles loads dependencies in parallel.
+		imp.addFiles(info, files, false)
+		prog.Created = append(prog.Created, info)
+	}
+
+	// Create packages specified by conf.CreatePkgs.
+	for _, cp := range conf.CreatePkgs {
+		files, errs := parseFiles(conf.fset(), conf.build(), nil, ".", cp.Filenames, conf.ParserMode)
+		files = append(files, cp.Files...)
+
+		path := cp.Path
+		if path == "" {
+			if len(files) > 0 {
+				path = files[0].Name.Name
+			} else {
+				path = "(unnamed)"
+			}
+		}
+		createPkg(path, files, errs)
+	}
+
+	// Create external test packages.
+	sort.Sort(byImportPath(xtestPkgs))
+	for _, bp := range xtestPkgs {
+		files, errs := imp.conf.parsePackageFiles(bp, 'x')
+		createPkg(bp.ImportPath+"_test", files, errs)
+	}
+
+	// -- finishing up (sequential) ----------------------------------------
+
+	if len(prog.Imported)+len(prog.Created) == 0 {
+		return nil, errors.New("no initial packages were loaded")
+	}
+
+	// Create infos for indirectly imported packages.
+	// e.g. incomplete packages without syntax, loaded from export data.
+	for _, obj := range prog.importMap {
+		info := prog.AllPackages[obj]
+		if info == nil {
+			prog.AllPackages[obj] = &PackageInfo{Pkg: obj, Importable: true}
+		} else {
+			// finished
+			info.checker = nil
+			info.errorFunc = nil
+		}
+	}
+
+	if !conf.AllowErrors {
+		// Report errors in indirectly imported packages.
+		for _, info := range prog.AllPackages {
+			if len(info.Errors) > 0 {
+				errpkgs = append(errpkgs, info.Pkg.Path())
+			}
+		}
+		if errpkgs != nil {
+			var more string
+			if len(errpkgs) > 3 {
+				more = fmt.Sprintf(" and %d more", len(errpkgs)-3)
+				errpkgs = errpkgs[:3]
+			}
+			return nil, fmt.Errorf("couldn't load packages due to errors: %s%s",
+				strings.Join(errpkgs, ", "), more)
+		}
+	}
+
+	markErrorFreePackages(prog.AllPackages)
+
+	return prog, nil
+}
+
+type byImportPath []*build.Package
+
+func (b byImportPath) Len() int           { return len(b) }
+func (b byImportPath) Less(i, j int) bool { return b[i].ImportPath < b[j].ImportPath }
+func (b byImportPath) Swap(i, j int)      { b[i], b[j] = b[j], b[i] }
+
+// markErrorFreePackages sets the TransitivelyErrorFree flag on all
+// applicable packages.
+func markErrorFreePackages(allPackages map[*types.Package]*PackageInfo) {
+	// Build the transpose of the import graph.
+	importedBy := make(map[*types.Package]map[*types.Package]bool)
+	for P := range allPackages {
+		for _, Q := range P.Imports() {
+			clients, ok := importedBy[Q]
+			if !ok {
+				clients = make(map[*types.Package]bool)
+				importedBy[Q] = clients
+			}
+			clients[P] = true
+		}
+	}
+
+	// Find all packages reachable from some error package.
+	reachable := make(map[*types.Package]bool)
+	var visit func(*types.Package)
+	visit = func(p *types.Package) {
+		if !reachable[p] {
+			reachable[p] = true
+			for q := range importedBy[p] {
+				visit(q)
+			}
+		}
+	}
+	for _, info := range allPackages {
+		if len(info.Errors) > 0 {
+			visit(info.Pkg)
+		}
+	}
+
+	// Mark the others as "transitively error-free".
+	for _, info := range allPackages {
+		if !reachable[info.Pkg] {
+			info.TransitivelyErrorFree = true
+		}
+	}
+}
+
+// build returns the effective build context.
+func (conf *Config) build() *build.Context {
+	if conf.Build != nil {
+		return conf.Build
+	}
+	return &build.Default
+}
+
+// parsePackageFiles enumerates the files belonging to package path,
+// then loads, parses and returns them, plus a list of I/O or parse
+// errors that were encountered.
+//
+// 'which' indicates which files to include:
+//    'g': include non-test *.go source files (GoFiles + processed CgoFiles)
+//    't': include in-package *_test.go source files (TestGoFiles)
+//    'x': include external *_test.go source files. (XTestGoFiles)
+//
+func (conf *Config) parsePackageFiles(bp *build.Package, which rune) ([]*ast.File, []error) {
+	if bp.Goroot && bp.ImportPath == "unsafe" {
+		return nil, nil
+	}
+	var filenames []string
+	switch which {
+	case 'g':
+		filenames = bp.GoFiles
+	case 't':
+		filenames = bp.TestGoFiles
+	case 'x':
+		filenames = bp.XTestGoFiles
+	default:
+		panic(which)
+	}
+
+	files, errs := parseFiles(conf.fset(), conf.build(), conf.DisplayPath, bp.Dir, filenames, conf.ParserMode)
+
+	// Preprocess CgoFiles and parse the outputs (sequentially).
+	if which == 'g' && bp.CgoFiles != nil {
+		cgofiles, err := processCgoFiles(bp, conf.fset(), conf.DisplayPath, conf.ParserMode)
+		if err != nil {
+			errs = append(errs, err)
+		} else {
+			files = append(files, cgofiles...)
+		}
+	}
+
+	return files, errs
+}
+
+// doImport imports the package denoted by path.
+// It implements the types.Importer signature.
+//
+// It returns an error if a package could not be created
+// (e.g. go/build or parse error), but type errors are reported via
+// the types.Config.Error callback (the first of which is also saved
+// in the package's PackageInfo).
+//
+// Idempotent.
+//
+func (imp *importer) doImport(from *PackageInfo, to string) (*types.Package, error) {
+	if to == "C" {
+		// This should be unreachable, but ad hoc packages are
+		// not currently subject to cgo preprocessing.
+		// See https://github.com/golang/go/issues/11627.
+		return nil, fmt.Errorf(`the loader doesn't cgo-process ad hoc packages like %q; see Go issue 11627`,
+			from.Pkg.Path())
+	}
+
+	bp, err := imp.findPackage(to, from.dir, 0)
+	if err != nil {
+		return nil, err
+	}
+
+	// The standard unsafe package is handled specially,
+	// and has no PackageInfo.
+	if bp.Goroot && bp.ImportPath == "unsafe" {
+		return types.Unsafe, nil
+	}
+
+	// Look for the package in the cache using its canonical path.
+	path := bp.ImportPath
+	imp.importedMu.Lock()
+	ii := imp.imported[path]
+	imp.importedMu.Unlock()
+	if ii == nil {
+		panic("internal error: unexpected import: " + path)
+	}
+	if ii.info != nil {
+		return ii.info.Pkg, nil
+	}
+
+	// Import of incomplete package: this indicates a cycle.
+	fromPath := from.Pkg.Path()
+	if cycle := imp.findPath(path, fromPath); cycle != nil {
+		cycle = append([]string{fromPath}, cycle...)
+		return nil, fmt.Errorf("import cycle: %s", strings.Join(cycle, " -> "))
+	}
+
+	panic("internal error: import of incomplete (yet acyclic) package: " + fromPath)
+}
+
+// findPackage locates the package denoted by the importPath in the
+// specified directory.
+func (imp *importer) findPackage(importPath, fromDir string, mode build.ImportMode) (*build.Package, error) {
+	// TODO(adonovan): opt: non-blocking duplicate-suppressing cache.
+	// i.e. don't hold the lock around FindPackage.
+	key := findpkgKey{importPath, fromDir, mode}
+	imp.findpkgMu.Lock()
+	defer imp.findpkgMu.Unlock()
+	v, ok := imp.findpkg[key]
+	if !ok {
+		bp, err := imp.conf.FindPackage(imp.conf.build(), importPath, fromDir, mode)
+		v = findpkgValue{bp, err}
+		imp.findpkg[key] = v
+	}
+	return v.bp, v.err
+}
+
+// importAll loads, parses, and type-checks the specified packages in
+// parallel and returns their completed importInfos in unspecified order.
+//
+// fromPath is the package path of the importing package, if it is
+// importable, "" otherwise.  It is used for cycle detection.
+//
+// fromDir is the directory containing the import declaration that
+// caused these imports.
+//
+func (imp *importer) importAll(fromPath, fromDir string, imports map[string]bool, mode build.ImportMode) (infos []*PackageInfo, errors []importError) {
+	// TODO(adonovan): opt: do the loop in parallel once
+	// findPackage is non-blocking.
+	var pending []*importInfo
+	for importPath := range imports {
+		bp, err := imp.findPackage(importPath, fromDir, mode)
+		if err != nil {
+			errors = append(errors, importError{
+				path: importPath,
+				err:  err,
+			})
+			continue
+		}
+		pending = append(pending, imp.startLoad(bp))
+	}
+
+	if fromPath != "" {
+		// We're loading a set of imports.
+		//
+		// We must record graph edges from the importing package
+		// to its dependencies, and check for cycles.
+		imp.graphMu.Lock()
+		deps, ok := imp.graph[fromPath]
+		if !ok {
+			deps = make(map[string]bool)
+			imp.graph[fromPath] = deps
+		}
+		for _, ii := range pending {
+			deps[ii.path] = true
+		}
+		imp.graphMu.Unlock()
+	}
+
+	for _, ii := range pending {
+		if fromPath != "" {
+			if cycle := imp.findPath(ii.path, fromPath); cycle != nil {
+				// Cycle-forming import: we must not await its
+				// completion since it would deadlock.
+				//
+				// We don't record the error in ii since
+				// the error is really associated with the
+				// cycle-forming edge, not the package itself.
+				// (Also it would complicate the
+				// invariants of importPath completion.)
+				if trace {
+					fmt.Fprintln(os.Stderr, "import cycle: %q", cycle)
+				}
+				continue
+			}
+		}
+		ii.awaitCompletion()
+		infos = append(infos, ii.info)
+	}
+
+	return infos, errors
+}
+
+// findPath returns an arbitrary path from 'from' to 'to' in the import
+// graph, or nil if there was none.
+func (imp *importer) findPath(from, to string) []string {
+	imp.graphMu.Lock()
+	defer imp.graphMu.Unlock()
+
+	seen := make(map[string]bool)
+	var search func(stack []string, importPath string) []string
+	search = func(stack []string, importPath string) []string {
+		if !seen[importPath] {
+			seen[importPath] = true
+			stack = append(stack, importPath)
+			if importPath == to {
+				return stack
+			}
+			for x := range imp.graph[importPath] {
+				if p := search(stack, x); p != nil {
+					return p
+				}
+			}
+		}
+		return nil
+	}
+	return search(make([]string, 0, 20), from)
+}
+
+// startLoad initiates the loading, parsing and type-checking of the
+// specified package and its dependencies, if it has not already begun.
+//
+// It returns an importInfo, not necessarily in a completed state.  The
+// caller must call awaitCompletion() before accessing its info field.
+//
+// startLoad is concurrency-safe and idempotent.
+//
+func (imp *importer) startLoad(bp *build.Package) *importInfo {
+	path := bp.ImportPath
+	imp.importedMu.Lock()
+	ii, ok := imp.imported[path]
+	if !ok {
+		ii = &importInfo{path: path, complete: make(chan struct{})}
+		imp.imported[path] = ii
+		go func() {
+			info := imp.load(bp)
+			ii.Complete(info)
+		}()
+	}
+	imp.importedMu.Unlock()
+
+	return ii
+}
+
+// load implements package loading by parsing Go source files
+// located by go/build.
+func (imp *importer) load(bp *build.Package) *PackageInfo {
+	info := imp.newPackageInfo(bp.ImportPath, bp.Dir)
+	info.Importable = true
+	files, errs := imp.conf.parsePackageFiles(bp, 'g')
+	for _, err := range errs {
+		info.appendError(err)
+	}
+
+	imp.addFiles(info, files, true)
+
+	imp.progMu.Lock()
+	imp.prog.importMap[bp.ImportPath] = info.Pkg
+	imp.progMu.Unlock()
+
+	return info
+}
+
+// addFiles adds and type-checks the specified files to info, loading
+// their dependencies if needed.  The order of files determines the
+// package initialization order.  It may be called multiple times on the
+// same package.  Errors are appended to the info.Errors field.
+//
+// cycleCheck determines whether the imports within files create
+// dependency edges that should be checked for potential cycles.
+//
+func (imp *importer) addFiles(info *PackageInfo, files []*ast.File, cycleCheck bool) {
+	info.Files = append(info.Files, files...)
+
+	// Ensure the dependencies are loaded, in parallel.
+	var fromPath string
+	if cycleCheck {
+		fromPath = info.Pkg.Path()
+	}
+	// TODO(adonovan): opt: make the caller do scanImports.
+	// Callers with a build.Package can skip it.
+	imp.importAll(fromPath, info.dir, scanImports(files), 0)
+
+	if trace {
+		fmt.Fprintf(os.Stderr, "%s: start %q (%d)\n",
+			time.Since(imp.start), info.Pkg.Path(), len(files))
+	}
+
+	// Ignore the returned (first) error since we
+	// already collect them all in the PackageInfo.
+	info.checker.Files(files)
+
+	if trace {
+		fmt.Fprintf(os.Stderr, "%s: stop %q\n",
+			time.Since(imp.start), info.Pkg.Path())
+	}
+}
+
+func (imp *importer) newPackageInfo(path, dir string) *PackageInfo {
+	pkg := types.NewPackage(path, "")
+	info := &PackageInfo{
+		Pkg: pkg,
+		Info: types.Info{
+			Types:      make(map[ast.Expr]types.TypeAndValue),
+			Defs:       make(map[*ast.Ident]types.Object),
+			Uses:       make(map[*ast.Ident]types.Object),
+			Implicits:  make(map[ast.Node]types.Object),
+			Scopes:     make(map[ast.Node]*types.Scope),
+			Selections: make(map[*ast.SelectorExpr]*types.Selection),
+		},
+		errorFunc: imp.conf.TypeChecker.Error,
+		dir:       dir,
+	}
+
+	// Copy the types.Config so we can vary it across PackageInfos.
+	tc := imp.conf.TypeChecker
+	tc.IgnoreFuncBodies = false
+	if f := imp.conf.TypeCheckFuncBodies; f != nil {
+		tc.IgnoreFuncBodies = !f(path)
+	}
+	tc.Import = func(_ map[string]*types.Package, to string) (*types.Package, error) {
+		return imp.doImport(info, to)
+	}
+	tc.Error = info.appendError // appendError wraps the user's Error function
+
+	info.checker = types.NewChecker(&tc, imp.conf.fset(), pkg, &info.Info)
+	imp.progMu.Lock()
+	imp.prog.AllPackages[pkg] = info
+	imp.progMu.Unlock()
+	return info
+}
diff --git a/go/src/golang.org/x/tools/go/loader/loader14_test.go b/go/src/golang.org/x/tools/go/loader/loader14_test.go
new file mode 100644
index 0000000..fab3170
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/loader/loader14_test.go
@@ -0,0 +1,676 @@
+// 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.
+
+// +build !go1.5
+
+// No testdata on Android.
+
+// +build !android
+
+package loader_test
+
+import (
+	"fmt"
+	"go/build"
+	"path/filepath"
+	"reflect"
+	"sort"
+	"strings"
+	"sync"
+	"testing"
+
+	"golang.org/x/tools/go/buildutil"
+	"golang.org/x/tools/go/loader"
+)
+
+// TestFromArgs checks that conf.FromArgs populates conf correctly.
+// It does no I/O.
+func TestFromArgs(t *testing.T) {
+	type result struct {
+		Err        string
+		Rest       []string
+		ImportPkgs map[string]bool
+		CreatePkgs []loader.PkgSpec
+	}
+	for _, test := range []struct {
+		args  []string
+		tests bool
+		want  result
+	}{
+		// Mix of existing and non-existent packages.
+		{
+			args: []string{"nosuchpkg", "errors"},
+			want: result{
+				ImportPkgs: map[string]bool{"errors": false, "nosuchpkg": false},
+			},
+		},
+		// Same, with -test flag.
+		{
+			args:  []string{"nosuchpkg", "errors"},
+			tests: true,
+			want: result{
+				ImportPkgs: map[string]bool{"errors": true, "nosuchpkg": true},
+			},
+		},
+		// Surplus arguments.
+		{
+			args: []string{"fmt", "errors", "--", "surplus"},
+			want: result{
+				Rest:       []string{"surplus"},
+				ImportPkgs: map[string]bool{"errors": false, "fmt": false},
+			},
+		},
+		// Ad hoc package specified as *.go files.
+		{
+			args: []string{"foo.go", "bar.go"},
+			want: result{CreatePkgs: []loader.PkgSpec{{
+				Filenames: []string{"foo.go", "bar.go"},
+			}}},
+		},
+		// Mixture of *.go and import paths.
+		{
+			args: []string{"foo.go", "fmt"},
+			want: result{
+				Err: "named files must be .go files: fmt",
+			},
+		},
+	} {
+		var conf loader.Config
+		rest, err := conf.FromArgs(test.args, test.tests)
+		got := result{
+			Rest:       rest,
+			ImportPkgs: conf.ImportPkgs,
+			CreatePkgs: conf.CreatePkgs,
+		}
+		if err != nil {
+			got.Err = err.Error()
+		}
+		if !reflect.DeepEqual(got, test.want) {
+			t.Errorf("FromArgs(%q) = %+v, want %+v", test.args, got, test.want)
+		}
+	}
+}
+
+func TestLoad_NoInitialPackages(t *testing.T) {
+	var conf loader.Config
+
+	const wantErr = "no initial packages were loaded"
+
+	prog, err := conf.Load()
+	if err == nil {
+		t.Errorf("Load succeeded unexpectedly, want %q", wantErr)
+	} else if err.Error() != wantErr {
+		t.Errorf("Load failed with wrong error %q, want %q", err, wantErr)
+	}
+	if prog != nil {
+		t.Errorf("Load unexpectedly returned a Program")
+	}
+}
+
+func TestLoad_MissingInitialPackage(t *testing.T) {
+	var conf loader.Config
+	conf.Import("nosuchpkg")
+	conf.Import("errors")
+
+	const wantErr = "couldn't load packages due to errors: nosuchpkg"
+
+	prog, err := conf.Load()
+	if err == nil {
+		t.Errorf("Load succeeded unexpectedly, want %q", wantErr)
+	} else if err.Error() != wantErr {
+		t.Errorf("Load failed with wrong error %q, want %q", err, wantErr)
+	}
+	if prog != nil {
+		t.Errorf("Load unexpectedly returned a Program")
+	}
+}
+
+func TestLoad_MissingInitialPackage_AllowErrors(t *testing.T) {
+	var conf loader.Config
+	conf.AllowErrors = true
+	conf.Import("nosuchpkg")
+	conf.ImportWithTests("errors")
+
+	prog, err := conf.Load()
+	if err != nil {
+		t.Errorf("Load failed unexpectedly: %v", err)
+	}
+	if prog == nil {
+		t.Fatalf("Load returned a nil Program")
+	}
+	if got, want := created(prog), "errors_test"; got != want {
+		t.Errorf("Created = %s, want %s", got, want)
+	}
+	if got, want := imported(prog), "errors"; got != want {
+		t.Errorf("Imported = %s, want %s", got, want)
+	}
+}
+
+func TestCreateUnnamedPackage(t *testing.T) {
+	var conf loader.Config
+	conf.CreateFromFilenames("")
+	prog, err := conf.Load()
+	if err != nil {
+		t.Fatalf("Load failed: %v", err)
+	}
+	if got, want := fmt.Sprint(prog.InitialPackages()), "[(unnamed)]"; got != want {
+		t.Errorf("InitialPackages = %s, want %s", got, want)
+	}
+}
+
+func TestLoad_MissingFileInCreatedPackage(t *testing.T) {
+	var conf loader.Config
+	conf.CreateFromFilenames("", "missing.go")
+
+	const wantErr = "couldn't load packages due to errors: (unnamed)"
+
+	prog, err := conf.Load()
+	if prog != nil {
+		t.Errorf("Load unexpectedly returned a Program")
+	}
+	if err == nil {
+		t.Fatalf("Load succeeded unexpectedly, want %q", wantErr)
+	}
+	if err.Error() != wantErr {
+		t.Fatalf("Load failed with wrong error %q, want %q", err, wantErr)
+	}
+}
+
+func TestLoad_MissingFileInCreatedPackage_AllowErrors(t *testing.T) {
+	conf := loader.Config{AllowErrors: true}
+	conf.CreateFromFilenames("", "missing.go")
+
+	prog, err := conf.Load()
+	if err != nil {
+		t.Errorf("Load failed: %v", err)
+	}
+	if got, want := fmt.Sprint(prog.InitialPackages()), "[(unnamed)]"; got != want {
+		t.Fatalf("InitialPackages = %s, want %s", got, want)
+	}
+}
+
+func TestLoad_ParseError(t *testing.T) {
+	var conf loader.Config
+	conf.CreateFromFilenames("badpkg", "testdata/badpkgdecl.go")
+
+	const wantErr = "couldn't load packages due to errors: badpkg"
+
+	prog, err := conf.Load()
+	if prog != nil {
+		t.Errorf("Load unexpectedly returned a Program")
+	}
+	if err == nil {
+		t.Fatalf("Load succeeded unexpectedly, want %q", wantErr)
+	}
+	if err.Error() != wantErr {
+		t.Fatalf("Load failed with wrong error %q, want %q", err, wantErr)
+	}
+}
+
+func TestLoad_ParseError_AllowErrors(t *testing.T) {
+	var conf loader.Config
+	conf.AllowErrors = true
+	conf.CreateFromFilenames("badpkg", "testdata/badpkgdecl.go")
+
+	prog, err := conf.Load()
+	if err != nil {
+		t.Errorf("Load failed unexpectedly: %v", err)
+	}
+	if prog == nil {
+		t.Fatalf("Load returned a nil Program")
+	}
+	if got, want := created(prog), "badpkg"; got != want {
+		t.Errorf("Created = %s, want %s", got, want)
+	}
+
+	badpkg := prog.Created[0]
+	if len(badpkg.Files) != 1 {
+		t.Errorf("badpkg has %d files, want 1", len(badpkg.Files))
+	}
+	wantErr := filepath.Join("testdata", "badpkgdecl.go") + ":1:34: expected 'package', found 'EOF'"
+	if !hasError(badpkg.Errors, wantErr) {
+		t.Errorf("badpkg.Errors = %v, want %s", badpkg.Errors, wantErr)
+	}
+}
+
+func TestLoad_FromSource_Success(t *testing.T) {
+	var conf loader.Config
+	conf.CreateFromFilenames("P", "testdata/a.go", "testdata/b.go")
+
+	prog, err := conf.Load()
+	if err != nil {
+		t.Errorf("Load failed unexpectedly: %v", err)
+	}
+	if prog == nil {
+		t.Fatalf("Load returned a nil Program")
+	}
+	if got, want := created(prog), "P"; got != want {
+		t.Errorf("Created = %s, want %s", got, want)
+	}
+}
+
+func TestLoad_FromImports_Success(t *testing.T) {
+	var conf loader.Config
+	conf.ImportWithTests("fmt")
+	conf.ImportWithTests("errors")
+
+	prog, err := conf.Load()
+	if err != nil {
+		t.Errorf("Load failed unexpectedly: %v", err)
+	}
+	if prog == nil {
+		t.Fatalf("Load returned a nil Program")
+	}
+	if got, want := created(prog), "errors_test fmt_test"; got != want {
+		t.Errorf("Created = %q, want %s", got, want)
+	}
+	if got, want := imported(prog), "errors fmt"; got != want {
+		t.Errorf("Imported = %s, want %s", got, want)
+	}
+	// Check set of transitive packages.
+	// There are >30 and the set may grow over time, so only check a few.
+	want := map[string]bool{
+		"strings": true,
+		"time":    true,
+		"runtime": true,
+		"testing": true,
+		"unicode": true,
+	}
+	for _, path := range all(prog) {
+		delete(want, path)
+	}
+	if len(want) > 0 {
+		t.Errorf("AllPackages is missing these keys: %q", keys(want))
+	}
+}
+
+func TestLoad_MissingIndirectImport(t *testing.T) {
+	pkgs := map[string]string{
+		"a": `package a; import _ "b"`,
+		"b": `package b; import _ "c"`,
+	}
+	conf := loader.Config{Build: fakeContext(pkgs)}
+	conf.Import("a")
+
+	const wantErr = "couldn't load packages due to errors: b"
+
+	prog, err := conf.Load()
+	if err == nil {
+		t.Errorf("Load succeeded unexpectedly, want %q", wantErr)
+	} else if err.Error() != wantErr {
+		t.Errorf("Load failed with wrong error %q, want %q", err, wantErr)
+	}
+	if prog != nil {
+		t.Errorf("Load unexpectedly returned a Program")
+	}
+}
+
+func TestLoad_BadDependency_AllowErrors(t *testing.T) {
+	for _, test := range []struct {
+		descr    string
+		pkgs     map[string]string
+		wantPkgs string
+	}{
+
+		{
+			descr: "missing dependency",
+			pkgs: map[string]string{
+				"a": `package a; import _ "b"`,
+				"b": `package b; import _ "c"`,
+			},
+			wantPkgs: "a b",
+		},
+		{
+			descr: "bad package decl in dependency",
+			pkgs: map[string]string{
+				"a": `package a; import _ "b"`,
+				"b": `package b; import _ "c"`,
+				"c": `package`,
+			},
+			wantPkgs: "a b",
+		},
+		{
+			descr: "parse error in dependency",
+			pkgs: map[string]string{
+				"a": `package a; import _ "b"`,
+				"b": `package b; import _ "c"`,
+				"c": `package c; var x = `,
+			},
+			wantPkgs: "a b c",
+		},
+	} {
+		conf := loader.Config{
+			AllowErrors: true,
+			Build:       fakeContext(test.pkgs),
+		}
+		conf.Import("a")
+
+		prog, err := conf.Load()
+		if err != nil {
+			t.Errorf("%s: Load failed unexpectedly: %v", test.descr, err)
+		}
+		if prog == nil {
+			t.Fatalf("%s: Load returned a nil Program", test.descr)
+		}
+
+		if got, want := imported(prog), "a"; got != want {
+			t.Errorf("%s: Imported = %s, want %s", test.descr, got, want)
+		}
+		if got := all(prog); strings.Join(got, " ") != test.wantPkgs {
+			t.Errorf("%s: AllPackages = %s, want %s", test.descr, got, test.wantPkgs)
+		}
+	}
+}
+
+func TestCwd(t *testing.T) {
+	ctxt := fakeContext(map[string]string{"one/two/three": `package three`})
+	for _, test := range []struct {
+		cwd, arg, want string
+	}{
+		{cwd: "/go/src/one", arg: "./two/three", want: "one/two/three"},
+		{cwd: "/go/src/one", arg: "../one/two/three", want: "one/two/three"},
+		{cwd: "/go/src/one", arg: "one/two/three", want: "one/two/three"},
+		{cwd: "/go/src/one/two/three", arg: ".", want: "one/two/three"},
+		{cwd: "/go/src/one", arg: "two/three", want: ""},
+	} {
+		conf := loader.Config{
+			Cwd:   test.cwd,
+			Build: ctxt,
+		}
+		conf.Import(test.arg)
+
+		var got string
+		prog, err := conf.Load()
+		if prog != nil {
+			got = imported(prog)
+		}
+		if got != test.want {
+			t.Errorf("Load(%s) from %s: Imported = %s, want %s",
+				test.arg, test.cwd, got, test.want)
+			if err != nil {
+				t.Errorf("Load failed: %v", err)
+			}
+		}
+	}
+}
+
+// TODO(adonovan): more Load tests:
+//
+// failures:
+// - to parse package decl of *_test.go files
+// - to parse package decl of external *_test.go files
+// - to parse whole of *_test.go files
+// - to parse whole of external *_test.go files
+// - to open a *.go file during import scanning
+// - to import from binary
+
+// features:
+// - InitialPackages
+// - PackageCreated hook
+// - TypeCheckFuncBodies hook
+
+func TestTransitivelyErrorFreeFlag(t *testing.T) {
+	// Create an minimal custom build.Context
+	// that fakes the following packages:
+	//
+	// a --> b --> c!   c has an error
+	//   \              d and e are transitively error-free.
+	//    e --> d
+	//
+	// Each package [a-e] consists of one file, x.go.
+	pkgs := map[string]string{
+		"a": `package a; import (_ "b"; _ "e")`,
+		"b": `package b; import _ "c"`,
+		"c": `package c; func f() { _ = int(false) }`, // type error within function body
+		"d": `package d;`,
+		"e": `package e; import _ "d"`,
+	}
+	conf := loader.Config{
+		AllowErrors: true,
+		Build:       fakeContext(pkgs),
+	}
+	conf.Import("a")
+
+	prog, err := conf.Load()
+	if err != nil {
+		t.Errorf("Load failed: %s", err)
+	}
+	if prog == nil {
+		t.Fatalf("Load returned nil *Program")
+	}
+
+	for pkg, info := range prog.AllPackages {
+		var wantErr, wantTEF bool
+		switch pkg.Path() {
+		case "a", "b":
+		case "c":
+			wantErr = true
+		case "d", "e":
+			wantTEF = true
+		default:
+			t.Errorf("unexpected package: %q", pkg.Path())
+			continue
+		}
+
+		if (info.Errors != nil) != wantErr {
+			if wantErr {
+				t.Errorf("Package %q.Error = nil, want error", pkg.Path())
+			} else {
+				t.Errorf("Package %q has unexpected Errors: %v",
+					pkg.Path(), info.Errors)
+			}
+		}
+
+		if info.TransitivelyErrorFree != wantTEF {
+			t.Errorf("Package %q.TransitivelyErrorFree=%t, want %t",
+				pkg.Path(), info.TransitivelyErrorFree, wantTEF)
+		}
+	}
+}
+
+// Test that syntax (scan/parse), type, and loader errors are recorded
+// (in PackageInfo.Errors) and reported (via Config.TypeChecker.Error).
+func TestErrorReporting(t *testing.T) {
+	pkgs := map[string]string{
+		"a": `package a; import (_ "b"; _ "c"); var x int = false`,
+		"b": `package b; 'syntax error!`,
+	}
+	conf := loader.Config{
+		AllowErrors: true,
+		Build:       fakeContext(pkgs),
+	}
+	var mu sync.Mutex
+	var allErrors []error
+	conf.TypeChecker.Error = func(err error) {
+		mu.Lock()
+		allErrors = append(allErrors, err)
+		mu.Unlock()
+	}
+	conf.Import("a")
+
+	prog, err := conf.Load()
+	if err != nil {
+		t.Errorf("Load failed: %s", err)
+	}
+	if prog == nil {
+		t.Fatalf("Load returned nil *Program")
+	}
+
+	// TODO(adonovan): test keys of ImportMap.
+
+	// Check errors recorded in each PackageInfo.
+	for pkg, info := range prog.AllPackages {
+		switch pkg.Path() {
+		case "a":
+			if !hasError(info.Errors, "cannot convert false") {
+				t.Errorf("a.Errors = %v, want bool conversion (type) error", info.Errors)
+			}
+			if !hasError(info.Errors, "could not import c") {
+				t.Errorf("a.Errors = %v, want import (loader) error", info.Errors)
+			}
+		case "b":
+			if !hasError(info.Errors, "rune literal not terminated") {
+				t.Errorf("b.Errors = %v, want unterminated literal (syntax) error", info.Errors)
+			}
+		}
+	}
+
+	// Check errors reported via error handler.
+	if !hasError(allErrors, "cannot convert false") ||
+		!hasError(allErrors, "rune literal not terminated") ||
+		!hasError(allErrors, "could not import c") {
+		t.Errorf("allErrors = %v, want syntax, type and loader errors", allErrors)
+	}
+}
+
+func TestCycles(t *testing.T) {
+	for _, test := range []struct {
+		descr   string
+		ctxt    *build.Context
+		wantErr string
+	}{
+		{
+			"self-cycle",
+			fakeContext(map[string]string{
+				"main":      `package main; import _ "selfcycle"`,
+				"selfcycle": `package selfcycle; import _ "selfcycle"`,
+			}),
+			`import cycle: selfcycle -> selfcycle`,
+		},
+		{
+			"three-package cycle",
+			fakeContext(map[string]string{
+				"main": `package main; import _ "a"`,
+				"a":    `package a; import _ "b"`,
+				"b":    `package b; import _ "c"`,
+				"c":    `package c; import _ "a"`,
+			}),
+			`import cycle: c -> a -> b -> c`,
+		},
+		{
+			"self-cycle in dependency of test file",
+			buildutil.FakeContext(map[string]map[string]string{
+				"main": {
+					"main.go":      `package main`,
+					"main_test.go": `package main; import _ "a"`,
+				},
+				"a": {
+					"a.go": `package a; import _ "a"`,
+				},
+			}),
+			`import cycle: a -> a`,
+		},
+		// TODO(adonovan): fix: these fail
+		// {
+		// 	"two-package cycle in dependency of test file",
+		// 	buildutil.FakeContext(map[string]map[string]string{
+		// 		"main": {
+		// 			"main.go":      `package main`,
+		// 			"main_test.go": `package main; import _ "a"`,
+		// 		},
+		// 		"a": {
+		// 			"a.go": `package a; import _ "main"`,
+		// 		},
+		// 	}),
+		// 	`import cycle: main -> a -> main`,
+		// },
+		// {
+		// 	"self-cycle in augmented package",
+		// 	buildutil.FakeContext(map[string]map[string]string{
+		// 		"main": {
+		// 			"main.go":      `package main`,
+		// 			"main_test.go": `package main; import _ "main"`,
+		// 		},
+		// 	}),
+		// 	`import cycle: main -> main`,
+		// },
+	} {
+		conf := loader.Config{
+			AllowErrors: true,
+			Build:       test.ctxt,
+		}
+		var mu sync.Mutex
+		var allErrors []error
+		conf.TypeChecker.Error = func(err error) {
+			mu.Lock()
+			allErrors = append(allErrors, err)
+			mu.Unlock()
+		}
+		conf.ImportWithTests("main")
+
+		prog, err := conf.Load()
+		if err != nil {
+			t.Errorf("%s: Load failed: %s", test.descr, err)
+		}
+		if prog == nil {
+			t.Fatalf("%s: Load returned nil *Program", test.descr)
+		}
+
+		if !hasError(allErrors, test.wantErr) {
+			t.Errorf("%s: Load() errors = %q, want %q",
+				test.descr, allErrors, test.wantErr)
+		}
+	}
+
+	// TODO(adonovan):
+	// - Test that in a legal test cycle, none of the symbols
+	//   defined by augmentation are visible via import.
+}
+
+// ---- utilities ----
+
+// Simplifying wrapper around buildutil.FakeContext for single-file packages.
+func fakeContext(pkgs map[string]string) *build.Context {
+	pkgs2 := make(map[string]map[string]string)
+	for path, content := range pkgs {
+		pkgs2[path] = map[string]string{"x.go": content}
+	}
+	return buildutil.FakeContext(pkgs2)
+}
+
+func hasError(errors []error, substr string) bool {
+	for _, err := range errors {
+		if strings.Contains(err.Error(), substr) {
+			return true
+		}
+	}
+	return false
+}
+
+func keys(m map[string]bool) (keys []string) {
+	for key := range m {
+		keys = append(keys, key)
+	}
+	sort.Strings(keys)
+	return
+}
+
+// Returns all loaded packages.
+func all(prog *loader.Program) []string {
+	var pkgs []string
+	for _, info := range prog.AllPackages {
+		pkgs = append(pkgs, info.Pkg.Path())
+	}
+	sort.Strings(pkgs)
+	return pkgs
+}
+
+// Returns initially imported packages, as a string.
+func imported(prog *loader.Program) string {
+	var pkgs []string
+	for _, info := range prog.Imported {
+		pkgs = append(pkgs, info.Pkg.Path())
+	}
+	sort.Strings(pkgs)
+	return strings.Join(pkgs, " ")
+}
+
+// Returns initially created packages, as a string.
+func created(prog *loader.Program) string {
+	var pkgs []string
+	for _, info := range prog.Created {
+		pkgs = append(pkgs, info.Pkg.Path())
+	}
+	return strings.Join(pkgs, " ")
+}
diff --git a/go/src/golang.org/x/tools/go/loader/loader_test.go b/go/src/golang.org/x/tools/go/loader/loader_test.go
index 602590e..1f05e18 100644
--- a/go/src/golang.org/x/tools/go/loader/loader_test.go
+++ b/go/src/golang.org/x/tools/go/loader/loader_test.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 // No testdata on Android.
 
 // +build !android
@@ -22,6 +24,8 @@
 	"golang.org/x/tools/go/loader"
 )
 
+var go16 bool // Go version >= go1.6
+
 // TestFromArgs checks that conf.FromArgs populates conf correctly.
 // It does no I/O.
 func TestFromArgs(t *testing.T) {
@@ -393,6 +397,86 @@
 	}
 }
 
+func TestLoad_vendor(t *testing.T) {
+	if !go16 {
+		// TODO(adonovan): delete in due course.
+		t.Skipf("vendoring requires Go 1.6")
+	}
+	pkgs := map[string]string{
+		"a":          `package a; import _ "x"`,
+		"a/vendor":   ``, // mkdir a/vendor
+		"a/vendor/x": `package xa`,
+		"b":          `package b; import _ "x"`,
+		"b/vendor":   ``, // mkdir b/vendor
+		"b/vendor/x": `package xb`,
+		"c":          `package c; import _ "x"`,
+		"x":          `package xc`,
+	}
+	conf := loader.Config{Build: fakeContext(pkgs)}
+	conf.Import("a")
+	conf.Import("b")
+	conf.Import("c")
+
+	prog, err := conf.Load()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// Check that a, b, and c see different versions of x.
+	for _, r := range "abc" {
+		name := string(r)
+		got := prog.Package(name).Pkg.Imports()[0]
+		want := "x" + name
+		if got.Name() != want {
+			t.Errorf("package %s import %q = %s, want %s",
+				name, "x", got.Name(), want)
+		}
+	}
+}
+
+func TestVendorCwd(t *testing.T) {
+	if !go16 {
+		// TODO(adonovan): delete in due course.
+		t.Skipf("vendoring requires Go 1.6")
+	}
+	// Test the interaction of cwd and vendor directories.
+	ctxt := fakeContext(map[string]string{
+		"net":          ``, // mkdir net
+		"net/http":     `package http; import _ "hpack"`,
+		"vendor":       ``, // mkdir vendor
+		"vendor/hpack": `package vendorhpack`,
+		"hpack":        `package hpack`,
+	})
+	for i, test := range []struct {
+		cwd, arg, want string
+	}{
+		{cwd: "/go/src/net", arg: "http"}, // not found
+		{cwd: "/go/src/net", arg: "./http", want: "net/http vendor/hpack"},
+		{cwd: "/go/src/net", arg: "hpack", want: "hpack"},
+		{cwd: "/go/src/vendor", arg: "hpack", want: "hpack"},
+		{cwd: "/go/src/vendor", arg: "./hpack", want: "vendor/hpack"},
+	} {
+		conf := loader.Config{
+			Cwd:   test.cwd,
+			Build: ctxt,
+		}
+		conf.Import(test.arg)
+
+		var got string
+		prog, err := conf.Load()
+		if prog != nil {
+			got = strings.Join(all(prog), " ")
+		}
+		if got != test.want {
+			t.Errorf("#%d: Load(%s) from %s: got %s, want %s",
+				i, test.arg, test.cwd, got, test.want)
+			if err != nil {
+				t.Errorf("Load failed: %v", err)
+			}
+		}
+	}
+}
+
 // TODO(adonovan): more Load tests:
 //
 // failures:
diff --git a/go/src/golang.org/x/tools/go/loader/stdlib14_test.go b/go/src/golang.org/x/tools/go/loader/stdlib14_test.go
new file mode 100644
index 0000000..c3a2987
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/loader/stdlib14_test.go
@@ -0,0 +1,197 @@
+// 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.
+
+// +build !go1.5
+
+package loader_test
+
+// This file enumerates all packages beneath $GOROOT, loads them, plus
+// their external tests if any, runs the type checker on them, and
+// prints some summary information.
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/token"
+	"io/ioutil"
+	"path/filepath"
+	"runtime"
+	"strings"
+	"testing"
+	"time"
+
+	"golang.org/x/tools/go/buildutil"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/types"
+)
+
+func TestStdlib(t *testing.T) {
+	if runtime.GOOS == "android" {
+		t.Skipf("incomplete std lib on %s", runtime.GOOS)
+	}
+
+	runtime.GC()
+	t0 := time.Now()
+	var memstats runtime.MemStats
+	runtime.ReadMemStats(&memstats)
+	alloc := memstats.Alloc
+
+	// Load, parse and type-check the program.
+	ctxt := build.Default // copy
+	ctxt.GOPATH = ""      // disable GOPATH
+	conf := loader.Config{Build: &ctxt}
+	for _, path := range buildutil.AllPackages(conf.Build) {
+		conf.ImportWithTests(path)
+	}
+
+	prog, err := conf.Load()
+	if err != nil {
+		t.Fatalf("Load failed: %v", err)
+	}
+
+	t1 := time.Now()
+	runtime.GC()
+	runtime.ReadMemStats(&memstats)
+
+	numPkgs := len(prog.AllPackages)
+	if want := 205; numPkgs < want {
+		t.Errorf("Loaded only %d packages, want at least %d", numPkgs, want)
+	}
+
+	// Dump package members.
+	if false {
+		for pkg := range prog.AllPackages {
+			fmt.Printf("Package %s:\n", pkg.Path())
+			scope := pkg.Scope()
+			qualifier := types.RelativeTo(pkg)
+			for _, name := range scope.Names() {
+				if ast.IsExported(name) {
+					fmt.Printf("\t%s\n", types.ObjectString(scope.Lookup(name), qualifier))
+				}
+			}
+			fmt.Println()
+		}
+	}
+
+	// Check that Test functions for io/ioutil, regexp and
+	// compress/bzip2 are all simultaneously present.
+	// (The apparent cycle formed when augmenting all three of
+	// these packages by their tests was the original motivation
+	// for reporting b/7114.)
+	//
+	// compress/bzip2.TestBitReader in bzip2_test.go    imports io/ioutil
+	// io/ioutil.TestTempFile       in tempfile_test.go imports regexp
+	// regexp.TestRE2Search         in exec_test.go     imports compress/bzip2
+	for _, test := range []struct{ pkg, fn string }{
+		{"io/ioutil", "TestTempFile"},
+		{"regexp", "TestRE2Search"},
+		{"compress/bzip2", "TestBitReader"},
+	} {
+		info := prog.Imported[test.pkg]
+		if info == nil {
+			t.Errorf("failed to load package %q", test.pkg)
+			continue
+		}
+		obj, _ := info.Pkg.Scope().Lookup(test.fn).(*types.Func)
+		if obj == nil {
+			t.Errorf("package %q has no func %q", test.pkg, test.fn)
+			continue
+		}
+	}
+
+	// Dump some statistics.
+
+	// determine line count
+	var lineCount int
+	prog.Fset.Iterate(func(f *token.File) bool {
+		lineCount += f.LineCount()
+		return true
+	})
+
+	t.Log("GOMAXPROCS:           ", runtime.GOMAXPROCS(0))
+	t.Log("#Source lines:        ", lineCount)
+	t.Log("Load/parse/typecheck: ", t1.Sub(t0))
+	t.Log("#MB:                  ", int64(memstats.Alloc-alloc)/1000000)
+}
+
+func TestCgoOption(t *testing.T) {
+	switch runtime.GOOS {
+	// On these systems, the net and os/user packages don't use cgo
+	// or the std library is incomplete (Android).
+	case "android", "plan9", "solaris", "windows":
+		t.Skipf("no cgo or incomplete std lib on %s", runtime.GOOS)
+	}
+	// In nocgo builds (e.g. linux-amd64-nocgo),
+	// there is no "runtime/cgo" package,
+	// so cgo-generated Go files will have a failing import.
+	if !build.Default.CgoEnabled {
+		return
+	}
+	// Test that we can load cgo-using packages with
+	// CGO_ENABLED=[01], which causes go/build to select pure
+	// Go/native implementations, respectively, based on build
+	// tags.
+	//
+	// Each entry specifies a package-level object and the generic
+	// file expected to define it when cgo is disabled.
+	// When cgo is enabled, the exact file is not specified (since
+	// it varies by platform), but must differ from the generic one.
+	//
+	// The test also loads the actual file to verify that the
+	// object is indeed defined at that location.
+	for _, test := range []struct {
+		pkg, name, genericFile string
+	}{
+		{"net", "cgoLookupHost", "cgo_stub.go"},
+		{"os/user", "lookupId", "lookup_stubs.go"},
+	} {
+		ctxt := build.Default
+		for _, ctxt.CgoEnabled = range []bool{false, true} {
+			conf := loader.Config{Build: &ctxt}
+			conf.Import(test.pkg)
+			prog, err := conf.Load()
+			if err != nil {
+				t.Errorf("Load failed: %v", err)
+				continue
+			}
+			info := prog.Imported[test.pkg]
+			if info == nil {
+				t.Errorf("package %s not found", test.pkg)
+				continue
+			}
+			obj := info.Pkg.Scope().Lookup(test.name)
+			if obj == nil {
+				t.Errorf("no object %s.%s", test.pkg, test.name)
+				continue
+			}
+			posn := prog.Fset.Position(obj.Pos())
+			t.Logf("%s: %s (CgoEnabled=%t)", posn, obj, ctxt.CgoEnabled)
+
+			gotFile := filepath.Base(posn.Filename)
+			filesMatch := gotFile == test.genericFile
+
+			if ctxt.CgoEnabled && filesMatch {
+				t.Errorf("CGO_ENABLED=1: %s found in %s, want native file",
+					obj, gotFile)
+			} else if !ctxt.CgoEnabled && !filesMatch {
+				t.Errorf("CGO_ENABLED=0: %s found in %s, want %s",
+					obj, gotFile, test.genericFile)
+			}
+
+			// Load the file and check the object is declared at the right place.
+			b, err := ioutil.ReadFile(posn.Filename)
+			if err != nil {
+				t.Errorf("can't read %s: %s", posn.Filename, err)
+				continue
+			}
+			line := string(bytes.Split(b, []byte("\n"))[posn.Line-1])
+			ident := line[posn.Column-1:]
+			if !strings.HasPrefix(ident, test.name) {
+				t.Errorf("%s: %s not declared here (looking at %q)", posn, obj, ident)
+			}
+		}
+	}
+}
diff --git a/go/src/golang.org/x/tools/go/loader/stdlib_test.go b/go/src/golang.org/x/tools/go/loader/stdlib_test.go
index b62ecfb..46cd8a2 100644
--- a/go/src/golang.org/x/tools/go/loader/stdlib_test.go
+++ b/go/src/golang.org/x/tools/go/loader/stdlib_test.go
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package loader_test
 
 // This file enumerates all packages beneath $GOROOT, loads them, plus
 // their external tests if any, runs the type checker on them, and
 // prints some summary information.
-//
-// Run test with GOMAXPROCS=8.
 
 import (
 	"bytes"
@@ -16,6 +16,7 @@
 	"go/ast"
 	"go/build"
 	"go/token"
+	"go/types"
 	"io/ioutil"
 	"path/filepath"
 	"runtime"
@@ -25,13 +26,15 @@
 
 	"golang.org/x/tools/go/buildutil"
 	"golang.org/x/tools/go/loader"
-	"golang.org/x/tools/go/types"
 )
 
 func TestStdlib(t *testing.T) {
 	if runtime.GOOS == "android" {
 		t.Skipf("incomplete std lib on %s", runtime.GOOS)
 	}
+	if testing.Short() {
+		t.Skip("skipping in short mode; uses tons of memory (golang.org/issue/14113)")
+	}
 
 	runtime.GC()
 	t0 := time.Now()
@@ -118,6 +121,9 @@
 }
 
 func TestCgoOption(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping in short mode; uses tons of memory (golang.org/issue/14113)")
+	}
 	switch runtime.GOOS {
 	// On these systems, the net and os/user packages don't use cgo
 	// or the std library is incomplete (Android).
diff --git a/go/src/golang.org/x/tools/go/loader/util.go b/go/src/golang.org/x/tools/go/loader/util.go
index 3b64856..7f38dd7 100644
--- a/go/src/golang.org/x/tools/go/loader/util.go
+++ b/go/src/golang.org/x/tools/go/loader/util.go
@@ -88,7 +88,7 @@
 	return parsed, errors
 }
 
-// scanImports returns the set of all package import paths from all
+// scanImports returns the set of all import paths from all
 // import specs in the specified files.
 func scanImports(files []*ast.File) map[string]bool {
 	imports := make(map[string]bool)
@@ -103,8 +103,8 @@
 					if err != nil {
 						continue // quietly ignore the error
 					}
-					if path == "C" || path == "unsafe" {
-						continue // skip pseudo packages
+					if path == "C" {
+						continue // skip pseudopackage
 					}
 					imports[path] = true
 				}
diff --git a/go/src/golang.org/x/tools/go/pointer/analysis.go b/go/src/golang.org/x/tools/go/pointer/analysis.go
index d02e536..9f3476c 100644
--- a/go/src/golang.org/x/tools/go/pointer/analysis.go
+++ b/go/src/golang.org/x/tools/go/pointer/analysis.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package pointer
 
 // This file defines the main datatypes and Analyze function of the pointer analysis.
@@ -9,6 +11,7 @@
 import (
 	"fmt"
 	"go/token"
+	"go/types"
 	"io"
 	"os"
 	"reflect"
@@ -18,7 +21,6 @@
 
 	"golang.org/x/tools/go/callgraph"
 	"golang.org/x/tools/go/ssa"
-	"golang.org/x/tools/go/types"
 	"golang.org/x/tools/go/types/typeutil"
 )
 
@@ -254,17 +256,17 @@
 	for _, pkg := range a.prog.AllPackages() {
 		// (This only checks that the package scope is complete,
 		// not that func bodies exist, but it's a good signal.)
-		if !pkg.Object.Complete() {
-			return nil, fmt.Errorf(`pointer analysis requires a complete program yet package %q was incomplete`, pkg.Object.Path())
+		if !pkg.Pkg.Complete() {
+			return nil, fmt.Errorf(`pointer analysis requires a complete program yet package %q was incomplete`, pkg.Pkg.Path())
 		}
 	}
 
 	if reflect := a.prog.ImportedPackage("reflect"); reflect != nil {
-		rV := reflect.Object.Scope().Lookup("Value")
+		rV := reflect.Pkg.Scope().Lookup("Value")
 		a.reflectValueObj = rV
 		a.reflectValueCall = a.prog.LookupMethod(rV.Type(), nil, "Call")
-		a.reflectType = reflect.Object.Scope().Lookup("Type").Type().(*types.Named)
-		a.reflectRtypeObj = reflect.Object.Scope().Lookup("rtype")
+		a.reflectType = reflect.Pkg.Scope().Lookup("Type").Type().(*types.Named)
+		a.reflectRtypeObj = reflect.Pkg.Scope().Lookup("rtype")
 		a.reflectRtypePtr = types.NewPointer(a.reflectRtypeObj.Type())
 
 		// Override flattening of reflect.Value, treating it like a basic type.
diff --git a/go/src/golang.org/x/tools/go/pointer/analysis14.go b/go/src/golang.org/x/tools/go/pointer/analysis14.go
new file mode 100644
index 0000000..70761fe
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/pointer/analysis14.go
@@ -0,0 +1,449 @@
+// 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.
+
+// +build !go1.5
+
+package pointer
+
+// This file defines the main datatypes and Analyze function of the pointer analysis.
+
+import (
+	"fmt"
+	"go/token"
+	"io"
+	"os"
+	"reflect"
+	"runtime"
+	"runtime/debug"
+	"sort"
+
+	"golang.org/x/tools/go/callgraph"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/go/types/typeutil"
+)
+
+const (
+	// optimization options; enable all when committing
+	optRenumber = true // enable renumbering optimization (makes logs hard to read)
+	optHVN      = true // enable pointer equivalence via Hash-Value Numbering
+
+	// debugging options; disable all when committing
+	debugHVN           = false // enable assertions in HVN
+	debugHVNVerbose    = false // enable extra HVN logging
+	debugHVNCrossCheck = false // run solver with/without HVN and compare (caveats below)
+	debugTimers        = false // show running time of each phase
+)
+
+// object.flags bitmask values.
+const (
+	otTagged   = 1 << iota // type-tagged object
+	otIndirect             // type-tagged object with indirect payload
+	otFunction             // function object
+)
+
+// An object represents a contiguous block of memory to which some
+// (generalized) pointer may point.
+//
+// (Note: most variables called 'obj' are not *objects but nodeids
+// such that a.nodes[obj].obj != nil.)
+//
+type object struct {
+	// flags is a bitset of the node type (ot*) flags defined above.
+	flags uint32
+
+	// Number of following nodes belonging to the same "object"
+	// allocation.  Zero for all other nodes.
+	size uint32
+
+	// data describes this object; it has one of these types:
+	//
+	// ssa.Value	for an object allocated by an SSA operation.
+	// types.Type	for an rtype instance object or *rtype-tagged object.
+	// string	for an instrinsic object, e.g. the array behind os.Args.
+	// nil		for an object allocated by an instrinsic.
+	//		(cgn provides the identity of the intrinsic.)
+	data interface{}
+
+	// The call-graph node (=context) in which this object was allocated.
+	// May be nil for global objects: Global, Const, some Functions.
+	cgn *cgnode
+}
+
+// nodeid denotes a node.
+// It is an index within analysis.nodes.
+// We use small integers, not *node pointers, for many reasons:
+// - they are smaller on 64-bit systems.
+// - sets of them can be represented compactly in bitvectors or BDDs.
+// - order matters; a field offset can be computed by simple addition.
+type nodeid uint32
+
+// A node is an equivalence class of memory locations.
+// Nodes may be pointers, pointed-to locations, neither, or both.
+//
+// Nodes that are pointed-to locations ("labels") have an enclosing
+// object (see analysis.enclosingObject).
+//
+type node struct {
+	// If non-nil, this node is the start of an object
+	// (addressable memory location).
+	// The following obj.size nodes implicitly belong to the object;
+	// they locate their object by scanning back.
+	obj *object
+
+	// The type of the field denoted by this node.  Non-aggregate,
+	// unless this is an tagged.T node (i.e. the thing
+	// pointed to by an interface) in which case typ is that type.
+	typ types.Type
+
+	// subelement indicates which directly embedded subelement of
+	// an object of aggregate type (struct, tuple, array) this is.
+	subelement *fieldInfo // e.g. ".a.b[*].c"
+
+	// Solver state for the canonical node of this pointer-
+	// equivalence class.  Each node is created with its own state
+	// but they become shared after HVN.
+	solve *solverState
+}
+
+// An analysis instance holds the state of a single pointer analysis problem.
+type analysis struct {
+	config      *Config                     // the client's control/observer interface
+	prog        *ssa.Program                // the program being analyzed
+	log         io.Writer                   // log stream; nil to disable
+	panicNode   nodeid                      // sink for panic, source for recover
+	nodes       []*node                     // indexed by nodeid
+	flattenMemo map[types.Type][]*fieldInfo // memoization of flatten()
+	trackTypes  map[types.Type]bool         // memoization of shouldTrack()
+	constraints []constraint                // set of constraints
+	cgnodes     []*cgnode                   // all cgnodes
+	genq        []*cgnode                   // queue of functions to generate constraints for
+	intrinsics  map[*ssa.Function]intrinsic // non-nil values are summaries for intrinsic fns
+	globalval   map[ssa.Value]nodeid        // node for each global ssa.Value
+	globalobj   map[ssa.Value]nodeid        // maps v to sole member of pts(v), if singleton
+	localval    map[ssa.Value]nodeid        // node for each local ssa.Value
+	localobj    map[ssa.Value]nodeid        // maps v to sole member of pts(v), if singleton
+	atFuncs     map[*ssa.Function]bool      // address-taken functions (for presolver)
+	mapValues   []nodeid                    // values of makemap objects (indirect in HVN)
+	work        nodeset                     // solver's worklist
+	result      *Result                     // results of the analysis
+	track       track                       // pointerlike types whose aliasing we track
+	deltaSpace  []int                       // working space for iterating over PTS deltas
+
+	// Reflection & intrinsics:
+	hasher              typeutil.Hasher // cache of type hashes
+	reflectValueObj     types.Object    // type symbol for reflect.Value (if present)
+	reflectValueCall    *ssa.Function   // (reflect.Value).Call
+	reflectRtypeObj     types.Object    // *types.TypeName for reflect.rtype (if present)
+	reflectRtypePtr     *types.Pointer  // *reflect.rtype
+	reflectType         *types.Named    // reflect.Type
+	rtypes              typeutil.Map    // nodeid of canonical *rtype-tagged object for type T
+	reflectZeros        typeutil.Map    // nodeid of canonical T-tagged object for zero value
+	runtimeSetFinalizer *ssa.Function   // runtime.SetFinalizer
+}
+
+// enclosingObj returns the first node of the addressable memory
+// object that encloses node id.  Panic ensues if that node does not
+// belong to any object.
+func (a *analysis) enclosingObj(id nodeid) nodeid {
+	// Find previous node with obj != nil.
+	for i := id; i >= 0; i-- {
+		n := a.nodes[i]
+		if obj := n.obj; obj != nil {
+			if i+nodeid(obj.size) <= id {
+				break // out of bounds
+			}
+			return i
+		}
+	}
+	panic("node has no enclosing object")
+}
+
+// labelFor returns the Label for node id.
+// Panic ensues if that node is not addressable.
+func (a *analysis) labelFor(id nodeid) *Label {
+	return &Label{
+		obj:        a.nodes[a.enclosingObj(id)].obj,
+		subelement: a.nodes[id].subelement,
+	}
+}
+
+func (a *analysis) warnf(pos token.Pos, format string, args ...interface{}) {
+	msg := fmt.Sprintf(format, args...)
+	if a.log != nil {
+		fmt.Fprintf(a.log, "%s: warning: %s\n", a.prog.Fset.Position(pos), msg)
+	}
+	a.result.Warnings = append(a.result.Warnings, Warning{pos, msg})
+}
+
+// computeTrackBits sets a.track to the necessary 'track' bits for the pointer queries.
+func (a *analysis) computeTrackBits() {
+	var queryTypes []types.Type
+	for v := range a.config.Queries {
+		queryTypes = append(queryTypes, v.Type())
+	}
+	for v := range a.config.IndirectQueries {
+		queryTypes = append(queryTypes, mustDeref(v.Type()))
+	}
+	for _, t := range queryTypes {
+		switch t.Underlying().(type) {
+		case *types.Chan:
+			a.track |= trackChan
+		case *types.Map:
+			a.track |= trackMap
+		case *types.Pointer:
+			a.track |= trackPtr
+		case *types.Slice:
+			a.track |= trackSlice
+		case *types.Interface:
+			a.track = trackAll
+			return
+		}
+		if rVObj := a.reflectValueObj; rVObj != nil && types.Identical(t, rVObj.Type()) {
+			a.track = trackAll
+			return
+		}
+	}
+}
+
+// Analyze runs the pointer analysis with the scope and options
+// specified by config, and returns the (synthetic) root of the callgraph.
+//
+// Pointer analysis of a transitively closed well-typed program should
+// always succeed.  An error can occur only due to an internal bug.
+//
+func Analyze(config *Config) (result *Result, err error) {
+	if config.Mains == nil {
+		return nil, fmt.Errorf("no main/test packages to analyze (check $GOROOT/$GOPATH)")
+	}
+	defer func() {
+		if p := recover(); p != nil {
+			err = fmt.Errorf("internal error in pointer analysis: %v (please report this bug)", p)
+			fmt.Fprintln(os.Stderr, "Internal panic in pointer analysis:")
+			debug.PrintStack()
+		}
+	}()
+
+	a := &analysis{
+		config:      config,
+		log:         config.Log,
+		prog:        config.prog(),
+		globalval:   make(map[ssa.Value]nodeid),
+		globalobj:   make(map[ssa.Value]nodeid),
+		flattenMemo: make(map[types.Type][]*fieldInfo),
+		trackTypes:  make(map[types.Type]bool),
+		atFuncs:     make(map[*ssa.Function]bool),
+		hasher:      typeutil.MakeHasher(),
+		intrinsics:  make(map[*ssa.Function]intrinsic),
+		result: &Result{
+			Queries:         make(map[ssa.Value]Pointer),
+			IndirectQueries: make(map[ssa.Value]Pointer),
+		},
+		deltaSpace: make([]int, 0, 100),
+	}
+
+	if false {
+		a.log = os.Stderr // for debugging crashes; extremely verbose
+	}
+
+	if a.log != nil {
+		fmt.Fprintln(a.log, "==== Starting analysis")
+	}
+
+	// Pointer analysis requires a complete program for soundness.
+	// Check to prevent accidental misconfiguration.
+	for _, pkg := range a.prog.AllPackages() {
+		// (This only checks that the package scope is complete,
+		// not that func bodies exist, but it's a good signal.)
+		if !pkg.Pkg.Complete() {
+			return nil, fmt.Errorf(`pointer analysis requires a complete program yet package %q was incomplete`, pkg.Pkg.Path())
+		}
+	}
+
+	if reflect := a.prog.ImportedPackage("reflect"); reflect != nil {
+		rV := reflect.Pkg.Scope().Lookup("Value")
+		a.reflectValueObj = rV
+		a.reflectValueCall = a.prog.LookupMethod(rV.Type(), nil, "Call")
+		a.reflectType = reflect.Pkg.Scope().Lookup("Type").Type().(*types.Named)
+		a.reflectRtypeObj = reflect.Pkg.Scope().Lookup("rtype")
+		a.reflectRtypePtr = types.NewPointer(a.reflectRtypeObj.Type())
+
+		// Override flattening of reflect.Value, treating it like a basic type.
+		tReflectValue := a.reflectValueObj.Type()
+		a.flattenMemo[tReflectValue] = []*fieldInfo{{typ: tReflectValue}}
+
+		// Override shouldTrack of reflect.Value and *reflect.rtype.
+		// Always track pointers of these types.
+		a.trackTypes[tReflectValue] = true
+		a.trackTypes[a.reflectRtypePtr] = true
+
+		a.rtypes.SetHasher(a.hasher)
+		a.reflectZeros.SetHasher(a.hasher)
+	}
+	if runtime := a.prog.ImportedPackage("runtime"); runtime != nil {
+		a.runtimeSetFinalizer = runtime.Func("SetFinalizer")
+	}
+	a.computeTrackBits()
+
+	a.generate()
+	a.showCounts()
+
+	if optRenumber {
+		a.renumber()
+	}
+
+	N := len(a.nodes) // excludes solver-created nodes
+
+	if optHVN {
+		if debugHVNCrossCheck {
+			// Cross-check: run the solver once without
+			// optimization, once with, and compare the
+			// solutions.
+			savedConstraints := a.constraints
+
+			a.solve()
+			a.dumpSolution("A.pts", N)
+
+			// Restore.
+			a.constraints = savedConstraints
+			for _, n := range a.nodes {
+				n.solve = new(solverState)
+			}
+			a.nodes = a.nodes[:N]
+
+			// rtypes is effectively part of the solver state.
+			a.rtypes = typeutil.Map{}
+			a.rtypes.SetHasher(a.hasher)
+		}
+
+		a.hvn()
+	}
+
+	if debugHVNCrossCheck {
+		runtime.GC()
+		runtime.GC()
+	}
+
+	a.solve()
+
+	// Compare solutions.
+	if optHVN && debugHVNCrossCheck {
+		a.dumpSolution("B.pts", N)
+
+		if !diff("A.pts", "B.pts") {
+			return nil, fmt.Errorf("internal error: optimization changed solution")
+		}
+	}
+
+	// Create callgraph.Nodes in deterministic order.
+	if cg := a.result.CallGraph; cg != nil {
+		for _, caller := range a.cgnodes {
+			cg.CreateNode(caller.fn)
+		}
+	}
+
+	// Add dynamic edges to call graph.
+	var space [100]int
+	for _, caller := range a.cgnodes {
+		for _, site := range caller.sites {
+			for _, callee := range a.nodes[site.targets].solve.pts.AppendTo(space[:0]) {
+				a.callEdge(caller, site, nodeid(callee))
+			}
+		}
+	}
+
+	return a.result, nil
+}
+
+// callEdge is called for each edge in the callgraph.
+// calleeid is the callee's object node (has otFunction flag).
+//
+func (a *analysis) callEdge(caller *cgnode, site *callsite, calleeid nodeid) {
+	obj := a.nodes[calleeid].obj
+	if obj.flags&otFunction == 0 {
+		panic(fmt.Sprintf("callEdge %s -> n%d: not a function object", site, calleeid))
+	}
+	callee := obj.cgn
+
+	if cg := a.result.CallGraph; cg != nil {
+		// TODO(adonovan): opt: I would expect duplicate edges
+		// (to wrappers) to arise due to the elimination of
+		// context information, but I haven't observed any.
+		// Understand this better.
+		callgraph.AddEdge(cg.CreateNode(caller.fn), site.instr, cg.CreateNode(callee.fn))
+	}
+
+	if a.log != nil {
+		fmt.Fprintf(a.log, "\tcall edge %s -> %s\n", site, callee)
+	}
+
+	// Warn about calls to non-intrinsic external functions.
+	// TODO(adonovan): de-dup these messages.
+	if fn := callee.fn; fn.Blocks == nil && a.findIntrinsic(fn) == nil {
+		a.warnf(site.pos(), "unsound call to unknown intrinsic: %s", fn)
+		a.warnf(fn.Pos(), " (declared here)")
+	}
+}
+
+// dumpSolution writes the PTS solution to the specified file.
+//
+// It only dumps the nodes that existed before solving.  The order in
+// which solver-created nodes are created depends on pre-solver
+// optimization, so we can't include them in the cross-check.
+//
+func (a *analysis) dumpSolution(filename string, N int) {
+	f, err := os.Create(filename)
+	if err != nil {
+		panic(err)
+	}
+	for id, n := range a.nodes[:N] {
+		if _, err := fmt.Fprintf(f, "pts(n%d) = {", id); err != nil {
+			panic(err)
+		}
+		var sep string
+		for _, l := range n.solve.pts.AppendTo(a.deltaSpace) {
+			if l >= N {
+				break
+			}
+			fmt.Fprintf(f, "%s%d", sep, l)
+			sep = " "
+		}
+		fmt.Fprintf(f, "} : %s\n", n.typ)
+	}
+	if err := f.Close(); err != nil {
+		panic(err)
+	}
+}
+
+// showCounts logs the size of the constraint system.  A typical
+// optimized distribution is 65% copy, 13% load, 11% addr, 5%
+// offsetAddr, 4% store, 2% others.
+//
+func (a *analysis) showCounts() {
+	if a.log != nil {
+		counts := make(map[reflect.Type]int)
+		for _, c := range a.constraints {
+			counts[reflect.TypeOf(c)]++
+		}
+		fmt.Fprintf(a.log, "# constraints:\t%d\n", len(a.constraints))
+		var lines []string
+		for t, n := range counts {
+			line := fmt.Sprintf("%7d  (%2d%%)\t%s", n, 100*n/len(a.constraints), t)
+			lines = append(lines, line)
+		}
+		sort.Sort(sort.Reverse(sort.StringSlice(lines)))
+		for _, line := range lines {
+			fmt.Fprintf(a.log, "\t%s\n", line)
+		}
+
+		fmt.Fprintf(a.log, "# nodes:\t%d\n", len(a.nodes))
+
+		// Show number of pointer equivalence classes.
+		m := make(map[*solverState]bool)
+		for _, n := range a.nodes {
+			m[n.solve] = true
+		}
+		fmt.Fprintf(a.log, "# ptsets:\t%d\n", len(m))
+	}
+}
diff --git a/go/src/golang.org/x/tools/go/pointer/api.go b/go/src/golang.org/x/tools/go/pointer/api.go
index 8f9ae0a..077ef56 100644
--- a/go/src/golang.org/x/tools/go/pointer/api.go
+++ b/go/src/golang.org/x/tools/go/pointer/api.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package pointer
 
 import (
diff --git a/go/src/golang.org/x/tools/go/pointer/api14.go b/go/src/golang.org/x/tools/go/pointer/api14.go
new file mode 100644
index 0000000..5481732
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/pointer/api14.go
@@ -0,0 +1,247 @@
+// 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.
+
+// +build !go1.5
+
+package pointer
+
+import (
+	"bytes"
+	"fmt"
+	"go/token"
+	"io"
+
+	"golang.org/x/tools/container/intsets"
+	"golang.org/x/tools/go/callgraph"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/types/typeutil"
+)
+
+// A Config formulates a pointer analysis problem for Analyze().
+type Config struct {
+	// Mains contains the set of 'main' packages to analyze
+	// Clients must provide the analysis with at least one
+	// package defining a main() function.
+	//
+	// Non-main packages in the ssa.Program that are not
+	// dependencies of any main package may still affect the
+	// analysis result, because they contribute runtime types and
+	// thus methods.
+	// TODO(adonovan): investigate whether this is desirable.
+	Mains []*ssa.Package
+
+	// Reflection determines whether to handle reflection
+	// operators soundly, which is currently rather slow since it
+	// causes constraint to be generated during solving
+	// proportional to the number of constraint variables, which
+	// has not yet been reduced by presolver optimisation.
+	Reflection bool
+
+	// BuildCallGraph determines whether to construct a callgraph.
+	// If enabled, the graph will be available in Result.CallGraph.
+	BuildCallGraph bool
+
+	// The client populates Queries[v] or IndirectQueries[v]
+	// for each ssa.Value v of interest, to request that the
+	// points-to sets pts(v) or pts(*v) be computed.  If the
+	// client needs both points-to sets, v may appear in both
+	// maps.
+	//
+	// (IndirectQueries is typically used for Values corresponding
+	// to source-level lvalues, e.g. an *ssa.Global.)
+	//
+	// The analysis populates the corresponding
+	// Result.{Indirect,}Queries map when it creates the pointer
+	// variable for v or *v.  Upon completion the client can
+	// inspect that map for the results.
+	//
+	// TODO(adonovan): this API doesn't scale well for batch tools
+	// that want to dump the entire solution.  Perhaps optionally
+	// populate a map[*ssa.DebugRef]Pointer in the Result, one
+	// entry per source expression.
+	//
+	Queries         map[ssa.Value]struct{}
+	IndirectQueries map[ssa.Value]struct{}
+
+	// If Log is non-nil, log messages are written to it.
+	// Logging is extremely verbose.
+	Log io.Writer
+}
+
+type track uint32
+
+const (
+	trackChan  track = 1 << iota // track 'chan' references
+	trackMap                     // track 'map' references
+	trackPtr                     // track regular pointers
+	trackSlice                   // track slice references
+
+	trackAll = ^track(0)
+)
+
+// AddQuery adds v to Config.Queries.
+// Precondition: CanPoint(v.Type()).
+// TODO(adonovan): consider returning a new Pointer for this query,
+// which will be initialized during analysis.  That avoids the needs
+// for the corresponding ssa.Value-keyed maps in Config and Result.
+func (c *Config) AddQuery(v ssa.Value) {
+	if !CanPoint(v.Type()) {
+		panic(fmt.Sprintf("%s is not a pointer-like value: %s", v, v.Type()))
+	}
+	if c.Queries == nil {
+		c.Queries = make(map[ssa.Value]struct{})
+	}
+	c.Queries[v] = struct{}{}
+}
+
+// AddQuery adds v to Config.IndirectQueries.
+// Precondition: CanPoint(v.Type().Underlying().(*types.Pointer).Elem()).
+func (c *Config) AddIndirectQuery(v ssa.Value) {
+	if c.IndirectQueries == nil {
+		c.IndirectQueries = make(map[ssa.Value]struct{})
+	}
+	if !CanPoint(mustDeref(v.Type())) {
+		panic(fmt.Sprintf("%s is not the address of a pointer-like value: %s", v, v.Type()))
+	}
+	c.IndirectQueries[v] = struct{}{}
+}
+
+func (c *Config) prog() *ssa.Program {
+	for _, main := range c.Mains {
+		return main.Prog
+	}
+	panic("empty scope")
+}
+
+type Warning struct {
+	Pos     token.Pos
+	Message string
+}
+
+// A Result contains the results of a pointer analysis.
+//
+// See Config for how to request the various Result components.
+//
+type Result struct {
+	CallGraph       *callgraph.Graph      // discovered call graph
+	Queries         map[ssa.Value]Pointer // pts(v) for each v in Config.Queries.
+	IndirectQueries map[ssa.Value]Pointer // pts(*v) for each v in Config.IndirectQueries.
+	Warnings        []Warning             // warnings of unsoundness
+}
+
+// A Pointer is an equivalence class of pointer-like values.
+//
+// A Pointer doesn't have a unique type because pointers of distinct
+// types may alias the same object.
+//
+type Pointer struct {
+	a *analysis
+	n nodeid
+}
+
+// A PointsToSet is a set of labels (locations or allocations).
+type PointsToSet struct {
+	a   *analysis // may be nil if pts is nil
+	pts *nodeset
+}
+
+func (s PointsToSet) String() string {
+	var buf bytes.Buffer
+	buf.WriteByte('[')
+	if s.pts != nil {
+		var space [50]int
+		for i, l := range s.pts.AppendTo(space[:0]) {
+			if i > 0 {
+				buf.WriteString(", ")
+			}
+			buf.WriteString(s.a.labelFor(nodeid(l)).String())
+		}
+	}
+	buf.WriteByte(']')
+	return buf.String()
+}
+
+// PointsTo returns the set of labels that this points-to set
+// contains.
+func (s PointsToSet) Labels() []*Label {
+	var labels []*Label
+	if s.pts != nil {
+		var space [50]int
+		for _, l := range s.pts.AppendTo(space[:0]) {
+			labels = append(labels, s.a.labelFor(nodeid(l)))
+		}
+	}
+	return labels
+}
+
+// If this PointsToSet came from a Pointer of interface kind
+// or a reflect.Value, DynamicTypes returns the set of dynamic
+// types that it may contain.  (For an interface, they will
+// always be concrete types.)
+//
+// The result is a mapping whose keys are the dynamic types to which
+// it may point.  For each pointer-like key type, the corresponding
+// map value is the PointsToSet for pointers of that type.
+//
+// The result is empty unless CanHaveDynamicTypes(T).
+//
+func (s PointsToSet) DynamicTypes() *typeutil.Map {
+	var tmap typeutil.Map
+	tmap.SetHasher(s.a.hasher)
+	if s.pts != nil {
+		var space [50]int
+		for _, x := range s.pts.AppendTo(space[:0]) {
+			ifaceObjId := nodeid(x)
+			if !s.a.isTaggedObject(ifaceObjId) {
+				continue // !CanHaveDynamicTypes(tDyn)
+			}
+			tDyn, v, indirect := s.a.taggedValue(ifaceObjId)
+			if indirect {
+				panic("indirect tagged object") // implement later
+			}
+			pts, ok := tmap.At(tDyn).(PointsToSet)
+			if !ok {
+				pts = PointsToSet{s.a, new(nodeset)}
+				tmap.Set(tDyn, pts)
+			}
+			pts.pts.addAll(&s.a.nodes[v].solve.pts)
+		}
+	}
+	return &tmap
+}
+
+// Intersects reports whether this points-to set and the
+// argument points-to set contain common members.
+func (x PointsToSet) Intersects(y PointsToSet) bool {
+	if x.pts == nil || y.pts == nil {
+		return false
+	}
+	// This takes Θ(|x|+|y|) time.
+	var z intsets.Sparse
+	z.Intersection(&x.pts.Sparse, &y.pts.Sparse)
+	return !z.IsEmpty()
+}
+
+func (p Pointer) String() string {
+	return fmt.Sprintf("n%d", p.n)
+}
+
+// PointsTo returns the points-to set of this pointer.
+func (p Pointer) PointsTo() PointsToSet {
+	if p.n == 0 {
+		return PointsToSet{}
+	}
+	return PointsToSet{p.a, &p.a.nodes[p.n].solve.pts}
+}
+
+// MayAlias reports whether the receiver pointer may alias
+// the argument pointer.
+func (p Pointer) MayAlias(q Pointer) bool {
+	return p.PointsTo().Intersects(q.PointsTo())
+}
+
+// DynamicTypes returns p.PointsTo().DynamicTypes().
+func (p Pointer) DynamicTypes() *typeutil.Map {
+	return p.PointsTo().DynamicTypes()
+}
diff --git a/go/src/golang.org/x/tools/go/pointer/constraint.go b/go/src/golang.org/x/tools/go/pointer/constraint.go
index e6371cc..ea44287 100644
--- a/go/src/golang.org/x/tools/go/pointer/constraint.go
+++ b/go/src/golang.org/x/tools/go/pointer/constraint.go
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package pointer
 
-import (
-	"golang.org/x/tools/go/types"
-)
+import "go/types"
 
 type constraint interface {
 	// For a complex constraint, returns the nodeid of the pointer
diff --git a/go/src/golang.org/x/tools/go/pointer/constraint14.go b/go/src/golang.org/x/tools/go/pointer/constraint14.go
new file mode 100644
index 0000000..d18064c
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/pointer/constraint14.go
@@ -0,0 +1,153 @@
+// 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.
+
+// +build !go1.5
+
+package pointer
+
+import (
+	"golang.org/x/tools/go/types"
+)
+
+type constraint interface {
+	// For a complex constraint, returns the nodeid of the pointer
+	// to which it is attached.   For addr and copy, returns dst.
+	ptr() nodeid
+
+	// renumber replaces each nodeid n in the constraint by mapping[n].
+	renumber(mapping []nodeid)
+
+	// presolve is a hook for constraint-specific behaviour during
+	// pre-solver optimization.  Typical implementations mark as
+	// indirect the set of nodes to which the solver will add copy
+	// edges or PTS labels.
+	presolve(h *hvn)
+
+	// solve is called for complex constraints when the pts for
+	// the node to which they are attached has changed.
+	solve(a *analysis, delta *nodeset)
+
+	String() string
+}
+
+// dst = &src
+// pts(dst) ⊇ {src}
+// A base constraint used to initialize the solver's pt sets
+type addrConstraint struct {
+	dst nodeid // (ptr)
+	src nodeid
+}
+
+func (c *addrConstraint) ptr() nodeid { return c.dst }
+func (c *addrConstraint) renumber(mapping []nodeid) {
+	c.dst = mapping[c.dst]
+	c.src = mapping[c.src]
+}
+
+// dst = src
+// A simple constraint represented directly as a copyTo graph edge.
+type copyConstraint struct {
+	dst nodeid // (ptr)
+	src nodeid
+}
+
+func (c *copyConstraint) ptr() nodeid { return c.dst }
+func (c *copyConstraint) renumber(mapping []nodeid) {
+	c.dst = mapping[c.dst]
+	c.src = mapping[c.src]
+}
+
+// dst = src[offset]
+// A complex constraint attached to src (the pointer)
+type loadConstraint struct {
+	offset uint32
+	dst    nodeid
+	src    nodeid // (ptr)
+}
+
+func (c *loadConstraint) ptr() nodeid { return c.src }
+func (c *loadConstraint) renumber(mapping []nodeid) {
+	c.dst = mapping[c.dst]
+	c.src = mapping[c.src]
+}
+
+// dst[offset] = src
+// A complex constraint attached to dst (the pointer)
+type storeConstraint struct {
+	offset uint32
+	dst    nodeid // (ptr)
+	src    nodeid
+}
+
+func (c *storeConstraint) ptr() nodeid { return c.dst }
+func (c *storeConstraint) renumber(mapping []nodeid) {
+	c.dst = mapping[c.dst]
+	c.src = mapping[c.src]
+}
+
+// dst = &src.f  or  dst = &src[0]
+// A complex constraint attached to dst (the pointer)
+type offsetAddrConstraint struct {
+	offset uint32
+	dst    nodeid
+	src    nodeid // (ptr)
+}
+
+func (c *offsetAddrConstraint) ptr() nodeid { return c.src }
+func (c *offsetAddrConstraint) renumber(mapping []nodeid) {
+	c.dst = mapping[c.dst]
+	c.src = mapping[c.src]
+}
+
+// dst = src.(typ)  where typ is an interface
+// A complex constraint attached to src (the interface).
+// No representation change: pts(dst) and pts(src) contains tagged objects.
+type typeFilterConstraint struct {
+	typ types.Type // an interface type
+	dst nodeid
+	src nodeid // (ptr)
+}
+
+func (c *typeFilterConstraint) ptr() nodeid { return c.src }
+func (c *typeFilterConstraint) renumber(mapping []nodeid) {
+	c.dst = mapping[c.dst]
+	c.src = mapping[c.src]
+}
+
+// dst = src.(typ)  where typ is a concrete type
+// A complex constraint attached to src (the interface).
+//
+// If exact, only tagged objects identical to typ are untagged.
+// If !exact, tagged objects assignable to typ are untagged too.
+// The latter is needed for various reflect operators, e.g. Send.
+//
+// This entails a representation change:
+// pts(src) contains tagged objects,
+// pts(dst) contains their payloads.
+type untagConstraint struct {
+	typ   types.Type // a concrete type
+	dst   nodeid
+	src   nodeid // (ptr)
+	exact bool
+}
+
+func (c *untagConstraint) ptr() nodeid { return c.src }
+func (c *untagConstraint) renumber(mapping []nodeid) {
+	c.dst = mapping[c.dst]
+	c.src = mapping[c.src]
+}
+
+// src.method(params...)
+// A complex constraint attached to iface.
+type invokeConstraint struct {
+	method *types.Func // the abstract method
+	iface  nodeid      // (ptr) the interface
+	params nodeid      // the start of the identity/params/results block
+}
+
+func (c *invokeConstraint) ptr() nodeid { return c.iface }
+func (c *invokeConstraint) renumber(mapping []nodeid) {
+	c.iface = mapping[c.iface]
+	c.params = mapping[c.params]
+}
diff --git a/go/src/golang.org/x/tools/go/pointer/doc.go b/go/src/golang.org/x/tools/go/pointer/doc.go
index 22e569c..17d98cb 100644
--- a/go/src/golang.org/x/tools/go/pointer/doc.go
+++ b/go/src/golang.org/x/tools/go/pointer/doc.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 /*
 
 Package pointer implements Andersen's analysis, an inclusion-based
diff --git a/go/src/golang.org/x/tools/go/pointer/doc14.go b/go/src/golang.org/x/tools/go/pointer/doc14.go
new file mode 100644
index 0000000..fe5ad60
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/pointer/doc14.go
@@ -0,0 +1,612 @@
+// 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.
+
+// +build !go1.5
+
+/*
+
+Package pointer implements Andersen's analysis, an inclusion-based
+pointer analysis algorithm first described in (Andersen, 1994).
+
+A pointer analysis relates every pointer expression in a whole program
+to the set of memory locations to which it might point.  This
+information can be used to construct a call graph of the program that
+precisely represents the destinations of dynamic function and method
+calls.  It can also be used to determine, for example, which pairs of
+channel operations operate on the same channel.
+
+The package allows the client to request a set of expressions of
+interest for which the points-to information will be returned once the
+analysis is complete.  In addition, the client may request that a
+callgraph is constructed.  The example program in example_test.go
+demonstrates both of these features.  Clients should not request more
+information than they need since it may increase the cost of the
+analysis significantly.
+
+
+CLASSIFICATION
+
+Our algorithm is INCLUSION-BASED: the points-to sets for x and y will
+be related by pts(y) ⊇ pts(x) if the program contains the statement
+y = x.
+
+It is FLOW-INSENSITIVE: it ignores all control flow constructs and the
+order of statements in a program.  It is therefore a "MAY ALIAS"
+analysis: its facts are of the form "P may/may not point to L",
+not "P must point to L".
+
+It is FIELD-SENSITIVE: it builds separate points-to sets for distinct
+fields, such as x and y in struct { x, y *int }.
+
+It is mostly CONTEXT-INSENSITIVE: most functions are analyzed once,
+so values can flow in at one call to the function and return out at
+another.  Only some smaller functions are analyzed with consideration
+of their calling context.
+
+It has a CONTEXT-SENSITIVE HEAP: objects are named by both allocation
+site and context, so the objects returned by two distinct calls to f:
+   func f() *T { return new(T) }
+are distinguished up to the limits of the calling context.
+
+It is a WHOLE PROGRAM analysis: it requires SSA-form IR for the
+complete Go program and summaries for native code.
+
+See the (Hind, PASTE'01) survey paper for an explanation of these terms.
+
+
+SOUNDNESS
+
+The analysis is fully sound when invoked on pure Go programs that do not
+use reflection or unsafe.Pointer conversions.  In other words, if there
+is any possible execution of the program in which pointer P may point to
+object O, the analysis will report that fact.
+
+
+REFLECTION
+
+By default, the "reflect" library is ignored by the analysis, as if all
+its functions were no-ops, but if the client enables the Reflection flag,
+the analysis will make a reasonable attempt to model the effects of
+calls into this library.  However, this comes at a significant
+performance cost, and not all features of that library are yet
+implemented.  In addition, some simplifying approximations must be made
+to ensure that the analysis terminates; for example, reflection can be
+used to construct an infinite set of types and values of those types,
+but the analysis arbitrarily bounds the depth of such types.
+
+Most but not all reflection operations are supported.
+In particular, addressable reflect.Values are not yet implemented, so
+operations such as (reflect.Value).Set have no analytic effect.
+
+
+UNSAFE POINTER CONVERSIONS
+
+The pointer analysis makes no attempt to understand aliasing between the
+operand x and result y of an unsafe.Pointer conversion:
+   y = (*T)(unsafe.Pointer(x))
+It is as if the conversion allocated an entirely new object:
+   y = new(T)
+
+
+NATIVE CODE
+
+The analysis cannot model the aliasing effects of functions written in
+languages other than Go, such as runtime intrinsics in C or assembly, or
+code accessed via cgo.  The result is as if such functions are no-ops.
+However, various important intrinsics are understood by the analysis,
+along with built-ins such as append.
+
+The analysis currently provides no way for users to specify the aliasing
+effects of native code.
+
+------------------------------------------------------------------------
+
+IMPLEMENTATION
+
+The remaining documentation is intended for package maintainers and
+pointer analysis specialists.  Maintainers should have a solid
+understanding of the referenced papers (especially those by H&L and PKH)
+before making making significant changes.
+
+The implementation is similar to that described in (Pearce et al,
+PASTE'04).  Unlike many algorithms which interleave constraint
+generation and solving, constructing the callgraph as they go, this
+implementation for the most part observes a phase ordering (generation
+before solving), with only simple (copy) constraints being generated
+during solving.  (The exception is reflection, which creates various
+constraints during solving as new types flow to reflect.Value
+operations.)  This improves the traction of presolver optimisations,
+but imposes certain restrictions, e.g. potential context sensitivity
+is limited since all variants must be created a priori.
+
+
+TERMINOLOGY
+
+A type is said to be "pointer-like" if it is a reference to an object.
+Pointer-like types include pointers and also interfaces, maps, channels,
+functions and slices.
+
+We occasionally use C's x->f notation to distinguish the case where x
+is a struct pointer from x.f where is a struct value.
+
+Pointer analysis literature (and our comments) often uses the notation
+dst=*src+offset to mean something different than what it means in Go.
+It means: for each node index p in pts(src), the node index p+offset is
+in pts(dst).  Similarly *dst+offset=src is used for store constraints
+and dst=src+offset for offset-address constraints.
+
+
+NODES
+
+Nodes are the key datastructure of the analysis, and have a dual role:
+they represent both constraint variables (equivalence classes of
+pointers) and members of points-to sets (things that can be pointed
+at, i.e. "labels").
+
+Nodes are naturally numbered.  The numbering enables compact
+representations of sets of nodes such as bitvectors (or BDDs); and the
+ordering enables a very cheap way to group related nodes together.  For
+example, passing n parameters consists of generating n parallel
+constraints from caller+i to callee+i for 0<=i<n.
+
+The zero nodeid means "not a pointer".  For simplicity, we generate flow
+constraints even for non-pointer types such as int.  The pointer
+equivalence (PE) presolver optimization detects which variables cannot
+point to anything; this includes not only all variables of non-pointer
+types (such as int) but also variables of pointer-like types if they are
+always nil, or are parameters to a function that is never called.
+
+Each node represents a scalar part of a value or object.
+Aggregate types (structs, tuples, arrays) are recursively flattened
+out into a sequential list of scalar component types, and all the
+elements of an array are represented by a single node.  (The
+flattening of a basic type is a list containing a single node.)
+
+Nodes are connected into a graph with various kinds of labelled edges:
+simple edges (or copy constraints) represent value flow.  Complex
+edges (load, store, etc) trigger the creation of new simple edges
+during the solving phase.
+
+
+OBJECTS
+
+Conceptually, an "object" is a contiguous sequence of nodes denoting
+an addressable location: something that a pointer can point to.  The
+first node of an object has a non-nil obj field containing information
+about the allocation: its size, context, and ssa.Value.
+
+Objects include:
+   - functions and globals;
+   - variable allocations in the stack frame or heap;
+   - maps, channels and slices created by calls to make();
+   - allocations to construct an interface;
+   - allocations caused by conversions, e.g. []byte(str).
+   - arrays allocated by calls to append();
+
+Many objects have no Go types.  For example, the func, map and chan type
+kinds in Go are all varieties of pointers, but their respective objects
+are actual functions (executable code), maps (hash tables), and channels
+(synchronized queues).  Given the way we model interfaces, they too are
+pointers to "tagged" objects with no Go type.  And an *ssa.Global denotes
+the address of a global variable, but the object for a Global is the
+actual data.  So, the types of an ssa.Value that creates an object is
+"off by one indirection": a pointer to the object.
+
+The individual nodes of an object are sometimes referred to as "labels".
+
+For uniformity, all objects have a non-zero number of fields, even those
+of the empty type struct{}.  (All arrays are treated as if of length 1,
+so there are no empty arrays.  The empty tuple is never address-taken,
+so is never an object.)
+
+
+TAGGED OBJECTS
+
+An tagged object has the following layout:
+
+    T          -- obj.flags ⊇ {otTagged}
+    v
+    ...
+
+The T node's typ field is the dynamic type of the "payload": the value
+v which follows, flattened out.  The T node's obj has the otTagged
+flag.
+
+Tagged objects are needed when generalizing across types: interfaces,
+reflect.Values, reflect.Types.  Each of these three types is modelled
+as a pointer that exclusively points to tagged objects.
+
+Tagged objects may be indirect (obj.flags ⊇ {otIndirect}) meaning that
+the value v is not of type T but *T; this is used only for
+reflect.Values that represent lvalues.  (These are not implemented yet.)
+
+
+ANALYSIS ABSTRACTION OF EACH TYPE
+
+Variables of the following "scalar" types may be represented by a
+single node: basic types, pointers, channels, maps, slices, 'func'
+pointers, interfaces.
+
+Pointers
+  Nothing to say here, oddly.
+
+Basic types (bool, string, numbers, unsafe.Pointer)
+  Currently all fields in the flattening of a type, including
+  non-pointer basic types such as int, are represented in objects and
+  values.  Though non-pointer nodes within values are uninteresting,
+  non-pointer nodes in objects may be useful (if address-taken)
+  because they permit the analysis to deduce, in this example,
+
+     var s struct{ ...; x int; ... }
+     p := &s.x
+
+  that p points to s.x.  If we ignored such object fields, we could only
+  say that p points somewhere within s.
+
+  All other basic types are ignored.  Expressions of these types have
+  zero nodeid, and fields of these types within aggregate other types
+  are omitted.
+
+  unsafe.Pointers are not modelled as pointers, so a conversion of an
+  unsafe.Pointer to *T is (unsoundly) treated equivalent to new(T).
+
+Channels
+  An expression of type 'chan T' is a kind of pointer that points
+  exclusively to channel objects, i.e. objects created by MakeChan (or
+  reflection).
+
+  'chan T' is treated like *T.
+  *ssa.MakeChan is treated as equivalent to new(T).
+  *ssa.Send and receive (*ssa.UnOp(ARROW)) and are equivalent to store
+   and load.
+
+Maps
+  An expression of type 'map[K]V' is a kind of pointer that points
+  exclusively to map objects, i.e. objects created by MakeMap (or
+  reflection).
+
+  map K[V] is treated like *M where M = struct{k K; v V}.
+  *ssa.MakeMap is equivalent to new(M).
+  *ssa.MapUpdate is equivalent to *y=x where *y and x have type M.
+  *ssa.Lookup is equivalent to y=x.v where x has type *M.
+
+Slices
+  A slice []T, which dynamically resembles a struct{array *T, len, cap int},
+  is treated as if it were just a *T pointer; the len and cap fields are
+  ignored.
+
+  *ssa.MakeSlice is treated like new([1]T): an allocation of a
+   singleton array.
+  *ssa.Index on a slice is equivalent to a load.
+  *ssa.IndexAddr on a slice returns the address of the sole element of the
+  slice, i.e. the same address.
+  *ssa.Slice is treated as a simple copy.
+
+Functions
+  An expression of type 'func...' is a kind of pointer that points
+  exclusively to function objects.
+
+  A function object has the following layout:
+
+     identity         -- typ:*types.Signature; obj.flags ⊇ {otFunction}
+     params_0         -- (the receiver, if a method)
+     ...
+     params_n-1
+     results_0
+     ...
+     results_m-1
+
+  There may be multiple function objects for the same *ssa.Function
+  due to context-sensitive treatment of some functions.
+
+  The first node is the function's identity node.
+  Associated with every callsite is a special "targets" variable,
+  whose pts() contains the identity node of each function to which
+  the call may dispatch.  Identity words are not otherwise used during
+  the analysis, but we construct the call graph from the pts()
+  solution for such nodes.
+
+  The following block of contiguous nodes represents the flattened-out
+  types of the parameters ("P-block") and results ("R-block") of the
+  function object.
+
+  The treatment of free variables of closures (*ssa.FreeVar) is like
+  that of global variables; it is not context-sensitive.
+  *ssa.MakeClosure instructions create copy edges to Captures.
+
+  A Go value of type 'func' (i.e. a pointer to one or more functions)
+  is a pointer whose pts() contains function objects.  The valueNode()
+  for an *ssa.Function returns a singleton for that function.
+
+Interfaces
+  An expression of type 'interface{...}' is a kind of pointer that
+  points exclusively to tagged objects.  All tagged objects pointed to
+  by an interface are direct (the otIndirect flag is clear) and
+  concrete (the tag type T is not itself an interface type).  The
+  associated ssa.Value for an interface's tagged objects may be an
+  *ssa.MakeInterface instruction, or nil if the tagged object was
+  created by an instrinsic (e.g. reflection).
+
+  Constructing an interface value causes generation of constraints for
+  all of the concrete type's methods; we can't tell a priori which
+  ones may be called.
+
+  TypeAssert y = x.(T) is implemented by a dynamic constraint
+  triggered by each tagged object O added to pts(x): a typeFilter
+  constraint if T is an interface type, or an untag constraint if T is
+  a concrete type.  A typeFilter tests whether O.typ implements T; if
+  so, O is added to pts(y).  An untagFilter tests whether O.typ is
+  assignable to T,and if so, a copy edge O.v -> y is added.
+
+  ChangeInterface is a simple copy because the representation of
+  tagged objects is independent of the interface type (in contrast
+  to the "method tables" approach used by the gc runtime).
+
+  y := Invoke x.m(...) is implemented by allocating contiguous P/R
+  blocks for the callsite and adding a dynamic rule triggered by each
+  tagged object added to pts(x).  The rule adds param/results copy
+  edges to/from each discovered concrete method.
+
+  (Q. Why do we model an interface as a pointer to a pair of type and
+  value, rather than as a pair of a pointer to type and a pointer to
+  value?
+  A. Control-flow joins would merge interfaces ({T1}, {V1}) and ({T2},
+  {V2}) to make ({T1,T2}, {V1,V2}), leading to the infeasible and
+  type-unsafe combination (T1,V2).  Treating the value and its concrete
+  type as inseparable makes the analysis type-safe.)
+
+reflect.Value
+  A reflect.Value is modelled very similar to an interface{}, i.e. as
+  a pointer exclusively to tagged objects, but with two generalizations.
+
+  1) a reflect.Value that represents an lvalue points to an indirect
+     (obj.flags ⊇ {otIndirect}) tagged object, which has a similar
+     layout to an tagged object except that the value is a pointer to
+     the dynamic type.  Indirect tagged objects preserve the correct
+     aliasing so that mutations made by (reflect.Value).Set can be
+     observed.
+
+     Indirect objects only arise when an lvalue is derived from an
+     rvalue by indirection, e.g. the following code:
+
+        type S struct { X T }
+        var s S
+        var i interface{} = &s    // i points to a *S-tagged object (from MakeInterface)
+        v1 := reflect.ValueOf(i)  // v1 points to same *S-tagged object as i
+        v2 := v1.Elem()           // v2 points to an indirect S-tagged object, pointing to s
+        v3 := v2.FieldByName("X") // v3 points to an indirect int-tagged object, pointing to s.X
+        v3.Set(y)                 // pts(s.X) ⊇ pts(y)
+
+     Whether indirect or not, the concrete type of the tagged object
+     corresponds to the user-visible dynamic type, and the existence
+     of a pointer is an implementation detail.
+
+     (NB: indirect tagged objects are not yet implemented)
+
+  2) The dynamic type tag of a tagged object pointed to by a
+     reflect.Value may be an interface type; it need not be concrete.
+
+     This arises in code such as this:
+        tEface := reflect.TypeOf(new(interface{}).Elem() // interface{}
+        eface := reflect.Zero(tEface)
+     pts(eface) is a singleton containing an interface{}-tagged
+     object.  That tagged object's payload is an interface{} value,
+     i.e. the pts of the payload contains only concrete-tagged
+     objects, although in this example it's the zero interface{} value,
+     so its pts is empty.
+
+reflect.Type
+  Just as in the real "reflect" library, we represent a reflect.Type
+  as an interface whose sole implementation is the concrete type,
+  *reflect.rtype.  (This choice is forced on us by go/types: clients
+  cannot fabricate types with arbitrary method sets.)
+
+  rtype instances are canonical: there is at most one per dynamic
+  type.  (rtypes are in fact large structs but since identity is all
+  that matters, we represent them by a single node.)
+
+  The payload of each *rtype-tagged object is an *rtype pointer that
+  points to exactly one such canonical rtype object.  We exploit this
+  by setting the node.typ of the payload to the dynamic type, not
+  '*rtype'.  This saves us an indirection in each resolution rule.  As
+  an optimisation, *rtype-tagged objects are canonicalized too.
+
+
+Aggregate types:
+
+Aggregate types are treated as if all directly contained
+aggregates are recursively flattened out.
+
+Structs
+  *ssa.Field y = x.f creates a simple edge to y from x's node at f's offset.
+
+  *ssa.FieldAddr y = &x->f requires a dynamic closure rule to create
+   simple edges for each struct discovered in pts(x).
+
+  The nodes of a struct consist of a special 'identity' node (whose
+  type is that of the struct itself), followed by the nodes for all
+  the struct's fields, recursively flattened out.  A pointer to the
+  struct is a pointer to its identity node.  That node allows us to
+  distinguish a pointer to a struct from a pointer to its first field.
+
+  Field offsets are logical field offsets (plus one for the identity
+  node), so the sizes of the fields can be ignored by the analysis.
+
+  (The identity node is non-traditional but enables the distiction
+  described above, which is valuable for code comprehension tools.
+  Typical pointer analyses for C, whose purpose is compiler
+  optimization, must soundly model unsafe.Pointer (void*) conversions,
+  and this requires fidelity to the actual memory layout using physical
+  field offsets.)
+
+  *ssa.Field y = x.f creates a simple edge to y from x's node at f's offset.
+
+  *ssa.FieldAddr y = &x->f requires a dynamic closure rule to create
+   simple edges for each struct discovered in pts(x).
+
+Arrays
+  We model an array by an identity node (whose type is that of the
+  array itself) followed by a node representing all the elements of
+  the array; the analysis does not distinguish elements with different
+  indices.  Effectively, an array is treated like struct{elem T}, a
+  load y=x[i] like y=x.elem, and a store x[i]=y like x.elem=y; the
+  index i is ignored.
+
+  A pointer to an array is pointer to its identity node.  (A slice is
+  also a pointer to an array's identity node.)  The identity node
+  allows us to distinguish a pointer to an array from a pointer to one
+  of its elements, but it is rather costly because it introduces more
+  offset constraints into the system.  Furthermore, sound treatment of
+  unsafe.Pointer would require us to dispense with this node.
+
+  Arrays may be allocated by Alloc, by make([]T), by calls to append,
+  and via reflection.
+
+Tuples (T, ...)
+  Tuples are treated like structs with naturally numbered fields.
+  *ssa.Extract is analogous to *ssa.Field.
+
+  However, tuples have no identity field since by construction, they
+  cannot be address-taken.
+
+
+FUNCTION CALLS
+
+  There are three kinds of function call:
+  (1) static "call"-mode calls of functions.
+  (2) dynamic "call"-mode calls of functions.
+  (3) dynamic "invoke"-mode calls of interface methods.
+  Cases 1 and 2 apply equally to methods and standalone functions.
+
+  Static calls.
+    A static call consists three steps:
+    - finding the function object of the callee;
+    - creating copy edges from the actual parameter value nodes to the
+      P-block in the function object (this includes the receiver if
+      the callee is a method);
+    - creating copy edges from the R-block in the function object to
+      the value nodes for the result of the call.
+
+    A static function call is little more than two struct value copies
+    between the P/R blocks of caller and callee:
+
+       callee.P = caller.P
+       caller.R = callee.R
+
+    Context sensitivity
+
+      Static calls (alone) may be treated context sensitively,
+      i.e. each callsite may cause a distinct re-analysis of the
+      callee, improving precision.  Our current context-sensitivity
+      policy treats all intrinsics and getter/setter methods in this
+      manner since such functions are small and seem like an obvious
+      source of spurious confluences, though this has not yet been
+      evaluated.
+
+  Dynamic function calls
+
+    Dynamic calls work in a similar manner except that the creation of
+    copy edges occurs dynamically, in a similar fashion to a pair of
+    struct copies in which the callee is indirect:
+
+       callee->P = caller.P
+       caller.R = callee->R
+
+    (Recall that the function object's P- and R-blocks are contiguous.)
+
+  Interface method invocation
+
+    For invoke-mode calls, we create a params/results block for the
+    callsite and attach a dynamic closure rule to the interface.  For
+    each new tagged object that flows to the interface, we look up
+    the concrete method, find its function object, and connect its P/R
+    blocks to the callsite's P/R blocks, adding copy edges to the graph
+    during solving.
+
+  Recording call targets
+
+    The analysis notifies its clients of each callsite it encounters,
+    passing a CallSite interface.  Among other things, the CallSite
+    contains a synthetic constraint variable ("targets") whose
+    points-to solution includes the set of all function objects to
+    which the call may dispatch.
+
+    It is via this mechanism that the callgraph is made available.
+    Clients may also elect to be notified of callgraph edges directly;
+    internally this just iterates all "targets" variables' pts(·)s.
+
+
+PRESOLVER
+
+We implement Hash-Value Numbering (HVN), a pre-solver constraint
+optimization described in Hardekopf & Lin, SAS'07.  This is documented
+in more detail in hvn.go.  We intend to add its cousins HR and HU in
+future.
+
+
+SOLVER
+
+The solver is currently a naive Andersen-style implementation; it does
+not perform online cycle detection, though we plan to add solver
+optimisations such as Hybrid- and Lazy- Cycle Detection from (Hardekopf
+& Lin, PLDI'07).
+
+It uses difference propagation (Pearce et al, SQC'04) to avoid
+redundant re-triggering of closure rules for values already seen.
+
+Points-to sets are represented using sparse bit vectors (similar to
+those used in LLVM and gcc), which are more space- and time-efficient
+than sets based on Go's built-in map type or dense bit vectors.
+
+Nodes are permuted prior to solving so that object nodes (which may
+appear in points-to sets) are lower numbered than non-object (var)
+nodes.  This improves the density of the set over which the PTSs
+range, and thus the efficiency of the representation.
+
+Partly thanks to avoiding map iteration, the execution of the solver is
+100% deterministic, a great help during debugging.
+
+
+FURTHER READING
+
+Andersen, L. O. 1994. Program analysis and specialization for the C
+programming language. Ph.D. dissertation. DIKU, University of
+Copenhagen.
+
+David J. Pearce, Paul H. J. Kelly, and Chris Hankin. 2004.  Efficient
+field-sensitive pointer analysis for C. In Proceedings of the 5th ACM
+SIGPLAN-SIGSOFT workshop on Program analysis for software tools and
+engineering (PASTE '04). ACM, New York, NY, USA, 37-42.
+http://doi.acm.org/10.1145/996821.996835
+
+David J. Pearce, Paul H. J. Kelly, and Chris Hankin. 2004. Online
+Cycle Detection and Difference Propagation: Applications to Pointer
+Analysis. Software Quality Control 12, 4 (December 2004), 311-337.
+http://dx.doi.org/10.1023/B:SQJO.0000039791.93071.a2
+
+David Grove and Craig Chambers. 2001. A framework for call graph
+construction algorithms. ACM Trans. Program. Lang. Syst. 23, 6
+(November 2001), 685-746.
+http://doi.acm.org/10.1145/506315.506316
+
+Ben Hardekopf and Calvin Lin. 2007. The ant and the grasshopper: fast
+and accurate pointer analysis for millions of lines of code. In
+Proceedings of the 2007 ACM SIGPLAN conference on Programming language
+design and implementation (PLDI '07). ACM, New York, NY, USA, 290-299.
+http://doi.acm.org/10.1145/1250734.1250767
+
+Ben Hardekopf and Calvin Lin. 2007. Exploiting pointer and location
+equivalence to optimize pointer analysis. In Proceedings of the 14th
+international conference on Static Analysis (SAS'07), Hanne Riis
+Nielson and Gilberto Filé (Eds.). Springer-Verlag, Berlin, Heidelberg,
+265-280.
+
+Atanas Rountev and Satish Chandra. 2000. Off-line variable substitution
+for scaling points-to analysis. In Proceedings of the ACM SIGPLAN 2000
+conference on Programming language design and implementation (PLDI '00).
+ACM, New York, NY, USA, 47-56. DOI=10.1145/349299.349310
+http://doi.acm.org/10.1145/349299.349310
+
+*/
+package pointer // import "golang.org/x/tools/go/pointer"
diff --git a/go/src/golang.org/x/tools/go/pointer/example_test.go b/go/src/golang.org/x/tools/go/pointer/example_test.go
index ba70557..673de7a 100644
--- a/go/src/golang.org/x/tools/go/pointer/example_test.go
+++ b/go/src/golang.org/x/tools/go/pointer/example_test.go
@@ -66,7 +66,7 @@
 	mainPkg := prog.Package(iprog.Created[0].Pkg)
 
 	// Build SSA code for bodies of all functions in the whole program.
-	prog.BuildAll()
+	prog.Build()
 
 	// Configure the pointer analysis to build a call-graph.
 	config := &pointer.Config{
@@ -76,7 +76,7 @@
 
 	// Query points-to set of (C).f's parameter m, a map.
 	C := mainPkg.Type("C").Type()
-	Cfm := prog.LookupMethod(C, mainPkg.Object, "f").Params[1]
+	Cfm := prog.LookupMethod(C, mainPkg.Pkg, "f").Params[1]
 	config.AddQuery(Cfm)
 
 	// Run the pointer analysis.
diff --git a/go/src/golang.org/x/tools/go/pointer/gen.go b/go/src/golang.org/x/tools/go/pointer/gen.go
index 6c256ac..405a63b 100644
--- a/go/src/golang.org/x/tools/go/pointer/gen.go
+++ b/go/src/golang.org/x/tools/go/pointer/gen.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package pointer
 
 // This file defines the constraint generation phase.
@@ -13,10 +15,10 @@
 import (
 	"fmt"
 	"go/token"
+	"go/types"
 
 	"golang.org/x/tools/go/callgraph"
 	"golang.org/x/tools/go/ssa"
-	"golang.org/x/tools/go/types"
 )
 
 var (
@@ -1050,11 +1052,32 @@
 			// Assumes that Next is always directly applied to a Range result.
 			theMap := instr.Iter.(*ssa.Range).X
 			tMap := theMap.Type().Underlying().(*types.Map)
+
 			ksize := a.sizeof(tMap.Key())
 			vsize := a.sizeof(tMap.Elem())
 
+			// The k/v components of the Next tuple may each be invalid.
+			tTuple := instr.Type().(*types.Tuple)
+
 			// Load from the map's (k,v) into the tuple's (ok, k, v).
-			a.genLoad(cgn, a.valueNode(instr)+1, theMap, 0, ksize+vsize)
+			osrc := uint32(0) // offset within map object
+			odst := uint32(1) // offset within tuple (initially just after 'ok bool')
+			sz := uint32(0)   // amount to copy
+
+			// Is key valid?
+			if tTuple.At(1).Type() != tInvalid {
+				sz += ksize
+			} else {
+				odst += ksize
+				osrc += ksize
+			}
+
+			// Is value valid?
+			if tTuple.At(2).Type() != tInvalid {
+				sz += vsize
+			}
+
+			a.genLoad(cgn, a.valueNode(instr)+nodeid(odst), theMap, osrc, sz)
 		}
 
 	case *ssa.Lookup:
@@ -1223,7 +1246,7 @@
 	// I think so, but the answer may depend on reflection.
 	mset := a.prog.MethodSets.MethodSet(T)
 	for i, n := 0, mset.Len(); i < n; i++ {
-		m := a.prog.Method(mset.At(i))
+		m := a.prog.MethodValue(mset.At(i))
 		a.valueNode(m)
 
 		if !itf {
diff --git a/go/src/golang.org/x/tools/go/pointer/gen14.go b/go/src/golang.org/x/tools/go/pointer/gen14.go
new file mode 100644
index 0000000..c1bce7c
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/pointer/gen14.go
@@ -0,0 +1,1315 @@
+// 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.
+
+// +build !go1.5
+
+package pointer
+
+// This file defines the constraint generation phase.
+
+// TODO(adonovan): move the constraint definitions and the store() etc
+// functions which add them (and are also used by the solver) into a
+// new file, constraints.go.
+
+import (
+	"fmt"
+	"go/token"
+
+	"golang.org/x/tools/go/callgraph"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/types"
+)
+
+var (
+	tEface     = types.NewInterface(nil, nil).Complete()
+	tInvalid   = types.Typ[types.Invalid]
+	tUnsafePtr = types.Typ[types.UnsafePointer]
+)
+
+// ---------- Node creation ----------
+
+// nextNode returns the index of the next unused node.
+func (a *analysis) nextNode() nodeid {
+	return nodeid(len(a.nodes))
+}
+
+// addNodes creates nodes for all scalar elements in type typ, and
+// returns the id of the first one, or zero if the type was
+// analytically uninteresting.
+//
+// comment explains the origin of the nodes, as a debugging aid.
+//
+func (a *analysis) addNodes(typ types.Type, comment string) nodeid {
+	id := a.nextNode()
+	for _, fi := range a.flatten(typ) {
+		a.addOneNode(fi.typ, comment, fi)
+	}
+	if id == a.nextNode() {
+		return 0 // type contained no pointers
+	}
+	return id
+}
+
+// addOneNode creates a single node with type typ, and returns its id.
+//
+// typ should generally be scalar (except for tagged.T nodes
+// and struct/array identity nodes).  Use addNodes for non-scalar types.
+//
+// comment explains the origin of the nodes, as a debugging aid.
+// subelement indicates the subelement, e.g. ".a.b[*].c".
+//
+func (a *analysis) addOneNode(typ types.Type, comment string, subelement *fieldInfo) nodeid {
+	id := a.nextNode()
+	a.nodes = append(a.nodes, &node{typ: typ, subelement: subelement, solve: new(solverState)})
+	if a.log != nil {
+		fmt.Fprintf(a.log, "\tcreate n%d %s for %s%s\n",
+			id, typ, comment, subelement.path())
+	}
+	return id
+}
+
+// setValueNode associates node id with the value v.
+// cgn identifies the context iff v is a local variable.
+//
+func (a *analysis) setValueNode(v ssa.Value, id nodeid, cgn *cgnode) {
+	if cgn != nil {
+		a.localval[v] = id
+	} else {
+		a.globalval[v] = id
+	}
+	if a.log != nil {
+		fmt.Fprintf(a.log, "\tval[%s] = n%d  (%T)\n", v.Name(), id, v)
+	}
+
+	// Due to context-sensitivity, we may encounter the same Value
+	// in many contexts. We merge them to a canonical node, since
+	// that's what all clients want.
+
+	// Record the (v, id) relation if the client has queried pts(v).
+	if _, ok := a.config.Queries[v]; ok {
+		t := v.Type()
+		ptr, ok := a.result.Queries[v]
+		if !ok {
+			// First time?  Create the canonical query node.
+			ptr = Pointer{a, a.addNodes(t, "query")}
+			a.result.Queries[v] = ptr
+		}
+		a.result.Queries[v] = ptr
+		a.copy(ptr.n, id, a.sizeof(t))
+	}
+
+	// Record the (*v, id) relation if the client has queried pts(*v).
+	if _, ok := a.config.IndirectQueries[v]; ok {
+		t := v.Type()
+		ptr, ok := a.result.IndirectQueries[v]
+		if !ok {
+			// First time? Create the canonical indirect query node.
+			ptr = Pointer{a, a.addNodes(v.Type(), "query.indirect")}
+			a.result.IndirectQueries[v] = ptr
+		}
+		a.genLoad(cgn, ptr.n, v, 0, a.sizeof(t))
+	}
+}
+
+// endObject marks the end of a sequence of calls to addNodes denoting
+// a single object allocation.
+//
+// obj is the start node of the object, from a prior call to nextNode.
+// Its size, flags and optional data will be updated.
+//
+func (a *analysis) endObject(obj nodeid, cgn *cgnode, data interface{}) *object {
+	// Ensure object is non-empty by padding;
+	// the pad will be the object node.
+	size := uint32(a.nextNode() - obj)
+	if size == 0 {
+		a.addOneNode(tInvalid, "padding", nil)
+	}
+	objNode := a.nodes[obj]
+	o := &object{
+		size: size, // excludes padding
+		cgn:  cgn,
+		data: data,
+	}
+	objNode.obj = o
+
+	return o
+}
+
+// makeFunctionObject creates and returns a new function object
+// (contour) for fn, and returns the id of its first node.  It also
+// enqueues fn for subsequent constraint generation.
+//
+// For a context-sensitive contour, callersite identifies the sole
+// callsite; for shared contours, caller is nil.
+//
+func (a *analysis) makeFunctionObject(fn *ssa.Function, callersite *callsite) nodeid {
+	if a.log != nil {
+		fmt.Fprintf(a.log, "\t---- makeFunctionObject %s\n", fn)
+	}
+
+	// obj is the function object (identity, params, results).
+	obj := a.nextNode()
+	cgn := a.makeCGNode(fn, obj, callersite)
+	sig := fn.Signature
+	a.addOneNode(sig, "func.cgnode", nil) // (scalar with Signature type)
+	if recv := sig.Recv(); recv != nil {
+		a.addNodes(recv.Type(), "func.recv")
+	}
+	a.addNodes(sig.Params(), "func.params")
+	a.addNodes(sig.Results(), "func.results")
+	a.endObject(obj, cgn, fn).flags |= otFunction
+
+	if a.log != nil {
+		fmt.Fprintf(a.log, "\t----\n")
+	}
+
+	// Queue it up for constraint processing.
+	a.genq = append(a.genq, cgn)
+
+	return obj
+}
+
+// makeTagged creates a tagged object of type typ.
+func (a *analysis) makeTagged(typ types.Type, cgn *cgnode, data interface{}) nodeid {
+	obj := a.addOneNode(typ, "tagged.T", nil) // NB: type may be non-scalar!
+	a.addNodes(typ, "tagged.v")
+	a.endObject(obj, cgn, data).flags |= otTagged
+	return obj
+}
+
+// makeRtype returns the canonical tagged object of type *rtype whose
+// payload points to the sole rtype object for T.
+//
+// TODO(adonovan): move to reflect.go; it's part of the solver really.
+//
+func (a *analysis) makeRtype(T types.Type) nodeid {
+	if v := a.rtypes.At(T); v != nil {
+		return v.(nodeid)
+	}
+
+	// Create the object for the reflect.rtype itself, which is
+	// ordinarily a large struct but here a single node will do.
+	obj := a.nextNode()
+	a.addOneNode(T, "reflect.rtype", nil)
+	a.endObject(obj, nil, T)
+
+	id := a.makeTagged(a.reflectRtypePtr, nil, T)
+	a.nodes[id+1].typ = T // trick (each *rtype tagged object is a singleton)
+	a.addressOf(a.reflectRtypePtr, id+1, obj)
+
+	a.rtypes.Set(T, id)
+	return id
+}
+
+// rtypeValue returns the type of the *reflect.rtype-tagged object obj.
+func (a *analysis) rtypeTaggedValue(obj nodeid) types.Type {
+	tDyn, t, _ := a.taggedValue(obj)
+	if tDyn != a.reflectRtypePtr {
+		panic(fmt.Sprintf("not a *reflect.rtype-tagged object: obj=n%d tag=%v payload=n%d", obj, tDyn, t))
+	}
+	return a.nodes[t].typ
+}
+
+// valueNode returns the id of the value node for v, creating it (and
+// the association) as needed.  It may return zero for uninteresting
+// values containing no pointers.
+//
+func (a *analysis) valueNode(v ssa.Value) nodeid {
+	// Value nodes for locals are created en masse by genFunc.
+	if id, ok := a.localval[v]; ok {
+		return id
+	}
+
+	// Value nodes for globals are created on demand.
+	id, ok := a.globalval[v]
+	if !ok {
+		var comment string
+		if a.log != nil {
+			comment = v.String()
+		}
+		id = a.addNodes(v.Type(), comment)
+		if obj := a.objectNode(nil, v); obj != 0 {
+			a.addressOf(v.Type(), id, obj)
+		}
+		a.setValueNode(v, id, nil)
+	}
+	return id
+}
+
+// valueOffsetNode ascertains the node for tuple/struct value v,
+// then returns the node for its subfield #index.
+//
+func (a *analysis) valueOffsetNode(v ssa.Value, index int) nodeid {
+	id := a.valueNode(v)
+	if id == 0 {
+		panic(fmt.Sprintf("cannot offset within n0: %s = %s", v.Name(), v))
+	}
+	return id + nodeid(a.offsetOf(v.Type(), index))
+}
+
+// isTaggedObject reports whether object obj is a tagged object.
+func (a *analysis) isTaggedObject(obj nodeid) bool {
+	return a.nodes[obj].obj.flags&otTagged != 0
+}
+
+// taggedValue returns the dynamic type tag, the (first node of the)
+// payload, and the indirect flag of the tagged object starting at id.
+// Panic ensues if !isTaggedObject(id).
+//
+func (a *analysis) taggedValue(obj nodeid) (tDyn types.Type, v nodeid, indirect bool) {
+	n := a.nodes[obj]
+	flags := n.obj.flags
+	if flags&otTagged == 0 {
+		panic(fmt.Sprintf("not a tagged object: n%d", obj))
+	}
+	return n.typ, obj + 1, flags&otIndirect != 0
+}
+
+// funcParams returns the first node of the params (P) block of the
+// function whose object node (obj.flags&otFunction) is id.
+//
+func (a *analysis) funcParams(id nodeid) nodeid {
+	n := a.nodes[id]
+	if n.obj == nil || n.obj.flags&otFunction == 0 {
+		panic(fmt.Sprintf("funcParams(n%d): not a function object block", id))
+	}
+	return id + 1
+}
+
+// funcResults returns the first node of the results (R) block of the
+// function whose object node (obj.flags&otFunction) is id.
+//
+func (a *analysis) funcResults(id nodeid) nodeid {
+	n := a.nodes[id]
+	if n.obj == nil || n.obj.flags&otFunction == 0 {
+		panic(fmt.Sprintf("funcResults(n%d): not a function object block", id))
+	}
+	sig := n.typ.(*types.Signature)
+	id += 1 + nodeid(a.sizeof(sig.Params()))
+	if sig.Recv() != nil {
+		id += nodeid(a.sizeof(sig.Recv().Type()))
+	}
+	return id
+}
+
+// ---------- Constraint creation ----------
+
+// copy creates a constraint of the form dst = src.
+// sizeof is the width (in logical fields) of the copied type.
+//
+func (a *analysis) copy(dst, src nodeid, sizeof uint32) {
+	if src == dst || sizeof == 0 {
+		return // trivial
+	}
+	if src == 0 || dst == 0 {
+		panic(fmt.Sprintf("ill-typed copy dst=n%d src=n%d", dst, src))
+	}
+	for i := uint32(0); i < sizeof; i++ {
+		a.addConstraint(&copyConstraint{dst, src})
+		src++
+		dst++
+	}
+}
+
+// addressOf creates a constraint of the form id = &obj.
+// T is the type of the address.
+func (a *analysis) addressOf(T types.Type, id, obj nodeid) {
+	if id == 0 {
+		panic("addressOf: zero id")
+	}
+	if obj == 0 {
+		panic("addressOf: zero obj")
+	}
+	if a.shouldTrack(T) {
+		a.addConstraint(&addrConstraint{id, obj})
+	}
+}
+
+// load creates a load constraint of the form dst = src[offset].
+// offset is the pointer offset in logical fields.
+// sizeof is the width (in logical fields) of the loaded type.
+//
+func (a *analysis) load(dst, src nodeid, offset, sizeof uint32) {
+	if dst == 0 {
+		return // load of non-pointerlike value
+	}
+	if src == 0 && dst == 0 {
+		return // non-pointerlike operation
+	}
+	if src == 0 || dst == 0 {
+		panic(fmt.Sprintf("ill-typed load dst=n%d src=n%d", dst, src))
+	}
+	for i := uint32(0); i < sizeof; i++ {
+		a.addConstraint(&loadConstraint{offset, dst, src})
+		offset++
+		dst++
+	}
+}
+
+// store creates a store constraint of the form dst[offset] = src.
+// offset is the pointer offset in logical fields.
+// sizeof is the width (in logical fields) of the stored type.
+//
+func (a *analysis) store(dst, src nodeid, offset uint32, sizeof uint32) {
+	if src == 0 {
+		return // store of non-pointerlike value
+	}
+	if src == 0 && dst == 0 {
+		return // non-pointerlike operation
+	}
+	if src == 0 || dst == 0 {
+		panic(fmt.Sprintf("ill-typed store dst=n%d src=n%d", dst, src))
+	}
+	for i := uint32(0); i < sizeof; i++ {
+		a.addConstraint(&storeConstraint{offset, dst, src})
+		offset++
+		src++
+	}
+}
+
+// offsetAddr creates an offsetAddr constraint of the form dst = &src.#offset.
+// offset is the field offset in logical fields.
+// T is the type of the address.
+//
+func (a *analysis) offsetAddr(T types.Type, dst, src nodeid, offset uint32) {
+	if !a.shouldTrack(T) {
+		return
+	}
+	if offset == 0 {
+		// Simplify  dst = &src->f0
+		//       to  dst = src
+		// (NB: this optimisation is defeated by the identity
+		// field prepended to struct and array objects.)
+		a.copy(dst, src, 1)
+	} else {
+		a.addConstraint(&offsetAddrConstraint{offset, dst, src})
+	}
+}
+
+// typeAssert creates a typeFilter or untag constraint of the form dst = src.(T):
+// typeFilter for an interface, untag for a concrete type.
+// The exact flag is specified as for untagConstraint.
+//
+func (a *analysis) typeAssert(T types.Type, dst, src nodeid, exact bool) {
+	if isInterface(T) {
+		a.addConstraint(&typeFilterConstraint{T, dst, src})
+	} else {
+		a.addConstraint(&untagConstraint{T, dst, src, exact})
+	}
+}
+
+// addConstraint adds c to the constraint set.
+func (a *analysis) addConstraint(c constraint) {
+	a.constraints = append(a.constraints, c)
+	if a.log != nil {
+		fmt.Fprintf(a.log, "\t%s\n", c)
+	}
+}
+
+// copyElems generates load/store constraints for *dst = *src,
+// where src and dst are slices or *arrays.
+//
+func (a *analysis) copyElems(cgn *cgnode, typ types.Type, dst, src ssa.Value) {
+	tmp := a.addNodes(typ, "copy")
+	sz := a.sizeof(typ)
+	a.genLoad(cgn, tmp, src, 1, sz)
+	a.genStore(cgn, dst, tmp, 1, sz)
+}
+
+// ---------- Constraint generation ----------
+
+// genConv generates constraints for the conversion operation conv.
+func (a *analysis) genConv(conv *ssa.Convert, cgn *cgnode) {
+	res := a.valueNode(conv)
+	if res == 0 {
+		return // result is non-pointerlike
+	}
+
+	tSrc := conv.X.Type()
+	tDst := conv.Type()
+
+	switch utSrc := tSrc.Underlying().(type) {
+	case *types.Slice:
+		// []byte/[]rune -> string?
+		return
+
+	case *types.Pointer:
+		// *T -> unsafe.Pointer?
+		if tDst.Underlying() == tUnsafePtr {
+			return // we don't model unsafe aliasing (unsound)
+		}
+
+	case *types.Basic:
+		switch tDst.Underlying().(type) {
+		case *types.Pointer:
+			// Treat unsafe.Pointer->*T conversions like
+			// new(T) and create an unaliased object.
+			if utSrc == tUnsafePtr {
+				obj := a.addNodes(mustDeref(tDst), "unsafe.Pointer conversion")
+				a.endObject(obj, cgn, conv)
+				a.addressOf(tDst, res, obj)
+				return
+			}
+
+		case *types.Slice:
+			// string -> []byte/[]rune (or named aliases)?
+			if utSrc.Info()&types.IsString != 0 {
+				obj := a.addNodes(sliceToArray(tDst), "convert")
+				a.endObject(obj, cgn, conv)
+				a.addressOf(tDst, res, obj)
+				return
+			}
+
+		case *types.Basic:
+			// All basic-to-basic type conversions are no-ops.
+			// This includes uintptr<->unsafe.Pointer conversions,
+			// which we (unsoundly) ignore.
+			return
+		}
+	}
+
+	panic(fmt.Sprintf("illegal *ssa.Convert %s -> %s: %s", tSrc, tDst, conv.Parent()))
+}
+
+// genAppend generates constraints for a call to append.
+func (a *analysis) genAppend(instr *ssa.Call, cgn *cgnode) {
+	// Consider z = append(x, y).   y is optional.
+	// This may allocate a new [1]T array; call its object w.
+	// We get the following constraints:
+	// 	z = x
+	// 	z = &w
+	//     *z = *y
+
+	x := instr.Call.Args[0]
+
+	z := instr
+	a.copy(a.valueNode(z), a.valueNode(x), 1) // z = x
+
+	if len(instr.Call.Args) == 1 {
+		return // no allocation for z = append(x) or _ = append(x).
+	}
+
+	// TODO(adonovan): test append([]byte, ...string) []byte.
+
+	y := instr.Call.Args[1]
+	tArray := sliceToArray(instr.Call.Args[0].Type())
+
+	var w nodeid
+	w = a.nextNode()
+	a.addNodes(tArray, "append")
+	a.endObject(w, cgn, instr)
+
+	a.copyElems(cgn, tArray.Elem(), z, y)        // *z = *y
+	a.addressOf(instr.Type(), a.valueNode(z), w) //  z = &w
+}
+
+// genBuiltinCall generates contraints for a call to a built-in.
+func (a *analysis) genBuiltinCall(instr ssa.CallInstruction, cgn *cgnode) {
+	call := instr.Common()
+	switch call.Value.(*ssa.Builtin).Name() {
+	case "append":
+		// Safe cast: append cannot appear in a go or defer statement.
+		a.genAppend(instr.(*ssa.Call), cgn)
+
+	case "copy":
+		tElem := call.Args[0].Type().Underlying().(*types.Slice).Elem()
+		a.copyElems(cgn, tElem, call.Args[0], call.Args[1])
+
+	case "panic":
+		a.copy(a.panicNode, a.valueNode(call.Args[0]), 1)
+
+	case "recover":
+		if v := instr.Value(); v != nil {
+			a.copy(a.valueNode(v), a.panicNode, 1)
+		}
+
+	case "print":
+		// In the tests, the probe might be the sole reference
+		// to its arg, so make sure we create nodes for it.
+		if len(call.Args) > 0 {
+			a.valueNode(call.Args[0])
+		}
+
+	case "ssa:wrapnilchk":
+		a.copy(a.valueNode(instr.Value()), a.valueNode(call.Args[0]), 1)
+
+	default:
+		// No-ops: close len cap real imag complex print println delete.
+	}
+}
+
+// shouldUseContext defines the context-sensitivity policy.  It
+// returns true if we should analyse all static calls to fn anew.
+//
+// Obviously this interface rather limits how much freedom we have to
+// choose a policy.  The current policy, rather arbitrarily, is true
+// for intrinsics and accessor methods (actually: short, single-block,
+// call-free functions).  This is just a starting point.
+//
+func (a *analysis) shouldUseContext(fn *ssa.Function) bool {
+	if a.findIntrinsic(fn) != nil {
+		return true // treat intrinsics context-sensitively
+	}
+	if len(fn.Blocks) != 1 {
+		return false // too expensive
+	}
+	blk := fn.Blocks[0]
+	if len(blk.Instrs) > 10 {
+		return false // too expensive
+	}
+	if fn.Synthetic != "" && (fn.Pkg == nil || fn != fn.Pkg.Func("init")) {
+		return true // treat synthetic wrappers context-sensitively
+	}
+	for _, instr := range blk.Instrs {
+		switch instr := instr.(type) {
+		case ssa.CallInstruction:
+			// Disallow function calls (except to built-ins)
+			// because of the danger of unbounded recursion.
+			if _, ok := instr.Common().Value.(*ssa.Builtin); !ok {
+				return false
+			}
+		}
+	}
+	return true
+}
+
+// genStaticCall generates constraints for a statically dispatched function call.
+func (a *analysis) genStaticCall(caller *cgnode, site *callsite, call *ssa.CallCommon, result nodeid) {
+	fn := call.StaticCallee()
+
+	// Special cases for inlined intrinsics.
+	switch fn {
+	case a.runtimeSetFinalizer:
+		// Inline SetFinalizer so the call appears direct.
+		site.targets = a.addOneNode(tInvalid, "SetFinalizer.targets", nil)
+		a.addConstraint(&runtimeSetFinalizerConstraint{
+			targets: site.targets,
+			x:       a.valueNode(call.Args[0]),
+			f:       a.valueNode(call.Args[1]),
+		})
+		return
+
+	case a.reflectValueCall:
+		// Inline (reflect.Value).Call so the call appears direct.
+		dotdotdot := false
+		ret := reflectCallImpl(a, caller, site, a.valueNode(call.Args[0]), a.valueNode(call.Args[1]), dotdotdot)
+		if result != 0 {
+			a.addressOf(fn.Signature.Results().At(0).Type(), result, ret)
+		}
+		return
+	}
+
+	// Ascertain the context (contour/cgnode) for a particular call.
+	var obj nodeid
+	if a.shouldUseContext(fn) {
+		obj = a.makeFunctionObject(fn, site) // new contour
+	} else {
+		obj = a.objectNode(nil, fn) // shared contour
+	}
+	a.callEdge(caller, site, obj)
+
+	sig := call.Signature()
+
+	// Copy receiver, if any.
+	params := a.funcParams(obj)
+	args := call.Args
+	if sig.Recv() != nil {
+		sz := a.sizeof(sig.Recv().Type())
+		a.copy(params, a.valueNode(args[0]), sz)
+		params += nodeid(sz)
+		args = args[1:]
+	}
+
+	// Copy actual parameters into formal params block.
+	// Must loop, since the actuals aren't contiguous.
+	for i, arg := range args {
+		sz := a.sizeof(sig.Params().At(i).Type())
+		a.copy(params, a.valueNode(arg), sz)
+		params += nodeid(sz)
+	}
+
+	// Copy formal results block to actual result.
+	if result != 0 {
+		a.copy(result, a.funcResults(obj), a.sizeof(sig.Results()))
+	}
+}
+
+// genDynamicCall generates constraints for a dynamic function call.
+func (a *analysis) genDynamicCall(caller *cgnode, site *callsite, call *ssa.CallCommon, result nodeid) {
+	// pts(targets) will be the set of possible call targets.
+	site.targets = a.valueNode(call.Value)
+
+	// We add dynamic closure rules that store the arguments into
+	// the P-block and load the results from the R-block of each
+	// function discovered in pts(targets).
+
+	sig := call.Signature()
+	var offset uint32 = 1 // P/R block starts at offset 1
+	for i, arg := range call.Args {
+		sz := a.sizeof(sig.Params().At(i).Type())
+		a.genStore(caller, call.Value, a.valueNode(arg), offset, sz)
+		offset += sz
+	}
+	if result != 0 {
+		a.genLoad(caller, result, call.Value, offset, a.sizeof(sig.Results()))
+	}
+}
+
+// genInvoke generates constraints for a dynamic method invocation.
+func (a *analysis) genInvoke(caller *cgnode, site *callsite, call *ssa.CallCommon, result nodeid) {
+	if call.Value.Type() == a.reflectType {
+		a.genInvokeReflectType(caller, site, call, result)
+		return
+	}
+
+	sig := call.Signature()
+
+	// Allocate a contiguous targets/params/results block for this call.
+	block := a.nextNode()
+	// pts(targets) will be the set of possible call targets
+	site.targets = a.addOneNode(sig, "invoke.targets", nil)
+	p := a.addNodes(sig.Params(), "invoke.params")
+	r := a.addNodes(sig.Results(), "invoke.results")
+
+	// Copy the actual parameters into the call's params block.
+	for i, n := 0, sig.Params().Len(); i < n; i++ {
+		sz := a.sizeof(sig.Params().At(i).Type())
+		a.copy(p, a.valueNode(call.Args[i]), sz)
+		p += nodeid(sz)
+	}
+	// Copy the call's results block to the actual results.
+	if result != 0 {
+		a.copy(result, r, a.sizeof(sig.Results()))
+	}
+
+	// We add a dynamic invoke constraint that will connect the
+	// caller's and the callee's P/R blocks for each discovered
+	// call target.
+	a.addConstraint(&invokeConstraint{call.Method, a.valueNode(call.Value), block})
+}
+
+// genInvokeReflectType is a specialization of genInvoke where the
+// receiver type is a reflect.Type, under the assumption that there
+// can be at most one implementation of this interface, *reflect.rtype.
+//
+// (Though this may appear to be an instance of a pattern---method
+// calls on interfaces known to have exactly one implementation---in
+// practice it occurs rarely, so we special case for reflect.Type.)
+//
+// In effect we treat this:
+//    var rt reflect.Type = ...
+//    rt.F()
+// as this:
+//    rt.(*reflect.rtype).F()
+//
+func (a *analysis) genInvokeReflectType(caller *cgnode, site *callsite, call *ssa.CallCommon, result nodeid) {
+	// Unpack receiver into rtype
+	rtype := a.addOneNode(a.reflectRtypePtr, "rtype.recv", nil)
+	recv := a.valueNode(call.Value)
+	a.typeAssert(a.reflectRtypePtr, rtype, recv, true)
+
+	// Look up the concrete method.
+	fn := a.prog.LookupMethod(a.reflectRtypePtr, call.Method.Pkg(), call.Method.Name())
+
+	obj := a.makeFunctionObject(fn, site) // new contour for this call
+	a.callEdge(caller, site, obj)
+
+	// From now on, it's essentially a static call, but little is
+	// gained by factoring together the code for both cases.
+
+	sig := fn.Signature // concrete method
+	targets := a.addOneNode(sig, "call.targets", nil)
+	a.addressOf(sig, targets, obj) // (a singleton)
+
+	// Copy receiver.
+	params := a.funcParams(obj)
+	a.copy(params, rtype, 1)
+	params++
+
+	// Copy actual parameters into formal P-block.
+	// Must loop, since the actuals aren't contiguous.
+	for i, arg := range call.Args {
+		sz := a.sizeof(sig.Params().At(i).Type())
+		a.copy(params, a.valueNode(arg), sz)
+		params += nodeid(sz)
+	}
+
+	// Copy formal R-block to actual R-block.
+	if result != 0 {
+		a.copy(result, a.funcResults(obj), a.sizeof(sig.Results()))
+	}
+}
+
+// genCall generates constraints for call instruction instr.
+func (a *analysis) genCall(caller *cgnode, instr ssa.CallInstruction) {
+	call := instr.Common()
+
+	// Intrinsic implementations of built-in functions.
+	if _, ok := call.Value.(*ssa.Builtin); ok {
+		a.genBuiltinCall(instr, caller)
+		return
+	}
+
+	var result nodeid
+	if v := instr.Value(); v != nil {
+		result = a.valueNode(v)
+	}
+
+	site := &callsite{instr: instr}
+	if call.StaticCallee() != nil {
+		a.genStaticCall(caller, site, call, result)
+	} else if call.IsInvoke() {
+		a.genInvoke(caller, site, call, result)
+	} else {
+		a.genDynamicCall(caller, site, call, result)
+	}
+
+	caller.sites = append(caller.sites, site)
+
+	if a.log != nil {
+		// TODO(adonovan): debug: improve log message.
+		fmt.Fprintf(a.log, "\t%s to targets %s from %s\n", site, site.targets, caller)
+	}
+}
+
+// objectNode returns the object to which v points, if known.
+// In other words, if the points-to set of v is a singleton, it
+// returns the sole label, zero otherwise.
+//
+// We exploit this information to make the generated constraints less
+// dynamic.  For example, a complex load constraint can be replaced by
+// a simple copy constraint when the sole destination is known a priori.
+//
+// Some SSA instructions always have singletons points-to sets:
+// 	Alloc, Function, Global, MakeChan, MakeClosure,  MakeInterface,  MakeMap,  MakeSlice.
+// Others may be singletons depending on their operands:
+// 	FreeVar, Const, Convert, FieldAddr, IndexAddr, Slice.
+//
+// Idempotent.  Objects are created as needed, possibly via recursion
+// down the SSA value graph, e.g IndexAddr(FieldAddr(Alloc))).
+//
+func (a *analysis) objectNode(cgn *cgnode, v ssa.Value) nodeid {
+	switch v.(type) {
+	case *ssa.Global, *ssa.Function, *ssa.Const, *ssa.FreeVar:
+		// Global object.
+		obj, ok := a.globalobj[v]
+		if !ok {
+			switch v := v.(type) {
+			case *ssa.Global:
+				obj = a.nextNode()
+				a.addNodes(mustDeref(v.Type()), "global")
+				a.endObject(obj, nil, v)
+
+			case *ssa.Function:
+				obj = a.makeFunctionObject(v, nil)
+
+			case *ssa.Const:
+				// not addressable
+
+			case *ssa.FreeVar:
+				// not addressable
+			}
+
+			if a.log != nil {
+				fmt.Fprintf(a.log, "\tglobalobj[%s] = n%d\n", v, obj)
+			}
+			a.globalobj[v] = obj
+		}
+		return obj
+	}
+
+	// Local object.
+	obj, ok := a.localobj[v]
+	if !ok {
+		switch v := v.(type) {
+		case *ssa.Alloc:
+			obj = a.nextNode()
+			a.addNodes(mustDeref(v.Type()), "alloc")
+			a.endObject(obj, cgn, v)
+
+		case *ssa.MakeSlice:
+			obj = a.nextNode()
+			a.addNodes(sliceToArray(v.Type()), "makeslice")
+			a.endObject(obj, cgn, v)
+
+		case *ssa.MakeChan:
+			obj = a.nextNode()
+			a.addNodes(v.Type().Underlying().(*types.Chan).Elem(), "makechan")
+			a.endObject(obj, cgn, v)
+
+		case *ssa.MakeMap:
+			obj = a.nextNode()
+			tmap := v.Type().Underlying().(*types.Map)
+			a.addNodes(tmap.Key(), "makemap.key")
+			elem := a.addNodes(tmap.Elem(), "makemap.value")
+
+			// To update the value field, MapUpdate
+			// generates store-with-offset constraints which
+			// the presolver can't model, so we must mark
+			// those nodes indirect.
+			for id, end := elem, elem+nodeid(a.sizeof(tmap.Elem())); id < end; id++ {
+				a.mapValues = append(a.mapValues, id)
+			}
+			a.endObject(obj, cgn, v)
+
+		case *ssa.MakeInterface:
+			tConc := v.X.Type()
+			obj = a.makeTagged(tConc, cgn, v)
+
+			// Copy the value into it, if nontrivial.
+			if x := a.valueNode(v.X); x != 0 {
+				a.copy(obj+1, x, a.sizeof(tConc))
+			}
+
+		case *ssa.FieldAddr:
+			if xobj := a.objectNode(cgn, v.X); xobj != 0 {
+				obj = xobj + nodeid(a.offsetOf(mustDeref(v.X.Type()), v.Field))
+			}
+
+		case *ssa.IndexAddr:
+			if xobj := a.objectNode(cgn, v.X); xobj != 0 {
+				obj = xobj + 1
+			}
+
+		case *ssa.Slice:
+			obj = a.objectNode(cgn, v.X)
+
+		case *ssa.Convert:
+			// TODO(adonovan): opt: handle these cases too:
+			// - unsafe.Pointer->*T conversion acts like Alloc
+			// - string->[]byte/[]rune conversion acts like MakeSlice
+		}
+
+		if a.log != nil {
+			fmt.Fprintf(a.log, "\tlocalobj[%s] = n%d\n", v.Name(), obj)
+		}
+		a.localobj[v] = obj
+	}
+	return obj
+}
+
+// genLoad generates constraints for result = *(ptr + val).
+func (a *analysis) genLoad(cgn *cgnode, result nodeid, ptr ssa.Value, offset, sizeof uint32) {
+	if obj := a.objectNode(cgn, ptr); obj != 0 {
+		// Pre-apply loadConstraint.solve().
+		a.copy(result, obj+nodeid(offset), sizeof)
+	} else {
+		a.load(result, a.valueNode(ptr), offset, sizeof)
+	}
+}
+
+// genOffsetAddr generates constraints for a 'v=ptr.field' (FieldAddr)
+// or 'v=ptr[*]' (IndexAddr) instruction v.
+func (a *analysis) genOffsetAddr(cgn *cgnode, v ssa.Value, ptr nodeid, offset uint32) {
+	dst := a.valueNode(v)
+	if obj := a.objectNode(cgn, v); obj != 0 {
+		// Pre-apply offsetAddrConstraint.solve().
+		a.addressOf(v.Type(), dst, obj)
+	} else {
+		a.offsetAddr(v.Type(), dst, ptr, offset)
+	}
+}
+
+// genStore generates constraints for *(ptr + offset) = val.
+func (a *analysis) genStore(cgn *cgnode, ptr ssa.Value, val nodeid, offset, sizeof uint32) {
+	if obj := a.objectNode(cgn, ptr); obj != 0 {
+		// Pre-apply storeConstraint.solve().
+		a.copy(obj+nodeid(offset), val, sizeof)
+	} else {
+		a.store(a.valueNode(ptr), val, offset, sizeof)
+	}
+}
+
+// genInstr generates constraints for instruction instr in context cgn.
+func (a *analysis) genInstr(cgn *cgnode, instr ssa.Instruction) {
+	if a.log != nil {
+		var prefix string
+		if val, ok := instr.(ssa.Value); ok {
+			prefix = val.Name() + " = "
+		}
+		fmt.Fprintf(a.log, "; %s%s\n", prefix, instr)
+	}
+
+	switch instr := instr.(type) {
+	case *ssa.DebugRef:
+		// no-op.
+
+	case *ssa.UnOp:
+		switch instr.Op {
+		case token.ARROW: // <-x
+			// We can ignore instr.CommaOk because the node we're
+			// altering is always at zero offset relative to instr
+			tElem := instr.X.Type().Underlying().(*types.Chan).Elem()
+			a.genLoad(cgn, a.valueNode(instr), instr.X, 0, a.sizeof(tElem))
+
+		case token.MUL: // *x
+			a.genLoad(cgn, a.valueNode(instr), instr.X, 0, a.sizeof(instr.Type()))
+
+		default:
+			// NOT, SUB, XOR: no-op.
+		}
+
+	case *ssa.BinOp:
+		// All no-ops.
+
+	case ssa.CallInstruction: // *ssa.Call, *ssa.Go, *ssa.Defer
+		a.genCall(cgn, instr)
+
+	case *ssa.ChangeType:
+		a.copy(a.valueNode(instr), a.valueNode(instr.X), 1)
+
+	case *ssa.Convert:
+		a.genConv(instr, cgn)
+
+	case *ssa.Extract:
+		a.copy(a.valueNode(instr),
+			a.valueOffsetNode(instr.Tuple, instr.Index),
+			a.sizeof(instr.Type()))
+
+	case *ssa.FieldAddr:
+		a.genOffsetAddr(cgn, instr, a.valueNode(instr.X),
+			a.offsetOf(mustDeref(instr.X.Type()), instr.Field))
+
+	case *ssa.IndexAddr:
+		a.genOffsetAddr(cgn, instr, a.valueNode(instr.X), 1)
+
+	case *ssa.Field:
+		a.copy(a.valueNode(instr),
+			a.valueOffsetNode(instr.X, instr.Field),
+			a.sizeof(instr.Type()))
+
+	case *ssa.Index:
+		a.copy(a.valueNode(instr), 1+a.valueNode(instr.X), a.sizeof(instr.Type()))
+
+	case *ssa.Select:
+		recv := a.valueOffsetNode(instr, 2) // instr : (index, recvOk, recv0, ... recv_n-1)
+		for _, st := range instr.States {
+			elemSize := a.sizeof(st.Chan.Type().Underlying().(*types.Chan).Elem())
+			switch st.Dir {
+			case types.RecvOnly:
+				a.genLoad(cgn, recv, st.Chan, 0, elemSize)
+				recv += nodeid(elemSize)
+
+			case types.SendOnly:
+				a.genStore(cgn, st.Chan, a.valueNode(st.Send), 0, elemSize)
+			}
+		}
+
+	case *ssa.Return:
+		results := a.funcResults(cgn.obj)
+		for _, r := range instr.Results {
+			sz := a.sizeof(r.Type())
+			a.copy(results, a.valueNode(r), sz)
+			results += nodeid(sz)
+		}
+
+	case *ssa.Send:
+		a.genStore(cgn, instr.Chan, a.valueNode(instr.X), 0, a.sizeof(instr.X.Type()))
+
+	case *ssa.Store:
+		a.genStore(cgn, instr.Addr, a.valueNode(instr.Val), 0, a.sizeof(instr.Val.Type()))
+
+	case *ssa.Alloc, *ssa.MakeSlice, *ssa.MakeChan, *ssa.MakeMap, *ssa.MakeInterface:
+		v := instr.(ssa.Value)
+		a.addressOf(v.Type(), a.valueNode(v), a.objectNode(cgn, v))
+
+	case *ssa.ChangeInterface:
+		a.copy(a.valueNode(instr), a.valueNode(instr.X), 1)
+
+	case *ssa.TypeAssert:
+		a.typeAssert(instr.AssertedType, a.valueNode(instr), a.valueNode(instr.X), true)
+
+	case *ssa.Slice:
+		a.copy(a.valueNode(instr), a.valueNode(instr.X), 1)
+
+	case *ssa.If, *ssa.Jump:
+		// no-op.
+
+	case *ssa.Phi:
+		sz := a.sizeof(instr.Type())
+		for _, e := range instr.Edges {
+			a.copy(a.valueNode(instr), a.valueNode(e), sz)
+		}
+
+	case *ssa.MakeClosure:
+		fn := instr.Fn.(*ssa.Function)
+		a.copy(a.valueNode(instr), a.valueNode(fn), 1)
+		// Free variables are treated like global variables.
+		for i, b := range instr.Bindings {
+			a.copy(a.valueNode(fn.FreeVars[i]), a.valueNode(b), a.sizeof(b.Type()))
+		}
+
+	case *ssa.RunDefers:
+		// The analysis is flow insensitive, so we just "call"
+		// defers as we encounter them.
+
+	case *ssa.Range:
+		// Do nothing.  Next{Iter: *ssa.Range} handles this case.
+
+	case *ssa.Next:
+		if !instr.IsString { // map
+			// Assumes that Next is always directly applied to a Range result.
+			theMap := instr.Iter.(*ssa.Range).X
+			tMap := theMap.Type().Underlying().(*types.Map)
+
+			ksize := a.sizeof(tMap.Key())
+			vsize := a.sizeof(tMap.Elem())
+
+			// The k/v components of the Next tuple may each be invalid.
+			tTuple := instr.Type().(*types.Tuple)
+
+			// Load from the map's (k,v) into the tuple's (ok, k, v).
+			osrc := uint32(0) // offset within map object
+			odst := uint32(1) // offset within tuple (initially just after 'ok bool')
+			sz := uint32(0)   // amount to copy
+
+			// Is key valid?
+			if tTuple.At(1).Type() != tInvalid {
+				sz += ksize
+			} else {
+				odst += ksize
+				osrc += ksize
+			}
+
+			// Is value valid?
+			if tTuple.At(2).Type() != tInvalid {
+				sz += vsize
+			}
+
+			a.genLoad(cgn, a.valueNode(instr)+nodeid(odst), theMap, osrc, sz)
+		}
+
+	case *ssa.Lookup:
+		if tMap, ok := instr.X.Type().Underlying().(*types.Map); ok {
+			// CommaOk can be ignored: field 0 is a no-op.
+			ksize := a.sizeof(tMap.Key())
+			vsize := a.sizeof(tMap.Elem())
+			a.genLoad(cgn, a.valueNode(instr), instr.X, ksize, vsize)
+		}
+
+	case *ssa.MapUpdate:
+		tmap := instr.Map.Type().Underlying().(*types.Map)
+		ksize := a.sizeof(tmap.Key())
+		vsize := a.sizeof(tmap.Elem())
+		a.genStore(cgn, instr.Map, a.valueNode(instr.Key), 0, ksize)
+		a.genStore(cgn, instr.Map, a.valueNode(instr.Value), ksize, vsize)
+
+	case *ssa.Panic:
+		a.copy(a.panicNode, a.valueNode(instr.X), 1)
+
+	default:
+		panic(fmt.Sprintf("unimplemented: %T", instr))
+	}
+}
+
+func (a *analysis) makeCGNode(fn *ssa.Function, obj nodeid, callersite *callsite) *cgnode {
+	cgn := &cgnode{fn: fn, obj: obj, callersite: callersite}
+	a.cgnodes = append(a.cgnodes, cgn)
+	return cgn
+}
+
+// genRootCalls generates the synthetic root of the callgraph and the
+// initial calls from it to the analysis scope, such as main, a test
+// or a library.
+//
+func (a *analysis) genRootCalls() *cgnode {
+	r := a.prog.NewFunction("<root>", new(types.Signature), "root of callgraph")
+	root := a.makeCGNode(r, 0, nil)
+
+	// TODO(adonovan): make an ssa utility to construct an actual
+	// root function so we don't need to special-case site-less
+	// call edges.
+
+	// For each main package, call main.init(), main.main().
+	for _, mainPkg := range a.config.Mains {
+		main := mainPkg.Func("main")
+		if main == nil {
+			panic(fmt.Sprintf("%s has no main function", mainPkg))
+		}
+
+		targets := a.addOneNode(main.Signature, "root.targets", nil)
+		site := &callsite{targets: targets}
+		root.sites = append(root.sites, site)
+		for _, fn := range [2]*ssa.Function{mainPkg.Func("init"), main} {
+			if a.log != nil {
+				fmt.Fprintf(a.log, "\troot call to %s:\n", fn)
+			}
+			a.copy(targets, a.valueNode(fn), 1)
+		}
+	}
+
+	return root
+}
+
+// genFunc generates constraints for function fn.
+func (a *analysis) genFunc(cgn *cgnode) {
+	fn := cgn.fn
+
+	impl := a.findIntrinsic(fn)
+
+	if a.log != nil {
+		fmt.Fprintf(a.log, "\n\n==== Generating constraints for %s, %s\n", cgn, cgn.contour())
+
+		// Hack: don't display body if intrinsic.
+		if impl != nil {
+			fn2 := *cgn.fn // copy
+			fn2.Locals = nil
+			fn2.Blocks = nil
+			fn2.WriteTo(a.log)
+		} else {
+			cgn.fn.WriteTo(a.log)
+		}
+	}
+
+	if impl != nil {
+		impl(a, cgn)
+		return
+	}
+
+	if fn.Blocks == nil {
+		// External function with no intrinsic treatment.
+		// We'll warn about calls to such functions at the end.
+		return
+	}
+
+	if a.log != nil {
+		fmt.Fprintln(a.log, "; Creating nodes for local values")
+	}
+
+	a.localval = make(map[ssa.Value]nodeid)
+	a.localobj = make(map[ssa.Value]nodeid)
+
+	// The value nodes for the params are in the func object block.
+	params := a.funcParams(cgn.obj)
+	for _, p := range fn.Params {
+		a.setValueNode(p, params, cgn)
+		params += nodeid(a.sizeof(p.Type()))
+	}
+
+	// Free variables have global cardinality:
+	// the outer function sets them with MakeClosure;
+	// the inner function accesses them with FreeVar.
+	//
+	// TODO(adonovan): treat free vars context-sensitively.
+
+	// Create value nodes for all value instructions
+	// since SSA may contain forward references.
+	var space [10]*ssa.Value
+	for _, b := range fn.Blocks {
+		for _, instr := range b.Instrs {
+			switch instr := instr.(type) {
+			case *ssa.Range:
+				// do nothing: it has a funky type,
+				// and *ssa.Next does all the work.
+
+			case ssa.Value:
+				var comment string
+				if a.log != nil {
+					comment = instr.Name()
+				}
+				id := a.addNodes(instr.Type(), comment)
+				a.setValueNode(instr, id, cgn)
+			}
+
+			// Record all address-taken functions (for presolver).
+			rands := instr.Operands(space[:0])
+			if call, ok := instr.(ssa.CallInstruction); ok && !call.Common().IsInvoke() {
+				// Skip CallCommon.Value in "call" mode.
+				// TODO(adonovan): fix: relies on unspecified ordering.  Specify it.
+				rands = rands[1:]
+			}
+			for _, rand := range rands {
+				if atf, ok := (*rand).(*ssa.Function); ok {
+					a.atFuncs[atf] = true
+				}
+			}
+		}
+	}
+
+	// Generate constraints for instructions.
+	for _, b := range fn.Blocks {
+		for _, instr := range b.Instrs {
+			a.genInstr(cgn, instr)
+		}
+	}
+
+	a.localval = nil
+	a.localobj = nil
+}
+
+// genMethodsOf generates nodes and constraints for all methods of type T.
+func (a *analysis) genMethodsOf(T types.Type) {
+	itf := isInterface(T)
+
+	// TODO(adonovan): can we skip this entirely if itf is true?
+	// I think so, but the answer may depend on reflection.
+	mset := a.prog.MethodSets.MethodSet(T)
+	for i, n := 0, mset.Len(); i < n; i++ {
+		m := a.prog.MethodValue(mset.At(i))
+		a.valueNode(m)
+
+		if !itf {
+			// Methods of concrete types are address-taken functions.
+			a.atFuncs[m] = true
+		}
+	}
+}
+
+// generate generates offline constraints for the entire program.
+func (a *analysis) generate() {
+	start("Constraint generation")
+	if a.log != nil {
+		fmt.Fprintln(a.log, "==== Generating constraints")
+	}
+
+	// Create a dummy node since we use the nodeid 0 for
+	// non-pointerlike variables.
+	a.addNodes(tInvalid, "(zero)")
+
+	// Create the global node for panic values.
+	a.panicNode = a.addNodes(tEface, "panic")
+
+	// Create nodes and constraints for all methods of reflect.rtype.
+	// (Shared contours are used by dynamic calls to reflect.Type
+	// methods---typically just String().)
+	if rtype := a.reflectRtypePtr; rtype != nil {
+		a.genMethodsOf(rtype)
+	}
+
+	root := a.genRootCalls()
+
+	if a.config.BuildCallGraph {
+		a.result.CallGraph = callgraph.New(root.fn)
+	}
+
+	// Create nodes and constraints for all methods of all types
+	// that are dynamically accessible via reflection or interfaces.
+	for _, T := range a.prog.RuntimeTypes() {
+		a.genMethodsOf(T)
+	}
+
+	// Generate constraints for entire program.
+	for len(a.genq) > 0 {
+		cgn := a.genq[0]
+		a.genq = a.genq[1:]
+		a.genFunc(cgn)
+	}
+
+	// The runtime magically allocates os.Args; so should we.
+	if os := a.prog.ImportedPackage("os"); os != nil {
+		// In effect:  os.Args = new([1]string)[:]
+		T := types.NewSlice(types.Typ[types.String])
+		obj := a.addNodes(sliceToArray(T), "<command-line args>")
+		a.endObject(obj, nil, "<command-line args>")
+		a.addressOf(T, a.objectNode(nil, os.Var("Args")), obj)
+	}
+
+	// Discard generation state, to avoid confusion after node renumbering.
+	a.panicNode = 0
+	a.globalval = nil
+	a.localval = nil
+	a.localobj = nil
+
+	stop("Constraint generation")
+}
diff --git a/go/src/golang.org/x/tools/go/pointer/hvn.go b/go/src/golang.org/x/tools/go/pointer/hvn.go
index a3ef1f3..e550bc9 100644
--- a/go/src/golang.org/x/tools/go/pointer/hvn.go
+++ b/go/src/golang.org/x/tools/go/pointer/hvn.go
@@ -1,3 +1,9 @@
+// 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.
+
+// +build go1.5
+
 package pointer
 
 // This file implements Hash-Value Numbering (HVN), a pre-solver
@@ -159,11 +165,11 @@
 
 import (
 	"fmt"
+	"go/types"
 	"io"
 	"reflect"
 
 	"golang.org/x/tools/container/intsets"
-	"golang.org/x/tools/go/types"
 )
 
 // A peLabel is a pointer-equivalence label: two nodes with the same
diff --git a/go/src/golang.org/x/tools/go/pointer/hvn14.go b/go/src/golang.org/x/tools/go/pointer/hvn14.go
new file mode 100644
index 0000000..bc38745
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/pointer/hvn14.go
@@ -0,0 +1,975 @@
+// 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.
+
+// +build !go1.5
+
+package pointer
+
+// This file implements Hash-Value Numbering (HVN), a pre-solver
+// constraint optimization described in Hardekopf & Lin, SAS'07 (see
+// doc.go) that analyses the graph topology to determine which sets of
+// variables are "pointer equivalent" (PE), i.e. must have identical
+// points-to sets in the solution.
+//
+// A separate ("offline") graph is constructed.  Its nodes are those of
+// the main-graph, plus an additional node *X for each pointer node X.
+// With this graph we can reason about the unknown points-to set of
+// dereferenced pointers.  (We do not generalize this to represent
+// unknown fields x->f, perhaps because such fields would be numerous,
+// though it might be worth an experiment.)
+//
+// Nodes whose points-to relations are not entirely captured by the
+// graph are marked as "indirect": the *X nodes, the parameters of
+// address-taken functions (which includes all functions in method
+// sets), or nodes updated by the solver rules for reflection, etc.
+//
+// All addr (y=&x) nodes are initially assigned a pointer-equivalence
+// (PE) label equal to x's nodeid in the main graph.  (These are the
+// only PE labels that are less than len(a.nodes).)
+//
+// All offsetAddr (y=&x.f) constraints are initially assigned a PE
+// label; such labels are memoized, keyed by (x, f), so that equivalent
+// nodes y as assigned the same label.
+//
+// Then we process each strongly connected component (SCC) of the graph
+// in topological order, assigning it a PE label based on the set P of
+// PE labels that flow to it from its immediate dependencies.
+//
+// If any node in P is "indirect", the entire SCC is assigned a fresh PE
+// label.  Otherwise:
+//
+// |P|=0  if P is empty, all nodes in the SCC are non-pointers (e.g.
+//        uninitialized variables, or formal params of dead functions)
+//        and the SCC is assigned the PE label of zero.
+//
+// |P|=1  if P is a singleton, the SCC is assigned the same label as the
+//        sole element of P.
+//
+// |P|>1  if P contains multiple labels, a unique label representing P is
+//        invented and recorded in an hash table, so that other
+//        equivalent SCCs may also be assigned this label, akin to
+//        conventional hash-value numbering in a compiler.
+//
+// Finally, a renumbering is computed such that each node is replaced by
+// the lowest-numbered node with the same PE label.  All constraints are
+// renumbered, and any resulting duplicates are eliminated.
+//
+// The only nodes that are not renumbered are the objects x in addr
+// (y=&x) constraints, since the ids of these nodes (and fields derived
+// from them via offsetAddr rules) are the elements of all points-to
+// sets, so they must remain as they are if we want the same solution.
+//
+// The solverStates (node.solve) for nodes in the same equivalence class
+// are linked together so that all nodes in the class have the same
+// solution.  This avoids the need to renumber nodeids buried in
+// Queries, cgnodes, etc (like (*analysis).renumber() does) since only
+// the solution is needed.
+//
+// The result of HVN is that the number of distinct nodes and
+// constraints is reduced, but the solution is identical (almost---see
+// CROSS-CHECK below).  In particular, both linear and cyclic chains of
+// copies are each replaced by a single node.
+//
+// Nodes and constraints created "online" (e.g. while solving reflection
+// constraints) are not subject to this optimization.
+//
+// PERFORMANCE
+//
+// In two benchmarks (oracle and godoc), HVN eliminates about two thirds
+// of nodes, the majority accounted for by non-pointers: nodes of
+// non-pointer type, pointers that remain nil, formal parameters of dead
+// functions, nodes of untracked types, etc.  It also reduces the number
+// of constraints, also by about two thirds, and the solving time by
+// 30--42%, although we must pay about 15% for the running time of HVN
+// itself.  The benefit is greater for larger applications.
+//
+// There are many possible optimizations to improve the performance:
+// * Use fewer than 1:1 onodes to main graph nodes: many of the onodes
+//   we create are not needed.
+// * HU (HVN with Union---see paper): coalesce "union" peLabels when
+//   their expanded-out sets are equal.
+// * HR (HVN with deReference---see paper): this will require that we
+//   apply HVN until fixed point, which may need more bookkeeping of the
+//   correspondance of main nodes to onodes.
+// * Location Equivalence (see paper): have points-to sets contain not
+//   locations but location-equivalence class labels, each representing
+//   a set of locations.
+// * HVN with field-sensitive ref: model each of the fields of a
+//   pointer-to-struct.
+//
+// CROSS-CHECK
+//
+// To verify the soundness of the optimization, when the
+// debugHVNCrossCheck option is enabled, we run the solver twice, once
+// before and once after running HVN, dumping the solution to disk, and
+// then we compare the results.  If they are not identical, the analysis
+// panics.
+//
+// The solution dumped to disk includes only the N*N submatrix of the
+// complete solution where N is the number of nodes after generation.
+// In other words, we ignore pointer variables and objects created by
+// the solver itself, since their numbering depends on the solver order,
+// which is affected by the optimization.  In any case, that's the only
+// part the client cares about.
+//
+// The cross-check is too strict and may fail spuriously.  Although the
+// H&L paper describing HVN states that the solutions obtained should be
+// identical, this is not the case in practice because HVN can collapse
+// cycles involving *p even when pts(p)={}.  Consider this example
+// distilled from testdata/hello.go:
+//
+//	var x T
+//	func f(p **T) {
+//		t0 = *p
+//		...
+//		t1 = φ(t0, &x)
+//		*p = t1
+//	}
+//
+// If f is dead code, we get:
+// 	unoptimized:  pts(p)={} pts(t0)={} pts(t1)={&x}
+// 	optimized:    pts(p)={} pts(t0)=pts(t1)=pts(*p)={&x}
+//
+// It's hard to argue that this is a bug: the result is sound and the
+// loss of precision is inconsequential---f is dead code, after all.
+// But unfortunately it limits the usefulness of the cross-check since
+// failures must be carefully analyzed.  Ben Hardekopf suggests (in
+// personal correspondence) some approaches to mitigating it:
+//
+// 	If there is a node with an HVN points-to set that is a superset
+// 	of the NORM points-to set, then either it's a bug or it's a
+// 	result of this issue. If it's a result of this issue, then in
+// 	the offline constraint graph there should be a REF node inside
+// 	some cycle that reaches this node, and in the NORM solution the
+// 	pointer being dereferenced by that REF node should be the empty
+// 	set. If that isn't true then this is a bug. If it is true, then
+// 	you can further check that in the NORM solution the "extra"
+// 	points-to info in the HVN solution does in fact come from that
+// 	purported cycle (if it doesn't, then this is still a bug). If
+// 	you're doing the further check then you'll need to do it for
+// 	each "extra" points-to element in the HVN points-to set.
+//
+// 	There are probably ways to optimize these checks by taking
+// 	advantage of graph properties. For example, extraneous points-to
+// 	info will flow through the graph and end up in many
+// 	nodes. Rather than checking every node with extra info, you
+// 	could probably work out the "origin point" of the extra info and
+// 	just check there. Note that the check in the first bullet is
+// 	looking for soundness bugs, while the check in the second bullet
+// 	is looking for precision bugs; depending on your needs, you may
+// 	care more about one than the other.
+//
+// which we should evaluate.  The cross-check is nonetheless invaluable
+// for all but one of the programs in the pointer_test suite.
+
+import (
+	"fmt"
+	"io"
+	"reflect"
+
+	"golang.org/x/tools/container/intsets"
+	"golang.org/x/tools/go/types"
+)
+
+// A peLabel is a pointer-equivalence label: two nodes with the same
+// peLabel have identical points-to solutions.
+//
+// The numbers are allocated consecutively like so:
+// 	0	not a pointer
+//	1..N-1	addrConstraints (equals the constraint's .src field, hence sparse)
+//	...	offsetAddr constraints
+//	...	SCCs (with indirect nodes or multiple inputs)
+//
+// Each PE label denotes a set of pointers containing a single addr, a
+// single offsetAddr, or some set of other PE labels.
+//
+type peLabel int
+
+type hvn struct {
+	a        *analysis
+	N        int                // len(a.nodes) immediately after constraint generation
+	log      io.Writer          // (optional) log of HVN lemmas
+	onodes   []*onode           // nodes of the offline graph
+	label    peLabel            // the next available PE label
+	hvnLabel map[string]peLabel // hash-value numbering (PE label) for each set of onodeids
+	stack    []onodeid          // DFS stack
+	index    int32              // next onode.index, from Tarjan's SCC algorithm
+
+	// For each distinct offsetAddrConstraint (src, offset) pair,
+	// offsetAddrLabels records a unique PE label >= N.
+	offsetAddrLabels map[offsetAddr]peLabel
+}
+
+// The index of an node in the offline graph.
+// (Currently the first N align with the main nodes,
+// but this may change with HRU.)
+type onodeid uint32
+
+// An onode is a node in the offline constraint graph.
+// (Where ambiguous, members of analysis.nodes are referred to as
+// "main graph" nodes.)
+//
+// Edges in the offline constraint graph (edges and implicit) point to
+// the source, i.e. against the flow of values: they are dependencies.
+// Implicit edges are used for SCC computation, but not for gathering
+// incoming labels.
+//
+type onode struct {
+	rep onodeid // index of representative of SCC in offline constraint graph
+
+	edges    intsets.Sparse // constraint edges X-->Y (this onode is X)
+	implicit intsets.Sparse // implicit edges *X-->*Y (this onode is X)
+	peLabels intsets.Sparse // set of peLabels are pointer-equivalent to this one
+	indirect bool           // node has points-to relations not represented in graph
+
+	// Tarjan's SCC algorithm
+	index, lowlink int32 // Tarjan numbering
+	scc            int32 // -ve => on stack; 0 => unvisited; +ve => node is root of a found SCC
+}
+
+type offsetAddr struct {
+	ptr    nodeid
+	offset uint32
+}
+
+// nextLabel issues the next unused pointer-equivalence label.
+func (h *hvn) nextLabel() peLabel {
+	h.label++
+	return h.label
+}
+
+// ref(X) returns the index of the onode for *X.
+func (h *hvn) ref(id onodeid) onodeid {
+	return id + onodeid(len(h.a.nodes))
+}
+
+// hvn computes pointer-equivalence labels (peLabels) using the Hash-based
+// Value Numbering (HVN) algorithm described in Hardekopf & Lin, SAS'07.
+//
+func (a *analysis) hvn() {
+	start("HVN")
+
+	if a.log != nil {
+		fmt.Fprintf(a.log, "\n\n==== Pointer equivalence optimization\n\n")
+	}
+
+	h := hvn{
+		a:                a,
+		N:                len(a.nodes),
+		log:              a.log,
+		hvnLabel:         make(map[string]peLabel),
+		offsetAddrLabels: make(map[offsetAddr]peLabel),
+	}
+
+	if h.log != nil {
+		fmt.Fprintf(h.log, "\nCreating offline graph nodes...\n")
+	}
+
+	// Create offline nodes.  The first N nodes correspond to main
+	// graph nodes; the next N are their corresponding ref() nodes.
+	h.onodes = make([]*onode, 2*h.N)
+	for id := range a.nodes {
+		id := onodeid(id)
+		h.onodes[id] = &onode{}
+		h.onodes[h.ref(id)] = &onode{indirect: true}
+	}
+
+	// Each node initially represents just itself.
+	for id, o := range h.onodes {
+		o.rep = onodeid(id)
+	}
+
+	h.markIndirectNodes()
+
+	// Reserve the first N PE labels for addrConstraints.
+	h.label = peLabel(h.N)
+
+	// Add offline constraint edges.
+	if h.log != nil {
+		fmt.Fprintf(h.log, "\nAdding offline graph edges...\n")
+	}
+	for _, c := range a.constraints {
+		if debugHVNVerbose && h.log != nil {
+			fmt.Fprintf(h.log, "; %s\n", c)
+		}
+		c.presolve(&h)
+	}
+
+	// Find and collapse SCCs.
+	if h.log != nil {
+		fmt.Fprintf(h.log, "\nFinding SCCs...\n")
+	}
+	h.index = 1
+	for id, o := range h.onodes {
+		if id > 0 && o.index == 0 {
+			// Start depth-first search at each unvisited node.
+			h.visit(onodeid(id))
+		}
+	}
+
+	// Dump the solution
+	// (NB: somewhat redundant with logging from simplify().)
+	if debugHVNVerbose && h.log != nil {
+		fmt.Fprintf(h.log, "\nPointer equivalences:\n")
+		for id, o := range h.onodes {
+			if id == 0 {
+				continue
+			}
+			if id == int(h.N) {
+				fmt.Fprintf(h.log, "---\n")
+			}
+			fmt.Fprintf(h.log, "o%d\t", id)
+			if o.rep != onodeid(id) {
+				fmt.Fprintf(h.log, "rep=o%d", o.rep)
+			} else {
+				fmt.Fprintf(h.log, "p%d", o.peLabels.Min())
+				if o.indirect {
+					fmt.Fprint(h.log, " indirect")
+				}
+			}
+			fmt.Fprintln(h.log)
+		}
+	}
+
+	// Simplify the main constraint graph
+	h.simplify()
+
+	a.showCounts()
+
+	stop("HVN")
+}
+
+// ---- constraint-specific rules ----
+
+// dst := &src
+func (c *addrConstraint) presolve(h *hvn) {
+	// Each object (src) is an initial PE label.
+	label := peLabel(c.src) // label < N
+	if debugHVNVerbose && h.log != nil {
+		// duplicate log messages are possible
+		fmt.Fprintf(h.log, "\tcreate p%d: {&n%d}\n", label, c.src)
+	}
+	odst := onodeid(c.dst)
+	osrc := onodeid(c.src)
+
+	// Assign dst this label.
+	h.onodes[odst].peLabels.Insert(int(label))
+	if debugHVNVerbose && h.log != nil {
+		fmt.Fprintf(h.log, "\to%d has p%d\n", odst, label)
+	}
+
+	h.addImplicitEdge(h.ref(odst), osrc) // *dst ~~> src.
+}
+
+// dst = src
+func (c *copyConstraint) presolve(h *hvn) {
+	odst := onodeid(c.dst)
+	osrc := onodeid(c.src)
+	h.addEdge(odst, osrc)                       //  dst -->  src
+	h.addImplicitEdge(h.ref(odst), h.ref(osrc)) // *dst ~~> *src
+}
+
+// dst = *src + offset
+func (c *loadConstraint) presolve(h *hvn) {
+	odst := onodeid(c.dst)
+	osrc := onodeid(c.src)
+	if c.offset == 0 {
+		h.addEdge(odst, h.ref(osrc)) // dst --> *src
+	} else {
+		// We don't interpret load-with-offset, e.g. results
+		// of map value lookup, R-block of dynamic call, slice
+		// copy/append, reflection.
+		h.markIndirect(odst, "load with offset")
+	}
+}
+
+// *dst + offset = src
+func (c *storeConstraint) presolve(h *hvn) {
+	odst := onodeid(c.dst)
+	osrc := onodeid(c.src)
+	if c.offset == 0 {
+		h.onodes[h.ref(odst)].edges.Insert(int(osrc)) // *dst --> src
+		if debugHVNVerbose && h.log != nil {
+			fmt.Fprintf(h.log, "\to%d --> o%d\n", h.ref(odst), osrc)
+		}
+	} else {
+		// We don't interpret store-with-offset.
+		// See discussion of soundness at markIndirectNodes.
+	}
+}
+
+// dst = &src.offset
+func (c *offsetAddrConstraint) presolve(h *hvn) {
+	// Give each distinct (addr, offset) pair a fresh PE label.
+	// The cache performs CSE, effectively.
+	key := offsetAddr{c.src, c.offset}
+	label, ok := h.offsetAddrLabels[key]
+	if !ok {
+		label = h.nextLabel()
+		h.offsetAddrLabels[key] = label
+		if debugHVNVerbose && h.log != nil {
+			fmt.Fprintf(h.log, "\tcreate p%d: {&n%d.#%d}\n",
+				label, c.src, c.offset)
+		}
+	}
+
+	// Assign dst this label.
+	h.onodes[c.dst].peLabels.Insert(int(label))
+	if debugHVNVerbose && h.log != nil {
+		fmt.Fprintf(h.log, "\to%d has p%d\n", c.dst, label)
+	}
+}
+
+// dst = src.(typ)  where typ is an interface
+func (c *typeFilterConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.dst), "typeFilter result")
+}
+
+// dst = src.(typ)  where typ is concrete
+func (c *untagConstraint) presolve(h *hvn) {
+	odst := onodeid(c.dst)
+	for end := odst + onodeid(h.a.sizeof(c.typ)); odst < end; odst++ {
+		h.markIndirect(odst, "untag result")
+	}
+}
+
+// dst = src.method(c.params...)
+func (c *invokeConstraint) presolve(h *hvn) {
+	// All methods are address-taken functions, so
+	// their formal P-blocks were already marked indirect.
+
+	// Mark the caller's targets node as indirect.
+	sig := c.method.Type().(*types.Signature)
+	id := c.params
+	h.markIndirect(onodeid(c.params), "invoke targets node")
+	id++
+
+	id += nodeid(h.a.sizeof(sig.Params()))
+
+	// Mark the caller's R-block as indirect.
+	end := id + nodeid(h.a.sizeof(sig.Results()))
+	for id < end {
+		h.markIndirect(onodeid(id), "invoke R-block")
+		id++
+	}
+}
+
+// markIndirectNodes marks as indirect nodes whose points-to relations
+// are not entirely captured by the offline graph, including:
+//
+//    (a) All address-taken nodes (including the following nodes within
+//        the same object).  This is described in the paper.
+//
+// The most subtle cause of indirect nodes is the generation of
+// store-with-offset constraints since the offline graph doesn't
+// represent them.  A global audit of constraint generation reveals the
+// following uses of store-with-offset:
+//
+//    (b) genDynamicCall, for P-blocks of dynamically called functions,
+//        to which dynamic copy edges will be added to them during
+//        solving: from storeConstraint for standalone functions,
+//        and from invokeConstraint for methods.
+//        All such P-blocks must be marked indirect.
+//    (c) MakeUpdate, to update the value part of a map object.
+//        All MakeMap objects's value parts must be marked indirect.
+//    (d) copyElems, to update the destination array.
+//        All array elements must be marked indirect.
+//
+// Not all indirect marking happens here.  ref() nodes are marked
+// indirect at construction, and each constraint's presolve() method may
+// mark additional nodes.
+//
+func (h *hvn) markIndirectNodes() {
+	// (a) all address-taken nodes, plus all nodes following them
+	//     within the same object, since these may be indirectly
+	//     stored or address-taken.
+	for _, c := range h.a.constraints {
+		if c, ok := c.(*addrConstraint); ok {
+			start := h.a.enclosingObj(c.src)
+			end := start + nodeid(h.a.nodes[start].obj.size)
+			for id := c.src; id < end; id++ {
+				h.markIndirect(onodeid(id), "A-T object")
+			}
+		}
+	}
+
+	// (b) P-blocks of all address-taken functions.
+	for id := 0; id < h.N; id++ {
+		obj := h.a.nodes[id].obj
+
+		// TODO(adonovan): opt: if obj.cgn.fn is a method and
+		// obj.cgn is not its shared contour, this is an
+		// "inlined" static method call.  We needn't consider it
+		// address-taken since no invokeConstraint will affect it.
+
+		if obj != nil && obj.flags&otFunction != 0 && h.a.atFuncs[obj.cgn.fn] {
+			// address-taken function
+			if debugHVNVerbose && h.log != nil {
+				fmt.Fprintf(h.log, "n%d is address-taken: %s\n", id, obj.cgn.fn)
+			}
+			h.markIndirect(onodeid(id), "A-T func identity")
+			id++
+			sig := obj.cgn.fn.Signature
+			psize := h.a.sizeof(sig.Params())
+			if sig.Recv() != nil {
+				psize += h.a.sizeof(sig.Recv().Type())
+			}
+			for end := id + int(psize); id < end; id++ {
+				h.markIndirect(onodeid(id), "A-T func P-block")
+			}
+			id--
+			continue
+		}
+	}
+
+	// (c) all map objects' value fields.
+	for _, id := range h.a.mapValues {
+		h.markIndirect(onodeid(id), "makemap.value")
+	}
+
+	// (d) all array element objects.
+	// TODO(adonovan): opt: can we do better?
+	for id := 0; id < h.N; id++ {
+		// Identity node for an object of array type?
+		if tArray, ok := h.a.nodes[id].typ.(*types.Array); ok {
+			// Mark the array element nodes indirect.
+			// (Skip past the identity field.)
+			for _ = range h.a.flatten(tArray.Elem()) {
+				id++
+				h.markIndirect(onodeid(id), "array elem")
+			}
+		}
+	}
+}
+
+func (h *hvn) markIndirect(oid onodeid, comment string) {
+	h.onodes[oid].indirect = true
+	if debugHVNVerbose && h.log != nil {
+		fmt.Fprintf(h.log, "\to%d is indirect: %s\n", oid, comment)
+	}
+}
+
+// Adds an edge dst-->src.
+// Note the unusual convention: edges are dependency (contraflow) edges.
+func (h *hvn) addEdge(odst, osrc onodeid) {
+	h.onodes[odst].edges.Insert(int(osrc))
+	if debugHVNVerbose && h.log != nil {
+		fmt.Fprintf(h.log, "\to%d --> o%d\n", odst, osrc)
+	}
+}
+
+func (h *hvn) addImplicitEdge(odst, osrc onodeid) {
+	h.onodes[odst].implicit.Insert(int(osrc))
+	if debugHVNVerbose && h.log != nil {
+		fmt.Fprintf(h.log, "\to%d ~~> o%d\n", odst, osrc)
+	}
+}
+
+// visit implements the depth-first search of Tarjan's SCC algorithm.
+// Precondition: x is canonical.
+func (h *hvn) visit(x onodeid) {
+	h.checkCanonical(x)
+	xo := h.onodes[x]
+	xo.index = h.index
+	xo.lowlink = h.index
+	h.index++
+
+	h.stack = append(h.stack, x) // push
+	assert(xo.scc == 0, "node revisited")
+	xo.scc = -1
+
+	var deps []int
+	deps = xo.edges.AppendTo(deps)
+	deps = xo.implicit.AppendTo(deps)
+
+	for _, y := range deps {
+		// Loop invariant: x is canonical.
+
+		y := h.find(onodeid(y))
+
+		if x == y {
+			continue // nodes already coalesced
+		}
+
+		xo := h.onodes[x]
+		yo := h.onodes[y]
+
+		switch {
+		case yo.scc > 0:
+			// y is already a collapsed SCC
+
+		case yo.scc < 0:
+			// y is on the stack, and thus in the current SCC.
+			if yo.index < xo.lowlink {
+				xo.lowlink = yo.index
+			}
+
+		default:
+			// y is unvisited; visit it now.
+			h.visit(y)
+			// Note: x and y are now non-canonical.
+
+			x = h.find(onodeid(x))
+
+			if yo.lowlink < xo.lowlink {
+				xo.lowlink = yo.lowlink
+			}
+		}
+	}
+	h.checkCanonical(x)
+
+	// Is x the root of an SCC?
+	if xo.lowlink == xo.index {
+		// Coalesce all nodes in the SCC.
+		if debugHVNVerbose && h.log != nil {
+			fmt.Fprintf(h.log, "scc o%d\n", x)
+		}
+		for {
+			// Pop y from stack.
+			i := len(h.stack) - 1
+			y := h.stack[i]
+			h.stack = h.stack[:i]
+
+			h.checkCanonical(x)
+			xo := h.onodes[x]
+			h.checkCanonical(y)
+			yo := h.onodes[y]
+
+			if xo == yo {
+				// SCC is complete.
+				xo.scc = 1
+				h.labelSCC(x)
+				break
+			}
+			h.coalesce(x, y)
+		}
+	}
+}
+
+// Precondition: x is canonical.
+func (h *hvn) labelSCC(x onodeid) {
+	h.checkCanonical(x)
+	xo := h.onodes[x]
+	xpe := &xo.peLabels
+
+	// All indirect nodes get new labels.
+	if xo.indirect {
+		label := h.nextLabel()
+		if debugHVNVerbose && h.log != nil {
+			fmt.Fprintf(h.log, "\tcreate p%d: indirect SCC\n", label)
+			fmt.Fprintf(h.log, "\to%d has p%d\n", x, label)
+		}
+
+		// Remove pre-labeling, in case a direct pre-labeled node was
+		// merged with an indirect one.
+		xpe.Clear()
+		xpe.Insert(int(label))
+
+		return
+	}
+
+	// Invariant: all peLabels sets are non-empty.
+	// Those that are logically empty contain zero as their sole element.
+	// No other sets contains zero.
+
+	// Find all labels coming in to the coalesced SCC node.
+	for _, y := range xo.edges.AppendTo(nil) {
+		y := h.find(onodeid(y))
+		if y == x {
+			continue // already coalesced
+		}
+		ype := &h.onodes[y].peLabels
+		if debugHVNVerbose && h.log != nil {
+			fmt.Fprintf(h.log, "\tedge from o%d = %s\n", y, ype)
+		}
+
+		if ype.IsEmpty() {
+			if debugHVNVerbose && h.log != nil {
+				fmt.Fprintf(h.log, "\tnode has no PE label\n")
+			}
+		}
+		assert(!ype.IsEmpty(), "incoming node has no PE label")
+
+		if ype.Has(0) {
+			// {0} represents a non-pointer.
+			assert(ype.Len() == 1, "PE set contains {0, ...}")
+		} else {
+			xpe.UnionWith(ype)
+		}
+	}
+
+	switch xpe.Len() {
+	case 0:
+		// SCC has no incoming non-zero PE labels: it is a non-pointer.
+		xpe.Insert(0)
+
+	case 1:
+		// already a singleton
+
+	default:
+		// SCC has multiple incoming non-zero PE labels.
+		// Find the canonical label representing this set.
+		// We use String() as a fingerprint consistent with Equals().
+		key := xpe.String()
+		label, ok := h.hvnLabel[key]
+		if !ok {
+			label = h.nextLabel()
+			if debugHVNVerbose && h.log != nil {
+				fmt.Fprintf(h.log, "\tcreate p%d: union %s\n", label, xpe.String())
+			}
+			h.hvnLabel[key] = label
+		}
+		xpe.Clear()
+		xpe.Insert(int(label))
+	}
+
+	if debugHVNVerbose && h.log != nil {
+		fmt.Fprintf(h.log, "\to%d has p%d\n", x, xpe.Min())
+	}
+}
+
+// coalesce combines two nodes in the offline constraint graph.
+// Precondition: x and y are canonical.
+func (h *hvn) coalesce(x, y onodeid) {
+	xo := h.onodes[x]
+	yo := h.onodes[y]
+
+	// x becomes y's canonical representative.
+	yo.rep = x
+
+	if debugHVNVerbose && h.log != nil {
+		fmt.Fprintf(h.log, "\tcoalesce o%d into o%d\n", y, x)
+	}
+
+	// x accumulates y's edges.
+	xo.edges.UnionWith(&yo.edges)
+	yo.edges.Clear()
+
+	// x accumulates y's implicit edges.
+	xo.implicit.UnionWith(&yo.implicit)
+	yo.implicit.Clear()
+
+	// x accumulates y's pointer-equivalence labels.
+	xo.peLabels.UnionWith(&yo.peLabels)
+	yo.peLabels.Clear()
+
+	// x accumulates y's indirect flag.
+	if yo.indirect {
+		xo.indirect = true
+	}
+}
+
+// simplify computes a degenerate renumbering of nodeids from the PE
+// labels assigned by the hvn, and uses it to simplify the main
+// constraint graph, eliminating non-pointer nodes and duplicate
+// constraints.
+//
+func (h *hvn) simplify() {
+	// canon maps each peLabel to its canonical main node.
+	canon := make([]nodeid, h.label)
+	for i := range canon {
+		canon[i] = nodeid(h.N) // indicates "unset"
+	}
+
+	// mapping maps each main node index to the index of the canonical node.
+	mapping := make([]nodeid, len(h.a.nodes))
+
+	for id := range h.a.nodes {
+		id := nodeid(id)
+		if id == 0 {
+			canon[0] = 0
+			mapping[0] = 0
+			continue
+		}
+		oid := h.find(onodeid(id))
+		peLabels := &h.onodes[oid].peLabels
+		assert(peLabels.Len() == 1, "PE class is not a singleton")
+		label := peLabel(peLabels.Min())
+
+		canonId := canon[label]
+		if canonId == nodeid(h.N) {
+			// id becomes the representative of the PE label.
+			canonId = id
+			canon[label] = canonId
+
+			if h.a.log != nil {
+				fmt.Fprintf(h.a.log, "\tpts(n%d) is canonical : \t(%s)\n",
+					id, h.a.nodes[id].typ)
+			}
+
+		} else {
+			// Link the solver states for the two nodes.
+			assert(h.a.nodes[canonId].solve != nil, "missing solver state")
+			h.a.nodes[id].solve = h.a.nodes[canonId].solve
+
+			if h.a.log != nil {
+				// TODO(adonovan): debug: reorganize the log so it prints
+				// one line:
+				// 	pe y = x1, ..., xn
+				// for each canonical y.  Requires allocation.
+				fmt.Fprintf(h.a.log, "\tpts(n%d) = pts(n%d) : %s\n",
+					id, canonId, h.a.nodes[id].typ)
+			}
+		}
+
+		mapping[id] = canonId
+	}
+
+	// Renumber the constraints, eliminate duplicates, and eliminate
+	// any containing non-pointers (n0).
+	addrs := make(map[addrConstraint]bool)
+	copys := make(map[copyConstraint]bool)
+	loads := make(map[loadConstraint]bool)
+	stores := make(map[storeConstraint]bool)
+	offsetAddrs := make(map[offsetAddrConstraint]bool)
+	untags := make(map[untagConstraint]bool)
+	typeFilters := make(map[typeFilterConstraint]bool)
+	invokes := make(map[invokeConstraint]bool)
+
+	nbefore := len(h.a.constraints)
+	cc := h.a.constraints[:0] // in-situ compaction
+	for _, c := range h.a.constraints {
+		// Renumber.
+		switch c := c.(type) {
+		case *addrConstraint:
+			// Don't renumber c.src since it is the label of
+			// an addressable object and will appear in PT sets.
+			c.dst = mapping[c.dst]
+		default:
+			c.renumber(mapping)
+		}
+
+		if c.ptr() == 0 {
+			continue // skip: constraint attached to non-pointer
+		}
+
+		var dup bool
+		switch c := c.(type) {
+		case *addrConstraint:
+			_, dup = addrs[*c]
+			addrs[*c] = true
+
+		case *copyConstraint:
+			if c.src == c.dst {
+				continue // skip degenerate copies
+			}
+			if c.src == 0 {
+				continue // skip copy from non-pointer
+			}
+			_, dup = copys[*c]
+			copys[*c] = true
+
+		case *loadConstraint:
+			if c.src == 0 {
+				continue // skip load from non-pointer
+			}
+			_, dup = loads[*c]
+			loads[*c] = true
+
+		case *storeConstraint:
+			if c.src == 0 {
+				continue // skip store from non-pointer
+			}
+			_, dup = stores[*c]
+			stores[*c] = true
+
+		case *offsetAddrConstraint:
+			if c.src == 0 {
+				continue // skip offset from non-pointer
+			}
+			_, dup = offsetAddrs[*c]
+			offsetAddrs[*c] = true
+
+		case *untagConstraint:
+			if c.src == 0 {
+				continue // skip untag of non-pointer
+			}
+			_, dup = untags[*c]
+			untags[*c] = true
+
+		case *typeFilterConstraint:
+			if c.src == 0 {
+				continue // skip filter of non-pointer
+			}
+			_, dup = typeFilters[*c]
+			typeFilters[*c] = true
+
+		case *invokeConstraint:
+			if c.params == 0 {
+				panic("non-pointer invoke.params")
+			}
+			if c.iface == 0 {
+				continue // skip invoke on non-pointer
+			}
+			_, dup = invokes[*c]
+			invokes[*c] = true
+
+		default:
+			// We don't bother de-duping advanced constraints
+			// (e.g. reflection) since they are uncommon.
+
+			// Eliminate constraints containing non-pointer nodeids.
+			//
+			// We use reflection to find the fields to avoid
+			// adding yet another method to constraint.
+			//
+			// TODO(adonovan): experiment with a constraint
+			// method that returns a slice of pointers to
+			// nodeids fields to enable uniform iteration;
+			// the renumber() method could be removed and
+			// implemented using the new one.
+			//
+			// TODO(adonovan): opt: this is unsound since
+			// some constraints still have an effect if one
+			// of the operands is zero: rVCall, rVMapIndex,
+			// rvSetMapIndex.  Handle them specially.
+			rtNodeid := reflect.TypeOf(nodeid(0))
+			x := reflect.ValueOf(c).Elem()
+			for i, nf := 0, x.NumField(); i < nf; i++ {
+				f := x.Field(i)
+				if f.Type() == rtNodeid {
+					if f.Uint() == 0 {
+						dup = true // skip it
+						break
+					}
+				}
+			}
+		}
+		if dup {
+			continue // skip duplicates
+		}
+
+		cc = append(cc, c)
+	}
+	h.a.constraints = cc
+
+	if h.log != nil {
+		fmt.Fprintf(h.log, "#constraints: was %d, now %d\n", nbefore, len(h.a.constraints))
+	}
+}
+
+// find returns the canonical onodeid for x.
+// (The onodes form a disjoint set forest.)
+func (h *hvn) find(x onodeid) onodeid {
+	// TODO(adonovan): opt: this is a CPU hotspot.  Try "union by rank".
+	xo := h.onodes[x]
+	rep := xo.rep
+	if rep != x {
+		rep = h.find(rep) // simple path compression
+		xo.rep = rep
+	}
+	return rep
+}
+
+func (h *hvn) checkCanonical(x onodeid) {
+	if debugHVN {
+		assert(x == h.find(x), "not canonical")
+	}
+}
+
+func assert(p bool, msg string) {
+	if debugHVN && !p {
+		panic("assertion failed: " + msg)
+	}
+}
diff --git a/go/src/golang.org/x/tools/go/pointer/intrinsics.go b/go/src/golang.org/x/tools/go/pointer/intrinsics.go
index 251c0e2..fbfb36d 100644
--- a/go/src/golang.org/x/tools/go/pointer/intrinsics.go
+++ b/go/src/golang.org/x/tools/go/pointer/intrinsics.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package pointer
 
 // This package defines the treatment of intrinsics, i.e. library
@@ -17,9 +19,9 @@
 
 import (
 	"fmt"
+	"go/types"
 
 	"golang.org/x/tools/go/ssa"
-	"golang.org/x/tools/go/types"
 )
 
 // Instances of 'intrinsic' generate analysis constraints for calls to
@@ -211,7 +213,7 @@
 		return false // "reflect" package not loaded
 	}
 	reflectPackage := a.reflectValueObj.Pkg()
-	if fn.Pkg != nil && fn.Pkg.Object == reflectPackage {
+	if fn.Pkg != nil && fn.Pkg.Pkg == reflectPackage {
 		return true
 	}
 	// Synthetic wrappers have a nil Pkg, so they slip through the
diff --git a/go/src/golang.org/x/tools/go/pointer/intrinsics14.go b/go/src/golang.org/x/tools/go/pointer/intrinsics14.go
new file mode 100644
index 0000000..5e108d2
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/pointer/intrinsics14.go
@@ -0,0 +1,382 @@
+// 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.
+
+// +build !go1.5
+
+package pointer
+
+// This package defines the treatment of intrinsics, i.e. library
+// functions requiring special analytical treatment.
+//
+// Most of these are C or assembly functions, but even some Go
+// functions require may special treatment if the analysis completely
+// replaces the implementation of an API such as reflection.
+
+// TODO(adonovan): support a means of writing analytic summaries in
+// the target code, so that users can summarise the effects of their
+// own C functions using a snippet of Go.
+
+import (
+	"fmt"
+
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/types"
+)
+
+// Instances of 'intrinsic' generate analysis constraints for calls to
+// intrinsic functions.
+// Implementations may exploit information from the calling site
+// via cgn.callersite; for shared contours this is nil.
+type intrinsic func(a *analysis, cgn *cgnode)
+
+// Initialized in explicit init() to defeat (spurious) initialization
+// cycle error.
+var intrinsicsByName = make(map[string]intrinsic)
+
+func init() {
+	// Key strings are from Function.String().
+	// That little dot Û° is an Arabic zero numeral (U+06F0),
+	// categories [Nd].
+	for name, fn := range map[string]intrinsic{
+		// Other packages.
+		"bytes.Equal":                           extÛ°NoEffect,
+		"bytes.IndexByte":                       extÛ°NoEffect,
+		"crypto/aes.decryptBlockAsm":            extÛ°NoEffect,
+		"crypto/aes.encryptBlockAsm":            extÛ°NoEffect,
+		"crypto/aes.expandKeyAsm":               extÛ°NoEffect,
+		"crypto/aes.hasAsm":                     extÛ°NoEffect,
+		"crypto/md5.block":                      extÛ°NoEffect,
+		"crypto/rc4.xorKeyStream":               extÛ°NoEffect,
+		"crypto/sha1.block":                     extÛ°NoEffect,
+		"crypto/sha256.block":                   extÛ°NoEffect,
+		"hash/crc32.castagnoliSSE42":            extÛ°NoEffect,
+		"hash/crc32.haveSSE42":                  extÛ°NoEffect,
+		"math.Abs":                              extÛ°NoEffect,
+		"math.Acos":                             extÛ°NoEffect,
+		"math.Asin":                             extÛ°NoEffect,
+		"math.Atan":                             extÛ°NoEffect,
+		"math.Atan2":                            extÛ°NoEffect,
+		"math.Ceil":                             extÛ°NoEffect,
+		"math.Cos":                              extÛ°NoEffect,
+		"math.Dim":                              extÛ°NoEffect,
+		"math.Exp":                              extÛ°NoEffect,
+		"math.Exp2":                             extÛ°NoEffect,
+		"math.Expm1":                            extÛ°NoEffect,
+		"math.Float32bits":                      extÛ°NoEffect,
+		"math.Float32frombits":                  extÛ°NoEffect,
+		"math.Float64bits":                      extÛ°NoEffect,
+		"math.Float64frombits":                  extÛ°NoEffect,
+		"math.Floor":                            extÛ°NoEffect,
+		"math.Frexp":                            extÛ°NoEffect,
+		"math.Hypot":                            extÛ°NoEffect,
+		"math.Ldexp":                            extÛ°NoEffect,
+		"math.Log":                              extÛ°NoEffect,
+		"math.Log10":                            extÛ°NoEffect,
+		"math.Log1p":                            extÛ°NoEffect,
+		"math.Log2":                             extÛ°NoEffect,
+		"math.Max":                              extÛ°NoEffect,
+		"math.Min":                              extÛ°NoEffect,
+		"math.Mod":                              extÛ°NoEffect,
+		"math.Modf":                             extÛ°NoEffect,
+		"math.Remainder":                        extÛ°NoEffect,
+		"math.Sin":                              extÛ°NoEffect,
+		"math.Sincos":                           extÛ°NoEffect,
+		"math.Sqrt":                             extÛ°NoEffect,
+		"math.Tan":                              extÛ°NoEffect,
+		"math.Trunc":                            extÛ°NoEffect,
+		"math/big.addMulVVW":                    extÛ°NoEffect,
+		"math/big.addVV":                        extÛ°NoEffect,
+		"math/big.addVW":                        extÛ°NoEffect,
+		"math/big.bitLen":                       extÛ°NoEffect,
+		"math/big.divWVW":                       extÛ°NoEffect,
+		"math/big.divWW":                        extÛ°NoEffect,
+		"math/big.mulAddVWW":                    extÛ°NoEffect,
+		"math/big.mulWW":                        extÛ°NoEffect,
+		"math/big.shlVU":                        extÛ°NoEffect,
+		"math/big.shrVU":                        extÛ°NoEffect,
+		"math/big.subVV":                        extÛ°NoEffect,
+		"math/big.subVW":                        extÛ°NoEffect,
+		"net.runtime_Semacquire":                extÛ°NoEffect,
+		"net.runtime_Semrelease":                extÛ°NoEffect,
+		"net.runtime_pollClose":                 extÛ°NoEffect,
+		"net.runtime_pollOpen":                  extÛ°NoEffect,
+		"net.runtime_pollReset":                 extÛ°NoEffect,
+		"net.runtime_pollServerInit":            extÛ°NoEffect,
+		"net.runtime_pollSetDeadline":           extÛ°NoEffect,
+		"net.runtime_pollUnblock":               extÛ°NoEffect,
+		"net.runtime_pollWait":                  extÛ°NoEffect,
+		"net.runtime_pollWaitCanceled":          extÛ°NoEffect,
+		"os.epipecheck":                         extÛ°NoEffect,
+		"runtime.BlockProfile":                  extÛ°NoEffect,
+		"runtime.Breakpoint":                    extÛ°NoEffect,
+		"runtime.CPUProfile":                    extÛ°NoEffect, // good enough
+		"runtime.Caller":                        extÛ°NoEffect,
+		"runtime.Callers":                       extÛ°NoEffect, // good enough
+		"runtime.FuncForPC":                     extÛ°NoEffect,
+		"runtime.GC":                            extÛ°NoEffect,
+		"runtime.GOMAXPROCS":                    extÛ°NoEffect,
+		"runtime.Goexit":                        extÛ°NoEffect,
+		"runtime.GoroutineProfile":              extÛ°NoEffect,
+		"runtime.Gosched":                       extÛ°NoEffect,
+		"runtime.MemProfile":                    extÛ°NoEffect,
+		"runtime.NumCPU":                        extÛ°NoEffect,
+		"runtime.NumGoroutine":                  extÛ°NoEffect,
+		"runtime.ReadMemStats":                  extÛ°NoEffect,
+		"runtime.SetBlockProfileRate":           extÛ°NoEffect,
+		"runtime.SetCPUProfileRate":             extÛ°NoEffect,
+		"runtime.SetFinalizer":                  extÛ°runtimeÛ°SetFinalizer,
+		"runtime.Stack":                         extÛ°NoEffect,
+		"runtime.ThreadCreateProfile":           extÛ°NoEffect,
+		"runtime.cstringToGo":                   extÛ°NoEffect,
+		"runtime.funcentry_go":                  extÛ°NoEffect,
+		"runtime.funcline_go":                   extÛ°NoEffect,
+		"runtime.funcname_go":                   extÛ°NoEffect,
+		"runtime.getgoroot":                     extÛ°NoEffect,
+		"runtime/pprof.runtime_cyclesPerSecond": extÛ°NoEffect,
+		"strings.IndexByte":                     extÛ°NoEffect,
+		"sync.runtime_Semacquire":               extÛ°NoEffect,
+		"sync.runtime_Semrelease":               extÛ°NoEffect,
+		"sync.runtime_Syncsemacquire":           extÛ°NoEffect,
+		"sync.runtime_Syncsemcheck":             extÛ°NoEffect,
+		"sync.runtime_Syncsemrelease":           extÛ°NoEffect,
+		"sync.runtime_procPin":                  extÛ°NoEffect,
+		"sync.runtime_procUnpin":                extÛ°NoEffect,
+		"sync.runtime_registerPool":             extÛ°NoEffect,
+		"sync/atomic.AddInt32":                  extÛ°NoEffect,
+		"sync/atomic.AddInt64":                  extÛ°NoEffect,
+		"sync/atomic.AddUint32":                 extÛ°NoEffect,
+		"sync/atomic.AddUint64":                 extÛ°NoEffect,
+		"sync/atomic.AddUintptr":                extÛ°NoEffect,
+		"sync/atomic.CompareAndSwapInt32":       extÛ°NoEffect,
+		"sync/atomic.CompareAndSwapUint32":      extÛ°NoEffect,
+		"sync/atomic.CompareAndSwapUint64":      extÛ°NoEffect,
+		"sync/atomic.CompareAndSwapUintptr":     extÛ°NoEffect,
+		"sync/atomic.LoadInt32":                 extÛ°NoEffect,
+		"sync/atomic.LoadInt64":                 extÛ°NoEffect,
+		"sync/atomic.LoadPointer":               extÛ°NoEffect, // ignore unsafe.Pointers
+		"sync/atomic.LoadUint32":                extÛ°NoEffect,
+		"sync/atomic.LoadUint64":                extÛ°NoEffect,
+		"sync/atomic.LoadUintptr":               extÛ°NoEffect,
+		"sync/atomic.StoreInt32":                extÛ°NoEffect,
+		"sync/atomic.StorePointer":              extÛ°NoEffect, // ignore unsafe.Pointers
+		"sync/atomic.StoreUint32":               extÛ°NoEffect,
+		"sync/atomic.StoreUintptr":              extÛ°NoEffect,
+		"syscall.Close":                         extÛ°NoEffect,
+		"syscall.Exit":                          extÛ°NoEffect,
+		"syscall.Getpid":                        extÛ°NoEffect,
+		"syscall.Getwd":                         extÛ°NoEffect,
+		"syscall.Kill":                          extÛ°NoEffect,
+		"syscall.RawSyscall":                    extÛ°NoEffect,
+		"syscall.RawSyscall6":                   extÛ°NoEffect,
+		"syscall.Syscall":                       extÛ°NoEffect,
+		"syscall.Syscall6":                      extÛ°NoEffect,
+		"syscall.runtime_AfterFork":             extÛ°NoEffect,
+		"syscall.runtime_BeforeFork":            extÛ°NoEffect,
+		"syscall.setenv_c":                      extÛ°NoEffect,
+		"time.Sleep":                            extÛ°NoEffect,
+		"time.now":                              extÛ°NoEffect,
+		"time.startTimer":                       extÛ°timeÛ°startTimer,
+		"time.stopTimer":                        extÛ°NoEffect,
+	} {
+		intrinsicsByName[name] = fn
+	}
+}
+
+// findIntrinsic returns the constraint generation function for an
+// intrinsic function fn, or nil if the function should be handled normally.
+//
+func (a *analysis) findIntrinsic(fn *ssa.Function) intrinsic {
+	// Consult the *Function-keyed cache.
+	// A cached nil indicates a normal non-intrinsic function.
+	impl, ok := a.intrinsics[fn]
+	if !ok {
+		impl = intrinsicsByName[fn.String()] // may be nil
+
+		if a.isReflect(fn) {
+			if !a.config.Reflection {
+				impl = extÛ°NoEffect // reflection disabled
+			} else if impl == nil {
+				// Ensure all "reflect" code is treated intrinsically.
+				impl = extÛ°NotYetImplemented
+			}
+		}
+
+		a.intrinsics[fn] = impl
+	}
+	return impl
+}
+
+// isReflect reports whether fn belongs to the "reflect" package.
+func (a *analysis) isReflect(fn *ssa.Function) bool {
+	if a.reflectValueObj == nil {
+		return false // "reflect" package not loaded
+	}
+	reflectPackage := a.reflectValueObj.Pkg()
+	if fn.Pkg != nil && fn.Pkg.Pkg == reflectPackage {
+		return true
+	}
+	// Synthetic wrappers have a nil Pkg, so they slip through the
+	// previous check.  Check the receiver package.
+	// TODO(adonovan): should synthetic wrappers have a non-nil Pkg?
+	if recv := fn.Signature.Recv(); recv != nil {
+		if named, ok := deref(recv.Type()).(*types.Named); ok {
+			if named.Obj().Pkg() == reflectPackage {
+				return true // e.g. wrapper of (reflect.Value).f
+			}
+		}
+	}
+	return false
+}
+
+// A trivial intrinsic suitable for any function that does not:
+// 1) induce aliases between its arguments or any global variables;
+// 2) call any functions; or
+// 3) create any labels.
+//
+// Many intrinsics (such as CompareAndSwapInt32) have a fourth kind of
+// effect: loading or storing through a pointer.  Though these could
+// be significant, we deliberately ignore them because they are
+// generally not worth the effort.
+//
+// We sometimes violate condition #3 if the function creates only
+// non-function labels, as the control-flow graph is still sound.
+//
+func extÛ°NoEffect(a *analysis, cgn *cgnode) {}
+
+func extÛ°NotYetImplemented(a *analysis, cgn *cgnode) {
+	fn := cgn.fn
+	a.warnf(fn.Pos(), "unsound: intrinsic treatment of %s not yet implemented", fn)
+}
+
+// ---------- func runtime.SetFinalizer(x, f interface{}) ----------
+
+// runtime.SetFinalizer(x, f)
+type runtimeSetFinalizerConstraint struct {
+	targets nodeid // (indirect)
+	f       nodeid // (ptr)
+	x       nodeid
+}
+
+func (c *runtimeSetFinalizerConstraint) ptr() nodeid { return c.f }
+func (c *runtimeSetFinalizerConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.targets), "SetFinalizer.targets")
+}
+func (c *runtimeSetFinalizerConstraint) renumber(mapping []nodeid) {
+	c.targets = mapping[c.targets]
+	c.f = mapping[c.f]
+	c.x = mapping[c.x]
+}
+
+func (c *runtimeSetFinalizerConstraint) String() string {
+	return fmt.Sprintf("runtime.SetFinalizer(n%d, n%d)", c.x, c.f)
+}
+
+func (c *runtimeSetFinalizerConstraint) solve(a *analysis, delta *nodeset) {
+	for _, fObj := range delta.AppendTo(a.deltaSpace) {
+		tDyn, f, indirect := a.taggedValue(nodeid(fObj))
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		tSig, ok := tDyn.Underlying().(*types.Signature)
+		if !ok {
+			continue // not a function
+		}
+		if tSig.Recv() != nil {
+			panic(tSig)
+		}
+		if tSig.Params().Len() != 1 {
+			continue //  not a unary function
+		}
+
+		// Extract x to tmp.
+		tx := tSig.Params().At(0).Type()
+		tmp := a.addNodes(tx, "SetFinalizer.tmp")
+		a.typeAssert(tx, tmp, c.x, false)
+
+		// Call f(tmp).
+		a.store(f, tmp, 1, a.sizeof(tx))
+
+		// Add dynamic call target.
+		if a.onlineCopy(c.targets, f) {
+			a.addWork(c.targets)
+		}
+	}
+}
+
+func extÛ°runtimeÛ°SetFinalizer(a *analysis, cgn *cgnode) {
+	// This is the shared contour, used for dynamic calls.
+	targets := a.addOneNode(tInvalid, "SetFinalizer.targets", nil)
+	cgn.sites = append(cgn.sites, &callsite{targets: targets})
+	params := a.funcParams(cgn.obj)
+	a.addConstraint(&runtimeSetFinalizerConstraint{
+		targets: targets,
+		x:       params,
+		f:       params + 1,
+	})
+}
+
+// ---------- func time.startTimer(t *runtimeTimer) ----------
+
+// time.StartTimer(t)
+type timeStartTimerConstraint struct {
+	targets nodeid // (indirect)
+	t       nodeid // (ptr)
+}
+
+func (c *timeStartTimerConstraint) ptr() nodeid { return c.t }
+func (c *timeStartTimerConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.targets), "StartTimer.targets")
+}
+func (c *timeStartTimerConstraint) renumber(mapping []nodeid) {
+	c.targets = mapping[c.targets]
+	c.t = mapping[c.t]
+}
+
+func (c *timeStartTimerConstraint) String() string {
+	return fmt.Sprintf("time.startTimer(n%d)", c.t)
+}
+
+func (c *timeStartTimerConstraint) solve(a *analysis, delta *nodeset) {
+	for _, tObj := range delta.AppendTo(a.deltaSpace) {
+		t := nodeid(tObj)
+
+		// We model startTimer as if it was defined thus:
+		// 	func startTimer(t *runtimeTimer) { t.f(t.arg) }
+
+		// We hard-code the field offsets of time.runtimeTimer:
+		// type runtimeTimer struct {
+		//  0     __identity__
+		//  1    i      int32
+		//  2    when   int64
+		//  3    period int64
+		//  4    f      func(int64, interface{})
+		//  5    arg    interface{}
+		// }
+		f := t + 4
+		arg := t + 5
+
+		// store t.arg to t.f.params[0]
+		// (offset 1 => skip identity)
+		a.store(f, arg, 1, 1)
+
+		// Add dynamic call target.
+		if a.onlineCopy(c.targets, f) {
+			a.addWork(c.targets)
+		}
+	}
+}
+
+func extÛ°timeÛ°startTimer(a *analysis, cgn *cgnode) {
+	// This is the shared contour, used for dynamic calls.
+	targets := a.addOneNode(tInvalid, "startTimer.targets", nil)
+	cgn.sites = append(cgn.sites, &callsite{targets: targets})
+	params := a.funcParams(cgn.obj)
+	a.addConstraint(&timeStartTimerConstraint{
+		targets: targets,
+		t:       params,
+	})
+}
diff --git a/go/src/golang.org/x/tools/go/pointer/labels.go b/go/src/golang.org/x/tools/go/pointer/labels.go
index cf6ef20..bfe60d2 100644
--- a/go/src/golang.org/x/tools/go/pointer/labels.go
+++ b/go/src/golang.org/x/tools/go/pointer/labels.go
@@ -2,15 +2,17 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package pointer
 
 import (
 	"fmt"
 	"go/token"
+	"go/types"
 	"strings"
 
 	"golang.org/x/tools/go/ssa"
-	"golang.org/x/tools/go/types"
 )
 
 // A Label is an entity that may be pointed to by a pointer, map,
diff --git a/go/src/golang.org/x/tools/go/pointer/labels14.go b/go/src/golang.org/x/tools/go/pointer/labels14.go
new file mode 100644
index 0000000..c9ca6a3
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/pointer/labels14.go
@@ -0,0 +1,154 @@
+// 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.
+
+// +build !go1.5
+
+package pointer
+
+import (
+	"fmt"
+	"go/token"
+	"strings"
+
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/types"
+)
+
+// A Label is an entity that may be pointed to by a pointer, map,
+// channel, 'func', slice or interface.
+//
+// Labels include:
+//      - functions
+//      - globals
+//      - tagged objects, representing interfaces and reflect.Values
+//      - arrays created by conversions (e.g. []byte("foo"), []byte(s))
+//      - stack- and heap-allocated variables (including composite literals)
+//      - channels, maps and arrays created by make()
+//      - intrinsic or reflective operations that allocate (e.g. append, reflect.New)
+//      - intrinsic objects, e.g. the initial array behind os.Args.
+//      - and their subelements, e.g. "alloc.y[*].z"
+//
+// Labels are so varied that they defy good generalizations;
+// some have no value, no callgraph node, or no position.
+// Many objects have types that are inexpressible in Go:
+// maps, channels, functions, tagged objects.
+//
+// At most one of Value() or ReflectType() may return non-nil.
+//
+type Label struct {
+	obj        *object    // the addressable memory location containing this label
+	subelement *fieldInfo // subelement path within obj, e.g. ".a.b[*].c"
+}
+
+// Value returns the ssa.Value that allocated this label's object, if any.
+func (l Label) Value() ssa.Value {
+	val, _ := l.obj.data.(ssa.Value)
+	return val
+}
+
+// ReflectType returns the type represented by this label if it is an
+// reflect.rtype instance object or *reflect.rtype-tagged object.
+//
+func (l Label) ReflectType() types.Type {
+	rtype, _ := l.obj.data.(types.Type)
+	return rtype
+}
+
+// Path returns the path to the subelement of the object containing
+// this label.  For example, ".x[*].y".
+//
+func (l Label) Path() string {
+	return l.subelement.path()
+}
+
+// Pos returns the position of this label, if known, zero otherwise.
+func (l Label) Pos() token.Pos {
+	switch data := l.obj.data.(type) {
+	case ssa.Value:
+		return data.Pos()
+	case types.Type:
+		if nt, ok := deref(data).(*types.Named); ok {
+			return nt.Obj().Pos()
+		}
+	}
+	if cgn := l.obj.cgn; cgn != nil {
+		return cgn.fn.Pos()
+	}
+	return token.NoPos
+}
+
+// String returns the printed form of this label.
+//
+// Examples:                                    Object type:
+//      x                                       (a variable)
+//      (sync.Mutex).Lock                       (a function)
+//      convert                                 (array created by conversion)
+//      makemap                                 (map allocated via make)
+//      makechan                                (channel allocated via make)
+//      makeinterface                           (tagged object allocated by makeinterface)
+//      <alloc in reflect.Zero>                 (allocation in instrinsic)
+//      sync.Mutex                              (a reflect.rtype instance)
+//      <command-line arguments>                (an intrinsic object)
+//
+// Labels within compound objects have subelement paths:
+//      x.y[*].z                                (a struct variable, x)
+//      append.y[*].z                           (array allocated by append)
+//      makeslice.y[*].z                        (array allocated via make)
+//
+// TODO(adonovan): expose func LabelString(*types.Package, Label).
+//
+func (l Label) String() string {
+	var s string
+	switch v := l.obj.data.(type) {
+	case types.Type:
+		return v.String()
+
+	case string:
+		s = v // an intrinsic object (e.g. os.Args[*])
+
+	case nil:
+		if l.obj.cgn != nil {
+			// allocation by intrinsic or reflective operation
+			s = fmt.Sprintf("<alloc in %s>", l.obj.cgn.fn)
+		} else {
+			s = "<unknown>" // should be unreachable
+		}
+
+	case *ssa.Function:
+		s = v.String()
+
+	case *ssa.Global:
+		s = v.String()
+
+	case *ssa.Const:
+		s = v.Name()
+
+	case *ssa.Alloc:
+		s = v.Comment
+		if s == "" {
+			s = "alloc"
+		}
+
+	case *ssa.Call:
+		// Currently only calls to append can allocate objects.
+		if v.Call.Value.(*ssa.Builtin).Object().Name() != "append" {
+			panic("unhandled *ssa.Call label: " + v.Name())
+		}
+		s = "append"
+
+	case *ssa.MakeMap, *ssa.MakeChan, *ssa.MakeSlice, *ssa.Convert:
+		s = strings.ToLower(strings.TrimPrefix(fmt.Sprintf("%T", v), "*ssa."))
+
+	case *ssa.MakeInterface:
+		// MakeInterface is usually implicit in Go source (so
+		// Pos()==0), and tagged objects may be allocated
+		// synthetically (so no *MakeInterface data).
+		s = "makeinterface:" + v.X.Type().String()
+
+	default:
+		panic(fmt.Sprintf("unhandled object data type: %T", v))
+	}
+
+	return s + l.subelement.path()
+}
diff --git a/go/src/golang.org/x/tools/go/pointer/pointer14_test.go b/go/src/golang.org/x/tools/go/pointer/pointer14_test.go
new file mode 100644
index 0000000..2bcdd56
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/pointer/pointer14_test.go
@@ -0,0 +1,578 @@
+// 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.
+
+// +build !go1.5
+
+// No testdata on Android.
+
+// +build !android
+
+package pointer_test
+
+// This test uses 'expectation' comments embedded within testdata/*.go
+// files to specify the expected pointer analysis behaviour.
+// See below for grammar.
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"go/token"
+	"io/ioutil"
+	"os"
+	"regexp"
+	"strconv"
+	"strings"
+	"testing"
+
+	"golang.org/x/tools/go/callgraph"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/pointer"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/ssa/ssautil"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/go/types/typeutil"
+)
+
+var inputs = []string{
+	"testdata/a_test.go",
+	"testdata/another.go",
+	"testdata/arrayreflect.go",
+	"testdata/arrays.go",
+	"testdata/channels.go",
+	"testdata/chanreflect.go",
+	"testdata/context.go",
+	"testdata/conv.go",
+	"testdata/finalizer.go",
+	"testdata/flow.go",
+	"testdata/fmtexcerpt.go",
+	"testdata/func.go",
+	"testdata/funcreflect.go",
+	"testdata/hello.go", // NB: causes spurious failure of HVN cross-check
+	"testdata/interfaces.go",
+	"testdata/issue9002.go",
+	"testdata/mapreflect.go",
+	"testdata/maps.go",
+	"testdata/panic.go",
+	"testdata/recur.go",
+	"testdata/reflect.go",
+	"testdata/rtti.go",
+	"testdata/structreflect.go",
+	"testdata/structs.go",
+	"testdata/timer.go",
+}
+
+// Expectation grammar:
+//
+// @calls f -> g
+//
+//   A 'calls' expectation asserts that edge (f, g) appears in the
+//   callgraph.  f and g are notated as per Function.String(), which
+//   may contain spaces (e.g. promoted method in anon struct).
+//
+// @pointsto a | b | c
+//
+//   A 'pointsto' expectation asserts that the points-to set of its
+//   operand contains exactly the set of labels {a,b,c} notated as per
+//   labelString.
+//
+//   A 'pointsto' expectation must appear on the same line as a
+//   print(x) statement; the expectation's operand is x.
+//
+//   If one of the strings is "...", the expectation asserts that the
+//   points-to set at least the other labels.
+//
+//   We use '|' because label names may contain spaces, e.g.  methods
+//   of anonymous structs.
+//
+//   From a theoretical perspective, concrete types in interfaces are
+//   labels too, but they are represented differently and so have a
+//   different expectation, @types, below.
+//
+// @types t | u | v
+//
+//   A 'types' expectation asserts that the set of possible dynamic
+//   types of its interface operand is exactly {t,u,v}, notated per
+//   go/types.Type.String(). In other words, it asserts that the type
+//   component of the interface may point to that set of concrete type
+//   literals.  It also works for reflect.Value, though the types
+//   needn't be concrete in that case.
+//
+//   A 'types' expectation must appear on the same line as a
+//   print(x) statement; the expectation's operand is x.
+//
+//   If one of the strings is "...", the expectation asserts that the
+//   interface's type may point to at least the other types.
+//
+//   We use '|' because type names may contain spaces.
+//
+// @warning "regexp"
+//
+//   A 'warning' expectation asserts that the analysis issues a
+//   warning that matches the regular expression within the string
+//   literal.
+//
+// @line id
+//
+//   A line directive associates the name "id" with the current
+//   file:line.  The string form of labels will use this id instead of
+//   a file:line, making @pointsto expectations more robust against
+//   perturbations in the source file.
+//   (NB, anon functions still include line numbers.)
+//
+type expectation struct {
+	kind     string // "pointsto" | "types" | "calls" | "warning"
+	filename string
+	linenum  int // source line number, 1-based
+	args     []string
+	types    []types.Type // for types
+}
+
+func (e *expectation) String() string {
+	return fmt.Sprintf("@%s[%s]", e.kind, strings.Join(e.args, " | "))
+}
+
+func (e *expectation) errorf(format string, args ...interface{}) {
+	fmt.Printf("%s:%d: ", e.filename, e.linenum)
+	fmt.Printf(format, args...)
+	fmt.Println()
+}
+
+func (e *expectation) needsProbe() bool {
+	return e.kind == "pointsto" || e.kind == "types"
+}
+
+// Find probe (call to print(x)) of same source file/line as expectation.
+func findProbe(prog *ssa.Program, probes map[*ssa.CallCommon]bool, queries map[ssa.Value]pointer.Pointer, e *expectation) (site *ssa.CallCommon, pts pointer.PointsToSet) {
+	for call := range probes {
+		pos := prog.Fset.Position(call.Pos())
+		if pos.Line == e.linenum && pos.Filename == e.filename {
+			// TODO(adonovan): send this to test log (display only on failure).
+			// fmt.Printf("%s:%d: info: found probe for %s: %s\n",
+			// 	e.filename, e.linenum, e, p.arg0) // debugging
+			return call, queries[call.Args[0]].PointsTo()
+		}
+	}
+	return // e.g. analysis didn't reach this call
+}
+
+func doOneInput(input, filename string) bool {
+	var conf loader.Config
+
+	// Parsing.
+	f, err := conf.ParseFile(filename, input)
+	if err != nil {
+		fmt.Println(err)
+		return false
+	}
+
+	// Create single-file main package and import its dependencies.
+	conf.CreateFromFiles("main", f)
+	iprog, err := conf.Load()
+	if err != nil {
+		fmt.Println(err)
+		return false
+	}
+	mainPkgInfo := iprog.Created[0].Pkg
+
+	// SSA creation + building.
+	prog := ssautil.CreateProgram(iprog, ssa.SanityCheckFunctions)
+	prog.Build()
+
+	mainpkg := prog.Package(mainPkgInfo)
+	ptrmain := mainpkg // main package for the pointer analysis
+	if mainpkg.Func("main") == nil {
+		// No main function; assume it's a test.
+		ptrmain = prog.CreateTestMainPackage(mainpkg)
+	}
+
+	// Find all calls to the built-in print(x).  Analytically,
+	// print is a no-op, but it's a convenient hook for testing
+	// the PTS of an expression, so our tests use it.
+	probes := make(map[*ssa.CallCommon]bool)
+	for fn := range ssautil.AllFunctions(prog) {
+		if fn.Pkg == mainpkg {
+			for _, b := range fn.Blocks {
+				for _, instr := range b.Instrs {
+					if instr, ok := instr.(ssa.CallInstruction); ok {
+						call := instr.Common()
+						if b, ok := call.Value.(*ssa.Builtin); ok && b.Name() == "print" && len(call.Args) == 1 {
+							probes[instr.Common()] = true
+						}
+					}
+				}
+			}
+		}
+	}
+
+	ok := true
+
+	lineMapping := make(map[string]string) // maps "file:line" to @line tag
+
+	// Parse expectations in this input.
+	var exps []*expectation
+	re := regexp.MustCompile("// *@([a-z]*) *(.*)$")
+	lines := strings.Split(input, "\n")
+	for linenum, line := range lines {
+		linenum++ // make it 1-based
+		if matches := re.FindAllStringSubmatch(line, -1); matches != nil {
+			match := matches[0]
+			kind, rest := match[1], match[2]
+			e := &expectation{kind: kind, filename: filename, linenum: linenum}
+
+			if kind == "line" {
+				if rest == "" {
+					ok = false
+					e.errorf("@%s expectation requires identifier", kind)
+				} else {
+					lineMapping[fmt.Sprintf("%s:%d", filename, linenum)] = rest
+				}
+				continue
+			}
+
+			if e.needsProbe() && !strings.Contains(line, "print(") {
+				ok = false
+				e.errorf("@%s expectation must follow call to print(x)", kind)
+				continue
+			}
+
+			switch kind {
+			case "pointsto":
+				e.args = split(rest, "|")
+
+			case "types":
+				for _, typstr := range split(rest, "|") {
+					var t types.Type = types.Typ[types.Invalid] // means "..."
+					if typstr != "..." {
+						tv, err := types.Eval(prog.Fset, mainpkg.Pkg, f.Pos(), typstr)
+						if err != nil {
+							ok = false
+							// Don't print err since its location is bad.
+							e.errorf("'%s' is not a valid type: %s", typstr, err)
+							continue
+						}
+						t = tv.Type
+					}
+					e.types = append(e.types, t)
+				}
+
+			case "calls":
+				e.args = split(rest, "->")
+				// TODO(adonovan): eagerly reject the
+				// expectation if fn doesn't denote
+				// existing function, rather than fail
+				// the expectation after analysis.
+				if len(e.args) != 2 {
+					ok = false
+					e.errorf("@calls expectation wants 'caller -> callee' arguments")
+					continue
+				}
+
+			case "warning":
+				lit, err := strconv.Unquote(strings.TrimSpace(rest))
+				if err != nil {
+					ok = false
+					e.errorf("couldn't parse @warning operand: %s", err.Error())
+					continue
+				}
+				e.args = append(e.args, lit)
+
+			default:
+				ok = false
+				e.errorf("unknown expectation kind: %s", e)
+				continue
+			}
+			exps = append(exps, e)
+		}
+	}
+
+	var log bytes.Buffer
+	fmt.Fprintf(&log, "Input: %s\n", filename)
+
+	// Run the analysis.
+	config := &pointer.Config{
+		Reflection:     true,
+		BuildCallGraph: true,
+		Mains:          []*ssa.Package{ptrmain},
+		Log:            &log,
+	}
+	for probe := range probes {
+		v := probe.Args[0]
+		if pointer.CanPoint(v.Type()) {
+			config.AddQuery(v)
+		}
+	}
+
+	// Print the log is there was an error or a panic.
+	complete := false
+	defer func() {
+		if !complete || !ok {
+			log.WriteTo(os.Stderr)
+		}
+	}()
+
+	result, err := pointer.Analyze(config)
+	if err != nil {
+		panic(err) // internal error in pointer analysis
+	}
+
+	// Check the expectations.
+	for _, e := range exps {
+		var call *ssa.CallCommon
+		var pts pointer.PointsToSet
+		var tProbe types.Type
+		if e.needsProbe() {
+			if call, pts = findProbe(prog, probes, result.Queries, e); call == nil {
+				ok = false
+				e.errorf("unreachable print() statement has expectation %s", e)
+				continue
+			}
+			tProbe = call.Args[0].Type()
+			if !pointer.CanPoint(tProbe) {
+				ok = false
+				e.errorf("expectation on non-pointerlike operand: %s", tProbe)
+				continue
+			}
+		}
+
+		switch e.kind {
+		case "pointsto":
+			if !checkPointsToExpectation(e, pts, lineMapping, prog) {
+				ok = false
+			}
+
+		case "types":
+			if !checkTypesExpectation(e, pts, tProbe) {
+				ok = false
+			}
+
+		case "calls":
+			if !checkCallsExpectation(prog, e, result.CallGraph) {
+				ok = false
+			}
+
+		case "warning":
+			if !checkWarningExpectation(prog, e, result.Warnings) {
+				ok = false
+			}
+		}
+	}
+
+	complete = true
+
+	// ok = false // debugging: uncomment to always see log
+
+	return ok
+}
+
+func labelString(l *pointer.Label, lineMapping map[string]string, prog *ssa.Program) string {
+	// Functions and Globals need no pos suffix,
+	// nor do allocations in intrinsic operations
+	// (for which we'll print the function name).
+	switch l.Value().(type) {
+	case nil, *ssa.Function, *ssa.Global:
+		return l.String()
+	}
+
+	str := l.String()
+	if pos := l.Pos(); pos != token.NoPos {
+		// Append the position, using a @line tag instead of a line number, if defined.
+		posn := prog.Fset.Position(pos)
+		s := fmt.Sprintf("%s:%d", posn.Filename, posn.Line)
+		if tag, ok := lineMapping[s]; ok {
+			return fmt.Sprintf("%s@%s:%d", str, tag, posn.Column)
+		}
+		str = fmt.Sprintf("%s@%s", str, posn)
+	}
+	return str
+}
+
+func checkPointsToExpectation(e *expectation, pts pointer.PointsToSet, lineMapping map[string]string, prog *ssa.Program) bool {
+	expected := make(map[string]int)
+	surplus := make(map[string]int)
+	exact := true
+	for _, g := range e.args {
+		if g == "..." {
+			exact = false
+			continue
+		}
+		expected[g]++
+	}
+	// Find the set of labels that the probe's
+	// argument (x in print(x)) may point to.
+	for _, label := range pts.Labels() {
+		name := labelString(label, lineMapping, prog)
+		if expected[name] > 0 {
+			expected[name]--
+		} else if exact {
+			surplus[name]++
+		}
+	}
+	// Report multiset difference:
+	ok := true
+	for _, count := range expected {
+		if count > 0 {
+			ok = false
+			e.errorf("value does not alias these expected labels: %s", join(expected))
+			break
+		}
+	}
+	for _, count := range surplus {
+		if count > 0 {
+			ok = false
+			e.errorf("value may additionally alias these labels: %s", join(surplus))
+			break
+		}
+	}
+	return ok
+}
+
+func checkTypesExpectation(e *expectation, pts pointer.PointsToSet, typ types.Type) bool {
+	var expected typeutil.Map
+	var surplus typeutil.Map
+	exact := true
+	for _, g := range e.types {
+		if g == types.Typ[types.Invalid] {
+			exact = false
+			continue
+		}
+		expected.Set(g, struct{}{})
+	}
+
+	if !pointer.CanHaveDynamicTypes(typ) {
+		e.errorf("@types expectation requires an interface- or reflect.Value-typed operand, got %s", typ)
+		return false
+	}
+
+	// Find the set of types that the probe's
+	// argument (x in print(x)) may contain.
+	for _, T := range pts.DynamicTypes().Keys() {
+		if expected.At(T) != nil {
+			expected.Delete(T)
+		} else if exact {
+			surplus.Set(T, struct{}{})
+		}
+	}
+	// Report set difference:
+	ok := true
+	if expected.Len() > 0 {
+		ok = false
+		e.errorf("interface cannot contain these types: %s", expected.KeysString())
+	}
+	if surplus.Len() > 0 {
+		ok = false
+		e.errorf("interface may additionally contain these types: %s", surplus.KeysString())
+	}
+	return ok
+}
+
+var errOK = errors.New("OK")
+
+func checkCallsExpectation(prog *ssa.Program, e *expectation, cg *callgraph.Graph) bool {
+	found := make(map[string]int)
+	err := callgraph.GraphVisitEdges(cg, func(edge *callgraph.Edge) error {
+		// Name-based matching is inefficient but it allows us to
+		// match functions whose names that would not appear in an
+		// index ("<root>") or which are not unique ("func@1.2").
+		if edge.Caller.Func.String() == e.args[0] {
+			calleeStr := edge.Callee.Func.String()
+			if calleeStr == e.args[1] {
+				return errOK // expectation satisified; stop the search
+			}
+			found[calleeStr]++
+		}
+		return nil
+	})
+	if err == errOK {
+		return true
+	}
+	if len(found) == 0 {
+		e.errorf("didn't find any calls from %s", e.args[0])
+	}
+	e.errorf("found no call from %s to %s, but only to %s",
+		e.args[0], e.args[1], join(found))
+	return false
+}
+
+func checkWarningExpectation(prog *ssa.Program, e *expectation, warnings []pointer.Warning) bool {
+	// TODO(adonovan): check the position part of the warning too?
+	re, err := regexp.Compile(e.args[0])
+	if err != nil {
+		e.errorf("invalid regular expression in @warning expectation: %s", err.Error())
+		return false
+	}
+
+	if len(warnings) == 0 {
+		e.errorf("@warning %s expectation, but no warnings", strconv.Quote(e.args[0]))
+		return false
+	}
+
+	for _, w := range warnings {
+		if re.MatchString(w.Message) {
+			return true
+		}
+	}
+
+	e.errorf("@warning %s expectation not satised; found these warnings though:", strconv.Quote(e.args[0]))
+	for _, w := range warnings {
+		fmt.Printf("%s: warning: %s\n", prog.Fset.Position(w.Pos), w.Message)
+	}
+	return false
+}
+
+func TestInput(t *testing.T) {
+	ok := true
+
+	wd, err := os.Getwd()
+	if err != nil {
+		t.Errorf("os.Getwd: %s", err)
+		return
+	}
+
+	// 'go test' does a chdir so that relative paths in
+	// diagnostics no longer make sense relative to the invoking
+	// shell's cwd.  We print a special marker so that Emacs can
+	// make sense of them.
+	fmt.Fprintf(os.Stderr, "Entering directory `%s'\n", wd)
+
+	for _, filename := range inputs {
+		content, err := ioutil.ReadFile(filename)
+		if err != nil {
+			t.Errorf("couldn't read file '%s': %s", filename, err)
+			continue
+		}
+
+		if !doOneInput(string(content), filename) {
+			ok = false
+		}
+	}
+	if !ok {
+		t.Fail()
+	}
+}
+
+// join joins the elements of multiset with " | "s.
+func join(set map[string]int) string {
+	var buf bytes.Buffer
+	sep := ""
+	for name, count := range set {
+		for i := 0; i < count; i++ {
+			buf.WriteString(sep)
+			sep = " | "
+			buf.WriteString(name)
+		}
+	}
+	return buf.String()
+}
+
+// split returns the list of sep-delimited non-empty strings in s.
+func split(s, sep string) (r []string) {
+	for _, elem := range strings.Split(s, sep) {
+		elem = strings.TrimSpace(elem)
+		if elem != "" {
+			r = append(r, elem)
+		}
+	}
+	return
+}
diff --git a/go/src/golang.org/x/tools/go/pointer/pointer_test.go b/go/src/golang.org/x/tools/go/pointer/pointer_test.go
index 2744d4f..7cb16d7 100644
--- a/go/src/golang.org/x/tools/go/pointer/pointer_test.go
+++ b/go/src/golang.org/x/tools/go/pointer/pointer_test.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 // No testdata on Android.
 
 // +build !android
@@ -17,6 +19,7 @@
 	"errors"
 	"fmt"
 	"go/token"
+	"go/types"
 	"io/ioutil"
 	"os"
 	"regexp"
@@ -29,7 +32,6 @@
 	"golang.org/x/tools/go/pointer"
 	"golang.org/x/tools/go/ssa"
 	"golang.org/x/tools/go/ssa/ssautil"
-	"golang.org/x/tools/go/types"
 	"golang.org/x/tools/go/types/typeutil"
 )
 
@@ -176,7 +178,7 @@
 
 	// SSA creation + building.
 	prog := ssautil.CreateProgram(iprog, ssa.SanityCheckFunctions)
-	prog.BuildAll()
+	prog.Build()
 
 	mainpkg := prog.Package(mainPkgInfo)
 	ptrmain := mainpkg // main package for the pointer analysis
@@ -243,7 +245,7 @@
 				for _, typstr := range split(rest, "|") {
 					var t types.Type = types.Typ[types.Invalid] // means "..."
 					if typstr != "..." {
-						tv, err := types.Eval(prog.Fset, mainpkg.Object, f.Pos(), typstr)
+						tv, err := types.Eval(prog.Fset, mainpkg.Pkg, f.Pos(), typstr)
 						if err != nil {
 							ok = false
 							// Don't print err since its location is bad.
@@ -520,6 +522,9 @@
 }
 
 func TestInput(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping in short mode; this test requires tons of memory; golang.org/issue/14113")
+	}
 	ok := true
 
 	wd, err := os.Getwd()
diff --git a/go/src/golang.org/x/tools/go/pointer/reflect.go b/go/src/golang.org/x/tools/go/pointer/reflect.go
index 466995c..bdb22cf 100644
--- a/go/src/golang.org/x/tools/go/pointer/reflect.go
+++ b/go/src/golang.org/x/tools/go/pointer/reflect.go
@@ -1,3 +1,9 @@
+// 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.
+
+// +build go1.5
+
 package pointer
 
 // This file implements the generation and resolution rules for
@@ -26,11 +32,11 @@
 
 import (
 	"fmt"
+	exact "go/constant"
+	"go/types"
 	"reflect"
 
-	"golang.org/x/tools/go/exact"
 	"golang.org/x/tools/go/ssa"
-	"golang.org/x/tools/go/types"
 )
 
 func init() {
@@ -1879,7 +1885,7 @@
 				if isIface {
 					sig = sel.Type().(*types.Signature)
 				} else {
-					fn = a.prog.Method(sel)
+					fn = a.prog.MethodValue(sel)
 					// move receiver to params[0]
 					sig = changeRecv(fn.Signature)
 				}
diff --git a/go/src/golang.org/x/tools/go/pointer/reflect14.go b/go/src/golang.org/x/tools/go/pointer/reflect14.go
new file mode 100644
index 0000000..c55f69e
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/pointer/reflect14.go
@@ -0,0 +1,1977 @@
+// 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.
+
+// +build !go1.5
+
+package pointer
+
+// This file implements the generation and resolution rules for
+// constraints arising from the use of reflection in the target
+// program.  See doc.go for explanation of the representation.
+//
+// For consistency, the names of all parameters match those of the
+// actual functions in the "reflect" package.
+//
+// To avoid proliferation of equivalent labels, intrinsics should
+// memoize as much as possible, like TypeOf and Zero do for their
+// tagged objects.
+//
+// TODO(adonovan): this file is rather subtle.  Explain how we derive
+// the implementation of each reflect operator from its spec,
+// including the subtleties of reflect.flag{Addr,RO,Indir}.
+// [Hint: our implementation is as if reflect.flagIndir was always
+// true, i.e. reflect.Values are pointers to tagged objects, there is
+// no inline allocation optimization; and indirect tagged objects (not
+// yet implemented) correspond to reflect.Values with
+// reflect.flagAddr.]
+// A picture would help too.
+//
+// TODO(adonovan): try factoring up the common parts of the majority of
+// these constraints that are single input, single output.
+
+import (
+	"fmt"
+	"reflect"
+
+	"golang.org/x/tools/go/exact"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/types"
+)
+
+func init() {
+	for name, fn := range map[string]intrinsic{
+		// reflect.Value methods.
+		"(reflect.Value).Addr":            extÛ°reflectÛ°ValueÛ°Addr,
+		"(reflect.Value).Bool":            extÛ°NoEffect,
+		"(reflect.Value).Bytes":           extÛ°reflectÛ°ValueÛ°Bytes,
+		"(reflect.Value).Call":            extÛ°reflectÛ°ValueÛ°Call,
+		"(reflect.Value).CallSlice":       extÛ°reflectÛ°ValueÛ°CallSlice,
+		"(reflect.Value).CanAddr":         extÛ°NoEffect,
+		"(reflect.Value).CanInterface":    extÛ°NoEffect,
+		"(reflect.Value).CanSet":          extÛ°NoEffect,
+		"(reflect.Value).Cap":             extÛ°NoEffect,
+		"(reflect.Value).Close":           extÛ°NoEffect,
+		"(reflect.Value).Complex":         extÛ°NoEffect,
+		"(reflect.Value).Convert":         extÛ°reflectÛ°ValueÛ°Convert,
+		"(reflect.Value).Elem":            extÛ°reflectÛ°ValueÛ°Elem,
+		"(reflect.Value).Field":           extÛ°reflectÛ°ValueÛ°Field,
+		"(reflect.Value).FieldByIndex":    extÛ°reflectÛ°ValueÛ°FieldByIndex,
+		"(reflect.Value).FieldByName":     extÛ°reflectÛ°ValueÛ°FieldByName,
+		"(reflect.Value).FieldByNameFunc": extÛ°reflectÛ°ValueÛ°FieldByNameFunc,
+		"(reflect.Value).Float":           extÛ°NoEffect,
+		"(reflect.Value).Index":           extÛ°reflectÛ°ValueÛ°Index,
+		"(reflect.Value).Int":             extÛ°NoEffect,
+		"(reflect.Value).Interface":       extÛ°reflectÛ°ValueÛ°Interface,
+		"(reflect.Value).InterfaceData":   extÛ°NoEffect,
+		"(reflect.Value).IsNil":           extÛ°NoEffect,
+		"(reflect.Value).IsValid":         extÛ°NoEffect,
+		"(reflect.Value).Kind":            extÛ°NoEffect,
+		"(reflect.Value).Len":             extÛ°NoEffect,
+		"(reflect.Value).MapIndex":        extÛ°reflectÛ°ValueÛ°MapIndex,
+		"(reflect.Value).MapKeys":         extÛ°reflectÛ°ValueÛ°MapKeys,
+		"(reflect.Value).Method":          extÛ°reflectÛ°ValueÛ°Method,
+		"(reflect.Value).MethodByName":    extÛ°reflectÛ°ValueÛ°MethodByName,
+		"(reflect.Value).NumField":        extÛ°NoEffect,
+		"(reflect.Value).NumMethod":       extÛ°NoEffect,
+		"(reflect.Value).OverflowComplex": extÛ°NoEffect,
+		"(reflect.Value).OverflowFloat":   extÛ°NoEffect,
+		"(reflect.Value).OverflowInt":     extÛ°NoEffect,
+		"(reflect.Value).OverflowUint":    extÛ°NoEffect,
+		"(reflect.Value).Pointer":         extÛ°NoEffect,
+		"(reflect.Value).Recv":            extÛ°reflectÛ°ValueÛ°Recv,
+		"(reflect.Value).Send":            extÛ°reflectÛ°ValueÛ°Send,
+		"(reflect.Value).Set":             extÛ°reflectÛ°ValueÛ°Set,
+		"(reflect.Value).SetBool":         extÛ°NoEffect,
+		"(reflect.Value).SetBytes":        extÛ°reflectÛ°ValueÛ°SetBytes,
+		"(reflect.Value).SetComplex":      extÛ°NoEffect,
+		"(reflect.Value).SetFloat":        extÛ°NoEffect,
+		"(reflect.Value).SetInt":          extÛ°NoEffect,
+		"(reflect.Value).SetLen":          extÛ°NoEffect,
+		"(reflect.Value).SetMapIndex":     extÛ°reflectÛ°ValueÛ°SetMapIndex,
+		"(reflect.Value).SetPointer":      extÛ°reflectÛ°ValueÛ°SetPointer,
+		"(reflect.Value).SetString":       extÛ°NoEffect,
+		"(reflect.Value).SetUint":         extÛ°NoEffect,
+		"(reflect.Value).Slice":           extÛ°reflectÛ°ValueÛ°Slice,
+		"(reflect.Value).String":          extÛ°NoEffect,
+		"(reflect.Value).TryRecv":         extÛ°reflectÛ°ValueÛ°Recv,
+		"(reflect.Value).TrySend":         extÛ°reflectÛ°ValueÛ°Send,
+		"(reflect.Value).Type":            extÛ°NoEffect,
+		"(reflect.Value).Uint":            extÛ°NoEffect,
+		"(reflect.Value).UnsafeAddr":      extÛ°NoEffect,
+
+		// Standalone reflect.* functions.
+		"reflect.Append":      extÛ°reflectÛ°Append,
+		"reflect.AppendSlice": extÛ°reflectÛ°AppendSlice,
+		"reflect.Copy":        extÛ°reflectÛ°Copy,
+		"reflect.ChanOf":      extÛ°reflectÛ°ChanOf,
+		"reflect.DeepEqual":   extÛ°NoEffect,
+		"reflect.Indirect":    extÛ°reflectÛ°Indirect,
+		"reflect.MakeChan":    extÛ°reflectÛ°MakeChan,
+		"reflect.MakeFunc":    extÛ°reflectÛ°MakeFunc,
+		"reflect.MakeMap":     extÛ°reflectÛ°MakeMap,
+		"reflect.MakeSlice":   extÛ°reflectÛ°MakeSlice,
+		"reflect.MapOf":       extÛ°reflectÛ°MapOf,
+		"reflect.New":         extÛ°reflectÛ°New,
+		"reflect.NewAt":       extÛ°reflectÛ°NewAt,
+		"reflect.PtrTo":       extÛ°reflectÛ°PtrTo,
+		"reflect.Select":      extÛ°reflectÛ°Select,
+		"reflect.SliceOf":     extÛ°reflectÛ°SliceOf,
+		"reflect.TypeOf":      extÛ°reflectÛ°TypeOf,
+		"reflect.ValueOf":     extÛ°reflectÛ°ValueOf,
+		"reflect.Zero":        extÛ°reflectÛ°Zero,
+		"reflect.init":        extÛ°NoEffect,
+
+		// *reflect.rtype methods
+		"(*reflect.rtype).Align":           extÛ°NoEffect,
+		"(*reflect.rtype).AssignableTo":    extÛ°NoEffect,
+		"(*reflect.rtype).Bits":            extÛ°NoEffect,
+		"(*reflect.rtype).ChanDir":         extÛ°NoEffect,
+		"(*reflect.rtype).ConvertibleTo":   extÛ°NoEffect,
+		"(*reflect.rtype).Elem":            extÛ°reflectÛ°rtypeÛ°Elem,
+		"(*reflect.rtype).Field":           extÛ°reflectÛ°rtypeÛ°Field,
+		"(*reflect.rtype).FieldAlign":      extÛ°NoEffect,
+		"(*reflect.rtype).FieldByIndex":    extÛ°reflectÛ°rtypeÛ°FieldByIndex,
+		"(*reflect.rtype).FieldByName":     extÛ°reflectÛ°rtypeÛ°FieldByName,
+		"(*reflect.rtype).FieldByNameFunc": extÛ°reflectÛ°rtypeÛ°FieldByNameFunc,
+		"(*reflect.rtype).Implements":      extÛ°NoEffect,
+		"(*reflect.rtype).In":              extÛ°reflectÛ°rtypeÛ°In,
+		"(*reflect.rtype).IsVariadic":      extÛ°NoEffect,
+		"(*reflect.rtype).Key":             extÛ°reflectÛ°rtypeÛ°Key,
+		"(*reflect.rtype).Kind":            extÛ°NoEffect,
+		"(*reflect.rtype).Len":             extÛ°NoEffect,
+		"(*reflect.rtype).Method":          extÛ°reflectÛ°rtypeÛ°Method,
+		"(*reflect.rtype).MethodByName":    extÛ°reflectÛ°rtypeÛ°MethodByName,
+		"(*reflect.rtype).Name":            extÛ°NoEffect,
+		"(*reflect.rtype).NumField":        extÛ°NoEffect,
+		"(*reflect.rtype).NumIn":           extÛ°NoEffect,
+		"(*reflect.rtype).NumMethod":       extÛ°NoEffect,
+		"(*reflect.rtype).NumOut":          extÛ°NoEffect,
+		"(*reflect.rtype).Out":             extÛ°reflectÛ°rtypeÛ°Out,
+		"(*reflect.rtype).PkgPath":         extÛ°NoEffect,
+		"(*reflect.rtype).Size":            extÛ°NoEffect,
+		"(*reflect.rtype).String":          extÛ°NoEffect,
+	} {
+		intrinsicsByName[name] = fn
+	}
+}
+
+// -------------------- (reflect.Value) --------------------
+
+func extÛ°reflectÛ°ValueÛ°Addr(a *analysis, cgn *cgnode) {} // TODO(adonovan)
+
+// ---------- func (Value).Bytes() Value ----------
+
+// result = v.Bytes()
+type rVBytesConstraint struct {
+	v      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rVBytesConstraint) ptr() nodeid { return c.v }
+func (c *rVBytesConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "rVBytes.result")
+}
+func (c *rVBytesConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.result = mapping[c.result]
+}
+
+func (c *rVBytesConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect n%d.Bytes()", c.result, c.v)
+}
+
+func (c *rVBytesConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, slice, indirect := a.taggedValue(vObj)
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		tSlice, ok := tDyn.Underlying().(*types.Slice)
+		if ok && types.Identical(tSlice.Elem(), types.Typ[types.Uint8]) {
+			if a.onlineCopy(c.result, slice) {
+				changed = true
+			}
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func extÛ°reflectÛ°ValueÛ°Bytes(a *analysis, cgn *cgnode) {
+	a.addConstraint(&rVBytesConstraint{
+		v:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// ---------- func (Value).Call(in []Value) []Value ----------
+
+// result = v.Call(in)
+type rVCallConstraint struct {
+	cgn       *cgnode
+	targets   nodeid // (indirect)
+	v         nodeid // (ptr)
+	arg       nodeid // = in[*]
+	result    nodeid // (indirect)
+	dotdotdot bool   // interpret last arg as a "..." slice
+}
+
+func (c *rVCallConstraint) ptr() nodeid { return c.v }
+func (c *rVCallConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.targets), "rVCall.targets")
+	h.markIndirect(onodeid(c.result), "rVCall.result")
+}
+func (c *rVCallConstraint) renumber(mapping []nodeid) {
+	c.targets = mapping[c.targets]
+	c.v = mapping[c.v]
+	c.arg = mapping[c.arg]
+	c.result = mapping[c.result]
+}
+
+func (c *rVCallConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect n%d.Call(n%d)", c.result, c.v, c.arg)
+}
+
+func (c *rVCallConstraint) solve(a *analysis, delta *nodeset) {
+	if c.targets == 0 {
+		panic("no targets")
+	}
+
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, fn, indirect := a.taggedValue(vObj)
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		tSig, ok := tDyn.Underlying().(*types.Signature)
+		if !ok {
+			continue // not a function
+		}
+		if tSig.Recv() != nil {
+			panic(tSig) // TODO(adonovan): rethink when we implement Method()
+		}
+
+		// Add dynamic call target.
+		if a.onlineCopy(c.targets, fn) {
+			a.addWork(c.targets)
+			// TODO(adonovan): is 'else continue' a sound optimisation here?
+		}
+
+		// Allocate a P/R block.
+		tParams := tSig.Params()
+		tResults := tSig.Results()
+		params := a.addNodes(tParams, "rVCall.params")
+		results := a.addNodes(tResults, "rVCall.results")
+
+		// Make a dynamic call to 'fn'.
+		a.store(fn, params, 1, a.sizeof(tParams))
+		a.load(results, fn, 1+a.sizeof(tParams), a.sizeof(tResults))
+
+		// Populate P by type-asserting each actual arg (all merged in c.arg).
+		for i, n := 0, tParams.Len(); i < n; i++ {
+			T := tParams.At(i).Type()
+			a.typeAssert(T, params, c.arg, false)
+			params += nodeid(a.sizeof(T))
+		}
+
+		// Use R by tagging and copying each actual result to c.result.
+		for i, n := 0, tResults.Len(); i < n; i++ {
+			T := tResults.At(i).Type()
+			// Convert from an arbitrary type to a reflect.Value
+			// (like MakeInterface followed by reflect.ValueOf).
+			if isInterface(T) {
+				// (don't tag)
+				if a.onlineCopy(c.result, results) {
+					changed = true
+				}
+			} else {
+				obj := a.makeTagged(T, c.cgn, nil)
+				a.onlineCopyN(obj+1, results, a.sizeof(T))
+				if a.addLabel(c.result, obj) { // (true)
+					changed = true
+				}
+			}
+			results += nodeid(a.sizeof(T))
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+// Common code for direct (inlined) and indirect calls to (reflect.Value).Call.
+func reflectCallImpl(a *analysis, cgn *cgnode, site *callsite, recv, arg nodeid, dotdotdot bool) nodeid {
+	// Allocate []reflect.Value array for the result.
+	ret := a.nextNode()
+	a.addNodes(types.NewArray(a.reflectValueObj.Type(), 1), "rVCall.ret")
+	a.endObject(ret, cgn, nil)
+
+	// pts(targets) will be the set of possible call targets.
+	site.targets = a.addOneNode(tInvalid, "rvCall.targets", nil)
+
+	// All arguments are merged since they arrive in a slice.
+	argelts := a.addOneNode(a.reflectValueObj.Type(), "rVCall.args", nil)
+	a.load(argelts, arg, 1, 1) // slice elements
+
+	a.addConstraint(&rVCallConstraint{
+		cgn:       cgn,
+		targets:   site.targets,
+		v:         recv,
+		arg:       argelts,
+		result:    ret + 1, // results go into elements of ret
+		dotdotdot: dotdotdot,
+	})
+	return ret
+}
+
+func reflectCall(a *analysis, cgn *cgnode, dotdotdot bool) {
+	// This is the shared contour implementation of (reflect.Value).Call
+	// and CallSlice, as used by indirect calls (rare).
+	// Direct calls are inlined in gen.go, eliding the
+	// intermediate cgnode for Call.
+	site := new(callsite)
+	cgn.sites = append(cgn.sites, site)
+	recv := a.funcParams(cgn.obj)
+	arg := recv + 1
+	ret := reflectCallImpl(a, cgn, site, recv, arg, dotdotdot)
+	a.addressOf(cgn.fn.Signature.Results().At(0).Type(), a.funcResults(cgn.obj), ret)
+}
+
+func extÛ°reflectÛ°ValueÛ°Call(a *analysis, cgn *cgnode) {
+	reflectCall(a, cgn, false)
+}
+
+func extÛ°reflectÛ°ValueÛ°CallSlice(a *analysis, cgn *cgnode) {
+	// TODO(adonovan): implement.  Also, inline direct calls in gen.go too.
+	if false {
+		reflectCall(a, cgn, true)
+	}
+}
+
+func extÛ°reflectÛ°ValueÛ°Convert(a *analysis, cgn *cgnode) {} // TODO(adonovan)
+
+// ---------- func (Value).Elem() Value ----------
+
+// result = v.Elem()
+type rVElemConstraint struct {
+	cgn    *cgnode
+	v      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rVElemConstraint) ptr() nodeid { return c.v }
+func (c *rVElemConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "rVElem.result")
+}
+func (c *rVElemConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.result = mapping[c.result]
+}
+
+func (c *rVElemConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect n%d.Elem()", c.result, c.v)
+}
+
+func (c *rVElemConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, payload, indirect := a.taggedValue(vObj)
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		switch t := tDyn.Underlying().(type) {
+		case *types.Interface:
+			if a.onlineCopy(c.result, payload) {
+				changed = true
+			}
+
+		case *types.Pointer:
+			obj := a.makeTagged(t.Elem(), c.cgn, nil)
+			a.load(obj+1, payload, 0, a.sizeof(t.Elem()))
+			if a.addLabel(c.result, obj) {
+				changed = true
+			}
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func extÛ°reflectÛ°ValueÛ°Elem(a *analysis, cgn *cgnode) {
+	a.addConstraint(&rVElemConstraint{
+		cgn:    cgn,
+		v:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+func extÛ°reflectÛ°ValueÛ°Field(a *analysis, cgn *cgnode)           {} // TODO(adonovan)
+func extÛ°reflectÛ°ValueÛ°FieldByIndex(a *analysis, cgn *cgnode)    {} // TODO(adonovan)
+func extÛ°reflectÛ°ValueÛ°FieldByName(a *analysis, cgn *cgnode)     {} // TODO(adonovan)
+func extÛ°reflectÛ°ValueÛ°FieldByNameFunc(a *analysis, cgn *cgnode) {} // TODO(adonovan)
+
+// ---------- func (Value).Index() Value ----------
+
+// result = v.Index()
+type rVIndexConstraint struct {
+	cgn    *cgnode
+	v      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rVIndexConstraint) ptr() nodeid { return c.v }
+func (c *rVIndexConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "rVIndex.result")
+}
+func (c *rVIndexConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.result = mapping[c.result]
+}
+
+func (c *rVIndexConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect n%d.Index()", c.result, c.v)
+}
+
+func (c *rVIndexConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, payload, indirect := a.taggedValue(vObj)
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		var res nodeid
+		switch t := tDyn.Underlying().(type) {
+		case *types.Array:
+			res = a.makeTagged(t.Elem(), c.cgn, nil)
+			a.onlineCopyN(res+1, payload+1, a.sizeof(t.Elem()))
+
+		case *types.Slice:
+			res = a.makeTagged(t.Elem(), c.cgn, nil)
+			a.load(res+1, payload, 1, a.sizeof(t.Elem()))
+
+		case *types.Basic:
+			if t.Kind() == types.String {
+				res = a.makeTagged(types.Typ[types.Rune], c.cgn, nil)
+			}
+		}
+		if res != 0 && a.addLabel(c.result, res) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func extÛ°reflectÛ°ValueÛ°Index(a *analysis, cgn *cgnode) {
+	a.addConstraint(&rVIndexConstraint{
+		cgn:    cgn,
+		v:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// ---------- func (Value).Interface() Value ----------
+
+// result = v.Interface()
+type rVInterfaceConstraint struct {
+	v      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rVInterfaceConstraint) ptr() nodeid { return c.v }
+func (c *rVInterfaceConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "rVInterface.result")
+}
+func (c *rVInterfaceConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.result = mapping[c.result]
+}
+
+func (c *rVInterfaceConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect n%d.Interface()", c.result, c.v)
+}
+
+func (c *rVInterfaceConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, payload, indirect := a.taggedValue(vObj)
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		if isInterface(tDyn) {
+			if a.onlineCopy(c.result, payload) {
+				a.addWork(c.result)
+			}
+		} else {
+			if a.addLabel(c.result, vObj) {
+				changed = true
+			}
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func extÛ°reflectÛ°ValueÛ°Interface(a *analysis, cgn *cgnode) {
+	a.addConstraint(&rVInterfaceConstraint{
+		v:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// ---------- func (Value).MapIndex(Value) Value ----------
+
+// result = v.MapIndex(_)
+type rVMapIndexConstraint struct {
+	cgn    *cgnode
+	v      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rVMapIndexConstraint) ptr() nodeid { return c.v }
+func (c *rVMapIndexConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "rVMapIndex.result")
+}
+func (c *rVMapIndexConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.result = mapping[c.result]
+}
+
+func (c *rVMapIndexConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect n%d.MapIndex(_)", c.result, c.v)
+}
+
+func (c *rVMapIndexConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, m, indirect := a.taggedValue(vObj)
+		tMap, _ := tDyn.Underlying().(*types.Map)
+		if tMap == nil {
+			continue // not a map
+		}
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		obj := a.makeTagged(tMap.Elem(), c.cgn, nil)
+		a.load(obj+1, m, a.sizeof(tMap.Key()), a.sizeof(tMap.Elem()))
+		if a.addLabel(c.result, obj) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func extÛ°reflectÛ°ValueÛ°MapIndex(a *analysis, cgn *cgnode) {
+	a.addConstraint(&rVMapIndexConstraint{
+		cgn:    cgn,
+		v:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// ---------- func (Value).MapKeys() []Value ----------
+
+// result = v.MapKeys()
+type rVMapKeysConstraint struct {
+	cgn    *cgnode
+	v      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rVMapKeysConstraint) ptr() nodeid { return c.v }
+func (c *rVMapKeysConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "rVMapKeys.result")
+}
+func (c *rVMapKeysConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.result = mapping[c.result]
+}
+
+func (c *rVMapKeysConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect n%d.MapKeys()", c.result, c.v)
+}
+
+func (c *rVMapKeysConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, m, indirect := a.taggedValue(vObj)
+		tMap, _ := tDyn.Underlying().(*types.Map)
+		if tMap == nil {
+			continue // not a map
+		}
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		kObj := a.makeTagged(tMap.Key(), c.cgn, nil)
+		a.load(kObj+1, m, 0, a.sizeof(tMap.Key()))
+		if a.addLabel(c.result, kObj) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func extÛ°reflectÛ°ValueÛ°MapKeys(a *analysis, cgn *cgnode) {
+	// Allocate an array for the result.
+	obj := a.nextNode()
+	T := types.NewSlice(a.reflectValueObj.Type())
+	a.addNodes(sliceToArray(T), "reflect.MapKeys result")
+	a.endObject(obj, cgn, nil)
+	a.addressOf(T, a.funcResults(cgn.obj), obj)
+
+	a.addConstraint(&rVMapKeysConstraint{
+		cgn:    cgn,
+		v:      a.funcParams(cgn.obj),
+		result: obj + 1, // result is stored in array elems
+	})
+}
+
+func extÛ°reflectÛ°ValueÛ°Method(a *analysis, cgn *cgnode)       {} // TODO(adonovan)
+func extÛ°reflectÛ°ValueÛ°MethodByName(a *analysis, cgn *cgnode) {} // TODO(adonovan)
+
+// ---------- func (Value).Recv(Value) Value ----------
+
+// result, _ = v.Recv()
+type rVRecvConstraint struct {
+	cgn    *cgnode
+	v      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rVRecvConstraint) ptr() nodeid { return c.v }
+func (c *rVRecvConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "rVRecv.result")
+}
+func (c *rVRecvConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.result = mapping[c.result]
+}
+
+func (c *rVRecvConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect n%d.Recv()", c.result, c.v)
+}
+
+func (c *rVRecvConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, ch, indirect := a.taggedValue(vObj)
+		tChan, _ := tDyn.Underlying().(*types.Chan)
+		if tChan == nil {
+			continue // not a channel
+		}
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		tElem := tChan.Elem()
+		elemObj := a.makeTagged(tElem, c.cgn, nil)
+		a.load(elemObj+1, ch, 0, a.sizeof(tElem))
+		if a.addLabel(c.result, elemObj) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func extÛ°reflectÛ°ValueÛ°Recv(a *analysis, cgn *cgnode) {
+	a.addConstraint(&rVRecvConstraint{
+		cgn:    cgn,
+		v:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// ---------- func (Value).Send(Value) ----------
+
+// v.Send(x)
+type rVSendConstraint struct {
+	cgn *cgnode
+	v   nodeid // (ptr)
+	x   nodeid
+}
+
+func (c *rVSendConstraint) ptr() nodeid   { return c.v }
+func (c *rVSendConstraint) presolve(*hvn) {}
+func (c *rVSendConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.x = mapping[c.x]
+}
+
+func (c *rVSendConstraint) String() string {
+	return fmt.Sprintf("reflect n%d.Send(n%d)", c.v, c.x)
+}
+
+func (c *rVSendConstraint) solve(a *analysis, delta *nodeset) {
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, ch, indirect := a.taggedValue(vObj)
+		tChan, _ := tDyn.Underlying().(*types.Chan)
+		if tChan == nil {
+			continue // not a channel
+		}
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		// Extract x's payload to xtmp, then store to channel.
+		tElem := tChan.Elem()
+		xtmp := a.addNodes(tElem, "Send.xtmp")
+		a.typeAssert(tElem, xtmp, c.x, false)
+		a.store(ch, xtmp, 0, a.sizeof(tElem))
+	}
+}
+
+func extÛ°reflectÛ°ValueÛ°Send(a *analysis, cgn *cgnode) {
+	params := a.funcParams(cgn.obj)
+	a.addConstraint(&rVSendConstraint{
+		cgn: cgn,
+		v:   params,
+		x:   params + 1,
+	})
+}
+
+func extÛ°reflectÛ°ValueÛ°Set(a *analysis, cgn *cgnode) {} // TODO(adonovan)
+
+// ---------- func (Value).SetBytes(x []byte) ----------
+
+// v.SetBytes(x)
+type rVSetBytesConstraint struct {
+	cgn *cgnode
+	v   nodeid // (ptr)
+	x   nodeid
+}
+
+func (c *rVSetBytesConstraint) ptr() nodeid   { return c.v }
+func (c *rVSetBytesConstraint) presolve(*hvn) {}
+func (c *rVSetBytesConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.x = mapping[c.x]
+}
+
+func (c *rVSetBytesConstraint) String() string {
+	return fmt.Sprintf("reflect n%d.SetBytes(n%d)", c.v, c.x)
+}
+
+func (c *rVSetBytesConstraint) solve(a *analysis, delta *nodeset) {
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, slice, indirect := a.taggedValue(vObj)
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		tSlice, ok := tDyn.Underlying().(*types.Slice)
+		if ok && types.Identical(tSlice.Elem(), types.Typ[types.Uint8]) {
+			if a.onlineCopy(slice, c.x) {
+				a.addWork(slice)
+			}
+		}
+	}
+}
+
+func extÛ°reflectÛ°ValueÛ°SetBytes(a *analysis, cgn *cgnode) {
+	params := a.funcParams(cgn.obj)
+	a.addConstraint(&rVSetBytesConstraint{
+		cgn: cgn,
+		v:   params,
+		x:   params + 1,
+	})
+}
+
+// ---------- func (Value).SetMapIndex(k Value, v Value) ----------
+
+// v.SetMapIndex(key, val)
+type rVSetMapIndexConstraint struct {
+	cgn *cgnode
+	v   nodeid // (ptr)
+	key nodeid
+	val nodeid
+}
+
+func (c *rVSetMapIndexConstraint) ptr() nodeid   { return c.v }
+func (c *rVSetMapIndexConstraint) presolve(*hvn) {}
+func (c *rVSetMapIndexConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.key = mapping[c.key]
+	c.val = mapping[c.val]
+}
+
+func (c *rVSetMapIndexConstraint) String() string {
+	return fmt.Sprintf("reflect n%d.SetMapIndex(n%d, n%d)", c.v, c.key, c.val)
+}
+
+func (c *rVSetMapIndexConstraint) solve(a *analysis, delta *nodeset) {
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, m, indirect := a.taggedValue(vObj)
+		tMap, _ := tDyn.Underlying().(*types.Map)
+		if tMap == nil {
+			continue // not a map
+		}
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		keysize := a.sizeof(tMap.Key())
+
+		// Extract key's payload to keytmp, then store to map key.
+		keytmp := a.addNodes(tMap.Key(), "SetMapIndex.keytmp")
+		a.typeAssert(tMap.Key(), keytmp, c.key, false)
+		a.store(m, keytmp, 0, keysize)
+
+		// Extract val's payload to vtmp, then store to map value.
+		valtmp := a.addNodes(tMap.Elem(), "SetMapIndex.valtmp")
+		a.typeAssert(tMap.Elem(), valtmp, c.val, false)
+		a.store(m, valtmp, keysize, a.sizeof(tMap.Elem()))
+	}
+}
+
+func extÛ°reflectÛ°ValueÛ°SetMapIndex(a *analysis, cgn *cgnode) {
+	params := a.funcParams(cgn.obj)
+	a.addConstraint(&rVSetMapIndexConstraint{
+		cgn: cgn,
+		v:   params,
+		key: params + 1,
+		val: params + 2,
+	})
+}
+
+func extÛ°reflectÛ°ValueÛ°SetPointer(a *analysis, cgn *cgnode) {} // TODO(adonovan)
+
+// ---------- func (Value).Slice(v Value, i, j int) Value ----------
+
+// result = v.Slice(_, _)
+type rVSliceConstraint struct {
+	cgn    *cgnode
+	v      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rVSliceConstraint) ptr() nodeid { return c.v }
+func (c *rVSliceConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "rVSlice.result")
+}
+func (c *rVSliceConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.result = mapping[c.result]
+}
+
+func (c *rVSliceConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect n%d.Slice(_, _)", c.result, c.v)
+}
+
+func (c *rVSliceConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, payload, indirect := a.taggedValue(vObj)
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		var res nodeid
+		switch t := tDyn.Underlying().(type) {
+		case *types.Pointer:
+			if tArr, ok := t.Elem().Underlying().(*types.Array); ok {
+				// pointer to array
+				res = a.makeTagged(types.NewSlice(tArr.Elem()), c.cgn, nil)
+				if a.onlineCopy(res+1, payload) {
+					a.addWork(res + 1)
+				}
+			}
+
+		case *types.Array:
+			// TODO(adonovan): implement addressable
+			// arrays when we do indirect tagged objects.
+
+		case *types.Slice:
+			res = vObj
+
+		case *types.Basic:
+			if t == types.Typ[types.String] {
+				res = vObj
+			}
+		}
+
+		if res != 0 && a.addLabel(c.result, res) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func extÛ°reflectÛ°ValueÛ°Slice(a *analysis, cgn *cgnode) {
+	a.addConstraint(&rVSliceConstraint{
+		cgn:    cgn,
+		v:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// -------------------- Standalone reflect functions --------------------
+
+func extÛ°reflectÛ°Append(a *analysis, cgn *cgnode)      {} // TODO(adonovan)
+func extÛ°reflectÛ°AppendSlice(a *analysis, cgn *cgnode) {} // TODO(adonovan)
+func extÛ°reflectÛ°Copy(a *analysis, cgn *cgnode)        {} // TODO(adonovan)
+
+// ---------- func ChanOf(ChanDir, Type) Type ----------
+
+// result = ChanOf(dir, t)
+type reflectChanOfConstraint struct {
+	cgn    *cgnode
+	t      nodeid // (ptr)
+	result nodeid // (indirect)
+	dirs   []types.ChanDir
+}
+
+func (c *reflectChanOfConstraint) ptr() nodeid { return c.t }
+func (c *reflectChanOfConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "reflectChanOf.result")
+}
+func (c *reflectChanOfConstraint) renumber(mapping []nodeid) {
+	c.t = mapping[c.t]
+	c.result = mapping[c.result]
+}
+
+func (c *reflectChanOfConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect.ChanOf(n%d)", c.result, c.t)
+}
+
+func (c *reflectChanOfConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		tObj := nodeid(x)
+		T := a.rtypeTaggedValue(tObj)
+
+		if typeTooHigh(T) {
+			continue
+		}
+
+		for _, dir := range c.dirs {
+			if a.addLabel(c.result, a.makeRtype(types.NewChan(dir, T))) {
+				changed = true
+			}
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+// dirMap maps reflect.ChanDir to the set of channel types generated by ChanOf.
+var dirMap = [...][]types.ChanDir{
+	0:               {types.SendOnly, types.RecvOnly, types.SendRecv}, // unknown
+	reflect.RecvDir: {types.RecvOnly},
+	reflect.SendDir: {types.SendOnly},
+	reflect.BothDir: {types.SendRecv},
+}
+
+func extÛ°reflectÛ°ChanOf(a *analysis, cgn *cgnode) {
+	// If we have access to the callsite,
+	// and the channel argument is a constant (as is usual),
+	// only generate the requested direction.
+	var dir reflect.ChanDir // unknown
+	if site := cgn.callersite; site != nil {
+		if c, ok := site.instr.Common().Args[0].(*ssa.Const); ok {
+			v, _ := exact.Int64Val(c.Value)
+			if 0 <= v && v <= int64(reflect.BothDir) {
+				dir = reflect.ChanDir(v)
+			}
+		}
+	}
+
+	params := a.funcParams(cgn.obj)
+	a.addConstraint(&reflectChanOfConstraint{
+		cgn:    cgn,
+		t:      params + 1,
+		result: a.funcResults(cgn.obj),
+		dirs:   dirMap[dir],
+	})
+}
+
+// ---------- func Indirect(v Value) Value ----------
+
+// result = Indirect(v)
+type reflectIndirectConstraint struct {
+	cgn    *cgnode
+	v      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *reflectIndirectConstraint) ptr() nodeid { return c.v }
+func (c *reflectIndirectConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "reflectIndirect.result")
+}
+func (c *reflectIndirectConstraint) renumber(mapping []nodeid) {
+	c.v = mapping[c.v]
+	c.result = mapping[c.result]
+}
+
+func (c *reflectIndirectConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect.Indirect(n%d)", c.result, c.v)
+}
+
+func (c *reflectIndirectConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		vObj := nodeid(x)
+		tDyn, _, _ := a.taggedValue(vObj)
+		var res nodeid
+		if tPtr, ok := tDyn.Underlying().(*types.Pointer); ok {
+			// load the payload of the pointer's tagged object
+			// into a new tagged object
+			res = a.makeTagged(tPtr.Elem(), c.cgn, nil)
+			a.load(res+1, vObj+1, 0, a.sizeof(tPtr.Elem()))
+		} else {
+			res = vObj
+		}
+
+		if a.addLabel(c.result, res) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func extÛ°reflectÛ°Indirect(a *analysis, cgn *cgnode) {
+	a.addConstraint(&reflectIndirectConstraint{
+		cgn:    cgn,
+		v:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// ---------- func MakeChan(Type) Value ----------
+
+// result = MakeChan(typ)
+type reflectMakeChanConstraint struct {
+	cgn    *cgnode
+	typ    nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *reflectMakeChanConstraint) ptr() nodeid { return c.typ }
+func (c *reflectMakeChanConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "reflectMakeChan.result")
+}
+func (c *reflectMakeChanConstraint) renumber(mapping []nodeid) {
+	c.typ = mapping[c.typ]
+	c.result = mapping[c.result]
+}
+
+func (c *reflectMakeChanConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect.MakeChan(n%d)", c.result, c.typ)
+}
+
+func (c *reflectMakeChanConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		typObj := nodeid(x)
+		T := a.rtypeTaggedValue(typObj)
+		tChan, ok := T.Underlying().(*types.Chan)
+		if !ok || tChan.Dir() != types.SendRecv {
+			continue // not a bidirectional channel type
+		}
+
+		obj := a.nextNode()
+		a.addNodes(tChan.Elem(), "reflect.MakeChan.value")
+		a.endObject(obj, c.cgn, nil)
+
+		// put its address in a new T-tagged object
+		id := a.makeTagged(T, c.cgn, nil)
+		a.addLabel(id+1, obj)
+
+		// flow the T-tagged object to the result
+		if a.addLabel(c.result, id) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func extÛ°reflectÛ°MakeChan(a *analysis, cgn *cgnode) {
+	a.addConstraint(&reflectMakeChanConstraint{
+		cgn:    cgn,
+		typ:    a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+func extÛ°reflectÛ°MakeFunc(a *analysis, cgn *cgnode) {} // TODO(adonovan)
+
+// ---------- func MakeMap(Type) Value ----------
+
+// result = MakeMap(typ)
+type reflectMakeMapConstraint struct {
+	cgn    *cgnode
+	typ    nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *reflectMakeMapConstraint) ptr() nodeid { return c.typ }
+func (c *reflectMakeMapConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "reflectMakeMap.result")
+}
+func (c *reflectMakeMapConstraint) renumber(mapping []nodeid) {
+	c.typ = mapping[c.typ]
+	c.result = mapping[c.result]
+}
+
+func (c *reflectMakeMapConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect.MakeMap(n%d)", c.result, c.typ)
+}
+
+func (c *reflectMakeMapConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		typObj := nodeid(x)
+		T := a.rtypeTaggedValue(typObj)
+		tMap, ok := T.Underlying().(*types.Map)
+		if !ok {
+			continue // not a map type
+		}
+
+		mapObj := a.nextNode()
+		a.addNodes(tMap.Key(), "reflect.MakeMap.key")
+		a.addNodes(tMap.Elem(), "reflect.MakeMap.value")
+		a.endObject(mapObj, c.cgn, nil)
+
+		// put its address in a new T-tagged object
+		id := a.makeTagged(T, c.cgn, nil)
+		a.addLabel(id+1, mapObj)
+
+		// flow the T-tagged object to the result
+		if a.addLabel(c.result, id) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func extÛ°reflectÛ°MakeMap(a *analysis, cgn *cgnode) {
+	a.addConstraint(&reflectMakeMapConstraint{
+		cgn:    cgn,
+		typ:    a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// ---------- func MakeSlice(Type) Value ----------
+
+// result = MakeSlice(typ)
+type reflectMakeSliceConstraint struct {
+	cgn    *cgnode
+	typ    nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *reflectMakeSliceConstraint) ptr() nodeid { return c.typ }
+func (c *reflectMakeSliceConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "reflectMakeSlice.result")
+}
+func (c *reflectMakeSliceConstraint) renumber(mapping []nodeid) {
+	c.typ = mapping[c.typ]
+	c.result = mapping[c.result]
+}
+
+func (c *reflectMakeSliceConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect.MakeSlice(n%d)", c.result, c.typ)
+}
+
+func (c *reflectMakeSliceConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		typObj := nodeid(x)
+		T := a.rtypeTaggedValue(typObj)
+		if _, ok := T.Underlying().(*types.Slice); !ok {
+			continue // not a slice type
+		}
+
+		obj := a.nextNode()
+		a.addNodes(sliceToArray(T), "reflect.MakeSlice")
+		a.endObject(obj, c.cgn, nil)
+
+		// put its address in a new T-tagged object
+		id := a.makeTagged(T, c.cgn, nil)
+		a.addLabel(id+1, obj)
+
+		// flow the T-tagged object to the result
+		if a.addLabel(c.result, id) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func extÛ°reflectÛ°MakeSlice(a *analysis, cgn *cgnode) {
+	a.addConstraint(&reflectMakeSliceConstraint{
+		cgn:    cgn,
+		typ:    a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+func extÛ°reflectÛ°MapOf(a *analysis, cgn *cgnode) {} // TODO(adonovan)
+
+// ---------- func New(Type) Value ----------
+
+// result = New(typ)
+type reflectNewConstraint struct {
+	cgn    *cgnode
+	typ    nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *reflectNewConstraint) ptr() nodeid { return c.typ }
+func (c *reflectNewConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "reflectNew.result")
+}
+func (c *reflectNewConstraint) renumber(mapping []nodeid) {
+	c.typ = mapping[c.typ]
+	c.result = mapping[c.result]
+}
+
+func (c *reflectNewConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect.New(n%d)", c.result, c.typ)
+}
+
+func (c *reflectNewConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		typObj := nodeid(x)
+		T := a.rtypeTaggedValue(typObj)
+
+		// allocate new T object
+		newObj := a.nextNode()
+		a.addNodes(T, "reflect.New")
+		a.endObject(newObj, c.cgn, nil)
+
+		// put its address in a new *T-tagged object
+		id := a.makeTagged(types.NewPointer(T), c.cgn, nil)
+		a.addLabel(id+1, newObj)
+
+		// flow the pointer to the result
+		if a.addLabel(c.result, id) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func extÛ°reflectÛ°New(a *analysis, cgn *cgnode) {
+	a.addConstraint(&reflectNewConstraint{
+		cgn:    cgn,
+		typ:    a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+func extÛ°reflectÛ°NewAt(a *analysis, cgn *cgnode) {
+	extÛ°reflectÛ°New(a, cgn)
+
+	// TODO(adonovan): also report dynamic calls to unsound intrinsics.
+	if site := cgn.callersite; site != nil {
+		a.warnf(site.pos(), "unsound: %s contains a reflect.NewAt() call", site.instr.Parent())
+	}
+}
+
+// ---------- func PtrTo(Type) Type ----------
+
+// result = PtrTo(t)
+type reflectPtrToConstraint struct {
+	cgn    *cgnode
+	t      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *reflectPtrToConstraint) ptr() nodeid { return c.t }
+func (c *reflectPtrToConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "reflectPtrTo.result")
+}
+func (c *reflectPtrToConstraint) renumber(mapping []nodeid) {
+	c.t = mapping[c.t]
+	c.result = mapping[c.result]
+}
+
+func (c *reflectPtrToConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect.PtrTo(n%d)", c.result, c.t)
+}
+
+func (c *reflectPtrToConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		tObj := nodeid(x)
+		T := a.rtypeTaggedValue(tObj)
+
+		if typeTooHigh(T) {
+			continue
+		}
+
+		if a.addLabel(c.result, a.makeRtype(types.NewPointer(T))) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func extÛ°reflectÛ°PtrTo(a *analysis, cgn *cgnode) {
+	a.addConstraint(&reflectPtrToConstraint{
+		cgn:    cgn,
+		t:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+func extÛ°reflectÛ°Select(a *analysis, cgn *cgnode) {} // TODO(adonovan)
+
+// ---------- func SliceOf(Type) Type ----------
+
+// result = SliceOf(t)
+type reflectSliceOfConstraint struct {
+	cgn    *cgnode
+	t      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *reflectSliceOfConstraint) ptr() nodeid { return c.t }
+func (c *reflectSliceOfConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "reflectSliceOf.result")
+}
+func (c *reflectSliceOfConstraint) renumber(mapping []nodeid) {
+	c.t = mapping[c.t]
+	c.result = mapping[c.result]
+}
+
+func (c *reflectSliceOfConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect.SliceOf(n%d)", c.result, c.t)
+}
+
+func (c *reflectSliceOfConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		tObj := nodeid(x)
+		T := a.rtypeTaggedValue(tObj)
+
+		if typeTooHigh(T) {
+			continue
+		}
+
+		if a.addLabel(c.result, a.makeRtype(types.NewSlice(T))) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func extÛ°reflectÛ°SliceOf(a *analysis, cgn *cgnode) {
+	a.addConstraint(&reflectSliceOfConstraint{
+		cgn:    cgn,
+		t:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// ---------- func TypeOf(v Value) Type ----------
+
+// result = TypeOf(i)
+type reflectTypeOfConstraint struct {
+	cgn    *cgnode
+	i      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *reflectTypeOfConstraint) ptr() nodeid { return c.i }
+func (c *reflectTypeOfConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "reflectTypeOf.result")
+}
+func (c *reflectTypeOfConstraint) renumber(mapping []nodeid) {
+	c.i = mapping[c.i]
+	c.result = mapping[c.result]
+}
+
+func (c *reflectTypeOfConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect.TypeOf(n%d)", c.result, c.i)
+}
+
+func (c *reflectTypeOfConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		iObj := nodeid(x)
+		tDyn, _, _ := a.taggedValue(iObj)
+		if a.addLabel(c.result, a.makeRtype(tDyn)) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func extÛ°reflectÛ°TypeOf(a *analysis, cgn *cgnode) {
+	a.addConstraint(&reflectTypeOfConstraint{
+		cgn:    cgn,
+		i:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// ---------- func ValueOf(interface{}) Value ----------
+
+func extÛ°reflectÛ°ValueOf(a *analysis, cgn *cgnode) {
+	// TODO(adonovan): when we start creating indirect tagged
+	// objects, we'll need to handle them specially here since
+	// they must never appear in the PTS of an interface{}.
+	a.copy(a.funcResults(cgn.obj), a.funcParams(cgn.obj), 1)
+}
+
+// ---------- func Zero(Type) Value ----------
+
+// result = Zero(typ)
+type reflectZeroConstraint struct {
+	cgn    *cgnode
+	typ    nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *reflectZeroConstraint) ptr() nodeid { return c.typ }
+func (c *reflectZeroConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "reflectZero.result")
+}
+func (c *reflectZeroConstraint) renumber(mapping []nodeid) {
+	c.typ = mapping[c.typ]
+	c.result = mapping[c.result]
+}
+
+func (c *reflectZeroConstraint) String() string {
+	return fmt.Sprintf("n%d = reflect.Zero(n%d)", c.result, c.typ)
+}
+
+func (c *reflectZeroConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		typObj := nodeid(x)
+		T := a.rtypeTaggedValue(typObj)
+
+		// TODO(adonovan): if T is an interface type, we need
+		// to create an indirect tagged object containing
+		// new(T).  To avoid updates of such shared values,
+		// we'll need another flag on indirect tagged objects
+		// that marks whether they are addressable or
+		// readonly, just like the reflect package does.
+
+		// memoize using a.reflectZeros[T]
+		var id nodeid
+		if z := a.reflectZeros.At(T); false && z != nil {
+			id = z.(nodeid)
+		} else {
+			id = a.makeTagged(T, c.cgn, nil)
+			a.reflectZeros.Set(T, id)
+		}
+		if a.addLabel(c.result, id) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func extÛ°reflectÛ°Zero(a *analysis, cgn *cgnode) {
+	a.addConstraint(&reflectZeroConstraint{
+		cgn:    cgn,
+		typ:    a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// -------------------- (*reflect.rtype) methods --------------------
+
+// ---------- func (*rtype) Elem() Type ----------
+
+// result = Elem(t)
+type rtypeElemConstraint struct {
+	cgn    *cgnode
+	t      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rtypeElemConstraint) ptr() nodeid { return c.t }
+func (c *rtypeElemConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "rtypeElem.result")
+}
+func (c *rtypeElemConstraint) renumber(mapping []nodeid) {
+	c.t = mapping[c.t]
+	c.result = mapping[c.result]
+}
+
+func (c *rtypeElemConstraint) String() string {
+	return fmt.Sprintf("n%d = (*reflect.rtype).Elem(n%d)", c.result, c.t)
+}
+
+func (c *rtypeElemConstraint) solve(a *analysis, delta *nodeset) {
+	// Implemented by *types.{Map,Chan,Array,Slice,Pointer}.
+	type hasElem interface {
+		Elem() types.Type
+	}
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		tObj := nodeid(x)
+		T := a.nodes[tObj].obj.data.(types.Type)
+		if tHasElem, ok := T.Underlying().(hasElem); ok {
+			if a.addLabel(c.result, a.makeRtype(tHasElem.Elem())) {
+				changed = true
+			}
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func extÛ°reflectÛ°rtypeÛ°Elem(a *analysis, cgn *cgnode) {
+	a.addConstraint(&rtypeElemConstraint{
+		cgn:    cgn,
+		t:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// ---------- func (*rtype) Field(int) StructField ----------
+// ---------- func (*rtype) FieldByName(string) (StructField, bool) ----------
+
+// result = FieldByName(t, name)
+// result = Field(t, _)
+type rtypeFieldByNameConstraint struct {
+	cgn    *cgnode
+	name   string // name of field; "" for unknown
+	t      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rtypeFieldByNameConstraint) ptr() nodeid { return c.t }
+func (c *rtypeFieldByNameConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result+3), "rtypeFieldByName.result.Type")
+}
+func (c *rtypeFieldByNameConstraint) renumber(mapping []nodeid) {
+	c.t = mapping[c.t]
+	c.result = mapping[c.result]
+}
+
+func (c *rtypeFieldByNameConstraint) String() string {
+	return fmt.Sprintf("n%d = (*reflect.rtype).FieldByName(n%d, %q)", c.result, c.t, c.name)
+}
+
+func (c *rtypeFieldByNameConstraint) solve(a *analysis, delta *nodeset) {
+	// type StructField struct {
+	// 0	__identity__
+	// 1	Name      string
+	// 2	PkgPath   string
+	// 3	Type      Type
+	// 4	Tag       StructTag
+	// 5	Offset    uintptr
+	// 6	Index     []int
+	// 7	Anonymous bool
+	// }
+
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		tObj := nodeid(x)
+		T := a.nodes[tObj].obj.data.(types.Type)
+		tStruct, ok := T.Underlying().(*types.Struct)
+		if !ok {
+			continue // not a struct type
+		}
+
+		n := tStruct.NumFields()
+		for i := 0; i < n; i++ {
+			f := tStruct.Field(i)
+			if c.name == "" || c.name == f.Name() {
+
+				// a.offsetOf(Type) is 3.
+				if id := c.result + 3; a.addLabel(id, a.makeRtype(f.Type())) {
+					a.addWork(id)
+				}
+				// TODO(adonovan): StructField.Index should be non-nil.
+			}
+		}
+	}
+}
+
+func extÛ°reflectÛ°rtypeÛ°FieldByName(a *analysis, cgn *cgnode) {
+	// If we have access to the callsite,
+	// and the argument is a string constant,
+	// return only that field.
+	var name string
+	if site := cgn.callersite; site != nil {
+		if c, ok := site.instr.Common().Args[0].(*ssa.Const); ok {
+			name = exact.StringVal(c.Value)
+		}
+	}
+
+	a.addConstraint(&rtypeFieldByNameConstraint{
+		cgn:    cgn,
+		name:   name,
+		t:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+func extÛ°reflectÛ°rtypeÛ°Field(a *analysis, cgn *cgnode) {
+	// No-one ever calls Field with a constant argument,
+	// so we don't specialize that case.
+	a.addConstraint(&rtypeFieldByNameConstraint{
+		cgn:    cgn,
+		t:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+func extÛ°reflectÛ°rtypeÛ°FieldByIndex(a *analysis, cgn *cgnode)    {} // TODO(adonovan)
+func extÛ°reflectÛ°rtypeÛ°FieldByNameFunc(a *analysis, cgn *cgnode) {} // TODO(adonovan)
+
+// ---------- func (*rtype) In/Out(i int) Type ----------
+
+// result = In/Out(t, i)
+type rtypeInOutConstraint struct {
+	cgn    *cgnode
+	t      nodeid // (ptr)
+	result nodeid // (indirect)
+	out    bool
+	i      int // -ve if not a constant
+}
+
+func (c *rtypeInOutConstraint) ptr() nodeid { return c.t }
+func (c *rtypeInOutConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "rtypeInOut.result")
+}
+func (c *rtypeInOutConstraint) renumber(mapping []nodeid) {
+	c.t = mapping[c.t]
+	c.result = mapping[c.result]
+}
+
+func (c *rtypeInOutConstraint) String() string {
+	return fmt.Sprintf("n%d = (*reflect.rtype).InOut(n%d, %d)", c.result, c.t, c.i)
+}
+
+func (c *rtypeInOutConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		tObj := nodeid(x)
+		T := a.nodes[tObj].obj.data.(types.Type)
+		sig, ok := T.Underlying().(*types.Signature)
+		if !ok {
+			continue // not a func type
+		}
+
+		tuple := sig.Params()
+		if c.out {
+			tuple = sig.Results()
+		}
+		for i, n := 0, tuple.Len(); i < n; i++ {
+			if c.i < 0 || c.i == i {
+				if a.addLabel(c.result, a.makeRtype(tuple.At(i).Type())) {
+					changed = true
+				}
+			}
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func extÛ°reflectÛ°rtypeÛ°InOut(a *analysis, cgn *cgnode, out bool) {
+	// If we have access to the callsite,
+	// and the argument is an int constant,
+	// return only that parameter.
+	index := -1
+	if site := cgn.callersite; site != nil {
+		if c, ok := site.instr.Common().Args[0].(*ssa.Const); ok {
+			v, _ := exact.Int64Val(c.Value)
+			index = int(v)
+		}
+	}
+	a.addConstraint(&rtypeInOutConstraint{
+		cgn:    cgn,
+		t:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+		out:    out,
+		i:      index,
+	})
+}
+
+func extÛ°reflectÛ°rtypeÛ°In(a *analysis, cgn *cgnode) {
+	extÛ°reflectÛ°rtypeÛ°InOut(a, cgn, false)
+}
+
+func extÛ°reflectÛ°rtypeÛ°Out(a *analysis, cgn *cgnode) {
+	extÛ°reflectÛ°rtypeÛ°InOut(a, cgn, true)
+}
+
+// ---------- func (*rtype) Key() Type ----------
+
+// result = Key(t)
+type rtypeKeyConstraint struct {
+	cgn    *cgnode
+	t      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rtypeKeyConstraint) ptr() nodeid { return c.t }
+func (c *rtypeKeyConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result), "rtypeKey.result")
+}
+func (c *rtypeKeyConstraint) renumber(mapping []nodeid) {
+	c.t = mapping[c.t]
+	c.result = mapping[c.result]
+}
+
+func (c *rtypeKeyConstraint) String() string {
+	return fmt.Sprintf("n%d = (*reflect.rtype).Key(n%d)", c.result, c.t)
+}
+
+func (c *rtypeKeyConstraint) solve(a *analysis, delta *nodeset) {
+	changed := false
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		tObj := nodeid(x)
+		T := a.nodes[tObj].obj.data.(types.Type)
+		if tMap, ok := T.Underlying().(*types.Map); ok {
+			if a.addLabel(c.result, a.makeRtype(tMap.Key())) {
+				changed = true
+			}
+		}
+	}
+	if changed {
+		a.addWork(c.result)
+	}
+}
+
+func extÛ°reflectÛ°rtypeÛ°Key(a *analysis, cgn *cgnode) {
+	a.addConstraint(&rtypeKeyConstraint{
+		cgn:    cgn,
+		t:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// ---------- func (*rtype) Method(int) (Method, bool) ----------
+// ---------- func (*rtype) MethodByName(string) (Method, bool) ----------
+
+// result = MethodByName(t, name)
+// result = Method(t, _)
+type rtypeMethodByNameConstraint struct {
+	cgn    *cgnode
+	name   string // name of method; "" for unknown
+	t      nodeid // (ptr)
+	result nodeid // (indirect)
+}
+
+func (c *rtypeMethodByNameConstraint) ptr() nodeid { return c.t }
+func (c *rtypeMethodByNameConstraint) presolve(h *hvn) {
+	h.markIndirect(onodeid(c.result+3), "rtypeMethodByName.result.Type")
+	h.markIndirect(onodeid(c.result+4), "rtypeMethodByName.result.Func")
+}
+func (c *rtypeMethodByNameConstraint) renumber(mapping []nodeid) {
+	c.t = mapping[c.t]
+	c.result = mapping[c.result]
+}
+
+func (c *rtypeMethodByNameConstraint) String() string {
+	return fmt.Sprintf("n%d = (*reflect.rtype).MethodByName(n%d, %q)", c.result, c.t, c.name)
+}
+
+// changeRecv returns sig with Recv prepended to Params().
+func changeRecv(sig *types.Signature) *types.Signature {
+	params := sig.Params()
+	n := params.Len()
+	p2 := make([]*types.Var, n+1)
+	p2[0] = sig.Recv()
+	for i := 0; i < n; i++ {
+		p2[i+1] = params.At(i)
+	}
+	return types.NewSignature(nil, types.NewTuple(p2...), sig.Results(), sig.Variadic())
+}
+
+func (c *rtypeMethodByNameConstraint) solve(a *analysis, delta *nodeset) {
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		tObj := nodeid(x)
+		T := a.nodes[tObj].obj.data.(types.Type)
+
+		isIface := isInterface(T)
+
+		// We don't use Lookup(c.name) when c.name != "" to avoid
+		// ambiguity: >1 unexported methods could match.
+		mset := a.prog.MethodSets.MethodSet(T)
+		for i, n := 0, mset.Len(); i < n; i++ {
+			sel := mset.At(i)
+			if c.name == "" || c.name == sel.Obj().Name() {
+				// type Method struct {
+				// 0     __identity__
+				// 1	Name    string
+				// 2	PkgPath string
+				// 3	Type    Type
+				// 4	Func    Value
+				// 5	Index   int
+				// }
+
+				var sig *types.Signature
+				var fn *ssa.Function
+				if isIface {
+					sig = sel.Type().(*types.Signature)
+				} else {
+					fn = a.prog.MethodValue(sel)
+					// move receiver to params[0]
+					sig = changeRecv(fn.Signature)
+				}
+
+				// a.offsetOf(Type) is 3.
+				if id := c.result + 3; a.addLabel(id, a.makeRtype(sig)) {
+					a.addWork(id)
+				}
+				if fn != nil {
+					// a.offsetOf(Func) is 4.
+					if id := c.result + 4; a.addLabel(id, a.objectNode(nil, fn)) {
+						a.addWork(id)
+					}
+				}
+			}
+		}
+	}
+}
+
+func extÛ°reflectÛ°rtypeÛ°MethodByName(a *analysis, cgn *cgnode) {
+	// If we have access to the callsite,
+	// and the argument is a string constant,
+	// return only that method.
+	var name string
+	if site := cgn.callersite; site != nil {
+		if c, ok := site.instr.Common().Args[0].(*ssa.Const); ok {
+			name = exact.StringVal(c.Value)
+		}
+	}
+
+	a.addConstraint(&rtypeMethodByNameConstraint{
+		cgn:    cgn,
+		name:   name,
+		t:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+func extÛ°reflectÛ°rtypeÛ°Method(a *analysis, cgn *cgnode) {
+	// No-one ever calls Method with a constant argument,
+	// so we don't specialize that case.
+	a.addConstraint(&rtypeMethodByNameConstraint{
+		cgn:    cgn,
+		t:      a.funcParams(cgn.obj),
+		result: a.funcResults(cgn.obj),
+	})
+}
+
+// typeHeight returns the "height" of the type, which is roughly
+// speaking the number of chan, map, pointer and slice type constructors
+// at the root of T; these are the four type kinds that can be created
+// via reflection.  Chan and map constructors are counted as double the
+// height of slice and pointer constructors since they are less often
+// deeply nested.
+//
+// The solver rules for type constructors must somehow bound the set of
+// types they create to ensure termination of the algorithm in cases
+// where the output of a type constructor flows to its input, e.g.
+//
+// 	func f(t reflect.Type) {
+// 		f(reflect.PtrTo(t))
+// 	}
+//
+// It does this by limiting the type height to k, but this still leaves
+// a potentially exponential (4^k) number of of types that may be
+// enumerated in pathological cases.
+//
+func typeHeight(T types.Type) int {
+	switch T := T.(type) {
+	case *types.Chan:
+		return 2 + typeHeight(T.Elem())
+	case *types.Map:
+		k := typeHeight(T.Key())
+		v := typeHeight(T.Elem())
+		if v > k {
+			k = v // max(k, v)
+		}
+		return 2 + k
+	case *types.Slice:
+		return 1 + typeHeight(T.Elem())
+	case *types.Pointer:
+		return 1 + typeHeight(T.Elem())
+	}
+	return 0
+}
+
+func typeTooHigh(T types.Type) bool {
+	return typeHeight(T) > 3
+}
diff --git a/go/src/golang.org/x/tools/go/pointer/solve.go b/go/src/golang.org/x/tools/go/pointer/solve.go
index ad1a65f..3c60685 100644
--- a/go/src/golang.org/x/tools/go/pointer/solve.go
+++ b/go/src/golang.org/x/tools/go/pointer/solve.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package pointer
 
 // This file defines a naive Andersen-style solver for the inclusion
@@ -9,8 +11,7 @@
 
 import (
 	"fmt"
-
-	"golang.org/x/tools/go/types"
+	"go/types"
 )
 
 type solverState struct {
diff --git a/go/src/golang.org/x/tools/go/pointer/solve14.go b/go/src/golang.org/x/tools/go/pointer/solve14.go
new file mode 100644
index 0000000..25b52db
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/pointer/solve14.go
@@ -0,0 +1,373 @@
+// 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.
+
+// +build !go1.5
+
+package pointer
+
+// This file defines a naive Andersen-style solver for the inclusion
+// constraint system.
+
+import (
+	"fmt"
+
+	"golang.org/x/tools/go/types"
+)
+
+type solverState struct {
+	complex []constraint // complex constraints attached to this node
+	copyTo  nodeset      // simple copy constraint edges
+	pts     nodeset      // points-to set of this node
+	prevPTS nodeset      // pts(n) in previous iteration (for difference propagation)
+}
+
+func (a *analysis) solve() {
+	start("Solving")
+	if a.log != nil {
+		fmt.Fprintf(a.log, "\n\n==== Solving constraints\n\n")
+	}
+
+	// Solver main loop.
+	var delta nodeset
+	for {
+		// Add new constraints to the graph:
+		// static constraints from SSA on round 1,
+		// dynamic constraints from reflection thereafter.
+		a.processNewConstraints()
+
+		var x int
+		if !a.work.TakeMin(&x) {
+			break // empty
+		}
+		id := nodeid(x)
+		if a.log != nil {
+			fmt.Fprintf(a.log, "\tnode n%d\n", id)
+		}
+
+		n := a.nodes[id]
+
+		// Difference propagation.
+		delta.Difference(&n.solve.pts.Sparse, &n.solve.prevPTS.Sparse)
+		if delta.IsEmpty() {
+			continue
+		}
+		if a.log != nil {
+			fmt.Fprintf(a.log, "\t\tpts(n%d : %s) = %s + %s\n",
+				id, n.typ, &delta, &n.solve.prevPTS)
+		}
+		n.solve.prevPTS.Copy(&n.solve.pts.Sparse)
+
+		// Apply all resolution rules attached to n.
+		a.solveConstraints(n, &delta)
+
+		if a.log != nil {
+			fmt.Fprintf(a.log, "\t\tpts(n%d) = %s\n", id, &n.solve.pts)
+		}
+	}
+
+	if !a.nodes[0].solve.pts.IsEmpty() {
+		panic(fmt.Sprintf("pts(0) is nonempty: %s", &a.nodes[0].solve.pts))
+	}
+
+	// Release working state (but keep final PTS).
+	for _, n := range a.nodes {
+		n.solve.complex = nil
+		n.solve.copyTo.Clear()
+		n.solve.prevPTS.Clear()
+	}
+
+	if a.log != nil {
+		fmt.Fprintf(a.log, "Solver done\n")
+
+		// Dump solution.
+		for i, n := range a.nodes {
+			if !n.solve.pts.IsEmpty() {
+				fmt.Fprintf(a.log, "pts(n%d) = %s : %s\n", i, &n.solve.pts, n.typ)
+			}
+		}
+	}
+	stop("Solving")
+}
+
+// processNewConstraints takes the new constraints from a.constraints
+// and adds them to the graph, ensuring
+// that new constraints are applied to pre-existing labels and
+// that pre-existing constraints are applied to new labels.
+//
+func (a *analysis) processNewConstraints() {
+	// Take the slice of new constraints.
+	// (May grow during call to solveConstraints.)
+	constraints := a.constraints
+	a.constraints = nil
+
+	// Initialize points-to sets from addr-of (base) constraints.
+	for _, c := range constraints {
+		if c, ok := c.(*addrConstraint); ok {
+			dst := a.nodes[c.dst]
+			dst.solve.pts.add(c.src)
+
+			// Populate the worklist with nodes that point to
+			// something initially (due to addrConstraints) and
+			// have other constraints attached.
+			// (A no-op in round 1.)
+			if !dst.solve.copyTo.IsEmpty() || len(dst.solve.complex) > 0 {
+				a.addWork(c.dst)
+			}
+		}
+	}
+
+	// Attach simple (copy) and complex constraints to nodes.
+	var stale nodeset
+	for _, c := range constraints {
+		var id nodeid
+		switch c := c.(type) {
+		case *addrConstraint:
+			// base constraints handled in previous loop
+			continue
+		case *copyConstraint:
+			// simple (copy) constraint
+			id = c.src
+			a.nodes[id].solve.copyTo.add(c.dst)
+		default:
+			// complex constraint
+			id = c.ptr()
+			solve := a.nodes[id].solve
+			solve.complex = append(solve.complex, c)
+		}
+
+		if n := a.nodes[id]; !n.solve.pts.IsEmpty() {
+			if !n.solve.prevPTS.IsEmpty() {
+				stale.add(id)
+			}
+			a.addWork(id)
+		}
+	}
+	// Apply new constraints to pre-existing PTS labels.
+	var space [50]int
+	for _, id := range stale.AppendTo(space[:0]) {
+		n := a.nodes[nodeid(id)]
+		a.solveConstraints(n, &n.solve.prevPTS)
+	}
+}
+
+// solveConstraints applies each resolution rule attached to node n to
+// the set of labels delta.  It may generate new constraints in
+// a.constraints.
+//
+func (a *analysis) solveConstraints(n *node, delta *nodeset) {
+	if delta.IsEmpty() {
+		return
+	}
+
+	// Process complex constraints dependent on n.
+	for _, c := range n.solve.complex {
+		if a.log != nil {
+			fmt.Fprintf(a.log, "\t\tconstraint %s\n", c)
+		}
+		c.solve(a, delta)
+	}
+
+	// Process copy constraints.
+	var copySeen nodeset
+	for _, x := range n.solve.copyTo.AppendTo(a.deltaSpace) {
+		mid := nodeid(x)
+		if copySeen.add(mid) {
+			if a.nodes[mid].solve.pts.addAll(delta) {
+				a.addWork(mid)
+			}
+		}
+	}
+}
+
+// addLabel adds label to the points-to set of ptr and reports whether the set grew.
+func (a *analysis) addLabel(ptr, label nodeid) bool {
+	b := a.nodes[ptr].solve.pts.add(label)
+	if b && a.log != nil {
+		fmt.Fprintf(a.log, "\t\tpts(n%d) += n%d\n", ptr, label)
+	}
+	return b
+}
+
+func (a *analysis) addWork(id nodeid) {
+	a.work.Insert(int(id))
+	if a.log != nil {
+		fmt.Fprintf(a.log, "\t\twork: n%d\n", id)
+	}
+}
+
+// onlineCopy adds a copy edge.  It is called online, i.e. during
+// solving, so it adds edges and pts members directly rather than by
+// instantiating a 'constraint'.
+//
+// The size of the copy is implicitly 1.
+// It returns true if pts(dst) changed.
+//
+func (a *analysis) onlineCopy(dst, src nodeid) bool {
+	if dst != src {
+		if nsrc := a.nodes[src]; nsrc.solve.copyTo.add(dst) {
+			if a.log != nil {
+				fmt.Fprintf(a.log, "\t\t\tdynamic copy n%d <- n%d\n", dst, src)
+			}
+			// TODO(adonovan): most calls to onlineCopy
+			// are followed by addWork, possibly batched
+			// via a 'changed' flag; see if there's a
+			// noticeable penalty to calling addWork here.
+			return a.nodes[dst].solve.pts.addAll(&nsrc.solve.pts)
+		}
+	}
+	return false
+}
+
+// Returns sizeof.
+// Implicitly adds nodes to worklist.
+//
+// TODO(adonovan): now that we support a.copy() during solving, we
+// could eliminate onlineCopyN, but it's much slower.  Investigate.
+//
+func (a *analysis) onlineCopyN(dst, src nodeid, sizeof uint32) uint32 {
+	for i := uint32(0); i < sizeof; i++ {
+		if a.onlineCopy(dst, src) {
+			a.addWork(dst)
+		}
+		src++
+		dst++
+	}
+	return sizeof
+}
+
+func (c *loadConstraint) solve(a *analysis, delta *nodeset) {
+	var changed bool
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		k := nodeid(x)
+		koff := k + nodeid(c.offset)
+		if a.onlineCopy(c.dst, koff) {
+			changed = true
+		}
+	}
+	if changed {
+		a.addWork(c.dst)
+	}
+}
+
+func (c *storeConstraint) solve(a *analysis, delta *nodeset) {
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		k := nodeid(x)
+		koff := k + nodeid(c.offset)
+		if a.onlineCopy(koff, c.src) {
+			a.addWork(koff)
+		}
+	}
+}
+
+func (c *offsetAddrConstraint) solve(a *analysis, delta *nodeset) {
+	dst := a.nodes[c.dst]
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		k := nodeid(x)
+		if dst.solve.pts.add(k + nodeid(c.offset)) {
+			a.addWork(c.dst)
+		}
+	}
+}
+
+func (c *typeFilterConstraint) solve(a *analysis, delta *nodeset) {
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		ifaceObj := nodeid(x)
+		tDyn, _, indirect := a.taggedValue(ifaceObj)
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		if types.AssignableTo(tDyn, c.typ) {
+			if a.addLabel(c.dst, ifaceObj) {
+				a.addWork(c.dst)
+			}
+		}
+	}
+}
+
+func (c *untagConstraint) solve(a *analysis, delta *nodeset) {
+	predicate := types.AssignableTo
+	if c.exact {
+		predicate = types.Identical
+	}
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		ifaceObj := nodeid(x)
+		tDyn, v, indirect := a.taggedValue(ifaceObj)
+		if indirect {
+			// TODO(adonovan): we'll need to implement this
+			// when we start creating indirect tagged objects.
+			panic("indirect tagged object")
+		}
+
+		if predicate(tDyn, c.typ) {
+			// Copy payload sans tag to dst.
+			//
+			// TODO(adonovan): opt: if tDyn is
+			// nonpointerlike we can skip this entire
+			// constraint, perhaps.  We only care about
+			// pointers among the fields.
+			a.onlineCopyN(c.dst, v, a.sizeof(tDyn))
+		}
+	}
+}
+
+func (c *invokeConstraint) solve(a *analysis, delta *nodeset) {
+	for _, x := range delta.AppendTo(a.deltaSpace) {
+		ifaceObj := nodeid(x)
+		tDyn, v, indirect := a.taggedValue(ifaceObj)
+		if indirect {
+			// TODO(adonovan): we may need to implement this if
+			// we ever apply invokeConstraints to reflect.Value PTSs,
+			// e.g. for (reflect.Value).Call.
+			panic("indirect tagged object")
+		}
+
+		// Look up the concrete method.
+		fn := a.prog.LookupMethod(tDyn, c.method.Pkg(), c.method.Name())
+		if fn == nil {
+			panic(fmt.Sprintf("n%d: no ssa.Function for %s", c.iface, c.method))
+		}
+		sig := fn.Signature
+
+		fnObj := a.globalobj[fn] // dynamic calls use shared contour
+		if fnObj == 0 {
+			// a.objectNode(fn) was not called during gen phase.
+			panic(fmt.Sprintf("a.globalobj[%s]==nil", fn))
+		}
+
+		// Make callsite's fn variable point to identity of
+		// concrete method.  (There's no need to add it to
+		// worklist since it never has attached constraints.)
+		a.addLabel(c.params, fnObj)
+
+		// Extract value and connect to method's receiver.
+		// Copy payload to method's receiver param (arg0).
+		arg0 := a.funcParams(fnObj)
+		recvSize := a.sizeof(sig.Recv().Type())
+		a.onlineCopyN(arg0, v, recvSize)
+
+		src := c.params + 1 // skip past identity
+		dst := arg0 + nodeid(recvSize)
+
+		// Copy caller's argument block to method formal parameters.
+		paramsSize := a.sizeof(sig.Params())
+		a.onlineCopyN(dst, src, paramsSize)
+		src += nodeid(paramsSize)
+		dst += nodeid(paramsSize)
+
+		// Copy method results to caller's result block.
+		resultsSize := a.sizeof(sig.Results())
+		a.onlineCopyN(src, dst, resultsSize)
+	}
+}
+
+func (c *addrConstraint) solve(a *analysis, delta *nodeset) {
+	panic("addr is not a complex constraint")
+}
+
+func (c *copyConstraint) solve(a *analysis, delta *nodeset) {
+	panic("copy is not a complex constraint")
+}
diff --git a/go/src/golang.org/x/tools/go/pointer/stdlib_test.go b/go/src/golang.org/x/tools/go/pointer/stdlib_test.go
index ef7c652..d3d14ea 100644
--- a/go/src/golang.org/x/tools/go/pointer/stdlib_test.go
+++ b/go/src/golang.org/x/tools/go/pointer/stdlib_test.go
@@ -52,7 +52,7 @@
 
 	// Create SSA packages.
 	prog := ssautil.CreateProgram(iprog, 0)
-	prog.BuildAll()
+	prog.Build()
 
 	numPkgs := len(prog.AllPackages())
 	if want := 240; numPkgs < want {
diff --git a/go/src/golang.org/x/tools/go/pointer/testdata/maps.go b/go/src/golang.org/x/tools/go/pointer/testdata/maps.go
index 6f3751d..6729304 100644
--- a/go/src/golang.org/x/tools/go/pointer/testdata/maps.go
+++ b/go/src/golang.org/x/tools/go/pointer/testdata/maps.go
@@ -45,7 +45,30 @@
 	print(m2[nil]) // @pointsto main.c
 }
 
+var g int
+
+func maps3() {
+	// Regression test for a constraint generation bug for map range
+	// loops in which the key is unused: the (ok, k, v) tuple
+	// returned by ssa.Next may have type 'invalid' for the k and/or
+	// v components, so copying the map key or value may cause
+	// miswiring if the key has >1 components.  In the worst case,
+	// this causes a crash.  The test below used to report that
+	// pts(v) includes not just main.g but new(float64) too, which
+	// is ill-typed.
+
+	// sizeof(K) > 1, abstractly
+	type K struct{ a, b *float64 }
+	k := K{new(float64), nil}
+	m := map[K]*int{k: &g}
+
+	for _, v := range m {
+		print(v) // @pointsto main.g
+	}
+}
+
 func main() {
 	maps1()
 	maps2()
+	maps3()
 }
diff --git a/go/src/golang.org/x/tools/go/pointer/util.go b/go/src/golang.org/x/tools/go/pointer/util.go
index d4ccbb5..4d2fa74 100644
--- a/go/src/golang.org/x/tools/go/pointer/util.go
+++ b/go/src/golang.org/x/tools/go/pointer/util.go
@@ -2,11 +2,14 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package pointer
 
 import (
 	"bytes"
 	"fmt"
+	"go/types"
 	"log"
 	"os"
 	"os/exec"
@@ -14,7 +17,6 @@
 	"time"
 
 	"golang.org/x/tools/container/intsets"
-	"golang.org/x/tools/go/types"
 )
 
 // CanPoint reports whether the type T is pointerlike,
diff --git a/go/src/golang.org/x/tools/go/pointer/util14.go b/go/src/golang.org/x/tools/go/pointer/util14.go
new file mode 100644
index 0000000..d04deeb
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/pointer/util14.go
@@ -0,0 +1,316 @@
+// 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.
+
+// +build !go1.5
+
+package pointer
+
+import (
+	"bytes"
+	"fmt"
+	"log"
+	"os"
+	"os/exec"
+	"runtime"
+	"time"
+
+	"golang.org/x/tools/container/intsets"
+	"golang.org/x/tools/go/types"
+)
+
+// CanPoint reports whether the type T is pointerlike,
+// for the purposes of this analysis.
+func CanPoint(T types.Type) bool {
+	switch T := T.(type) {
+	case *types.Named:
+		if obj := T.Obj(); obj.Name() == "Value" && obj.Pkg().Path() == "reflect" {
+			return true // treat reflect.Value like interface{}
+		}
+		return CanPoint(T.Underlying())
+
+	case *types.Pointer, *types.Interface, *types.Map, *types.Chan, *types.Signature, *types.Slice:
+		return true
+	}
+
+	return false // array struct tuple builtin basic
+}
+
+// CanHaveDynamicTypes reports whether the type T can "hold" dynamic types,
+// i.e. is an interface (incl. reflect.Type) or a reflect.Value.
+//
+func CanHaveDynamicTypes(T types.Type) bool {
+	switch T := T.(type) {
+	case *types.Named:
+		if obj := T.Obj(); obj.Name() == "Value" && obj.Pkg().Path() == "reflect" {
+			return true // reflect.Value
+		}
+		return CanHaveDynamicTypes(T.Underlying())
+	case *types.Interface:
+		return true
+	}
+	return false
+}
+
+func isInterface(T types.Type) bool { return types.IsInterface(T) }
+
+// mustDeref returns the element type of its argument, which must be a
+// pointer; panic ensues otherwise.
+func mustDeref(typ types.Type) types.Type {
+	return typ.Underlying().(*types.Pointer).Elem()
+}
+
+// deref returns a pointer's element type; otherwise it returns typ.
+func deref(typ types.Type) types.Type {
+	if p, ok := typ.Underlying().(*types.Pointer); ok {
+		return p.Elem()
+	}
+	return typ
+}
+
+// A fieldInfo describes one subelement (node) of the flattening-out
+// of a type T: the subelement's type and its path from the root of T.
+//
+// For example, for this type:
+//     type line struct{ points []struct{x, y int} }
+// flatten() of the inner struct yields the following []fieldInfo:
+//    struct{ x, y int }                      ""
+//    int                                     ".x"
+//    int                                     ".y"
+// and flatten(line) yields:
+//    struct{ points []struct{x, y int} }     ""
+//    struct{ x, y int }                      ".points[*]"
+//    int                                     ".points[*].x
+//    int                                     ".points[*].y"
+//
+type fieldInfo struct {
+	typ types.Type
+
+	// op and tail describe the path to the element (e.g. ".a#2.b[*].c").
+	op   interface{} // *Array: true; *Tuple: int; *Struct: *types.Var; *Named: nil
+	tail *fieldInfo
+}
+
+// path returns a user-friendly string describing the subelement path.
+//
+func (fi *fieldInfo) path() string {
+	var buf bytes.Buffer
+	for p := fi; p != nil; p = p.tail {
+		switch op := p.op.(type) {
+		case bool:
+			fmt.Fprintf(&buf, "[*]")
+		case int:
+			fmt.Fprintf(&buf, "#%d", op)
+		case *types.Var:
+			fmt.Fprintf(&buf, ".%s", op.Name())
+		}
+	}
+	return buf.String()
+}
+
+// flatten returns a list of directly contained fields in the preorder
+// traversal of the type tree of t.  The resulting elements are all
+// scalars (basic types or pointerlike types), except for struct/array
+// "identity" nodes, whose type is that of the aggregate.
+//
+// reflect.Value is considered pointerlike, similar to interface{}.
+//
+// Callers must not mutate the result.
+//
+func (a *analysis) flatten(t types.Type) []*fieldInfo {
+	fl, ok := a.flattenMemo[t]
+	if !ok {
+		switch t := t.(type) {
+		case *types.Named:
+			u := t.Underlying()
+			if isInterface(u) {
+				// Debuggability hack: don't remove
+				// the named type from interfaces as
+				// they're very verbose.
+				fl = append(fl, &fieldInfo{typ: t})
+			} else {
+				fl = a.flatten(u)
+			}
+
+		case *types.Basic,
+			*types.Signature,
+			*types.Chan,
+			*types.Map,
+			*types.Interface,
+			*types.Slice,
+			*types.Pointer:
+			fl = append(fl, &fieldInfo{typ: t})
+
+		case *types.Array:
+			fl = append(fl, &fieldInfo{typ: t}) // identity node
+			for _, fi := range a.flatten(t.Elem()) {
+				fl = append(fl, &fieldInfo{typ: fi.typ, op: true, tail: fi})
+			}
+
+		case *types.Struct:
+			fl = append(fl, &fieldInfo{typ: t}) // identity node
+			for i, n := 0, t.NumFields(); i < n; i++ {
+				f := t.Field(i)
+				for _, fi := range a.flatten(f.Type()) {
+					fl = append(fl, &fieldInfo{typ: fi.typ, op: f, tail: fi})
+				}
+			}
+
+		case *types.Tuple:
+			// No identity node: tuples are never address-taken.
+			n := t.Len()
+			if n == 1 {
+				// Don't add a fieldInfo link for singletons,
+				// e.g. in params/results.
+				fl = append(fl, a.flatten(t.At(0).Type())...)
+			} else {
+				for i := 0; i < n; i++ {
+					f := t.At(i)
+					for _, fi := range a.flatten(f.Type()) {
+						fl = append(fl, &fieldInfo{typ: fi.typ, op: i, tail: fi})
+					}
+				}
+			}
+
+		default:
+			panic(t)
+		}
+
+		a.flattenMemo[t] = fl
+	}
+
+	return fl
+}
+
+// sizeof returns the number of pointerlike abstractions (nodes) in the type t.
+func (a *analysis) sizeof(t types.Type) uint32 {
+	return uint32(len(a.flatten(t)))
+}
+
+// shouldTrack reports whether object type T contains (recursively)
+// any fields whose addresses should be tracked.
+func (a *analysis) shouldTrack(T types.Type) bool {
+	if a.track == trackAll {
+		return true // fast path
+	}
+	track, ok := a.trackTypes[T]
+	if !ok {
+		a.trackTypes[T] = true // break cycles conservatively
+		// NB: reflect.Value, reflect.Type are pre-populated to true.
+		for _, fi := range a.flatten(T) {
+			switch ft := fi.typ.Underlying().(type) {
+			case *types.Interface, *types.Signature:
+				track = true // needed for callgraph
+			case *types.Basic:
+				// no-op
+			case *types.Chan:
+				track = a.track&trackChan != 0 || a.shouldTrack(ft.Elem())
+			case *types.Map:
+				track = a.track&trackMap != 0 || a.shouldTrack(ft.Key()) || a.shouldTrack(ft.Elem())
+			case *types.Slice:
+				track = a.track&trackSlice != 0 || a.shouldTrack(ft.Elem())
+			case *types.Pointer:
+				track = a.track&trackPtr != 0 || a.shouldTrack(ft.Elem())
+			case *types.Array, *types.Struct:
+				// No need to look at field types since they will follow (flattened).
+			default:
+				// Includes *types.Tuple, which are never address-taken.
+				panic(ft)
+			}
+			if track {
+				break
+			}
+		}
+		a.trackTypes[T] = track
+		if !track && a.log != nil {
+			fmt.Fprintf(a.log, "\ttype not tracked: %s\n", T)
+		}
+	}
+	return track
+}
+
+// offsetOf returns the (abstract) offset of field index within struct
+// or tuple typ.
+func (a *analysis) offsetOf(typ types.Type, index int) uint32 {
+	var offset uint32
+	switch t := typ.Underlying().(type) {
+	case *types.Tuple:
+		for i := 0; i < index; i++ {
+			offset += a.sizeof(t.At(i).Type())
+		}
+	case *types.Struct:
+		offset++ // the node for the struct itself
+		for i := 0; i < index; i++ {
+			offset += a.sizeof(t.Field(i).Type())
+		}
+	default:
+		panic(fmt.Sprintf("offsetOf(%s : %T)", typ, typ))
+	}
+	return offset
+}
+
+// sliceToArray returns the type representing the arrays to which
+// slice type slice points.
+func sliceToArray(slice types.Type) *types.Array {
+	return types.NewArray(slice.Underlying().(*types.Slice).Elem(), 1)
+}
+
+// Node set -------------------------------------------------------------------
+
+type nodeset struct {
+	intsets.Sparse
+}
+
+func (ns *nodeset) String() string {
+	var buf bytes.Buffer
+	buf.WriteRune('{')
+	var space [50]int
+	for i, n := range ns.AppendTo(space[:0]) {
+		if i > 0 {
+			buf.WriteString(", ")
+		}
+		buf.WriteRune('n')
+		fmt.Fprintf(&buf, "%d", n)
+	}
+	buf.WriteRune('}')
+	return buf.String()
+}
+
+func (ns *nodeset) add(n nodeid) bool {
+	return ns.Sparse.Insert(int(n))
+}
+
+func (x *nodeset) addAll(y *nodeset) bool {
+	return x.UnionWith(&y.Sparse)
+}
+
+// Profiling & debugging -------------------------------------------------------
+
+var timers = make(map[string]time.Time)
+
+func start(name string) {
+	if debugTimers {
+		timers[name] = time.Now()
+		log.Printf("%s...\n", name)
+	}
+}
+
+func stop(name string) {
+	if debugTimers {
+		log.Printf("%s took %s\n", name, time.Since(timers[name]))
+	}
+}
+
+// diff runs the command "diff a b" and reports its success.
+func diff(a, b string) bool {
+	var cmd *exec.Cmd
+	switch runtime.GOOS {
+	case "plan9":
+		cmd = exec.Command("/bin/diff", "-c", a, b)
+	default:
+		cmd = exec.Command("/usr/bin/diff", "-u", a, b)
+	}
+	cmd.Stdout = os.Stderr
+	cmd.Stderr = os.Stderr
+	return cmd.Run() == nil
+}
diff --git a/go/src/golang.org/x/tools/go/ssa/builder.go b/go/src/golang.org/x/tools/go/ssa/builder.go
index 5b8ce0e..4707ebe 100644
--- a/go/src/golang.org/x/tools/go/ssa/builder.go
+++ b/go/src/golang.org/x/tools/go/ssa/builder.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package ssa
 
 // This file implements the BUILD phase of SSA construction.
@@ -32,13 +34,11 @@
 import (
 	"fmt"
 	"go/ast"
+	exact "go/constant"
 	"go/token"
+	"go/types"
 	"os"
 	"sync"
-	"sync/atomic"
-
-	"golang.org/x/tools/go/exact"
-	"golang.org/x/tools/go/types"
 )
 
 type opaqueType struct {
@@ -243,7 +243,7 @@
 			}
 			if m, ok := m.(*Const); ok {
 				// treat make([]T, n, m) as new([m]T)[:n]
-				cap, _ := exact.Int64Val(m.Value)
+				cap := m.Int64()
 				at := types.NewArray(typ.Underlying().(*types.Slice).Elem(), cap)
 				alloc := emitNew(fn, at, pos)
 				alloc.Comment = "makeslice"
@@ -1055,6 +1055,7 @@
 	} else {
 		// e.g. x, y = pos()
 		tuple := b.exprN(fn, rhss[0])
+		emitDebugRef(fn, rhss[0], tuple, false)
 		for i, lval := range lvals {
 			lval.store(fn, emitExtract(fn, tuple, i))
 		}
@@ -1194,9 +1195,26 @@
 		fn.emit(m)
 		for _, e := range e.Elts {
 			e := e.(*ast.KeyValueExpr)
+
+			// If a key expression in a map literal is  itself a
+			// composite literal, the type may be omitted.
+			// For example:
+			//	map[*struct{}]bool{{}: true}
+			// An &-operation may be implied:
+			//	map[*struct{}]bool{&struct{}{}: true}
+			var key Value
+			if _, ok := unparen(e.Key).(*ast.CompositeLit); ok && isPointer(t.Key()) {
+				// A CompositeLit never evaluates to a pointer,
+				// so if the type of the location is a pointer,
+				// an &-operation is implied.
+				key = b.addr(fn, e.Key, true).address(fn)
+			} else {
+				key = b.expr(fn, e.Key)
+			}
+
 			loc := element{
 				m:   m,
-				k:   emitConv(fn, b.expr(fn, e.Key), t.Key()),
+				k:   emitConv(fn, key, t.Key()),
 				t:   t.Elem(),
 				pos: e.Colon,
 			}
@@ -2217,9 +2235,7 @@
 //
 // BuildAll is idempotent and thread-safe.
 //
-// TODO(adonovan): rename to Build.
-//
-func (prog *Program) BuildAll() {
+func (prog *Program) Build() {
 	var wg sync.WaitGroup
 	for _, p := range prog.packages {
 		if prog.mode&BuildSerially != 0 {
@@ -2243,10 +2259,9 @@
 //
 // Build is idempotent and thread-safe.
 //
-func (p *Package) Build() {
-	if !atomic.CompareAndSwapInt32(&p.started, 0, 1) {
-		return // already started
-	}
+func (p *Package) Build() { p.buildOnce.Do(p.build) }
+
+func (p *Package) build() {
 	if p.info == nil {
 		return // synthetic package, e.g. "testmain"
 	}
@@ -2281,10 +2296,10 @@
 		emitStore(init, initguard, vTrue, token.NoPos)
 
 		// Call the init() function of each package we import.
-		for _, pkg := range p.Object.Imports() {
+		for _, pkg := range p.Pkg.Imports() {
 			prereq := p.Prog.packages[pkg]
 			if prereq == nil {
-				panic(fmt.Sprintf("Package(%q).Build(): unsatisfied import: Program.CreatePackage(%q) was not called", p.Object.Path(), pkg.Path()))
+				panic(fmt.Sprintf("Package(%q).Build(): unsatisfied import: Program.CreatePackage(%q) was not called", p.Pkg.Path(), pkg.Path()))
 			}
 			var v Call
 			v.Call.Value = prereq.init
diff --git a/go/src/golang.org/x/tools/go/ssa/builder14.go b/go/src/golang.org/x/tools/go/ssa/builder14.go
new file mode 100644
index 0000000..fcc4b92
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/ssa/builder14.go
@@ -0,0 +1,2386 @@
+// 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.
+
+// +build !go1.5
+
+package ssa
+
+// This file implements the BUILD phase of SSA construction.
+//
+// SSA construction has two phases, CREATE and BUILD.  In the CREATE phase
+// (create.go), all packages are constructed and type-checked and
+// definitions of all package members are created, method-sets are
+// computed, and wrapper methods are synthesized.
+// ssa.Packages are created in arbitrary order.
+//
+// In the BUILD phase (builder.go), the builder traverses the AST of
+// each Go source function and generates SSA instructions for the
+// function body.  Initializer expressions for package-level variables
+// are emitted to the package's init() function in the order specified
+// by go/types.Info.InitOrder, then code for each function in the
+// package is generated in lexical order.
+// The BUILD phases for distinct packages are independent and are
+// executed in parallel.
+//
+// TODO(adonovan): indeed, building functions is now embarrassingly parallel.
+// Audit for concurrency then benchmark using more goroutines.
+//
+// The builder's and Program's indices (maps) are populated and
+// mutated during the CREATE phase, but during the BUILD phase they
+// remain constant.  The sole exception is Prog.methodSets and its
+// related maps, which are protected by a dedicated mutex.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"os"
+	"sync"
+
+	"golang.org/x/tools/go/exact"
+	"golang.org/x/tools/go/types"
+)
+
+type opaqueType struct {
+	types.Type
+	name string
+}
+
+func (t *opaqueType) String() string { return t.name }
+
+var (
+	varOk    = newVar("ok", tBool)
+	varIndex = newVar("index", tInt)
+
+	// Type constants.
+	tBool       = types.Typ[types.Bool]
+	tByte       = types.Typ[types.Byte]
+	tInt        = types.Typ[types.Int]
+	tInvalid    = types.Typ[types.Invalid]
+	tString     = types.Typ[types.String]
+	tUntypedNil = types.Typ[types.UntypedNil]
+	tRangeIter  = &opaqueType{nil, "iter"} // the type of all "range" iterators
+	tEface      = new(types.Interface)
+
+	// SSA Value constants.
+	vZero = intConst(0)
+	vOne  = intConst(1)
+	vTrue = NewConst(exact.MakeBool(true), tBool)
+)
+
+// builder holds state associated with the package currently being built.
+// Its methods contain all the logic for AST-to-SSA conversion.
+type builder struct{}
+
+// cond emits to fn code to evaluate boolean condition e and jump
+// to t or f depending on its value, performing various simplifications.
+//
+// Postcondition: fn.currentBlock is nil.
+//
+func (b *builder) cond(fn *Function, e ast.Expr, t, f *BasicBlock) {
+	switch e := e.(type) {
+	case *ast.ParenExpr:
+		b.cond(fn, e.X, t, f)
+		return
+
+	case *ast.BinaryExpr:
+		switch e.Op {
+		case token.LAND:
+			ltrue := fn.newBasicBlock("cond.true")
+			b.cond(fn, e.X, ltrue, f)
+			fn.currentBlock = ltrue
+			b.cond(fn, e.Y, t, f)
+			return
+
+		case token.LOR:
+			lfalse := fn.newBasicBlock("cond.false")
+			b.cond(fn, e.X, t, lfalse)
+			fn.currentBlock = lfalse
+			b.cond(fn, e.Y, t, f)
+			return
+		}
+
+	case *ast.UnaryExpr:
+		if e.Op == token.NOT {
+			b.cond(fn, e.X, f, t)
+			return
+		}
+	}
+
+	// A traditional compiler would simplify "if false" (etc) here
+	// but we do not, for better fidelity to the source code.
+	//
+	// The value of a constant condition may be platform-specific,
+	// and may cause blocks that are reachable in some configuration
+	// to be hidden from subsequent analyses such as bug-finding tools.
+	emitIf(fn, b.expr(fn, e), t, f)
+}
+
+// logicalBinop emits code to fn to evaluate e, a &&- or
+// ||-expression whose reified boolean value is wanted.
+// The value is returned.
+//
+func (b *builder) logicalBinop(fn *Function, e *ast.BinaryExpr) Value {
+	rhs := fn.newBasicBlock("binop.rhs")
+	done := fn.newBasicBlock("binop.done")
+
+	// T(e) = T(e.X) = T(e.Y) after untyped constants have been
+	// eliminated.
+	// TODO(adonovan): not true; MyBool==MyBool yields UntypedBool.
+	t := fn.Pkg.typeOf(e)
+
+	var short Value // value of the short-circuit path
+	switch e.Op {
+	case token.LAND:
+		b.cond(fn, e.X, rhs, done)
+		short = NewConst(exact.MakeBool(false), t)
+
+	case token.LOR:
+		b.cond(fn, e.X, done, rhs)
+		short = NewConst(exact.MakeBool(true), t)
+	}
+
+	// Is rhs unreachable?
+	if rhs.Preds == nil {
+		// Simplify false&&y to false, true||y to true.
+		fn.currentBlock = done
+		return short
+	}
+
+	// Is done unreachable?
+	if done.Preds == nil {
+		// Simplify true&&y (or false||y) to y.
+		fn.currentBlock = rhs
+		return b.expr(fn, e.Y)
+	}
+
+	// All edges from e.X to done carry the short-circuit value.
+	var edges []Value
+	for _ = range done.Preds {
+		edges = append(edges, short)
+	}
+
+	// The edge from e.Y to done carries the value of e.Y.
+	fn.currentBlock = rhs
+	edges = append(edges, b.expr(fn, e.Y))
+	emitJump(fn, done)
+	fn.currentBlock = done
+
+	phi := &Phi{Edges: edges, Comment: e.Op.String()}
+	phi.pos = e.OpPos
+	phi.typ = t
+	return done.emit(phi)
+}
+
+// exprN lowers a multi-result expression e to SSA form, emitting code
+// to fn and returning a single Value whose type is a *types.Tuple.
+// The caller must access the components via Extract.
+//
+// Multi-result expressions include CallExprs in a multi-value
+// assignment or return statement, and "value,ok" uses of
+// TypeAssertExpr, IndexExpr (when X is a map), and UnaryExpr (when Op
+// is token.ARROW).
+//
+func (b *builder) exprN(fn *Function, e ast.Expr) Value {
+	typ := fn.Pkg.typeOf(e).(*types.Tuple)
+	switch e := e.(type) {
+	case *ast.ParenExpr:
+		return b.exprN(fn, e.X)
+
+	case *ast.CallExpr:
+		// Currently, no built-in function nor type conversion
+		// has multiple results, so we can avoid some of the
+		// cases for single-valued CallExpr.
+		var c Call
+		b.setCall(fn, e, &c.Call)
+		c.typ = typ
+		return fn.emit(&c)
+
+	case *ast.IndexExpr:
+		mapt := fn.Pkg.typeOf(e.X).Underlying().(*types.Map)
+		lookup := &Lookup{
+			X:       b.expr(fn, e.X),
+			Index:   emitConv(fn, b.expr(fn, e.Index), mapt.Key()),
+			CommaOk: true,
+		}
+		lookup.setType(typ)
+		lookup.setPos(e.Lbrack)
+		return fn.emit(lookup)
+
+	case *ast.TypeAssertExpr:
+		return emitTypeTest(fn, b.expr(fn, e.X), typ.At(0).Type(), e.Lparen)
+
+	case *ast.UnaryExpr: // must be receive <-
+		unop := &UnOp{
+			Op:      token.ARROW,
+			X:       b.expr(fn, e.X),
+			CommaOk: true,
+		}
+		unop.setType(typ)
+		unop.setPos(e.OpPos)
+		return fn.emit(unop)
+	}
+	panic(fmt.Sprintf("exprN(%T) in %s", e, fn))
+}
+
+// builtin emits to fn SSA instructions to implement a call to the
+// built-in function obj with the specified arguments
+// and return type.  It returns the value defined by the result.
+//
+// The result is nil if no special handling was required; in this case
+// the caller should treat this like an ordinary library function
+// call.
+//
+func (b *builder) builtin(fn *Function, obj *types.Builtin, args []ast.Expr, typ types.Type, pos token.Pos) Value {
+	switch obj.Name() {
+	case "make":
+		switch typ.Underlying().(type) {
+		case *types.Slice:
+			n := b.expr(fn, args[1])
+			m := n
+			if len(args) == 3 {
+				m = b.expr(fn, args[2])
+			}
+			if m, ok := m.(*Const); ok {
+				// treat make([]T, n, m) as new([m]T)[:n]
+				cap, _ := exact.Int64Val(m.Value)
+				at := types.NewArray(typ.Underlying().(*types.Slice).Elem(), cap)
+				alloc := emitNew(fn, at, pos)
+				alloc.Comment = "makeslice"
+				v := &Slice{
+					X:    alloc,
+					High: n,
+				}
+				v.setPos(pos)
+				v.setType(typ)
+				return fn.emit(v)
+			}
+			v := &MakeSlice{
+				Len: n,
+				Cap: m,
+			}
+			v.setPos(pos)
+			v.setType(typ)
+			return fn.emit(v)
+
+		case *types.Map:
+			var res Value
+			if len(args) == 2 {
+				res = b.expr(fn, args[1])
+			}
+			v := &MakeMap{Reserve: res}
+			v.setPos(pos)
+			v.setType(typ)
+			return fn.emit(v)
+
+		case *types.Chan:
+			var sz Value = vZero
+			if len(args) == 2 {
+				sz = b.expr(fn, args[1])
+			}
+			v := &MakeChan{Size: sz}
+			v.setPos(pos)
+			v.setType(typ)
+			return fn.emit(v)
+		}
+
+	case "new":
+		alloc := emitNew(fn, deref(typ), pos)
+		alloc.Comment = "new"
+		return alloc
+
+	case "len", "cap":
+		// Special case: len or cap of an array or *array is
+		// based on the type, not the value which may be nil.
+		// We must still evaluate the value, though.  (If it
+		// was side-effect free, the whole call would have
+		// been constant-folded.)
+		t := deref(fn.Pkg.typeOf(args[0])).Underlying()
+		if at, ok := t.(*types.Array); ok {
+			b.expr(fn, args[0]) // for effects only
+			return intConst(at.Len())
+		}
+		// Otherwise treat as normal.
+
+	case "panic":
+		fn.emit(&Panic{
+			X:   emitConv(fn, b.expr(fn, args[0]), tEface),
+			pos: pos,
+		})
+		fn.currentBlock = fn.newBasicBlock("unreachable")
+		return vTrue // any non-nil Value will do
+	}
+	return nil // treat all others as a regular function call
+}
+
+// addr lowers a single-result addressable expression e to SSA form,
+// emitting code to fn and returning the location (an lvalue) defined
+// by the expression.
+//
+// If escaping is true, addr marks the base variable of the
+// addressable expression e as being a potentially escaping pointer
+// value.  For example, in this code:
+//
+//   a := A{
+//     b: [1]B{B{c: 1}}
+//   }
+//   return &a.b[0].c
+//
+// the application of & causes a.b[0].c to have its address taken,
+// which means that ultimately the local variable a must be
+// heap-allocated.  This is a simple but very conservative escape
+// analysis.
+//
+// Operations forming potentially escaping pointers include:
+// - &x, including when implicit in method call or composite literals.
+// - a[:] iff a is an array (not *array)
+// - references to variables in lexically enclosing functions.
+//
+func (b *builder) addr(fn *Function, e ast.Expr, escaping bool) lvalue {
+	switch e := e.(type) {
+	case *ast.Ident:
+		if isBlankIdent(e) {
+			return blank{}
+		}
+		obj := fn.Pkg.objectOf(e)
+		v := fn.Prog.packageLevelValue(obj) // var (address)
+		if v == nil {
+			v = fn.lookup(obj, escaping)
+		}
+		return &address{addr: v, pos: e.Pos(), expr: e}
+
+	case *ast.CompositeLit:
+		t := deref(fn.Pkg.typeOf(e))
+		var v *Alloc
+		if escaping {
+			v = emitNew(fn, t, e.Lbrace)
+		} else {
+			v = fn.addLocal(t, e.Lbrace)
+		}
+		v.Comment = "complit"
+		var sb storebuf
+		b.compLit(fn, v, e, true, &sb)
+		sb.emit(fn)
+		return &address{addr: v, pos: e.Lbrace, expr: e}
+
+	case *ast.ParenExpr:
+		return b.addr(fn, e.X, escaping)
+
+	case *ast.SelectorExpr:
+		sel, ok := fn.Pkg.info.Selections[e]
+		if !ok {
+			// qualified identifier
+			return b.addr(fn, e.Sel, escaping)
+		}
+		if sel.Kind() != types.FieldVal {
+			panic(sel)
+		}
+		wantAddr := true
+		v := b.receiver(fn, e.X, wantAddr, escaping, sel)
+		last := len(sel.Index()) - 1
+		return &address{
+			addr: emitFieldSelection(fn, v, sel.Index()[last], true, e.Sel),
+			pos:  e.Sel.Pos(),
+			expr: e.Sel,
+		}
+
+	case *ast.IndexExpr:
+		var x Value
+		var et types.Type
+		switch t := fn.Pkg.typeOf(e.X).Underlying().(type) {
+		case *types.Array:
+			x = b.addr(fn, e.X, escaping).address(fn)
+			et = types.NewPointer(t.Elem())
+		case *types.Pointer: // *array
+			x = b.expr(fn, e.X)
+			et = types.NewPointer(t.Elem().Underlying().(*types.Array).Elem())
+		case *types.Slice:
+			x = b.expr(fn, e.X)
+			et = types.NewPointer(t.Elem())
+		case *types.Map:
+			return &element{
+				m:   b.expr(fn, e.X),
+				k:   emitConv(fn, b.expr(fn, e.Index), t.Key()),
+				t:   t.Elem(),
+				pos: e.Lbrack,
+			}
+		default:
+			panic("unexpected container type in IndexExpr: " + t.String())
+		}
+		v := &IndexAddr{
+			X:     x,
+			Index: emitConv(fn, b.expr(fn, e.Index), tInt),
+		}
+		v.setPos(e.Lbrack)
+		v.setType(et)
+		return &address{addr: fn.emit(v), pos: e.Lbrack, expr: e}
+
+	case *ast.StarExpr:
+		return &address{addr: b.expr(fn, e.X), pos: e.Star, expr: e}
+	}
+
+	panic(fmt.Sprintf("unexpected address expression: %T", e))
+}
+
+type store struct {
+	lhs lvalue
+	rhs Value
+}
+
+type storebuf struct{ stores []store }
+
+func (sb *storebuf) store(lhs lvalue, rhs Value) {
+	sb.stores = append(sb.stores, store{lhs, rhs})
+}
+
+func (sb *storebuf) emit(fn *Function) {
+	for _, s := range sb.stores {
+		s.lhs.store(fn, s.rhs)
+	}
+}
+
+// assign emits to fn code to initialize the lvalue loc with the value
+// of expression e.  If isZero is true, assign assumes that loc holds
+// the zero value for its type.
+//
+// This is equivalent to loc.store(fn, b.expr(fn, e)), but may generate
+// better code in some cases, e.g., for composite literals in an
+// addressable location.
+//
+// If sb is not nil, assign generates code to evaluate expression e, but
+// not to update loc.  Instead, the necessary stores are appended to the
+// storebuf sb so that they can be executed later.  This allows correct
+// in-place update of existing variables when the RHS is a composite
+// literal that may reference parts of the LHS.
+//
+func (b *builder) assign(fn *Function, loc lvalue, e ast.Expr, isZero bool, sb *storebuf) {
+	// Can we initialize it in place?
+	if e, ok := unparen(e).(*ast.CompositeLit); ok {
+		// A CompositeLit never evaluates to a pointer,
+		// so if the type of the location is a pointer,
+		// an &-operation is implied.
+		if _, ok := loc.(blank); !ok { // avoid calling blank.typ()
+			if isPointer(loc.typ()) {
+				ptr := b.addr(fn, e, true).address(fn)
+				// copy address
+				if sb != nil {
+					sb.store(loc, ptr)
+				} else {
+					loc.store(fn, ptr)
+				}
+				return
+			}
+		}
+
+		if _, ok := loc.(*address); ok {
+			if isInterface(loc.typ()) {
+				// e.g. var x interface{} = T{...}
+				// Can't in-place initialize an interface value.
+				// Fall back to copying.
+			} else {
+				// x = T{...} or x := T{...}
+				addr := loc.address(fn)
+				if sb != nil {
+					b.compLit(fn, addr, e, isZero, sb)
+				} else {
+					var sb storebuf
+					b.compLit(fn, addr, e, isZero, &sb)
+					sb.emit(fn)
+				}
+
+				// Subtle: emit debug ref for aggregate types only;
+				// slice and map are handled by store ops in compLit.
+				switch loc.typ().Underlying().(type) {
+				case *types.Struct, *types.Array:
+					emitDebugRef(fn, e, addr, true)
+				}
+
+				return
+			}
+		}
+	}
+
+	// simple case: just copy
+	rhs := b.expr(fn, e)
+	if sb != nil {
+		sb.store(loc, rhs)
+	} else {
+		loc.store(fn, rhs)
+	}
+}
+
+// expr lowers a single-result expression e to SSA form, emitting code
+// to fn and returning the Value defined by the expression.
+//
+func (b *builder) expr(fn *Function, e ast.Expr) Value {
+	e = unparen(e)
+
+	tv := fn.Pkg.info.Types[e]
+
+	// Is expression a constant?
+	if tv.Value != nil {
+		return NewConst(tv.Value, tv.Type)
+	}
+
+	var v Value
+	if tv.Addressable() {
+		// Prefer pointer arithmetic ({Index,Field}Addr) followed
+		// by Load over subelement extraction (e.g. Index, Field),
+		// to avoid large copies.
+		v = b.addr(fn, e, false).load(fn)
+	} else {
+		v = b.expr0(fn, e, tv)
+	}
+	if fn.debugInfo() {
+		emitDebugRef(fn, e, v, false)
+	}
+	return v
+}
+
+func (b *builder) expr0(fn *Function, e ast.Expr, tv types.TypeAndValue) Value {
+	switch e := e.(type) {
+	case *ast.BasicLit:
+		panic("non-constant BasicLit") // unreachable
+
+	case *ast.FuncLit:
+		fn2 := &Function{
+			name:      fmt.Sprintf("%s$%d", fn.Name(), 1+len(fn.AnonFuncs)),
+			Signature: fn.Pkg.typeOf(e.Type).Underlying().(*types.Signature),
+			pos:       e.Type.Func,
+			parent:    fn,
+			Pkg:       fn.Pkg,
+			Prog:      fn.Prog,
+			syntax:    e,
+		}
+		fn.AnonFuncs = append(fn.AnonFuncs, fn2)
+		b.buildFunction(fn2)
+		if fn2.FreeVars == nil {
+			return fn2
+		}
+		v := &MakeClosure{Fn: fn2}
+		v.setType(tv.Type)
+		for _, fv := range fn2.FreeVars {
+			v.Bindings = append(v.Bindings, fv.outer)
+			fv.outer = nil
+		}
+		return fn.emit(v)
+
+	case *ast.TypeAssertExpr: // single-result form only
+		return emitTypeAssert(fn, b.expr(fn, e.X), tv.Type, e.Lparen)
+
+	case *ast.CallExpr:
+		if fn.Pkg.info.Types[e.Fun].IsType() {
+			// Explicit type conversion, e.g. string(x) or big.Int(x)
+			x := b.expr(fn, e.Args[0])
+			y := emitConv(fn, x, tv.Type)
+			if y != x {
+				switch y := y.(type) {
+				case *Convert:
+					y.pos = e.Lparen
+				case *ChangeType:
+					y.pos = e.Lparen
+				case *MakeInterface:
+					y.pos = e.Lparen
+				}
+			}
+			return y
+		}
+		// Call to "intrinsic" built-ins, e.g. new, make, panic.
+		if id, ok := unparen(e.Fun).(*ast.Ident); ok {
+			if obj, ok := fn.Pkg.info.Uses[id].(*types.Builtin); ok {
+				if v := b.builtin(fn, obj, e.Args, tv.Type, e.Lparen); v != nil {
+					return v
+				}
+			}
+		}
+		// Regular function call.
+		var v Call
+		b.setCall(fn, e, &v.Call)
+		v.setType(tv.Type)
+		return fn.emit(&v)
+
+	case *ast.UnaryExpr:
+		switch e.Op {
+		case token.AND: // &X --- potentially escaping.
+			addr := b.addr(fn, e.X, true)
+			if _, ok := unparen(e.X).(*ast.StarExpr); ok {
+				// &*p must panic if p is nil (http://golang.org/s/go12nil).
+				// For simplicity, we'll just (suboptimally) rely
+				// on the side effects of a load.
+				// TODO(adonovan): emit dedicated nilcheck.
+				addr.load(fn)
+			}
+			return addr.address(fn)
+		case token.ADD:
+			return b.expr(fn, e.X)
+		case token.NOT, token.ARROW, token.SUB, token.XOR: // ! <- - ^
+			v := &UnOp{
+				Op: e.Op,
+				X:  b.expr(fn, e.X),
+			}
+			v.setPos(e.OpPos)
+			v.setType(tv.Type)
+			return fn.emit(v)
+		default:
+			panic(e.Op)
+		}
+
+	case *ast.BinaryExpr:
+		switch e.Op {
+		case token.LAND, token.LOR:
+			return b.logicalBinop(fn, e)
+		case token.SHL, token.SHR:
+			fallthrough
+		case token.ADD, token.SUB, token.MUL, token.QUO, token.REM, token.AND, token.OR, token.XOR, token.AND_NOT:
+			return emitArith(fn, e.Op, b.expr(fn, e.X), b.expr(fn, e.Y), tv.Type, e.OpPos)
+
+		case token.EQL, token.NEQ, token.GTR, token.LSS, token.LEQ, token.GEQ:
+			cmp := emitCompare(fn, e.Op, b.expr(fn, e.X), b.expr(fn, e.Y), e.OpPos)
+			// The type of x==y may be UntypedBool.
+			return emitConv(fn, cmp, DefaultType(tv.Type))
+		default:
+			panic("illegal op in BinaryExpr: " + e.Op.String())
+		}
+
+	case *ast.SliceExpr:
+		var low, high, max Value
+		var x Value
+		switch fn.Pkg.typeOf(e.X).Underlying().(type) {
+		case *types.Array:
+			// Potentially escaping.
+			x = b.addr(fn, e.X, true).address(fn)
+		case *types.Basic, *types.Slice, *types.Pointer: // *array
+			x = b.expr(fn, e.X)
+		default:
+			panic("unreachable")
+		}
+		if e.High != nil {
+			high = b.expr(fn, e.High)
+		}
+		if e.Low != nil {
+			low = b.expr(fn, e.Low)
+		}
+		if e.Slice3 {
+			max = b.expr(fn, e.Max)
+		}
+		v := &Slice{
+			X:    x,
+			Low:  low,
+			High: high,
+			Max:  max,
+		}
+		v.setPos(e.Lbrack)
+		v.setType(tv.Type)
+		return fn.emit(v)
+
+	case *ast.Ident:
+		obj := fn.Pkg.info.Uses[e]
+		// Universal built-in or nil?
+		switch obj := obj.(type) {
+		case *types.Builtin:
+			return &Builtin{name: obj.Name(), sig: tv.Type.(*types.Signature)}
+		case *types.Nil:
+			return nilConst(tv.Type)
+		}
+		// Package-level func or var?
+		if v := fn.Prog.packageLevelValue(obj); v != nil {
+			if _, ok := obj.(*types.Var); ok {
+				return emitLoad(fn, v) // var (address)
+			}
+			return v // (func)
+		}
+		// Local var.
+		return emitLoad(fn, fn.lookup(obj, false)) // var (address)
+
+	case *ast.SelectorExpr:
+		sel, ok := fn.Pkg.info.Selections[e]
+		if !ok {
+			// qualified identifier
+			return b.expr(fn, e.Sel)
+		}
+		switch sel.Kind() {
+		case types.MethodExpr:
+			// (*T).f or T.f, the method f from the method-set of type T.
+			// The result is a "thunk".
+			return emitConv(fn, makeThunk(fn.Prog, sel), tv.Type)
+
+		case types.MethodVal:
+			// e.f where e is an expression and f is a method.
+			// The result is a "bound".
+			obj := sel.Obj().(*types.Func)
+			rt := recvType(obj)
+			wantAddr := isPointer(rt)
+			escaping := true
+			v := b.receiver(fn, e.X, wantAddr, escaping, sel)
+			if isInterface(rt) {
+				// If v has interface type I,
+				// we must emit a check that v is non-nil.
+				// We use: typeassert v.(I).
+				emitTypeAssert(fn, v, rt, token.NoPos)
+			}
+			c := &MakeClosure{
+				Fn:       makeBound(fn.Prog, obj),
+				Bindings: []Value{v},
+			}
+			c.setPos(e.Sel.Pos())
+			c.setType(tv.Type)
+			return fn.emit(c)
+
+		case types.FieldVal:
+			indices := sel.Index()
+			last := len(indices) - 1
+			v := b.expr(fn, e.X)
+			v = emitImplicitSelections(fn, v, indices[:last])
+			v = emitFieldSelection(fn, v, indices[last], false, e.Sel)
+			return v
+		}
+
+		panic("unexpected expression-relative selector")
+
+	case *ast.IndexExpr:
+		switch t := fn.Pkg.typeOf(e.X).Underlying().(type) {
+		case *types.Array:
+			// Non-addressable array (in a register).
+			v := &Index{
+				X:     b.expr(fn, e.X),
+				Index: emitConv(fn, b.expr(fn, e.Index), tInt),
+			}
+			v.setPos(e.Lbrack)
+			v.setType(t.Elem())
+			return fn.emit(v)
+
+		case *types.Map:
+			// Maps are not addressable.
+			mapt := fn.Pkg.typeOf(e.X).Underlying().(*types.Map)
+			v := &Lookup{
+				X:     b.expr(fn, e.X),
+				Index: emitConv(fn, b.expr(fn, e.Index), mapt.Key()),
+			}
+			v.setPos(e.Lbrack)
+			v.setType(mapt.Elem())
+			return fn.emit(v)
+
+		case *types.Basic: // => string
+			// Strings are not addressable.
+			v := &Lookup{
+				X:     b.expr(fn, e.X),
+				Index: b.expr(fn, e.Index),
+			}
+			v.setPos(e.Lbrack)
+			v.setType(tByte)
+			return fn.emit(v)
+
+		case *types.Slice, *types.Pointer: // *array
+			// Addressable slice/array; use IndexAddr and Load.
+			return b.addr(fn, e, false).load(fn)
+
+		default:
+			panic("unexpected container type in IndexExpr: " + t.String())
+		}
+
+	case *ast.CompositeLit, *ast.StarExpr:
+		// Addressable types (lvalues)
+		return b.addr(fn, e, false).load(fn)
+	}
+
+	panic(fmt.Sprintf("unexpected expr: %T", e))
+}
+
+// stmtList emits to fn code for all statements in list.
+func (b *builder) stmtList(fn *Function, list []ast.Stmt) {
+	for _, s := range list {
+		b.stmt(fn, s)
+	}
+}
+
+// receiver emits to fn code for expression e in the "receiver"
+// position of selection e.f (where f may be a field or a method) and
+// returns the effective receiver after applying the implicit field
+// selections of sel.
+//
+// wantAddr requests that the result is an an address.  If
+// !sel.Indirect(), this may require that e be built in addr() mode; it
+// must thus be addressable.
+//
+// escaping is defined as per builder.addr().
+//
+func (b *builder) receiver(fn *Function, e ast.Expr, wantAddr, escaping bool, sel *types.Selection) Value {
+	var v Value
+	if wantAddr && !sel.Indirect() && !isPointer(fn.Pkg.typeOf(e)) {
+		v = b.addr(fn, e, escaping).address(fn)
+	} else {
+		v = b.expr(fn, e)
+	}
+
+	last := len(sel.Index()) - 1
+	v = emitImplicitSelections(fn, v, sel.Index()[:last])
+	if !wantAddr && isPointer(v.Type()) {
+		v = emitLoad(fn, v)
+	}
+	return v
+}
+
+// setCallFunc populates the function parts of a CallCommon structure
+// (Func, Method, Recv, Args[0]) based on the kind of invocation
+// occurring in e.
+//
+func (b *builder) setCallFunc(fn *Function, e *ast.CallExpr, c *CallCommon) {
+	c.pos = e.Lparen
+
+	// Is this a method call?
+	if selector, ok := unparen(e.Fun).(*ast.SelectorExpr); ok {
+		sel, ok := fn.Pkg.info.Selections[selector]
+		if ok && sel.Kind() == types.MethodVal {
+			obj := sel.Obj().(*types.Func)
+			recv := recvType(obj)
+			wantAddr := isPointer(recv)
+			escaping := true
+			v := b.receiver(fn, selector.X, wantAddr, escaping, sel)
+			if isInterface(recv) {
+				// Invoke-mode call.
+				c.Value = v
+				c.Method = obj
+			} else {
+				// "Call"-mode call.
+				c.Value = fn.Prog.declaredFunc(obj)
+				c.Args = append(c.Args, v)
+			}
+			return
+		}
+
+		// sel.Kind()==MethodExpr indicates T.f() or (*T).f():
+		// a statically dispatched call to the method f in the
+		// method-set of T or *T.  T may be an interface.
+		//
+		// e.Fun would evaluate to a concrete method, interface
+		// wrapper function, or promotion wrapper.
+		//
+		// For now, we evaluate it in the usual way.
+		//
+		// TODO(adonovan): opt: inline expr() here, to make the
+		// call static and to avoid generation of wrappers.
+		// It's somewhat tricky as it may consume the first
+		// actual parameter if the call is "invoke" mode.
+		//
+		// Examples:
+		//  type T struct{}; func (T) f() {}   // "call" mode
+		//  type T interface { f() }           // "invoke" mode
+		//
+		//  type S struct{ T }
+		//
+		//  var s S
+		//  S.f(s)
+		//  (*S).f(&s)
+		//
+		// Suggested approach:
+		// - consume the first actual parameter expression
+		//   and build it with b.expr().
+		// - apply implicit field selections.
+		// - use MethodVal logic to populate fields of c.
+	}
+
+	// Evaluate the function operand in the usual way.
+	c.Value = b.expr(fn, e.Fun)
+}
+
+// emitCallArgs emits to f code for the actual parameters of call e to
+// a (possibly built-in) function of effective type sig.
+// The argument values are appended to args, which is then returned.
+//
+func (b *builder) emitCallArgs(fn *Function, sig *types.Signature, e *ast.CallExpr, args []Value) []Value {
+	// f(x, y, z...): pass slice z straight through.
+	if e.Ellipsis != 0 {
+		for i, arg := range e.Args {
+			v := emitConv(fn, b.expr(fn, arg), sig.Params().At(i).Type())
+			args = append(args, v)
+		}
+		return args
+	}
+
+	offset := len(args) // 1 if call has receiver, 0 otherwise
+
+	// Evaluate actual parameter expressions.
+	//
+	// If this is a chained call of the form f(g()) where g has
+	// multiple return values (MRV), they are flattened out into
+	// args; a suffix of them may end up in a varargs slice.
+	for _, arg := range e.Args {
+		v := b.expr(fn, arg)
+		if ttuple, ok := v.Type().(*types.Tuple); ok { // MRV chain
+			for i, n := 0, ttuple.Len(); i < n; i++ {
+				args = append(args, emitExtract(fn, v, i))
+			}
+		} else {
+			args = append(args, v)
+		}
+	}
+
+	// Actual->formal assignability conversions for normal parameters.
+	np := sig.Params().Len() // number of normal parameters
+	if sig.Variadic() {
+		np--
+	}
+	for i := 0; i < np; i++ {
+		args[offset+i] = emitConv(fn, args[offset+i], sig.Params().At(i).Type())
+	}
+
+	// Actual->formal assignability conversions for variadic parameter,
+	// and construction of slice.
+	if sig.Variadic() {
+		varargs := args[offset+np:]
+		st := sig.Params().At(np).Type().(*types.Slice)
+		vt := st.Elem()
+		if len(varargs) == 0 {
+			args = append(args, nilConst(st))
+		} else {
+			// Replace a suffix of args with a slice containing it.
+			at := types.NewArray(vt, int64(len(varargs)))
+			a := emitNew(fn, at, token.NoPos)
+			a.setPos(e.Rparen)
+			a.Comment = "varargs"
+			for i, arg := range varargs {
+				iaddr := &IndexAddr{
+					X:     a,
+					Index: intConst(int64(i)),
+				}
+				iaddr.setType(types.NewPointer(vt))
+				fn.emit(iaddr)
+				emitStore(fn, iaddr, arg, arg.Pos())
+			}
+			s := &Slice{X: a}
+			s.setType(st)
+			args[offset+np] = fn.emit(s)
+			args = args[:offset+np+1]
+		}
+	}
+	return args
+}
+
+// setCall emits to fn code to evaluate all the parameters of a function
+// call e, and populates *c with those values.
+//
+func (b *builder) setCall(fn *Function, e *ast.CallExpr, c *CallCommon) {
+	// First deal with the f(...) part and optional receiver.
+	b.setCallFunc(fn, e, c)
+
+	// Then append the other actual parameters.
+	sig, _ := fn.Pkg.typeOf(e.Fun).Underlying().(*types.Signature)
+	if sig == nil {
+		panic(fmt.Sprintf("no signature for call of %s", e.Fun))
+	}
+	c.Args = b.emitCallArgs(fn, sig, e, c.Args)
+}
+
+// assignOp emits to fn code to perform loc += incr or loc -= incr.
+func (b *builder) assignOp(fn *Function, loc lvalue, incr Value, op token.Token) {
+	oldv := loc.load(fn)
+	loc.store(fn, emitArith(fn, op, oldv, emitConv(fn, incr, oldv.Type()), loc.typ(), token.NoPos))
+}
+
+// localValueSpec emits to fn code to define all of the vars in the
+// function-local ValueSpec, spec.
+//
+func (b *builder) localValueSpec(fn *Function, spec *ast.ValueSpec) {
+	switch {
+	case len(spec.Values) == len(spec.Names):
+		// e.g. var x, y = 0, 1
+		// 1:1 assignment
+		for i, id := range spec.Names {
+			if !isBlankIdent(id) {
+				fn.addLocalForIdent(id)
+			}
+			lval := b.addr(fn, id, false) // non-escaping
+			b.assign(fn, lval, spec.Values[i], true, nil)
+		}
+
+	case len(spec.Values) == 0:
+		// e.g. var x, y int
+		// Locals are implicitly zero-initialized.
+		for _, id := range spec.Names {
+			if !isBlankIdent(id) {
+				lhs := fn.addLocalForIdent(id)
+				if fn.debugInfo() {
+					emitDebugRef(fn, id, lhs, true)
+				}
+			}
+		}
+
+	default:
+		// e.g. var x, y = pos()
+		tuple := b.exprN(fn, spec.Values[0])
+		for i, id := range spec.Names {
+			if !isBlankIdent(id) {
+				fn.addLocalForIdent(id)
+				lhs := b.addr(fn, id, false) // non-escaping
+				lhs.store(fn, emitExtract(fn, tuple, i))
+			}
+		}
+	}
+}
+
+// assignStmt emits code to fn for a parallel assignment of rhss to lhss.
+// isDef is true if this is a short variable declaration (:=).
+//
+// Note the similarity with localValueSpec.
+//
+func (b *builder) assignStmt(fn *Function, lhss, rhss []ast.Expr, isDef bool) {
+	// Side effects of all LHSs and RHSs must occur in left-to-right order.
+	lvals := make([]lvalue, len(lhss))
+	isZero := make([]bool, len(lhss))
+	for i, lhs := range lhss {
+		var lval lvalue = blank{}
+		if !isBlankIdent(lhs) {
+			if isDef {
+				if obj := fn.Pkg.info.Defs[lhs.(*ast.Ident)]; obj != nil {
+					fn.addNamedLocal(obj)
+					isZero[i] = true
+				}
+			}
+			lval = b.addr(fn, lhs, false) // non-escaping
+		}
+		lvals[i] = lval
+	}
+	if len(lhss) == len(rhss) {
+		// Simple assignment:   x     = f()        (!isDef)
+		// Parallel assignment: x, y  = f(), g()   (!isDef)
+		// or short var decl:   x, y := f(), g()   (isDef)
+		//
+		// In all cases, the RHSs may refer to the LHSs,
+		// so we need a storebuf.
+		var sb storebuf
+		for i := range rhss {
+			b.assign(fn, lvals[i], rhss[i], isZero[i], &sb)
+		}
+		sb.emit(fn)
+	} else {
+		// e.g. x, y = pos()
+		tuple := b.exprN(fn, rhss[0])
+		emitDebugRef(fn, rhss[0], tuple, false)
+		for i, lval := range lvals {
+			lval.store(fn, emitExtract(fn, tuple, i))
+		}
+	}
+}
+
+// arrayLen returns the length of the array whose composite literal elements are elts.
+func (b *builder) arrayLen(fn *Function, elts []ast.Expr) int64 {
+	var max int64 = -1
+	var i int64 = -1
+	for _, e := range elts {
+		if kv, ok := e.(*ast.KeyValueExpr); ok {
+			i = b.expr(fn, kv.Key).(*Const).Int64()
+		} else {
+			i++
+		}
+		if i > max {
+			max = i
+		}
+	}
+	return max + 1
+}
+
+// compLit emits to fn code to initialize a composite literal e at
+// address addr with type typ.
+//
+// Nested composite literals are recursively initialized in place
+// where possible. If isZero is true, compLit assumes that addr
+// holds the zero value for typ.
+//
+// Because the elements of a composite literal may refer to the
+// variables being updated, as in the second line below,
+//	x := T{a: 1}
+//	x = T{a: x.a}
+// all the reads must occur before all the writes.  Thus all stores to
+// loc are emitted to the storebuf sb for later execution.
+//
+// A CompositeLit may have pointer type only in the recursive (nested)
+// case when the type name is implicit.  e.g. in []*T{{}}, the inner
+// literal has type *T behaves like &T{}.
+// In that case, addr must hold a T, not a *T.
+//
+func (b *builder) compLit(fn *Function, addr Value, e *ast.CompositeLit, isZero bool, sb *storebuf) {
+	typ := deref(fn.Pkg.typeOf(e))
+	switch t := typ.Underlying().(type) {
+	case *types.Struct:
+		if !isZero && len(e.Elts) != t.NumFields() {
+			// memclear
+			sb.store(&address{addr, e.Lbrace, nil},
+				zeroValue(fn, deref(addr.Type())))
+			isZero = true
+		}
+		for i, e := range e.Elts {
+			fieldIndex := i
+			pos := e.Pos()
+			if kv, ok := e.(*ast.KeyValueExpr); ok {
+				fname := kv.Key.(*ast.Ident).Name
+				for i, n := 0, t.NumFields(); i < n; i++ {
+					sf := t.Field(i)
+					if sf.Name() == fname {
+						fieldIndex = i
+						pos = kv.Colon
+						e = kv.Value
+						break
+					}
+				}
+			}
+			sf := t.Field(fieldIndex)
+			faddr := &FieldAddr{
+				X:     addr,
+				Field: fieldIndex,
+			}
+			faddr.setType(types.NewPointer(sf.Type()))
+			fn.emit(faddr)
+			b.assign(fn, &address{addr: faddr, pos: pos, expr: e}, e, isZero, sb)
+		}
+
+	case *types.Array, *types.Slice:
+		var at *types.Array
+		var array Value
+		switch t := t.(type) {
+		case *types.Slice:
+			at = types.NewArray(t.Elem(), b.arrayLen(fn, e.Elts))
+			alloc := emitNew(fn, at, e.Lbrace)
+			alloc.Comment = "slicelit"
+			array = alloc
+		case *types.Array:
+			at = t
+			array = addr
+
+			if !isZero && int64(len(e.Elts)) != at.Len() {
+				// memclear
+				sb.store(&address{array, e.Lbrace, nil},
+					zeroValue(fn, deref(array.Type())))
+			}
+		}
+
+		var idx *Const
+		for _, e := range e.Elts {
+			pos := e.Pos()
+			if kv, ok := e.(*ast.KeyValueExpr); ok {
+				idx = b.expr(fn, kv.Key).(*Const)
+				pos = kv.Colon
+				e = kv.Value
+			} else {
+				var idxval int64
+				if idx != nil {
+					idxval = idx.Int64() + 1
+				}
+				idx = intConst(idxval)
+			}
+			iaddr := &IndexAddr{
+				X:     array,
+				Index: idx,
+			}
+			iaddr.setType(types.NewPointer(at.Elem()))
+			fn.emit(iaddr)
+			if t != at { // slice
+				// backing array is unaliased => storebuf not needed.
+				b.assign(fn, &address{addr: iaddr, pos: pos, expr: e}, e, true, nil)
+			} else {
+				b.assign(fn, &address{addr: iaddr, pos: pos, expr: e}, e, true, sb)
+			}
+		}
+
+		if t != at { // slice
+			s := &Slice{X: array}
+			s.setPos(e.Lbrace)
+			s.setType(typ)
+			sb.store(&address{addr: addr, pos: e.Lbrace, expr: e}, fn.emit(s))
+		}
+
+	case *types.Map:
+		m := &MakeMap{Reserve: intConst(int64(len(e.Elts)))}
+		m.setPos(e.Lbrace)
+		m.setType(typ)
+		fn.emit(m)
+		for _, e := range e.Elts {
+			e := e.(*ast.KeyValueExpr)
+
+			// If a key expression in a map literal is  itself a
+			// composite literal, the type may be omitted.
+			// For example:
+			//	map[*struct{}]bool{{}: true}
+			// An &-operation may be implied:
+			//	map[*struct{}]bool{&struct{}{}: true}
+			var key Value
+			if _, ok := unparen(e.Key).(*ast.CompositeLit); ok && isPointer(t.Key()) {
+				// A CompositeLit never evaluates to a pointer,
+				// so if the type of the location is a pointer,
+				// an &-operation is implied.
+				key = b.addr(fn, e.Key, true).address(fn)
+			} else {
+				key = b.expr(fn, e.Key)
+			}
+
+			loc := element{
+				m:   m,
+				k:   emitConv(fn, key, t.Key()),
+				t:   t.Elem(),
+				pos: e.Colon,
+			}
+
+			// We call assign() only because it takes care
+			// of any &-operation required in the recursive
+			// case, e.g.,
+			// map[int]*struct{}{0: {}} implies &struct{}{}.
+			// In-place update is of course impossible,
+			// and no storebuf is needed.
+			b.assign(fn, &loc, e.Value, true, nil)
+		}
+		sb.store(&address{addr: addr, pos: e.Lbrace, expr: e}, m)
+
+	default:
+		panic("unexpected CompositeLit type: " + t.String())
+	}
+}
+
+// switchStmt emits to fn code for the switch statement s, optionally
+// labelled by label.
+//
+func (b *builder) switchStmt(fn *Function, s *ast.SwitchStmt, label *lblock) {
+	// We treat SwitchStmt like a sequential if-else chain.
+	// Multiway dispatch can be recovered later by ssautil.Switches()
+	// to those cases that are free of side effects.
+	if s.Init != nil {
+		b.stmt(fn, s.Init)
+	}
+	var tag Value = vTrue
+	if s.Tag != nil {
+		tag = b.expr(fn, s.Tag)
+	}
+	done := fn.newBasicBlock("switch.done")
+	if label != nil {
+		label._break = done
+	}
+	// We pull the default case (if present) down to the end.
+	// But each fallthrough label must point to the next
+	// body block in source order, so we preallocate a
+	// body block (fallthru) for the next case.
+	// Unfortunately this makes for a confusing block order.
+	var dfltBody *[]ast.Stmt
+	var dfltFallthrough *BasicBlock
+	var fallthru, dfltBlock *BasicBlock
+	ncases := len(s.Body.List)
+	for i, clause := range s.Body.List {
+		body := fallthru
+		if body == nil {
+			body = fn.newBasicBlock("switch.body") // first case only
+		}
+
+		// Preallocate body block for the next case.
+		fallthru = done
+		if i+1 < ncases {
+			fallthru = fn.newBasicBlock("switch.body")
+		}
+
+		cc := clause.(*ast.CaseClause)
+		if cc.List == nil {
+			// Default case.
+			dfltBody = &cc.Body
+			dfltFallthrough = fallthru
+			dfltBlock = body
+			continue
+		}
+
+		var nextCond *BasicBlock
+		for _, cond := range cc.List {
+			nextCond = fn.newBasicBlock("switch.next")
+			// TODO(adonovan): opt: when tag==vTrue, we'd
+			// get better code if we use b.cond(cond)
+			// instead of BinOp(EQL, tag, b.expr(cond))
+			// followed by If.  Don't forget conversions
+			// though.
+			cond := emitCompare(fn, token.EQL, tag, b.expr(fn, cond), token.NoPos)
+			emitIf(fn, cond, body, nextCond)
+			fn.currentBlock = nextCond
+		}
+		fn.currentBlock = body
+		fn.targets = &targets{
+			tail:         fn.targets,
+			_break:       done,
+			_fallthrough: fallthru,
+		}
+		b.stmtList(fn, cc.Body)
+		fn.targets = fn.targets.tail
+		emitJump(fn, done)
+		fn.currentBlock = nextCond
+	}
+	if dfltBlock != nil {
+		emitJump(fn, dfltBlock)
+		fn.currentBlock = dfltBlock
+		fn.targets = &targets{
+			tail:         fn.targets,
+			_break:       done,
+			_fallthrough: dfltFallthrough,
+		}
+		b.stmtList(fn, *dfltBody)
+		fn.targets = fn.targets.tail
+	}
+	emitJump(fn, done)
+	fn.currentBlock = done
+}
+
+// typeSwitchStmt emits to fn code for the type switch statement s, optionally
+// labelled by label.
+//
+func (b *builder) typeSwitchStmt(fn *Function, s *ast.TypeSwitchStmt, label *lblock) {
+	// We treat TypeSwitchStmt like a sequential if-else chain.
+	// Multiway dispatch can be recovered later by ssautil.Switches().
+
+	// Typeswitch lowering:
+	//
+	// var x X
+	// switch y := x.(type) {
+	// case T1, T2: S1                  // >1 	(y := x)
+	// case nil:    SN                  // nil 	(y := x)
+	// default:     SD                  // 0 types 	(y := x)
+	// case T3:     S3                  // 1 type 	(y := x.(T3))
+	// }
+	//
+	//      ...s.Init...
+	// 	x := eval x
+	// .caseT1:
+	// 	t1, ok1 := typeswitch,ok x <T1>
+	// 	if ok1 then goto S1 else goto .caseT2
+	// .caseT2:
+	// 	t2, ok2 := typeswitch,ok x <T2>
+	// 	if ok2 then goto S1 else goto .caseNil
+	// .S1:
+	//      y := x
+	// 	...S1...
+	// 	goto done
+	// .caseNil:
+	// 	if t2, ok2 := typeswitch,ok x <T2>
+	// 	if x == nil then goto SN else goto .caseT3
+	// .SN:
+	//      y := x
+	// 	...SN...
+	// 	goto done
+	// .caseT3:
+	// 	t3, ok3 := typeswitch,ok x <T3>
+	// 	if ok3 then goto S3 else goto default
+	// .S3:
+	//      y := t3
+	// 	...S3...
+	// 	goto done
+	// .default:
+	//      y := x
+	// 	...SD...
+	// 	goto done
+	// .done:
+
+	if s.Init != nil {
+		b.stmt(fn, s.Init)
+	}
+
+	var x Value
+	switch ass := s.Assign.(type) {
+	case *ast.ExprStmt: // x.(type)
+		x = b.expr(fn, unparen(ass.X).(*ast.TypeAssertExpr).X)
+	case *ast.AssignStmt: // y := x.(type)
+		x = b.expr(fn, unparen(ass.Rhs[0]).(*ast.TypeAssertExpr).X)
+	}
+
+	done := fn.newBasicBlock("typeswitch.done")
+	if label != nil {
+		label._break = done
+	}
+	var default_ *ast.CaseClause
+	for _, clause := range s.Body.List {
+		cc := clause.(*ast.CaseClause)
+		if cc.List == nil {
+			default_ = cc
+			continue
+		}
+		body := fn.newBasicBlock("typeswitch.body")
+		var next *BasicBlock
+		var casetype types.Type
+		var ti Value // ti, ok := typeassert,ok x <Ti>
+		for _, cond := range cc.List {
+			next = fn.newBasicBlock("typeswitch.next")
+			casetype = fn.Pkg.typeOf(cond)
+			var condv Value
+			if casetype == tUntypedNil {
+				condv = emitCompare(fn, token.EQL, x, nilConst(x.Type()), token.NoPos)
+				ti = x
+			} else {
+				yok := emitTypeTest(fn, x, casetype, cc.Case)
+				ti = emitExtract(fn, yok, 0)
+				condv = emitExtract(fn, yok, 1)
+			}
+			emitIf(fn, condv, body, next)
+			fn.currentBlock = next
+		}
+		if len(cc.List) != 1 {
+			ti = x
+		}
+		fn.currentBlock = body
+		b.typeCaseBody(fn, cc, ti, done)
+		fn.currentBlock = next
+	}
+	if default_ != nil {
+		b.typeCaseBody(fn, default_, x, done)
+	} else {
+		emitJump(fn, done)
+	}
+	fn.currentBlock = done
+}
+
+func (b *builder) typeCaseBody(fn *Function, cc *ast.CaseClause, x Value, done *BasicBlock) {
+	if obj := fn.Pkg.info.Implicits[cc]; obj != nil {
+		// In a switch y := x.(type), each case clause
+		// implicitly declares a distinct object y.
+		// In a single-type case, y has that type.
+		// In multi-type cases, 'case nil' and default,
+		// y has the same type as the interface operand.
+		emitStore(fn, fn.addNamedLocal(obj), x, obj.Pos())
+	}
+	fn.targets = &targets{
+		tail:   fn.targets,
+		_break: done,
+	}
+	b.stmtList(fn, cc.Body)
+	fn.targets = fn.targets.tail
+	emitJump(fn, done)
+}
+
+// selectStmt emits to fn code for the select statement s, optionally
+// labelled by label.
+//
+func (b *builder) selectStmt(fn *Function, s *ast.SelectStmt, label *lblock) {
+	// A blocking select of a single case degenerates to a
+	// simple send or receive.
+	// TODO(adonovan): opt: is this optimization worth its weight?
+	if len(s.Body.List) == 1 {
+		clause := s.Body.List[0].(*ast.CommClause)
+		if clause.Comm != nil {
+			b.stmt(fn, clause.Comm)
+			done := fn.newBasicBlock("select.done")
+			if label != nil {
+				label._break = done
+			}
+			fn.targets = &targets{
+				tail:   fn.targets,
+				_break: done,
+			}
+			b.stmtList(fn, clause.Body)
+			fn.targets = fn.targets.tail
+			emitJump(fn, done)
+			fn.currentBlock = done
+			return
+		}
+	}
+
+	// First evaluate all channels in all cases, and find
+	// the directions of each state.
+	var states []*SelectState
+	blocking := true
+	debugInfo := fn.debugInfo()
+	for _, clause := range s.Body.List {
+		var st *SelectState
+		switch comm := clause.(*ast.CommClause).Comm.(type) {
+		case nil: // default case
+			blocking = false
+			continue
+
+		case *ast.SendStmt: // ch<- i
+			ch := b.expr(fn, comm.Chan)
+			st = &SelectState{
+				Dir:  types.SendOnly,
+				Chan: ch,
+				Send: emitConv(fn, b.expr(fn, comm.Value),
+					ch.Type().Underlying().(*types.Chan).Elem()),
+				Pos: comm.Arrow,
+			}
+			if debugInfo {
+				st.DebugNode = comm
+			}
+
+		case *ast.AssignStmt: // x := <-ch
+			recv := unparen(comm.Rhs[0]).(*ast.UnaryExpr)
+			st = &SelectState{
+				Dir:  types.RecvOnly,
+				Chan: b.expr(fn, recv.X),
+				Pos:  recv.OpPos,
+			}
+			if debugInfo {
+				st.DebugNode = recv
+			}
+
+		case *ast.ExprStmt: // <-ch
+			recv := unparen(comm.X).(*ast.UnaryExpr)
+			st = &SelectState{
+				Dir:  types.RecvOnly,
+				Chan: b.expr(fn, recv.X),
+				Pos:  recv.OpPos,
+			}
+			if debugInfo {
+				st.DebugNode = recv
+			}
+		}
+		states = append(states, st)
+	}
+
+	// We dispatch on the (fair) result of Select using a
+	// sequential if-else chain, in effect:
+	//
+	// idx, recvOk, r0...r_n-1 := select(...)
+	// if idx == 0 {  // receive on channel 0  (first receive => r0)
+	//     x, ok := r0, recvOk
+	//     ...state0...
+	// } else if v == 1 {   // send on channel 1
+	//     ...state1...
+	// } else {
+	//     ...default...
+	// }
+	sel := &Select{
+		States:   states,
+		Blocking: blocking,
+	}
+	sel.setPos(s.Select)
+	var vars []*types.Var
+	vars = append(vars, varIndex, varOk)
+	for _, st := range states {
+		if st.Dir == types.RecvOnly {
+			tElem := st.Chan.Type().Underlying().(*types.Chan).Elem()
+			vars = append(vars, anonVar(tElem))
+		}
+	}
+	sel.setType(types.NewTuple(vars...))
+
+	fn.emit(sel)
+	idx := emitExtract(fn, sel, 0)
+
+	done := fn.newBasicBlock("select.done")
+	if label != nil {
+		label._break = done
+	}
+
+	var defaultBody *[]ast.Stmt
+	state := 0
+	r := 2 // index in 'sel' tuple of value; increments if st.Dir==RECV
+	for _, cc := range s.Body.List {
+		clause := cc.(*ast.CommClause)
+		if clause.Comm == nil {
+			defaultBody = &clause.Body
+			continue
+		}
+		body := fn.newBasicBlock("select.body")
+		next := fn.newBasicBlock("select.next")
+		emitIf(fn, emitCompare(fn, token.EQL, idx, intConst(int64(state)), token.NoPos), body, next)
+		fn.currentBlock = body
+		fn.targets = &targets{
+			tail:   fn.targets,
+			_break: done,
+		}
+		switch comm := clause.Comm.(type) {
+		case *ast.ExprStmt: // <-ch
+			if debugInfo {
+				v := emitExtract(fn, sel, r)
+				emitDebugRef(fn, states[state].DebugNode.(ast.Expr), v, false)
+			}
+			r++
+
+		case *ast.AssignStmt: // x := <-states[state].Chan
+			if comm.Tok == token.DEFINE {
+				fn.addLocalForIdent(comm.Lhs[0].(*ast.Ident))
+			}
+			x := b.addr(fn, comm.Lhs[0], false) // non-escaping
+			v := emitExtract(fn, sel, r)
+			if debugInfo {
+				emitDebugRef(fn, states[state].DebugNode.(ast.Expr), v, false)
+			}
+			x.store(fn, v)
+
+			if len(comm.Lhs) == 2 { // x, ok := ...
+				if comm.Tok == token.DEFINE {
+					fn.addLocalForIdent(comm.Lhs[1].(*ast.Ident))
+				}
+				ok := b.addr(fn, comm.Lhs[1], false) // non-escaping
+				ok.store(fn, emitExtract(fn, sel, 1))
+			}
+			r++
+		}
+		b.stmtList(fn, clause.Body)
+		fn.targets = fn.targets.tail
+		emitJump(fn, done)
+		fn.currentBlock = next
+		state++
+	}
+	if defaultBody != nil {
+		fn.targets = &targets{
+			tail:   fn.targets,
+			_break: done,
+		}
+		b.stmtList(fn, *defaultBody)
+		fn.targets = fn.targets.tail
+	} else {
+		// A blocking select must match some case.
+		// (This should really be a runtime.errorString, not a string.)
+		fn.emit(&Panic{
+			X: emitConv(fn, stringConst("blocking select matched no case"), tEface),
+		})
+		fn.currentBlock = fn.newBasicBlock("unreachable")
+	}
+	emitJump(fn, done)
+	fn.currentBlock = done
+}
+
+// forStmt emits to fn code for the for statement s, optionally
+// labelled by label.
+//
+func (b *builder) forStmt(fn *Function, s *ast.ForStmt, label *lblock) {
+	//	...init...
+	//      jump loop
+	// loop:
+	//      if cond goto body else done
+	// body:
+	//      ...body...
+	//      jump post
+	// post:				 (target of continue)
+	//      ...post...
+	//      jump loop
+	// done:                                 (target of break)
+	if s.Init != nil {
+		b.stmt(fn, s.Init)
+	}
+	body := fn.newBasicBlock("for.body")
+	done := fn.newBasicBlock("for.done") // target of 'break'
+	loop := body                         // target of back-edge
+	if s.Cond != nil {
+		loop = fn.newBasicBlock("for.loop")
+	}
+	cont := loop // target of 'continue'
+	if s.Post != nil {
+		cont = fn.newBasicBlock("for.post")
+	}
+	if label != nil {
+		label._break = done
+		label._continue = cont
+	}
+	emitJump(fn, loop)
+	fn.currentBlock = loop
+	if loop != body {
+		b.cond(fn, s.Cond, body, done)
+		fn.currentBlock = body
+	}
+	fn.targets = &targets{
+		tail:      fn.targets,
+		_break:    done,
+		_continue: cont,
+	}
+	b.stmt(fn, s.Body)
+	fn.targets = fn.targets.tail
+	emitJump(fn, cont)
+
+	if s.Post != nil {
+		fn.currentBlock = cont
+		b.stmt(fn, s.Post)
+		emitJump(fn, loop) // back-edge
+	}
+	fn.currentBlock = done
+}
+
+// rangeIndexed emits to fn the header for an integer-indexed loop
+// over array, *array or slice value x.
+// The v result is defined only if tv is non-nil.
+// forPos is the position of the "for" token.
+//
+func (b *builder) rangeIndexed(fn *Function, x Value, tv types.Type, pos token.Pos) (k, v Value, loop, done *BasicBlock) {
+	//
+	//      length = len(x)
+	//      index = -1
+	// loop:                                   (target of continue)
+	//      index++
+	// 	if index < length goto body else done
+	// body:
+	//      k = index
+	//      v = x[index]
+	//      ...body...
+	// 	jump loop
+	// done:                                   (target of break)
+
+	// Determine number of iterations.
+	var length Value
+	if arr, ok := deref(x.Type()).Underlying().(*types.Array); ok {
+		// For array or *array, the number of iterations is
+		// known statically thanks to the type.  We avoid a
+		// data dependence upon x, permitting later dead-code
+		// elimination if x is pure, static unrolling, etc.
+		// Ranging over a nil *array may have >0 iterations.
+		// We still generate code for x, in case it has effects.
+		length = intConst(arr.Len())
+	} else {
+		// length = len(x).
+		var c Call
+		c.Call.Value = makeLen(x.Type())
+		c.Call.Args = []Value{x}
+		c.setType(tInt)
+		length = fn.emit(&c)
+	}
+
+	index := fn.addLocal(tInt, token.NoPos)
+	emitStore(fn, index, intConst(-1), pos)
+
+	loop = fn.newBasicBlock("rangeindex.loop")
+	emitJump(fn, loop)
+	fn.currentBlock = loop
+
+	incr := &BinOp{
+		Op: token.ADD,
+		X:  emitLoad(fn, index),
+		Y:  vOne,
+	}
+	incr.setType(tInt)
+	emitStore(fn, index, fn.emit(incr), pos)
+
+	body := fn.newBasicBlock("rangeindex.body")
+	done = fn.newBasicBlock("rangeindex.done")
+	emitIf(fn, emitCompare(fn, token.LSS, incr, length, token.NoPos), body, done)
+	fn.currentBlock = body
+
+	k = emitLoad(fn, index)
+	if tv != nil {
+		switch t := x.Type().Underlying().(type) {
+		case *types.Array:
+			instr := &Index{
+				X:     x,
+				Index: k,
+			}
+			instr.setType(t.Elem())
+			v = fn.emit(instr)
+
+		case *types.Pointer: // *array
+			instr := &IndexAddr{
+				X:     x,
+				Index: k,
+			}
+			instr.setType(types.NewPointer(t.Elem().Underlying().(*types.Array).Elem()))
+			v = emitLoad(fn, fn.emit(instr))
+
+		case *types.Slice:
+			instr := &IndexAddr{
+				X:     x,
+				Index: k,
+			}
+			instr.setType(types.NewPointer(t.Elem()))
+			v = emitLoad(fn, fn.emit(instr))
+
+		default:
+			panic("rangeIndexed x:" + t.String())
+		}
+	}
+	return
+}
+
+// rangeIter emits to fn the header for a loop using
+// Range/Next/Extract to iterate over map or string value x.
+// tk and tv are the types of the key/value results k and v, or nil
+// if the respective component is not wanted.
+//
+func (b *builder) rangeIter(fn *Function, x Value, tk, tv types.Type, pos token.Pos) (k, v Value, loop, done *BasicBlock) {
+	//
+	//	it = range x
+	// loop:                                   (target of continue)
+	//	okv = next it                      (ok, key, value)
+	//  	ok = extract okv #0
+	// 	if ok goto body else done
+	// body:
+	// 	k = extract okv #1
+	// 	v = extract okv #2
+	//      ...body...
+	// 	jump loop
+	// done:                                   (target of break)
+	//
+
+	if tk == nil {
+		tk = tInvalid
+	}
+	if tv == nil {
+		tv = tInvalid
+	}
+
+	rng := &Range{X: x}
+	rng.setPos(pos)
+	rng.setType(tRangeIter)
+	it := fn.emit(rng)
+
+	loop = fn.newBasicBlock("rangeiter.loop")
+	emitJump(fn, loop)
+	fn.currentBlock = loop
+
+	_, isString := x.Type().Underlying().(*types.Basic)
+
+	okv := &Next{
+		Iter:     it,
+		IsString: isString,
+	}
+	okv.setType(types.NewTuple(
+		varOk,
+		newVar("k", tk),
+		newVar("v", tv),
+	))
+	fn.emit(okv)
+
+	body := fn.newBasicBlock("rangeiter.body")
+	done = fn.newBasicBlock("rangeiter.done")
+	emitIf(fn, emitExtract(fn, okv, 0), body, done)
+	fn.currentBlock = body
+
+	if tk != tInvalid {
+		k = emitExtract(fn, okv, 1)
+	}
+	if tv != tInvalid {
+		v = emitExtract(fn, okv, 2)
+	}
+	return
+}
+
+// rangeChan emits to fn the header for a loop that receives from
+// channel x until it fails.
+// tk is the channel's element type, or nil if the k result is
+// not wanted
+// pos is the position of the '=' or ':=' token.
+//
+func (b *builder) rangeChan(fn *Function, x Value, tk types.Type, pos token.Pos) (k Value, loop, done *BasicBlock) {
+	//
+	// loop:                                   (target of continue)
+	//      ko = <-x                           (key, ok)
+	//      ok = extract ko #1
+	//      if ok goto body else done
+	// body:
+	//      k = extract ko #0
+	//      ...
+	//      goto loop
+	// done:                                   (target of break)
+
+	loop = fn.newBasicBlock("rangechan.loop")
+	emitJump(fn, loop)
+	fn.currentBlock = loop
+	recv := &UnOp{
+		Op:      token.ARROW,
+		X:       x,
+		CommaOk: true,
+	}
+	recv.setPos(pos)
+	recv.setType(types.NewTuple(
+		newVar("k", x.Type().Underlying().(*types.Chan).Elem()),
+		varOk,
+	))
+	ko := fn.emit(recv)
+	body := fn.newBasicBlock("rangechan.body")
+	done = fn.newBasicBlock("rangechan.done")
+	emitIf(fn, emitExtract(fn, ko, 1), body, done)
+	fn.currentBlock = body
+	if tk != nil {
+		k = emitExtract(fn, ko, 0)
+	}
+	return
+}
+
+// rangeStmt emits to fn code for the range statement s, optionally
+// labelled by label.
+//
+func (b *builder) rangeStmt(fn *Function, s *ast.RangeStmt, label *lblock) {
+	var tk, tv types.Type
+	if s.Key != nil && !isBlankIdent(s.Key) {
+		tk = fn.Pkg.typeOf(s.Key)
+	}
+	if s.Value != nil && !isBlankIdent(s.Value) {
+		tv = fn.Pkg.typeOf(s.Value)
+	}
+
+	// If iteration variables are defined (:=), this
+	// occurs once outside the loop.
+	//
+	// Unlike a short variable declaration, a RangeStmt
+	// using := never redeclares an existing variable; it
+	// always creates a new one.
+	if s.Tok == token.DEFINE {
+		if tk != nil {
+			fn.addLocalForIdent(s.Key.(*ast.Ident))
+		}
+		if tv != nil {
+			fn.addLocalForIdent(s.Value.(*ast.Ident))
+		}
+	}
+
+	x := b.expr(fn, s.X)
+
+	var k, v Value
+	var loop, done *BasicBlock
+	switch rt := x.Type().Underlying().(type) {
+	case *types.Slice, *types.Array, *types.Pointer: // *array
+		k, v, loop, done = b.rangeIndexed(fn, x, tv, s.For)
+
+	case *types.Chan:
+		k, loop, done = b.rangeChan(fn, x, tk, s.For)
+
+	case *types.Map, *types.Basic: // string
+		k, v, loop, done = b.rangeIter(fn, x, tk, tv, s.For)
+
+	default:
+		panic("Cannot range over: " + rt.String())
+	}
+
+	// Evaluate both LHS expressions before we update either.
+	var kl, vl lvalue
+	if tk != nil {
+		kl = b.addr(fn, s.Key, false) // non-escaping
+	}
+	if tv != nil {
+		vl = b.addr(fn, s.Value, false) // non-escaping
+	}
+	if tk != nil {
+		kl.store(fn, k)
+	}
+	if tv != nil {
+		vl.store(fn, v)
+	}
+
+	if label != nil {
+		label._break = done
+		label._continue = loop
+	}
+
+	fn.targets = &targets{
+		tail:      fn.targets,
+		_break:    done,
+		_continue: loop,
+	}
+	b.stmt(fn, s.Body)
+	fn.targets = fn.targets.tail
+	emitJump(fn, loop) // back-edge
+	fn.currentBlock = done
+}
+
+// stmt lowers statement s to SSA form, emitting code to fn.
+func (b *builder) stmt(fn *Function, _s ast.Stmt) {
+	// The label of the current statement.  If non-nil, its _goto
+	// target is always set; its _break and _continue are set only
+	// within the body of switch/typeswitch/select/for/range.
+	// It is effectively an additional default-nil parameter of stmt().
+	var label *lblock
+start:
+	switch s := _s.(type) {
+	case *ast.EmptyStmt:
+		// ignore.  (Usually removed by gofmt.)
+
+	case *ast.DeclStmt: // Con, Var or Typ
+		d := s.Decl.(*ast.GenDecl)
+		if d.Tok == token.VAR {
+			for _, spec := range d.Specs {
+				if vs, ok := spec.(*ast.ValueSpec); ok {
+					b.localValueSpec(fn, vs)
+				}
+			}
+		}
+
+	case *ast.LabeledStmt:
+		label = fn.labelledBlock(s.Label)
+		emitJump(fn, label._goto)
+		fn.currentBlock = label._goto
+		_s = s.Stmt
+		goto start // effectively: tailcall stmt(fn, s.Stmt, label)
+
+	case *ast.ExprStmt:
+		b.expr(fn, s.X)
+
+	case *ast.SendStmt:
+		fn.emit(&Send{
+			Chan: b.expr(fn, s.Chan),
+			X: emitConv(fn, b.expr(fn, s.Value),
+				fn.Pkg.typeOf(s.Chan).Underlying().(*types.Chan).Elem()),
+			pos: s.Arrow,
+		})
+
+	case *ast.IncDecStmt:
+		op := token.ADD
+		if s.Tok == token.DEC {
+			op = token.SUB
+		}
+		loc := b.addr(fn, s.X, false)
+		b.assignOp(fn, loc, NewConst(exact.MakeInt64(1), loc.typ()), op)
+
+	case *ast.AssignStmt:
+		switch s.Tok {
+		case token.ASSIGN, token.DEFINE:
+			b.assignStmt(fn, s.Lhs, s.Rhs, s.Tok == token.DEFINE)
+
+		default: // +=, etc.
+			op := s.Tok + token.ADD - token.ADD_ASSIGN
+			b.assignOp(fn, b.addr(fn, s.Lhs[0], false), b.expr(fn, s.Rhs[0]), op)
+		}
+
+	case *ast.GoStmt:
+		// The "intrinsics" new/make/len/cap are forbidden here.
+		// panic is treated like an ordinary function call.
+		v := Go{pos: s.Go}
+		b.setCall(fn, s.Call, &v.Call)
+		fn.emit(&v)
+
+	case *ast.DeferStmt:
+		// The "intrinsics" new/make/len/cap are forbidden here.
+		// panic is treated like an ordinary function call.
+		v := Defer{pos: s.Defer}
+		b.setCall(fn, s.Call, &v.Call)
+		fn.emit(&v)
+
+		// A deferred call can cause recovery from panic,
+		// and control resumes at the Recover block.
+		createRecoverBlock(fn)
+
+	case *ast.ReturnStmt:
+		var results []Value
+		if len(s.Results) == 1 && fn.Signature.Results().Len() > 1 {
+			// Return of one expression in a multi-valued function.
+			tuple := b.exprN(fn, s.Results[0])
+			ttuple := tuple.Type().(*types.Tuple)
+			for i, n := 0, ttuple.Len(); i < n; i++ {
+				results = append(results,
+					emitConv(fn, emitExtract(fn, tuple, i),
+						fn.Signature.Results().At(i).Type()))
+			}
+		} else {
+			// 1:1 return, or no-arg return in non-void function.
+			for i, r := range s.Results {
+				v := emitConv(fn, b.expr(fn, r), fn.Signature.Results().At(i).Type())
+				results = append(results, v)
+			}
+		}
+		if fn.namedResults != nil {
+			// Function has named result parameters (NRPs).
+			// Perform parallel assignment of return operands to NRPs.
+			for i, r := range results {
+				emitStore(fn, fn.namedResults[i], r, s.Return)
+			}
+		}
+		// Run function calls deferred in this
+		// function when explicitly returning from it.
+		fn.emit(new(RunDefers))
+		if fn.namedResults != nil {
+			// Reload NRPs to form the result tuple.
+			results = results[:0]
+			for _, r := range fn.namedResults {
+				results = append(results, emitLoad(fn, r))
+			}
+		}
+		fn.emit(&Return{Results: results, pos: s.Return})
+		fn.currentBlock = fn.newBasicBlock("unreachable")
+
+	case *ast.BranchStmt:
+		var block *BasicBlock
+		switch s.Tok {
+		case token.BREAK:
+			if s.Label != nil {
+				block = fn.labelledBlock(s.Label)._break
+			} else {
+				for t := fn.targets; t != nil && block == nil; t = t.tail {
+					block = t._break
+				}
+			}
+
+		case token.CONTINUE:
+			if s.Label != nil {
+				block = fn.labelledBlock(s.Label)._continue
+			} else {
+				for t := fn.targets; t != nil && block == nil; t = t.tail {
+					block = t._continue
+				}
+			}
+
+		case token.FALLTHROUGH:
+			for t := fn.targets; t != nil && block == nil; t = t.tail {
+				block = t._fallthrough
+			}
+
+		case token.GOTO:
+			block = fn.labelledBlock(s.Label)._goto
+		}
+		emitJump(fn, block)
+		fn.currentBlock = fn.newBasicBlock("unreachable")
+
+	case *ast.BlockStmt:
+		b.stmtList(fn, s.List)
+
+	case *ast.IfStmt:
+		if s.Init != nil {
+			b.stmt(fn, s.Init)
+		}
+		then := fn.newBasicBlock("if.then")
+		done := fn.newBasicBlock("if.done")
+		els := done
+		if s.Else != nil {
+			els = fn.newBasicBlock("if.else")
+		}
+		b.cond(fn, s.Cond, then, els)
+		fn.currentBlock = then
+		b.stmt(fn, s.Body)
+		emitJump(fn, done)
+
+		if s.Else != nil {
+			fn.currentBlock = els
+			b.stmt(fn, s.Else)
+			emitJump(fn, done)
+		}
+
+		fn.currentBlock = done
+
+	case *ast.SwitchStmt:
+		b.switchStmt(fn, s, label)
+
+	case *ast.TypeSwitchStmt:
+		b.typeSwitchStmt(fn, s, label)
+
+	case *ast.SelectStmt:
+		b.selectStmt(fn, s, label)
+
+	case *ast.ForStmt:
+		b.forStmt(fn, s, label)
+
+	case *ast.RangeStmt:
+		b.rangeStmt(fn, s, label)
+
+	default:
+		panic(fmt.Sprintf("unexpected statement kind: %T", s))
+	}
+}
+
+// buildFunction builds SSA code for the body of function fn.  Idempotent.
+func (b *builder) buildFunction(fn *Function) {
+	if fn.Blocks != nil {
+		return // building already started
+	}
+
+	var recvField *ast.FieldList
+	var body *ast.BlockStmt
+	var functype *ast.FuncType
+	switch n := fn.syntax.(type) {
+	case nil:
+		return // not a Go source function.  (Synthetic, or from object file.)
+	case *ast.FuncDecl:
+		functype = n.Type
+		recvField = n.Recv
+		body = n.Body
+	case *ast.FuncLit:
+		functype = n.Type
+		body = n.Body
+	default:
+		panic(n)
+	}
+
+	if body == nil {
+		// External function.
+		if fn.Params == nil {
+			// This condition ensures we add a non-empty
+			// params list once only, but we may attempt
+			// the degenerate empty case repeatedly.
+			// TODO(adonovan): opt: don't do that.
+
+			// We set Function.Params even though there is no body
+			// code to reference them.  This simplifies clients.
+			if recv := fn.Signature.Recv(); recv != nil {
+				fn.addParamObj(recv)
+			}
+			params := fn.Signature.Params()
+			for i, n := 0, params.Len(); i < n; i++ {
+				fn.addParamObj(params.At(i))
+			}
+		}
+		return
+	}
+	if fn.Prog.mode&LogSource != 0 {
+		defer logStack("build function %s @ %s", fn, fn.Prog.Fset.Position(fn.pos))()
+	}
+	fn.startBody()
+	fn.createSyntacticParams(recvField, functype)
+	b.stmt(fn, body)
+	if cb := fn.currentBlock; cb != nil && (cb == fn.Blocks[0] || cb == fn.Recover || cb.Preds != nil) {
+		// Control fell off the end of the function's body block.
+		//
+		// Block optimizations eliminate the current block, if
+		// unreachable.  It is a builder invariant that
+		// if this no-arg return is ill-typed for
+		// fn.Signature.Results, this block must be
+		// unreachable.  The sanity checker checks this.
+		fn.emit(new(RunDefers))
+		fn.emit(new(Return))
+	}
+	fn.finishBody()
+}
+
+// buildFuncDecl builds SSA code for the function or method declared
+// by decl in package pkg.
+//
+func (b *builder) buildFuncDecl(pkg *Package, decl *ast.FuncDecl) {
+	id := decl.Name
+	if isBlankIdent(id) {
+		return // discard
+	}
+	fn := pkg.values[pkg.info.Defs[id]].(*Function)
+	if decl.Recv == nil && id.Name == "init" {
+		var v Call
+		v.Call.Value = fn
+		v.setType(types.NewTuple())
+		pkg.init.emit(&v)
+	}
+	b.buildFunction(fn)
+}
+
+// BuildAll calls Package.Build() for each package in prog.
+// Building occurs in parallel unless the BuildSerially mode flag was set.
+//
+// BuildAll is intended for whole-program analysis; a typical compiler
+// need only build a single package.
+//
+// BuildAll is idempotent and thread-safe.
+//
+func (prog *Program) Build() {
+	var wg sync.WaitGroup
+	for _, p := range prog.packages {
+		if prog.mode&BuildSerially != 0 {
+			p.Build()
+		} else {
+			wg.Add(1)
+			go func(p *Package) {
+				p.Build()
+				wg.Done()
+			}(p)
+		}
+	}
+	wg.Wait()
+}
+
+// Build builds SSA code for all functions and vars in package p.
+//
+// Precondition: CreatePackage must have been called for all of p's
+// direct imports (and hence its direct imports must have been
+// error-free).
+//
+// Build is idempotent and thread-safe.
+//
+func (p *Package) Build() { p.buildOnce.Do(p.build) }
+
+func (p *Package) build() {
+	if p.info == nil {
+		return // synthetic package, e.g. "testmain"
+	}
+	if p.files == nil {
+		p.info = nil
+		return // package loaded from export data
+	}
+
+	// Ensure we have runtime type info for all exported members.
+	// TODO(adonovan): ideally belongs in memberFromObject, but
+	// that would require package creation in topological order.
+	for name, mem := range p.Members {
+		if ast.IsExported(name) {
+			p.Prog.needMethodsOf(mem.Type())
+		}
+	}
+	if p.Prog.mode&LogSource != 0 {
+		defer logStack("build %s", p)()
+	}
+	init := p.init
+	init.startBody()
+
+	var done *BasicBlock
+
+	if p.Prog.mode&BareInits == 0 {
+		// Make init() skip if package is already initialized.
+		initguard := p.Var("init$guard")
+		doinit := init.newBasicBlock("init.start")
+		done = init.newBasicBlock("init.done")
+		emitIf(init, emitLoad(init, initguard), done, doinit)
+		init.currentBlock = doinit
+		emitStore(init, initguard, vTrue, token.NoPos)
+
+		// Call the init() function of each package we import.
+		for _, pkg := range p.Pkg.Imports() {
+			prereq := p.Prog.packages[pkg]
+			if prereq == nil {
+				panic(fmt.Sprintf("Package(%q).Build(): unsatisfied import: Program.CreatePackage(%q) was not called", p.Pkg.Path(), pkg.Path()))
+			}
+			var v Call
+			v.Call.Value = prereq.init
+			v.Call.pos = init.pos
+			v.setType(types.NewTuple())
+			init.emit(&v)
+		}
+	}
+
+	var b builder
+
+	// Initialize package-level vars in correct order.
+	for _, varinit := range p.info.InitOrder {
+		if init.Prog.mode&LogSource != 0 {
+			fmt.Fprintf(os.Stderr, "build global initializer %v @ %s\n",
+				varinit.Lhs, p.Prog.Fset.Position(varinit.Rhs.Pos()))
+		}
+		if len(varinit.Lhs) == 1 {
+			// 1:1 initialization: var x, y = a(), b()
+			var lval lvalue
+			if v := varinit.Lhs[0]; v.Name() != "_" {
+				lval = &address{addr: p.values[v].(*Global), pos: v.Pos()}
+			} else {
+				lval = blank{}
+			}
+			b.assign(init, lval, varinit.Rhs, true, nil)
+		} else {
+			// n:1 initialization: var x, y :=  f()
+			tuple := b.exprN(init, varinit.Rhs)
+			for i, v := range varinit.Lhs {
+				if v.Name() == "_" {
+					continue
+				}
+				emitStore(init, p.values[v].(*Global), emitExtract(init, tuple, i), v.Pos())
+			}
+		}
+	}
+
+	// Build all package-level functions, init functions
+	// and methods, including unreachable/blank ones.
+	// We build them in source order, but it's not significant.
+	for _, file := range p.files {
+		for _, decl := range file.Decls {
+			if decl, ok := decl.(*ast.FuncDecl); ok {
+				b.buildFuncDecl(p, decl)
+			}
+		}
+	}
+
+	// Finish up init().
+	if p.Prog.mode&BareInits == 0 {
+		emitJump(init, done)
+		init.currentBlock = done
+	}
+	init.emit(new(Return))
+	init.finishBody()
+
+	p.info = nil // We no longer need ASTs or go/types deductions.
+
+	if p.Prog.mode&SanityCheckFunctions != 0 {
+		sanityCheckPackage(p)
+	}
+}
+
+// Like ObjectOf, but panics instead of returning nil.
+// Only valid during p's create and build phases.
+func (p *Package) objectOf(id *ast.Ident) types.Object {
+	if o := p.info.ObjectOf(id); o != nil {
+		return o
+	}
+	panic(fmt.Sprintf("no types.Object for ast.Ident %s @ %s",
+		id.Name, p.Prog.Fset.Position(id.Pos())))
+}
+
+// Like TypeOf, but panics instead of returning nil.
+// Only valid during p's create and build phases.
+func (p *Package) typeOf(e ast.Expr) types.Type {
+	if T := p.info.TypeOf(e); T != nil {
+		return T
+	}
+	panic(fmt.Sprintf("no type for %T @ %s",
+		e, p.Prog.Fset.Position(e.Pos())))
+}
diff --git a/go/src/golang.org/x/tools/go/ssa/builder14_test.go b/go/src/golang.org/x/tools/go/ssa/builder14_test.go
new file mode 100644
index 0000000..3eaa825
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/ssa/builder14_test.go
@@ -0,0 +1,421 @@
+// 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.
+
+// +build !go1.5
+
+package ssa_test
+
+import (
+	"bytes"
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"reflect"
+	"sort"
+	"strings"
+	"testing"
+
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/ssa/ssautil"
+	"golang.org/x/tools/go/types"
+
+	_ "golang.org/x/tools/go/gcimporter"
+)
+
+func isEmpty(f *ssa.Function) bool { return f.Blocks == nil }
+
+// Tests that programs partially loaded from gc object files contain
+// functions with no code for the external portions, but are otherwise ok.
+func TestBuildPackage(t *testing.T) {
+	input := `
+package main
+
+import (
+	"bytes"
+	"io"
+	"testing"
+)
+
+func main() {
+        var t testing.T
+	t.Parallel()    // static call to external declared method
+        t.Fail()        // static call to promoted external declared method
+        testing.Short() // static call to external package-level function
+
+        var w io.Writer = new(bytes.Buffer)
+        w.Write(nil)    // interface invoke of external declared method
+}
+`
+
+	// Parse the file.
+	fset := token.NewFileSet()
+	f, err := parser.ParseFile(fset, "input.go", input, 0)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	// Build an SSA program from the parsed file.
+	// Load its dependencies from gc binary export data.
+	mainPkg, _, err := ssautil.BuildPackage(new(types.Config), fset,
+		types.NewPackage("main", ""), []*ast.File{f}, ssa.SanityCheckFunctions)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	// The main package, its direct and indirect dependencies are loaded.
+	deps := []string{
+		// directly imported dependencies:
+		"bytes", "io", "testing",
+		// indirect dependencies (partial list):
+		"errors", "fmt", "os", "runtime",
+	}
+
+	prog := mainPkg.Prog
+	all := prog.AllPackages()
+	if len(all) <= len(deps) {
+		t.Errorf("unexpected set of loaded packages: %q", all)
+	}
+	for _, path := range deps {
+		pkg := prog.ImportedPackage(path)
+		if pkg == nil {
+			t.Errorf("package not loaded: %q", path)
+			continue
+		}
+
+		// External packages should have no function bodies (except for wrappers).
+		isExt := pkg != mainPkg
+
+		// init()
+		if isExt && !isEmpty(pkg.Func("init")) {
+			t.Errorf("external package %s has non-empty init", pkg)
+		} else if !isExt && isEmpty(pkg.Func("init")) {
+			t.Errorf("main package %s has empty init", pkg)
+		}
+
+		for _, mem := range pkg.Members {
+			switch mem := mem.(type) {
+			case *ssa.Function:
+				// Functions at package level.
+				if isExt && !isEmpty(mem) {
+					t.Errorf("external function %s is non-empty", mem)
+				} else if !isExt && isEmpty(mem) {
+					t.Errorf("function %s is empty", mem)
+				}
+
+			case *ssa.Type:
+				// Methods of named types T.
+				// (In this test, all exported methods belong to *T not T.)
+				if !isExt {
+					t.Fatalf("unexpected name type in main package: %s", mem)
+				}
+				mset := prog.MethodSets.MethodSet(types.NewPointer(mem.Type()))
+				for i, n := 0, mset.Len(); i < n; i++ {
+					m := prog.MethodValue(mset.At(i))
+					// For external types, only synthetic wrappers have code.
+					expExt := !strings.Contains(m.Synthetic, "wrapper")
+					if expExt && !isEmpty(m) {
+						t.Errorf("external method %s is non-empty: %s",
+							m, m.Synthetic)
+					} else if !expExt && isEmpty(m) {
+						t.Errorf("method function %s is empty: %s",
+							m, m.Synthetic)
+					}
+				}
+			}
+		}
+	}
+
+	expectedCallee := []string{
+		"(*testing.T).Parallel",
+		"(*testing.common).Fail",
+		"testing.Short",
+		"N/A",
+	}
+	callNum := 0
+	for _, b := range mainPkg.Func("main").Blocks {
+		for _, instr := range b.Instrs {
+			switch instr := instr.(type) {
+			case ssa.CallInstruction:
+				call := instr.Common()
+				if want := expectedCallee[callNum]; want != "N/A" {
+					got := call.StaticCallee().String()
+					if want != got {
+						t.Errorf("call #%d from main.main: got callee %s, want %s",
+							callNum, got, want)
+					}
+				}
+				callNum++
+			}
+		}
+	}
+	if callNum != 4 {
+		t.Errorf("in main.main: got %d calls, want %d", callNum, 4)
+	}
+}
+
+// TestRuntimeTypes tests that (*Program).RuntimeTypes() includes all necessary types.
+func TestRuntimeTypes(t *testing.T) {
+	tests := []struct {
+		input string
+		want  []string
+	}{
+		// An exported package-level type is needed.
+		{`package A; type T struct{}; func (T) f() {}`,
+			[]string{"*p.T", "p.T"},
+		},
+		// An unexported package-level type is not needed.
+		{`package B; type t struct{}; func (t) f() {}`,
+			nil,
+		},
+		// Subcomponents of type of exported package-level var are needed.
+		{`package C; import "bytes"; var V struct {*bytes.Buffer}`,
+			[]string{"*bytes.Buffer", "*struct{*bytes.Buffer}", "struct{*bytes.Buffer}"},
+		},
+		// Subcomponents of type of unexported package-level var are not needed.
+		{`package D; import "bytes"; var v struct {*bytes.Buffer}`,
+			nil,
+		},
+		// Subcomponents of type of exported package-level function are needed.
+		{`package E; import "bytes"; func F(struct {*bytes.Buffer}) {}`,
+			[]string{"*bytes.Buffer", "struct{*bytes.Buffer}"},
+		},
+		// Subcomponents of type of unexported package-level function are not needed.
+		{`package F; import "bytes"; func f(struct {*bytes.Buffer}) {}`,
+			nil,
+		},
+		// Subcomponents of type of exported method of uninstantiated unexported type are not needed.
+		{`package G; import "bytes"; type x struct{}; func (x) G(struct {*bytes.Buffer}) {}; var v x`,
+			nil,
+		},
+		// ...unless used by MakeInterface.
+		{`package G2; import "bytes"; type x struct{}; func (x) G(struct {*bytes.Buffer}) {}; var v interface{} = x{}`,
+			[]string{"*bytes.Buffer", "*p.x", "p.x", "struct{*bytes.Buffer}"},
+		},
+		// Subcomponents of type of unexported method are not needed.
+		{`package I; import "bytes"; type X struct{}; func (X) G(struct {*bytes.Buffer}) {}`,
+			[]string{"*bytes.Buffer", "*p.X", "p.X", "struct{*bytes.Buffer}"},
+		},
+		// Local types aren't needed.
+		{`package J; import "bytes"; func f() { type T struct {*bytes.Buffer}; var t T; _ = t }`,
+			nil,
+		},
+		// ...unless used by MakeInterface.
+		{`package K; import "bytes"; func f() { type T struct {*bytes.Buffer}; _ = interface{}(T{}) }`,
+			[]string{"*bytes.Buffer", "*p.T", "p.T"},
+		},
+		// Types used as operand of MakeInterface are needed.
+		{`package L; import "bytes"; func f() { _ = interface{}(struct{*bytes.Buffer}{}) }`,
+			[]string{"*bytes.Buffer", "struct{*bytes.Buffer}"},
+		},
+		// MakeInterface is optimized away when storing to a blank.
+		{`package M; import "bytes"; var _ interface{} = struct{*bytes.Buffer}{}`,
+			nil,
+		},
+	}
+	for _, test := range tests {
+		// Parse the file.
+		fset := token.NewFileSet()
+		f, err := parser.ParseFile(fset, "input.go", test.input, 0)
+		if err != nil {
+			t.Errorf("test %q: %s", test.input[:15], err)
+			continue
+		}
+
+		// Create a single-file main package.
+		// Load dependencies from gc binary export data.
+		ssapkg, _, err := ssautil.BuildPackage(new(types.Config), fset,
+			types.NewPackage("p", ""), []*ast.File{f}, ssa.SanityCheckFunctions)
+		if err != nil {
+			t.Errorf("test %q: %s", test.input[:15], err)
+			continue
+		}
+
+		var typstrs []string
+		for _, T := range ssapkg.Prog.RuntimeTypes() {
+			typstrs = append(typstrs, T.String())
+		}
+		sort.Strings(typstrs)
+
+		if !reflect.DeepEqual(typstrs, test.want) {
+			t.Errorf("test 'package %s': got %q, want %q",
+				f.Name.Name, typstrs, test.want)
+		}
+	}
+}
+
+// TestInit tests that synthesized init functions are correctly formed.
+// Bare init functions omit calls to dependent init functions and the use of
+// an init guard. They are useful in cases where the client uses a different
+// calling convention for init functions, or cases where it is easier for a
+// client to analyze bare init functions. Both of these aspects are used by
+// the llgo compiler for simpler integration with gccgo's runtime library,
+// and to simplify the analysis whereby it deduces which stores to globals
+// can be lowered to global initializers.
+func TestInit(t *testing.T) {
+	tests := []struct {
+		mode        ssa.BuilderMode
+		input, want string
+	}{
+		{0, `package A; import _ "errors"; var i int = 42`,
+			`# Name: A.init
+# Package: A
+# Synthetic: package initializer
+func init():
+0:                                                                entry P:0 S:2
+	t0 = *init$guard                                                   bool
+	if t0 goto 2 else 1
+1:                                                           init.start P:1 S:1
+	*init$guard = true:bool
+	t1 = errors.init()                                                   ()
+	*i = 42:int
+	jump 2
+2:                                                            init.done P:2 S:0
+	return
+
+`},
+		{ssa.BareInits, `package B; import _ "errors"; var i int = 42`,
+			`# Name: B.init
+# Package: B
+# Synthetic: package initializer
+func init():
+0:                                                                entry P:0 S:0
+	*i = 42:int
+	return
+
+`},
+	}
+	for _, test := range tests {
+		// Create a single-file main package.
+		var conf loader.Config
+		f, err := conf.ParseFile("<input>", test.input)
+		if err != nil {
+			t.Errorf("test %q: %s", test.input[:15], err)
+			continue
+		}
+		conf.CreateFromFiles(f.Name.Name, f)
+
+		lprog, err := conf.Load()
+		if err != nil {
+			t.Errorf("test 'package %s': Load: %s", f.Name.Name, err)
+			continue
+		}
+		prog := ssautil.CreateProgram(lprog, test.mode)
+		mainPkg := prog.Package(lprog.Created[0].Pkg)
+		prog.Build()
+		initFunc := mainPkg.Func("init")
+		if initFunc == nil {
+			t.Errorf("test 'package %s': no init function", f.Name.Name)
+			continue
+		}
+
+		var initbuf bytes.Buffer
+		_, err = initFunc.WriteTo(&initbuf)
+		if err != nil {
+			t.Errorf("test 'package %s': WriteTo: %s", f.Name.Name, err)
+			continue
+		}
+
+		if initbuf.String() != test.want {
+			t.Errorf("test 'package %s': got %s, want %s", f.Name.Name, initbuf.String(), test.want)
+		}
+	}
+}
+
+// TestSyntheticFuncs checks that the expected synthetic functions are
+// created, reachable, and not duplicated.
+func TestSyntheticFuncs(t *testing.T) {
+	const input = `package P
+type T int
+func (T) f() int
+func (*T) g() int
+var (
+	// thunks
+	a = T.f
+	b = T.f
+	c = (struct{T}).f
+	d = (struct{T}).f
+	e = (*T).g
+	f = (*T).g
+	g = (struct{*T}).g
+	h = (struct{*T}).g
+
+	// bounds
+	i = T(0).f
+	j = T(0).f
+	k = new(T).g
+	l = new(T).g
+
+	// wrappers
+	m interface{} = struct{T}{}
+	n interface{} = struct{T}{}
+	o interface{} = struct{*T}{}
+	p interface{} = struct{*T}{}
+	q interface{} = new(struct{T})
+	r interface{} = new(struct{T})
+	s interface{} = new(struct{*T})
+	t interface{} = new(struct{*T})
+)
+`
+	// Parse
+	var conf loader.Config
+	f, err := conf.ParseFile("<input>", input)
+	if err != nil {
+		t.Fatalf("parse: %v", err)
+	}
+	conf.CreateFromFiles(f.Name.Name, f)
+
+	// Load
+	lprog, err := conf.Load()
+	if err != nil {
+		t.Fatalf("Load: %v", err)
+	}
+
+	// Create and build SSA
+	prog := ssautil.CreateProgram(lprog, 0)
+	prog.Build()
+
+	// Enumerate reachable synthetic functions
+	want := map[string]string{
+		"(*P.T).g$bound": "bound method wrapper for func (*P.T).g() int",
+		"(P.T).f$bound":  "bound method wrapper for func (P.T).f() int",
+
+		"(*P.T).g$thunk":         "thunk for func (*P.T).g() int",
+		"(P.T).f$thunk":          "thunk for func (P.T).f() int",
+		"(struct{*P.T}).g$thunk": "thunk for func (*P.T).g() int",
+		"(struct{P.T}).f$thunk":  "thunk for func (P.T).f() int",
+
+		"(*P.T).f":          "wrapper for func (P.T).f() int",
+		"(*struct{*P.T}).f": "wrapper for func (P.T).f() int",
+		"(*struct{*P.T}).g": "wrapper for func (*P.T).g() int",
+		"(*struct{P.T}).f":  "wrapper for func (P.T).f() int",
+		"(*struct{P.T}).g":  "wrapper for func (*P.T).g() int",
+		"(struct{*P.T}).f":  "wrapper for func (P.T).f() int",
+		"(struct{*P.T}).g":  "wrapper for func (*P.T).g() int",
+		"(struct{P.T}).f":   "wrapper for func (P.T).f() int",
+
+		"P.init": "package initializer",
+	}
+	for fn := range ssautil.AllFunctions(prog) {
+		if fn.Synthetic == "" {
+			continue
+		}
+		name := fn.String()
+		wantDescr, ok := want[name]
+		if !ok {
+			t.Errorf("got unexpected/duplicate func: %q: %q", name, fn.Synthetic)
+			continue
+		}
+		delete(want, name)
+
+		if wantDescr != fn.Synthetic {
+			t.Errorf("(%s).Synthetic = %q, want %q", name, fn.Synthetic, wantDescr)
+		}
+	}
+	for fn, descr := range want {
+		t.Errorf("want func: %q: %q", fn, descr)
+	}
+}
diff --git a/go/src/golang.org/x/tools/go/ssa/builder_test.go b/go/src/golang.org/x/tools/go/ssa/builder_test.go
index e7ac838..fdb58ff 100644
--- a/go/src/golang.org/x/tools/go/ssa/builder_test.go
+++ b/go/src/golang.org/x/tools/go/ssa/builder_test.go
@@ -2,13 +2,17 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package ssa_test
 
 import (
 	"bytes"
 	"go/ast"
+	"go/importer"
 	"go/parser"
 	"go/token"
+	"go/types"
 	"reflect"
 	"sort"
 	"strings"
@@ -17,9 +21,6 @@
 	"golang.org/x/tools/go/loader"
 	"golang.org/x/tools/go/ssa"
 	"golang.org/x/tools/go/ssa/ssautil"
-	"golang.org/x/tools/go/types"
-
-	_ "golang.org/x/tools/go/gcimporter"
 )
 
 func isEmpty(f *ssa.Function) bool { return f.Blocks == nil }
@@ -57,7 +58,7 @@
 
 	// Build an SSA program from the parsed file.
 	// Load its dependencies from gc binary export data.
-	mainPkg, _, err := ssautil.BuildPackage(new(types.Config), fset,
+	mainPkg, _, err := ssautil.BuildPackage(&types.Config{Importer: importer.Default()}, fset,
 		types.NewPackage("main", ""), []*ast.File{f}, ssa.SanityCheckFunctions)
 	if err != nil {
 		t.Error(err)
@@ -112,7 +113,7 @@
 				}
 				mset := prog.MethodSets.MethodSet(types.NewPointer(mem.Type()))
 				for i, n := 0, mset.Len(); i < n; i++ {
-					m := prog.Method(mset.At(i))
+					m := prog.MethodValue(mset.At(i))
 					// For external types, only synthetic wrappers have code.
 					expExt := !strings.Contains(m.Synthetic, "wrapper")
 					if expExt && !isEmpty(m) {
@@ -225,7 +226,7 @@
 
 		// Create a single-file main package.
 		// Load dependencies from gc binary export data.
-		ssapkg, _, err := ssautil.BuildPackage(new(types.Config), fset,
+		ssapkg, _, err := ssautil.BuildPackage(&types.Config{Importer: importer.Default()}, fset,
 			types.NewPackage("p", ""), []*ast.File{f}, ssa.SanityCheckFunctions)
 		if err != nil {
 			t.Errorf("test %q: %s", test.input[:15], err)
@@ -303,7 +304,7 @@
 		}
 		prog := ssautil.CreateProgram(lprog, test.mode)
 		mainPkg := prog.Package(lprog.Created[0].Pkg)
-		prog.BuildAll()
+		prog.Build()
 		initFunc := mainPkg.Func("init")
 		if initFunc == nil {
 			t.Errorf("test 'package %s': no init function", f.Name.Name)
@@ -374,7 +375,7 @@
 
 	// Create and build SSA
 	prog := ssautil.CreateProgram(lprog, 0)
-	prog.BuildAll()
+	prog.Build()
 
 	// Enumerate reachable synthetic functions
 	want := map[string]string{
diff --git a/go/src/golang.org/x/tools/go/ssa/const.go b/go/src/golang.org/x/tools/go/ssa/const.go
index 304096e..0690463 100644
--- a/go/src/golang.org/x/tools/go/ssa/const.go
+++ b/go/src/golang.org/x/tools/go/ssa/const.go
@@ -2,17 +2,18 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.6
+
 package ssa
 
 // This file defines the Const SSA value type.
 
 import (
 	"fmt"
+	exact "go/constant"
 	"go/token"
+	"go/types"
 	"strconv"
-
-	"golang.org/x/tools/go/exact"
-	"golang.org/x/tools/go/types"
 )
 
 // NewConst returns a new constant of the specified value and type.
@@ -116,11 +117,13 @@
 	return c.Value == nil
 }
 
+// TODO(adonovan): move everything below into golang.org/x/tools/go/ssa/interp.
+
 // Int64 returns the numeric value of this constant truncated to fit
 // a signed 64-bit integer.
 //
 func (c *Const) Int64() int64 {
-	switch x := c.Value; x.Kind() {
+	switch x := exact.ToInt(c.Value); x.Kind() {
 	case exact.Int:
 		if i, ok := exact.Int64Val(x); ok {
 			return i
@@ -137,7 +140,7 @@
 // an unsigned 64-bit integer.
 //
 func (c *Const) Uint64() uint64 {
-	switch x := c.Value; x.Kind() {
+	switch x := exact.ToInt(c.Value); x.Kind() {
 	case exact.Int:
 		if u, ok := exact.Uint64Val(x); ok {
 			return u
diff --git a/go/src/golang.org/x/tools/go/ssa/const14.go b/go/src/golang.org/x/tools/go/ssa/const14.go
new file mode 100644
index 0000000..0ec43b6
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/ssa/const14.go
@@ -0,0 +1,170 @@
+// 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.
+
+// +build !go1.5
+
+package ssa
+
+// This file defines the Const SSA value type.
+
+import (
+	"fmt"
+	"go/token"
+	"strconv"
+
+	"golang.org/x/tools/go/exact"
+	"golang.org/x/tools/go/types"
+)
+
+// NewConst returns a new constant of the specified value and type.
+// val must be valid according to the specification of Const.Value.
+//
+func NewConst(val exact.Value, typ types.Type) *Const {
+	return &Const{typ, val}
+}
+
+// intConst returns an 'int' constant that evaluates to i.
+// (i is an int64 in case the host is narrower than the target.)
+func intConst(i int64) *Const {
+	return NewConst(exact.MakeInt64(i), tInt)
+}
+
+// nilConst returns a nil constant of the specified type, which may
+// be any reference type, including interfaces.
+//
+func nilConst(typ types.Type) *Const {
+	return NewConst(nil, typ)
+}
+
+// stringConst returns a 'string' constant that evaluates to s.
+func stringConst(s string) *Const {
+	return NewConst(exact.MakeString(s), tString)
+}
+
+// zeroConst returns a new "zero" constant of the specified type,
+// which must not be an array or struct type: the zero values of
+// aggregates are well-defined but cannot be represented by Const.
+//
+func zeroConst(t types.Type) *Const {
+	switch t := t.(type) {
+	case *types.Basic:
+		switch {
+		case t.Info()&types.IsBoolean != 0:
+			return NewConst(exact.MakeBool(false), t)
+		case t.Info()&types.IsNumeric != 0:
+			return NewConst(exact.MakeInt64(0), t)
+		case t.Info()&types.IsString != 0:
+			return NewConst(exact.MakeString(""), t)
+		case t.Kind() == types.UnsafePointer:
+			fallthrough
+		case t.Kind() == types.UntypedNil:
+			return nilConst(t)
+		default:
+			panic(fmt.Sprint("zeroConst for unexpected type:", t))
+		}
+	case *types.Pointer, *types.Slice, *types.Interface, *types.Chan, *types.Map, *types.Signature:
+		return nilConst(t)
+	case *types.Named:
+		return NewConst(zeroConst(t.Underlying()).Value, t)
+	case *types.Array, *types.Struct, *types.Tuple:
+		panic(fmt.Sprint("zeroConst applied to aggregate:", t))
+	}
+	panic(fmt.Sprint("zeroConst: unexpected ", t))
+}
+
+func (c *Const) RelString(from *types.Package) string {
+	var s string
+	if c.Value == nil {
+		s = "nil"
+	} else if c.Value.Kind() == exact.String {
+		s = exact.StringVal(c.Value)
+		const max = 20
+		// TODO(adonovan): don't cut a rune in half.
+		if len(s) > max {
+			s = s[:max-3] + "..." // abbreviate
+		}
+		s = strconv.Quote(s)
+	} else {
+		s = c.Value.String()
+	}
+	return s + ":" + relType(c.Type(), from)
+}
+
+func (c *Const) Name() string {
+	return c.RelString(nil)
+}
+
+func (c *Const) String() string {
+	return c.Name()
+}
+
+func (c *Const) Type() types.Type {
+	return c.typ
+}
+
+func (c *Const) Referrers() *[]Instruction {
+	return nil
+}
+
+func (c *Const) Parent() *Function { return nil }
+
+func (c *Const) Pos() token.Pos {
+	return token.NoPos
+}
+
+// IsNil returns true if this constant represents a typed or untyped nil value.
+func (c *Const) IsNil() bool {
+	return c.Value == nil
+}
+
+// Int64 returns the numeric value of this constant truncated to fit
+// a signed 64-bit integer.
+//
+func (c *Const) Int64() int64 {
+	switch x := c.Value; x.Kind() {
+	case exact.Int:
+		if i, ok := exact.Int64Val(x); ok {
+			return i
+		}
+		return 0
+	case exact.Float:
+		f, _ := exact.Float64Val(x)
+		return int64(f)
+	}
+	panic(fmt.Sprintf("unexpected constant value: %T", c.Value))
+}
+
+// Uint64 returns the numeric value of this constant truncated to fit
+// an unsigned 64-bit integer.
+//
+func (c *Const) Uint64() uint64 {
+	switch x := c.Value; x.Kind() {
+	case exact.Int:
+		if u, ok := exact.Uint64Val(x); ok {
+			return u
+		}
+		return 0
+	case exact.Float:
+		f, _ := exact.Float64Val(x)
+		return uint64(f)
+	}
+	panic(fmt.Sprintf("unexpected constant value: %T", c.Value))
+}
+
+// Float64 returns the numeric value of this constant truncated to fit
+// a float64.
+//
+func (c *Const) Float64() float64 {
+	f, _ := exact.Float64Val(c.Value)
+	return f
+}
+
+// Complex128 returns the complex value of this constant truncated to
+// fit a complex128.
+//
+func (c *Const) Complex128() complex128 {
+	re, _ := exact.Float64Val(exact.Real(c.Value))
+	im, _ := exact.Float64Val(exact.Imag(c.Value))
+	return complex(re, im)
+}
diff --git a/go/src/golang.org/x/tools/go/ssa/const15.go b/go/src/golang.org/x/tools/go/ssa/const15.go
new file mode 100644
index 0000000..a42b255
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/ssa/const15.go
@@ -0,0 +1,171 @@
+// 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.
+
+// +build go1.5,!go1.6
+
+package ssa
+
+// This file defines the Const SSA value type.
+
+import (
+	"fmt"
+	exact "go/constant"
+	"go/token"
+	"go/types"
+	"strconv"
+)
+
+// NewConst returns a new constant of the specified value and type.
+// val must be valid according to the specification of Const.Value.
+//
+func NewConst(val exact.Value, typ types.Type) *Const {
+	return &Const{typ, val}
+}
+
+// intConst returns an 'int' constant that evaluates to i.
+// (i is an int64 in case the host is narrower than the target.)
+func intConst(i int64) *Const {
+	return NewConst(exact.MakeInt64(i), tInt)
+}
+
+// nilConst returns a nil constant of the specified type, which may
+// be any reference type, including interfaces.
+//
+func nilConst(typ types.Type) *Const {
+	return NewConst(nil, typ)
+}
+
+// stringConst returns a 'string' constant that evaluates to s.
+func stringConst(s string) *Const {
+	return NewConst(exact.MakeString(s), tString)
+}
+
+// zeroConst returns a new "zero" constant of the specified type,
+// which must not be an array or struct type: the zero values of
+// aggregates are well-defined but cannot be represented by Const.
+//
+func zeroConst(t types.Type) *Const {
+	switch t := t.(type) {
+	case *types.Basic:
+		switch {
+		case t.Info()&types.IsBoolean != 0:
+			return NewConst(exact.MakeBool(false), t)
+		case t.Info()&types.IsNumeric != 0:
+			return NewConst(exact.MakeInt64(0), t)
+		case t.Info()&types.IsString != 0:
+			return NewConst(exact.MakeString(""), t)
+		case t.Kind() == types.UnsafePointer:
+			fallthrough
+		case t.Kind() == types.UntypedNil:
+			return nilConst(t)
+		default:
+			panic(fmt.Sprint("zeroConst for unexpected type:", t))
+		}
+	case *types.Pointer, *types.Slice, *types.Interface, *types.Chan, *types.Map, *types.Signature:
+		return nilConst(t)
+	case *types.Named:
+		return NewConst(zeroConst(t.Underlying()).Value, t)
+	case *types.Array, *types.Struct, *types.Tuple:
+		panic(fmt.Sprint("zeroConst applied to aggregate:", t))
+	}
+	panic(fmt.Sprint("zeroConst: unexpected ", t))
+}
+
+func (c *Const) RelString(from *types.Package) string {
+	var s string
+	if c.Value == nil {
+		s = "nil"
+	} else if c.Value.Kind() == exact.String {
+		s = exact.StringVal(c.Value)
+		const max = 20
+		// TODO(adonovan): don't cut a rune in half.
+		if len(s) > max {
+			s = s[:max-3] + "..." // abbreviate
+		}
+		s = strconv.Quote(s)
+	} else {
+		s = c.Value.String()
+	}
+	return s + ":" + relType(c.Type(), from)
+}
+
+func (c *Const) Name() string {
+	return c.RelString(nil)
+}
+
+func (c *Const) String() string {
+	return c.Name()
+}
+
+func (c *Const) Type() types.Type {
+	return c.typ
+}
+
+func (c *Const) Referrers() *[]Instruction {
+	return nil
+}
+
+func (c *Const) Parent() *Function { return nil }
+
+func (c *Const) Pos() token.Pos {
+	return token.NoPos
+}
+
+// IsNil returns true if this constant represents a typed or untyped nil value.
+func (c *Const) IsNil() bool {
+	return c.Value == nil
+}
+
+// TODO(adonovan): move everything below into golang.org/x/tools/go/ssa/interp.
+
+// Int64 returns the numeric value of this constant truncated to fit
+// a signed 64-bit integer.
+//
+func (c *Const) Int64() int64 {
+	switch x := c.Value; x.Kind() {
+	case exact.Int:
+		if i, ok := exact.Int64Val(x); ok {
+			return i
+		}
+		return 0
+	case exact.Float:
+		f, _ := exact.Float64Val(x)
+		return int64(f)
+	}
+	panic(fmt.Sprintf("unexpected constant value: %T", c.Value))
+}
+
+// Uint64 returns the numeric value of this constant truncated to fit
+// an unsigned 64-bit integer.
+//
+func (c *Const) Uint64() uint64 {
+	switch x := c.Value; x.Kind() {
+	case exact.Int:
+		if u, ok := exact.Uint64Val(x); ok {
+			return u
+		}
+		return 0
+	case exact.Float:
+		f, _ := exact.Float64Val(x)
+		return uint64(f)
+	}
+	panic(fmt.Sprintf("unexpected constant value: %T", c.Value))
+}
+
+// Float64 returns the numeric value of this constant truncated to fit
+// a float64.
+//
+func (c *Const) Float64() float64 {
+	f, _ := exact.Float64Val(c.Value)
+	return f
+}
+
+// Complex128 returns the complex value of this constant truncated to
+// fit a complex128.
+//
+func (c *Const) Complex128() complex128 {
+	re, _ := exact.Float64Val(exact.Real(c.Value))
+	im, _ := exact.Float64Val(exact.Imag(c.Value))
+	return complex(re, im)
+}
diff --git a/go/src/golang.org/x/tools/go/ssa/create.go b/go/src/golang.org/x/tools/go/ssa/create.go
index 88226ae..372d1c7 100644
--- a/go/src/golang.org/x/tools/go/ssa/create.go
+++ b/go/src/golang.org/x/tools/go/ssa/create.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package ssa
 
 // This file implements the CREATE phase of SSA construction.
@@ -11,10 +13,10 @@
 	"fmt"
 	"go/ast"
 	"go/token"
+	"go/types"
 	"os"
 	"sync"
 
-	"golang.org/x/tools/go/types"
 	"golang.org/x/tools/go/types/typeutil"
 )
 
@@ -162,7 +164,7 @@
 		Prog:    prog,
 		Members: make(map[string]Member),
 		values:  make(map[types.Object]Value),
-		Object:  pkg,
+		Pkg:     pkg,
 		info:    info,  // transient (CREATE and BUILD phases)
 		files:   files, // transient (CREATE and BUILD phases)
 	}
@@ -190,7 +192,7 @@
 		// GC-compiled binary package.
 		// No code.
 		// No position information.
-		scope := p.Object.Scope()
+		scope := p.Pkg.Scope()
 		for _, name := range scope.Names() {
 			obj := scope.Lookup(name)
 			memberFromObject(p, obj, nil)
@@ -224,9 +226,9 @@
 	}
 
 	if importable {
-		prog.imported[p.Object.Path()] = p
+		prog.imported[p.Pkg.Path()] = p
 	}
-	prog.packages[p.Object] = p
+	prog.packages[p.Pkg] = p
 
 	return p
 }
diff --git a/go/src/golang.org/x/tools/go/ssa/create14.go b/go/src/golang.org/x/tools/go/ssa/create14.go
new file mode 100644
index 0000000..58be47e
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/ssa/create14.go
@@ -0,0 +1,259 @@
+// 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.
+
+// +build !go1.5
+
+package ssa
+
+// This file implements the CREATE phase of SSA construction.
+// See builder.go for explanation.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"os"
+	"sync"
+
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/go/types/typeutil"
+)
+
+// NewProgram returns a new SSA Program.
+//
+// mode controls diagnostics and checking during SSA construction.
+//
+func NewProgram(fset *token.FileSet, mode BuilderMode) *Program {
+	prog := &Program{
+		Fset:     fset,
+		imported: make(map[string]*Package),
+		packages: make(map[*types.Package]*Package),
+		thunks:   make(map[selectionKey]*Function),
+		bounds:   make(map[*types.Func]*Function),
+		mode:     mode,
+	}
+
+	h := typeutil.MakeHasher() // protected by methodsMu, in effect
+	prog.methodSets.SetHasher(h)
+	prog.canon.SetHasher(h)
+
+	return prog
+}
+
+// memberFromObject populates package pkg with a member for the
+// typechecker object obj.
+//
+// For objects from Go source code, syntax is the associated syntax
+// tree (for funcs and vars only); it will be used during the build
+// phase.
+//
+func memberFromObject(pkg *Package, obj types.Object, syntax ast.Node) {
+	name := obj.Name()
+	switch obj := obj.(type) {
+	case *types.TypeName:
+		pkg.Members[name] = &Type{
+			object: obj,
+			pkg:    pkg,
+		}
+
+	case *types.Const:
+		c := &NamedConst{
+			object: obj,
+			Value:  NewConst(obj.Val(), obj.Type()),
+			pkg:    pkg,
+		}
+		pkg.values[obj] = c.Value
+		pkg.Members[name] = c
+
+	case *types.Var:
+		g := &Global{
+			Pkg:    pkg,
+			name:   name,
+			object: obj,
+			typ:    types.NewPointer(obj.Type()), // address
+			pos:    obj.Pos(),
+		}
+		pkg.values[obj] = g
+		pkg.Members[name] = g
+
+	case *types.Func:
+		sig := obj.Type().(*types.Signature)
+		if sig.Recv() == nil && name == "init" {
+			pkg.ninit++
+			name = fmt.Sprintf("init#%d", pkg.ninit)
+		}
+		fn := &Function{
+			name:      name,
+			object:    obj,
+			Signature: sig,
+			syntax:    syntax,
+			pos:       obj.Pos(),
+			Pkg:       pkg,
+			Prog:      pkg.Prog,
+		}
+		if syntax == nil {
+			fn.Synthetic = "loaded from gc object file"
+		}
+
+		pkg.values[obj] = fn
+		if sig.Recv() == nil {
+			pkg.Members[name] = fn // package-level function
+		}
+
+	default: // (incl. *types.Package)
+		panic("unexpected Object type: " + obj.String())
+	}
+}
+
+// membersFromDecl populates package pkg with members for each
+// typechecker object (var, func, const or type) associated with the
+// specified decl.
+//
+func membersFromDecl(pkg *Package, decl ast.Decl) {
+	switch decl := decl.(type) {
+	case *ast.GenDecl: // import, const, type or var
+		switch decl.Tok {
+		case token.CONST:
+			for _, spec := range decl.Specs {
+				for _, id := range spec.(*ast.ValueSpec).Names {
+					if !isBlankIdent(id) {
+						memberFromObject(pkg, pkg.info.Defs[id], nil)
+					}
+				}
+			}
+
+		case token.VAR:
+			for _, spec := range decl.Specs {
+				for _, id := range spec.(*ast.ValueSpec).Names {
+					if !isBlankIdent(id) {
+						memberFromObject(pkg, pkg.info.Defs[id], spec)
+					}
+				}
+			}
+
+		case token.TYPE:
+			for _, spec := range decl.Specs {
+				id := spec.(*ast.TypeSpec).Name
+				if !isBlankIdent(id) {
+					memberFromObject(pkg, pkg.info.Defs[id], nil)
+				}
+			}
+		}
+
+	case *ast.FuncDecl:
+		id := decl.Name
+		if !isBlankIdent(id) {
+			memberFromObject(pkg, pkg.info.Defs[id], decl)
+		}
+	}
+}
+
+// CreatePackage constructs and returns an SSA Package from the
+// specified type-checked, error-free file ASTs, and populates its
+// Members mapping.
+//
+// importable determines whether this package should be returned by a
+// subsequent call to ImportedPackage(pkg.Path()).
+//
+// The real work of building SSA form for each function is not done
+// until a subsequent call to Package.Build().
+//
+func (prog *Program) CreatePackage(pkg *types.Package, files []*ast.File, info *types.Info, importable bool) *Package {
+	p := &Package{
+		Prog:    prog,
+		Members: make(map[string]Member),
+		values:  make(map[types.Object]Value),
+		Pkg:     pkg,
+		info:    info,  // transient (CREATE and BUILD phases)
+		files:   files, // transient (CREATE and BUILD phases)
+	}
+
+	// Add init() function.
+	p.init = &Function{
+		name:      "init",
+		Signature: new(types.Signature),
+		Synthetic: "package initializer",
+		Pkg:       p,
+		Prog:      prog,
+	}
+	p.Members[p.init.name] = p.init
+
+	// CREATE phase.
+	// Allocate all package members: vars, funcs, consts and types.
+	if len(files) > 0 {
+		// Go source package.
+		for _, file := range files {
+			for _, decl := range file.Decls {
+				membersFromDecl(p, decl)
+			}
+		}
+	} else {
+		// GC-compiled binary package.
+		// No code.
+		// No position information.
+		scope := p.Pkg.Scope()
+		for _, name := range scope.Names() {
+			obj := scope.Lookup(name)
+			memberFromObject(p, obj, nil)
+			if obj, ok := obj.(*types.TypeName); ok {
+				named := obj.Type().(*types.Named)
+				for i, n := 0, named.NumMethods(); i < n; i++ {
+					memberFromObject(p, named.Method(i), nil)
+				}
+			}
+		}
+	}
+
+	if prog.mode&BareInits == 0 {
+		// Add initializer guard variable.
+		initguard := &Global{
+			Pkg:  p,
+			name: "init$guard",
+			typ:  types.NewPointer(tBool),
+		}
+		p.Members[initguard.Name()] = initguard
+	}
+
+	if prog.mode&GlobalDebug != 0 {
+		p.SetDebugMode(true)
+	}
+
+	if prog.mode&PrintPackages != 0 {
+		printMu.Lock()
+		p.WriteTo(os.Stdout)
+		printMu.Unlock()
+	}
+
+	if importable {
+		prog.imported[p.Pkg.Path()] = p
+	}
+	prog.packages[p.Pkg] = p
+
+	return p
+}
+
+// printMu serializes printing of Packages/Functions to stdout.
+var printMu sync.Mutex
+
+// AllPackages returns a new slice containing all packages in the
+// program prog in unspecified order.
+//
+func (prog *Program) AllPackages() []*Package {
+	pkgs := make([]*Package, 0, len(prog.packages))
+	for _, pkg := range prog.packages {
+		pkgs = append(pkgs, pkg)
+	}
+	return pkgs
+}
+
+// ImportedPackage returns the importable SSA Package whose import
+// path is path, or nil if no such SSA package has been created.
+//
+// Not all packages are importable.  For example, no import
+// declaration can resolve to the x_test package created by 'go test'
+// or the ad-hoc main package created 'go build foo.go'.
+//
+func (prog *Program) ImportedPackage(path string) *Package {
+	return prog.imported[path]
+}
diff --git a/go/src/golang.org/x/tools/go/ssa/emit.go b/go/src/golang.org/x/tools/go/ssa/emit.go
index fa9646b..238c070 100644
--- a/go/src/golang.org/x/tools/go/ssa/emit.go
+++ b/go/src/golang.org/x/tools/go/ssa/emit.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package ssa
 
 // Helpers for emitting SSA instructions.
@@ -10,8 +12,7 @@
 	"fmt"
 	"go/ast"
 	"go/token"
-
-	"golang.org/x/tools/go/types"
+	"go/types"
 )
 
 // emitNew emits to f a new (heap Alloc) instruction allocating an
diff --git a/go/src/golang.org/x/tools/go/ssa/emit14.go b/go/src/golang.org/x/tools/go/ssa/emit14.go
new file mode 100644
index 0000000..454aea0
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/ssa/emit14.go
@@ -0,0 +1,471 @@
+// 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.
+
+// +build !go1.5
+
+package ssa
+
+// Helpers for emitting SSA instructions.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+
+	"golang.org/x/tools/go/types"
+)
+
+// emitNew emits to f a new (heap Alloc) instruction allocating an
+// object of type typ.  pos is the optional source location.
+//
+func emitNew(f *Function, typ types.Type, pos token.Pos) *Alloc {
+	v := &Alloc{Heap: true}
+	v.setType(types.NewPointer(typ))
+	v.setPos(pos)
+	f.emit(v)
+	return v
+}
+
+// emitLoad emits to f an instruction to load the address addr into a
+// new temporary, and returns the value so defined.
+//
+func emitLoad(f *Function, addr Value) *UnOp {
+	v := &UnOp{Op: token.MUL, X: addr}
+	v.setType(deref(addr.Type()))
+	f.emit(v)
+	return v
+}
+
+// emitDebugRef emits to f a DebugRef pseudo-instruction associating
+// expression e with value v.
+//
+func emitDebugRef(f *Function, e ast.Expr, v Value, isAddr bool) {
+	if !f.debugInfo() {
+		return // debugging not enabled
+	}
+	if v == nil || e == nil {
+		panic("nil")
+	}
+	var obj types.Object
+	e = unparen(e)
+	if id, ok := e.(*ast.Ident); ok {
+		if isBlankIdent(id) {
+			return
+		}
+		obj = f.Pkg.objectOf(id)
+		switch obj.(type) {
+		case *types.Nil, *types.Const, *types.Builtin:
+			return
+		}
+	}
+	f.emit(&DebugRef{
+		X:      v,
+		Expr:   e,
+		IsAddr: isAddr,
+		object: obj,
+	})
+}
+
+// emitArith emits to f code to compute the binary operation op(x, y)
+// where op is an eager shift, logical or arithmetic operation.
+// (Use emitCompare() for comparisons and Builder.logicalBinop() for
+// non-eager operations.)
+//
+func emitArith(f *Function, op token.Token, x, y Value, t types.Type, pos token.Pos) Value {
+	switch op {
+	case token.SHL, token.SHR:
+		x = emitConv(f, x, t)
+		// y may be signed or an 'untyped' constant.
+		// TODO(adonovan): whence signed values?
+		if b, ok := y.Type().Underlying().(*types.Basic); ok && b.Info()&types.IsUnsigned == 0 {
+			y = emitConv(f, y, types.Typ[types.Uint64])
+		}
+
+	case token.ADD, token.SUB, token.MUL, token.QUO, token.REM, token.AND, token.OR, token.XOR, token.AND_NOT:
+		x = emitConv(f, x, t)
+		y = emitConv(f, y, t)
+
+	default:
+		panic("illegal op in emitArith: " + op.String())
+
+	}
+	v := &BinOp{
+		Op: op,
+		X:  x,
+		Y:  y,
+	}
+	v.setPos(pos)
+	v.setType(t)
+	return f.emit(v)
+}
+
+// emitCompare emits to f code compute the boolean result of
+// comparison comparison 'x op y'.
+//
+func emitCompare(f *Function, op token.Token, x, y Value, pos token.Pos) Value {
+	xt := x.Type().Underlying()
+	yt := y.Type().Underlying()
+
+	// Special case to optimise a tagless SwitchStmt so that
+	// these are equivalent
+	//   switch { case e: ...}
+	//   switch true { case e: ... }
+	//   if e==true { ... }
+	// even in the case when e's type is an interface.
+	// TODO(adonovan): opt: generalise to x==true, false!=y, etc.
+	if x == vTrue && op == token.EQL {
+		if yt, ok := yt.(*types.Basic); ok && yt.Info()&types.IsBoolean != 0 {
+			return y
+		}
+	}
+
+	if types.Identical(xt, yt) {
+		// no conversion necessary
+	} else if _, ok := xt.(*types.Interface); ok {
+		y = emitConv(f, y, x.Type())
+	} else if _, ok := yt.(*types.Interface); ok {
+		x = emitConv(f, x, y.Type())
+	} else if _, ok := x.(*Const); ok {
+		x = emitConv(f, x, y.Type())
+	} else if _, ok := y.(*Const); ok {
+		y = emitConv(f, y, x.Type())
+	} else {
+		// other cases, e.g. channels.  No-op.
+	}
+
+	v := &BinOp{
+		Op: op,
+		X:  x,
+		Y:  y,
+	}
+	v.setPos(pos)
+	v.setType(tBool)
+	return f.emit(v)
+}
+
+// isValuePreserving returns true if a conversion from ut_src to
+// ut_dst is value-preserving, i.e. just a change of type.
+// Precondition: neither argument is a named type.
+//
+func isValuePreserving(ut_src, ut_dst types.Type) bool {
+	// Identical underlying types?
+	if types.Identical(ut_dst, ut_src) {
+		return true
+	}
+
+	switch ut_dst.(type) {
+	case *types.Chan:
+		// Conversion between channel types?
+		_, ok := ut_src.(*types.Chan)
+		return ok
+
+	case *types.Pointer:
+		// Conversion between pointers with identical base types?
+		_, ok := ut_src.(*types.Pointer)
+		return ok
+	}
+	return false
+}
+
+// emitConv emits to f code to convert Value val to exactly type typ,
+// and returns the converted value.  Implicit conversions are required
+// by language assignability rules in assignments, parameter passing,
+// etc.  Conversions cannot fail dynamically.
+//
+func emitConv(f *Function, val Value, typ types.Type) Value {
+	t_src := val.Type()
+
+	// Identical types?  Conversion is a no-op.
+	if types.Identical(t_src, typ) {
+		return val
+	}
+
+	ut_dst := typ.Underlying()
+	ut_src := t_src.Underlying()
+
+	// Just a change of type, but not value or representation?
+	if isValuePreserving(ut_src, ut_dst) {
+		c := &ChangeType{X: val}
+		c.setType(typ)
+		return f.emit(c)
+	}
+
+	// Conversion to, or construction of a value of, an interface type?
+	if _, ok := ut_dst.(*types.Interface); ok {
+		// Assignment from one interface type to another?
+		if _, ok := ut_src.(*types.Interface); ok {
+			c := &ChangeInterface{X: val}
+			c.setType(typ)
+			return f.emit(c)
+		}
+
+		// Untyped nil constant?  Return interface-typed nil constant.
+		if ut_src == tUntypedNil {
+			return nilConst(typ)
+		}
+
+		// Convert (non-nil) "untyped" literals to their default type.
+		if t, ok := ut_src.(*types.Basic); ok && t.Info()&types.IsUntyped != 0 {
+			val = emitConv(f, val, DefaultType(ut_src))
+		}
+
+		f.Pkg.Prog.needMethodsOf(val.Type())
+		mi := &MakeInterface{X: val}
+		mi.setType(typ)
+		return f.emit(mi)
+	}
+
+	// Conversion of a compile-time constant value?
+	if c, ok := val.(*Const); ok {
+		if _, ok := ut_dst.(*types.Basic); ok || c.IsNil() {
+			// Conversion of a compile-time constant to
+			// another constant type results in a new
+			// constant of the destination type and
+			// (initially) the same abstract value.
+			// We don't truncate the value yet.
+			return NewConst(c.Value, typ)
+		}
+
+		// We're converting from constant to non-constant type,
+		// e.g. string -> []byte/[]rune.
+	}
+
+	// A representation-changing conversion?
+	// At least one of {ut_src,ut_dst} must be *Basic.
+	// (The other may be []byte or []rune.)
+	_, ok1 := ut_src.(*types.Basic)
+	_, ok2 := ut_dst.(*types.Basic)
+	if ok1 || ok2 {
+		c := &Convert{X: val}
+		c.setType(typ)
+		return f.emit(c)
+	}
+
+	panic(fmt.Sprintf("in %s: cannot convert %s (%s) to %s", f, val, val.Type(), typ))
+}
+
+// emitStore emits to f an instruction to store value val at location
+// addr, applying implicit conversions as required by assignability rules.
+//
+func emitStore(f *Function, addr, val Value, pos token.Pos) *Store {
+	s := &Store{
+		Addr: addr,
+		Val:  emitConv(f, val, deref(addr.Type())),
+		pos:  pos,
+	}
+	f.emit(s)
+	return s
+}
+
+// emitJump emits to f a jump to target, and updates the control-flow graph.
+// Postcondition: f.currentBlock is nil.
+//
+func emitJump(f *Function, target *BasicBlock) {
+	b := f.currentBlock
+	b.emit(new(Jump))
+	addEdge(b, target)
+	f.currentBlock = nil
+}
+
+// emitIf emits to f a conditional jump to tblock or fblock based on
+// cond, and updates the control-flow graph.
+// Postcondition: f.currentBlock is nil.
+//
+func emitIf(f *Function, cond Value, tblock, fblock *BasicBlock) {
+	b := f.currentBlock
+	b.emit(&If{Cond: cond})
+	addEdge(b, tblock)
+	addEdge(b, fblock)
+	f.currentBlock = nil
+}
+
+// emitExtract emits to f an instruction to extract the index'th
+// component of tuple.  It returns the extracted value.
+//
+func emitExtract(f *Function, tuple Value, index int) Value {
+	e := &Extract{Tuple: tuple, Index: index}
+	e.setType(tuple.Type().(*types.Tuple).At(index).Type())
+	return f.emit(e)
+}
+
+// emitTypeAssert emits to f a type assertion value := x.(t) and
+// returns the value.  x.Type() must be an interface.
+//
+func emitTypeAssert(f *Function, x Value, t types.Type, pos token.Pos) Value {
+	a := &TypeAssert{X: x, AssertedType: t}
+	a.setPos(pos)
+	a.setType(t)
+	return f.emit(a)
+}
+
+// emitTypeTest emits to f a type test value,ok := x.(t) and returns
+// a (value, ok) tuple.  x.Type() must be an interface.
+//
+func emitTypeTest(f *Function, x Value, t types.Type, pos token.Pos) Value {
+	a := &TypeAssert{
+		X:            x,
+		AssertedType: t,
+		CommaOk:      true,
+	}
+	a.setPos(pos)
+	a.setType(types.NewTuple(
+		newVar("value", t),
+		varOk,
+	))
+	return f.emit(a)
+}
+
+// emitTailCall emits to f a function call in tail position.  The
+// caller is responsible for all fields of 'call' except its type.
+// Intended for wrapper methods.
+// Precondition: f does/will not use deferred procedure calls.
+// Postcondition: f.currentBlock is nil.
+//
+func emitTailCall(f *Function, call *Call) {
+	tresults := f.Signature.Results()
+	nr := tresults.Len()
+	if nr == 1 {
+		call.typ = tresults.At(0).Type()
+	} else {
+		call.typ = tresults
+	}
+	tuple := f.emit(call)
+	var ret Return
+	switch nr {
+	case 0:
+		// no-op
+	case 1:
+		ret.Results = []Value{tuple}
+	default:
+		for i := 0; i < nr; i++ {
+			v := emitExtract(f, tuple, i)
+			// TODO(adonovan): in principle, this is required:
+			//   v = emitConv(f, o.Type, f.Signature.Results[i].Type)
+			// but in practice emitTailCall is only used when
+			// the types exactly match.
+			ret.Results = append(ret.Results, v)
+		}
+	}
+	f.emit(&ret)
+	f.currentBlock = nil
+}
+
+// emitImplicitSelections emits to f code to apply the sequence of
+// implicit field selections specified by indices to base value v, and
+// returns the selected value.
+//
+// If v is the address of a struct, the result will be the address of
+// a field; if it is the value of a struct, the result will be the
+// value of a field.
+//
+func emitImplicitSelections(f *Function, v Value, indices []int) Value {
+	for _, index := range indices {
+		fld := deref(v.Type()).Underlying().(*types.Struct).Field(index)
+
+		if isPointer(v.Type()) {
+			instr := &FieldAddr{
+				X:     v,
+				Field: index,
+			}
+			instr.setType(types.NewPointer(fld.Type()))
+			v = f.emit(instr)
+			// Load the field's value iff indirectly embedded.
+			if isPointer(fld.Type()) {
+				v = emitLoad(f, v)
+			}
+		} else {
+			instr := &Field{
+				X:     v,
+				Field: index,
+			}
+			instr.setType(fld.Type())
+			v = f.emit(instr)
+		}
+	}
+	return v
+}
+
+// emitFieldSelection emits to f code to select the index'th field of v.
+//
+// If wantAddr, the input must be a pointer-to-struct and the result
+// will be the field's address; otherwise the result will be the
+// field's value.
+// Ident id is used for position and debug info.
+//
+func emitFieldSelection(f *Function, v Value, index int, wantAddr bool, id *ast.Ident) Value {
+	fld := deref(v.Type()).Underlying().(*types.Struct).Field(index)
+	if isPointer(v.Type()) {
+		instr := &FieldAddr{
+			X:     v,
+			Field: index,
+		}
+		instr.setPos(id.Pos())
+		instr.setType(types.NewPointer(fld.Type()))
+		v = f.emit(instr)
+		// Load the field's value iff we don't want its address.
+		if !wantAddr {
+			v = emitLoad(f, v)
+		}
+	} else {
+		instr := &Field{
+			X:     v,
+			Field: index,
+		}
+		instr.setPos(id.Pos())
+		instr.setType(fld.Type())
+		v = f.emit(instr)
+	}
+	emitDebugRef(f, id, v, wantAddr)
+	return v
+}
+
+// zeroValue emits to f code to produce a zero value of type t,
+// and returns it.
+//
+func zeroValue(f *Function, t types.Type) Value {
+	switch t.Underlying().(type) {
+	case *types.Struct, *types.Array:
+		return emitLoad(f, f.addLocal(t, token.NoPos))
+	default:
+		return zeroConst(t)
+	}
+}
+
+// createRecoverBlock emits to f a block of code to return after a
+// recovered panic, and sets f.Recover to it.
+//
+// If f's result parameters are named, the code loads and returns
+// their current values, otherwise it returns the zero values of their
+// type.
+//
+// Idempotent.
+//
+func createRecoverBlock(f *Function) {
+	if f.Recover != nil {
+		return // already created
+	}
+	saved := f.currentBlock
+
+	f.Recover = f.newBasicBlock("recover")
+	f.currentBlock = f.Recover
+
+	var results []Value
+	if f.namedResults != nil {
+		// Reload NRPs to form value tuple.
+		for _, r := range f.namedResults {
+			results = append(results, emitLoad(f, r))
+		}
+	} else {
+		R := f.Signature.Results()
+		for i, n := 0, R.Len(); i < n; i++ {
+			T := R.At(i).Type()
+
+			// Return zero value of each result type.
+			results = append(results, zeroValue(f, T))
+		}
+	}
+	f.emit(&Return{Results: results})
+
+	f.currentBlock = saved
+}
diff --git a/go/src/golang.org/x/tools/go/ssa/example14_test.go b/go/src/golang.org/x/tools/go/ssa/example14_test.go
new file mode 100644
index 0000000..0171d4f
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/ssa/example14_test.go
@@ -0,0 +1,140 @@
+// 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.
+
+// +build !go1.5
+
+package ssa_test
+
+import (
+	"fmt"
+	"os"
+
+	"go/ast"
+	"go/parser"
+	"go/token"
+
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/ssa/ssautil"
+	"golang.org/x/tools/go/types"
+)
+
+const hello = `
+package main
+
+import "fmt"
+
+const message = "Hello, World!"
+
+func main() {
+	fmt.Println(message)
+}
+`
+
+// This program demonstrates how to run the SSA builder on a single
+// package of one or more already-parsed files.  Its dependencies are
+// loaded from compiler export data.  This is what you'd typically use
+// for a compiler; it does not depend on golang.org/x/tools/go/loader.
+//
+// It shows the printed representation of packages, functions, and
+// instructions.  Within the function listing, the name of each
+// BasicBlock such as ".0.entry" is printed left-aligned, followed by
+// the block's Instructions.
+//
+// For each instruction that defines an SSA virtual register
+// (i.e. implements Value), the type of that value is shown in the
+// right column.
+//
+// Build and run the ssadump.go program if you want a standalone tool
+// with similar functionality. It is located at
+// golang.org/x/tools/cmd/ssadump.
+//
+func ExampleBuildPackage() {
+	// Parse the source files.
+	fset := token.NewFileSet()
+	f, err := parser.ParseFile(fset, "hello.go", hello, parser.ParseComments)
+	if err != nil {
+		fmt.Print(err) // parse error
+		return
+	}
+	files := []*ast.File{f}
+
+	// Create the type-checker's package.
+	pkg := types.NewPackage("hello", "")
+
+	// Type-check the package, load dependencies.
+	// Create and build the SSA program.
+	hello, _, err := ssautil.BuildPackage(
+		new(types.Config), fset, pkg, files, ssa.SanityCheckFunctions)
+	if err != nil {
+		fmt.Print(err) // type error in some package
+		return
+	}
+
+	// Print out the package.
+	hello.WriteTo(os.Stdout)
+
+	// Print out the package-level functions.
+	hello.Func("init").WriteTo(os.Stdout)
+	hello.Func("main").WriteTo(os.Stdout)
+
+	// Output:
+	//
+	// package hello:
+	//   func  init       func()
+	//   var   init$guard bool
+	//   func  main       func()
+	//   const message    message = "Hello, World!":untyped string
+	//
+	// # Name: hello.init
+	// # Package: hello
+	// # Synthetic: package initializer
+	// func init():
+	// 0:                                                                entry P:0 S:2
+	// 	t0 = *init$guard                                                   bool
+	// 	if t0 goto 2 else 1
+	// 1:                                                           init.start P:1 S:1
+	// 	*init$guard = true:bool
+	// 	t1 = fmt.init()                                                      ()
+	// 	jump 2
+	// 2:                                                            init.done P:2 S:0
+	// 	return
+	//
+	// # Name: hello.main
+	// # Package: hello
+	// # Location: hello.go:8:6
+	// func main():
+	// 0:                                                                entry P:0 S:0
+	// 	t0 = new [1]interface{} (varargs)                       *[1]interface{}
+	// 	t1 = &t0[0:int]                                            *interface{}
+	// 	t2 = make interface{} <- string ("Hello, World!":string)    interface{}
+	// 	*t1 = t2
+	// 	t3 = slice t0[:]                                          []interface{}
+	// 	t4 = fmt.Println(t3...)                              (n int, err error)
+	// 	return
+}
+
+// This program shows how to load a main package (cmd/cover) and all its
+// dependencies from source, using the loader, and then build SSA code
+// for the entire program.  This is what you'd typically use for a
+// whole-program analysis.
+//
+func ExampleLoadProgram() {
+	// Load cmd/cover and its dependencies.
+	var conf loader.Config
+	conf.Import("cmd/cover")
+	lprog, err := conf.Load()
+	if err != nil {
+		fmt.Print(err) // type error in some package
+		return
+	}
+
+	// Create SSA-form program representation.
+	prog := ssautil.CreateProgram(lprog, ssa.SanityCheckFunctions)
+
+	// Build SSA code for the entire cmd/cover program.
+	prog.Build()
+
+	// Output:
+}
diff --git a/go/src/golang.org/x/tools/go/ssa/example_test.go b/go/src/golang.org/x/tools/go/ssa/example_test.go
index 3e095b8..718817c 100644
--- a/go/src/golang.org/x/tools/go/ssa/example_test.go
+++ b/go/src/golang.org/x/tools/go/ssa/example_test.go
@@ -2,20 +2,22 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package ssa_test
 
 import (
 	"fmt"
-	"os"
-
 	"go/ast"
+	"go/importer"
 	"go/parser"
 	"go/token"
+	"go/types"
+	"os"
 
 	"golang.org/x/tools/go/loader"
 	"golang.org/x/tools/go/ssa"
 	"golang.org/x/tools/go/ssa/ssautil"
-	"golang.org/x/tools/go/types"
 )
 
 const hello = `
@@ -64,7 +66,7 @@
 	// Type-check the package, load dependencies.
 	// Create and build the SSA program.
 	hello, _, err := ssautil.BuildPackage(
-		new(types.Config), fset, pkg, files, ssa.SanityCheckFunctions)
+		&types.Config{Importer: importer.Default()}, fset, pkg, files, ssa.SanityCheckFunctions)
 	if err != nil {
 		fmt.Print(err) // type error in some package
 		return
@@ -113,15 +115,15 @@
 	// 	return
 }
 
-// This program shows how to load a main package (cmd/nm) and all its
+// This program shows how to load a main package (cmd/cover) and all its
 // dependencies from source, using the loader, and then build SSA code
 // for the entire program.  This is what you'd typically use for a
 // whole-program analysis.
 //
 func ExampleLoadProgram() {
-	// Load cmd/nm and its dependencies.
+	// Load cmd/cover and its dependencies.
 	var conf loader.Config
-	conf.Import("cmd/nm")
+	conf.Import("cmd/cover")
 	lprog, err := conf.Load()
 	if err != nil {
 		fmt.Print(err) // type error in some package
@@ -131,8 +133,8 @@
 	// Create SSA-form program representation.
 	prog := ssautil.CreateProgram(lprog, ssa.SanityCheckFunctions)
 
-	// Build SSA code for the entire cmd/nm program.
-	prog.BuildAll()
+	// Build SSA code for the entire cmd/cover program.
+	prog.Build()
 
 	// Output:
 }
diff --git a/go/src/golang.org/x/tools/go/ssa/func.go b/go/src/golang.org/x/tools/go/ssa/func.go
index a9c0f75..88052c3 100644
--- a/go/src/golang.org/x/tools/go/ssa/func.go
+++ b/go/src/golang.org/x/tools/go/ssa/func.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package ssa
 
 // This file implements the Function and BasicBlock types.
@@ -11,11 +13,10 @@
 	"fmt"
 	"go/ast"
 	"go/token"
+	"go/types"
 	"io"
 	"os"
 	"strings"
-
-	"golang.org/x/tools/go/types"
 )
 
 // addEdge adds a control-flow graph edge from from to to.
@@ -501,7 +502,7 @@
 
 	// Package-level function?
 	// Prefix with package name for cross-package references only.
-	if p := f.pkgobj(); p != nil && p != from {
+	if p := f.pkg(); p != nil && p != from {
 		return fmt.Sprintf("%s.%s", p.Path(), f.name)
 	}
 
@@ -529,9 +530,9 @@
 	types.WriteSignature(buf, sig, types.RelativeTo(from))
 }
 
-func (f *Function) pkgobj() *types.Package {
+func (f *Function) pkg() *types.Package {
 	if f.Pkg != nil {
-		return f.Pkg.Object
+		return f.Pkg.Pkg
 	}
 	return nil
 }
@@ -549,7 +550,7 @@
 func WriteFunction(buf *bytes.Buffer, f *Function) {
 	fmt.Fprintf(buf, "# Name: %s\n", f.String())
 	if f.Pkg != nil {
-		fmt.Fprintf(buf, "# Package: %s\n", f.Pkg.Object.Path())
+		fmt.Fprintf(buf, "# Package: %s\n", f.Pkg.Pkg.Path())
 	}
 	if syn := f.Synthetic; syn != "" {
 		fmt.Fprintln(buf, "# Synthetic:", syn)
@@ -566,7 +567,7 @@
 		fmt.Fprintf(buf, "# Recover: %s\n", f.Recover)
 	}
 
-	from := f.pkgobj()
+	from := f.pkg()
 
 	if f.FreeVars != nil {
 		buf.WriteString("# Free variables:\n")
diff --git a/go/src/golang.org/x/tools/go/ssa/func14.go b/go/src/golang.org/x/tools/go/ssa/func14.go
new file mode 100644
index 0000000..528f66e
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/ssa/func14.go
@@ -0,0 +1,692 @@
+// 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.
+
+// +build !go1.5
+
+package ssa
+
+// This file implements the Function and BasicBlock types.
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/token"
+	"io"
+	"os"
+	"strings"
+
+	"golang.org/x/tools/go/types"
+)
+
+// addEdge adds a control-flow graph edge from from to to.
+func addEdge(from, to *BasicBlock) {
+	from.Succs = append(from.Succs, to)
+	to.Preds = append(to.Preds, from)
+}
+
+// Parent returns the function that contains block b.
+func (b *BasicBlock) Parent() *Function { return b.parent }
+
+// String returns a human-readable label of this block.
+// It is not guaranteed unique within the function.
+//
+func (b *BasicBlock) String() string {
+	return fmt.Sprintf("%d", b.Index)
+}
+
+// emit appends an instruction to the current basic block.
+// If the instruction defines a Value, it is returned.
+//
+func (b *BasicBlock) emit(i Instruction) Value {
+	i.setBlock(b)
+	b.Instrs = append(b.Instrs, i)
+	v, _ := i.(Value)
+	return v
+}
+
+// predIndex returns the i such that b.Preds[i] == c or panics if
+// there is none.
+func (b *BasicBlock) predIndex(c *BasicBlock) int {
+	for i, pred := range b.Preds {
+		if pred == c {
+			return i
+		}
+	}
+	panic(fmt.Sprintf("no edge %s -> %s", c, b))
+}
+
+// hasPhi returns true if b.Instrs contains φ-nodes.
+func (b *BasicBlock) hasPhi() bool {
+	_, ok := b.Instrs[0].(*Phi)
+	return ok
+}
+
+// phis returns the prefix of b.Instrs containing all the block's φ-nodes.
+func (b *BasicBlock) phis() []Instruction {
+	for i, instr := range b.Instrs {
+		if _, ok := instr.(*Phi); !ok {
+			return b.Instrs[:i]
+		}
+	}
+	return nil // unreachable in well-formed blocks
+}
+
+// replacePred replaces all occurrences of p in b's predecessor list with q.
+// Ordinarily there should be at most one.
+//
+func (b *BasicBlock) replacePred(p, q *BasicBlock) {
+	for i, pred := range b.Preds {
+		if pred == p {
+			b.Preds[i] = q
+		}
+	}
+}
+
+// replaceSucc replaces all occurrences of p in b's successor list with q.
+// Ordinarily there should be at most one.
+//
+func (b *BasicBlock) replaceSucc(p, q *BasicBlock) {
+	for i, succ := range b.Succs {
+		if succ == p {
+			b.Succs[i] = q
+		}
+	}
+}
+
+// removePred removes all occurrences of p in b's
+// predecessor list and φ-nodes.
+// Ordinarily there should be at most one.
+//
+func (b *BasicBlock) removePred(p *BasicBlock) {
+	phis := b.phis()
+
+	// We must preserve edge order for φ-nodes.
+	j := 0
+	for i, pred := range b.Preds {
+		if pred != p {
+			b.Preds[j] = b.Preds[i]
+			// Strike out φ-edge too.
+			for _, instr := range phis {
+				phi := instr.(*Phi)
+				phi.Edges[j] = phi.Edges[i]
+			}
+			j++
+		}
+	}
+	// Nil out b.Preds[j:] and φ-edges[j:] to aid GC.
+	for i := j; i < len(b.Preds); i++ {
+		b.Preds[i] = nil
+		for _, instr := range phis {
+			instr.(*Phi).Edges[i] = nil
+		}
+	}
+	b.Preds = b.Preds[:j]
+	for _, instr := range phis {
+		phi := instr.(*Phi)
+		phi.Edges = phi.Edges[:j]
+	}
+}
+
+// Destinations associated with unlabelled for/switch/select stmts.
+// We push/pop one of these as we enter/leave each construct and for
+// each BranchStmt we scan for the innermost target of the right type.
+//
+type targets struct {
+	tail         *targets // rest of stack
+	_break       *BasicBlock
+	_continue    *BasicBlock
+	_fallthrough *BasicBlock
+}
+
+// Destinations associated with a labelled block.
+// We populate these as labels are encountered in forward gotos or
+// labelled statements.
+//
+type lblock struct {
+	_goto     *BasicBlock
+	_break    *BasicBlock
+	_continue *BasicBlock
+}
+
+// labelledBlock returns the branch target associated with the
+// specified label, creating it if needed.
+//
+func (f *Function) labelledBlock(label *ast.Ident) *lblock {
+	lb := f.lblocks[label.Obj]
+	if lb == nil {
+		lb = &lblock{_goto: f.newBasicBlock(label.Name)}
+		if f.lblocks == nil {
+			f.lblocks = make(map[*ast.Object]*lblock)
+		}
+		f.lblocks[label.Obj] = lb
+	}
+	return lb
+}
+
+// addParam adds a (non-escaping) parameter to f.Params of the
+// specified name, type and source position.
+//
+func (f *Function) addParam(name string, typ types.Type, pos token.Pos) *Parameter {
+	v := &Parameter{
+		name:   name,
+		typ:    typ,
+		pos:    pos,
+		parent: f,
+	}
+	f.Params = append(f.Params, v)
+	return v
+}
+
+func (f *Function) addParamObj(obj types.Object) *Parameter {
+	name := obj.Name()
+	if name == "" {
+		name = fmt.Sprintf("arg%d", len(f.Params))
+	}
+	param := f.addParam(name, obj.Type(), obj.Pos())
+	param.object = obj
+	return param
+}
+
+// addSpilledParam declares a parameter that is pre-spilled to the
+// stack; the function body will load/store the spilled location.
+// Subsequent lifting will eliminate spills where possible.
+//
+func (f *Function) addSpilledParam(obj types.Object) {
+	param := f.addParamObj(obj)
+	spill := &Alloc{Comment: obj.Name()}
+	spill.setType(types.NewPointer(obj.Type()))
+	spill.setPos(obj.Pos())
+	f.objects[obj] = spill
+	f.Locals = append(f.Locals, spill)
+	f.emit(spill)
+	f.emit(&Store{Addr: spill, Val: param})
+}
+
+// startBody initializes the function prior to generating SSA code for its body.
+// Precondition: f.Type() already set.
+//
+func (f *Function) startBody() {
+	f.currentBlock = f.newBasicBlock("entry")
+	f.objects = make(map[types.Object]Value) // needed for some synthetics, e.g. init
+}
+
+// createSyntacticParams populates f.Params and generates code (spills
+// and named result locals) for all the parameters declared in the
+// syntax.  In addition it populates the f.objects mapping.
+//
+// Preconditions:
+// f.startBody() was called.
+// Postcondition:
+// len(f.Params) == len(f.Signature.Params) + (f.Signature.Recv() ? 1 : 0)
+//
+func (f *Function) createSyntacticParams(recv *ast.FieldList, functype *ast.FuncType) {
+	// Receiver (at most one inner iteration).
+	if recv != nil {
+		for _, field := range recv.List {
+			for _, n := range field.Names {
+				f.addSpilledParam(f.Pkg.info.Defs[n])
+			}
+			// Anonymous receiver?  No need to spill.
+			if field.Names == nil {
+				f.addParamObj(f.Signature.Recv())
+			}
+		}
+	}
+
+	// Parameters.
+	if functype.Params != nil {
+		n := len(f.Params) // 1 if has recv, 0 otherwise
+		for _, field := range functype.Params.List {
+			for _, n := range field.Names {
+				f.addSpilledParam(f.Pkg.info.Defs[n])
+			}
+			// Anonymous parameter?  No need to spill.
+			if field.Names == nil {
+				f.addParamObj(f.Signature.Params().At(len(f.Params) - n))
+			}
+		}
+	}
+
+	// Named results.
+	if functype.Results != nil {
+		for _, field := range functype.Results.List {
+			// Implicit "var" decl of locals for named results.
+			for _, n := range field.Names {
+				f.namedResults = append(f.namedResults, f.addLocalForIdent(n))
+			}
+		}
+	}
+}
+
+// numberRegisters assigns numbers to all SSA registers
+// (value-defining Instructions) in f, to aid debugging.
+// (Non-Instruction Values are named at construction.)
+//
+func numberRegisters(f *Function) {
+	v := 0
+	for _, b := range f.Blocks {
+		for _, instr := range b.Instrs {
+			switch instr.(type) {
+			case Value:
+				instr.(interface {
+					setNum(int)
+				}).setNum(v)
+				v++
+			}
+		}
+	}
+}
+
+// buildReferrers populates the def/use information in all non-nil
+// Value.Referrers slice.
+// Precondition: all such slices are initially empty.
+func buildReferrers(f *Function) {
+	var rands []*Value
+	for _, b := range f.Blocks {
+		for _, instr := range b.Instrs {
+			rands = instr.Operands(rands[:0]) // recycle storage
+			for _, rand := range rands {
+				if r := *rand; r != nil {
+					if ref := r.Referrers(); ref != nil {
+						*ref = append(*ref, instr)
+					}
+				}
+			}
+		}
+	}
+}
+
+// finishBody() finalizes the function after SSA code generation of its body.
+func (f *Function) finishBody() {
+	f.objects = nil
+	f.currentBlock = nil
+	f.lblocks = nil
+
+	// Don't pin the AST in memory (except in debug mode).
+	if n := f.syntax; n != nil && !f.debugInfo() {
+		f.syntax = extentNode{n.Pos(), n.End()}
+	}
+
+	// Remove from f.Locals any Allocs that escape to the heap.
+	j := 0
+	for _, l := range f.Locals {
+		if !l.Heap {
+			f.Locals[j] = l
+			j++
+		}
+	}
+	// Nil out f.Locals[j:] to aid GC.
+	for i := j; i < len(f.Locals); i++ {
+		f.Locals[i] = nil
+	}
+	f.Locals = f.Locals[:j]
+
+	optimizeBlocks(f)
+
+	buildReferrers(f)
+
+	buildDomTree(f)
+
+	if f.Prog.mode&NaiveForm == 0 {
+		// For debugging pre-state of lifting pass:
+		// numberRegisters(f)
+		// f.WriteTo(os.Stderr)
+		lift(f)
+	}
+
+	f.namedResults = nil // (used by lifting)
+
+	numberRegisters(f)
+
+	if f.Prog.mode&PrintFunctions != 0 {
+		printMu.Lock()
+		f.WriteTo(os.Stdout)
+		printMu.Unlock()
+	}
+
+	if f.Prog.mode&SanityCheckFunctions != 0 {
+		mustSanityCheck(f, nil)
+	}
+}
+
+// removeNilBlocks eliminates nils from f.Blocks and updates each
+// BasicBlock.Index.  Use this after any pass that may delete blocks.
+//
+func (f *Function) removeNilBlocks() {
+	j := 0
+	for _, b := range f.Blocks {
+		if b != nil {
+			b.Index = j
+			f.Blocks[j] = b
+			j++
+		}
+	}
+	// Nil out f.Blocks[j:] to aid GC.
+	for i := j; i < len(f.Blocks); i++ {
+		f.Blocks[i] = nil
+	}
+	f.Blocks = f.Blocks[:j]
+}
+
+// SetDebugMode sets the debug mode for package pkg.  If true, all its
+// functions will include full debug info.  This greatly increases the
+// size of the instruction stream, and causes Functions to depend upon
+// the ASTs, potentially keeping them live in memory for longer.
+//
+func (pkg *Package) SetDebugMode(debug bool) {
+	// TODO(adonovan): do we want ast.File granularity?
+	pkg.debug = debug
+}
+
+// debugInfo reports whether debug info is wanted for this function.
+func (f *Function) debugInfo() bool {
+	return f.Pkg != nil && f.Pkg.debug
+}
+
+// addNamedLocal creates a local variable, adds it to function f and
+// returns it.  Its name and type are taken from obj.  Subsequent
+// calls to f.lookup(obj) will return the same local.
+//
+func (f *Function) addNamedLocal(obj types.Object) *Alloc {
+	l := f.addLocal(obj.Type(), obj.Pos())
+	l.Comment = obj.Name()
+	f.objects[obj] = l
+	return l
+}
+
+func (f *Function) addLocalForIdent(id *ast.Ident) *Alloc {
+	return f.addNamedLocal(f.Pkg.info.Defs[id])
+}
+
+// addLocal creates an anonymous local variable of type typ, adds it
+// to function f and returns it.  pos is the optional source location.
+//
+func (f *Function) addLocal(typ types.Type, pos token.Pos) *Alloc {
+	v := &Alloc{}
+	v.setType(types.NewPointer(typ))
+	v.setPos(pos)
+	f.Locals = append(f.Locals, v)
+	f.emit(v)
+	return v
+}
+
+// lookup returns the address of the named variable identified by obj
+// that is local to function f or one of its enclosing functions.
+// If escaping, the reference comes from a potentially escaping pointer
+// expression and the referent must be heap-allocated.
+//
+func (f *Function) lookup(obj types.Object, escaping bool) Value {
+	if v, ok := f.objects[obj]; ok {
+		if alloc, ok := v.(*Alloc); ok && escaping {
+			alloc.Heap = true
+		}
+		return v // function-local var (address)
+	}
+
+	// Definition must be in an enclosing function;
+	// plumb it through intervening closures.
+	if f.parent == nil {
+		panic("no ssa.Value for " + obj.String())
+	}
+	outer := f.parent.lookup(obj, true) // escaping
+	v := &FreeVar{
+		name:   obj.Name(),
+		typ:    outer.Type(),
+		pos:    outer.Pos(),
+		outer:  outer,
+		parent: f,
+	}
+	f.objects[obj] = v
+	f.FreeVars = append(f.FreeVars, v)
+	return v
+}
+
+// emit emits the specified instruction to function f.
+func (f *Function) emit(instr Instruction) Value {
+	return f.currentBlock.emit(instr)
+}
+
+// RelString returns the full name of this function, qualified by
+// package name, receiver type, etc.
+//
+// The specific formatting rules are not guaranteed and may change.
+//
+// Examples:
+//      "math.IsNaN"                  // a package-level function
+//      "(*bytes.Buffer).Bytes"       // a declared method or a wrapper
+//      "(*bytes.Buffer).Bytes$thunk" // thunk (func wrapping method; receiver is param 0)
+//      "(*bytes.Buffer).Bytes$bound" // bound (func wrapping method; receiver supplied by closure)
+//      "main.main$1"                 // an anonymous function in main
+//      "main.init#1"                 // a declared init function
+//      "main.init"                   // the synthesized package initializer
+//
+// When these functions are referred to from within the same package
+// (i.e. from == f.Pkg.Object), they are rendered without the package path.
+// For example: "IsNaN", "(*Buffer).Bytes", etc.
+//
+// All non-synthetic functions have distinct package-qualified names.
+// (But two methods may have the same name "(T).f" if one is a synthetic
+// wrapper promoting a non-exported method "f" from another package; in
+// that case, the strings are equal but the identifiers "f" are distinct.)
+//
+func (f *Function) RelString(from *types.Package) string {
+	// Anonymous?
+	if f.parent != nil {
+		// An anonymous function's Name() looks like "parentName$1",
+		// but its String() should include the type/package/etc.
+		parent := f.parent.RelString(from)
+		for i, anon := range f.parent.AnonFuncs {
+			if anon == f {
+				return fmt.Sprintf("%s$%d", parent, 1+i)
+			}
+		}
+
+		return f.name // should never happen
+	}
+
+	// Method (declared or wrapper)?
+	if recv := f.Signature.Recv(); recv != nil {
+		return f.relMethod(from, recv.Type())
+	}
+
+	// Thunk?
+	if f.method != nil {
+		return f.relMethod(from, f.method.Recv())
+	}
+
+	// Bound?
+	if len(f.FreeVars) == 1 && strings.HasSuffix(f.name, "$bound") {
+		return f.relMethod(from, f.FreeVars[0].Type())
+	}
+
+	// Package-level function?
+	// Prefix with package name for cross-package references only.
+	if p := f.pkg(); p != nil && p != from {
+		return fmt.Sprintf("%s.%s", p.Path(), f.name)
+	}
+
+	// Unknown.
+	return f.name
+}
+
+func (f *Function) relMethod(from *types.Package, recv types.Type) string {
+	return fmt.Sprintf("(%s).%s", relType(recv, from), f.name)
+}
+
+// writeSignature writes to buf the signature sig in declaration syntax.
+func writeSignature(buf *bytes.Buffer, from *types.Package, name string, sig *types.Signature, params []*Parameter) {
+	buf.WriteString("func ")
+	if recv := sig.Recv(); recv != nil {
+		buf.WriteString("(")
+		if n := params[0].Name(); n != "" {
+			buf.WriteString(n)
+			buf.WriteString(" ")
+		}
+		types.WriteType(buf, params[0].Type(), types.RelativeTo(from))
+		buf.WriteString(") ")
+	}
+	buf.WriteString(name)
+	types.WriteSignature(buf, sig, types.RelativeTo(from))
+}
+
+func (f *Function) pkg() *types.Package {
+	if f.Pkg != nil {
+		return f.Pkg.Pkg
+	}
+	return nil
+}
+
+var _ io.WriterTo = (*Function)(nil) // *Function implements io.Writer
+
+func (f *Function) WriteTo(w io.Writer) (int64, error) {
+	var buf bytes.Buffer
+	WriteFunction(&buf, f)
+	n, err := w.Write(buf.Bytes())
+	return int64(n), err
+}
+
+// WriteFunction writes to buf a human-readable "disassembly" of f.
+func WriteFunction(buf *bytes.Buffer, f *Function) {
+	fmt.Fprintf(buf, "# Name: %s\n", f.String())
+	if f.Pkg != nil {
+		fmt.Fprintf(buf, "# Package: %s\n", f.Pkg.Pkg.Path())
+	}
+	if syn := f.Synthetic; syn != "" {
+		fmt.Fprintln(buf, "# Synthetic:", syn)
+	}
+	if pos := f.Pos(); pos.IsValid() {
+		fmt.Fprintf(buf, "# Location: %s\n", f.Prog.Fset.Position(pos))
+	}
+
+	if f.parent != nil {
+		fmt.Fprintf(buf, "# Parent: %s\n", f.parent.Name())
+	}
+
+	if f.Recover != nil {
+		fmt.Fprintf(buf, "# Recover: %s\n", f.Recover)
+	}
+
+	from := f.pkg()
+
+	if f.FreeVars != nil {
+		buf.WriteString("# Free variables:\n")
+		for i, fv := range f.FreeVars {
+			fmt.Fprintf(buf, "# % 3d:\t%s %s\n", i, fv.Name(), relType(fv.Type(), from))
+		}
+	}
+
+	if len(f.Locals) > 0 {
+		buf.WriteString("# Locals:\n")
+		for i, l := range f.Locals {
+			fmt.Fprintf(buf, "# % 3d:\t%s %s\n", i, l.Name(), relType(deref(l.Type()), from))
+		}
+	}
+	writeSignature(buf, from, f.Name(), f.Signature, f.Params)
+	buf.WriteString(":\n")
+
+	if f.Blocks == nil {
+		buf.WriteString("\t(external)\n")
+	}
+
+	// NB. column calculations are confused by non-ASCII
+	// characters and assume 8-space tabs.
+	const punchcard = 80 // for old time's sake.
+	const tabwidth = 8
+	for _, b := range f.Blocks {
+		if b == nil {
+			// Corrupt CFG.
+			fmt.Fprintf(buf, ".nil:\n")
+			continue
+		}
+		n, _ := fmt.Fprintf(buf, "%d:", b.Index)
+		bmsg := fmt.Sprintf("%s P:%d S:%d", b.Comment, len(b.Preds), len(b.Succs))
+		fmt.Fprintf(buf, "%*s%s\n", punchcard-1-n-len(bmsg), "", bmsg)
+
+		if false { // CFG debugging
+			fmt.Fprintf(buf, "\t# CFG: %s --> %s --> %s\n", b.Preds, b, b.Succs)
+		}
+		for _, instr := range b.Instrs {
+			buf.WriteString("\t")
+			switch v := instr.(type) {
+			case Value:
+				l := punchcard - tabwidth
+				// Left-align the instruction.
+				if name := v.Name(); name != "" {
+					n, _ := fmt.Fprintf(buf, "%s = ", name)
+					l -= n
+				}
+				n, _ := buf.WriteString(instr.String())
+				l -= n
+				// Right-align the type if there's space.
+				if t := v.Type(); t != nil {
+					buf.WriteByte(' ')
+					ts := relType(t, from)
+					l -= len(ts) + len("  ") // (spaces before and after type)
+					if l > 0 {
+						fmt.Fprintf(buf, "%*s", l, "")
+					}
+					buf.WriteString(ts)
+				}
+			case nil:
+				// Be robust against bad transforms.
+				buf.WriteString("<deleted>")
+			default:
+				buf.WriteString(instr.String())
+			}
+			buf.WriteString("\n")
+		}
+	}
+	fmt.Fprintf(buf, "\n")
+}
+
+// newBasicBlock adds to f a new basic block and returns it.  It does
+// not automatically become the current block for subsequent calls to emit.
+// comment is an optional string for more readable debugging output.
+//
+func (f *Function) newBasicBlock(comment string) *BasicBlock {
+	b := &BasicBlock{
+		Index:   len(f.Blocks),
+		Comment: comment,
+		parent:  f,
+	}
+	b.Succs = b.succs2[:0]
+	f.Blocks = append(f.Blocks, b)
+	return b
+}
+
+// NewFunction returns a new synthetic Function instance belonging to
+// prog, with its name and signature fields set as specified.
+//
+// The caller is responsible for initializing the remaining fields of
+// the function object, e.g. Pkg, Params, Blocks.
+//
+// It is practically impossible for clients to construct well-formed
+// SSA functions/packages/programs directly, so we assume this is the
+// job of the Builder alone.  NewFunction exists to provide clients a
+// little flexibility.  For example, analysis tools may wish to
+// construct fake Functions for the root of the callgraph, a fake
+// "reflect" package, etc.
+//
+// TODO(adonovan): think harder about the API here.
+//
+func (prog *Program) NewFunction(name string, sig *types.Signature, provenance string) *Function {
+	return &Function{Prog: prog, name: name, Signature: sig, Synthetic: provenance}
+}
+
+type extentNode [2]token.Pos
+
+func (n extentNode) Pos() token.Pos { return n[0] }
+func (n extentNode) End() token.Pos { return n[1] }
+
+// Syntax returns an ast.Node whose Pos/End methods provide the
+// lexical extent of the function if it was defined by Go source code
+// (f.Synthetic==""), or nil otherwise.
+//
+// If f was built with debug information (see Package.SetDebugRef),
+// the result is the *ast.FuncDecl or *ast.FuncLit that declared the
+// function.  Otherwise, it is an opaque Node providing only position
+// information; this avoids pinning the AST in memory.
+//
+func (f *Function) Syntax() ast.Node { return f.syntax }
diff --git a/go/src/golang.org/x/tools/go/ssa/interp/external.go b/go/src/golang.org/x/tools/go/ssa/interp/external.go
index eb0757f..8ae81b2 100644
--- a/go/src/golang.org/x/tools/go/ssa/interp/external.go
+++ b/go/src/golang.org/x/tools/go/ssa/interp/external.go
@@ -2,21 +2,24 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package interp
 
 // Emulated functions that we cannot interpret because they are
 // external or because they use "unsafe" or "reflect" operations.
 
 import (
+	"go/types"
 	"math"
 	"os"
 	"runtime"
+	"strings"
 	"syscall"
 	"time"
 	"unsafe"
 
 	"golang.org/x/tools/go/ssa"
-	"golang.org/x/tools/go/types"
 )
 
 type externalFn func(fr *frame, args []value) value
@@ -80,6 +83,8 @@
 		"math.Ldexp":                       extÛ°mathÛ°Ldexp,
 		"math.Log":                         extÛ°mathÛ°Log,
 		"math.Min":                         extÛ°mathÛ°Min,
+		"math.hasSSE4":                     extÛ°mathÛ°hasSSE4,
+		"os.Pipe":                          extÛ°osÛ°Pipe,
 		"os.runtime_args":                  extÛ°osÛ°runtime_args,
 		"os.runtime_beforeExit":            extÛ°osÛ°runtime_beforeExit,
 		"reflect.New":                      extÛ°reflectÛ°New,
@@ -106,6 +111,7 @@
 		"(*runtime.Func).Name":             extÛ°runtimeÛ°FuncÛ°Name,
 		"runtime.environ":                  extÛ°runtimeÛ°environ,
 		"runtime.getgoroot":                extÛ°runtimeÛ°getgoroot,
+		"strings.Index":                    extÛ°stringsÛ°Index,
 		"strings.IndexByte":                extÛ°stringsÛ°IndexByte,
 		"sync.runtime_Semacquire":          extÛ°syncÛ°runtime_Semacquire,
 		"sync.runtime_Semrelease":          extÛ°syncÛ°runtime_Semrelease,
@@ -134,6 +140,7 @@
 		"syscall.Stat":                     extÛ°syscallÛ°Stat,
 		"syscall.Write":                    extÛ°syscallÛ°Write,
 		"syscall.runtime_envs":             extÛ°runtimeÛ°environ,
+		"testing.runExample":               extÛ°testingÛ°runExample,
 		"time.Sleep":                       extÛ°timeÛ°Sleep,
 		"time.now":                         extÛ°timeÛ°now,
 	}
@@ -220,6 +227,10 @@
 	return math.Min(args[0].(float64), args[1].(float64))
 }
 
+func extÛ°mathÛ°hasSSE4(fr *frame, args []value) value {
+	return false
+}
+
 func extÛ°mathÛ°Ldexp(fr *frame, args []value) value {
 	return math.Ldexp(args[0].(float64), args[1].(int))
 }
@@ -256,6 +267,7 @@
 	if fr != nil {
 		fn := fr.fn
 		// TODO(adonovan): use pc/posn of current instruction, not start of fn.
+		// (Required to interpret the log package's tests.)
 		pc = uintptr(unsafe.Pointer(fn))
 		posn := fn.Prog.Fset.Position(fn.Pos())
 		file = posn.Filename
@@ -316,6 +328,11 @@
 	return -1
 }
 
+func extÛ°stringsÛ°Index(fr *frame, args []value) value {
+	// Call compiled version to avoid tricky asm dependency.
+	return strings.Index(args[0].(string), args[1].(string))
+}
+
 func extÛ°syncÛ°runtime_Syncsemcheck(fr *frame, args []value) value {
 	// TODO(adonovan): fix: implement.
 	return nil
@@ -460,6 +477,22 @@
 	return uintptr(unsafe.Pointer(f))
 }
 
+// This is a workaround for a bug in go/ssa/testmain.go: it creates
+// InternalExamples even for Example functions with no Output comment.
+// TODO(adonovan): fix (and redesign) testmain.go after Go 1.6.
+func extÛ°testingÛ°runExample(fr *frame, args []value) value {
+	// This is a stripped down runExample that simply calls the function.
+	// It does not capture and compare output nor recover from panic.
+	//
+	// func runExample(eg testing.InternalExample) bool {
+	//     eg.F()
+	//     return true
+	// }
+	F := args[0].(structure)[1]
+	call(fr.i, fr, 0, F, nil)
+	return true
+}
+
 func extÛ°timeÛ°now(fr *frame, args []value) value {
 	nano := time.Now().UnixNano()
 	return tuple{int64(nano / 1e9), int32(nano % 1e9)}
diff --git a/go/src/golang.org/x/tools/go/ssa/interp/external14.go b/go/src/golang.org/x/tools/go/ssa/interp/external14.go
new file mode 100644
index 0000000..c07c562
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/ssa/interp/external14.go
@@ -0,0 +1,526 @@
+// 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.
+
+// +build !go1.5
+
+package interp
+
+// Emulated functions that we cannot interpret because they are
+// external or because they use "unsafe" or "reflect" operations.
+
+import (
+	"math"
+	"os"
+	"runtime"
+	"strings"
+	"syscall"
+	"time"
+	"unsafe"
+
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/types"
+)
+
+type externalFn func(fr *frame, args []value) value
+
+// TODO(adonovan): fix: reflect.Value abstracts an lvalue or an
+// rvalue; Set() causes mutations that can be observed via aliases.
+// We have not captured that correctly here.
+
+// Key strings are from Function.String().
+var externals map[string]externalFn
+
+func init() {
+	// That little dot Û° is an Arabic zero numeral (U+06F0), categories [Nd].
+	externals = map[string]externalFn{
+		"(*sync.Pool).Get":                 extÛ°syncÛ°PoolÛ°Get,
+		"(*sync.Pool).Put":                 extÛ°syncÛ°PoolÛ°Put,
+		"(reflect.Value).Bool":             extÛ°reflectÛ°ValueÛ°Bool,
+		"(reflect.Value).CanAddr":          extÛ°reflectÛ°ValueÛ°CanAddr,
+		"(reflect.Value).CanInterface":     extÛ°reflectÛ°ValueÛ°CanInterface,
+		"(reflect.Value).Elem":             extÛ°reflectÛ°ValueÛ°Elem,
+		"(reflect.Value).Field":            extÛ°reflectÛ°ValueÛ°Field,
+		"(reflect.Value).Float":            extÛ°reflectÛ°ValueÛ°Float,
+		"(reflect.Value).Index":            extÛ°reflectÛ°ValueÛ°Index,
+		"(reflect.Value).Int":              extÛ°reflectÛ°ValueÛ°Int,
+		"(reflect.Value).Interface":        extÛ°reflectÛ°ValueÛ°Interface,
+		"(reflect.Value).IsNil":            extÛ°reflectÛ°ValueÛ°IsNil,
+		"(reflect.Value).IsValid":          extÛ°reflectÛ°ValueÛ°IsValid,
+		"(reflect.Value).Kind":             extÛ°reflectÛ°ValueÛ°Kind,
+		"(reflect.Value).Len":              extÛ°reflectÛ°ValueÛ°Len,
+		"(reflect.Value).MapIndex":         extÛ°reflectÛ°ValueÛ°MapIndex,
+		"(reflect.Value).MapKeys":          extÛ°reflectÛ°ValueÛ°MapKeys,
+		"(reflect.Value).NumField":         extÛ°reflectÛ°ValueÛ°NumField,
+		"(reflect.Value).NumMethod":        extÛ°reflectÛ°ValueÛ°NumMethod,
+		"(reflect.Value).Pointer":          extÛ°reflectÛ°ValueÛ°Pointer,
+		"(reflect.Value).Set":              extÛ°reflectÛ°ValueÛ°Set,
+		"(reflect.Value).String":           extÛ°reflectÛ°ValueÛ°String,
+		"(reflect.Value).Type":             extÛ°reflectÛ°ValueÛ°Type,
+		"(reflect.Value).Uint":             extÛ°reflectÛ°ValueÛ°Uint,
+		"(reflect.error).Error":            extÛ°reflectÛ°errorÛ°Error,
+		"(reflect.rtype).Bits":             extÛ°reflectÛ°rtypeÛ°Bits,
+		"(reflect.rtype).Elem":             extÛ°reflectÛ°rtypeÛ°Elem,
+		"(reflect.rtype).Field":            extÛ°reflectÛ°rtypeÛ°Field,
+		"(reflect.rtype).In":               extÛ°reflectÛ°rtypeÛ°In,
+		"(reflect.rtype).Kind":             extÛ°reflectÛ°rtypeÛ°Kind,
+		"(reflect.rtype).NumField":         extÛ°reflectÛ°rtypeÛ°NumField,
+		"(reflect.rtype).NumIn":            extÛ°reflectÛ°rtypeÛ°NumIn,
+		"(reflect.rtype).NumMethod":        extÛ°reflectÛ°rtypeÛ°NumMethod,
+		"(reflect.rtype).NumOut":           extÛ°reflectÛ°rtypeÛ°NumOut,
+		"(reflect.rtype).Out":              extÛ°reflectÛ°rtypeÛ°Out,
+		"(reflect.rtype).Size":             extÛ°reflectÛ°rtypeÛ°Size,
+		"(reflect.rtype).String":           extÛ°reflectÛ°rtypeÛ°String,
+		"bytes.Equal":                      extÛ°bytesÛ°Equal,
+		"bytes.IndexByte":                  extÛ°bytesÛ°IndexByte,
+		"hash/crc32.haveSSE42":             extÛ°crc32Û°haveSSE42,
+		"math.Abs":                         extÛ°mathÛ°Abs,
+		"math.Exp":                         extÛ°mathÛ°Exp,
+		"math.Float32bits":                 extÛ°mathÛ°Float32bits,
+		"math.Float32frombits":             extÛ°mathÛ°Float32frombits,
+		"math.Float64bits":                 extÛ°mathÛ°Float64bits,
+		"math.Float64frombits":             extÛ°mathÛ°Float64frombits,
+		"math.Ldexp":                       extÛ°mathÛ°Ldexp,
+		"math.Log":                         extÛ°mathÛ°Log,
+		"math.Min":                         extÛ°mathÛ°Min,
+		"math.hasSSE4":                     extÛ°mathÛ°hasSSE4,
+		"os.Pipe":                          extÛ°osÛ°Pipe,
+		"os.runtime_args":                  extÛ°osÛ°runtime_args,
+		"os.runtime_beforeExit":            extÛ°osÛ°runtime_beforeExit,
+		"reflect.New":                      extÛ°reflectÛ°New,
+		"reflect.SliceOf":                  extÛ°reflectÛ°SliceOf,
+		"reflect.TypeOf":                   extÛ°reflectÛ°TypeOf,
+		"reflect.ValueOf":                  extÛ°reflectÛ°ValueOf,
+		"reflect.Zero":                     extÛ°reflectÛ°Zero,
+		"reflect.init":                     extÛ°reflectÛ°Init,
+		"reflect.valueInterface":           extÛ°reflectÛ°valueInterface,
+		"runtime.Breakpoint":               extÛ°runtimeÛ°Breakpoint,
+		"runtime.Caller":                   extÛ°runtimeÛ°Caller,
+		"runtime.Callers":                  extÛ°runtimeÛ°Callers,
+		"runtime.FuncForPC":                extÛ°runtimeÛ°FuncForPC,
+		"runtime.GC":                       extÛ°runtimeÛ°GC,
+		"runtime.GOMAXPROCS":               extÛ°runtimeÛ°GOMAXPROCS,
+		"runtime.Goexit":                   extÛ°runtimeÛ°Goexit,
+		"runtime.Gosched":                  extÛ°runtimeÛ°Gosched,
+		"runtime.init":                     extÛ°runtimeÛ°init,
+		"runtime.NumCPU":                   extÛ°runtimeÛ°NumCPU,
+		"runtime.ReadMemStats":             extÛ°runtimeÛ°ReadMemStats,
+		"runtime.SetFinalizer":             extÛ°runtimeÛ°SetFinalizer,
+		"(*runtime.Func).Entry":            extÛ°runtimeÛ°FuncÛ°Entry,
+		"(*runtime.Func).FileLine":         extÛ°runtimeÛ°FuncÛ°FileLine,
+		"(*runtime.Func).Name":             extÛ°runtimeÛ°FuncÛ°Name,
+		"runtime.environ":                  extÛ°runtimeÛ°environ,
+		"runtime.getgoroot":                extÛ°runtimeÛ°getgoroot,
+		"strings.Index":                    extÛ°stringsÛ°Index,
+		"strings.IndexByte":                extÛ°stringsÛ°IndexByte,
+		"sync.runtime_Semacquire":          extÛ°syncÛ°runtime_Semacquire,
+		"sync.runtime_Semrelease":          extÛ°syncÛ°runtime_Semrelease,
+		"sync.runtime_Syncsemcheck":        extÛ°syncÛ°runtime_Syncsemcheck,
+		"sync.runtime_registerPoolCleanup": extÛ°syncÛ°runtime_registerPoolCleanup,
+		"sync/atomic.AddInt32":             extÛ°atomicÛ°AddInt32,
+		"sync/atomic.AddUint32":            extÛ°atomicÛ°AddUint32,
+		"sync/atomic.AddUint64":            extÛ°atomicÛ°AddUint64,
+		"sync/atomic.CompareAndSwapInt32":  extÛ°atomicÛ°CompareAndSwapInt32,
+		"sync/atomic.LoadInt32":            extÛ°atomicÛ°LoadInt32,
+		"sync/atomic.LoadUint32":           extÛ°atomicÛ°LoadUint32,
+		"sync/atomic.StoreInt32":           extÛ°atomicÛ°StoreInt32,
+		"sync/atomic.StoreUint32":          extÛ°atomicÛ°StoreUint32,
+		"syscall.Close":                    extÛ°syscallÛ°Close,
+		"syscall.Exit":                     extÛ°syscallÛ°Exit,
+		"syscall.Fstat":                    extÛ°syscallÛ°Fstat,
+		"syscall.Getpid":                   extÛ°syscallÛ°Getpid,
+		"syscall.Getwd":                    extÛ°syscallÛ°Getwd,
+		"syscall.Kill":                     extÛ°syscallÛ°Kill,
+		"syscall.Lstat":                    extÛ°syscallÛ°Lstat,
+		"syscall.Open":                     extÛ°syscallÛ°Open,
+		"syscall.ParseDirent":              extÛ°syscallÛ°ParseDirent,
+		"syscall.RawSyscall":               extÛ°syscallÛ°RawSyscall,
+		"syscall.Read":                     extÛ°syscallÛ°Read,
+		"syscall.ReadDirent":               extÛ°syscallÛ°ReadDirent,
+		"syscall.Stat":                     extÛ°syscallÛ°Stat,
+		"syscall.Write":                    extÛ°syscallÛ°Write,
+		"syscall.runtime_envs":             extÛ°runtimeÛ°environ,
+		"testing.runExample":               extÛ°testingÛ°runExample,
+		"time.Sleep":                       extÛ°timeÛ°Sleep,
+		"time.now":                         extÛ°timeÛ°now,
+	}
+}
+
+// wrapError returns an interpreted 'error' interface value for err.
+func wrapError(err error) value {
+	if err == nil {
+		return iface{}
+	}
+	return iface{t: errorType, v: err.Error()}
+}
+
+func extÛ°syncÛ°PoolÛ°Get(fr *frame, args []value) value {
+	Pool := fr.i.prog.ImportedPackage("sync").Type("Pool").Object()
+	_, newIndex, _ := types.LookupFieldOrMethod(Pool.Type(), false, Pool.Pkg(), "New")
+
+	if New := (*args[0].(*value)).(structure)[newIndex[0]]; New != nil {
+		return call(fr.i, fr, 0, New, nil)
+	}
+	return nil
+}
+
+func extÛ°syncÛ°PoolÛ°Put(fr *frame, args []value) value {
+	return nil
+}
+
+func extÛ°bytesÛ°Equal(fr *frame, args []value) value {
+	// func Equal(a, b []byte) bool
+	a := args[0].([]value)
+	b := args[1].([]value)
+	if len(a) != len(b) {
+		return false
+	}
+	for i := range a {
+		if a[i] != b[i] {
+			return false
+		}
+	}
+	return true
+}
+
+func extÛ°bytesÛ°IndexByte(fr *frame, args []value) value {
+	// func IndexByte(s []byte, c byte) int
+	s := args[0].([]value)
+	c := args[1].(byte)
+	for i, b := range s {
+		if b.(byte) == c {
+			return i
+		}
+	}
+	return -1
+}
+
+func extÛ°crc32Û°haveSSE42(fr *frame, args []value) value {
+	return false
+}
+
+func extÛ°mathÛ°Float64frombits(fr *frame, args []value) value {
+	return math.Float64frombits(args[0].(uint64))
+}
+
+func extÛ°mathÛ°Float64bits(fr *frame, args []value) value {
+	return math.Float64bits(args[0].(float64))
+}
+
+func extÛ°mathÛ°Float32frombits(fr *frame, args []value) value {
+	return math.Float32frombits(args[0].(uint32))
+}
+
+func extÛ°mathÛ°Abs(fr *frame, args []value) value {
+	return math.Abs(args[0].(float64))
+}
+
+func extÛ°mathÛ°Exp(fr *frame, args []value) value {
+	return math.Exp(args[0].(float64))
+}
+
+func extÛ°mathÛ°Float32bits(fr *frame, args []value) value {
+	return math.Float32bits(args[0].(float32))
+}
+
+func extÛ°mathÛ°Min(fr *frame, args []value) value {
+	return math.Min(args[0].(float64), args[1].(float64))
+}
+
+func extÛ°mathÛ°hasSSE4(fr *frame, args []value) value {
+	return false
+}
+
+func extÛ°mathÛ°Ldexp(fr *frame, args []value) value {
+	return math.Ldexp(args[0].(float64), args[1].(int))
+}
+
+func extÛ°mathÛ°Log(fr *frame, args []value) value {
+	return math.Log(args[0].(float64))
+}
+
+func extÛ°osÛ°runtime_args(fr *frame, args []value) value {
+	return fr.i.osArgs
+}
+
+func extÛ°osÛ°runtime_beforeExit(fr *frame, args []value) value {
+	return nil
+}
+
+func extÛ°runtimeÛ°Breakpoint(fr *frame, args []value) value {
+	runtime.Breakpoint()
+	return nil
+}
+
+func extÛ°runtimeÛ°Caller(fr *frame, args []value) value {
+	// func Caller(skip int) (pc uintptr, file string, line int, ok bool)
+	skip := 1 + args[0].(int)
+	for i := 0; i < skip; i++ {
+		if fr != nil {
+			fr = fr.caller
+		}
+	}
+	var pc uintptr
+	var file string
+	var line int
+	var ok bool
+	if fr != nil {
+		fn := fr.fn
+		// TODO(adonovan): use pc/posn of current instruction, not start of fn.
+		// (Required to interpret the log package's tests.)
+		pc = uintptr(unsafe.Pointer(fn))
+		posn := fn.Prog.Fset.Position(fn.Pos())
+		file = posn.Filename
+		line = posn.Line
+		ok = true
+	}
+	return tuple{pc, file, line, ok}
+}
+
+func extÛ°runtimeÛ°Callers(fr *frame, args []value) value {
+	// Callers(skip int, pc []uintptr) int
+	skip := args[0].(int)
+	pc := args[1].([]value)
+	for i := 0; i < skip; i++ {
+		if fr != nil {
+			fr = fr.caller
+		}
+	}
+	i := 0
+	for fr != nil {
+		pc[i] = uintptr(unsafe.Pointer(fr.fn))
+		i++
+		fr = fr.caller
+	}
+	return i
+}
+
+func extÛ°runtimeÛ°FuncForPC(fr *frame, args []value) value {
+	// FuncForPC(pc uintptr) *Func
+	pc := args[0].(uintptr)
+	var fn *ssa.Function
+	if pc != 0 {
+		fn = (*ssa.Function)(unsafe.Pointer(pc)) // indeed unsafe!
+	}
+	var Func value
+	Func = structure{fn} // a runtime.Func
+	return &Func
+}
+
+func extÛ°runtimeÛ°environ(fr *frame, args []value) value {
+	// This function also implements syscall.runtime_envs.
+	return environ
+}
+
+func extÛ°runtimeÛ°getgoroot(fr *frame, args []value) value {
+	return os.Getenv("GOROOT")
+}
+
+func extÛ°stringsÛ°IndexByte(fr *frame, args []value) value {
+	// func IndexByte(s string, c byte) int
+	s := args[0].(string)
+	c := args[1].(byte)
+	for i := 0; i < len(s); i++ {
+		if s[i] == c {
+			return i
+		}
+	}
+	return -1
+}
+
+func extÛ°stringsÛ°Index(fr *frame, args []value) value {
+	// Call compiled version to avoid tricky asm dependency.
+	return strings.Index(args[0].(string), args[1].(string))
+}
+
+func extÛ°syncÛ°runtime_Syncsemcheck(fr *frame, args []value) value {
+	// TODO(adonovan): fix: implement.
+	return nil
+}
+
+func extÛ°syncÛ°runtime_registerPoolCleanup(fr *frame, args []value) value {
+	return nil
+}
+
+func extÛ°syncÛ°runtime_Semacquire(fr *frame, args []value) value {
+	// TODO(adonovan): fix: implement.
+	return nil
+}
+
+func extÛ°syncÛ°runtime_Semrelease(fr *frame, args []value) value {
+	// TODO(adonovan): fix: implement.
+	return nil
+}
+
+func extÛ°runtimeÛ°GOMAXPROCS(fr *frame, args []value) value {
+	// Ignore args[0]; don't let the interpreted program
+	// set the interpreter's GOMAXPROCS!
+	return runtime.GOMAXPROCS(0)
+}
+
+func extÛ°runtimeÛ°Goexit(fr *frame, args []value) value {
+	// TODO(adonovan): don't kill the interpreter's main goroutine.
+	runtime.Goexit()
+	return nil
+}
+
+func extÛ°runtimeÛ°GC(fr *frame, args []value) value {
+	runtime.GC()
+	return nil
+}
+
+func extÛ°runtimeÛ°Gosched(fr *frame, args []value) value {
+	runtime.Gosched()
+	return nil
+}
+
+func extÛ°runtimeÛ°init(fr *frame, args []value) value {
+	return nil
+}
+
+func extÛ°runtimeÛ°NumCPU(fr *frame, args []value) value {
+	return runtime.NumCPU()
+}
+
+func extÛ°runtimeÛ°ReadMemStats(fr *frame, args []value) value {
+	// TODO(adonovan): populate args[0].(Struct)
+	return nil
+}
+
+func extÛ°atomicÛ°LoadUint32(fr *frame, args []value) value {
+	// TODO(adonovan): fix: not atomic!
+	return (*args[0].(*value)).(uint32)
+}
+
+func extÛ°atomicÛ°StoreUint32(fr *frame, args []value) value {
+	// TODO(adonovan): fix: not atomic!
+	*args[0].(*value) = args[1].(uint32)
+	return nil
+}
+
+func extÛ°atomicÛ°LoadInt32(fr *frame, args []value) value {
+	// TODO(adonovan): fix: not atomic!
+	return (*args[0].(*value)).(int32)
+}
+
+func extÛ°atomicÛ°StoreInt32(fr *frame, args []value) value {
+	// TODO(adonovan): fix: not atomic!
+	*args[0].(*value) = args[1].(int32)
+	return nil
+}
+
+func extÛ°atomicÛ°CompareAndSwapInt32(fr *frame, args []value) value {
+	// TODO(adonovan): fix: not atomic!
+	p := args[0].(*value)
+	if (*p).(int32) == args[1].(int32) {
+		*p = args[2].(int32)
+		return true
+	}
+	return false
+}
+
+func extÛ°atomicÛ°AddInt32(fr *frame, args []value) value {
+	// TODO(adonovan): fix: not atomic!
+	p := args[0].(*value)
+	newv := (*p).(int32) + args[1].(int32)
+	*p = newv
+	return newv
+}
+
+func extÛ°atomicÛ°AddUint32(fr *frame, args []value) value {
+	// TODO(adonovan): fix: not atomic!
+	p := args[0].(*value)
+	newv := (*p).(uint32) + args[1].(uint32)
+	*p = newv
+	return newv
+}
+
+func extÛ°atomicÛ°AddUint64(fr *frame, args []value) value {
+	// TODO(adonovan): fix: not atomic!
+	p := args[0].(*value)
+	newv := (*p).(uint64) + args[1].(uint64)
+	*p = newv
+	return newv
+}
+
+func extÛ°runtimeÛ°SetFinalizer(fr *frame, args []value) value {
+	return nil // ignore
+}
+
+// Pretend: type runtime.Func struct { entry *ssa.Function }
+
+func extÛ°runtimeÛ°FuncÛ°FileLine(fr *frame, args []value) value {
+	// func (*runtime.Func) FileLine(uintptr) (string, int)
+	f, _ := (*args[0].(*value)).(structure)[0].(*ssa.Function)
+	pc := args[1].(uintptr)
+	_ = pc
+	if f != nil {
+		// TODO(adonovan): use position of current instruction, not fn.
+		posn := f.Prog.Fset.Position(f.Pos())
+		return tuple{posn.Filename, posn.Line}
+	}
+	return tuple{"", 0}
+}
+
+func extÛ°runtimeÛ°FuncÛ°Name(fr *frame, args []value) value {
+	// func (*runtime.Func) Name() string
+	f, _ := (*args[0].(*value)).(structure)[0].(*ssa.Function)
+	if f != nil {
+		return f.String()
+	}
+	return ""
+}
+
+func extÛ°runtimeÛ°FuncÛ°Entry(fr *frame, args []value) value {
+	// func (*runtime.Func) Entry() uintptr
+	f, _ := (*args[0].(*value)).(structure)[0].(*ssa.Function)
+	return uintptr(unsafe.Pointer(f))
+}
+
+// This is a workaround for a bug in go/ssa/testmain.go: it creates
+// InternalExamples even for Example functions with no Output comment.
+// TODO(adonovan): fix (and redesign) testmain.go after Go 1.6.
+func extÛ°testingÛ°runExample(fr *frame, args []value) value {
+	// This is a stripped down runExample that simply calls the function.
+	// It does not capture and compare output nor recover from panic.
+	//
+	// func runExample(eg testing.InternalExample) bool {
+	//     eg.F()
+	//     return true
+	// }
+	F := args[0].(structure)[1]
+	call(fr.i, fr, 0, F, nil)
+	return true
+}
+
+func extÛ°timeÛ°now(fr *frame, args []value) value {
+	nano := time.Now().UnixNano()
+	return tuple{int64(nano / 1e9), int32(nano % 1e9)}
+}
+
+func extÛ°timeÛ°Sleep(fr *frame, args []value) value {
+	time.Sleep(time.Duration(args[0].(int64)))
+	return nil
+}
+
+func extÛ°syscallÛ°Exit(fr *frame, args []value) value {
+	panic(exitPanic(args[0].(int)))
+}
+
+func extÛ°syscallÛ°Getwd(fr *frame, args []value) value {
+	s, err := syscall.Getwd()
+	return tuple{s, wrapError(err)}
+}
+
+func extÛ°syscallÛ°Getpid(fr *frame, args []value) value {
+	return syscall.Getpid()
+}
+
+func valueToBytes(v value) []byte {
+	in := v.([]value)
+	b := make([]byte, len(in))
+	for i := range in {
+		b[i] = in[i].(byte)
+	}
+	return b
+}
diff --git a/go/src/golang.org/x/tools/go/ssa/interp/external_plan9.go b/go/src/golang.org/x/tools/go/ssa/interp/external_plan9.go
index 05d02d5..81bedcf 100644
--- a/go/src/golang.org/x/tools/go/ssa/interp/external_plan9.go
+++ b/go/src/golang.org/x/tools/go/ssa/interp/external_plan9.go
@@ -6,6 +6,9 @@
 
 import "syscall"
 
+func extÛ°osÛ°Pipe(fr *frame, args []value) value {
+	panic("os.Pipe not yet implemented")
+}
 func extÛ°syscallÛ°Close(fr *frame, args []value) value {
 	panic("syscall.Close not yet implemented")
 }
diff --git a/go/src/golang.org/x/tools/go/ssa/interp/external_unix.go b/go/src/golang.org/x/tools/go/ssa/interp/external_unix.go
index c482eab..be12586 100644
--- a/go/src/golang.org/x/tools/go/ssa/interp/external_unix.go
+++ b/go/src/golang.org/x/tools/go/ssa/interp/external_unix.go
@@ -8,6 +8,22 @@
 
 import "syscall"
 
+func extÛ°osÛ°Pipe(fr *frame, args []value) value {
+	// func os.Pipe() (r *File, w *File, err error)
+
+	// The portable POSIX pipe(2) call is good enough for our needs.
+	var p [2]int
+	if err := syscall.Pipe(p[:]); err != nil {
+		// TODO(adonovan): fix: return an *os.SyscallError.
+		return tuple{nil, nil, wrapError(err)}
+	}
+
+	NewFile := fr.i.prog.ImportedPackage("os").Func("NewFile")
+	r := call(fr.i, fr, 0, NewFile, []value{uintptr(p[0]), "|0"})
+	w := call(fr.i, fr, 0, NewFile, []value{uintptr(p[1]), "|1"})
+	return tuple{r, w, wrapError(nil)}
+}
+
 func fillStat(st *syscall.Stat_t, stat structure) {
 	stat[0] = st.Dev
 	stat[1] = st.Ino
diff --git a/go/src/golang.org/x/tools/go/ssa/interp/external_windows.go b/go/src/golang.org/x/tools/go/ssa/interp/external_windows.go
index ef28a37..24d1a87 100644
--- a/go/src/golang.org/x/tools/go/ssa/interp/external_windows.go
+++ b/go/src/golang.org/x/tools/go/ssa/interp/external_windows.go
@@ -6,6 +6,9 @@
 
 import "syscall"
 
+func extÛ°osÛ°Pipe(fr *frame, args []value) value {
+	panic("os.Pipe not yet implemented")
+}
 func extÛ°syscallÛ°Close(fr *frame, args []value) value {
 	panic("syscall.Close not yet implemented")
 }
diff --git a/go/src/golang.org/x/tools/go/ssa/interp/interp.go b/go/src/golang.org/x/tools/go/ssa/interp/interp.go
index afe4939..b855645 100644
--- a/go/src/golang.org/x/tools/go/ssa/interp/interp.go
+++ b/go/src/golang.org/x/tools/go/ssa/interp/interp.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 // Package ssa/interp defines an interpreter for the SSA
 // representation of Go programs.
 //
@@ -47,12 +49,12 @@
 import (
 	"fmt"
 	"go/token"
+	"go/types"
 	"os"
 	"reflect"
 	"runtime"
 
 	"golang.org/x/tools/go/ssa"
-	"golang.org/x/tools/go/types"
 )
 
 type continuation int
@@ -619,7 +621,7 @@
 		*g = v
 		return
 	}
-	panic("no global variable: " + pkg.Object.Path() + "." + name)
+	panic("no global variable: " + pkg.Pkg.Path() + "." + name)
 }
 
 var environ []value
@@ -687,7 +689,7 @@
 		}
 
 		// Ad-hoc initialization for magic system variables.
-		switch pkg.Object.Path() {
+		switch pkg.Pkg.Path() {
 		case "syscall":
 			setGlobal(i, pkg, "envs", environ)
 
@@ -695,7 +697,7 @@
 			deleteBodies(pkg, "DeepEqual", "deepValueEqual")
 
 		case "runtime":
-			sz := sizes.Sizeof(pkg.Object.Scope().Lookup("MemStats").Type())
+			sz := sizes.Sizeof(pkg.Pkg.Scope().Lookup("MemStats").Type())
 			setGlobal(i, pkg, "sizeof_C_MStats", uintptr(sz))
 			deleteBodies(pkg, "GOROOT", "gogetenv")
 		}
diff --git a/go/src/golang.org/x/tools/go/ssa/interp/interp14.go b/go/src/golang.org/x/tools/go/ssa/interp/interp14.go
new file mode 100644
index 0000000..dbd4dac
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/ssa/interp/interp14.go
@@ -0,0 +1,752 @@
+// 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.
+
+// +build !go1.5
+
+// Package ssa/interp defines an interpreter for the SSA
+// representation of Go programs.
+//
+// This interpreter is provided as an adjunct for testing the SSA
+// construction algorithm.  Its purpose is to provide a minimal
+// metacircular implementation of the dynamic semantics of each SSA
+// instruction.  It is not, and will never be, a production-quality Go
+// interpreter.
+//
+// The following is a partial list of Go features that are currently
+// unsupported or incomplete in the interpreter.
+//
+// * Unsafe operations, including all uses of unsafe.Pointer, are
+// impossible to support given the "boxed" value representation we
+// have chosen.
+//
+// * The reflect package is only partially implemented.
+//
+// * "sync/atomic" operations are not currently atomic due to the
+// "boxed" value representation: it is not possible to read, modify
+// and write an interface value atomically.  As a consequence, Mutexes
+// are currently broken.  TODO(adonovan): provide a metacircular
+// implementation of Mutex avoiding the broken atomic primitives.
+//
+// * recover is only partially implemented.  Also, the interpreter
+// makes no attempt to distinguish target panics from interpreter
+// crashes.
+//
+// * map iteration is asymptotically inefficient.
+//
+// * the sizes of the int, uint and uintptr types in the target
+// program are assumed to be the same as those of the interpreter
+// itself.
+//
+// * all values occupy space, even those of types defined by the spec
+// to have zero size, e.g. struct{}.  This can cause asymptotic
+// performance degradation.
+//
+// * os.Exit is implemented using panic, causing deferred functions to
+// run.
+package interp // import "golang.org/x/tools/go/ssa/interp"
+
+import (
+	"fmt"
+	"go/token"
+	"os"
+	"reflect"
+	"runtime"
+
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/types"
+)
+
+type continuation int
+
+const (
+	kNext continuation = iota
+	kReturn
+	kJump
+)
+
+// Mode is a bitmask of options affecting the interpreter.
+type Mode uint
+
+const (
+	DisableRecover Mode = 1 << iota // Disable recover() in target programs; show interpreter crash instead.
+	EnableTracing                   // Print a trace of all instructions as they are interpreted.
+)
+
+type methodSet map[string]*ssa.Function
+
+// State shared between all interpreted goroutines.
+type interpreter struct {
+	osArgs             []value              // the value of os.Args
+	prog               *ssa.Program         // the SSA program
+	globals            map[ssa.Value]*value // addresses of global variables (immutable)
+	mode               Mode                 // interpreter options
+	reflectPackage     *ssa.Package         // the fake reflect package
+	errorMethods       methodSet            // the method set of reflect.error, which implements the error interface.
+	rtypeMethods       methodSet            // the method set of rtype, which implements the reflect.Type interface.
+	runtimeErrorString types.Type           // the runtime.errorString type
+	sizes              types.Sizes          // the effective type-sizing function
+}
+
+type deferred struct {
+	fn    value
+	args  []value
+	instr *ssa.Defer
+	tail  *deferred
+}
+
+type frame struct {
+	i                *interpreter
+	caller           *frame
+	fn               *ssa.Function
+	block, prevBlock *ssa.BasicBlock
+	env              map[ssa.Value]value // dynamic values of SSA variables
+	locals           []value
+	defers           *deferred
+	result           value
+	panicking        bool
+	panic            interface{}
+}
+
+func (fr *frame) get(key ssa.Value) value {
+	switch key := key.(type) {
+	case nil:
+		// Hack; simplifies handling of optional attributes
+		// such as ssa.Slice.{Low,High}.
+		return nil
+	case *ssa.Function, *ssa.Builtin:
+		return key
+	case *ssa.Const:
+		return constValue(key)
+	case *ssa.Global:
+		if r, ok := fr.i.globals[key]; ok {
+			return r
+		}
+	}
+	if r, ok := fr.env[key]; ok {
+		return r
+	}
+	panic(fmt.Sprintf("get: no value for %T: %v", key, key.Name()))
+}
+
+// runDefer runs a deferred call d.
+// It always returns normally, but may set or clear fr.panic.
+//
+func (fr *frame) runDefer(d *deferred) {
+	if fr.i.mode&EnableTracing != 0 {
+		fmt.Fprintf(os.Stderr, "%s: invoking deferred function call\n",
+			fr.i.prog.Fset.Position(d.instr.Pos()))
+	}
+	var ok bool
+	defer func() {
+		if !ok {
+			// Deferred call created a new state of panic.
+			fr.panicking = true
+			fr.panic = recover()
+		}
+	}()
+	call(fr.i, fr, d.instr.Pos(), d.fn, d.args)
+	ok = true
+}
+
+// runDefers executes fr's deferred function calls in LIFO order.
+//
+// On entry, fr.panicking indicates a state of panic; if
+// true, fr.panic contains the panic value.
+//
+// On completion, if a deferred call started a panic, or if no
+// deferred call recovered from a previous state of panic, then
+// runDefers itself panics after the last deferred call has run.
+//
+// If there was no initial state of panic, or it was recovered from,
+// runDefers returns normally.
+//
+func (fr *frame) runDefers() {
+	for d := fr.defers; d != nil; d = d.tail {
+		fr.runDefer(d)
+	}
+	fr.defers = nil
+	if fr.panicking {
+		panic(fr.panic) // new panic, or still panicking
+	}
+}
+
+// lookupMethod returns the method set for type typ, which may be one
+// of the interpreter's fake types.
+func lookupMethod(i *interpreter, typ types.Type, meth *types.Func) *ssa.Function {
+	switch typ {
+	case rtypeType:
+		return i.rtypeMethods[meth.Id()]
+	case errorType:
+		return i.errorMethods[meth.Id()]
+	}
+	return i.prog.LookupMethod(typ, meth.Pkg(), meth.Name())
+}
+
+// visitInstr interprets a single ssa.Instruction within the activation
+// record frame.  It returns a continuation value indicating where to
+// read the next instruction from.
+func visitInstr(fr *frame, instr ssa.Instruction) continuation {
+	switch instr := instr.(type) {
+	case *ssa.DebugRef:
+		// no-op
+
+	case *ssa.UnOp:
+		fr.env[instr] = unop(instr, fr.get(instr.X))
+
+	case *ssa.BinOp:
+		fr.env[instr] = binop(instr.Op, instr.X.Type(), fr.get(instr.X), fr.get(instr.Y))
+
+	case *ssa.Call:
+		fn, args := prepareCall(fr, &instr.Call)
+		fr.env[instr] = call(fr.i, fr, instr.Pos(), fn, args)
+
+	case *ssa.ChangeInterface:
+		fr.env[instr] = fr.get(instr.X)
+
+	case *ssa.ChangeType:
+		fr.env[instr] = fr.get(instr.X) // (can't fail)
+
+	case *ssa.Convert:
+		fr.env[instr] = conv(instr.Type(), instr.X.Type(), fr.get(instr.X))
+
+	case *ssa.MakeInterface:
+		fr.env[instr] = iface{t: instr.X.Type(), v: fr.get(instr.X)}
+
+	case *ssa.Extract:
+		fr.env[instr] = fr.get(instr.Tuple).(tuple)[instr.Index]
+
+	case *ssa.Slice:
+		fr.env[instr] = slice(fr.get(instr.X), fr.get(instr.Low), fr.get(instr.High), fr.get(instr.Max))
+
+	case *ssa.Return:
+		switch len(instr.Results) {
+		case 0:
+		case 1:
+			fr.result = fr.get(instr.Results[0])
+		default:
+			var res []value
+			for _, r := range instr.Results {
+				res = append(res, fr.get(r))
+			}
+			fr.result = tuple(res)
+		}
+		fr.block = nil
+		return kReturn
+
+	case *ssa.RunDefers:
+		fr.runDefers()
+
+	case *ssa.Panic:
+		panic(targetPanic{fr.get(instr.X)})
+
+	case *ssa.Send:
+		fr.get(instr.Chan).(chan value) <- fr.get(instr.X)
+
+	case *ssa.Store:
+		store(deref(instr.Addr.Type()), fr.get(instr.Addr).(*value), fr.get(instr.Val))
+
+	case *ssa.If:
+		succ := 1
+		if fr.get(instr.Cond).(bool) {
+			succ = 0
+		}
+		fr.prevBlock, fr.block = fr.block, fr.block.Succs[succ]
+		return kJump
+
+	case *ssa.Jump:
+		fr.prevBlock, fr.block = fr.block, fr.block.Succs[0]
+		return kJump
+
+	case *ssa.Defer:
+		fn, args := prepareCall(fr, &instr.Call)
+		fr.defers = &deferred{
+			fn:    fn,
+			args:  args,
+			instr: instr,
+			tail:  fr.defers,
+		}
+
+	case *ssa.Go:
+		fn, args := prepareCall(fr, &instr.Call)
+		go call(fr.i, nil, instr.Pos(), fn, args)
+
+	case *ssa.MakeChan:
+		fr.env[instr] = make(chan value, asInt(fr.get(instr.Size)))
+
+	case *ssa.Alloc:
+		var addr *value
+		if instr.Heap {
+			// new
+			addr = new(value)
+			fr.env[instr] = addr
+		} else {
+			// local
+			addr = fr.env[instr].(*value)
+		}
+		*addr = zero(deref(instr.Type()))
+
+	case *ssa.MakeSlice:
+		slice := make([]value, asInt(fr.get(instr.Cap)))
+		tElt := instr.Type().Underlying().(*types.Slice).Elem()
+		for i := range slice {
+			slice[i] = zero(tElt)
+		}
+		fr.env[instr] = slice[:asInt(fr.get(instr.Len))]
+
+	case *ssa.MakeMap:
+		reserve := 0
+		if instr.Reserve != nil {
+			reserve = asInt(fr.get(instr.Reserve))
+		}
+		fr.env[instr] = makeMap(instr.Type().Underlying().(*types.Map).Key(), reserve)
+
+	case *ssa.Range:
+		fr.env[instr] = rangeIter(fr.get(instr.X), instr.X.Type())
+
+	case *ssa.Next:
+		fr.env[instr] = fr.get(instr.Iter).(iter).next()
+
+	case *ssa.FieldAddr:
+		x := fr.get(instr.X)
+		// FIXME wrong!  &global.f must not change if we do *global = zero!
+		fr.env[instr] = &(*x.(*value)).(structure)[instr.Field]
+
+	case *ssa.Field:
+		fr.env[instr] = fr.get(instr.X).(structure)[instr.Field]
+
+	case *ssa.IndexAddr:
+		x := fr.get(instr.X)
+		idx := fr.get(instr.Index)
+		switch x := x.(type) {
+		case []value:
+			fr.env[instr] = &x[asInt(idx)]
+		case *value: // *array
+			fr.env[instr] = &(*x).(array)[asInt(idx)]
+		default:
+			panic(fmt.Sprintf("unexpected x type in IndexAddr: %T", x))
+		}
+
+	case *ssa.Index:
+		fr.env[instr] = fr.get(instr.X).(array)[asInt(fr.get(instr.Index))]
+
+	case *ssa.Lookup:
+		fr.env[instr] = lookup(instr, fr.get(instr.X), fr.get(instr.Index))
+
+	case *ssa.MapUpdate:
+		m := fr.get(instr.Map)
+		key := fr.get(instr.Key)
+		v := fr.get(instr.Value)
+		switch m := m.(type) {
+		case map[value]value:
+			m[key] = v
+		case *hashmap:
+			m.insert(key.(hashable), v)
+		default:
+			panic(fmt.Sprintf("illegal map type: %T", m))
+		}
+
+	case *ssa.TypeAssert:
+		fr.env[instr] = typeAssert(fr.i, instr, fr.get(instr.X).(iface))
+
+	case *ssa.MakeClosure:
+		var bindings []value
+		for _, binding := range instr.Bindings {
+			bindings = append(bindings, fr.get(binding))
+		}
+		fr.env[instr] = &closure{instr.Fn.(*ssa.Function), bindings}
+
+	case *ssa.Phi:
+		for i, pred := range instr.Block().Preds {
+			if fr.prevBlock == pred {
+				fr.env[instr] = fr.get(instr.Edges[i])
+				break
+			}
+		}
+
+	case *ssa.Select:
+		var cases []reflect.SelectCase
+		if !instr.Blocking {
+			cases = append(cases, reflect.SelectCase{
+				Dir: reflect.SelectDefault,
+			})
+		}
+		for _, state := range instr.States {
+			var dir reflect.SelectDir
+			if state.Dir == types.RecvOnly {
+				dir = reflect.SelectRecv
+			} else {
+				dir = reflect.SelectSend
+			}
+			var send reflect.Value
+			if state.Send != nil {
+				send = reflect.ValueOf(fr.get(state.Send))
+			}
+			cases = append(cases, reflect.SelectCase{
+				Dir:  dir,
+				Chan: reflect.ValueOf(fr.get(state.Chan)),
+				Send: send,
+			})
+		}
+		chosen, recv, recvOk := reflect.Select(cases)
+		if !instr.Blocking {
+			chosen-- // default case should have index -1.
+		}
+		r := tuple{chosen, recvOk}
+		for i, st := range instr.States {
+			if st.Dir == types.RecvOnly {
+				var v value
+				if i == chosen && recvOk {
+					// No need to copy since send makes an unaliased copy.
+					v = recv.Interface().(value)
+				} else {
+					v = zero(st.Chan.Type().Underlying().(*types.Chan).Elem())
+				}
+				r = append(r, v)
+			}
+		}
+		fr.env[instr] = r
+
+	default:
+		panic(fmt.Sprintf("unexpected instruction: %T", instr))
+	}
+
+	// if val, ok := instr.(ssa.Value); ok {
+	// 	fmt.Println(toString(fr.env[val])) // debugging
+	// }
+
+	return kNext
+}
+
+// prepareCall determines the function value and argument values for a
+// function call in a Call, Go or Defer instruction, performing
+// interface method lookup if needed.
+//
+func prepareCall(fr *frame, call *ssa.CallCommon) (fn value, args []value) {
+	v := fr.get(call.Value)
+	if call.Method == nil {
+		// Function call.
+		fn = v
+	} else {
+		// Interface method invocation.
+		recv := v.(iface)
+		if recv.t == nil {
+			panic("method invoked on nil interface")
+		}
+		if f := lookupMethod(fr.i, recv.t, call.Method); f == nil {
+			// Unreachable in well-typed programs.
+			panic(fmt.Sprintf("method set for dynamic type %v does not contain %s", recv.t, call.Method))
+		} else {
+			fn = f
+		}
+		args = append(args, recv.v)
+	}
+	for _, arg := range call.Args {
+		args = append(args, fr.get(arg))
+	}
+	return
+}
+
+// call interprets a call to a function (function, builtin or closure)
+// fn with arguments args, returning its result.
+// callpos is the position of the callsite.
+//
+func call(i *interpreter, caller *frame, callpos token.Pos, fn value, args []value) value {
+	switch fn := fn.(type) {
+	case *ssa.Function:
+		if fn == nil {
+			panic("call of nil function") // nil of func type
+		}
+		return callSSA(i, caller, callpos, fn, args, nil)
+	case *closure:
+		return callSSA(i, caller, callpos, fn.Fn, args, fn.Env)
+	case *ssa.Builtin:
+		return callBuiltin(caller, callpos, fn, args)
+	}
+	panic(fmt.Sprintf("cannot call %T", fn))
+}
+
+func loc(fset *token.FileSet, pos token.Pos) string {
+	if pos == token.NoPos {
+		return ""
+	}
+	return " at " + fset.Position(pos).String()
+}
+
+// callSSA interprets a call to function fn with arguments args,
+// and lexical environment env, returning its result.
+// callpos is the position of the callsite.
+//
+func callSSA(i *interpreter, caller *frame, callpos token.Pos, fn *ssa.Function, args []value, env []value) value {
+	if i.mode&EnableTracing != 0 {
+		fset := fn.Prog.Fset
+		// TODO(adonovan): fix: loc() lies for external functions.
+		fmt.Fprintf(os.Stderr, "Entering %s%s.\n", fn, loc(fset, fn.Pos()))
+		suffix := ""
+		if caller != nil {
+			suffix = ", resuming " + caller.fn.String() + loc(fset, callpos)
+		}
+		defer fmt.Fprintf(os.Stderr, "Leaving %s%s.\n", fn, suffix)
+	}
+	fr := &frame{
+		i:      i,
+		caller: caller, // for panic/recover
+		fn:     fn,
+	}
+	if fn.Parent() == nil {
+		name := fn.String()
+		if ext := externals[name]; ext != nil {
+			if i.mode&EnableTracing != 0 {
+				fmt.Fprintln(os.Stderr, "\t(external)")
+			}
+			return ext(fr, args)
+		}
+		if fn.Blocks == nil {
+			panic("no code for function: " + name)
+		}
+	}
+	fr.env = make(map[ssa.Value]value)
+	fr.block = fn.Blocks[0]
+	fr.locals = make([]value, len(fn.Locals))
+	for i, l := range fn.Locals {
+		fr.locals[i] = zero(deref(l.Type()))
+		fr.env[l] = &fr.locals[i]
+	}
+	for i, p := range fn.Params {
+		fr.env[p] = args[i]
+	}
+	for i, fv := range fn.FreeVars {
+		fr.env[fv] = env[i]
+	}
+	for fr.block != nil {
+		runFrame(fr)
+	}
+	// Destroy the locals to avoid accidental use after return.
+	for i := range fn.Locals {
+		fr.locals[i] = bad{}
+	}
+	return fr.result
+}
+
+// runFrame executes SSA instructions starting at fr.block and
+// continuing until a return, a panic, or a recovered panic.
+//
+// After a panic, runFrame panics.
+//
+// After a normal return, fr.result contains the result of the call
+// and fr.block is nil.
+//
+// A recovered panic in a function without named return parameters
+// (NRPs) becomes a normal return of the zero value of the function's
+// result type.
+//
+// After a recovered panic in a function with NRPs, fr.result is
+// undefined and fr.block contains the block at which to resume
+// control.
+//
+func runFrame(fr *frame) {
+	defer func() {
+		if fr.block == nil {
+			return // normal return
+		}
+		if fr.i.mode&DisableRecover != 0 {
+			return // let interpreter crash
+		}
+		fr.panicking = true
+		fr.panic = recover()
+		if fr.i.mode&EnableTracing != 0 {
+			fmt.Fprintf(os.Stderr, "Panicking: %T %v.\n", fr.panic, fr.panic)
+		}
+		fr.runDefers()
+		fr.block = fr.fn.Recover
+	}()
+
+	for {
+		if fr.i.mode&EnableTracing != 0 {
+			fmt.Fprintf(os.Stderr, ".%s:\n", fr.block)
+		}
+	block:
+		for _, instr := range fr.block.Instrs {
+			if fr.i.mode&EnableTracing != 0 {
+				if v, ok := instr.(ssa.Value); ok {
+					fmt.Fprintln(os.Stderr, "\t", v.Name(), "=", instr)
+				} else {
+					fmt.Fprintln(os.Stderr, "\t", instr)
+				}
+			}
+			switch visitInstr(fr, instr) {
+			case kReturn:
+				return
+			case kNext:
+				// no-op
+			case kJump:
+				break block
+			}
+		}
+	}
+}
+
+// doRecover implements the recover() built-in.
+func doRecover(caller *frame) value {
+	// recover() must be exactly one level beneath the deferred
+	// function (two levels beneath the panicking function) to
+	// have any effect.  Thus we ignore both "defer recover()" and
+	// "defer f() -> g() -> recover()".
+	if caller.i.mode&DisableRecover == 0 &&
+		caller != nil && !caller.panicking &&
+		caller.caller != nil && caller.caller.panicking {
+		caller.caller.panicking = false
+		p := caller.caller.panic
+		caller.caller.panic = nil
+		switch p := p.(type) {
+		case targetPanic:
+			// The target program explicitly called panic().
+			return p.v
+		case runtime.Error:
+			// The interpreter encountered a runtime error.
+			return iface{caller.i.runtimeErrorString, p.Error()}
+		case string:
+			// The interpreter explicitly called panic().
+			return iface{caller.i.runtimeErrorString, p}
+		default:
+			panic(fmt.Sprintf("unexpected panic type %T in target call to recover()", p))
+		}
+	}
+	return iface{}
+}
+
+// setGlobal sets the value of a system-initialized global variable.
+func setGlobal(i *interpreter, pkg *ssa.Package, name string, v value) {
+	if g, ok := i.globals[pkg.Var(name)]; ok {
+		*g = v
+		return
+	}
+	panic("no global variable: " + pkg.Pkg.Path() + "." + name)
+}
+
+var environ []value
+
+func init() {
+	for _, s := range os.Environ() {
+		environ = append(environ, s)
+	}
+	environ = append(environ, "GOSSAINTERP=1")
+	environ = append(environ, "GOARCH="+runtime.GOARCH)
+}
+
+// deleteBodies delete the bodies of all standalone functions except the
+// specified ones.  A missing intrinsic leads to a clear runtime error.
+func deleteBodies(pkg *ssa.Package, except ...string) {
+	keep := make(map[string]bool)
+	for _, e := range except {
+		keep[e] = true
+	}
+	for _, mem := range pkg.Members {
+		if fn, ok := mem.(*ssa.Function); ok && !keep[fn.Name()] {
+			fn.Blocks = nil
+		}
+	}
+}
+
+// Interpret interprets the Go program whose main package is mainpkg.
+// mode specifies various interpreter options.  filename and args are
+// the initial values of os.Args for the target program.  sizes is the
+// effective type-sizing function for this program.
+//
+// Interpret returns the exit code of the program: 2 for panic (like
+// gc does), or the argument to os.Exit for normal termination.
+//
+// The SSA program must include the "runtime" package.
+//
+func Interpret(mainpkg *ssa.Package, mode Mode, sizes types.Sizes, filename string, args []string) (exitCode int) {
+	i := &interpreter{
+		prog:    mainpkg.Prog,
+		globals: make(map[ssa.Value]*value),
+		mode:    mode,
+		sizes:   sizes,
+	}
+	runtimePkg := i.prog.ImportedPackage("runtime")
+	if runtimePkg == nil {
+		panic("ssa.Program doesn't include runtime package")
+	}
+	i.runtimeErrorString = runtimePkg.Type("errorString").Object().Type()
+
+	initReflect(i)
+
+	i.osArgs = append(i.osArgs, filename)
+	for _, arg := range args {
+		i.osArgs = append(i.osArgs, arg)
+	}
+
+	for _, pkg := range i.prog.AllPackages() {
+		// Initialize global storage.
+		for _, m := range pkg.Members {
+			switch v := m.(type) {
+			case *ssa.Global:
+				cell := zero(deref(v.Type()))
+				i.globals[v] = &cell
+			}
+		}
+
+		// Ad-hoc initialization for magic system variables.
+		switch pkg.Pkg.Path() {
+		case "syscall":
+			setGlobal(i, pkg, "envs", environ)
+
+		case "reflect":
+			deleteBodies(pkg, "DeepEqual", "deepValueEqual")
+
+		case "runtime":
+			sz := sizes.Sizeof(pkg.Pkg.Scope().Lookup("MemStats").Type())
+			setGlobal(i, pkg, "sizeof_C_MStats", uintptr(sz))
+			deleteBodies(pkg, "GOROOT", "gogetenv")
+		}
+	}
+
+	// Top-level error handler.
+	exitCode = 2
+	defer func() {
+		if exitCode != 2 || i.mode&DisableRecover != 0 {
+			return
+		}
+		switch p := recover().(type) {
+		case exitPanic:
+			exitCode = int(p)
+			return
+		case targetPanic:
+			fmt.Fprintln(os.Stderr, "panic:", toString(p.v))
+		case runtime.Error:
+			fmt.Fprintln(os.Stderr, "panic:", p.Error())
+		case string:
+			fmt.Fprintln(os.Stderr, "panic:", p)
+		default:
+			fmt.Fprintf(os.Stderr, "panic: unexpected type: %T: %v\n", p, p)
+		}
+
+		// TODO(adonovan): dump panicking interpreter goroutine?
+		// buf := make([]byte, 0x10000)
+		// runtime.Stack(buf, false)
+		// fmt.Fprintln(os.Stderr, string(buf))
+		// (Or dump panicking target goroutine?)
+	}()
+
+	// Run!
+	call(i, nil, token.NoPos, mainpkg.Func("init"), nil)
+	if mainFn := mainpkg.Func("main"); mainFn != nil {
+		call(i, nil, token.NoPos, mainFn, nil)
+		exitCode = 0
+	} else {
+		fmt.Fprintln(os.Stderr, "No main function.")
+		exitCode = 1
+	}
+	return
+}
+
+// deref returns a pointer's element type; otherwise it returns typ.
+// TODO(adonovan): Import from ssa?
+func deref(typ types.Type) types.Type {
+	if p, ok := typ.Underlying().(*types.Pointer); ok {
+		return p.Elem()
+	}
+	return typ
+}
diff --git a/go/src/golang.org/x/tools/go/ssa/interp/interp14_test.go b/go/src/golang.org/x/tools/go/ssa/interp/interp14_test.go
new file mode 100644
index 0000000..63c3f53
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/ssa/interp/interp14_test.go
@@ -0,0 +1,367 @@
+// 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.
+
+// +build !go1.5
+
+// +build !android,!windows,!plan9
+
+package interp_test
+
+import (
+	"bytes"
+	"fmt"
+	"go/build"
+	"os"
+	"path/filepath"
+	"strings"
+	"testing"
+	"time"
+
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/ssa/interp"
+	"golang.org/x/tools/go/ssa/ssautil"
+	"golang.org/x/tools/go/types"
+)
+
+// Each line contains a space-separated list of $GOROOT/test/
+// filenames comprising the main package of a program.
+// They are ordered quickest-first, roughly.
+//
+// TODO(adonovan): integrate into the $GOROOT/test driver scripts,
+// golden file checking, etc.
+var gorootTestTests = []string{
+	"235.go",
+	"alias1.go",
+	"chancap.go",
+	"func5.go",
+	"func6.go",
+	"func7.go",
+	"func8.go",
+	"helloworld.go",
+	"varinit.go",
+	"escape3.go",
+	"initcomma.go",
+	"cmp.go",
+	"compos.go",
+	"turing.go",
+	"indirect.go",
+	// "complit.go", // tests go1.5 features
+	"for.go",
+	"struct0.go",
+	"intcvt.go",
+	"printbig.go",
+	"deferprint.go",
+	"escape.go",
+	"range.go",
+	"const4.go",
+	"float_lit.go",
+	"bigalg.go",
+	"decl.go",
+	"if.go",
+	"named.go",
+	"bigmap.go",
+	"func.go",
+	"reorder2.go",
+	"closure.go",
+	"gc.go",
+	"simassign.go",
+	"iota.go",
+	"nilptr2.go",
+	"goprint.go", // doesn't actually assert anything (cmpout)
+	"utf.go",
+	"method.go",
+	"char_lit.go",
+	"env.go",
+	"int_lit.go",
+	"string_lit.go",
+	"defer.go",
+	"typeswitch.go",
+	"stringrange.go",
+	"reorder.go",
+	"method3.go",
+	"literal.go",
+	"nul1.go", // doesn't actually assert anything (errorcheckoutput)
+	"zerodivide.go",
+	"convert.go",
+	"convT2X.go",
+	"switch.go",
+	"initialize.go",
+	"ddd.go",
+	"blank.go", // partly disabled
+	"map.go",
+	"closedchan.go",
+	"divide.go",
+	"rename.go",
+	"const3.go",
+	"nil.go",
+	"recover.go", // reflection parts disabled
+	"recover1.go",
+	"recover2.go",
+	"recover3.go",
+	"typeswitch1.go",
+	"floatcmp.go",
+	"crlf.go", // doesn't actually assert anything (runoutput)
+	// Slow tests follow.
+	"bom.go", // ~1.7s
+	"gc1.go", // ~1.7s
+	"cmplxdivide.go cmplxdivide1.go", // ~2.4s
+
+	// Working, but not worth enabling:
+	// "append.go",    // works, but slow (15s).
+	// "gc2.go",       // works, but slow, and cheats on the memory check.
+	// "sigchld.go",   // works, but only on POSIX.
+	// "peano.go",     // works only up to n=9, and slow even then.
+	// "stack.go",     // works, but too slow (~30s) by default.
+	// "solitaire.go", // works, but too slow (~30s).
+	// "const.go",     // works but for but one bug: constant folder doesn't consider representations.
+	// "init1.go",     // too slow (80s) and not that interesting. Cheats on ReadMemStats check too.
+	// "rotate.go rotate0.go", // emits source for a test
+	// "rotate.go rotate1.go", // emits source for a test
+	// "rotate.go rotate2.go", // emits source for a test
+	// "rotate.go rotate3.go", // emits source for a test
+	// "64bit.go",             // emits source for a test
+	// "run.go",               // test driver, not a test.
+
+	// Broken.  TODO(adonovan): fix.
+	// copy.go         // very slow; but with N=4 quickly crashes, slice index out of range.
+	// nilptr.go       // interp: V > uintptr not implemented. Slow test, lots of mem
+	// args.go         // works, but requires specific os.Args from the driver.
+	// index.go        // a template, not a real test.
+	// mallocfin.go    // SetFinalizer not implemented.
+
+	// TODO(adonovan): add tests from $GOROOT/test/* subtrees:
+	// bench chan bugs fixedbugs interface ken.
+}
+
+// These are files in go.tools/go/ssa/interp/testdata/.
+var testdataTests = []string{
+	"boundmeth.go",
+	// "complit.go", // requires go1.5
+	"coverage.go",
+	"defer.go",
+	"fieldprom.go",
+	"ifaceconv.go",
+	"ifaceprom.go",
+	"initorder.go",
+	"methprom.go",
+	"mrvchain.go",
+	"range.go",
+	"recover.go",
+	"reflect.go",
+	"static.go",
+	"callstack.go",
+}
+
+// These are files and packages in $GOROOT/src/.
+var gorootSrcTests = []string{
+	"encoding/ascii85",
+	"encoding/hex",
+	// "encoding/pem", // TODO(adonovan): implement (reflect.Value).SetString
+	// "testing",      // TODO(adonovan): implement runtime.Goexit correctly
+	// "hash/crc32",   // TODO(adonovan): implement hash/crc32.haveCLMUL
+	// "log",          // TODO(adonovan): implement runtime.Callers correctly
+
+	// Too slow:
+	// "container/ring",
+	// "hash/adler32",
+
+	"unicode/utf8",
+	"path",
+	"flag",
+	"encoding/csv",
+	"text/scanner",
+	"unicode",
+}
+
+type successPredicate func(exitcode int, output string) error
+
+func run(t *testing.T, dir, input string, success successPredicate) bool {
+	fmt.Printf("Input: %s\n", input)
+
+	start := time.Now()
+
+	var inputs []string
+	for _, i := range strings.Split(input, " ") {
+		if strings.HasSuffix(i, ".go") {
+			i = dir + i
+		}
+		inputs = append(inputs, i)
+	}
+
+	var conf loader.Config
+	if _, err := conf.FromArgs(inputs, true); err != nil {
+		t.Errorf("FromArgs(%s) failed: %s", inputs, err)
+		return false
+	}
+
+	conf.Import("runtime")
+
+	// Print a helpful hint if we don't make it to the end.
+	var hint string
+	defer func() {
+		if hint != "" {
+			fmt.Println("FAIL")
+			fmt.Println(hint)
+		} else {
+			fmt.Println("PASS")
+		}
+
+		interp.CapturedOutput = nil
+	}()
+
+	hint = fmt.Sprintf("To dump SSA representation, run:\n%% go build golang.org/x/tools/cmd/ssadump && ./ssadump -test -build=CFP %s\n", input)
+
+	iprog, err := conf.Load()
+	if err != nil {
+		t.Errorf("conf.Load(%s) failed: %s", inputs, err)
+		return false
+	}
+
+	prog := ssautil.CreateProgram(iprog, ssa.SanityCheckFunctions)
+	prog.Build()
+
+	var mainPkg *ssa.Package
+	var initialPkgs []*ssa.Package
+	for _, info := range iprog.InitialPackages() {
+		if info.Pkg.Path() == "runtime" {
+			continue // not an initial package
+		}
+		p := prog.Package(info.Pkg)
+		initialPkgs = append(initialPkgs, p)
+		if mainPkg == nil && p.Func("main") != nil {
+			mainPkg = p
+		}
+	}
+	if mainPkg == nil {
+		testmainPkg := prog.CreateTestMainPackage(initialPkgs...)
+		if testmainPkg == nil {
+			t.Errorf("CreateTestMainPackage(%s) returned nil", mainPkg)
+			return false
+		}
+		if testmainPkg.Func("main") == nil {
+			t.Errorf("synthetic testmain package has no main")
+			return false
+		}
+		mainPkg = testmainPkg
+	}
+
+	var out bytes.Buffer
+	interp.CapturedOutput = &out
+
+	hint = fmt.Sprintf("To trace execution, run:\n%% go build golang.org/x/tools/cmd/ssadump && ./ssadump -build=C -run --interp=T %s\n", input)
+	exitCode := interp.Interpret(mainPkg, 0, &types.StdSizes{8, 8}, inputs[0], []string{})
+
+	// The definition of success varies with each file.
+	if err := success(exitCode, out.String()); err != nil {
+		t.Errorf("interp.Interpret(%s) failed: %s", inputs, err)
+		return false
+	}
+
+	hint = "" // call off the hounds
+
+	if false {
+		fmt.Println(input, time.Since(start)) // test profiling
+	}
+
+	return true
+}
+
+const slash = string(os.PathSeparator)
+
+func printFailures(failures []string) {
+	if failures != nil {
+		fmt.Println("The following tests failed:")
+		for _, f := range failures {
+			fmt.Printf("\t%s\n", f)
+		}
+	}
+}
+
+func success(exitcode int, output string) error {
+	if exitcode != 0 {
+		return fmt.Errorf("exit code was %d", exitcode)
+	}
+	if strings.Contains(output, "BUG") {
+		return fmt.Errorf("exited zero but output contained 'BUG'")
+	}
+	return nil
+}
+
+// TestTestdataFiles runs the interpreter on testdata/*.go.
+func TestTestdataFiles(t *testing.T) {
+	var failures []string
+	start := time.Now()
+	for _, input := range testdataTests {
+		if testing.Short() && time.Since(start) > 30*time.Second {
+			printFailures(failures)
+			t.Skipf("timeout - aborting test")
+		}
+		if !run(t, "testdata"+slash, input, success) {
+			failures = append(failures, input)
+		}
+	}
+	printFailures(failures)
+}
+
+// TestGorootTest runs the interpreter on $GOROOT/test/*.go.
+func TestGorootTest(t *testing.T) {
+	if testing.Short() {
+		t.Skip() // too slow (~30s)
+	}
+
+	var failures []string
+
+	for _, input := range gorootTestTests {
+		if !run(t, filepath.Join(build.Default.GOROOT, "test")+slash, input, success) {
+			failures = append(failures, input)
+		}
+	}
+	for _, input := range gorootSrcTests {
+		if !run(t, filepath.Join(build.Default.GOROOT, "src")+slash, input, success) {
+			failures = append(failures, input)
+		}
+	}
+	printFailures(failures)
+}
+
+// TestTestmainPackage runs the interpreter on a synthetic "testmain" package.
+func TestTestmainPackage(t *testing.T) {
+	if testing.Short() {
+		t.Skip() // too slow on some platforms
+	}
+
+	success := func(exitcode int, output string) error {
+		if exitcode == 0 {
+			return fmt.Errorf("unexpected success")
+		}
+		if !strings.Contains(output, "FAIL: TestFoo") {
+			return fmt.Errorf("missing failure log for TestFoo")
+		}
+		if !strings.Contains(output, "FAIL: TestBar") {
+			return fmt.Errorf("missing failure log for TestBar")
+		}
+		// TODO(adonovan): test benchmarks too
+		return nil
+	}
+	run(t, "testdata"+slash, "a_test.go", success)
+}
+
+// CreateTestMainPackage should return nil if there were no tests.
+func TestNullTestmainPackage(t *testing.T) {
+	var conf loader.Config
+	conf.CreateFromFilenames("", "testdata/b_test.go")
+	iprog, err := conf.Load()
+	if err != nil {
+		t.Fatalf("CreatePackages failed: %s", err)
+	}
+	prog := ssautil.CreateProgram(iprog, ssa.SanityCheckFunctions)
+	mainPkg := prog.Package(iprog.Created[0].Pkg)
+	if mainPkg.Func("main") != nil {
+		t.Fatalf("unexpected main function")
+	}
+	if prog.CreateTestMainPackage(mainPkg) != nil {
+		t.Fatalf("CreateTestMainPackage returned non-nil")
+	}
+}
diff --git a/go/src/golang.org/x/tools/go/ssa/interp/interp_test.go b/go/src/golang.org/x/tools/go/ssa/interp/interp_test.go
index f36c23e..5163816 100644
--- a/go/src/golang.org/x/tools/go/ssa/interp/interp_test.go
+++ b/go/src/golang.org/x/tools/go/ssa/interp/interp_test.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 // +build !android,!windows,!plan9
 
 package interp_test
@@ -10,6 +12,7 @@
 	"bytes"
 	"fmt"
 	"go/build"
+	"go/types"
 	"os"
 	"path/filepath"
 	"strings"
@@ -20,7 +23,6 @@
 	"golang.org/x/tools/go/ssa"
 	"golang.org/x/tools/go/ssa/interp"
 	"golang.org/x/tools/go/ssa/ssautil"
-	"golang.org/x/tools/go/types"
 )
 
 // Each line contains a space-separated list of $GOROOT/test/
@@ -158,20 +160,19 @@
 	"encoding/hex",
 	// "encoding/pem", // TODO(adonovan): implement (reflect.Value).SetString
 	// "testing",      // TODO(adonovan): implement runtime.Goexit correctly
-	"unicode",
+	// "hash/crc32",   // TODO(adonovan): implement hash/crc32.haveCLMUL
+	// "log",          // TODO(adonovan): implement runtime.Callers correctly
 
 	// Too slow:
 	// "container/ring",
 	// "hash/adler32",
 
-	// TODO(adonovan): packages with Examples require os.Pipe (unimplemented):
-	// "hash/crc32",
-	// "unicode/utf8",
-	// "log",
-	// "path",
-	// "flag",
-	// "encoding/csv"
-	// "text/scanner"
+	"unicode/utf8",
+	"path",
+	"flag",
+	"encoding/csv",
+	"text/scanner",
+	"unicode",
 }
 
 type successPredicate func(exitcode int, output string) error
@@ -210,7 +211,7 @@
 		interp.CapturedOutput = nil
 	}()
 
-	hint = fmt.Sprintf("To dump SSA representation, run:\n%% go build golang.org/x/tools/cmd/ssadump && ./ssadump -build=CFP %s\n", input)
+	hint = fmt.Sprintf("To dump SSA representation, run:\n%% go build golang.org/x/tools/cmd/ssadump && ./ssadump -test -build=CFP %s\n", input)
 
 	iprog, err := conf.Load()
 	if err != nil {
@@ -219,7 +220,7 @@
 	}
 
 	prog := ssautil.CreateProgram(iprog, ssa.SanityCheckFunctions)
-	prog.BuildAll()
+	prog.Build()
 
 	var mainPkg *ssa.Package
 	var initialPkgs []*ssa.Package
diff --git a/go/src/golang.org/x/tools/go/ssa/interp/map.go b/go/src/golang.org/x/tools/go/ssa/interp/map.go
index 5dbaf0a..4c092b3 100644
--- a/go/src/golang.org/x/tools/go/ssa/interp/map.go
+++ b/go/src/golang.org/x/tools/go/ssa/interp/map.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package interp
 
 // Custom hashtable atop map.
@@ -12,7 +14,7 @@
 // concurrent map access.
 
 import (
-	"golang.org/x/tools/go/types"
+	"go/types"
 )
 
 type hashable interface {
diff --git a/go/src/golang.org/x/tools/go/ssa/interp/map14.go b/go/src/golang.org/x/tools/go/ssa/interp/map14.go
new file mode 100644
index 0000000..a268c81
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/ssa/interp/map14.go
@@ -0,0 +1,115 @@
+// 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.
+
+// +build !go1.5
+
+package interp
+
+// Custom hashtable atop map.
+// For use when the key's equivalence relation is not consistent with ==.
+
+// The Go specification doesn't address the atomicity of map operations.
+// The FAQ states that an implementation is permitted to crash on
+// concurrent map access.
+
+import (
+	"golang.org/x/tools/go/types"
+)
+
+type hashable interface {
+	hash(t types.Type) int
+	eq(t types.Type, x interface{}) bool
+}
+
+type entry struct {
+	key   hashable
+	value value
+	next  *entry
+}
+
+// A hashtable atop the built-in map.  Since each bucket contains
+// exactly one hash value, there's no need to perform hash-equality
+// tests when walking the linked list.  Rehashing is done by the
+// underlying map.
+type hashmap struct {
+	keyType types.Type
+	table   map[int]*entry
+	length  int // number of entries in map
+}
+
+// makeMap returns an empty initialized map of key type kt,
+// preallocating space for reserve elements.
+func makeMap(kt types.Type, reserve int) value {
+	if usesBuiltinMap(kt) {
+		return make(map[value]value, reserve)
+	}
+	return &hashmap{keyType: kt, table: make(map[int]*entry, reserve)}
+}
+
+// delete removes the association for key k, if any.
+func (m *hashmap) delete(k hashable) {
+	if m != nil {
+		hash := k.hash(m.keyType)
+		head := m.table[hash]
+		if head != nil {
+			if k.eq(m.keyType, head.key) {
+				m.table[hash] = head.next
+				m.length--
+				return
+			}
+			prev := head
+			for e := head.next; e != nil; e = e.next {
+				if k.eq(m.keyType, e.key) {
+					prev.next = e.next
+					m.length--
+					return
+				}
+				prev = e
+			}
+		}
+	}
+}
+
+// lookup returns the value associated with key k, if present, or
+// value(nil) otherwise.
+func (m *hashmap) lookup(k hashable) value {
+	if m != nil {
+		hash := k.hash(m.keyType)
+		for e := m.table[hash]; e != nil; e = e.next {
+			if k.eq(m.keyType, e.key) {
+				return e.value
+			}
+		}
+	}
+	return nil
+}
+
+// insert updates the map to associate key k with value v.  If there
+// was already an association for an eq() (though not necessarily ==)
+// k, the previous key remains in the map and its associated value is
+// updated.
+func (m *hashmap) insert(k hashable, v value) {
+	hash := k.hash(m.keyType)
+	head := m.table[hash]
+	for e := head; e != nil; e = e.next {
+		if k.eq(m.keyType, e.key) {
+			e.value = v
+			return
+		}
+	}
+	m.table[hash] = &entry{
+		key:   k,
+		value: v,
+		next:  head,
+	}
+	m.length++
+}
+
+// len returns the number of key/value associations in the map.
+func (m *hashmap) len() int {
+	if m != nil {
+		return m.length
+	}
+	return 0
+}
diff --git a/go/src/golang.org/x/tools/go/ssa/interp/ops.go b/go/src/golang.org/x/tools/go/ssa/interp/ops.go
index de89904..c7a0a40 100644
--- a/go/src/golang.org/x/tools/go/ssa/interp/ops.go
+++ b/go/src/golang.org/x/tools/go/ssa/interp/ops.go
@@ -2,19 +2,21 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package interp
 
 import (
 	"bytes"
 	"fmt"
+	exact "go/constant"
 	"go/token"
+	"go/types"
 	"strings"
 	"sync"
 	"unsafe"
 
-	"golang.org/x/tools/go/exact"
 	"golang.org/x/tools/go/ssa"
-	"golang.org/x/tools/go/types"
 )
 
 // If the target program panics, the interpreter panics with this type.
diff --git a/go/src/golang.org/x/tools/go/ssa/interp/ops14.go b/go/src/golang.org/x/tools/go/ssa/interp/ops14.go
new file mode 100644
index 0000000..2490dff
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/ssa/interp/ops14.go
@@ -0,0 +1,1396 @@
+// 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.
+
+// +build !go1.5
+
+package interp
+
+import (
+	"bytes"
+	"fmt"
+	"go/token"
+	"strings"
+	"sync"
+	"unsafe"
+
+	"golang.org/x/tools/go/exact"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/types"
+)
+
+// If the target program panics, the interpreter panics with this type.
+type targetPanic struct {
+	v value
+}
+
+func (p targetPanic) String() string {
+	return toString(p.v)
+}
+
+// If the target program calls exit, the interpreter panics with this type.
+type exitPanic int
+
+// constValue returns the value of the constant with the
+// dynamic type tag appropriate for c.Type().
+func constValue(c *ssa.Const) value {
+	if c.IsNil() {
+		return zero(c.Type()) // typed nil
+	}
+
+	if t, ok := c.Type().Underlying().(*types.Basic); ok {
+		// TODO(adonovan): eliminate untyped constants from SSA form.
+		switch t.Kind() {
+		case types.Bool, types.UntypedBool:
+			return exact.BoolVal(c.Value)
+		case types.Int, types.UntypedInt:
+			// Assume sizeof(int) is same on host and target.
+			return int(c.Int64())
+		case types.Int8:
+			return int8(c.Int64())
+		case types.Int16:
+			return int16(c.Int64())
+		case types.Int32, types.UntypedRune:
+			return int32(c.Int64())
+		case types.Int64:
+			return c.Int64()
+		case types.Uint:
+			// Assume sizeof(uint) is same on host and target.
+			return uint(c.Uint64())
+		case types.Uint8:
+			return uint8(c.Uint64())
+		case types.Uint16:
+			return uint16(c.Uint64())
+		case types.Uint32:
+			return uint32(c.Uint64())
+		case types.Uint64:
+			return c.Uint64()
+		case types.Uintptr:
+			// Assume sizeof(uintptr) is same on host and target.
+			return uintptr(c.Uint64())
+		case types.Float32:
+			return float32(c.Float64())
+		case types.Float64, types.UntypedFloat:
+			return c.Float64()
+		case types.Complex64:
+			return complex64(c.Complex128())
+		case types.Complex128, types.UntypedComplex:
+			return c.Complex128()
+		case types.String, types.UntypedString:
+			if c.Value.Kind() == exact.String {
+				return exact.StringVal(c.Value)
+			}
+			return string(rune(c.Int64()))
+		}
+	}
+
+	panic(fmt.Sprintf("constValue: %s", c))
+}
+
+// asInt converts x, which must be an integer, to an int suitable for
+// use as a slice or array index or operand to make().
+func asInt(x value) int {
+	switch x := x.(type) {
+	case int:
+		return x
+	case int8:
+		return int(x)
+	case int16:
+		return int(x)
+	case int32:
+		return int(x)
+	case int64:
+		return int(x)
+	case uint:
+		return int(x)
+	case uint8:
+		return int(x)
+	case uint16:
+		return int(x)
+	case uint32:
+		return int(x)
+	case uint64:
+		return int(x)
+	case uintptr:
+		return int(x)
+	}
+	panic(fmt.Sprintf("cannot convert %T to int", x))
+}
+
+// asUint64 converts x, which must be an unsigned integer, to a uint64
+// suitable for use as a bitwise shift count.
+func asUint64(x value) uint64 {
+	switch x := x.(type) {
+	case uint:
+		return uint64(x)
+	case uint8:
+		return uint64(x)
+	case uint16:
+		return uint64(x)
+	case uint32:
+		return uint64(x)
+	case uint64:
+		return x
+	case uintptr:
+		return uint64(x)
+	}
+	panic(fmt.Sprintf("cannot convert %T to uint64", x))
+}
+
+// zero returns a new "zero" value of the specified type.
+func zero(t types.Type) value {
+	switch t := t.(type) {
+	case *types.Basic:
+		if t.Kind() == types.UntypedNil {
+			panic("untyped nil has no zero value")
+		}
+		if t.Info()&types.IsUntyped != 0 {
+			// TODO(adonovan): make it an invariant that
+			// this is unreachable.  Currently some
+			// constants have 'untyped' types when they
+			// should be defaulted by the typechecker.
+			t = ssa.DefaultType(t).(*types.Basic)
+		}
+		switch t.Kind() {
+		case types.Bool:
+			return false
+		case types.Int:
+			return int(0)
+		case types.Int8:
+			return int8(0)
+		case types.Int16:
+			return int16(0)
+		case types.Int32:
+			return int32(0)
+		case types.Int64:
+			return int64(0)
+		case types.Uint:
+			return uint(0)
+		case types.Uint8:
+			return uint8(0)
+		case types.Uint16:
+			return uint16(0)
+		case types.Uint32:
+			return uint32(0)
+		case types.Uint64:
+			return uint64(0)
+		case types.Uintptr:
+			return uintptr(0)
+		case types.Float32:
+			return float32(0)
+		case types.Float64:
+			return float64(0)
+		case types.Complex64:
+			return complex64(0)
+		case types.Complex128:
+			return complex128(0)
+		case types.String:
+			return ""
+		case types.UnsafePointer:
+			return unsafe.Pointer(nil)
+		default:
+			panic(fmt.Sprint("zero for unexpected type:", t))
+		}
+	case *types.Pointer:
+		return (*value)(nil)
+	case *types.Array:
+		a := make(array, t.Len())
+		for i := range a {
+			a[i] = zero(t.Elem())
+		}
+		return a
+	case *types.Named:
+		return zero(t.Underlying())
+	case *types.Interface:
+		return iface{} // nil type, methodset and value
+	case *types.Slice:
+		return []value(nil)
+	case *types.Struct:
+		s := make(structure, t.NumFields())
+		for i := range s {
+			s[i] = zero(t.Field(i).Type())
+		}
+		return s
+	case *types.Tuple:
+		if t.Len() == 1 {
+			return zero(t.At(0).Type())
+		}
+		s := make(tuple, t.Len())
+		for i := range s {
+			s[i] = zero(t.At(i).Type())
+		}
+		return s
+	case *types.Chan:
+		return chan value(nil)
+	case *types.Map:
+		if usesBuiltinMap(t.Key()) {
+			return map[value]value(nil)
+		}
+		return (*hashmap)(nil)
+	case *types.Signature:
+		return (*ssa.Function)(nil)
+	}
+	panic(fmt.Sprint("zero: unexpected ", t))
+}
+
+// slice returns x[lo:hi:max].  Any of lo, hi and max may be nil.
+func slice(x, lo, hi, max value) value {
+	var Len, Cap int
+	switch x := x.(type) {
+	case string:
+		Len = len(x)
+	case []value:
+		Len = len(x)
+		Cap = cap(x)
+	case *value: // *array
+		a := (*x).(array)
+		Len = len(a)
+		Cap = cap(a)
+	}
+
+	l := 0
+	if lo != nil {
+		l = asInt(lo)
+	}
+
+	h := Len
+	if hi != nil {
+		h = asInt(hi)
+	}
+
+	m := Cap
+	if max != nil {
+		m = asInt(max)
+	}
+
+	switch x := x.(type) {
+	case string:
+		return x[l:h]
+	case []value:
+		return x[l:h:m]
+	case *value: // *array
+		a := (*x).(array)
+		return []value(a)[l:h:m]
+	}
+	panic(fmt.Sprintf("slice: unexpected X type: %T", x))
+}
+
+// lookup returns x[idx] where x is a map or string.
+func lookup(instr *ssa.Lookup, x, idx value) value {
+	switch x := x.(type) { // map or string
+	case map[value]value, *hashmap:
+		var v value
+		var ok bool
+		switch x := x.(type) {
+		case map[value]value:
+			v, ok = x[idx]
+		case *hashmap:
+			v = x.lookup(idx.(hashable))
+			ok = v != nil
+		}
+		if !ok {
+			v = zero(instr.X.Type().Underlying().(*types.Map).Elem())
+		}
+		if instr.CommaOk {
+			v = tuple{v, ok}
+		}
+		return v
+	case string:
+		return x[asInt(idx)]
+	}
+	panic(fmt.Sprintf("unexpected x type in Lookup: %T", x))
+}
+
+// binop implements all arithmetic and logical binary operators for
+// numeric datatypes and strings.  Both operands must have identical
+// dynamic type.
+//
+func binop(op token.Token, t types.Type, x, y value) value {
+	switch op {
+	case token.ADD:
+		switch x.(type) {
+		case int:
+			return x.(int) + y.(int)
+		case int8:
+			return x.(int8) + y.(int8)
+		case int16:
+			return x.(int16) + y.(int16)
+		case int32:
+			return x.(int32) + y.(int32)
+		case int64:
+			return x.(int64) + y.(int64)
+		case uint:
+			return x.(uint) + y.(uint)
+		case uint8:
+			return x.(uint8) + y.(uint8)
+		case uint16:
+			return x.(uint16) + y.(uint16)
+		case uint32:
+			return x.(uint32) + y.(uint32)
+		case uint64:
+			return x.(uint64) + y.(uint64)
+		case uintptr:
+			return x.(uintptr) + y.(uintptr)
+		case float32:
+			return x.(float32) + y.(float32)
+		case float64:
+			return x.(float64) + y.(float64)
+		case complex64:
+			return x.(complex64) + y.(complex64)
+		case complex128:
+			return x.(complex128) + y.(complex128)
+		case string:
+			return x.(string) + y.(string)
+		}
+
+	case token.SUB:
+		switch x.(type) {
+		case int:
+			return x.(int) - y.(int)
+		case int8:
+			return x.(int8) - y.(int8)
+		case int16:
+			return x.(int16) - y.(int16)
+		case int32:
+			return x.(int32) - y.(int32)
+		case int64:
+			return x.(int64) - y.(int64)
+		case uint:
+			return x.(uint) - y.(uint)
+		case uint8:
+			return x.(uint8) - y.(uint8)
+		case uint16:
+			return x.(uint16) - y.(uint16)
+		case uint32:
+			return x.(uint32) - y.(uint32)
+		case uint64:
+			return x.(uint64) - y.(uint64)
+		case uintptr:
+			return x.(uintptr) - y.(uintptr)
+		case float32:
+			return x.(float32) - y.(float32)
+		case float64:
+			return x.(float64) - y.(float64)
+		case complex64:
+			return x.(complex64) - y.(complex64)
+		case complex128:
+			return x.(complex128) - y.(complex128)
+		}
+
+	case token.MUL:
+		switch x.(type) {
+		case int:
+			return x.(int) * y.(int)
+		case int8:
+			return x.(int8) * y.(int8)
+		case int16:
+			return x.(int16) * y.(int16)
+		case int32:
+			return x.(int32) * y.(int32)
+		case int64:
+			return x.(int64) * y.(int64)
+		case uint:
+			return x.(uint) * y.(uint)
+		case uint8:
+			return x.(uint8) * y.(uint8)
+		case uint16:
+			return x.(uint16) * y.(uint16)
+		case uint32:
+			return x.(uint32) * y.(uint32)
+		case uint64:
+			return x.(uint64) * y.(uint64)
+		case uintptr:
+			return x.(uintptr) * y.(uintptr)
+		case float32:
+			return x.(float32) * y.(float32)
+		case float64:
+			return x.(float64) * y.(float64)
+		case complex64:
+			return x.(complex64) * y.(complex64)
+		case complex128:
+			return x.(complex128) * y.(complex128)
+		}
+
+	case token.QUO:
+		switch x.(type) {
+		case int:
+			return x.(int) / y.(int)
+		case int8:
+			return x.(int8) / y.(int8)
+		case int16:
+			return x.(int16) / y.(int16)
+		case int32:
+			return x.(int32) / y.(int32)
+		case int64:
+			return x.(int64) / y.(int64)
+		case uint:
+			return x.(uint) / y.(uint)
+		case uint8:
+			return x.(uint8) / y.(uint8)
+		case uint16:
+			return x.(uint16) / y.(uint16)
+		case uint32:
+			return x.(uint32) / y.(uint32)
+		case uint64:
+			return x.(uint64) / y.(uint64)
+		case uintptr:
+			return x.(uintptr) / y.(uintptr)
+		case float32:
+			return x.(float32) / y.(float32)
+		case float64:
+			return x.(float64) / y.(float64)
+		case complex64:
+			return x.(complex64) / y.(complex64)
+		case complex128:
+			return x.(complex128) / y.(complex128)
+		}
+
+	case token.REM:
+		switch x.(type) {
+		case int:
+			return x.(int) % y.(int)
+		case int8:
+			return x.(int8) % y.(int8)
+		case int16:
+			return x.(int16) % y.(int16)
+		case int32:
+			return x.(int32) % y.(int32)
+		case int64:
+			return x.(int64) % y.(int64)
+		case uint:
+			return x.(uint) % y.(uint)
+		case uint8:
+			return x.(uint8) % y.(uint8)
+		case uint16:
+			return x.(uint16) % y.(uint16)
+		case uint32:
+			return x.(uint32) % y.(uint32)
+		case uint64:
+			return x.(uint64) % y.(uint64)
+		case uintptr:
+			return x.(uintptr) % y.(uintptr)
+		}
+
+	case token.AND:
+		switch x.(type) {
+		case int:
+			return x.(int) & y.(int)
+		case int8:
+			return x.(int8) & y.(int8)
+		case int16:
+			return x.(int16) & y.(int16)
+		case int32:
+			return x.(int32) & y.(int32)
+		case int64:
+			return x.(int64) & y.(int64)
+		case uint:
+			return x.(uint) & y.(uint)
+		case uint8:
+			return x.(uint8) & y.(uint8)
+		case uint16:
+			return x.(uint16) & y.(uint16)
+		case uint32:
+			return x.(uint32) & y.(uint32)
+		case uint64:
+			return x.(uint64) & y.(uint64)
+		case uintptr:
+			return x.(uintptr) & y.(uintptr)
+		}
+
+	case token.OR:
+		switch x.(type) {
+		case int:
+			return x.(int) | y.(int)
+		case int8:
+			return x.(int8) | y.(int8)
+		case int16:
+			return x.(int16) | y.(int16)
+		case int32:
+			return x.(int32) | y.(int32)
+		case int64:
+			return x.(int64) | y.(int64)
+		case uint:
+			return x.(uint) | y.(uint)
+		case uint8:
+			return x.(uint8) | y.(uint8)
+		case uint16:
+			return x.(uint16) | y.(uint16)
+		case uint32:
+			return x.(uint32) | y.(uint32)
+		case uint64:
+			return x.(uint64) | y.(uint64)
+		case uintptr:
+			return x.(uintptr) | y.(uintptr)
+		}
+
+	case token.XOR:
+		switch x.(type) {
+		case int:
+			return x.(int) ^ y.(int)
+		case int8:
+			return x.(int8) ^ y.(int8)
+		case int16:
+			return x.(int16) ^ y.(int16)
+		case int32:
+			return x.(int32) ^ y.(int32)
+		case int64:
+			return x.(int64) ^ y.(int64)
+		case uint:
+			return x.(uint) ^ y.(uint)
+		case uint8:
+			return x.(uint8) ^ y.(uint8)
+		case uint16:
+			return x.(uint16) ^ y.(uint16)
+		case uint32:
+			return x.(uint32) ^ y.(uint32)
+		case uint64:
+			return x.(uint64) ^ y.(uint64)
+		case uintptr:
+			return x.(uintptr) ^ y.(uintptr)
+		}
+
+	case token.AND_NOT:
+		switch x.(type) {
+		case int:
+			return x.(int) &^ y.(int)
+		case int8:
+			return x.(int8) &^ y.(int8)
+		case int16:
+			return x.(int16) &^ y.(int16)
+		case int32:
+			return x.(int32) &^ y.(int32)
+		case int64:
+			return x.(int64) &^ y.(int64)
+		case uint:
+			return x.(uint) &^ y.(uint)
+		case uint8:
+			return x.(uint8) &^ y.(uint8)
+		case uint16:
+			return x.(uint16) &^ y.(uint16)
+		case uint32:
+			return x.(uint32) &^ y.(uint32)
+		case uint64:
+			return x.(uint64) &^ y.(uint64)
+		case uintptr:
+			return x.(uintptr) &^ y.(uintptr)
+		}
+
+	case token.SHL:
+		y := asUint64(y)
+		switch x.(type) {
+		case int:
+			return x.(int) << y
+		case int8:
+			return x.(int8) << y
+		case int16:
+			return x.(int16) << y
+		case int32:
+			return x.(int32) << y
+		case int64:
+			return x.(int64) << y
+		case uint:
+			return x.(uint) << y
+		case uint8:
+			return x.(uint8) << y
+		case uint16:
+			return x.(uint16) << y
+		case uint32:
+			return x.(uint32) << y
+		case uint64:
+			return x.(uint64) << y
+		case uintptr:
+			return x.(uintptr) << y
+		}
+
+	case token.SHR:
+		y := asUint64(y)
+		switch x.(type) {
+		case int:
+			return x.(int) >> y
+		case int8:
+			return x.(int8) >> y
+		case int16:
+			return x.(int16) >> y
+		case int32:
+			return x.(int32) >> y
+		case int64:
+			return x.(int64) >> y
+		case uint:
+			return x.(uint) >> y
+		case uint8:
+			return x.(uint8) >> y
+		case uint16:
+			return x.(uint16) >> y
+		case uint32:
+			return x.(uint32) >> y
+		case uint64:
+			return x.(uint64) >> y
+		case uintptr:
+			return x.(uintptr) >> y
+		}
+
+	case token.LSS:
+		switch x.(type) {
+		case int:
+			return x.(int) < y.(int)
+		case int8:
+			return x.(int8) < y.(int8)
+		case int16:
+			return x.(int16) < y.(int16)
+		case int32:
+			return x.(int32) < y.(int32)
+		case int64:
+			return x.(int64) < y.(int64)
+		case uint:
+			return x.(uint) < y.(uint)
+		case uint8:
+			return x.(uint8) < y.(uint8)
+		case uint16:
+			return x.(uint16) < y.(uint16)
+		case uint32:
+			return x.(uint32) < y.(uint32)
+		case uint64:
+			return x.(uint64) < y.(uint64)
+		case uintptr:
+			return x.(uintptr) < y.(uintptr)
+		case float32:
+			return x.(float32) < y.(float32)
+		case float64:
+			return x.(float64) < y.(float64)
+		case string:
+			return x.(string) < y.(string)
+		}
+
+	case token.LEQ:
+		switch x.(type) {
+		case int:
+			return x.(int) <= y.(int)
+		case int8:
+			return x.(int8) <= y.(int8)
+		case int16:
+			return x.(int16) <= y.(int16)
+		case int32:
+			return x.(int32) <= y.(int32)
+		case int64:
+			return x.(int64) <= y.(int64)
+		case uint:
+			return x.(uint) <= y.(uint)
+		case uint8:
+			return x.(uint8) <= y.(uint8)
+		case uint16:
+			return x.(uint16) <= y.(uint16)
+		case uint32:
+			return x.(uint32) <= y.(uint32)
+		case uint64:
+			return x.(uint64) <= y.(uint64)
+		case uintptr:
+			return x.(uintptr) <= y.(uintptr)
+		case float32:
+			return x.(float32) <= y.(float32)
+		case float64:
+			return x.(float64) <= y.(float64)
+		case string:
+			return x.(string) <= y.(string)
+		}
+
+	case token.EQL:
+		return eqnil(t, x, y)
+
+	case token.NEQ:
+		return !eqnil(t, x, y)
+
+	case token.GTR:
+		switch x.(type) {
+		case int:
+			return x.(int) > y.(int)
+		case int8:
+			return x.(int8) > y.(int8)
+		case int16:
+			return x.(int16) > y.(int16)
+		case int32:
+			return x.(int32) > y.(int32)
+		case int64:
+			return x.(int64) > y.(int64)
+		case uint:
+			return x.(uint) > y.(uint)
+		case uint8:
+			return x.(uint8) > y.(uint8)
+		case uint16:
+			return x.(uint16) > y.(uint16)
+		case uint32:
+			return x.(uint32) > y.(uint32)
+		case uint64:
+			return x.(uint64) > y.(uint64)
+		case uintptr:
+			return x.(uintptr) > y.(uintptr)
+		case float32:
+			return x.(float32) > y.(float32)
+		case float64:
+			return x.(float64) > y.(float64)
+		case string:
+			return x.(string) > y.(string)
+		}
+
+	case token.GEQ:
+		switch x.(type) {
+		case int:
+			return x.(int) >= y.(int)
+		case int8:
+			return x.(int8) >= y.(int8)
+		case int16:
+			return x.(int16) >= y.(int16)
+		case int32:
+			return x.(int32) >= y.(int32)
+		case int64:
+			return x.(int64) >= y.(int64)
+		case uint:
+			return x.(uint) >= y.(uint)
+		case uint8:
+			return x.(uint8) >= y.(uint8)
+		case uint16:
+			return x.(uint16) >= y.(uint16)
+		case uint32:
+			return x.(uint32) >= y.(uint32)
+		case uint64:
+			return x.(uint64) >= y.(uint64)
+		case uintptr:
+			return x.(uintptr) >= y.(uintptr)
+		case float32:
+			return x.(float32) >= y.(float32)
+		case float64:
+			return x.(float64) >= y.(float64)
+		case string:
+			return x.(string) >= y.(string)
+		}
+	}
+	panic(fmt.Sprintf("invalid binary op: %T %s %T", x, op, y))
+}
+
+// eqnil returns the comparison x == y using the equivalence relation
+// appropriate for type t.
+// If t is a reference type, at most one of x or y may be a nil value
+// of that type.
+//
+func eqnil(t types.Type, x, y value) bool {
+	switch t.Underlying().(type) {
+	case *types.Map, *types.Signature, *types.Slice:
+		// Since these types don't support comparison,
+		// one of the operands must be a literal nil.
+		switch x := x.(type) {
+		case *hashmap:
+			return (x != nil) == (y.(*hashmap) != nil)
+		case map[value]value:
+			return (x != nil) == (y.(map[value]value) != nil)
+		case *ssa.Function:
+			switch y := y.(type) {
+			case *ssa.Function:
+				return (x != nil) == (y != nil)
+			case *closure:
+				return true
+			}
+		case *closure:
+			return (x != nil) == (y.(*ssa.Function) != nil)
+		case []value:
+			return (x != nil) == (y.([]value) != nil)
+		}
+		panic(fmt.Sprintf("eqnil(%s): illegal dynamic type: %T", t, x))
+	}
+
+	return equals(t, x, y)
+}
+
+func unop(instr *ssa.UnOp, x value) value {
+	switch instr.Op {
+	case token.ARROW: // receive
+		v, ok := <-x.(chan value)
+		if !ok {
+			v = zero(instr.X.Type().Underlying().(*types.Chan).Elem())
+		}
+		if instr.CommaOk {
+			v = tuple{v, ok}
+		}
+		return v
+	case token.SUB:
+		switch x := x.(type) {
+		case int:
+			return -x
+		case int8:
+			return -x
+		case int16:
+			return -x
+		case int32:
+			return -x
+		case int64:
+			return -x
+		case uint:
+			return -x
+		case uint8:
+			return -x
+		case uint16:
+			return -x
+		case uint32:
+			return -x
+		case uint64:
+			return -x
+		case uintptr:
+			return -x
+		case float32:
+			return -x
+		case float64:
+			return -x
+		case complex64:
+			return -x
+		case complex128:
+			return -x
+		}
+	case token.MUL:
+		return load(deref(instr.X.Type()), x.(*value))
+	case token.NOT:
+		return !x.(bool)
+	case token.XOR:
+		switch x := x.(type) {
+		case int:
+			return ^x
+		case int8:
+			return ^x
+		case int16:
+			return ^x
+		case int32:
+			return ^x
+		case int64:
+			return ^x
+		case uint:
+			return ^x
+		case uint8:
+			return ^x
+		case uint16:
+			return ^x
+		case uint32:
+			return ^x
+		case uint64:
+			return ^x
+		case uintptr:
+			return ^x
+		}
+	}
+	panic(fmt.Sprintf("invalid unary op %s %T", instr.Op, x))
+}
+
+// typeAssert checks whether dynamic type of itf is instr.AssertedType.
+// It returns the extracted value on success, and panics on failure,
+// unless instr.CommaOk, in which case it always returns a "value,ok" tuple.
+//
+func typeAssert(i *interpreter, instr *ssa.TypeAssert, itf iface) value {
+	var v value
+	err := ""
+	if itf.t == nil {
+		err = fmt.Sprintf("interface conversion: interface is nil, not %s", instr.AssertedType)
+
+	} else if idst, ok := instr.AssertedType.Underlying().(*types.Interface); ok {
+		v = itf
+		err = checkInterface(i, idst, itf)
+
+	} else if types.Identical(itf.t, instr.AssertedType) {
+		v = itf.v // extract value
+
+	} else {
+		err = fmt.Sprintf("interface conversion: interface is %s, not %s", itf.t, instr.AssertedType)
+	}
+
+	if err != "" {
+		if !instr.CommaOk {
+			panic(err)
+		}
+		return tuple{zero(instr.AssertedType), false}
+	}
+	if instr.CommaOk {
+		return tuple{v, true}
+	}
+	return v
+}
+
+// If CapturedOutput is non-nil, all writes by the interpreted program
+// to file descriptors 1 and 2 will also be written to CapturedOutput.
+//
+// (The $GOROOT/test system requires that the test be considered a
+// failure if "BUG" appears in the combined stdout/stderr output, even
+// if it exits zero.  This is a global variable shared by all
+// interpreters in the same process.)
+//
+var CapturedOutput *bytes.Buffer
+var capturedOutputMu sync.Mutex
+
+// write writes bytes b to the target program's file descriptor fd.
+// The print/println built-ins and the write() system call funnel
+// through here so they can be captured by the test driver.
+func write(fd int, b []byte) (int, error) {
+	// TODO(adonovan): fix: on Windows, std{out,err} are not 1, 2.
+	if CapturedOutput != nil && (fd == 1 || fd == 2) {
+		capturedOutputMu.Lock()
+		CapturedOutput.Write(b) // ignore errors
+		capturedOutputMu.Unlock()
+	}
+	return syswrite(fd, b)
+}
+
+// callBuiltin interprets a call to builtin fn with arguments args,
+// returning its result.
+func callBuiltin(caller *frame, callpos token.Pos, fn *ssa.Builtin, args []value) value {
+	switch fn.Name() {
+	case "append":
+		if len(args) == 1 {
+			return args[0]
+		}
+		if s, ok := args[1].(string); ok {
+			// append([]byte, ...string) []byte
+			arg0 := args[0].([]value)
+			for i := 0; i < len(s); i++ {
+				arg0 = append(arg0, s[i])
+			}
+			return arg0
+		}
+		// append([]T, ...[]T) []T
+		return append(args[0].([]value), args[1].([]value)...)
+
+	case "copy": // copy([]T, []T) int or copy([]byte, string) int
+		src := args[1]
+		if _, ok := src.(string); ok {
+			params := fn.Type().(*types.Signature).Params()
+			src = conv(params.At(0).Type(), params.At(1).Type(), src)
+		}
+		return copy(args[0].([]value), src.([]value))
+
+	case "close": // close(chan T)
+		close(args[0].(chan value))
+		return nil
+
+	case "delete": // delete(map[K]value, K)
+		switch m := args[0].(type) {
+		case map[value]value:
+			delete(m, args[1])
+		case *hashmap:
+			m.delete(args[1].(hashable))
+		default:
+			panic(fmt.Sprintf("illegal map type: %T", m))
+		}
+		return nil
+
+	case "print", "println": // print(any, ...)
+		ln := fn.Name() == "println"
+		var buf bytes.Buffer
+		for i, arg := range args {
+			if i > 0 && ln {
+				buf.WriteRune(' ')
+			}
+			buf.WriteString(toString(arg))
+		}
+		if ln {
+			buf.WriteRune('\n')
+		}
+		write(1, buf.Bytes())
+		return nil
+
+	case "len":
+		switch x := args[0].(type) {
+		case string:
+			return len(x)
+		case array:
+			return len(x)
+		case *value:
+			return len((*x).(array))
+		case []value:
+			return len(x)
+		case map[value]value:
+			return len(x)
+		case *hashmap:
+			return x.len()
+		case chan value:
+			return len(x)
+		default:
+			panic(fmt.Sprintf("len: illegal operand: %T", x))
+		}
+
+	case "cap":
+		switch x := args[0].(type) {
+		case array:
+			return cap(x)
+		case *value:
+			return cap((*x).(array))
+		case []value:
+			return cap(x)
+		case chan value:
+			return cap(x)
+		default:
+			panic(fmt.Sprintf("cap: illegal operand: %T", x))
+		}
+
+	case "real":
+		switch c := args[0].(type) {
+		case complex64:
+			return real(c)
+		case complex128:
+			return real(c)
+		default:
+			panic(fmt.Sprintf("real: illegal operand: %T", c))
+		}
+
+	case "imag":
+		switch c := args[0].(type) {
+		case complex64:
+			return imag(c)
+		case complex128:
+			return imag(c)
+		default:
+			panic(fmt.Sprintf("imag: illegal operand: %T", c))
+		}
+
+	case "complex":
+		switch f := args[0].(type) {
+		case float32:
+			return complex(f, args[1].(float32))
+		case float64:
+			return complex(f, args[1].(float64))
+		default:
+			panic(fmt.Sprintf("complex: illegal operand: %T", f))
+		}
+
+	case "panic":
+		// ssa.Panic handles most cases; this is only for "go
+		// panic" or "defer panic".
+		panic(targetPanic{args[0]})
+
+	case "recover":
+		return doRecover(caller)
+
+	case "ssa:wrapnilchk":
+		recv := args[0]
+		if recv.(*value) == nil {
+			recvType := args[1]
+			methodName := args[2]
+			panic(fmt.Sprintf("value method (%s).%s called using nil *%s pointer",
+				recvType, methodName, recvType))
+		}
+		return recv
+	}
+
+	panic("unknown built-in: " + fn.Name())
+}
+
+func rangeIter(x value, t types.Type) iter {
+	switch x := x.(type) {
+	case map[value]value:
+		// TODO(adonovan): fix: leaks goroutines and channels
+		// on each incomplete map iteration.  We need to open
+		// up an iteration interface using the
+		// reflect.(Value).MapKeys machinery.
+		it := make(mapIter)
+		go func() {
+			for k, v := range x {
+				it <- [2]value{k, v}
+			}
+			close(it)
+		}()
+		return it
+	case *hashmap:
+		// TODO(adonovan): fix: leaks goroutines and channels
+		// on each incomplete map iteration.  We need to open
+		// up an iteration interface using the
+		// reflect.(Value).MapKeys machinery.
+		it := make(mapIter)
+		go func() {
+			for _, e := range x.table {
+				for e != nil {
+					it <- [2]value{e.key, e.value}
+					e = e.next
+				}
+			}
+			close(it)
+		}()
+		return it
+	case string:
+		return &stringIter{Reader: strings.NewReader(x)}
+	}
+	panic(fmt.Sprintf("cannot range over %T", x))
+}
+
+// widen widens a basic typed value x to the widest type of its
+// category, one of:
+//   bool, int64, uint64, float64, complex128, string.
+// This is inefficient but reduces the size of the cross-product of
+// cases we have to consider.
+//
+func widen(x value) value {
+	switch y := x.(type) {
+	case bool, int64, uint64, float64, complex128, string, unsafe.Pointer:
+		return x
+	case int:
+		return int64(y)
+	case int8:
+		return int64(y)
+	case int16:
+		return int64(y)
+	case int32:
+		return int64(y)
+	case uint:
+		return uint64(y)
+	case uint8:
+		return uint64(y)
+	case uint16:
+		return uint64(y)
+	case uint32:
+		return uint64(y)
+	case uintptr:
+		return uint64(y)
+	case float32:
+		return float64(y)
+	case complex64:
+		return complex128(y)
+	}
+	panic(fmt.Sprintf("cannot widen %T", x))
+}
+
+// conv converts the value x of type t_src to type t_dst and returns
+// the result.
+// Possible cases are described with the ssa.Convert operator.
+//
+func conv(t_dst, t_src types.Type, x value) value {
+	ut_src := t_src.Underlying()
+	ut_dst := t_dst.Underlying()
+
+	// Destination type is not an "untyped" type.
+	if b, ok := ut_dst.(*types.Basic); ok && b.Info()&types.IsUntyped != 0 {
+		panic("oops: conversion to 'untyped' type: " + b.String())
+	}
+
+	// Nor is it an interface type.
+	if _, ok := ut_dst.(*types.Interface); ok {
+		if _, ok := ut_src.(*types.Interface); ok {
+			panic("oops: Convert should be ChangeInterface")
+		} else {
+			panic("oops: Convert should be MakeInterface")
+		}
+	}
+
+	// Remaining conversions:
+	//    + untyped string/number/bool constant to a specific
+	//      representation.
+	//    + conversions between non-complex numeric types.
+	//    + conversions between complex numeric types.
+	//    + integer/[]byte/[]rune -> string.
+	//    + string -> []byte/[]rune.
+	//
+	// All are treated the same: first we extract the value to the
+	// widest representation (int64, uint64, float64, complex128,
+	// or string), then we convert it to the desired type.
+
+	switch ut_src := ut_src.(type) {
+	case *types.Pointer:
+		switch ut_dst := ut_dst.(type) {
+		case *types.Basic:
+			// *value to unsafe.Pointer?
+			if ut_dst.Kind() == types.UnsafePointer {
+				return unsafe.Pointer(x.(*value))
+			}
+		}
+
+	case *types.Slice:
+		// []byte or []rune -> string
+		// TODO(adonovan): fix: type B byte; conv([]B -> string).
+		switch ut_src.Elem().(*types.Basic).Kind() {
+		case types.Byte:
+			x := x.([]value)
+			b := make([]byte, 0, len(x))
+			for i := range x {
+				b = append(b, x[i].(byte))
+			}
+			return string(b)
+
+		case types.Rune:
+			x := x.([]value)
+			r := make([]rune, 0, len(x))
+			for i := range x {
+				r = append(r, x[i].(rune))
+			}
+			return string(r)
+		}
+
+	case *types.Basic:
+		x = widen(x)
+
+		// integer -> string?
+		// TODO(adonovan): fix: test integer -> named alias of string.
+		if ut_src.Info()&types.IsInteger != 0 {
+			if ut_dst, ok := ut_dst.(*types.Basic); ok && ut_dst.Kind() == types.String {
+				return string(asInt(x))
+			}
+		}
+
+		// string -> []rune, []byte or string?
+		if s, ok := x.(string); ok {
+			switch ut_dst := ut_dst.(type) {
+			case *types.Slice:
+				var res []value
+				// TODO(adonovan): fix: test named alias of rune, byte.
+				switch ut_dst.Elem().(*types.Basic).Kind() {
+				case types.Rune:
+					for _, r := range []rune(s) {
+						res = append(res, r)
+					}
+					return res
+				case types.Byte:
+					for _, b := range []byte(s) {
+						res = append(res, b)
+					}
+					return res
+				}
+			case *types.Basic:
+				if ut_dst.Kind() == types.String {
+					return x.(string)
+				}
+			}
+			break // fail: no other conversions for string
+		}
+
+		// unsafe.Pointer -> *value
+		if ut_src.Kind() == types.UnsafePointer {
+			// TODO(adonovan): this is wrong and cannot
+			// really be fixed with the current design.
+			//
+			// return (*value)(x.(unsafe.Pointer))
+			// creates a new pointer of a different
+			// type but the underlying interface value
+			// knows its "true" type and so cannot be
+			// meaningfully used through the new pointer.
+			//
+			// To make this work, the interpreter needs to
+			// simulate the memory layout of a real
+			// compiled implementation.
+			//
+			// To at least preserve type-safety, we'll
+			// just return the zero value of the
+			// destination type.
+			return zero(t_dst)
+		}
+
+		// Conversions between complex numeric types?
+		if ut_src.Info()&types.IsComplex != 0 {
+			switch ut_dst.(*types.Basic).Kind() {
+			case types.Complex64:
+				return complex64(x.(complex128))
+			case types.Complex128:
+				return x.(complex128)
+			}
+			break // fail: no other conversions for complex
+		}
+
+		// Conversions between non-complex numeric types?
+		if ut_src.Info()&types.IsNumeric != 0 {
+			kind := ut_dst.(*types.Basic).Kind()
+			switch x := x.(type) {
+			case int64: // signed integer -> numeric?
+				switch kind {
+				case types.Int:
+					return int(x)
+				case types.Int8:
+					return int8(x)
+				case types.Int16:
+					return int16(x)
+				case types.Int32:
+					return int32(x)
+				case types.Int64:
+					return int64(x)
+				case types.Uint:
+					return uint(x)
+				case types.Uint8:
+					return uint8(x)
+				case types.Uint16:
+					return uint16(x)
+				case types.Uint32:
+					return uint32(x)
+				case types.Uint64:
+					return uint64(x)
+				case types.Uintptr:
+					return uintptr(x)
+				case types.Float32:
+					return float32(x)
+				case types.Float64:
+					return float64(x)
+				}
+
+			case uint64: // unsigned integer -> numeric?
+				switch kind {
+				case types.Int:
+					return int(x)
+				case types.Int8:
+					return int8(x)
+				case types.Int16:
+					return int16(x)
+				case types.Int32:
+					return int32(x)
+				case types.Int64:
+					return int64(x)
+				case types.Uint:
+					return uint(x)
+				case types.Uint8:
+					return uint8(x)
+				case types.Uint16:
+					return uint16(x)
+				case types.Uint32:
+					return uint32(x)
+				case types.Uint64:
+					return uint64(x)
+				case types.Uintptr:
+					return uintptr(x)
+				case types.Float32:
+					return float32(x)
+				case types.Float64:
+					return float64(x)
+				}
+
+			case float64: // floating point -> numeric?
+				switch kind {
+				case types.Int:
+					return int(x)
+				case types.Int8:
+					return int8(x)
+				case types.Int16:
+					return int16(x)
+				case types.Int32:
+					return int32(x)
+				case types.Int64:
+					return int64(x)
+				case types.Uint:
+					return uint(x)
+				case types.Uint8:
+					return uint8(x)
+				case types.Uint16:
+					return uint16(x)
+				case types.Uint32:
+					return uint32(x)
+				case types.Uint64:
+					return uint64(x)
+				case types.Uintptr:
+					return uintptr(x)
+				case types.Float32:
+					return float32(x)
+				case types.Float64:
+					return float64(x)
+				}
+			}
+		}
+	}
+
+	panic(fmt.Sprintf("unsupported conversion: %s  -> %s, dynamic type %T", t_src, t_dst, x))
+}
+
+// checkInterface checks that the method set of x implements the
+// interface itype.
+// On success it returns "", on failure, an error message.
+//
+func checkInterface(i *interpreter, itype *types.Interface, x iface) string {
+	if meth, _ := types.MissingMethod(x.t, itype, true); meth != nil {
+		return fmt.Sprintf("interface conversion: %v is not %v: missing method %s",
+			x.t, itype, meth.Name())
+	}
+	return "" // ok
+}
diff --git a/go/src/golang.org/x/tools/go/ssa/interp/reflect.go b/go/src/golang.org/x/tools/go/ssa/interp/reflect.go
index 468771b..48bb911 100644
--- a/go/src/golang.org/x/tools/go/ssa/interp/reflect.go
+++ b/go/src/golang.org/x/tools/go/ssa/interp/reflect.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package interp
 
 // Emulated "reflect" package.
@@ -13,11 +15,11 @@
 import (
 	"fmt"
 	"go/token"
+	"go/types"
 	"reflect"
 	"unsafe"
 
 	"golang.org/x/tools/go/ssa"
-	"golang.org/x/tools/go/types"
 )
 
 type opaqueType struct {
@@ -520,7 +522,7 @@
 func initReflect(i *interpreter) {
 	i.reflectPackage = &ssa.Package{
 		Prog:    i.prog,
-		Object:  reflectTypesPackage,
+		Pkg:     reflectTypesPackage,
 		Members: make(map[string]ssa.Member),
 	}
 
@@ -539,18 +541,18 @@
 	// provide fake source files.  This would guarantee that no bad
 	// information leaks into other packages.
 	if r := i.prog.ImportedPackage("reflect"); r != nil {
-		rV := r.Object.Scope().Lookup("Value").Type().(*types.Named)
+		rV := r.Pkg.Scope().Lookup("Value").Type().(*types.Named)
 
 		// delete bodies of the old methods
 		mset := i.prog.MethodSets.MethodSet(rV)
 		for j := 0; j < mset.Len(); j++ {
-			i.prog.Method(mset.At(j)).Blocks = nil
+			i.prog.MethodValue(mset.At(j)).Blocks = nil
 		}
 
 		tEface := types.NewInterface(nil, nil).Complete()
 		rV.SetUnderlying(types.NewStruct([]*types.Var{
-			types.NewField(token.NoPos, r.Object, "t", tEface, false), // a lie
-			types.NewField(token.NoPos, r.Object, "v", tEface, false),
+			types.NewField(token.NoPos, r.Pkg, "t", tEface, false), // a lie
+			types.NewField(token.NoPos, r.Pkg, "v", tEface, false),
 		}, nil))
 	}
 
diff --git a/go/src/golang.org/x/tools/go/ssa/interp/reflect14.go b/go/src/golang.org/x/tools/go/ssa/interp/reflect14.go
new file mode 100644
index 0000000..9f42327
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/ssa/interp/reflect14.go
@@ -0,0 +1,576 @@
+// 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.
+
+// +build !go1.5
+
+package interp
+
+// Emulated "reflect" package.
+//
+// We completely replace the built-in "reflect" package.
+// The only thing clients can depend upon are that reflect.Type is an
+// interface and reflect.Value is an (opaque) struct.
+
+import (
+	"fmt"
+	"go/token"
+	"reflect"
+	"unsafe"
+
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/types"
+)
+
+type opaqueType struct {
+	types.Type
+	name string
+}
+
+func (t *opaqueType) String() string { return t.name }
+
+// A bogus "reflect" type-checker package.  Shared across interpreters.
+var reflectTypesPackage = types.NewPackage("reflect", "reflect")
+
+// rtype is the concrete type the interpreter uses to implement the
+// reflect.Type interface.
+//
+// type rtype <opaque>
+var rtypeType = makeNamedType("rtype", &opaqueType{nil, "rtype"})
+
+// error is an (interpreted) named type whose underlying type is string.
+// The interpreter uses it for all implementations of the built-in error
+// interface that it creates.
+// We put it in the "reflect" package for expedience.
+//
+// type error string
+var errorType = makeNamedType("error", &opaqueType{nil, "error"})
+
+func makeNamedType(name string, underlying types.Type) *types.Named {
+	obj := types.NewTypeName(token.NoPos, reflectTypesPackage, name, nil)
+	return types.NewNamed(obj, underlying, nil)
+}
+
+func makeReflectValue(t types.Type, v value) value {
+	return structure{rtype{t}, v}
+}
+
+// Given a reflect.Value, returns its rtype.
+func rV2T(v value) rtype {
+	return v.(structure)[0].(rtype)
+}
+
+// Given a reflect.Value, returns the underlying interpreter value.
+func rV2V(v value) value {
+	return v.(structure)[1]
+}
+
+// makeReflectType boxes up an rtype in a reflect.Type interface.
+func makeReflectType(rt rtype) value {
+	return iface{rtypeType, rt}
+}
+
+func extÛ°reflectÛ°Init(fr *frame, args []value) value {
+	// Signature: func()
+	return nil
+}
+
+func extÛ°reflectÛ°rtypeÛ°Bits(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype) int
+	rt := args[0].(rtype).t
+	basic, ok := rt.Underlying().(*types.Basic)
+	if !ok {
+		panic(fmt.Sprintf("reflect.Type.Bits(%T): non-basic type", rt))
+	}
+	return int(fr.i.sizes.Sizeof(basic)) * 8
+}
+
+func extÛ°reflectÛ°rtypeÛ°Elem(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype) reflect.Type
+	return makeReflectType(rtype{args[0].(rtype).t.Underlying().(interface {
+		Elem() types.Type
+	}).Elem()})
+}
+
+func extÛ°reflectÛ°rtypeÛ°Field(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype, i int) reflect.StructField
+	st := args[0].(rtype).t.Underlying().(*types.Struct)
+	i := args[1].(int)
+	f := st.Field(i)
+	return structure{
+		f.Name(),
+		f.Pkg().Path(),
+		makeReflectType(rtype{f.Type()}),
+		st.Tag(i),
+		0,         // TODO(adonovan): offset
+		[]value{}, // TODO(adonovan): indices
+		f.Anonymous(),
+	}
+}
+
+func extÛ°reflectÛ°rtypeÛ°In(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype, i int) int
+	i := args[1].(int)
+	return makeReflectType(rtype{args[0].(rtype).t.(*types.Signature).Params().At(i).Type()})
+}
+
+func extÛ°reflectÛ°rtypeÛ°Kind(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype) uint
+	return uint(reflectKind(args[0].(rtype).t))
+}
+
+func extÛ°reflectÛ°rtypeÛ°NumField(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype) int
+	return args[0].(rtype).t.Underlying().(*types.Struct).NumFields()
+}
+
+func extÛ°reflectÛ°rtypeÛ°NumIn(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype) int
+	return args[0].(rtype).t.(*types.Signature).Params().Len()
+}
+
+func extÛ°reflectÛ°rtypeÛ°NumMethod(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype) int
+	return fr.i.prog.MethodSets.MethodSet(args[0].(rtype).t).Len()
+}
+
+func extÛ°reflectÛ°rtypeÛ°NumOut(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype) int
+	return args[0].(rtype).t.(*types.Signature).Results().Len()
+}
+
+func extÛ°reflectÛ°rtypeÛ°Out(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype, i int) int
+	i := args[1].(int)
+	return makeReflectType(rtype{args[0].(rtype).t.(*types.Signature).Results().At(i).Type()})
+}
+
+func extÛ°reflectÛ°rtypeÛ°Size(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype) uintptr
+	return uintptr(fr.i.sizes.Sizeof(args[0].(rtype).t))
+}
+
+func extÛ°reflectÛ°rtypeÛ°String(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype) string
+	return args[0].(rtype).t.String()
+}
+
+func extÛ°reflectÛ°New(fr *frame, args []value) value {
+	// Signature: func (t reflect.Type) reflect.Value
+	t := args[0].(iface).v.(rtype).t
+	alloc := zero(t)
+	return makeReflectValue(types.NewPointer(t), &alloc)
+}
+
+func extÛ°reflectÛ°SliceOf(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype) Type
+	return makeReflectType(rtype{types.NewSlice(args[0].(iface).v.(rtype).t)})
+}
+
+func extÛ°reflectÛ°TypeOf(fr *frame, args []value) value {
+	// Signature: func (t reflect.rtype) Type
+	return makeReflectType(rtype{args[0].(iface).t})
+}
+
+func extÛ°reflectÛ°ValueOf(fr *frame, args []value) value {
+	// Signature: func (interface{}) reflect.Value
+	itf := args[0].(iface)
+	return makeReflectValue(itf.t, itf.v)
+}
+
+func extÛ°reflectÛ°Zero(fr *frame, args []value) value {
+	// Signature: func (t reflect.Type) reflect.Value
+	t := args[0].(iface).v.(rtype).t
+	return makeReflectValue(t, zero(t))
+}
+
+func reflectKind(t types.Type) reflect.Kind {
+	switch t := t.(type) {
+	case *types.Named:
+		return reflectKind(t.Underlying())
+	case *types.Basic:
+		switch t.Kind() {
+		case types.Bool:
+			return reflect.Bool
+		case types.Int:
+			return reflect.Int
+		case types.Int8:
+			return reflect.Int8
+		case types.Int16:
+			return reflect.Int16
+		case types.Int32:
+			return reflect.Int32
+		case types.Int64:
+			return reflect.Int64
+		case types.Uint:
+			return reflect.Uint
+		case types.Uint8:
+			return reflect.Uint8
+		case types.Uint16:
+			return reflect.Uint16
+		case types.Uint32:
+			return reflect.Uint32
+		case types.Uint64:
+			return reflect.Uint64
+		case types.Uintptr:
+			return reflect.Uintptr
+		case types.Float32:
+			return reflect.Float32
+		case types.Float64:
+			return reflect.Float64
+		case types.Complex64:
+			return reflect.Complex64
+		case types.Complex128:
+			return reflect.Complex128
+		case types.String:
+			return reflect.String
+		case types.UnsafePointer:
+			return reflect.UnsafePointer
+		}
+	case *types.Array:
+		return reflect.Array
+	case *types.Chan:
+		return reflect.Chan
+	case *types.Signature:
+		return reflect.Func
+	case *types.Interface:
+		return reflect.Interface
+	case *types.Map:
+		return reflect.Map
+	case *types.Pointer:
+		return reflect.Ptr
+	case *types.Slice:
+		return reflect.Slice
+	case *types.Struct:
+		return reflect.Struct
+	}
+	panic(fmt.Sprint("unexpected type: ", t))
+}
+
+func extÛ°reflectÛ°ValueÛ°Kind(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) uint
+	return uint(reflectKind(rV2T(args[0]).t))
+}
+
+func extÛ°reflectÛ°ValueÛ°String(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) string
+	return toString(rV2V(args[0]))
+}
+
+func extÛ°reflectÛ°ValueÛ°Type(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) reflect.Type
+	return makeReflectType(rV2T(args[0]))
+}
+
+func extÛ°reflectÛ°ValueÛ°Uint(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) uint64
+	switch v := rV2V(args[0]).(type) {
+	case uint:
+		return uint64(v)
+	case uint8:
+		return uint64(v)
+	case uint16:
+		return uint64(v)
+	case uint32:
+		return uint64(v)
+	case uint64:
+		return uint64(v)
+	case uintptr:
+		return uint64(v)
+	}
+	panic("reflect.Value.Uint")
+}
+
+func extÛ°reflectÛ°ValueÛ°Len(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) int
+	switch v := rV2V(args[0]).(type) {
+	case string:
+		return len(v)
+	case array:
+		return len(v)
+	case chan value:
+		return cap(v)
+	case []value:
+		return len(v)
+	case *hashmap:
+		return v.len()
+	case map[value]value:
+		return len(v)
+	default:
+		panic(fmt.Sprintf("reflect.(Value).Len(%v)", v))
+	}
+}
+
+func extÛ°reflectÛ°ValueÛ°MapIndex(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) Value
+	tValue := rV2T(args[0]).t.Underlying().(*types.Map).Key()
+	k := rV2V(args[1])
+	switch m := rV2V(args[0]).(type) {
+	case map[value]value:
+		if v, ok := m[k]; ok {
+			return makeReflectValue(tValue, v)
+		}
+
+	case *hashmap:
+		if v := m.lookup(k.(hashable)); v != nil {
+			return makeReflectValue(tValue, v)
+		}
+
+	default:
+		panic(fmt.Sprintf("(reflect.Value).MapIndex(%T, %T)", m, k))
+	}
+	return makeReflectValue(nil, nil)
+}
+
+func extÛ°reflectÛ°ValueÛ°MapKeys(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) []Value
+	var keys []value
+	tKey := rV2T(args[0]).t.Underlying().(*types.Map).Key()
+	switch v := rV2V(args[0]).(type) {
+	case map[value]value:
+		for k := range v {
+			keys = append(keys, makeReflectValue(tKey, k))
+		}
+
+	case *hashmap:
+		for _, e := range v.table {
+			for ; e != nil; e = e.next {
+				keys = append(keys, makeReflectValue(tKey, e.key))
+			}
+		}
+
+	default:
+		panic(fmt.Sprintf("(reflect.Value).MapKeys(%T)", v))
+	}
+	return keys
+}
+
+func extÛ°reflectÛ°ValueÛ°NumField(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) int
+	return len(rV2V(args[0]).(structure))
+}
+
+func extÛ°reflectÛ°ValueÛ°NumMethod(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) int
+	return fr.i.prog.MethodSets.MethodSet(rV2T(args[0]).t).Len()
+}
+
+func extÛ°reflectÛ°ValueÛ°Pointer(fr *frame, args []value) value {
+	// Signature: func (v reflect.Value) uintptr
+	switch v := rV2V(args[0]).(type) {
+	case *value:
+		return uintptr(unsafe.Pointer(v))
+	case chan value:
+		return reflect.ValueOf(v).Pointer()
+	case []value:
+		return reflect.ValueOf(v).Pointer()
+	case *hashmap:
+		return reflect.ValueOf(v.table).Pointer()
+	case map[value]value:
+		return reflect.ValueOf(v).Pointer()
+	case *ssa.Function:
+		return uintptr(unsafe.Pointer(v))
+	case *closure:
+		return uintptr(unsafe.Pointer(v))
+	default:
+		panic(fmt.Sprintf("reflect.(Value).Pointer(%T)", v))
+	}
+}
+
+func extÛ°reflectÛ°ValueÛ°Index(fr *frame, args []value) value {
+	// Signature: func (v reflect.Value, i int) Value
+	i := args[1].(int)
+	t := rV2T(args[0]).t.Underlying()
+	switch v := rV2V(args[0]).(type) {
+	case array:
+		return makeReflectValue(t.(*types.Array).Elem(), v[i])
+	case []value:
+		return makeReflectValue(t.(*types.Slice).Elem(), v[i])
+	default:
+		panic(fmt.Sprintf("reflect.(Value).Index(%T)", v))
+	}
+}
+
+func extÛ°reflectÛ°ValueÛ°Bool(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) bool
+	return rV2V(args[0]).(bool)
+}
+
+func extÛ°reflectÛ°ValueÛ°CanAddr(fr *frame, args []value) value {
+	// Signature: func (v reflect.Value) bool
+	// Always false for our representation.
+	return false
+}
+
+func extÛ°reflectÛ°ValueÛ°CanInterface(fr *frame, args []value) value {
+	// Signature: func (v reflect.Value) bool
+	// Always true for our representation.
+	return true
+}
+
+func extÛ°reflectÛ°ValueÛ°Elem(fr *frame, args []value) value {
+	// Signature: func (v reflect.Value) reflect.Value
+	switch x := rV2V(args[0]).(type) {
+	case iface:
+		return makeReflectValue(x.t, x.v)
+	case *value:
+		return makeReflectValue(rV2T(args[0]).t.Underlying().(*types.Pointer).Elem(), *x)
+	default:
+		panic(fmt.Sprintf("reflect.(Value).Elem(%T)", x))
+	}
+}
+
+func extÛ°reflectÛ°ValueÛ°Field(fr *frame, args []value) value {
+	// Signature: func (v reflect.Value, i int) reflect.Value
+	v := args[0]
+	i := args[1].(int)
+	return makeReflectValue(rV2T(v).t.Underlying().(*types.Struct).Field(i).Type(), rV2V(v).(structure)[i])
+}
+
+func extÛ°reflectÛ°ValueÛ°Float(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) float64
+	switch v := rV2V(args[0]).(type) {
+	case float32:
+		return float64(v)
+	case float64:
+		return float64(v)
+	}
+	panic("reflect.Value.Float")
+}
+
+func extÛ°reflectÛ°ValueÛ°Interface(fr *frame, args []value) value {
+	// Signature: func (v reflect.Value) interface{}
+	return extÛ°reflectÛ°valueInterface(fr, args)
+}
+
+func extÛ°reflectÛ°ValueÛ°Int(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) int64
+	switch x := rV2V(args[0]).(type) {
+	case int:
+		return int64(x)
+	case int8:
+		return int64(x)
+	case int16:
+		return int64(x)
+	case int32:
+		return int64(x)
+	case int64:
+		return x
+	default:
+		panic(fmt.Sprintf("reflect.(Value).Int(%T)", x))
+	}
+}
+
+func extÛ°reflectÛ°ValueÛ°IsNil(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) bool
+	switch x := rV2V(args[0]).(type) {
+	case *value:
+		return x == nil
+	case chan value:
+		return x == nil
+	case map[value]value:
+		return x == nil
+	case *hashmap:
+		return x == nil
+	case iface:
+		return x.t == nil
+	case []value:
+		return x == nil
+	case *ssa.Function:
+		return x == nil
+	case *ssa.Builtin:
+		return x == nil
+	case *closure:
+		return x == nil
+	default:
+		panic(fmt.Sprintf("reflect.(Value).IsNil(%T)", x))
+	}
+}
+
+func extÛ°reflectÛ°ValueÛ°IsValid(fr *frame, args []value) value {
+	// Signature: func (reflect.Value) bool
+	return rV2V(args[0]) != nil
+}
+
+func extÛ°reflectÛ°ValueÛ°Set(fr *frame, args []value) value {
+	// TODO(adonovan): implement.
+	return nil
+}
+
+func extÛ°reflectÛ°valueInterface(fr *frame, args []value) value {
+	// Signature: func (v reflect.Value, safe bool) interface{}
+	v := args[0].(structure)
+	return iface{rV2T(v).t, rV2V(v)}
+}
+
+func extÛ°reflectÛ°errorÛ°Error(fr *frame, args []value) value {
+	return args[0]
+}
+
+// newMethod creates a new method of the specified name, package and receiver type.
+func newMethod(pkg *ssa.Package, recvType types.Type, name string) *ssa.Function {
+	// TODO(adonovan): fix: hack: currently the only part of Signature
+	// that is needed is the "pointerness" of Recv.Type, and for
+	// now, we'll set it to always be false since we're only
+	// concerned with rtype.  Encapsulate this better.
+	sig := types.NewSignature(types.NewVar(token.NoPos, nil, "recv", recvType), nil, nil, false)
+	fn := pkg.Prog.NewFunction(name, sig, "fake reflect method")
+	fn.Pkg = pkg
+	return fn
+}
+
+func initReflect(i *interpreter) {
+	i.reflectPackage = &ssa.Package{
+		Prog:    i.prog,
+		Pkg:     reflectTypesPackage,
+		Members: make(map[string]ssa.Member),
+	}
+
+	// Clobber the type-checker's notion of reflect.Value's
+	// underlying type so that it more closely matches the fake one
+	// (at least in the number of fields---we lie about the type of
+	// the rtype field).
+	//
+	// We must ensure that calls to (ssa.Value).Type() return the
+	// fake type so that correct "shape" is used when allocating
+	// variables, making zero values, loading, and storing.
+	//
+	// TODO(adonovan): obviously this is a hack.  We need a cleaner
+	// way to fake the reflect package (almost---DeepEqual is fine).
+	// One approach would be not to even load its source code, but
+	// provide fake source files.  This would guarantee that no bad
+	// information leaks into other packages.
+	if r := i.prog.ImportedPackage("reflect"); r != nil {
+		rV := r.Pkg.Scope().Lookup("Value").Type().(*types.Named)
+
+		// delete bodies of the old methods
+		mset := i.prog.MethodSets.MethodSet(rV)
+		for j := 0; j < mset.Len(); j++ {
+			i.prog.MethodValue(mset.At(j)).Blocks = nil
+		}
+
+		tEface := types.NewInterface(nil, nil).Complete()
+		rV.SetUnderlying(types.NewStruct([]*types.Var{
+			types.NewField(token.NoPos, r.Pkg, "t", tEface, false), // a lie
+			types.NewField(token.NoPos, r.Pkg, "v", tEface, false),
+		}, nil))
+	}
+
+	i.rtypeMethods = methodSet{
+		"Bits":      newMethod(i.reflectPackage, rtypeType, "Bits"),
+		"Elem":      newMethod(i.reflectPackage, rtypeType, "Elem"),
+		"Field":     newMethod(i.reflectPackage, rtypeType, "Field"),
+		"In":        newMethod(i.reflectPackage, rtypeType, "In"),
+		"Kind":      newMethod(i.reflectPackage, rtypeType, "Kind"),
+		"NumField":  newMethod(i.reflectPackage, rtypeType, "NumField"),
+		"NumIn":     newMethod(i.reflectPackage, rtypeType, "NumIn"),
+		"NumMethod": newMethod(i.reflectPackage, rtypeType, "NumMethod"),
+		"NumOut":    newMethod(i.reflectPackage, rtypeType, "NumOut"),
+		"Out":       newMethod(i.reflectPackage, rtypeType, "Out"),
+		"Size":      newMethod(i.reflectPackage, rtypeType, "Size"),
+		"String":    newMethod(i.reflectPackage, rtypeType, "String"),
+	}
+	i.errorMethods = methodSet{
+		"Error": newMethod(i.reflectPackage, errorType, "Error"),
+	}
+}
diff --git a/go/src/golang.org/x/tools/go/ssa/interp/testdata/complit.go b/go/src/golang.org/x/tools/go/ssa/interp/testdata/complit.go
index 02f9916..7bec523 100644
--- a/go/src/golang.org/x/tools/go/ssa/interp/testdata/complit.go
+++ b/go/src/golang.org/x/tools/go/ssa/interp/testdata/complit.go
@@ -164,5 +164,21 @@
 	}
 }
 
+// Regression test for https://github.com/golang/go/issues/13341:
+// within a map literal, if a key expression is a composite literal,
+// Go 1.5 allows its type to be omitted.  An & operation may be implied.
+func init() {
+	type S struct{ x int }
+	// same as map[*S]bool{&S{x: 1}: true}
+	m := map[*S]bool{{x: 1}: true}
+	for s := range m {
+		if s.x != 1 {
+			panic(s) // wrong key
+		}
+		return
+	}
+	panic("map is empty")
+}
+
 func main() {
 }
diff --git a/go/src/golang.org/x/tools/go/ssa/interp/value.go b/go/src/golang.org/x/tools/go/ssa/interp/value.go
index 2ab0c04..2194b01 100644
--- a/go/src/golang.org/x/tools/go/ssa/interp/value.go
+++ b/go/src/golang.org/x/tools/go/ssa/interp/value.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package interp
 
 // Values
@@ -36,6 +38,7 @@
 import (
 	"bytes"
 	"fmt"
+	"go/types"
 	"io"
 	"reflect"
 	"strings"
@@ -43,7 +46,6 @@
 	"unsafe"
 
 	"golang.org/x/tools/go/ssa"
-	"golang.org/x/tools/go/types"
 	"golang.org/x/tools/go/types/typeutil"
 )
 
diff --git a/go/src/golang.org/x/tools/go/ssa/interp/value14.go b/go/src/golang.org/x/tools/go/ssa/interp/value14.go
new file mode 100644
index 0000000..f8fedd3
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/ssa/interp/value14.go
@@ -0,0 +1,499 @@
+// 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.
+
+// +build !go1.5
+
+package interp
+
+// Values
+//
+// All interpreter values are "boxed" in the empty interface, value.
+// The range of possible dynamic types within value are:
+//
+// - bool
+// - numbers (all built-in int/float/complex types are distinguished)
+// - string
+// - map[value]value --- maps for which  usesBuiltinMap(keyType)
+//   *hashmap        --- maps for which !usesBuiltinMap(keyType)
+// - chan value
+// - []value --- slices
+// - iface --- interfaces.
+// - structure --- structs.  Fields are ordered and accessed by numeric indices.
+// - array --- arrays.
+// - *value --- pointers.  Careful: *value is a distinct type from *array etc.
+// - *ssa.Function \
+//   *ssa.Builtin   } --- functions.  A nil 'func' is always of type *ssa.Function.
+//   *closure      /
+// - tuple --- as returned by Return, Next, "value,ok" modes, etc.
+// - iter --- iterators from 'range' over map or string.
+// - bad --- a poison pill for locals that have gone out of scope.
+// - rtype -- the interpreter's concrete implementation of reflect.Type
+//
+// Note that nil is not on this list.
+//
+// Pay close attention to whether or not the dynamic type is a pointer.
+// The compiler cannot help you since value is an empty interface.
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"reflect"
+	"strings"
+	"sync"
+	"unsafe"
+
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/go/types/typeutil"
+)
+
+type value interface{}
+
+type tuple []value
+
+type array []value
+
+type iface struct {
+	t types.Type // never an "untyped" type
+	v value
+}
+
+type structure []value
+
+// For map, array, *array, slice, string or channel.
+type iter interface {
+	// next returns a Tuple (key, value, ok).
+	// key and value are unaliased, e.g. copies of the sequence element.
+	next() tuple
+}
+
+type closure struct {
+	Fn  *ssa.Function
+	Env []value
+}
+
+type bad struct{}
+
+type rtype struct {
+	t types.Type
+}
+
+// Hash functions and equivalence relation:
+
+// hashString computes the FNV hash of s.
+func hashString(s string) int {
+	var h uint32
+	for i := 0; i < len(s); i++ {
+		h ^= uint32(s[i])
+		h *= 16777619
+	}
+	return int(h)
+}
+
+var (
+	mu     sync.Mutex
+	hasher = typeutil.MakeHasher()
+)
+
+// hashType returns a hash for t such that
+// types.Identical(x, y) => hashType(x) == hashType(y).
+func hashType(t types.Type) int {
+	mu.Lock()
+	h := int(hasher.Hash(t))
+	mu.Unlock()
+	return h
+}
+
+// usesBuiltinMap returns true if the built-in hash function and
+// equivalence relation for type t are consistent with those of the
+// interpreter's representation of type t.  Such types are: all basic
+// types (bool, numbers, string), pointers and channels.
+//
+// usesBuiltinMap returns false for types that require a custom map
+// implementation: interfaces, arrays and structs.
+//
+// Panic ensues if t is an invalid map key type: function, map or slice.
+func usesBuiltinMap(t types.Type) bool {
+	switch t := t.(type) {
+	case *types.Basic, *types.Chan, *types.Pointer:
+		return true
+	case *types.Named:
+		return usesBuiltinMap(t.Underlying())
+	case *types.Interface, *types.Array, *types.Struct:
+		return false
+	}
+	panic(fmt.Sprintf("invalid map key type: %T", t))
+}
+
+func (x array) eq(t types.Type, _y interface{}) bool {
+	y := _y.(array)
+	tElt := t.Underlying().(*types.Array).Elem()
+	for i, xi := range x {
+		if !equals(tElt, xi, y[i]) {
+			return false
+		}
+	}
+	return true
+}
+
+func (x array) hash(t types.Type) int {
+	h := 0
+	tElt := t.Underlying().(*types.Array).Elem()
+	for _, xi := range x {
+		h += hash(tElt, xi)
+	}
+	return h
+}
+
+func (x structure) eq(t types.Type, _y interface{}) bool {
+	y := _y.(structure)
+	tStruct := t.Underlying().(*types.Struct)
+	for i, n := 0, tStruct.NumFields(); i < n; i++ {
+		if f := tStruct.Field(i); !f.Anonymous() {
+			if !equals(f.Type(), x[i], y[i]) {
+				return false
+			}
+		}
+	}
+	return true
+}
+
+func (x structure) hash(t types.Type) int {
+	tStruct := t.Underlying().(*types.Struct)
+	h := 0
+	for i, n := 0, tStruct.NumFields(); i < n; i++ {
+		if f := tStruct.Field(i); !f.Anonymous() {
+			h += hash(f.Type(), x[i])
+		}
+	}
+	return h
+}
+
+// nil-tolerant variant of types.Identical.
+func sameType(x, y types.Type) bool {
+	if x == nil {
+		return y == nil
+	}
+	return y != nil && types.Identical(x, y)
+}
+
+func (x iface) eq(t types.Type, _y interface{}) bool {
+	y := _y.(iface)
+	return sameType(x.t, y.t) && (x.t == nil || equals(x.t, x.v, y.v))
+}
+
+func (x iface) hash(_ types.Type) int {
+	return hashType(x.t)*8581 + hash(x.t, x.v)
+}
+
+func (x rtype) hash(_ types.Type) int {
+	return hashType(x.t)
+}
+
+func (x rtype) eq(_ types.Type, y interface{}) bool {
+	return types.Identical(x.t, y.(rtype).t)
+}
+
+// equals returns true iff x and y are equal according to Go's
+// linguistic equivalence relation for type t.
+// In a well-typed program, the dynamic types of x and y are
+// guaranteed equal.
+func equals(t types.Type, x, y value) bool {
+	switch x := x.(type) {
+	case bool:
+		return x == y.(bool)
+	case int:
+		return x == y.(int)
+	case int8:
+		return x == y.(int8)
+	case int16:
+		return x == y.(int16)
+	case int32:
+		return x == y.(int32)
+	case int64:
+		return x == y.(int64)
+	case uint:
+		return x == y.(uint)
+	case uint8:
+		return x == y.(uint8)
+	case uint16:
+		return x == y.(uint16)
+	case uint32:
+		return x == y.(uint32)
+	case uint64:
+		return x == y.(uint64)
+	case uintptr:
+		return x == y.(uintptr)
+	case float32:
+		return x == y.(float32)
+	case float64:
+		return x == y.(float64)
+	case complex64:
+		return x == y.(complex64)
+	case complex128:
+		return x == y.(complex128)
+	case string:
+		return x == y.(string)
+	case *value:
+		return x == y.(*value)
+	case chan value:
+		return x == y.(chan value)
+	case structure:
+		return x.eq(t, y)
+	case array:
+		return x.eq(t, y)
+	case iface:
+		return x.eq(t, y)
+	case rtype:
+		return x.eq(t, y)
+	}
+
+	// Since map, func and slice don't support comparison, this
+	// case is only reachable if one of x or y is literally nil
+	// (handled in eqnil) or via interface{} values.
+	panic(fmt.Sprintf("comparing uncomparable type %s", t))
+}
+
+// Returns an integer hash of x such that equals(x, y) => hash(x) == hash(y).
+func hash(t types.Type, x value) int {
+	switch x := x.(type) {
+	case bool:
+		if x {
+			return 1
+		}
+		return 0
+	case int:
+		return x
+	case int8:
+		return int(x)
+	case int16:
+		return int(x)
+	case int32:
+		return int(x)
+	case int64:
+		return int(x)
+	case uint:
+		return int(x)
+	case uint8:
+		return int(x)
+	case uint16:
+		return int(x)
+	case uint32:
+		return int(x)
+	case uint64:
+		return int(x)
+	case uintptr:
+		return int(x)
+	case float32:
+		return int(x)
+	case float64:
+		return int(x)
+	case complex64:
+		return int(real(x))
+	case complex128:
+		return int(real(x))
+	case string:
+		return hashString(x)
+	case *value:
+		return int(uintptr(unsafe.Pointer(x)))
+	case chan value:
+		return int(uintptr(reflect.ValueOf(x).Pointer()))
+	case structure:
+		return x.hash(t)
+	case array:
+		return x.hash(t)
+	case iface:
+		return x.hash(t)
+	case rtype:
+		return x.hash(t)
+	}
+	panic(fmt.Sprintf("%T is unhashable", x))
+}
+
+// reflect.Value struct values don't have a fixed shape, since the
+// payload can be a scalar or an aggregate depending on the instance.
+// So store (and load) can't simply use recursion over the shape of the
+// rhs value, or the lhs, to copy the value; we need the static type
+// information.  (We can't make reflect.Value a new basic data type
+// because its "structness" is exposed to Go programs.)
+
+// load returns the value of type T in *addr.
+func load(T types.Type, addr *value) value {
+	switch T := T.Underlying().(type) {
+	case *types.Struct:
+		v := (*addr).(structure)
+		a := make(structure, len(v))
+		for i := range a {
+			a[i] = load(T.Field(i).Type(), &v[i])
+		}
+		return a
+	case *types.Array:
+		v := (*addr).(array)
+		a := make(array, len(v))
+		for i := range a {
+			a[i] = load(T.Elem(), &v[i])
+		}
+		return a
+	default:
+		return *addr
+	}
+}
+
+// store stores value v of type T into *addr.
+func store(T types.Type, addr *value, v value) {
+	switch T := T.Underlying().(type) {
+	case *types.Struct:
+		lhs := (*addr).(structure)
+		rhs := v.(structure)
+		for i := range lhs {
+			store(T.Field(i).Type(), &lhs[i], rhs[i])
+		}
+	case *types.Array:
+		lhs := (*addr).(array)
+		rhs := v.(array)
+		for i := range lhs {
+			store(T.Elem(), &lhs[i], rhs[i])
+		}
+	default:
+		*addr = v
+	}
+}
+
+// Prints in the style of built-in println.
+// (More or less; in gc println is actually a compiler intrinsic and
+// can distinguish println(1) from println(interface{}(1)).)
+func writeValue(buf *bytes.Buffer, v value) {
+	switch v := v.(type) {
+	case nil, bool, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr, float32, float64, complex64, complex128, string:
+		fmt.Fprintf(buf, "%v", v)
+
+	case map[value]value:
+		buf.WriteString("map[")
+		sep := ""
+		for k, e := range v {
+			buf.WriteString(sep)
+			sep = " "
+			writeValue(buf, k)
+			buf.WriteString(":")
+			writeValue(buf, e)
+		}
+		buf.WriteString("]")
+
+	case *hashmap:
+		buf.WriteString("map[")
+		sep := " "
+		for _, e := range v.table {
+			for e != nil {
+				buf.WriteString(sep)
+				sep = " "
+				writeValue(buf, e.key)
+				buf.WriteString(":")
+				writeValue(buf, e.value)
+				e = e.next
+			}
+		}
+		buf.WriteString("]")
+
+	case chan value:
+		fmt.Fprintf(buf, "%v", v) // (an address)
+
+	case *value:
+		if v == nil {
+			buf.WriteString("<nil>")
+		} else {
+			fmt.Fprintf(buf, "%p", v)
+		}
+
+	case iface:
+		fmt.Fprintf(buf, "(%s, ", v.t)
+		writeValue(buf, v.v)
+		buf.WriteString(")")
+
+	case structure:
+		buf.WriteString("{")
+		for i, e := range v {
+			if i > 0 {
+				buf.WriteString(" ")
+			}
+			writeValue(buf, e)
+		}
+		buf.WriteString("}")
+
+	case array:
+		buf.WriteString("[")
+		for i, e := range v {
+			if i > 0 {
+				buf.WriteString(" ")
+			}
+			writeValue(buf, e)
+		}
+		buf.WriteString("]")
+
+	case []value:
+		buf.WriteString("[")
+		for i, e := range v {
+			if i > 0 {
+				buf.WriteString(" ")
+			}
+			writeValue(buf, e)
+		}
+		buf.WriteString("]")
+
+	case *ssa.Function, *ssa.Builtin, *closure:
+		fmt.Fprintf(buf, "%p", v) // (an address)
+
+	case rtype:
+		buf.WriteString(v.t.String())
+
+	case tuple:
+		// Unreachable in well-formed Go programs
+		buf.WriteString("(")
+		for i, e := range v {
+			if i > 0 {
+				buf.WriteString(", ")
+			}
+			writeValue(buf, e)
+		}
+		buf.WriteString(")")
+
+	default:
+		fmt.Fprintf(buf, "<%T>", v)
+	}
+}
+
+// Implements printing of Go values in the style of built-in println.
+func toString(v value) string {
+	var b bytes.Buffer
+	writeValue(&b, v)
+	return b.String()
+}
+
+// ------------------------------------------------------------------------
+// Iterators
+
+type stringIter struct {
+	*strings.Reader
+	i int
+}
+
+func (it *stringIter) next() tuple {
+	okv := make(tuple, 3)
+	ch, n, err := it.ReadRune()
+	ok := err != io.EOF
+	okv[0] = ok
+	if ok {
+		okv[1] = it.i
+		okv[2] = ch
+	}
+	it.i += n
+	return okv
+}
+
+type mapIter chan [2]value
+
+func (it mapIter) next() tuple {
+	kv, ok := <-it
+	return tuple{ok, kv[0], kv[1]}
+}
diff --git a/go/src/golang.org/x/tools/go/ssa/lift.go b/go/src/golang.org/x/tools/go/ssa/lift.go
index 3771f61..722d086 100644
--- a/go/src/golang.org/x/tools/go/ssa/lift.go
+++ b/go/src/golang.org/x/tools/go/ssa/lift.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package ssa
 
 // This file defines the lifting pass which tries to "lift" Alloc
@@ -44,10 +46,9 @@
 import (
 	"fmt"
 	"go/token"
+	"go/types"
 	"math/big"
 	"os"
-
-	"golang.org/x/tools/go/types"
 )
 
 // If true, perform sanity checking and show diagnostic information at
diff --git a/go/src/golang.org/x/tools/go/ssa/lift14.go b/go/src/golang.org/x/tools/go/ssa/lift14.go
new file mode 100644
index 0000000..d57a85c
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/ssa/lift14.go
@@ -0,0 +1,601 @@
+// 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.
+
+// +build !go1.5
+
+package ssa
+
+// This file defines the lifting pass which tries to "lift" Alloc
+// cells (new/local variables) into SSA registers, replacing loads
+// with the dominating stored value, eliminating loads and stores, and
+// inserting φ-nodes as needed.
+
+// Cited papers and resources:
+//
+// Ron Cytron et al. 1991. Efficiently computing SSA form...
+// http://doi.acm.org/10.1145/115372.115320
+//
+// Cooper, Harvey, Kennedy.  2001.  A Simple, Fast Dominance Algorithm.
+// Software Practice and Experience 2001, 4:1-10.
+// http://www.hipersoft.rice.edu/grads/publications/dom14.pdf
+//
+// Daniel Berlin, llvmdev mailing list, 2012.
+// http://lists.cs.uiuc.edu/pipermail/llvmdev/2012-January/046638.html
+// (Be sure to expand the whole thread.)
+
+// TODO(adonovan): opt: there are many optimizations worth evaluating, and
+// the conventional wisdom for SSA construction is that a simple
+// algorithm well engineered often beats those of better asymptotic
+// complexity on all but the most egregious inputs.
+//
+// Danny Berlin suggests that the Cooper et al. algorithm for
+// computing the dominance frontier is superior to Cytron et al.
+// Furthermore he recommends that rather than computing the DF for the
+// whole function then renaming all alloc cells, it may be cheaper to
+// compute the DF for each alloc cell separately and throw it away.
+//
+// Consider exploiting liveness information to avoid creating dead
+// φ-nodes which we then immediately remove.
+//
+// Integrate lifting with scalar replacement of aggregates (SRA) since
+// the two are synergistic.
+//
+// Also see many other "TODO: opt" suggestions in the code.
+
+import (
+	"fmt"
+	"go/token"
+	"math/big"
+	"os"
+
+	"golang.org/x/tools/go/types"
+)
+
+// If true, perform sanity checking and show diagnostic information at
+// each step of lifting.  Very verbose.
+const debugLifting = false
+
+// domFrontier maps each block to the set of blocks in its dominance
+// frontier.  The outer slice is conceptually a map keyed by
+// Block.Index.  The inner slice is conceptually a set, possibly
+// containing duplicates.
+//
+// TODO(adonovan): opt: measure impact of dups; consider a packed bit
+// representation, e.g. big.Int, and bitwise parallel operations for
+// the union step in the Children loop.
+//
+// domFrontier's methods mutate the slice's elements but not its
+// length, so their receivers needn't be pointers.
+//
+type domFrontier [][]*BasicBlock
+
+func (df domFrontier) add(u, v *BasicBlock) {
+	p := &df[u.Index]
+	*p = append(*p, v)
+}
+
+// build builds the dominance frontier df for the dominator (sub)tree
+// rooted at u, using the Cytron et al. algorithm.
+//
+// TODO(adonovan): opt: consider Berlin approach, computing pruned SSA
+// by pruning the entire IDF computation, rather than merely pruning
+// the DF -> IDF step.
+func (df domFrontier) build(u *BasicBlock) {
+	// Encounter each node u in postorder of dom tree.
+	for _, child := range u.dom.children {
+		df.build(child)
+	}
+	for _, vb := range u.Succs {
+		if v := vb.dom; v.idom != u {
+			df.add(u, vb)
+		}
+	}
+	for _, w := range u.dom.children {
+		for _, vb := range df[w.Index] {
+			// TODO(adonovan): opt: use word-parallel bitwise union.
+			if v := vb.dom; v.idom != u {
+				df.add(u, vb)
+			}
+		}
+	}
+}
+
+func buildDomFrontier(fn *Function) domFrontier {
+	df := make(domFrontier, len(fn.Blocks))
+	df.build(fn.Blocks[0])
+	if fn.Recover != nil {
+		df.build(fn.Recover)
+	}
+	return df
+}
+
+func removeInstr(refs []Instruction, instr Instruction) []Instruction {
+	i := 0
+	for _, ref := range refs {
+		if ref == instr {
+			continue
+		}
+		refs[i] = ref
+		i++
+	}
+	for j := i; j != len(refs); j++ {
+		refs[j] = nil // aid GC
+	}
+	return refs[:i]
+}
+
+// lift attempts to replace local and new Allocs accessed only with
+// load/store by SSA registers, inserting φ-nodes where necessary.
+// The result is a program in classical pruned SSA form.
+//
+// Preconditions:
+// - fn has no dead blocks (blockopt has run).
+// - Def/use info (Operands and Referrers) is up-to-date.
+// - The dominator tree is up-to-date.
+//
+func lift(fn *Function) {
+	// TODO(adonovan): opt: lots of little optimizations may be
+	// worthwhile here, especially if they cause us to avoid
+	// buildDomFrontier.  For example:
+	//
+	// - Alloc never loaded?  Eliminate.
+	// - Alloc never stored?  Replace all loads with a zero constant.
+	// - Alloc stored once?  Replace loads with dominating store;
+	//   don't forget that an Alloc is itself an effective store
+	//   of zero.
+	// - Alloc used only within a single block?
+	//   Use degenerate algorithm avoiding φ-nodes.
+	// - Consider synergy with scalar replacement of aggregates (SRA).
+	//   e.g. *(&x.f) where x is an Alloc.
+	//   Perhaps we'd get better results if we generated this as x.f
+	//   i.e. Field(x, .f) instead of Load(FieldIndex(x, .f)).
+	//   Unclear.
+	//
+	// But we will start with the simplest correct code.
+	df := buildDomFrontier(fn)
+
+	if debugLifting {
+		title := false
+		for i, blocks := range df {
+			if blocks != nil {
+				if !title {
+					fmt.Fprintf(os.Stderr, "Dominance frontier of %s:\n", fn)
+					title = true
+				}
+				fmt.Fprintf(os.Stderr, "\t%s: %s\n", fn.Blocks[i], blocks)
+			}
+		}
+	}
+
+	newPhis := make(newPhiMap)
+
+	// During this pass we will replace some BasicBlock.Instrs
+	// (allocs, loads and stores) with nil, keeping a count in
+	// BasicBlock.gaps.  At the end we will reset Instrs to the
+	// concatenation of all non-dead newPhis and non-nil Instrs
+	// for the block, reusing the original array if space permits.
+
+	// While we're here, we also eliminate 'rundefers'
+	// instructions in functions that contain no 'defer'
+	// instructions.
+	usesDefer := false
+
+	// Determine which allocs we can lift and number them densely.
+	// The renaming phase uses this numbering for compact maps.
+	numAllocs := 0
+	for _, b := range fn.Blocks {
+		b.gaps = 0
+		b.rundefers = 0
+		for _, instr := range b.Instrs {
+			switch instr := instr.(type) {
+			case *Alloc:
+				index := -1
+				if liftAlloc(df, instr, newPhis) {
+					index = numAllocs
+					numAllocs++
+				}
+				instr.index = index
+			case *Defer:
+				usesDefer = true
+			case *RunDefers:
+				b.rundefers++
+			}
+		}
+	}
+
+	// renaming maps an alloc (keyed by index) to its replacement
+	// value.  Initially the renaming contains nil, signifying the
+	// zero constant of the appropriate type; we construct the
+	// Const lazily at most once on each path through the domtree.
+	// TODO(adonovan): opt: cache per-function not per subtree.
+	renaming := make([]Value, numAllocs)
+
+	// Renaming.
+	rename(fn.Blocks[0], renaming, newPhis)
+
+	// Eliminate dead new phis, then prepend the live ones to each block.
+	for _, b := range fn.Blocks {
+
+		// Compress the newPhis slice to eliminate unused phis.
+		// TODO(adonovan): opt: compute liveness to avoid
+		// placing phis in blocks for which the alloc cell is
+		// not live.
+		nps := newPhis[b]
+		j := 0
+		for _, np := range nps {
+			if !phiIsLive(np.phi) {
+				// discard it, first removing it from referrers
+				for _, newval := range np.phi.Edges {
+					if refs := newval.Referrers(); refs != nil {
+						*refs = removeInstr(*refs, np.phi)
+					}
+				}
+				continue
+			}
+			nps[j] = np
+			j++
+		}
+		nps = nps[:j]
+
+		rundefersToKill := b.rundefers
+		if usesDefer {
+			rundefersToKill = 0
+		}
+
+		if j+b.gaps+rundefersToKill == 0 {
+			continue // fast path: no new phis or gaps
+		}
+
+		// Compact nps + non-nil Instrs into a new slice.
+		// TODO(adonovan): opt: compact in situ if there is
+		// sufficient space or slack in the slice.
+		dst := make([]Instruction, len(b.Instrs)+j-b.gaps-rundefersToKill)
+		for i, np := range nps {
+			dst[i] = np.phi
+		}
+		for _, instr := range b.Instrs {
+			if instr == nil {
+				continue
+			}
+			if !usesDefer {
+				if _, ok := instr.(*RunDefers); ok {
+					continue
+				}
+			}
+			dst[j] = instr
+			j++
+		}
+		for i, np := range nps {
+			dst[i] = np.phi
+		}
+		b.Instrs = dst
+	}
+
+	// Remove any fn.Locals that were lifted.
+	j := 0
+	for _, l := range fn.Locals {
+		if l.index < 0 {
+			fn.Locals[j] = l
+			j++
+		}
+	}
+	// Nil out fn.Locals[j:] to aid GC.
+	for i := j; i < len(fn.Locals); i++ {
+		fn.Locals[i] = nil
+	}
+	fn.Locals = fn.Locals[:j]
+}
+
+func phiIsLive(phi *Phi) bool {
+	for _, instr := range *phi.Referrers() {
+		if instr == phi {
+			continue // self-refs don't count
+		}
+		if _, ok := instr.(*DebugRef); ok {
+			continue // debug refs don't count
+		}
+		return true
+	}
+	return false
+}
+
+type blockSet struct{ big.Int } // (inherit methods from Int)
+
+// add adds b to the set and returns true if the set changed.
+func (s *blockSet) add(b *BasicBlock) bool {
+	i := b.Index
+	if s.Bit(i) != 0 {
+		return false
+	}
+	s.SetBit(&s.Int, i, 1)
+	return true
+}
+
+// take removes an arbitrary element from a set s and
+// returns its index, or returns -1 if empty.
+func (s *blockSet) take() int {
+	l := s.BitLen()
+	for i := 0; i < l; i++ {
+		if s.Bit(i) == 1 {
+			s.SetBit(&s.Int, i, 0)
+			return i
+		}
+	}
+	return -1
+}
+
+// newPhi is a pair of a newly introduced φ-node and the lifted Alloc
+// it replaces.
+type newPhi struct {
+	phi   *Phi
+	alloc *Alloc
+}
+
+// newPhiMap records for each basic block, the set of newPhis that
+// must be prepended to the block.
+type newPhiMap map[*BasicBlock][]newPhi
+
+// liftAlloc determines whether alloc can be lifted into registers,
+// and if so, it populates newPhis with all the φ-nodes it may require
+// and returns true.
+//
+func liftAlloc(df domFrontier, alloc *Alloc, newPhis newPhiMap) bool {
+	// Don't lift aggregates into registers, because we don't have
+	// a way to express their zero-constants.
+	switch deref(alloc.Type()).Underlying().(type) {
+	case *types.Array, *types.Struct:
+		return false
+	}
+
+	// Don't lift named return values in functions that defer
+	// calls that may recover from panic.
+	if fn := alloc.Parent(); fn.Recover != nil {
+		for _, nr := range fn.namedResults {
+			if nr == alloc {
+				return false
+			}
+		}
+	}
+
+	// Compute defblocks, the set of blocks containing a
+	// definition of the alloc cell.
+	var defblocks blockSet
+	for _, instr := range *alloc.Referrers() {
+		// Bail out if we discover the alloc is not liftable;
+		// the only operations permitted to use the alloc are
+		// loads/stores into the cell, and DebugRef.
+		switch instr := instr.(type) {
+		case *Store:
+			if instr.Val == alloc {
+				return false // address used as value
+			}
+			if instr.Addr != alloc {
+				panic("Alloc.Referrers is inconsistent")
+			}
+			defblocks.add(instr.Block())
+		case *UnOp:
+			if instr.Op != token.MUL {
+				return false // not a load
+			}
+			if instr.X != alloc {
+				panic("Alloc.Referrers is inconsistent")
+			}
+		case *DebugRef:
+			// ok
+		default:
+			return false // some other instruction
+		}
+	}
+	// The Alloc itself counts as a (zero) definition of the cell.
+	defblocks.add(alloc.Block())
+
+	if debugLifting {
+		fmt.Fprintln(os.Stderr, "\tlifting ", alloc, alloc.Name())
+	}
+
+	fn := alloc.Parent()
+
+	// Φ-insertion.
+	//
+	// What follows is the body of the main loop of the insert-φ
+	// function described by Cytron et al, but instead of using
+	// counter tricks, we just reset the 'hasAlready' and 'work'
+	// sets each iteration.  These are bitmaps so it's pretty cheap.
+	//
+	// TODO(adonovan): opt: recycle slice storage for W,
+	// hasAlready, defBlocks across liftAlloc calls.
+	var hasAlready blockSet
+
+	// Initialize W and work to defblocks.
+	var work blockSet = defblocks // blocks seen
+	var W blockSet                // blocks to do
+	W.Set(&defblocks.Int)
+
+	// Traverse iterated dominance frontier, inserting φ-nodes.
+	for i := W.take(); i != -1; i = W.take() {
+		u := fn.Blocks[i]
+		for _, v := range df[u.Index] {
+			if hasAlready.add(v) {
+				// Create φ-node.
+				// It will be prepended to v.Instrs later, if needed.
+				phi := &Phi{
+					Edges:   make([]Value, len(v.Preds)),
+					Comment: alloc.Comment,
+				}
+				phi.pos = alloc.Pos()
+				phi.setType(deref(alloc.Type()))
+				phi.block = v
+				if debugLifting {
+					fmt.Fprintf(os.Stderr, "\tplace %s = %s at block %s\n", phi.Name(), phi, v)
+				}
+				newPhis[v] = append(newPhis[v], newPhi{phi, alloc})
+
+				if work.add(v) {
+					W.add(v)
+				}
+			}
+		}
+	}
+
+	return true
+}
+
+// replaceAll replaces all intraprocedural uses of x with y,
+// updating x.Referrers and y.Referrers.
+// Precondition: x.Referrers() != nil, i.e. x must be local to some function.
+//
+func replaceAll(x, y Value) {
+	var rands []*Value
+	pxrefs := x.Referrers()
+	pyrefs := y.Referrers()
+	for _, instr := range *pxrefs {
+		rands = instr.Operands(rands[:0]) // recycle storage
+		for _, rand := range rands {
+			if *rand != nil {
+				if *rand == x {
+					*rand = y
+				}
+			}
+		}
+		if pyrefs != nil {
+			*pyrefs = append(*pyrefs, instr) // dups ok
+		}
+	}
+	*pxrefs = nil // x is now unreferenced
+}
+
+// renamed returns the value to which alloc is being renamed,
+// constructing it lazily if it's the implicit zero initialization.
+//
+func renamed(renaming []Value, alloc *Alloc) Value {
+	v := renaming[alloc.index]
+	if v == nil {
+		v = zeroConst(deref(alloc.Type()))
+		renaming[alloc.index] = v
+	}
+	return v
+}
+
+// rename implements the (Cytron et al) SSA renaming algorithm, a
+// preorder traversal of the dominator tree replacing all loads of
+// Alloc cells with the value stored to that cell by the dominating
+// store instruction.  For lifting, we need only consider loads,
+// stores and φ-nodes.
+//
+// renaming is a map from *Alloc (keyed by index number) to its
+// dominating stored value; newPhis[x] is the set of new φ-nodes to be
+// prepended to block x.
+//
+func rename(u *BasicBlock, renaming []Value, newPhis newPhiMap) {
+	// Each φ-node becomes the new name for its associated Alloc.
+	for _, np := range newPhis[u] {
+		phi := np.phi
+		alloc := np.alloc
+		renaming[alloc.index] = phi
+	}
+
+	// Rename loads and stores of allocs.
+	for i, instr := range u.Instrs {
+		switch instr := instr.(type) {
+		case *Alloc:
+			if instr.index >= 0 { // store of zero to Alloc cell
+				// Replace dominated loads by the zero value.
+				renaming[instr.index] = nil
+				if debugLifting {
+					fmt.Fprintf(os.Stderr, "\tkill alloc %s\n", instr)
+				}
+				// Delete the Alloc.
+				u.Instrs[i] = nil
+				u.gaps++
+			}
+
+		case *Store:
+			if alloc, ok := instr.Addr.(*Alloc); ok && alloc.index >= 0 { // store to Alloc cell
+				// Replace dominated loads by the stored value.
+				renaming[alloc.index] = instr.Val
+				if debugLifting {
+					fmt.Fprintf(os.Stderr, "\tkill store %s; new value: %s\n",
+						instr, instr.Val.Name())
+				}
+				// Remove the store from the referrer list of the stored value.
+				if refs := instr.Val.Referrers(); refs != nil {
+					*refs = removeInstr(*refs, instr)
+				}
+				// Delete the Store.
+				u.Instrs[i] = nil
+				u.gaps++
+			}
+
+		case *UnOp:
+			if instr.Op == token.MUL {
+				if alloc, ok := instr.X.(*Alloc); ok && alloc.index >= 0 { // load of Alloc cell
+					newval := renamed(renaming, alloc)
+					if debugLifting {
+						fmt.Fprintf(os.Stderr, "\tupdate load %s = %s with %s\n",
+							instr.Name(), instr, newval.Name())
+					}
+					// Replace all references to
+					// the loaded value by the
+					// dominating stored value.
+					replaceAll(instr, newval)
+					// Delete the Load.
+					u.Instrs[i] = nil
+					u.gaps++
+				}
+			}
+
+		case *DebugRef:
+			if alloc, ok := instr.X.(*Alloc); ok && alloc.index >= 0 { // ref of Alloc cell
+				if instr.IsAddr {
+					instr.X = renamed(renaming, alloc)
+					instr.IsAddr = false
+
+					// Add DebugRef to instr.X's referrers.
+					if refs := instr.X.Referrers(); refs != nil {
+						*refs = append(*refs, instr)
+					}
+				} else {
+					// A source expression denotes the address
+					// of an Alloc that was optimized away.
+					instr.X = nil
+
+					// Delete the DebugRef.
+					u.Instrs[i] = nil
+					u.gaps++
+				}
+			}
+		}
+	}
+
+	// For each φ-node in a CFG successor, rename the edge.
+	for _, v := range u.Succs {
+		phis := newPhis[v]
+		if len(phis) == 0 {
+			continue
+		}
+		i := v.predIndex(u)
+		for _, np := range phis {
+			phi := np.phi
+			alloc := np.alloc
+			newval := renamed(renaming, alloc)
+			if debugLifting {
+				fmt.Fprintf(os.Stderr, "\tsetphi %s edge %s -> %s (#%d) (alloc=%s) := %s\n",
+					phi.Name(), u, v, i, alloc.Name(), newval.Name())
+			}
+			phi.Edges[i] = newval
+			if prefs := newval.Referrers(); prefs != nil {
+				*prefs = append(*prefs, phi)
+			}
+		}
+	}
+
+	// Continue depth-first recursion over domtree, pushing a
+	// fresh copy of the renaming map for each subtree.
+	for _, v := range u.dom.children {
+		// TODO(adonovan): opt: avoid copy on final iteration; use destructive update.
+		r := make([]Value, len(renaming))
+		copy(r, renaming)
+		rename(v, r, newPhis)
+	}
+}
diff --git a/go/src/golang.org/x/tools/go/ssa/lvalue.go b/go/src/golang.org/x/tools/go/ssa/lvalue.go
index 4284b1c..85e090f 100644
--- a/go/src/golang.org/x/tools/go/ssa/lvalue.go
+++ b/go/src/golang.org/x/tools/go/ssa/lvalue.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package ssa
 
 // lvalues are the union of addressable expressions and map-index
@@ -10,8 +12,7 @@
 import (
 	"go/ast"
 	"go/token"
-
-	"golang.org/x/tools/go/types"
+	"go/types"
 )
 
 // An lvalue represents an assignable location that may appear on the
diff --git a/go/src/golang.org/x/tools/go/ssa/lvalue14.go b/go/src/golang.org/x/tools/go/ssa/lvalue14.go
new file mode 100644
index 0000000..597761b
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/ssa/lvalue14.go
@@ -0,0 +1,123 @@
+// 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.
+
+// +build !go1.5
+
+package ssa
+
+// lvalues are the union of addressable expressions and map-index
+// expressions.
+
+import (
+	"go/ast"
+	"go/token"
+
+	"golang.org/x/tools/go/types"
+)
+
+// An lvalue represents an assignable location that may appear on the
+// left-hand side of an assignment.  This is a generalization of a
+// pointer to permit updates to elements of maps.
+//
+type lvalue interface {
+	store(fn *Function, v Value) // stores v into the location
+	load(fn *Function) Value     // loads the contents of the location
+	address(fn *Function) Value  // address of the location
+	typ() types.Type             // returns the type of the location
+}
+
+// An address is an lvalue represented by a true pointer.
+type address struct {
+	addr Value
+	pos  token.Pos // source position
+	expr ast.Expr  // source syntax of the value (not address) [debug mode]
+}
+
+func (a *address) load(fn *Function) Value {
+	load := emitLoad(fn, a.addr)
+	load.pos = a.pos
+	return load
+}
+
+func (a *address) store(fn *Function, v Value) {
+	store := emitStore(fn, a.addr, v, a.pos)
+	if a.expr != nil {
+		// store.Val is v, converted for assignability.
+		emitDebugRef(fn, a.expr, store.Val, false)
+	}
+}
+
+func (a *address) address(fn *Function) Value {
+	if a.expr != nil {
+		emitDebugRef(fn, a.expr, a.addr, true)
+	}
+	return a.addr
+}
+
+func (a *address) typ() types.Type {
+	return deref(a.addr.Type())
+}
+
+// An element is an lvalue represented by m[k], the location of an
+// element of a map or string.  These locations are not addressable
+// since pointers cannot be formed from them, but they do support
+// load(), and in the case of maps, store().
+//
+type element struct {
+	m, k Value      // map or string
+	t    types.Type // map element type or string byte type
+	pos  token.Pos  // source position of colon ({k:v}) or lbrack (m[k]=v)
+}
+
+func (e *element) load(fn *Function) Value {
+	l := &Lookup{
+		X:     e.m,
+		Index: e.k,
+	}
+	l.setPos(e.pos)
+	l.setType(e.t)
+	return fn.emit(l)
+}
+
+func (e *element) store(fn *Function, v Value) {
+	up := &MapUpdate{
+		Map:   e.m,
+		Key:   e.k,
+		Value: emitConv(fn, v, e.t),
+	}
+	up.pos = e.pos
+	fn.emit(up)
+}
+
+func (e *element) address(fn *Function) Value {
+	panic("map/string elements are not addressable")
+}
+
+func (e *element) typ() types.Type {
+	return e.t
+}
+
+// A blank is a dummy variable whose name is "_".
+// It is not reified: loads are illegal and stores are ignored.
+//
+type blank struct{}
+
+func (bl blank) load(fn *Function) Value {
+	panic("blank.load is illegal")
+}
+
+func (bl blank) store(fn *Function, v Value) {
+	// no-op
+}
+
+func (bl blank) address(fn *Function) Value {
+	panic("blank var is not addressable")
+}
+
+func (bl blank) typ() types.Type {
+	// This should be the type of the blank Ident; the typechecker
+	// doesn't provide this yet, but fortunately, we don't need it
+	// yet either.
+	panic("blank.typ is unimplemented")
+}
diff --git a/go/src/golang.org/x/tools/go/ssa/methods.go b/go/src/golang.org/x/tools/go/ssa/methods.go
index 12534de..7d1fb42 100644
--- a/go/src/golang.org/x/tools/go/ssa/methods.go
+++ b/go/src/golang.org/x/tools/go/ssa/methods.go
@@ -2,30 +2,28 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package ssa
 
 // This file defines utilities for population of method sets.
 
 import (
 	"fmt"
-
-	"golang.org/x/tools/go/types"
+	"go/types"
 )
 
-// Method returns the Function implementing method sel, building
+// MethodValue returns the Function implementing method sel, building
 // wrapper methods on demand.  It returns nil if sel denotes an
 // abstract (interface) method.
 //
 // Precondition: sel.Kind() == MethodVal.
 //
-// TODO(adonovan): rename this to MethodValue because of the
-// precondition, and for consistency with functions in source.go.
-//
 // Thread-safe.
 //
 // EXCLUSIVE_LOCKS_ACQUIRED(prog.methodsMu)
 //
-func (prog *Program) Method(sel *types.Selection) *Function {
+func (prog *Program) MethodValue(sel *types.Selection) *Function {
 	if sel.Kind() != types.MethodVal {
 		panic(fmt.Sprintf("Method(%s) kind != MethodVal", sel))
 	}
@@ -52,7 +50,7 @@
 	if sel == nil {
 		panic(fmt.Sprintf("%s has no method %s", T, types.Id(pkg, name)))
 	}
-	return prog.Method(sel)
+	return prog.MethodValue(sel)
 }
 
 // methodSet contains the (concrete) methods of a non-interface type.
diff --git a/go/src/golang.org/x/tools/go/ssa/methods14.go b/go/src/golang.org/x/tools/go/ssa/methods14.go
new file mode 100644
index 0000000..7c2a40d
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/ssa/methods14.go
@@ -0,0 +1,242 @@
+// 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.
+
+// +build !go1.5
+
+package ssa
+
+// This file defines utilities for population of method sets.
+
+import (
+	"fmt"
+
+	"golang.org/x/tools/go/types"
+)
+
+// MethodValue returns the Function implementing method sel, building
+// wrapper methods on demand.  It returns nil if sel denotes an
+// abstract (interface) method.
+//
+// Precondition: sel.Kind() == MethodVal.
+//
+// Thread-safe.
+//
+// EXCLUSIVE_LOCKS_ACQUIRED(prog.methodsMu)
+//
+func (prog *Program) MethodValue(sel *types.Selection) *Function {
+	if sel.Kind() != types.MethodVal {
+		panic(fmt.Sprintf("Method(%s) kind != MethodVal", sel))
+	}
+	T := sel.Recv()
+	if isInterface(T) {
+		return nil // abstract method
+	}
+	if prog.mode&LogSource != 0 {
+		defer logStack("Method %s %v", T, sel)()
+	}
+
+	prog.methodsMu.Lock()
+	defer prog.methodsMu.Unlock()
+
+	return prog.addMethod(prog.createMethodSet(T), sel)
+}
+
+// LookupMethod returns the implementation of the method of type T
+// identified by (pkg, name).  It returns nil if the method exists but
+// is abstract, and panics if T has no such method.
+//
+func (prog *Program) LookupMethod(T types.Type, pkg *types.Package, name string) *Function {
+	sel := prog.MethodSets.MethodSet(T).Lookup(pkg, name)
+	if sel == nil {
+		panic(fmt.Sprintf("%s has no method %s", T, types.Id(pkg, name)))
+	}
+	return prog.MethodValue(sel)
+}
+
+// methodSet contains the (concrete) methods of a non-interface type.
+type methodSet struct {
+	mapping  map[string]*Function // populated lazily
+	complete bool                 // mapping contains all methods
+}
+
+// Precondition: !isInterface(T).
+// EXCLUSIVE_LOCKS_REQUIRED(prog.methodsMu)
+func (prog *Program) createMethodSet(T types.Type) *methodSet {
+	mset, ok := prog.methodSets.At(T).(*methodSet)
+	if !ok {
+		mset = &methodSet{mapping: make(map[string]*Function)}
+		prog.methodSets.Set(T, mset)
+	}
+	return mset
+}
+
+// EXCLUSIVE_LOCKS_REQUIRED(prog.methodsMu)
+func (prog *Program) addMethod(mset *methodSet, sel *types.Selection) *Function {
+	if sel.Kind() == types.MethodExpr {
+		panic(sel)
+	}
+	id := sel.Obj().Id()
+	fn := mset.mapping[id]
+	if fn == nil {
+		obj := sel.Obj().(*types.Func)
+
+		needsPromotion := len(sel.Index()) > 1
+		needsIndirection := !isPointer(recvType(obj)) && isPointer(sel.Recv())
+		if needsPromotion || needsIndirection {
+			fn = makeWrapper(prog, sel)
+		} else {
+			fn = prog.declaredFunc(obj)
+		}
+		if fn.Signature.Recv() == nil {
+			panic(fn) // missing receiver
+		}
+		mset.mapping[id] = fn
+	}
+	return fn
+}
+
+// RuntimeTypes returns a new unordered slice containing all
+// concrete types in the program for which a complete (non-empty)
+// method set is required at run-time.
+//
+// Thread-safe.
+//
+// EXCLUSIVE_LOCKS_ACQUIRED(prog.methodsMu)
+//
+func (prog *Program) RuntimeTypes() []types.Type {
+	prog.methodsMu.Lock()
+	defer prog.methodsMu.Unlock()
+
+	var res []types.Type
+	prog.methodSets.Iterate(func(T types.Type, v interface{}) {
+		if v.(*methodSet).complete {
+			res = append(res, T)
+		}
+	})
+	return res
+}
+
+// declaredFunc returns the concrete function/method denoted by obj.
+// Panic ensues if there is none.
+//
+func (prog *Program) declaredFunc(obj *types.Func) *Function {
+	if v := prog.packageLevelValue(obj); v != nil {
+		return v.(*Function)
+	}
+	panic("no concrete method: " + obj.String())
+}
+
+// needMethodsOf ensures that runtime type information (including the
+// complete method set) is available for the specified type T and all
+// its subcomponents.
+//
+// needMethodsOf must be called for at least every type that is an
+// operand of some MakeInterface instruction, and for the type of
+// every exported package member.
+//
+// Precondition: T is not a method signature (*Signature with Recv()!=nil).
+//
+// Thread-safe.  (Called via emitConv from multiple builder goroutines.)
+//
+// TODO(adonovan): make this faster.  It accounts for 20% of SSA build time.
+//
+// EXCLUSIVE_LOCKS_ACQUIRED(prog.methodsMu)
+//
+func (prog *Program) needMethodsOf(T types.Type) {
+	prog.methodsMu.Lock()
+	prog.needMethods(T, false)
+	prog.methodsMu.Unlock()
+}
+
+// Precondition: T is not a method signature (*Signature with Recv()!=nil).
+// Recursive case: skip => don't create methods for T.
+//
+// EXCLUSIVE_LOCKS_REQUIRED(prog.methodsMu)
+//
+func (prog *Program) needMethods(T types.Type, skip bool) {
+	// Each package maintains its own set of types it has visited.
+	if prevSkip, ok := prog.runtimeTypes.At(T).(bool); ok {
+		// needMethods(T) was previously called
+		if !prevSkip || skip {
+			return // already seen, with same or false 'skip' value
+		}
+	}
+	prog.runtimeTypes.Set(T, skip)
+
+	tmset := prog.MethodSets.MethodSet(T)
+
+	if !skip && !isInterface(T) && tmset.Len() > 0 {
+		// Create methods of T.
+		mset := prog.createMethodSet(T)
+		if !mset.complete {
+			mset.complete = true
+			n := tmset.Len()
+			for i := 0; i < n; i++ {
+				prog.addMethod(mset, tmset.At(i))
+			}
+		}
+	}
+
+	// Recursion over signatures of each method.
+	for i := 0; i < tmset.Len(); i++ {
+		sig := tmset.At(i).Type().(*types.Signature)
+		prog.needMethods(sig.Params(), false)
+		prog.needMethods(sig.Results(), false)
+	}
+
+	switch t := T.(type) {
+	case *types.Basic:
+		// nop
+
+	case *types.Interface:
+		// nop---handled by recursion over method set.
+
+	case *types.Pointer:
+		prog.needMethods(t.Elem(), false)
+
+	case *types.Slice:
+		prog.needMethods(t.Elem(), false)
+
+	case *types.Chan:
+		prog.needMethods(t.Elem(), false)
+
+	case *types.Map:
+		prog.needMethods(t.Key(), false)
+		prog.needMethods(t.Elem(), false)
+
+	case *types.Signature:
+		if t.Recv() != nil {
+			panic(fmt.Sprintf("Signature %s has Recv %s", t, t.Recv()))
+		}
+		prog.needMethods(t.Params(), false)
+		prog.needMethods(t.Results(), false)
+
+	case *types.Named:
+		// A pointer-to-named type can be derived from a named
+		// type via reflection.  It may have methods too.
+		prog.needMethods(types.NewPointer(T), false)
+
+		// Consider 'type T struct{S}' where S has methods.
+		// Reflection provides no way to get from T to struct{S},
+		// only to S, so the method set of struct{S} is unwanted,
+		// so set 'skip' flag during recursion.
+		prog.needMethods(t.Underlying(), true)
+
+	case *types.Array:
+		prog.needMethods(t.Elem(), false)
+
+	case *types.Struct:
+		for i, n := 0, t.NumFields(); i < n; i++ {
+			prog.needMethods(t.Field(i).Type(), false)
+		}
+
+	case *types.Tuple:
+		for i, n := 0, t.Len(); i < n; i++ {
+			prog.needMethods(t.At(i).Type(), false)
+		}
+
+	default:
+		panic(T)
+	}
+}
diff --git a/go/src/golang.org/x/tools/go/ssa/print.go b/go/src/golang.org/x/tools/go/ssa/print.go
index 88c31f6..55c9266 100644
--- a/go/src/golang.org/x/tools/go/ssa/print.go
+++ b/go/src/golang.org/x/tools/go/ssa/print.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package ssa
 
 // This file implements the String() methods for all Value and
@@ -10,11 +12,11 @@
 import (
 	"bytes"
 	"fmt"
+	"go/types"
 	"io"
 	"reflect"
 	"sort"
 
-	"golang.org/x/tools/go/types"
 	"golang.org/x/tools/go/types/typeutil"
 )
 
@@ -27,7 +29,7 @@
 func relName(v Value, i Instruction) string {
 	var from *types.Package
 	if i != nil {
-		from = i.Parent().pkgobj()
+		from = i.Parent().pkg()
 	}
 	switch v := v.(type) {
 	case Member: // *Function or *Global
@@ -45,8 +47,8 @@
 func relString(m Member, from *types.Package) string {
 	// NB: not all globals have an Object (e.g. init$guard),
 	// so use Package().Object not Object.Package().
-	if obj := m.Package().Object; obj != nil && obj != from {
-		return fmt.Sprintf("%s.%s", obj.Path(), m.Name())
+	if pkg := m.Package().Pkg; pkg != nil && pkg != from {
+		return fmt.Sprintf("%s.%s", pkg.Path(), m.Name())
 	}
 	return m.Name()
 }
@@ -57,12 +59,12 @@
 // It never appears in disassembly, which uses Value.Name().
 
 func (v *Parameter) String() string {
-	from := v.Parent().pkgobj()
+	from := v.Parent().pkg()
 	return fmt.Sprintf("parameter %s : %s", v.Name(), relType(v.Type(), from))
 }
 
 func (v *FreeVar) String() string {
-	from := v.Parent().pkgobj()
+	from := v.Parent().pkg()
 	return fmt.Sprintf("freevar %s : %s", v.Name(), relType(v.Type(), from))
 }
 
@@ -77,7 +79,7 @@
 	if v.Heap {
 		op = "new"
 	}
-	from := v.Parent().pkgobj()
+	from := v.Parent().pkg()
 	return fmt.Sprintf("%s %s (%s)", op, relType(deref(v.Type()), from), v.Comment)
 }
 
@@ -147,7 +149,7 @@
 }
 
 func printConv(prefix string, v, x Value) string {
-	from := v.Parent().pkgobj()
+	from := v.Parent().pkg()
 	return fmt.Sprintf("%s %s <- %s (%s)",
 		prefix,
 		relType(v.Type(), from),
@@ -177,7 +179,7 @@
 }
 
 func (v *MakeSlice) String() string {
-	from := v.Parent().pkgobj()
+	from := v.Parent().pkg()
 	return fmt.Sprintf("make %s %s %s",
 		relType(v.Type(), from),
 		relName(v.Len, v),
@@ -209,12 +211,12 @@
 	if v.Reserve != nil {
 		res = relName(v.Reserve, v)
 	}
-	from := v.Parent().pkgobj()
+	from := v.Parent().pkg()
 	return fmt.Sprintf("make %s %s", relType(v.Type(), from), res)
 }
 
 func (v *MakeChan) String() string {
-	from := v.Parent().pkgobj()
+	from := v.Parent().pkg()
 	return fmt.Sprintf("make %s %s", relType(v.Type(), from), relName(v.Size, v))
 }
 
@@ -259,7 +261,7 @@
 }
 
 func (v *TypeAssert) String() string {
-	from := v.Parent().pkgobj()
+	from := v.Parent().pkg()
 	return fmt.Sprintf("typeassert%s %s.(%s)", commaOk(v.CommaOk), relName(v.X, v), relType(v.AssertedType, from))
 }
 
@@ -366,7 +368,7 @@
 }
 
 func (p *Package) String() string {
-	return "package " + p.Object.Path()
+	return "package " + p.Pkg.Path()
 }
 
 var _ io.WriterTo = (*Package)(nil) // *Package implements io.Writer
@@ -391,7 +393,7 @@
 		names = append(names, name)
 	}
 
-	from := p.Object
+	from := p.Pkg
 	sort.Strings(names)
 	for _, name := range names {
 		switch mem := p.Members[name].(type) {
diff --git a/go/src/golang.org/x/tools/go/ssa/print14.go b/go/src/golang.org/x/tools/go/ssa/print14.go
new file mode 100644
index 0000000..155d5ec
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/ssa/print14.go
@@ -0,0 +1,429 @@
+// 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.
+
+// +build !go1.5
+
+package ssa
+
+// This file implements the String() methods for all Value and
+// Instruction types.
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"reflect"
+	"sort"
+
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/go/types/typeutil"
+)
+
+// relName returns the name of v relative to i.
+// In most cases, this is identical to v.Name(), but references to
+// Functions (including methods) and Globals use RelString and
+// all types are displayed with relType, so that only cross-package
+// references are package-qualified.
+//
+func relName(v Value, i Instruction) string {
+	var from *types.Package
+	if i != nil {
+		from = i.Parent().pkg()
+	}
+	switch v := v.(type) {
+	case Member: // *Function or *Global
+		return v.RelString(from)
+	case *Const:
+		return v.RelString(from)
+	}
+	return v.Name()
+}
+
+func relType(t types.Type, from *types.Package) string {
+	return types.TypeString(t, types.RelativeTo(from))
+}
+
+func relString(m Member, from *types.Package) string {
+	// NB: not all globals have an Object (e.g. init$guard),
+	// so use Package().Object not Object.Package().
+	if pkg := m.Package().Pkg; pkg != nil && pkg != from {
+		return fmt.Sprintf("%s.%s", pkg.Path(), m.Name())
+	}
+	return m.Name()
+}
+
+// Value.String()
+//
+// This method is provided only for debugging.
+// It never appears in disassembly, which uses Value.Name().
+
+func (v *Parameter) String() string {
+	from := v.Parent().pkg()
+	return fmt.Sprintf("parameter %s : %s", v.Name(), relType(v.Type(), from))
+}
+
+func (v *FreeVar) String() string {
+	from := v.Parent().pkg()
+	return fmt.Sprintf("freevar %s : %s", v.Name(), relType(v.Type(), from))
+}
+
+func (v *Builtin) String() string {
+	return fmt.Sprintf("builtin %s", v.Name())
+}
+
+// Instruction.String()
+
+func (v *Alloc) String() string {
+	op := "local"
+	if v.Heap {
+		op = "new"
+	}
+	from := v.Parent().pkg()
+	return fmt.Sprintf("%s %s (%s)", op, relType(deref(v.Type()), from), v.Comment)
+}
+
+func (v *Phi) String() string {
+	var b bytes.Buffer
+	b.WriteString("phi [")
+	for i, edge := range v.Edges {
+		if i > 0 {
+			b.WriteString(", ")
+		}
+		// Be robust against malformed CFG.
+		block := -1
+		if v.block != nil && i < len(v.block.Preds) {
+			block = v.block.Preds[i].Index
+		}
+		fmt.Fprintf(&b, "%d: ", block)
+		edgeVal := "<nil>" // be robust
+		if edge != nil {
+			edgeVal = relName(edge, v)
+		}
+		b.WriteString(edgeVal)
+	}
+	b.WriteString("]")
+	if v.Comment != "" {
+		b.WriteString(" #")
+		b.WriteString(v.Comment)
+	}
+	return b.String()
+}
+
+func printCall(v *CallCommon, prefix string, instr Instruction) string {
+	var b bytes.Buffer
+	b.WriteString(prefix)
+	if !v.IsInvoke() {
+		b.WriteString(relName(v.Value, instr))
+	} else {
+		fmt.Fprintf(&b, "invoke %s.%s", relName(v.Value, instr), v.Method.Name())
+	}
+	b.WriteString("(")
+	for i, arg := range v.Args {
+		if i > 0 {
+			b.WriteString(", ")
+		}
+		b.WriteString(relName(arg, instr))
+	}
+	if v.Signature().Variadic() {
+		b.WriteString("...")
+	}
+	b.WriteString(")")
+	return b.String()
+}
+
+func (c *CallCommon) String() string {
+	return printCall(c, "", nil)
+}
+
+func (v *Call) String() string {
+	return printCall(&v.Call, "", v)
+}
+
+func (v *BinOp) String() string {
+	return fmt.Sprintf("%s %s %s", relName(v.X, v), v.Op.String(), relName(v.Y, v))
+}
+
+func (v *UnOp) String() string {
+	return fmt.Sprintf("%s%s%s", v.Op, relName(v.X, v), commaOk(v.CommaOk))
+}
+
+func printConv(prefix string, v, x Value) string {
+	from := v.Parent().pkg()
+	return fmt.Sprintf("%s %s <- %s (%s)",
+		prefix,
+		relType(v.Type(), from),
+		relType(x.Type(), from),
+		relName(x, v.(Instruction)))
+}
+
+func (v *ChangeType) String() string      { return printConv("changetype", v, v.X) }
+func (v *Convert) String() string         { return printConv("convert", v, v.X) }
+func (v *ChangeInterface) String() string { return printConv("change interface", v, v.X) }
+func (v *MakeInterface) String() string   { return printConv("make", v, v.X) }
+
+func (v *MakeClosure) String() string {
+	var b bytes.Buffer
+	fmt.Fprintf(&b, "make closure %s", relName(v.Fn, v))
+	if v.Bindings != nil {
+		b.WriteString(" [")
+		for i, c := range v.Bindings {
+			if i > 0 {
+				b.WriteString(", ")
+			}
+			b.WriteString(relName(c, v))
+		}
+		b.WriteString("]")
+	}
+	return b.String()
+}
+
+func (v *MakeSlice) String() string {
+	from := v.Parent().pkg()
+	return fmt.Sprintf("make %s %s %s",
+		relType(v.Type(), from),
+		relName(v.Len, v),
+		relName(v.Cap, v))
+}
+
+func (v *Slice) String() string {
+	var b bytes.Buffer
+	b.WriteString("slice ")
+	b.WriteString(relName(v.X, v))
+	b.WriteString("[")
+	if v.Low != nil {
+		b.WriteString(relName(v.Low, v))
+	}
+	b.WriteString(":")
+	if v.High != nil {
+		b.WriteString(relName(v.High, v))
+	}
+	if v.Max != nil {
+		b.WriteString(":")
+		b.WriteString(relName(v.Max, v))
+	}
+	b.WriteString("]")
+	return b.String()
+}
+
+func (v *MakeMap) String() string {
+	res := ""
+	if v.Reserve != nil {
+		res = relName(v.Reserve, v)
+	}
+	from := v.Parent().pkg()
+	return fmt.Sprintf("make %s %s", relType(v.Type(), from), res)
+}
+
+func (v *MakeChan) String() string {
+	from := v.Parent().pkg()
+	return fmt.Sprintf("make %s %s", relType(v.Type(), from), relName(v.Size, v))
+}
+
+func (v *FieldAddr) String() string {
+	st := deref(v.X.Type()).Underlying().(*types.Struct)
+	// Be robust against a bad index.
+	name := "?"
+	if 0 <= v.Field && v.Field < st.NumFields() {
+		name = st.Field(v.Field).Name()
+	}
+	return fmt.Sprintf("&%s.%s [#%d]", relName(v.X, v), name, v.Field)
+}
+
+func (v *Field) String() string {
+	st := v.X.Type().Underlying().(*types.Struct)
+	// Be robust against a bad index.
+	name := "?"
+	if 0 <= v.Field && v.Field < st.NumFields() {
+		name = st.Field(v.Field).Name()
+	}
+	return fmt.Sprintf("%s.%s [#%d]", relName(v.X, v), name, v.Field)
+}
+
+func (v *IndexAddr) String() string {
+	return fmt.Sprintf("&%s[%s]", relName(v.X, v), relName(v.Index, v))
+}
+
+func (v *Index) String() string {
+	return fmt.Sprintf("%s[%s]", relName(v.X, v), relName(v.Index, v))
+}
+
+func (v *Lookup) String() string {
+	return fmt.Sprintf("%s[%s]%s", relName(v.X, v), relName(v.Index, v), commaOk(v.CommaOk))
+}
+
+func (v *Range) String() string {
+	return "range " + relName(v.X, v)
+}
+
+func (v *Next) String() string {
+	return "next " + relName(v.Iter, v)
+}
+
+func (v *TypeAssert) String() string {
+	from := v.Parent().pkg()
+	return fmt.Sprintf("typeassert%s %s.(%s)", commaOk(v.CommaOk), relName(v.X, v), relType(v.AssertedType, from))
+}
+
+func (v *Extract) String() string {
+	return fmt.Sprintf("extract %s #%d", relName(v.Tuple, v), v.Index)
+}
+
+func (s *Jump) String() string {
+	// Be robust against malformed CFG.
+	block := -1
+	if s.block != nil && len(s.block.Succs) == 1 {
+		block = s.block.Succs[0].Index
+	}
+	return fmt.Sprintf("jump %d", block)
+}
+
+func (s *If) String() string {
+	// Be robust against malformed CFG.
+	tblock, fblock := -1, -1
+	if s.block != nil && len(s.block.Succs) == 2 {
+		tblock = s.block.Succs[0].Index
+		fblock = s.block.Succs[1].Index
+	}
+	return fmt.Sprintf("if %s goto %d else %d", relName(s.Cond, s), tblock, fblock)
+}
+
+func (s *Go) String() string {
+	return printCall(&s.Call, "go ", s)
+}
+
+func (s *Panic) String() string {
+	return "panic " + relName(s.X, s)
+}
+
+func (s *Return) String() string {
+	var b bytes.Buffer
+	b.WriteString("return")
+	for i, r := range s.Results {
+		if i == 0 {
+			b.WriteString(" ")
+		} else {
+			b.WriteString(", ")
+		}
+		b.WriteString(relName(r, s))
+	}
+	return b.String()
+}
+
+func (*RunDefers) String() string {
+	return "rundefers"
+}
+
+func (s *Send) String() string {
+	return fmt.Sprintf("send %s <- %s", relName(s.Chan, s), relName(s.X, s))
+}
+
+func (s *Defer) String() string {
+	return printCall(&s.Call, "defer ", s)
+}
+
+func (s *Select) String() string {
+	var b bytes.Buffer
+	for i, st := range s.States {
+		if i > 0 {
+			b.WriteString(", ")
+		}
+		if st.Dir == types.RecvOnly {
+			b.WriteString("<-")
+			b.WriteString(relName(st.Chan, s))
+		} else {
+			b.WriteString(relName(st.Chan, s))
+			b.WriteString("<-")
+			b.WriteString(relName(st.Send, s))
+		}
+	}
+	non := ""
+	if !s.Blocking {
+		non = "non"
+	}
+	return fmt.Sprintf("select %sblocking [%s]", non, b.String())
+}
+
+func (s *Store) String() string {
+	return fmt.Sprintf("*%s = %s", relName(s.Addr, s), relName(s.Val, s))
+}
+
+func (s *MapUpdate) String() string {
+	return fmt.Sprintf("%s[%s] = %s", relName(s.Map, s), relName(s.Key, s), relName(s.Value, s))
+}
+
+func (s *DebugRef) String() string {
+	p := s.Parent().Prog.Fset.Position(s.Pos())
+	var descr interface{}
+	if s.object != nil {
+		descr = s.object // e.g. "var x int"
+	} else {
+		descr = reflect.TypeOf(s.Expr) // e.g. "*ast.CallExpr"
+	}
+	var addr string
+	if s.IsAddr {
+		addr = "address of "
+	}
+	return fmt.Sprintf("; %s%s @ %d:%d is %s", addr, descr, p.Line, p.Column, s.X.Name())
+}
+
+func (p *Package) String() string {
+	return "package " + p.Pkg.Path()
+}
+
+var _ io.WriterTo = (*Package)(nil) // *Package implements io.Writer
+
+func (p *Package) WriteTo(w io.Writer) (int64, error) {
+	var buf bytes.Buffer
+	WritePackage(&buf, p)
+	n, err := w.Write(buf.Bytes())
+	return int64(n), err
+}
+
+// WritePackage writes to buf a human-readable summary of p.
+func WritePackage(buf *bytes.Buffer, p *Package) {
+	fmt.Fprintf(buf, "%s:\n", p)
+
+	var names []string
+	maxname := 0
+	for name := range p.Members {
+		if l := len(name); l > maxname {
+			maxname = l
+		}
+		names = append(names, name)
+	}
+
+	from := p.Pkg
+	sort.Strings(names)
+	for _, name := range names {
+		switch mem := p.Members[name].(type) {
+		case *NamedConst:
+			fmt.Fprintf(buf, "  const %-*s %s = %s\n",
+				maxname, name, mem.Name(), mem.Value.RelString(from))
+
+		case *Function:
+			fmt.Fprintf(buf, "  func  %-*s %s\n",
+				maxname, name, relType(mem.Type(), from))
+
+		case *Type:
+			fmt.Fprintf(buf, "  type  %-*s %s\n",
+				maxname, name, relType(mem.Type().Underlying(), from))
+			for _, meth := range typeutil.IntuitiveMethodSet(mem.Type(), &p.Prog.MethodSets) {
+				fmt.Fprintf(buf, "    %s\n", types.SelectionString(meth, types.RelativeTo(from)))
+			}
+
+		case *Global:
+			fmt.Fprintf(buf, "  var   %-*s %s\n",
+				maxname, name, relType(mem.Type().(*types.Pointer).Elem(), from))
+		}
+	}
+
+	fmt.Fprintf(buf, "\n")
+}
+
+func commaOk(x bool) string {
+	if x {
+		return ",ok"
+	}
+	return ""
+}
diff --git a/go/src/golang.org/x/tools/go/ssa/sanity.go b/go/src/golang.org/x/tools/go/ssa/sanity.go
index b0593d0..4babb37 100644
--- a/go/src/golang.org/x/tools/go/ssa/sanity.go
+++ b/go/src/golang.org/x/tools/go/ssa/sanity.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package ssa
 
 // An optional pass for sanity-checking invariants of the SSA representation.
@@ -9,11 +11,10 @@
 
 import (
 	"fmt"
+	"go/types"
 	"io"
 	"os"
 	"strings"
-
-	"golang.org/x/tools/go/types"
 )
 
 type sanity struct {
@@ -407,8 +408,8 @@
 		s.errorf("nil Prog")
 	}
 
-	fn.String()               // must not crash
-	fn.RelString(fn.pkgobj()) // must not crash
+	fn.String()            // must not crash
+	fn.RelString(fn.pkg()) // must not crash
 
 	// All functions have a package, except delegates (which are
 	// shared across packages, or duplicated as weak symbols in a
@@ -484,7 +485,7 @@
 // It does not require that the package is built.
 // Unlike sanityCheck (for functions), it just panics at the first error.
 func sanityCheckPackage(pkg *Package) {
-	if pkg.Object == nil {
+	if pkg.Pkg == nil {
 		panic(fmt.Sprintf("Package %s has no Object", pkg))
 	}
 	pkg.String() // must not crash
@@ -492,7 +493,7 @@
 	for name, mem := range pkg.Members {
 		if name != mem.Name() {
 			panic(fmt.Sprintf("%s: %T.Name() = %s, want %s",
-				pkg.Object.Path(), mem, mem.Name(), name))
+				pkg.Pkg.Path(), mem, mem.Name(), name))
 		}
 		obj := mem.Object()
 		if obj == nil {
@@ -510,7 +511,7 @@
 				// its types.Func ("init") and its ssa.Function ("init#%d").
 			} else {
 				panic(fmt.Sprintf("%s: %T.Object().Name() = %s, want %s",
-					pkg.Object.Path(), mem, obj.Name(), name))
+					pkg.Pkg.Path(), mem, obj.Name(), name))
 			}
 		}
 		if obj.Pos() != mem.Pos() {
diff --git a/go/src/golang.org/x/tools/go/ssa/sanity14.go b/go/src/golang.org/x/tools/go/ssa/sanity14.go
new file mode 100644
index 0000000..fe4d4ed
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/ssa/sanity14.go
@@ -0,0 +1,522 @@
+// 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.
+
+// +build !go1.5
+
+package ssa
+
+// An optional pass for sanity-checking invariants of the SSA representation.
+// Currently it checks CFG invariants but little at the instruction level.
+
+import (
+	"fmt"
+	"io"
+	"os"
+	"strings"
+
+	"golang.org/x/tools/go/types"
+)
+
+type sanity struct {
+	reporter io.Writer
+	fn       *Function
+	block    *BasicBlock
+	instrs   map[Instruction]struct{}
+	insane   bool
+}
+
+// sanityCheck performs integrity checking of the SSA representation
+// of the function fn and returns true if it was valid.  Diagnostics
+// are written to reporter if non-nil, os.Stderr otherwise.  Some
+// diagnostics are only warnings and do not imply a negative result.
+//
+// Sanity-checking is intended to facilitate the debugging of code
+// transformation passes.
+//
+func sanityCheck(fn *Function, reporter io.Writer) bool {
+	if reporter == nil {
+		reporter = os.Stderr
+	}
+	return (&sanity{reporter: reporter}).checkFunction(fn)
+}
+
+// mustSanityCheck is like sanityCheck but panics instead of returning
+// a negative result.
+//
+func mustSanityCheck(fn *Function, reporter io.Writer) {
+	if !sanityCheck(fn, reporter) {
+		fn.WriteTo(os.Stderr)
+		panic("SanityCheck failed")
+	}
+}
+
+func (s *sanity) diagnostic(prefix, format string, args ...interface{}) {
+	fmt.Fprintf(s.reporter, "%s: function %s", prefix, s.fn)
+	if s.block != nil {
+		fmt.Fprintf(s.reporter, ", block %s", s.block)
+	}
+	io.WriteString(s.reporter, ": ")
+	fmt.Fprintf(s.reporter, format, args...)
+	io.WriteString(s.reporter, "\n")
+}
+
+func (s *sanity) errorf(format string, args ...interface{}) {
+	s.insane = true
+	s.diagnostic("Error", format, args...)
+}
+
+func (s *sanity) warnf(format string, args ...interface{}) {
+	s.diagnostic("Warning", format, args...)
+}
+
+// findDuplicate returns an arbitrary basic block that appeared more
+// than once in blocks, or nil if all were unique.
+func findDuplicate(blocks []*BasicBlock) *BasicBlock {
+	if len(blocks) < 2 {
+		return nil
+	}
+	if blocks[0] == blocks[1] {
+		return blocks[0]
+	}
+	// Slow path:
+	m := make(map[*BasicBlock]bool)
+	for _, b := range blocks {
+		if m[b] {
+			return b
+		}
+		m[b] = true
+	}
+	return nil
+}
+
+func (s *sanity) checkInstr(idx int, instr Instruction) {
+	switch instr := instr.(type) {
+	case *If, *Jump, *Return, *Panic:
+		s.errorf("control flow instruction not at end of block")
+	case *Phi:
+		if idx == 0 {
+			// It suffices to apply this check to just the first phi node.
+			if dup := findDuplicate(s.block.Preds); dup != nil {
+				s.errorf("phi node in block with duplicate predecessor %s", dup)
+			}
+		} else {
+			prev := s.block.Instrs[idx-1]
+			if _, ok := prev.(*Phi); !ok {
+				s.errorf("Phi instruction follows a non-Phi: %T", prev)
+			}
+		}
+		if ne, np := len(instr.Edges), len(s.block.Preds); ne != np {
+			s.errorf("phi node has %d edges but %d predecessors", ne, np)
+
+		} else {
+			for i, e := range instr.Edges {
+				if e == nil {
+					s.errorf("phi node '%s' has no value for edge #%d from %s", instr.Comment, i, s.block.Preds[i])
+				}
+			}
+		}
+
+	case *Alloc:
+		if !instr.Heap {
+			found := false
+			for _, l := range s.fn.Locals {
+				if l == instr {
+					found = true
+					break
+				}
+			}
+			if !found {
+				s.errorf("local alloc %s = %s does not appear in Function.Locals", instr.Name(), instr)
+			}
+		}
+
+	case *BinOp:
+	case *Call:
+	case *ChangeInterface:
+	case *ChangeType:
+	case *Convert:
+		if _, ok := instr.X.Type().Underlying().(*types.Basic); !ok {
+			if _, ok := instr.Type().Underlying().(*types.Basic); !ok {
+				s.errorf("convert %s -> %s: at least one type must be basic", instr.X.Type(), instr.Type())
+			}
+		}
+
+	case *Defer:
+	case *Extract:
+	case *Field:
+	case *FieldAddr:
+	case *Go:
+	case *Index:
+	case *IndexAddr:
+	case *Lookup:
+	case *MakeChan:
+	case *MakeClosure:
+		numFree := len(instr.Fn.(*Function).FreeVars)
+		numBind := len(instr.Bindings)
+		if numFree != numBind {
+			s.errorf("MakeClosure has %d Bindings for function %s with %d free vars",
+				numBind, instr.Fn, numFree)
+
+		}
+		if recv := instr.Type().(*types.Signature).Recv(); recv != nil {
+			s.errorf("MakeClosure's type includes receiver %s", recv.Type())
+		}
+
+	case *MakeInterface:
+	case *MakeMap:
+	case *MakeSlice:
+	case *MapUpdate:
+	case *Next:
+	case *Range:
+	case *RunDefers:
+	case *Select:
+	case *Send:
+	case *Slice:
+	case *Store:
+	case *TypeAssert:
+	case *UnOp:
+	case *DebugRef:
+		// TODO(adonovan): implement checks.
+	default:
+		panic(fmt.Sprintf("Unknown instruction type: %T", instr))
+	}
+
+	if call, ok := instr.(CallInstruction); ok {
+		if call.Common().Signature() == nil {
+			s.errorf("nil signature: %s", call)
+		}
+	}
+
+	// Check that value-defining instructions have valid types
+	// and a valid referrer list.
+	if v, ok := instr.(Value); ok {
+		t := v.Type()
+		if t == nil {
+			s.errorf("no type: %s = %s", v.Name(), v)
+		} else if t == tRangeIter {
+			// not a proper type; ignore.
+		} else if b, ok := t.Underlying().(*types.Basic); ok && b.Info()&types.IsUntyped != 0 {
+			s.errorf("instruction has 'untyped' result: %s = %s : %s", v.Name(), v, t)
+		}
+		s.checkReferrerList(v)
+	}
+
+	// Untyped constants are legal as instruction Operands(),
+	// for example:
+	//   _ = "foo"[0]
+	// or:
+	//   if wordsize==64 {...}
+
+	// All other non-Instruction Values can be found via their
+	// enclosing Function or Package.
+}
+
+func (s *sanity) checkFinalInstr(idx int, instr Instruction) {
+	switch instr := instr.(type) {
+	case *If:
+		if nsuccs := len(s.block.Succs); nsuccs != 2 {
+			s.errorf("If-terminated block has %d successors; expected 2", nsuccs)
+			return
+		}
+		if s.block.Succs[0] == s.block.Succs[1] {
+			s.errorf("If-instruction has same True, False target blocks: %s", s.block.Succs[0])
+			return
+		}
+
+	case *Jump:
+		if nsuccs := len(s.block.Succs); nsuccs != 1 {
+			s.errorf("Jump-terminated block has %d successors; expected 1", nsuccs)
+			return
+		}
+
+	case *Return:
+		if nsuccs := len(s.block.Succs); nsuccs != 0 {
+			s.errorf("Return-terminated block has %d successors; expected none", nsuccs)
+			return
+		}
+		if na, nf := len(instr.Results), s.fn.Signature.Results().Len(); nf != na {
+			s.errorf("%d-ary return in %d-ary function", na, nf)
+		}
+
+	case *Panic:
+		if nsuccs := len(s.block.Succs); nsuccs != 0 {
+			s.errorf("Panic-terminated block has %d successors; expected none", nsuccs)
+			return
+		}
+
+	default:
+		s.errorf("non-control flow instruction at end of block")
+	}
+}
+
+func (s *sanity) checkBlock(b *BasicBlock, index int) {
+	s.block = b
+
+	if b.Index != index {
+		s.errorf("block has incorrect Index %d", b.Index)
+	}
+	if b.parent != s.fn {
+		s.errorf("block has incorrect parent %s", b.parent)
+	}
+
+	// Check all blocks are reachable.
+	// (The entry block is always implicitly reachable,
+	// as is the Recover block, if any.)
+	if (index > 0 && b != b.parent.Recover) && len(b.Preds) == 0 {
+		s.warnf("unreachable block")
+		if b.Instrs == nil {
+			// Since this block is about to be pruned,
+			// tolerating transient problems in it
+			// simplifies other optimizations.
+			return
+		}
+	}
+
+	// Check predecessor and successor relations are dual,
+	// and that all blocks in CFG belong to same function.
+	for _, a := range b.Preds {
+		found := false
+		for _, bb := range a.Succs {
+			if bb == b {
+				found = true
+				break
+			}
+		}
+		if !found {
+			s.errorf("expected successor edge in predecessor %s; found only: %s", a, a.Succs)
+		}
+		if a.parent != s.fn {
+			s.errorf("predecessor %s belongs to different function %s", a, a.parent)
+		}
+	}
+	for _, c := range b.Succs {
+		found := false
+		for _, bb := range c.Preds {
+			if bb == b {
+				found = true
+				break
+			}
+		}
+		if !found {
+			s.errorf("expected predecessor edge in successor %s; found only: %s", c, c.Preds)
+		}
+		if c.parent != s.fn {
+			s.errorf("successor %s belongs to different function %s", c, c.parent)
+		}
+	}
+
+	// Check each instruction is sane.
+	n := len(b.Instrs)
+	if n == 0 {
+		s.errorf("basic block contains no instructions")
+	}
+	var rands [10]*Value // reuse storage
+	for j, instr := range b.Instrs {
+		if instr == nil {
+			s.errorf("nil instruction at index %d", j)
+			continue
+		}
+		if b2 := instr.Block(); b2 == nil {
+			s.errorf("nil Block() for instruction at index %d", j)
+			continue
+		} else if b2 != b {
+			s.errorf("wrong Block() (%s) for instruction at index %d ", b2, j)
+			continue
+		}
+		if j < n-1 {
+			s.checkInstr(j, instr)
+		} else {
+			s.checkFinalInstr(j, instr)
+		}
+
+		// Check Instruction.Operands.
+	operands:
+		for i, op := range instr.Operands(rands[:0]) {
+			if op == nil {
+				s.errorf("nil operand pointer %d of %s", i, instr)
+				continue
+			}
+			val := *op
+			if val == nil {
+				continue // a nil operand is ok
+			}
+
+			// Check that "untyped" types only appear on constant operands.
+			if _, ok := (*op).(*Const); !ok {
+				if basic, ok := (*op).Type().(*types.Basic); ok {
+					if basic.Info()&types.IsUntyped != 0 {
+						s.errorf("operand #%d of %s is untyped: %s", i, instr, basic)
+					}
+				}
+			}
+
+			// Check that Operands that are also Instructions belong to same function.
+			// TODO(adonovan): also check their block dominates block b.
+			if val, ok := val.(Instruction); ok {
+				if val.Parent() != s.fn {
+					s.errorf("operand %d of %s is an instruction (%s) from function %s", i, instr, val, val.Parent())
+				}
+			}
+
+			// Check that each function-local operand of
+			// instr refers back to instr.  (NB: quadratic)
+			switch val := val.(type) {
+			case *Const, *Global, *Builtin:
+				continue // not local
+			case *Function:
+				if val.parent == nil {
+					continue // only anon functions are local
+				}
+			}
+
+			// TODO(adonovan): check val.Parent() != nil <=> val.Referrers() is defined.
+
+			if refs := val.Referrers(); refs != nil {
+				for _, ref := range *refs {
+					if ref == instr {
+						continue operands
+					}
+				}
+				s.errorf("operand %d of %s (%s) does not refer to us", i, instr, val)
+			} else {
+				s.errorf("operand %d of %s (%s) has no referrers", i, instr, val)
+			}
+		}
+	}
+}
+
+func (s *sanity) checkReferrerList(v Value) {
+	refs := v.Referrers()
+	if refs == nil {
+		s.errorf("%s has missing referrer list", v.Name())
+		return
+	}
+	for i, ref := range *refs {
+		if _, ok := s.instrs[ref]; !ok {
+			s.errorf("%s.Referrers()[%d] = %s is not an instruction belonging to this function", v.Name(), i, ref)
+		}
+	}
+}
+
+func (s *sanity) checkFunction(fn *Function) bool {
+	// TODO(adonovan): check Function invariants:
+	// - check params match signature
+	// - check transient fields are nil
+	// - warn if any fn.Locals do not appear among block instructions.
+	s.fn = fn
+	if fn.Prog == nil {
+		s.errorf("nil Prog")
+	}
+
+	fn.String()            // must not crash
+	fn.RelString(fn.pkg()) // must not crash
+
+	// All functions have a package, except delegates (which are
+	// shared across packages, or duplicated as weak symbols in a
+	// separate-compilation model), and error.Error.
+	if fn.Pkg == nil {
+		if strings.HasPrefix(fn.Synthetic, "wrapper ") ||
+			strings.HasPrefix(fn.Synthetic, "bound ") ||
+			strings.HasPrefix(fn.Synthetic, "thunk ") ||
+			strings.HasSuffix(fn.name, "Error") {
+			// ok
+		} else {
+			s.errorf("nil Pkg")
+		}
+	}
+	if src, syn := fn.Synthetic == "", fn.Syntax() != nil; src != syn {
+		s.errorf("got fromSource=%t, hasSyntax=%t; want same values", src, syn)
+	}
+	for i, l := range fn.Locals {
+		if l.Parent() != fn {
+			s.errorf("Local %s at index %d has wrong parent", l.Name(), i)
+		}
+		if l.Heap {
+			s.errorf("Local %s at index %d has Heap flag set", l.Name(), i)
+		}
+	}
+	// Build the set of valid referrers.
+	s.instrs = make(map[Instruction]struct{})
+	for _, b := range fn.Blocks {
+		for _, instr := range b.Instrs {
+			s.instrs[instr] = struct{}{}
+		}
+	}
+	for i, p := range fn.Params {
+		if p.Parent() != fn {
+			s.errorf("Param %s at index %d has wrong parent", p.Name(), i)
+		}
+		s.checkReferrerList(p)
+	}
+	for i, fv := range fn.FreeVars {
+		if fv.Parent() != fn {
+			s.errorf("FreeVar %s at index %d has wrong parent", fv.Name(), i)
+		}
+		s.checkReferrerList(fv)
+	}
+
+	if fn.Blocks != nil && len(fn.Blocks) == 0 {
+		// Function _had_ blocks (so it's not external) but
+		// they were "optimized" away, even the entry block.
+		s.errorf("Blocks slice is non-nil but empty")
+	}
+	for i, b := range fn.Blocks {
+		if b == nil {
+			s.warnf("nil *BasicBlock at f.Blocks[%d]", i)
+			continue
+		}
+		s.checkBlock(b, i)
+	}
+	if fn.Recover != nil && fn.Blocks[fn.Recover.Index] != fn.Recover {
+		s.errorf("Recover block is not in Blocks slice")
+	}
+
+	s.block = nil
+	for i, anon := range fn.AnonFuncs {
+		if anon.Parent() != fn {
+			s.errorf("AnonFuncs[%d]=%s but %s.Parent()=%s", i, anon, anon, anon.Parent())
+		}
+	}
+	s.fn = nil
+	return !s.insane
+}
+
+// sanityCheckPackage checks invariants of packages upon creation.
+// It does not require that the package is built.
+// Unlike sanityCheck (for functions), it just panics at the first error.
+func sanityCheckPackage(pkg *Package) {
+	if pkg.Pkg == nil {
+		panic(fmt.Sprintf("Package %s has no Object", pkg))
+	}
+	pkg.String() // must not crash
+
+	for name, mem := range pkg.Members {
+		if name != mem.Name() {
+			panic(fmt.Sprintf("%s: %T.Name() = %s, want %s",
+				pkg.Pkg.Path(), mem, mem.Name(), name))
+		}
+		obj := mem.Object()
+		if obj == nil {
+			// This check is sound because fields
+			// {Global,Function}.object have type
+			// types.Object.  (If they were declared as
+			// *types.{Var,Func}, we'd have a non-empty
+			// interface containing a nil pointer.)
+
+			continue // not all members have typechecker objects
+		}
+		if obj.Name() != name {
+			if obj.Name() == "init" && strings.HasPrefix(mem.Name(), "init#") {
+				// Ok.  The name of a declared init function varies between
+				// its types.Func ("init") and its ssa.Function ("init#%d").
+			} else {
+				panic(fmt.Sprintf("%s: %T.Object().Name() = %s, want %s",
+					pkg.Pkg.Path(), mem, obj.Name(), name))
+			}
+		}
+		if obj.Pos() != mem.Pos() {
+			panic(fmt.Sprintf("%s Pos=%d obj.Pos=%d", mem, mem.Pos(), obj.Pos()))
+		}
+	}
+}
diff --git a/go/src/golang.org/x/tools/go/ssa/source.go b/go/src/golang.org/x/tools/go/ssa/source.go
index 84e6f1d..3a6f039 100644
--- a/go/src/golang.org/x/tools/go/ssa/source.go
+++ b/go/src/golang.org/x/tools/go/ssa/source.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package ssa
 
 // This file defines utilities for working with source positions
@@ -13,8 +15,7 @@
 import (
 	"go/ast"
 	"go/token"
-
-	"golang.org/x/tools/go/types"
+	"go/types"
 )
 
 // EnclosingFunction returns the function that contains the syntax
diff --git a/go/src/golang.org/x/tools/go/ssa/source14.go b/go/src/golang.org/x/tools/go/ssa/source14.go
new file mode 100644
index 0000000..af93136
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/ssa/source14.go
@@ -0,0 +1,296 @@
+// 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.
+
+// +build !go1.5
+
+package ssa
+
+// This file defines utilities for working with source positions
+// or source-level named entities ("objects").
+
+// TODO(adonovan): test that {Value,Instruction}.Pos() positions match
+// the originating syntax, as specified.
+
+import (
+	"go/ast"
+	"go/token"
+
+	"golang.org/x/tools/go/types"
+)
+
+// EnclosingFunction returns the function that contains the syntax
+// node denoted by path.
+//
+// Syntax associated with package-level variable specifications is
+// enclosed by the package's init() function.
+//
+// Returns nil if not found; reasons might include:
+//    - the node is not enclosed by any function.
+//    - the node is within an anonymous function (FuncLit) and
+//      its SSA function has not been created yet
+//      (pkg.Build() has not yet been called).
+//
+func EnclosingFunction(pkg *Package, path []ast.Node) *Function {
+	// Start with package-level function...
+	fn := findEnclosingPackageLevelFunction(pkg, path)
+	if fn == nil {
+		return nil // not in any function
+	}
+
+	// ...then walk down the nested anonymous functions.
+	n := len(path)
+outer:
+	for i := range path {
+		if lit, ok := path[n-1-i].(*ast.FuncLit); ok {
+			for _, anon := range fn.AnonFuncs {
+				if anon.Pos() == lit.Type.Func {
+					fn = anon
+					continue outer
+				}
+			}
+			// SSA function not found:
+			// - package not yet built, or maybe
+			// - builder skipped FuncLit in dead block
+			//   (in principle; but currently the Builder
+			//   generates even dead FuncLits).
+			return nil
+		}
+	}
+	return fn
+}
+
+// HasEnclosingFunction returns true if the AST node denoted by path
+// is contained within the declaration of some function or
+// package-level variable.
+//
+// Unlike EnclosingFunction, the behaviour of this function does not
+// depend on whether SSA code for pkg has been built, so it can be
+// used to quickly reject check inputs that will cause
+// EnclosingFunction to fail, prior to SSA building.
+//
+func HasEnclosingFunction(pkg *Package, path []ast.Node) bool {
+	return findEnclosingPackageLevelFunction(pkg, path) != nil
+}
+
+// findEnclosingPackageLevelFunction returns the Function
+// corresponding to the package-level function enclosing path.
+//
+func findEnclosingPackageLevelFunction(pkg *Package, path []ast.Node) *Function {
+	if n := len(path); n >= 2 { // [... {Gen,Func}Decl File]
+		switch decl := path[n-2].(type) {
+		case *ast.GenDecl:
+			if decl.Tok == token.VAR && n >= 3 {
+				// Package-level 'var' initializer.
+				return pkg.init
+			}
+
+		case *ast.FuncDecl:
+			if decl.Recv == nil && decl.Name.Name == "init" {
+				// Explicit init() function.
+				for _, b := range pkg.init.Blocks {
+					for _, instr := range b.Instrs {
+						if instr, ok := instr.(*Call); ok {
+							if callee, ok := instr.Call.Value.(*Function); ok && callee.Pkg == pkg && callee.Pos() == decl.Name.NamePos {
+								return callee
+							}
+						}
+					}
+				}
+				// Hack: return non-nil when SSA is not yet
+				// built so that HasEnclosingFunction works.
+				return pkg.init
+			}
+			// Declared function/method.
+			return findNamedFunc(pkg, decl.Name.NamePos)
+		}
+	}
+	return nil // not in any function
+}
+
+// findNamedFunc returns the named function whose FuncDecl.Ident is at
+// position pos.
+//
+func findNamedFunc(pkg *Package, pos token.Pos) *Function {
+	// Look at all package members and method sets of named types.
+	// Not very efficient.
+	for _, mem := range pkg.Members {
+		switch mem := mem.(type) {
+		case *Function:
+			if mem.Pos() == pos {
+				return mem
+			}
+		case *Type:
+			mset := pkg.Prog.MethodSets.MethodSet(types.NewPointer(mem.Type()))
+			for i, n := 0, mset.Len(); i < n; i++ {
+				// Don't call Program.Method: avoid creating wrappers.
+				obj := mset.At(i).Obj().(*types.Func)
+				if obj.Pos() == pos {
+					return pkg.values[obj].(*Function)
+				}
+			}
+		}
+	}
+	return nil
+}
+
+// ValueForExpr returns the SSA Value that corresponds to non-constant
+// expression e.
+//
+// It returns nil if no value was found, e.g.
+//    - the expression is not lexically contained within f;
+//    - f was not built with debug information; or
+//    - e is a constant expression.  (For efficiency, no debug
+//      information is stored for constants. Use
+//      go/types.Info.Types[e].Value instead.)
+//    - e is a reference to nil or a built-in function.
+//    - the value was optimised away.
+//
+// If e is an addressable expression used in an lvalue context,
+// value is the address denoted by e, and isAddr is true.
+//
+// The types of e (or &e, if isAddr) and the result are equal
+// (modulo "untyped" bools resulting from comparisons).
+//
+// (Tip: to find the ssa.Value given a source position, use
+// importer.PathEnclosingInterval to locate the ast.Node, then
+// EnclosingFunction to locate the Function, then ValueForExpr to find
+// the ssa.Value.)
+//
+func (f *Function) ValueForExpr(e ast.Expr) (value Value, isAddr bool) {
+	if f.debugInfo() { // (opt)
+		e = unparen(e)
+		for _, b := range f.Blocks {
+			for _, instr := range b.Instrs {
+				if ref, ok := instr.(*DebugRef); ok {
+					if ref.Expr == e {
+						return ref.X, ref.IsAddr
+					}
+				}
+			}
+		}
+	}
+	return
+}
+
+// --- Lookup functions for source-level named entities (types.Objects) ---
+
+// Package returns the SSA Package corresponding to the specified
+// type-checker package object.
+// It returns nil if no such SSA package has been created.
+//
+func (prog *Program) Package(obj *types.Package) *Package {
+	return prog.packages[obj]
+}
+
+// packageLevelValue returns the package-level value corresponding to
+// the specified named object, which may be a package-level const
+// (*Const), var (*Global) or func (*Function) of some package in
+// prog.  It returns nil if the object is not found.
+//
+func (prog *Program) packageLevelValue(obj types.Object) Value {
+	if pkg, ok := prog.packages[obj.Pkg()]; ok {
+		return pkg.values[obj]
+	}
+	return nil
+}
+
+// FuncValue returns the concrete Function denoted by the source-level
+// named function obj, or nil if obj denotes an interface method.
+//
+// TODO(adonovan): check the invariant that obj.Type() matches the
+// result's Signature, both in the params/results and in the receiver.
+//
+func (prog *Program) FuncValue(obj *types.Func) *Function {
+	fn, _ := prog.packageLevelValue(obj).(*Function)
+	return fn
+}
+
+// ConstValue returns the SSA Value denoted by the source-level named
+// constant obj.
+//
+func (prog *Program) ConstValue(obj *types.Const) *Const {
+	// TODO(adonovan): opt: share (don't reallocate)
+	// Consts for const objects and constant ast.Exprs.
+
+	// Universal constant? {true,false,nil}
+	if obj.Parent() == types.Universe {
+		return NewConst(obj.Val(), obj.Type())
+	}
+	// Package-level named constant?
+	if v := prog.packageLevelValue(obj); v != nil {
+		return v.(*Const)
+	}
+	return NewConst(obj.Val(), obj.Type())
+}
+
+// VarValue returns the SSA Value that corresponds to a specific
+// identifier denoting the source-level named variable obj.
+//
+// VarValue returns nil if a local variable was not found, perhaps
+// because its package was not built, the debug information was not
+// requested during SSA construction, or the value was optimized away.
+//
+// ref is the path to an ast.Ident (e.g. from PathEnclosingInterval),
+// and that ident must resolve to obj.
+//
+// pkg is the package enclosing the reference.  (A reference to a var
+// always occurs within a function, so we need to know where to find it.)
+//
+// If the identifier is a field selector and its base expression is
+// non-addressable, then VarValue returns the value of that field.
+// For example:
+//    func f() struct {x int}
+//    f().x  // VarValue(x) returns a *Field instruction of type int
+//
+// All other identifiers denote addressable locations (variables).
+// For them, VarValue may return either the variable's address or its
+// value, even when the expression is evaluated only for its value; the
+// situation is reported by isAddr, the second component of the result.
+//
+// If !isAddr, the returned value is the one associated with the
+// specific identifier.  For example,
+//       var x int    // VarValue(x) returns Const 0 here
+//       x = 1        // VarValue(x) returns Const 1 here
+//
+// It is not specified whether the value or the address is returned in
+// any particular case, as it may depend upon optimizations performed
+// during SSA code generation, such as registerization, constant
+// folding, avoidance of materialization of subexpressions, etc.
+//
+func (prog *Program) VarValue(obj *types.Var, pkg *Package, ref []ast.Node) (value Value, isAddr bool) {
+	// All references to a var are local to some function, possibly init.
+	fn := EnclosingFunction(pkg, ref)
+	if fn == nil {
+		return // e.g. def of struct field; SSA not built?
+	}
+
+	id := ref[0].(*ast.Ident)
+
+	// Defining ident of a parameter?
+	if id.Pos() == obj.Pos() {
+		for _, param := range fn.Params {
+			if param.Object() == obj {
+				return param, false
+			}
+		}
+	}
+
+	// Other ident?
+	for _, b := range fn.Blocks {
+		for _, instr := range b.Instrs {
+			if dr, ok := instr.(*DebugRef); ok {
+				if dr.Pos() == id.Pos() {
+					return dr.X, dr.IsAddr
+				}
+			}
+		}
+	}
+
+	// Defining ident of package-level var?
+	if v := prog.packageLevelValue(obj); v != nil {
+		return v.(*Global), true
+	}
+
+	return // e.g. debug info not requested, or var optimized away
+}
diff --git a/go/src/golang.org/x/tools/go/ssa/source14_test.go b/go/src/golang.org/x/tools/go/ssa/source14_test.go
new file mode 100644
index 0000000..cd7b268
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/ssa/source14_test.go
@@ -0,0 +1,395 @@
+// 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.
+
+// +build !go1.5
+
+package ssa_test
+
+// This file defines tests of source-level debugging utilities.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"os"
+	"regexp"
+	"runtime"
+	"strings"
+	"testing"
+
+	"golang.org/x/tools/go/ast/astutil"
+	"golang.org/x/tools/go/exact"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/ssa/ssautil"
+	"golang.org/x/tools/go/types"
+)
+
+func TestObjValueLookup(t *testing.T) {
+	if runtime.GOOS == "android" {
+		t.Skipf("no testdata directory on %s", runtime.GOOS)
+	}
+
+	conf := loader.Config{ParserMode: parser.ParseComments}
+	f, err := conf.ParseFile("testdata/objlookup.go", nil)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	conf.CreateFromFiles("main", f)
+
+	// Maps each var Ident (represented "name:linenum") to the
+	// kind of ssa.Value we expect (represented "Constant", "&Alloc").
+	expectations := make(map[string]string)
+
+	// Find all annotations of form x::BinOp, &y::Alloc, etc.
+	re := regexp.MustCompile(`(\b|&)?(\w*)::(\w*)\b`)
+	for _, c := range f.Comments {
+		text := c.Text()
+		pos := conf.Fset.Position(c.Pos())
+		for _, m := range re.FindAllStringSubmatch(text, -1) {
+			key := fmt.Sprintf("%s:%d", m[2], pos.Line)
+			value := m[1] + m[3]
+			expectations[key] = value
+		}
+	}
+
+	iprog, err := conf.Load()
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	prog := ssautil.CreateProgram(iprog, 0 /*|ssa.PrintFunctions*/)
+	mainInfo := iprog.Created[0]
+	mainPkg := prog.Package(mainInfo.Pkg)
+	mainPkg.SetDebugMode(true)
+	mainPkg.Build()
+
+	var varIds []*ast.Ident
+	var varObjs []*types.Var
+	for id, obj := range mainInfo.Defs {
+		// Check invariants for func and const objects.
+		switch obj := obj.(type) {
+		case *types.Func:
+			checkFuncValue(t, prog, obj)
+
+		case *types.Const:
+			checkConstValue(t, prog, obj)
+
+		case *types.Var:
+			if id.Name == "_" {
+				continue
+			}
+			varIds = append(varIds, id)
+			varObjs = append(varObjs, obj)
+		}
+	}
+	for id, obj := range mainInfo.Uses {
+		if obj, ok := obj.(*types.Var); ok {
+			varIds = append(varIds, id)
+			varObjs = append(varObjs, obj)
+		}
+	}
+
+	// Check invariants for var objects.
+	// The result varies based on the specific Ident.
+	for i, id := range varIds {
+		obj := varObjs[i]
+		ref, _ := astutil.PathEnclosingInterval(f, id.Pos(), id.Pos())
+		pos := prog.Fset.Position(id.Pos())
+		exp := expectations[fmt.Sprintf("%s:%d", id.Name, pos.Line)]
+		if exp == "" {
+			t.Errorf("%s: no expectation for var ident %s ", pos, id.Name)
+			continue
+		}
+		wantAddr := false
+		if exp[0] == '&' {
+			wantAddr = true
+			exp = exp[1:]
+		}
+		checkVarValue(t, prog, mainPkg, ref, obj, exp, wantAddr)
+	}
+}
+
+func checkFuncValue(t *testing.T, prog *ssa.Program, obj *types.Func) {
+	fn := prog.FuncValue(obj)
+	// fmt.Printf("FuncValue(%s) = %s\n", obj, fn) // debugging
+	if fn == nil {
+		if obj.Name() != "interfaceMethod" {
+			t.Errorf("FuncValue(%s) == nil", obj)
+		}
+		return
+	}
+	if fnobj := fn.Object(); fnobj != obj {
+		t.Errorf("FuncValue(%s).Object() == %s; value was %s",
+			obj, fnobj, fn.Name())
+		return
+	}
+	if !types.Identical(fn.Type(), obj.Type()) {
+		t.Errorf("FuncValue(%s).Type() == %s", obj, fn.Type())
+		return
+	}
+}
+
+func checkConstValue(t *testing.T, prog *ssa.Program, obj *types.Const) {
+	c := prog.ConstValue(obj)
+	// fmt.Printf("ConstValue(%s) = %s\n", obj, c) // debugging
+	if c == nil {
+		t.Errorf("ConstValue(%s) == nil", obj)
+		return
+	}
+	if !types.Identical(c.Type(), obj.Type()) {
+		t.Errorf("ConstValue(%s).Type() == %s", obj, c.Type())
+		return
+	}
+	if obj.Name() != "nil" {
+		if !exact.Compare(c.Value, token.EQL, obj.Val()) {
+			t.Errorf("ConstValue(%s).Value (%s) != %s",
+				obj, c.Value, obj.Val())
+			return
+		}
+	}
+}
+
+func checkVarValue(t *testing.T, prog *ssa.Program, pkg *ssa.Package, ref []ast.Node, obj *types.Var, expKind string, wantAddr bool) {
+	// The prefix of all assertions messages.
+	prefix := fmt.Sprintf("VarValue(%s @ L%d)",
+		obj, prog.Fset.Position(ref[0].Pos()).Line)
+
+	v, gotAddr := prog.VarValue(obj, pkg, ref)
+
+	// Kind is the concrete type of the ssa Value.
+	gotKind := "nil"
+	if v != nil {
+		gotKind = fmt.Sprintf("%T", v)[len("*ssa."):]
+	}
+
+	// fmt.Printf("%s = %v (kind %q; expect %q) wantAddr=%t gotAddr=%t\n", prefix, v, gotKind, expKind, wantAddr, gotAddr) // debugging
+
+	// Check the kinds match.
+	// "nil" indicates expected failure (e.g. optimized away).
+	if expKind != gotKind {
+		t.Errorf("%s concrete type == %s, want %s", prefix, gotKind, expKind)
+	}
+
+	// Check the types match.
+	// If wantAddr, the expected type is the object's address.
+	if v != nil {
+		expType := obj.Type()
+		if wantAddr {
+			expType = types.NewPointer(expType)
+			if !gotAddr {
+				t.Errorf("%s: got value, want address", prefix)
+			}
+		} else if gotAddr {
+			t.Errorf("%s: got address, want value", prefix)
+		}
+		if !types.Identical(v.Type(), expType) {
+			t.Errorf("%s.Type() == %s, want %s", prefix, v.Type(), expType)
+		}
+	}
+}
+
+// Ensure that, in debug mode, we can determine the ssa.Value
+// corresponding to every ast.Expr.
+func TestValueForExpr(t *testing.T) {
+	if runtime.GOOS == "android" {
+		t.Skipf("no testdata dir on %s", runtime.GOOS)
+	}
+
+	conf := loader.Config{ParserMode: parser.ParseComments}
+	f, err := conf.ParseFile("testdata/valueforexpr.go", nil)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	conf.CreateFromFiles("main", f)
+
+	iprog, err := conf.Load()
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	mainInfo := iprog.Created[0]
+
+	prog := ssautil.CreateProgram(iprog, 0)
+	mainPkg := prog.Package(mainInfo.Pkg)
+	mainPkg.SetDebugMode(true)
+	mainPkg.Build()
+
+	if false {
+		// debugging
+		for _, mem := range mainPkg.Members {
+			if fn, ok := mem.(*ssa.Function); ok {
+				fn.WriteTo(os.Stderr)
+			}
+		}
+	}
+
+	// Find the actual AST node for each canonical position.
+	parenExprByPos := make(map[token.Pos]*ast.ParenExpr)
+	ast.Inspect(f, func(n ast.Node) bool {
+		if n != nil {
+			if e, ok := n.(*ast.ParenExpr); ok {
+				parenExprByPos[e.Pos()] = e
+			}
+		}
+		return true
+	})
+
+	// Find all annotations of form /*@kind*/.
+	for _, c := range f.Comments {
+		text := strings.TrimSpace(c.Text())
+		if text == "" || text[0] != '@' {
+			continue
+		}
+		text = text[1:]
+		pos := c.End() + 1
+		position := prog.Fset.Position(pos)
+		var e ast.Expr
+		if target := parenExprByPos[pos]; target == nil {
+			t.Errorf("%s: annotation doesn't precede ParenExpr: %q", position, text)
+			continue
+		} else {
+			e = target.X
+		}
+
+		path, _ := astutil.PathEnclosingInterval(f, pos, pos)
+		if path == nil {
+			t.Errorf("%s: can't find AST path from root to comment: %s", position, text)
+			continue
+		}
+
+		fn := ssa.EnclosingFunction(mainPkg, path)
+		if fn == nil {
+			t.Errorf("%s: can't find enclosing function", position)
+			continue
+		}
+
+		v, gotAddr := fn.ValueForExpr(e) // (may be nil)
+		got := strings.TrimPrefix(fmt.Sprintf("%T", v), "*ssa.")
+		if want := text; got != want {
+			t.Errorf("%s: got value %q, want %q", position, got, want)
+		}
+		if v != nil {
+			T := v.Type()
+			if gotAddr {
+				T = T.Underlying().(*types.Pointer).Elem() // deref
+			}
+			if !types.Identical(T, mainInfo.TypeOf(e)) {
+				t.Errorf("%s: got type %s, want %s", position, mainInfo.TypeOf(e), T)
+			}
+		}
+	}
+}
+
+// findInterval parses input and returns the [start, end) positions of
+// the first occurrence of substr in input.  f==nil indicates failure;
+// an error has already been reported in that case.
+//
+func findInterval(t *testing.T, fset *token.FileSet, input, substr string) (f *ast.File, start, end token.Pos) {
+	f, err := parser.ParseFile(fset, "<input>", input, 0)
+	if err != nil {
+		t.Errorf("parse error: %s", err)
+		return
+	}
+
+	i := strings.Index(input, substr)
+	if i < 0 {
+		t.Errorf("%q is not a substring of input", substr)
+		f = nil
+		return
+	}
+
+	filePos := fset.File(f.Package)
+	return f, filePos.Pos(i), filePos.Pos(i + len(substr))
+}
+
+func TestEnclosingFunction(t *testing.T) {
+	tests := []struct {
+		input  string // the input file
+		substr string // first occurrence of this string denotes interval
+		fn     string // name of expected containing function
+	}{
+		// We use distinctive numbers as syntactic landmarks.
+
+		// Ordinary function:
+		{`package main
+		  func f() { println(1003) }`,
+			"100", "main.f"},
+		// Methods:
+		{`package main
+                  type T int
+		  func (t T) f() { println(200) }`,
+			"200", "(main.T).f"},
+		// Function literal:
+		{`package main
+		  func f() { println(func() { print(300) }) }`,
+			"300", "main.f$1"},
+		// Doubly nested
+		{`package main
+		  func f() { println(func() { print(func() { print(350) })})}`,
+			"350", "main.f$1$1"},
+		// Implicit init for package-level var initializer.
+		{"package main; var a = 400", "400", "main.init"},
+		// No code for constants:
+		{"package main; const a = 500", "500", "(none)"},
+		// Explicit init()
+		{"package main; func init() { println(600) }", "600", "main.init#1"},
+		// Multiple explicit init functions:
+		{`package main
+		  func init() { println("foo") }
+		  func init() { println(800) }`,
+			"800", "main.init#2"},
+		// init() containing FuncLit.
+		{`package main
+		  func init() { println(func(){print(900)}) }`,
+			"900", "main.init#1$1"},
+	}
+	for _, test := range tests {
+		conf := loader.Config{Fset: token.NewFileSet()}
+		f, start, end := findInterval(t, conf.Fset, test.input, test.substr)
+		if f == nil {
+			continue
+		}
+		path, exact := astutil.PathEnclosingInterval(f, start, end)
+		if !exact {
+			t.Errorf("EnclosingFunction(%q) not exact", test.substr)
+			continue
+		}
+
+		conf.CreateFromFiles("main", f)
+
+		iprog, err := conf.Load()
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+		prog := ssautil.CreateProgram(iprog, 0)
+		pkg := prog.Package(iprog.Created[0].Pkg)
+		pkg.Build()
+
+		name := "(none)"
+		fn := ssa.EnclosingFunction(pkg, path)
+		if fn != nil {
+			name = fn.String()
+		}
+
+		if name != test.fn {
+			t.Errorf("EnclosingFunction(%q in %q) got %s, want %s",
+				test.substr, test.input, name, test.fn)
+			continue
+		}
+
+		// While we're here: test HasEnclosingFunction.
+		if has := ssa.HasEnclosingFunction(pkg, path); has != (fn != nil) {
+			t.Errorf("HasEnclosingFunction(%q in %q) got %v, want %v",
+				test.substr, test.input, has, fn != nil)
+			continue
+		}
+	}
+}
diff --git a/go/src/golang.org/x/tools/go/ssa/source_test.go b/go/src/golang.org/x/tools/go/ssa/source_test.go
index 75669c1..3fd7ac4 100644
--- a/go/src/golang.org/x/tools/go/ssa/source_test.go
+++ b/go/src/golang.org/x/tools/go/ssa/source_test.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package ssa_test
 
 // This file defines tests of source-level debugging utilities.
@@ -9,8 +11,10 @@
 import (
 	"fmt"
 	"go/ast"
+	exact "go/constant"
 	"go/parser"
 	"go/token"
+	"go/types"
 	"os"
 	"regexp"
 	"runtime"
@@ -18,11 +22,9 @@
 	"testing"
 
 	"golang.org/x/tools/go/ast/astutil"
-	"golang.org/x/tools/go/exact"
 	"golang.org/x/tools/go/loader"
 	"golang.org/x/tools/go/ssa"
 	"golang.org/x/tools/go/ssa/ssautil"
-	"golang.org/x/tools/go/types"
 )
 
 func TestObjValueLookup(t *testing.T) {
diff --git a/go/src/golang.org/x/tools/go/ssa/ssa.go b/go/src/golang.org/x/tools/go/ssa/ssa.go
index f4c64bb..c547af8 100644
--- a/go/src/golang.org/x/tools/go/ssa/ssa.go
+++ b/go/src/golang.org/x/tools/go/ssa/ssa.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package ssa
 
 // This package defines a high-level intermediate representation for
@@ -10,11 +12,11 @@
 import (
 	"fmt"
 	"go/ast"
+	exact "go/constant"
 	"go/token"
+	"go/types"
 	"sync"
 
-	"golang.org/x/tools/go/exact"
-	"golang.org/x/tools/go/types"
 	"golang.org/x/tools/go/types/typeutil"
 )
 
@@ -45,7 +47,7 @@
 //
 type Package struct {
 	Prog    *Program               // the owning program
-	Object  *types.Package         // the type checker's package object for this package
+	Pkg     *types.Package         // the corresponding go/types.Package
 	Members map[string]Member      // all package members keyed by name (incl. init and init#%d)
 	values  map[types.Object]Value // package members (incl. types and methods), keyed by object
 	init    *Function              // Func("init"); the package's init function
@@ -53,10 +55,10 @@
 
 	// The following fields are set transiently, then cleared
 	// after building.
-	started int32       // atomically tested and set at start of build phase
-	ninit   int32       // number of init functions
-	info    *types.Info // package type information
-	files   []*ast.File // package ASTs
+	buildOnce sync.Once   // ensures package building occurs once
+	ninit     int32       // number of init functions
+	info      *types.Info // package type information
+	files     []*ast.File // package ASTs
 }
 
 // A Member is a member of a Go package, implemented by *NamedConst,
diff --git a/go/src/golang.org/x/tools/go/ssa/ssa14.go b/go/src/golang.org/x/tools/go/ssa/ssa14.go
new file mode 100644
index 0000000..dcc62da
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/ssa/ssa14.go
@@ -0,0 +1,1702 @@
+// 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.
+
+// +build !go1.5
+
+package ssa
+
+// This package defines a high-level intermediate representation for
+// Go programs using static single-assignment (SSA) form.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"sync"
+
+	"golang.org/x/tools/go/exact"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/go/types/typeutil"
+)
+
+// A Program is a partial or complete Go program converted to SSA form.
+type Program struct {
+	Fset       *token.FileSet              // position information for the files of this Program
+	imported   map[string]*Package         // all importable Packages, keyed by import path
+	packages   map[*types.Package]*Package // all loaded Packages, keyed by object
+	mode       BuilderMode                 // set of mode bits for SSA construction
+	MethodSets typeutil.MethodSetCache     // cache of type-checker's method-sets
+
+	methodsMu    sync.Mutex                 // guards the following maps:
+	methodSets   typeutil.Map               // maps type to its concrete methodSet
+	runtimeTypes typeutil.Map               // types for which rtypes are needed
+	canon        typeutil.Map               // type canonicalization map
+	bounds       map[*types.Func]*Function  // bounds for curried x.Method closures
+	thunks       map[selectionKey]*Function // thunks for T.Method expressions
+}
+
+// A Package is a single analyzed Go package containing Members for
+// all package-level functions, variables, constants and types it
+// declares.  These may be accessed directly via Members, or via the
+// type-specific accessor methods Func, Type, Var and Const.
+//
+// Members also contains entries for "init" (the synthetic package
+// initializer) and "init#%d", the nth declared init function,
+// and unspecified other things too.
+//
+type Package struct {
+	Prog    *Program               // the owning program
+	Pkg     *types.Package         // the corresponding go/types.Package
+	Members map[string]Member      // all package members keyed by name (incl. init and init#%d)
+	values  map[types.Object]Value // package members (incl. types and methods), keyed by object
+	init    *Function              // Func("init"); the package's init function
+	debug   bool                   // include full debug info in this package
+
+	// The following fields are set transiently, then cleared
+	// after building.
+	buildOnce sync.Once   // ensures package building occurs once
+	ninit     int32       // number of init functions
+	info      *types.Info // package type information
+	files     []*ast.File // package ASTs
+}
+
+// A Member is a member of a Go package, implemented by *NamedConst,
+// *Global, *Function, or *Type; they are created by package-level
+// const, var, func and type declarations respectively.
+//
+type Member interface {
+	Name() string                    // declared name of the package member
+	String() string                  // package-qualified name of the package member
+	RelString(*types.Package) string // like String, but relative refs are unqualified
+	Object() types.Object            // typechecker's object for this member, if any
+	Pos() token.Pos                  // position of member's declaration, if known
+	Type() types.Type                // type of the package member
+	Token() token.Token              // token.{VAR,FUNC,CONST,TYPE}
+	Package() *Package               // the containing package
+}
+
+// A Type is a Member of a Package representing a package-level named type.
+//
+// Type() returns a *types.Named.
+//
+type Type struct {
+	object *types.TypeName
+	pkg    *Package
+}
+
+// A NamedConst is a Member of a Package representing a package-level
+// named constant.
+//
+// Pos() returns the position of the declaring ast.ValueSpec.Names[*]
+// identifier.
+//
+// NB: a NamedConst is not a Value; it contains a constant Value, which
+// it augments with the name and position of its 'const' declaration.
+//
+type NamedConst struct {
+	object *types.Const
+	Value  *Const
+	pos    token.Pos
+	pkg    *Package
+}
+
+// A Value is an SSA value that can be referenced by an instruction.
+type Value interface {
+	// Name returns the name of this value, and determines how
+	// this Value appears when used as an operand of an
+	// Instruction.
+	//
+	// This is the same as the source name for Parameters,
+	// Builtins, Functions, FreeVars, Globals.
+	// For constants, it is a representation of the constant's value
+	// and type.  For all other Values this is the name of the
+	// virtual register defined by the instruction.
+	//
+	// The name of an SSA Value is not semantically significant,
+	// and may not even be unique within a function.
+	Name() string
+
+	// If this value is an Instruction, String returns its
+	// disassembled form; otherwise it returns unspecified
+	// human-readable information about the Value, such as its
+	// kind, name and type.
+	String() string
+
+	// Type returns the type of this value.  Many instructions
+	// (e.g. IndexAddr) change their behaviour depending on the
+	// types of their operands.
+	Type() types.Type
+
+	// Parent returns the function to which this Value belongs.
+	// It returns nil for named Functions, Builtin, Const and Global.
+	Parent() *Function
+
+	// Referrers returns the list of instructions that have this
+	// value as one of their operands; it may contain duplicates
+	// if an instruction has a repeated operand.
+	//
+	// Referrers actually returns a pointer through which the
+	// caller may perform mutations to the object's state.
+	//
+	// Referrers is currently only defined if Parent()!=nil,
+	// i.e. for the function-local values FreeVar, Parameter,
+	// Functions (iff anonymous) and all value-defining instructions.
+	// It returns nil for named Functions, Builtin, Const and Global.
+	//
+	// Instruction.Operands contains the inverse of this relation.
+	Referrers() *[]Instruction
+
+	// Pos returns the location of the AST token most closely
+	// associated with the operation that gave rise to this value,
+	// or token.NoPos if it was not explicit in the source.
+	//
+	// For each ast.Node type, a particular token is designated as
+	// the closest location for the expression, e.g. the Lparen
+	// for an *ast.CallExpr.  This permits a compact but
+	// approximate mapping from Values to source positions for use
+	// in diagnostic messages, for example.
+	//
+	// (Do not use this position to determine which Value
+	// corresponds to an ast.Expr; use Function.ValueForExpr
+	// instead.  NB: it requires that the function was built with
+	// debug information.)
+	Pos() token.Pos
+}
+
+// An Instruction is an SSA instruction that computes a new Value or
+// has some effect.
+//
+// An Instruction that defines a value (e.g. BinOp) also implements
+// the Value interface; an Instruction that only has an effect (e.g. Store)
+// does not.
+//
+type Instruction interface {
+	// String returns the disassembled form of this value.
+	//
+	// Examples of Instructions that are Values:
+	//       "x + y"     (BinOp)
+	//       "len([])"   (Call)
+	// Note that the name of the Value is not printed.
+	//
+	// Examples of Instructions that are not Values:
+	//       "return x"  (Return)
+	//       "*y = x"    (Store)
+	//
+	// (The separation Value.Name() from Value.String() is useful
+	// for some analyses which distinguish the operation from the
+	// value it defines, e.g., 'y = local int' is both an allocation
+	// of memory 'local int' and a definition of a pointer y.)
+	String() string
+
+	// Parent returns the function to which this instruction
+	// belongs.
+	Parent() *Function
+
+	// Block returns the basic block to which this instruction
+	// belongs.
+	Block() *BasicBlock
+
+	// setBlock sets the basic block to which this instruction belongs.
+	setBlock(*BasicBlock)
+
+	// Operands returns the operands of this instruction: the
+	// set of Values it references.
+	//
+	// Specifically, it appends their addresses to rands, a
+	// user-provided slice, and returns the resulting slice,
+	// permitting avoidance of memory allocation.
+	//
+	// The operands are appended in undefined order, but the order
+	// is consistent for a given Instruction; the addresses are
+	// always non-nil but may point to a nil Value.  Clients may
+	// store through the pointers, e.g. to effect a value
+	// renaming.
+	//
+	// Value.Referrers is a subset of the inverse of this
+	// relation.  (Referrers are not tracked for all types of
+	// Values.)
+	Operands(rands []*Value) []*Value
+
+	// Pos returns the location of the AST token most closely
+	// associated with the operation that gave rise to this
+	// instruction, or token.NoPos if it was not explicit in the
+	// source.
+	//
+	// For each ast.Node type, a particular token is designated as
+	// the closest location for the expression, e.g. the Go token
+	// for an *ast.GoStmt.  This permits a compact but approximate
+	// mapping from Instructions to source positions for use in
+	// diagnostic messages, for example.
+	//
+	// (Do not use this position to determine which Instruction
+	// corresponds to an ast.Expr; see the notes for Value.Pos.
+	// This position may be used to determine which non-Value
+	// Instruction corresponds to some ast.Stmts, but not all: If
+	// and Jump instructions have no Pos(), for example.)
+	Pos() token.Pos
+}
+
+// A Node is a node in the SSA value graph.  Every concrete type that
+// implements Node is also either a Value, an Instruction, or both.
+//
+// Node contains the methods common to Value and Instruction, plus the
+// Operands and Referrers methods generalized to return nil for
+// non-Instructions and non-Values, respectively.
+//
+// Node is provided to simplify SSA graph algorithms.  Clients should
+// use the more specific and informative Value or Instruction
+// interfaces where appropriate.
+//
+type Node interface {
+	// Common methods:
+	String() string
+	Pos() token.Pos
+	Parent() *Function
+
+	// Partial methods:
+	Operands(rands []*Value) []*Value // nil for non-Instructions
+	Referrers() *[]Instruction        // nil for non-Values
+}
+
+// Function represents the parameters, results, and code of a function
+// or method.
+//
+// If Blocks is nil, this indicates an external function for which no
+// Go source code is available.  In this case, FreeVars and Locals
+// are nil too.  Clients performing whole-program analysis must
+// handle external functions specially.
+//
+// Blocks contains the function's control-flow graph (CFG).
+// Blocks[0] is the function entry point; block order is not otherwise
+// semantically significant, though it may affect the readability of
+// the disassembly.
+// To iterate over the blocks in dominance order, use DomPreorder().
+//
+// Recover is an optional second entry point to which control resumes
+// after a recovered panic.  The Recover block may contain only a return
+// statement, preceded by a load of the function's named return
+// parameters, if any.
+//
+// A nested function (Parent()!=nil) that refers to one or more
+// lexically enclosing local variables ("free variables") has FreeVars.
+// Such functions cannot be called directly but require a
+// value created by MakeClosure which, via its Bindings, supplies
+// values for these parameters.
+//
+// If the function is a method (Signature.Recv() != nil) then the first
+// element of Params is the receiver parameter.
+//
+// A Go package may declare many functions called "init".
+// For each one, Object().Name() returns "init" but Name() returns
+// "init#1", etc, in declaration order.
+//
+// Pos() returns the declaring ast.FuncLit.Type.Func or the position
+// of the ast.FuncDecl.Name, if the function was explicit in the
+// source.  Synthetic wrappers, for which Synthetic != "", may share
+// the same position as the function they wrap.
+// Syntax.Pos() always returns the position of the declaring "func" token.
+//
+// Type() returns the function's Signature.
+//
+type Function struct {
+	name      string
+	object    types.Object     // a declared *types.Func or one of its wrappers
+	method    *types.Selection // info about provenance of synthetic methods
+	Signature *types.Signature
+	pos       token.Pos
+
+	Synthetic string        // provenance of synthetic function; "" for true source functions
+	syntax    ast.Node      // *ast.Func{Decl,Lit}; replaced with simple ast.Node after build, unless debug mode
+	parent    *Function     // enclosing function if anon; nil if global
+	Pkg       *Package      // enclosing package; nil for shared funcs (wrappers and error.Error)
+	Prog      *Program      // enclosing program
+	Params    []*Parameter  // function parameters; for methods, includes receiver
+	FreeVars  []*FreeVar    // free variables whose values must be supplied by closure
+	Locals    []*Alloc      // local variables of this function
+	Blocks    []*BasicBlock // basic blocks of the function; nil => external
+	Recover   *BasicBlock   // optional; control transfers here after recovered panic
+	AnonFuncs []*Function   // anonymous functions directly beneath this one
+	referrers []Instruction // referring instructions (iff Parent() != nil)
+
+	// The following fields are set transiently during building,
+	// then cleared.
+	currentBlock *BasicBlock             // where to emit code
+	objects      map[types.Object]Value  // addresses of local variables
+	namedResults []*Alloc                // tuple of named results
+	targets      *targets                // linked stack of branch targets
+	lblocks      map[*ast.Object]*lblock // labelled blocks
+}
+
+// BasicBlock represents an SSA basic block.
+//
+// The final element of Instrs is always an explicit transfer of
+// control (If, Jump, Return, or Panic).
+//
+// A block may contain no Instructions only if it is unreachable,
+// i.e., Preds is nil.  Empty blocks are typically pruned.
+//
+// BasicBlocks and their Preds/Succs relation form a (possibly cyclic)
+// graph independent of the SSA Value graph: the control-flow graph or
+// CFG.  It is illegal for multiple edges to exist between the same
+// pair of blocks.
+//
+// Each BasicBlock is also a node in the dominator tree of the CFG.
+// The tree may be navigated using Idom()/Dominees() and queried using
+// Dominates().
+//
+// The order of Preds and Succs is significant (to Phi and If
+// instructions, respectively).
+//
+type BasicBlock struct {
+	Index        int            // index of this block within Parent().Blocks
+	Comment      string         // optional label; no semantic significance
+	parent       *Function      // parent function
+	Instrs       []Instruction  // instructions in order
+	Preds, Succs []*BasicBlock  // predecessors and successors
+	succs2       [2]*BasicBlock // initial space for Succs
+	dom          domInfo        // dominator tree info
+	gaps         int            // number of nil Instrs (transient)
+	rundefers    int            // number of rundefers (transient)
+}
+
+// Pure values ----------------------------------------
+
+// A FreeVar represents a free variable of the function to which it
+// belongs.
+//
+// FreeVars are used to implement anonymous functions, whose free
+// variables are lexically captured in a closure formed by
+// MakeClosure.  The value of such a free var is an Alloc or another
+// FreeVar and is considered a potentially escaping heap address, with
+// pointer type.
+//
+// FreeVars are also used to implement bound method closures.  Such a
+// free var represents the receiver value and may be of any type that
+// has concrete methods.
+//
+// Pos() returns the position of the value that was captured, which
+// belongs to an enclosing function.
+//
+type FreeVar struct {
+	name      string
+	typ       types.Type
+	pos       token.Pos
+	parent    *Function
+	referrers []Instruction
+
+	// Transiently needed during building.
+	outer Value // the Value captured from the enclosing context.
+}
+
+// A Parameter represents an input parameter of a function.
+//
+type Parameter struct {
+	name      string
+	object    types.Object // a *types.Var; nil for non-source locals
+	typ       types.Type
+	pos       token.Pos
+	parent    *Function
+	referrers []Instruction
+}
+
+// A Const represents the value of a constant expression.
+//
+// The underlying type of a constant may be any boolean, numeric, or
+// string type.  In addition, a Const may represent the nil value of
+// any reference type---interface, map, channel, pointer, slice, or
+// function---but not "untyped nil".
+//
+// All source-level constant expressions are represented by a Const
+// of the same type and value.
+//
+// Value holds the exact value of the constant, independent of its
+// Type(), using the same representation as package go/exact uses for
+// constants, or nil for a typed nil value.
+//
+// Pos() returns token.NoPos.
+//
+// Example printed form:
+// 	42:int
+//	"hello":untyped string
+//	3+4i:MyComplex
+//
+type Const struct {
+	typ   types.Type
+	Value exact.Value
+}
+
+// A Global is a named Value holding the address of a package-level
+// variable.
+//
+// Pos() returns the position of the ast.ValueSpec.Names[*]
+// identifier.
+//
+type Global struct {
+	name   string
+	object types.Object // a *types.Var; may be nil for synthetics e.g. init$guard
+	typ    types.Type
+	pos    token.Pos
+
+	Pkg *Package
+}
+
+// A Builtin represents a specific use of a built-in function, e.g. len.
+//
+// Builtins are immutable values.  Builtins do not have addresses.
+// Builtins can only appear in CallCommon.Func.
+//
+// Name() indicates the function: one of the built-in functions from the
+// Go spec (excluding "make" and "new") or one of these ssa-defined
+// intrinsics:
+//
+//   // wrapnilchk returns ptr if non-nil, panics otherwise.
+//   // (For use in indirection wrappers.)
+//   func ssa:wrapnilchk(ptr *T, recvType, methodName string) *T
+//
+// Object() returns a *types.Builtin for built-ins defined by the spec,
+// nil for others.
+//
+// Type() returns a *types.Signature representing the effective
+// signature of the built-in for this call.
+//
+type Builtin struct {
+	name string
+	sig  *types.Signature
+}
+
+// Value-defining instructions  ----------------------------------------
+
+// The Alloc instruction reserves space for a variable of the given type,
+// zero-initializes it, and yields its address.
+//
+// Alloc values are always addresses, and have pointer types, so the
+// type of the allocated variable is actually
+// Type().Underlying().(*types.Pointer).Elem().
+//
+// If Heap is false, Alloc allocates space in the function's
+// activation record (frame); we refer to an Alloc(Heap=false) as a
+// "local" alloc.  Each local Alloc returns the same address each time
+// it is executed within the same activation; the space is
+// re-initialized to zero.
+//
+// If Heap is true, Alloc allocates space in the heap; we
+// refer to an Alloc(Heap=true) as a "new" alloc.  Each new Alloc
+// returns a different address each time it is executed.
+//
+// When Alloc is applied to a channel, map or slice type, it returns
+// the address of an uninitialized (nil) reference of that kind; store
+// the result of MakeSlice, MakeMap or MakeChan in that location to
+// instantiate these types.
+//
+// Pos() returns the ast.CompositeLit.Lbrace for a composite literal,
+// or the ast.CallExpr.Rparen for a call to new() or for a call that
+// allocates a varargs slice.
+//
+// Example printed form:
+// 	t0 = local int
+// 	t1 = new int
+//
+type Alloc struct {
+	register
+	Comment string
+	Heap    bool
+	index   int // dense numbering; for lifting
+}
+
+// The Phi instruction represents an SSA φ-node, which combines values
+// that differ across incoming control-flow edges and yields a new
+// value.  Within a block, all φ-nodes must appear before all non-φ
+// nodes.
+//
+// Pos() returns the position of the && or || for short-circuit
+// control-flow joins, or that of the *Alloc for φ-nodes inserted
+// during SSA renaming.
+//
+// Example printed form:
+// 	t2 = phi [0: t0, 1: t1]
+//
+type Phi struct {
+	register
+	Comment string  // a hint as to its purpose
+	Edges   []Value // Edges[i] is value for Block().Preds[i]
+}
+
+// The Call instruction represents a function or method call.
+//
+// The Call instruction yields the function result if there is exactly
+// one.  Otherwise it returns a tuple, the components of which are
+// accessed via Extract.
+//
+// See CallCommon for generic function call documentation.
+//
+// Pos() returns the ast.CallExpr.Lparen, if explicit in the source.
+//
+// Example printed form:
+// 	t2 = println(t0, t1)
+// 	t4 = t3()
+// 	t7 = invoke t5.Println(...t6)
+//
+type Call struct {
+	register
+	Call CallCommon
+}
+
+// The BinOp instruction yields the result of binary operation X Op Y.
+//
+// Pos() returns the ast.BinaryExpr.OpPos, if explicit in the source.
+//
+// Example printed form:
+// 	t1 = t0 + 1:int
+//
+type BinOp struct {
+	register
+	// One of:
+	// ADD SUB MUL QUO REM          + - * / %
+	// AND OR XOR SHL SHR AND_NOT   & | ^ << >> &~
+	// EQL LSS GTR NEQ LEQ GEQ      == != < <= < >=
+	Op   token.Token
+	X, Y Value
+}
+
+// The UnOp instruction yields the result of Op X.
+// ARROW is channel receive.
+// MUL is pointer indirection (load).
+// XOR is bitwise complement.
+// SUB is negation.
+// NOT is logical negation.
+//
+// If CommaOk and Op=ARROW, the result is a 2-tuple of the value above
+// and a boolean indicating the success of the receive.  The
+// components of the tuple are accessed using Extract.
+//
+// Pos() returns the ast.UnaryExpr.OpPos, if explicit in the source.
+// For receive operations (ARROW) implicit in ranging over a channel,
+// Pos() returns the ast.RangeStmt.For.
+// For implicit memory loads (STAR), Pos() returns the position of the
+// most closely associated source-level construct; the details are not
+// specified.
+//
+// Example printed form:
+// 	t0 = *x
+// 	t2 = <-t1,ok
+//
+type UnOp struct {
+	register
+	Op      token.Token // One of: NOT SUB ARROW MUL XOR ! - <- * ^
+	X       Value
+	CommaOk bool
+}
+
+// The ChangeType instruction applies to X a value-preserving type
+// change to Type().
+//
+// Type changes are permitted:
+//    - between a named type and its underlying type.
+//    - between two named types of the same underlying type.
+//    - between (possibly named) pointers to identical base types.
+//    - from a bidirectional channel to a read- or write-channel,
+//      optionally adding/removing a name.
+//
+// This operation cannot fail dynamically.
+//
+// Pos() returns the ast.CallExpr.Lparen, if the instruction arose
+// from an explicit conversion in the source.
+//
+// Example printed form:
+// 	t1 = changetype *int <- IntPtr (t0)
+//
+type ChangeType struct {
+	register
+	X Value
+}
+
+// The Convert instruction yields the conversion of value X to type
+// Type().  One or both of those types is basic (but possibly named).
+//
+// A conversion may change the value and representation of its operand.
+// Conversions are permitted:
+//    - between real numeric types.
+//    - between complex numeric types.
+//    - between string and []byte or []rune.
+//    - between pointers and unsafe.Pointer.
+//    - between unsafe.Pointer and uintptr.
+//    - from (Unicode) integer to (UTF-8) string.
+// A conversion may imply a type name change also.
+//
+// This operation cannot fail dynamically.
+//
+// Conversions of untyped string/number/bool constants to a specific
+// representation are eliminated during SSA construction.
+//
+// Pos() returns the ast.CallExpr.Lparen, if the instruction arose
+// from an explicit conversion in the source.
+//
+// Example printed form:
+// 	t1 = convert []byte <- string (t0)
+//
+type Convert struct {
+	register
+	X Value
+}
+
+// ChangeInterface constructs a value of one interface type from a
+// value of another interface type known to be assignable to it.
+// This operation cannot fail.
+//
+// Pos() returns the ast.CallExpr.Lparen if the instruction arose from
+// an explicit T(e) conversion; the ast.TypeAssertExpr.Lparen if the
+// instruction arose from an explicit e.(T) operation; or token.NoPos
+// otherwise.
+//
+// Example printed form:
+// 	t1 = change interface interface{} <- I (t0)
+//
+type ChangeInterface struct {
+	register
+	X Value
+}
+
+// MakeInterface constructs an instance of an interface type from a
+// value of a concrete type.
+//
+// Use Program.MethodSets.MethodSet(X.Type()) to find the method-set
+// of X, and Program.Method(m) to find the implementation of a method.
+//
+// To construct the zero value of an interface type T, use:
+// 	NewConst(exact.MakeNil(), T, pos)
+//
+// Pos() returns the ast.CallExpr.Lparen, if the instruction arose
+// from an explicit conversion in the source.
+//
+// Example printed form:
+// 	t1 = make interface{} <- int (42:int)
+// 	t2 = make Stringer <- t0
+//
+type MakeInterface struct {
+	register
+	X Value
+}
+
+// The MakeClosure instruction yields a closure value whose code is
+// Fn and whose free variables' values are supplied by Bindings.
+//
+// Type() returns a (possibly named) *types.Signature.
+//
+// Pos() returns the ast.FuncLit.Type.Func for a function literal
+// closure or the ast.SelectorExpr.Sel for a bound method closure.
+//
+// Example printed form:
+// 	t0 = make closure anon@1.2 [x y z]
+// 	t1 = make closure bound$(main.I).add [i]
+//
+type MakeClosure struct {
+	register
+	Fn       Value   // always a *Function
+	Bindings []Value // values for each free variable in Fn.FreeVars
+}
+
+// The MakeMap instruction creates a new hash-table-based map object
+// and yields a value of kind map.
+//
+// Type() returns a (possibly named) *types.Map.
+//
+// Pos() returns the ast.CallExpr.Lparen, if created by make(map), or
+// the ast.CompositeLit.Lbrack if created by a literal.
+//
+// Example printed form:
+// 	t1 = make map[string]int t0
+// 	t1 = make StringIntMap t0
+//
+type MakeMap struct {
+	register
+	Reserve Value // initial space reservation; nil => default
+}
+
+// The MakeChan instruction creates a new channel object and yields a
+// value of kind chan.
+//
+// Type() returns a (possibly named) *types.Chan.
+//
+// Pos() returns the ast.CallExpr.Lparen for the make(chan) that
+// created it.
+//
+// Example printed form:
+// 	t0 = make chan int 0
+// 	t0 = make IntChan 0
+//
+type MakeChan struct {
+	register
+	Size Value // int; size of buffer; zero => synchronous.
+}
+
+// The MakeSlice instruction yields a slice of length Len backed by a
+// newly allocated array of length Cap.
+//
+// Both Len and Cap must be non-nil Values of integer type.
+//
+// (Alloc(types.Array) followed by Slice will not suffice because
+// Alloc can only create arrays of constant length.)
+//
+// Type() returns a (possibly named) *types.Slice.
+//
+// Pos() returns the ast.CallExpr.Lparen for the make([]T) that
+// created it.
+//
+// Example printed form:
+// 	t1 = make []string 1:int t0
+// 	t1 = make StringSlice 1:int t0
+//
+type MakeSlice struct {
+	register
+	Len Value
+	Cap Value
+}
+
+// The Slice instruction yields a slice of an existing string, slice
+// or *array X between optional integer bounds Low and High.
+//
+// Dynamically, this instruction panics if X evaluates to a nil *array
+// pointer.
+//
+// Type() returns string if the type of X was string, otherwise a
+// *types.Slice with the same element type as X.
+//
+// Pos() returns the ast.SliceExpr.Lbrack if created by a x[:] slice
+// operation, the ast.CompositeLit.Lbrace if created by a literal, or
+// NoPos if not explicit in the source (e.g. a variadic argument slice).
+//
+// Example printed form:
+// 	t1 = slice t0[1:]
+//
+type Slice struct {
+	register
+	X              Value // slice, string, or *array
+	Low, High, Max Value // each may be nil
+}
+
+// The FieldAddr instruction yields the address of Field of *struct X.
+//
+// The field is identified by its index within the field list of the
+// struct type of X.
+//
+// Dynamically, this instruction panics if X evaluates to a nil
+// pointer.
+//
+// Type() returns a (possibly named) *types.Pointer.
+//
+// Pos() returns the position of the ast.SelectorExpr.Sel for the
+// field, if explicit in the source.
+//
+// Example printed form:
+// 	t1 = &t0.name [#1]
+//
+type FieldAddr struct {
+	register
+	X     Value // *struct
+	Field int   // index into X.Type().Deref().(*types.Struct).Fields
+}
+
+// The Field instruction yields the Field of struct X.
+//
+// The field is identified by its index within the field list of the
+// struct type of X; by using numeric indices we avoid ambiguity of
+// package-local identifiers and permit compact representations.
+//
+// Pos() returns the position of the ast.SelectorExpr.Sel for the
+// field, if explicit in the source.
+//
+// Example printed form:
+// 	t1 = t0.name [#1]
+//
+type Field struct {
+	register
+	X     Value // struct
+	Field int   // index into X.Type().(*types.Struct).Fields
+}
+
+// The IndexAddr instruction yields the address of the element at
+// index Index of collection X.  Index is an integer expression.
+//
+// The elements of maps and strings are not addressable; use Lookup or
+// MapUpdate instead.
+//
+// Dynamically, this instruction panics if X evaluates to a nil *array
+// pointer.
+//
+// Type() returns a (possibly named) *types.Pointer.
+//
+// Pos() returns the ast.IndexExpr.Lbrack for the index operation, if
+// explicit in the source.
+//
+// Example printed form:
+// 	t2 = &t0[t1]
+//
+type IndexAddr struct {
+	register
+	X     Value // slice or *array,
+	Index Value // numeric index
+}
+
+// The Index instruction yields element Index of array X.
+//
+// Pos() returns the ast.IndexExpr.Lbrack for the index operation, if
+// explicit in the source.
+//
+// Example printed form:
+// 	t2 = t0[t1]
+//
+type Index struct {
+	register
+	X     Value // array
+	Index Value // integer index
+}
+
+// The Lookup instruction yields element Index of collection X, a map
+// or string.  Index is an integer expression if X is a string or the
+// appropriate key type if X is a map.
+//
+// If CommaOk, the result is a 2-tuple of the value above and a
+// boolean indicating the result of a map membership test for the key.
+// The components of the tuple are accessed using Extract.
+//
+// Pos() returns the ast.IndexExpr.Lbrack, if explicit in the source.
+//
+// Example printed form:
+// 	t2 = t0[t1]
+// 	t5 = t3[t4],ok
+//
+type Lookup struct {
+	register
+	X       Value // string or map
+	Index   Value // numeric or key-typed index
+	CommaOk bool  // return a value,ok pair
+}
+
+// SelectState is a helper for Select.
+// It represents one goal state and its corresponding communication.
+//
+type SelectState struct {
+	Dir       types.ChanDir // direction of case (SendOnly or RecvOnly)
+	Chan      Value         // channel to use (for send or receive)
+	Send      Value         // value to send (for send)
+	Pos       token.Pos     // position of token.ARROW
+	DebugNode ast.Node      // ast.SendStmt or ast.UnaryExpr(<-) [debug mode]
+}
+
+// The Select instruction tests whether (or blocks until) one
+// of the specified sent or received states is entered.
+//
+// Let n be the number of States for which Dir==RECV and T_i (0<=i<n)
+// be the element type of each such state's Chan.
+// Select returns an n+2-tuple
+//    (index int, recvOk bool, r_0 T_0, ... r_n-1 T_n-1)
+// The tuple's components, described below, must be accessed via the
+// Extract instruction.
+//
+// If Blocking, select waits until exactly one state holds, i.e. a
+// channel becomes ready for the designated operation of sending or
+// receiving; select chooses one among the ready states
+// pseudorandomly, performs the send or receive operation, and sets
+// 'index' to the index of the chosen channel.
+//
+// If !Blocking, select doesn't block if no states hold; instead it
+// returns immediately with index equal to -1.
+//
+// If the chosen channel was used for a receive, the r_i component is
+// set to the received value, where i is the index of that state among
+// all n receive states; otherwise r_i has the zero value of type T_i.
+// Note that the receive index i is not the same as the state
+// index index.
+//
+// The second component of the triple, recvOk, is a boolean whose value
+// is true iff the selected operation was a receive and the receive
+// successfully yielded a value.
+//
+// Pos() returns the ast.SelectStmt.Select.
+//
+// Example printed form:
+// 	t3 = select nonblocking [<-t0, t1<-t2]
+// 	t4 = select blocking []
+//
+type Select struct {
+	register
+	States   []*SelectState
+	Blocking bool
+}
+
+// The Range instruction yields an iterator over the domain and range
+// of X, which must be a string or map.
+//
+// Elements are accessed via Next.
+//
+// Type() returns an opaque and degenerate "rangeIter" type.
+//
+// Pos() returns the ast.RangeStmt.For.
+//
+// Example printed form:
+// 	t0 = range "hello":string
+//
+type Range struct {
+	register
+	X Value // string or map
+}
+
+// The Next instruction reads and advances the (map or string)
+// iterator Iter and returns a 3-tuple value (ok, k, v).  If the
+// iterator is not exhausted, ok is true and k and v are the next
+// elements of the domain and range, respectively.  Otherwise ok is
+// false and k and v are undefined.
+//
+// Components of the tuple are accessed using Extract.
+//
+// The IsString field distinguishes iterators over strings from those
+// over maps, as the Type() alone is insufficient: consider
+// map[int]rune.
+//
+// Type() returns a *types.Tuple for the triple (ok, k, v).
+// The types of k and/or v may be types.Invalid.
+//
+// Example printed form:
+// 	t1 = next t0
+//
+type Next struct {
+	register
+	Iter     Value
+	IsString bool // true => string iterator; false => map iterator.
+}
+
+// The TypeAssert instruction tests whether interface value X has type
+// AssertedType.
+//
+// If !CommaOk, on success it returns v, the result of the conversion
+// (defined below); on failure it panics.
+//
+// If CommaOk: on success it returns a pair (v, true) where v is the
+// result of the conversion; on failure it returns (z, false) where z
+// is AssertedType's zero value.  The components of the pair must be
+// accessed using the Extract instruction.
+//
+// If AssertedType is a concrete type, TypeAssert checks whether the
+// dynamic type in interface X is equal to it, and if so, the result
+// of the conversion is a copy of the value in the interface.
+//
+// If AssertedType is an interface, TypeAssert checks whether the
+// dynamic type of the interface is assignable to it, and if so, the
+// result of the conversion is a copy of the interface value X.
+// If AssertedType is a superinterface of X.Type(), the operation will
+// fail iff the operand is nil.  (Contrast with ChangeInterface, which
+// performs no nil-check.)
+//
+// Type() reflects the actual type of the result, possibly a
+// 2-types.Tuple; AssertedType is the asserted type.
+//
+// Pos() returns the ast.CallExpr.Lparen if the instruction arose from
+// an explicit T(e) conversion; the ast.TypeAssertExpr.Lparen if the
+// instruction arose from an explicit e.(T) operation; or the
+// ast.CaseClause.Case if the instruction arose from a case of a
+// type-switch statement.
+//
+// Example printed form:
+// 	t1 = typeassert t0.(int)
+// 	t3 = typeassert,ok t2.(T)
+//
+type TypeAssert struct {
+	register
+	X            Value
+	AssertedType types.Type
+	CommaOk      bool
+}
+
+// The Extract instruction yields component Index of Tuple.
+//
+// This is used to access the results of instructions with multiple
+// return values, such as Call, TypeAssert, Next, UnOp(ARROW) and
+// IndexExpr(Map).
+//
+// Example printed form:
+// 	t1 = extract t0 #1
+//
+type Extract struct {
+	register
+	Tuple Value
+	Index int
+}
+
+// Instructions executed for effect.  They do not yield a value. --------------------
+
+// The Jump instruction transfers control to the sole successor of its
+// owning block.
+//
+// A Jump must be the last instruction of its containing BasicBlock.
+//
+// Pos() returns NoPos.
+//
+// Example printed form:
+// 	jump done
+//
+type Jump struct {
+	anInstruction
+}
+
+// The If instruction transfers control to one of the two successors
+// of its owning block, depending on the boolean Cond: the first if
+// true, the second if false.
+//
+// An If instruction must be the last instruction of its containing
+// BasicBlock.
+//
+// Pos() returns NoPos.
+//
+// Example printed form:
+// 	if t0 goto done else body
+//
+type If struct {
+	anInstruction
+	Cond Value
+}
+
+// The Return instruction returns values and control back to the calling
+// function.
+//
+// len(Results) is always equal to the number of results in the
+// function's signature.
+//
+// If len(Results) > 1, Return returns a tuple value with the specified
+// components which the caller must access using Extract instructions.
+//
+// There is no instruction to return a ready-made tuple like those
+// returned by a "value,ok"-mode TypeAssert, Lookup or UnOp(ARROW) or
+// a tail-call to a function with multiple result parameters.
+//
+// Return must be the last instruction of its containing BasicBlock.
+// Such a block has no successors.
+//
+// Pos() returns the ast.ReturnStmt.Return, if explicit in the source.
+//
+// Example printed form:
+// 	return
+// 	return nil:I, 2:int
+//
+type Return struct {
+	anInstruction
+	Results []Value
+	pos     token.Pos
+}
+
+// The RunDefers instruction pops and invokes the entire stack of
+// procedure calls pushed by Defer instructions in this function.
+//
+// It is legal to encounter multiple 'rundefers' instructions in a
+// single control-flow path through a function; this is useful in
+// the combined init() function, for example.
+//
+// Pos() returns NoPos.
+//
+// Example printed form:
+//	rundefers
+//
+type RunDefers struct {
+	anInstruction
+}
+
+// The Panic instruction initiates a panic with value X.
+//
+// A Panic instruction must be the last instruction of its containing
+// BasicBlock, which must have no successors.
+//
+// NB: 'go panic(x)' and 'defer panic(x)' do not use this instruction;
+// they are treated as calls to a built-in function.
+//
+// Pos() returns the ast.CallExpr.Lparen if this panic was explicit
+// in the source.
+//
+// Example printed form:
+// 	panic t0
+//
+type Panic struct {
+	anInstruction
+	X   Value // an interface{}
+	pos token.Pos
+}
+
+// The Go instruction creates a new goroutine and calls the specified
+// function within it.
+//
+// See CallCommon for generic function call documentation.
+//
+// Pos() returns the ast.GoStmt.Go.
+//
+// Example printed form:
+// 	go println(t0, t1)
+// 	go t3()
+// 	go invoke t5.Println(...t6)
+//
+type Go struct {
+	anInstruction
+	Call CallCommon
+	pos  token.Pos
+}
+
+// The Defer instruction pushes the specified call onto a stack of
+// functions to be called by a RunDefers instruction or by a panic.
+//
+// See CallCommon for generic function call documentation.
+//
+// Pos() returns the ast.DeferStmt.Defer.
+//
+// Example printed form:
+// 	defer println(t0, t1)
+// 	defer t3()
+// 	defer invoke t5.Println(...t6)
+//
+type Defer struct {
+	anInstruction
+	Call CallCommon
+	pos  token.Pos
+}
+
+// The Send instruction sends X on channel Chan.
+//
+// Pos() returns the ast.SendStmt.Arrow, if explicit in the source.
+//
+// Example printed form:
+// 	send t0 <- t1
+//
+type Send struct {
+	anInstruction
+	Chan, X Value
+	pos     token.Pos
+}
+
+// The Store instruction stores Val at address Addr.
+// Stores can be of arbitrary types.
+//
+// Pos() returns the position of the source-level construct most closely
+// associated with the memory store operation.
+// Since implicit memory stores are numerous and varied and depend upon
+// implementation choices, the details are not specified.
+//
+// Example printed form:
+// 	*x = y
+//
+type Store struct {
+	anInstruction
+	Addr Value
+	Val  Value
+	pos  token.Pos
+}
+
+// The MapUpdate instruction updates the association of Map[Key] to
+// Value.
+//
+// Pos() returns the ast.KeyValueExpr.Colon or ast.IndexExpr.Lbrack,
+// if explicit in the source.
+//
+// Example printed form:
+//	t0[t1] = t2
+//
+type MapUpdate struct {
+	anInstruction
+	Map   Value
+	Key   Value
+	Value Value
+	pos   token.Pos
+}
+
+// A DebugRef instruction maps a source-level expression Expr to the
+// SSA value X that represents the value (!IsAddr) or address (IsAddr)
+// of that expression.
+//
+// DebugRef is a pseudo-instruction: it has no dynamic effect.
+//
+// Pos() returns Expr.Pos(), the start position of the source-level
+// expression.  This is not the same as the "designated" token as
+// documented at Value.Pos(). e.g. CallExpr.Pos() does not return the
+// position of the ("designated") Lparen token.
+//
+// If Expr is an *ast.Ident denoting a var or func, Object() returns
+// the object; though this information can be obtained from the type
+// checker, including it here greatly facilitates debugging.
+// For non-Ident expressions, Object() returns nil.
+//
+// DebugRefs are generated only for functions built with debugging
+// enabled; see Package.SetDebugMode() and the GlobalDebug builder
+// mode flag.
+//
+// DebugRefs are not emitted for ast.Idents referring to constants or
+// predeclared identifiers, since they are trivial and numerous.
+// Nor are they emitted for ast.ParenExprs.
+//
+// (By representing these as instructions, rather than out-of-band,
+// consistency is maintained during transformation passes by the
+// ordinary SSA renaming machinery.)
+//
+// Example printed form:
+//      ; *ast.CallExpr @ 102:9 is t5
+//      ; var x float64 @ 109:72 is x
+//      ; address of *ast.CompositeLit @ 216:10 is t0
+//
+type DebugRef struct {
+	anInstruction
+	Expr   ast.Expr     // the referring expression (never *ast.ParenExpr)
+	object types.Object // the identity of the source var/func
+	IsAddr bool         // Expr is addressable and X is the address it denotes
+	X      Value        // the value or address of Expr
+}
+
+// Embeddable mix-ins and helpers for common parts of other structs. -----------
+
+// register is a mix-in embedded by all SSA values that are also
+// instructions, i.e. virtual registers, and provides a uniform
+// implementation of most of the Value interface: Value.Name() is a
+// numbered register (e.g. "t0"); the other methods are field accessors.
+//
+// Temporary names are automatically assigned to each register on
+// completion of building a function in SSA form.
+//
+// Clients must not assume that the 'id' value (and the Name() derived
+// from it) is unique within a function.  As always in this API,
+// semantics are determined only by identity; names exist only to
+// facilitate debugging.
+//
+type register struct {
+	anInstruction
+	num       int        // "name" of virtual register, e.g. "t0".  Not guaranteed unique.
+	typ       types.Type // type of virtual register
+	pos       token.Pos  // position of source expression, or NoPos
+	referrers []Instruction
+}
+
+// anInstruction is a mix-in embedded by all Instructions.
+// It provides the implementations of the Block and setBlock methods.
+type anInstruction struct {
+	block *BasicBlock // the basic block of this instruction
+}
+
+// CallCommon is contained by Go, Defer and Call to hold the
+// common parts of a function or method call.
+//
+// Each CallCommon exists in one of two modes, function call and
+// interface method invocation, or "call" and "invoke" for short.
+//
+// 1. "call" mode: when Method is nil (!IsInvoke), a CallCommon
+// represents an ordinary function call of the value in Value,
+// which may be a *Builtin, a *Function or any other value of kind
+// 'func'.
+//
+// Value may be one of:
+//    (a) a *Function, indicating a statically dispatched call
+//        to a package-level function, an anonymous function, or
+//        a method of a named type.
+//    (b) a *MakeClosure, indicating an immediately applied
+//        function literal with free variables.
+//    (c) a *Builtin, indicating a statically dispatched call
+//        to a built-in function.
+//    (d) any other value, indicating a dynamically dispatched
+//        function call.
+// StaticCallee returns the identity of the callee in cases
+// (a) and (b), nil otherwise.
+//
+// Args contains the arguments to the call.  If Value is a method,
+// Args[0] contains the receiver parameter.
+//
+// Example printed form:
+// 	t2 = println(t0, t1)
+// 	go t3()
+//	defer t5(...t6)
+//
+// 2. "invoke" mode: when Method is non-nil (IsInvoke), a CallCommon
+// represents a dynamically dispatched call to an interface method.
+// In this mode, Value is the interface value and Method is the
+// interface's abstract method.  Note: an abstract method may be
+// shared by multiple interfaces due to embedding; Value.Type()
+// provides the specific interface used for this call.
+//
+// Value is implicitly supplied to the concrete method implementation
+// as the receiver parameter; in other words, Args[0] holds not the
+// receiver but the first true argument.
+//
+// Example printed form:
+// 	t1 = invoke t0.String()
+// 	go invoke t3.Run(t2)
+// 	defer invoke t4.Handle(...t5)
+//
+// For all calls to variadic functions (Signature().Variadic()),
+// the last element of Args is a slice.
+//
+type CallCommon struct {
+	Value  Value       // receiver (invoke mode) or func value (call mode)
+	Method *types.Func // abstract method (invoke mode)
+	Args   []Value     // actual parameters (in static method call, includes receiver)
+	pos    token.Pos   // position of CallExpr.Lparen, iff explicit in source
+}
+
+// IsInvoke returns true if this call has "invoke" (not "call") mode.
+func (c *CallCommon) IsInvoke() bool {
+	return c.Method != nil
+}
+
+func (c *CallCommon) Pos() token.Pos { return c.pos }
+
+// Signature returns the signature of the called function.
+//
+// For an "invoke"-mode call, the signature of the interface method is
+// returned.
+//
+// In either "call" or "invoke" mode, if the callee is a method, its
+// receiver is represented by sig.Recv, not sig.Params().At(0).
+//
+func (c *CallCommon) Signature() *types.Signature {
+	if c.Method != nil {
+		return c.Method.Type().(*types.Signature)
+	}
+	return c.Value.Type().Underlying().(*types.Signature)
+}
+
+// StaticCallee returns the callee if this is a trivially static
+// "call"-mode call to a function.
+func (c *CallCommon) StaticCallee() *Function {
+	switch fn := c.Value.(type) {
+	case *Function:
+		return fn
+	case *MakeClosure:
+		return fn.Fn.(*Function)
+	}
+	return nil
+}
+
+// Description returns a description of the mode of this call suitable
+// for a user interface, e.g., "static method call".
+func (c *CallCommon) Description() string {
+	switch fn := c.Value.(type) {
+	case *Builtin:
+		return "built-in function call"
+	case *MakeClosure:
+		return "static function closure call"
+	case *Function:
+		if fn.Signature.Recv() != nil {
+			return "static method call"
+		}
+		return "static function call"
+	}
+	if c.IsInvoke() {
+		return "dynamic method call" // ("invoke" mode)
+	}
+	return "dynamic function call"
+}
+
+// The CallInstruction interface, implemented by *Go, *Defer and *Call,
+// exposes the common parts of function-calling instructions,
+// yet provides a way back to the Value defined by *Call alone.
+//
+type CallInstruction interface {
+	Instruction
+	Common() *CallCommon // returns the common parts of the call
+	Value() *Call        // returns the result value of the call (*Call) or nil (*Go, *Defer)
+}
+
+func (s *Call) Common() *CallCommon  { return &s.Call }
+func (s *Defer) Common() *CallCommon { return &s.Call }
+func (s *Go) Common() *CallCommon    { return &s.Call }
+
+func (s *Call) Value() *Call  { return s }
+func (s *Defer) Value() *Call { return nil }
+func (s *Go) Value() *Call    { return nil }
+
+func (v *Builtin) Type() types.Type        { return v.sig }
+func (v *Builtin) Name() string            { return v.name }
+func (*Builtin) Referrers() *[]Instruction { return nil }
+func (v *Builtin) Pos() token.Pos          { return token.NoPos }
+func (v *Builtin) Object() types.Object    { return types.Universe.Lookup(v.name) }
+func (v *Builtin) Parent() *Function       { return nil }
+
+func (v *FreeVar) Type() types.Type          { return v.typ }
+func (v *FreeVar) Name() string              { return v.name }
+func (v *FreeVar) Referrers() *[]Instruction { return &v.referrers }
+func (v *FreeVar) Pos() token.Pos            { return v.pos }
+func (v *FreeVar) Parent() *Function         { return v.parent }
+
+func (v *Global) Type() types.Type                     { return v.typ }
+func (v *Global) Name() string                         { return v.name }
+func (v *Global) Parent() *Function                    { return nil }
+func (v *Global) Pos() token.Pos                       { return v.pos }
+func (v *Global) Referrers() *[]Instruction            { return nil }
+func (v *Global) Token() token.Token                   { return token.VAR }
+func (v *Global) Object() types.Object                 { return v.object }
+func (v *Global) String() string                       { return v.RelString(nil) }
+func (v *Global) Package() *Package                    { return v.Pkg }
+func (v *Global) RelString(from *types.Package) string { return relString(v, from) }
+
+func (v *Function) Name() string         { return v.name }
+func (v *Function) Type() types.Type     { return v.Signature }
+func (v *Function) Pos() token.Pos       { return v.pos }
+func (v *Function) Token() token.Token   { return token.FUNC }
+func (v *Function) Object() types.Object { return v.object }
+func (v *Function) String() string       { return v.RelString(nil) }
+func (v *Function) Package() *Package    { return v.Pkg }
+func (v *Function) Parent() *Function    { return v.parent }
+func (v *Function) Referrers() *[]Instruction {
+	if v.parent != nil {
+		return &v.referrers
+	}
+	return nil
+}
+
+func (v *Parameter) Type() types.Type          { return v.typ }
+func (v *Parameter) Name() string              { return v.name }
+func (v *Parameter) Object() types.Object      { return v.object }
+func (v *Parameter) Referrers() *[]Instruction { return &v.referrers }
+func (v *Parameter) Pos() token.Pos            { return v.pos }
+func (v *Parameter) Parent() *Function         { return v.parent }
+
+func (v *Alloc) Type() types.Type          { return v.typ }
+func (v *Alloc) Referrers() *[]Instruction { return &v.referrers }
+func (v *Alloc) Pos() token.Pos            { return v.pos }
+
+func (v *register) Type() types.Type          { return v.typ }
+func (v *register) setType(typ types.Type)    { v.typ = typ }
+func (v *register) Name() string              { return fmt.Sprintf("t%d", v.num) }
+func (v *register) setNum(num int)            { v.num = num }
+func (v *register) Referrers() *[]Instruction { return &v.referrers }
+func (v *register) Pos() token.Pos            { return v.pos }
+func (v *register) setPos(pos token.Pos)      { v.pos = pos }
+
+func (v *anInstruction) Parent() *Function          { return v.block.parent }
+func (v *anInstruction) Block() *BasicBlock         { return v.block }
+func (v *anInstruction) setBlock(block *BasicBlock) { v.block = block }
+func (v *anInstruction) Referrers() *[]Instruction  { return nil }
+
+func (t *Type) Name() string                         { return t.object.Name() }
+func (t *Type) Pos() token.Pos                       { return t.object.Pos() }
+func (t *Type) Type() types.Type                     { return t.object.Type() }
+func (t *Type) Token() token.Token                   { return token.TYPE }
+func (t *Type) Object() types.Object                 { return t.object }
+func (t *Type) String() string                       { return t.RelString(nil) }
+func (t *Type) Package() *Package                    { return t.pkg }
+func (t *Type) RelString(from *types.Package) string { return relString(t, from) }
+
+func (c *NamedConst) Name() string                         { return c.object.Name() }
+func (c *NamedConst) Pos() token.Pos                       { return c.object.Pos() }
+func (c *NamedConst) String() string                       { return c.RelString(nil) }
+func (c *NamedConst) Type() types.Type                     { return c.object.Type() }
+func (c *NamedConst) Token() token.Token                   { return token.CONST }
+func (c *NamedConst) Object() types.Object                 { return c.object }
+func (c *NamedConst) Package() *Package                    { return c.pkg }
+func (c *NamedConst) RelString(from *types.Package) string { return relString(c, from) }
+
+// Func returns the package-level function of the specified name,
+// or nil if not found.
+//
+func (p *Package) Func(name string) (f *Function) {
+	f, _ = p.Members[name].(*Function)
+	return
+}
+
+// Var returns the package-level variable of the specified name,
+// or nil if not found.
+//
+func (p *Package) Var(name string) (g *Global) {
+	g, _ = p.Members[name].(*Global)
+	return
+}
+
+// Const returns the package-level constant of the specified name,
+// or nil if not found.
+//
+func (p *Package) Const(name string) (c *NamedConst) {
+	c, _ = p.Members[name].(*NamedConst)
+	return
+}
+
+// Type returns the package-level type of the specified name,
+// or nil if not found.
+//
+func (p *Package) Type(name string) (t *Type) {
+	t, _ = p.Members[name].(*Type)
+	return
+}
+
+func (v *Call) Pos() token.Pos      { return v.Call.pos }
+func (s *Defer) Pos() token.Pos     { return s.pos }
+func (s *Go) Pos() token.Pos        { return s.pos }
+func (s *MapUpdate) Pos() token.Pos { return s.pos }
+func (s *Panic) Pos() token.Pos     { return s.pos }
+func (s *Return) Pos() token.Pos    { return s.pos }
+func (s *Send) Pos() token.Pos      { return s.pos }
+func (s *Store) Pos() token.Pos     { return s.pos }
+func (s *If) Pos() token.Pos        { return token.NoPos }
+func (s *Jump) Pos() token.Pos      { return token.NoPos }
+func (s *RunDefers) Pos() token.Pos { return token.NoPos }
+func (s *DebugRef) Pos() token.Pos  { return s.Expr.Pos() }
+
+// Operands.
+
+func (v *Alloc) Operands(rands []*Value) []*Value {
+	return rands
+}
+
+func (v *BinOp) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X, &v.Y)
+}
+
+func (c *CallCommon) Operands(rands []*Value) []*Value {
+	rands = append(rands, &c.Value)
+	for i := range c.Args {
+		rands = append(rands, &c.Args[i])
+	}
+	return rands
+}
+
+func (s *Go) Operands(rands []*Value) []*Value {
+	return s.Call.Operands(rands)
+}
+
+func (s *Call) Operands(rands []*Value) []*Value {
+	return s.Call.Operands(rands)
+}
+
+func (s *Defer) Operands(rands []*Value) []*Value {
+	return s.Call.Operands(rands)
+}
+
+func (v *ChangeInterface) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X)
+}
+
+func (v *ChangeType) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X)
+}
+
+func (v *Convert) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X)
+}
+
+func (s *DebugRef) Operands(rands []*Value) []*Value {
+	return append(rands, &s.X)
+}
+
+func (v *Extract) Operands(rands []*Value) []*Value {
+	return append(rands, &v.Tuple)
+}
+
+func (v *Field) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X)
+}
+
+func (v *FieldAddr) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X)
+}
+
+func (s *If) Operands(rands []*Value) []*Value {
+	return append(rands, &s.Cond)
+}
+
+func (v *Index) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X, &v.Index)
+}
+
+func (v *IndexAddr) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X, &v.Index)
+}
+
+func (*Jump) Operands(rands []*Value) []*Value {
+	return rands
+}
+
+func (v *Lookup) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X, &v.Index)
+}
+
+func (v *MakeChan) Operands(rands []*Value) []*Value {
+	return append(rands, &v.Size)
+}
+
+func (v *MakeClosure) Operands(rands []*Value) []*Value {
+	rands = append(rands, &v.Fn)
+	for i := range v.Bindings {
+		rands = append(rands, &v.Bindings[i])
+	}
+	return rands
+}
+
+func (v *MakeInterface) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X)
+}
+
+func (v *MakeMap) Operands(rands []*Value) []*Value {
+	return append(rands, &v.Reserve)
+}
+
+func (v *MakeSlice) Operands(rands []*Value) []*Value {
+	return append(rands, &v.Len, &v.Cap)
+}
+
+func (v *MapUpdate) Operands(rands []*Value) []*Value {
+	return append(rands, &v.Map, &v.Key, &v.Value)
+}
+
+func (v *Next) Operands(rands []*Value) []*Value {
+	return append(rands, &v.Iter)
+}
+
+func (s *Panic) Operands(rands []*Value) []*Value {
+	return append(rands, &s.X)
+}
+
+func (v *Phi) Operands(rands []*Value) []*Value {
+	for i := range v.Edges {
+		rands = append(rands, &v.Edges[i])
+	}
+	return rands
+}
+
+func (v *Range) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X)
+}
+
+func (s *Return) Operands(rands []*Value) []*Value {
+	for i := range s.Results {
+		rands = append(rands, &s.Results[i])
+	}
+	return rands
+}
+
+func (*RunDefers) Operands(rands []*Value) []*Value {
+	return rands
+}
+
+func (v *Select) Operands(rands []*Value) []*Value {
+	for i := range v.States {
+		rands = append(rands, &v.States[i].Chan, &v.States[i].Send)
+	}
+	return rands
+}
+
+func (s *Send) Operands(rands []*Value) []*Value {
+	return append(rands, &s.Chan, &s.X)
+}
+
+func (v *Slice) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X, &v.Low, &v.High, &v.Max)
+}
+
+func (s *Store) Operands(rands []*Value) []*Value {
+	return append(rands, &s.Addr, &s.Val)
+}
+
+func (v *TypeAssert) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X)
+}
+
+func (v *UnOp) Operands(rands []*Value) []*Value {
+	return append(rands, &v.X)
+}
+
+// Non-Instruction Values:
+func (v *Builtin) Operands(rands []*Value) []*Value   { return rands }
+func (v *FreeVar) Operands(rands []*Value) []*Value   { return rands }
+func (v *Const) Operands(rands []*Value) []*Value     { return rands }
+func (v *Function) Operands(rands []*Value) []*Value  { return rands }
+func (v *Global) Operands(rands []*Value) []*Value    { return rands }
+func (v *Parameter) Operands(rands []*Value) []*Value { return rands }
diff --git a/go/src/golang.org/x/tools/go/ssa/ssautil/load.go b/go/src/golang.org/x/tools/go/ssa/ssautil/load.go
index c2b8ce1..7c57838 100644
--- a/go/src/golang.org/x/tools/go/ssa/ssautil/load.go
+++ b/go/src/golang.org/x/tools/go/ssa/ssautil/load.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package ssautil
 
 // This file defines utility functions for constructing programs in SSA form.
@@ -9,10 +11,10 @@
 import (
 	"go/ast"
 	"go/token"
+	"go/types"
 
 	"golang.org/x/tools/go/loader"
 	"golang.org/x/tools/go/ssa"
-	"golang.org/x/tools/go/types"
 )
 
 // CreateProgram returns a new program in SSA form, given a program
diff --git a/go/src/golang.org/x/tools/go/ssa/ssautil/load14.go b/go/src/golang.org/x/tools/go/ssa/ssautil/load14.go
new file mode 100644
index 0000000..752a9d9
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/ssa/ssautil/load14.go
@@ -0,0 +1,97 @@
+// Copyright 2015 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.
+
+// +build !go1.5
+
+package ssautil
+
+// This file defines utility functions for constructing programs in SSA form.
+
+import (
+	"go/ast"
+	"go/token"
+
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/types"
+)
+
+// CreateProgram returns a new program in SSA form, given a program
+// loaded from source.  An SSA package is created for each transitively
+// error-free package of lprog.
+//
+// Code for bodies of functions is not built until BuildAll() is called
+// on the result.
+//
+// mode controls diagnostics and checking during SSA construction.
+//
+func CreateProgram(lprog *loader.Program, mode ssa.BuilderMode) *ssa.Program {
+	prog := ssa.NewProgram(lprog.Fset, mode)
+
+	for _, info := range lprog.AllPackages {
+		if info.TransitivelyErrorFree {
+			prog.CreatePackage(info.Pkg, info.Files, &info.Info, info.Importable)
+		}
+	}
+
+	return prog
+}
+
+// BuildPackage builds an SSA program with IR for a single package.
+//
+// It populates pkg by type-checking the specified file ASTs.  All
+// dependencies are loaded using the importer specified by tc, which
+// typically loads compiler export data; SSA code cannot be built for
+// those packages.  BuildPackage then constructs an ssa.Program with all
+// dependency packages created, and builds and returns the SSA package
+// corresponding to pkg.
+//
+// The caller must have set pkg.Path() to the import path.
+//
+// The operation fails if there were any type-checking or import errors.
+//
+// See ../ssa/example_test.go for an example.
+//
+func BuildPackage(tc *types.Config, fset *token.FileSet, pkg *types.Package, files []*ast.File, mode ssa.BuilderMode) (*ssa.Package, *types.Info, error) {
+	if fset == nil {
+		panic("no token.FileSet")
+	}
+	if pkg.Path() == "" {
+		panic("package has no import path")
+	}
+
+	info := &types.Info{
+		Types:      make(map[ast.Expr]types.TypeAndValue),
+		Defs:       make(map[*ast.Ident]types.Object),
+		Uses:       make(map[*ast.Ident]types.Object),
+		Implicits:  make(map[ast.Node]types.Object),
+		Scopes:     make(map[ast.Node]*types.Scope),
+		Selections: make(map[*ast.SelectorExpr]*types.Selection),
+	}
+	if err := types.NewChecker(tc, fset, pkg, info).Files(files); err != nil {
+		return nil, nil, err
+	}
+
+	prog := ssa.NewProgram(fset, mode)
+
+	// Create SSA packages for all imports.
+	// Order is not significant.
+	created := make(map[*types.Package]bool)
+	var createAll func(pkgs []*types.Package)
+	createAll = func(pkgs []*types.Package) {
+		for _, p := range pkgs {
+			if !created[p] {
+				created[p] = true
+				prog.CreatePackage(p, nil, nil, true)
+				createAll(p.Imports())
+			}
+		}
+	}
+	createAll(pkg.Imports())
+
+	// Create and build the primary package.
+	ssapkg := prog.CreatePackage(pkg, files, info, false)
+	ssapkg.Build()
+	return ssapkg, info, nil
+}
diff --git a/go/src/golang.org/x/tools/go/ssa/ssautil/load14_test.go b/go/src/golang.org/x/tools/go/ssa/ssautil/load14_test.go
new file mode 100644
index 0000000..41955ec
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/ssa/ssautil/load14_test.go
@@ -0,0 +1,67 @@
+// Copyright 2015 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.
+
+// +build !go1.5
+
+package ssautil_test
+
+import (
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"os"
+	"testing"
+
+	"golang.org/x/tools/go/ssa/ssautil"
+	"golang.org/x/tools/go/types"
+
+	_ "golang.org/x/tools/go/gcimporter"
+)
+
+const hello = `package main
+
+import "fmt"
+
+func main() {
+	fmt.Println("Hello, world")
+}
+`
+
+func TestBuildPackage(t *testing.T) {
+	// There is a more substantial test of BuildPackage and the
+	// SSA program it builds in ../ssa/builder_test.go.
+
+	fset := token.NewFileSet()
+	f, err := parser.ParseFile(fset, "hello.go", hello, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	pkg := types.NewPackage("hello", "")
+	ssapkg, _, err := ssautil.BuildPackage(new(types.Config), fset, pkg, []*ast.File{f}, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if pkg.Name() != "main" {
+		t.Errorf("pkg.Name() = %s, want main", pkg.Name())
+	}
+	if ssapkg.Func("main") == nil {
+		ssapkg.WriteTo(os.Stderr)
+		t.Errorf("ssapkg has no main function")
+	}
+}
+
+func TestBuildPackage_MissingImport(t *testing.T) {
+	fset := token.NewFileSet()
+	f, err := parser.ParseFile(fset, "bad.go", `package bad; import "missing"`, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	pkg := types.NewPackage("bad", "")
+	ssapkg, _, err := ssautil.BuildPackage(new(types.Config), fset, pkg, []*ast.File{f}, 0)
+	if err == nil || ssapkg != nil {
+		t.Fatal("BuildPackage succeeded unexpectedly")
+	}
+}
diff --git a/go/src/golang.org/x/tools/go/ssa/ssautil/load_test.go b/go/src/golang.org/x/tools/go/ssa/ssautil/load_test.go
index 458d2dc..8ce73bc 100644
--- a/go/src/golang.org/x/tools/go/ssa/ssautil/load_test.go
+++ b/go/src/golang.org/x/tools/go/ssa/ssautil/load_test.go
@@ -2,19 +2,20 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package ssautil_test
 
 import (
 	"go/ast"
+	"go/importer"
 	"go/parser"
 	"go/token"
+	"go/types"
 	"os"
 	"testing"
 
 	"golang.org/x/tools/go/ssa/ssautil"
-	"golang.org/x/tools/go/types"
-
-	_ "golang.org/x/tools/go/gcimporter"
 )
 
 const hello = `package main
@@ -37,7 +38,7 @@
 	}
 
 	pkg := types.NewPackage("hello", "")
-	ssapkg, _, err := ssautil.BuildPackage(new(types.Config), fset, pkg, []*ast.File{f}, 0)
+	ssapkg, _, err := ssautil.BuildPackage(&types.Config{Importer: importer.Default()}, fset, pkg, []*ast.File{f}, 0)
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/go/src/golang.org/x/tools/go/ssa/ssautil/switch.go b/go/src/golang.org/x/tools/go/ssa/ssautil/switch.go
index 70fff9c..2fcc167 100644
--- a/go/src/golang.org/x/tools/go/ssa/ssautil/switch.go
+++ b/go/src/golang.org/x/tools/go/ssa/ssautil/switch.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package ssautil
 
 // This file implements discovery of switch and type-switch constructs
@@ -22,9 +24,9 @@
 	"bytes"
 	"fmt"
 	"go/token"
+	"go/types"
 
 	"golang.org/x/tools/go/ssa"
-	"golang.org/x/tools/go/types"
 )
 
 // A ConstCase represents a single constant comparison.
diff --git a/go/src/golang.org/x/tools/go/ssa/ssautil/switch14.go b/go/src/golang.org/x/tools/go/ssa/ssautil/switch14.go
new file mode 100644
index 0000000..b2f7f21
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/ssa/ssautil/switch14.go
@@ -0,0 +1,236 @@
+// 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.
+
+// +build !go1.5
+
+package ssautil
+
+// This file implements discovery of switch and type-switch constructs
+// from low-level control flow.
+//
+// Many techniques exist for compiling a high-level switch with
+// constant cases to efficient machine code.  The optimal choice will
+// depend on the data type, the specific case values, the code in the
+// body of each case, and the hardware.
+// Some examples:
+// - a lookup table (for a switch that maps constants to constants)
+// - a computed goto
+// - a binary tree
+// - a perfect hash
+// - a two-level switch (to partition constant strings by their first byte).
+
+import (
+	"bytes"
+	"fmt"
+	"go/token"
+
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/types"
+)
+
+// A ConstCase represents a single constant comparison.
+// It is part of a Switch.
+type ConstCase struct {
+	Block *ssa.BasicBlock // block performing the comparison
+	Body  *ssa.BasicBlock // body of the case
+	Value *ssa.Const      // case comparand
+}
+
+// A TypeCase represents a single type assertion.
+// It is part of a Switch.
+type TypeCase struct {
+	Block   *ssa.BasicBlock // block performing the type assert
+	Body    *ssa.BasicBlock // body of the case
+	Type    types.Type      // case type
+	Binding ssa.Value       // value bound by this case
+}
+
+// A Switch is a logical high-level control flow operation
+// (a multiway branch) discovered by analysis of a CFG containing
+// only if/else chains.  It is not part of the ssa.Instruction set.
+//
+// One of ConstCases and TypeCases has length >= 2;
+// the other is nil.
+//
+// In a value switch, the list of cases may contain duplicate constants.
+// A type switch may contain duplicate types, or types assignable
+// to an interface type also in the list.
+// TODO(adonovan): eliminate such duplicates.
+//
+type Switch struct {
+	Start      *ssa.BasicBlock // block containing start of if/else chain
+	X          ssa.Value       // the switch operand
+	ConstCases []ConstCase     // ordered list of constant comparisons
+	TypeCases  []TypeCase      // ordered list of type assertions
+	Default    *ssa.BasicBlock // successor if all comparisons fail
+}
+
+func (sw *Switch) String() string {
+	// We represent each block by the String() of its
+	// first Instruction, e.g. "print(42:int)".
+	var buf bytes.Buffer
+	if sw.ConstCases != nil {
+		fmt.Fprintf(&buf, "switch %s {\n", sw.X.Name())
+		for _, c := range sw.ConstCases {
+			fmt.Fprintf(&buf, "case %s: %s\n", c.Value, c.Body.Instrs[0])
+		}
+	} else {
+		fmt.Fprintf(&buf, "switch %s.(type) {\n", sw.X.Name())
+		for _, c := range sw.TypeCases {
+			fmt.Fprintf(&buf, "case %s %s: %s\n",
+				c.Binding.Name(), c.Type, c.Body.Instrs[0])
+		}
+	}
+	if sw.Default != nil {
+		fmt.Fprintf(&buf, "default: %s\n", sw.Default.Instrs[0])
+	}
+	fmt.Fprintf(&buf, "}")
+	return buf.String()
+}
+
+// Switches examines the control-flow graph of fn and returns the
+// set of inferred value and type switches.  A value switch tests an
+// ssa.Value for equality against two or more compile-time constant
+// values.  Switches involving link-time constants (addresses) are
+// ignored.  A type switch type-asserts an ssa.Value against two or
+// more types.
+//
+// The switches are returned in dominance order.
+//
+// The resulting switches do not necessarily correspond to uses of the
+// 'switch' keyword in the source: for example, a single source-level
+// switch statement with non-constant cases may result in zero, one or
+// many Switches, one per plural sequence of constant cases.
+// Switches may even be inferred from if/else- or goto-based control flow.
+// (In general, the control flow constructs of the source program
+// cannot be faithfully reproduced from the SSA representation.)
+//
+func Switches(fn *ssa.Function) []Switch {
+	// Traverse the CFG in dominance order, so we don't
+	// enter an if/else-chain in the middle.
+	var switches []Switch
+	seen := make(map[*ssa.BasicBlock]bool) // TODO(adonovan): opt: use ssa.blockSet
+	for _, b := range fn.DomPreorder() {
+		if x, k := isComparisonBlock(b); x != nil {
+			// Block b starts a switch.
+			sw := Switch{Start: b, X: x}
+			valueSwitch(&sw, k, seen)
+			if len(sw.ConstCases) > 1 {
+				switches = append(switches, sw)
+			}
+		}
+
+		if y, x, T := isTypeAssertBlock(b); y != nil {
+			// Block b starts a type switch.
+			sw := Switch{Start: b, X: x}
+			typeSwitch(&sw, y, T, seen)
+			if len(sw.TypeCases) > 1 {
+				switches = append(switches, sw)
+			}
+		}
+	}
+	return switches
+}
+
+func valueSwitch(sw *Switch, k *ssa.Const, seen map[*ssa.BasicBlock]bool) {
+	b := sw.Start
+	x := sw.X
+	for x == sw.X {
+		if seen[b] {
+			break
+		}
+		seen[b] = true
+
+		sw.ConstCases = append(sw.ConstCases, ConstCase{
+			Block: b,
+			Body:  b.Succs[0],
+			Value: k,
+		})
+		b = b.Succs[1]
+		if len(b.Instrs) > 2 {
+			// Block b contains not just 'if x == k',
+			// so it may have side effects that
+			// make it unsafe to elide.
+			break
+		}
+		if len(b.Preds) != 1 {
+			// Block b has multiple predecessors,
+			// so it cannot be treated as a case.
+			break
+		}
+		x, k = isComparisonBlock(b)
+	}
+	sw.Default = b
+}
+
+func typeSwitch(sw *Switch, y ssa.Value, T types.Type, seen map[*ssa.BasicBlock]bool) {
+	b := sw.Start
+	x := sw.X
+	for x == sw.X {
+		if seen[b] {
+			break
+		}
+		seen[b] = true
+
+		sw.TypeCases = append(sw.TypeCases, TypeCase{
+			Block:   b,
+			Body:    b.Succs[0],
+			Type:    T,
+			Binding: y,
+		})
+		b = b.Succs[1]
+		if len(b.Instrs) > 4 {
+			// Block b contains not just
+			//  {TypeAssert; Extract #0; Extract #1; If}
+			// so it may have side effects that
+			// make it unsafe to elide.
+			break
+		}
+		if len(b.Preds) != 1 {
+			// Block b has multiple predecessors,
+			// so it cannot be treated as a case.
+			break
+		}
+		y, x, T = isTypeAssertBlock(b)
+	}
+	sw.Default = b
+}
+
+// isComparisonBlock returns the operands (v, k) if a block ends with
+// a comparison v==k, where k is a compile-time constant.
+//
+func isComparisonBlock(b *ssa.BasicBlock) (v ssa.Value, k *ssa.Const) {
+	if n := len(b.Instrs); n >= 2 {
+		if i, ok := b.Instrs[n-1].(*ssa.If); ok {
+			if binop, ok := i.Cond.(*ssa.BinOp); ok && binop.Block() == b && binop.Op == token.EQL {
+				if k, ok := binop.Y.(*ssa.Const); ok {
+					return binop.X, k
+				}
+				if k, ok := binop.X.(*ssa.Const); ok {
+					return binop.Y, k
+				}
+			}
+		}
+	}
+	return
+}
+
+// isTypeAssertBlock returns the operands (y, x, T) if a block ends with
+// a type assertion "if y, ok := x.(T); ok {".
+//
+func isTypeAssertBlock(b *ssa.BasicBlock) (y, x ssa.Value, T types.Type) {
+	if n := len(b.Instrs); n >= 4 {
+		if i, ok := b.Instrs[n-1].(*ssa.If); ok {
+			if ext1, ok := i.Cond.(*ssa.Extract); ok && ext1.Block() == b && ext1.Index == 1 {
+				if ta, ok := ext1.Tuple.(*ssa.TypeAssert); ok && ta.Block() == b {
+					// hack: relies upon instruction ordering.
+					if ext0, ok := b.Instrs[n-3].(*ssa.Extract); ok {
+						return ext0, ta.X, ta.AssertedType
+					}
+				}
+			}
+		}
+	}
+	return
+}
diff --git a/go/src/golang.org/x/tools/go/ssa/ssautil/visit.go b/go/src/golang.org/x/tools/go/ssa/ssautil/visit.go
index 30843c3..6c51f93 100644
--- a/go/src/golang.org/x/tools/go/ssa/ssautil/visit.go
+++ b/go/src/golang.org/x/tools/go/ssa/ssautil/visit.go
@@ -44,7 +44,7 @@
 	for _, T := range visit.prog.RuntimeTypes() {
 		mset := visit.prog.MethodSets.MethodSet(T)
 		for i, n := 0, mset.Len(); i < n; i++ {
-			visit.function(visit.prog.Method(mset.At(i)))
+			visit.function(visit.prog.MethodValue(mset.At(i)))
 		}
 	}
 }
diff --git a/go/src/golang.org/x/tools/go/ssa/stdlib_test.go b/go/src/golang.org/x/tools/go/ssa/stdlib_test.go
index d339d07..99c615d 100644
--- a/go/src/golang.org/x/tools/go/ssa/stdlib_test.go
+++ b/go/src/golang.org/x/tools/go/ssa/stdlib_test.go
@@ -27,6 +27,18 @@
 	"golang.org/x/tools/go/ssa/ssautil"
 )
 
+// Skip the set of packages that transitively depend on
+// cmd/internal/objfile, which uses vendoring,
+// which go/loader does not yet support.
+// TODO(adonovan): add support for vendoring and delete this.
+var skip = map[string]bool{
+	"cmd/addr2line":        true,
+	"cmd/internal/objfile": true,
+	"cmd/nm":               true,
+	"cmd/objdump":          true,
+	"cmd/pprof":            true,
+}
+
 func bytesAllocated() uint64 {
 	runtime.GC()
 	var stats runtime.MemStats
@@ -35,6 +47,9 @@
 }
 
 func TestStdlib(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping in short mode; too slow (golang.org/issue/14113)")
+	}
 	// Load, parse and type-check the program.
 	t0 := time.Now()
 	alloc0 := bytesAllocated()
@@ -43,9 +58,11 @@
 	ctxt := build.Default // copy
 	ctxt.GOPATH = ""      // disable GOPATH
 	conf := loader.Config{Build: &ctxt}
-	if _, err := conf.FromArgs(buildutil.AllPackages(conf.Build), true); err != nil {
-		t.Errorf("FromArgs failed: %v", err)
-		return
+	for _, path := range buildutil.AllPackages(conf.Build) {
+		if skip[path] {
+			continue
+		}
+		conf.ImportWithTests(path)
 	}
 
 	iprog, err := conf.Load()
@@ -66,7 +83,7 @@
 	t2 := time.Now()
 
 	// Build SSA.
-	prog.BuildAll()
+	prog.Build()
 
 	t3 := time.Now()
 	alloc3 := bytesAllocated()
diff --git a/go/src/golang.org/x/tools/go/ssa/testdata/valueforexpr.go b/go/src/golang.org/x/tools/go/ssa/testdata/valueforexpr.go
index 028c153..4a2cb85 100644
--- a/go/src/golang.org/x/tools/go/ssa/testdata/valueforexpr.go
+++ b/go/src/golang.org/x/tools/go/ssa/testdata/valueforexpr.go
@@ -12,7 +12,11 @@
 	_ = /*@Parameter*/ (unspilled)
 	_ = /*@<nil>*/ (1 + 2) // (constant)
 	i := 0
+
+	f := func() (int, int) { return 0, 0 }
+
 	/*@Call*/ (print( /*@BinOp*/ (i + 1)))
+	_, _ = /*@Call*/ (f())
 	ch := /*@MakeChan*/ (make(chan int))
 	/*@UnOp*/ (<-ch)
 	x := /*@UnOp*/ (<-ch)
diff --git a/go/src/golang.org/x/tools/go/ssa/testmain.go b/go/src/golang.org/x/tools/go/ssa/testmain.go
index a7b1242..48b184a 100644
--- a/go/src/golang.org/x/tools/go/ssa/testmain.go
+++ b/go/src/golang.org/x/tools/go/ssa/testmain.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package ssa
 
 // CreateTestMainPackage synthesizes a main package that runs all the
@@ -10,13 +12,12 @@
 
 import (
 	"go/ast"
+	exact "go/constant"
 	"go/token"
+	"go/types"
 	"os"
 	"sort"
 	"strings"
-
-	"golang.org/x/tools/go/exact"
-	"golang.org/x/tools/go/types"
 )
 
 // FindTests returns the list of packages that define at least one Test,
@@ -102,7 +103,7 @@
 		Prog:    prog,
 		Members: make(map[string]Member),
 		values:  make(map[types.Object]Value),
-		Object:  types.NewPackage("test$main", "main"),
+		Pkg:     types.NewPackage("test$main", "main"),
 	}
 
 	// Build package's init function.
@@ -127,23 +128,23 @@
 		v.setType(types.NewTuple())
 		init.emit(&v)
 
-		pkgpaths = append(pkgpaths, pkg.Object.Path())
+		pkgpaths = append(pkgpaths, pkg.Pkg.Path())
 	}
 	sort.Strings(pkgpaths)
 	init.emit(new(Return))
 	init.finishBody()
 	testmain.init = init
-	testmain.Object.MarkComplete()
+	testmain.Pkg.MarkComplete()
 	testmain.Members[init.name] = init
 
 	// For debugging convenience, define an unexported const
 	// that enumerates the packages.
-	packagesConst := types.NewConst(token.NoPos, testmain.Object, "packages", tString,
+	packagesConst := types.NewConst(token.NoPos, testmain.Pkg, "packages", tString,
 		exact.MakeString(strings.Join(pkgpaths, " ")))
 	memberFromObject(testmain, packagesConst, nil)
 
 	// Create main *types.Func and *ssa.Function
-	mainFunc := types.NewFunc(token.NoPos, testmain.Object, "main", new(types.Signature))
+	mainFunc := types.NewFunc(token.NoPos, testmain.Pkg, "main", new(types.Signature))
 	memberFromObject(testmain, mainFunc, nil)
 	main := testmain.Func("main")
 	main.Synthetic = "test main function"
@@ -222,7 +223,7 @@
 		sanityCheckPackage(testmain)
 	}
 
-	prog.packages[testmain.Object] = testmain
+	prog.packages[testmain.Pkg] = testmain
 
 	return testmain
 }
@@ -241,6 +242,12 @@
 	tPtrElem := types.NewPointer(tElem)
 	tPtrFunc := types.NewPointer(funcField(slice))
 
+	// TODO(adonovan): fix: populate the
+	// testing.InternalExample.Output field correctly so that tests
+	// work correctly under the interpreter.  This requires that we
+	// do this step using ASTs, not *ssa.Functions---quite a
+	// redesign.  See also the fake runExample in go/ssa/interp.
+
 	// Emit: array = new [n]testing.InternalTest
 	tArray := types.NewArray(tElem, int64(len(testfuncs)))
 	array := emitNew(fn, tArray, token.NoPos)
diff --git a/go/src/golang.org/x/tools/go/ssa/testmain14.go b/go/src/golang.org/x/tools/go/ssa/testmain14.go
new file mode 100644
index 0000000..ddd27a1
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/ssa/testmain14.go
@@ -0,0 +1,304 @@
+// 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.
+
+// +build !go1.5
+
+package ssa
+
+// CreateTestMainPackage synthesizes a main package that runs all the
+// tests of the supplied packages.
+// It is closely coupled to $GOROOT/src/cmd/go/test.go and $GOROOT/src/testing.
+
+import (
+	"go/ast"
+	"go/token"
+	"os"
+	"sort"
+	"strings"
+
+	"golang.org/x/tools/go/exact"
+	"golang.org/x/tools/go/types"
+)
+
+// FindTests returns the list of packages that define at least one Test,
+// Example or Benchmark function (as defined by "go test"), and the
+// lists of all such functions.
+//
+func FindTests(pkgs []*Package) (testpkgs []*Package, tests, benchmarks, examples []*Function) {
+	if len(pkgs) == 0 {
+		return
+	}
+	prog := pkgs[0].Prog
+
+	// The first two of these may be nil: if the program doesn't import "testing",
+	// it can't contain any tests, but it may yet contain Examples.
+	var testSig *types.Signature                              // func(*testing.T)
+	var benchmarkSig *types.Signature                         // func(*testing.B)
+	var exampleSig = types.NewSignature(nil, nil, nil, false) // func()
+
+	// Obtain the types from the parameters of testing.Main().
+	if testingPkg := prog.ImportedPackage("testing"); testingPkg != nil {
+		params := testingPkg.Func("Main").Signature.Params()
+		testSig = funcField(params.At(1).Type())
+		benchmarkSig = funcField(params.At(2).Type())
+	}
+
+	seen := make(map[*Package]bool)
+	for _, pkg := range pkgs {
+		if pkg.Prog != prog {
+			panic("wrong Program")
+		}
+
+		// TODO(adonovan): use a stable order, e.g. lexical.
+		for _, mem := range pkg.Members {
+			if f, ok := mem.(*Function); ok &&
+				ast.IsExported(f.Name()) &&
+				strings.HasSuffix(prog.Fset.Position(f.Pos()).Filename, "_test.go") {
+
+				switch {
+				case testSig != nil && isTestSig(f, "Test", testSig):
+					tests = append(tests, f)
+				case benchmarkSig != nil && isTestSig(f, "Benchmark", benchmarkSig):
+					benchmarks = append(benchmarks, f)
+				case isTestSig(f, "Example", exampleSig):
+					examples = append(examples, f)
+				default:
+					continue
+				}
+
+				if !seen[pkg] {
+					seen[pkg] = true
+					testpkgs = append(testpkgs, pkg)
+				}
+			}
+		}
+	}
+	return
+}
+
+// Like isTest, but checks the signature too.
+func isTestSig(f *Function, prefix string, sig *types.Signature) bool {
+	return isTest(f.Name(), prefix) && types.Identical(f.Signature, sig)
+}
+
+// If non-nil, testMainStartBodyHook is called immediately after
+// startBody for main.init and main.main, making it easy for users to
+// add custom imports and initialization steps for proprietary build
+// systems that don't exactly follow 'go test' conventions.
+var testMainStartBodyHook func(*Function)
+
+// CreateTestMainPackage creates and returns a synthetic "main"
+// package that runs all the tests of the supplied packages, similar
+// to the one that would be created by the 'go test' tool.
+//
+// It returns nil if the program contains no tests.
+//
+func (prog *Program) CreateTestMainPackage(pkgs ...*Package) *Package {
+	pkgs, tests, benchmarks, examples := FindTests(pkgs)
+	if len(pkgs) == 0 {
+		return nil
+	}
+
+	testmain := &Package{
+		Prog:    prog,
+		Members: make(map[string]Member),
+		values:  make(map[types.Object]Value),
+		Pkg:     types.NewPackage("test$main", "main"),
+	}
+
+	// Build package's init function.
+	init := &Function{
+		name:      "init",
+		Signature: new(types.Signature),
+		Synthetic: "package initializer",
+		Pkg:       testmain,
+		Prog:      prog,
+	}
+	init.startBody()
+
+	if testMainStartBodyHook != nil {
+		testMainStartBodyHook(init)
+	}
+
+	// Initialize packages to test.
+	var pkgpaths []string
+	for _, pkg := range pkgs {
+		var v Call
+		v.Call.Value = pkg.init
+		v.setType(types.NewTuple())
+		init.emit(&v)
+
+		pkgpaths = append(pkgpaths, pkg.Pkg.Path())
+	}
+	sort.Strings(pkgpaths)
+	init.emit(new(Return))
+	init.finishBody()
+	testmain.init = init
+	testmain.Pkg.MarkComplete()
+	testmain.Members[init.name] = init
+
+	// For debugging convenience, define an unexported const
+	// that enumerates the packages.
+	packagesConst := types.NewConst(token.NoPos, testmain.Pkg, "packages", tString,
+		exact.MakeString(strings.Join(pkgpaths, " ")))
+	memberFromObject(testmain, packagesConst, nil)
+
+	// Create main *types.Func and *ssa.Function
+	mainFunc := types.NewFunc(token.NoPos, testmain.Pkg, "main", new(types.Signature))
+	memberFromObject(testmain, mainFunc, nil)
+	main := testmain.Func("main")
+	main.Synthetic = "test main function"
+
+	main.startBody()
+
+	if testMainStartBodyHook != nil {
+		testMainStartBodyHook(main)
+	}
+
+	if testingPkg := prog.ImportedPackage("testing"); testingPkg != nil {
+		testingMain := testingPkg.Func("Main")
+		testingMainParams := testingMain.Signature.Params()
+
+		// The generated code is as if compiled from this:
+		//
+		// func main() {
+		//      match      := func(_, _ string) (bool, error) { return true, nil }
+		//      tests      := []testing.InternalTest{{"TestFoo", TestFoo}, ...}
+		//      benchmarks := []testing.InternalBenchmark{...}
+		//      examples   := []testing.InternalExample{...}
+		// 	testing.Main(match, tests, benchmarks, examples)
+		// }
+
+		matcher := &Function{
+			name:      "matcher",
+			Signature: testingMainParams.At(0).Type().(*types.Signature),
+			Synthetic: "test matcher predicate",
+			parent:    main,
+			Pkg:       testmain,
+			Prog:      prog,
+		}
+		main.AnonFuncs = append(main.AnonFuncs, matcher)
+		matcher.startBody()
+		matcher.emit(&Return{Results: []Value{vTrue, nilConst(types.Universe.Lookup("error").Type())}})
+		matcher.finishBody()
+
+		// Emit call: testing.Main(matcher, tests, benchmarks, examples).
+		var c Call
+		c.Call.Value = testingMain
+		c.Call.Args = []Value{
+			matcher,
+			testMainSlice(main, tests, testingMainParams.At(1).Type()),
+			testMainSlice(main, benchmarks, testingMainParams.At(2).Type()),
+			testMainSlice(main, examples, testingMainParams.At(3).Type()),
+		}
+		emitTailCall(main, &c)
+	} else {
+		// The program does not import "testing", but FindTests
+		// returned non-nil, which must mean there were Examples
+		// but no Tests or Benchmarks.
+		// We'll simply call them from testmain.main; this will
+		// ensure they don't panic, but will not check any
+		// "Output:" comments.
+		for _, eg := range examples {
+			var c Call
+			c.Call.Value = eg
+			c.setType(types.NewTuple())
+			main.emit(&c)
+		}
+		main.emit(&Return{})
+		main.currentBlock = nil
+	}
+
+	main.finishBody()
+
+	testmain.Members["main"] = main
+
+	if prog.mode&PrintPackages != 0 {
+		printMu.Lock()
+		testmain.WriteTo(os.Stdout)
+		printMu.Unlock()
+	}
+
+	if prog.mode&SanityCheckFunctions != 0 {
+		sanityCheckPackage(testmain)
+	}
+
+	prog.packages[testmain.Pkg] = testmain
+
+	return testmain
+}
+
+// testMainSlice emits to fn code to construct a slice of type slice
+// (one of []testing.Internal{Test,Benchmark,Example}) for all
+// functions in testfuncs.  It returns the slice value.
+//
+func testMainSlice(fn *Function, testfuncs []*Function, slice types.Type) Value {
+	if testfuncs == nil {
+		return nilConst(slice)
+	}
+
+	tElem := slice.(*types.Slice).Elem()
+	tPtrString := types.NewPointer(tString)
+	tPtrElem := types.NewPointer(tElem)
+	tPtrFunc := types.NewPointer(funcField(slice))
+
+	// TODO(adonovan): fix: populate the
+	// testing.InternalExample.Output field correctly so that tests
+	// work correctly under the interpreter.  This requires that we
+	// do this step using ASTs, not *ssa.Functions---quite a
+	// redesign.  See also the fake runExample in go/ssa/interp.
+
+	// Emit: array = new [n]testing.InternalTest
+	tArray := types.NewArray(tElem, int64(len(testfuncs)))
+	array := emitNew(fn, tArray, token.NoPos)
+	array.Comment = "test main"
+	for i, testfunc := range testfuncs {
+		// Emit: pitem = &array[i]
+		ia := &IndexAddr{X: array, Index: intConst(int64(i))}
+		ia.setType(tPtrElem)
+		pitem := fn.emit(ia)
+
+		// Emit: pname = &pitem.Name
+		fa := &FieldAddr{X: pitem, Field: 0} // .Name
+		fa.setType(tPtrString)
+		pname := fn.emit(fa)
+
+		// Emit: *pname = "testfunc"
+		emitStore(fn, pname, stringConst(testfunc.Name()), token.NoPos)
+
+		// Emit: pfunc = &pitem.F
+		fa = &FieldAddr{X: pitem, Field: 1} // .F
+		fa.setType(tPtrFunc)
+		pfunc := fn.emit(fa)
+
+		// Emit: *pfunc = testfunc
+		emitStore(fn, pfunc, testfunc, token.NoPos)
+	}
+
+	// Emit: slice array[:]
+	sl := &Slice{X: array}
+	sl.setType(slice)
+	return fn.emit(sl)
+}
+
+// Given the type of one of the three slice parameters of testing.Main,
+// returns the function type.
+func funcField(slice types.Type) *types.Signature {
+	return slice.(*types.Slice).Elem().Underlying().(*types.Struct).Field(1).Type().(*types.Signature)
+}
+
+// Plundered from $GOROOT/src/cmd/go/test.go
+
+// isTest tells whether name looks like a test (or benchmark, according to prefix).
+// It is a Test (say) if there is a character after Test that is not a lower-case letter.
+// We don't want TesticularCancer.
+func isTest(name, prefix string) bool {
+	if !strings.HasPrefix(name, prefix) {
+		return false
+	}
+	if len(name) == len(prefix) { // "Test" is ok
+		return true
+	}
+	return ast.IsExported(name[len(prefix):])
+}
diff --git a/go/src/golang.org/x/tools/go/ssa/util.go b/go/src/golang.org/x/tools/go/ssa/util.go
index 4f9d43d..317a013 100644
--- a/go/src/golang.org/x/tools/go/ssa/util.go
+++ b/go/src/golang.org/x/tools/go/ssa/util.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package ssa
 
 // This file defines a number of miscellaneous utility functions.
@@ -10,11 +12,11 @@
 	"fmt"
 	"go/ast"
 	"go/token"
+	"go/types"
 	"io"
 	"os"
 
 	"golang.org/x/tools/go/ast/astutil"
-	"golang.org/x/tools/go/types"
 )
 
 //// AST utilities
diff --git a/go/src/golang.org/x/tools/go/ssa/util14.go b/go/src/golang.org/x/tools/go/ssa/util14.go
new file mode 100644
index 0000000..444d69c
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/ssa/util14.go
@@ -0,0 +1,121 @@
+// 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.
+
+// +build !go1.5
+
+package ssa
+
+// This file defines a number of miscellaneous utility functions.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"io"
+	"os"
+
+	"golang.org/x/tools/go/ast/astutil"
+	"golang.org/x/tools/go/types"
+)
+
+//// AST utilities
+
+func unparen(e ast.Expr) ast.Expr { return astutil.Unparen(e) }
+
+// isBlankIdent returns true iff e is an Ident with name "_".
+// They have no associated types.Object, and thus no type.
+//
+func isBlankIdent(e ast.Expr) bool {
+	id, ok := e.(*ast.Ident)
+	return ok && id.Name == "_"
+}
+
+//// Type utilities.  Some of these belong in go/types.
+
+// isPointer returns true for types whose underlying type is a pointer.
+func isPointer(typ types.Type) bool {
+	_, ok := typ.Underlying().(*types.Pointer)
+	return ok
+}
+
+func isInterface(T types.Type) bool { return types.IsInterface(T) }
+
+// deref returns a pointer's element type; otherwise it returns typ.
+func deref(typ types.Type) types.Type {
+	if p, ok := typ.Underlying().(*types.Pointer); ok {
+		return p.Elem()
+	}
+	return typ
+}
+
+// recvType returns the receiver type of method obj.
+func recvType(obj *types.Func) types.Type {
+	return obj.Type().(*types.Signature).Recv().Type()
+}
+
+// DefaultType returns the default "typed" type for an "untyped" type;
+// it returns the incoming type for all other types.  The default type
+// for untyped nil is untyped nil.
+//
+// Exported to ssa/interp.
+//
+// TODO(gri): this is a copy of go/types.defaultType; export that function.
+//
+func DefaultType(typ types.Type) types.Type {
+	if t, ok := typ.(*types.Basic); ok {
+		k := t.Kind()
+		switch k {
+		case types.UntypedBool:
+			k = types.Bool
+		case types.UntypedInt:
+			k = types.Int
+		case types.UntypedRune:
+			k = types.Rune
+		case types.UntypedFloat:
+			k = types.Float64
+		case types.UntypedComplex:
+			k = types.Complex128
+		case types.UntypedString:
+			k = types.String
+		}
+		typ = types.Typ[k]
+	}
+	return typ
+}
+
+// logStack prints the formatted "start" message to stderr and
+// returns a closure that prints the corresponding "end" message.
+// Call using 'defer logStack(...)()' to show builder stack on panic.
+// Don't forget trailing parens!
+//
+func logStack(format string, args ...interface{}) func() {
+	msg := fmt.Sprintf(format, args...)
+	io.WriteString(os.Stderr, msg)
+	io.WriteString(os.Stderr, "\n")
+	return func() {
+		io.WriteString(os.Stderr, msg)
+		io.WriteString(os.Stderr, " end\n")
+	}
+}
+
+// newVar creates a 'var' for use in a types.Tuple.
+func newVar(name string, typ types.Type) *types.Var {
+	return types.NewParam(token.NoPos, nil, name, typ)
+}
+
+// anonVar creates an anonymous 'var' for use in a types.Tuple.
+func anonVar(typ types.Type) *types.Var {
+	return newVar("", typ)
+}
+
+var lenResults = types.NewTuple(anonVar(tInt))
+
+// makeLen returns the len builtin specialized to type func(T)int.
+func makeLen(T types.Type) *Builtin {
+	lenParams := types.NewTuple(anonVar(T))
+	return &Builtin{
+		name: "len",
+		sig:  types.NewSignature(nil, lenParams, lenResults, false),
+	}
+}
diff --git a/go/src/golang.org/x/tools/go/ssa/wrappers.go b/go/src/golang.org/x/tools/go/ssa/wrappers.go
index ff1eac5..6ca01ab 100644
--- a/go/src/golang.org/x/tools/go/ssa/wrappers.go
+++ b/go/src/golang.org/x/tools/go/ssa/wrappers.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package ssa
 
 // This file defines synthesis of Functions that delegate to declared
@@ -22,7 +24,7 @@
 import (
 	"fmt"
 
-	"golang.org/x/tools/go/types"
+	"go/types"
 )
 
 // -- wrappers -----------------------------------------------------------
diff --git a/go/src/golang.org/x/tools/go/ssa/wrappers14.go b/go/src/golang.org/x/tools/go/ssa/wrappers14.go
new file mode 100644
index 0000000..89f71b7
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/ssa/wrappers14.go
@@ -0,0 +1,296 @@
+// 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.
+
+// +build !go1.5
+
+package ssa
+
+// This file defines synthesis of Functions that delegate to declared
+// methods; they come in three kinds:
+//
+// (1) wrappers: methods that wrap declared methods, performing
+//     implicit pointer indirections and embedded field selections.
+//
+// (2) thunks: funcs that wrap declared methods.  Like wrappers,
+//     thunks perform indirections and field selections. The thunk's
+//     first parameter is used as the receiver for the method call.
+//
+// (3) bounds: funcs that wrap declared methods.  The bound's sole
+//     free variable, supplied by a closure, is used as the receiver
+//     for the method call.  No indirections or field selections are
+//     performed since they can be done before the call.
+
+import (
+	"fmt"
+
+	"golang.org/x/tools/go/types"
+)
+
+// -- wrappers -----------------------------------------------------------
+
+// makeWrapper returns a synthetic method that delegates to the
+// declared method denoted by meth.Obj(), first performing any
+// necessary pointer indirections or field selections implied by meth.
+//
+// The resulting method's receiver type is meth.Recv().
+//
+// This function is versatile but quite subtle!  Consider the
+// following axes of variation when making changes:
+//   - optional receiver indirection
+//   - optional implicit field selections
+//   - meth.Obj() may denote a concrete or an interface method
+//   - the result may be a thunk or a wrapper.
+//
+// EXCLUSIVE_LOCKS_REQUIRED(prog.methodsMu)
+//
+func makeWrapper(prog *Program, sel *types.Selection) *Function {
+	obj := sel.Obj().(*types.Func)       // the declared function
+	sig := sel.Type().(*types.Signature) // type of this wrapper
+
+	var recv *types.Var // wrapper's receiver or thunk's params[0]
+	name := obj.Name()
+	var description string
+	var start int // first regular param
+	if sel.Kind() == types.MethodExpr {
+		name += "$thunk"
+		description = "thunk"
+		recv = sig.Params().At(0)
+		start = 1
+	} else {
+		description = "wrapper"
+		recv = sig.Recv()
+	}
+
+	description = fmt.Sprintf("%s for %s", description, sel.Obj())
+	if prog.mode&LogSource != 0 {
+		defer logStack("make %s to (%s)", description, recv.Type())()
+	}
+	fn := &Function{
+		name:      name,
+		method:    sel,
+		object:    obj,
+		Signature: sig,
+		Synthetic: description,
+		Prog:      prog,
+		pos:       obj.Pos(),
+	}
+	fn.startBody()
+	fn.addSpilledParam(recv)
+	createParams(fn, start)
+
+	indices := sel.Index()
+
+	var v Value = fn.Locals[0] // spilled receiver
+	if isPointer(sel.Recv()) {
+		v = emitLoad(fn, v)
+
+		// For simple indirection wrappers, perform an informative nil-check:
+		// "value method (T).f called using nil *T pointer"
+		if len(indices) == 1 && !isPointer(recvType(obj)) {
+			var c Call
+			c.Call.Value = &Builtin{
+				name: "ssa:wrapnilchk",
+				sig: types.NewSignature(nil,
+					types.NewTuple(anonVar(sel.Recv()), anonVar(tString), anonVar(tString)),
+					types.NewTuple(anonVar(sel.Recv())), false),
+			}
+			c.Call.Args = []Value{
+				v,
+				stringConst(deref(sel.Recv()).String()),
+				stringConst(sel.Obj().Name()),
+			}
+			c.setType(v.Type())
+			v = fn.emit(&c)
+		}
+	}
+
+	// Invariant: v is a pointer, either
+	//   value of *A receiver param, or
+	// address of  A spilled receiver.
+
+	// We use pointer arithmetic (FieldAddr possibly followed by
+	// Load) in preference to value extraction (Field possibly
+	// preceded by Load).
+
+	v = emitImplicitSelections(fn, v, indices[:len(indices)-1])
+
+	// Invariant: v is a pointer, either
+	//   value of implicit *C field, or
+	// address of implicit  C field.
+
+	var c Call
+	if r := recvType(obj); !isInterface(r) { // concrete method
+		if !isPointer(r) {
+			v = emitLoad(fn, v)
+		}
+		c.Call.Value = prog.declaredFunc(obj)
+		c.Call.Args = append(c.Call.Args, v)
+	} else {
+		c.Call.Method = obj
+		c.Call.Value = emitLoad(fn, v)
+	}
+	for _, arg := range fn.Params[1:] {
+		c.Call.Args = append(c.Call.Args, arg)
+	}
+	emitTailCall(fn, &c)
+	fn.finishBody()
+	return fn
+}
+
+// createParams creates parameters for wrapper method fn based on its
+// Signature.Params, which do not include the receiver.
+// start is the index of the first regular parameter to use.
+//
+func createParams(fn *Function, start int) {
+	var last *Parameter
+	tparams := fn.Signature.Params()
+	for i, n := start, tparams.Len(); i < n; i++ {
+		last = fn.addParamObj(tparams.At(i))
+	}
+	if fn.Signature.Variadic() {
+		last.typ = types.NewSlice(last.typ)
+	}
+}
+
+// -- bounds -----------------------------------------------------------
+
+// makeBound returns a bound method wrapper (or "bound"), a synthetic
+// function that delegates to a concrete or interface method denoted
+// by obj.  The resulting function has no receiver, but has one free
+// variable which will be used as the method's receiver in the
+// tail-call.
+//
+// Use MakeClosure with such a wrapper to construct a bound method
+// closure.  e.g.:
+//
+//   type T int          or:  type T interface { meth() }
+//   func (t T) meth()
+//   var t T
+//   f := t.meth
+//   f() // calls t.meth()
+//
+// f is a closure of a synthetic wrapper defined as if by:
+//
+//   f := func() { return t.meth() }
+//
+// Unlike makeWrapper, makeBound need perform no indirection or field
+// selections because that can be done before the closure is
+// constructed.
+//
+// EXCLUSIVE_LOCKS_ACQUIRED(meth.Prog.methodsMu)
+//
+func makeBound(prog *Program, obj *types.Func) *Function {
+	prog.methodsMu.Lock()
+	defer prog.methodsMu.Unlock()
+	fn, ok := prog.bounds[obj]
+	if !ok {
+		description := fmt.Sprintf("bound method wrapper for %s", obj)
+		if prog.mode&LogSource != 0 {
+			defer logStack("%s", description)()
+		}
+		fn = &Function{
+			name:      obj.Name() + "$bound",
+			object:    obj,
+			Signature: changeRecv(obj.Type().(*types.Signature), nil), // drop receiver
+			Synthetic: description,
+			Prog:      prog,
+			pos:       obj.Pos(),
+		}
+
+		fv := &FreeVar{name: "recv", typ: recvType(obj), parent: fn}
+		fn.FreeVars = []*FreeVar{fv}
+		fn.startBody()
+		createParams(fn, 0)
+		var c Call
+
+		if !isInterface(recvType(obj)) { // concrete
+			c.Call.Value = prog.declaredFunc(obj)
+			c.Call.Args = []Value{fv}
+		} else {
+			c.Call.Value = fv
+			c.Call.Method = obj
+		}
+		for _, arg := range fn.Params {
+			c.Call.Args = append(c.Call.Args, arg)
+		}
+		emitTailCall(fn, &c)
+		fn.finishBody()
+
+		prog.bounds[obj] = fn
+	}
+	return fn
+}
+
+// -- thunks -----------------------------------------------------------
+
+// makeThunk returns a thunk, a synthetic function that delegates to a
+// concrete or interface method denoted by sel.Obj().  The resulting
+// function has no receiver, but has an additional (first) regular
+// parameter.
+//
+// Precondition: sel.Kind() == types.MethodExpr.
+//
+//   type T int          or:  type T interface { meth() }
+//   func (t T) meth()
+//   f := T.meth
+//   var t T
+//   f(t) // calls t.meth()
+//
+// f is a synthetic wrapper defined as if by:
+//
+//   f := func(t T) { return t.meth() }
+//
+// TODO(adonovan): opt: currently the stub is created even when used
+// directly in a function call: C.f(i, 0).  This is less efficient
+// than inlining the stub.
+//
+// EXCLUSIVE_LOCKS_ACQUIRED(meth.Prog.methodsMu)
+//
+func makeThunk(prog *Program, sel *types.Selection) *Function {
+	if sel.Kind() != types.MethodExpr {
+		panic(sel)
+	}
+
+	key := selectionKey{
+		kind:     sel.Kind(),
+		recv:     sel.Recv(),
+		obj:      sel.Obj(),
+		index:    fmt.Sprint(sel.Index()),
+		indirect: sel.Indirect(),
+	}
+
+	prog.methodsMu.Lock()
+	defer prog.methodsMu.Unlock()
+
+	// Canonicalize key.recv to avoid constructing duplicate thunks.
+	canonRecv, ok := prog.canon.At(key.recv).(types.Type)
+	if !ok {
+		canonRecv = key.recv
+		prog.canon.Set(key.recv, canonRecv)
+	}
+	key.recv = canonRecv
+
+	fn, ok := prog.thunks[key]
+	if !ok {
+		fn = makeWrapper(prog, sel)
+		if fn.Signature.Recv() != nil {
+			panic(fn) // unexpected receiver
+		}
+		prog.thunks[key] = fn
+	}
+	return fn
+}
+
+func changeRecv(s *types.Signature, recv *types.Var) *types.Signature {
+	return types.NewSignature(recv, s.Params(), s.Results(), s.Variadic())
+}
+
+// selectionKey is like types.Selection but a usable map key.
+type selectionKey struct {
+	kind     types.SelectionKind
+	recv     types.Type // canonicalized via Program.canon
+	obj      types.Object
+	index    string
+	indirect bool
+}
diff --git a/go/src/golang.org/x/tools/go/types/expr.go b/go/src/golang.org/x/tools/go/types/expr.go
index 6efc7b4..79dad12 100644
--- a/go/src/golang.org/x/tools/go/types/expr.go
+++ b/go/src/golang.org/x/tools/go/types/expr.go
@@ -1246,7 +1246,7 @@
 		switch typ := x.typ.Underlying().(type) {
 		case *Basic:
 			if isString(typ) {
-				if slice3(e) {
+				if e.Slice3 {
 					check.invalidOp(x.pos(), "3-index slice of string")
 					goto Error
 				}
@@ -1290,14 +1290,14 @@
 		x.mode = value
 
 		// spec: "Only the first index may be omitted; it defaults to 0."
-		if slice3(e) && (e.High == nil || sliceMax(e) == nil) {
+		if e.Slice3 && (e.High == nil || e.Max == nil) {
 			check.error(e.Rbrack, "2nd and 3rd index required in 3-index slice")
 			goto Error
 		}
 
 		// check indices
 		var ind [3]int64
-		for i, expr := range []ast.Expr{e.Low, e.High, sliceMax(e)} {
+		for i, expr := range []ast.Expr{e.Low, e.High, e.Max} {
 			x := int64(-1)
 			switch {
 			case expr != nil:
diff --git a/go/src/golang.org/x/tools/go/types/go11.go b/go/src/golang.org/x/tools/go/types/go11.go
deleted file mode 100644
index cf41cab..0000000
--- a/go/src/golang.org/x/tools/go/types/go11.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// 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.
-
-// +build !go1.2
-
-package types
-
-import "go/ast"
-
-func slice3(x *ast.SliceExpr) bool {
-	return false
-}
-
-func sliceMax(x *ast.SliceExpr) ast.Expr {
-	return nil
-}
diff --git a/go/src/golang.org/x/tools/go/types/go12.go b/go/src/golang.org/x/tools/go/types/go12.go
deleted file mode 100644
index 2017442..0000000
--- a/go/src/golang.org/x/tools/go/types/go12.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// 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.
-
-// +build go1.2
-
-package types
-
-import "go/ast"
-
-func slice3(x *ast.SliceExpr) bool {
-	return x.Slice3
-}
-
-func sliceMax(x *ast.SliceExpr) ast.Expr {
-	return x.Max
-}
diff --git a/go/src/golang.org/x/tools/go/types/stdlib_test.go b/go/src/golang.org/x/tools/go/types/stdlib_test.go
index d6aa82a..7554f91 100644
--- a/go/src/golang.org/x/tools/go/types/stdlib_test.go
+++ b/go/src/golang.org/x/tools/go/types/stdlib_test.go
@@ -143,6 +143,8 @@
 		"issue7746.go",   // large constants - consumes too much memory
 		"issue11326.go",  // large constants
 		"issue11326b.go", // large constants
+		"issue11362.go",  // canonical import path check is implementation-defined behavior
+		"issue13471.go",  // large constants
 	)
 }
 
@@ -187,6 +189,13 @@
 		files = append(files, file)
 	}
 
+	// gcimporter doesn't support vendored imports.
+	// TODO(gri): fix.
+	if strings.HasSuffix(path, "src/cmd/internal/objfile") ||
+		strings.HasSuffix(path, "src/net/http") {
+		return
+	}
+
 	// typecheck package files
 	var conf Config
 	conf.Error = func(err error) { t.Error(err) }
diff --git a/go/src/golang.org/x/tools/go/types/type.go b/go/src/golang.org/x/tools/go/types/type.go
index 1df8b45..8e24b54 100644
--- a/go/src/golang.org/x/tools/go/types/type.go
+++ b/go/src/golang.org/x/tools/go/types/type.go
@@ -398,7 +398,7 @@
 	return typ
 }
 
-// TypeName returns the type name for the named type t.
+// Obj returns the type name for the named type t.
 func (t *Named) Obj() *TypeName { return t.obj }
 
 // NumMethods returns the number of explicit methods whose receiver is named type t.
diff --git a/go/src/golang.org/x/tools/go/types/typeutil/example_test.go b/go/src/golang.org/x/tools/go/types/typeutil/example_test.go
index 9e3ada7..fe49644 100644
--- a/go/src/golang.org/x/tools/go/types/typeutil/example_test.go
+++ b/go/src/golang.org/x/tools/go/types/typeutil/example_test.go
@@ -2,17 +2,18 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package typeutil_test
 
 import (
 	"fmt"
-	"sort"
-
 	"go/ast"
 	"go/parser"
 	"go/token"
+	"go/types"
+	"sort"
 
-	"golang.org/x/tools/go/types"
 	"golang.org/x/tools/go/types/typeutil"
 )
 
diff --git a/go/src/golang.org/x/tools/go/types/typeutil/imports.go b/go/src/golang.org/x/tools/go/types/typeutil/imports.go
index 967fe1e..4b753f4 100644
--- a/go/src/golang.org/x/tools/go/types/typeutil/imports.go
+++ b/go/src/golang.org/x/tools/go/types/typeutil/imports.go
@@ -2,9 +2,11 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package typeutil
 
-import "golang.org/x/tools/go/types"
+import "go/types"
 
 // Dependencies returns all dependencies of the specified packages.
 //
diff --git a/go/src/golang.org/x/tools/go/types/typeutil/imports14.go b/go/src/golang.org/x/tools/go/types/typeutil/imports14.go
new file mode 100644
index 0000000..9741df3
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/types/typeutil/imports14.go
@@ -0,0 +1,33 @@
+// Copyright 2014 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.
+
+// +build !go1.5
+
+package typeutil
+
+import "golang.org/x/tools/go/types"
+
+// Dependencies returns all dependencies of the specified packages.
+//
+// Dependent packages appear in topological order: if package P imports
+// package Q, Q appears earlier than P in the result.
+// The algorithm follows import statements in the order they
+// appear in the source code, so the result is a total order.
+//
+func Dependencies(pkgs ...*types.Package) []*types.Package {
+	var result []*types.Package
+	seen := make(map[*types.Package]bool)
+	var visit func(pkgs []*types.Package)
+	visit = func(pkgs []*types.Package) {
+		for _, p := range pkgs {
+			if !seen[p] {
+				seen[p] = true
+				visit(p.Imports())
+				result = append(result, p)
+			}
+		}
+	}
+	visit(pkgs)
+	return result
+}
diff --git a/go/src/golang.org/x/tools/go/types/typeutil/imports14_test.go b/go/src/golang.org/x/tools/go/types/typeutil/imports14_test.go
new file mode 100644
index 0000000..b70f5f0
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/types/typeutil/imports14_test.go
@@ -0,0 +1,81 @@
+// Copyright 2014 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.
+
+// +build !go1.5
+
+package typeutil_test
+
+import (
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"testing"
+
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/go/types/typeutil"
+)
+
+func TestDependencies(t *testing.T) {
+	packages := make(map[string]*types.Package)
+	conf := types.Config{
+		Packages: packages,
+		Import: func(_ map[string]*types.Package, path string) (*types.Package, error) {
+			return packages[path], nil
+		},
+	}
+	fset := token.NewFileSet()
+
+	// All edges go to the right.
+	//  /--D--B--A
+	// F    \_C_/
+	//  \__E_/
+	for i, content := range []string{
+		`package a`,
+		`package c; import (_ "a")`,
+		`package b; import (_ "a")`,
+		`package e; import (_ "c")`,
+		`package d; import (_ "b"; _ "c")`,
+		`package f; import (_ "d"; _ "e")`,
+	} {
+		f, err := parser.ParseFile(fset, fmt.Sprintf("%d.go", i), content, 0)
+		if err != nil {
+			t.Fatal(err)
+		}
+		pkg, err := conf.Check(f.Name.Name, fset, []*ast.File{f}, nil)
+		if err != nil {
+			t.Fatal(err)
+		}
+		packages[pkg.Path()] = pkg
+	}
+
+	for _, test := range []struct {
+		roots, want string
+	}{
+		{"a", "a"},
+		{"b", "ab"},
+		{"c", "ac"},
+		{"d", "abcd"},
+		{"e", "ace"},
+		{"f", "abcdef"},
+
+		{"be", "abce"},
+		{"eb", "aceb"},
+		{"de", "abcde"},
+		{"ed", "acebd"},
+		{"ef", "acebdf"},
+	} {
+		var pkgs []*types.Package
+		for _, r := range test.roots {
+			pkgs = append(pkgs, packages[string(r)])
+		}
+		var got string
+		for _, p := range typeutil.Dependencies(pkgs...) {
+			got += p.Path()
+		}
+		if got != test.want {
+			t.Errorf("Dependencies(%q) = %q, want %q", test.roots, got, test.want)
+		}
+	}
+}
diff --git a/go/src/golang.org/x/tools/go/types/typeutil/imports_test.go b/go/src/golang.org/x/tools/go/types/typeutil/imports_test.go
index 8071ae1..b846fbb 100644
--- a/go/src/golang.org/x/tools/go/types/typeutil/imports_test.go
+++ b/go/src/golang.org/x/tools/go/types/typeutil/imports_test.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package typeutil_test
 
 import (
@@ -9,19 +11,20 @@
 	"go/ast"
 	"go/parser"
 	"go/token"
+	"go/types"
 	"testing"
 
-	"golang.org/x/tools/go/types"
 	"golang.org/x/tools/go/types/typeutil"
 )
 
+type closure map[string]*types.Package
+
+func (c closure) Import(path string) (*types.Package, error) { return c[path], nil }
+
 func TestDependencies(t *testing.T) {
 	packages := make(map[string]*types.Package)
 	conf := types.Config{
-		Packages: packages,
-		Import: func(_ map[string]*types.Package, path string) (*types.Package, error) {
-			return packages[path], nil
-		},
+		Importer: closure(packages),
 	}
 	fset := token.NewFileSet()
 
@@ -30,12 +33,12 @@
 	// F    \_C_/
 	//  \__E_/
 	for i, content := range []string{
-		`package A`,
-		`package C; import (_ "A")`,
-		`package B; import (_ "A")`,
-		`package E; import (_ "C")`,
-		`package D; import (_ "B"; _ "C")`,
-		`package F; import (_ "D"; _ "E")`,
+		`package a`,
+		`package c; import (_ "a")`,
+		`package b; import (_ "a")`,
+		`package e; import (_ "c")`,
+		`package d; import (_ "b"; _ "c")`,
+		`package f; import (_ "d"; _ "e")`,
 	} {
 		f, err := parser.ParseFile(fset, fmt.Sprintf("%d.go", i), content, 0)
 		if err != nil {
@@ -51,22 +54,22 @@
 	for _, test := range []struct {
 		roots, want string
 	}{
-		{"A", "A"},
-		{"B", "AB"},
-		{"C", "AC"},
-		{"D", "ABCD"},
-		{"E", "ACE"},
-		{"F", "ABCDEF"},
+		{"a", "a"},
+		{"b", "ab"},
+		{"c", "ac"},
+		{"d", "abcd"},
+		{"e", "ace"},
+		{"f", "abcdef"},
 
-		{"BE", "ABCE"},
-		{"EB", "ACEB"},
-		{"DE", "ABCDE"},
-		{"ED", "ACEBD"},
-		{"EF", "ACEBDF"},
+		{"be", "abce"},
+		{"eb", "aceb"},
+		{"de", "abcde"},
+		{"ed", "acebd"},
+		{"ef", "acebdf"},
 	} {
 		var pkgs []*types.Package
 		for _, r := range test.roots {
-			pkgs = append(pkgs, conf.Packages[string(r)])
+			pkgs = append(pkgs, packages[string(r)])
 		}
 		var got string
 		for _, p := range typeutil.Dependencies(pkgs...) {
diff --git a/go/src/golang.org/x/tools/go/types/typeutil/map.go b/go/src/golang.org/x/tools/go/types/typeutil/map.go
index b3a04cc..81dd556 100644
--- a/go/src/golang.org/x/tools/go/types/typeutil/map.go
+++ b/go/src/golang.org/x/tools/go/types/typeutil/map.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 // Package typeutil defines various utilities for types, such as Map,
 // a mapping from types.Type to interface{} values.
 package typeutil // import "golang.org/x/tools/go/types/typeutil"
@@ -9,9 +11,8 @@
 import (
 	"bytes"
 	"fmt"
+	"go/types"
 	"reflect"
-
-	"golang.org/x/tools/go/types"
 )
 
 // Map is a hash-table-based mapping from types (types.Type) to
diff --git a/go/src/golang.org/x/tools/go/types/typeutil/map14.go b/go/src/golang.org/x/tools/go/types/typeutil/map14.go
new file mode 100644
index 0000000..16209e3
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/types/typeutil/map14.go
@@ -0,0 +1,316 @@
+// Copyright 2014 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.
+
+// +build !go1.5
+
+// Package typeutil defines various utilities for types, such as Map,
+// a mapping from types.Type to interface{} values.
+package typeutil // import "golang.org/x/tools/go/types/typeutil"
+
+import (
+	"bytes"
+	"fmt"
+	"reflect"
+
+	"golang.org/x/tools/go/types"
+)
+
+// Map is a hash-table-based mapping from types (types.Type) to
+// arbitrary interface{} values.  The concrete types that implement
+// the Type interface are pointers.  Since they are not canonicalized,
+// == cannot be used to check for equivalence, and thus we cannot
+// simply use a Go map.
+//
+// Just as with map[K]V, a nil *Map is a valid empty map.
+//
+// Not thread-safe.
+//
+type Map struct {
+	hasher Hasher             // shared by many Maps
+	table  map[uint32][]entry // maps hash to bucket; entry.key==nil means unused
+	length int                // number of map entries
+}
+
+// entry is an entry (key/value association) in a hash bucket.
+type entry struct {
+	key   types.Type
+	value interface{}
+}
+
+// SetHasher sets the hasher used by Map.
+//
+// All Hashers are functionally equivalent but contain internal state
+// used to cache the results of hashing previously seen types.
+//
+// A single Hasher created by MakeHasher() may be shared among many
+// Maps.  This is recommended if the instances have many keys in
+// common, as it will amortize the cost of hash computation.
+//
+// A Hasher may grow without bound as new types are seen.  Even when a
+// type is deleted from the map, the Hasher never shrinks, since other
+// types in the map may reference the deleted type indirectly.
+//
+// Hashers are not thread-safe, and read-only operations such as
+// Map.Lookup require updates to the hasher, so a full Mutex lock (not a
+// read-lock) is require around all Map operations if a shared
+// hasher is accessed from multiple threads.
+//
+// If SetHasher is not called, the Map will create a private hasher at
+// the first call to Insert.
+//
+func (m *Map) SetHasher(hasher Hasher) {
+	m.hasher = hasher
+}
+
+// Delete removes the entry with the given key, if any.
+// It returns true if the entry was found.
+//
+func (m *Map) Delete(key types.Type) bool {
+	if m != nil && m.table != nil {
+		hash := m.hasher.Hash(key)
+		bucket := m.table[hash]
+		for i, e := range bucket {
+			if e.key != nil && types.Identical(key, e.key) {
+				// We can't compact the bucket as it
+				// would disturb iterators.
+				bucket[i] = entry{}
+				m.length--
+				return true
+			}
+		}
+	}
+	return false
+}
+
+// At returns the map entry for the given key.
+// The result is nil if the entry is not present.
+//
+func (m *Map) At(key types.Type) interface{} {
+	if m != nil && m.table != nil {
+		for _, e := range m.table[m.hasher.Hash(key)] {
+			if e.key != nil && types.Identical(key, e.key) {
+				return e.value
+			}
+		}
+	}
+	return nil
+}
+
+// Set sets the map entry for key to val,
+// and returns the previous entry, if any.
+func (m *Map) Set(key types.Type, value interface{}) (prev interface{}) {
+	if m.table != nil {
+		hash := m.hasher.Hash(key)
+		bucket := m.table[hash]
+		var hole *entry
+		for i, e := range bucket {
+			if e.key == nil {
+				hole = &bucket[i]
+			} else if types.Identical(key, e.key) {
+				prev = e.value
+				bucket[i].value = value
+				return
+			}
+		}
+
+		if hole != nil {
+			*hole = entry{key, value} // overwrite deleted entry
+		} else {
+			m.table[hash] = append(bucket, entry{key, value})
+		}
+	} else {
+		if m.hasher.memo == nil {
+			m.hasher = MakeHasher()
+		}
+		hash := m.hasher.Hash(key)
+		m.table = map[uint32][]entry{hash: {entry{key, value}}}
+	}
+
+	m.length++
+	return
+}
+
+// Len returns the number of map entries.
+func (m *Map) Len() int {
+	if m != nil {
+		return m.length
+	}
+	return 0
+}
+
+// Iterate calls function f on each entry in the map in unspecified order.
+//
+// If f should mutate the map, Iterate provides the same guarantees as
+// Go maps: if f deletes a map entry that Iterate has not yet reached,
+// f will not be invoked for it, but if f inserts a map entry that
+// Iterate has not yet reached, whether or not f will be invoked for
+// it is unspecified.
+//
+func (m *Map) Iterate(f func(key types.Type, value interface{})) {
+	if m != nil {
+		for _, bucket := range m.table {
+			for _, e := range bucket {
+				if e.key != nil {
+					f(e.key, e.value)
+				}
+			}
+		}
+	}
+}
+
+// Keys returns a new slice containing the set of map keys.
+// The order is unspecified.
+func (m *Map) Keys() []types.Type {
+	keys := make([]types.Type, 0, m.Len())
+	m.Iterate(func(key types.Type, _ interface{}) {
+		keys = append(keys, key)
+	})
+	return keys
+}
+
+func (m *Map) toString(values bool) string {
+	if m == nil {
+		return "{}"
+	}
+	var buf bytes.Buffer
+	fmt.Fprint(&buf, "{")
+	sep := ""
+	m.Iterate(func(key types.Type, value interface{}) {
+		fmt.Fprint(&buf, sep)
+		sep = ", "
+		fmt.Fprint(&buf, key)
+		if values {
+			fmt.Fprintf(&buf, ": %q", value)
+		}
+	})
+	fmt.Fprint(&buf, "}")
+	return buf.String()
+}
+
+// String returns a string representation of the map's entries.
+// Values are printed using fmt.Sprintf("%v", v).
+// Order is unspecified.
+//
+func (m *Map) String() string {
+	return m.toString(true)
+}
+
+// KeysString returns a string representation of the map's key set.
+// Order is unspecified.
+//
+func (m *Map) KeysString() string {
+	return m.toString(false)
+}
+
+////////////////////////////////////////////////////////////////////////
+// Hasher
+
+// A Hasher maps each type to its hash value.
+// For efficiency, a hasher uses memoization; thus its memory
+// footprint grows monotonically over time.
+// Hashers are not thread-safe.
+// Hashers have reference semantics.
+// Call MakeHasher to create a Hasher.
+type Hasher struct {
+	memo map[types.Type]uint32
+}
+
+// MakeHasher returns a new Hasher instance.
+func MakeHasher() Hasher {
+	return Hasher{make(map[types.Type]uint32)}
+}
+
+// Hash computes a hash value for the given type t such that
+// Identical(t, t') => Hash(t) == Hash(t').
+func (h Hasher) Hash(t types.Type) uint32 {
+	hash, ok := h.memo[t]
+	if !ok {
+		hash = h.hashFor(t)
+		h.memo[t] = hash
+	}
+	return hash
+}
+
+// hashString computes the Fowler–Noll–Vo hash of s.
+func hashString(s string) uint32 {
+	var h uint32
+	for i := 0; i < len(s); i++ {
+		h ^= uint32(s[i])
+		h *= 16777619
+	}
+	return h
+}
+
+// hashFor computes the hash of t.
+func (h Hasher) hashFor(t types.Type) uint32 {
+	// See Identical for rationale.
+	switch t := t.(type) {
+	case *types.Basic:
+		return uint32(t.Kind())
+
+	case *types.Array:
+		return 9043 + 2*uint32(t.Len()) + 3*h.Hash(t.Elem())
+
+	case *types.Slice:
+		return 9049 + 2*h.Hash(t.Elem())
+
+	case *types.Struct:
+		var hash uint32 = 9059
+		for i, n := 0, t.NumFields(); i < n; i++ {
+			f := t.Field(i)
+			if f.Anonymous() {
+				hash += 8861
+			}
+			hash += hashString(t.Tag(i))
+			hash += hashString(f.Name()) // (ignore f.Pkg)
+			hash += h.Hash(f.Type())
+		}
+		return hash
+
+	case *types.Pointer:
+		return 9067 + 2*h.Hash(t.Elem())
+
+	case *types.Signature:
+		var hash uint32 = 9091
+		if t.Variadic() {
+			hash *= 8863
+		}
+		return hash + 3*h.hashTuple(t.Params()) + 5*h.hashTuple(t.Results())
+
+	case *types.Interface:
+		var hash uint32 = 9103
+		for i, n := 0, t.NumMethods(); i < n; i++ {
+			// See go/types.identicalMethods for rationale.
+			// Method order is not significant.
+			// Ignore m.Pkg().
+			m := t.Method(i)
+			hash += 3*hashString(m.Name()) + 5*h.Hash(m.Type())
+		}
+		return hash
+
+	case *types.Map:
+		return 9109 + 2*h.Hash(t.Key()) + 3*h.Hash(t.Elem())
+
+	case *types.Chan:
+		return 9127 + 2*uint32(t.Dir()) + 3*h.Hash(t.Elem())
+
+	case *types.Named:
+		// Not safe with a copying GC; objects may move.
+		return uint32(reflect.ValueOf(t.Obj()).Pointer())
+
+	case *types.Tuple:
+		return h.hashTuple(t)
+	}
+	panic(t)
+}
+
+func (h Hasher) hashTuple(tuple *types.Tuple) uint32 {
+	// See go/types.identicalTypes for rationale.
+	n := tuple.Len()
+	var hash uint32 = 9137 + 2*uint32(n)
+	for i := 0; i < n; i++ {
+		hash += 3 * h.Hash(tuple.At(i).Type())
+	}
+	return hash
+}
diff --git a/go/src/golang.org/x/tools/go/types/typeutil/map14_test.go b/go/src/golang.org/x/tools/go/types/typeutil/map14_test.go
new file mode 100644
index 0000000..9043d05
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/types/typeutil/map14_test.go
@@ -0,0 +1,176 @@
+// Copyright 2014 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.
+
+// +build !go1.5
+
+package typeutil_test
+
+// TODO(adonovan):
+// - test use of explicit hasher across two maps.
+// - test hashcodes are consistent with equals for a range of types
+//   (e.g. all types generated by type-checking some body of real code).
+
+import (
+	"testing"
+
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/go/types/typeutil"
+)
+
+var (
+	tStr      = types.Typ[types.String]             // string
+	tPStr1    = types.NewPointer(tStr)              // *string
+	tPStr2    = types.NewPointer(tStr)              // *string, again
+	tInt      = types.Typ[types.Int]                // int
+	tChanInt1 = types.NewChan(types.RecvOnly, tInt) // <-chan int
+	tChanInt2 = types.NewChan(types.RecvOnly, tInt) // <-chan int, again
+)
+
+func checkEqualButNotIdentical(t *testing.T, x, y types.Type, comment string) {
+	if !types.Identical(x, y) {
+		t.Errorf("%s: not equal: %s, %s", comment, x, y)
+	}
+	if x == y {
+		t.Errorf("%s: identical: %v, %v", comment, x, y)
+	}
+}
+
+func TestAxioms(t *testing.T) {
+	checkEqualButNotIdentical(t, tPStr1, tPStr2, "tPstr{1,2}")
+	checkEqualButNotIdentical(t, tChanInt1, tChanInt2, "tChanInt{1,2}")
+}
+
+func TestMap(t *testing.T) {
+	var tmap *typeutil.Map
+
+	// All methods but Set are safe on on (*T)(nil).
+	tmap.Len()
+	tmap.At(tPStr1)
+	tmap.Delete(tPStr1)
+	tmap.KeysString()
+	tmap.String()
+
+	tmap = new(typeutil.Map)
+
+	// Length of empty map.
+	if l := tmap.Len(); l != 0 {
+		t.Errorf("Len() on empty Map: got %d, want 0", l)
+	}
+	// At of missing key.
+	if v := tmap.At(tPStr1); v != nil {
+		t.Errorf("At() on empty Map: got %v, want nil", v)
+	}
+	// Deletion of missing key.
+	if tmap.Delete(tPStr1) {
+		t.Errorf("Delete() on empty Map: got true, want false")
+	}
+	// Set of new key.
+	if prev := tmap.Set(tPStr1, "*string"); prev != nil {
+		t.Errorf("Set() on empty Map returned non-nil previous value %s", prev)
+	}
+
+	// Now: {*string: "*string"}
+
+	// Length of non-empty map.
+	if l := tmap.Len(); l != 1 {
+		t.Errorf("Len(): got %d, want 1", l)
+	}
+	// At via insertion key.
+	if v := tmap.At(tPStr1); v != "*string" {
+		t.Errorf("At(): got %q, want \"*string\"", v)
+	}
+	// At via equal key.
+	if v := tmap.At(tPStr2); v != "*string" {
+		t.Errorf("At(): got %q, want \"*string\"", v)
+	}
+	// Iteration over sole entry.
+	tmap.Iterate(func(key types.Type, value interface{}) {
+		if key != tPStr1 {
+			t.Errorf("Iterate: key: got %s, want %s", key, tPStr1)
+		}
+		if want := "*string"; value != want {
+			t.Errorf("Iterate: value: got %s, want %s", value, want)
+		}
+	})
+
+	// Setion with key equal to present one.
+	if prev := tmap.Set(tPStr2, "*string again"); prev != "*string" {
+		t.Errorf("Set() previous value: got %s, want \"*string\"", prev)
+	}
+
+	// Setion of another association.
+	if prev := tmap.Set(tChanInt1, "<-chan int"); prev != nil {
+		t.Errorf("Set() previous value: got %s, want nil", prev)
+	}
+
+	// Now: {*string: "*string again", <-chan int: "<-chan int"}
+
+	want1 := "{*string: \"*string again\", <-chan int: \"<-chan int\"}"
+	want2 := "{<-chan int: \"<-chan int\", *string: \"*string again\"}"
+	if s := tmap.String(); s != want1 && s != want2 {
+		t.Errorf("String(): got %s, want %s", s, want1)
+	}
+
+	want1 = "{*string, <-chan int}"
+	want2 = "{<-chan int, *string}"
+	if s := tmap.KeysString(); s != want1 && s != want2 {
+		t.Errorf("KeysString(): got %s, want %s", s, want1)
+	}
+
+	// Keys().
+	I := types.Identical
+	switch k := tmap.Keys(); {
+	case I(k[0], tChanInt1) && I(k[1], tPStr1): // ok
+	case I(k[1], tChanInt1) && I(k[0], tPStr1): // ok
+	default:
+		t.Errorf("Keys(): got %v, want %s", k, want2)
+	}
+
+	if l := tmap.Len(); l != 2 {
+		t.Errorf("Len(): got %d, want 1", l)
+	}
+	// At via original key.
+	if v := tmap.At(tPStr1); v != "*string again" {
+		t.Errorf("At(): got %q, want \"*string again\"", v)
+	}
+	hamming := 1
+	tmap.Iterate(func(key types.Type, value interface{}) {
+		switch {
+		case I(key, tChanInt1):
+			hamming *= 2 // ok
+		case I(key, tPStr1):
+			hamming *= 3 // ok
+		}
+	})
+	if hamming != 6 {
+		t.Errorf("Iterate: hamming: got %d, want %d", hamming, 6)
+	}
+
+	if v := tmap.At(tChanInt2); v != "<-chan int" {
+		t.Errorf("At(): got %q, want \"<-chan int\"", v)
+	}
+	// Deletion with key equal to present one.
+	if !tmap.Delete(tChanInt2) {
+		t.Errorf("Delete() of existing key: got false, want true")
+	}
+
+	// Now: {*string: "*string again"}
+
+	if l := tmap.Len(); l != 1 {
+		t.Errorf("Len(): got %d, want 1", l)
+	}
+	// Deletion again.
+	if !tmap.Delete(tPStr2) {
+		t.Errorf("Delete() of existing key: got false, want true")
+	}
+
+	// Now: {}
+
+	if l := tmap.Len(); l != 0 {
+		t.Errorf("Len(): got %d, want %d", l, 0)
+	}
+	if s := tmap.String(); s != "{}" {
+		t.Errorf("Len(): got %q, want %q", s, "")
+	}
+}
diff --git a/go/src/golang.org/x/tools/go/types/typeutil/map_test.go b/go/src/golang.org/x/tools/go/types/typeutil/map_test.go
index 776b5e2..e5dc4e4 100644
--- a/go/src/golang.org/x/tools/go/types/typeutil/map_test.go
+++ b/go/src/golang.org/x/tools/go/types/typeutil/map_test.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package typeutil_test
 
 // TODO(adonovan):
@@ -10,9 +12,9 @@
 //   (e.g. all types generated by type-checking some body of real code).
 
 import (
+	"go/types"
 	"testing"
 
-	"golang.org/x/tools/go/types"
 	"golang.org/x/tools/go/types/typeutil"
 )
 
diff --git a/go/src/golang.org/x/tools/go/types/typeutil/methodsetcache.go b/go/src/golang.org/x/tools/go/types/typeutil/methodsetcache.go
index daad644..edc3f5b 100644
--- a/go/src/golang.org/x/tools/go/types/typeutil/methodsetcache.go
+++ b/go/src/golang.org/x/tools/go/types/typeutil/methodsetcache.go
@@ -2,14 +2,15 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 // This file implements a cache of method sets.
 
 package typeutil
 
 import (
+	"go/types"
 	"sync"
-
-	"golang.org/x/tools/go/types"
 )
 
 // A MethodSetCache records the method set of each type T for which
diff --git a/go/src/golang.org/x/tools/go/types/typeutil/methodsetcache14.go b/go/src/golang.org/x/tools/go/types/typeutil/methodsetcache14.go
new file mode 100644
index 0000000..83b5e76
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/types/typeutil/methodsetcache14.go
@@ -0,0 +1,75 @@
+// Copyright 2014 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.
+
+// +build !go1.5
+
+// This file implements a cache of method sets.
+
+package typeutil
+
+import (
+	"sync"
+
+	"golang.org/x/tools/go/types"
+)
+
+// A MethodSetCache records the method set of each type T for which
+// MethodSet(T) is called so that repeat queries are fast.
+// The zero value is a ready-to-use cache instance.
+type MethodSetCache struct {
+	mu     sync.Mutex
+	named  map[*types.Named]struct{ value, pointer *types.MethodSet } // method sets for named N and *N
+	others map[types.Type]*types.MethodSet                            // all other types
+}
+
+// MethodSet returns the method set of type T.  It is thread-safe.
+//
+// If cache is nil, this function is equivalent to types.NewMethodSet(T).
+// Utility functions can thus expose an optional *MethodSetCache
+// parameter to clients that care about performance.
+//
+func (cache *MethodSetCache) MethodSet(T types.Type) *types.MethodSet {
+	if cache == nil {
+		return types.NewMethodSet(T)
+	}
+	cache.mu.Lock()
+	defer cache.mu.Unlock()
+
+	switch T := T.(type) {
+	case *types.Named:
+		return cache.lookupNamed(T).value
+
+	case *types.Pointer:
+		if N, ok := T.Elem().(*types.Named); ok {
+			return cache.lookupNamed(N).pointer
+		}
+	}
+
+	// all other types
+	// (The map uses pointer equivalence, not type identity.)
+	mset := cache.others[T]
+	if mset == nil {
+		mset = types.NewMethodSet(T)
+		if cache.others == nil {
+			cache.others = make(map[types.Type]*types.MethodSet)
+		}
+		cache.others[T] = mset
+	}
+	return mset
+}
+
+func (cache *MethodSetCache) lookupNamed(named *types.Named) struct{ value, pointer *types.MethodSet } {
+	if cache.named == nil {
+		cache.named = make(map[*types.Named]struct{ value, pointer *types.MethodSet })
+	}
+	// Avoid recomputing mset(*T) for each distinct Pointer
+	// instance whose underlying type is a named type.
+	msets, ok := cache.named[named]
+	if !ok {
+		msets.value = types.NewMethodSet(named)
+		msets.pointer = types.NewMethodSet(types.NewPointer(named))
+		cache.named[named] = msets
+	}
+	return msets
+}
diff --git a/go/src/golang.org/x/tools/go/types/typeutil/ui.go b/go/src/golang.org/x/tools/go/types/typeutil/ui.go
index 20c5249..945fb29 100644
--- a/go/src/golang.org/x/tools/go/types/typeutil/ui.go
+++ b/go/src/golang.org/x/tools/go/types/typeutil/ui.go
@@ -2,11 +2,13 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package typeutil
 
 // This file defines utilities for user interfaces that display types.
 
-import "golang.org/x/tools/go/types"
+import "go/types"
 
 // IntuitiveMethodSet returns the intuitive method set of a type, T.
 //
diff --git a/go/src/golang.org/x/tools/go/types/typeutil/ui14.go b/go/src/golang.org/x/tools/go/types/typeutil/ui14.go
new file mode 100644
index 0000000..bb78e0b
--- /dev/null
+++ b/go/src/golang.org/x/tools/go/types/typeutil/ui14.go
@@ -0,0 +1,40 @@
+// Copyright 2014 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.
+
+// +build !go1.5
+
+package typeutil
+
+// This file defines utilities for user interfaces that display types.
+
+import "golang.org/x/tools/go/types"
+
+// IntuitiveMethodSet returns the intuitive method set of a type, T.
+//
+// The result contains MethodSet(T) and additionally, if T is a
+// concrete type, methods belonging to *T if there is no identically
+// named method on T itself.  This corresponds to user intuition about
+// method sets; this function is intended only for user interfaces.
+//
+// The order of the result is as for types.MethodSet(T).
+//
+func IntuitiveMethodSet(T types.Type, msets *MethodSetCache) []*types.Selection {
+	var result []*types.Selection
+	mset := msets.MethodSet(T)
+	if _, ok := T.Underlying().(*types.Interface); ok {
+		for i, n := 0, mset.Len(); i < n; i++ {
+			result = append(result, mset.At(i))
+		}
+	} else {
+		pmset := msets.MethodSet(types.NewPointer(T))
+		for i, n := 0, pmset.Len(); i < n; i++ {
+			meth := pmset.At(i)
+			if m := mset.Lookup(meth.Obj().Pkg(), meth.Obj().Name()); m != nil {
+				meth = m
+			}
+			result = append(result, meth)
+		}
+	}
+	return result
+}
diff --git a/go/src/golang.org/x/tools/go/vcs/discovery.go b/go/src/golang.org/x/tools/go/vcs/discovery.go
index c4b0e3d..f431dc1 100644
--- a/go/src/golang.org/x/tools/go/vcs/discovery.go
+++ b/go/src/golang.org/x/tools/go/vcs/discovery.go
@@ -36,7 +36,7 @@
 	for {
 		t, err = d.Token()
 		if err != nil {
-			if err == io.EOF {
+			if err == io.EOF || len(imports) > 0 {
 				err = nil
 			}
 			return
diff --git a/go/src/golang.org/x/tools/go/vcs/vcs.go b/go/src/golang.org/x/tools/go/vcs/vcs.go
index 2d9b7de..f0aed57 100644
--- a/go/src/golang.org/x/tools/go/vcs/vcs.go
+++ b/go/src/golang.org/x/tools/go/vcs/vcs.go
@@ -335,8 +335,7 @@
 // FromDir inspects dir and its parents to determine the
 // version control system and code repository to use.
 // On return, root is the import path
-// corresponding to the root of the repository
-// (thus root is a prefix of importPath).
+// corresponding to the root of the repository.
 func FromDir(dir, srcRoot string) (vcs *Cmd, root string, err error) {
 	// Clean and double-check that dir is in (a subdirectory of) srcRoot.
 	dir = filepath.Clean(dir)
@@ -348,7 +347,7 @@
 	for len(dir) > len(srcRoot) {
 		for _, vcs := range vcsList {
 			if fi, err := os.Stat(filepath.Join(dir, "."+vcs.Cmd)); err == nil && fi.IsDir() {
-				return vcs, dir[len(srcRoot)+1:], nil
+				return vcs, filepath.ToSlash(dir[len(srcRoot)+1:]), nil
 			}
 		}
 
@@ -369,11 +368,11 @@
 type RepoRoot struct {
 	VCS *Cmd
 
-	// repo is the repository URL, including scheme
+	// Repo is the repository URL, including scheme.
 	Repo string
 
-	// root is the import path corresponding to the root of the
-	// repository
+	// Root is the import path corresponding to the root of the
+	// repository.
 	Root string
 }
 
@@ -478,11 +477,11 @@
 // RepoRootForImportDynamic finds a *RepoRoot for a custom domain that's not
 // statically known by RepoRootForImportPathStatic.
 //
-// This handles "vanity import paths" like "name.tld/pkg/foo".
+// This handles custom import paths like "name.tld/pkg/foo" or just "name.tld".
 func RepoRootForImportDynamic(importPath string, verbose bool) (*RepoRoot, error) {
 	slash := strings.Index(importPath, "/")
 	if slash < 0 {
-		return nil, errors.New("import path doesn't contain a slash")
+		slash = len(importPath)
 	}
 	host := importPath[:slash]
 	if !strings.Contains(host, ".") {
@@ -599,20 +598,6 @@
 		check:  noVCSSuffix,
 	},
 
-	// Google Code - new syntax
-	{
-		prefix: "code.google.com/",
-		re:     `^(?P<root>code\.google\.com/[pr]/(?P<project>[a-z0-9\-]+)(\.(?P<subrepo>[a-z0-9\-]+))?)(/[A-Za-z0-9_.\-]+)*$`,
-		repo:   "https://{root}",
-		check:  googleCodeVCS,
-	},
-
-	// Google Code - old syntax
-	{
-		re:    `^(?P<project>[a-z0-9_\-.]+)\.googlecode\.com/(git|hg|svn)(?P<path>/.*)?$`,
-		check: oldGoogleCode,
-	},
-
 	// Github
 	{
 		prefix: "github.com/",
@@ -668,45 +653,6 @@
 	return nil
 }
 
-var googleCheckout = regexp.MustCompile(`id="checkoutcmd">(hg|git|svn)`)
-
-// googleCodeVCS determines the version control system for
-// a code.google.com repository, by scraping the project's
-// /source/checkout page.
-func googleCodeVCS(match map[string]string) error {
-	if err := noVCSSuffix(match); err != nil {
-		return err
-	}
-	data, err := httpGET(expand(match, "https://code.google.com/p/{project}/source/checkout?repo={subrepo}"))
-	if err != nil {
-		return err
-	}
-
-	if m := googleCheckout.FindSubmatch(data); m != nil {
-		if vcs := ByCmd(string(m[1])); vcs != nil {
-			// Subversion requires the old URLs.
-			// TODO: Test.
-			if vcs == vcsSvn {
-				if match["subrepo"] != "" {
-					return fmt.Errorf("sub-repositories not supported in Google Code Subversion projects")
-				}
-				match["repo"] = expand(match, "https://{project}.googlecode.com/svn")
-			}
-			match["vcs"] = vcs.Cmd
-			return nil
-		}
-	}
-
-	return fmt.Errorf("unable to detect version control system for code.google.com/ path")
-}
-
-// oldGoogleCode is invoked for old-style foo.googlecode.com paths.
-// It prints an error giving the equivalent new path.
-func oldGoogleCode(match map[string]string) error {
-	return fmt.Errorf("invalid Google Code import path: use %s instead",
-		expand(match, "code.google.com/p/{project}{path}"))
-}
-
 // bitbucketVCS determines the version control system for a
 // Bitbucket repository, by using the Bitbucket API.
 func bitbucketVCS(match map[string]string) error {
diff --git a/go/src/golang.org/x/tools/go/vcs/vcs_test.go b/go/src/golang.org/x/tools/go/vcs/vcs_test.go
index 5d2d498..2d4bcda 100644
--- a/go/src/golang.org/x/tools/go/vcs/vcs_test.go
+++ b/go/src/golang.org/x/tools/go/vcs/vcs_test.go
@@ -7,6 +7,7 @@
 import (
 	"io/ioutil"
 	"os"
+	pathpkg "path"
 	"path/filepath"
 	"reflect"
 	"runtime"
@@ -47,11 +48,11 @@
 	}
 }
 
-// Test that FromDir correctly inspects a given directory and returns the right VCS.
+// Test that FromDir correctly inspects a given directory and returns the right VCS and root.
 func TestFromDir(t *testing.T) {
 	type testStruct struct {
 		path string
-		want *Cmd
+		want *RepoRoot
 	}
 
 	tests := make([]testStruct, len(vcsList))
@@ -63,16 +64,29 @@
 
 	for i, vcs := range vcsList {
 		tests[i] = testStruct{
-			filepath.Join(tempDir, vcs.Name, "."+vcs.Cmd),
-			vcs,
+			path: filepath.Join(tempDir, "example.com", vcs.Name, "."+vcs.Cmd),
+			want: &RepoRoot{
+				VCS:  vcs,
+				Root: pathpkg.Join("example.com", vcs.Name),
+			},
 		}
 	}
 
 	for _, test := range tests {
 		os.MkdirAll(test.path, 0755)
-		got, _, _ := FromDir(test.path, tempDir)
-		if got.Name != test.want.Name {
-			t.Errorf("FromDir(%q, %q) = %s, want %s", test.path, tempDir, got, test.want)
+		var (
+			got = new(RepoRoot)
+			err error
+		)
+		got.VCS, got.Root, err = FromDir(test.path, tempDir)
+		if err != nil {
+			t.Errorf("FromDir(%q, %q): %v", test.path, tempDir, err)
+			os.RemoveAll(test.path)
+			continue
+		}
+		want := test.want
+		if got.VCS.Name != want.VCS.Name || got.Root != want.Root {
+			t.Errorf("FromDir(%q, %q) = VCS(%s) Root(%s), want VCS(%s) Root(%s)", test.path, tempDir, got.VCS, got.Root, want.VCS, want.Root)
 		}
 		os.RemoveAll(test.path)
 	}
diff --git a/go/src/golang.org/x/tools/godoc/analysis/analysis.go b/go/src/golang.org/x/tools/godoc/analysis/analysis.go
index c11ecbd..5c43bbe 100644
--- a/go/src/golang.org/x/tools/godoc/analysis/analysis.go
+++ b/go/src/golang.org/x/tools/godoc/analysis/analysis.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 // Package analysis performs type and pointer analysis
 // and generates mark-up for the Go source view.
 //
@@ -45,8 +47,10 @@
 import (
 	"fmt"
 	"go/build"
+	exact "go/constant"
 	"go/scanner"
 	"go/token"
+	"go/types"
 	"html"
 	"io"
 	"log"
@@ -57,12 +61,10 @@
 	"strings"
 	"sync"
 
-	"golang.org/x/tools/go/exact"
 	"golang.org/x/tools/go/loader"
 	"golang.org/x/tools/go/pointer"
 	"golang.org/x/tools/go/ssa"
 	"golang.org/x/tools/go/ssa/ssautil"
-	"golang.org/x/tools/go/types"
 )
 
 // -- links ------------------------------------------------------------
@@ -405,7 +407,7 @@
 		}
 	}
 	for _, pkg := range allPackages {
-		if pkg.Object.Name() == "main" && pkg.Func("main") != nil {
+		if pkg.Pkg.Name() == "main" && pkg.Func("main") != nil {
 			mainPkgs = append(mainPkgs, pkg)
 		}
 	}
@@ -413,7 +415,7 @@
 
 	// Build SSA code for bodies of all functions in the whole program.
 	result.setStatusf("Constructing SSA form...")
-	prog.BuildAll()
+	prog.Build()
 	log.Print("SSA construction complete")
 
 	a := analysis{
diff --git a/go/src/golang.org/x/tools/godoc/analysis/analysis14.go b/go/src/golang.org/x/tools/godoc/analysis/analysis14.go
new file mode 100644
index 0000000..ca35b41
--- /dev/null
+++ b/go/src/golang.org/x/tools/godoc/analysis/analysis14.go
@@ -0,0 +1,622 @@
+// Copyright 2014 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.
+
+// +build !go1.5
+
+// Package analysis performs type and pointer analysis
+// and generates mark-up for the Go source view.
+//
+// The Run method populates a Result object by running type and
+// (optionally) pointer analysis.  The Result object is thread-safe
+// and at all times may be accessed by a serving thread, even as it is
+// progressively populated as analysis facts are derived.
+//
+// The Result is a mapping from each godoc file URL
+// (e.g. /src/fmt/print.go) to information about that file.  The
+// information is a list of HTML markup links and a JSON array of
+// structured data values.  Some of the links call client-side
+// JavaScript functions that index this array.
+//
+// The analysis computes mark-up for the following relations:
+//
+// IMPORTS: for each ast.ImportSpec, the package that it denotes.
+//
+// RESOLUTION: for each ast.Ident, its kind and type, and the location
+// of its definition.
+//
+// METHOD SETS, IMPLEMENTS: for each ast.Ident defining a named type,
+// its method-set, the set of interfaces it implements or is
+// implemented by, and its size/align values.
+//
+// CALLERS, CALLEES: for each function declaration ('func' token), its
+// callers, and for each call-site ('(' token), its callees.
+//
+// CALLGRAPH: the package docs include an interactive viewer for the
+// intra-package call graph of "fmt".
+//
+// CHANNEL PEERS: for each channel operation make/<-/close, the set of
+// other channel ops that alias the same channel(s).
+//
+// ERRORS: for each locus of a frontend (scanner/parser/type) error, the
+// location is highlighted in red and hover text provides the compiler
+// error message.
+//
+package analysis // import "golang.org/x/tools/godoc/analysis"
+
+import (
+	"fmt"
+	"go/build"
+	"go/scanner"
+	"go/token"
+	"html"
+	"io"
+	"log"
+	"os"
+	"path/filepath"
+	"runtime"
+	"sort"
+	"strings"
+	"sync"
+
+	"golang.org/x/tools/go/exact"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/pointer"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/ssa/ssautil"
+	"golang.org/x/tools/go/types"
+)
+
+// -- links ------------------------------------------------------------
+
+// A Link is an HTML decoration of the bytes [Start, End) of a file.
+// Write is called before/after those bytes to emit the mark-up.
+type Link interface {
+	Start() int
+	End() int
+	Write(w io.Writer, _ int, start bool) // the godoc.LinkWriter signature
+}
+
+// An <a> element.
+type aLink struct {
+	start, end int    // =godoc.Segment
+	title      string // hover text
+	onclick    string // JS code (NB: trusted)
+	href       string // URL     (NB: trusted)
+}
+
+func (a aLink) Start() int { return a.start }
+func (a aLink) End() int   { return a.end }
+func (a aLink) Write(w io.Writer, _ int, start bool) {
+	if start {
+		fmt.Fprintf(w, `<a title='%s'`, html.EscapeString(a.title))
+		if a.onclick != "" {
+			fmt.Fprintf(w, ` onclick='%s'`, html.EscapeString(a.onclick))
+		}
+		if a.href != "" {
+			// TODO(adonovan): I think that in principle, a.href must first be
+			// url.QueryEscape'd, but if I do that, a leading slash becomes "%2F",
+			// which causes the browser to treat the path as relative, not absolute.
+			// WTF?
+			fmt.Fprintf(w, ` href='%s'`, html.EscapeString(a.href))
+		}
+		fmt.Fprintf(w, ">")
+	} else {
+		fmt.Fprintf(w, "</a>")
+	}
+}
+
+// An <a class='error'> element.
+type errorLink struct {
+	start int
+	msg   string
+}
+
+func (e errorLink) Start() int { return e.start }
+func (e errorLink) End() int   { return e.start + 1 }
+
+func (e errorLink) Write(w io.Writer, _ int, start bool) {
+	// <span> causes havoc, not sure why, so use <a>.
+	if start {
+		fmt.Fprintf(w, `<a class='error' title='%s'>`, html.EscapeString(e.msg))
+	} else {
+		fmt.Fprintf(w, "</a>")
+	}
+}
+
+// -- fileInfo ---------------------------------------------------------
+
+// FileInfo holds analysis information for the source file view.
+// Clients must not mutate it.
+type FileInfo struct {
+	Data  []interface{} // JSON serializable values
+	Links []Link        // HTML link markup
+}
+
+// A fileInfo is the server's store of hyperlinks and JSON data for a
+// particular file.
+type fileInfo struct {
+	mu        sync.Mutex
+	data      []interface{} // JSON objects
+	links     []Link
+	sorted    bool
+	hasErrors bool // TODO(adonovan): surface this in the UI
+}
+
+// addLink adds a link to the Go source file fi.
+func (fi *fileInfo) addLink(link Link) {
+	fi.mu.Lock()
+	fi.links = append(fi.links, link)
+	fi.sorted = false
+	if _, ok := link.(errorLink); ok {
+		fi.hasErrors = true
+	}
+	fi.mu.Unlock()
+}
+
+// addData adds the structured value x to the JSON data for the Go
+// source file fi.  Its index is returned.
+func (fi *fileInfo) addData(x interface{}) int {
+	fi.mu.Lock()
+	index := len(fi.data)
+	fi.data = append(fi.data, x)
+	fi.mu.Unlock()
+	return index
+}
+
+// get returns the file info in external form.
+// Callers must not mutate its fields.
+func (fi *fileInfo) get() FileInfo {
+	var r FileInfo
+	// Copy slices, to avoid races.
+	fi.mu.Lock()
+	r.Data = append(r.Data, fi.data...)
+	if !fi.sorted {
+		sort.Sort(linksByStart(fi.links))
+		fi.sorted = true
+	}
+	r.Links = append(r.Links, fi.links...)
+	fi.mu.Unlock()
+	return r
+}
+
+// PackageInfo holds analysis information for the package view.
+// Clients must not mutate it.
+type PackageInfo struct {
+	CallGraph      []*PCGNodeJSON
+	CallGraphIndex map[string]int
+	Types          []*TypeInfoJSON
+}
+
+type pkgInfo struct {
+	mu             sync.Mutex
+	callGraph      []*PCGNodeJSON
+	callGraphIndex map[string]int  // keys are (*ssa.Function).RelString()
+	types          []*TypeInfoJSON // type info for exported types
+}
+
+func (pi *pkgInfo) setCallGraph(callGraph []*PCGNodeJSON, callGraphIndex map[string]int) {
+	pi.mu.Lock()
+	pi.callGraph = callGraph
+	pi.callGraphIndex = callGraphIndex
+	pi.mu.Unlock()
+}
+
+func (pi *pkgInfo) addType(t *TypeInfoJSON) {
+	pi.mu.Lock()
+	pi.types = append(pi.types, t)
+	pi.mu.Unlock()
+}
+
+// get returns the package info in external form.
+// Callers must not mutate its fields.
+func (pi *pkgInfo) get() PackageInfo {
+	var r PackageInfo
+	// Copy slices, to avoid races.
+	pi.mu.Lock()
+	r.CallGraph = append(r.CallGraph, pi.callGraph...)
+	r.CallGraphIndex = pi.callGraphIndex
+	r.Types = append(r.Types, pi.types...)
+	pi.mu.Unlock()
+	return r
+}
+
+// -- Result -----------------------------------------------------------
+
+// Result contains the results of analysis.
+// The result contains a mapping from filenames to a set of HTML links
+// and JavaScript data referenced by the links.
+type Result struct {
+	mu        sync.Mutex           // guards maps (but not their contents)
+	status    string               // global analysis status
+	fileInfos map[string]*fileInfo // keys are godoc file URLs
+	pkgInfos  map[string]*pkgInfo  // keys are import paths
+}
+
+// fileInfo returns the fileInfo for the specified godoc file URL,
+// constructing it as needed.  Thread-safe.
+func (res *Result) fileInfo(url string) *fileInfo {
+	res.mu.Lock()
+	fi, ok := res.fileInfos[url]
+	if !ok {
+		if res.fileInfos == nil {
+			res.fileInfos = make(map[string]*fileInfo)
+		}
+		fi = new(fileInfo)
+		res.fileInfos[url] = fi
+	}
+	res.mu.Unlock()
+	return fi
+}
+
+// Status returns a human-readable description of the current analysis status.
+func (res *Result) Status() string {
+	res.mu.Lock()
+	defer res.mu.Unlock()
+	return res.status
+}
+
+func (res *Result) setStatusf(format string, args ...interface{}) {
+	res.mu.Lock()
+	res.status = fmt.Sprintf(format, args...)
+	log.Printf(format, args...)
+	res.mu.Unlock()
+}
+
+// FileInfo returns new slices containing opaque JSON values and the
+// HTML link markup for the specified godoc file URL.  Thread-safe.
+// Callers must not mutate the elements.
+// It returns "zero" if no data is available.
+//
+func (res *Result) FileInfo(url string) (fi FileInfo) {
+	return res.fileInfo(url).get()
+}
+
+// pkgInfo returns the pkgInfo for the specified import path,
+// constructing it as needed.  Thread-safe.
+func (res *Result) pkgInfo(importPath string) *pkgInfo {
+	res.mu.Lock()
+	pi, ok := res.pkgInfos[importPath]
+	if !ok {
+		if res.pkgInfos == nil {
+			res.pkgInfos = make(map[string]*pkgInfo)
+		}
+		pi = new(pkgInfo)
+		res.pkgInfos[importPath] = pi
+	}
+	res.mu.Unlock()
+	return pi
+}
+
+// PackageInfo returns new slices of JSON values for the callgraph and
+// type info for the specified package.  Thread-safe.
+// Callers must not mutate its fields.
+// PackageInfo returns "zero" if no data is available.
+//
+func (res *Result) PackageInfo(importPath string) PackageInfo {
+	return res.pkgInfo(importPath).get()
+}
+
+// -- analysis ---------------------------------------------------------
+
+type analysis struct {
+	result    *Result
+	prog      *ssa.Program
+	ops       []chanOp       // all channel ops in program
+	allNamed  []*types.Named // all named types in the program
+	ptaConfig pointer.Config
+	path2url  map[string]string // maps openable path to godoc file URL (/src/fmt/print.go)
+	pcgs      map[*ssa.Package]*packageCallGraph
+}
+
+// fileAndOffset returns the file and offset for a given pos.
+func (a *analysis) fileAndOffset(pos token.Pos) (fi *fileInfo, offset int) {
+	return a.fileAndOffsetPosn(a.prog.Fset.Position(pos))
+}
+
+// fileAndOffsetPosn returns the file and offset for a given position.
+func (a *analysis) fileAndOffsetPosn(posn token.Position) (fi *fileInfo, offset int) {
+	url := a.path2url[posn.Filename]
+	return a.result.fileInfo(url), posn.Offset
+}
+
+// posURL returns the URL of the source extent [pos, pos+len).
+func (a *analysis) posURL(pos token.Pos, len int) string {
+	if pos == token.NoPos {
+		return ""
+	}
+	posn := a.prog.Fset.Position(pos)
+	url := a.path2url[posn.Filename]
+	return fmt.Sprintf("%s?s=%d:%d#L%d",
+		url, posn.Offset, posn.Offset+len, posn.Line)
+}
+
+// ----------------------------------------------------------------------
+
+// Run runs program analysis and computes the resulting markup,
+// populating *result in a thread-safe manner, first with type
+// information then later with pointer analysis information if
+// enabled by the pta flag.
+//
+func Run(pta bool, result *Result) {
+	conf := loader.Config{
+		AllowErrors: true,
+	}
+
+	// Silence the default error handler.
+	// Don't print all errors; we'll report just
+	// one per errant package later.
+	conf.TypeChecker.Error = func(e error) {}
+
+	var roots, args []string // roots[i] ends with os.PathSeparator
+
+	// Enumerate packages in $GOROOT.
+	root := filepath.Join(runtime.GOROOT(), "src") + string(os.PathSeparator)
+	roots = append(roots, root)
+	args = allPackages(root)
+	log.Printf("GOROOT=%s: %s\n", root, args)
+
+	// Enumerate packages in $GOPATH.
+	for i, dir := range filepath.SplitList(build.Default.GOPATH) {
+		root := filepath.Join(dir, "src") + string(os.PathSeparator)
+		roots = append(roots, root)
+		pkgs := allPackages(root)
+		log.Printf("GOPATH[%d]=%s: %s\n", i, root, pkgs)
+		args = append(args, pkgs...)
+	}
+
+	// Uncomment to make startup quicker during debugging.
+	//args = []string{"golang.org/x/tools/cmd/godoc"}
+	//args = []string{"fmt"}
+
+	if _, err := conf.FromArgs(args, true); err != nil {
+		// TODO(adonovan): degrade gracefully, not fail totally.
+		// (The crippling case is a parse error in an external test file.)
+		result.setStatusf("Analysis failed: %s.", err) // import error
+		return
+	}
+
+	result.setStatusf("Loading and type-checking packages...")
+	iprog, err := conf.Load()
+	if iprog != nil {
+		// Report only the first error of each package.
+		for _, info := range iprog.AllPackages {
+			for _, err := range info.Errors {
+				fmt.Fprintln(os.Stderr, err)
+				break
+			}
+		}
+		log.Printf("Loaded %d packages.", len(iprog.AllPackages))
+	}
+	if err != nil {
+		result.setStatusf("Loading failed: %s.\n", err)
+		return
+	}
+
+	// Create SSA-form program representation.
+	// Only the transitively error-free packages are used.
+	prog := ssautil.CreateProgram(iprog, ssa.GlobalDebug)
+
+	// Compute the set of main packages, including testmain.
+	allPackages := prog.AllPackages()
+	var mainPkgs []*ssa.Package
+	if testmain := prog.CreateTestMainPackage(allPackages...); testmain != nil {
+		mainPkgs = append(mainPkgs, testmain)
+		if p := testmain.Const("packages"); p != nil {
+			log.Printf("Tested packages: %v", exact.StringVal(p.Value.Value))
+		}
+	}
+	for _, pkg := range allPackages {
+		if pkg.Pkg.Name() == "main" && pkg.Func("main") != nil {
+			mainPkgs = append(mainPkgs, pkg)
+		}
+	}
+	log.Print("Transitively error-free main packages: ", mainPkgs)
+
+	// Build SSA code for bodies of all functions in the whole program.
+	result.setStatusf("Constructing SSA form...")
+	prog.Build()
+	log.Print("SSA construction complete")
+
+	a := analysis{
+		result: result,
+		prog:   prog,
+		pcgs:   make(map[*ssa.Package]*packageCallGraph),
+	}
+
+	// Build a mapping from openable filenames to godoc file URLs,
+	// i.e. "/src/" plus path relative to GOROOT/src or GOPATH[i]/src.
+	a.path2url = make(map[string]string)
+	for _, info := range iprog.AllPackages {
+	nextfile:
+		for _, f := range info.Files {
+			if f.Pos() == 0 {
+				continue // e.g. files generated by cgo
+			}
+			abs := iprog.Fset.File(f.Pos()).Name()
+			// Find the root to which this file belongs.
+			for _, root := range roots {
+				rel := strings.TrimPrefix(abs, root)
+				if len(rel) < len(abs) {
+					a.path2url[abs] = "/src/" + filepath.ToSlash(rel)
+					continue nextfile
+				}
+			}
+
+			log.Printf("Can't locate file %s (package %q) beneath any root",
+				abs, info.Pkg.Path())
+		}
+	}
+
+	// Add links for scanner, parser, type-checker errors.
+	// TODO(adonovan): fix: these links can overlap with
+	// identifier markup, causing the renderer to emit some
+	// characters twice.
+	errors := make(map[token.Position][]string)
+	for _, info := range iprog.AllPackages {
+		for _, err := range info.Errors {
+			switch err := err.(type) {
+			case types.Error:
+				posn := a.prog.Fset.Position(err.Pos)
+				errors[posn] = append(errors[posn], err.Msg)
+			case scanner.ErrorList:
+				for _, e := range err {
+					errors[e.Pos] = append(errors[e.Pos], e.Msg)
+				}
+			default:
+				log.Printf("Package %q has error (%T) without position: %v\n",
+					info.Pkg.Path(), err, err)
+			}
+		}
+	}
+	for posn, errs := range errors {
+		fi, offset := a.fileAndOffsetPosn(posn)
+		fi.addLink(errorLink{
+			start: offset,
+			msg:   strings.Join(errs, "\n"),
+		})
+	}
+
+	// ---------- type-based analyses ----------
+
+	// Compute the all-pairs IMPLEMENTS relation.
+	// Collect all named types, even local types
+	// (which can have methods via promotion)
+	// and the built-in "error".
+	errorType := types.Universe.Lookup("error").Type().(*types.Named)
+	a.allNamed = append(a.allNamed, errorType)
+	for _, info := range iprog.AllPackages {
+		for _, obj := range info.Defs {
+			if obj, ok := obj.(*types.TypeName); ok {
+				a.allNamed = append(a.allNamed, obj.Type().(*types.Named))
+			}
+		}
+	}
+	log.Print("Computing implements relation...")
+	facts := computeImplements(&a.prog.MethodSets, a.allNamed)
+
+	// Add the type-based analysis results.
+	log.Print("Extracting type info...")
+	for _, info := range iprog.AllPackages {
+		a.doTypeInfo(info, facts)
+	}
+
+	a.visitInstrs(pta)
+
+	result.setStatusf("Type analysis complete.")
+
+	if pta {
+		a.pointer(mainPkgs)
+	}
+}
+
+// visitInstrs visits all SSA instructions in the program.
+func (a *analysis) visitInstrs(pta bool) {
+	log.Print("Visit instructions...")
+	for fn := range ssautil.AllFunctions(a.prog) {
+		for _, b := range fn.Blocks {
+			for _, instr := range b.Instrs {
+				// CALLEES (static)
+				// (Dynamic calls require pointer analysis.)
+				//
+				// We use the SSA representation to find the static callee,
+				// since in many cases it does better than the
+				// types.Info.{Refs,Selection} information.  For example:
+				//
+				//   defer func(){}()      // static call to anon function
+				//   f := func(){}; f()    // static call to anon function
+				//   f := fmt.Println; f() // static call to named function
+				//
+				// The downside is that we get no static callee information
+				// for packages that (transitively) contain errors.
+				if site, ok := instr.(ssa.CallInstruction); ok {
+					if callee := site.Common().StaticCallee(); callee != nil {
+						// TODO(adonovan): callgraph: elide wrappers.
+						// (Do static calls ever go to wrappers?)
+						if site.Common().Pos() != token.NoPos {
+							a.addCallees(site, []*ssa.Function{callee})
+						}
+					}
+				}
+
+				if !pta {
+					continue
+				}
+
+				// CHANNEL PEERS
+				// Collect send/receive/close instructions in the whole ssa.Program.
+				for _, op := range chanOps(instr) {
+					a.ops = append(a.ops, op)
+					a.ptaConfig.AddQuery(op.ch) // add channel ssa.Value to PTA query
+				}
+			}
+		}
+	}
+	log.Print("Visit instructions complete")
+}
+
+// pointer runs the pointer analysis.
+func (a *analysis) pointer(mainPkgs []*ssa.Package) {
+	// Run the pointer analysis and build the complete callgraph.
+	a.ptaConfig.Mains = mainPkgs
+	a.ptaConfig.BuildCallGraph = true
+	a.ptaConfig.Reflection = false // (for now)
+
+	a.result.setStatusf("Pointer analysis running...")
+
+	ptares, err := pointer.Analyze(&a.ptaConfig)
+	if err != nil {
+		// If this happens, it indicates a bug.
+		a.result.setStatusf("Pointer analysis failed: %s.", err)
+		return
+	}
+	log.Print("Pointer analysis complete.")
+
+	// Add the results of pointer analysis.
+
+	a.result.setStatusf("Computing channel peers...")
+	a.doChannelPeers(ptares.Queries)
+	a.result.setStatusf("Computing dynamic call graph edges...")
+	a.doCallgraph(ptares.CallGraph)
+
+	a.result.setStatusf("Analysis complete.")
+}
+
+type linksByStart []Link
+
+func (a linksByStart) Less(i, j int) bool { return a[i].Start() < a[j].Start() }
+func (a linksByStart) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+func (a linksByStart) Len() int           { return len(a) }
+
+// allPackages returns a new sorted slice of all packages beneath the
+// specified package root directory, e.g. $GOROOT/src or $GOPATH/src.
+// Derived from from go/ssa/stdlib_test.go
+// root must end with os.PathSeparator.
+//
+// TODO(adonovan): use buildutil.AllPackages when the tree thaws.
+func allPackages(root string) []string {
+	var pkgs []string
+	filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
+		if info == nil {
+			return nil // non-existent root directory?
+		}
+		if !info.IsDir() {
+			return nil // not a directory
+		}
+		// Prune the search if we encounter any of these names:
+		base := filepath.Base(path)
+		if base == "testdata" || strings.HasPrefix(base, ".") {
+			return filepath.SkipDir
+		}
+		pkg := filepath.ToSlash(strings.TrimPrefix(path, root))
+		switch pkg {
+		case "builtin":
+			return filepath.SkipDir
+		case "":
+			return nil // ignore root of tree
+		}
+		pkgs = append(pkgs, pkg)
+		return nil
+	})
+	return pkgs
+}
diff --git a/go/src/golang.org/x/tools/godoc/analysis/callgraph.go b/go/src/golang.org/x/tools/godoc/analysis/callgraph.go
index a98d294..4e97061 100644
--- a/go/src/golang.org/x/tools/godoc/analysis/callgraph.go
+++ b/go/src/golang.org/x/tools/godoc/analysis/callgraph.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package analysis
 
 // This file computes the CALLERS and CALLEES relations from the call
@@ -12,13 +14,13 @@
 	"fmt"
 	"go/ast"
 	"go/token"
+	"go/types"
 	"log"
 	"math/big"
 	"sort"
 
 	"golang.org/x/tools/go/callgraph"
 	"golang.org/x/tools/go/ssa"
-	"golang.org/x/tools/go/types"
 )
 
 // doCallgraph computes the CALLEES and CALLERS relations.
@@ -104,7 +106,7 @@
 
 		var this *types.Package // for relativizing names
 		if callee.Pkg != nil {
-			this = callee.Pkg.Object
+			this = callee.Pkg.Pkg
 		}
 
 		// Compute sites grouped by parent, with text and URLs.
@@ -169,14 +171,14 @@
 				roots := &pcg.nodes[0].edges
 				roots.SetBit(roots, i, 1)
 			}
-			index[n.fn.RelString(pkg.Object)] = i
+			index[n.fn.RelString(pkg.Pkg)] = i
 		}
 
 		json := a.pcgJSON(pcg)
 
 		// TODO(adonovan): pkg.Path() is not unique!
 		// It is possible to declare a non-test package called x_test.
-		a.result.pkgInfo(pkg.Object.Path()).setCallGraph(json, index)
+		a.result.pkgInfo(pkg.Pkg.Path()).setCallGraph(json, index)
 	}
 }
 
@@ -188,7 +190,7 @@
 	}
 	var this *types.Package // for relativizing names
 	if p := site.Parent().Package(); p != nil {
-		this = p.Object
+		this = p.Pkg
 	}
 
 	for _, fn := range fns {
@@ -242,10 +244,10 @@
 	}
 	if fn.Synthetic != "" && fn.Name() == "init" {
 		// (This is the actual initializer, not a declared 'func init').
-		if fn.Pkg.Object == this {
+		if fn.Pkg.Pkg == this {
 			return "package initializer"
 		}
-		return fmt.Sprintf("%q package initializer", fn.Pkg.Object.Path())
+		return fmt.Sprintf("%q package initializer", fn.Pkg.Pkg.Path())
 	}
 	return fn.RelString(this)
 }
@@ -273,7 +275,7 @@
 	for fn := range pcg.nodeIndex {
 		nodes = append(nodes, &pcgNode{
 			fn:     fn,
-			pretty: prettyFunc(fn.Pkg.Object, fn),
+			pretty: prettyFunc(fn.Pkg.Pkg, fn),
 		})
 	}
 	sort.Sort(pcgNodesByPretty(nodes[1:]))
diff --git a/go/src/golang.org/x/tools/godoc/analysis/callgraph14.go b/go/src/golang.org/x/tools/godoc/analysis/callgraph14.go
new file mode 100644
index 0000000..2692d7e
--- /dev/null
+++ b/go/src/golang.org/x/tools/godoc/analysis/callgraph14.go
@@ -0,0 +1,353 @@
+// Copyright 2014 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.
+
+// +build !go1.5
+
+package analysis
+
+// This file computes the CALLERS and CALLEES relations from the call
+// graph.  CALLERS/CALLEES information is displayed in the lower pane
+// when a "func" token or ast.CallExpr.Lparen is clicked, respectively.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"log"
+	"math/big"
+	"sort"
+
+	"golang.org/x/tools/go/callgraph"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/types"
+)
+
+// doCallgraph computes the CALLEES and CALLERS relations.
+func (a *analysis) doCallgraph(cg *callgraph.Graph) {
+	log.Print("Deleting synthetic nodes...")
+	// TODO(adonovan): opt: DeleteSyntheticNodes is asymptotically
+	// inefficient and can be (unpredictably) slow.
+	cg.DeleteSyntheticNodes()
+	log.Print("Synthetic nodes deleted")
+
+	// Populate nodes of package call graphs (PCGs).
+	for _, n := range cg.Nodes {
+		a.pcgAddNode(n.Func)
+	}
+	// Within each PCG, sort funcs by name.
+	for _, pcg := range a.pcgs {
+		pcg.sortNodes()
+	}
+
+	calledFuncs := make(map[ssa.CallInstruction]map[*ssa.Function]bool)
+	callingSites := make(map[*ssa.Function]map[ssa.CallInstruction]bool)
+	for _, n := range cg.Nodes {
+		for _, e := range n.Out {
+			if e.Site == nil {
+				continue // a call from a synthetic node such as <root>
+			}
+
+			// Add (site pos, callee) to calledFuncs.
+			// (Dynamic calls only.)
+			callee := e.Callee.Func
+
+			a.pcgAddEdge(n.Func, callee)
+
+			if callee.Synthetic != "" {
+				continue // call of a package initializer
+			}
+
+			if e.Site.Common().StaticCallee() == nil {
+				// dynamic call
+				// (CALLEES information for static calls
+				// is computed using SSA information.)
+				lparen := e.Site.Common().Pos()
+				if lparen != token.NoPos {
+					fns := calledFuncs[e.Site]
+					if fns == nil {
+						fns = make(map[*ssa.Function]bool)
+						calledFuncs[e.Site] = fns
+					}
+					fns[callee] = true
+				}
+			}
+
+			// Add (callee, site) to callingSites.
+			fns := callingSites[callee]
+			if fns == nil {
+				fns = make(map[ssa.CallInstruction]bool)
+				callingSites[callee] = fns
+			}
+			fns[e.Site] = true
+		}
+	}
+
+	// CALLEES.
+	log.Print("Callees...")
+	for site, fns := range calledFuncs {
+		var funcs funcsByPos
+		for fn := range fns {
+			funcs = append(funcs, fn)
+		}
+		sort.Sort(funcs)
+
+		a.addCallees(site, funcs)
+	}
+
+	// CALLERS
+	log.Print("Callers...")
+	for callee, sites := range callingSites {
+		pos := funcToken(callee)
+		if pos == token.NoPos {
+			log.Printf("CALLERS: skipping %s: no pos", callee)
+			continue
+		}
+
+		var this *types.Package // for relativizing names
+		if callee.Pkg != nil {
+			this = callee.Pkg.Pkg
+		}
+
+		// Compute sites grouped by parent, with text and URLs.
+		sitesByParent := make(map[*ssa.Function]sitesByPos)
+		for site := range sites {
+			fn := site.Parent()
+			sitesByParent[fn] = append(sitesByParent[fn], site)
+		}
+		var funcs funcsByPos
+		for fn := range sitesByParent {
+			funcs = append(funcs, fn)
+		}
+		sort.Sort(funcs)
+
+		v := callersJSON{
+			Callee:  callee.String(),
+			Callers: []callerJSON{}, // (JS wants non-nil)
+		}
+		for _, fn := range funcs {
+			caller := callerJSON{
+				Func:  prettyFunc(this, fn),
+				Sites: []anchorJSON{}, // (JS wants non-nil)
+			}
+			sites := sitesByParent[fn]
+			sort.Sort(sites)
+			for _, site := range sites {
+				pos := site.Common().Pos()
+				if pos != token.NoPos {
+					caller.Sites = append(caller.Sites, anchorJSON{
+						Text: fmt.Sprintf("%d", a.prog.Fset.Position(pos).Line),
+						Href: a.posURL(pos, len("(")),
+					})
+				}
+			}
+			v.Callers = append(v.Callers, caller)
+		}
+
+		fi, offset := a.fileAndOffset(pos)
+		fi.addLink(aLink{
+			start:   offset,
+			end:     offset + len("func"),
+			title:   fmt.Sprintf("%d callers", len(sites)),
+			onclick: fmt.Sprintf("onClickCallers(%d)", fi.addData(v)),
+		})
+	}
+
+	// PACKAGE CALLGRAPH
+	log.Print("Package call graph...")
+	for pkg, pcg := range a.pcgs {
+		// Maps (*ssa.Function).RelString() to index in JSON CALLGRAPH array.
+		index := make(map[string]int)
+
+		// Treat exported functions (and exported methods of
+		// exported named types) as roots even if they aren't
+		// actually called from outside the package.
+		for i, n := range pcg.nodes {
+			if i == 0 || n.fn.Object() == nil || !n.fn.Object().Exported() {
+				continue
+			}
+			recv := n.fn.Signature.Recv()
+			if recv == nil || deref(recv.Type()).(*types.Named).Obj().Exported() {
+				roots := &pcg.nodes[0].edges
+				roots.SetBit(roots, i, 1)
+			}
+			index[n.fn.RelString(pkg.Pkg)] = i
+		}
+
+		json := a.pcgJSON(pcg)
+
+		// TODO(adonovan): pkg.Path() is not unique!
+		// It is possible to declare a non-test package called x_test.
+		a.result.pkgInfo(pkg.Pkg.Path()).setCallGraph(json, index)
+	}
+}
+
+// addCallees adds client data and links for the facts that site calls fns.
+func (a *analysis) addCallees(site ssa.CallInstruction, fns []*ssa.Function) {
+	v := calleesJSON{
+		Descr:   site.Common().Description(),
+		Callees: []anchorJSON{}, // (JS wants non-nil)
+	}
+	var this *types.Package // for relativizing names
+	if p := site.Parent().Package(); p != nil {
+		this = p.Pkg
+	}
+
+	for _, fn := range fns {
+		v.Callees = append(v.Callees, anchorJSON{
+			Text: prettyFunc(this, fn),
+			Href: a.posURL(funcToken(fn), len("func")),
+		})
+	}
+
+	fi, offset := a.fileAndOffset(site.Common().Pos())
+	fi.addLink(aLink{
+		start:   offset,
+		end:     offset + len("("),
+		title:   fmt.Sprintf("%d callees", len(v.Callees)),
+		onclick: fmt.Sprintf("onClickCallees(%d)", fi.addData(v)),
+	})
+}
+
+// -- utilities --------------------------------------------------------
+
+// stable order within packages but undefined across packages.
+type funcsByPos []*ssa.Function
+
+func (a funcsByPos) Less(i, j int) bool { return a[i].Pos() < a[j].Pos() }
+func (a funcsByPos) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+func (a funcsByPos) Len() int           { return len(a) }
+
+type sitesByPos []ssa.CallInstruction
+
+func (a sitesByPos) Less(i, j int) bool { return a[i].Common().Pos() < a[j].Common().Pos() }
+func (a sitesByPos) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+func (a sitesByPos) Len() int           { return len(a) }
+
+func funcToken(fn *ssa.Function) token.Pos {
+	switch syntax := fn.Syntax().(type) {
+	case *ast.FuncLit:
+		return syntax.Type.Func
+	case *ast.FuncDecl:
+		return syntax.Type.Func
+	}
+	return token.NoPos
+}
+
+// prettyFunc pretty-prints fn for the user interface.
+// TODO(adonovan): return HTML so we have more markup freedom.
+func prettyFunc(this *types.Package, fn *ssa.Function) string {
+	if fn.Parent() != nil {
+		return fmt.Sprintf("%s in %s",
+			types.TypeString(fn.Signature, types.RelativeTo(this)),
+			prettyFunc(this, fn.Parent()))
+	}
+	if fn.Synthetic != "" && fn.Name() == "init" {
+		// (This is the actual initializer, not a declared 'func init').
+		if fn.Pkg.Pkg == this {
+			return "package initializer"
+		}
+		return fmt.Sprintf("%q package initializer", fn.Pkg.Pkg.Path())
+	}
+	return fn.RelString(this)
+}
+
+// -- intra-package callgraph ------------------------------------------
+
+// pcgNode represents a node in the package call graph (PCG).
+type pcgNode struct {
+	fn     *ssa.Function
+	pretty string  // cache of prettyFunc(fn)
+	edges  big.Int // set of callee func indices
+}
+
+// A packageCallGraph represents the intra-package edges of the global call graph.
+// The zeroth node indicates "all external functions".
+type packageCallGraph struct {
+	nodeIndex map[*ssa.Function]int // maps func to node index (a small int)
+	nodes     []*pcgNode            // maps node index to node
+}
+
+// sortNodes populates pcg.nodes in name order and updates the nodeIndex.
+func (pcg *packageCallGraph) sortNodes() {
+	nodes := make([]*pcgNode, 0, len(pcg.nodeIndex))
+	nodes = append(nodes, &pcgNode{fn: nil, pretty: "<external>"})
+	for fn := range pcg.nodeIndex {
+		nodes = append(nodes, &pcgNode{
+			fn:     fn,
+			pretty: prettyFunc(fn.Pkg.Pkg, fn),
+		})
+	}
+	sort.Sort(pcgNodesByPretty(nodes[1:]))
+	for i, n := range nodes {
+		pcg.nodeIndex[n.fn] = i
+	}
+	pcg.nodes = nodes
+}
+
+func (pcg *packageCallGraph) addEdge(caller, callee *ssa.Function) {
+	var callerIndex int
+	if caller.Pkg == callee.Pkg {
+		// intra-package edge
+		callerIndex = pcg.nodeIndex[caller]
+		if callerIndex < 1 {
+			panic(caller)
+		}
+	}
+	edges := &pcg.nodes[callerIndex].edges
+	edges.SetBit(edges, pcg.nodeIndex[callee], 1)
+}
+
+func (a *analysis) pcgAddNode(fn *ssa.Function) {
+	if fn.Pkg == nil {
+		return
+	}
+	pcg, ok := a.pcgs[fn.Pkg]
+	if !ok {
+		pcg = &packageCallGraph{nodeIndex: make(map[*ssa.Function]int)}
+		a.pcgs[fn.Pkg] = pcg
+	}
+	pcg.nodeIndex[fn] = -1
+}
+
+func (a *analysis) pcgAddEdge(caller, callee *ssa.Function) {
+	if callee.Pkg != nil {
+		a.pcgs[callee.Pkg].addEdge(caller, callee)
+	}
+}
+
+// pcgJSON returns a new slice of callgraph JSON values.
+func (a *analysis) pcgJSON(pcg *packageCallGraph) []*PCGNodeJSON {
+	var nodes []*PCGNodeJSON
+	for _, n := range pcg.nodes {
+
+		// TODO(adonovan): why is there no good way to iterate
+		// over the set bits of a big.Int?
+		var callees []int
+		nbits := n.edges.BitLen()
+		for j := 0; j < nbits; j++ {
+			if n.edges.Bit(j) == 1 {
+				callees = append(callees, j)
+			}
+		}
+
+		var pos token.Pos
+		if n.fn != nil {
+			pos = funcToken(n.fn)
+		}
+		nodes = append(nodes, &PCGNodeJSON{
+			Func: anchorJSON{
+				Text: n.pretty,
+				Href: a.posURL(pos, len("func")),
+			},
+			Callees: callees,
+		})
+	}
+	return nodes
+}
+
+type pcgNodesByPretty []*pcgNode
+
+func (a pcgNodesByPretty) Less(i, j int) bool { return a[i].pretty < a[j].pretty }
+func (a pcgNodesByPretty) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+func (a pcgNodesByPretty) Len() int           { return len(a) }
diff --git a/go/src/golang.org/x/tools/godoc/analysis/implements.go b/go/src/golang.org/x/tools/godoc/analysis/implements.go
index bee04d0..1c856c3 100644
--- a/go/src/golang.org/x/tools/godoc/analysis/implements.go
+++ b/go/src/golang.org/x/tools/godoc/analysis/implements.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package analysis
 
 // This file computes the "implements" relation over all pairs of
@@ -11,9 +13,9 @@
 // belong to different packages and at least one is not exported?
 
 import (
+	"go/types"
 	"sort"
 
-	"golang.org/x/tools/go/types"
 	"golang.org/x/tools/go/types/typeutil"
 )
 
diff --git a/go/src/golang.org/x/tools/godoc/analysis/implements14.go b/go/src/golang.org/x/tools/godoc/analysis/implements14.go
new file mode 100644
index 0000000..0ad1008
--- /dev/null
+++ b/go/src/golang.org/x/tools/godoc/analysis/implements14.go
@@ -0,0 +1,197 @@
+// Copyright 2014 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.
+
+// +build !go1.5
+
+package analysis
+
+// This file computes the "implements" relation over all pairs of
+// named types in the program.  (The mark-up is done by typeinfo.go.)
+
+// TODO(adonovan): do we want to report implements(C, I) where C and I
+// belong to different packages and at least one is not exported?
+
+import (
+	"sort"
+
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/go/types/typeutil"
+)
+
+// computeImplements computes the "implements" relation over all pairs
+// of named types in allNamed.
+func computeImplements(cache *typeutil.MethodSetCache, allNamed []*types.Named) map[*types.Named]implementsFacts {
+	// Information about a single type's method set.
+	type msetInfo struct {
+		typ          types.Type
+		mset         *types.MethodSet
+		mask1, mask2 uint64
+	}
+
+	initMsetInfo := func(info *msetInfo, typ types.Type) {
+		info.typ = typ
+		info.mset = cache.MethodSet(typ)
+		for i := 0; i < info.mset.Len(); i++ {
+			name := info.mset.At(i).Obj().Name()
+			info.mask1 |= 1 << methodBit(name[0])
+			info.mask2 |= 1 << methodBit(name[len(name)-1])
+		}
+	}
+
+	// satisfies(T, U) reports whether type T satisfies type U.
+	// U must be an interface.
+	//
+	// Since there are thousands of types (and thus millions of
+	// pairs of types) and types.Assignable(T, U) is relatively
+	// expensive, we compute assignability directly from the
+	// method sets.  (At least one of T and U must be an
+	// interface.)
+	//
+	// We use a trick (thanks gri!) related to a Bloom filter to
+	// quickly reject most tests, which are false.  For each
+	// method set, we precompute a mask, a set of bits, one per
+	// distinct initial byte of each method name.  Thus the mask
+	// for io.ReadWriter would be {'R','W'}.  AssignableTo(T, U)
+	// cannot be true unless mask(T)&mask(U)==mask(U).
+	//
+	// As with a Bloom filter, we can improve precision by testing
+	// additional hashes, e.g. using the last letter of each
+	// method name, so long as the subset mask property holds.
+	//
+	// When analyzing the standard library, there are about 1e6
+	// calls to satisfies(), of which 0.6% return true.  With a
+	// 1-hash filter, 95% of calls avoid the expensive check; with
+	// a 2-hash filter, this grows to 98.2%.
+	satisfies := func(T, U *msetInfo) bool {
+		return T.mask1&U.mask1 == U.mask1 &&
+			T.mask2&U.mask2 == U.mask2 &&
+			containsAllIdsOf(T.mset, U.mset)
+	}
+
+	// Information about a named type N, and perhaps also *N.
+	type namedInfo struct {
+		isInterface bool
+		base        msetInfo // N
+		ptr         msetInfo // *N, iff N !isInterface
+	}
+
+	var infos []namedInfo
+
+	// Precompute the method sets and their masks.
+	for _, N := range allNamed {
+		var info namedInfo
+		initMsetInfo(&info.base, N)
+		_, info.isInterface = N.Underlying().(*types.Interface)
+		if !info.isInterface {
+			initMsetInfo(&info.ptr, types.NewPointer(N))
+		}
+
+		if info.base.mask1|info.ptr.mask1 == 0 {
+			continue // neither N nor *N has methods
+		}
+
+		infos = append(infos, info)
+	}
+
+	facts := make(map[*types.Named]implementsFacts)
+
+	// Test all pairs of distinct named types (T, U).
+	// TODO(adonovan): opt: compute (U, T) at the same time.
+	for t := range infos {
+		T := &infos[t]
+		var to, from, fromPtr []types.Type
+		for u := range infos {
+			if t == u {
+				continue
+			}
+			U := &infos[u]
+			switch {
+			case T.isInterface && U.isInterface:
+				if satisfies(&U.base, &T.base) {
+					to = append(to, U.base.typ)
+				}
+				if satisfies(&T.base, &U.base) {
+					from = append(from, U.base.typ)
+				}
+			case T.isInterface: // U concrete
+				if satisfies(&U.base, &T.base) {
+					to = append(to, U.base.typ)
+				} else if satisfies(&U.ptr, &T.base) {
+					to = append(to, U.ptr.typ)
+				}
+			case U.isInterface: // T concrete
+				if satisfies(&T.base, &U.base) {
+					from = append(from, U.base.typ)
+				} else if satisfies(&T.ptr, &U.base) {
+					fromPtr = append(fromPtr, U.base.typ)
+				}
+			}
+		}
+
+		// Sort types (arbitrarily) to avoid nondeterminism.
+		sort.Sort(typesByString(to))
+		sort.Sort(typesByString(from))
+		sort.Sort(typesByString(fromPtr))
+
+		facts[T.base.typ.(*types.Named)] = implementsFacts{to, from, fromPtr}
+	}
+
+	return facts
+}
+
+type implementsFacts struct {
+	to      []types.Type // named or ptr-to-named types assignable to interface T
+	from    []types.Type // named interfaces assignable from T
+	fromPtr []types.Type // named interfaces assignable only from *T
+}
+
+type typesByString []types.Type
+
+func (p typesByString) Len() int           { return len(p) }
+func (p typesByString) Less(i, j int) bool { return p[i].String() < p[j].String() }
+func (p typesByString) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
+
+// methodBit returns the index of x in [a-zA-Z], or 52 if not found.
+func methodBit(x byte) uint64 {
+	switch {
+	case 'a' <= x && x <= 'z':
+		return uint64(x - 'a')
+	case 'A' <= x && x <= 'Z':
+		return uint64(26 + x - 'A')
+	}
+	return 52 // all other bytes
+}
+
+// containsAllIdsOf reports whether the method identifiers of T are a
+// superset of those in U.  If U belongs to an interface type, the
+// result is equal to types.Assignable(T, U), but is cheaper to compute.
+//
+// TODO(gri): make this a method of *types.MethodSet.
+//
+func containsAllIdsOf(T, U *types.MethodSet) bool {
+	t, tlen := 0, T.Len()
+	u, ulen := 0, U.Len()
+	for t < tlen && u < ulen {
+		tMeth := T.At(t).Obj()
+		uMeth := U.At(u).Obj()
+		tId := tMeth.Id()
+		uId := uMeth.Id()
+		if tId > uId {
+			// U has a method T lacks: fail.
+			return false
+		}
+		if tId < uId {
+			// T has a method U lacks: ignore it.
+			t++
+			continue
+		}
+		// U and T both have a method of this Id.  Check types.
+		if !types.Identical(tMeth.Type(), uMeth.Type()) {
+			return false // type mismatch
+		}
+		u++
+		t++
+	}
+	return u == ulen
+}
diff --git a/go/src/golang.org/x/tools/godoc/analysis/peers.go b/go/src/golang.org/x/tools/godoc/analysis/peers.go
index e1696e2..74a08a1 100644
--- a/go/src/golang.org/x/tools/godoc/analysis/peers.go
+++ b/go/src/golang.org/x/tools/godoc/analysis/peers.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package analysis
 
 // This file computes the channel "peers" relation over all pairs of
@@ -14,10 +16,10 @@
 import (
 	"fmt"
 	"go/token"
+	"go/types"
 
 	"golang.org/x/tools/go/pointer"
 	"golang.org/x/tools/go/ssa"
-	"golang.org/x/tools/go/types"
 )
 
 func (a *analysis) doChannelPeers(ptsets map[ssa.Value]pointer.Pointer) {
@@ -72,7 +74,7 @@
 					Href: a.posURL(makechan.Pos()-token.Pos(len("make")),
 						len("make")),
 				},
-				Fn: makechan.Parent().RelString(op.fn.Package().Object),
+				Fn: makechan.Parent().RelString(op.fn.Package().Pkg),
 			})
 			for _, op := range aliasedOps[makechan] {
 				ops[op] = true
diff --git a/go/src/golang.org/x/tools/godoc/analysis/peers14.go b/go/src/golang.org/x/tools/godoc/analysis/peers14.go
new file mode 100644
index 0000000..ba5e8d6
--- /dev/null
+++ b/go/src/golang.org/x/tools/godoc/analysis/peers14.go
@@ -0,0 +1,156 @@
+// Copyright 2014 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.
+
+// +build !go1.5
+
+package analysis
+
+// This file computes the channel "peers" relation over all pairs of
+// channel operations in the program.  The peers are displayed in the
+// lower pane when a channel operation (make, <-, close) is clicked.
+
+// TODO(adonovan): handle calls to reflect.{Select,Recv,Send,Close} too,
+// then enable reflection in PTA.
+
+import (
+	"fmt"
+	"go/token"
+
+	"golang.org/x/tools/go/pointer"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/types"
+)
+
+func (a *analysis) doChannelPeers(ptsets map[ssa.Value]pointer.Pointer) {
+	addSendRecv := func(j *commJSON, op chanOp) {
+		j.Ops = append(j.Ops, commOpJSON{
+			Op: anchorJSON{
+				Text: op.mode,
+				Href: a.posURL(op.pos, op.len),
+			},
+			Fn: prettyFunc(nil, op.fn),
+		})
+	}
+
+	// Build an undirected bipartite multigraph (binary relation)
+	// of MakeChan ops and send/recv/close ops.
+	//
+	// TODO(adonovan): opt: use channel element types to partition
+	// the O(n^2) problem into subproblems.
+	aliasedOps := make(map[*ssa.MakeChan][]chanOp)
+	opToMakes := make(map[chanOp][]*ssa.MakeChan)
+	for _, op := range a.ops {
+		// Combine the PT sets from all contexts.
+		var makes []*ssa.MakeChan // aliased ops
+		ptr, ok := ptsets[op.ch]
+		if !ok {
+			continue // e.g. channel op in dead code
+		}
+		for _, label := range ptr.PointsTo().Labels() {
+			makechan, ok := label.Value().(*ssa.MakeChan)
+			if !ok {
+				continue // skip intrinsically-created channels for now
+			}
+			if makechan.Pos() == token.NoPos {
+				continue // not possible?
+			}
+			makes = append(makes, makechan)
+			aliasedOps[makechan] = append(aliasedOps[makechan], op)
+		}
+		opToMakes[op] = makes
+	}
+
+	// Now that complete relation is built, build links for ops.
+	for _, op := range a.ops {
+		v := commJSON{
+			Ops: []commOpJSON{}, // (JS wants non-nil)
+		}
+		ops := make(map[chanOp]bool)
+		for _, makechan := range opToMakes[op] {
+			v.Ops = append(v.Ops, commOpJSON{
+				Op: anchorJSON{
+					Text: "made",
+					Href: a.posURL(makechan.Pos()-token.Pos(len("make")),
+						len("make")),
+				},
+				Fn: makechan.Parent().RelString(op.fn.Package().Pkg),
+			})
+			for _, op := range aliasedOps[makechan] {
+				ops[op] = true
+			}
+		}
+		for op := range ops {
+			addSendRecv(&v, op)
+		}
+
+		// Add links for each aliased op.
+		fi, offset := a.fileAndOffset(op.pos)
+		fi.addLink(aLink{
+			start:   offset,
+			end:     offset + op.len,
+			title:   "show channel ops",
+			onclick: fmt.Sprintf("onClickComm(%d)", fi.addData(v)),
+		})
+	}
+	// Add links for makechan ops themselves.
+	for makechan, ops := range aliasedOps {
+		v := commJSON{
+			Ops: []commOpJSON{}, // (JS wants non-nil)
+		}
+		for _, op := range ops {
+			addSendRecv(&v, op)
+		}
+
+		fi, offset := a.fileAndOffset(makechan.Pos())
+		fi.addLink(aLink{
+			start:   offset - len("make"),
+			end:     offset,
+			title:   "show channel ops",
+			onclick: fmt.Sprintf("onClickComm(%d)", fi.addData(v)),
+		})
+	}
+}
+
+// -- utilities --------------------------------------------------------
+
+// chanOp abstracts an ssa.Send, ssa.Unop(ARROW), close(), or a SelectState.
+// Derived from oracle/peers.go.
+type chanOp struct {
+	ch   ssa.Value
+	mode string // sent|received|closed
+	pos  token.Pos
+	len  int
+	fn   *ssa.Function
+}
+
+// chanOps returns a slice of all the channel operations in the instruction.
+// Derived from oracle/peers.go.
+func chanOps(instr ssa.Instruction) []chanOp {
+	fn := instr.Parent()
+	var ops []chanOp
+	switch instr := instr.(type) {
+	case *ssa.UnOp:
+		if instr.Op == token.ARROW {
+			// TODO(adonovan): don't assume <-ch; could be 'range ch'.
+			ops = append(ops, chanOp{instr.X, "received", instr.Pos(), len("<-"), fn})
+		}
+	case *ssa.Send:
+		ops = append(ops, chanOp{instr.Chan, "sent", instr.Pos(), len("<-"), fn})
+	case *ssa.Select:
+		for _, st := range instr.States {
+			mode := "received"
+			if st.Dir == types.SendOnly {
+				mode = "sent"
+			}
+			ops = append(ops, chanOp{st.Chan, mode, st.Pos, len("<-"), fn})
+		}
+	case ssa.CallInstruction:
+		call := instr.Common()
+		if blt, ok := call.Value.(*ssa.Builtin); ok && blt.Name() == "close" {
+			pos := instr.Common().Pos()
+			ops = append(ops, chanOp{call.Args[0], "closed", pos - token.Pos(len("close")), len("close("), fn})
+		}
+	}
+	return ops
+}
diff --git a/go/src/golang.org/x/tools/godoc/analysis/typeinfo.go b/go/src/golang.org/x/tools/godoc/analysis/typeinfo.go
index 83e19c1..1ccff52 100644
--- a/go/src/golang.org/x/tools/godoc/analysis/typeinfo.go
+++ b/go/src/golang.org/x/tools/godoc/analysis/typeinfo.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package analysis
 
 // This file computes the markup for information from go/types:
@@ -20,12 +22,12 @@
 
 import (
 	"fmt"
+	"go/types"
 	"reflect"
 	"strconv"
 	"strings"
 
 	"golang.org/x/tools/go/loader"
-	"golang.org/x/tools/go/types"
 	"golang.org/x/tools/go/types/typeutil"
 )
 
diff --git a/go/src/golang.org/x/tools/godoc/analysis/typeinfo14.go b/go/src/golang.org/x/tools/godoc/analysis/typeinfo14.go
new file mode 100644
index 0000000..d10abce
--- /dev/null
+++ b/go/src/golang.org/x/tools/godoc/analysis/typeinfo14.go
@@ -0,0 +1,234 @@
+// Copyright 2014 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.
+
+// +build !go1.5
+
+package analysis
+
+// This file computes the markup for information from go/types:
+// IMPORTS, identifier RESOLUTION, METHOD SETS, size/alignment, and
+// the IMPLEMENTS relation.
+//
+// IMPORTS links connect import specs to the documentation for the
+// imported package.
+//
+// RESOLUTION links referring identifiers to their defining
+// identifier, and adds tooltips for kind and type.
+//
+// METHOD SETS, size/alignment, and the IMPLEMENTS relation are
+// displayed in the lower pane when a type's defining identifier is
+// clicked.
+
+import (
+	"fmt"
+	"reflect"
+	"strconv"
+	"strings"
+
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/go/types/typeutil"
+)
+
+// TODO(adonovan): audit to make sure it's safe on ill-typed packages.
+
+// TODO(adonovan): use same Sizes as loader.Config.
+var sizes = types.StdSizes{8, 8}
+
+func (a *analysis) doTypeInfo(info *loader.PackageInfo, implements map[*types.Named]implementsFacts) {
+	// We must not assume the corresponding SSA packages were
+	// created (i.e. were transitively error-free).
+
+	// IMPORTS
+	for _, f := range info.Files {
+		// Package decl.
+		fi, offset := a.fileAndOffset(f.Name.Pos())
+		fi.addLink(aLink{
+			start: offset,
+			end:   offset + len(f.Name.Name),
+			title: "Package docs for " + info.Pkg.Path(),
+			// TODO(adonovan): fix: we're putting the untrusted Path()
+			// into a trusted field.  What's the appropriate sanitizer?
+			href: "/pkg/" + info.Pkg.Path(),
+		})
+
+		// Import specs.
+		for _, imp := range f.Imports {
+			// Remove quotes.
+			L := int(imp.End()-imp.Path.Pos()) - len(`""`)
+			path, _ := strconv.Unquote(imp.Path.Value)
+			fi, offset := a.fileAndOffset(imp.Path.Pos())
+			fi.addLink(aLink{
+				start: offset + 1,
+				end:   offset + 1 + L,
+				title: "Package docs for " + path,
+				// TODO(adonovan): fix: we're putting the untrusted path
+				// into a trusted field.  What's the appropriate sanitizer?
+				href: "/pkg/" + path,
+			})
+		}
+	}
+
+	// RESOLUTION
+	qualifier := types.RelativeTo(info.Pkg)
+	for id, obj := range info.Uses {
+		// Position of the object definition.
+		pos := obj.Pos()
+		Len := len(obj.Name())
+
+		// Correct the position for non-renaming import specs.
+		//  import "sync/atomic"
+		//          ^^^^^^^^^^^
+		if obj, ok := obj.(*types.PkgName); ok && id.Name == obj.Imported().Name() {
+			// Assume this is a non-renaming import.
+			// NB: not true for degenerate renamings: `import foo "foo"`.
+			pos++
+			Len = len(obj.Imported().Path())
+		}
+
+		if obj.Pkg() == nil {
+			continue // don't mark up built-ins.
+		}
+
+		fi, offset := a.fileAndOffset(id.NamePos)
+		fi.addLink(aLink{
+			start: offset,
+			end:   offset + len(id.Name),
+			title: types.ObjectString(obj, qualifier),
+			href:  a.posURL(pos, Len),
+		})
+	}
+
+	// IMPLEMENTS & METHOD SETS
+	for _, obj := range info.Defs {
+		if obj, ok := obj.(*types.TypeName); ok {
+			a.namedType(obj, implements)
+		}
+	}
+}
+
+func (a *analysis) namedType(obj *types.TypeName, implements map[*types.Named]implementsFacts) {
+	qualifier := types.RelativeTo(obj.Pkg())
+	T := obj.Type().(*types.Named)
+	v := &TypeInfoJSON{
+		Name:    obj.Name(),
+		Size:    sizes.Sizeof(T),
+		Align:   sizes.Alignof(T),
+		Methods: []anchorJSON{}, // (JS wants non-nil)
+	}
+
+	// addFact adds the fact "is implemented by T" (by) or
+	// "implements T" (!by) to group.
+	addFact := func(group *implGroupJSON, T types.Type, by bool) {
+		Tobj := deref(T).(*types.Named).Obj()
+		var byKind string
+		if by {
+			// Show underlying kind of implementing type,
+			// e.g. "slice", "array", "struct".
+			s := reflect.TypeOf(T.Underlying()).String()
+			byKind = strings.ToLower(strings.TrimPrefix(s, "*types."))
+		}
+		group.Facts = append(group.Facts, implFactJSON{
+			ByKind: byKind,
+			Other: anchorJSON{
+				Href: a.posURL(Tobj.Pos(), len(Tobj.Name())),
+				Text: types.TypeString(T, qualifier),
+			},
+		})
+	}
+
+	// IMPLEMENTS
+	if r, ok := implements[T]; ok {
+		if isInterface(T) {
+			// "T is implemented by <conc>" ...
+			// "T is implemented by <iface>"...
+			// "T implements        <iface>"...
+			group := implGroupJSON{
+				Descr: types.TypeString(T, qualifier),
+			}
+			// Show concrete types first; use two passes.
+			for _, sub := range r.to {
+				if !isInterface(sub) {
+					addFact(&group, sub, true)
+				}
+			}
+			for _, sub := range r.to {
+				if isInterface(sub) {
+					addFact(&group, sub, true)
+				}
+			}
+			for _, super := range r.from {
+				addFact(&group, super, false)
+			}
+			v.ImplGroups = append(v.ImplGroups, group)
+		} else {
+			// T is concrete.
+			if r.from != nil {
+				// "T implements <iface>"...
+				group := implGroupJSON{
+					Descr: types.TypeString(T, qualifier),
+				}
+				for _, super := range r.from {
+					addFact(&group, super, false)
+				}
+				v.ImplGroups = append(v.ImplGroups, group)
+			}
+			if r.fromPtr != nil {
+				// "*C implements <iface>"...
+				group := implGroupJSON{
+					Descr: "*" + types.TypeString(T, qualifier),
+				}
+				for _, psuper := range r.fromPtr {
+					addFact(&group, psuper, false)
+				}
+				v.ImplGroups = append(v.ImplGroups, group)
+			}
+		}
+	}
+
+	// METHOD SETS
+	for _, sel := range typeutil.IntuitiveMethodSet(T, &a.prog.MethodSets) {
+		meth := sel.Obj().(*types.Func)
+		pos := meth.Pos() // may be 0 for error.Error
+		v.Methods = append(v.Methods, anchorJSON{
+			Href: a.posURL(pos, len(meth.Name())),
+			Text: types.SelectionString(sel, qualifier),
+		})
+	}
+
+	// Since there can be many specs per decl, we
+	// can't attach the link to the keyword 'type'
+	// (as we do with 'func'); we use the Ident.
+	fi, offset := a.fileAndOffset(obj.Pos())
+	fi.addLink(aLink{
+		start:   offset,
+		end:     offset + len(obj.Name()),
+		title:   fmt.Sprintf("type info for %s", obj.Name()),
+		onclick: fmt.Sprintf("onClickTypeInfo(%d)", fi.addData(v)),
+	})
+
+	// Add info for exported package-level types to the package info.
+	if obj.Exported() && isPackageLevel(obj) {
+		// TODO(adonovan): Path is not unique!
+		// It is possible to declare a non-test package called x_test.
+		a.result.pkgInfo(obj.Pkg().Path()).addType(v)
+	}
+}
+
+// -- utilities --------------------------------------------------------
+
+func isInterface(T types.Type) bool { return types.IsInterface(T) }
+
+// deref returns a pointer's element type; otherwise it returns typ.
+func deref(typ types.Type) types.Type {
+	if p, ok := typ.Underlying().(*types.Pointer); ok {
+		return p.Elem()
+	}
+	return typ
+}
+
+// isPackageLevel reports whether obj is a package-level object.
+func isPackageLevel(obj types.Object) bool {
+	return obj.Pkg().Scope().Lookup(obj.Name()) == obj
+}
diff --git a/go/src/golang.org/x/tools/godoc/appengine.go b/go/src/golang.org/x/tools/godoc/appengine.go
new file mode 100644
index 0000000..2a68558
--- /dev/null
+++ b/go/src/golang.org/x/tools/godoc/appengine.go
@@ -0,0 +1,13 @@
+// Copyright 2015 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.
+
+// +build appengine
+
+package godoc
+
+import "appengine"
+
+func init() {
+	onAppengine = !appengine.IsDevAppServer()
+}
diff --git a/go/src/golang.org/x/tools/godoc/dl/dl.go b/go/src/golang.org/x/tools/godoc/dl/dl.go
new file mode 100644
index 0000000..ed6e590
--- /dev/null
+++ b/go/src/golang.org/x/tools/godoc/dl/dl.go
@@ -0,0 +1,511 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by the Apache 2.0
+// license that can be found in the LICENSE file.
+
+// +build appengine
+
+// Package dl implements a simple downloads frontend server.
+//
+// It accepts HTTP POST requests to create a new download metadata entity, and
+// lists entities with sorting and filtering.
+// It is designed to run only on the instance of godoc that serves golang.org.
+package dl
+
+import (
+	"crypto/hmac"
+	"crypto/md5"
+	"encoding/json"
+	"fmt"
+	"html/template"
+	"io"
+	"net/http"
+	"regexp"
+	"sort"
+	"strconv"
+	"strings"
+	"sync"
+	"time"
+
+	"golang.org/x/net/context"
+
+	"google.golang.org/appengine"
+	"google.golang.org/appengine/datastore"
+	"google.golang.org/appengine/log"
+	"google.golang.org/appengine/memcache"
+	"google.golang.org/appengine/user"
+)
+
+const (
+	gcsBaseURL    = "https://storage.googleapis.com/golang/"
+	cacheKey      = "download_list_3" // increment if listTemplateData changes
+	cacheDuration = time.Hour
+)
+
+func RegisterHandlers(mux *http.ServeMux) {
+	mux.Handle("/dl", http.RedirectHandler("/dl/", http.StatusFound))
+	mux.HandleFunc("/dl/", getHandler) // also serves listHandler
+	mux.HandleFunc("/dl/upload", uploadHandler)
+	mux.HandleFunc("/dl/init", initHandler)
+}
+
+type File struct {
+	Filename       string
+	OS             string
+	Arch           string
+	Version        string
+	Checksum       string `datastore:",noindex"` // SHA1; deprecated
+	ChecksumSHA256 string `datastore:",noindex"`
+	Size           int64  `datastore:",noindex"`
+	Kind           string // "archive", "installer", "source"
+	Uploaded       time.Time
+}
+
+func (f File) ChecksumType() string {
+	if f.ChecksumSHA256 != "" {
+		return "SHA256"
+	}
+	return "SHA1"
+}
+
+func (f File) PrettyChecksum() string {
+	if f.ChecksumSHA256 != "" {
+		return f.ChecksumSHA256
+	}
+	return f.Checksum
+}
+
+func (f File) PrettyOS() string {
+	if f.OS == "darwin" {
+		switch {
+		case strings.Contains(f.Filename, "osx10.8"):
+			return "OS X 10.8+"
+		case strings.Contains(f.Filename, "osx10.6"):
+			return "OS X 10.6+"
+		}
+	}
+	return pretty(f.OS)
+}
+
+func (f File) PrettySize() string {
+	const mb = 1 << 20
+	if f.Size == 0 {
+		return ""
+	}
+	if f.Size < mb {
+		// All Go releases are >1mb, but handle this case anyway.
+		return fmt.Sprintf("%v bytes", f.Size)
+	}
+	return fmt.Sprintf("%.0fMB", float64(f.Size)/mb)
+}
+
+func (f File) Highlight() bool {
+	switch {
+	case f.Kind == "source":
+		return true
+	case f.Arch == "amd64" && f.OS == "linux":
+		return true
+	case f.Arch == "amd64" && f.Kind == "installer":
+		switch f.OS {
+		case "windows":
+			return true
+		case "darwin":
+			if !strings.Contains(f.Filename, "osx10.6") {
+				return true
+			}
+		}
+	}
+	return false
+}
+
+func (f File) URL() string {
+	return gcsBaseURL + f.Filename
+}
+
+type Release struct {
+	Version string
+	Stable  bool
+	Files   []File
+	Visible bool // show files on page load
+}
+
+type Feature struct {
+	// The File field will be filled in by the first stable File
+	// whose name matches the given fileRE.
+	File
+	fileRE *regexp.Regexp
+
+	Platform     string // "Microsoft Windows", "Mac OS X", "Linux"
+	Requirements string // "Windows XP and above, 64-bit Intel Processor"
+}
+
+// featuredFiles lists the platforms and files to be featured
+// at the top of the downloads page.
+var featuredFiles = []Feature{
+	{
+		Platform:     "Microsoft Windows",
+		Requirements: "Windows XP or later, Intel 64-bit processor",
+		fileRE:       regexp.MustCompile(`\.windows-amd64\.msi$`),
+	},
+	{
+		Platform:     "Apple OS X",
+		Requirements: "OS X 10.8 or later, Intel 64-bit processor",
+		fileRE:       regexp.MustCompile(`\.darwin-amd64(-osx10\.8)?\.pkg$`),
+	},
+	{
+		Platform:     "Linux",
+		Requirements: "Linux 2.6.23 or later, Intel 64-bit processor",
+		fileRE:       regexp.MustCompile(`\.linux-amd64\.tar\.gz$`),
+	},
+	{
+		Platform: "Source",
+		fileRE:   regexp.MustCompile(`\.src\.tar\.gz$`),
+	},
+}
+
+// data to send to the template; increment cacheKey if you change this.
+type listTemplateData struct {
+	Featured         []Feature
+	Stable, Unstable []Release
+	LoginURL         string
+}
+
+var (
+	listTemplate  = template.Must(template.New("").Funcs(templateFuncs).Parse(templateHTML))
+	templateFuncs = template.FuncMap{"pretty": pretty}
+)
+
+func listHandler(w http.ResponseWriter, r *http.Request) {
+	if r.Method != "GET" {
+		http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
+		return
+	}
+	var (
+		c = appengine.NewContext(r)
+		d listTemplateData
+	)
+	if _, err := memcache.Gob.Get(c, cacheKey, &d); err != nil {
+		if err == memcache.ErrCacheMiss {
+			log.Debugf(c, "cache miss")
+		} else {
+			log.Errorf(c, "cache get error: %v", err)
+		}
+
+		var fs []File
+		_, err := datastore.NewQuery("File").Ancestor(rootKey(c)).GetAll(c, &fs)
+		if err != nil {
+			log.Errorf(c, "error listing: %v", err)
+			return
+		}
+		d.Stable, d.Unstable = filesToReleases(fs)
+		if len(d.Stable) > 0 {
+			d.Featured = filesToFeatured(d.Stable[0].Files)
+		}
+
+		d.LoginURL, _ = user.LoginURL(c, "/dl")
+		if user.Current(c) != nil {
+			d.LoginURL, _ = user.LogoutURL(c, "/dl")
+		}
+
+		item := &memcache.Item{Key: cacheKey, Object: &d, Expiration: cacheDuration}
+		if err := memcache.Gob.Set(c, item); err != nil {
+			log.Errorf(c, "cache set error: %v", err)
+		}
+	}
+	if err := listTemplate.ExecuteTemplate(w, "root", d); err != nil {
+		log.Errorf(c, "error executing template: %v", err)
+	}
+}
+
+func filesToFeatured(fs []File) (featured []Feature) {
+	for _, feature := range featuredFiles {
+		for _, file := range fs {
+			if feature.fileRE.MatchString(file.Filename) {
+				feature.File = file
+				featured = append(featured, feature)
+				break
+			}
+		}
+	}
+	return
+}
+
+func filesToReleases(fs []File) (stable, unstable []Release) {
+	sort.Sort(fileOrder(fs))
+
+	var r *Release
+	var stableMaj, stableMin int
+	add := func() {
+		if r == nil {
+			return
+		}
+		if r.Stable {
+			if len(stable) == 0 {
+				// Display files for latest stable release.
+				stableMaj, stableMin, _ = parseVersion(r.Version)
+				r.Visible = len(stable) == 0
+			}
+			stable = append(stable, *r)
+			return
+		}
+		if len(unstable) != 0 {
+			// Only show one (latest) unstable version.
+			return
+		}
+		maj, min, _ := parseVersion(r.Version)
+		if maj < stableMaj || maj == stableMaj && min <= stableMin {
+			// Display unstable version only if newer than the
+			// latest stable release.
+			return
+		}
+		r.Visible = true
+		unstable = append(unstable, *r)
+	}
+	for _, f := range fs {
+		if r == nil || f.Version != r.Version {
+			add()
+			r = &Release{
+				Version: f.Version,
+				Stable:  isStable(f.Version),
+			}
+		}
+		r.Files = append(r.Files, f)
+	}
+	add()
+	return
+}
+
+// isStable reports whether the version string v is a stable version.
+func isStable(v string) bool {
+	return !strings.Contains(v, "beta") && !strings.Contains(v, "rc")
+}
+
+type fileOrder []File
+
+func (s fileOrder) Len() int      { return len(s) }
+func (s fileOrder) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+func (s fileOrder) Less(i, j int) bool {
+	a, b := s[i], s[j]
+	if av, bv := a.Version, b.Version; av != bv {
+		return versionLess(av, bv)
+	}
+	if a.OS != b.OS {
+		return a.OS < b.OS
+	}
+	if a.Arch != b.Arch {
+		return a.Arch < b.Arch
+	}
+	if a.Kind != b.Kind {
+		return a.Kind < b.Kind
+	}
+	return a.Filename < b.Filename
+}
+
+func versionLess(a, b string) bool {
+	// Put stable releases first.
+	if isStable(a) != isStable(b) {
+		return isStable(a)
+	}
+	maja, mina, ta := parseVersion(a)
+	majb, minb, tb := parseVersion(b)
+	if maja == majb {
+		if mina == minb {
+			return ta >= tb
+		}
+		return mina >= minb
+	}
+	return maja >= majb
+}
+
+func parseVersion(v string) (maj, min int, tail string) {
+	if i := strings.Index(v, "beta"); i > 0 {
+		tail = v[i:]
+		v = v[:i]
+	}
+	if i := strings.Index(v, "rc"); i > 0 {
+		tail = v[i:]
+		v = v[:i]
+	}
+	p := strings.Split(strings.TrimPrefix(v, "go1."), ".")
+	maj, _ = strconv.Atoi(p[0])
+	if len(p) < 2 {
+		return
+	}
+	min, _ = strconv.Atoi(p[1])
+	return
+}
+
+func uploadHandler(w http.ResponseWriter, r *http.Request) {
+	if r.Method != "POST" {
+		http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
+		return
+	}
+	c := appengine.NewContext(r)
+
+	// Authenticate using a user token (same as gomote).
+	user := r.FormValue("user")
+	if !validUser(user) {
+		http.Error(w, "bad user", http.StatusForbidden)
+		return
+	}
+	if r.FormValue("key") != userKey(c, user) {
+		http.Error(w, "bad key", http.StatusForbidden)
+		return
+	}
+
+	var f File
+	defer r.Body.Close()
+	if err := json.NewDecoder(r.Body).Decode(&f); err != nil {
+		log.Errorf(c, "error decoding upload JSON: %v", err)
+		http.Error(w, "Something broke", http.StatusInternalServerError)
+		return
+	}
+	if f.Filename == "" {
+		http.Error(w, "Must provide Filename", http.StatusBadRequest)
+		return
+	}
+	if f.Uploaded.IsZero() {
+		f.Uploaded = time.Now()
+	}
+	k := datastore.NewKey(c, "File", f.Filename, 0, rootKey(c))
+	if _, err := datastore.Put(c, k, &f); err != nil {
+		log.Errorf(c, "putting File entity: %v", err)
+		http.Error(w, "could not put File entity", http.StatusInternalServerError)
+		return
+	}
+	if err := memcache.Delete(c, cacheKey); err != nil {
+		log.Errorf(c, "cache delete error: %v", err)
+	}
+	io.WriteString(w, "OK")
+}
+
+func getHandler(w http.ResponseWriter, r *http.Request) {
+	name := strings.TrimPrefix(r.URL.Path, "/dl/")
+	if name == "" {
+		listHandler(w, r)
+		return
+	}
+	if !fileRe.MatchString(name) {
+		http.NotFound(w, r)
+		return
+	}
+	http.Redirect(w, r, gcsBaseURL+name, http.StatusFound)
+}
+
+func validUser(user string) bool {
+	switch user {
+	case "adg", "bradfitz", "cbro":
+		return true
+	}
+	return false
+}
+
+func userKey(c context.Context, user string) string {
+	h := hmac.New(md5.New, []byte(secret(c)))
+	h.Write([]byte("user-" + user))
+	return fmt.Sprintf("%x", h.Sum(nil))
+}
+
+var fileRe = regexp.MustCompile(`^go[0-9a-z.]+\.[0-9a-z.-]+\.(tar\.gz|pkg|msi|zip)$`)
+
+func initHandler(w http.ResponseWriter, r *http.Request) {
+	var fileRoot struct {
+		Root string
+	}
+	c := appengine.NewContext(r)
+	k := rootKey(c)
+	err := datastore.RunInTransaction(c, func(c context.Context) error {
+		err := datastore.Get(c, k, &fileRoot)
+		if err != nil && err != datastore.ErrNoSuchEntity {
+			return err
+		}
+		_, err = datastore.Put(c, k, &fileRoot)
+		return err
+	}, nil)
+	if err != nil {
+		http.Error(w, err.Error(), 500)
+		return
+	}
+	io.WriteString(w, "OK")
+}
+
+// rootKey is the ancestor of all File entities.
+func rootKey(c context.Context) *datastore.Key {
+	return datastore.NewKey(c, "FileRoot", "root", 0, nil)
+}
+
+// pretty returns a human-readable version of the given OS, Arch, or Kind.
+func pretty(s string) string {
+	t, ok := prettyStrings[s]
+	if !ok {
+		return s
+	}
+	return t
+}
+
+var prettyStrings = map[string]string{
+	"darwin":  "OS X",
+	"freebsd": "FreeBSD",
+	"linux":   "Linux",
+	"windows": "Windows",
+
+	"386":   "32-bit",
+	"amd64": "64-bit",
+
+	"armv6l": "ARMv6",
+
+	"archive":   "Archive",
+	"installer": "Installer",
+	"source":    "Source",
+}
+
+// Code below copied from x/build/app/key
+
+var theKey struct {
+	sync.RWMutex
+	builderKey
+}
+
+type builderKey struct {
+	Secret string
+}
+
+func (k *builderKey) Key(c context.Context) *datastore.Key {
+	return datastore.NewKey(c, "BuilderKey", "root", 0, nil)
+}
+
+func secret(c context.Context) string {
+	// check with rlock
+	theKey.RLock()
+	k := theKey.Secret
+	theKey.RUnlock()
+	if k != "" {
+		return k
+	}
+
+	// prepare to fill; check with lock and keep lock
+	theKey.Lock()
+	defer theKey.Unlock()
+	if theKey.Secret != "" {
+		return theKey.Secret
+	}
+
+	// fill
+	if err := datastore.Get(c, theKey.Key(c), &theKey.builderKey); err != nil {
+		if err == datastore.ErrNoSuchEntity {
+			// If the key is not stored in datastore, write it.
+			// This only happens at the beginning of a new deployment.
+			// The code is left here for SDK use and in case a fresh
+			// deployment is ever needed.  "gophers rule" is not the
+			// real key.
+			if !appengine.IsDevAppServer() {
+				panic("lost key from datastore")
+			}
+			theKey.Secret = "gophers rule"
+			datastore.Put(c, theKey.Key(c), &theKey.builderKey)
+			return theKey.Secret
+		}
+		panic("cannot load builder key: " + err.Error())
+	}
+
+	return theKey.Secret
+}
diff --git a/go/src/golang.org/x/tools/godoc/dl/dl_test.go b/go/src/golang.org/x/tools/godoc/dl/dl_test.go
new file mode 100644
index 0000000..9d6a057
--- /dev/null
+++ b/go/src/golang.org/x/tools/godoc/dl/dl_test.go
@@ -0,0 +1,72 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by the Apache 2.0
+// license that can be found in the LICENSE file.
+
+// +build appengine
+
+package dl
+
+import (
+	"sort"
+	"strings"
+	"testing"
+)
+
+func TestParseVersion(t *testing.T) {
+	for _, c := range []struct {
+		in       string
+		maj, min int
+		tail     string
+	}{
+		{"go1.5", 5, 0, ""},
+		{"go1.5beta1", 5, 0, "beta1"},
+		{"go1.5.1", 5, 1, ""},
+		{"go1.5.1rc1", 5, 1, "rc1"},
+	} {
+		maj, min, tail := parseVersion(c.in)
+		if maj != c.maj || min != c.min || tail != c.tail {
+			t.Errorf("parseVersion(%q) = %v, %v, %q; want %v, %v, %q",
+				c.in, maj, min, tail, c.maj, c.min, c.tail)
+		}
+	}
+}
+
+func TestFileOrder(t *testing.T) {
+	fs := []File{
+		{Filename: "go1.3.src.tar.gz", Version: "go1.3", OS: "", Arch: "", Kind: "source"},
+		{Filename: "go1.3.1.src.tar.gz", Version: "go1.3.1", OS: "", Arch: "", Kind: "source"},
+		{Filename: "go1.3.linux-amd64.tar.gz", Version: "go1.3", OS: "linux", Arch: "amd64", Kind: "archive"},
+		{Filename: "go1.3.1.linux-amd64.tar.gz", Version: "go1.3.1", OS: "linux", Arch: "amd64", Kind: "archive"},
+		{Filename: "go1.3.darwin-amd64.tar.gz", Version: "go1.3", OS: "darwin", Arch: "amd64", Kind: "archive"},
+		{Filename: "go1.3.darwin-amd64.pkg", Version: "go1.3", OS: "darwin", Arch: "amd64", Kind: "installer"},
+		{Filename: "go1.3.darwin-386.tar.gz", Version: "go1.3", OS: "darwin", Arch: "386", Kind: "archive"},
+		{Filename: "go1.3beta1.linux-amd64.tar.gz", Version: "go1.3beta1", OS: "linux", Arch: "amd64", Kind: "archive"},
+		{Filename: "go1.3beta2.linux-amd64.tar.gz", Version: "go1.3beta2", OS: "linux", Arch: "amd64", Kind: "archive"},
+		{Filename: "go1.3rc1.linux-amd64.tar.gz", Version: "go1.3rc1", OS: "linux", Arch: "amd64", Kind: "archive"},
+		{Filename: "go1.2.linux-amd64.tar.gz", Version: "go1.2", OS: "linux", Arch: "amd64", Kind: "archive"},
+		{Filename: "go1.2.2.linux-amd64.tar.gz", Version: "go1.2.2", OS: "linux", Arch: "amd64", Kind: "archive"},
+	}
+	sort.Sort(fileOrder(fs))
+	var s []string
+	for _, f := range fs {
+		s = append(s, f.Filename)
+	}
+	got := strings.Join(s, "\n")
+	want := strings.Join([]string{
+		"go1.3.1.src.tar.gz",
+		"go1.3.1.linux-amd64.tar.gz",
+		"go1.3.src.tar.gz",
+		"go1.3.darwin-386.tar.gz",
+		"go1.3.darwin-amd64.tar.gz",
+		"go1.3.darwin-amd64.pkg",
+		"go1.3.linux-amd64.tar.gz",
+		"go1.2.2.linux-amd64.tar.gz",
+		"go1.2.linux-amd64.tar.gz",
+		"go1.3rc1.linux-amd64.tar.gz",
+		"go1.3beta2.linux-amd64.tar.gz",
+		"go1.3beta1.linux-amd64.tar.gz",
+	}, "\n")
+	if got != want {
+		t.Errorf("sort order is\n%s\nwant:\n%s", got, want)
+	}
+}
diff --git a/go/src/golang.org/x/tools/godoc/dl/tmpl.go b/go/src/golang.org/x/tools/godoc/dl/tmpl.go
new file mode 100644
index 0000000..54a2d54
--- /dev/null
+++ b/go/src/golang.org/x/tools/godoc/dl/tmpl.go
@@ -0,0 +1,270 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by the Apache 2.0
+// license that can be found in the LICENSE file.
+
+// +build appengine
+
+package dl
+
+// TODO(adg): refactor this to use the tools/godoc/static template.
+
+const templateHTML = `
+{{define "root"}}
+<!DOCTYPE html>
+<html>
+<head>
+        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+        <title>Downloads - The Go Programming Language</title>
+        <link type="text/css" rel="stylesheet" href="/lib/godoc/style.css">
+        <script type="text/javascript">window.initFuncs = [];</script>
+	<style>
+		table.codetable {
+			margin-left: 20px; margin-right: 20px;
+			border-collapse: collapse;
+		}
+		table.codetable tr {
+			background-color: #f0f0f0;
+		}
+		table.codetable tr:nth-child(2n), table.codetable tr.first {
+			background-color: white;
+		}
+		table.codetable td, table.codetable th {
+			white-space: nowrap;
+			padding: 6px 10px;
+		}
+		table.codetable tt {
+			font-size: xx-small;
+		}
+		table.codetable tr.highlight td {
+			font-weight: bold;
+		}
+		a.downloadBox {
+			display: block;
+			color: #222;
+			border: 1px solid #375EAB;
+			border-radius: 5px;
+			background: #E0EBF5;
+			width: 280px;
+			float: left;
+			margin-left: 10px;
+			margin-bottom: 10px;
+			padding: 10px;
+		}
+		a.downloadBox:hover {
+			text-decoration: none;
+		}
+		.downloadBox .platform {
+			font-size: large;
+		}
+		.downloadBox .filename {
+			color: #375EAB;
+			font-weight: bold;
+			line-height: 1.5em;
+		}
+		a.downloadBox:hover .filename {
+			text-decoration: underline;
+		}
+		.downloadBox .size {
+			font-size: small;
+			font-weight: normal;
+		}
+		.downloadBox .reqs {
+			font-size: small;
+			font-style: italic;
+		}
+		.downloadBox .checksum {
+			font-size: 5pt;
+		}
+	</style>
+</head>
+<body>
+
+<div id="topbar"><div class="container">
+
+<div class="top-heading"><a href="/">The Go Programming Language</a></div>
+<form method="GET" action="/search">
+<div id="menu">
+<a href="/doc/">Documents</a>
+<a href="/pkg/">Packages</a>
+<a href="/project/">The Project</a>
+<a href="/help/">Help</a>
+<a href="/blog/">Blog</a>
+<input type="text" id="search" name="q" class="inactive" value="Search" placeholder="Search">
+</div>
+</form>
+
+</div></div>
+
+<div id="page">
+<div class="container">
+
+<h1>Downloads</h1>
+
+<p>
+After downloading a binary release suitable for your system,
+please follow the <a href="/doc/install">installation instructions</a>.
+</p>
+
+<p>
+If you are building from source, 
+follow the <a href="/doc/install/source">source installation instructions</a>.
+</p>
+
+<p>
+See the <a href="/doc/devel/release.html">release history</a> for more
+information about Go releases.
+</p>
+
+{{with .Featured}}
+<h3 id="featured">Featured downloads</h3>
+{{range .}}
+{{template "download" .}}
+{{end}}
+{{end}}
+
+<div style="clear: both;"></div>
+
+{{with .Stable}}
+<h3 id="stable">Stable versions</h3>
+{{template "releases" .}}
+{{end}}
+
+{{with .Unstable}}
+<h3 id="unstable">Unstable version</h3>
+{{template "releases" .}}
+{{end}}
+
+<h3>Older versions</h3>
+
+<p>
+Older releases of Go are available at <a href="https://code.google.com/p/go/downloads/list?can=1">Google Code</a>.
+</p>
+
+
+<!-- Disabled for now; there's no admin functionality yet.
+<p>
+<small><a href="{{.LoginURL}}">&pi;</a></small>
+</p>
+-->
+
+<div id="footer">
+        <p>
+        Except as
+        <a href="https://developers.google.com/site-policies#restrictions">noted</a>,
+        the content of this page is licensed under the Creative Commons
+        Attribution 3.0 License,<br>
+        and code is licensed under a <a href="http://golang.org/LICENSE">BSD license</a>.<br>
+        <a href="http://golang.org/doc/tos.html">Terms of Service</a> |
+        <a href="http://www.google.com/intl/en/policies/privacy/">Privacy Policy</a>
+        </p>
+</div><!-- #footer -->
+
+</div><!-- .container -->
+</div><!-- #page -->
+<script>
+  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+
+  ga('create', 'UA-11222381-2', 'auto');
+  ga('send', 'pageview');
+
+</script>
+</body>
+<script src="/lib/godoc/jquery.js"></script>
+<script src="/lib/godoc/godocs.js"></script>
+<script>
+$(document).ready(function() {
+  $('a.download').click(function(e) {
+    // Try using the link text as the file name,
+    // unless there's a child element of class 'filename'.
+    var filename = $(this).text();
+    var child = $(this).find('.filename');
+    if (child.length > 0) {
+      filename = child.text();
+    }
+
+    // This must be kept in sync with the filenameRE in godocs.js.
+    var filenameRE = /^go1\.\d+(\.\d+)?([a-z0-9]+)?\.([a-z0-9]+)(-[a-z0-9]+)?(-osx10\.[68])?\.([a-z.]+)$/;
+    var m = filenameRE.exec(filename);
+    if (!m) {
+      // Don't redirect to the download page if it won't recognize this file.
+      // (Should not happen.)
+      return;
+    }
+
+    var dest = "/doc/install";
+    if (filename.indexOf(".src.") != -1) {
+      dest += "/source";
+    }
+    dest += "?download=" + filename;
+
+    e.preventDefault();
+    e.stopPropagation();
+    window.location = dest;
+  });
+});
+</script>
+</html>
+{{end}}
+
+{{define "releases"}}
+{{range .}}
+<div class="toggle{{if .Visible}}Visible{{end}}" id="{{.Version}}">
+	<div class="collapsed">
+		<h2 class="toggleButton" title="Click to show downloads for this version">{{.Version}} â–¹</h2>
+	</div>
+	<div class="expanded">
+		<h2 class="toggleButton" title="Click to hide downloads for this version">{{.Version}} â–¾</h2>
+		{{if .Stable}}{{else}}
+			<p>This is an <b>unstable</b> version of Go. Use with caution.</p>
+		{{end}}
+		{{template "files" .Files}}
+	</div>
+</div>
+{{end}}
+{{end}}
+
+{{define "files"}}
+<table class="codetable">
+<thead>
+<tr class="first">
+  <th>File name</th>
+  <th>Kind</th>
+  <th>OS</th>
+  <th>Arch</th>
+  <th>Size</th>
+  {{/* Use the checksum type of the first file for the column heading. */}}
+  <th>{{(index . 0).ChecksumType}} Checksum</th>
+</tr>
+</thead>
+{{range .}}
+<tr{{if .Highlight}} class="highlight"{{end}}>
+  <td class="filename"><a class="download" href="{{.URL}}">{{.Filename}}</a></td>
+  <td>{{pretty .Kind}}</td>
+  <td>{{.PrettyOS}}</td>
+  <td>{{pretty .Arch}}</td>
+  <td>{{.PrettySize}}</td>
+  <td><tt>{{.PrettyChecksum}}</tt></td>
+</tr>
+{{else}}
+<tr>
+  <td colspan="5">No downloads available.</td>
+</tr>
+{{end}}
+</table>
+{{end}}
+
+{{define "download"}}
+<a class="download downloadBox" href="{{.URL}}">
+<div class="platform">{{.Platform}}</div>
+{{with .Requirements}}<div class="reqs">{{.}}</div>{{end}}
+<div>
+  <span class="filename">{{.Filename}}</span>
+  {{if .Size}}<span class="size">({{.PrettySize}})</span>{{end}}
+</div>
+<div class="checksum">{{.ChecksumType}}: {{.PrettyChecksum}}</div>
+</a>
+{{end}}
+`
diff --git a/go/src/golang.org/x/tools/godoc/godoc.go b/go/src/golang.org/x/tools/godoc/godoc.go
index 6b176c6..dda1f49 100644
--- a/go/src/golang.org/x/tools/godoc/godoc.go
+++ b/go/src/golang.org/x/tools/godoc/godoc.go
@@ -281,6 +281,7 @@
 type PageInfo struct {
 	Dirname string // directory containing the package
 	Err     error  // error or nil
+	Share   bool   // show share button on examples
 
 	// package info
 	FSet       *token.FileSet         // nil if no package documentation
@@ -433,7 +434,7 @@
 		buf.WriteString(indent)
 		buf.WriteString("Example:\n\t")
 		buf.WriteString(code)
-		buf.WriteString("\n")
+		buf.WriteString("\n\n")
 	}
 	return buf.String()
 }
@@ -490,7 +491,8 @@
 
 		err := p.ExampleHTML.Execute(&buf, struct {
 			Name, Doc, Code, Play, Output string
-		}{eg.Name, eg.Doc, code, play, out})
+			Share                         bool
+		}{eg.Name, eg.Doc, code, play, out, info.Share})
 		if err != nil {
 			log.Print(err)
 		}
diff --git a/go/src/golang.org/x/tools/godoc/page.go b/go/src/golang.org/x/tools/godoc/page.go
index b296b27..79b1e19 100644
--- a/go/src/golang.org/x/tools/godoc/page.go
+++ b/go/src/golang.org/x/tools/godoc/page.go
@@ -16,6 +16,7 @@
 	Subtitle string
 	Query    string
 	Body     []byte
+	Share    bool
 
 	// filled in by servePage
 	SearchBox  bool
@@ -39,5 +40,19 @@
 		Title:    "File " + relpath,
 		Subtitle: relpath,
 		Body:     applyTemplate(p.ErrorHTML, "errorHTML", err), // err may contain an absolute path!
+		Share:    allowShare(r),
 	})
 }
+
+var onAppengine = false // overriden in appengine.go when on app engine
+
+func allowShare(r *http.Request) bool {
+	if !onAppengine {
+		return true
+	}
+	switch r.Header.Get("X-AppEngine-Country") {
+	case "", "ZZ", "CN":
+		return false
+	}
+	return true
+}
diff --git a/go/src/golang.org/x/tools/godoc/pres.go b/go/src/golang.org/x/tools/godoc/pres.go
index a8f8b2b..11e0dd3 100644
--- a/go/src/golang.org/x/tools/godoc/pres.go
+++ b/go/src/golang.org/x/tools/godoc/pres.go
@@ -119,14 +119,15 @@
 		p:       p,
 		c:       c,
 		pattern: "/cmd/",
-		fsRoot:  "/src/cmd",
+		fsRoot:  "/src",
 	}
 	p.pkgHandler = handlerServer{
-		p:       p,
-		c:       c,
-		pattern: "/pkg/",
-		fsRoot:  "/src",
-		exclude: []string{"/src/cmd"},
+		p:           p,
+		c:           c,
+		pattern:     "/pkg/",
+		stripPrefix: "pkg/",
+		fsRoot:      "/src",
+		exclude:     []string{"/src/cmd"},
 	}
 	p.cmdHandler.registerWithMux(p.mux)
 	p.pkgHandler.registerWithMux(p.mux)
diff --git a/go/src/golang.org/x/tools/godoc/proxy/proxy.go b/go/src/golang.org/x/tools/godoc/proxy/proxy.go
new file mode 100644
index 0000000..5b331ee
--- /dev/null
+++ b/go/src/golang.org/x/tools/godoc/proxy/proxy.go
@@ -0,0 +1,169 @@
+// Copyright 2015 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.
+
+// +build appengine
+
+// Package proxy proxies requests to the sandbox compiler service and the
+// playground share handler.
+// It is designed to run only on the instance of godoc that serves golang.org.
+package proxy
+
+import (
+	"bytes"
+	"crypto/sha1"
+	"encoding/json"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net/http"
+	"net/http/httputil"
+	"net/url"
+	"time"
+
+	"golang.org/x/net/context"
+
+	"google.golang.org/appengine"
+	"google.golang.org/appengine/log"
+	"google.golang.org/appengine/memcache"
+	"google.golang.org/appengine/urlfetch"
+)
+
+type Request struct {
+	Body string
+}
+
+type Response struct {
+	Errors string
+	Events []Event
+}
+
+type Event struct {
+	Message string
+	Kind    string        // "stdout" or "stderr"
+	Delay   time.Duration // time to wait before printing Message
+}
+
+const (
+	// We need to use HTTP here for "reasons", but the traffic isn't
+	// sensitive and it only travels across Google's internal network
+	// so we should be OK.
+	sandboxURL    = "http://sandbox.golang.org/compile"
+	playgroundURL = "http://play.golang.org"
+)
+
+const expires = 7 * 24 * time.Hour // 1 week
+var cacheControlHeader = fmt.Sprintf("public, max-age=%d", int(expires.Seconds()))
+
+func RegisterHandlers(mux *http.ServeMux) {
+	mux.HandleFunc("/compile", compile)
+	mux.HandleFunc("/share", share)
+}
+
+func compile(w http.ResponseWriter, r *http.Request) {
+	if r.Method != "POST" {
+		http.Error(w, "I only answer to POST requests.", http.StatusMethodNotAllowed)
+		return
+	}
+
+	c := appengine.NewContext(r)
+
+	body := r.FormValue("body")
+	res := &Response{}
+	key := cacheKey(body)
+	if _, err := memcache.Gob.Get(c, key, res); err != nil {
+		if err != memcache.ErrCacheMiss {
+			log.Errorf(c, "getting response cache: %v", err)
+		}
+
+		req := &Request{Body: body}
+		if err := makeSandboxRequest(c, req, res); err != nil {
+			log.Errorf(c, "compile error: %v", err)
+			http.Error(w, "Internal Server Error", http.StatusInternalServerError)
+			return
+		}
+
+		item := &memcache.Item{Key: key, Object: res}
+		if err := memcache.Gob.Set(c, item); err != nil {
+			log.Errorf(c, "setting response cache: %v", err)
+		}
+	}
+
+	expiresTime := time.Now().Add(expires).UTC()
+	w.Header().Set("Expires", expiresTime.Format(time.RFC1123))
+	w.Header().Set("Cache-Control", cacheControlHeader)
+
+	var out interface{}
+	switch r.FormValue("version") {
+	case "2":
+		out = res
+	default: // "1"
+		out = struct {
+			CompileErrors string `json:"compile_errors"`
+			Output        string `json:"output"`
+		}{res.Errors, flatten(res.Events)}
+	}
+	if err := json.NewEncoder(w).Encode(out); err != nil {
+		log.Errorf(c, "encoding response: %v", err)
+	}
+}
+
+// makeSandboxRequest sends the given Request to the sandbox
+// and stores the response in the given Response.
+func makeSandboxRequest(c context.Context, req *Request, res *Response) error {
+	reqJ, err := json.Marshal(req)
+	if err != nil {
+		return fmt.Errorf("marshalling request: %v", err)
+	}
+	r, err := urlfetch.Client(c).Post(sandboxURL, "application/json", bytes.NewReader(reqJ))
+	if err != nil {
+		return fmt.Errorf("making request: %v", err)
+	}
+	defer r.Body.Close()
+	if r.StatusCode != http.StatusOK {
+		b, _ := ioutil.ReadAll(r.Body)
+		return fmt.Errorf("bad status: %v body:\n%s", r.Status, b)
+	}
+	err = json.NewDecoder(r.Body).Decode(res)
+	if err != nil {
+		return fmt.Errorf("unmarshalling response: %v", err)
+	}
+	return nil
+}
+
+// flatten takes a sequence of Events and returns their contents, concatenated.
+func flatten(seq []Event) string {
+	var buf bytes.Buffer
+	for _, e := range seq {
+		buf.WriteString(e.Message)
+	}
+	return buf.String()
+}
+
+func cacheKey(body string) string {
+	h := sha1.New()
+	io.WriteString(h, body)
+	return fmt.Sprintf("prog-%x", h.Sum(nil))
+}
+
+func share(w http.ResponseWriter, r *http.Request) {
+	if !allowShare(r) {
+		http.Error(w, "Forbidden", http.StatusForbidden)
+		return
+	}
+	target, _ := url.Parse(playgroundURL)
+	p := httputil.NewSingleHostReverseProxy(target)
+	p.Transport = &urlfetch.Transport{Context: appengine.NewContext(r)}
+	p.ServeHTTP(w, r)
+}
+
+func allowShare(r *http.Request) bool {
+	if appengine.IsDevAppServer() {
+		return true
+	}
+	switch r.Header.Get("X-AppEngine-Country") {
+	case "", "ZZ", "CN":
+		return false
+	}
+	return true
+}
diff --git a/go/src/golang.org/x/tools/godoc/redirect/redirect.go b/go/src/golang.org/x/tools/godoc/redirect/redirect.go
index 77d927d..b07d97f 100644
--- a/go/src/golang.org/x/tools/godoc/redirect/redirect.go
+++ b/go/src/golang.org/x/tools/godoc/redirect/redirect.go
@@ -36,6 +36,7 @@
 	mux.HandleFunc("/src/pkg/", srcPkgHandler)
 	mux.HandleFunc("/cl/", clHandler)
 	mux.HandleFunc("/change/", changeHandler)
+	mux.HandleFunc("/design/", designHandler)
 }
 
 func handlePathRedirects(mux *http.ServeMux, redirects map[string]string, prefix string) {
@@ -98,6 +99,7 @@
 	"/issues":     "https://github.com/golang/go/issues",
 	"/issues/new": "https://github.com/golang/go/issues/new",
 	"/play":       "http://play.golang.org",
+	"/design":     "https://github.com/golang/proposal/tree/master/design",
 
 	// In Go 1.2 the references page is part of /doc/.
 	"/ref": "/doc/#references",
@@ -140,7 +142,11 @@
 
 func Handler(target string) http.Handler {
 	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		http.Redirect(w, r, target, http.StatusMovedPermanently)
+		url := target
+		if qs := r.URL.RawQuery; qs != "" {
+			url += "?" + qs
+		}
+		http.Redirect(w, r, url, http.StatusMovedPermanently)
 	})
 }
 
@@ -230,3 +236,15 @@
 	}
 	http.Redirect(w, r, target, http.StatusFound)
 }
+
+func designHandler(w http.ResponseWriter, r *http.Request) {
+	const prefix = "/design/"
+	if p := r.URL.Path; p == prefix {
+		// redirect /prefix/ to /prefix
+		http.Redirect(w, r, p[:len(p)-1], http.StatusFound)
+		return
+	}
+	name := r.URL.Path[len(prefix):]
+	target := "https://github.com/golang/proposal/blob/master/design/" + name + ".md"
+	http.Redirect(w, r, target, http.StatusFound)
+}
diff --git a/go/src/golang.org/x/tools/godoc/redirect/redirect_test.go b/go/src/golang.org/x/tools/godoc/redirect/redirect_test.go
new file mode 100644
index 0000000..5e8045a
--- /dev/null
+++ b/go/src/golang.org/x/tools/godoc/redirect/redirect_test.go
@@ -0,0 +1,101 @@
+// Copyright 2015 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 redirect
+
+import (
+	"net/http"
+	"net/http/httptest"
+	"testing"
+)
+
+type redirectResult struct {
+	status int
+	path   string
+}
+
+func errorResult(status int) redirectResult {
+	return redirectResult{status, ""}
+}
+
+func TestRedirects(t *testing.T) {
+	var tests = map[string]redirectResult{
+		"/build":    {301, "http://build.golang.org"},
+		"/ref":      {301, "/doc/#references"},
+		"/doc/mem":  {301, "/ref/mem"},
+		"/doc/spec": {301, "/ref/spec"},
+		"/tour":     {301, "http://tour.golang.org"},
+		"/foo":      errorResult(404),
+
+		"/pkg/asn1":           {301, "/pkg/encoding/asn1/"},
+		"/pkg/template/parse": {301, "/pkg/text/template/parse/"},
+
+		"/src/pkg/foo": {301, "/src/foo"},
+
+		"/cmd/gofix": {301, "/cmd/fix/"},
+
+		// git commits (/change)
+		// TODO: mercurial tags and LoadChangeMap.
+		"/change":   {301, "https://go.googlesource.com/go"},
+		"/change/a": {302, "https://go.googlesource.com/go/+/a"},
+
+		"/issue":                    {301, "https://github.com/golang/go/issues"},
+		"/issue?":                   {301, "https://github.com/golang/go/issues"},
+		"/issue/1":                  {302, "https://github.com/golang/go/issues/1"},
+		"/issue/new":                {301, "https://github.com/golang/go/issues/new"},
+		"/issue/new?a=b&c=d%20&e=f": {301, "https://github.com/golang/go/issues/new?a=b&c=d%20&e=f"},
+		"/issues":                   {301, "https://github.com/golang/go/issues"},
+		"/issues/1":                 {302, "https://github.com/golang/go/issues/1"},
+		"/issues/new":               {301, "https://github.com/golang/go/issues/new"},
+		"/issues/1/2/3":             errorResult(404),
+
+		"/design":              {301, "https://github.com/golang/proposal/tree/master/design"},
+		"/design/":             {302, "/design"},
+		"/design/123-foo":      {302, "https://github.com/golang/proposal/blob/master/design/123-foo.md"},
+		"/design/text/123-foo": {302, "https://github.com/golang/proposal/blob/master/design/text/123-foo.md"},
+
+		"/cl/1":          {302, "https://go-review.googlesource.com/r/1"},
+		"/cl/1/":         {302, "https://go-review.googlesource.com/r/1"},
+		"/cl/267120043":  {302, "https://codereview.appspot.com/267120043"},
+		"/cl/267120043/": {302, "https://codereview.appspot.com/267120043"},
+	}
+
+	mux := http.NewServeMux()
+	Register(mux)
+	ts := httptest.NewServer(mux)
+	defer ts.Close()
+
+	for path, want := range tests {
+		if want.path != "" && want.path[0] == '/' {
+			// All redirects are absolute.
+			want.path = ts.URL + want.path
+		}
+
+		req, err := http.NewRequest("GET", ts.URL+path, nil)
+		if err != nil {
+			t.Errorf("(path: %q) unexpected error: %v", path, err)
+			continue
+		}
+
+		resp, err := http.DefaultTransport.RoundTrip(req)
+		if err != nil {
+			t.Errorf("(path: %q) unexpected error: %v", path, err)
+			continue
+		}
+
+		if resp.StatusCode != want.status {
+			t.Errorf("(path: %q) got status %d, want %d", path, resp.StatusCode, want.status)
+		}
+
+		if want.status != 301 && want.status != 302 {
+			// Not a redirect. Just check status.
+			continue
+		}
+
+		out, _ := resp.Location()
+		if got := out.String(); got != want.path {
+			t.Errorf("(path: %q) got %s, want %s", path, got, want.path)
+		}
+	}
+}
diff --git a/go/src/golang.org/x/tools/godoc/search.go b/go/src/golang.org/x/tools/godoc/search.go
index e126330..ff3f2be 100644
--- a/go/src/golang.org/x/tools/godoc/search.go
+++ b/go/src/golang.org/x/tools/godoc/search.go
@@ -126,6 +126,7 @@
 		Tabtitle: query,
 		Query:    query,
 		Body:     body.Bytes(),
+		Share:    allowShare(r),
 	})
 }
 
diff --git a/go/src/golang.org/x/tools/godoc/server.go b/go/src/golang.org/x/tools/godoc/server.go
index 2c18efb..6906df8 100644
--- a/go/src/golang.org/x/tools/godoc/server.go
+++ b/go/src/golang.org/x/tools/godoc/server.go
@@ -34,11 +34,12 @@
 // handlerServer is a migration from an old godoc http Handler type.
 // This should probably merge into something else.
 type handlerServer struct {
-	p       *Presentation
-	c       *Corpus  // copy of p.Corpus
-	pattern string   // url pattern; e.g. "/pkg/"
-	fsRoot  string   // file system root to which the pattern is mapped; e.g. "/src"
-	exclude []string // file system paths to exclude; e.g. "/src/cmd"
+	p           *Presentation
+	c           *Corpus  // copy of p.Corpus
+	pattern     string   // url pattern; e.g. "/pkg/"
+	stripPrefix string   // prefix to strip from import path; e.g. "pkg/"
+	fsRoot      string   // file system root to which the pattern is mapped; e.g. "/src"
+	exclude     []string // file system paths to exclude; e.g. "/src/cmd"
 }
 
 func (s *handlerServer) registerWithMux(mux *http.ServeMux) {
@@ -214,9 +215,9 @@
 	if mode&NoFiltering != 0 {
 		return true
 	}
-	if strings.Contains(path, "internal") {
+	if strings.Contains(path, "internal") || strings.Contains(path, "vendor") {
 		for _, c := range strings.Split(filepath.Clean(path), string(os.PathSeparator)) {
-			if c == "internal" {
+			if c == "internal" || c == "vendor" {
 				return false
 			}
 		}
@@ -235,7 +236,7 @@
 		return
 	}
 
-	relpath := pathpkg.Clean(r.URL.Path[len(h.pattern):])
+	relpath := pathpkg.Clean(r.URL.Path[len(h.stripPrefix)+1:])
 	abspath := pathpkg.Join(h.fsRoot, relpath)
 	mode := h.p.GetPageInfoMode(r)
 	if relpath == builtinPkgPath {
@@ -300,11 +301,13 @@
 		info.TypeInfoIndex[ti.Name] = i
 	}
 
+	info.Share = allowShare(r)
 	h.p.ServePage(w, Page{
 		Title:    title,
 		Tabtitle: tabtitle,
 		Subtitle: subtitle,
 		Body:     applyTemplate(h.p.PackageHTML, "packageHTML", info),
+		Share:    info.Share,
 	})
 }
 
@@ -546,6 +549,7 @@
 		Title:    title + " " + relpath,
 		Tabtitle: relpath,
 		Body:     buf.Bytes(),
+		Share:    allowShare(r),
 	})
 }
 
@@ -606,6 +610,7 @@
 		Title:    "Directory " + relpath,
 		Tabtitle: relpath,
 		Body:     applyTemplate(p.DirlistHTML, "dirlistHTML", list),
+		Share:    allowShare(r),
 	})
 }
 
@@ -631,6 +636,12 @@
 		log.Printf("decoding metadata %s: %v", relpath, err)
 	}
 
+	page := Page{
+		Title:    meta.Title,
+		Subtitle: meta.Subtitle,
+		Share:    allowShare(r),
+	}
+
 	// evaluate as template if indicated
 	if meta.Template {
 		tmpl, err := template.New("main").Funcs(p.TemplateFuncs()).Parse(string(src))
@@ -640,7 +651,7 @@
 			return
 		}
 		var buf bytes.Buffer
-		if err := tmpl.Execute(&buf, nil); err != nil {
+		if err := tmpl.Execute(&buf, page); err != nil {
 			log.Printf("executing template %s: %v", relpath, err)
 			p.ServeError(w, r, relpath, err)
 			return
@@ -655,11 +666,8 @@
 		src = buf.Bytes()
 	}
 
-	p.ServePage(w, Page{
-		Title:    meta.Title,
-		Subtitle: meta.Subtitle,
-		Body:     src,
-	})
+	page.Body = src
+	p.ServePage(w, page)
 }
 
 func (p *Presentation) ServeFile(w http.ResponseWriter, r *http.Request) {
diff --git a/go/src/golang.org/x/tools/godoc/short/short.go b/go/src/golang.org/x/tools/godoc/short/short.go
new file mode 100644
index 0000000..44d3c93
--- /dev/null
+++ b/go/src/golang.org/x/tools/godoc/short/short.go
@@ -0,0 +1,173 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by the Apache 2.0
+// license that can be found in the LICENSE file.
+
+// +build appengine
+
+// Package short implements a simple URL shortener, serving an administrative
+// interface at /s and shortened urls from /s/key.
+// It is designed to run only on the instance of godoc that serves golang.org.
+package short
+
+// TODO(adg): collect statistics on URL visits
+
+import (
+	"errors"
+	"fmt"
+	"html/template"
+	"net/http"
+	"net/url"
+	"regexp"
+
+	"golang.org/x/net/context"
+
+	"google.golang.org/appengine"
+	"google.golang.org/appengine/datastore"
+	"google.golang.org/appengine/log"
+	"google.golang.org/appengine/memcache"
+	"google.golang.org/appengine/user"
+)
+
+const (
+	prefix  = "/s"
+	kind    = "Link"
+	baseURL = "https://golang.org" + prefix
+)
+
+// Link represents a short link.
+type Link struct {
+	Key, Target string
+}
+
+var validKey = regexp.MustCompile(`^[a-zA-Z0-9-_.]+$`)
+
+func RegisterHandlers(mux *http.ServeMux) {
+	mux.HandleFunc(prefix, adminHandler)
+	mux.HandleFunc(prefix+"/", linkHandler)
+}
+
+// linkHandler services requests to short URLs.
+//   http://golang.org/s/key
+// It consults memcache and datastore for the Link for key.
+// It then sends a redirects or an error message.
+func linkHandler(w http.ResponseWriter, r *http.Request) {
+	c := appengine.NewContext(r)
+
+	key := r.URL.Path[len(prefix)+1:]
+	if !validKey.MatchString(key) {
+		http.Error(w, "not found", http.StatusNotFound)
+		return
+	}
+
+	var link Link
+	_, err := memcache.JSON.Get(c, cacheKey(key), &link)
+	if err != nil {
+		k := datastore.NewKey(c, kind, key, 0, nil)
+		err = datastore.Get(c, k, &link)
+		switch err {
+		case datastore.ErrNoSuchEntity:
+			http.Error(w, "not found", http.StatusNotFound)
+			return
+		default: // != nil
+			log.Errorf(c, "%q: %v", key, err)
+			http.Error(w, "internal server error", http.StatusInternalServerError)
+			return
+		case nil:
+			item := &memcache.Item{
+				Key:    cacheKey(key),
+				Object: &link,
+			}
+			if err := memcache.JSON.Set(c, item); err != nil {
+				log.Warningf(c, "%q: %v", key, err)
+			}
+		}
+	}
+
+	http.Redirect(w, r, link.Target, http.StatusFound)
+}
+
+var adminTemplate = template.Must(template.New("admin").Parse(templateHTML))
+
+// adminHandler serves an administrative interface.
+func adminHandler(w http.ResponseWriter, r *http.Request) {
+	c := appengine.NewContext(r)
+
+	if !user.IsAdmin(c) {
+		http.Error(w, "forbidden", http.StatusForbidden)
+		return
+	}
+
+	var newLink *Link
+	var doErr error
+	if r.Method == "POST" {
+		key := r.FormValue("key")
+		switch r.FormValue("do") {
+		case "Add":
+			newLink = &Link{key, r.FormValue("target")}
+			doErr = putLink(c, newLink)
+		case "Delete":
+			k := datastore.NewKey(c, kind, key, 0, nil)
+			doErr = datastore.Delete(c, k)
+		default:
+			http.Error(w, "unknown action", http.StatusBadRequest)
+		}
+		err := memcache.Delete(c, cacheKey(key))
+		if err != nil && err != memcache.ErrCacheMiss {
+			log.Warningf(c, "%q: %v", key, err)
+		}
+	}
+
+	var links []*Link
+	_, err := datastore.NewQuery(kind).Order("Key").GetAll(c, &links)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		log.Errorf(c, "%v", err)
+		return
+	}
+
+	// Put the new link in the list if it's not there already.
+	// (Eventual consistency means that it might not show up
+	// immediately, which might be confusing for the user.)
+	if newLink != nil && doErr == nil {
+		found := false
+		for i := range links {
+			if links[i].Key == newLink.Key {
+				found = true
+				break
+			}
+		}
+		if !found {
+			links = append([]*Link{newLink}, links...)
+		}
+		newLink = nil
+	}
+
+	var data = struct {
+		BaseURL string
+		Prefix  string
+		Links   []*Link
+		New     *Link
+		Error   error
+	}{baseURL, prefix, links, newLink, doErr}
+	if err := adminTemplate.Execute(w, &data); err != nil {
+		log.Criticalf(c, "adminTemplate: %v", err)
+	}
+}
+
+// putLink validates the provided link and puts it into the datastore.
+func putLink(c context.Context, link *Link) error {
+	if !validKey.MatchString(link.Key) {
+		return errors.New("invalid key; must match " + validKey.String())
+	}
+	if _, err := url.Parse(link.Target); err != nil {
+		return fmt.Errorf("bad target: %v", err)
+	}
+	k := datastore.NewKey(c, kind, link.Key, 0, nil)
+	_, err := datastore.Put(c, k, link)
+	return err
+}
+
+// cacheKey returns a short URL key as a memcache key.
+func cacheKey(key string) string {
+	return "link-" + key
+}
diff --git a/go/src/golang.org/x/tools/godoc/short/tmpl.go b/go/src/golang.org/x/tools/godoc/short/tmpl.go
new file mode 100644
index 0000000..95e4c2a
--- /dev/null
+++ b/go/src/golang.org/x/tools/godoc/short/tmpl.go
@@ -0,0 +1,121 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by the Apache 2.0
+// license that can be found in the LICENSE file.
+
+// +build appengine
+
+package short
+
+const templateHTML = `
+<!doctype HTML>
+<html>
+<head>
+<title>golang.org URL shortener</title>
+<style>
+body {
+	background: white;
+}
+input {
+	border: 1px solid #ccc;
+}
+input[type=text] {
+	width: 400px;
+}
+input, td, th {
+	color: #333;
+	font-family: Georgia, Times New Roman, serif;
+}
+input, td {
+	font-size: 14pt;
+}
+th {
+	font-size: 16pt;
+	text-align: left;
+	padding-top: 10px;
+}
+.autoselect {
+	border: none;
+}
+.error {
+	color: #900;
+}
+table {
+	margin-left: auto;
+	margin-right: auto;
+}
+</style>
+</head>
+<body>
+
+<table>
+
+{{with .Error}}
+<tr>
+	<th colspan="3">Error</th>
+</tr>
+<tr>
+	<td class="error" colspan="3">{{.}}</td>
+</tr>
+{{end}}
+
+<tr>
+	<th>Key</th>
+	<th>Target</th>
+	<th></th>
+</tr>
+
+<form method="POST" action="{{.Prefix}}">
+<tr>
+	<td><input type="text" name="key"{{with .New}} value="{{.Key}}"{{end}}></td>
+	<td><input type="text" name="target"{{with .New}} value="{{.Target}}"{{end}}></td>
+	<td><input type="submit" name="do" value="Add">
+</tr>
+</form>
+
+{{with .Links}}
+<tr>
+	<th>Short Link</th>
+	<th>&nbsp;</th>
+	<th>&nbsp;</th>
+</tr>
+{{range .}}
+<tr>
+	<td><input class="autoselect" type="text" orig="{{$.BaseURL}}/{{.Key}}" value="{{$.BaseURL}}/{{.Key}}"></td>
+	<td><input class="autoselect" type="text" orig="{{.Target}}" value="{{.Target}}"></td>
+	<td>
+		<form method="POST" action="{{$.Prefix}}">
+			<input type="hidden" name="key" value="{{.Key}}">
+			<input type="submit" name="do" value="Delete" class="delete">
+		</form>
+	</td>
+</tr>
+{{end}}
+{{end}}
+
+</table>
+
+</body>
+<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
+<script type="text/javascript">window.jQuery || document.write(unescape("%3Cscript src='/doc/jquery.js' type='text/javascript'%3E%3C/script%3E"));</script>
+<script>
+$(document).ready(function() {
+	$('.autoselect').each(function() {
+		$(this).click(function() {
+			$(this).select();
+		});
+		$(this).change(function() {
+			$(this).val($(this).attr('orig'));
+		});
+	});
+	$('.delete').click(function(e) {
+		var link = $(this).closest('tr').find('input').first().val();
+		var ok = confirm('Delete this link?\n' + link);
+		if (!ok) {
+			e.preventDefault();
+			return false;
+		}
+	});
+});
+</script>
+</html>
+`
diff --git a/go/src/golang.org/x/tools/godoc/static/example.html b/go/src/golang.org/x/tools/godoc/static/example.html
index cda2a84..4f4e09e 100644
--- a/go/src/golang.org/x/tools/godoc/static/example.html
+++ b/go/src/golang.org/x/tools/godoc/static/example.html
@@ -13,7 +13,9 @@
 				<div class="buttons">
 					<a class="run" title="Run this code [shift-enter]">Run</a>
 					<a class="fmt" title="Format this code">Format</a>
+					{{if $.Share}}
 					<a class="share" title="Share this code">Share</a>
+					{{end}}
 				</div>
 			</div>
 		{{else}}
diff --git a/go/src/golang.org/x/tools/godoc/static/godoc.html b/go/src/golang.org/x/tools/godoc/static/godoc.html
index 6d6d1b6..4605057 100644
--- a/go/src/golang.org/x/tools/godoc/static/godoc.html
+++ b/go/src/golang.org/x/tools/godoc/static/godoc.html
@@ -55,7 +55,9 @@
 	<div class="buttons">
 		<a class="run" title="Run this code [shift-enter]">Run</a>
 		<a class="fmt" title="Format this code">Format</a>
+		{{if $.Share}}
 		<a class="share" title="Share this code">Share</a>
+		{{end}}
 	</div>
 </div>
 {{end}}
diff --git a/go/src/golang.org/x/tools/godoc/static/godocs.js b/go/src/golang.org/x/tools/godoc/static/godocs.js
index 47d1de9..ec9f37a 100644
--- a/go/src/golang.org/x/tools/godoc/static/godocs.js
+++ b/go/src/golang.org/x/tools/godoc/static/godocs.js
@@ -248,7 +248,7 @@
 function personalizeInstallInstructions() {
   var prefix = '?download=';
   var s = window.location.search;
-  if (!s.startsWith(prefix)) {
+  if (s.indexOf(prefix) != 0) {
     // No 'download' query string; bail.
     return;
   }
@@ -273,6 +273,8 @@
   }
   if (os != 'windows') {
     $('#windowsInstructions').hide();
+    $('.testUnix').show();
+    $('.testWindows').hide();
   } else {
     if (ext != 'msi') {
       $('#windowsInstallerInstructions').hide();
@@ -280,6 +282,8 @@
     if (ext != 'zip') {
       $('#windowsZipInstructions').hide();
     }
+    $('.testUnix').hide();
+    $('.testWindows').show();
   }
 
   var download = "https://storage.googleapis.com/golang/" + filename;
diff --git a/go/src/golang.org/x/tools/godoc/static/makestatic.go b/go/src/golang.org/x/tools/godoc/static/makestatic.go
index f5e3272..f48313c 100644
--- a/go/src/golang.org/x/tools/godoc/static/makestatic.go
+++ b/go/src/golang.org/x/tools/godoc/static/makestatic.go
@@ -84,7 +84,7 @@
 	}
 	defer f.Close()
 	w := bufio.NewWriter(f)
-	fmt.Fprintf(w, "%v\n\npackage static\n\n", warning)
+	fmt.Fprintf(w, "%v\npackage static\n\n", warning)
 	fmt.Fprintf(w, "var Files = map[string]string{\n")
 	for _, fn := range files {
 		b, err := ioutil.ReadFile(fn)
@@ -118,4 +118,4 @@
 	return bytes.Replace(b, []byte("\xEF\xBB\xBF"), []byte("`+\"\\xEF\\xBB\\xBF\"+`"), -1)
 }
 
-const warning = "// DO NOT EDIT ** This file was generated by \"go generate\" ** DO NOT EDIT //"
+const warning = "// Code generated by \"makestatic\"; DO NOT EDIT\n"
diff --git a/go/src/golang.org/x/tools/godoc/static/static.go b/go/src/golang.org/x/tools/godoc/static/static.go
index 3009e24..3517441 100644
--- a/go/src/golang.org/x/tools/godoc/static/static.go
+++ b/go/src/golang.org/x/tools/godoc/static/static.go
@@ -1,4 +1,4 @@
-// DO NOT EDIT ** This file was generated by "go generate" ** DO NOT EDIT //
+// Code generated by "makestatic"; DO NOT EDIT
 
 package static
 
@@ -441,7 +441,9 @@
 				<div class="buttons">
 					<a class="run" title="Run this code [shift-enter]">Run</a>
 					<a class="fmt" title="Format this code">Format</a>
+					{{if $.Share}}
 					<a class="share" title="Share this code">Share</a>
+					{{end}}
 				</div>
 			</div>
 		{{else}}
@@ -513,7 +515,9 @@
 	<div class="buttons">
 		<a class="run" title="Run this code [shift-enter]">Run</a>
 		<a class="fmt" title="Format this code">Format</a>
+		{{if $.Share}}
 		<a class="share" title="Share this code">Share</a>
+		{{end}}
 	</div>
 </div>
 {{end}}
@@ -813,7 +817,7 @@
 function personalizeInstallInstructions() {
   var prefix = '?download=';
   var s = window.location.search;
-  if (!s.startsWith(prefix)) {
+  if (s.indexOf(prefix) != 0) {
     // No 'download' query string; bail.
     return;
   }
@@ -838,6 +842,8 @@
   }
   if (os != 'windows') {
     $('#windowsInstructions').hide();
+    $('.testUnix').show();
+    $('.testWindows').hide();
   } else {
     if (ext != 'msi') {
       $('#windowsInstallerInstructions').hide();
@@ -845,6 +851,8 @@
     if (ext != 'zip') {
       $('#windowsZipInstructions').hide();
     }
+    $('.testUnix').hide();
+    $('.testWindows').show();
   }
 
   var download = "https://storage.googleapis.com/golang/" + filename;
@@ -2808,7 +2816,7 @@
 .exampleHeading .text:hover {
 	text-decoration: underline;
 }
-p {
+p, li {
 	max-width: 800px;
 	word-wrap: break-word;
 }
@@ -2870,10 +2878,7 @@
 	margin: 20px;
 }
 dd {
-	margin: 0;
-}
-dd.indent {
-	margin: 0 20px;
+	margin: 0 0 0 20px;
 }
 dl,
 dd {
diff --git a/go/src/golang.org/x/tools/godoc/static/style.css b/go/src/golang.org/x/tools/godoc/static/style.css
index 4d2b07a..8ea0852 100644
--- a/go/src/golang.org/x/tools/godoc/static/style.css
+++ b/go/src/golang.org/x/tools/godoc/static/style.css
@@ -42,7 +42,7 @@
 .exampleHeading .text:hover {
 	text-decoration: underline;
 }
-p {
+p, li {
 	max-width: 800px;
 	word-wrap: break-word;
 }
@@ -104,10 +104,7 @@
 	margin: 20px;
 }
 dd {
-	margin: 0;
-}
-dd.indent {
-	margin: 0 20px;
+	margin: 0 0 0 20px;
 }
 dl,
 dd {
diff --git a/go/src/golang.org/x/tools/godoc/vfs/zipfs/zipfs.go b/go/src/golang.org/x/tools/godoc/vfs/zipfs/zipfs.go
index 87eaf8d..ca69d8c 100644
--- a/go/src/golang.org/x/tools/godoc/vfs/zipfs/zipfs.go
+++ b/go/src/golang.org/x/tools/godoc/vfs/zipfs/zipfs.go
@@ -86,21 +86,35 @@
 	return fs.ReadCloser.Close()
 }
 
-func zipPath(name string) string {
+func zipPath(name string) (string, error) {
 	name = path.Clean(name)
 	if !path.IsAbs(name) {
-		panic(fmt.Sprintf("stat: not an absolute path: %s", name))
+		return "", fmt.Errorf("stat: not an absolute path: %s", name)
 	}
-	return name[1:] // strip leading '/'
+	return name[1:], nil // strip leading '/'
+}
+
+func isRoot(abspath string) bool {
+	return path.Clean(abspath) == "/"
 }
 
 func (fs *zipFS) stat(abspath string) (int, zipFI, error) {
-	i, exact := fs.list.lookup(abspath)
-	if i < 0 {
-		// abspath has leading '/' stripped - print it explicitly
-		return -1, zipFI{}, fmt.Errorf("file not found: /%s", abspath)
+	if isRoot(abspath) {
+		return 0, zipFI{
+			name: "",
+			file: nil,
+		}, nil
 	}
-	_, name := path.Split(abspath)
+	zippath, err := zipPath(abspath)
+	if err != nil {
+		return 0, zipFI{}, err
+	}
+	i, exact := fs.list.lookup(zippath)
+	if i < 0 {
+		// zippath has leading '/' stripped - print it explicitly
+		return -1, zipFI{}, fmt.Errorf("file not found: /%s", zippath)
+	}
+	_, name := path.Split(zippath)
 	var file *zip.File
 	if exact {
 		file = fs.list[i] // exact match found - must be a file
@@ -109,7 +123,7 @@
 }
 
 func (fs *zipFS) Open(abspath string) (vfs.ReadSeekCloser, error) {
-	_, fi, err := fs.stat(zipPath(abspath))
+	_, fi, err := fs.stat(abspath)
 	if err != nil {
 		return nil, err
 	}
@@ -142,18 +156,17 @@
 }
 
 func (fs *zipFS) Lstat(abspath string) (os.FileInfo, error) {
-	_, fi, err := fs.stat(zipPath(abspath))
+	_, fi, err := fs.stat(abspath)
 	return fi, err
 }
 
 func (fs *zipFS) Stat(abspath string) (os.FileInfo, error) {
-	_, fi, err := fs.stat(zipPath(abspath))
+	_, fi, err := fs.stat(abspath)
 	return fi, err
 }
 
 func (fs *zipFS) ReadDir(abspath string) ([]os.FileInfo, error) {
-	path := zipPath(abspath)
-	i, fi, err := fs.stat(path)
+	i, fi, err := fs.stat(abspath)
 	if err != nil {
 		return nil, err
 	}
@@ -162,7 +175,21 @@
 	}
 
 	var list []os.FileInfo
-	dirname := path + "/"
+
+	// make dirname the prefix that file names must start with to be considered
+	// in this directory. we must special case the root directory because, per
+	// the spec of this package, zip file entries MUST NOT start with /, so we
+	// should not append /, as we would in every other case.
+	var dirname string
+	if isRoot(abspath) {
+		dirname = ""
+	} else {
+		zippath, err := zipPath(abspath)
+		if err != nil {
+			return nil, err
+		}
+		dirname = zippath + "/"
+	}
 	prevname := ""
 	for _, e := range fs.list[i:] {
 		if !strings.HasPrefix(e.Name, dirname) {
diff --git a/go/src/golang.org/x/tools/godoc/vfs/zipfs/zipfs_test.go b/go/src/golang.org/x/tools/godoc/vfs/zipfs/zipfs_test.go
new file mode 100644
index 0000000..57efb49
--- /dev/null
+++ b/go/src/golang.org/x/tools/godoc/vfs/zipfs/zipfs_test.go
@@ -0,0 +1,179 @@
+// Copyright 2015 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 zipfs
+package zipfs
+
+import (
+	"archive/zip"
+	"bytes"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+	"reflect"
+	"testing"
+
+	"golang.org/x/tools/godoc/vfs"
+)
+
+var (
+
+	// files to use to build zip used by zipfs in testing; maps path : contents
+	files = map[string]string{"foo": "foo", "bar/baz": "baz", "a/b/c": "c"}
+
+	// expected info for each entry in a file system described by files
+	tests = []struct {
+		Path      string
+		IsDir     bool
+		IsRegular bool
+		Name      string
+		Contents  string
+		Files     map[string]bool
+	}{
+		{"/", true, false, "", "", map[string]bool{"foo": true, "bar": true, "a": true}},
+		{"//", true, false, "", "", map[string]bool{"foo": true, "bar": true, "a": true}},
+		{"/foo", false, true, "foo", "foo", nil},
+		{"/foo/", false, true, "foo", "foo", nil},
+		{"/foo//", false, true, "foo", "foo", nil},
+		{"/bar", true, false, "bar", "", map[string]bool{"baz": true}},
+		{"/bar/", true, false, "bar", "", map[string]bool{"baz": true}},
+		{"/bar/baz", false, true, "baz", "baz", nil},
+		{"//bar//baz", false, true, "baz", "baz", nil},
+		{"/a/b", true, false, "b", "", map[string]bool{"c": true}},
+	}
+
+	// to be initialized in setup()
+	fs        vfs.FileSystem
+	statFuncs []statFunc
+)
+
+type statFunc struct {
+	Name string
+	Func func(string) (os.FileInfo, error)
+}
+
+func TestMain(t *testing.M) {
+	if err := setup(); err != nil {
+		fmt.Fprintf(os.Stderr, "Error setting up zipfs testing state: %v.\n", err)
+		os.Exit(1)
+	}
+	os.Exit(t.Run())
+}
+
+// setups state each of the tests uses
+func setup() error {
+	// create zipfs
+	b := new(bytes.Buffer)
+	zw := zip.NewWriter(b)
+	for file, contents := range files {
+		w, err := zw.Create(file)
+		if err != nil {
+			return err
+		}
+		_, err = io.WriteString(w, contents)
+		if err != nil {
+			return err
+		}
+	}
+	zw.Close()
+	zr, err := zip.NewReader(bytes.NewReader(b.Bytes()), int64(b.Len()))
+	if err != nil {
+		return err
+	}
+	rc := &zip.ReadCloser{
+		Reader: *zr,
+	}
+	fs = New(rc, "foo")
+
+	// pull out different stat functions
+	statFuncs = []statFunc{
+		{"Stat", fs.Stat},
+		{"Lstat", fs.Lstat},
+	}
+
+	return nil
+}
+
+func TestZipFSReadDir(t *testing.T) {
+	for _, test := range tests {
+		if test.IsDir {
+			infos, err := fs.ReadDir(test.Path)
+			if err != nil {
+				t.Errorf("Failed to read directory %v\n", test.Path)
+				continue
+			}
+			got := make(map[string]bool)
+			for _, info := range infos {
+				got[info.Name()] = true
+			}
+			if want := test.Files; !reflect.DeepEqual(got, want) {
+				t.Errorf("ReadDir %v got %v\nwanted %v\n", test.Path, got, want)
+			}
+		}
+	}
+}
+
+func TestZipFSStatFuncs(t *testing.T) {
+	for _, test := range tests {
+		for _, statFunc := range statFuncs {
+
+			// test can stat
+			info, err := statFunc.Func(test.Path)
+			if err != nil {
+				t.Errorf("Unexpected error using %v for %v: %v\n", statFunc.Name, test.Path, err)
+				continue
+			}
+
+			// test info.Name()
+			if got, want := info.Name(), test.Name; got != want {
+				t.Errorf("Using %v for %v info.Name() got %v wanted %v\n", statFunc.Name, test.Path, got, want)
+			}
+			// test info.IsDir()
+			if got, want := info.IsDir(), test.IsDir; got != want {
+				t.Errorf("Using %v for %v info.IsDir() got %v wanted %v\n", statFunc.Name, test.Path, got, want)
+			}
+			// test info.Mode().IsDir()
+			if got, want := info.Mode().IsDir(), test.IsDir; got != want {
+				t.Errorf("Using %v for %v info.Mode().IsDir() got %v wanted %v\n", statFunc.Name, test.Path, got, want)
+			}
+			// test info.Mode().IsRegular()
+			if got, want := info.Mode().IsRegular(), test.IsRegular; got != want {
+				t.Errorf("Using %v for %v info.Mode().IsRegular() got %v wanted %v\n", statFunc.Name, test.Path, got, want)
+			}
+			// test info.Size()
+			if test.IsRegular {
+				if got, want := info.Size(), int64(len(test.Contents)); got != want {
+					t.Errorf("Using %v for %v inf.Size() got %v wanted %v", statFunc.Name, test.Path, got, want)
+				}
+			}
+		}
+	}
+}
+
+func TestZipFSOpenSeek(t *testing.T) {
+	for _, test := range tests {
+		if test.IsRegular {
+
+			// test Open()
+			f, err := fs.Open(test.Path)
+			if err != nil {
+				t.Error(err)
+				return
+			}
+			defer f.Close()
+
+			// test Seek() multiple times
+			for i := 0; i < 3; i++ {
+				all, err := ioutil.ReadAll(f)
+				if err != nil {
+					t.Error(err)
+					return
+				}
+				if got, want := string(all), test.Contents; got != want {
+					t.Errorf("File contents for %v got %v wanted %v\n", test.Path, got, want)
+				}
+				f.Seek(0, 0)
+			}
+		}
+	}
+}
diff --git a/go/src/golang.org/x/tools/imports/mkstdlib.go b/go/src/golang.org/x/tools/imports/mkstdlib.go
index c43d325..e2dca76 100644
--- a/go/src/golang.org/x/tools/imports/mkstdlib.go
+++ b/go/src/golang.org/x/tools/imports/mkstdlib.go
@@ -46,6 +46,9 @@
 		mustOpen(api("go1.txt")),
 		mustOpen(api("go1.1.txt")),
 		mustOpen(api("go1.2.txt")),
+		mustOpen(api("go1.3.txt")),
+		mustOpen(api("go1.4.txt")),
+		mustOpen(api("go1.5.txt")),
 	)
 	sc := bufio.NewScanner(f)
 	fullImport := map[string]string{} // "zip.NewReader" => "archive/zip"
diff --git a/go/src/golang.org/x/tools/imports/sortimports.go b/go/src/golang.org/x/tools/imports/sortimports.go
index 68b3dc4..653afc5 100644
--- a/go/src/golang.org/x/tools/imports/sortimports.go
+++ b/go/src/golang.org/x/tools/imports/sortimports.go
@@ -1,5 +1,3 @@
-// +build go1.2
-
 // 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.
diff --git a/go/src/golang.org/x/tools/imports/sortimports_compat.go b/go/src/golang.org/x/tools/imports/sortimports_compat.go
deleted file mode 100644
index 295f237..0000000
--- a/go/src/golang.org/x/tools/imports/sortimports_compat.go
+++ /dev/null
@@ -1,14 +0,0 @@
-// +build !go1.2
-
-// 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 imports
-
-import "go/ast"
-
-// Go 1.1 users don't get fancy package grouping.
-// But this is still gofmt-compliant:
-
-var sortImports = ast.SortImports
diff --git a/go/src/golang.org/x/tools/imports/zstdlib.go b/go/src/golang.org/x/tools/imports/zstdlib.go
index 6cdc033..39eb3c7 100644
--- a/go/src/golang.org/x/tools/imports/zstdlib.go
+++ b/go/src/golang.org/x/tools/imports/zstdlib.go
@@ -3,2169 +3,2551 @@
 package imports
 
 var stdlib = map[string]string{
-	"adler32.Checksum":                        "hash/adler32",
-	"adler32.New":                             "hash/adler32",
-	"adler32.Size":                            "hash/adler32",
-	"aes.BlockSize":                           "crypto/aes",
-	"aes.KeySizeError":                        "crypto/aes",
-	"aes.NewCipher":                           "crypto/aes",
-	"ascii85.CorruptInputError":               "encoding/ascii85",
-	"ascii85.Decode":                          "encoding/ascii85",
-	"ascii85.Encode":                          "encoding/ascii85",
-	"ascii85.MaxEncodedLen":                   "encoding/ascii85",
-	"ascii85.NewDecoder":                      "encoding/ascii85",
-	"ascii85.NewEncoder":                      "encoding/ascii85",
-	"asn1.BitString":                          "encoding/asn1",
-	"asn1.Enumerated":                         "encoding/asn1",
-	"asn1.Flag":                               "encoding/asn1",
-	"asn1.Marshal":                            "encoding/asn1",
-	"asn1.ObjectIdentifier":                   "encoding/asn1",
-	"asn1.RawContent":                         "encoding/asn1",
-	"asn1.RawValue":                           "encoding/asn1",
-	"asn1.StructuralError":                    "encoding/asn1",
-	"asn1.SyntaxError":                        "encoding/asn1",
-	"asn1.Unmarshal":                          "encoding/asn1",
-	"asn1.UnmarshalWithParams":                "encoding/asn1",
-	"ast.ArrayType":                           "go/ast",
-	"ast.AssignStmt":                          "go/ast",
-	"ast.Bad":                                 "go/ast",
-	"ast.BadDecl":                             "go/ast",
-	"ast.BadExpr":                             "go/ast",
-	"ast.BadStmt":                             "go/ast",
-	"ast.BasicLit":                            "go/ast",
-	"ast.BinaryExpr":                          "go/ast",
-	"ast.BlockStmt":                           "go/ast",
-	"ast.BranchStmt":                          "go/ast",
-	"ast.CallExpr":                            "go/ast",
-	"ast.CaseClause":                          "go/ast",
-	"ast.ChanDir":                             "go/ast",
-	"ast.ChanType":                            "go/ast",
-	"ast.CommClause":                          "go/ast",
-	"ast.Comment":                             "go/ast",
-	"ast.CommentGroup":                        "go/ast",
-	"ast.CommentMap":                          "go/ast",
-	"ast.CompositeLit":                        "go/ast",
-	"ast.Con":                                 "go/ast",
-	"ast.DeclStmt":                            "go/ast",
-	"ast.DeferStmt":                           "go/ast",
-	"ast.Ellipsis":                            "go/ast",
-	"ast.EmptyStmt":                           "go/ast",
-	"ast.ExprStmt":                            "go/ast",
-	"ast.Field":                               "go/ast",
-	"ast.FieldFilter":                         "go/ast",
-	"ast.FieldList":                           "go/ast",
-	"ast.File":                                "go/ast",
-	"ast.FileExports":                         "go/ast",
-	"ast.Filter":                              "go/ast",
-	"ast.FilterDecl":                          "go/ast",
-	"ast.FilterFile":                          "go/ast",
-	"ast.FilterFuncDuplicates":                "go/ast",
-	"ast.FilterImportDuplicates":              "go/ast",
-	"ast.FilterPackage":                       "go/ast",
-	"ast.FilterUnassociatedComments":          "go/ast",
-	"ast.ForStmt":                             "go/ast",
-	"ast.Fprint":                              "go/ast",
-	"ast.Fun":                                 "go/ast",
-	"ast.FuncDecl":                            "go/ast",
-	"ast.FuncLit":                             "go/ast",
-	"ast.FuncType":                            "go/ast",
-	"ast.GenDecl":                             "go/ast",
-	"ast.GoStmt":                              "go/ast",
-	"ast.Ident":                               "go/ast",
-	"ast.IfStmt":                              "go/ast",
-	"ast.ImportSpec":                          "go/ast",
-	"ast.Importer":                            "go/ast",
-	"ast.IncDecStmt":                          "go/ast",
-	"ast.IndexExpr":                           "go/ast",
-	"ast.Inspect":                             "go/ast",
-	"ast.InterfaceType":                       "go/ast",
-	"ast.IsExported":                          "go/ast",
-	"ast.KeyValueExpr":                        "go/ast",
-	"ast.LabeledStmt":                         "go/ast",
-	"ast.Lbl":                                 "go/ast",
-	"ast.MapType":                             "go/ast",
-	"ast.MergeMode":                           "go/ast",
-	"ast.MergePackageFiles":                   "go/ast",
-	"ast.NewCommentMap":                       "go/ast",
-	"ast.NewIdent":                            "go/ast",
-	"ast.NewObj":                              "go/ast",
-	"ast.NewPackage":                          "go/ast",
-	"ast.NewScope":                            "go/ast",
-	"ast.Node":                                "go/ast",
-	"ast.NotNilFilter":                        "go/ast",
-	"ast.ObjKind":                             "go/ast",
-	"ast.Object":                              "go/ast",
-	"ast.Package":                             "go/ast",
-	"ast.PackageExports":                      "go/ast",
-	"ast.ParenExpr":                           "go/ast",
-	"ast.Pkg":                                 "go/ast",
-	"ast.Print":                               "go/ast",
-	"ast.RECV":                                "go/ast",
-	"ast.RangeStmt":                           "go/ast",
-	"ast.ReturnStmt":                          "go/ast",
-	"ast.SEND":                                "go/ast",
-	"ast.Scope":                               "go/ast",
-	"ast.SelectStmt":                          "go/ast",
-	"ast.SelectorExpr":                        "go/ast",
-	"ast.SendStmt":                            "go/ast",
-	"ast.SliceExpr":                           "go/ast",
-	"ast.SortImports":                         "go/ast",
-	"ast.StarExpr":                            "go/ast",
-	"ast.StructType":                          "go/ast",
-	"ast.SwitchStmt":                          "go/ast",
-	"ast.Typ":                                 "go/ast",
-	"ast.TypeAssertExpr":                      "go/ast",
-	"ast.TypeSpec":                            "go/ast",
-	"ast.TypeSwitchStmt":                      "go/ast",
-	"ast.UnaryExpr":                           "go/ast",
-	"ast.ValueSpec":                           "go/ast",
-	"ast.Var":                                 "go/ast",
-	"ast.Visitor":                             "go/ast",
-	"ast.Walk":                                "go/ast",
-	"atomic.AddInt32":                         "sync/atomic",
-	"atomic.AddInt64":                         "sync/atomic",
-	"atomic.AddUint32":                        "sync/atomic",
-	"atomic.AddUint64":                        "sync/atomic",
-	"atomic.AddUintptr":                       "sync/atomic",
-	"atomic.CompareAndSwapInt32":              "sync/atomic",
-	"atomic.CompareAndSwapInt64":              "sync/atomic",
-	"atomic.CompareAndSwapPointer":            "sync/atomic",
-	"atomic.CompareAndSwapUint32":             "sync/atomic",
-	"atomic.CompareAndSwapUint64":             "sync/atomic",
-	"atomic.CompareAndSwapUintptr":            "sync/atomic",
-	"atomic.LoadInt32":                        "sync/atomic",
-	"atomic.LoadInt64":                        "sync/atomic",
-	"atomic.LoadPointer":                      "sync/atomic",
-	"atomic.LoadUint32":                       "sync/atomic",
-	"atomic.LoadUint64":                       "sync/atomic",
-	"atomic.LoadUintptr":                      "sync/atomic",
-	"atomic.StoreInt32":                       "sync/atomic",
-	"atomic.StoreInt64":                       "sync/atomic",
-	"atomic.StorePointer":                     "sync/atomic",
-	"atomic.StoreUint32":                      "sync/atomic",
-	"atomic.StoreUint64":                      "sync/atomic",
-	"atomic.StoreUintptr":                     "sync/atomic",
-	"atomic.SwapInt32":                        "sync/atomic",
-	"atomic.SwapInt64":                        "sync/atomic",
-	"atomic.SwapPointer":                      "sync/atomic",
-	"atomic.SwapUint32":                       "sync/atomic",
-	"atomic.SwapUint64":                       "sync/atomic",
-	"atomic.SwapUintptr":                      "sync/atomic",
-	"base32.CorruptInputError":                "encoding/base32",
-	"base32.Encoding":                         "encoding/base32",
-	"base32.HexEncoding":                      "encoding/base32",
-	"base32.NewDecoder":                       "encoding/base32",
-	"base32.NewEncoder":                       "encoding/base32",
-	"base32.NewEncoding":                      "encoding/base32",
-	"base32.StdEncoding":                      "encoding/base32",
-	"base64.CorruptInputError":                "encoding/base64",
-	"base64.Encoding":                         "encoding/base64",
-	"base64.NewDecoder":                       "encoding/base64",
-	"base64.NewEncoder":                       "encoding/base64",
-	"base64.NewEncoding":                      "encoding/base64",
-	"base64.StdEncoding":                      "encoding/base64",
-	"base64.URLEncoding":                      "encoding/base64",
-	"big.Int":                                 "math/big",
-	"big.MaxBase":                             "math/big",
-	"big.NewInt":                              "math/big",
-	"big.NewRat":                              "math/big",
-	"big.Rat":                                 "math/big",
-	"big.Word":                                "math/big",
-	"binary.BigEndian":                        "encoding/binary",
-	"binary.ByteOrder":                        "encoding/binary",
-	"binary.LittleEndian":                     "encoding/binary",
-	"binary.MaxVarintLen16":                   "encoding/binary",
-	"binary.MaxVarintLen32":                   "encoding/binary",
-	"binary.MaxVarintLen64":                   "encoding/binary",
-	"binary.PutUvarint":                       "encoding/binary",
-	"binary.PutVarint":                        "encoding/binary",
-	"binary.Read":                             "encoding/binary",
-	"binary.ReadUvarint":                      "encoding/binary",
-	"binary.ReadVarint":                       "encoding/binary",
-	"binary.Size":                             "encoding/binary",
-	"binary.Uvarint":                          "encoding/binary",
-	"binary.Varint":                           "encoding/binary",
-	"binary.Write":                            "encoding/binary",
-	"bufio.ErrAdvanceTooFar":                  "bufio",
-	"bufio.ErrBufferFull":                     "bufio",
-	"bufio.ErrInvalidUnreadByte":              "bufio",
-	"bufio.ErrInvalidUnreadRune":              "bufio",
-	"bufio.ErrNegativeAdvance":                "bufio",
-	"bufio.ErrNegativeCount":                  "bufio",
-	"bufio.ErrTooLong":                        "bufio",
-	"bufio.MaxScanTokenSize":                  "bufio",
-	"bufio.NewReadWriter":                     "bufio",
-	"bufio.NewReader":                         "bufio",
-	"bufio.NewReaderSize":                     "bufio",
-	"bufio.NewScanner":                        "bufio",
-	"bufio.NewWriter":                         "bufio",
-	"bufio.NewWriterSize":                     "bufio",
-	"bufio.ReadWriter":                        "bufio",
-	"bufio.Reader":                            "bufio",
-	"bufio.ScanBytes":                         "bufio",
-	"bufio.ScanLines":                         "bufio",
-	"bufio.ScanRunes":                         "bufio",
-	"bufio.ScanWords":                         "bufio",
-	"bufio.Scanner":                           "bufio",
-	"bufio.SplitFunc":                         "bufio",
-	"bufio.Writer":                            "bufio",
-	"build.AllowBinary":                       "go/build",
-	"build.ArchChar":                          "go/build",
-	"build.Context":                           "go/build",
-	"build.Default":                           "go/build",
-	"build.FindOnly":                          "go/build",
-	"build.Import":                            "go/build",
-	"build.ImportDir":                         "go/build",
-	"build.ImportMode":                        "go/build",
-	"build.IsLocalImport":                     "go/build",
-	"build.NoGoError":                         "go/build",
-	"build.Package":                           "go/build",
-	"build.ToolDir":                           "go/build",
-	"bytes.Buffer":                            "bytes",
-	"bytes.Compare":                           "bytes",
-	"bytes.Contains":                          "bytes",
-	"bytes.Count":                             "bytes",
-	"bytes.Equal":                             "bytes",
-	"bytes.EqualFold":                         "bytes",
-	"bytes.ErrTooLarge":                       "bytes",
-	"bytes.Fields":                            "bytes",
-	"bytes.FieldsFunc":                        "bytes",
-	"bytes.HasPrefix":                         "bytes",
-	"bytes.HasSuffix":                         "bytes",
-	"bytes.Index":                             "bytes",
-	"bytes.IndexAny":                          "bytes",
-	"bytes.IndexByte":                         "bytes",
-	"bytes.IndexFunc":                         "bytes",
-	"bytes.IndexRune":                         "bytes",
-	"bytes.Join":                              "bytes",
-	"bytes.LastIndex":                         "bytes",
-	"bytes.LastIndexAny":                      "bytes",
-	"bytes.LastIndexFunc":                     "bytes",
-	"bytes.Map":                               "bytes",
-	"bytes.MinRead":                           "bytes",
-	"bytes.NewBuffer":                         "bytes",
-	"bytes.NewBufferString":                   "bytes",
-	"bytes.NewReader":                         "bytes",
-	"bytes.Reader":                            "bytes",
-	"bytes.Repeat":                            "bytes",
-	"bytes.Replace":                           "bytes",
-	"bytes.Runes":                             "bytes",
-	"bytes.Split":                             "bytes",
-	"bytes.SplitAfter":                        "bytes",
-	"bytes.SplitAfterN":                       "bytes",
-	"bytes.SplitN":                            "bytes",
-	"bytes.Title":                             "bytes",
-	"bytes.ToLower":                           "bytes",
-	"bytes.ToLowerSpecial":                    "bytes",
-	"bytes.ToTitle":                           "bytes",
-	"bytes.ToTitleSpecial":                    "bytes",
-	"bytes.ToUpper":                           "bytes",
-	"bytes.ToUpperSpecial":                    "bytes",
-	"bytes.Trim":                              "bytes",
-	"bytes.TrimFunc":                          "bytes",
-	"bytes.TrimLeft":                          "bytes",
-	"bytes.TrimLeftFunc":                      "bytes",
-	"bytes.TrimPrefix":                        "bytes",
-	"bytes.TrimRight":                         "bytes",
-	"bytes.TrimRightFunc":                     "bytes",
-	"bytes.TrimSpace":                         "bytes",
-	"bytes.TrimSuffix":                        "bytes",
-	"bzip2.NewReader":                         "compress/bzip2",
-	"bzip2.StructuralError":                   "compress/bzip2",
-	"cgi.Handler":                             "net/http/cgi",
-	"cgi.Request":                             "net/http/cgi",
-	"cgi.RequestFromMap":                      "net/http/cgi",
-	"cgi.Serve":                               "net/http/cgi",
-	"cipher.AEAD":                             "crypto/cipher",
-	"cipher.Block":                            "crypto/cipher",
-	"cipher.BlockMode":                        "crypto/cipher",
-	"cipher.NewCBCDecrypter":                  "crypto/cipher",
-	"cipher.NewCBCEncrypter":                  "crypto/cipher",
-	"cipher.NewCFBDecrypter":                  "crypto/cipher",
-	"cipher.NewCFBEncrypter":                  "crypto/cipher",
-	"cipher.NewCTR":                           "crypto/cipher",
-	"cipher.NewGCM":                           "crypto/cipher",
-	"cipher.NewOFB":                           "crypto/cipher",
-	"cipher.Stream":                           "crypto/cipher",
-	"cipher.StreamReader":                     "crypto/cipher",
-	"cipher.StreamWriter":                     "crypto/cipher",
-	"cmplx.Abs":                               "math/cmplx",
-	"cmplx.Acos":                              "math/cmplx",
-	"cmplx.Acosh":                             "math/cmplx",
-	"cmplx.Asin":                              "math/cmplx",
-	"cmplx.Asinh":                             "math/cmplx",
-	"cmplx.Atan":                              "math/cmplx",
-	"cmplx.Atanh":                             "math/cmplx",
-	"cmplx.Conj":                              "math/cmplx",
-	"cmplx.Cos":                               "math/cmplx",
-	"cmplx.Cosh":                              "math/cmplx",
-	"cmplx.Cot":                               "math/cmplx",
-	"cmplx.Exp":                               "math/cmplx",
-	"cmplx.Inf":                               "math/cmplx",
-	"cmplx.IsInf":                             "math/cmplx",
-	"cmplx.IsNaN":                             "math/cmplx",
-	"cmplx.Log":                               "math/cmplx",
-	"cmplx.Log10":                             "math/cmplx",
-	"cmplx.NaN":                               "math/cmplx",
-	"cmplx.Phase":                             "math/cmplx",
-	"cmplx.Polar":                             "math/cmplx",
-	"cmplx.Pow":                               "math/cmplx",
-	"cmplx.Rect":                              "math/cmplx",
-	"cmplx.Sin":                               "math/cmplx",
-	"cmplx.Sinh":                              "math/cmplx",
-	"cmplx.Sqrt":                              "math/cmplx",
-	"cmplx.Tan":                               "math/cmplx",
-	"cmplx.Tanh":                              "math/cmplx",
-	"color.Alpha":                             "image/color",
-	"color.Alpha16":                           "image/color",
-	"color.Alpha16Model":                      "image/color",
-	"color.AlphaModel":                        "image/color",
-	"color.Black":                             "image/color",
-	"color.Color":                             "image/color",
-	"color.Gray":                              "image/color",
-	"color.Gray16":                            "image/color",
-	"color.Gray16Model":                       "image/color",
-	"color.GrayModel":                         "image/color",
-	"color.Model":                             "image/color",
-	"color.ModelFunc":                         "image/color",
-	"color.NRGBA":                             "image/color",
-	"color.NRGBA64":                           "image/color",
-	"color.NRGBA64Model":                      "image/color",
-	"color.NRGBAModel":                        "image/color",
-	"color.Opaque":                            "image/color",
-	"color.Palette":                           "image/color",
-	"color.RGBA":                              "image/color",
-	"color.RGBA64":                            "image/color",
-	"color.RGBA64Model":                       "image/color",
-	"color.RGBAModel":                         "image/color",
-	"color.RGBToYCbCr":                        "image/color",
-	"color.Transparent":                       "image/color",
-	"color.White":                             "image/color",
-	"color.YCbCr":                             "image/color",
-	"color.YCbCrModel":                        "image/color",
-	"color.YCbCrToRGB":                        "image/color",
-	"cookiejar.Jar":                           "net/http/cookiejar",
-	"cookiejar.New":                           "net/http/cookiejar",
-	"cookiejar.Options":                       "net/http/cookiejar",
-	"cookiejar.PublicSuffixList":              "net/http/cookiejar",
-	"crc32.Castagnoli":                        "hash/crc32",
-	"crc32.Checksum":                          "hash/crc32",
-	"crc32.ChecksumIEEE":                      "hash/crc32",
-	"crc32.IEEE":                              "hash/crc32",
-	"crc32.IEEETable":                         "hash/crc32",
-	"crc32.Koopman":                           "hash/crc32",
-	"crc32.MakeTable":                         "hash/crc32",
-	"crc32.New":                               "hash/crc32",
-	"crc32.NewIEEE":                           "hash/crc32",
-	"crc32.Size":                              "hash/crc32",
-	"crc32.Table":                             "hash/crc32",
-	"crc32.Update":                            "hash/crc32",
-	"crc64.Checksum":                          "hash/crc64",
-	"crc64.ECMA":                              "hash/crc64",
-	"crc64.ISO":                               "hash/crc64",
-	"crc64.MakeTable":                         "hash/crc64",
-	"crc64.New":                               "hash/crc64",
-	"crc64.Size":                              "hash/crc64",
-	"crc64.Table":                             "hash/crc64",
-	"crc64.Update":                            "hash/crc64",
-	"crypto.Hash":                             "crypto",
-	"crypto.MD4":                              "crypto",
-	"crypto.MD5":                              "crypto",
-	"crypto.MD5SHA1":                          "crypto",
-	"crypto.PrivateKey":                       "crypto",
-	"crypto.PublicKey":                        "crypto",
-	"crypto.RIPEMD160":                        "crypto",
-	"crypto.RegisterHash":                     "crypto",
-	"crypto.SHA1":                             "crypto",
-	"crypto.SHA224":                           "crypto",
-	"crypto.SHA256":                           "crypto",
-	"crypto.SHA384":                           "crypto",
-	"crypto.SHA512":                           "crypto",
-	"csv.ErrBareQuote":                        "encoding/csv",
-	"csv.ErrFieldCount":                       "encoding/csv",
-	"csv.ErrQuote":                            "encoding/csv",
-	"csv.ErrTrailingComma":                    "encoding/csv",
-	"csv.NewReader":                           "encoding/csv",
-	"csv.NewWriter":                           "encoding/csv",
-	"csv.ParseError":                          "encoding/csv",
-	"csv.Reader":                              "encoding/csv",
-	"csv.Writer":                              "encoding/csv",
-	"debug.FreeOSMemory":                      "runtime/debug",
-	"debug.GCStats":                           "runtime/debug",
-	"debug.PrintStack":                        "runtime/debug",
-	"debug.ReadGCStats":                       "runtime/debug",
-	"debug.SetGCPercent":                      "runtime/debug",
-	"debug.SetMaxStack":                       "runtime/debug",
-	"debug.SetMaxThreads":                     "runtime/debug",
-	"debug.Stack":                             "runtime/debug",
-	"des.BlockSize":                           "crypto/des",
-	"des.KeySizeError":                        "crypto/des",
-	"des.NewCipher":                           "crypto/des",
-	"des.NewTripleDESCipher":                  "crypto/des",
-	"doc.AllDecls":                            "go/doc",
-	"doc.AllMethods":                          "go/doc",
-	"doc.Example":                             "go/doc",
-	"doc.Examples":                            "go/doc",
-	"doc.Filter":                              "go/doc",
-	"doc.Func":                                "go/doc",
-	"doc.IllegalPrefixes":                     "go/doc",
-	"doc.Mode":                                "go/doc",
-	"doc.New":                                 "go/doc",
-	"doc.Note":                                "go/doc",
-	"doc.Package":                             "go/doc",
-	"doc.Synopsis":                            "go/doc",
-	"doc.ToHTML":                              "go/doc",
-	"doc.ToText":                              "go/doc",
-	"doc.Type":                                "go/doc",
-	"doc.Value":                               "go/doc",
-	"draw.Draw":                               "image/draw",
-	"draw.DrawMask":                           "image/draw",
-	"draw.Drawer":                             "image/draw",
-	"draw.FloydSteinberg":                     "image/draw",
-	"draw.Image":                              "image/draw",
-	"draw.Op":                                 "image/draw",
-	"draw.Over":                               "image/draw",
-	"draw.Quantizer":                          "image/draw",
-	"draw.Src":                                "image/draw",
-	"driver.Bool":                             "database/sql/driver",
-	"driver.ColumnConverter":                  "database/sql/driver",
-	"driver.Conn":                             "database/sql/driver",
-	"driver.DefaultParameterConverter":        "database/sql/driver",
-	"driver.Driver":                           "database/sql/driver",
-	"driver.ErrBadConn":                       "database/sql/driver",
-	"driver.ErrSkip":                          "database/sql/driver",
-	"driver.Execer":                           "database/sql/driver",
-	"driver.Int32":                            "database/sql/driver",
-	"driver.IsScanValue":                      "database/sql/driver",
-	"driver.IsValue":                          "database/sql/driver",
-	"driver.NotNull":                          "database/sql/driver",
-	"driver.Null":                             "database/sql/driver",
-	"driver.Queryer":                          "database/sql/driver",
-	"driver.Result":                           "database/sql/driver",
-	"driver.ResultNoRows":                     "database/sql/driver",
-	"driver.Rows":                             "database/sql/driver",
-	"driver.RowsAffected":                     "database/sql/driver",
-	"driver.Stmt":                             "database/sql/driver",
-	"driver.String":                           "database/sql/driver",
-	"driver.Tx":                               "database/sql/driver",
-	"driver.Value":                            "database/sql/driver",
-	"driver.ValueConverter":                   "database/sql/driver",
-	"driver.Valuer":                           "database/sql/driver",
-	"dsa.ErrInvalidPublicKey":                 "crypto/dsa",
-	"dsa.GenerateKey":                         "crypto/dsa",
-	"dsa.GenerateParameters":                  "crypto/dsa",
-	"dsa.L1024N160":                           "crypto/dsa",
-	"dsa.L2048N224":                           "crypto/dsa",
-	"dsa.L2048N256":                           "crypto/dsa",
-	"dsa.L3072N256":                           "crypto/dsa",
-	"dsa.ParameterSizes":                      "crypto/dsa",
-	"dsa.Parameters":                          "crypto/dsa",
-	"dsa.PrivateKey":                          "crypto/dsa",
-	"dsa.PublicKey":                           "crypto/dsa",
-	"dsa.Sign":                                "crypto/dsa",
-	"dsa.Verify":                              "crypto/dsa",
-	"dwarf.AddrType":                          "debug/dwarf",
-	"dwarf.ArrayType":                         "debug/dwarf",
-	"dwarf.Attr":                              "debug/dwarf",
-	"dwarf.AttrAbstractOrigin":                "debug/dwarf",
-	"dwarf.AttrAccessibility":                 "debug/dwarf",
-	"dwarf.AttrAddrClass":                     "debug/dwarf",
-	"dwarf.AttrAllocated":                     "debug/dwarf",
-	"dwarf.AttrArtificial":                    "debug/dwarf",
-	"dwarf.AttrAssociated":                    "debug/dwarf",
-	"dwarf.AttrBaseTypes":                     "debug/dwarf",
-	"dwarf.AttrBitOffset":                     "debug/dwarf",
-	"dwarf.AttrBitSize":                       "debug/dwarf",
-	"dwarf.AttrByteSize":                      "debug/dwarf",
-	"dwarf.AttrCallColumn":                    "debug/dwarf",
-	"dwarf.AttrCallFile":                      "debug/dwarf",
-	"dwarf.AttrCallLine":                      "debug/dwarf",
-	"dwarf.AttrCalling":                       "debug/dwarf",
-	"dwarf.AttrCommonRef":                     "debug/dwarf",
-	"dwarf.AttrCompDir":                       "debug/dwarf",
-	"dwarf.AttrConstValue":                    "debug/dwarf",
-	"dwarf.AttrContainingType":                "debug/dwarf",
-	"dwarf.AttrCount":                         "debug/dwarf",
-	"dwarf.AttrDataLocation":                  "debug/dwarf",
-	"dwarf.AttrDataMemberLoc":                 "debug/dwarf",
-	"dwarf.AttrDeclColumn":                    "debug/dwarf",
-	"dwarf.AttrDeclFile":                      "debug/dwarf",
-	"dwarf.AttrDeclLine":                      "debug/dwarf",
-	"dwarf.AttrDeclaration":                   "debug/dwarf",
-	"dwarf.AttrDefaultValue":                  "debug/dwarf",
-	"dwarf.AttrDescription":                   "debug/dwarf",
-	"dwarf.AttrDiscr":                         "debug/dwarf",
-	"dwarf.AttrDiscrList":                     "debug/dwarf",
-	"dwarf.AttrDiscrValue":                    "debug/dwarf",
-	"dwarf.AttrEncoding":                      "debug/dwarf",
-	"dwarf.AttrEntrypc":                       "debug/dwarf",
-	"dwarf.AttrExtension":                     "debug/dwarf",
-	"dwarf.AttrExternal":                      "debug/dwarf",
-	"dwarf.AttrFrameBase":                     "debug/dwarf",
-	"dwarf.AttrFriend":                        "debug/dwarf",
-	"dwarf.AttrHighpc":                        "debug/dwarf",
-	"dwarf.AttrIdentifierCase":                "debug/dwarf",
-	"dwarf.AttrImport":                        "debug/dwarf",
-	"dwarf.AttrInline":                        "debug/dwarf",
-	"dwarf.AttrIsOptional":                    "debug/dwarf",
-	"dwarf.AttrLanguage":                      "debug/dwarf",
-	"dwarf.AttrLocation":                      "debug/dwarf",
-	"dwarf.AttrLowerBound":                    "debug/dwarf",
-	"dwarf.AttrLowpc":                         "debug/dwarf",
-	"dwarf.AttrMacroInfo":                     "debug/dwarf",
-	"dwarf.AttrName":                          "debug/dwarf",
-	"dwarf.AttrNamelistItem":                  "debug/dwarf",
-	"dwarf.AttrOrdering":                      "debug/dwarf",
-	"dwarf.AttrPriority":                      "debug/dwarf",
-	"dwarf.AttrProducer":                      "debug/dwarf",
-	"dwarf.AttrPrototyped":                    "debug/dwarf",
-	"dwarf.AttrRanges":                        "debug/dwarf",
-	"dwarf.AttrReturnAddr":                    "debug/dwarf",
-	"dwarf.AttrSegment":                       "debug/dwarf",
-	"dwarf.AttrSibling":                       "debug/dwarf",
-	"dwarf.AttrSpecification":                 "debug/dwarf",
-	"dwarf.AttrStartScope":                    "debug/dwarf",
-	"dwarf.AttrStaticLink":                    "debug/dwarf",
-	"dwarf.AttrStmtList":                      "debug/dwarf",
-	"dwarf.AttrStride":                        "debug/dwarf",
-	"dwarf.AttrStrideSize":                    "debug/dwarf",
-	"dwarf.AttrStringLength":                  "debug/dwarf",
-	"dwarf.AttrTrampoline":                    "debug/dwarf",
-	"dwarf.AttrType":                          "debug/dwarf",
-	"dwarf.AttrUpperBound":                    "debug/dwarf",
-	"dwarf.AttrUseLocation":                   "debug/dwarf",
-	"dwarf.AttrUseUTF8":                       "debug/dwarf",
-	"dwarf.AttrVarParam":                      "debug/dwarf",
-	"dwarf.AttrVirtuality":                    "debug/dwarf",
-	"dwarf.AttrVisibility":                    "debug/dwarf",
-	"dwarf.AttrVtableElemLoc":                 "debug/dwarf",
-	"dwarf.BasicType":                         "debug/dwarf",
-	"dwarf.BoolType":                          "debug/dwarf",
-	"dwarf.CharType":                          "debug/dwarf",
-	"dwarf.CommonType":                        "debug/dwarf",
-	"dwarf.ComplexType":                       "debug/dwarf",
-	"dwarf.Data":                              "debug/dwarf",
-	"dwarf.DecodeError":                       "debug/dwarf",
-	"dwarf.DotDotDotType":                     "debug/dwarf",
-	"dwarf.Entry":                             "debug/dwarf",
-	"dwarf.EnumType":                          "debug/dwarf",
-	"dwarf.EnumValue":                         "debug/dwarf",
-	"dwarf.Field":                             "debug/dwarf",
-	"dwarf.FloatType":                         "debug/dwarf",
-	"dwarf.FuncType":                          "debug/dwarf",
-	"dwarf.IntType":                           "debug/dwarf",
-	"dwarf.New":                               "debug/dwarf",
-	"dwarf.Offset":                            "debug/dwarf",
-	"dwarf.PtrType":                           "debug/dwarf",
-	"dwarf.QualType":                          "debug/dwarf",
-	"dwarf.Reader":                            "debug/dwarf",
-	"dwarf.StructField":                       "debug/dwarf",
-	"dwarf.StructType":                        "debug/dwarf",
-	"dwarf.Tag":                               "debug/dwarf",
-	"dwarf.TagAccessDeclaration":              "debug/dwarf",
-	"dwarf.TagArrayType":                      "debug/dwarf",
-	"dwarf.TagBaseType":                       "debug/dwarf",
-	"dwarf.TagCatchDwarfBlock":                "debug/dwarf",
-	"dwarf.TagClassType":                      "debug/dwarf",
-	"dwarf.TagCommonDwarfBlock":               "debug/dwarf",
-	"dwarf.TagCommonInclusion":                "debug/dwarf",
-	"dwarf.TagCompileUnit":                    "debug/dwarf",
-	"dwarf.TagConstType":                      "debug/dwarf",
-	"dwarf.TagConstant":                       "debug/dwarf",
-	"dwarf.TagDwarfProcedure":                 "debug/dwarf",
-	"dwarf.TagEntryPoint":                     "debug/dwarf",
-	"dwarf.TagEnumerationType":                "debug/dwarf",
-	"dwarf.TagEnumerator":                     "debug/dwarf",
-	"dwarf.TagFileType":                       "debug/dwarf",
-	"dwarf.TagFormalParameter":                "debug/dwarf",
-	"dwarf.TagFriend":                         "debug/dwarf",
-	"dwarf.TagImportedDeclaration":            "debug/dwarf",
-	"dwarf.TagImportedModule":                 "debug/dwarf",
-	"dwarf.TagImportedUnit":                   "debug/dwarf",
-	"dwarf.TagInheritance":                    "debug/dwarf",
-	"dwarf.TagInlinedSubroutine":              "debug/dwarf",
-	"dwarf.TagInterfaceType":                  "debug/dwarf",
-	"dwarf.TagLabel":                          "debug/dwarf",
-	"dwarf.TagLexDwarfBlock":                  "debug/dwarf",
-	"dwarf.TagMember":                         "debug/dwarf",
-	"dwarf.TagModule":                         "debug/dwarf",
-	"dwarf.TagMutableType":                    "debug/dwarf",
-	"dwarf.TagNamelist":                       "debug/dwarf",
-	"dwarf.TagNamelistItem":                   "debug/dwarf",
-	"dwarf.TagNamespace":                      "debug/dwarf",
-	"dwarf.TagPackedType":                     "debug/dwarf",
-	"dwarf.TagPartialUnit":                    "debug/dwarf",
-	"dwarf.TagPointerType":                    "debug/dwarf",
-	"dwarf.TagPtrToMemberType":                "debug/dwarf",
-	"dwarf.TagReferenceType":                  "debug/dwarf",
-	"dwarf.TagRestrictType":                   "debug/dwarf",
-	"dwarf.TagSetType":                        "debug/dwarf",
-	"dwarf.TagStringType":                     "debug/dwarf",
-	"dwarf.TagStructType":                     "debug/dwarf",
-	"dwarf.TagSubprogram":                     "debug/dwarf",
-	"dwarf.TagSubrangeType":                   "debug/dwarf",
-	"dwarf.TagSubroutineType":                 "debug/dwarf",
-	"dwarf.TagTemplateTypeParameter":          "debug/dwarf",
-	"dwarf.TagTemplateValueParameter":         "debug/dwarf",
-	"dwarf.TagThrownType":                     "debug/dwarf",
-	"dwarf.TagTryDwarfBlock":                  "debug/dwarf",
-	"dwarf.TagTypedef":                        "debug/dwarf",
-	"dwarf.TagUnionType":                      "debug/dwarf",
-	"dwarf.TagUnspecifiedParameters":          "debug/dwarf",
-	"dwarf.TagUnspecifiedType":                "debug/dwarf",
-	"dwarf.TagVariable":                       "debug/dwarf",
-	"dwarf.TagVariant":                        "debug/dwarf",
-	"dwarf.TagVariantPart":                    "debug/dwarf",
-	"dwarf.TagVolatileType":                   "debug/dwarf",
-	"dwarf.TagWithStmt":                       "debug/dwarf",
-	"dwarf.Type":                              "debug/dwarf",
-	"dwarf.TypedefType":                       "debug/dwarf",
-	"dwarf.UcharType":                         "debug/dwarf",
-	"dwarf.UintType":                          "debug/dwarf",
-	"dwarf.VoidType":                          "debug/dwarf",
-	"ecdsa.GenerateKey":                       "crypto/ecdsa",
-	"ecdsa.PrivateKey":                        "crypto/ecdsa",
-	"ecdsa.PublicKey":                         "crypto/ecdsa",
-	"ecdsa.Sign":                              "crypto/ecdsa",
-	"ecdsa.Verify":                            "crypto/ecdsa",
-	"elf.ARM_MAGIC_TRAMP_NUMBER":              "debug/elf",
-	"elf.Class":                               "debug/elf",
-	"elf.DF_BIND_NOW":                         "debug/elf",
-	"elf.DF_ORIGIN":                           "debug/elf",
-	"elf.DF_STATIC_TLS":                       "debug/elf",
-	"elf.DF_SYMBOLIC":                         "debug/elf",
-	"elf.DF_TEXTREL":                          "debug/elf",
-	"elf.DT_BIND_NOW":                         "debug/elf",
-	"elf.DT_DEBUG":                            "debug/elf",
-	"elf.DT_ENCODING":                         "debug/elf",
-	"elf.DT_FINI":                             "debug/elf",
-	"elf.DT_FINI_ARRAY":                       "debug/elf",
-	"elf.DT_FINI_ARRAYSZ":                     "debug/elf",
-	"elf.DT_FLAGS":                            "debug/elf",
-	"elf.DT_HASH":                             "debug/elf",
-	"elf.DT_HIOS":                             "debug/elf",
-	"elf.DT_HIPROC":                           "debug/elf",
-	"elf.DT_INIT":                             "debug/elf",
-	"elf.DT_INIT_ARRAY":                       "debug/elf",
-	"elf.DT_INIT_ARRAYSZ":                     "debug/elf",
-	"elf.DT_JMPREL":                           "debug/elf",
-	"elf.DT_LOOS":                             "debug/elf",
-	"elf.DT_LOPROC":                           "debug/elf",
-	"elf.DT_NEEDED":                           "debug/elf",
-	"elf.DT_NULL":                             "debug/elf",
-	"elf.DT_PLTGOT":                           "debug/elf",
-	"elf.DT_PLTREL":                           "debug/elf",
-	"elf.DT_PLTRELSZ":                         "debug/elf",
-	"elf.DT_PREINIT_ARRAY":                    "debug/elf",
-	"elf.DT_PREINIT_ARRAYSZ":                  "debug/elf",
-	"elf.DT_REL":                              "debug/elf",
-	"elf.DT_RELA":                             "debug/elf",
-	"elf.DT_RELAENT":                          "debug/elf",
-	"elf.DT_RELASZ":                           "debug/elf",
-	"elf.DT_RELENT":                           "debug/elf",
-	"elf.DT_RELSZ":                            "debug/elf",
-	"elf.DT_RPATH":                            "debug/elf",
-	"elf.DT_RUNPATH":                          "debug/elf",
-	"elf.DT_SONAME":                           "debug/elf",
-	"elf.DT_STRSZ":                            "debug/elf",
-	"elf.DT_STRTAB":                           "debug/elf",
-	"elf.DT_SYMBOLIC":                         "debug/elf",
-	"elf.DT_SYMENT":                           "debug/elf",
-	"elf.DT_SYMTAB":                           "debug/elf",
-	"elf.DT_TEXTREL":                          "debug/elf",
-	"elf.DT_VERNEED":                          "debug/elf",
-	"elf.DT_VERNEEDNUM":                       "debug/elf",
-	"elf.DT_VERSYM":                           "debug/elf",
-	"elf.Data":                                "debug/elf",
-	"elf.Dyn32":                               "debug/elf",
-	"elf.Dyn64":                               "debug/elf",
-	"elf.DynFlag":                             "debug/elf",
-	"elf.DynTag":                              "debug/elf",
-	"elf.EI_ABIVERSION":                       "debug/elf",
-	"elf.EI_CLASS":                            "debug/elf",
-	"elf.EI_DATA":                             "debug/elf",
-	"elf.EI_NIDENT":                           "debug/elf",
-	"elf.EI_OSABI":                            "debug/elf",
-	"elf.EI_PAD":                              "debug/elf",
-	"elf.EI_VERSION":                          "debug/elf",
-	"elf.ELFCLASS32":                          "debug/elf",
-	"elf.ELFCLASS64":                          "debug/elf",
-	"elf.ELFCLASSNONE":                        "debug/elf",
-	"elf.ELFDATA2LSB":                         "debug/elf",
-	"elf.ELFDATA2MSB":                         "debug/elf",
-	"elf.ELFDATANONE":                         "debug/elf",
-	"elf.ELFMAG":                              "debug/elf",
-	"elf.ELFOSABI_86OPEN":                     "debug/elf",
-	"elf.ELFOSABI_AIX":                        "debug/elf",
-	"elf.ELFOSABI_ARM":                        "debug/elf",
-	"elf.ELFOSABI_FREEBSD":                    "debug/elf",
-	"elf.ELFOSABI_HPUX":                       "debug/elf",
-	"elf.ELFOSABI_HURD":                       "debug/elf",
-	"elf.ELFOSABI_IRIX":                       "debug/elf",
-	"elf.ELFOSABI_LINUX":                      "debug/elf",
-	"elf.ELFOSABI_MODESTO":                    "debug/elf",
-	"elf.ELFOSABI_NETBSD":                     "debug/elf",
-	"elf.ELFOSABI_NONE":                       "debug/elf",
-	"elf.ELFOSABI_NSK":                        "debug/elf",
-	"elf.ELFOSABI_OPENBSD":                    "debug/elf",
-	"elf.ELFOSABI_OPENVMS":                    "debug/elf",
-	"elf.ELFOSABI_SOLARIS":                    "debug/elf",
-	"elf.ELFOSABI_STANDALONE":                 "debug/elf",
-	"elf.ELFOSABI_TRU64":                      "debug/elf",
-	"elf.EM_386":                              "debug/elf",
-	"elf.EM_486":                              "debug/elf",
-	"elf.EM_68HC12":                           "debug/elf",
-	"elf.EM_68K":                              "debug/elf",
-	"elf.EM_860":                              "debug/elf",
-	"elf.EM_88K":                              "debug/elf",
-	"elf.EM_960":                              "debug/elf",
-	"elf.EM_ALPHA":                            "debug/elf",
-	"elf.EM_ALPHA_STD":                        "debug/elf",
-	"elf.EM_ARC":                              "debug/elf",
-	"elf.EM_ARM":                              "debug/elf",
-	"elf.EM_COLDFIRE":                         "debug/elf",
-	"elf.EM_FR20":                             "debug/elf",
-	"elf.EM_H8S":                              "debug/elf",
-	"elf.EM_H8_300":                           "debug/elf",
-	"elf.EM_H8_300H":                          "debug/elf",
-	"elf.EM_H8_500":                           "debug/elf",
-	"elf.EM_IA_64":                            "debug/elf",
-	"elf.EM_M32":                              "debug/elf",
-	"elf.EM_ME16":                             "debug/elf",
-	"elf.EM_MIPS":                             "debug/elf",
-	"elf.EM_MIPS_RS3_LE":                      "debug/elf",
-	"elf.EM_MIPS_RS4_BE":                      "debug/elf",
-	"elf.EM_MIPS_X":                           "debug/elf",
-	"elf.EM_MMA":                              "debug/elf",
-	"elf.EM_NCPU":                             "debug/elf",
-	"elf.EM_NDR1":                             "debug/elf",
-	"elf.EM_NONE":                             "debug/elf",
-	"elf.EM_PARISC":                           "debug/elf",
-	"elf.EM_PCP":                              "debug/elf",
-	"elf.EM_PPC":                              "debug/elf",
-	"elf.EM_PPC64":                            "debug/elf",
-	"elf.EM_RCE":                              "debug/elf",
-	"elf.EM_RH32":                             "debug/elf",
-	"elf.EM_S370":                             "debug/elf",
-	"elf.EM_S390":                             "debug/elf",
-	"elf.EM_SH":                               "debug/elf",
-	"elf.EM_SPARC":                            "debug/elf",
-	"elf.EM_SPARC32PLUS":                      "debug/elf",
-	"elf.EM_SPARCV9":                          "debug/elf",
-	"elf.EM_ST100":                            "debug/elf",
-	"elf.EM_STARCORE":                         "debug/elf",
-	"elf.EM_TINYJ":                            "debug/elf",
-	"elf.EM_TRICORE":                          "debug/elf",
-	"elf.EM_V800":                             "debug/elf",
-	"elf.EM_VPP500":                           "debug/elf",
-	"elf.EM_X86_64":                           "debug/elf",
-	"elf.ET_CORE":                             "debug/elf",
-	"elf.ET_DYN":                              "debug/elf",
-	"elf.ET_EXEC":                             "debug/elf",
-	"elf.ET_HIOS":                             "debug/elf",
-	"elf.ET_HIPROC":                           "debug/elf",
-	"elf.ET_LOOS":                             "debug/elf",
-	"elf.ET_LOPROC":                           "debug/elf",
-	"elf.ET_NONE":                             "debug/elf",
-	"elf.ET_REL":                              "debug/elf",
-	"elf.EV_CURRENT":                          "debug/elf",
-	"elf.EV_NONE":                             "debug/elf",
-	"elf.File":                                "debug/elf",
-	"elf.FileHeader":                          "debug/elf",
-	"elf.FormatError":                         "debug/elf",
-	"elf.Header32":                            "debug/elf",
-	"elf.Header64":                            "debug/elf",
-	"elf.ImportedSymbol":                      "debug/elf",
-	"elf.Machine":                             "debug/elf",
-	"elf.NT_FPREGSET":                         "debug/elf",
-	"elf.NT_PRPSINFO":                         "debug/elf",
-	"elf.NT_PRSTATUS":                         "debug/elf",
-	"elf.NType":                               "debug/elf",
-	"elf.NewFile":                             "debug/elf",
-	"elf.OSABI":                               "debug/elf",
-	"elf.Open":                                "debug/elf",
-	"elf.PF_MASKOS":                           "debug/elf",
-	"elf.PF_MASKPROC":                         "debug/elf",
-	"elf.PF_R":                                "debug/elf",
-	"elf.PF_W":                                "debug/elf",
-	"elf.PF_X":                                "debug/elf",
-	"elf.PT_DYNAMIC":                          "debug/elf",
-	"elf.PT_HIOS":                             "debug/elf",
-	"elf.PT_HIPROC":                           "debug/elf",
-	"elf.PT_INTERP":                           "debug/elf",
-	"elf.PT_LOAD":                             "debug/elf",
-	"elf.PT_LOOS":                             "debug/elf",
-	"elf.PT_LOPROC":                           "debug/elf",
-	"elf.PT_NOTE":                             "debug/elf",
-	"elf.PT_NULL":                             "debug/elf",
-	"elf.PT_PHDR":                             "debug/elf",
-	"elf.PT_SHLIB":                            "debug/elf",
-	"elf.PT_TLS":                              "debug/elf",
-	"elf.Prog":                                "debug/elf",
-	"elf.Prog32":                              "debug/elf",
-	"elf.Prog64":                              "debug/elf",
-	"elf.ProgFlag":                            "debug/elf",
-	"elf.ProgHeader":                          "debug/elf",
-	"elf.ProgType":                            "debug/elf",
-	"elf.R_386":                               "debug/elf",
-	"elf.R_386_32":                            "debug/elf",
-	"elf.R_386_COPY":                          "debug/elf",
-	"elf.R_386_GLOB_DAT":                      "debug/elf",
-	"elf.R_386_GOT32":                         "debug/elf",
-	"elf.R_386_GOTOFF":                        "debug/elf",
-	"elf.R_386_GOTPC":                         "debug/elf",
-	"elf.R_386_JMP_SLOT":                      "debug/elf",
-	"elf.R_386_NONE":                          "debug/elf",
-	"elf.R_386_PC32":                          "debug/elf",
-	"elf.R_386_PLT32":                         "debug/elf",
-	"elf.R_386_RELATIVE":                      "debug/elf",
-	"elf.R_386_TLS_DTPMOD32":                  "debug/elf",
-	"elf.R_386_TLS_DTPOFF32":                  "debug/elf",
-	"elf.R_386_TLS_GD":                        "debug/elf",
-	"elf.R_386_TLS_GD_32":                     "debug/elf",
-	"elf.R_386_TLS_GD_CALL":                   "debug/elf",
-	"elf.R_386_TLS_GD_POP":                    "debug/elf",
-	"elf.R_386_TLS_GD_PUSH":                   "debug/elf",
-	"elf.R_386_TLS_GOTIE":                     "debug/elf",
-	"elf.R_386_TLS_IE":                        "debug/elf",
-	"elf.R_386_TLS_IE_32":                     "debug/elf",
-	"elf.R_386_TLS_LDM":                       "debug/elf",
-	"elf.R_386_TLS_LDM_32":                    "debug/elf",
-	"elf.R_386_TLS_LDM_CALL":                  "debug/elf",
-	"elf.R_386_TLS_LDM_POP":                   "debug/elf",
-	"elf.R_386_TLS_LDM_PUSH":                  "debug/elf",
-	"elf.R_386_TLS_LDO_32":                    "debug/elf",
-	"elf.R_386_TLS_LE":                        "debug/elf",
-	"elf.R_386_TLS_LE_32":                     "debug/elf",
-	"elf.R_386_TLS_TPOFF":                     "debug/elf",
-	"elf.R_386_TLS_TPOFF32":                   "debug/elf",
-	"elf.R_ALPHA":                             "debug/elf",
-	"elf.R_ALPHA_BRADDR":                      "debug/elf",
-	"elf.R_ALPHA_COPY":                        "debug/elf",
-	"elf.R_ALPHA_GLOB_DAT":                    "debug/elf",
-	"elf.R_ALPHA_GPDISP":                      "debug/elf",
-	"elf.R_ALPHA_GPREL32":                     "debug/elf",
-	"elf.R_ALPHA_GPRELHIGH":                   "debug/elf",
-	"elf.R_ALPHA_GPRELLOW":                    "debug/elf",
-	"elf.R_ALPHA_GPVALUE":                     "debug/elf",
-	"elf.R_ALPHA_HINT":                        "debug/elf",
-	"elf.R_ALPHA_IMMED_BR_HI32":               "debug/elf",
-	"elf.R_ALPHA_IMMED_GP_16":                 "debug/elf",
-	"elf.R_ALPHA_IMMED_GP_HI32":               "debug/elf",
-	"elf.R_ALPHA_IMMED_LO32":                  "debug/elf",
-	"elf.R_ALPHA_IMMED_SCN_HI32":              "debug/elf",
-	"elf.R_ALPHA_JMP_SLOT":                    "debug/elf",
-	"elf.R_ALPHA_LITERAL":                     "debug/elf",
-	"elf.R_ALPHA_LITUSE":                      "debug/elf",
-	"elf.R_ALPHA_NONE":                        "debug/elf",
-	"elf.R_ALPHA_OP_PRSHIFT":                  "debug/elf",
-	"elf.R_ALPHA_OP_PSUB":                     "debug/elf",
-	"elf.R_ALPHA_OP_PUSH":                     "debug/elf",
-	"elf.R_ALPHA_OP_STORE":                    "debug/elf",
-	"elf.R_ALPHA_REFLONG":                     "debug/elf",
-	"elf.R_ALPHA_REFQUAD":                     "debug/elf",
-	"elf.R_ALPHA_RELATIVE":                    "debug/elf",
-	"elf.R_ALPHA_SREL16":                      "debug/elf",
-	"elf.R_ALPHA_SREL32":                      "debug/elf",
-	"elf.R_ALPHA_SREL64":                      "debug/elf",
-	"elf.R_ARM":                               "debug/elf",
-	"elf.R_ARM_ABS12":                         "debug/elf",
-	"elf.R_ARM_ABS16":                         "debug/elf",
-	"elf.R_ARM_ABS32":                         "debug/elf",
-	"elf.R_ARM_ABS8":                          "debug/elf",
-	"elf.R_ARM_AMP_VCALL9":                    "debug/elf",
-	"elf.R_ARM_COPY":                          "debug/elf",
-	"elf.R_ARM_GLOB_DAT":                      "debug/elf",
-	"elf.R_ARM_GNU_VTENTRY":                   "debug/elf",
-	"elf.R_ARM_GNU_VTINHERIT":                 "debug/elf",
-	"elf.R_ARM_GOT32":                         "debug/elf",
-	"elf.R_ARM_GOTOFF":                        "debug/elf",
-	"elf.R_ARM_GOTPC":                         "debug/elf",
-	"elf.R_ARM_JUMP_SLOT":                     "debug/elf",
-	"elf.R_ARM_NONE":                          "debug/elf",
-	"elf.R_ARM_PC13":                          "debug/elf",
-	"elf.R_ARM_PC24":                          "debug/elf",
-	"elf.R_ARM_PLT32":                         "debug/elf",
-	"elf.R_ARM_RABS32":                        "debug/elf",
-	"elf.R_ARM_RBASE":                         "debug/elf",
-	"elf.R_ARM_REL32":                         "debug/elf",
-	"elf.R_ARM_RELATIVE":                      "debug/elf",
-	"elf.R_ARM_RPC24":                         "debug/elf",
-	"elf.R_ARM_RREL32":                        "debug/elf",
-	"elf.R_ARM_RSBREL32":                      "debug/elf",
-	"elf.R_ARM_SBREL32":                       "debug/elf",
-	"elf.R_ARM_SWI24":                         "debug/elf",
-	"elf.R_ARM_THM_ABS5":                      "debug/elf",
-	"elf.R_ARM_THM_PC22":                      "debug/elf",
-	"elf.R_ARM_THM_PC8":                       "debug/elf",
-	"elf.R_ARM_THM_RPC22":                     "debug/elf",
-	"elf.R_ARM_THM_SWI8":                      "debug/elf",
-	"elf.R_ARM_THM_XPC22":                     "debug/elf",
-	"elf.R_ARM_XPC25":                         "debug/elf",
-	"elf.R_INFO":                              "debug/elf",
-	"elf.R_INFO32":                            "debug/elf",
-	"elf.R_PPC":                               "debug/elf",
-	"elf.R_PPC_ADDR14":                        "debug/elf",
-	"elf.R_PPC_ADDR14_BRNTAKEN":               "debug/elf",
-	"elf.R_PPC_ADDR14_BRTAKEN":                "debug/elf",
-	"elf.R_PPC_ADDR16":                        "debug/elf",
-	"elf.R_PPC_ADDR16_HA":                     "debug/elf",
-	"elf.R_PPC_ADDR16_HI":                     "debug/elf",
-	"elf.R_PPC_ADDR16_LO":                     "debug/elf",
-	"elf.R_PPC_ADDR24":                        "debug/elf",
-	"elf.R_PPC_ADDR32":                        "debug/elf",
-	"elf.R_PPC_COPY":                          "debug/elf",
-	"elf.R_PPC_DTPMOD32":                      "debug/elf",
-	"elf.R_PPC_DTPREL16":                      "debug/elf",
-	"elf.R_PPC_DTPREL16_HA":                   "debug/elf",
-	"elf.R_PPC_DTPREL16_HI":                   "debug/elf",
-	"elf.R_PPC_DTPREL16_LO":                   "debug/elf",
-	"elf.R_PPC_DTPREL32":                      "debug/elf",
-	"elf.R_PPC_EMB_BIT_FLD":                   "debug/elf",
-	"elf.R_PPC_EMB_MRKREF":                    "debug/elf",
-	"elf.R_PPC_EMB_NADDR16":                   "debug/elf",
-	"elf.R_PPC_EMB_NADDR16_HA":                "debug/elf",
-	"elf.R_PPC_EMB_NADDR16_HI":                "debug/elf",
-	"elf.R_PPC_EMB_NADDR16_LO":                "debug/elf",
-	"elf.R_PPC_EMB_NADDR32":                   "debug/elf",
-	"elf.R_PPC_EMB_RELSDA":                    "debug/elf",
-	"elf.R_PPC_EMB_RELSEC16":                  "debug/elf",
-	"elf.R_PPC_EMB_RELST_HA":                  "debug/elf",
-	"elf.R_PPC_EMB_RELST_HI":                  "debug/elf",
-	"elf.R_PPC_EMB_RELST_LO":                  "debug/elf",
-	"elf.R_PPC_EMB_SDA21":                     "debug/elf",
-	"elf.R_PPC_EMB_SDA2I16":                   "debug/elf",
-	"elf.R_PPC_EMB_SDA2REL":                   "debug/elf",
-	"elf.R_PPC_EMB_SDAI16":                    "debug/elf",
-	"elf.R_PPC_GLOB_DAT":                      "debug/elf",
-	"elf.R_PPC_GOT16":                         "debug/elf",
-	"elf.R_PPC_GOT16_HA":                      "debug/elf",
-	"elf.R_PPC_GOT16_HI":                      "debug/elf",
-	"elf.R_PPC_GOT16_LO":                      "debug/elf",
-	"elf.R_PPC_GOT_TLSGD16":                   "debug/elf",
-	"elf.R_PPC_GOT_TLSGD16_HA":                "debug/elf",
-	"elf.R_PPC_GOT_TLSGD16_HI":                "debug/elf",
-	"elf.R_PPC_GOT_TLSGD16_LO":                "debug/elf",
-	"elf.R_PPC_GOT_TLSLD16":                   "debug/elf",
-	"elf.R_PPC_GOT_TLSLD16_HA":                "debug/elf",
-	"elf.R_PPC_GOT_TLSLD16_HI":                "debug/elf",
-	"elf.R_PPC_GOT_TLSLD16_LO":                "debug/elf",
-	"elf.R_PPC_GOT_TPREL16":                   "debug/elf",
-	"elf.R_PPC_GOT_TPREL16_HA":                "debug/elf",
-	"elf.R_PPC_GOT_TPREL16_HI":                "debug/elf",
-	"elf.R_PPC_GOT_TPREL16_LO":                "debug/elf",
-	"elf.R_PPC_JMP_SLOT":                      "debug/elf",
-	"elf.R_PPC_LOCAL24PC":                     "debug/elf",
-	"elf.R_PPC_NONE":                          "debug/elf",
-	"elf.R_PPC_PLT16_HA":                      "debug/elf",
-	"elf.R_PPC_PLT16_HI":                      "debug/elf",
-	"elf.R_PPC_PLT16_LO":                      "debug/elf",
-	"elf.R_PPC_PLT32":                         "debug/elf",
-	"elf.R_PPC_PLTREL24":                      "debug/elf",
-	"elf.R_PPC_PLTREL32":                      "debug/elf",
-	"elf.R_PPC_REL14":                         "debug/elf",
-	"elf.R_PPC_REL14_BRNTAKEN":                "debug/elf",
-	"elf.R_PPC_REL14_BRTAKEN":                 "debug/elf",
-	"elf.R_PPC_REL24":                         "debug/elf",
-	"elf.R_PPC_REL32":                         "debug/elf",
-	"elf.R_PPC_RELATIVE":                      "debug/elf",
-	"elf.R_PPC_SDAREL16":                      "debug/elf",
-	"elf.R_PPC_SECTOFF":                       "debug/elf",
-	"elf.R_PPC_SECTOFF_HA":                    "debug/elf",
-	"elf.R_PPC_SECTOFF_HI":                    "debug/elf",
-	"elf.R_PPC_SECTOFF_LO":                    "debug/elf",
-	"elf.R_PPC_TLS":                           "debug/elf",
-	"elf.R_PPC_TPREL16":                       "debug/elf",
-	"elf.R_PPC_TPREL16_HA":                    "debug/elf",
-	"elf.R_PPC_TPREL16_HI":                    "debug/elf",
-	"elf.R_PPC_TPREL16_LO":                    "debug/elf",
-	"elf.R_PPC_TPREL32":                       "debug/elf",
-	"elf.R_PPC_UADDR16":                       "debug/elf",
-	"elf.R_PPC_UADDR32":                       "debug/elf",
-	"elf.R_SPARC":                             "debug/elf",
-	"elf.R_SPARC_10":                          "debug/elf",
-	"elf.R_SPARC_11":                          "debug/elf",
-	"elf.R_SPARC_13":                          "debug/elf",
-	"elf.R_SPARC_16":                          "debug/elf",
-	"elf.R_SPARC_22":                          "debug/elf",
-	"elf.R_SPARC_32":                          "debug/elf",
-	"elf.R_SPARC_5":                           "debug/elf",
-	"elf.R_SPARC_6":                           "debug/elf",
-	"elf.R_SPARC_64":                          "debug/elf",
-	"elf.R_SPARC_7":                           "debug/elf",
-	"elf.R_SPARC_8":                           "debug/elf",
-	"elf.R_SPARC_COPY":                        "debug/elf",
-	"elf.R_SPARC_DISP16":                      "debug/elf",
-	"elf.R_SPARC_DISP32":                      "debug/elf",
-	"elf.R_SPARC_DISP64":                      "debug/elf",
-	"elf.R_SPARC_DISP8":                       "debug/elf",
-	"elf.R_SPARC_GLOB_DAT":                    "debug/elf",
-	"elf.R_SPARC_GLOB_JMP":                    "debug/elf",
-	"elf.R_SPARC_GOT10":                       "debug/elf",
-	"elf.R_SPARC_GOT13":                       "debug/elf",
-	"elf.R_SPARC_GOT22":                       "debug/elf",
-	"elf.R_SPARC_H44":                         "debug/elf",
-	"elf.R_SPARC_HH22":                        "debug/elf",
-	"elf.R_SPARC_HI22":                        "debug/elf",
-	"elf.R_SPARC_HIPLT22":                     "debug/elf",
-	"elf.R_SPARC_HIX22":                       "debug/elf",
-	"elf.R_SPARC_HM10":                        "debug/elf",
-	"elf.R_SPARC_JMP_SLOT":                    "debug/elf",
-	"elf.R_SPARC_L44":                         "debug/elf",
-	"elf.R_SPARC_LM22":                        "debug/elf",
-	"elf.R_SPARC_LO10":                        "debug/elf",
-	"elf.R_SPARC_LOPLT10":                     "debug/elf",
-	"elf.R_SPARC_LOX10":                       "debug/elf",
-	"elf.R_SPARC_M44":                         "debug/elf",
-	"elf.R_SPARC_NONE":                        "debug/elf",
-	"elf.R_SPARC_OLO10":                       "debug/elf",
-	"elf.R_SPARC_PC10":                        "debug/elf",
-	"elf.R_SPARC_PC22":                        "debug/elf",
-	"elf.R_SPARC_PCPLT10":                     "debug/elf",
-	"elf.R_SPARC_PCPLT22":                     "debug/elf",
-	"elf.R_SPARC_PCPLT32":                     "debug/elf",
-	"elf.R_SPARC_PC_HH22":                     "debug/elf",
-	"elf.R_SPARC_PC_HM10":                     "debug/elf",
-	"elf.R_SPARC_PC_LM22":                     "debug/elf",
-	"elf.R_SPARC_PLT32":                       "debug/elf",
-	"elf.R_SPARC_PLT64":                       "debug/elf",
-	"elf.R_SPARC_REGISTER":                    "debug/elf",
-	"elf.R_SPARC_RELATIVE":                    "debug/elf",
-	"elf.R_SPARC_UA16":                        "debug/elf",
-	"elf.R_SPARC_UA32":                        "debug/elf",
-	"elf.R_SPARC_UA64":                        "debug/elf",
-	"elf.R_SPARC_WDISP16":                     "debug/elf",
-	"elf.R_SPARC_WDISP19":                     "debug/elf",
-	"elf.R_SPARC_WDISP22":                     "debug/elf",
-	"elf.R_SPARC_WDISP30":                     "debug/elf",
-	"elf.R_SPARC_WPLT30":                      "debug/elf",
-	"elf.R_SYM32":                             "debug/elf",
-	"elf.R_SYM64":                             "debug/elf",
-	"elf.R_TYPE32":                            "debug/elf",
-	"elf.R_TYPE64":                            "debug/elf",
-	"elf.R_X86_64":                            "debug/elf",
-	"elf.R_X86_64_16":                         "debug/elf",
-	"elf.R_X86_64_32":                         "debug/elf",
-	"elf.R_X86_64_32S":                        "debug/elf",
-	"elf.R_X86_64_64":                         "debug/elf",
-	"elf.R_X86_64_8":                          "debug/elf",
-	"elf.R_X86_64_COPY":                       "debug/elf",
-	"elf.R_X86_64_DTPMOD64":                   "debug/elf",
-	"elf.R_X86_64_DTPOFF32":                   "debug/elf",
-	"elf.R_X86_64_DTPOFF64":                   "debug/elf",
-	"elf.R_X86_64_GLOB_DAT":                   "debug/elf",
-	"elf.R_X86_64_GOT32":                      "debug/elf",
-	"elf.R_X86_64_GOTPCREL":                   "debug/elf",
-	"elf.R_X86_64_GOTTPOFF":                   "debug/elf",
-	"elf.R_X86_64_JMP_SLOT":                   "debug/elf",
-	"elf.R_X86_64_NONE":                       "debug/elf",
-	"elf.R_X86_64_PC16":                       "debug/elf",
-	"elf.R_X86_64_PC32":                       "debug/elf",
-	"elf.R_X86_64_PC8":                        "debug/elf",
-	"elf.R_X86_64_PLT32":                      "debug/elf",
-	"elf.R_X86_64_RELATIVE":                   "debug/elf",
-	"elf.R_X86_64_TLSGD":                      "debug/elf",
-	"elf.R_X86_64_TLSLD":                      "debug/elf",
-	"elf.R_X86_64_TPOFF32":                    "debug/elf",
-	"elf.R_X86_64_TPOFF64":                    "debug/elf",
-	"elf.Rel32":                               "debug/elf",
-	"elf.Rel64":                               "debug/elf",
-	"elf.Rela32":                              "debug/elf",
-	"elf.Rela64":                              "debug/elf",
-	"elf.SHF_ALLOC":                           "debug/elf",
-	"elf.SHF_EXECINSTR":                       "debug/elf",
-	"elf.SHF_GROUP":                           "debug/elf",
-	"elf.SHF_INFO_LINK":                       "debug/elf",
-	"elf.SHF_LINK_ORDER":                      "debug/elf",
-	"elf.SHF_MASKOS":                          "debug/elf",
-	"elf.SHF_MASKPROC":                        "debug/elf",
-	"elf.SHF_MERGE":                           "debug/elf",
-	"elf.SHF_OS_NONCONFORMING":                "debug/elf",
-	"elf.SHF_STRINGS":                         "debug/elf",
-	"elf.SHF_TLS":                             "debug/elf",
-	"elf.SHF_WRITE":                           "debug/elf",
-	"elf.SHN_ABS":                             "debug/elf",
-	"elf.SHN_COMMON":                          "debug/elf",
-	"elf.SHN_HIOS":                            "debug/elf",
-	"elf.SHN_HIPROC":                          "debug/elf",
-	"elf.SHN_HIRESERVE":                       "debug/elf",
-	"elf.SHN_LOOS":                            "debug/elf",
-	"elf.SHN_LOPROC":                          "debug/elf",
-	"elf.SHN_LORESERVE":                       "debug/elf",
-	"elf.SHN_UNDEF":                           "debug/elf",
-	"elf.SHN_XINDEX":                          "debug/elf",
-	"elf.SHT_DYNAMIC":                         "debug/elf",
-	"elf.SHT_DYNSYM":                          "debug/elf",
-	"elf.SHT_FINI_ARRAY":                      "debug/elf",
-	"elf.SHT_GNU_ATTRIBUTES":                  "debug/elf",
-	"elf.SHT_GNU_HASH":                        "debug/elf",
-	"elf.SHT_GNU_LIBLIST":                     "debug/elf",
-	"elf.SHT_GNU_VERDEF":                      "debug/elf",
-	"elf.SHT_GNU_VERNEED":                     "debug/elf",
-	"elf.SHT_GNU_VERSYM":                      "debug/elf",
-	"elf.SHT_GROUP":                           "debug/elf",
-	"elf.SHT_HASH":                            "debug/elf",
-	"elf.SHT_HIOS":                            "debug/elf",
-	"elf.SHT_HIPROC":                          "debug/elf",
-	"elf.SHT_HIUSER":                          "debug/elf",
-	"elf.SHT_INIT_ARRAY":                      "debug/elf",
-	"elf.SHT_LOOS":                            "debug/elf",
-	"elf.SHT_LOPROC":                          "debug/elf",
-	"elf.SHT_LOUSER":                          "debug/elf",
-	"elf.SHT_NOBITS":                          "debug/elf",
-	"elf.SHT_NOTE":                            "debug/elf",
-	"elf.SHT_NULL":                            "debug/elf",
-	"elf.SHT_PREINIT_ARRAY":                   "debug/elf",
-	"elf.SHT_PROGBITS":                        "debug/elf",
-	"elf.SHT_REL":                             "debug/elf",
-	"elf.SHT_RELA":                            "debug/elf",
-	"elf.SHT_SHLIB":                           "debug/elf",
-	"elf.SHT_STRTAB":                          "debug/elf",
-	"elf.SHT_SYMTAB":                          "debug/elf",
-	"elf.SHT_SYMTAB_SHNDX":                    "debug/elf",
-	"elf.STB_GLOBAL":                          "debug/elf",
-	"elf.STB_HIOS":                            "debug/elf",
-	"elf.STB_HIPROC":                          "debug/elf",
-	"elf.STB_LOCAL":                           "debug/elf",
-	"elf.STB_LOOS":                            "debug/elf",
-	"elf.STB_LOPROC":                          "debug/elf",
-	"elf.STB_WEAK":                            "debug/elf",
-	"elf.STT_COMMON":                          "debug/elf",
-	"elf.STT_FILE":                            "debug/elf",
-	"elf.STT_FUNC":                            "debug/elf",
-	"elf.STT_HIOS":                            "debug/elf",
-	"elf.STT_HIPROC":                          "debug/elf",
-	"elf.STT_LOOS":                            "debug/elf",
-	"elf.STT_LOPROC":                          "debug/elf",
-	"elf.STT_NOTYPE":                          "debug/elf",
-	"elf.STT_OBJECT":                          "debug/elf",
-	"elf.STT_SECTION":                         "debug/elf",
-	"elf.STT_TLS":                             "debug/elf",
-	"elf.STV_DEFAULT":                         "debug/elf",
-	"elf.STV_HIDDEN":                          "debug/elf",
-	"elf.STV_INTERNAL":                        "debug/elf",
-	"elf.STV_PROTECTED":                       "debug/elf",
-	"elf.ST_BIND":                             "debug/elf",
-	"elf.ST_INFO":                             "debug/elf",
-	"elf.ST_TYPE":                             "debug/elf",
-	"elf.ST_VISIBILITY":                       "debug/elf",
-	"elf.Section":                             "debug/elf",
-	"elf.Section32":                           "debug/elf",
-	"elf.Section64":                           "debug/elf",
-	"elf.SectionFlag":                         "debug/elf",
-	"elf.SectionHeader":                       "debug/elf",
-	"elf.SectionIndex":                        "debug/elf",
-	"elf.SectionType":                         "debug/elf",
-	"elf.Sym32":                               "debug/elf",
-	"elf.Sym32Size":                           "debug/elf",
-	"elf.Sym64":                               "debug/elf",
-	"elf.Sym64Size":                           "debug/elf",
-	"elf.SymBind":                             "debug/elf",
-	"elf.SymType":                             "debug/elf",
-	"elf.SymVis":                              "debug/elf",
-	"elf.Symbol":                              "debug/elf",
-	"elf.Type":                                "debug/elf",
-	"elf.Version":                             "debug/elf",
-	"elliptic.Curve":                          "crypto/elliptic",
-	"elliptic.CurveParams":                    "crypto/elliptic",
-	"elliptic.GenerateKey":                    "crypto/elliptic",
-	"elliptic.Marshal":                        "crypto/elliptic",
-	"elliptic.P224":                           "crypto/elliptic",
-	"elliptic.P256":                           "crypto/elliptic",
-	"elliptic.P384":                           "crypto/elliptic",
-	"elliptic.P521":                           "crypto/elliptic",
-	"elliptic.Unmarshal":                      "crypto/elliptic",
-	"encoding.BinaryMarshaler":                "encoding",
-	"encoding.BinaryUnmarshaler":              "encoding",
-	"encoding.TextMarshaler":                  "encoding",
-	"encoding.TextUnmarshaler":                "encoding",
-	"errors.New":                              "errors",
-	"exec.Cmd":                                "os/exec",
-	"exec.Command":                            "os/exec",
-	"exec.ErrNotFound":                        "os/exec",
-	"exec.Error":                              "os/exec",
-	"exec.ExitError":                          "os/exec",
-	"exec.LookPath":                           "os/exec",
-	"expvar.Do":                               "expvar",
-	"expvar.Float":                            "expvar",
-	"expvar.Func":                             "expvar",
-	"expvar.Get":                              "expvar",
-	"expvar.Int":                              "expvar",
-	"expvar.KeyValue":                         "expvar",
-	"expvar.Map":                              "expvar",
-	"expvar.NewFloat":                         "expvar",
-	"expvar.NewInt":                           "expvar",
-	"expvar.NewMap":                           "expvar",
-	"expvar.NewString":                        "expvar",
-	"expvar.Publish":                          "expvar",
-	"expvar.String":                           "expvar",
-	"expvar.Var":                              "expvar",
-	"fcgi.Serve":                              "net/http/fcgi",
-	"filepath.Abs":                            "path/filepath",
-	"filepath.Base":                           "path/filepath",
-	"filepath.Clean":                          "path/filepath",
-	"filepath.Dir":                            "path/filepath",
-	"filepath.ErrBadPattern":                  "path/filepath",
-	"filepath.EvalSymlinks":                   "path/filepath",
-	"filepath.Ext":                            "path/filepath",
-	"filepath.FromSlash":                      "path/filepath",
-	"filepath.Glob":                           "path/filepath",
-	"filepath.HasPrefix":                      "path/filepath",
-	"filepath.IsAbs":                          "path/filepath",
-	"filepath.Join":                           "path/filepath",
-	"filepath.ListSeparator":                  "path/filepath",
-	"filepath.Match":                          "path/filepath",
-	"filepath.Rel":                            "path/filepath",
-	"filepath.Separator":                      "path/filepath",
-	"filepath.SkipDir":                        "path/filepath",
-	"filepath.Split":                          "path/filepath",
-	"filepath.SplitList":                      "path/filepath",
-	"filepath.ToSlash":                        "path/filepath",
-	"filepath.VolumeName":                     "path/filepath",
-	"filepath.Walk":                           "path/filepath",
-	"filepath.WalkFunc":                       "path/filepath",
-	"flag.Arg":                                "flag",
-	"flag.Args":                               "flag",
-	"flag.Bool":                               "flag",
-	"flag.BoolVar":                            "flag",
-	"flag.CommandLine":                        "flag",
-	"flag.ContinueOnError":                    "flag",
-	"flag.Duration":                           "flag",
-	"flag.DurationVar":                        "flag",
-	"flag.ErrHelp":                            "flag",
-	"flag.ErrorHandling":                      "flag",
-	"flag.ExitOnError":                        "flag",
-	"flag.Flag":                               "flag",
-	"flag.FlagSet":                            "flag",
-	"flag.Float64":                            "flag",
-	"flag.Float64Var":                         "flag",
-	"flag.Getter":                             "flag",
-	"flag.Int":                                "flag",
-	"flag.Int64":                              "flag",
-	"flag.Int64Var":                           "flag",
-	"flag.IntVar":                             "flag",
-	"flag.Lookup":                             "flag",
-	"flag.NArg":                               "flag",
-	"flag.NFlag":                              "flag",
-	"flag.NewFlagSet":                         "flag",
-	"flag.PanicOnError":                       "flag",
-	"flag.Parse":                              "flag",
-	"flag.Parsed":                             "flag",
-	"flag.PrintDefaults":                      "flag",
-	"flag.Set":                                "flag",
-	"flag.String":                             "flag",
-	"flag.StringVar":                          "flag",
-	"flag.Uint":                               "flag",
-	"flag.Uint64":                             "flag",
-	"flag.Uint64Var":                          "flag",
-	"flag.UintVar":                            "flag",
-	"flag.Usage":                              "flag",
-	"flag.Value":                              "flag",
-	"flag.Var":                                "flag",
-	"flag.Visit":                              "flag",
-	"flag.VisitAll":                           "flag",
-	"flate.BestCompression":                   "compress/flate",
-	"flate.BestSpeed":                         "compress/flate",
-	"flate.CorruptInputError":                 "compress/flate",
-	"flate.DefaultCompression":                "compress/flate",
-	"flate.InternalError":                     "compress/flate",
-	"flate.NewReader":                         "compress/flate",
-	"flate.NewReaderDict":                     "compress/flate",
-	"flate.NewWriter":                         "compress/flate",
-	"flate.NewWriterDict":                     "compress/flate",
-	"flate.NoCompression":                     "compress/flate",
-	"flate.ReadError":                         "compress/flate",
-	"flate.Reader":                            "compress/flate",
-	"flate.WriteError":                        "compress/flate",
-	"flate.Writer":                            "compress/flate",
-	"fmt.Errorf":                              "fmt",
-	"fmt.Formatter":                           "fmt",
-	"fmt.Fprint":                              "fmt",
-	"fmt.Fprintf":                             "fmt",
-	"fmt.Fprintln":                            "fmt",
-	"fmt.Fscan":                               "fmt",
-	"fmt.Fscanf":                              "fmt",
-	"fmt.Fscanln":                             "fmt",
-	"fmt.GoStringer":                          "fmt",
-	"fmt.Print":                               "fmt",
-	"fmt.Printf":                              "fmt",
-	"fmt.Println":                             "fmt",
-	"fmt.Scan":                                "fmt",
-	"fmt.ScanState":                           "fmt",
-	"fmt.Scanf":                               "fmt",
-	"fmt.Scanln":                              "fmt",
-	"fmt.Scanner":                             "fmt",
-	"fmt.Sprint":                              "fmt",
-	"fmt.Sprintf":                             "fmt",
-	"fmt.Sprintln":                            "fmt",
-	"fmt.Sscan":                               "fmt",
-	"fmt.Sscanf":                              "fmt",
-	"fmt.Sscanln":                             "fmt",
-	"fmt.State":                               "fmt",
-	"fmt.Stringer":                            "fmt",
-	"fnv.New32":                               "hash/fnv",
-	"fnv.New32a":                              "hash/fnv",
-	"fnv.New64":                               "hash/fnv",
-	"fnv.New64a":                              "hash/fnv",
-	"format.Node":                             "go/format",
-	"format.Source":                           "go/format",
-	"gif.Decode":                              "image/gif",
-	"gif.DecodeAll":                           "image/gif",
-	"gif.DecodeConfig":                        "image/gif",
-	"gif.Encode":                              "image/gif",
-	"gif.EncodeAll":                           "image/gif",
-	"gif.GIF":                                 "image/gif",
-	"gif.Options":                             "image/gif",
-	"gob.CommonType":                          "encoding/gob",
-	"gob.Decoder":                             "encoding/gob",
-	"gob.Encoder":                             "encoding/gob",
-	"gob.GobDecoder":                          "encoding/gob",
-	"gob.GobEncoder":                          "encoding/gob",
-	"gob.NewDecoder":                          "encoding/gob",
-	"gob.NewEncoder":                          "encoding/gob",
-	"gob.Register":                            "encoding/gob",
-	"gob.RegisterName":                        "encoding/gob",
-	"gosym.DecodingError":                     "debug/gosym",
-	"gosym.Func":                              "debug/gosym",
-	"gosym.LineTable":                         "debug/gosym",
-	"gosym.NewLineTable":                      "debug/gosym",
-	"gosym.NewTable":                          "debug/gosym",
-	"gosym.Obj":                               "debug/gosym",
-	"gosym.Sym":                               "debug/gosym",
-	"gosym.Table":                             "debug/gosym",
-	"gosym.UnknownFileError":                  "debug/gosym",
-	"gosym.UnknownLineError":                  "debug/gosym",
-	"gzip.BestCompression":                    "compress/gzip",
-	"gzip.BestSpeed":                          "compress/gzip",
-	"gzip.DefaultCompression":                 "compress/gzip",
-	"gzip.ErrChecksum":                        "compress/gzip",
-	"gzip.ErrHeader":                          "compress/gzip",
-	"gzip.Header":                             "compress/gzip",
-	"gzip.NewReader":                          "compress/gzip",
-	"gzip.NewWriter":                          "compress/gzip",
-	"gzip.NewWriterLevel":                     "compress/gzip",
-	"gzip.NoCompression":                      "compress/gzip",
-	"gzip.Reader":                             "compress/gzip",
-	"gzip.Writer":                             "compress/gzip",
-	"hash.Hash":                               "hash",
-	"hash.Hash32":                             "hash",
-	"hash.Hash64":                             "hash",
-	"heap.Fix":                                "container/heap",
-	"heap.Init":                               "container/heap",
-	"heap.Interface":                          "container/heap",
-	"heap.Pop":                                "container/heap",
-	"heap.Push":                               "container/heap",
-	"heap.Remove":                             "container/heap",
-	"hex.Decode":                              "encoding/hex",
-	"hex.DecodeString":                        "encoding/hex",
-	"hex.DecodedLen":                          "encoding/hex",
-	"hex.Dump":                                "encoding/hex",
-	"hex.Dumper":                              "encoding/hex",
-	"hex.Encode":                              "encoding/hex",
-	"hex.EncodeToString":                      "encoding/hex",
-	"hex.EncodedLen":                          "encoding/hex",
-	"hex.ErrLength":                           "encoding/hex",
-	"hex.InvalidByteError":                    "encoding/hex",
-	"hmac.Equal":                              "crypto/hmac",
-	"hmac.New":                                "crypto/hmac",
-	"html.EscapeString":                       "html",
-	"html.UnescapeString":                     "html",
-	"http.CanonicalHeaderKey":                 "net/http",
-	"http.Client":                             "net/http",
-	"http.CloseNotifier":                      "net/http",
-	"http.Cookie":                             "net/http",
-	"http.CookieJar":                          "net/http",
-	"http.DefaultClient":                      "net/http",
-	"http.DefaultMaxHeaderBytes":              "net/http",
-	"http.DefaultMaxIdleConnsPerHost":         "net/http",
-	"http.DefaultServeMux":                    "net/http",
-	"http.DefaultTransport":                   "net/http",
-	"http.DetectContentType":                  "net/http",
-	"http.Dir":                                "net/http",
-	"http.ErrBodyNotAllowed":                  "net/http",
-	"http.ErrBodyReadAfterClose":              "net/http",
-	"http.ErrContentLength":                   "net/http",
-	"http.ErrHandlerTimeout":                  "net/http",
-	"http.ErrHeaderTooLong":                   "net/http",
-	"http.ErrHijacked":                        "net/http",
-	"http.ErrLineTooLong":                     "net/http",
-	"http.ErrMissingBoundary":                 "net/http",
-	"http.ErrMissingContentLength":            "net/http",
-	"http.ErrMissingFile":                     "net/http",
-	"http.ErrNoCookie":                        "net/http",
-	"http.ErrNoLocation":                      "net/http",
-	"http.ErrNotMultipart":                    "net/http",
-	"http.ErrNotSupported":                    "net/http",
-	"http.ErrShortBody":                       "net/http",
-	"http.ErrUnexpectedTrailer":               "net/http",
-	"http.ErrWriteAfterFlush":                 "net/http",
-	"http.Error":                              "net/http",
-	"http.File":                               "net/http",
-	"http.FileServer":                         "net/http",
-	"http.FileSystem":                         "net/http",
-	"http.Flusher":                            "net/http",
-	"http.Get":                                "net/http",
-	"http.Handle":                             "net/http",
-	"http.HandleFunc":                         "net/http",
-	"http.Handler":                            "net/http",
-	"http.HandlerFunc":                        "net/http",
-	"http.Head":                               "net/http",
-	"http.Header":                             "net/http",
-	"http.Hijacker":                           "net/http",
-	"http.ListenAndServe":                     "net/http",
-	"http.ListenAndServeTLS":                  "net/http",
-	"http.MaxBytesReader":                     "net/http",
-	"http.NewFileTransport":                   "net/http",
-	"http.NewRequest":                         "net/http",
-	"http.NewServeMux":                        "net/http",
-	"http.NotFound":                           "net/http",
-	"http.NotFoundHandler":                    "net/http",
-	"http.ParseHTTPVersion":                   "net/http",
-	"http.ParseTime":                          "net/http",
-	"http.Post":                               "net/http",
-	"http.PostForm":                           "net/http",
-	"http.ProtocolError":                      "net/http",
-	"http.ProxyFromEnvironment":               "net/http",
-	"http.ProxyURL":                           "net/http",
-	"http.ReadRequest":                        "net/http",
-	"http.ReadResponse":                       "net/http",
-	"http.Redirect":                           "net/http",
-	"http.RedirectHandler":                    "net/http",
-	"http.Request":                            "net/http",
-	"http.Response":                           "net/http",
-	"http.ResponseWriter":                     "net/http",
-	"http.RoundTripper":                       "net/http",
-	"http.Serve":                              "net/http",
-	"http.ServeContent":                       "net/http",
-	"http.ServeFile":                          "net/http",
-	"http.ServeMux":                           "net/http",
-	"http.Server":                             "net/http",
-	"http.SetCookie":                          "net/http",
-	"http.StatusAccepted":                     "net/http",
-	"http.StatusBadGateway":                   "net/http",
-	"http.StatusBadRequest":                   "net/http",
-	"http.StatusConflict":                     "net/http",
-	"http.StatusContinue":                     "net/http",
-	"http.StatusCreated":                      "net/http",
-	"http.StatusExpectationFailed":            "net/http",
-	"http.StatusForbidden":                    "net/http",
-	"http.StatusFound":                        "net/http",
-	"http.StatusGatewayTimeout":               "net/http",
-	"http.StatusGone":                         "net/http",
-	"http.StatusHTTPVersionNotSupported":      "net/http",
-	"http.StatusInternalServerError":          "net/http",
-	"http.StatusLengthRequired":               "net/http",
-	"http.StatusMethodNotAllowed":             "net/http",
-	"http.StatusMovedPermanently":             "net/http",
-	"http.StatusMultipleChoices":              "net/http",
-	"http.StatusNoContent":                    "net/http",
-	"http.StatusNonAuthoritativeInfo":         "net/http",
-	"http.StatusNotAcceptable":                "net/http",
-	"http.StatusNotFound":                     "net/http",
-	"http.StatusNotImplemented":               "net/http",
-	"http.StatusNotModified":                  "net/http",
-	"http.StatusOK":                           "net/http",
-	"http.StatusPartialContent":               "net/http",
-	"http.StatusPaymentRequired":              "net/http",
-	"http.StatusPreconditionFailed":           "net/http",
-	"http.StatusProxyAuthRequired":            "net/http",
-	"http.StatusRequestEntityTooLarge":        "net/http",
-	"http.StatusRequestTimeout":               "net/http",
-	"http.StatusRequestURITooLong":            "net/http",
-	"http.StatusRequestedRangeNotSatisfiable": "net/http",
-	"http.StatusResetContent":                 "net/http",
-	"http.StatusSeeOther":                     "net/http",
-	"http.StatusServiceUnavailable":           "net/http",
-	"http.StatusSwitchingProtocols":           "net/http",
-	"http.StatusTeapot":                       "net/http",
-	"http.StatusTemporaryRedirect":            "net/http",
-	"http.StatusText":                         "net/http",
-	"http.StatusUnauthorized":                 "net/http",
-	"http.StatusUnsupportedMediaType":         "net/http",
-	"http.StatusUseProxy":                     "net/http",
-	"http.StripPrefix":                        "net/http",
-	"http.TimeFormat":                         "net/http",
-	"http.TimeoutHandler":                     "net/http",
-	"http.Transport":                          "net/http",
-	"httptest.DefaultRemoteAddr":              "net/http/httptest",
-	"httptest.NewRecorder":                    "net/http/httptest",
-	"httptest.NewServer":                      "net/http/httptest",
-	"httptest.NewTLSServer":                   "net/http/httptest",
-	"httptest.NewUnstartedServer":             "net/http/httptest",
-	"httptest.ResponseRecorder":               "net/http/httptest",
-	"httptest.Server":                         "net/http/httptest",
-	"httputil.ClientConn":                     "net/http/httputil",
-	"httputil.DumpRequest":                    "net/http/httputil",
-	"httputil.DumpRequestOut":                 "net/http/httputil",
-	"httputil.DumpResponse":                   "net/http/httputil",
-	"httputil.ErrClosed":                      "net/http/httputil",
-	"httputil.ErrLineTooLong":                 "net/http/httputil",
-	"httputil.ErrPersistEOF":                  "net/http/httputil",
-	"httputil.ErrPipeline":                    "net/http/httputil",
-	"httputil.NewChunkedReader":               "net/http/httputil",
-	"httputil.NewChunkedWriter":               "net/http/httputil",
-	"httputil.NewClientConn":                  "net/http/httputil",
-	"httputil.NewProxyClientConn":             "net/http/httputil",
-	"httputil.NewServerConn":                  "net/http/httputil",
-	"httputil.NewSingleHostReverseProxy":      "net/http/httputil",
-	"httputil.ReverseProxy":                   "net/http/httputil",
-	"httputil.ServerConn":                     "net/http/httputil",
-	"image.Alpha":                             "image",
-	"image.Alpha16":                           "image",
-	"image.Black":                             "image",
-	"image.Config":                            "image",
-	"image.Decode":                            "image",
-	"image.DecodeConfig":                      "image",
-	"image.ErrFormat":                         "image",
-	"image.Gray":                              "image",
-	"image.Gray16":                            "image",
-	"image.Image":                             "image",
-	"image.NRGBA":                             "image",
-	"image.NRGBA64":                           "image",
-	"image.NewAlpha":                          "image",
-	"image.NewAlpha16":                        "image",
-	"image.NewGray":                           "image",
-	"image.NewGray16":                         "image",
-	"image.NewNRGBA":                          "image",
-	"image.NewNRGBA64":                        "image",
-	"image.NewPaletted":                       "image",
-	"image.NewRGBA":                           "image",
-	"image.NewRGBA64":                         "image",
-	"image.NewUniform":                        "image",
-	"image.NewYCbCr":                          "image",
-	"image.Opaque":                            "image",
-	"image.Paletted":                          "image",
-	"image.PalettedImage":                     "image",
-	"image.Point":                             "image",
-	"image.Pt":                                "image",
-	"image.RGBA":                              "image",
-	"image.RGBA64":                            "image",
-	"image.Rect":                              "image",
-	"image.Rectangle":                         "image",
-	"image.RegisterFormat":                    "image",
-	"image.Transparent":                       "image",
-	"image.Uniform":                           "image",
-	"image.White":                             "image",
-	"image.YCbCr":                             "image",
-	"image.YCbCrSubsampleRatio":               "image",
-	"image.YCbCrSubsampleRatio420":            "image",
-	"image.YCbCrSubsampleRatio422":            "image",
-	"image.YCbCrSubsampleRatio440":            "image",
-	"image.YCbCrSubsampleRatio444":            "image",
-	"image.ZP":                                "image",
-	"image.ZR":                                "image",
-	"io.ByteReader":                           "io",
-	"io.ByteScanner":                          "io",
-	"io.ByteWriter":                           "io",
-	"io.Closer":                               "io",
-	"io.Copy":                                 "io",
-	"io.CopyN":                                "io",
-	"io.EOF":                                  "io",
-	"io.ErrClosedPipe":                        "io",
-	"io.ErrNoProgress":                        "io",
-	"io.ErrShortBuffer":                       "io",
-	"io.ErrShortWrite":                        "io",
-	"io.ErrUnexpectedEOF":                     "io",
-	"io.LimitReader":                          "io",
-	"io.LimitedReader":                        "io",
-	"io.MultiReader":                          "io",
-	"io.MultiWriter":                          "io",
-	"io.NewSectionReader":                     "io",
-	"io.Pipe":                                 "io",
-	"io.PipeReader":                           "io",
-	"io.PipeWriter":                           "io",
-	"io.ReadAtLeast":                          "io",
-	"io.ReadCloser":                           "io",
-	"io.ReadFull":                             "io",
-	"io.ReadSeeker":                           "io",
-	"io.ReadWriteCloser":                      "io",
-	"io.ReadWriteSeeker":                      "io",
-	"io.ReadWriter":                           "io",
-	"io.Reader":                               "io",
-	"io.ReaderAt":                             "io",
-	"io.ReaderFrom":                           "io",
-	"io.RuneReader":                           "io",
-	"io.RuneScanner":                          "io",
-	"io.SectionReader":                        "io",
-	"io.Seeker":                               "io",
-	"io.TeeReader":                            "io",
-	"io.WriteCloser":                          "io",
-	"io.WriteSeeker":                          "io",
-	"io.WriteString":                          "io",
-	"io.Writer":                               "io",
-	"io.WriterAt":                             "io",
-	"io.WriterTo":                             "io",
-	"iotest.DataErrReader":                    "testing/iotest",
-	"iotest.ErrTimeout":                       "testing/iotest",
-	"iotest.HalfReader":                       "testing/iotest",
-	"iotest.NewReadLogger":                    "testing/iotest",
-	"iotest.NewWriteLogger":                   "testing/iotest",
-	"iotest.OneByteReader":                    "testing/iotest",
-	"iotest.TimeoutReader":                    "testing/iotest",
-	"iotest.TruncateWriter":                   "testing/iotest",
-	"ioutil.Discard":                          "io/ioutil",
-	"ioutil.NopCloser":                        "io/ioutil",
-	"ioutil.ReadAll":                          "io/ioutil",
-	"ioutil.ReadDir":                          "io/ioutil",
-	"ioutil.ReadFile":                         "io/ioutil",
-	"ioutil.TempDir":                          "io/ioutil",
-	"ioutil.TempFile":                         "io/ioutil",
-	"ioutil.WriteFile":                        "io/ioutil",
-	"jpeg.Decode":                             "image/jpeg",
-	"jpeg.DecodeConfig":                       "image/jpeg",
-	"jpeg.DefaultQuality":                     "image/jpeg",
-	"jpeg.Encode":                             "image/jpeg",
-	"jpeg.FormatError":                        "image/jpeg",
-	"jpeg.Options":                            "image/jpeg",
-	"jpeg.Reader":                             "image/jpeg",
-	"jpeg.UnsupportedError":                   "image/jpeg",
-	"json.Compact":                            "encoding/json",
-	"json.Decoder":                            "encoding/json",
-	"json.Encoder":                            "encoding/json",
-	"json.HTMLEscape":                         "encoding/json",
-	"json.Indent":                             "encoding/json",
-	"json.InvalidUTF8Error":                   "encoding/json",
-	"json.InvalidUnmarshalError":              "encoding/json",
-	"json.Marshal":                            "encoding/json",
-	"json.MarshalIndent":                      "encoding/json",
-	"json.Marshaler":                          "encoding/json",
-	"json.MarshalerError":                     "encoding/json",
-	"json.NewDecoder":                         "encoding/json",
-	"json.NewEncoder":                         "encoding/json",
-	"json.Number":                             "encoding/json",
-	"json.RawMessage":                         "encoding/json",
-	"json.SyntaxError":                        "encoding/json",
-	"json.Unmarshal":                          "encoding/json",
-	"json.UnmarshalFieldError":                "encoding/json",
-	"json.UnmarshalTypeError":                 "encoding/json",
-	"json.Unmarshaler":                        "encoding/json",
-	"json.UnsupportedTypeError":               "encoding/json",
-	"json.UnsupportedValueError":              "encoding/json",
-	"jsonrpc.Dial":                            "net/rpc/jsonrpc",
-	"jsonrpc.NewClient":                       "net/rpc/jsonrpc",
-	"jsonrpc.NewClientCodec":                  "net/rpc/jsonrpc",
-	"jsonrpc.NewServerCodec":                  "net/rpc/jsonrpc",
-	"jsonrpc.ServeConn":                       "net/rpc/jsonrpc",
-	"list.Element":                            "container/list",
-	"list.List":                               "container/list",
-	"list.New":                                "container/list",
-	"log.Fatal":                               "log",
-	"log.Fatalf":                              "log",
-	"log.Fatalln":                             "log",
-	"log.Flags":                               "log",
-	"log.Ldate":                               "log",
-	"log.Llongfile":                           "log",
-	"log.Lmicroseconds":                       "log",
-	"log.Logger":                              "log",
-	"log.Lshortfile":                          "log",
-	"log.LstdFlags":                           "log",
-	"log.Ltime":                               "log",
-	"log.New":                                 "log",
-	"log.Panic":                               "log",
-	"log.Panicf":                              "log",
-	"log.Panicln":                             "log",
-	"log.Prefix":                              "log",
-	"log.Print":                               "log",
-	"log.Printf":                              "log",
-	"log.Println":                             "log",
-	"log.SetFlags":                            "log",
-	"log.SetOutput":                           "log",
-	"log.SetPrefix":                           "log",
-	"lzw.LSB":                                 "compress/lzw",
-	"lzw.MSB":                                 "compress/lzw",
-	"lzw.NewReader":                           "compress/lzw",
-	"lzw.NewWriter":                           "compress/lzw",
-	"lzw.Order":                               "compress/lzw",
-	"macho.Cpu":                               "debug/macho",
-	"macho.Cpu386":                            "debug/macho",
-	"macho.CpuAmd64":                          "debug/macho",
-	"macho.Dylib":                             "debug/macho",
-	"macho.DylibCmd":                          "debug/macho",
-	"macho.Dysymtab":                          "debug/macho",
-	"macho.DysymtabCmd":                       "debug/macho",
-	"macho.File":                              "debug/macho",
-	"macho.FileHeader":                        "debug/macho",
-	"macho.FormatError":                       "debug/macho",
-	"macho.Load":                              "debug/macho",
-	"macho.LoadBytes":                         "debug/macho",
-	"macho.LoadCmd":                           "debug/macho",
-	"macho.LoadCmdDylib":                      "debug/macho",
-	"macho.LoadCmdDylinker":                   "debug/macho",
-	"macho.LoadCmdDysymtab":                   "debug/macho",
-	"macho.LoadCmdSegment":                    "debug/macho",
-	"macho.LoadCmdSegment64":                  "debug/macho",
-	"macho.LoadCmdSymtab":                     "debug/macho",
-	"macho.LoadCmdThread":                     "debug/macho",
-	"macho.LoadCmdUnixThread":                 "debug/macho",
-	"macho.Magic32":                           "debug/macho",
-	"macho.Magic64":                           "debug/macho",
-	"macho.NewFile":                           "debug/macho",
-	"macho.Nlist32":                           "debug/macho",
-	"macho.Nlist64":                           "debug/macho",
-	"macho.Open":                              "debug/macho",
-	"macho.Regs386":                           "debug/macho",
-	"macho.RegsAMD64":                         "debug/macho",
-	"macho.Section":                           "debug/macho",
-	"macho.Section32":                         "debug/macho",
-	"macho.Section64":                         "debug/macho",
-	"macho.SectionHeader":                     "debug/macho",
-	"macho.Segment":                           "debug/macho",
-	"macho.Segment32":                         "debug/macho",
-	"macho.Segment64":                         "debug/macho",
-	"macho.SegmentHeader":                     "debug/macho",
-	"macho.Symbol":                            "debug/macho",
-	"macho.Symtab":                            "debug/macho",
-	"macho.SymtabCmd":                         "debug/macho",
-	"macho.Thread":                            "debug/macho",
-	"macho.Type":                              "debug/macho",
-	"macho.TypeExec":                          "debug/macho",
-	"macho.TypeObj":                           "debug/macho",
-	"mail.Address":                            "net/mail",
-	"mail.ErrHeaderNotPresent":                "net/mail",
-	"mail.Header":                             "net/mail",
-	"mail.Message":                            "net/mail",
-	"mail.ParseAddress":                       "net/mail",
-	"mail.ParseAddressList":                   "net/mail",
-	"mail.ReadMessage":                        "net/mail",
-	"math.Abs":                                "math",
-	"math.Acos":                               "math",
-	"math.Acosh":                              "math",
-	"math.Asin":                               "math",
-	"math.Asinh":                              "math",
-	"math.Atan":                               "math",
-	"math.Atan2":                              "math",
-	"math.Atanh":                              "math",
-	"math.Cbrt":                               "math",
-	"math.Ceil":                               "math",
-	"math.Copysign":                           "math",
-	"math.Cos":                                "math",
-	"math.Cosh":                               "math",
-	"math.Dim":                                "math",
-	"math.E":                                  "math",
-	"math.Erf":                                "math",
-	"math.Erfc":                               "math",
-	"math.Exp":                                "math",
-	"math.Exp2":                               "math",
-	"math.Expm1":                              "math",
-	"math.Float32bits":                        "math",
-	"math.Float32frombits":                    "math",
-	"math.Float64bits":                        "math",
-	"math.Float64frombits":                    "math",
-	"math.Floor":                              "math",
-	"math.Frexp":                              "math",
-	"math.Gamma":                              "math",
-	"math.Hypot":                              "math",
-	"math.Ilogb":                              "math",
-	"math.Inf":                                "math",
-	"math.IsInf":                              "math",
-	"math.IsNaN":                              "math",
-	"math.J0":                                 "math",
-	"math.J1":                                 "math",
-	"math.Jn":                                 "math",
-	"math.Ldexp":                              "math",
-	"math.Lgamma":                             "math",
-	"math.Ln10":                               "math",
-	"math.Ln2":                                "math",
-	"math.Log":                                "math",
-	"math.Log10":                              "math",
-	"math.Log10E":                             "math",
-	"math.Log1p":                              "math",
-	"math.Log2":                               "math",
-	"math.Log2E":                              "math",
-	"math.Logb":                               "math",
-	"math.Max":                                "math",
-	"math.MaxFloat32":                         "math",
-	"math.MaxFloat64":                         "math",
-	"math.MaxInt16":                           "math",
-	"math.MaxInt32":                           "math",
-	"math.MaxInt64":                           "math",
-	"math.MaxInt8":                            "math",
-	"math.MaxUint16":                          "math",
-	"math.MaxUint32":                          "math",
-	"math.MaxUint64":                          "math",
-	"math.MaxUint8":                           "math",
-	"math.Min":                                "math",
-	"math.MinInt16":                           "math",
-	"math.MinInt32":                           "math",
-	"math.MinInt64":                           "math",
-	"math.MinInt8":                            "math",
-	"math.Mod":                                "math",
-	"math.Modf":                               "math",
-	"math.NaN":                                "math",
-	"math.Nextafter":                          "math",
-	"math.Phi":                                "math",
-	"math.Pi":                                 "math",
-	"math.Pow":                                "math",
-	"math.Pow10":                              "math",
-	"math.Remainder":                          "math",
-	"math.Signbit":                            "math",
-	"math.Sin":                                "math",
-	"math.Sincos":                             "math",
-	"math.Sinh":                               "math",
-	"math.SmallestNonzeroFloat32":             "math",
-	"math.SmallestNonzeroFloat64":             "math",
-	"math.Sqrt":                               "math",
-	"math.Sqrt2":                              "math",
-	"math.SqrtE":                              "math",
-	"math.SqrtPhi":                            "math",
-	"math.SqrtPi":                             "math",
-	"math.Tan":                                "math",
-	"math.Tanh":                               "math",
-	"math.Trunc":                              "math",
-	"math.Y0":                                 "math",
-	"math.Y1":                                 "math",
-	"math.Yn":                                 "math",
-	"md5.BlockSize":                           "crypto/md5",
-	"md5.New":                                 "crypto/md5",
-	"md5.Size":                                "crypto/md5",
-	"md5.Sum":                                 "crypto/md5",
-	"mime.AddExtensionType":                   "mime",
-	"mime.FormatMediaType":                    "mime",
-	"mime.ParseMediaType":                     "mime",
-	"mime.TypeByExtension":                    "mime",
-	"multipart.File":                          "mime/multipart",
-	"multipart.FileHeader":                    "mime/multipart",
-	"multipart.Form":                          "mime/multipart",
-	"multipart.NewReader":                     "mime/multipart",
-	"multipart.NewWriter":                     "mime/multipart",
-	"multipart.Part":                          "mime/multipart",
-	"multipart.Reader":                        "mime/multipart",
-	"multipart.Writer":                        "mime/multipart",
-	"net.Addr":                                "net",
-	"net.AddrError":                           "net",
-	"net.CIDRMask":                            "net",
-	"net.Conn":                                "net",
-	"net.DNSConfigError":                      "net",
-	"net.DNSError":                            "net",
-	"net.Dial":                                "net",
-	"net.DialIP":                              "net",
-	"net.DialTCP":                             "net",
-	"net.DialTimeout":                         "net",
-	"net.DialUDP":                             "net",
-	"net.DialUnix":                            "net",
-	"net.Dialer":                              "net",
-	"net.ErrWriteToConnected":                 "net",
-	"net.Error":                               "net",
-	"net.FileConn":                            "net",
-	"net.FileListener":                        "net",
-	"net.FilePacketConn":                      "net",
-	"net.FlagBroadcast":                       "net",
-	"net.FlagLoopback":                        "net",
-	"net.FlagMulticast":                       "net",
-	"net.FlagPointToPoint":                    "net",
-	"net.FlagUp":                              "net",
-	"net.Flags":                               "net",
-	"net.HardwareAddr":                        "net",
-	"net.IP":                                  "net",
-	"net.IPAddr":                              "net",
-	"net.IPConn":                              "net",
-	"net.IPMask":                              "net",
-	"net.IPNet":                               "net",
-	"net.IPv4":                                "net",
-	"net.IPv4Mask":                            "net",
-	"net.IPv4allrouter":                       "net",
-	"net.IPv4allsys":                          "net",
-	"net.IPv4bcast":                           "net",
-	"net.IPv4len":                             "net",
-	"net.IPv4zero":                            "net",
-	"net.IPv6interfacelocalallnodes":          "net",
-	"net.IPv6len":                             "net",
-	"net.IPv6linklocalallnodes":               "net",
-	"net.IPv6linklocalallrouters":             "net",
-	"net.IPv6loopback":                        "net",
-	"net.IPv6unspecified":                     "net",
-	"net.IPv6zero":                            "net",
-	"net.Interface":                           "net",
-	"net.InterfaceAddrs":                      "net",
-	"net.InterfaceByIndex":                    "net",
-	"net.InterfaceByName":                     "net",
-	"net.Interfaces":                          "net",
-	"net.InvalidAddrError":                    "net",
-	"net.JoinHostPort":                        "net",
-	"net.Listen":                              "net",
-	"net.ListenIP":                            "net",
-	"net.ListenMulticastUDP":                  "net",
-	"net.ListenPacket":                        "net",
-	"net.ListenTCP":                           "net",
-	"net.ListenUDP":                           "net",
-	"net.ListenUnix":                          "net",
-	"net.ListenUnixgram":                      "net",
-	"net.Listener":                            "net",
-	"net.LookupAddr":                          "net",
-	"net.LookupCNAME":                         "net",
-	"net.LookupHost":                          "net",
-	"net.LookupIP":                            "net",
-	"net.LookupMX":                            "net",
-	"net.LookupNS":                            "net",
-	"net.LookupPort":                          "net",
-	"net.LookupSRV":                           "net",
-	"net.LookupTXT":                           "net",
-	"net.MX":                                  "net",
-	"net.NS":                                  "net",
-	"net.OpError":                             "net",
-	"net.PacketConn":                          "net",
-	"net.ParseCIDR":                           "net",
-	"net.ParseError":                          "net",
-	"net.ParseIP":                             "net",
-	"net.ParseMAC":                            "net",
-	"net.Pipe":                                "net",
-	"net.ResolveIPAddr":                       "net",
-	"net.ResolveTCPAddr":                      "net",
-	"net.ResolveUDPAddr":                      "net",
-	"net.ResolveUnixAddr":                     "net",
-	"net.SRV":                                 "net",
-	"net.SplitHostPort":                       "net",
-	"net.TCPAddr":                             "net",
-	"net.TCPConn":                             "net",
-	"net.TCPListener":                         "net",
-	"net.UDPAddr":                             "net",
-	"net.UDPConn":                             "net",
-	"net.UnixAddr":                            "net",
-	"net.UnixConn":                            "net",
-	"net.UnixListener":                        "net",
-	"net.UnknownNetworkError":                 "net",
-	"os.Args":                                 "os",
-	"os.Chdir":                                "os",
-	"os.Chmod":                                "os",
-	"os.Chown":                                "os",
-	"os.Chtimes":                              "os",
-	"os.Clearenv":                             "os",
-	"os.Create":                               "os",
-	"os.DevNull":                              "os",
-	"os.Environ":                              "os",
-	"os.ErrExist":                             "os",
-	"os.ErrInvalid":                           "os",
-	"os.ErrNotExist":                          "os",
-	"os.ErrPermission":                        "os",
-	"os.Exit":                                 "os",
-	"os.Expand":                               "os",
-	"os.ExpandEnv":                            "os",
-	"os.File":                                 "os",
-	"os.FileInfo":                             "os",
-	"os.FileMode":                             "os",
-	"os.FindProcess":                          "os",
-	"os.Getegid":                              "os",
-	"os.Getenv":                               "os",
-	"os.Geteuid":                              "os",
-	"os.Getgid":                               "os",
-	"os.Getgroups":                            "os",
-	"os.Getpagesize":                          "os",
-	"os.Getpid":                               "os",
-	"os.Getppid":                              "os",
-	"os.Getuid":                               "os",
-	"os.Getwd":                                "os",
-	"os.Hostname":                             "os",
-	"os.Interrupt":                            "os",
-	"os.IsExist":                              "os",
-	"os.IsNotExist":                           "os",
-	"os.IsPathSeparator":                      "os",
-	"os.IsPermission":                         "os",
-	"os.Kill":                                 "os",
-	"os.Lchown":                               "os",
-	"os.Link":                                 "os",
-	"os.LinkError":                            "os",
-	"os.Lstat":                                "os",
-	"os.Mkdir":                                "os",
-	"os.MkdirAll":                             "os",
-	"os.ModeAppend":                           "os",
-	"os.ModeCharDevice":                       "os",
-	"os.ModeDevice":                           "os",
-	"os.ModeDir":                              "os",
-	"os.ModeExclusive":                        "os",
-	"os.ModeNamedPipe":                        "os",
-	"os.ModePerm":                             "os",
-	"os.ModeSetgid":                           "os",
-	"os.ModeSetuid":                           "os",
-	"os.ModeSocket":                           "os",
-	"os.ModeSticky":                           "os",
-	"os.ModeSymlink":                          "os",
-	"os.ModeTemporary":                        "os",
-	"os.ModeType":                             "os",
-	"os.NewFile":                              "os",
-	"os.NewSyscallError":                      "os",
-	"os.O_APPEND":                             "os",
-	"os.O_CREATE":                             "os",
-	"os.O_EXCL":                               "os",
-	"os.O_RDONLY":                             "os",
-	"os.O_RDWR":                               "os",
-	"os.O_SYNC":                               "os",
-	"os.O_TRUNC":                              "os",
-	"os.O_WRONLY":                             "os",
-	"os.Open":                                 "os",
-	"os.OpenFile":                             "os",
-	"os.PathError":                            "os",
-	"os.PathListSeparator":                    "os",
-	"os.PathSeparator":                        "os",
-	"os.Pipe":                                 "os",
-	"os.ProcAttr":                             "os",
-	"os.Process":                              "os",
-	"os.ProcessState":                         "os",
-	"os.Readlink":                             "os",
-	"os.Remove":                               "os",
-	"os.RemoveAll":                            "os",
-	"os.Rename":                               "os",
-	"os.SEEK_CUR":                             "os",
-	"os.SEEK_END":                             "os",
-	"os.SEEK_SET":                             "os",
-	"os.SameFile":                             "os",
-	"os.Setenv":                               "os",
-	"os.Signal":                               "os",
-	"os.StartProcess":                         "os",
-	"os.Stat":                                 "os",
-	"os.Stderr":                               "os",
-	"os.Stdin":                                "os",
-	"os.Stdout":                               "os",
-	"os.Symlink":                              "os",
-	"os.SyscallError":                         "os",
-	"os.TempDir":                              "os",
-	"os.Truncate":                             "os",
-	"palette.Plan9":                           "image/color/palette",
-	"palette.WebSafe":                         "image/color/palette",
-	"parse.ActionNode":                        "text/template/parse",
-	"parse.BoolNode":                          "text/template/parse",
-	"parse.BranchNode":                        "text/template/parse",
-	"parse.ChainNode":                         "text/template/parse",
-	"parse.CommandNode":                       "text/template/parse",
-	"parse.DotNode":                           "text/template/parse",
-	"parse.FieldNode":                         "text/template/parse",
-	"parse.IdentifierNode":                    "text/template/parse",
-	"parse.IfNode":                            "text/template/parse",
-	"parse.IsEmptyTree":                       "text/template/parse",
-	"parse.ListNode":                          "text/template/parse",
-	"parse.New":                               "text/template/parse",
-	"parse.NewIdentifier":                     "text/template/parse",
-	"parse.NilNode":                           "text/template/parse",
-	"parse.Node":                              "text/template/parse",
-	"parse.NodeAction":                        "text/template/parse",
-	"parse.NodeBool":                          "text/template/parse",
-	"parse.NodeChain":                         "text/template/parse",
-	"parse.NodeCommand":                       "text/template/parse",
-	"parse.NodeDot":                           "text/template/parse",
-	"parse.NodeField":                         "text/template/parse",
-	"parse.NodeIdentifier":                    "text/template/parse",
-	"parse.NodeIf":                            "text/template/parse",
-	"parse.NodeList":                          "text/template/parse",
-	"parse.NodeNil":                           "text/template/parse",
-	"parse.NodeNumber":                        "text/template/parse",
-	"parse.NodePipe":                          "text/template/parse",
-	"parse.NodeRange":                         "text/template/parse",
-	"parse.NodeString":                        "text/template/parse",
-	"parse.NodeTemplate":                      "text/template/parse",
-	"parse.NodeText":                          "text/template/parse",
-	"parse.NodeType":                          "text/template/parse",
-	"parse.NodeVariable":                      "text/template/parse",
-	"parse.NodeWith":                          "text/template/parse",
-	"parse.NumberNode":                        "text/template/parse",
-	"parse.Parse":                             "text/template/parse",
-	"parse.PipeNode":                          "text/template/parse",
-	"parse.Pos":                               "text/template/parse",
-	"parse.RangeNode":                         "text/template/parse",
-	"parse.StringNode":                        "text/template/parse",
-	"parse.TemplateNode":                      "text/template/parse",
-	"parse.TextNode":                          "text/template/parse",
-	"parse.Tree":                              "text/template/parse",
-	"parse.VariableNode":                      "text/template/parse",
-	"parse.WithNode":                          "text/template/parse",
-	"parser.AllErrors":                        "go/parser",
-	"parser.DeclarationErrors":                "go/parser",
-	"parser.ImportsOnly":                      "go/parser",
-	"parser.Mode":                             "go/parser",
-	"parser.PackageClauseOnly":                "go/parser",
-	"parser.ParseComments":                    "go/parser",
-	"parser.ParseDir":                         "go/parser",
-	"parser.ParseExpr":                        "go/parser",
-	"parser.ParseFile":                        "go/parser",
-	"parser.SpuriousErrors":                   "go/parser",
-	"parser.Trace":                            "go/parser",
-	"path.Base":                               "path",
-	"path.Clean":                              "path",
-	"path.Dir":                                "path",
-	"path.ErrBadPattern":                      "path",
-	"path.Ext":                                "path",
-	"path.IsAbs":                              "path",
-	"path.Join":                               "path",
-	"path.Match":                              "path",
-	"path.Split":                              "path",
-	"pe.COFFSymbol":                           "debug/pe",
-	"pe.COFFSymbolSize":                       "debug/pe",
-	"pe.File":                                 "debug/pe",
-	"pe.FileHeader":                           "debug/pe",
-	"pe.FormatError":                          "debug/pe",
-	"pe.IMAGE_FILE_MACHINE_AM33":              "debug/pe",
-	"pe.IMAGE_FILE_MACHINE_AMD64":             "debug/pe",
-	"pe.IMAGE_FILE_MACHINE_ARM":               "debug/pe",
-	"pe.IMAGE_FILE_MACHINE_EBC":               "debug/pe",
-	"pe.IMAGE_FILE_MACHINE_I386":              "debug/pe",
-	"pe.IMAGE_FILE_MACHINE_IA64":              "debug/pe",
-	"pe.IMAGE_FILE_MACHINE_M32R":              "debug/pe",
-	"pe.IMAGE_FILE_MACHINE_MIPS16":            "debug/pe",
-	"pe.IMAGE_FILE_MACHINE_MIPSFPU":           "debug/pe",
-	"pe.IMAGE_FILE_MACHINE_MIPSFPU16":         "debug/pe",
-	"pe.IMAGE_FILE_MACHINE_POWERPC":           "debug/pe",
-	"pe.IMAGE_FILE_MACHINE_POWERPCFP":         "debug/pe",
-	"pe.IMAGE_FILE_MACHINE_R4000":             "debug/pe",
-	"pe.IMAGE_FILE_MACHINE_SH3":               "debug/pe",
-	"pe.IMAGE_FILE_MACHINE_SH3DSP":            "debug/pe",
-	"pe.IMAGE_FILE_MACHINE_SH4":               "debug/pe",
-	"pe.IMAGE_FILE_MACHINE_SH5":               "debug/pe",
-	"pe.IMAGE_FILE_MACHINE_THUMB":             "debug/pe",
-	"pe.IMAGE_FILE_MACHINE_UNKNOWN":           "debug/pe",
-	"pe.IMAGE_FILE_MACHINE_WCEMIPSV2":         "debug/pe",
-	"pe.ImportDirectory":                      "debug/pe",
-	"pe.NewFile":                              "debug/pe",
-	"pe.Open":                                 "debug/pe",
-	"pe.Section":                              "debug/pe",
-	"pe.SectionHeader":                        "debug/pe",
-	"pe.SectionHeader32":                      "debug/pe",
-	"pe.Symbol":                               "debug/pe",
-	"pem.Block":                               "encoding/pem",
-	"pem.Decode":                              "encoding/pem",
-	"pem.Encode":                              "encoding/pem",
-	"pem.EncodeToMemory":                      "encoding/pem",
-	"pkix.AlgorithmIdentifier":                "crypto/x509/pkix",
-	"pkix.AttributeTypeAndValue":              "crypto/x509/pkix",
-	"pkix.CertificateList":                    "crypto/x509/pkix",
-	"pkix.Extension":                          "crypto/x509/pkix",
-	"pkix.Name":                               "crypto/x509/pkix",
-	"pkix.RDNSequence":                        "crypto/x509/pkix",
-	"pkix.RelativeDistinguishedNameSET":       "crypto/x509/pkix",
-	"pkix.RevokedCertificate":                 "crypto/x509/pkix",
-	"pkix.TBSCertificateList":                 "crypto/x509/pkix",
-	"png.Decode":                              "image/png",
-	"png.DecodeConfig":                        "image/png",
-	"png.Encode":                              "image/png",
-	"png.FormatError":                         "image/png",
-	"png.UnsupportedError":                    "image/png",
-	"pprof.Cmdline":                           "net/http/pprof",
-	"pprof.Handler":                           "net/http/pprof",
-	"pprof.Index":                             "net/http/pprof",
-	"pprof.Lookup":                            "runtime/pprof",
-	"pprof.NewProfile":                        "runtime/pprof",
+	"adler32.Checksum":                              "hash/adler32",
+	"adler32.New":                                   "hash/adler32",
+	"adler32.Size":                                  "hash/adler32",
+	"aes.BlockSize":                                 "crypto/aes",
+	"aes.KeySizeError":                              "crypto/aes",
+	"aes.NewCipher":                                 "crypto/aes",
+	"ascii85.CorruptInputError":                     "encoding/ascii85",
+	"ascii85.Decode":                                "encoding/ascii85",
+	"ascii85.Encode":                                "encoding/ascii85",
+	"ascii85.MaxEncodedLen":                         "encoding/ascii85",
+	"ascii85.NewDecoder":                            "encoding/ascii85",
+	"ascii85.NewEncoder":                            "encoding/ascii85",
+	"asn1.BitString":                                "encoding/asn1",
+	"asn1.Enumerated":                               "encoding/asn1",
+	"asn1.Flag":                                     "encoding/asn1",
+	"asn1.Marshal":                                  "encoding/asn1",
+	"asn1.ObjectIdentifier":                         "encoding/asn1",
+	"asn1.RawContent":                               "encoding/asn1",
+	"asn1.RawValue":                                 "encoding/asn1",
+	"asn1.StructuralError":                          "encoding/asn1",
+	"asn1.SyntaxError":                              "encoding/asn1",
+	"asn1.Unmarshal":                                "encoding/asn1",
+	"asn1.UnmarshalWithParams":                      "encoding/asn1",
+	"ast.ArrayType":                                 "go/ast",
+	"ast.AssignStmt":                                "go/ast",
+	"ast.Bad":                                       "go/ast",
+	"ast.BadDecl":                                   "go/ast",
+	"ast.BadExpr":                                   "go/ast",
+	"ast.BadStmt":                                   "go/ast",
+	"ast.BasicLit":                                  "go/ast",
+	"ast.BinaryExpr":                                "go/ast",
+	"ast.BlockStmt":                                 "go/ast",
+	"ast.BranchStmt":                                "go/ast",
+	"ast.CallExpr":                                  "go/ast",
+	"ast.CaseClause":                                "go/ast",
+	"ast.ChanDir":                                   "go/ast",
+	"ast.ChanType":                                  "go/ast",
+	"ast.CommClause":                                "go/ast",
+	"ast.Comment":                                   "go/ast",
+	"ast.CommentGroup":                              "go/ast",
+	"ast.CommentMap":                                "go/ast",
+	"ast.CompositeLit":                              "go/ast",
+	"ast.Con":                                       "go/ast",
+	"ast.DeclStmt":                                  "go/ast",
+	"ast.DeferStmt":                                 "go/ast",
+	"ast.Ellipsis":                                  "go/ast",
+	"ast.EmptyStmt":                                 "go/ast",
+	"ast.ExprStmt":                                  "go/ast",
+	"ast.Field":                                     "go/ast",
+	"ast.FieldFilter":                               "go/ast",
+	"ast.FieldList":                                 "go/ast",
+	"ast.File":                                      "go/ast",
+	"ast.FileExports":                               "go/ast",
+	"ast.Filter":                                    "go/ast",
+	"ast.FilterDecl":                                "go/ast",
+	"ast.FilterFile":                                "go/ast",
+	"ast.FilterFuncDuplicates":                      "go/ast",
+	"ast.FilterImportDuplicates":                    "go/ast",
+	"ast.FilterPackage":                             "go/ast",
+	"ast.FilterUnassociatedComments":                "go/ast",
+	"ast.ForStmt":                                   "go/ast",
+	"ast.Fprint":                                    "go/ast",
+	"ast.Fun":                                       "go/ast",
+	"ast.FuncDecl":                                  "go/ast",
+	"ast.FuncLit":                                   "go/ast",
+	"ast.FuncType":                                  "go/ast",
+	"ast.GenDecl":                                   "go/ast",
+	"ast.GoStmt":                                    "go/ast",
+	"ast.Ident":                                     "go/ast",
+	"ast.IfStmt":                                    "go/ast",
+	"ast.ImportSpec":                                "go/ast",
+	"ast.Importer":                                  "go/ast",
+	"ast.IncDecStmt":                                "go/ast",
+	"ast.IndexExpr":                                 "go/ast",
+	"ast.Inspect":                                   "go/ast",
+	"ast.InterfaceType":                             "go/ast",
+	"ast.IsExported":                                "go/ast",
+	"ast.KeyValueExpr":                              "go/ast",
+	"ast.LabeledStmt":                               "go/ast",
+	"ast.Lbl":                                       "go/ast",
+	"ast.MapType":                                   "go/ast",
+	"ast.MergeMode":                                 "go/ast",
+	"ast.MergePackageFiles":                         "go/ast",
+	"ast.NewCommentMap":                             "go/ast",
+	"ast.NewIdent":                                  "go/ast",
+	"ast.NewObj":                                    "go/ast",
+	"ast.NewPackage":                                "go/ast",
+	"ast.NewScope":                                  "go/ast",
+	"ast.Node":                                      "go/ast",
+	"ast.NotNilFilter":                              "go/ast",
+	"ast.ObjKind":                                   "go/ast",
+	"ast.Object":                                    "go/ast",
+	"ast.Package":                                   "go/ast",
+	"ast.PackageExports":                            "go/ast",
+	"ast.ParenExpr":                                 "go/ast",
+	"ast.Pkg":                                       "go/ast",
+	"ast.Print":                                     "go/ast",
+	"ast.RECV":                                      "go/ast",
+	"ast.RangeStmt":                                 "go/ast",
+	"ast.ReturnStmt":                                "go/ast",
+	"ast.SEND":                                      "go/ast",
+	"ast.Scope":                                     "go/ast",
+	"ast.SelectStmt":                                "go/ast",
+	"ast.SelectorExpr":                              "go/ast",
+	"ast.SendStmt":                                  "go/ast",
+	"ast.SliceExpr":                                 "go/ast",
+	"ast.SortImports":                               "go/ast",
+	"ast.StarExpr":                                  "go/ast",
+	"ast.StructType":                                "go/ast",
+	"ast.SwitchStmt":                                "go/ast",
+	"ast.Typ":                                       "go/ast",
+	"ast.TypeAssertExpr":                            "go/ast",
+	"ast.TypeSpec":                                  "go/ast",
+	"ast.TypeSwitchStmt":                            "go/ast",
+	"ast.UnaryExpr":                                 "go/ast",
+	"ast.ValueSpec":                                 "go/ast",
+	"ast.Var":                                       "go/ast",
+	"ast.Visitor":                                   "go/ast",
+	"ast.Walk":                                      "go/ast",
+	"atomic.AddInt32":                               "sync/atomic",
+	"atomic.AddInt64":                               "sync/atomic",
+	"atomic.AddUint32":                              "sync/atomic",
+	"atomic.AddUint64":                              "sync/atomic",
+	"atomic.AddUintptr":                             "sync/atomic",
+	"atomic.CompareAndSwapInt32":                    "sync/atomic",
+	"atomic.CompareAndSwapInt64":                    "sync/atomic",
+	"atomic.CompareAndSwapPointer":                  "sync/atomic",
+	"atomic.CompareAndSwapUint32":                   "sync/atomic",
+	"atomic.CompareAndSwapUint64":                   "sync/atomic",
+	"atomic.CompareAndSwapUintptr":                  "sync/atomic",
+	"atomic.LoadInt32":                              "sync/atomic",
+	"atomic.LoadInt64":                              "sync/atomic",
+	"atomic.LoadPointer":                            "sync/atomic",
+	"atomic.LoadUint32":                             "sync/atomic",
+	"atomic.LoadUint64":                             "sync/atomic",
+	"atomic.LoadUintptr":                            "sync/atomic",
+	"atomic.StoreInt32":                             "sync/atomic",
+	"atomic.StoreInt64":                             "sync/atomic",
+	"atomic.StorePointer":                           "sync/atomic",
+	"atomic.StoreUint32":                            "sync/atomic",
+	"atomic.StoreUint64":                            "sync/atomic",
+	"atomic.StoreUintptr":                           "sync/atomic",
+	"atomic.SwapInt32":                              "sync/atomic",
+	"atomic.SwapInt64":                              "sync/atomic",
+	"atomic.SwapPointer":                            "sync/atomic",
+	"atomic.SwapUint32":                             "sync/atomic",
+	"atomic.SwapUint64":                             "sync/atomic",
+	"atomic.SwapUintptr":                            "sync/atomic",
+	"atomic.Value":                                  "sync/atomic",
+	"base32.CorruptInputError":                      "encoding/base32",
+	"base32.Encoding":                               "encoding/base32",
+	"base32.HexEncoding":                            "encoding/base32",
+	"base32.NewDecoder":                             "encoding/base32",
+	"base32.NewEncoder":                             "encoding/base32",
+	"base32.NewEncoding":                            "encoding/base32",
+	"base32.StdEncoding":                            "encoding/base32",
+	"base64.CorruptInputError":                      "encoding/base64",
+	"base64.Encoding":                               "encoding/base64",
+	"base64.NewDecoder":                             "encoding/base64",
+	"base64.NewEncoder":                             "encoding/base64",
+	"base64.NewEncoding":                            "encoding/base64",
+	"base64.NoPadding":                              "encoding/base64",
+	"base64.RawStdEncoding":                         "encoding/base64",
+	"base64.RawURLEncoding":                         "encoding/base64",
+	"base64.StdEncoding":                            "encoding/base64",
+	"base64.StdPadding":                             "encoding/base64",
+	"base64.URLEncoding":                            "encoding/base64",
+	"big.Above":                                     "math/big",
+	"big.Accuracy":                                  "math/big",
+	"big.AwayFromZero":                              "math/big",
+	"big.Below":                                     "math/big",
+	"big.ErrNaN":                                    "math/big",
+	"big.Exact":                                     "math/big",
+	"big.Float":                                     "math/big",
+	"big.Int":                                       "math/big",
+	"big.Jacobi":                                    "math/big",
+	"big.MaxBase":                                   "math/big",
+	"big.MaxExp":                                    "math/big",
+	"big.MaxPrec":                                   "math/big",
+	"big.MinExp":                                    "math/big",
+	"big.NewFloat":                                  "math/big",
+	"big.NewInt":                                    "math/big",
+	"big.NewRat":                                    "math/big",
+	"big.ParseFloat":                                "math/big",
+	"big.Rat":                                       "math/big",
+	"big.RoundingMode":                              "math/big",
+	"big.ToNearestAway":                             "math/big",
+	"big.ToNearestEven":                             "math/big",
+	"big.ToNegativeInf":                             "math/big",
+	"big.ToPositiveInf":                             "math/big",
+	"big.ToZero":                                    "math/big",
+	"big.Word":                                      "math/big",
+	"binary.BigEndian":                              "encoding/binary",
+	"binary.ByteOrder":                              "encoding/binary",
+	"binary.LittleEndian":                           "encoding/binary",
+	"binary.MaxVarintLen16":                         "encoding/binary",
+	"binary.MaxVarintLen32":                         "encoding/binary",
+	"binary.MaxVarintLen64":                         "encoding/binary",
+	"binary.PutUvarint":                             "encoding/binary",
+	"binary.PutVarint":                              "encoding/binary",
+	"binary.Read":                                   "encoding/binary",
+	"binary.ReadUvarint":                            "encoding/binary",
+	"binary.ReadVarint":                             "encoding/binary",
+	"binary.Size":                                   "encoding/binary",
+	"binary.Uvarint":                                "encoding/binary",
+	"binary.Varint":                                 "encoding/binary",
+	"binary.Write":                                  "encoding/binary",
+	"bufio.ErrAdvanceTooFar":                        "bufio",
+	"bufio.ErrBufferFull":                           "bufio",
+	"bufio.ErrInvalidUnreadByte":                    "bufio",
+	"bufio.ErrInvalidUnreadRune":                    "bufio",
+	"bufio.ErrNegativeAdvance":                      "bufio",
+	"bufio.ErrNegativeCount":                        "bufio",
+	"bufio.ErrTooLong":                              "bufio",
+	"bufio.MaxScanTokenSize":                        "bufio",
+	"bufio.NewReadWriter":                           "bufio",
+	"bufio.NewReader":                               "bufio",
+	"bufio.NewReaderSize":                           "bufio",
+	"bufio.NewScanner":                              "bufio",
+	"bufio.NewWriter":                               "bufio",
+	"bufio.NewWriterSize":                           "bufio",
+	"bufio.ReadWriter":                              "bufio",
+	"bufio.Reader":                                  "bufio",
+	"bufio.ScanBytes":                               "bufio",
+	"bufio.ScanLines":                               "bufio",
+	"bufio.ScanRunes":                               "bufio",
+	"bufio.ScanWords":                               "bufio",
+	"bufio.Scanner":                                 "bufio",
+	"bufio.SplitFunc":                               "bufio",
+	"bufio.Writer":                                  "bufio",
+	"build.AllowBinary":                             "go/build",
+	"build.ArchChar":                                "go/build",
+	"build.Context":                                 "go/build",
+	"build.Default":                                 "go/build",
+	"build.FindOnly":                                "go/build",
+	"build.Import":                                  "go/build",
+	"build.ImportComment":                           "go/build",
+	"build.ImportDir":                               "go/build",
+	"build.ImportMode":                              "go/build",
+	"build.IsLocalImport":                           "go/build",
+	"build.MultiplePackageError":                    "go/build",
+	"build.NoGoError":                               "go/build",
+	"build.Package":                                 "go/build",
+	"build.ToolDir":                                 "go/build",
+	"bytes.Buffer":                                  "bytes",
+	"bytes.Compare":                                 "bytes",
+	"bytes.Contains":                                "bytes",
+	"bytes.Count":                                   "bytes",
+	"bytes.Equal":                                   "bytes",
+	"bytes.EqualFold":                               "bytes",
+	"bytes.ErrTooLarge":                             "bytes",
+	"bytes.Fields":                                  "bytes",
+	"bytes.FieldsFunc":                              "bytes",
+	"bytes.HasPrefix":                               "bytes",
+	"bytes.HasSuffix":                               "bytes",
+	"bytes.Index":                                   "bytes",
+	"bytes.IndexAny":                                "bytes",
+	"bytes.IndexByte":                               "bytes",
+	"bytes.IndexFunc":                               "bytes",
+	"bytes.IndexRune":                               "bytes",
+	"bytes.Join":                                    "bytes",
+	"bytes.LastIndex":                               "bytes",
+	"bytes.LastIndexAny":                            "bytes",
+	"bytes.LastIndexByte":                           "bytes",
+	"bytes.LastIndexFunc":                           "bytes",
+	"bytes.Map":                                     "bytes",
+	"bytes.MinRead":                                 "bytes",
+	"bytes.NewBuffer":                               "bytes",
+	"bytes.NewBufferString":                         "bytes",
+	"bytes.NewReader":                               "bytes",
+	"bytes.Reader":                                  "bytes",
+	"bytes.Repeat":                                  "bytes",
+	"bytes.Replace":                                 "bytes",
+	"bytes.Runes":                                   "bytes",
+	"bytes.Split":                                   "bytes",
+	"bytes.SplitAfter":                              "bytes",
+	"bytes.SplitAfterN":                             "bytes",
+	"bytes.SplitN":                                  "bytes",
+	"bytes.Title":                                   "bytes",
+	"bytes.ToLower":                                 "bytes",
+	"bytes.ToLowerSpecial":                          "bytes",
+	"bytes.ToTitle":                                 "bytes",
+	"bytes.ToTitleSpecial":                          "bytes",
+	"bytes.ToUpper":                                 "bytes",
+	"bytes.ToUpperSpecial":                          "bytes",
+	"bytes.Trim":                                    "bytes",
+	"bytes.TrimFunc":                                "bytes",
+	"bytes.TrimLeft":                                "bytes",
+	"bytes.TrimLeftFunc":                            "bytes",
+	"bytes.TrimPrefix":                              "bytes",
+	"bytes.TrimRight":                               "bytes",
+	"bytes.TrimRightFunc":                           "bytes",
+	"bytes.TrimSpace":                               "bytes",
+	"bytes.TrimSuffix":                              "bytes",
+	"bzip2.NewReader":                               "compress/bzip2",
+	"bzip2.StructuralError":                         "compress/bzip2",
+	"cgi.Handler":                                   "net/http/cgi",
+	"cgi.Request":                                   "net/http/cgi",
+	"cgi.RequestFromMap":                            "net/http/cgi",
+	"cgi.Serve":                                     "net/http/cgi",
+	"cipher.AEAD":                                   "crypto/cipher",
+	"cipher.Block":                                  "crypto/cipher",
+	"cipher.BlockMode":                              "crypto/cipher",
+	"cipher.NewCBCDecrypter":                        "crypto/cipher",
+	"cipher.NewCBCEncrypter":                        "crypto/cipher",
+	"cipher.NewCFBDecrypter":                        "crypto/cipher",
+	"cipher.NewCFBEncrypter":                        "crypto/cipher",
+	"cipher.NewCTR":                                 "crypto/cipher",
+	"cipher.NewGCM":                                 "crypto/cipher",
+	"cipher.NewGCMWithNonceSize":                    "crypto/cipher",
+	"cipher.NewOFB":                                 "crypto/cipher",
+	"cipher.Stream":                                 "crypto/cipher",
+	"cipher.StreamReader":                           "crypto/cipher",
+	"cipher.StreamWriter":                           "crypto/cipher",
+	"cmplx.Abs":                                     "math/cmplx",
+	"cmplx.Acos":                                    "math/cmplx",
+	"cmplx.Acosh":                                   "math/cmplx",
+	"cmplx.Asin":                                    "math/cmplx",
+	"cmplx.Asinh":                                   "math/cmplx",
+	"cmplx.Atan":                                    "math/cmplx",
+	"cmplx.Atanh":                                   "math/cmplx",
+	"cmplx.Conj":                                    "math/cmplx",
+	"cmplx.Cos":                                     "math/cmplx",
+	"cmplx.Cosh":                                    "math/cmplx",
+	"cmplx.Cot":                                     "math/cmplx",
+	"cmplx.Exp":                                     "math/cmplx",
+	"cmplx.Inf":                                     "math/cmplx",
+	"cmplx.IsInf":                                   "math/cmplx",
+	"cmplx.IsNaN":                                   "math/cmplx",
+	"cmplx.Log":                                     "math/cmplx",
+	"cmplx.Log10":                                   "math/cmplx",
+	"cmplx.NaN":                                     "math/cmplx",
+	"cmplx.Phase":                                   "math/cmplx",
+	"cmplx.Polar":                                   "math/cmplx",
+	"cmplx.Pow":                                     "math/cmplx",
+	"cmplx.Rect":                                    "math/cmplx",
+	"cmplx.Sin":                                     "math/cmplx",
+	"cmplx.Sinh":                                    "math/cmplx",
+	"cmplx.Sqrt":                                    "math/cmplx",
+	"cmplx.Tan":                                     "math/cmplx",
+	"cmplx.Tanh":                                    "math/cmplx",
+	"color.Alpha":                                   "image/color",
+	"color.Alpha16":                                 "image/color",
+	"color.Alpha16Model":                            "image/color",
+	"color.AlphaModel":                              "image/color",
+	"color.Black":                                   "image/color",
+	"color.CMYK":                                    "image/color",
+	"color.CMYKModel":                               "image/color",
+	"color.CMYKToRGB":                               "image/color",
+	"color.Color":                                   "image/color",
+	"color.Gray":                                    "image/color",
+	"color.Gray16":                                  "image/color",
+	"color.Gray16Model":                             "image/color",
+	"color.GrayModel":                               "image/color",
+	"color.Model":                                   "image/color",
+	"color.ModelFunc":                               "image/color",
+	"color.NRGBA":                                   "image/color",
+	"color.NRGBA64":                                 "image/color",
+	"color.NRGBA64Model":                            "image/color",
+	"color.NRGBAModel":                              "image/color",
+	"color.Opaque":                                  "image/color",
+	"color.Palette":                                 "image/color",
+	"color.RGBA":                                    "image/color",
+	"color.RGBA64":                                  "image/color",
+	"color.RGBA64Model":                             "image/color",
+	"color.RGBAModel":                               "image/color",
+	"color.RGBToCMYK":                               "image/color",
+	"color.RGBToYCbCr":                              "image/color",
+	"color.Transparent":                             "image/color",
+	"color.White":                                   "image/color",
+	"color.YCbCr":                                   "image/color",
+	"color.YCbCrModel":                              "image/color",
+	"color.YCbCrToRGB":                              "image/color",
+	"constant.BinaryOp":                             "go/constant",
+	"constant.BitLen":                               "go/constant",
+	"constant.Bool":                                 "go/constant",
+	"constant.BoolVal":                              "go/constant",
+	"constant.Bytes":                                "go/constant",
+	"constant.Compare":                              "go/constant",
+	"constant.Complex":                              "go/constant",
+	"constant.Denom":                                "go/constant",
+	"constant.Float":                                "go/constant",
+	"constant.Float32Val":                           "go/constant",
+	"constant.Float64Val":                           "go/constant",
+	"constant.Imag":                                 "go/constant",
+	"constant.Int":                                  "go/constant",
+	"constant.Int64Val":                             "go/constant",
+	"constant.Kind":                                 "go/constant",
+	"constant.MakeBool":                             "go/constant",
+	"constant.MakeFloat64":                          "go/constant",
+	"constant.MakeFromBytes":                        "go/constant",
+	"constant.MakeFromLiteral":                      "go/constant",
+	"constant.MakeImag":                             "go/constant",
+	"constant.MakeInt64":                            "go/constant",
+	"constant.MakeString":                           "go/constant",
+	"constant.MakeUint64":                           "go/constant",
+	"constant.MakeUnknown":                          "go/constant",
+	"constant.Num":                                  "go/constant",
+	"constant.Real":                                 "go/constant",
+	"constant.Shift":                                "go/constant",
+	"constant.Sign":                                 "go/constant",
+	"constant.String":                               "go/constant",
+	"constant.StringVal":                            "go/constant",
+	"constant.Uint64Val":                            "go/constant",
+	"constant.UnaryOp":                              "go/constant",
+	"constant.Unknown":                              "go/constant",
+	"cookiejar.Jar":                                 "net/http/cookiejar",
+	"cookiejar.New":                                 "net/http/cookiejar",
+	"cookiejar.Options":                             "net/http/cookiejar",
+	"cookiejar.PublicSuffixList":                    "net/http/cookiejar",
+	"crc32.Castagnoli":                              "hash/crc32",
+	"crc32.Checksum":                                "hash/crc32",
+	"crc32.ChecksumIEEE":                            "hash/crc32",
+	"crc32.IEEE":                                    "hash/crc32",
+	"crc32.IEEETable":                               "hash/crc32",
+	"crc32.Koopman":                                 "hash/crc32",
+	"crc32.MakeTable":                               "hash/crc32",
+	"crc32.New":                                     "hash/crc32",
+	"crc32.NewIEEE":                                 "hash/crc32",
+	"crc32.Size":                                    "hash/crc32",
+	"crc32.Table":                                   "hash/crc32",
+	"crc32.Update":                                  "hash/crc32",
+	"crc64.Checksum":                                "hash/crc64",
+	"crc64.ECMA":                                    "hash/crc64",
+	"crc64.ISO":                                     "hash/crc64",
+	"crc64.MakeTable":                               "hash/crc64",
+	"crc64.New":                                     "hash/crc64",
+	"crc64.Size":                                    "hash/crc64",
+	"crc64.Table":                                   "hash/crc64",
+	"crc64.Update":                                  "hash/crc64",
+	"crypto.Decrypter":                              "crypto",
+	"crypto.DecrypterOpts":                          "crypto",
+	"crypto.Hash":                                   "crypto",
+	"crypto.MD4":                                    "crypto",
+	"crypto.MD5":                                    "crypto",
+	"crypto.MD5SHA1":                                "crypto",
+	"crypto.PrivateKey":                             "crypto",
+	"crypto.PublicKey":                              "crypto",
+	"crypto.RIPEMD160":                              "crypto",
+	"crypto.RegisterHash":                           "crypto",
+	"crypto.SHA1":                                   "crypto",
+	"crypto.SHA224":                                 "crypto",
+	"crypto.SHA256":                                 "crypto",
+	"crypto.SHA384":                                 "crypto",
+	"crypto.SHA3_224":                               "crypto",
+	"crypto.SHA3_256":                               "crypto",
+	"crypto.SHA3_384":                               "crypto",
+	"crypto.SHA3_512":                               "crypto",
+	"crypto.SHA512":                                 "crypto",
+	"crypto.SHA512_224":                             "crypto",
+	"crypto.SHA512_256":                             "crypto",
+	"crypto.Signer":                                 "crypto",
+	"crypto.SignerOpts":                             "crypto",
+	"csv.ErrBareQuote":                              "encoding/csv",
+	"csv.ErrFieldCount":                             "encoding/csv",
+	"csv.ErrQuote":                                  "encoding/csv",
+	"csv.ErrTrailingComma":                          "encoding/csv",
+	"csv.NewReader":                                 "encoding/csv",
+	"csv.NewWriter":                                 "encoding/csv",
+	"csv.ParseError":                                "encoding/csv",
+	"csv.Reader":                                    "encoding/csv",
+	"csv.Writer":                                    "encoding/csv",
+	"debug.FreeOSMemory":                            "runtime/debug",
+	"debug.GCStats":                                 "runtime/debug",
+	"debug.PrintStack":                              "runtime/debug",
+	"debug.ReadGCStats":                             "runtime/debug",
+	"debug.SetGCPercent":                            "runtime/debug",
+	"debug.SetMaxStack":                             "runtime/debug",
+	"debug.SetMaxThreads":                           "runtime/debug",
+	"debug.SetPanicOnFault":                         "runtime/debug",
+	"debug.Stack":                                   "runtime/debug",
+	"debug.WriteHeapDump":                           "runtime/debug",
+	"des.BlockSize":                                 "crypto/des",
+	"des.KeySizeError":                              "crypto/des",
+	"des.NewCipher":                                 "crypto/des",
+	"des.NewTripleDESCipher":                        "crypto/des",
+	"doc.AllDecls":                                  "go/doc",
+	"doc.AllMethods":                                "go/doc",
+	"doc.Example":                                   "go/doc",
+	"doc.Examples":                                  "go/doc",
+	"doc.Filter":                                    "go/doc",
+	"doc.Func":                                      "go/doc",
+	"doc.IllegalPrefixes":                           "go/doc",
+	"doc.Mode":                                      "go/doc",
+	"doc.New":                                       "go/doc",
+	"doc.Note":                                      "go/doc",
+	"doc.Package":                                   "go/doc",
+	"doc.Synopsis":                                  "go/doc",
+	"doc.ToHTML":                                    "go/doc",
+	"doc.ToText":                                    "go/doc",
+	"doc.Type":                                      "go/doc",
+	"doc.Value":                                     "go/doc",
+	"draw.Draw":                                     "image/draw",
+	"draw.DrawMask":                                 "image/draw",
+	"draw.Drawer":                                   "image/draw",
+	"draw.FloydSteinberg":                           "image/draw",
+	"draw.Image":                                    "image/draw",
+	"draw.Op":                                       "image/draw",
+	"draw.Over":                                     "image/draw",
+	"draw.Quantizer":                                "image/draw",
+	"draw.Src":                                      "image/draw",
+	"driver.Bool":                                   "database/sql/driver",
+	"driver.ColumnConverter":                        "database/sql/driver",
+	"driver.Conn":                                   "database/sql/driver",
+	"driver.DefaultParameterConverter":              "database/sql/driver",
+	"driver.Driver":                                 "database/sql/driver",
+	"driver.ErrBadConn":                             "database/sql/driver",
+	"driver.ErrSkip":                                "database/sql/driver",
+	"driver.Execer":                                 "database/sql/driver",
+	"driver.Int32":                                  "database/sql/driver",
+	"driver.IsScanValue":                            "database/sql/driver",
+	"driver.IsValue":                                "database/sql/driver",
+	"driver.NotNull":                                "database/sql/driver",
+	"driver.Null":                                   "database/sql/driver",
+	"driver.Queryer":                                "database/sql/driver",
+	"driver.Result":                                 "database/sql/driver",
+	"driver.ResultNoRows":                           "database/sql/driver",
+	"driver.Rows":                                   "database/sql/driver",
+	"driver.RowsAffected":                           "database/sql/driver",
+	"driver.Stmt":                                   "database/sql/driver",
+	"driver.String":                                 "database/sql/driver",
+	"driver.Tx":                                     "database/sql/driver",
+	"driver.Value":                                  "database/sql/driver",
+	"driver.ValueConverter":                         "database/sql/driver",
+	"driver.Valuer":                                 "database/sql/driver",
+	"dsa.ErrInvalidPublicKey":                       "crypto/dsa",
+	"dsa.GenerateKey":                               "crypto/dsa",
+	"dsa.GenerateParameters":                        "crypto/dsa",
+	"dsa.L1024N160":                                 "crypto/dsa",
+	"dsa.L2048N224":                                 "crypto/dsa",
+	"dsa.L2048N256":                                 "crypto/dsa",
+	"dsa.L3072N256":                                 "crypto/dsa",
+	"dsa.ParameterSizes":                            "crypto/dsa",
+	"dsa.Parameters":                                "crypto/dsa",
+	"dsa.PrivateKey":                                "crypto/dsa",
+	"dsa.PublicKey":                                 "crypto/dsa",
+	"dsa.Sign":                                      "crypto/dsa",
+	"dsa.Verify":                                    "crypto/dsa",
+	"dwarf.AddrType":                                "debug/dwarf",
+	"dwarf.ArrayType":                               "debug/dwarf",
+	"dwarf.Attr":                                    "debug/dwarf",
+	"dwarf.AttrAbstractOrigin":                      "debug/dwarf",
+	"dwarf.AttrAccessibility":                       "debug/dwarf",
+	"dwarf.AttrAddrClass":                           "debug/dwarf",
+	"dwarf.AttrAllocated":                           "debug/dwarf",
+	"dwarf.AttrArtificial":                          "debug/dwarf",
+	"dwarf.AttrAssociated":                          "debug/dwarf",
+	"dwarf.AttrBaseTypes":                           "debug/dwarf",
+	"dwarf.AttrBitOffset":                           "debug/dwarf",
+	"dwarf.AttrBitSize":                             "debug/dwarf",
+	"dwarf.AttrByteSize":                            "debug/dwarf",
+	"dwarf.AttrCallColumn":                          "debug/dwarf",
+	"dwarf.AttrCallFile":                            "debug/dwarf",
+	"dwarf.AttrCallLine":                            "debug/dwarf",
+	"dwarf.AttrCalling":                             "debug/dwarf",
+	"dwarf.AttrCommonRef":                           "debug/dwarf",
+	"dwarf.AttrCompDir":                             "debug/dwarf",
+	"dwarf.AttrConstValue":                          "debug/dwarf",
+	"dwarf.AttrContainingType":                      "debug/dwarf",
+	"dwarf.AttrCount":                               "debug/dwarf",
+	"dwarf.AttrDataLocation":                        "debug/dwarf",
+	"dwarf.AttrDataMemberLoc":                       "debug/dwarf",
+	"dwarf.AttrDeclColumn":                          "debug/dwarf",
+	"dwarf.AttrDeclFile":                            "debug/dwarf",
+	"dwarf.AttrDeclLine":                            "debug/dwarf",
+	"dwarf.AttrDeclaration":                         "debug/dwarf",
+	"dwarf.AttrDefaultValue":                        "debug/dwarf",
+	"dwarf.AttrDescription":                         "debug/dwarf",
+	"dwarf.AttrDiscr":                               "debug/dwarf",
+	"dwarf.AttrDiscrList":                           "debug/dwarf",
+	"dwarf.AttrDiscrValue":                          "debug/dwarf",
+	"dwarf.AttrEncoding":                            "debug/dwarf",
+	"dwarf.AttrEntrypc":                             "debug/dwarf",
+	"dwarf.AttrExtension":                           "debug/dwarf",
+	"dwarf.AttrExternal":                            "debug/dwarf",
+	"dwarf.AttrFrameBase":                           "debug/dwarf",
+	"dwarf.AttrFriend":                              "debug/dwarf",
+	"dwarf.AttrHighpc":                              "debug/dwarf",
+	"dwarf.AttrIdentifierCase":                      "debug/dwarf",
+	"dwarf.AttrImport":                              "debug/dwarf",
+	"dwarf.AttrInline":                              "debug/dwarf",
+	"dwarf.AttrIsOptional":                          "debug/dwarf",
+	"dwarf.AttrLanguage":                            "debug/dwarf",
+	"dwarf.AttrLocation":                            "debug/dwarf",
+	"dwarf.AttrLowerBound":                          "debug/dwarf",
+	"dwarf.AttrLowpc":                               "debug/dwarf",
+	"dwarf.AttrMacroInfo":                           "debug/dwarf",
+	"dwarf.AttrName":                                "debug/dwarf",
+	"dwarf.AttrNamelistItem":                        "debug/dwarf",
+	"dwarf.AttrOrdering":                            "debug/dwarf",
+	"dwarf.AttrPriority":                            "debug/dwarf",
+	"dwarf.AttrProducer":                            "debug/dwarf",
+	"dwarf.AttrPrototyped":                          "debug/dwarf",
+	"dwarf.AttrRanges":                              "debug/dwarf",
+	"dwarf.AttrReturnAddr":                          "debug/dwarf",
+	"dwarf.AttrSegment":                             "debug/dwarf",
+	"dwarf.AttrSibling":                             "debug/dwarf",
+	"dwarf.AttrSpecification":                       "debug/dwarf",
+	"dwarf.AttrStartScope":                          "debug/dwarf",
+	"dwarf.AttrStaticLink":                          "debug/dwarf",
+	"dwarf.AttrStmtList":                            "debug/dwarf",
+	"dwarf.AttrStride":                              "debug/dwarf",
+	"dwarf.AttrStrideSize":                          "debug/dwarf",
+	"dwarf.AttrStringLength":                        "debug/dwarf",
+	"dwarf.AttrTrampoline":                          "debug/dwarf",
+	"dwarf.AttrType":                                "debug/dwarf",
+	"dwarf.AttrUpperBound":                          "debug/dwarf",
+	"dwarf.AttrUseLocation":                         "debug/dwarf",
+	"dwarf.AttrUseUTF8":                             "debug/dwarf",
+	"dwarf.AttrVarParam":                            "debug/dwarf",
+	"dwarf.AttrVirtuality":                          "debug/dwarf",
+	"dwarf.AttrVisibility":                          "debug/dwarf",
+	"dwarf.AttrVtableElemLoc":                       "debug/dwarf",
+	"dwarf.BasicType":                               "debug/dwarf",
+	"dwarf.BoolType":                                "debug/dwarf",
+	"dwarf.CharType":                                "debug/dwarf",
+	"dwarf.Class":                                   "debug/dwarf",
+	"dwarf.ClassAddress":                            "debug/dwarf",
+	"dwarf.ClassBlock":                              "debug/dwarf",
+	"dwarf.ClassConstant":                           "debug/dwarf",
+	"dwarf.ClassExprLoc":                            "debug/dwarf",
+	"dwarf.ClassFlag":                               "debug/dwarf",
+	"dwarf.ClassLinePtr":                            "debug/dwarf",
+	"dwarf.ClassLocListPtr":                         "debug/dwarf",
+	"dwarf.ClassMacPtr":                             "debug/dwarf",
+	"dwarf.ClassRangeListPtr":                       "debug/dwarf",
+	"dwarf.ClassReference":                          "debug/dwarf",
+	"dwarf.ClassReferenceAlt":                       "debug/dwarf",
+	"dwarf.ClassReferenceSig":                       "debug/dwarf",
+	"dwarf.ClassString":                             "debug/dwarf",
+	"dwarf.ClassStringAlt":                          "debug/dwarf",
+	"dwarf.CommonType":                              "debug/dwarf",
+	"dwarf.ComplexType":                             "debug/dwarf",
+	"dwarf.Data":                                    "debug/dwarf",
+	"dwarf.DecodeError":                             "debug/dwarf",
+	"dwarf.DotDotDotType":                           "debug/dwarf",
+	"dwarf.Entry":                                   "debug/dwarf",
+	"dwarf.EnumType":                                "debug/dwarf",
+	"dwarf.EnumValue":                               "debug/dwarf",
+	"dwarf.ErrUnknownPC":                            "debug/dwarf",
+	"dwarf.Field":                                   "debug/dwarf",
+	"dwarf.FloatType":                               "debug/dwarf",
+	"dwarf.FuncType":                                "debug/dwarf",
+	"dwarf.IntType":                                 "debug/dwarf",
+	"dwarf.LineEntry":                               "debug/dwarf",
+	"dwarf.LineFile":                                "debug/dwarf",
+	"dwarf.LineReader":                              "debug/dwarf",
+	"dwarf.LineReaderPos":                           "debug/dwarf",
+	"dwarf.New":                                     "debug/dwarf",
+	"dwarf.Offset":                                  "debug/dwarf",
+	"dwarf.PtrType":                                 "debug/dwarf",
+	"dwarf.QualType":                                "debug/dwarf",
+	"dwarf.Reader":                                  "debug/dwarf",
+	"dwarf.StructField":                             "debug/dwarf",
+	"dwarf.StructType":                              "debug/dwarf",
+	"dwarf.Tag":                                     "debug/dwarf",
+	"dwarf.TagAccessDeclaration":                    "debug/dwarf",
+	"dwarf.TagArrayType":                            "debug/dwarf",
+	"dwarf.TagBaseType":                             "debug/dwarf",
+	"dwarf.TagCatchDwarfBlock":                      "debug/dwarf",
+	"dwarf.TagClassType":                            "debug/dwarf",
+	"dwarf.TagCommonDwarfBlock":                     "debug/dwarf",
+	"dwarf.TagCommonInclusion":                      "debug/dwarf",
+	"dwarf.TagCompileUnit":                          "debug/dwarf",
+	"dwarf.TagCondition":                            "debug/dwarf",
+	"dwarf.TagConstType":                            "debug/dwarf",
+	"dwarf.TagConstant":                             "debug/dwarf",
+	"dwarf.TagDwarfProcedure":                       "debug/dwarf",
+	"dwarf.TagEntryPoint":                           "debug/dwarf",
+	"dwarf.TagEnumerationType":                      "debug/dwarf",
+	"dwarf.TagEnumerator":                           "debug/dwarf",
+	"dwarf.TagFileType":                             "debug/dwarf",
+	"dwarf.TagFormalParameter":                      "debug/dwarf",
+	"dwarf.TagFriend":                               "debug/dwarf",
+	"dwarf.TagImportedDeclaration":                  "debug/dwarf",
+	"dwarf.TagImportedModule":                       "debug/dwarf",
+	"dwarf.TagImportedUnit":                         "debug/dwarf",
+	"dwarf.TagInheritance":                          "debug/dwarf",
+	"dwarf.TagInlinedSubroutine":                    "debug/dwarf",
+	"dwarf.TagInterfaceType":                        "debug/dwarf",
+	"dwarf.TagLabel":                                "debug/dwarf",
+	"dwarf.TagLexDwarfBlock":                        "debug/dwarf",
+	"dwarf.TagMember":                               "debug/dwarf",
+	"dwarf.TagModule":                               "debug/dwarf",
+	"dwarf.TagMutableType":                          "debug/dwarf",
+	"dwarf.TagNamelist":                             "debug/dwarf",
+	"dwarf.TagNamelistItem":                         "debug/dwarf",
+	"dwarf.TagNamespace":                            "debug/dwarf",
+	"dwarf.TagPackedType":                           "debug/dwarf",
+	"dwarf.TagPartialUnit":                          "debug/dwarf",
+	"dwarf.TagPointerType":                          "debug/dwarf",
+	"dwarf.TagPtrToMemberType":                      "debug/dwarf",
+	"dwarf.TagReferenceType":                        "debug/dwarf",
+	"dwarf.TagRestrictType":                         "debug/dwarf",
+	"dwarf.TagRvalueReferenceType":                  "debug/dwarf",
+	"dwarf.TagSetType":                              "debug/dwarf",
+	"dwarf.TagSharedType":                           "debug/dwarf",
+	"dwarf.TagStringType":                           "debug/dwarf",
+	"dwarf.TagStructType":                           "debug/dwarf",
+	"dwarf.TagSubprogram":                           "debug/dwarf",
+	"dwarf.TagSubrangeType":                         "debug/dwarf",
+	"dwarf.TagSubroutineType":                       "debug/dwarf",
+	"dwarf.TagTemplateAlias":                        "debug/dwarf",
+	"dwarf.TagTemplateTypeParameter":                "debug/dwarf",
+	"dwarf.TagTemplateValueParameter":               "debug/dwarf",
+	"dwarf.TagThrownType":                           "debug/dwarf",
+	"dwarf.TagTryDwarfBlock":                        "debug/dwarf",
+	"dwarf.TagTypeUnit":                             "debug/dwarf",
+	"dwarf.TagTypedef":                              "debug/dwarf",
+	"dwarf.TagUnionType":                            "debug/dwarf",
+	"dwarf.TagUnspecifiedParameters":                "debug/dwarf",
+	"dwarf.TagUnspecifiedType":                      "debug/dwarf",
+	"dwarf.TagVariable":                             "debug/dwarf",
+	"dwarf.TagVariant":                              "debug/dwarf",
+	"dwarf.TagVariantPart":                          "debug/dwarf",
+	"dwarf.TagVolatileType":                         "debug/dwarf",
+	"dwarf.TagWithStmt":                             "debug/dwarf",
+	"dwarf.Type":                                    "debug/dwarf",
+	"dwarf.TypedefType":                             "debug/dwarf",
+	"dwarf.UcharType":                               "debug/dwarf",
+	"dwarf.UintType":                                "debug/dwarf",
+	"dwarf.UnspecifiedType":                         "debug/dwarf",
+	"dwarf.VoidType":                                "debug/dwarf",
+	"ecdsa.GenerateKey":                             "crypto/ecdsa",
+	"ecdsa.PrivateKey":                              "crypto/ecdsa",
+	"ecdsa.PublicKey":                               "crypto/ecdsa",
+	"ecdsa.Sign":                                    "crypto/ecdsa",
+	"ecdsa.Verify":                                  "crypto/ecdsa",
+	"elf.ARM_MAGIC_TRAMP_NUMBER":                    "debug/elf",
+	"elf.Class":                                     "debug/elf",
+	"elf.DF_BIND_NOW":                               "debug/elf",
+	"elf.DF_ORIGIN":                                 "debug/elf",
+	"elf.DF_STATIC_TLS":                             "debug/elf",
+	"elf.DF_SYMBOLIC":                               "debug/elf",
+	"elf.DF_TEXTREL":                                "debug/elf",
+	"elf.DT_BIND_NOW":                               "debug/elf",
+	"elf.DT_DEBUG":                                  "debug/elf",
+	"elf.DT_ENCODING":                               "debug/elf",
+	"elf.DT_FINI":                                   "debug/elf",
+	"elf.DT_FINI_ARRAY":                             "debug/elf",
+	"elf.DT_FINI_ARRAYSZ":                           "debug/elf",
+	"elf.DT_FLAGS":                                  "debug/elf",
+	"elf.DT_HASH":                                   "debug/elf",
+	"elf.DT_HIOS":                                   "debug/elf",
+	"elf.DT_HIPROC":                                 "debug/elf",
+	"elf.DT_INIT":                                   "debug/elf",
+	"elf.DT_INIT_ARRAY":                             "debug/elf",
+	"elf.DT_INIT_ARRAYSZ":                           "debug/elf",
+	"elf.DT_JMPREL":                                 "debug/elf",
+	"elf.DT_LOOS":                                   "debug/elf",
+	"elf.DT_LOPROC":                                 "debug/elf",
+	"elf.DT_NEEDED":                                 "debug/elf",
+	"elf.DT_NULL":                                   "debug/elf",
+	"elf.DT_PLTGOT":                                 "debug/elf",
+	"elf.DT_PLTREL":                                 "debug/elf",
+	"elf.DT_PLTRELSZ":                               "debug/elf",
+	"elf.DT_PREINIT_ARRAY":                          "debug/elf",
+	"elf.DT_PREINIT_ARRAYSZ":                        "debug/elf",
+	"elf.DT_REL":                                    "debug/elf",
+	"elf.DT_RELA":                                   "debug/elf",
+	"elf.DT_RELAENT":                                "debug/elf",
+	"elf.DT_RELASZ":                                 "debug/elf",
+	"elf.DT_RELENT":                                 "debug/elf",
+	"elf.DT_RELSZ":                                  "debug/elf",
+	"elf.DT_RPATH":                                  "debug/elf",
+	"elf.DT_RUNPATH":                                "debug/elf",
+	"elf.DT_SONAME":                                 "debug/elf",
+	"elf.DT_STRSZ":                                  "debug/elf",
+	"elf.DT_STRTAB":                                 "debug/elf",
+	"elf.DT_SYMBOLIC":                               "debug/elf",
+	"elf.DT_SYMENT":                                 "debug/elf",
+	"elf.DT_SYMTAB":                                 "debug/elf",
+	"elf.DT_TEXTREL":                                "debug/elf",
+	"elf.DT_VERNEED":                                "debug/elf",
+	"elf.DT_VERNEEDNUM":                             "debug/elf",
+	"elf.DT_VERSYM":                                 "debug/elf",
+	"elf.Data":                                      "debug/elf",
+	"elf.Dyn32":                                     "debug/elf",
+	"elf.Dyn64":                                     "debug/elf",
+	"elf.DynFlag":                                   "debug/elf",
+	"elf.DynTag":                                    "debug/elf",
+	"elf.EI_ABIVERSION":                             "debug/elf",
+	"elf.EI_CLASS":                                  "debug/elf",
+	"elf.EI_DATA":                                   "debug/elf",
+	"elf.EI_NIDENT":                                 "debug/elf",
+	"elf.EI_OSABI":                                  "debug/elf",
+	"elf.EI_PAD":                                    "debug/elf",
+	"elf.EI_VERSION":                                "debug/elf",
+	"elf.ELFCLASS32":                                "debug/elf",
+	"elf.ELFCLASS64":                                "debug/elf",
+	"elf.ELFCLASSNONE":                              "debug/elf",
+	"elf.ELFDATA2LSB":                               "debug/elf",
+	"elf.ELFDATA2MSB":                               "debug/elf",
+	"elf.ELFDATANONE":                               "debug/elf",
+	"elf.ELFMAG":                                    "debug/elf",
+	"elf.ELFOSABI_86OPEN":                           "debug/elf",
+	"elf.ELFOSABI_AIX":                              "debug/elf",
+	"elf.ELFOSABI_ARM":                              "debug/elf",
+	"elf.ELFOSABI_FREEBSD":                          "debug/elf",
+	"elf.ELFOSABI_HPUX":                             "debug/elf",
+	"elf.ELFOSABI_HURD":                             "debug/elf",
+	"elf.ELFOSABI_IRIX":                             "debug/elf",
+	"elf.ELFOSABI_LINUX":                            "debug/elf",
+	"elf.ELFOSABI_MODESTO":                          "debug/elf",
+	"elf.ELFOSABI_NETBSD":                           "debug/elf",
+	"elf.ELFOSABI_NONE":                             "debug/elf",
+	"elf.ELFOSABI_NSK":                              "debug/elf",
+	"elf.ELFOSABI_OPENBSD":                          "debug/elf",
+	"elf.ELFOSABI_OPENVMS":                          "debug/elf",
+	"elf.ELFOSABI_SOLARIS":                          "debug/elf",
+	"elf.ELFOSABI_STANDALONE":                       "debug/elf",
+	"elf.ELFOSABI_TRU64":                            "debug/elf",
+	"elf.EM_386":                                    "debug/elf",
+	"elf.EM_486":                                    "debug/elf",
+	"elf.EM_68HC12":                                 "debug/elf",
+	"elf.EM_68K":                                    "debug/elf",
+	"elf.EM_860":                                    "debug/elf",
+	"elf.EM_88K":                                    "debug/elf",
+	"elf.EM_960":                                    "debug/elf",
+	"elf.EM_AARCH64":                                "debug/elf",
+	"elf.EM_ALPHA":                                  "debug/elf",
+	"elf.EM_ALPHA_STD":                              "debug/elf",
+	"elf.EM_ARC":                                    "debug/elf",
+	"elf.EM_ARM":                                    "debug/elf",
+	"elf.EM_COLDFIRE":                               "debug/elf",
+	"elf.EM_FR20":                                   "debug/elf",
+	"elf.EM_H8S":                                    "debug/elf",
+	"elf.EM_H8_300":                                 "debug/elf",
+	"elf.EM_H8_300H":                                "debug/elf",
+	"elf.EM_H8_500":                                 "debug/elf",
+	"elf.EM_IA_64":                                  "debug/elf",
+	"elf.EM_M32":                                    "debug/elf",
+	"elf.EM_ME16":                                   "debug/elf",
+	"elf.EM_MIPS":                                   "debug/elf",
+	"elf.EM_MIPS_RS3_LE":                            "debug/elf",
+	"elf.EM_MIPS_RS4_BE":                            "debug/elf",
+	"elf.EM_MIPS_X":                                 "debug/elf",
+	"elf.EM_MMA":                                    "debug/elf",
+	"elf.EM_NCPU":                                   "debug/elf",
+	"elf.EM_NDR1":                                   "debug/elf",
+	"elf.EM_NONE":                                   "debug/elf",
+	"elf.EM_PARISC":                                 "debug/elf",
+	"elf.EM_PCP":                                    "debug/elf",
+	"elf.EM_PPC":                                    "debug/elf",
+	"elf.EM_PPC64":                                  "debug/elf",
+	"elf.EM_RCE":                                    "debug/elf",
+	"elf.EM_RH32":                                   "debug/elf",
+	"elf.EM_S370":                                   "debug/elf",
+	"elf.EM_S390":                                   "debug/elf",
+	"elf.EM_SH":                                     "debug/elf",
+	"elf.EM_SPARC":                                  "debug/elf",
+	"elf.EM_SPARC32PLUS":                            "debug/elf",
+	"elf.EM_SPARCV9":                                "debug/elf",
+	"elf.EM_ST100":                                  "debug/elf",
+	"elf.EM_STARCORE":                               "debug/elf",
+	"elf.EM_TINYJ":                                  "debug/elf",
+	"elf.EM_TRICORE":                                "debug/elf",
+	"elf.EM_V800":                                   "debug/elf",
+	"elf.EM_VPP500":                                 "debug/elf",
+	"elf.EM_X86_64":                                 "debug/elf",
+	"elf.ET_CORE":                                   "debug/elf",
+	"elf.ET_DYN":                                    "debug/elf",
+	"elf.ET_EXEC":                                   "debug/elf",
+	"elf.ET_HIOS":                                   "debug/elf",
+	"elf.ET_HIPROC":                                 "debug/elf",
+	"elf.ET_LOOS":                                   "debug/elf",
+	"elf.ET_LOPROC":                                 "debug/elf",
+	"elf.ET_NONE":                                   "debug/elf",
+	"elf.ET_REL":                                    "debug/elf",
+	"elf.EV_CURRENT":                                "debug/elf",
+	"elf.EV_NONE":                                   "debug/elf",
+	"elf.ErrNoSymbols":                              "debug/elf",
+	"elf.File":                                      "debug/elf",
+	"elf.FileHeader":                                "debug/elf",
+	"elf.FormatError":                               "debug/elf",
+	"elf.Header32":                                  "debug/elf",
+	"elf.Header64":                                  "debug/elf",
+	"elf.ImportedSymbol":                            "debug/elf",
+	"elf.Machine":                                   "debug/elf",
+	"elf.NT_FPREGSET":                               "debug/elf",
+	"elf.NT_PRPSINFO":                               "debug/elf",
+	"elf.NT_PRSTATUS":                               "debug/elf",
+	"elf.NType":                                     "debug/elf",
+	"elf.NewFile":                                   "debug/elf",
+	"elf.OSABI":                                     "debug/elf",
+	"elf.Open":                                      "debug/elf",
+	"elf.PF_MASKOS":                                 "debug/elf",
+	"elf.PF_MASKPROC":                               "debug/elf",
+	"elf.PF_R":                                      "debug/elf",
+	"elf.PF_W":                                      "debug/elf",
+	"elf.PF_X":                                      "debug/elf",
+	"elf.PT_DYNAMIC":                                "debug/elf",
+	"elf.PT_HIOS":                                   "debug/elf",
+	"elf.PT_HIPROC":                                 "debug/elf",
+	"elf.PT_INTERP":                                 "debug/elf",
+	"elf.PT_LOAD":                                   "debug/elf",
+	"elf.PT_LOOS":                                   "debug/elf",
+	"elf.PT_LOPROC":                                 "debug/elf",
+	"elf.PT_NOTE":                                   "debug/elf",
+	"elf.PT_NULL":                                   "debug/elf",
+	"elf.PT_PHDR":                                   "debug/elf",
+	"elf.PT_SHLIB":                                  "debug/elf",
+	"elf.PT_TLS":                                    "debug/elf",
+	"elf.Prog":                                      "debug/elf",
+	"elf.Prog32":                                    "debug/elf",
+	"elf.Prog64":                                    "debug/elf",
+	"elf.ProgFlag":                                  "debug/elf",
+	"elf.ProgHeader":                                "debug/elf",
+	"elf.ProgType":                                  "debug/elf",
+	"elf.R_386":                                     "debug/elf",
+	"elf.R_386_32":                                  "debug/elf",
+	"elf.R_386_COPY":                                "debug/elf",
+	"elf.R_386_GLOB_DAT":                            "debug/elf",
+	"elf.R_386_GOT32":                               "debug/elf",
+	"elf.R_386_GOTOFF":                              "debug/elf",
+	"elf.R_386_GOTPC":                               "debug/elf",
+	"elf.R_386_JMP_SLOT":                            "debug/elf",
+	"elf.R_386_NONE":                                "debug/elf",
+	"elf.R_386_PC32":                                "debug/elf",
+	"elf.R_386_PLT32":                               "debug/elf",
+	"elf.R_386_RELATIVE":                            "debug/elf",
+	"elf.R_386_TLS_DTPMOD32":                        "debug/elf",
+	"elf.R_386_TLS_DTPOFF32":                        "debug/elf",
+	"elf.R_386_TLS_GD":                              "debug/elf",
+	"elf.R_386_TLS_GD_32":                           "debug/elf",
+	"elf.R_386_TLS_GD_CALL":                         "debug/elf",
+	"elf.R_386_TLS_GD_POP":                          "debug/elf",
+	"elf.R_386_TLS_GD_PUSH":                         "debug/elf",
+	"elf.R_386_TLS_GOTIE":                           "debug/elf",
+	"elf.R_386_TLS_IE":                              "debug/elf",
+	"elf.R_386_TLS_IE_32":                           "debug/elf",
+	"elf.R_386_TLS_LDM":                             "debug/elf",
+	"elf.R_386_TLS_LDM_32":                          "debug/elf",
+	"elf.R_386_TLS_LDM_CALL":                        "debug/elf",
+	"elf.R_386_TLS_LDM_POP":                         "debug/elf",
+	"elf.R_386_TLS_LDM_PUSH":                        "debug/elf",
+	"elf.R_386_TLS_LDO_32":                          "debug/elf",
+	"elf.R_386_TLS_LE":                              "debug/elf",
+	"elf.R_386_TLS_LE_32":                           "debug/elf",
+	"elf.R_386_TLS_TPOFF":                           "debug/elf",
+	"elf.R_386_TLS_TPOFF32":                         "debug/elf",
+	"elf.R_AARCH64":                                 "debug/elf",
+	"elf.R_AARCH64_ABS16":                           "debug/elf",
+	"elf.R_AARCH64_ABS32":                           "debug/elf",
+	"elf.R_AARCH64_ABS64":                           "debug/elf",
+	"elf.R_AARCH64_ADD_ABS_LO12_NC":                 "debug/elf",
+	"elf.R_AARCH64_ADR_GOT_PAGE":                    "debug/elf",
+	"elf.R_AARCH64_ADR_PREL_LO21":                   "debug/elf",
+	"elf.R_AARCH64_ADR_PREL_PG_HI21":                "debug/elf",
+	"elf.R_AARCH64_ADR_PREL_PG_HI21_NC":             "debug/elf",
+	"elf.R_AARCH64_CALL26":                          "debug/elf",
+	"elf.R_AARCH64_CONDBR19":                        "debug/elf",
+	"elf.R_AARCH64_COPY":                            "debug/elf",
+	"elf.R_AARCH64_GLOB_DAT":                        "debug/elf",
+	"elf.R_AARCH64_GOT_LD_PREL19":                   "debug/elf",
+	"elf.R_AARCH64_IRELATIVE":                       "debug/elf",
+	"elf.R_AARCH64_JUMP26":                          "debug/elf",
+	"elf.R_AARCH64_JUMP_SLOT":                       "debug/elf",
+	"elf.R_AARCH64_LD64_GOT_LO12_NC":                "debug/elf",
+	"elf.R_AARCH64_LDST128_ABS_LO12_NC":             "debug/elf",
+	"elf.R_AARCH64_LDST16_ABS_LO12_NC":              "debug/elf",
+	"elf.R_AARCH64_LDST32_ABS_LO12_NC":              "debug/elf",
+	"elf.R_AARCH64_LDST64_ABS_LO12_NC":              "debug/elf",
+	"elf.R_AARCH64_LDST8_ABS_LO12_NC":               "debug/elf",
+	"elf.R_AARCH64_LD_PREL_LO19":                    "debug/elf",
+	"elf.R_AARCH64_MOVW_SABS_G0":                    "debug/elf",
+	"elf.R_AARCH64_MOVW_SABS_G1":                    "debug/elf",
+	"elf.R_AARCH64_MOVW_SABS_G2":                    "debug/elf",
+	"elf.R_AARCH64_MOVW_UABS_G0":                    "debug/elf",
+	"elf.R_AARCH64_MOVW_UABS_G0_NC":                 "debug/elf",
+	"elf.R_AARCH64_MOVW_UABS_G1":                    "debug/elf",
+	"elf.R_AARCH64_MOVW_UABS_G1_NC":                 "debug/elf",
+	"elf.R_AARCH64_MOVW_UABS_G2":                    "debug/elf",
+	"elf.R_AARCH64_MOVW_UABS_G2_NC":                 "debug/elf",
+	"elf.R_AARCH64_MOVW_UABS_G3":                    "debug/elf",
+	"elf.R_AARCH64_NONE":                            "debug/elf",
+	"elf.R_AARCH64_NULL":                            "debug/elf",
+	"elf.R_AARCH64_P32_ABS16":                       "debug/elf",
+	"elf.R_AARCH64_P32_ABS32":                       "debug/elf",
+	"elf.R_AARCH64_P32_ADD_ABS_LO12_NC":             "debug/elf",
+	"elf.R_AARCH64_P32_ADR_GOT_PAGE":                "debug/elf",
+	"elf.R_AARCH64_P32_ADR_PREL_LO21":               "debug/elf",
+	"elf.R_AARCH64_P32_ADR_PREL_PG_HI21":            "debug/elf",
+	"elf.R_AARCH64_P32_CALL26":                      "debug/elf",
+	"elf.R_AARCH64_P32_CONDBR19":                    "debug/elf",
+	"elf.R_AARCH64_P32_COPY":                        "debug/elf",
+	"elf.R_AARCH64_P32_GLOB_DAT":                    "debug/elf",
+	"elf.R_AARCH64_P32_GOT_LD_PREL19":               "debug/elf",
+	"elf.R_AARCH64_P32_IRELATIVE":                   "debug/elf",
+	"elf.R_AARCH64_P32_JUMP26":                      "debug/elf",
+	"elf.R_AARCH64_P32_JUMP_SLOT":                   "debug/elf",
+	"elf.R_AARCH64_P32_LD32_GOT_LO12_NC":            "debug/elf",
+	"elf.R_AARCH64_P32_LDST128_ABS_LO12_NC":         "debug/elf",
+	"elf.R_AARCH64_P32_LDST16_ABS_LO12_NC":          "debug/elf",
+	"elf.R_AARCH64_P32_LDST32_ABS_LO12_NC":          "debug/elf",
+	"elf.R_AARCH64_P32_LDST64_ABS_LO12_NC":          "debug/elf",
+	"elf.R_AARCH64_P32_LDST8_ABS_LO12_NC":           "debug/elf",
+	"elf.R_AARCH64_P32_LD_PREL_LO19":                "debug/elf",
+	"elf.R_AARCH64_P32_MOVW_SABS_G0":                "debug/elf",
+	"elf.R_AARCH64_P32_MOVW_UABS_G0":                "debug/elf",
+	"elf.R_AARCH64_P32_MOVW_UABS_G0_NC":             "debug/elf",
+	"elf.R_AARCH64_P32_MOVW_UABS_G1":                "debug/elf",
+	"elf.R_AARCH64_P32_PREL16":                      "debug/elf",
+	"elf.R_AARCH64_P32_PREL32":                      "debug/elf",
+	"elf.R_AARCH64_P32_RELATIVE":                    "debug/elf",
+	"elf.R_AARCH64_P32_TLSDESC":                     "debug/elf",
+	"elf.R_AARCH64_P32_TLSDESC_ADD_LO12_NC":         "debug/elf",
+	"elf.R_AARCH64_P32_TLSDESC_ADR_PAGE21":          "debug/elf",
+	"elf.R_AARCH64_P32_TLSDESC_ADR_PREL21":          "debug/elf",
+	"elf.R_AARCH64_P32_TLSDESC_CALL":                "debug/elf",
+	"elf.R_AARCH64_P32_TLSDESC_LD32_LO12_NC":        "debug/elf",
+	"elf.R_AARCH64_P32_TLSDESC_LD_PREL19":           "debug/elf",
+	"elf.R_AARCH64_P32_TLSGD_ADD_LO12_NC":           "debug/elf",
+	"elf.R_AARCH64_P32_TLSGD_ADR_PAGE21":            "debug/elf",
+	"elf.R_AARCH64_P32_TLSIE_ADR_GOTTPREL_PAGE21":   "debug/elf",
+	"elf.R_AARCH64_P32_TLSIE_LD32_GOTTPREL_LO12_NC": "debug/elf",
+	"elf.R_AARCH64_P32_TLSIE_LD_GOTTPREL_PREL19":    "debug/elf",
+	"elf.R_AARCH64_P32_TLSLE_ADD_TPREL_HI12":        "debug/elf",
+	"elf.R_AARCH64_P32_TLSLE_ADD_TPREL_LO12":        "debug/elf",
+	"elf.R_AARCH64_P32_TLSLE_ADD_TPREL_LO12_NC":     "debug/elf",
+	"elf.R_AARCH64_P32_TLSLE_MOVW_TPREL_G0":         "debug/elf",
+	"elf.R_AARCH64_P32_TLSLE_MOVW_TPREL_G0_NC":      "debug/elf",
+	"elf.R_AARCH64_P32_TLSLE_MOVW_TPREL_G1":         "debug/elf",
+	"elf.R_AARCH64_P32_TLS_DTPMOD":                  "debug/elf",
+	"elf.R_AARCH64_P32_TLS_DTPREL":                  "debug/elf",
+	"elf.R_AARCH64_P32_TLS_TPREL":                   "debug/elf",
+	"elf.R_AARCH64_P32_TSTBR14":                     "debug/elf",
+	"elf.R_AARCH64_PREL16":                          "debug/elf",
+	"elf.R_AARCH64_PREL32":                          "debug/elf",
+	"elf.R_AARCH64_PREL64":                          "debug/elf",
+	"elf.R_AARCH64_RELATIVE":                        "debug/elf",
+	"elf.R_AARCH64_TLSDESC":                         "debug/elf",
+	"elf.R_AARCH64_TLSDESC_ADD":                     "debug/elf",
+	"elf.R_AARCH64_TLSDESC_ADD_LO12_NC":             "debug/elf",
+	"elf.R_AARCH64_TLSDESC_ADR_PAGE21":              "debug/elf",
+	"elf.R_AARCH64_TLSDESC_ADR_PREL21":              "debug/elf",
+	"elf.R_AARCH64_TLSDESC_CALL":                    "debug/elf",
+	"elf.R_AARCH64_TLSDESC_LD64_LO12_NC":            "debug/elf",
+	"elf.R_AARCH64_TLSDESC_LDR":                     "debug/elf",
+	"elf.R_AARCH64_TLSDESC_LD_PREL19":               "debug/elf",
+	"elf.R_AARCH64_TLSDESC_OFF_G0_NC":               "debug/elf",
+	"elf.R_AARCH64_TLSDESC_OFF_G1":                  "debug/elf",
+	"elf.R_AARCH64_TLSGD_ADD_LO12_NC":               "debug/elf",
+	"elf.R_AARCH64_TLSGD_ADR_PAGE21":                "debug/elf",
+	"elf.R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21":       "debug/elf",
+	"elf.R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC":     "debug/elf",
+	"elf.R_AARCH64_TLSIE_LD_GOTTPREL_PREL19":        "debug/elf",
+	"elf.R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC":       "debug/elf",
+	"elf.R_AARCH64_TLSIE_MOVW_GOTTPREL_G1":          "debug/elf",
+	"elf.R_AARCH64_TLSLE_ADD_TPREL_HI12":            "debug/elf",
+	"elf.R_AARCH64_TLSLE_ADD_TPREL_LO12":            "debug/elf",
+	"elf.R_AARCH64_TLSLE_ADD_TPREL_LO12_NC":         "debug/elf",
+	"elf.R_AARCH64_TLSLE_MOVW_TPREL_G0":             "debug/elf",
+	"elf.R_AARCH64_TLSLE_MOVW_TPREL_G0_NC":          "debug/elf",
+	"elf.R_AARCH64_TLSLE_MOVW_TPREL_G1":             "debug/elf",
+	"elf.R_AARCH64_TLSLE_MOVW_TPREL_G1_NC":          "debug/elf",
+	"elf.R_AARCH64_TLSLE_MOVW_TPREL_G2":             "debug/elf",
+	"elf.R_AARCH64_TLS_DTPMOD64":                    "debug/elf",
+	"elf.R_AARCH64_TLS_DTPREL64":                    "debug/elf",
+	"elf.R_AARCH64_TLS_TPREL64":                     "debug/elf",
+	"elf.R_AARCH64_TSTBR14":                         "debug/elf",
+	"elf.R_ALPHA":                                   "debug/elf",
+	"elf.R_ALPHA_BRADDR":                            "debug/elf",
+	"elf.R_ALPHA_COPY":                              "debug/elf",
+	"elf.R_ALPHA_GLOB_DAT":                          "debug/elf",
+	"elf.R_ALPHA_GPDISP":                            "debug/elf",
+	"elf.R_ALPHA_GPREL32":                           "debug/elf",
+	"elf.R_ALPHA_GPRELHIGH":                         "debug/elf",
+	"elf.R_ALPHA_GPRELLOW":                          "debug/elf",
+	"elf.R_ALPHA_GPVALUE":                           "debug/elf",
+	"elf.R_ALPHA_HINT":                              "debug/elf",
+	"elf.R_ALPHA_IMMED_BR_HI32":                     "debug/elf",
+	"elf.R_ALPHA_IMMED_GP_16":                       "debug/elf",
+	"elf.R_ALPHA_IMMED_GP_HI32":                     "debug/elf",
+	"elf.R_ALPHA_IMMED_LO32":                        "debug/elf",
+	"elf.R_ALPHA_IMMED_SCN_HI32":                    "debug/elf",
+	"elf.R_ALPHA_JMP_SLOT":                          "debug/elf",
+	"elf.R_ALPHA_LITERAL":                           "debug/elf",
+	"elf.R_ALPHA_LITUSE":                            "debug/elf",
+	"elf.R_ALPHA_NONE":                              "debug/elf",
+	"elf.R_ALPHA_OP_PRSHIFT":                        "debug/elf",
+	"elf.R_ALPHA_OP_PSUB":                           "debug/elf",
+	"elf.R_ALPHA_OP_PUSH":                           "debug/elf",
+	"elf.R_ALPHA_OP_STORE":                          "debug/elf",
+	"elf.R_ALPHA_REFLONG":                           "debug/elf",
+	"elf.R_ALPHA_REFQUAD":                           "debug/elf",
+	"elf.R_ALPHA_RELATIVE":                          "debug/elf",
+	"elf.R_ALPHA_SREL16":                            "debug/elf",
+	"elf.R_ALPHA_SREL32":                            "debug/elf",
+	"elf.R_ALPHA_SREL64":                            "debug/elf",
+	"elf.R_ARM":                                     "debug/elf",
+	"elf.R_ARM_ABS12":                               "debug/elf",
+	"elf.R_ARM_ABS16":                               "debug/elf",
+	"elf.R_ARM_ABS32":                               "debug/elf",
+	"elf.R_ARM_ABS8":                                "debug/elf",
+	"elf.R_ARM_AMP_VCALL9":                          "debug/elf",
+	"elf.R_ARM_COPY":                                "debug/elf",
+	"elf.R_ARM_GLOB_DAT":                            "debug/elf",
+	"elf.R_ARM_GNU_VTENTRY":                         "debug/elf",
+	"elf.R_ARM_GNU_VTINHERIT":                       "debug/elf",
+	"elf.R_ARM_GOT32":                               "debug/elf",
+	"elf.R_ARM_GOTOFF":                              "debug/elf",
+	"elf.R_ARM_GOTPC":                               "debug/elf",
+	"elf.R_ARM_JUMP_SLOT":                           "debug/elf",
+	"elf.R_ARM_NONE":                                "debug/elf",
+	"elf.R_ARM_PC13":                                "debug/elf",
+	"elf.R_ARM_PC24":                                "debug/elf",
+	"elf.R_ARM_PLT32":                               "debug/elf",
+	"elf.R_ARM_RABS32":                              "debug/elf",
+	"elf.R_ARM_RBASE":                               "debug/elf",
+	"elf.R_ARM_REL32":                               "debug/elf",
+	"elf.R_ARM_RELATIVE":                            "debug/elf",
+	"elf.R_ARM_RPC24":                               "debug/elf",
+	"elf.R_ARM_RREL32":                              "debug/elf",
+	"elf.R_ARM_RSBREL32":                            "debug/elf",
+	"elf.R_ARM_SBREL32":                             "debug/elf",
+	"elf.R_ARM_SWI24":                               "debug/elf",
+	"elf.R_ARM_THM_ABS5":                            "debug/elf",
+	"elf.R_ARM_THM_PC22":                            "debug/elf",
+	"elf.R_ARM_THM_PC8":                             "debug/elf",
+	"elf.R_ARM_THM_RPC22":                           "debug/elf",
+	"elf.R_ARM_THM_SWI8":                            "debug/elf",
+	"elf.R_ARM_THM_XPC22":                           "debug/elf",
+	"elf.R_ARM_XPC25":                               "debug/elf",
+	"elf.R_INFO":                                    "debug/elf",
+	"elf.R_INFO32":                                  "debug/elf",
+	"elf.R_PPC":                                     "debug/elf",
+	"elf.R_PPC64":                                   "debug/elf",
+	"elf.R_PPC64_ADDR14":                            "debug/elf",
+	"elf.R_PPC64_ADDR14_BRNTAKEN":                   "debug/elf",
+	"elf.R_PPC64_ADDR14_BRTAKEN":                    "debug/elf",
+	"elf.R_PPC64_ADDR16":                            "debug/elf",
+	"elf.R_PPC64_ADDR16_DS":                         "debug/elf",
+	"elf.R_PPC64_ADDR16_HA":                         "debug/elf",
+	"elf.R_PPC64_ADDR16_HI":                         "debug/elf",
+	"elf.R_PPC64_ADDR16_HIGHER":                     "debug/elf",
+	"elf.R_PPC64_ADDR16_HIGHERA":                    "debug/elf",
+	"elf.R_PPC64_ADDR16_HIGHEST":                    "debug/elf",
+	"elf.R_PPC64_ADDR16_HIGHESTA":                   "debug/elf",
+	"elf.R_PPC64_ADDR16_LO":                         "debug/elf",
+	"elf.R_PPC64_ADDR16_LO_DS":                      "debug/elf",
+	"elf.R_PPC64_ADDR24":                            "debug/elf",
+	"elf.R_PPC64_ADDR32":                            "debug/elf",
+	"elf.R_PPC64_ADDR64":                            "debug/elf",
+	"elf.R_PPC64_DTPMOD64":                          "debug/elf",
+	"elf.R_PPC64_DTPREL16":                          "debug/elf",
+	"elf.R_PPC64_DTPREL16_DS":                       "debug/elf",
+	"elf.R_PPC64_DTPREL16_HA":                       "debug/elf",
+	"elf.R_PPC64_DTPREL16_HI":                       "debug/elf",
+	"elf.R_PPC64_DTPREL16_HIGHER":                   "debug/elf",
+	"elf.R_PPC64_DTPREL16_HIGHERA":                  "debug/elf",
+	"elf.R_PPC64_DTPREL16_HIGHEST":                  "debug/elf",
+	"elf.R_PPC64_DTPREL16_HIGHESTA":                 "debug/elf",
+	"elf.R_PPC64_DTPREL16_LO":                       "debug/elf",
+	"elf.R_PPC64_DTPREL16_LO_DS":                    "debug/elf",
+	"elf.R_PPC64_DTPREL64":                          "debug/elf",
+	"elf.R_PPC64_GOT16":                             "debug/elf",
+	"elf.R_PPC64_GOT16_DS":                          "debug/elf",
+	"elf.R_PPC64_GOT16_HA":                          "debug/elf",
+	"elf.R_PPC64_GOT16_HI":                          "debug/elf",
+	"elf.R_PPC64_GOT16_LO":                          "debug/elf",
+	"elf.R_PPC64_GOT16_LO_DS":                       "debug/elf",
+	"elf.R_PPC64_GOT_DTPREL16_DS":                   "debug/elf",
+	"elf.R_PPC64_GOT_DTPREL16_HA":                   "debug/elf",
+	"elf.R_PPC64_GOT_DTPREL16_HI":                   "debug/elf",
+	"elf.R_PPC64_GOT_DTPREL16_LO_DS":                "debug/elf",
+	"elf.R_PPC64_GOT_TLSGD16":                       "debug/elf",
+	"elf.R_PPC64_GOT_TLSGD16_HA":                    "debug/elf",
+	"elf.R_PPC64_GOT_TLSGD16_HI":                    "debug/elf",
+	"elf.R_PPC64_GOT_TLSGD16_LO":                    "debug/elf",
+	"elf.R_PPC64_GOT_TLSLD16":                       "debug/elf",
+	"elf.R_PPC64_GOT_TLSLD16_HA":                    "debug/elf",
+	"elf.R_PPC64_GOT_TLSLD16_HI":                    "debug/elf",
+	"elf.R_PPC64_GOT_TLSLD16_LO":                    "debug/elf",
+	"elf.R_PPC64_GOT_TPREL16_DS":                    "debug/elf",
+	"elf.R_PPC64_GOT_TPREL16_HA":                    "debug/elf",
+	"elf.R_PPC64_GOT_TPREL16_HI":                    "debug/elf",
+	"elf.R_PPC64_GOT_TPREL16_LO_DS":                 "debug/elf",
+	"elf.R_PPC64_JMP_SLOT":                          "debug/elf",
+	"elf.R_PPC64_NONE":                              "debug/elf",
+	"elf.R_PPC64_REL14":                             "debug/elf",
+	"elf.R_PPC64_REL14_BRNTAKEN":                    "debug/elf",
+	"elf.R_PPC64_REL14_BRTAKEN":                     "debug/elf",
+	"elf.R_PPC64_REL16":                             "debug/elf",
+	"elf.R_PPC64_REL16_HA":                          "debug/elf",
+	"elf.R_PPC64_REL16_HI":                          "debug/elf",
+	"elf.R_PPC64_REL16_LO":                          "debug/elf",
+	"elf.R_PPC64_REL24":                             "debug/elf",
+	"elf.R_PPC64_REL32":                             "debug/elf",
+	"elf.R_PPC64_REL64":                             "debug/elf",
+	"elf.R_PPC64_TLS":                               "debug/elf",
+	"elf.R_PPC64_TLSGD":                             "debug/elf",
+	"elf.R_PPC64_TLSLD":                             "debug/elf",
+	"elf.R_PPC64_TOC":                               "debug/elf",
+	"elf.R_PPC64_TOC16":                             "debug/elf",
+	"elf.R_PPC64_TOC16_DS":                          "debug/elf",
+	"elf.R_PPC64_TOC16_HA":                          "debug/elf",
+	"elf.R_PPC64_TOC16_HI":                          "debug/elf",
+	"elf.R_PPC64_TOC16_LO":                          "debug/elf",
+	"elf.R_PPC64_TOC16_LO_DS":                       "debug/elf",
+	"elf.R_PPC64_TPREL16":                           "debug/elf",
+	"elf.R_PPC64_TPREL16_DS":                        "debug/elf",
+	"elf.R_PPC64_TPREL16_HA":                        "debug/elf",
+	"elf.R_PPC64_TPREL16_HI":                        "debug/elf",
+	"elf.R_PPC64_TPREL16_HIGHER":                    "debug/elf",
+	"elf.R_PPC64_TPREL16_HIGHERA":                   "debug/elf",
+	"elf.R_PPC64_TPREL16_HIGHEST":                   "debug/elf",
+	"elf.R_PPC64_TPREL16_HIGHESTA":                  "debug/elf",
+	"elf.R_PPC64_TPREL16_LO":                        "debug/elf",
+	"elf.R_PPC64_TPREL16_LO_DS":                     "debug/elf",
+	"elf.R_PPC64_TPREL64":                           "debug/elf",
+	"elf.R_PPC_ADDR14":                              "debug/elf",
+	"elf.R_PPC_ADDR14_BRNTAKEN":                     "debug/elf",
+	"elf.R_PPC_ADDR14_BRTAKEN":                      "debug/elf",
+	"elf.R_PPC_ADDR16":                              "debug/elf",
+	"elf.R_PPC_ADDR16_HA":                           "debug/elf",
+	"elf.R_PPC_ADDR16_HI":                           "debug/elf",
+	"elf.R_PPC_ADDR16_LO":                           "debug/elf",
+	"elf.R_PPC_ADDR24":                              "debug/elf",
+	"elf.R_PPC_ADDR32":                              "debug/elf",
+	"elf.R_PPC_COPY":                                "debug/elf",
+	"elf.R_PPC_DTPMOD32":                            "debug/elf",
+	"elf.R_PPC_DTPREL16":                            "debug/elf",
+	"elf.R_PPC_DTPREL16_HA":                         "debug/elf",
+	"elf.R_PPC_DTPREL16_HI":                         "debug/elf",
+	"elf.R_PPC_DTPREL16_LO":                         "debug/elf",
+	"elf.R_PPC_DTPREL32":                            "debug/elf",
+	"elf.R_PPC_EMB_BIT_FLD":                         "debug/elf",
+	"elf.R_PPC_EMB_MRKREF":                          "debug/elf",
+	"elf.R_PPC_EMB_NADDR16":                         "debug/elf",
+	"elf.R_PPC_EMB_NADDR16_HA":                      "debug/elf",
+	"elf.R_PPC_EMB_NADDR16_HI":                      "debug/elf",
+	"elf.R_PPC_EMB_NADDR16_LO":                      "debug/elf",
+	"elf.R_PPC_EMB_NADDR32":                         "debug/elf",
+	"elf.R_PPC_EMB_RELSDA":                          "debug/elf",
+	"elf.R_PPC_EMB_RELSEC16":                        "debug/elf",
+	"elf.R_PPC_EMB_RELST_HA":                        "debug/elf",
+	"elf.R_PPC_EMB_RELST_HI":                        "debug/elf",
+	"elf.R_PPC_EMB_RELST_LO":                        "debug/elf",
+	"elf.R_PPC_EMB_SDA21":                           "debug/elf",
+	"elf.R_PPC_EMB_SDA2I16":                         "debug/elf",
+	"elf.R_PPC_EMB_SDA2REL":                         "debug/elf",
+	"elf.R_PPC_EMB_SDAI16":                          "debug/elf",
+	"elf.R_PPC_GLOB_DAT":                            "debug/elf",
+	"elf.R_PPC_GOT16":                               "debug/elf",
+	"elf.R_PPC_GOT16_HA":                            "debug/elf",
+	"elf.R_PPC_GOT16_HI":                            "debug/elf",
+	"elf.R_PPC_GOT16_LO":                            "debug/elf",
+	"elf.R_PPC_GOT_TLSGD16":                         "debug/elf",
+	"elf.R_PPC_GOT_TLSGD16_HA":                      "debug/elf",
+	"elf.R_PPC_GOT_TLSGD16_HI":                      "debug/elf",
+	"elf.R_PPC_GOT_TLSGD16_LO":                      "debug/elf",
+	"elf.R_PPC_GOT_TLSLD16":                         "debug/elf",
+	"elf.R_PPC_GOT_TLSLD16_HA":                      "debug/elf",
+	"elf.R_PPC_GOT_TLSLD16_HI":                      "debug/elf",
+	"elf.R_PPC_GOT_TLSLD16_LO":                      "debug/elf",
+	"elf.R_PPC_GOT_TPREL16":                         "debug/elf",
+	"elf.R_PPC_GOT_TPREL16_HA":                      "debug/elf",
+	"elf.R_PPC_GOT_TPREL16_HI":                      "debug/elf",
+	"elf.R_PPC_GOT_TPREL16_LO":                      "debug/elf",
+	"elf.R_PPC_JMP_SLOT":                            "debug/elf",
+	"elf.R_PPC_LOCAL24PC":                           "debug/elf",
+	"elf.R_PPC_NONE":                                "debug/elf",
+	"elf.R_PPC_PLT16_HA":                            "debug/elf",
+	"elf.R_PPC_PLT16_HI":                            "debug/elf",
+	"elf.R_PPC_PLT16_LO":                            "debug/elf",
+	"elf.R_PPC_PLT32":                               "debug/elf",
+	"elf.R_PPC_PLTREL24":                            "debug/elf",
+	"elf.R_PPC_PLTREL32":                            "debug/elf",
+	"elf.R_PPC_REL14":                               "debug/elf",
+	"elf.R_PPC_REL14_BRNTAKEN":                      "debug/elf",
+	"elf.R_PPC_REL14_BRTAKEN":                       "debug/elf",
+	"elf.R_PPC_REL24":                               "debug/elf",
+	"elf.R_PPC_REL32":                               "debug/elf",
+	"elf.R_PPC_RELATIVE":                            "debug/elf",
+	"elf.R_PPC_SDAREL16":                            "debug/elf",
+	"elf.R_PPC_SECTOFF":                             "debug/elf",
+	"elf.R_PPC_SECTOFF_HA":                          "debug/elf",
+	"elf.R_PPC_SECTOFF_HI":                          "debug/elf",
+	"elf.R_PPC_SECTOFF_LO":                          "debug/elf",
+	"elf.R_PPC_TLS":                                 "debug/elf",
+	"elf.R_PPC_TPREL16":                             "debug/elf",
+	"elf.R_PPC_TPREL16_HA":                          "debug/elf",
+	"elf.R_PPC_TPREL16_HI":                          "debug/elf",
+	"elf.R_PPC_TPREL16_LO":                          "debug/elf",
+	"elf.R_PPC_TPREL32":                             "debug/elf",
+	"elf.R_PPC_UADDR16":                             "debug/elf",
+	"elf.R_PPC_UADDR32":                             "debug/elf",
+	"elf.R_SPARC":                                   "debug/elf",
+	"elf.R_SPARC_10":                                "debug/elf",
+	"elf.R_SPARC_11":                                "debug/elf",
+	"elf.R_SPARC_13":                                "debug/elf",
+	"elf.R_SPARC_16":                                "debug/elf",
+	"elf.R_SPARC_22":                                "debug/elf",
+	"elf.R_SPARC_32":                                "debug/elf",
+	"elf.R_SPARC_5":                                 "debug/elf",
+	"elf.R_SPARC_6":                                 "debug/elf",
+	"elf.R_SPARC_64":                                "debug/elf",
+	"elf.R_SPARC_7":                                 "debug/elf",
+	"elf.R_SPARC_8":                                 "debug/elf",
+	"elf.R_SPARC_COPY":                              "debug/elf",
+	"elf.R_SPARC_DISP16":                            "debug/elf",
+	"elf.R_SPARC_DISP32":                            "debug/elf",
+	"elf.R_SPARC_DISP64":                            "debug/elf",
+	"elf.R_SPARC_DISP8":                             "debug/elf",
+	"elf.R_SPARC_GLOB_DAT":                          "debug/elf",
+	"elf.R_SPARC_GLOB_JMP":                          "debug/elf",
+	"elf.R_SPARC_GOT10":                             "debug/elf",
+	"elf.R_SPARC_GOT13":                             "debug/elf",
+	"elf.R_SPARC_GOT22":                             "debug/elf",
+	"elf.R_SPARC_H44":                               "debug/elf",
+	"elf.R_SPARC_HH22":                              "debug/elf",
+	"elf.R_SPARC_HI22":                              "debug/elf",
+	"elf.R_SPARC_HIPLT22":                           "debug/elf",
+	"elf.R_SPARC_HIX22":                             "debug/elf",
+	"elf.R_SPARC_HM10":                              "debug/elf",
+	"elf.R_SPARC_JMP_SLOT":                          "debug/elf",
+	"elf.R_SPARC_L44":                               "debug/elf",
+	"elf.R_SPARC_LM22":                              "debug/elf",
+	"elf.R_SPARC_LO10":                              "debug/elf",
+	"elf.R_SPARC_LOPLT10":                           "debug/elf",
+	"elf.R_SPARC_LOX10":                             "debug/elf",
+	"elf.R_SPARC_M44":                               "debug/elf",
+	"elf.R_SPARC_NONE":                              "debug/elf",
+	"elf.R_SPARC_OLO10":                             "debug/elf",
+	"elf.R_SPARC_PC10":                              "debug/elf",
+	"elf.R_SPARC_PC22":                              "debug/elf",
+	"elf.R_SPARC_PCPLT10":                           "debug/elf",
+	"elf.R_SPARC_PCPLT22":                           "debug/elf",
+	"elf.R_SPARC_PCPLT32":                           "debug/elf",
+	"elf.R_SPARC_PC_HH22":                           "debug/elf",
+	"elf.R_SPARC_PC_HM10":                           "debug/elf",
+	"elf.R_SPARC_PC_LM22":                           "debug/elf",
+	"elf.R_SPARC_PLT32":                             "debug/elf",
+	"elf.R_SPARC_PLT64":                             "debug/elf",
+	"elf.R_SPARC_REGISTER":                          "debug/elf",
+	"elf.R_SPARC_RELATIVE":                          "debug/elf",
+	"elf.R_SPARC_UA16":                              "debug/elf",
+	"elf.R_SPARC_UA32":                              "debug/elf",
+	"elf.R_SPARC_UA64":                              "debug/elf",
+	"elf.R_SPARC_WDISP16":                           "debug/elf",
+	"elf.R_SPARC_WDISP19":                           "debug/elf",
+	"elf.R_SPARC_WDISP22":                           "debug/elf",
+	"elf.R_SPARC_WDISP30":                           "debug/elf",
+	"elf.R_SPARC_WPLT30":                            "debug/elf",
+	"elf.R_SYM32":                                   "debug/elf",
+	"elf.R_SYM64":                                   "debug/elf",
+	"elf.R_TYPE32":                                  "debug/elf",
+	"elf.R_TYPE64":                                  "debug/elf",
+	"elf.R_X86_64":                                  "debug/elf",
+	"elf.R_X86_64_16":                               "debug/elf",
+	"elf.R_X86_64_32":                               "debug/elf",
+	"elf.R_X86_64_32S":                              "debug/elf",
+	"elf.R_X86_64_64":                               "debug/elf",
+	"elf.R_X86_64_8":                                "debug/elf",
+	"elf.R_X86_64_COPY":                             "debug/elf",
+	"elf.R_X86_64_DTPMOD64":                         "debug/elf",
+	"elf.R_X86_64_DTPOFF32":                         "debug/elf",
+	"elf.R_X86_64_DTPOFF64":                         "debug/elf",
+	"elf.R_X86_64_GLOB_DAT":                         "debug/elf",
+	"elf.R_X86_64_GOT32":                            "debug/elf",
+	"elf.R_X86_64_GOTPCREL":                         "debug/elf",
+	"elf.R_X86_64_GOTTPOFF":                         "debug/elf",
+	"elf.R_X86_64_JMP_SLOT":                         "debug/elf",
+	"elf.R_X86_64_NONE":                             "debug/elf",
+	"elf.R_X86_64_PC16":                             "debug/elf",
+	"elf.R_X86_64_PC32":                             "debug/elf",
+	"elf.R_X86_64_PC8":                              "debug/elf",
+	"elf.R_X86_64_PLT32":                            "debug/elf",
+	"elf.R_X86_64_RELATIVE":                         "debug/elf",
+	"elf.R_X86_64_TLSGD":                            "debug/elf",
+	"elf.R_X86_64_TLSLD":                            "debug/elf",
+	"elf.R_X86_64_TPOFF32":                          "debug/elf",
+	"elf.R_X86_64_TPOFF64":                          "debug/elf",
+	"elf.Rel32":                                     "debug/elf",
+	"elf.Rel64":                                     "debug/elf",
+	"elf.Rela32":                                    "debug/elf",
+	"elf.Rela64":                                    "debug/elf",
+	"elf.SHF_ALLOC":                                 "debug/elf",
+	"elf.SHF_EXECINSTR":                             "debug/elf",
+	"elf.SHF_GROUP":                                 "debug/elf",
+	"elf.SHF_INFO_LINK":                             "debug/elf",
+	"elf.SHF_LINK_ORDER":                            "debug/elf",
+	"elf.SHF_MASKOS":                                "debug/elf",
+	"elf.SHF_MASKPROC":                              "debug/elf",
+	"elf.SHF_MERGE":                                 "debug/elf",
+	"elf.SHF_OS_NONCONFORMING":                      "debug/elf",
+	"elf.SHF_STRINGS":                               "debug/elf",
+	"elf.SHF_TLS":                                   "debug/elf",
+	"elf.SHF_WRITE":                                 "debug/elf",
+	"elf.SHN_ABS":                                   "debug/elf",
+	"elf.SHN_COMMON":                                "debug/elf",
+	"elf.SHN_HIOS":                                  "debug/elf",
+	"elf.SHN_HIPROC":                                "debug/elf",
+	"elf.SHN_HIRESERVE":                             "debug/elf",
+	"elf.SHN_LOOS":                                  "debug/elf",
+	"elf.SHN_LOPROC":                                "debug/elf",
+	"elf.SHN_LORESERVE":                             "debug/elf",
+	"elf.SHN_UNDEF":                                 "debug/elf",
+	"elf.SHN_XINDEX":                                "debug/elf",
+	"elf.SHT_DYNAMIC":                               "debug/elf",
+	"elf.SHT_DYNSYM":                                "debug/elf",
+	"elf.SHT_FINI_ARRAY":                            "debug/elf",
+	"elf.SHT_GNU_ATTRIBUTES":                        "debug/elf",
+	"elf.SHT_GNU_HASH":                              "debug/elf",
+	"elf.SHT_GNU_LIBLIST":                           "debug/elf",
+	"elf.SHT_GNU_VERDEF":                            "debug/elf",
+	"elf.SHT_GNU_VERNEED":                           "debug/elf",
+	"elf.SHT_GNU_VERSYM":                            "debug/elf",
+	"elf.SHT_GROUP":                                 "debug/elf",
+	"elf.SHT_HASH":                                  "debug/elf",
+	"elf.SHT_HIOS":                                  "debug/elf",
+	"elf.SHT_HIPROC":                                "debug/elf",
+	"elf.SHT_HIUSER":                                "debug/elf",
+	"elf.SHT_INIT_ARRAY":                            "debug/elf",
+	"elf.SHT_LOOS":                                  "debug/elf",
+	"elf.SHT_LOPROC":                                "debug/elf",
+	"elf.SHT_LOUSER":                                "debug/elf",
+	"elf.SHT_NOBITS":                                "debug/elf",
+	"elf.SHT_NOTE":                                  "debug/elf",
+	"elf.SHT_NULL":                                  "debug/elf",
+	"elf.SHT_PREINIT_ARRAY":                         "debug/elf",
+	"elf.SHT_PROGBITS":                              "debug/elf",
+	"elf.SHT_REL":                                   "debug/elf",
+	"elf.SHT_RELA":                                  "debug/elf",
+	"elf.SHT_SHLIB":                                 "debug/elf",
+	"elf.SHT_STRTAB":                                "debug/elf",
+	"elf.SHT_SYMTAB":                                "debug/elf",
+	"elf.SHT_SYMTAB_SHNDX":                          "debug/elf",
+	"elf.STB_GLOBAL":                                "debug/elf",
+	"elf.STB_HIOS":                                  "debug/elf",
+	"elf.STB_HIPROC":                                "debug/elf",
+	"elf.STB_LOCAL":                                 "debug/elf",
+	"elf.STB_LOOS":                                  "debug/elf",
+	"elf.STB_LOPROC":                                "debug/elf",
+	"elf.STB_WEAK":                                  "debug/elf",
+	"elf.STT_COMMON":                                "debug/elf",
+	"elf.STT_FILE":                                  "debug/elf",
+	"elf.STT_FUNC":                                  "debug/elf",
+	"elf.STT_HIOS":                                  "debug/elf",
+	"elf.STT_HIPROC":                                "debug/elf",
+	"elf.STT_LOOS":                                  "debug/elf",
+	"elf.STT_LOPROC":                                "debug/elf",
+	"elf.STT_NOTYPE":                                "debug/elf",
+	"elf.STT_OBJECT":                                "debug/elf",
+	"elf.STT_SECTION":                               "debug/elf",
+	"elf.STT_TLS":                                   "debug/elf",
+	"elf.STV_DEFAULT":                               "debug/elf",
+	"elf.STV_HIDDEN":                                "debug/elf",
+	"elf.STV_INTERNAL":                              "debug/elf",
+	"elf.STV_PROTECTED":                             "debug/elf",
+	"elf.ST_BIND":                                   "debug/elf",
+	"elf.ST_INFO":                                   "debug/elf",
+	"elf.ST_TYPE":                                   "debug/elf",
+	"elf.ST_VISIBILITY":                             "debug/elf",
+	"elf.Section":                                   "debug/elf",
+	"elf.Section32":                                 "debug/elf",
+	"elf.Section64":                                 "debug/elf",
+	"elf.SectionFlag":                               "debug/elf",
+	"elf.SectionHeader":                             "debug/elf",
+	"elf.SectionIndex":                              "debug/elf",
+	"elf.SectionType":                               "debug/elf",
+	"elf.Sym32":                                     "debug/elf",
+	"elf.Sym32Size":                                 "debug/elf",
+	"elf.Sym64":                                     "debug/elf",
+	"elf.Sym64Size":                                 "debug/elf",
+	"elf.SymBind":                                   "debug/elf",
+	"elf.SymType":                                   "debug/elf",
+	"elf.SymVis":                                    "debug/elf",
+	"elf.Symbol":                                    "debug/elf",
+	"elf.Type":                                      "debug/elf",
+	"elf.Version":                                   "debug/elf",
+	"elliptic.Curve":                                "crypto/elliptic",
+	"elliptic.CurveParams":                          "crypto/elliptic",
+	"elliptic.GenerateKey":                          "crypto/elliptic",
+	"elliptic.Marshal":                              "crypto/elliptic",
+	"elliptic.P224":                                 "crypto/elliptic",
+	"elliptic.P256":                                 "crypto/elliptic",
+	"elliptic.P384":                                 "crypto/elliptic",
+	"elliptic.P521":                                 "crypto/elliptic",
+	"elliptic.Unmarshal":                            "crypto/elliptic",
+	"encoding.BinaryMarshaler":                      "encoding",
+	"encoding.BinaryUnmarshaler":                    "encoding",
+	"encoding.TextMarshaler":                        "encoding",
+	"encoding.TextUnmarshaler":                      "encoding",
+	"errors.New":                                    "errors",
+	"exec.Cmd":                                      "os/exec",
+	"exec.Command":                                  "os/exec",
+	"exec.ErrNotFound":                              "os/exec",
+	"exec.Error":                                    "os/exec",
+	"exec.ExitError":                                "os/exec",
+	"exec.LookPath":                                 "os/exec",
+	"expvar.Do":                                     "expvar",
+	"expvar.Float":                                  "expvar",
+	"expvar.Func":                                   "expvar",
+	"expvar.Get":                                    "expvar",
+	"expvar.Int":                                    "expvar",
+	"expvar.KeyValue":                               "expvar",
+	"expvar.Map":                                    "expvar",
+	"expvar.NewFloat":                               "expvar",
+	"expvar.NewInt":                                 "expvar",
+	"expvar.NewMap":                                 "expvar",
+	"expvar.NewString":                              "expvar",
+	"expvar.Publish":                                "expvar",
+	"expvar.String":                                 "expvar",
+	"expvar.Var":                                    "expvar",
+	"fcgi.ErrConnClosed":                            "net/http/fcgi",
+	"fcgi.ErrRequestAborted":                        "net/http/fcgi",
+	"fcgi.Serve":                                    "net/http/fcgi",
+	"filepath.Abs":                                  "path/filepath",
+	"filepath.Base":                                 "path/filepath",
+	"filepath.Clean":                                "path/filepath",
+	"filepath.Dir":                                  "path/filepath",
+	"filepath.ErrBadPattern":                        "path/filepath",
+	"filepath.EvalSymlinks":                         "path/filepath",
+	"filepath.Ext":                                  "path/filepath",
+	"filepath.FromSlash":                            "path/filepath",
+	"filepath.Glob":                                 "path/filepath",
+	"filepath.HasPrefix":                            "path/filepath",
+	"filepath.IsAbs":                                "path/filepath",
+	"filepath.Join":                                 "path/filepath",
+	"filepath.ListSeparator":                        "path/filepath",
+	"filepath.Match":                                "path/filepath",
+	"filepath.Rel":                                  "path/filepath",
+	"filepath.Separator":                            "path/filepath",
+	"filepath.SkipDir":                              "path/filepath",
+	"filepath.Split":                                "path/filepath",
+	"filepath.SplitList":                            "path/filepath",
+	"filepath.ToSlash":                              "path/filepath",
+	"filepath.VolumeName":                           "path/filepath",
+	"filepath.Walk":                                 "path/filepath",
+	"filepath.WalkFunc":                             "path/filepath",
+	"flag.Arg":                                      "flag",
+	"flag.Args":                                     "flag",
+	"flag.Bool":                                     "flag",
+	"flag.BoolVar":                                  "flag",
+	"flag.CommandLine":                              "flag",
+	"flag.ContinueOnError":                          "flag",
+	"flag.Duration":                                 "flag",
+	"flag.DurationVar":                              "flag",
+	"flag.ErrHelp":                                  "flag",
+	"flag.ErrorHandling":                            "flag",
+	"flag.ExitOnError":                              "flag",
+	"flag.Flag":                                     "flag",
+	"flag.FlagSet":                                  "flag",
+	"flag.Float64":                                  "flag",
+	"flag.Float64Var":                               "flag",
+	"flag.Getter":                                   "flag",
+	"flag.Int":                                      "flag",
+	"flag.Int64":                                    "flag",
+	"flag.Int64Var":                                 "flag",
+	"flag.IntVar":                                   "flag",
+	"flag.Lookup":                                   "flag",
+	"flag.NArg":                                     "flag",
+	"flag.NFlag":                                    "flag",
+	"flag.NewFlagSet":                               "flag",
+	"flag.PanicOnError":                             "flag",
+	"flag.Parse":                                    "flag",
+	"flag.Parsed":                                   "flag",
+	"flag.PrintDefaults":                            "flag",
+	"flag.Set":                                      "flag",
+	"flag.String":                                   "flag",
+	"flag.StringVar":                                "flag",
+	"flag.Uint":                                     "flag",
+	"flag.Uint64":                                   "flag",
+	"flag.Uint64Var":                                "flag",
+	"flag.UintVar":                                  "flag",
+	"flag.UnquoteUsage":                             "flag",
+	"flag.Usage":                                    "flag",
+	"flag.Value":                                    "flag",
+	"flag.Var":                                      "flag",
+	"flag.Visit":                                    "flag",
+	"flag.VisitAll":                                 "flag",
+	"flate.BestCompression":                         "compress/flate",
+	"flate.BestSpeed":                               "compress/flate",
+	"flate.CorruptInputError":                       "compress/flate",
+	"flate.DefaultCompression":                      "compress/flate",
+	"flate.InternalError":                           "compress/flate",
+	"flate.NewReader":                               "compress/flate",
+	"flate.NewReaderDict":                           "compress/flate",
+	"flate.NewWriter":                               "compress/flate",
+	"flate.NewWriterDict":                           "compress/flate",
+	"flate.NoCompression":                           "compress/flate",
+	"flate.ReadError":                               "compress/flate",
+	"flate.Reader":                                  "compress/flate",
+	"flate.Resetter":                                "compress/flate",
+	"flate.WriteError":                              "compress/flate",
+	"flate.Writer":                                  "compress/flate",
+	"fmt.Errorf":                                    "fmt",
+	"fmt.Formatter":                                 "fmt",
+	"fmt.Fprint":                                    "fmt",
+	"fmt.Fprintf":                                   "fmt",
+	"fmt.Fprintln":                                  "fmt",
+	"fmt.Fscan":                                     "fmt",
+	"fmt.Fscanf":                                    "fmt",
+	"fmt.Fscanln":                                   "fmt",
+	"fmt.GoStringer":                                "fmt",
+	"fmt.Print":                                     "fmt",
+	"fmt.Printf":                                    "fmt",
+	"fmt.Println":                                   "fmt",
+	"fmt.Scan":                                      "fmt",
+	"fmt.ScanState":                                 "fmt",
+	"fmt.Scanf":                                     "fmt",
+	"fmt.Scanln":                                    "fmt",
+	"fmt.Scanner":                                   "fmt",
+	"fmt.Sprint":                                    "fmt",
+	"fmt.Sprintf":                                   "fmt",
+	"fmt.Sprintln":                                  "fmt",
+	"fmt.Sscan":                                     "fmt",
+	"fmt.Sscanf":                                    "fmt",
+	"fmt.Sscanln":                                   "fmt",
+	"fmt.State":                                     "fmt",
+	"fmt.Stringer":                                  "fmt",
+	"fnv.New32":                                     "hash/fnv",
+	"fnv.New32a":                                    "hash/fnv",
+	"fnv.New64":                                     "hash/fnv",
+	"fnv.New64a":                                    "hash/fnv",
+	"format.Node":                                   "go/format",
+	"format.Source":                                 "go/format",
+	"gif.Decode":                                    "image/gif",
+	"gif.DecodeAll":                                 "image/gif",
+	"gif.DecodeConfig":                              "image/gif",
+	"gif.DisposalBackground":                        "image/gif",
+	"gif.DisposalNone":                              "image/gif",
+	"gif.DisposalPrevious":                          "image/gif",
+	"gif.Encode":                                    "image/gif",
+	"gif.EncodeAll":                                 "image/gif",
+	"gif.GIF":                                       "image/gif",
+	"gif.Options":                                   "image/gif",
+	"gob.CommonType":                                "encoding/gob",
+	"gob.Decoder":                                   "encoding/gob",
+	"gob.Encoder":                                   "encoding/gob",
+	"gob.GobDecoder":                                "encoding/gob",
+	"gob.GobEncoder":                                "encoding/gob",
+	"gob.NewDecoder":                                "encoding/gob",
+	"gob.NewEncoder":                                "encoding/gob",
+	"gob.Register":                                  "encoding/gob",
+	"gob.RegisterName":                              "encoding/gob",
+	"gosym.DecodingError":                           "debug/gosym",
+	"gosym.Func":                                    "debug/gosym",
+	"gosym.LineTable":                               "debug/gosym",
+	"gosym.NewLineTable":                            "debug/gosym",
+	"gosym.NewTable":                                "debug/gosym",
+	"gosym.Obj":                                     "debug/gosym",
+	"gosym.Sym":                                     "debug/gosym",
+	"gosym.Table":                                   "debug/gosym",
+	"gosym.UnknownFileError":                        "debug/gosym",
+	"gosym.UnknownLineError":                        "debug/gosym",
+	"gzip.BestCompression":                          "compress/gzip",
+	"gzip.BestSpeed":                                "compress/gzip",
+	"gzip.DefaultCompression":                       "compress/gzip",
+	"gzip.ErrChecksum":                              "compress/gzip",
+	"gzip.ErrHeader":                                "compress/gzip",
+	"gzip.Header":                                   "compress/gzip",
+	"gzip.NewReader":                                "compress/gzip",
+	"gzip.NewWriter":                                "compress/gzip",
+	"gzip.NewWriterLevel":                           "compress/gzip",
+	"gzip.NoCompression":                            "compress/gzip",
+	"gzip.Reader":                                   "compress/gzip",
+	"gzip.Writer":                                   "compress/gzip",
+	"hash.Hash":                                     "hash",
+	"hash.Hash32":                                   "hash",
+	"hash.Hash64":                                   "hash",
+	"heap.Fix":                                      "container/heap",
+	"heap.Init":                                     "container/heap",
+	"heap.Interface":                                "container/heap",
+	"heap.Pop":                                      "container/heap",
+	"heap.Push":                                     "container/heap",
+	"heap.Remove":                                   "container/heap",
+	"hex.Decode":                                    "encoding/hex",
+	"hex.DecodeString":                              "encoding/hex",
+	"hex.DecodedLen":                                "encoding/hex",
+	"hex.Dump":                                      "encoding/hex",
+	"hex.Dumper":                                    "encoding/hex",
+	"hex.Encode":                                    "encoding/hex",
+	"hex.EncodeToString":                            "encoding/hex",
+	"hex.EncodedLen":                                "encoding/hex",
+	"hex.ErrLength":                                 "encoding/hex",
+	"hex.InvalidByteError":                          "encoding/hex",
+	"hmac.Equal":                                    "crypto/hmac",
+	"hmac.New":                                      "crypto/hmac",
+	"html.EscapeString":                             "html",
+	"html.UnescapeString":                           "html",
+	"http.CanonicalHeaderKey":                       "net/http",
+	"http.Client":                                   "net/http",
+	"http.CloseNotifier":                            "net/http",
+	"http.ConnState":                                "net/http",
+	"http.Cookie":                                   "net/http",
+	"http.CookieJar":                                "net/http",
+	"http.DefaultClient":                            "net/http",
+	"http.DefaultMaxHeaderBytes":                    "net/http",
+	"http.DefaultMaxIdleConnsPerHost":               "net/http",
+	"http.DefaultServeMux":                          "net/http",
+	"http.DefaultTransport":                         "net/http",
+	"http.DetectContentType":                        "net/http",
+	"http.Dir":                                      "net/http",
+	"http.ErrBodyNotAllowed":                        "net/http",
+	"http.ErrBodyReadAfterClose":                    "net/http",
+	"http.ErrContentLength":                         "net/http",
+	"http.ErrHandlerTimeout":                        "net/http",
+	"http.ErrHeaderTooLong":                         "net/http",
+	"http.ErrHijacked":                              "net/http",
+	"http.ErrLineTooLong":                           "net/http",
+	"http.ErrMissingBoundary":                       "net/http",
+	"http.ErrMissingContentLength":                  "net/http",
+	"http.ErrMissingFile":                           "net/http",
+	"http.ErrNoCookie":                              "net/http",
+	"http.ErrNoLocation":                            "net/http",
+	"http.ErrNotMultipart":                          "net/http",
+	"http.ErrNotSupported":                          "net/http",
+	"http.ErrShortBody":                             "net/http",
+	"http.ErrUnexpectedTrailer":                     "net/http",
+	"http.ErrWriteAfterFlush":                       "net/http",
+	"http.Error":                                    "net/http",
+	"http.File":                                     "net/http",
+	"http.FileServer":                               "net/http",
+	"http.FileSystem":                               "net/http",
+	"http.Flusher":                                  "net/http",
+	"http.Get":                                      "net/http",
+	"http.Handle":                                   "net/http",
+	"http.HandleFunc":                               "net/http",
+	"http.Handler":                                  "net/http",
+	"http.HandlerFunc":                              "net/http",
+	"http.Head":                                     "net/http",
+	"http.Header":                                   "net/http",
+	"http.Hijacker":                                 "net/http",
+	"http.ListenAndServe":                           "net/http",
+	"http.ListenAndServeTLS":                        "net/http",
+	"http.MaxBytesReader":                           "net/http",
+	"http.NewFileTransport":                         "net/http",
+	"http.NewRequest":                               "net/http",
+	"http.NewServeMux":                              "net/http",
+	"http.NotFound":                                 "net/http",
+	"http.NotFoundHandler":                          "net/http",
+	"http.ParseHTTPVersion":                         "net/http",
+	"http.ParseTime":                                "net/http",
+	"http.Post":                                     "net/http",
+	"http.PostForm":                                 "net/http",
+	"http.ProtocolError":                            "net/http",
+	"http.ProxyFromEnvironment":                     "net/http",
+	"http.ProxyURL":                                 "net/http",
+	"http.ReadRequest":                              "net/http",
+	"http.ReadResponse":                             "net/http",
+	"http.Redirect":                                 "net/http",
+	"http.RedirectHandler":                          "net/http",
+	"http.Request":                                  "net/http",
+	"http.Response":                                 "net/http",
+	"http.ResponseWriter":                           "net/http",
+	"http.RoundTripper":                             "net/http",
+	"http.Serve":                                    "net/http",
+	"http.ServeContent":                             "net/http",
+	"http.ServeFile":                                "net/http",
+	"http.ServeMux":                                 "net/http",
+	"http.Server":                                   "net/http",
+	"http.SetCookie":                                "net/http",
+	"http.StateActive":                              "net/http",
+	"http.StateClosed":                              "net/http",
+	"http.StateHijacked":                            "net/http",
+	"http.StateIdle":                                "net/http",
+	"http.StateNew":                                 "net/http",
+	"http.StatusAccepted":                           "net/http",
+	"http.StatusBadGateway":                         "net/http",
+	"http.StatusBadRequest":                         "net/http",
+	"http.StatusConflict":                           "net/http",
+	"http.StatusContinue":                           "net/http",
+	"http.StatusCreated":                            "net/http",
+	"http.StatusExpectationFailed":                  "net/http",
+	"http.StatusForbidden":                          "net/http",
+	"http.StatusFound":                              "net/http",
+	"http.StatusGatewayTimeout":                     "net/http",
+	"http.StatusGone":                               "net/http",
+	"http.StatusHTTPVersionNotSupported":            "net/http",
+	"http.StatusInternalServerError":                "net/http",
+	"http.StatusLengthRequired":                     "net/http",
+	"http.StatusMethodNotAllowed":                   "net/http",
+	"http.StatusMovedPermanently":                   "net/http",
+	"http.StatusMultipleChoices":                    "net/http",
+	"http.StatusNoContent":                          "net/http",
+	"http.StatusNonAuthoritativeInfo":               "net/http",
+	"http.StatusNotAcceptable":                      "net/http",
+	"http.StatusNotFound":                           "net/http",
+	"http.StatusNotImplemented":                     "net/http",
+	"http.StatusNotModified":                        "net/http",
+	"http.StatusOK":                                 "net/http",
+	"http.StatusPartialContent":                     "net/http",
+	"http.StatusPaymentRequired":                    "net/http",
+	"http.StatusPreconditionFailed":                 "net/http",
+	"http.StatusProxyAuthRequired":                  "net/http",
+	"http.StatusRequestEntityTooLarge":              "net/http",
+	"http.StatusRequestTimeout":                     "net/http",
+	"http.StatusRequestURITooLong":                  "net/http",
+	"http.StatusRequestedRangeNotSatisfiable":       "net/http",
+	"http.StatusResetContent":                       "net/http",
+	"http.StatusSeeOther":                           "net/http",
+	"http.StatusServiceUnavailable":                 "net/http",
+	"http.StatusSwitchingProtocols":                 "net/http",
+	"http.StatusTeapot":                             "net/http",
+	"http.StatusTemporaryRedirect":                  "net/http",
+	"http.StatusText":                               "net/http",
+	"http.StatusUnauthorized":                       "net/http",
+	"http.StatusUnsupportedMediaType":               "net/http",
+	"http.StatusUseProxy":                           "net/http",
+	"http.StripPrefix":                              "net/http",
+	"http.TimeFormat":                               "net/http",
+	"http.TimeoutHandler":                           "net/http",
+	"http.Transport":                                "net/http",
+	"httptest.DefaultRemoteAddr":                    "net/http/httptest",
+	"httptest.NewRecorder":                          "net/http/httptest",
+	"httptest.NewServer":                            "net/http/httptest",
+	"httptest.NewTLSServer":                         "net/http/httptest",
+	"httptest.NewUnstartedServer":                   "net/http/httptest",
+	"httptest.ResponseRecorder":                     "net/http/httptest",
+	"httptest.Server":                               "net/http/httptest",
+	"httputil.ClientConn":                           "net/http/httputil",
+	"httputil.DumpRequest":                          "net/http/httputil",
+	"httputil.DumpRequestOut":                       "net/http/httputil",
+	"httputil.DumpResponse":                         "net/http/httputil",
+	"httputil.ErrClosed":                            "net/http/httputil",
+	"httputil.ErrLineTooLong":                       "net/http/httputil",
+	"httputil.ErrPersistEOF":                        "net/http/httputil",
+	"httputil.ErrPipeline":                          "net/http/httputil",
+	"httputil.NewChunkedReader":                     "net/http/httputil",
+	"httputil.NewChunkedWriter":                     "net/http/httputil",
+	"httputil.NewClientConn":                        "net/http/httputil",
+	"httputil.NewProxyClientConn":                   "net/http/httputil",
+	"httputil.NewServerConn":                        "net/http/httputil",
+	"httputil.NewSingleHostReverseProxy":            "net/http/httputil",
+	"httputil.ReverseProxy":                         "net/http/httputil",
+	"httputil.ServerConn":                           "net/http/httputil",
+	"image.Alpha":                                   "image",
+	"image.Alpha16":                                 "image",
+	"image.Black":                                   "image",
+	"image.CMYK":                                    "image",
+	"image.Config":                                  "image",
+	"image.Decode":                                  "image",
+	"image.DecodeConfig":                            "image",
+	"image.ErrFormat":                               "image",
+	"image.Gray":                                    "image",
+	"image.Gray16":                                  "image",
+	"image.Image":                                   "image",
+	"image.NRGBA":                                   "image",
+	"image.NRGBA64":                                 "image",
+	"image.NewAlpha":                                "image",
+	"image.NewAlpha16":                              "image",
+	"image.NewCMYK":                                 "image",
+	"image.NewGray":                                 "image",
+	"image.NewGray16":                               "image",
+	"image.NewNRGBA":                                "image",
+	"image.NewNRGBA64":                              "image",
+	"image.NewPaletted":                             "image",
+	"image.NewRGBA":                                 "image",
+	"image.NewRGBA64":                               "image",
+	"image.NewUniform":                              "image",
+	"image.NewYCbCr":                                "image",
+	"image.Opaque":                                  "image",
+	"image.Paletted":                                "image",
+	"image.PalettedImage":                           "image",
+	"image.Point":                                   "image",
+	"image.Pt":                                      "image",
+	"image.RGBA":                                    "image",
+	"image.RGBA64":                                  "image",
+	"image.Rect":                                    "image",
+	"image.Rectangle":                               "image",
+	"image.RegisterFormat":                          "image",
+	"image.Transparent":                             "image",
+	"image.Uniform":                                 "image",
+	"image.White":                                   "image",
+	"image.YCbCr":                                   "image",
+	"image.YCbCrSubsampleRatio":                     "image",
+	"image.YCbCrSubsampleRatio410":                  "image",
+	"image.YCbCrSubsampleRatio411":                  "image",
+	"image.YCbCrSubsampleRatio420":                  "image",
+	"image.YCbCrSubsampleRatio422":                  "image",
+	"image.YCbCrSubsampleRatio440":                  "image",
+	"image.YCbCrSubsampleRatio444":                  "image",
+	"image.ZP":                                      "image",
+	"image.ZR":                                      "image",
+	"importer.Default":                              "go/importer",
+	"importer.For":                                  "go/importer",
+	"importer.Lookup":                               "go/importer",
+	"io.ByteReader":                                 "io",
+	"io.ByteScanner":                                "io",
+	"io.ByteWriter":                                 "io",
+	"io.Closer":                                     "io",
+	"io.Copy":                                       "io",
+	"io.CopyBuffer":                                 "io",
+	"io.CopyN":                                      "io",
+	"io.EOF":                                        "io",
+	"io.ErrClosedPipe":                              "io",
+	"io.ErrNoProgress":                              "io",
+	"io.ErrShortBuffer":                             "io",
+	"io.ErrShortWrite":                              "io",
+	"io.ErrUnexpectedEOF":                           "io",
+	"io.LimitReader":                                "io",
+	"io.LimitedReader":                              "io",
+	"io.MultiReader":                                "io",
+	"io.MultiWriter":                                "io",
+	"io.NewSectionReader":                           "io",
+	"io.Pipe":                                       "io",
+	"io.PipeReader":                                 "io",
+	"io.PipeWriter":                                 "io",
+	"io.ReadAtLeast":                                "io",
+	"io.ReadCloser":                                 "io",
+	"io.ReadFull":                                   "io",
+	"io.ReadSeeker":                                 "io",
+	"io.ReadWriteCloser":                            "io",
+	"io.ReadWriteSeeker":                            "io",
+	"io.ReadWriter":                                 "io",
+	"io.Reader":                                     "io",
+	"io.ReaderAt":                                   "io",
+	"io.ReaderFrom":                                 "io",
+	"io.RuneReader":                                 "io",
+	"io.RuneScanner":                                "io",
+	"io.SectionReader":                              "io",
+	"io.Seeker":                                     "io",
+	"io.TeeReader":                                  "io",
+	"io.WriteCloser":                                "io",
+	"io.WriteSeeker":                                "io",
+	"io.WriteString":                                "io",
+	"io.Writer":                                     "io",
+	"io.WriterAt":                                   "io",
+	"io.WriterTo":                                   "io",
+	"iotest.DataErrReader":                          "testing/iotest",
+	"iotest.ErrTimeout":                             "testing/iotest",
+	"iotest.HalfReader":                             "testing/iotest",
+	"iotest.NewReadLogger":                          "testing/iotest",
+	"iotest.NewWriteLogger":                         "testing/iotest",
+	"iotest.OneByteReader":                          "testing/iotest",
+	"iotest.TimeoutReader":                          "testing/iotest",
+	"iotest.TruncateWriter":                         "testing/iotest",
+	"ioutil.Discard":                                "io/ioutil",
+	"ioutil.NopCloser":                              "io/ioutil",
+	"ioutil.ReadAll":                                "io/ioutil",
+	"ioutil.ReadDir":                                "io/ioutil",
+	"ioutil.ReadFile":                               "io/ioutil",
+	"ioutil.TempDir":                                "io/ioutil",
+	"ioutil.TempFile":                               "io/ioutil",
+	"ioutil.WriteFile":                              "io/ioutil",
+	"jpeg.Decode":                                   "image/jpeg",
+	"jpeg.DecodeConfig":                             "image/jpeg",
+	"jpeg.DefaultQuality":                           "image/jpeg",
+	"jpeg.Encode":                                   "image/jpeg",
+	"jpeg.FormatError":                              "image/jpeg",
+	"jpeg.Options":                                  "image/jpeg",
+	"jpeg.Reader":                                   "image/jpeg",
+	"jpeg.UnsupportedError":                         "image/jpeg",
+	"json.Compact":                                  "encoding/json",
+	"json.Decoder":                                  "encoding/json",
+	"json.Delim":                                    "encoding/json",
+	"json.Encoder":                                  "encoding/json",
+	"json.HTMLEscape":                               "encoding/json",
+	"json.Indent":                                   "encoding/json",
+	"json.InvalidUTF8Error":                         "encoding/json",
+	"json.InvalidUnmarshalError":                    "encoding/json",
+	"json.Marshal":                                  "encoding/json",
+	"json.MarshalIndent":                            "encoding/json",
+	"json.Marshaler":                                "encoding/json",
+	"json.MarshalerError":                           "encoding/json",
+	"json.NewDecoder":                               "encoding/json",
+	"json.NewEncoder":                               "encoding/json",
+	"json.Number":                                   "encoding/json",
+	"json.RawMessage":                               "encoding/json",
+	"json.SyntaxError":                              "encoding/json",
+	"json.Token":                                    "encoding/json",
+	"json.Unmarshal":                                "encoding/json",
+	"json.UnmarshalFieldError":                      "encoding/json",
+	"json.UnmarshalTypeError":                       "encoding/json",
+	"json.Unmarshaler":                              "encoding/json",
+	"json.UnsupportedTypeError":                     "encoding/json",
+	"json.UnsupportedValueError":                    "encoding/json",
+	"jsonrpc.Dial":                                  "net/rpc/jsonrpc",
+	"jsonrpc.NewClient":                             "net/rpc/jsonrpc",
+	"jsonrpc.NewClientCodec":                        "net/rpc/jsonrpc",
+	"jsonrpc.NewServerCodec":                        "net/rpc/jsonrpc",
+	"jsonrpc.ServeConn":                             "net/rpc/jsonrpc",
+	"list.Element":                                  "container/list",
+	"list.List":                                     "container/list",
+	"list.New":                                      "container/list",
+	"log.Fatal":                                     "log",
+	"log.Fatalf":                                    "log",
+	"log.Fatalln":                                   "log",
+	"log.Flags":                                     "log",
+	"log.LUTC":                                      "log",
+	"log.Ldate":                                     "log",
+	"log.Llongfile":                                 "log",
+	"log.Lmicroseconds":                             "log",
+	"log.Logger":                                    "log",
+	"log.Lshortfile":                                "log",
+	"log.LstdFlags":                                 "log",
+	"log.Ltime":                                     "log",
+	"log.New":                                       "log",
+	"log.Output":                                    "log",
+	"log.Panic":                                     "log",
+	"log.Panicf":                                    "log",
+	"log.Panicln":                                   "log",
+	"log.Prefix":                                    "log",
+	"log.Print":                                     "log",
+	"log.Printf":                                    "log",
+	"log.Println":                                   "log",
+	"log.SetFlags":                                  "log",
+	"log.SetOutput":                                 "log",
+	"log.SetPrefix":                                 "log",
+	"lzw.LSB":                                       "compress/lzw",
+	"lzw.MSB":                                       "compress/lzw",
+	"lzw.NewReader":                                 "compress/lzw",
+	"lzw.NewWriter":                                 "compress/lzw",
+	"lzw.Order":                                     "compress/lzw",
+	"macho.Cpu":                                     "debug/macho",
+	"macho.Cpu386":                                  "debug/macho",
+	"macho.CpuAmd64":                                "debug/macho",
+	"macho.CpuArm":                                  "debug/macho",
+	"macho.CpuPpc":                                  "debug/macho",
+	"macho.CpuPpc64":                                "debug/macho",
+	"macho.Dylib":                                   "debug/macho",
+	"macho.DylibCmd":                                "debug/macho",
+	"macho.Dysymtab":                                "debug/macho",
+	"macho.DysymtabCmd":                             "debug/macho",
+	"macho.ErrNotFat":                               "debug/macho",
+	"macho.FatArch":                                 "debug/macho",
+	"macho.FatArchHeader":                           "debug/macho",
+	"macho.FatFile":                                 "debug/macho",
+	"macho.File":                                    "debug/macho",
+	"macho.FileHeader":                              "debug/macho",
+	"macho.FormatError":                             "debug/macho",
+	"macho.Load":                                    "debug/macho",
+	"macho.LoadBytes":                               "debug/macho",
+	"macho.LoadCmd":                                 "debug/macho",
+	"macho.LoadCmdDylib":                            "debug/macho",
+	"macho.LoadCmdDylinker":                         "debug/macho",
+	"macho.LoadCmdDysymtab":                         "debug/macho",
+	"macho.LoadCmdSegment":                          "debug/macho",
+	"macho.LoadCmdSegment64":                        "debug/macho",
+	"macho.LoadCmdSymtab":                           "debug/macho",
+	"macho.LoadCmdThread":                           "debug/macho",
+	"macho.LoadCmdUnixThread":                       "debug/macho",
+	"macho.Magic32":                                 "debug/macho",
+	"macho.Magic64":                                 "debug/macho",
+	"macho.MagicFat":                                "debug/macho",
+	"macho.NewFatFile":                              "debug/macho",
+	"macho.NewFile":                                 "debug/macho",
+	"macho.Nlist32":                                 "debug/macho",
+	"macho.Nlist64":                                 "debug/macho",
+	"macho.Open":                                    "debug/macho",
+	"macho.OpenFat":                                 "debug/macho",
+	"macho.Regs386":                                 "debug/macho",
+	"macho.RegsAMD64":                               "debug/macho",
+	"macho.Section":                                 "debug/macho",
+	"macho.Section32":                               "debug/macho",
+	"macho.Section64":                               "debug/macho",
+	"macho.SectionHeader":                           "debug/macho",
+	"macho.Segment":                                 "debug/macho",
+	"macho.Segment32":                               "debug/macho",
+	"macho.Segment64":                               "debug/macho",
+	"macho.SegmentHeader":                           "debug/macho",
+	"macho.Symbol":                                  "debug/macho",
+	"macho.Symtab":                                  "debug/macho",
+	"macho.SymtabCmd":                               "debug/macho",
+	"macho.Thread":                                  "debug/macho",
+	"macho.Type":                                    "debug/macho",
+	"macho.TypeBundle":                              "debug/macho",
+	"macho.TypeDylib":                               "debug/macho",
+	"macho.TypeExec":                                "debug/macho",
+	"macho.TypeObj":                                 "debug/macho",
+	"mail.Address":                                  "net/mail",
+	"mail.AddressParser":                            "net/mail",
+	"mail.ErrHeaderNotPresent":                      "net/mail",
+	"mail.Header":                                   "net/mail",
+	"mail.Message":                                  "net/mail",
+	"mail.ParseAddress":                             "net/mail",
+	"mail.ParseAddressList":                         "net/mail",
+	"mail.ReadMessage":                              "net/mail",
+	"math.Abs":                                      "math",
+	"math.Acos":                                     "math",
+	"math.Acosh":                                    "math",
+	"math.Asin":                                     "math",
+	"math.Asinh":                                    "math",
+	"math.Atan":                                     "math",
+	"math.Atan2":                                    "math",
+	"math.Atanh":                                    "math",
+	"math.Cbrt":                                     "math",
+	"math.Ceil":                                     "math",
+	"math.Copysign":                                 "math",
+	"math.Cos":                                      "math",
+	"math.Cosh":                                     "math",
+	"math.Dim":                                      "math",
+	"math.E":                                        "math",
+	"math.Erf":                                      "math",
+	"math.Erfc":                                     "math",
+	"math.Exp":                                      "math",
+	"math.Exp2":                                     "math",
+	"math.Expm1":                                    "math",
+	"math.Float32bits":                              "math",
+	"math.Float32frombits":                          "math",
+	"math.Float64bits":                              "math",
+	"math.Float64frombits":                          "math",
+	"math.Floor":                                    "math",
+	"math.Frexp":                                    "math",
+	"math.Gamma":                                    "math",
+	"math.Hypot":                                    "math",
+	"math.Ilogb":                                    "math",
+	"math.Inf":                                      "math",
+	"math.IsInf":                                    "math",
+	"math.IsNaN":                                    "math",
+	"math.J0":                                       "math",
+	"math.J1":                                       "math",
+	"math.Jn":                                       "math",
+	"math.Ldexp":                                    "math",
+	"math.Lgamma":                                   "math",
+	"math.Ln10":                                     "math",
+	"math.Ln2":                                      "math",
+	"math.Log":                                      "math",
+	"math.Log10":                                    "math",
+	"math.Log10E":                                   "math",
+	"math.Log1p":                                    "math",
+	"math.Log2":                                     "math",
+	"math.Log2E":                                    "math",
+	"math.Logb":                                     "math",
+	"math.Max":                                      "math",
+	"math.MaxFloat32":                               "math",
+	"math.MaxFloat64":                               "math",
+	"math.MaxInt16":                                 "math",
+	"math.MaxInt32":                                 "math",
+	"math.MaxInt64":                                 "math",
+	"math.MaxInt8":                                  "math",
+	"math.MaxUint16":                                "math",
+	"math.MaxUint32":                                "math",
+	"math.MaxUint64":                                "math",
+	"math.MaxUint8":                                 "math",
+	"math.Min":                                      "math",
+	"math.MinInt16":                                 "math",
+	"math.MinInt32":                                 "math",
+	"math.MinInt64":                                 "math",
+	"math.MinInt8":                                  "math",
+	"math.Mod":                                      "math",
+	"math.Modf":                                     "math",
+	"math.NaN":                                      "math",
+	"math.Nextafter":                                "math",
+	"math.Nextafter32":                              "math",
+	"math.Phi":                                      "math",
+	"math.Pi":                                       "math",
+	"math.Pow":                                      "math",
+	"math.Pow10":                                    "math",
+	"math.Remainder":                                "math",
+	"math.Signbit":                                  "math",
+	"math.Sin":                                      "math",
+	"math.Sincos":                                   "math",
+	"math.Sinh":                                     "math",
+	"math.SmallestNonzeroFloat32":                   "math",
+	"math.SmallestNonzeroFloat64":                   "math",
+	"math.Sqrt":                                     "math",
+	"math.Sqrt2":                                    "math",
+	"math.SqrtE":                                    "math",
+	"math.SqrtPhi":                                  "math",
+	"math.SqrtPi":                                   "math",
+	"math.Tan":                                      "math",
+	"math.Tanh":                                     "math",
+	"math.Trunc":                                    "math",
+	"math.Y0":                                       "math",
+	"math.Y1":                                       "math",
+	"math.Yn":                                       "math",
+	"md5.BlockSize":                                 "crypto/md5",
+	"md5.New":                                       "crypto/md5",
+	"md5.Size":                                      "crypto/md5",
+	"md5.Sum":                                       "crypto/md5",
+	"mime.AddExtensionType":                         "mime",
+	"mime.BEncoding":                                "mime",
+	"mime.ExtensionsByType":                         "mime",
+	"mime.FormatMediaType":                          "mime",
+	"mime.ParseMediaType":                           "mime",
+	"mime.QEncoding":                                "mime",
+	"mime.TypeByExtension":                          "mime",
+	"mime.WordDecoder":                              "mime",
+	"mime.WordEncoder":                              "mime",
+	"multipart.File":                                "mime/multipart",
+	"multipart.FileHeader":                          "mime/multipart",
+	"multipart.Form":                                "mime/multipart",
+	"multipart.NewReader":                           "mime/multipart",
+	"multipart.NewWriter":                           "mime/multipart",
+	"multipart.Part":                                "mime/multipart",
+	"multipart.Reader":                              "mime/multipart",
+	"multipart.Writer":                              "mime/multipart",
+	"net.Addr":                                      "net",
+	"net.AddrError":                                 "net",
+	"net.CIDRMask":                                  "net",
+	"net.Conn":                                      "net",
+	"net.DNSConfigError":                            "net",
+	"net.DNSError":                                  "net",
+	"net.Dial":                                      "net",
+	"net.DialIP":                                    "net",
+	"net.DialTCP":                                   "net",
+	"net.DialTimeout":                               "net",
+	"net.DialUDP":                                   "net",
+	"net.DialUnix":                                  "net",
+	"net.Dialer":                                    "net",
+	"net.ErrWriteToConnected":                       "net",
+	"net.Error":                                     "net",
+	"net.FileConn":                                  "net",
+	"net.FileListener":                              "net",
+	"net.FilePacketConn":                            "net",
+	"net.FlagBroadcast":                             "net",
+	"net.FlagLoopback":                              "net",
+	"net.FlagMulticast":                             "net",
+	"net.FlagPointToPoint":                          "net",
+	"net.FlagUp":                                    "net",
+	"net.Flags":                                     "net",
+	"net.HardwareAddr":                              "net",
+	"net.IP":                                        "net",
+	"net.IPAddr":                                    "net",
+	"net.IPConn":                                    "net",
+	"net.IPMask":                                    "net",
+	"net.IPNet":                                     "net",
+	"net.IPv4":                                      "net",
+	"net.IPv4Mask":                                  "net",
+	"net.IPv4allrouter":                             "net",
+	"net.IPv4allsys":                                "net",
+	"net.IPv4bcast":                                 "net",
+	"net.IPv4len":                                   "net",
+	"net.IPv4zero":                                  "net",
+	"net.IPv6interfacelocalallnodes":                "net",
+	"net.IPv6len":                                   "net",
+	"net.IPv6linklocalallnodes":                     "net",
+	"net.IPv6linklocalallrouters":                   "net",
+	"net.IPv6loopback":                              "net",
+	"net.IPv6unspecified":                           "net",
+	"net.IPv6zero":                                  "net",
+	"net.Interface":                                 "net",
+	"net.InterfaceAddrs":                            "net",
+	"net.InterfaceByIndex":                          "net",
+	"net.InterfaceByName":                           "net",
+	"net.Interfaces":                                "net",
+	"net.InvalidAddrError":                          "net",
+	"net.JoinHostPort":                              "net",
+	"net.Listen":                                    "net",
+	"net.ListenIP":                                  "net",
+	"net.ListenMulticastUDP":                        "net",
+	"net.ListenPacket":                              "net",
+	"net.ListenTCP":                                 "net",
+	"net.ListenUDP":                                 "net",
+	"net.ListenUnix":                                "net",
+	"net.ListenUnixgram":                            "net",
+	"net.Listener":                                  "net",
+	"net.LookupAddr":                                "net",
+	"net.LookupCNAME":                               "net",
+	"net.LookupHost":                                "net",
+	"net.LookupIP":                                  "net",
+	"net.LookupMX":                                  "net",
+	"net.LookupNS":                                  "net",
+	"net.LookupPort":                                "net",
+	"net.LookupSRV":                                 "net",
+	"net.LookupTXT":                                 "net",
+	"net.MX":                                        "net",
+	"net.NS":                                        "net",
+	"net.OpError":                                   "net",
+	"net.PacketConn":                                "net",
+	"net.ParseCIDR":                                 "net",
+	"net.ParseError":                                "net",
+	"net.ParseIP":                                   "net",
+	"net.ParseMAC":                                  "net",
+	"net.Pipe":                                      "net",
+	"net.ResolveIPAddr":                             "net",
+	"net.ResolveTCPAddr":                            "net",
+	"net.ResolveUDPAddr":                            "net",
+	"net.ResolveUnixAddr":                           "net",
+	"net.SRV":                                       "net",
+	"net.SplitHostPort":                             "net",
+	"net.TCPAddr":                                   "net",
+	"net.TCPConn":                                   "net",
+	"net.TCPListener":                               "net",
+	"net.UDPAddr":                                   "net",
+	"net.UDPConn":                                   "net",
+	"net.UnixAddr":                                  "net",
+	"net.UnixConn":                                  "net",
+	"net.UnixListener":                              "net",
+	"net.UnknownNetworkError":                       "net",
+	"os.Args":                                       "os",
+	"os.Chdir":                                      "os",
+	"os.Chmod":                                      "os",
+	"os.Chown":                                      "os",
+	"os.Chtimes":                                    "os",
+	"os.Clearenv":                                   "os",
+	"os.Create":                                     "os",
+	"os.DevNull":                                    "os",
+	"os.Environ":                                    "os",
+	"os.ErrExist":                                   "os",
+	"os.ErrInvalid":                                 "os",
+	"os.ErrNotExist":                                "os",
+	"os.ErrPermission":                              "os",
+	"os.Exit":                                       "os",
+	"os.Expand":                                     "os",
+	"os.ExpandEnv":                                  "os",
+	"os.File":                                       "os",
+	"os.FileInfo":                                   "os",
+	"os.FileMode":                                   "os",
+	"os.FindProcess":                                "os",
+	"os.Getegid":                                    "os",
+	"os.Getenv":                                     "os",
+	"os.Geteuid":                                    "os",
+	"os.Getgid":                                     "os",
+	"os.Getgroups":                                  "os",
+	"os.Getpagesize":                                "os",
+	"os.Getpid":                                     "os",
+	"os.Getppid":                                    "os",
+	"os.Getuid":                                     "os",
+	"os.Getwd":                                      "os",
+	"os.Hostname":                                   "os",
+	"os.Interrupt":                                  "os",
+	"os.IsExist":                                    "os",
+	"os.IsNotExist":                                 "os",
+	"os.IsPathSeparator":                            "os",
+	"os.IsPermission":                               "os",
+	"os.Kill":                                       "os",
+	"os.Lchown":                                     "os",
+	"os.Link":                                       "os",
+	"os.LinkError":                                  "os",
+	"os.LookupEnv":                                  "os",
+	"os.Lstat":                                      "os",
+	"os.Mkdir":                                      "os",
+	"os.MkdirAll":                                   "os",
+	"os.ModeAppend":                                 "os",
+	"os.ModeCharDevice":                             "os",
+	"os.ModeDevice":                                 "os",
+	"os.ModeDir":                                    "os",
+	"os.ModeExclusive":                              "os",
+	"os.ModeNamedPipe":                              "os",
+	"os.ModePerm":                                   "os",
+	"os.ModeSetgid":                                 "os",
+	"os.ModeSetuid":                                 "os",
+	"os.ModeSocket":                                 "os",
+	"os.ModeSticky":                                 "os",
+	"os.ModeSymlink":                                "os",
+	"os.ModeTemporary":                              "os",
+	"os.ModeType":                                   "os",
+	"os.NewFile":                                    "os",
+	"os.NewSyscallError":                            "os",
+	"os.O_APPEND":                                   "os",
+	"os.O_CREATE":                                   "os",
+	"os.O_EXCL":                                     "os",
+	"os.O_RDONLY":                                   "os",
+	"os.O_RDWR":                                     "os",
+	"os.O_SYNC":                                     "os",
+	"os.O_TRUNC":                                    "os",
+	"os.O_WRONLY":                                   "os",
+	"os.Open":                                       "os",
+	"os.OpenFile":                                   "os",
+	"os.PathError":                                  "os",
+	"os.PathListSeparator":                          "os",
+	"os.PathSeparator":                              "os",
+	"os.Pipe":                                       "os",
+	"os.ProcAttr":                                   "os",
+	"os.Process":                                    "os",
+	"os.ProcessState":                               "os",
+	"os.Readlink":                                   "os",
+	"os.Remove":                                     "os",
+	"os.RemoveAll":                                  "os",
+	"os.Rename":                                     "os",
+	"os.SEEK_CUR":                                   "os",
+	"os.SEEK_END":                                   "os",
+	"os.SEEK_SET":                                   "os",
+	"os.SameFile":                                   "os",
+	"os.Setenv":                                     "os",
+	"os.Signal":                                     "os",
+	"os.StartProcess":                               "os",
+	"os.Stat":                                       "os",
+	"os.Stderr":                                     "os",
+	"os.Stdin":                                      "os",
+	"os.Stdout":                                     "os",
+	"os.Symlink":                                    "os",
+	"os.SyscallError":                               "os",
+	"os.TempDir":                                    "os",
+	"os.Truncate":                                   "os",
+	"os.Unsetenv":                                   "os",
+	"palette.Plan9":                                 "image/color/palette",
+	"palette.WebSafe":                               "image/color/palette",
+	"parse.ActionNode":                              "text/template/parse",
+	"parse.BoolNode":                                "text/template/parse",
+	"parse.BranchNode":                              "text/template/parse",
+	"parse.ChainNode":                               "text/template/parse",
+	"parse.CommandNode":                             "text/template/parse",
+	"parse.DotNode":                                 "text/template/parse",
+	"parse.FieldNode":                               "text/template/parse",
+	"parse.IdentifierNode":                          "text/template/parse",
+	"parse.IfNode":                                  "text/template/parse",
+	"parse.IsEmptyTree":                             "text/template/parse",
+	"parse.ListNode":                                "text/template/parse",
+	"parse.New":                                     "text/template/parse",
+	"parse.NewIdentifier":                           "text/template/parse",
+	"parse.NilNode":                                 "text/template/parse",
+	"parse.Node":                                    "text/template/parse",
+	"parse.NodeAction":                              "text/template/parse",
+	"parse.NodeBool":                                "text/template/parse",
+	"parse.NodeChain":                               "text/template/parse",
+	"parse.NodeCommand":                             "text/template/parse",
+	"parse.NodeDot":                                 "text/template/parse",
+	"parse.NodeField":                               "text/template/parse",
+	"parse.NodeIdentifier":                          "text/template/parse",
+	"parse.NodeIf":                                  "text/template/parse",
+	"parse.NodeList":                                "text/template/parse",
+	"parse.NodeNil":                                 "text/template/parse",
+	"parse.NodeNumber":                              "text/template/parse",
+	"parse.NodePipe":                                "text/template/parse",
+	"parse.NodeRange":                               "text/template/parse",
+	"parse.NodeString":                              "text/template/parse",
+	"parse.NodeTemplate":                            "text/template/parse",
+	"parse.NodeText":                                "text/template/parse",
+	"parse.NodeType":                                "text/template/parse",
+	"parse.NodeVariable":                            "text/template/parse",
+	"parse.NodeWith":                                "text/template/parse",
+	"parse.NumberNode":                              "text/template/parse",
+	"parse.Parse":                                   "text/template/parse",
+	"parse.PipeNode":                                "text/template/parse",
+	"parse.Pos":                                     "text/template/parse",
+	"parse.RangeNode":                               "text/template/parse",
+	"parse.StringNode":                              "text/template/parse",
+	"parse.TemplateNode":                            "text/template/parse",
+	"parse.TextNode":                                "text/template/parse",
+	"parse.Tree":                                    "text/template/parse",
+	"parse.VariableNode":                            "text/template/parse",
+	"parse.WithNode":                                "text/template/parse",
+	"parser.AllErrors":                              "go/parser",
+	"parser.DeclarationErrors":                      "go/parser",
+	"parser.ImportsOnly":                            "go/parser",
+	"parser.Mode":                                   "go/parser",
+	"parser.PackageClauseOnly":                      "go/parser",
+	"parser.ParseComments":                          "go/parser",
+	"parser.ParseDir":                               "go/parser",
+	"parser.ParseExpr":                              "go/parser",
+	"parser.ParseExprFrom":                          "go/parser",
+	"parser.ParseFile":                              "go/parser",
+	"parser.SpuriousErrors":                         "go/parser",
+	"parser.Trace":                                  "go/parser",
+	"path.Base":                                     "path",
+	"path.Clean":                                    "path",
+	"path.Dir":                                      "path",
+	"path.ErrBadPattern":                            "path",
+	"path.Ext":                                      "path",
+	"path.IsAbs":                                    "path",
+	"path.Join":                                     "path",
+	"path.Match":                                    "path",
+	"path.Split":                                    "path",
+	"pe.COFFSymbol":                                 "debug/pe",
+	"pe.COFFSymbolSize":                             "debug/pe",
+	"pe.DataDirectory":                              "debug/pe",
+	"pe.File":                                       "debug/pe",
+	"pe.FileHeader":                                 "debug/pe",
+	"pe.FormatError":                                "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_AM33":                    "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_AMD64":                   "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_ARM":                     "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_EBC":                     "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_I386":                    "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_IA64":                    "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_M32R":                    "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_MIPS16":                  "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_MIPSFPU":                 "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_MIPSFPU16":               "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_POWERPC":                 "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_POWERPCFP":               "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_R4000":                   "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_SH3":                     "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_SH3DSP":                  "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_SH4":                     "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_SH5":                     "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_THUMB":                   "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_UNKNOWN":                 "debug/pe",
+	"pe.IMAGE_FILE_MACHINE_WCEMIPSV2":               "debug/pe",
+	"pe.ImportDirectory":                            "debug/pe",
+	"pe.NewFile":                                    "debug/pe",
+	"pe.Open":                                       "debug/pe",
+	"pe.OptionalHeader32":                           "debug/pe",
+	"pe.OptionalHeader64":                           "debug/pe",
+	"pe.Section":                                    "debug/pe",
+	"pe.SectionHeader":                              "debug/pe",
+	"pe.SectionHeader32":                            "debug/pe",
+	"pe.Symbol":                                     "debug/pe",
+	"pem.Block":                                     "encoding/pem",
+	"pem.Decode":                                    "encoding/pem",
+	"pem.Encode":                                    "encoding/pem",
+	"pem.EncodeToMemory":                            "encoding/pem",
+	"pkix.AlgorithmIdentifier":                      "crypto/x509/pkix",
+	"pkix.AttributeTypeAndValue":                    "crypto/x509/pkix",
+	"pkix.AttributeTypeAndValueSET":                 "crypto/x509/pkix",
+	"pkix.CertificateList":                          "crypto/x509/pkix",
+	"pkix.Extension":                                "crypto/x509/pkix",
+	"pkix.Name":                                     "crypto/x509/pkix",
+	"pkix.RDNSequence":                              "crypto/x509/pkix",
+	"pkix.RelativeDistinguishedNameSET":             "crypto/x509/pkix",
+	"pkix.RevokedCertificate":                       "crypto/x509/pkix",
+	"pkix.TBSCertificateList":                       "crypto/x509/pkix",
+	"plan9obj.File":                                 "debug/plan9obj",
+	"plan9obj.FileHeader":                           "debug/plan9obj",
+	"plan9obj.Magic386":                             "debug/plan9obj",
+	"plan9obj.Magic64":                              "debug/plan9obj",
+	"plan9obj.MagicAMD64":                           "debug/plan9obj",
+	"plan9obj.MagicARM":                             "debug/plan9obj",
+	"plan9obj.NewFile":                              "debug/plan9obj",
+	"plan9obj.Open":                                 "debug/plan9obj",
+	"plan9obj.Section":                              "debug/plan9obj",
+	"plan9obj.SectionHeader":                        "debug/plan9obj",
+	"plan9obj.Sym":                                  "debug/plan9obj",
+	"png.BestCompression":                           "image/png",
+	"png.BestSpeed":                                 "image/png",
+	"png.CompressionLevel":                          "image/png",
+	"png.Decode":                                    "image/png",
+	"png.DecodeConfig":                              "image/png",
+	"png.DefaultCompression":                        "image/png",
+	"png.Encode":                                    "image/png",
+	"png.Encoder":                                   "image/png",
+	"png.FormatError":                               "image/png",
+	"png.NoCompression":                             "image/png",
+	"png.UnsupportedError":                          "image/png",
+	"pprof.Cmdline":                                 "net/http/pprof",
+	"pprof.Handler":                                 "net/http/pprof",
+	"pprof.Index":                                   "net/http/pprof",
+	"pprof.Lookup":                                  "runtime/pprof",
+	"pprof.NewProfile":                              "runtime/pprof",
 	// "pprof.Profile" is ambiguous
-	"pprof.Profiles":         "runtime/pprof",
-	"pprof.StartCPUProfile":  "runtime/pprof",
-	"pprof.StopCPUProfile":   "runtime/pprof",
-	"pprof.Symbol":           "net/http/pprof",
-	"pprof.WriteHeapProfile": "runtime/pprof",
-	"printer.CommentedNode":  "go/printer",
-	"printer.Config":         "go/printer",
-	"printer.Fprint":         "go/printer",
-	"printer.Mode":           "go/printer",
-	"printer.RawFormat":      "go/printer",
-	"printer.SourcePos":      "go/printer",
-	"printer.TabIndent":      "go/printer",
-	"printer.UseSpaces":      "go/printer",
-	"quick.Check":            "testing/quick",
-	"quick.CheckEqual":       "testing/quick",
-	"quick.CheckEqualError":  "testing/quick",
-	"quick.CheckError":       "testing/quick",
-	"quick.Config":           "testing/quick",
-	"quick.Generator":        "testing/quick",
-	"quick.SetupError":       "testing/quick",
-	"quick.Value":            "testing/quick",
-	"rand.ExpFloat64":        "math/rand",
-	"rand.Float32":           "math/rand",
-	"rand.Float64":           "math/rand",
+	"pprof.Profiles":            "runtime/pprof",
+	"pprof.StartCPUProfile":     "runtime/pprof",
+	"pprof.StopCPUProfile":      "runtime/pprof",
+	"pprof.Symbol":              "net/http/pprof",
+	"pprof.Trace":               "net/http/pprof",
+	"pprof.WriteHeapProfile":    "runtime/pprof",
+	"printer.CommentedNode":     "go/printer",
+	"printer.Config":            "go/printer",
+	"printer.Fprint":            "go/printer",
+	"printer.Mode":              "go/printer",
+	"printer.RawFormat":         "go/printer",
+	"printer.SourcePos":         "go/printer",
+	"printer.TabIndent":         "go/printer",
+	"printer.UseSpaces":         "go/printer",
+	"quick.Check":               "testing/quick",
+	"quick.CheckEqual":          "testing/quick",
+	"quick.CheckEqualError":     "testing/quick",
+	"quick.CheckError":          "testing/quick",
+	"quick.Config":              "testing/quick",
+	"quick.Generator":           "testing/quick",
+	"quick.SetupError":          "testing/quick",
+	"quick.Value":               "testing/quick",
+	"quotedprintable.NewReader": "mime/quotedprintable",
+	"quotedprintable.NewWriter": "mime/quotedprintable",
+	"quotedprintable.Reader":    "mime/quotedprintable",
+	"quotedprintable.Writer":    "mime/quotedprintable",
+	"rand.ExpFloat64":           "math/rand",
+	"rand.Float32":              "math/rand",
+	"rand.Float64":              "math/rand",
 	// "rand.Int" is ambiguous
 	"rand.Int31":                    "math/rand",
 	"rand.Int31n":                   "math/rand",
@@ -2191,6 +2573,7 @@
 	"reflect.Append":                "reflect",
 	"reflect.AppendSlice":           "reflect",
 	"reflect.Array":                 "reflect",
+	"reflect.ArrayOf":               "reflect",
 	"reflect.Bool":                  "reflect",
 	"reflect.BothDir":               "reflect",
 	"reflect.Chan":                  "reflect",
@@ -2203,6 +2586,7 @@
 	"reflect.Float32":               "reflect",
 	"reflect.Float64":               "reflect",
 	"reflect.Func":                  "reflect",
+	"reflect.FuncOf":                "reflect",
 	"reflect.Indirect":              "reflect",
 	"reflect.Int":                   "reflect",
 	"reflect.Int16":                 "reflect",
@@ -2298,6 +2682,8 @@
 	"rsa.ErrVerification":           "crypto/rsa",
 	"rsa.GenerateKey":               "crypto/rsa",
 	"rsa.GenerateMultiPrimeKey":     "crypto/rsa",
+	"rsa.OAEPOptions":               "crypto/rsa",
+	"rsa.PKCS1v15DecryptOptions":    "crypto/rsa",
 	"rsa.PSSOptions":                "crypto/rsa",
 	"rsa.PSSSaltLengthAuto":         "crypto/rsa",
 	"rsa.PSSSaltLengthEqualsHash":   "crypto/rsa",
@@ -2335,11 +2721,14 @@
 	"runtime.NumCgoCall":            "runtime",
 	"runtime.NumGoroutine":          "runtime",
 	"runtime.ReadMemStats":          "runtime",
+	"runtime.ReadTrace":             "runtime",
 	"runtime.SetBlockProfileRate":   "runtime",
 	"runtime.SetCPUProfileRate":     "runtime",
 	"runtime.SetFinalizer":          "runtime",
 	"runtime.Stack":                 "runtime",
 	"runtime.StackRecord":           "runtime",
+	"runtime.StartTrace":            "runtime",
+	"runtime.StopTrace":             "runtime",
 	"runtime.ThreadCreateProfile":   "runtime",
 	"runtime.TypeAssertionError":    "runtime",
 	"runtime.UnlockOSThread":        "runtime",
@@ -2384,11 +2773,19 @@
 	"sha512.BlockSize":                                     "crypto/sha512",
 	"sha512.New":                                           "crypto/sha512",
 	"sha512.New384":                                        "crypto/sha512",
+	"sha512.New512_224":                                    "crypto/sha512",
+	"sha512.New512_256":                                    "crypto/sha512",
 	"sha512.Size":                                          "crypto/sha512",
+	"sha512.Size224":                                       "crypto/sha512",
+	"sha512.Size256":                                       "crypto/sha512",
 	"sha512.Size384":                                       "crypto/sha512",
 	"sha512.Sum384":                                        "crypto/sha512",
 	"sha512.Sum512":                                        "crypto/sha512",
+	"sha512.Sum512_224":                                    "crypto/sha512",
+	"sha512.Sum512_256":                                    "crypto/sha512",
+	"signal.Ignore":                                        "os/signal",
 	"signal.Notify":                                        "os/signal",
+	"signal.Reset":                                         "os/signal",
 	"signal.Stop":                                          "os/signal",
 	"smtp.Auth":                                            "net/smtp",
 	"smtp.CRAMMD5Auth":                                     "net/smtp",
@@ -2417,6 +2814,8 @@
 	"sort.Strings":                                         "sort",
 	"sort.StringsAreSorted":                                "sort",
 	"sql.DB":                                               "database/sql",
+	"sql.DBStats":                                          "database/sql",
+	"sql.Drivers":                                          "database/sql",
 	"sql.ErrNoRows":                                        "database/sql",
 	"sql.ErrTxDone":                                        "database/sql",
 	"sql.NullBool":                                         "database/sql",
@@ -2462,6 +2861,7 @@
 	"strconv.QuoteToASCII":                                 "strconv",
 	"strconv.Unquote":                                      "strconv",
 	"strconv.UnquoteChar":                                  "strconv",
+	"strings.Compare":                                      "strings",
 	"strings.Contains":                                     "strings",
 	"strings.ContainsAny":                                  "strings",
 	"strings.ContainsRune":                                 "strings",
@@ -2479,6 +2879,7 @@
 	"strings.Join":                                         "strings",
 	"strings.LastIndex":                                    "strings",
 	"strings.LastIndexAny":                                 "strings",
+	"strings.LastIndexByte":                                "strings",
 	"strings.LastIndexFunc":                                "strings",
 	"strings.Map":                                          "strings",
 	"strings.NewReader":                                    "strings",
@@ -2520,6 +2921,7 @@
 	"sync.Mutex":                                           "sync",
 	"sync.NewCond":                                         "sync",
 	"sync.Once":                                            "sync",
+	"sync.Pool":                                            "sync",
 	"sync.RWMutex":                                         "sync",
 	"sync.WaitGroup":                                       "sync",
 	"syntax.ClassNL":                                       "regexp/syntax",
@@ -2628,6 +3030,8 @@
 	"syscall.AF_IMPLINK":                                   "syscall",
 	"syscall.AF_INET":                                      "syscall",
 	"syscall.AF_INET6":                                     "syscall",
+	"syscall.AF_INET6_SDP":                                 "syscall",
+	"syscall.AF_INET_SDP":                                  "syscall",
 	"syscall.AF_IPX":                                       "syscall",
 	"syscall.AF_IRDA":                                      "syscall",
 	"syscall.AF_ISDN":                                      "syscall",
@@ -3005,6 +3409,7 @@
 	"syscall.CLOCAL":                                       "syscall",
 	"syscall.CLONE_CHILD_CLEARTID":                         "syscall",
 	"syscall.CLONE_CHILD_SETTID":                           "syscall",
+	"syscall.CLONE_CSIGNAL":                                "syscall",
 	"syscall.CLONE_DETACHED":                               "syscall",
 	"syscall.CLONE_FILES":                                  "syscall",
 	"syscall.CLONE_FS":                                     "syscall",
@@ -3017,6 +3422,7 @@
 	"syscall.CLONE_NEWUTS":                                 "syscall",
 	"syscall.CLONE_PARENT":                                 "syscall",
 	"syscall.CLONE_PARENT_SETTID":                          "syscall",
+	"syscall.CLONE_PID":                                    "syscall",
 	"syscall.CLONE_PTRACE":                                 "syscall",
 	"syscall.CLONE_SETTLS":                                 "syscall",
 	"syscall.CLONE_SIGHAND":                                "syscall",
@@ -3100,9 +3506,12 @@
 	"syscall.CreateDirectory":                              "syscall",
 	"syscall.CreateFile":                                   "syscall",
 	"syscall.CreateFileMapping":                            "syscall",
+	"syscall.CreateHardLink":                               "syscall",
 	"syscall.CreateIoCompletionPort":                       "syscall",
 	"syscall.CreatePipe":                                   "syscall",
 	"syscall.CreateProcess":                                "syscall",
+	"syscall.CreateSymbolicLink":                           "syscall",
+	"syscall.CreateToolhelp32Snapshot":                     "syscall",
 	"syscall.Credential":                                   "syscall",
 	"syscall.CryptAcquireContext":                          "syscall",
 	"syscall.CryptGenRandom":                               "syscall",
@@ -3281,6 +3690,7 @@
 	"syscall.DNSRecord":                                    "syscall",
 	"syscall.DNSSRVData":                                   "syscall",
 	"syscall.DNSTXTData":                                   "syscall",
+	"syscall.DNS_INFO_NO_RECORDS":                          "syscall",
 	"syscall.DNS_TYPE_A":                                   "syscall",
 	"syscall.DNS_TYPE_A6":                                  "syscall",
 	"syscall.DNS_TYPE_AAAA":                                "syscall",
@@ -3356,9 +3766,15 @@
 	"syscall.DUPLICATE_SAME_ACCESS":                        "syscall",
 	"syscall.DeleteFile":                                   "syscall",
 	"syscall.DetachLsf":                                    "syscall",
+	"syscall.DeviceIoControl":                              "syscall",
 	"syscall.Dirent":                                       "syscall",
+	"syscall.DnsNameCompare":                               "syscall",
 	"syscall.DnsQuery":                                     "syscall",
 	"syscall.DnsRecordListFree":                            "syscall",
+	"syscall.DnsSectionAdditional":                         "syscall",
+	"syscall.DnsSectionAnswer":                             "syscall",
+	"syscall.DnsSectionAuthority":                          "syscall",
+	"syscall.DnsSectionQuestion":                           "syscall",
 	"syscall.Dup":                                          "syscall",
 	"syscall.Dup2":                                         "syscall",
 	"syscall.Dup3":                                         "syscall",
@@ -3560,10 +3976,13 @@
 	"syscall.ERROR_INSUFFICIENT_BUFFER":                    "syscall",
 	"syscall.ERROR_IO_PENDING":                             "syscall",
 	"syscall.ERROR_MOD_NOT_FOUND":                          "syscall",
+	"syscall.ERROR_MORE_DATA":                              "syscall",
+	"syscall.ERROR_NETNAME_DELETED":                        "syscall",
 	"syscall.ERROR_NOT_FOUND":                              "syscall",
 	"syscall.ERROR_NO_MORE_FILES":                          "syscall",
 	"syscall.ERROR_OPERATION_ABORTED":                      "syscall",
 	"syscall.ERROR_PATH_NOT_FOUND":                         "syscall",
+	"syscall.ERROR_PRIVILEGE_NOT_HELD":                     "syscall",
 	"syscall.ERROR_PROC_NOT_FOUND":                         "syscall",
 	"syscall.ESHLIBVERS":                                   "syscall",
 	"syscall.ESHUTDOWN":                                    "syscall",
@@ -3868,6 +4287,7 @@
 	"syscall.EV_DELETE":                                    "syscall",
 	"syscall.EV_DISABLE":                                   "syscall",
 	"syscall.EV_DISPATCH":                                  "syscall",
+	"syscall.EV_DROP":                                      "syscall",
 	"syscall.EV_ENABLE":                                    "syscall",
 	"syscall.EV_EOF":                                       "syscall",
 	"syscall.EV_ERROR":                                     "syscall",
@@ -3910,11 +4330,13 @@
 	"syscall.FILE_ATTRIBUTE_HIDDEN":                        "syscall",
 	"syscall.FILE_ATTRIBUTE_NORMAL":                        "syscall",
 	"syscall.FILE_ATTRIBUTE_READONLY":                      "syscall",
+	"syscall.FILE_ATTRIBUTE_REPARSE_POINT":                 "syscall",
 	"syscall.FILE_ATTRIBUTE_SYSTEM":                        "syscall",
 	"syscall.FILE_BEGIN":                                   "syscall",
 	"syscall.FILE_CURRENT":                                 "syscall",
 	"syscall.FILE_END":                                     "syscall",
 	"syscall.FILE_FLAG_BACKUP_SEMANTICS":                   "syscall",
+	"syscall.FILE_FLAG_OPEN_REPARSE_POINT":                 "syscall",
 	"syscall.FILE_FLAG_OVERLAPPED":                         "syscall",
 	"syscall.FILE_LIST_DIRECTORY":                          "syscall",
 	"syscall.FILE_MAP_COPY":                                "syscall",
@@ -3947,6 +4369,7 @@
 	"syscall.FORMAT_MESSAGE_FROM_SYSTEM":                   "syscall",
 	"syscall.FORMAT_MESSAGE_IGNORE_INSERTS":                "syscall",
 	"syscall.FORMAT_MESSAGE_MAX_WIDTH_MASK":                "syscall",
+	"syscall.FSCTL_GET_REPARSE_POINT":                      "syscall",
 	"syscall.F_ADDFILESIGS":                                "syscall",
 	"syscall.F_ADDSIGS":                                    "syscall",
 	"syscall.F_ALLOCATEALL":                                "syscall",
@@ -4041,6 +4464,7 @@
 	"syscall.Fchmodat":                                     "syscall",
 	"syscall.Fchown":                                       "syscall",
 	"syscall.Fchownat":                                     "syscall",
+	"syscall.FcntlFlock":                                   "syscall",
 	"syscall.FdSet":                                        "syscall",
 	"syscall.Fdatasync":                                    "syscall",
 	"syscall.FileNotifyInformation":                        "syscall",
@@ -4066,6 +4490,7 @@
 	"syscall.Fstore_t":                                     "syscall",
 	"syscall.Fsync":                                        "syscall",
 	"syscall.Ftruncate":                                    "syscall",
+	"syscall.FullPath":                                     "syscall",
 	"syscall.Futimes":                                      "syscall",
 	"syscall.Futimesat":                                    "syscall",
 	"syscall.GENERIC_ALL":                                  "syscall",
@@ -4532,7 +4957,9 @@
 	"syscall.IOC_IN":                                       "syscall",
 	"syscall.IOC_INOUT":                                    "syscall",
 	"syscall.IOC_OUT":                                      "syscall",
+	"syscall.IOC_VENDOR":                                   "syscall",
 	"syscall.IOC_WS2":                                      "syscall",
+	"syscall.IO_REPARSE_TAG_SYMLINK":                       "syscall",
 	"syscall.IPMreq":                                       "syscall",
 	"syscall.IPMreqn":                                      "syscall",
 	"syscall.IPPROTO_3PC":                                  "syscall",
@@ -4556,6 +4983,8 @@
 	"syscall.IPPROTO_DDP":                                  "syscall",
 	"syscall.IPPROTO_DGP":                                  "syscall",
 	"syscall.IPPROTO_DIVERT":                               "syscall",
+	"syscall.IPPROTO_DIVERT_INIT":                          "syscall",
+	"syscall.IPPROTO_DIVERT_RESP":                          "syscall",
 	"syscall.IPPROTO_DONE":                                 "syscall",
 	"syscall.IPPROTO_DSTOPTS":                              "syscall",
 	"syscall.IPPROTO_EGP":                                  "syscall",
@@ -4729,6 +5158,7 @@
 	"syscall.IPV6_PORTRANGE_LOW":                           "syscall",
 	"syscall.IPV6_PREFER_TEMPADDR":                         "syscall",
 	"syscall.IPV6_RECVDSTOPTS":                             "syscall",
+	"syscall.IPV6_RECVDSTPORT":                             "syscall",
 	"syscall.IPV6_RECVERR":                                 "syscall",
 	"syscall.IPV6_RECVHOPLIMIT":                            "syscall",
 	"syscall.IPV6_RECVHOPOPTS":                             "syscall",
@@ -4762,6 +5192,7 @@
 	"syscall.IP_DEFAULT_MULTICAST_LOOP":                    "syscall",
 	"syscall.IP_DEFAULT_MULTICAST_TTL":                     "syscall",
 	"syscall.IP_DF":                                        "syscall",
+	"syscall.IP_DIVERTFL":                                  "syscall",
 	"syscall.IP_DONTFRAG":                                  "syscall",
 	"syscall.IP_DROP_MEMBERSHIP":                           "syscall",
 	"syscall.IP_DROP_SOURCE_MEMBERSHIP":                    "syscall",
@@ -4954,6 +5385,7 @@
 	"syscall.Listxattr":                                    "syscall",
 	"syscall.LoadCancelIoEx":                               "syscall",
 	"syscall.LoadConnectEx":                                "syscall",
+	"syscall.LoadCreateSymbolicLink":                       "syscall",
 	"syscall.LoadDLL":                                      "syscall",
 	"syscall.LoadGetAddrInfo":                              "syscall",
 	"syscall.LoadLibrary":                                  "syscall",
@@ -4987,10 +5419,20 @@
 	"syscall.MADV_RANDOM":                                  "syscall",
 	"syscall.MADV_REMOVE":                                  "syscall",
 	"syscall.MADV_SEQUENTIAL":                              "syscall",
+	"syscall.MADV_SPACEAVAIL":                              "syscall",
 	"syscall.MADV_UNMERGEABLE":                             "syscall",
 	"syscall.MADV_WILLNEED":                                "syscall",
 	"syscall.MADV_ZERO_WIRED_PAGES":                        "syscall",
 	"syscall.MAP_32BIT":                                    "syscall",
+	"syscall.MAP_ALIGNED_SUPER":                            "syscall",
+	"syscall.MAP_ALIGNMENT_16MB":                           "syscall",
+	"syscall.MAP_ALIGNMENT_1TB":                            "syscall",
+	"syscall.MAP_ALIGNMENT_256TB":                          "syscall",
+	"syscall.MAP_ALIGNMENT_4GB":                            "syscall",
+	"syscall.MAP_ALIGNMENT_64KB":                           "syscall",
+	"syscall.MAP_ALIGNMENT_64PB":                           "syscall",
+	"syscall.MAP_ALIGNMENT_MASK":                           "syscall",
+	"syscall.MAP_ALIGNMENT_SHIFT":                          "syscall",
 	"syscall.MAP_ANON":                                     "syscall",
 	"syscall.MAP_ANONYMOUS":                                "syscall",
 	"syscall.MAP_COPY":                                     "syscall",
@@ -4998,9 +5440,16 @@
 	"syscall.MAP_EXECUTABLE":                               "syscall",
 	"syscall.MAP_FILE":                                     "syscall",
 	"syscall.MAP_FIXED":                                    "syscall",
+	"syscall.MAP_FLAGMASK":                                 "syscall",
 	"syscall.MAP_GROWSDOWN":                                "syscall",
 	"syscall.MAP_HASSEMAPHORE":                             "syscall",
 	"syscall.MAP_HUGETLB":                                  "syscall",
+	"syscall.MAP_INHERIT":                                  "syscall",
+	"syscall.MAP_INHERIT_COPY":                             "syscall",
+	"syscall.MAP_INHERIT_DEFAULT":                          "syscall",
+	"syscall.MAP_INHERIT_DONATE_COPY":                      "syscall",
+	"syscall.MAP_INHERIT_NONE":                             "syscall",
+	"syscall.MAP_INHERIT_SHARE":                            "syscall",
 	"syscall.MAP_JIT":                                      "syscall",
 	"syscall.MAP_LOCKED":                                   "syscall",
 	"syscall.MAP_NOCACHE":                                  "syscall",
@@ -5017,7 +5466,10 @@
 	"syscall.MAP_RESERVED0100":                             "syscall",
 	"syscall.MAP_SHARED":                                   "syscall",
 	"syscall.MAP_STACK":                                    "syscall",
+	"syscall.MAP_TRYFIXED":                                 "syscall",
 	"syscall.MAP_TYPE":                                     "syscall",
+	"syscall.MAP_WIRED":                                    "syscall",
+	"syscall.MAXIMUM_REPARSE_DATA_BUFFER_SIZE":             "syscall",
 	"syscall.MAXLEN_IFDESCR":                               "syscall",
 	"syscall.MAXLEN_PHYSADDR":                              "syscall",
 	"syscall.MAX_ADAPTER_ADDRESS_LENGTH":                   "syscall",
@@ -5250,6 +5702,7 @@
 	"syscall.NetlinkRouteAttr":                             "syscall",
 	"syscall.NetlinkRouteRequest":                          "syscall",
 	"syscall.NewCallback":                                  "syscall",
+	"syscall.NewCallbackCDecl":                             "syscall",
 	"syscall.NewLazyDLL":                                   "syscall",
 	"syscall.NlAttr":                                       "syscall",
 	"syscall.NlMsgerr":                                     "syscall",
@@ -5533,6 +5986,9 @@
 	"syscall.Pread":                                        "syscall",
 	"syscall.Proc":                                         "syscall",
 	"syscall.ProcAttr":                                     "syscall",
+	"syscall.Process32First":                               "syscall",
+	"syscall.Process32Next":                                "syscall",
+	"syscall.ProcessEntry32":                               "syscall",
 	"syscall.ProcessInformation":                           "syscall",
 	"syscall.Protoent":                                     "syscall",
 	"syscall.PtraceAttach":                                 "syscall",
@@ -5651,6 +6107,7 @@
 	"syscall.RTF_FLOW":                                     "syscall",
 	"syscall.RTF_FMASK":                                    "syscall",
 	"syscall.RTF_GATEWAY":                                  "syscall",
+	"syscall.RTF_GWFLAG_COMPAT":                            "syscall",
 	"syscall.RTF_HOST":                                     "syscall",
 	"syscall.RTF_IFREF":                                    "syscall",
 	"syscall.RTF_IFSCOPE":                                  "syscall",
@@ -6026,6 +6483,7 @@
 	"syscall.SIOCGIFGENERIC":                               "syscall",
 	"syscall.SIOCGIFGMEMB":                                 "syscall",
 	"syscall.SIOCGIFGROUP":                                 "syscall",
+	"syscall.SIOCGIFHARDMTU":                               "syscall",
 	"syscall.SIOCGIFHWADDR":                                "syscall",
 	"syscall.SIOCGIFINDEX":                                 "syscall",
 	"syscall.SIOCGIFKPI":                                   "syscall",
@@ -6054,15 +6512,18 @@
 	"syscall.SIOCGLIFADDR":                                 "syscall",
 	"syscall.SIOCGLIFPHYADDR":                              "syscall",
 	"syscall.SIOCGLIFPHYRTABLE":                            "syscall",
+	"syscall.SIOCGLIFPHYTTL":                               "syscall",
 	"syscall.SIOCGLINKSTR":                                 "syscall",
 	"syscall.SIOCGLOWAT":                                   "syscall",
 	"syscall.SIOCGPGRP":                                    "syscall",
 	"syscall.SIOCGPRIVATE_0":                               "syscall",
 	"syscall.SIOCGPRIVATE_1":                               "syscall",
 	"syscall.SIOCGRARP":                                    "syscall",
+	"syscall.SIOCGSPPPPARAMS":                              "syscall",
 	"syscall.SIOCGSTAMP":                                   "syscall",
 	"syscall.SIOCGSTAMPNS":                                 "syscall",
 	"syscall.SIOCGVH":                                      "syscall",
+	"syscall.SIOCGVNETID":                                  "syscall",
 	"syscall.SIOCIFCREATE":                                 "syscall",
 	"syscall.SIOCIFCREATE2":                                "syscall",
 	"syscall.SIOCIFDESTROY":                                "syscall",
@@ -6122,14 +6583,19 @@
 	"syscall.SIOCSIFXFLAGS":                                "syscall",
 	"syscall.SIOCSLIFPHYADDR":                              "syscall",
 	"syscall.SIOCSLIFPHYRTABLE":                            "syscall",
+	"syscall.SIOCSLIFPHYTTL":                               "syscall",
 	"syscall.SIOCSLINKSTR":                                 "syscall",
 	"syscall.SIOCSLOWAT":                                   "syscall",
 	"syscall.SIOCSPGRP":                                    "syscall",
 	"syscall.SIOCSRARP":                                    "syscall",
+	"syscall.SIOCSSPPPPARAMS":                              "syscall",
 	"syscall.SIOCSVH":                                      "syscall",
+	"syscall.SIOCSVNETID":                                  "syscall",
 	"syscall.SIOCZIFDATA":                                  "syscall",
 	"syscall.SIO_GET_EXTENSION_FUNCTION_POINTER":           "syscall",
 	"syscall.SIO_GET_INTERFACE_LIST":                       "syscall",
+	"syscall.SIO_KEEPALIVE_VALS":                           "syscall",
+	"syscall.SIO_UDP_CONNRESET":                            "syscall",
 	"syscall.SOCK_CLOEXEC":                                 "syscall",
 	"syscall.SOCK_DCCP":                                    "syscall",
 	"syscall.SOCK_DGRAM":                                   "syscall",
@@ -6233,6 +6699,7 @@
 	"syscall.SO_UPDATE_CONNECT_CONTEXT":                    "syscall",
 	"syscall.SO_USELOOPBACK":                               "syscall",
 	"syscall.SO_USER_COOKIE":                               "syscall",
+	"syscall.SO_VENDOR":                                    "syscall",
 	"syscall.SO_WANTMORE":                                  "syscall",
 	"syscall.SO_WANTOOBFLAG":                               "syscall",
 	"syscall.SSLExtraCertChainPolicyPara":                  "syscall",
@@ -6261,6 +6728,7 @@
 	"syscall.SW_SHOWNA":                                    "syscall",
 	"syscall.SW_SHOWNOACTIVATE":                            "syscall",
 	"syscall.SW_SHOWNORMAL":                                "syscall",
+	"syscall.SYMBOLIC_LINK_FLAG_DIRECTORY":                 "syscall",
 	"syscall.SYNCHRONIZE":                                  "syscall",
 	"syscall.SYSCTL_VERSION":                               "syscall",
 	"syscall.SYSCTL_VERS_0":                                "syscall",
@@ -6306,6 +6774,7 @@
 	"syscall.SYS_AUDIT_SESSION_SELF":                       "syscall",
 	"syscall.SYS_BDFLUSH":                                  "syscall",
 	"syscall.SYS_BIND":                                     "syscall",
+	"syscall.SYS_BINDAT":                                   "syscall",
 	"syscall.SYS_BREAK":                                    "syscall",
 	"syscall.SYS_BRK":                                      "syscall",
 	"syscall.SYS_BSDTHREAD_CREATE":                         "syscall",
@@ -6325,6 +6794,7 @@
 	"syscall.SYS_CAP_RIGHTS_LIMIT":                         "syscall",
 	"syscall.SYS_CHDIR":                                    "syscall",
 	"syscall.SYS_CHFLAGS":                                  "syscall",
+	"syscall.SYS_CHFLAGSAT":                                "syscall",
 	"syscall.SYS_CHMOD":                                    "syscall",
 	"syscall.SYS_CHMOD_EXTENDED":                           "syscall",
 	"syscall.SYS_CHOWN":                                    "syscall",
@@ -6342,6 +6812,7 @@
 	"syscall.SYS_CLOSEFROM":                                "syscall",
 	"syscall.SYS_CLOSE_NOCANCEL":                           "syscall",
 	"syscall.SYS_CONNECT":                                  "syscall",
+	"syscall.SYS_CONNECTAT":                                "syscall",
 	"syscall.SYS_CONNECT_NOCANCEL":                         "syscall",
 	"syscall.SYS_COPYFILE":                                 "syscall",
 	"syscall.SYS_CPUSET":                                   "syscall",
@@ -6698,6 +7169,7 @@
 	"syscall.SYS_PREADV":                                   "syscall",
 	"syscall.SYS_PREAD_NOCANCEL":                           "syscall",
 	"syscall.SYS_PRLIMIT64":                                "syscall",
+	"syscall.SYS_PROCCTL":                                  "syscall",
 	"syscall.SYS_PROCESS_POLICY":                           "syscall",
 	"syscall.SYS_PROCESS_VM_READV":                         "syscall",
 	"syscall.SYS_PROCESS_VM_WRITEV":                        "syscall",
@@ -7118,6 +7590,7 @@
 	"syscall.Select":                                       "syscall",
 	"syscall.Sendfile":                                     "syscall",
 	"syscall.Sendmsg":                                      "syscall",
+	"syscall.SendmsgN":                                     "syscall",
 	"syscall.Sendto":                                       "syscall",
 	"syscall.Servent":                                      "syscall",
 	"syscall.SetBpf":                                       "syscall",
@@ -7264,6 +7737,7 @@
 	"syscall.Sync":                                         "syscall",
 	"syscall.SyncFileRange":                                "syscall",
 	"syscall.SysProcAttr":                                  "syscall",
+	"syscall.SysProcIDMap":                                 "syscall",
 	"syscall.Syscall":                                      "syscall",
 	"syscall.Syscall12":                                    "syscall",
 	"syscall.Syscall15":                                    "syscall",
@@ -7280,6 +7754,7 @@
 	"syscall.TCIOFLUSH":                                    "syscall",
 	"syscall.TCOFLUSH":                                     "syscall",
 	"syscall.TCPInfo":                                      "syscall",
+	"syscall.TCPKeepalive":                                 "syscall",
 	"syscall.TCP_CA_NAME_MAX":                              "syscall",
 	"syscall.TCP_CONGCTL":                                  "syscall",
 	"syscall.TCP_CONGESTION":                               "syscall",
@@ -7314,6 +7789,7 @@
 	"syscall.TCP_RXT_FINDROP":                              "syscall",
 	"syscall.TCP_SACK_ENABLE":                              "syscall",
 	"syscall.TCP_SYNCNT":                                   "syscall",
+	"syscall.TCP_VENDOR":                                   "syscall",
 	"syscall.TCP_WINDOW_CLAMP":                             "syscall",
 	"syscall.TCSAFLUSH":                                    "syscall",
 	"syscall.TCSETS":                                       "syscall",
@@ -7323,6 +7799,13 @@
 	"syscall.TF_USE_KERNEL_APC":                            "syscall",
 	"syscall.TF_USE_SYSTEM_THREAD":                         "syscall",
 	"syscall.TF_WRITE_BEHIND":                              "syscall",
+	"syscall.TH32CS_INHERIT":                               "syscall",
+	"syscall.TH32CS_SNAPALL":                               "syscall",
+	"syscall.TH32CS_SNAPHEAPLIST":                          "syscall",
+	"syscall.TH32CS_SNAPMODULE":                            "syscall",
+	"syscall.TH32CS_SNAPMODULE32":                          "syscall",
+	"syscall.TH32CS_SNAPPROCESS":                           "syscall",
+	"syscall.TH32CS_SNAPTHREAD":                            "syscall",
 	"syscall.TIME_ZONE_ID_DAYLIGHT":                        "syscall",
 	"syscall.TIME_ZONE_ID_STANDARD":                        "syscall",
 	"syscall.TIME_ZONE_ID_UNKNOWN":                         "syscall",
@@ -7540,6 +8023,7 @@
 	"syscall.Unlinkat":                                     "syscall",
 	"syscall.UnmapViewOfFile":                              "syscall",
 	"syscall.Unmount":                                      "syscall",
+	"syscall.Unsetenv":                                     "syscall",
 	"syscall.Unshare":                                      "syscall",
 	"syscall.UserInfo10":                                   "syscall",
 	"syscall.Ustat":                                        "syscall",
@@ -7597,6 +8081,7 @@
 	"syscall.WSADESCRIPTION_LEN":                           "syscall",
 	"syscall.WSAData":                                      "syscall",
 	"syscall.WSAEACCES":                                    "syscall",
+	"syscall.WSAECONNRESET":                                "syscall",
 	"syscall.WSAEnumProtocols":                             "syscall",
 	"syscall.WSAID_CONNECTEX":                              "syscall",
 	"syscall.WSAIoctl":                                     "syscall",
@@ -7700,6 +8185,7 @@
 	"tar.TypeFifo":                                         "archive/tar",
 	"tar.TypeGNULongLink":                                  "archive/tar",
 	"tar.TypeGNULongName":                                  "archive/tar",
+	"tar.TypeGNUSparse":                                    "archive/tar",
 	"tar.TypeLink":                                         "archive/tar",
 	"tar.TypeReg":                                          "archive/tar",
 	"tar.TypeRegA":                                         "archive/tar",
@@ -7745,10 +8231,14 @@
 	"testing.BenchmarkResult":                     "testing",
 	"testing.Cover":                               "testing",
 	"testing.CoverBlock":                          "testing",
+	"testing.Coverage":                            "testing",
 	"testing.InternalBenchmark":                   "testing",
 	"testing.InternalExample":                     "testing",
 	"testing.InternalTest":                        "testing",
+	"testing.M":                                   "testing",
 	"testing.Main":                                "testing",
+	"testing.MainStart":                           "testing",
+	"testing.PB":                                  "testing",
 	"testing.RegisterCover":                       "testing",
 	"testing.RunBenchmarks":                       "testing",
 	"testing.RunExamples":                         "testing",
@@ -7838,12 +8328,21 @@
 	"tls.Certificate":                             "crypto/tls",
 	"tls.Client":                                  "crypto/tls",
 	"tls.ClientAuthType":                          "crypto/tls",
+	"tls.ClientHelloInfo":                         "crypto/tls",
+	"tls.ClientSessionCache":                      "crypto/tls",
+	"tls.ClientSessionState":                      "crypto/tls",
 	"tls.Config":                                  "crypto/tls",
 	"tls.Conn":                                    "crypto/tls",
 	"tls.ConnectionState":                         "crypto/tls",
+	"tls.CurveID":                                 "crypto/tls",
+	"tls.CurveP256":                               "crypto/tls",
+	"tls.CurveP384":                               "crypto/tls",
+	"tls.CurveP521":                               "crypto/tls",
 	"tls.Dial":                                    "crypto/tls",
+	"tls.DialWithDialer":                          "crypto/tls",
 	"tls.Listen":                                  "crypto/tls",
 	"tls.LoadX509KeyPair":                         "crypto/tls",
+	"tls.NewLRUClientSessionCache":                "crypto/tls",
 	"tls.NewListener":                             "crypto/tls",
 	"tls.NoClientCert":                            "crypto/tls",
 	"tls.RequestClientCert":                       "crypto/tls",
@@ -7853,12 +8352,15 @@
 	"tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA":    "crypto/tls",
 	"tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256": "crypto/tls",
 	"tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA":    "crypto/tls",
+	"tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384": "crypto/tls",
 	"tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA":        "crypto/tls",
 	"tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA":     "crypto/tls",
 	"tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA":      "crypto/tls",
 	"tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256":   "crypto/tls",
 	"tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA":      "crypto/tls",
+	"tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384":   "crypto/tls",
 	"tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA":          "crypto/tls",
+	"tls.TLS_FALLBACK_SCSV":                       "crypto/tls",
 	"tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA":           "crypto/tls",
 	"tls.TLS_RSA_WITH_AES_128_CBC_SHA":            "crypto/tls",
 	"tls.TLS_RSA_WITH_AES_256_CBC_SHA":            "crypto/tls",
@@ -7961,13 +8463,145 @@
 	"token.VAR":                                   "go/token",
 	"token.XOR":                                   "go/token",
 	"token.XOR_ASSIGN":                            "go/token",
+	"trace.Start":                                 "runtime/trace",
+	"trace.Stop":                                  "runtime/trace",
+	"types.Array":                                 "go/types",
+	"types.AssertableTo":                          "go/types",
+	"types.AssignableTo":                          "go/types",
+	"types.Basic":                                 "go/types",
+	"types.BasicInfo":                             "go/types",
+	"types.BasicKind":                             "go/types",
+	"types.Bool":                                  "go/types",
+	"types.Builtin":                               "go/types",
+	"types.Byte":                                  "go/types",
+	"types.Chan":                                  "go/types",
+	"types.ChanDir":                               "go/types",
+	"types.Checker":                               "go/types",
+	"types.Comparable":                            "go/types",
+	"types.Complex128":                            "go/types",
+	"types.Complex64":                             "go/types",
+	"types.Config":                                "go/types",
+	"types.Const":                                 "go/types",
+	"types.ConvertibleTo":                         "go/types",
+	"types.DefPredeclaredTestFuncs":               "go/types",
+	"types.Error":                                 "go/types",
+	"types.Eval":                                  "go/types",
+	"types.ExprString":                            "go/types",
+	"types.FieldVal":                              "go/types",
+	"types.Float32":                               "go/types",
+	"types.Float64":                               "go/types",
+	"types.Func":                                  "go/types",
+	"types.Id":                                    "go/types",
+	"types.Identical":                             "go/types",
+	"types.Implements":                            "go/types",
+	"types.Importer":                              "go/types",
+	"types.Info":                                  "go/types",
+	"types.Initializer":                           "go/types",
+	"types.Int":                                   "go/types",
+	"types.Int16":                                 "go/types",
+	"types.Int32":                                 "go/types",
+	"types.Int64":                                 "go/types",
+	"types.Int8":                                  "go/types",
+	"types.Interface":                             "go/types",
+	"types.Invalid":                               "go/types",
+	"types.IsBoolean":                             "go/types",
+	"types.IsComplex":                             "go/types",
+	"types.IsConstType":                           "go/types",
+	"types.IsFloat":                               "go/types",
+	"types.IsInteger":                             "go/types",
+	"types.IsInterface":                           "go/types",
+	"types.IsNumeric":                             "go/types",
+	"types.IsOrdered":                             "go/types",
+	"types.IsString":                              "go/types",
+	"types.IsUnsigned":                            "go/types",
+	"types.IsUntyped":                             "go/types",
+	"types.Label":                                 "go/types",
+	"types.LookupFieldOrMethod":                   "go/types",
+	"types.Map":                                   "go/types",
+	"types.MethodExpr":                            "go/types",
+	"types.MethodSet":                             "go/types",
+	"types.MethodVal":                             "go/types",
+	"types.MissingMethod":                         "go/types",
+	"types.Named":                                 "go/types",
+	"types.NewArray":                              "go/types",
+	"types.NewChan":                               "go/types",
+	"types.NewChecker":                            "go/types",
+	"types.NewConst":                              "go/types",
+	"types.NewField":                              "go/types",
+	"types.NewFunc":                               "go/types",
+	"types.NewInterface":                          "go/types",
+	"types.NewLabel":                              "go/types",
+	"types.NewMap":                                "go/types",
+	"types.NewMethodSet":                          "go/types",
+	"types.NewNamed":                              "go/types",
+	"types.NewPackage":                            "go/types",
+	"types.NewParam":                              "go/types",
+	"types.NewPkgName":                            "go/types",
+	"types.NewPointer":                            "go/types",
+	"types.NewScope":                              "go/types",
+	"types.NewSignature":                          "go/types",
+	"types.NewSlice":                              "go/types",
+	"types.NewStruct":                             "go/types",
+	"types.NewTuple":                              "go/types",
+	"types.NewTypeName":                           "go/types",
+	"types.NewVar":                                "go/types",
+	"types.Nil":                                   "go/types",
+	"types.ObjectString":                          "go/types",
+	"types.Package":                               "go/types",
+	"types.PkgName":                               "go/types",
+	"types.Pointer":                               "go/types",
+	"types.Qualifier":                             "go/types",
+	"types.RecvOnly":                              "go/types",
+	"types.RelativeTo":                            "go/types",
+	"types.Rune":                                  "go/types",
+	"types.Scope":                                 "go/types",
+	"types.Selection":                             "go/types",
+	"types.SelectionKind":                         "go/types",
+	"types.SelectionString":                       "go/types",
+	"types.SendOnly":                              "go/types",
+	"types.SendRecv":                              "go/types",
+	"types.Signature":                             "go/types",
+	"types.Sizes":                                 "go/types",
+	"types.Slice":                                 "go/types",
+	"types.StdSizes":                              "go/types",
+	"types.String":                                "go/types",
+	"types.Struct":                                "go/types",
+	"types.Tuple":                                 "go/types",
+	"types.Typ":                                   "go/types",
+	"types.Type":                                  "go/types",
+	"types.TypeAndValue":                          "go/types",
+	"types.TypeName":                              "go/types",
+	"types.TypeString":                            "go/types",
+	"types.Uint":                                  "go/types",
+	"types.Uint16":                                "go/types",
+	"types.Uint32":                                "go/types",
+	"types.Uint64":                                "go/types",
+	"types.Uint8":                                 "go/types",
+	"types.Uintptr":                               "go/types",
+	"types.Universe":                              "go/types",
+	"types.Unsafe":                                "go/types",
+	"types.UnsafePointer":                         "go/types",
+	"types.UntypedBool":                           "go/types",
+	"types.UntypedComplex":                        "go/types",
+	"types.UntypedFloat":                          "go/types",
+	"types.UntypedInt":                            "go/types",
+	"types.UntypedNil":                            "go/types",
+	"types.UntypedRune":                           "go/types",
+	"types.UntypedString":                         "go/types",
+	"types.Var":                                   "go/types",
+	"types.WriteExpr":                             "go/types",
+	"types.WriteSignature":                        "go/types",
+	"types.WriteType":                             "go/types",
 	"unicode.ASCII_Hex_Digit":                     "unicode",
+	"unicode.Ahom":                                "unicode",
+	"unicode.Anatolian_Hieroglyphs":               "unicode",
 	"unicode.Arabic":                              "unicode",
 	"unicode.Armenian":                            "unicode",
 	"unicode.Avestan":                             "unicode",
 	"unicode.AzeriCase":                           "unicode",
 	"unicode.Balinese":                            "unicode",
 	"unicode.Bamum":                               "unicode",
+	"unicode.Bassa_Vah":                           "unicode",
 	"unicode.Batak":                               "unicode",
 	"unicode.Bengali":                             "unicode",
 	"unicode.Bidi_Control":                        "unicode",
@@ -7982,6 +8616,7 @@
 	"unicode.CaseRange":                           "unicode",
 	"unicode.CaseRanges":                          "unicode",
 	"unicode.Categories":                          "unicode",
+	"unicode.Caucasian_Albanian":                  "unicode",
 	"unicode.Cc":                                  "unicode",
 	"unicode.Cf":                                  "unicode",
 	"unicode.Chakma":                              "unicode",
@@ -8000,7 +8635,9 @@
 	"unicode.Devanagari":                          "unicode",
 	"unicode.Diacritic":                           "unicode",
 	"unicode.Digit":                               "unicode",
+	"unicode.Duployan":                            "unicode",
 	"unicode.Egyptian_Hieroglyphs":                "unicode",
+	"unicode.Elbasan":                             "unicode",
 	"unicode.Ethiopic":                            "unicode",
 	"unicode.Extender":                            "unicode",
 	"unicode.FoldCategory":                        "unicode",
@@ -8008,6 +8645,7 @@
 	"unicode.Georgian":                            "unicode",
 	"unicode.Glagolitic":                          "unicode",
 	"unicode.Gothic":                              "unicode",
+	"unicode.Grantha":                             "unicode",
 	"unicode.GraphicRanges":                       "unicode",
 	"unicode.Greek":                               "unicode",
 	"unicode.Gujarati":                            "unicode",
@@ -8015,6 +8653,7 @@
 	"unicode.Han":                                 "unicode",
 	"unicode.Hangul":                              "unicode",
 	"unicode.Hanunoo":                             "unicode",
+	"unicode.Hatran":                              "unicode",
 	"unicode.Hebrew":                              "unicode",
 	"unicode.Hex_Digit":                           "unicode",
 	"unicode.Hiragana":                            "unicode",
@@ -8050,12 +8689,15 @@
 	"unicode.Kayah_Li":                            "unicode",
 	"unicode.Kharoshthi":                          "unicode",
 	"unicode.Khmer":                               "unicode",
+	"unicode.Khojki":                              "unicode",
+	"unicode.Khudawadi":                           "unicode",
 	"unicode.L":                                   "unicode",
 	"unicode.Lao":                                 "unicode",
 	"unicode.Latin":                               "unicode",
 	"unicode.Lepcha":                              "unicode",
 	"unicode.Letter":                              "unicode",
 	"unicode.Limbu":                               "unicode",
+	"unicode.Linear_A":                            "unicode",
 	"unicode.Linear_B":                            "unicode",
 	"unicode.Lisu":                                "unicode",
 	"unicode.Ll":                                  "unicode",
@@ -8069,8 +8711,10 @@
 	"unicode.Lycian":                              "unicode",
 	"unicode.Lydian":                              "unicode",
 	"unicode.M":                                   "unicode",
+	"unicode.Mahajani":                            "unicode",
 	"unicode.Malayalam":                           "unicode",
 	"unicode.Mandaic":                             "unicode",
+	"unicode.Manichaean":                          "unicode",
 	"unicode.Mark":                                "unicode",
 	"unicode.MaxASCII":                            "unicode",
 	"unicode.MaxCase":                             "unicode",
@@ -8079,13 +8723,18 @@
 	"unicode.Mc":                                  "unicode",
 	"unicode.Me":                                  "unicode",
 	"unicode.Meetei_Mayek":                        "unicode",
+	"unicode.Mende_Kikakui":                       "unicode",
 	"unicode.Meroitic_Cursive":                    "unicode",
 	"unicode.Meroitic_Hieroglyphs":                "unicode",
 	"unicode.Miao":                                "unicode",
 	"unicode.Mn":                                  "unicode",
+	"unicode.Modi":                                "unicode",
 	"unicode.Mongolian":                           "unicode",
+	"unicode.Mro":                                 "unicode",
+	"unicode.Multani":                             "unicode",
 	"unicode.Myanmar":                             "unicode",
 	"unicode.N":                                   "unicode",
+	"unicode.Nabataean":                           "unicode",
 	"unicode.Nd":                                  "unicode",
 	"unicode.New_Tai_Lue":                         "unicode",
 	"unicode.Nko":                                 "unicode",
@@ -8095,7 +8744,10 @@
 	"unicode.Number":                              "unicode",
 	"unicode.Ogham":                               "unicode",
 	"unicode.Ol_Chiki":                            "unicode",
+	"unicode.Old_Hungarian":                       "unicode",
 	"unicode.Old_Italic":                          "unicode",
+	"unicode.Old_North_Arabian":                   "unicode",
+	"unicode.Old_Permic":                          "unicode",
 	"unicode.Old_Persian":                         "unicode",
 	"unicode.Old_South_Arabian":                   "unicode",
 	"unicode.Old_Turkic":                          "unicode",
@@ -8111,8 +8763,11 @@
 	"unicode.Other_Math":                          "unicode",
 	"unicode.Other_Uppercase":                     "unicode",
 	"unicode.P":                                   "unicode",
+	"unicode.Pahawh_Hmong":                        "unicode",
+	"unicode.Palmyrene":                           "unicode",
 	"unicode.Pattern_Syntax":                      "unicode",
 	"unicode.Pattern_White_Space":                 "unicode",
+	"unicode.Pau_Cin_Hau":                         "unicode",
 	"unicode.Pc":                                  "unicode",
 	"unicode.Pd":                                  "unicode",
 	"unicode.Pe":                                  "unicode",
@@ -8124,6 +8779,7 @@
 	"unicode.PrintRanges":                         "unicode",
 	"unicode.Properties":                          "unicode",
 	"unicode.Ps":                                  "unicode",
+	"unicode.Psalter_Pahlavi":                     "unicode",
 	"unicode.Punct":                               "unicode",
 	"unicode.Quotation_Mark":                      "unicode",
 	"unicode.Radical":                             "unicode",
@@ -8141,6 +8797,8 @@
 	"unicode.Scripts":                             "unicode",
 	"unicode.Sharada":                             "unicode",
 	"unicode.Shavian":                             "unicode",
+	"unicode.Siddham":                             "unicode",
+	"unicode.SignWriting":                         "unicode",
 	"unicode.SimpleFold":                          "unicode",
 	"unicode.Sinhala":                             "unicode",
 	"unicode.Sk":                                  "unicode",
@@ -8167,6 +8825,7 @@
 	"unicode.Thai":                                "unicode",
 	"unicode.Tibetan":                             "unicode",
 	"unicode.Tifinagh":                            "unicode",
+	"unicode.Tirhuta":                             "unicode",
 	"unicode.Title":                               "unicode",
 	"unicode.TitleCase":                           "unicode",
 	"unicode.To":                                  "unicode",
@@ -8182,6 +8841,7 @@
 	"unicode.Vai":                                 "unicode",
 	"unicode.Variation_Selector":                  "unicode",
 	"unicode.Version":                             "unicode",
+	"unicode.Warang_Citi":                         "unicode",
 	"unicode.White_Space":                         "unicode",
 	"unicode.Yi":                                  "unicode",
 	"unicode.Z":                                   "unicode",
@@ -8233,8 +8893,10 @@
 	"x509.CertPool":                               "crypto/x509",
 	"x509.Certificate":                            "crypto/x509",
 	"x509.CertificateInvalidError":                "crypto/x509",
+	"x509.CertificateRequest":                     "crypto/x509",
 	"x509.ConstraintViolationError":               "crypto/x509",
 	"x509.CreateCertificate":                      "crypto/x509",
+	"x509.CreateCertificateRequest":               "crypto/x509",
 	"x509.DSA":                                    "crypto/x509",
 	"x509.DSAWithSHA1":                            "crypto/x509",
 	"x509.DSAWithSHA256":                          "crypto/x509",
@@ -8290,6 +8952,7 @@
 	"x509.PEMCipherDES":                           "crypto/x509",
 	"x509.ParseCRL":                               "crypto/x509",
 	"x509.ParseCertificate":                       "crypto/x509",
+	"x509.ParseCertificateRequest":                "crypto/x509",
 	"x509.ParseCertificates":                      "crypto/x509",
 	"x509.ParseDERCRL":                            "crypto/x509",
 	"x509.ParseECPrivateKey":                      "crypto/x509",
@@ -8370,5 +9033,6 @@
 	"zlib.NewWriterLevel":                         "compress/zlib",
 	"zlib.NewWriterLevelDict":                     "compress/zlib",
 	"zlib.NoCompression":                          "compress/zlib",
+	"zlib.Resetter":                               "compress/zlib",
 	"zlib.Writer":                                 "compress/zlib",
 }
diff --git a/go/src/golang.org/x/tools/oracle/callees.go b/go/src/golang.org/x/tools/oracle/callees.go
index 56e45e1..06c2c15 100644
--- a/go/src/golang.org/x/tools/oracle/callees.go
+++ b/go/src/golang.org/x/tools/oracle/callees.go
@@ -2,19 +2,21 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package oracle
 
 import (
 	"fmt"
 	"go/ast"
 	"go/token"
+	"go/types"
 	"sort"
 
 	"golang.org/x/tools/go/loader"
 	"golang.org/x/tools/go/pointer"
 	"golang.org/x/tools/go/ssa"
 	"golang.org/x/tools/go/ssa/ssautil"
-	"golang.org/x/tools/go/types"
 	"golang.org/x/tools/oracle/serial"
 )
 
@@ -90,12 +92,17 @@
 				return nil
 			}
 		} else if sel.Kind() == types.MethodVal {
-			recvtype := sel.Recv()
+			// Inspect the receiver type of the selected method.
+			// If it is concrete, the call is statically dispatched.
+			// (Due to implicit field selections, it is not enough to look
+			// at sel.Recv(), the type of the actual receiver expression.)
+			method := sel.Obj().(*types.Func)
+			recvtype := method.Type().(*types.Signature).Recv().Type()
 			if !types.IsInterface(recvtype) {
 				// static method call
 				q.result = &calleesTypesResult{
 					site:   e,
-					callee: sel.Obj().(*types.Func),
+					callee: method,
 				}
 				return nil
 			}
@@ -115,7 +122,7 @@
 	}
 
 	// Defer SSA construction till after errors are reported.
-	prog.BuildAll()
+	prog.Build()
 
 	// Ascertain calling function and call site.
 	callerFn := ssa.EnclosingFunction(pkg, qpos.path)
diff --git a/go/src/golang.org/x/tools/oracle/callees14.go b/go/src/golang.org/x/tools/oracle/callees14.go
new file mode 100644
index 0000000..b6d0ffe
--- /dev/null
+++ b/go/src/golang.org/x/tools/oracle/callees14.go
@@ -0,0 +1,260 @@
+// 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.
+
+// +build !go1.5
+
+package oracle
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"sort"
+
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/pointer"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/ssa/ssautil"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/oracle/serial"
+)
+
+// Callees reports the possible callees of the function call site
+// identified by the specified source location.
+func callees(q *Query) error {
+	lconf := loader.Config{Build: q.Build}
+
+	if err := setPTAScope(&lconf, q.Scope); err != nil {
+		return err
+	}
+
+	// Load/parse/type-check the program.
+	lprog, err := lconf.Load()
+	if err != nil {
+		return err
+	}
+	q.Fset = lprog.Fset
+
+	qpos, err := parseQueryPos(lprog, q.Pos, true) // needs exact pos
+	if err != nil {
+		return err
+	}
+
+	// Determine the enclosing call for the specified position.
+	var e *ast.CallExpr
+	for _, n := range qpos.path {
+		if e, _ = n.(*ast.CallExpr); e != nil {
+			break
+		}
+	}
+	if e == nil {
+		return fmt.Errorf("there is no function call here")
+	}
+	// TODO(adonovan): issue an error if the call is "too far
+	// away" from the current selection, as this most likely is
+	// not what the user intended.
+
+	// Reject type conversions.
+	if qpos.info.Types[e.Fun].IsType() {
+		return fmt.Errorf("this is a type conversion, not a function call")
+	}
+
+	// Deal with obviously static calls before constructing SSA form.
+	// Some static calls may yet require SSA construction,
+	// e.g.  f := func(){}; f().
+	switch funexpr := unparen(e.Fun).(type) {
+	case *ast.Ident:
+		switch obj := qpos.info.Uses[funexpr].(type) {
+		case *types.Builtin:
+			// Reject calls to built-ins.
+			return fmt.Errorf("this is a call to the built-in '%s' operator", obj.Name())
+		case *types.Func:
+			// This is a static function call
+			q.result = &calleesTypesResult{
+				site:   e,
+				callee: obj,
+			}
+			return nil
+		}
+	case *ast.SelectorExpr:
+		sel := qpos.info.Selections[funexpr]
+		if sel == nil {
+			// qualified identifier.
+			// May refer to top level function variable
+			// or to top level function.
+			callee := qpos.info.Uses[funexpr.Sel]
+			if obj, ok := callee.(*types.Func); ok {
+				q.result = &calleesTypesResult{
+					site:   e,
+					callee: obj,
+				}
+				return nil
+			}
+		} else if sel.Kind() == types.MethodVal {
+			// Inspect the receiver type of the selected method.
+			// If it is concrete, the call is statically dispatched.
+			// (Due to implicit field selections, it is not enough to look
+			// at sel.Recv(), the type of the actual receiver expression.)
+			method := sel.Obj().(*types.Func)
+			recvtype := method.Type().(*types.Signature).Recv().Type()
+			if !types.IsInterface(recvtype) {
+				// static method call
+				q.result = &calleesTypesResult{
+					site:   e,
+					callee: method,
+				}
+				return nil
+			}
+		}
+	}
+
+	prog := ssautil.CreateProgram(lprog, ssa.GlobalDebug)
+
+	ptaConfig, err := setupPTA(prog, lprog, q.PTALog, q.Reflection)
+	if err != nil {
+		return err
+	}
+
+	pkg := prog.Package(qpos.info.Pkg)
+	if pkg == nil {
+		return fmt.Errorf("no SSA package")
+	}
+
+	// Defer SSA construction till after errors are reported.
+	prog.Build()
+
+	// Ascertain calling function and call site.
+	callerFn := ssa.EnclosingFunction(pkg, qpos.path)
+	if callerFn == nil {
+		return fmt.Errorf("no SSA function built for this location (dead code?)")
+	}
+
+	// Find the call site.
+	site, err := findCallSite(callerFn, e)
+	if err != nil {
+		return err
+	}
+
+	funcs, err := findCallees(ptaConfig, site)
+	if err != nil {
+		return err
+	}
+
+	q.result = &calleesSSAResult{
+		site:  site,
+		funcs: funcs,
+	}
+	return nil
+}
+
+func findCallSite(fn *ssa.Function, call *ast.CallExpr) (ssa.CallInstruction, error) {
+	instr, _ := fn.ValueForExpr(call)
+	callInstr, _ := instr.(ssa.CallInstruction)
+	if instr == nil {
+		return nil, fmt.Errorf("this call site is unreachable in this analysis")
+	}
+	return callInstr, nil
+}
+
+func findCallees(conf *pointer.Config, site ssa.CallInstruction) ([]*ssa.Function, error) {
+	// Avoid running the pointer analysis for static calls.
+	if callee := site.Common().StaticCallee(); callee != nil {
+		switch callee.String() {
+		case "runtime.SetFinalizer", "(reflect.Value).Call":
+			// The PTA treats calls to these intrinsics as dynamic.
+			// TODO(adonovan): avoid reliance on PTA internals.
+
+		default:
+			return []*ssa.Function{callee}, nil // singleton
+		}
+	}
+
+	// Dynamic call: use pointer analysis.
+	conf.BuildCallGraph = true
+	cg := ptrAnalysis(conf).CallGraph
+	cg.DeleteSyntheticNodes()
+
+	// Find all call edges from the site.
+	n := cg.Nodes[site.Parent()]
+	if n == nil {
+		return nil, fmt.Errorf("this call site is unreachable in this analysis")
+	}
+	calleesMap := make(map[*ssa.Function]bool)
+	for _, edge := range n.Out {
+		if edge.Site == site {
+			calleesMap[edge.Callee.Func] = true
+		}
+	}
+
+	// De-duplicate and sort.
+	funcs := make([]*ssa.Function, 0, len(calleesMap))
+	for f := range calleesMap {
+		funcs = append(funcs, f)
+	}
+	sort.Sort(byFuncPos(funcs))
+	return funcs, nil
+}
+
+type calleesSSAResult struct {
+	site  ssa.CallInstruction
+	funcs []*ssa.Function
+}
+
+type calleesTypesResult struct {
+	site   *ast.CallExpr
+	callee *types.Func
+}
+
+func (r *calleesSSAResult) display(printf printfFunc) {
+	if len(r.funcs) == 0 {
+		// dynamic call on a provably nil func/interface
+		printf(r.site, "%s on nil value", r.site.Common().Description())
+	} else {
+		printf(r.site, "this %s dispatches to:", r.site.Common().Description())
+		for _, callee := range r.funcs {
+			printf(callee, "\t%s", callee)
+		}
+	}
+}
+
+func (r *calleesSSAResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	j := &serial.Callees{
+		Pos:  fset.Position(r.site.Pos()).String(),
+		Desc: r.site.Common().Description(),
+	}
+	for _, callee := range r.funcs {
+		j.Callees = append(j.Callees, &serial.CalleesItem{
+			Name: callee.String(),
+			Pos:  fset.Position(callee.Pos()).String(),
+		})
+	}
+	res.Callees = j
+}
+
+func (r *calleesTypesResult) display(printf printfFunc) {
+	printf(r.site, "this static function call dispatches to:")
+	printf(r.callee, "\t%s", r.callee.FullName())
+}
+
+func (r *calleesTypesResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	j := &serial.Callees{
+		Pos:  fset.Position(r.site.Pos()).String(),
+		Desc: "static function call",
+	}
+	j.Callees = []*serial.CalleesItem{
+		&serial.CalleesItem{
+			Name: r.callee.FullName(),
+			Pos:  fset.Position(r.callee.Pos()).String(),
+		},
+	}
+	res.Callees = j
+}
+
+// NB: byFuncPos is not deterministic across packages since it depends on load order.
+// Use lessPos if the tests need it.
+type byFuncPos []*ssa.Function
+
+func (a byFuncPos) Len() int           { return len(a) }
+func (a byFuncPos) Less(i, j int) bool { return a[i].Pos() < a[j].Pos() }
+func (a byFuncPos) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
diff --git a/go/src/golang.org/x/tools/oracle/callers.go b/go/src/golang.org/x/tools/oracle/callers.go
index 159a403..e7f3c8f 100644
--- a/go/src/golang.org/x/tools/oracle/callers.go
+++ b/go/src/golang.org/x/tools/oracle/callers.go
@@ -53,7 +53,7 @@
 	}
 
 	// Defer SSA construction till after errors are reported.
-	prog.BuildAll()
+	prog.Build()
 
 	target := ssa.EnclosingFunction(pkg, qpos.path)
 	if target == nil {
diff --git a/go/src/golang.org/x/tools/oracle/callstack.go b/go/src/golang.org/x/tools/oracle/callstack.go
index 6f04b60..ba88e99 100644
--- a/go/src/golang.org/x/tools/oracle/callstack.go
+++ b/go/src/golang.org/x/tools/oracle/callstack.go
@@ -61,7 +61,7 @@
 	}
 
 	// Defer SSA construction till after errors are reported.
-	prog.BuildAll()
+	prog.Build()
 
 	target := ssa.EnclosingFunction(pkg, qpos.path)
 	if target == nil {
diff --git a/go/src/golang.org/x/tools/oracle/definition.go b/go/src/golang.org/x/tools/oracle/definition.go
index a0340c6..67f65f9 100644
--- a/go/src/golang.org/x/tools/oracle/definition.go
+++ b/go/src/golang.org/x/tools/oracle/definition.go
@@ -2,15 +2,17 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package oracle
 
 import (
 	"fmt"
 	"go/ast"
 	"go/token"
+	"go/types"
 
 	"golang.org/x/tools/go/loader"
-	"golang.org/x/tools/go/types"
 	"golang.org/x/tools/oracle/serial"
 )
 
@@ -23,7 +25,7 @@
 	lconf := loader.Config{Build: q.Build}
 	allowErrors(&lconf)
 
-	if err := importQueryPackage(q.Pos, &lconf); err != nil {
+	if _, err := importQueryPackage(q.Pos, &lconf); err != nil {
 		return err
 	}
 
diff --git a/go/src/golang.org/x/tools/oracle/definition14.go b/go/src/golang.org/x/tools/oracle/definition14.go
new file mode 100644
index 0000000..c22b1fd
--- /dev/null
+++ b/go/src/golang.org/x/tools/oracle/definition14.go
@@ -0,0 +1,78 @@
+// 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.
+
+// +build !go1.5
+
+package oracle
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/oracle/serial"
+)
+
+// definition reports the location of the definition of an identifier.
+//
+// TODO(adonovan): opt: for intra-file references, the parser's
+// resolution might be enough; we should start with that.
+//
+func definition(q *Query) error {
+	lconf := loader.Config{Build: q.Build}
+	allowErrors(&lconf)
+
+	if _, err := importQueryPackage(q.Pos, &lconf); err != nil {
+		return err
+	}
+
+	// Load/parse/type-check the program.
+	lprog, err := lconf.Load()
+	if err != nil {
+		return err
+	}
+	q.Fset = lprog.Fset
+
+	qpos, err := parseQueryPos(lprog, q.Pos, false)
+	if err != nil {
+		return err
+	}
+
+	id, _ := qpos.path[0].(*ast.Ident)
+	if id == nil {
+		return fmt.Errorf("no identifier here")
+	}
+
+	obj := qpos.info.ObjectOf(id)
+	if obj == nil {
+		// Happens for y in "switch y := x.(type)",
+		// and the package declaration,
+		// but I think that's all.
+		return fmt.Errorf("no object for identifier")
+	}
+
+	q.result = &definitionResult{qpos, obj}
+	return nil
+}
+
+type definitionResult struct {
+	qpos *queryPos
+	obj  types.Object // object it denotes
+}
+
+func (r *definitionResult) display(printf printfFunc) {
+	printf(r.obj, "defined here as %s", r.qpos.objectString(r.obj))
+}
+
+func (r *definitionResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	definition := &serial.Definition{
+		Desc: r.obj.String(),
+	}
+	if pos := r.obj.Pos(); pos != token.NoPos { // Package objects have no Pos()
+		definition.ObjPos = fset.Position(pos).String()
+	}
+	res.Definition = definition
+}
diff --git a/go/src/golang.org/x/tools/oracle/describe.go b/go/src/golang.org/x/tools/oracle/describe.go
index ea1c5ec..70ddacf 100644
--- a/go/src/golang.org/x/tools/oracle/describe.go
+++ b/go/src/golang.org/x/tools/oracle/describe.go
@@ -2,21 +2,23 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.6
+
 package oracle
 
 import (
 	"bytes"
 	"fmt"
 	"go/ast"
+	exact "go/constant"
 	"go/token"
+	"go/types"
 	"log"
 	"os"
 	"strings"
 
 	"golang.org/x/tools/go/ast/astutil"
-	"golang.org/x/tools/go/exact"
 	"golang.org/x/tools/go/loader"
-	"golang.org/x/tools/go/types"
 	"golang.org/x/tools/go/types/typeutil"
 	"golang.org/x/tools/oracle/serial"
 )
@@ -31,7 +33,7 @@
 	lconf := loader.Config{Build: q.Build}
 	allowErrors(&lconf)
 
-	if err := importQueryPackage(q.Pos, &lconf); err != nil {
+	if _, err := importQueryPackage(q.Pos, &lconf); err != nil {
 		return err
 	}
 
@@ -513,11 +515,15 @@
 	var pkg *types.Package
 	switch n := path[0].(type) {
 	case *ast.ImportSpec:
-		var pkgname *types.PkgName
+		var obj types.Object
 		if n.Name != nil {
-			pkgname = qpos.info.Defs[n.Name].(*types.PkgName)
-		} else if p := qpos.info.Implicits[n]; p != nil {
-			pkgname = p.(*types.PkgName)
+			obj = qpos.info.Defs[n.Name]
+		} else {
+			obj = qpos.info.Implicits[n]
+		}
+		pkgname, _ := obj.(*types.PkgName)
+		if pkgname == nil {
+			return nil, fmt.Errorf("can't import package %s", n.Path.Value)
 		}
 		pkg = pkgname.Imported()
 		description = fmt.Sprintf("import of package %q", pkg.Path())
@@ -674,6 +680,12 @@
 		return "const"
 	case *types.PkgName:
 		return "package"
+	case *types.Builtin:
+		return "builtin" // e.g. when describing package "unsafe"
+	case *types.Nil:
+		return "nil"
+	case *types.Label:
+		return "label"
 	}
 	panic(o)
 }
diff --git a/go/src/golang.org/x/tools/oracle/describe14.go b/go/src/golang.org/x/tools/oracle/describe14.go
new file mode 100644
index 0000000..c8ccc2d
--- /dev/null
+++ b/go/src/golang.org/x/tools/oracle/describe14.go
@@ -0,0 +1,786 @@
+// 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.
+
+// +build !go1.5
+
+package oracle
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/token"
+	"log"
+	"os"
+	"strings"
+
+	"golang.org/x/tools/go/ast/astutil"
+	"golang.org/x/tools/go/exact"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/go/types/typeutil"
+	"golang.org/x/tools/oracle/serial"
+)
+
+// describe describes the syntax node denoted by the query position,
+// including:
+// - its syntactic category
+// - the definition of its referent (for identifiers) [now redundant]
+// - its type and method set (for an expression or type expression)
+//
+func describe(q *Query) error {
+	lconf := loader.Config{Build: q.Build}
+	allowErrors(&lconf)
+
+	if _, err := importQueryPackage(q.Pos, &lconf); err != nil {
+		return err
+	}
+
+	// Load/parse/type-check the program.
+	lprog, err := lconf.Load()
+	if err != nil {
+		return err
+	}
+	q.Fset = lprog.Fset
+
+	qpos, err := parseQueryPos(lprog, q.Pos, true) // (need exact pos)
+	if err != nil {
+		return err
+	}
+
+	if false { // debugging
+		fprintf(os.Stderr, lprog.Fset, qpos.path[0], "you selected: %s %s",
+			astutil.NodeDescription(qpos.path[0]), pathToString(qpos.path))
+	}
+
+	path, action := findInterestingNode(qpos.info, qpos.path)
+	switch action {
+	case actionExpr:
+		q.result, err = describeValue(qpos, path)
+
+	case actionType:
+		q.result, err = describeType(qpos, path)
+
+	case actionPackage:
+		q.result, err = describePackage(qpos, path)
+
+	case actionStmt:
+		q.result, err = describeStmt(qpos, path)
+
+	case actionUnknown:
+		q.result = &describeUnknownResult{path[0]}
+
+	default:
+		panic(action) // unreachable
+	}
+	return err
+}
+
+type describeUnknownResult struct {
+	node ast.Node
+}
+
+func (r *describeUnknownResult) display(printf printfFunc) {
+	// Nothing much to say about misc syntax.
+	printf(r.node, "%s", astutil.NodeDescription(r.node))
+}
+
+func (r *describeUnknownResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	res.Describe = &serial.Describe{
+		Desc: astutil.NodeDescription(r.node),
+		Pos:  fset.Position(r.node.Pos()).String(),
+	}
+}
+
+type action int
+
+const (
+	actionUnknown action = iota // None of the below
+	actionExpr                  // FuncDecl, true Expr or Ident(types.{Const,Var})
+	actionType                  // type Expr or Ident(types.TypeName).
+	actionStmt                  // Stmt or Ident(types.Label)
+	actionPackage               // Ident(types.Package) or ImportSpec
+)
+
+// findInterestingNode classifies the syntax node denoted by path as one of:
+//    - an expression, part of an expression or a reference to a constant
+//      or variable;
+//    - a type, part of a type, or a reference to a named type;
+//    - a statement, part of a statement, or a label referring to a statement;
+//    - part of a package declaration or import spec.
+//    - none of the above.
+// and returns the most "interesting" associated node, which may be
+// the same node, an ancestor or a descendent.
+//
+func findInterestingNode(pkginfo *loader.PackageInfo, path []ast.Node) ([]ast.Node, action) {
+	// TODO(adonovan): integrate with go/types/stdlib_test.go and
+	// apply this to every AST node we can find to make sure it
+	// doesn't crash.
+
+	// TODO(adonovan): audit for ParenExpr safety, esp. since we
+	// traverse up and down.
+
+	// TODO(adonovan): if the users selects the "." in
+	// "fmt.Fprintf()", they'll get an ambiguous selection error;
+	// we won't even reach here.  Can we do better?
+
+	// TODO(adonovan): describing a field within 'type T struct {...}'
+	// describes the (anonymous) struct type and concludes "no methods".
+	// We should ascend to the enclosing type decl, if any.
+
+	for len(path) > 0 {
+		switch n := path[0].(type) {
+		case *ast.GenDecl:
+			if len(n.Specs) == 1 {
+				// Descend to sole {Import,Type,Value}Spec child.
+				path = append([]ast.Node{n.Specs[0]}, path...)
+				continue
+			}
+			return path, actionUnknown // uninteresting
+
+		case *ast.FuncDecl:
+			// Descend to function name.
+			path = append([]ast.Node{n.Name}, path...)
+			continue
+
+		case *ast.ImportSpec:
+			return path, actionPackage
+
+		case *ast.ValueSpec:
+			if len(n.Names) == 1 {
+				// Descend to sole Ident child.
+				path = append([]ast.Node{n.Names[0]}, path...)
+				continue
+			}
+			return path, actionUnknown // uninteresting
+
+		case *ast.TypeSpec:
+			// Descend to type name.
+			path = append([]ast.Node{n.Name}, path...)
+			continue
+
+		case ast.Stmt:
+			return path, actionStmt
+
+		case *ast.ArrayType,
+			*ast.StructType,
+			*ast.FuncType,
+			*ast.InterfaceType,
+			*ast.MapType,
+			*ast.ChanType:
+			return path, actionType
+
+		case *ast.Comment, *ast.CommentGroup, *ast.File, *ast.KeyValueExpr, *ast.CommClause:
+			return path, actionUnknown // uninteresting
+
+		case *ast.Ellipsis:
+			// Continue to enclosing node.
+			// e.g. [...]T in ArrayType
+			//      f(x...) in CallExpr
+			//      f(x...T) in FuncType
+
+		case *ast.Field:
+			// TODO(adonovan): this needs more thought,
+			// since fields can be so many things.
+			if len(n.Names) == 1 {
+				// Descend to sole Ident child.
+				path = append([]ast.Node{n.Names[0]}, path...)
+				continue
+			}
+			// Zero names (e.g. anon field in struct)
+			// or multiple field or param names:
+			// continue to enclosing field list.
+
+		case *ast.FieldList:
+			// Continue to enclosing node:
+			// {Struct,Func,Interface}Type or FuncDecl.
+
+		case *ast.BasicLit:
+			if _, ok := path[1].(*ast.ImportSpec); ok {
+				return path[1:], actionPackage
+			}
+			return path, actionExpr
+
+		case *ast.SelectorExpr:
+			// TODO(adonovan): use Selections info directly.
+			if pkginfo.Uses[n.Sel] == nil {
+				// TODO(adonovan): is this reachable?
+				return path, actionUnknown
+			}
+			// Descend to .Sel child.
+			path = append([]ast.Node{n.Sel}, path...)
+			continue
+
+		case *ast.Ident:
+			switch pkginfo.ObjectOf(n).(type) {
+			case *types.PkgName:
+				return path, actionPackage
+
+			case *types.Const:
+				return path, actionExpr
+
+			case *types.Label:
+				return path, actionStmt
+
+			case *types.TypeName:
+				return path, actionType
+
+			case *types.Var:
+				// For x in 'struct {x T}', return struct type, for now.
+				if _, ok := path[1].(*ast.Field); ok {
+					_ = path[2].(*ast.FieldList) // assertion
+					if _, ok := path[3].(*ast.StructType); ok {
+						return path[3:], actionType
+					}
+				}
+				return path, actionExpr
+
+			case *types.Func:
+				return path, actionExpr
+
+			case *types.Builtin:
+				// For reference to built-in function, return enclosing call.
+				path = path[1:] // ascend to enclosing function call
+				continue
+
+			case *types.Nil:
+				return path, actionExpr
+			}
+
+			// No object.
+			switch path[1].(type) {
+			case *ast.SelectorExpr:
+				// Return enclosing selector expression.
+				return path[1:], actionExpr
+
+			case *ast.Field:
+				// TODO(adonovan): test this.
+				// e.g. all f in:
+				//  struct { f, g int }
+				//  interface { f() }
+				//  func (f T) method(f, g int) (f, g bool)
+				//
+				// switch path[3].(type) {
+				// case *ast.FuncDecl:
+				// case *ast.StructType:
+				// case *ast.InterfaceType:
+				// }
+				//
+				// return path[1:], actionExpr
+				//
+				// Unclear what to do with these.
+				// Struct.Fields             -- field
+				// Interface.Methods         -- field
+				// FuncType.{Params.Results} -- actionExpr
+				// FuncDecl.Recv             -- actionExpr
+
+			case *ast.File:
+				// 'package foo'
+				return path, actionPackage
+
+			case *ast.ImportSpec:
+				// TODO(adonovan): fix: why no package object? go/types bug?
+				return path[1:], actionPackage
+
+			default:
+				// e.g. blank identifier
+				// or y in "switch y := x.(type)"
+				// or code in a _test.go file that's not part of the package.
+				log.Printf("unknown reference %s in %T\n", n, path[1])
+				return path, actionUnknown
+			}
+
+		case *ast.StarExpr:
+			if pkginfo.Types[n].IsType() {
+				return path, actionType
+			}
+			return path, actionExpr
+
+		case ast.Expr:
+			// All Expr but {BasicLit,Ident,StarExpr} are
+			// "true" expressions that evaluate to a value.
+			return path, actionExpr
+		}
+
+		// Ascend to parent.
+		path = path[1:]
+	}
+
+	return nil, actionUnknown // unreachable
+}
+
+func describeValue(qpos *queryPos, path []ast.Node) (*describeValueResult, error) {
+	var expr ast.Expr
+	var obj types.Object
+	switch n := path[0].(type) {
+	case *ast.ValueSpec:
+		// ambiguous ValueSpec containing multiple names
+		return nil, fmt.Errorf("multiple value specification")
+	case *ast.Ident:
+		obj = qpos.info.ObjectOf(n)
+		expr = n
+	case ast.Expr:
+		expr = n
+	default:
+		// TODO(adonovan): is this reachable?
+		return nil, fmt.Errorf("unexpected AST for expr: %T", n)
+	}
+
+	typ := qpos.info.TypeOf(expr)
+	constVal := qpos.info.Types[expr].Value
+
+	return &describeValueResult{
+		qpos:     qpos,
+		expr:     expr,
+		typ:      typ,
+		constVal: constVal,
+		obj:      obj,
+	}, nil
+}
+
+type describeValueResult struct {
+	qpos     *queryPos
+	expr     ast.Expr     // query node
+	typ      types.Type   // type of expression
+	constVal exact.Value  // value of expression, if constant
+	obj      types.Object // var/func/const object, if expr was Ident
+}
+
+func (r *describeValueResult) display(printf printfFunc) {
+	var prefix, suffix string
+	if r.constVal != nil {
+		suffix = fmt.Sprintf(" of constant value %s", constValString(r.constVal))
+	}
+	switch obj := r.obj.(type) {
+	case *types.Func:
+		if recv := obj.Type().(*types.Signature).Recv(); recv != nil {
+			if _, ok := recv.Type().Underlying().(*types.Interface); ok {
+				prefix = "interface method "
+			} else {
+				prefix = "method "
+			}
+		}
+	}
+
+	// Describe the expression.
+	if r.obj != nil {
+		if r.obj.Pos() == r.expr.Pos() {
+			// defining ident
+			printf(r.expr, "definition of %s%s%s", prefix, r.qpos.objectString(r.obj), suffix)
+		} else {
+			// referring ident
+			printf(r.expr, "reference to %s%s%s", prefix, r.qpos.objectString(r.obj), suffix)
+			if def := r.obj.Pos(); def != token.NoPos {
+				printf(def, "defined here")
+			}
+		}
+	} else {
+		desc := astutil.NodeDescription(r.expr)
+		if suffix != "" {
+			// constant expression
+			printf(r.expr, "%s%s", desc, suffix)
+		} else {
+			// non-constant expression
+			printf(r.expr, "%s of type %s", desc, r.qpos.typeString(r.typ))
+		}
+	}
+}
+
+func (r *describeValueResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	var value, objpos string
+	if r.constVal != nil {
+		value = r.constVal.String()
+	}
+	if r.obj != nil {
+		objpos = fset.Position(r.obj.Pos()).String()
+	}
+
+	res.Describe = &serial.Describe{
+		Desc:   astutil.NodeDescription(r.expr),
+		Pos:    fset.Position(r.expr.Pos()).String(),
+		Detail: "value",
+		Value: &serial.DescribeValue{
+			Type:   r.qpos.typeString(r.typ),
+			Value:  value,
+			ObjPos: objpos,
+		},
+	}
+}
+
+// ---- TYPE ------------------------------------------------------------
+
+func describeType(qpos *queryPos, path []ast.Node) (*describeTypeResult, error) {
+	var description string
+	var t types.Type
+	switch n := path[0].(type) {
+	case *ast.Ident:
+		t = qpos.info.TypeOf(n)
+		switch t := t.(type) {
+		case *types.Basic:
+			description = "reference to built-in "
+
+		case *types.Named:
+			isDef := t.Obj().Pos() == n.Pos() // see caveats at isDef above
+			if isDef {
+				description = "definition of "
+			} else {
+				description = "reference to "
+			}
+		}
+
+	case ast.Expr:
+		t = qpos.info.TypeOf(n)
+
+	default:
+		// Unreachable?
+		return nil, fmt.Errorf("unexpected AST for type: %T", n)
+	}
+
+	description = description + "type " + qpos.typeString(t)
+
+	// Show sizes for structs and named types (it's fairly obvious for others).
+	switch t.(type) {
+	case *types.Named, *types.Struct:
+		szs := types.StdSizes{8, 8} // assume amd64
+		description = fmt.Sprintf("%s (size %d, align %d)", description,
+			szs.Sizeof(t), szs.Alignof(t))
+	}
+
+	return &describeTypeResult{
+		qpos:        qpos,
+		node:        path[0],
+		description: description,
+		typ:         t,
+		methods:     accessibleMethods(t, qpos.info.Pkg),
+	}, nil
+}
+
+type describeTypeResult struct {
+	qpos        *queryPos
+	node        ast.Node
+	description string
+	typ         types.Type
+	methods     []*types.Selection
+}
+
+func (r *describeTypeResult) display(printf printfFunc) {
+	printf(r.node, "%s", r.description)
+
+	// Show the underlying type for a reference to a named type.
+	if nt, ok := r.typ.(*types.Named); ok && r.node.Pos() != nt.Obj().Pos() {
+		printf(nt.Obj(), "defined as %s", r.qpos.typeString(nt.Underlying()))
+	}
+
+	// Print the method set, if the type kind is capable of bearing methods.
+	switch r.typ.(type) {
+	case *types.Interface, *types.Struct, *types.Named:
+		if len(r.methods) > 0 {
+			printf(r.node, "Method set:")
+			for _, meth := range r.methods {
+				// TODO(adonovan): print these relative
+				// to the owning package, not the
+				// query package.
+				printf(meth.Obj(), "\t%s", r.qpos.selectionString(meth))
+			}
+		} else {
+			printf(r.node, "No methods.")
+		}
+	}
+}
+
+func (r *describeTypeResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	var namePos, nameDef string
+	if nt, ok := r.typ.(*types.Named); ok {
+		namePos = fset.Position(nt.Obj().Pos()).String()
+		nameDef = nt.Underlying().String()
+	}
+	res.Describe = &serial.Describe{
+		Desc:   r.description,
+		Pos:    fset.Position(r.node.Pos()).String(),
+		Detail: "type",
+		Type: &serial.DescribeType{
+			Type:    r.qpos.typeString(r.typ),
+			NamePos: namePos,
+			NameDef: nameDef,
+			Methods: methodsToSerial(r.qpos.info.Pkg, r.methods, fset),
+		},
+	}
+}
+
+// ---- PACKAGE ------------------------------------------------------------
+
+func describePackage(qpos *queryPos, path []ast.Node) (*describePackageResult, error) {
+	var description string
+	var pkg *types.Package
+	switch n := path[0].(type) {
+	case *ast.ImportSpec:
+		var obj types.Object
+		if n.Name != nil {
+			obj = qpos.info.Defs[n.Name]
+		} else {
+			obj = qpos.info.Implicits[n]
+		}
+		pkgname, _ := obj.(*types.PkgName)
+		if pkgname == nil {
+			return nil, fmt.Errorf("can't import package %s", n.Path.Value)
+		}
+		pkg = pkgname.Imported()
+		description = fmt.Sprintf("import of package %q", pkg.Path())
+
+	case *ast.Ident:
+		if _, isDef := path[1].(*ast.File); isDef {
+			// e.g. package id
+			pkg = qpos.info.Pkg
+			description = fmt.Sprintf("definition of package %q", pkg.Path())
+		} else {
+			// e.g. import id "..."
+			//  or  id.F()
+			pkg = qpos.info.ObjectOf(n).(*types.PkgName).Imported()
+			description = fmt.Sprintf("reference to package %q", pkg.Path())
+		}
+
+	default:
+		// Unreachable?
+		return nil, fmt.Errorf("unexpected AST for package: %T", n)
+	}
+
+	var members []*describeMember
+	// NB: "unsafe" has no types.Package
+	if pkg != nil {
+		// Enumerate the accessible package members
+		// in lexicographic order.
+		for _, name := range pkg.Scope().Names() {
+			if pkg == qpos.info.Pkg || ast.IsExported(name) {
+				mem := pkg.Scope().Lookup(name)
+				var methods []*types.Selection
+				if mem, ok := mem.(*types.TypeName); ok {
+					methods = accessibleMethods(mem.Type(), qpos.info.Pkg)
+				}
+				members = append(members, &describeMember{
+					mem,
+					methods,
+				})
+
+			}
+		}
+	}
+
+	return &describePackageResult{qpos.fset, path[0], description, pkg, members}, nil
+}
+
+type describePackageResult struct {
+	fset        *token.FileSet
+	node        ast.Node
+	description string
+	pkg         *types.Package
+	members     []*describeMember // in lexicographic name order
+}
+
+type describeMember struct {
+	obj     types.Object
+	methods []*types.Selection // in types.MethodSet order
+}
+
+func (r *describePackageResult) display(printf printfFunc) {
+	printf(r.node, "%s", r.description)
+
+	// Compute max width of name "column".
+	maxname := 0
+	for _, mem := range r.members {
+		if l := len(mem.obj.Name()); l > maxname {
+			maxname = l
+		}
+	}
+
+	for _, mem := range r.members {
+		printf(mem.obj, "\t%s", formatMember(mem.obj, maxname))
+		for _, meth := range mem.methods {
+			printf(meth.Obj(), "\t\t%s", types.SelectionString(meth, types.RelativeTo(r.pkg)))
+		}
+	}
+}
+
+func formatMember(obj types.Object, maxname int) string {
+	qualifier := types.RelativeTo(obj.Pkg())
+	var buf bytes.Buffer
+	fmt.Fprintf(&buf, "%-5s %-*s", tokenOf(obj), maxname, obj.Name())
+	switch obj := obj.(type) {
+	case *types.Const:
+		fmt.Fprintf(&buf, " %s = %s", types.TypeString(obj.Type(), qualifier), constValString(obj.Val()))
+
+	case *types.Func:
+		fmt.Fprintf(&buf, " %s", types.TypeString(obj.Type(), qualifier))
+
+	case *types.TypeName:
+		// Abbreviate long aggregate type names.
+		var abbrev string
+		switch t := obj.Type().Underlying().(type) {
+		case *types.Interface:
+			if t.NumMethods() > 1 {
+				abbrev = "interface{...}"
+			}
+		case *types.Struct:
+			if t.NumFields() > 1 {
+				abbrev = "struct{...}"
+			}
+		}
+		if abbrev == "" {
+			fmt.Fprintf(&buf, " %s", types.TypeString(obj.Type().Underlying(), qualifier))
+		} else {
+			fmt.Fprintf(&buf, " %s", abbrev)
+		}
+
+	case *types.Var:
+		fmt.Fprintf(&buf, " %s", types.TypeString(obj.Type(), qualifier))
+	}
+	return buf.String()
+}
+
+func (r *describePackageResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	var members []*serial.DescribeMember
+	for _, mem := range r.members {
+		typ := mem.obj.Type()
+		var val string
+		switch mem := mem.obj.(type) {
+		case *types.Const:
+			val = constValString(mem.Val())
+		case *types.TypeName:
+			typ = typ.Underlying()
+		}
+		members = append(members, &serial.DescribeMember{
+			Name:    mem.obj.Name(),
+			Type:    typ.String(),
+			Value:   val,
+			Pos:     fset.Position(mem.obj.Pos()).String(),
+			Kind:    tokenOf(mem.obj),
+			Methods: methodsToSerial(r.pkg, mem.methods, fset),
+		})
+	}
+	res.Describe = &serial.Describe{
+		Desc:   r.description,
+		Pos:    fset.Position(r.node.Pos()).String(),
+		Detail: "package",
+		Package: &serial.DescribePackage{
+			Path:    r.pkg.Path(),
+			Members: members,
+		},
+	}
+}
+
+func tokenOf(o types.Object) string {
+	switch o.(type) {
+	case *types.Func:
+		return "func"
+	case *types.Var:
+		return "var"
+	case *types.TypeName:
+		return "type"
+	case *types.Const:
+		return "const"
+	case *types.PkgName:
+		return "package"
+	case *types.Builtin:
+		return "builtin" // e.g. when describing package "unsafe"
+	case *types.Nil:
+		return "nil"
+	case *types.Label:
+		return "label"
+	}
+	panic(o)
+}
+
+// ---- STATEMENT ------------------------------------------------------------
+
+func describeStmt(qpos *queryPos, path []ast.Node) (*describeStmtResult, error) {
+	var description string
+	switch n := path[0].(type) {
+	case *ast.Ident:
+		if qpos.info.Defs[n] != nil {
+			description = "labelled statement"
+		} else {
+			description = "reference to labelled statement"
+		}
+
+	default:
+		// Nothing much to say about statements.
+		description = astutil.NodeDescription(n)
+	}
+	return &describeStmtResult{qpos.fset, path[0], description}, nil
+}
+
+type describeStmtResult struct {
+	fset        *token.FileSet
+	node        ast.Node
+	description string
+}
+
+func (r *describeStmtResult) display(printf printfFunc) {
+	printf(r.node, "%s", r.description)
+}
+
+func (r *describeStmtResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	res.Describe = &serial.Describe{
+		Desc:   r.description,
+		Pos:    fset.Position(r.node.Pos()).String(),
+		Detail: "unknown",
+	}
+}
+
+// ------------------- Utilities -------------------
+
+// pathToString returns a string containing the concrete types of the
+// nodes in path.
+func pathToString(path []ast.Node) string {
+	var buf bytes.Buffer
+	fmt.Fprint(&buf, "[")
+	for i, n := range path {
+		if i > 0 {
+			fmt.Fprint(&buf, " ")
+		}
+		fmt.Fprint(&buf, strings.TrimPrefix(fmt.Sprintf("%T", n), "*ast."))
+	}
+	fmt.Fprint(&buf, "]")
+	return buf.String()
+}
+
+func accessibleMethods(t types.Type, from *types.Package) []*types.Selection {
+	var methods []*types.Selection
+	for _, meth := range typeutil.IntuitiveMethodSet(t, nil) {
+		if isAccessibleFrom(meth.Obj(), from) {
+			methods = append(methods, meth)
+		}
+	}
+	return methods
+}
+
+func isAccessibleFrom(obj types.Object, pkg *types.Package) bool {
+	return ast.IsExported(obj.Name()) || obj.Pkg() == pkg
+}
+
+func methodsToSerial(this *types.Package, methods []*types.Selection, fset *token.FileSet) []serial.DescribeMethod {
+	qualifier := types.RelativeTo(this)
+	var jmethods []serial.DescribeMethod
+	for _, meth := range methods {
+		var ser serial.DescribeMethod
+		if meth != nil { // may contain nils when called by implements (on a method)
+			ser = serial.DescribeMethod{
+				Name: types.SelectionString(meth, qualifier),
+				Pos:  fset.Position(meth.Obj().Pos()).String(),
+			}
+		}
+		jmethods = append(jmethods, ser)
+	}
+	return jmethods
+}
+
+// constValString emulates Go 1.6's go/constant.ExactString well enough
+// to make the tests pass.  This is just a stopgap until we throw away
+// all the *14.go files.
+func constValString(v exact.Value) string {
+	if v.Kind() == exact.Float {
+		f, _ := exact.Float64Val(v)
+		return fmt.Sprintf("%g", f)
+	}
+	return v.String()
+}
diff --git a/go/src/golang.org/x/tools/oracle/describe15.go b/go/src/golang.org/x/tools/oracle/describe15.go
new file mode 100644
index 0000000..1276f9a
--- /dev/null
+++ b/go/src/golang.org/x/tools/oracle/describe15.go
@@ -0,0 +1,786 @@
+// 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.
+
+// +build go1.5,!go1.6
+
+package oracle
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	exact "go/constant"
+	"go/token"
+	"go/types"
+	"log"
+	"os"
+	"strings"
+
+	"golang.org/x/tools/go/ast/astutil"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/types/typeutil"
+	"golang.org/x/tools/oracle/serial"
+)
+
+// describe describes the syntax node denoted by the query position,
+// including:
+// - its syntactic category
+// - the definition of its referent (for identifiers) [now redundant]
+// - its type and method set (for an expression or type expression)
+//
+func describe(q *Query) error {
+	lconf := loader.Config{Build: q.Build}
+	allowErrors(&lconf)
+
+	if _, err := importQueryPackage(q.Pos, &lconf); err != nil {
+		return err
+	}
+
+	// Load/parse/type-check the program.
+	lprog, err := lconf.Load()
+	if err != nil {
+		return err
+	}
+	q.Fset = lprog.Fset
+
+	qpos, err := parseQueryPos(lprog, q.Pos, true) // (need exact pos)
+	if err != nil {
+		return err
+	}
+
+	if false { // debugging
+		fprintf(os.Stderr, lprog.Fset, qpos.path[0], "you selected: %s %s",
+			astutil.NodeDescription(qpos.path[0]), pathToString(qpos.path))
+	}
+
+	path, action := findInterestingNode(qpos.info, qpos.path)
+	switch action {
+	case actionExpr:
+		q.result, err = describeValue(qpos, path)
+
+	case actionType:
+		q.result, err = describeType(qpos, path)
+
+	case actionPackage:
+		q.result, err = describePackage(qpos, path)
+
+	case actionStmt:
+		q.result, err = describeStmt(qpos, path)
+
+	case actionUnknown:
+		q.result = &describeUnknownResult{path[0]}
+
+	default:
+		panic(action) // unreachable
+	}
+	return err
+}
+
+type describeUnknownResult struct {
+	node ast.Node
+}
+
+func (r *describeUnknownResult) display(printf printfFunc) {
+	// Nothing much to say about misc syntax.
+	printf(r.node, "%s", astutil.NodeDescription(r.node))
+}
+
+func (r *describeUnknownResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	res.Describe = &serial.Describe{
+		Desc: astutil.NodeDescription(r.node),
+		Pos:  fset.Position(r.node.Pos()).String(),
+	}
+}
+
+type action int
+
+const (
+	actionUnknown action = iota // None of the below
+	actionExpr                  // FuncDecl, true Expr or Ident(types.{Const,Var})
+	actionType                  // type Expr or Ident(types.TypeName).
+	actionStmt                  // Stmt or Ident(types.Label)
+	actionPackage               // Ident(types.Package) or ImportSpec
+)
+
+// findInterestingNode classifies the syntax node denoted by path as one of:
+//    - an expression, part of an expression or a reference to a constant
+//      or variable;
+//    - a type, part of a type, or a reference to a named type;
+//    - a statement, part of a statement, or a label referring to a statement;
+//    - part of a package declaration or import spec.
+//    - none of the above.
+// and returns the most "interesting" associated node, which may be
+// the same node, an ancestor or a descendent.
+//
+func findInterestingNode(pkginfo *loader.PackageInfo, path []ast.Node) ([]ast.Node, action) {
+	// TODO(adonovan): integrate with go/types/stdlib_test.go and
+	// apply this to every AST node we can find to make sure it
+	// doesn't crash.
+
+	// TODO(adonovan): audit for ParenExpr safety, esp. since we
+	// traverse up and down.
+
+	// TODO(adonovan): if the users selects the "." in
+	// "fmt.Fprintf()", they'll get an ambiguous selection error;
+	// we won't even reach here.  Can we do better?
+
+	// TODO(adonovan): describing a field within 'type T struct {...}'
+	// describes the (anonymous) struct type and concludes "no methods".
+	// We should ascend to the enclosing type decl, if any.
+
+	for len(path) > 0 {
+		switch n := path[0].(type) {
+		case *ast.GenDecl:
+			if len(n.Specs) == 1 {
+				// Descend to sole {Import,Type,Value}Spec child.
+				path = append([]ast.Node{n.Specs[0]}, path...)
+				continue
+			}
+			return path, actionUnknown // uninteresting
+
+		case *ast.FuncDecl:
+			// Descend to function name.
+			path = append([]ast.Node{n.Name}, path...)
+			continue
+
+		case *ast.ImportSpec:
+			return path, actionPackage
+
+		case *ast.ValueSpec:
+			if len(n.Names) == 1 {
+				// Descend to sole Ident child.
+				path = append([]ast.Node{n.Names[0]}, path...)
+				continue
+			}
+			return path, actionUnknown // uninteresting
+
+		case *ast.TypeSpec:
+			// Descend to type name.
+			path = append([]ast.Node{n.Name}, path...)
+			continue
+
+		case ast.Stmt:
+			return path, actionStmt
+
+		case *ast.ArrayType,
+			*ast.StructType,
+			*ast.FuncType,
+			*ast.InterfaceType,
+			*ast.MapType,
+			*ast.ChanType:
+			return path, actionType
+
+		case *ast.Comment, *ast.CommentGroup, *ast.File, *ast.KeyValueExpr, *ast.CommClause:
+			return path, actionUnknown // uninteresting
+
+		case *ast.Ellipsis:
+			// Continue to enclosing node.
+			// e.g. [...]T in ArrayType
+			//      f(x...) in CallExpr
+			//      f(x...T) in FuncType
+
+		case *ast.Field:
+			// TODO(adonovan): this needs more thought,
+			// since fields can be so many things.
+			if len(n.Names) == 1 {
+				// Descend to sole Ident child.
+				path = append([]ast.Node{n.Names[0]}, path...)
+				continue
+			}
+			// Zero names (e.g. anon field in struct)
+			// or multiple field or param names:
+			// continue to enclosing field list.
+
+		case *ast.FieldList:
+			// Continue to enclosing node:
+			// {Struct,Func,Interface}Type or FuncDecl.
+
+		case *ast.BasicLit:
+			if _, ok := path[1].(*ast.ImportSpec); ok {
+				return path[1:], actionPackage
+			}
+			return path, actionExpr
+
+		case *ast.SelectorExpr:
+			// TODO(adonovan): use Selections info directly.
+			if pkginfo.Uses[n.Sel] == nil {
+				// TODO(adonovan): is this reachable?
+				return path, actionUnknown
+			}
+			// Descend to .Sel child.
+			path = append([]ast.Node{n.Sel}, path...)
+			continue
+
+		case *ast.Ident:
+			switch pkginfo.ObjectOf(n).(type) {
+			case *types.PkgName:
+				return path, actionPackage
+
+			case *types.Const:
+				return path, actionExpr
+
+			case *types.Label:
+				return path, actionStmt
+
+			case *types.TypeName:
+				return path, actionType
+
+			case *types.Var:
+				// For x in 'struct {x T}', return struct type, for now.
+				if _, ok := path[1].(*ast.Field); ok {
+					_ = path[2].(*ast.FieldList) // assertion
+					if _, ok := path[3].(*ast.StructType); ok {
+						return path[3:], actionType
+					}
+				}
+				return path, actionExpr
+
+			case *types.Func:
+				return path, actionExpr
+
+			case *types.Builtin:
+				// For reference to built-in function, return enclosing call.
+				path = path[1:] // ascend to enclosing function call
+				continue
+
+			case *types.Nil:
+				return path, actionExpr
+			}
+
+			// No object.
+			switch path[1].(type) {
+			case *ast.SelectorExpr:
+				// Return enclosing selector expression.
+				return path[1:], actionExpr
+
+			case *ast.Field:
+				// TODO(adonovan): test this.
+				// e.g. all f in:
+				//  struct { f, g int }
+				//  interface { f() }
+				//  func (f T) method(f, g int) (f, g bool)
+				//
+				// switch path[3].(type) {
+				// case *ast.FuncDecl:
+				// case *ast.StructType:
+				// case *ast.InterfaceType:
+				// }
+				//
+				// return path[1:], actionExpr
+				//
+				// Unclear what to do with these.
+				// Struct.Fields             -- field
+				// Interface.Methods         -- field
+				// FuncType.{Params.Results} -- actionExpr
+				// FuncDecl.Recv             -- actionExpr
+
+			case *ast.File:
+				// 'package foo'
+				return path, actionPackage
+
+			case *ast.ImportSpec:
+				// TODO(adonovan): fix: why no package object? go/types bug?
+				return path[1:], actionPackage
+
+			default:
+				// e.g. blank identifier
+				// or y in "switch y := x.(type)"
+				// or code in a _test.go file that's not part of the package.
+				log.Printf("unknown reference %s in %T\n", n, path[1])
+				return path, actionUnknown
+			}
+
+		case *ast.StarExpr:
+			if pkginfo.Types[n].IsType() {
+				return path, actionType
+			}
+			return path, actionExpr
+
+		case ast.Expr:
+			// All Expr but {BasicLit,Ident,StarExpr} are
+			// "true" expressions that evaluate to a value.
+			return path, actionExpr
+		}
+
+		// Ascend to parent.
+		path = path[1:]
+	}
+
+	return nil, actionUnknown // unreachable
+}
+
+func describeValue(qpos *queryPos, path []ast.Node) (*describeValueResult, error) {
+	var expr ast.Expr
+	var obj types.Object
+	switch n := path[0].(type) {
+	case *ast.ValueSpec:
+		// ambiguous ValueSpec containing multiple names
+		return nil, fmt.Errorf("multiple value specification")
+	case *ast.Ident:
+		obj = qpos.info.ObjectOf(n)
+		expr = n
+	case ast.Expr:
+		expr = n
+	default:
+		// TODO(adonovan): is this reachable?
+		return nil, fmt.Errorf("unexpected AST for expr: %T", n)
+	}
+
+	typ := qpos.info.TypeOf(expr)
+	constVal := qpos.info.Types[expr].Value
+
+	return &describeValueResult{
+		qpos:     qpos,
+		expr:     expr,
+		typ:      typ,
+		constVal: constVal,
+		obj:      obj,
+	}, nil
+}
+
+type describeValueResult struct {
+	qpos     *queryPos
+	expr     ast.Expr     // query node
+	typ      types.Type   // type of expression
+	constVal exact.Value  // value of expression, if constant
+	obj      types.Object // var/func/const object, if expr was Ident
+}
+
+func (r *describeValueResult) display(printf printfFunc) {
+	var prefix, suffix string
+	if r.constVal != nil {
+		suffix = fmt.Sprintf(" of constant value %s", constValString(r.constVal))
+	}
+	switch obj := r.obj.(type) {
+	case *types.Func:
+		if recv := obj.Type().(*types.Signature).Recv(); recv != nil {
+			if _, ok := recv.Type().Underlying().(*types.Interface); ok {
+				prefix = "interface method "
+			} else {
+				prefix = "method "
+			}
+		}
+	}
+
+	// Describe the expression.
+	if r.obj != nil {
+		if r.obj.Pos() == r.expr.Pos() {
+			// defining ident
+			printf(r.expr, "definition of %s%s%s", prefix, r.qpos.objectString(r.obj), suffix)
+		} else {
+			// referring ident
+			printf(r.expr, "reference to %s%s%s", prefix, r.qpos.objectString(r.obj), suffix)
+			if def := r.obj.Pos(); def != token.NoPos {
+				printf(def, "defined here")
+			}
+		}
+	} else {
+		desc := astutil.NodeDescription(r.expr)
+		if suffix != "" {
+			// constant expression
+			printf(r.expr, "%s%s", desc, suffix)
+		} else {
+			// non-constant expression
+			printf(r.expr, "%s of type %s", desc, r.qpos.typeString(r.typ))
+		}
+	}
+}
+
+func (r *describeValueResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	var value, objpos string
+	if r.constVal != nil {
+		value = r.constVal.String()
+	}
+	if r.obj != nil {
+		objpos = fset.Position(r.obj.Pos()).String()
+	}
+
+	res.Describe = &serial.Describe{
+		Desc:   astutil.NodeDescription(r.expr),
+		Pos:    fset.Position(r.expr.Pos()).String(),
+		Detail: "value",
+		Value: &serial.DescribeValue{
+			Type:   r.qpos.typeString(r.typ),
+			Value:  value,
+			ObjPos: objpos,
+		},
+	}
+}
+
+// ---- TYPE ------------------------------------------------------------
+
+func describeType(qpos *queryPos, path []ast.Node) (*describeTypeResult, error) {
+	var description string
+	var t types.Type
+	switch n := path[0].(type) {
+	case *ast.Ident:
+		t = qpos.info.TypeOf(n)
+		switch t := t.(type) {
+		case *types.Basic:
+			description = "reference to built-in "
+
+		case *types.Named:
+			isDef := t.Obj().Pos() == n.Pos() // see caveats at isDef above
+			if isDef {
+				description = "definition of "
+			} else {
+				description = "reference to "
+			}
+		}
+
+	case ast.Expr:
+		t = qpos.info.TypeOf(n)
+
+	default:
+		// Unreachable?
+		return nil, fmt.Errorf("unexpected AST for type: %T", n)
+	}
+
+	description = description + "type " + qpos.typeString(t)
+
+	// Show sizes for structs and named types (it's fairly obvious for others).
+	switch t.(type) {
+	case *types.Named, *types.Struct:
+		szs := types.StdSizes{8, 8} // assume amd64
+		description = fmt.Sprintf("%s (size %d, align %d)", description,
+			szs.Sizeof(t), szs.Alignof(t))
+	}
+
+	return &describeTypeResult{
+		qpos:        qpos,
+		node:        path[0],
+		description: description,
+		typ:         t,
+		methods:     accessibleMethods(t, qpos.info.Pkg),
+	}, nil
+}
+
+type describeTypeResult struct {
+	qpos        *queryPos
+	node        ast.Node
+	description string
+	typ         types.Type
+	methods     []*types.Selection
+}
+
+func (r *describeTypeResult) display(printf printfFunc) {
+	printf(r.node, "%s", r.description)
+
+	// Show the underlying type for a reference to a named type.
+	if nt, ok := r.typ.(*types.Named); ok && r.node.Pos() != nt.Obj().Pos() {
+		printf(nt.Obj(), "defined as %s", r.qpos.typeString(nt.Underlying()))
+	}
+
+	// Print the method set, if the type kind is capable of bearing methods.
+	switch r.typ.(type) {
+	case *types.Interface, *types.Struct, *types.Named:
+		if len(r.methods) > 0 {
+			printf(r.node, "Method set:")
+			for _, meth := range r.methods {
+				// TODO(adonovan): print these relative
+				// to the owning package, not the
+				// query package.
+				printf(meth.Obj(), "\t%s", r.qpos.selectionString(meth))
+			}
+		} else {
+			printf(r.node, "No methods.")
+		}
+	}
+}
+
+func (r *describeTypeResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	var namePos, nameDef string
+	if nt, ok := r.typ.(*types.Named); ok {
+		namePos = fset.Position(nt.Obj().Pos()).String()
+		nameDef = nt.Underlying().String()
+	}
+	res.Describe = &serial.Describe{
+		Desc:   r.description,
+		Pos:    fset.Position(r.node.Pos()).String(),
+		Detail: "type",
+		Type: &serial.DescribeType{
+			Type:    r.qpos.typeString(r.typ),
+			NamePos: namePos,
+			NameDef: nameDef,
+			Methods: methodsToSerial(r.qpos.info.Pkg, r.methods, fset),
+		},
+	}
+}
+
+// ---- PACKAGE ------------------------------------------------------------
+
+func describePackage(qpos *queryPos, path []ast.Node) (*describePackageResult, error) {
+	var description string
+	var pkg *types.Package
+	switch n := path[0].(type) {
+	case *ast.ImportSpec:
+		var obj types.Object
+		if n.Name != nil {
+			obj = qpos.info.Defs[n.Name]
+		} else {
+			obj = qpos.info.Implicits[n]
+		}
+		pkgname, _ := obj.(*types.PkgName)
+		if pkgname == nil {
+			return nil, fmt.Errorf("can't import package %s", n.Path.Value)
+		}
+		pkg = pkgname.Imported()
+		description = fmt.Sprintf("import of package %q", pkg.Path())
+
+	case *ast.Ident:
+		if _, isDef := path[1].(*ast.File); isDef {
+			// e.g. package id
+			pkg = qpos.info.Pkg
+			description = fmt.Sprintf("definition of package %q", pkg.Path())
+		} else {
+			// e.g. import id "..."
+			//  or  id.F()
+			pkg = qpos.info.ObjectOf(n).(*types.PkgName).Imported()
+			description = fmt.Sprintf("reference to package %q", pkg.Path())
+		}
+
+	default:
+		// Unreachable?
+		return nil, fmt.Errorf("unexpected AST for package: %T", n)
+	}
+
+	var members []*describeMember
+	// NB: "unsafe" has no types.Package
+	if pkg != nil {
+		// Enumerate the accessible package members
+		// in lexicographic order.
+		for _, name := range pkg.Scope().Names() {
+			if pkg == qpos.info.Pkg || ast.IsExported(name) {
+				mem := pkg.Scope().Lookup(name)
+				var methods []*types.Selection
+				if mem, ok := mem.(*types.TypeName); ok {
+					methods = accessibleMethods(mem.Type(), qpos.info.Pkg)
+				}
+				members = append(members, &describeMember{
+					mem,
+					methods,
+				})
+
+			}
+		}
+	}
+
+	return &describePackageResult{qpos.fset, path[0], description, pkg, members}, nil
+}
+
+type describePackageResult struct {
+	fset        *token.FileSet
+	node        ast.Node
+	description string
+	pkg         *types.Package
+	members     []*describeMember // in lexicographic name order
+}
+
+type describeMember struct {
+	obj     types.Object
+	methods []*types.Selection // in types.MethodSet order
+}
+
+func (r *describePackageResult) display(printf printfFunc) {
+	printf(r.node, "%s", r.description)
+
+	// Compute max width of name "column".
+	maxname := 0
+	for _, mem := range r.members {
+		if l := len(mem.obj.Name()); l > maxname {
+			maxname = l
+		}
+	}
+
+	for _, mem := range r.members {
+		printf(mem.obj, "\t%s", formatMember(mem.obj, maxname))
+		for _, meth := range mem.methods {
+			printf(meth.Obj(), "\t\t%s", types.SelectionString(meth, types.RelativeTo(r.pkg)))
+		}
+	}
+}
+
+func formatMember(obj types.Object, maxname int) string {
+	qualifier := types.RelativeTo(obj.Pkg())
+	var buf bytes.Buffer
+	fmt.Fprintf(&buf, "%-5s %-*s", tokenOf(obj), maxname, obj.Name())
+	switch obj := obj.(type) {
+	case *types.Const:
+		fmt.Fprintf(&buf, " %s = %s", types.TypeString(obj.Type(), qualifier), constValString(obj.Val()))
+
+	case *types.Func:
+		fmt.Fprintf(&buf, " %s", types.TypeString(obj.Type(), qualifier))
+
+	case *types.TypeName:
+		// Abbreviate long aggregate type names.
+		var abbrev string
+		switch t := obj.Type().Underlying().(type) {
+		case *types.Interface:
+			if t.NumMethods() > 1 {
+				abbrev = "interface{...}"
+			}
+		case *types.Struct:
+			if t.NumFields() > 1 {
+				abbrev = "struct{...}"
+			}
+		}
+		if abbrev == "" {
+			fmt.Fprintf(&buf, " %s", types.TypeString(obj.Type().Underlying(), qualifier))
+		} else {
+			fmt.Fprintf(&buf, " %s", abbrev)
+		}
+
+	case *types.Var:
+		fmt.Fprintf(&buf, " %s", types.TypeString(obj.Type(), qualifier))
+	}
+	return buf.String()
+}
+
+func (r *describePackageResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	var members []*serial.DescribeMember
+	for _, mem := range r.members {
+		typ := mem.obj.Type()
+		var val string
+		switch mem := mem.obj.(type) {
+		case *types.Const:
+			val = constValString(mem.Val())
+		case *types.TypeName:
+			typ = typ.Underlying()
+		}
+		members = append(members, &serial.DescribeMember{
+			Name:    mem.obj.Name(),
+			Type:    typ.String(),
+			Value:   val,
+			Pos:     fset.Position(mem.obj.Pos()).String(),
+			Kind:    tokenOf(mem.obj),
+			Methods: methodsToSerial(r.pkg, mem.methods, fset),
+		})
+	}
+	res.Describe = &serial.Describe{
+		Desc:   r.description,
+		Pos:    fset.Position(r.node.Pos()).String(),
+		Detail: "package",
+		Package: &serial.DescribePackage{
+			Path:    r.pkg.Path(),
+			Members: members,
+		},
+	}
+}
+
+func tokenOf(o types.Object) string {
+	switch o.(type) {
+	case *types.Func:
+		return "func"
+	case *types.Var:
+		return "var"
+	case *types.TypeName:
+		return "type"
+	case *types.Const:
+		return "const"
+	case *types.PkgName:
+		return "package"
+	case *types.Builtin:
+		return "builtin" // e.g. when describing package "unsafe"
+	case *types.Nil:
+		return "nil"
+	case *types.Label:
+		return "label"
+	}
+	panic(o)
+}
+
+// ---- STATEMENT ------------------------------------------------------------
+
+func describeStmt(qpos *queryPos, path []ast.Node) (*describeStmtResult, error) {
+	var description string
+	switch n := path[0].(type) {
+	case *ast.Ident:
+		if qpos.info.Defs[n] != nil {
+			description = "labelled statement"
+		} else {
+			description = "reference to labelled statement"
+		}
+
+	default:
+		// Nothing much to say about statements.
+		description = astutil.NodeDescription(n)
+	}
+	return &describeStmtResult{qpos.fset, path[0], description}, nil
+}
+
+type describeStmtResult struct {
+	fset        *token.FileSet
+	node        ast.Node
+	description string
+}
+
+func (r *describeStmtResult) display(printf printfFunc) {
+	printf(r.node, "%s", r.description)
+}
+
+func (r *describeStmtResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	res.Describe = &serial.Describe{
+		Desc:   r.description,
+		Pos:    fset.Position(r.node.Pos()).String(),
+		Detail: "unknown",
+	}
+}
+
+// ------------------- Utilities -------------------
+
+// pathToString returns a string containing the concrete types of the
+// nodes in path.
+func pathToString(path []ast.Node) string {
+	var buf bytes.Buffer
+	fmt.Fprint(&buf, "[")
+	for i, n := range path {
+		if i > 0 {
+			fmt.Fprint(&buf, " ")
+		}
+		fmt.Fprint(&buf, strings.TrimPrefix(fmt.Sprintf("%T", n), "*ast."))
+	}
+	fmt.Fprint(&buf, "]")
+	return buf.String()
+}
+
+func accessibleMethods(t types.Type, from *types.Package) []*types.Selection {
+	var methods []*types.Selection
+	for _, meth := range typeutil.IntuitiveMethodSet(t, nil) {
+		if isAccessibleFrom(meth.Obj(), from) {
+			methods = append(methods, meth)
+		}
+	}
+	return methods
+}
+
+func isAccessibleFrom(obj types.Object, pkg *types.Package) bool {
+	return ast.IsExported(obj.Name()) || obj.Pkg() == pkg
+}
+
+func methodsToSerial(this *types.Package, methods []*types.Selection, fset *token.FileSet) []serial.DescribeMethod {
+	qualifier := types.RelativeTo(this)
+	var jmethods []serial.DescribeMethod
+	for _, meth := range methods {
+		var ser serial.DescribeMethod
+		if meth != nil { // may contain nils when called by implements (on a method)
+			ser = serial.DescribeMethod{
+				Name: types.SelectionString(meth, qualifier),
+				Pos:  fset.Position(meth.Obj().Pos()).String(),
+			}
+		}
+		jmethods = append(jmethods, ser)
+	}
+	return jmethods
+}
+
+// constValString emulates Go 1.6's go/constant.ExactString well enough
+// to make the tests pass.  This is just a stopgap until we throw away
+// all the *15.go files.
+func constValString(v exact.Value) string {
+	if v.Kind() == exact.Float {
+		f, _ := exact.Float64Val(v)
+		return fmt.Sprintf("%g", f)
+	}
+	return v.String()
+}
diff --git a/go/src/golang.org/x/tools/oracle/freevars.go b/go/src/golang.org/x/tools/oracle/freevars.go
index 400a118..6b89cb3 100644
--- a/go/src/golang.org/x/tools/oracle/freevars.go
+++ b/go/src/golang.org/x/tools/oracle/freevars.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package oracle
 
 import (
@@ -9,10 +11,10 @@
 	"go/ast"
 	"go/printer"
 	"go/token"
+	"go/types"
 	"sort"
 
 	"golang.org/x/tools/go/loader"
-	"golang.org/x/tools/go/types"
 	"golang.org/x/tools/oracle/serial"
 )
 
@@ -33,7 +35,7 @@
 	lconf := loader.Config{Build: q.Build}
 	allowErrors(&lconf)
 
-	if err := importQueryPackage(q.Pos, &lconf); err != nil {
+	if _, err := importQueryPackage(q.Pos, &lconf); err != nil {
 		return err
 	}
 
diff --git a/go/src/golang.org/x/tools/oracle/freevars14.go b/go/src/golang.org/x/tools/oracle/freevars14.go
new file mode 100644
index 0000000..760a9e6
--- /dev/null
+++ b/go/src/golang.org/x/tools/oracle/freevars14.go
@@ -0,0 +1,224 @@
+// 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.
+
+// +build !go1.5
+
+package oracle
+
+import (
+	"bytes"
+	"go/ast"
+	"go/printer"
+	"go/token"
+	"sort"
+
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/oracle/serial"
+)
+
+// freevars displays the lexical (not package-level) free variables of
+// the selection.
+//
+// It treats A.B.C as a separate variable from A to reveal the parts
+// of an aggregate type that are actually needed.
+// This aids refactoring.
+//
+// TODO(adonovan): optionally display the free references to
+// file/package scope objects, and to objects from other packages.
+// Depending on where the resulting function abstraction will go,
+// these might be interesting.  Perhaps group the results into three
+// bands.
+//
+func freevars(q *Query) error {
+	lconf := loader.Config{Build: q.Build}
+	allowErrors(&lconf)
+
+	if _, err := importQueryPackage(q.Pos, &lconf); err != nil {
+		return err
+	}
+
+	// Load/parse/type-check the program.
+	lprog, err := lconf.Load()
+	if err != nil {
+		return err
+	}
+	q.Fset = lprog.Fset
+
+	qpos, err := parseQueryPos(lprog, q.Pos, false)
+	if err != nil {
+		return err
+	}
+
+	file := qpos.path[len(qpos.path)-1] // the enclosing file
+	fileScope := qpos.info.Scopes[file]
+	pkgScope := fileScope.Parent()
+
+	// The id and sel functions return non-nil if they denote an
+	// object o or selection o.x.y that is referenced by the
+	// selection but defined neither within the selection nor at
+	// file scope, i.e. it is in the lexical environment.
+	var id func(n *ast.Ident) types.Object
+	var sel func(n *ast.SelectorExpr) types.Object
+
+	sel = func(n *ast.SelectorExpr) types.Object {
+		switch x := unparen(n.X).(type) {
+		case *ast.SelectorExpr:
+			return sel(x)
+		case *ast.Ident:
+			return id(x)
+		}
+		return nil
+	}
+
+	id = func(n *ast.Ident) types.Object {
+		obj := qpos.info.Uses[n]
+		if obj == nil {
+			return nil // not a reference
+		}
+		if _, ok := obj.(*types.PkgName); ok {
+			return nil // imported package
+		}
+		if !(file.Pos() <= obj.Pos() && obj.Pos() <= file.End()) {
+			return nil // not defined in this file
+		}
+		scope := obj.Parent()
+		if scope == nil {
+			return nil // e.g. interface method, struct field
+		}
+		if scope == fileScope || scope == pkgScope {
+			return nil // defined at file or package scope
+		}
+		if qpos.start <= obj.Pos() && obj.Pos() <= qpos.end {
+			return nil // defined within selection => not free
+		}
+		return obj
+	}
+
+	// Maps each reference that is free in the selection
+	// to the object it refers to.
+	// The map de-duplicates repeated references.
+	refsMap := make(map[string]freevarsRef)
+
+	// Visit all the identifiers in the selected ASTs.
+	ast.Inspect(qpos.path[0], func(n ast.Node) bool {
+		if n == nil {
+			return true // popping DFS stack
+		}
+
+		// Is this node contained within the selection?
+		// (freevars permits inexact selections,
+		// like two stmts in a block.)
+		if qpos.start <= n.Pos() && n.End() <= qpos.end {
+			var obj types.Object
+			var prune bool
+			switch n := n.(type) {
+			case *ast.Ident:
+				obj = id(n)
+
+			case *ast.SelectorExpr:
+				obj = sel(n)
+				prune = true
+			}
+
+			if obj != nil {
+				var kind string
+				switch obj.(type) {
+				case *types.Var:
+					kind = "var"
+				case *types.Func:
+					kind = "func"
+				case *types.TypeName:
+					kind = "type"
+				case *types.Const:
+					kind = "const"
+				case *types.Label:
+					kind = "label"
+				default:
+					panic(obj)
+				}
+
+				typ := qpos.info.TypeOf(n.(ast.Expr))
+				ref := freevarsRef{kind, printNode(lprog.Fset, n), typ, obj}
+				refsMap[ref.ref] = ref
+
+				if prune {
+					return false // don't descend
+				}
+			}
+		}
+
+		return true // descend
+	})
+
+	refs := make([]freevarsRef, 0, len(refsMap))
+	for _, ref := range refsMap {
+		refs = append(refs, ref)
+	}
+	sort.Sort(byRef(refs))
+
+	q.result = &freevarsResult{
+		qpos: qpos,
+		refs: refs,
+	}
+	return nil
+}
+
+type freevarsResult struct {
+	qpos *queryPos
+	refs []freevarsRef
+}
+
+type freevarsRef struct {
+	kind string
+	ref  string
+	typ  types.Type
+	obj  types.Object
+}
+
+func (r *freevarsResult) display(printf printfFunc) {
+	if len(r.refs) == 0 {
+		printf(r.qpos, "No free identifiers.")
+	} else {
+		printf(r.qpos, "Free identifiers:")
+		qualifier := types.RelativeTo(r.qpos.info.Pkg)
+		for _, ref := range r.refs {
+			// Avoid printing "type T T".
+			var typstr string
+			if ref.kind != "type" {
+				typstr = " " + types.TypeString(ref.typ, qualifier)
+			}
+			printf(ref.obj, "%s %s%s", ref.kind, ref.ref, typstr)
+		}
+	}
+}
+
+func (r *freevarsResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	var refs []*serial.FreeVar
+	for _, ref := range r.refs {
+		refs = append(refs,
+			&serial.FreeVar{
+				Pos:  fset.Position(ref.obj.Pos()).String(),
+				Kind: ref.kind,
+				Ref:  ref.ref,
+				Type: ref.typ.String(),
+			})
+	}
+	res.Freevars = refs
+}
+
+// -------- utils --------
+
+type byRef []freevarsRef
+
+func (p byRef) Len() int           { return len(p) }
+func (p byRef) Less(i, j int) bool { return p[i].ref < p[j].ref }
+func (p byRef) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
+
+// printNode returns the pretty-printed syntax of n.
+func printNode(fset *token.FileSet, n ast.Node) string {
+	var buf bytes.Buffer
+	printer.Fprint(&buf, fset, n)
+	return buf.String()
+}
diff --git a/go/src/golang.org/x/tools/oracle/implements.go b/go/src/golang.org/x/tools/oracle/implements.go
index 3155ca2..7c9da1d 100644
--- a/go/src/golang.org/x/tools/oracle/implements.go
+++ b/go/src/golang.org/x/tools/oracle/implements.go
@@ -2,24 +2,27 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package oracle
 
 import (
 	"fmt"
 	"go/ast"
 	"go/token"
+	"go/types"
 	"reflect"
 	"sort"
 	"strings"
 
 	"golang.org/x/tools/go/loader"
-	"golang.org/x/tools/go/types"
 	"golang.org/x/tools/go/types/typeutil"
 	"golang.org/x/tools/oracle/serial"
+	"golang.org/x/tools/refactor/importgraph"
 )
 
 // Implements displays the "implements" relation as it pertains to the
-// selected type within a single package.
+// selected type.
 // If the selection is a method, 'implements' displays
 // the corresponding methods of the types that would have been reported
 // by an implements query on the receiver type.
@@ -28,10 +31,35 @@
 	lconf := loader.Config{Build: q.Build}
 	allowErrors(&lconf)
 
-	if err := importQueryPackage(q.Pos, &lconf); err != nil {
+	qpkg, err := importQueryPackage(q.Pos, &lconf)
+	if err != nil {
 		return err
 	}
 
+	// Set the packages to search.
+	if len(q.Scope) > 0 {
+		// Inspect all packages in the analysis scope, if specified.
+		if err := setPTAScope(&lconf, q.Scope); err != nil {
+			return err
+		}
+	} else {
+		// Otherwise inspect the forward and reverse
+		// transitive closure of the selected package.
+		// (In theory even this is incomplete.)
+		_, rev, _ := importgraph.Build(q.Build)
+		for path := range rev.Search(qpkg) {
+			lconf.ImportWithTests(path)
+		}
+
+		// TODO(adonovan): for completeness, we should also
+		// type-check and inspect function bodies in all
+		// imported packages.  This would be expensive, but we
+		// could optimize by skipping functions that do not
+		// contain type declarations.  This would require
+		// changing the loader's TypeCheckFuncBodies hook to
+		// provide the []*ast.File.
+	}
+
 	// Load/parse/type-check the program.
 	lprog, err := lconf.Load()
 	if err != nil {
@@ -72,10 +100,6 @@
 
 	// Find all named types, even local types (which can have
 	// methods via promotion) and the built-in "error".
-	//
-	// TODO(adonovan): include all packages in PTA scope too?
-	// i.e. don't reduceScope?
-	//
 	var allNamed []types.Type
 	for _, info := range lprog.AllPackages {
 		for _, obj := range info.Defs {
diff --git a/go/src/golang.org/x/tools/oracle/implements14.go b/go/src/golang.org/x/tools/oracle/implements14.go
new file mode 100644
index 0000000..9f4c370
--- /dev/null
+++ b/go/src/golang.org/x/tools/oracle/implements14.go
@@ -0,0 +1,354 @@
+// 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.
+
+// +build !go1.5
+
+package oracle
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"reflect"
+	"sort"
+	"strings"
+
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/go/types/typeutil"
+	"golang.org/x/tools/oracle/serial"
+	"golang.org/x/tools/refactor/importgraph"
+)
+
+// Implements displays the "implements" relation as it pertains to the
+// selected type.
+// If the selection is a method, 'implements' displays
+// the corresponding methods of the types that would have been reported
+// by an implements query on the receiver type.
+//
+func implements(q *Query) error {
+	lconf := loader.Config{Build: q.Build}
+	allowErrors(&lconf)
+
+	qpkg, err := importQueryPackage(q.Pos, &lconf)
+	if err != nil {
+		return err
+	}
+
+	// Set the packages to search.
+	if len(q.Scope) > 0 {
+		// Inspect all packages in the analysis scope, if specified.
+		if err := setPTAScope(&lconf, q.Scope); err != nil {
+			return err
+		}
+	} else {
+		// Otherwise inspect the forward and reverse
+		// transitive closure of the selected package.
+		// (In theory even this is incomplete.)
+		_, rev, _ := importgraph.Build(q.Build)
+		for path := range rev.Search(qpkg) {
+			lconf.ImportWithTests(path)
+		}
+
+		// TODO(adonovan): for completeness, we should also
+		// type-check and inspect function bodies in all
+		// imported packages.  This would be expensive, but we
+		// could optimize by skipping functions that do not
+		// contain type declarations.  This would require
+		// changing the loader's TypeCheckFuncBodies hook to
+		// provide the []*ast.File.
+	}
+
+	// Load/parse/type-check the program.
+	lprog, err := lconf.Load()
+	if err != nil {
+		return err
+	}
+	q.Fset = lprog.Fset
+
+	qpos, err := parseQueryPos(lprog, q.Pos, false)
+	if err != nil {
+		return err
+	}
+
+	// Find the selected type.
+	path, action := findInterestingNode(qpos.info, qpos.path)
+
+	var method *types.Func
+	var T types.Type // selected type (receiver if method != nil)
+
+	switch action {
+	case actionExpr:
+		// method?
+		if id, ok := path[0].(*ast.Ident); ok {
+			if obj, ok := qpos.info.ObjectOf(id).(*types.Func); ok {
+				recv := obj.Type().(*types.Signature).Recv()
+				if recv == nil {
+					return fmt.Errorf("this function is not a method")
+				}
+				method = obj
+				T = recv.Type()
+			}
+		}
+	case actionType:
+		T = qpos.info.TypeOf(path[0].(ast.Expr))
+	}
+	if T == nil {
+		return fmt.Errorf("no type or method here")
+	}
+
+	// Find all named types, even local types (which can have
+	// methods via promotion) and the built-in "error".
+	var allNamed []types.Type
+	for _, info := range lprog.AllPackages {
+		for _, obj := range info.Defs {
+			if obj, ok := obj.(*types.TypeName); ok {
+				allNamed = append(allNamed, obj.Type())
+			}
+		}
+	}
+	allNamed = append(allNamed, types.Universe.Lookup("error").Type())
+
+	var msets typeutil.MethodSetCache
+
+	// Test each named type.
+	var to, from, fromPtr []types.Type
+	for _, U := range allNamed {
+		if isInterface(T) {
+			if msets.MethodSet(T).Len() == 0 {
+				continue // empty interface
+			}
+			if isInterface(U) {
+				if msets.MethodSet(U).Len() == 0 {
+					continue // empty interface
+				}
+
+				// T interface, U interface
+				if !types.Identical(T, U) {
+					if types.AssignableTo(U, T) {
+						to = append(to, U)
+					}
+					if types.AssignableTo(T, U) {
+						from = append(from, U)
+					}
+				}
+			} else {
+				// T interface, U concrete
+				if types.AssignableTo(U, T) {
+					to = append(to, U)
+				} else if pU := types.NewPointer(U); types.AssignableTo(pU, T) {
+					to = append(to, pU)
+				}
+			}
+		} else if isInterface(U) {
+			if msets.MethodSet(U).Len() == 0 {
+				continue // empty interface
+			}
+
+			// T concrete, U interface
+			if types.AssignableTo(T, U) {
+				from = append(from, U)
+			} else if pT := types.NewPointer(T); types.AssignableTo(pT, U) {
+				fromPtr = append(fromPtr, U)
+			}
+		}
+	}
+
+	var pos interface{} = qpos
+	if nt, ok := deref(T).(*types.Named); ok {
+		pos = nt.Obj()
+	}
+
+	// Sort types (arbitrarily) to ensure test determinism.
+	sort.Sort(typesByString(to))
+	sort.Sort(typesByString(from))
+	sort.Sort(typesByString(fromPtr))
+
+	var toMethod, fromMethod, fromPtrMethod []*types.Selection // contain nils
+	if method != nil {
+		for _, t := range to {
+			toMethod = append(toMethod,
+				types.NewMethodSet(t).Lookup(method.Pkg(), method.Name()))
+		}
+		for _, t := range from {
+			fromMethod = append(fromMethod,
+				types.NewMethodSet(t).Lookup(method.Pkg(), method.Name()))
+		}
+		for _, t := range fromPtr {
+			fromPtrMethod = append(fromPtrMethod,
+				types.NewMethodSet(t).Lookup(method.Pkg(), method.Name()))
+		}
+	}
+
+	q.result = &implementsResult{
+		qpos, T, pos, to, from, fromPtr, method, toMethod, fromMethod, fromPtrMethod,
+	}
+	return nil
+}
+
+type implementsResult struct {
+	qpos *queryPos
+
+	t       types.Type   // queried type (not necessarily named)
+	pos     interface{}  // pos of t (*types.Name or *QueryPos)
+	to      []types.Type // named or ptr-to-named types assignable to interface T
+	from    []types.Type // named interfaces assignable from T
+	fromPtr []types.Type // named interfaces assignable only from *T
+
+	// if a method was queried:
+	method        *types.Func        // queried method
+	toMethod      []*types.Selection // method of type to[i], if any
+	fromMethod    []*types.Selection // method of type from[i], if any
+	fromPtrMethod []*types.Selection // method of type fromPtrMethod[i], if any
+}
+
+func (r *implementsResult) display(printf printfFunc) {
+	relation := "is implemented by"
+
+	meth := func(sel *types.Selection) {
+		if sel != nil {
+			printf(sel.Obj(), "\t%s method (%s).%s",
+				relation, r.qpos.typeString(sel.Recv()), sel.Obj().Name())
+		}
+	}
+
+	if isInterface(r.t) {
+		if types.NewMethodSet(r.t).Len() == 0 { // TODO(adonovan): cache mset
+			printf(r.pos, "empty interface type %s", r.qpos.typeString(r.t))
+			return
+		}
+
+		if r.method == nil {
+			printf(r.pos, "interface type %s", r.qpos.typeString(r.t))
+		} else {
+			printf(r.method, "abstract method %s", r.qpos.objectString(r.method))
+		}
+
+		// Show concrete types (or methods) first; use two passes.
+		for i, sub := range r.to {
+			if !isInterface(sub) {
+				if r.method == nil {
+					printf(deref(sub).(*types.Named).Obj(), "\t%s %s type %s",
+						relation, typeKind(sub), r.qpos.typeString(sub))
+				} else {
+					meth(r.toMethod[i])
+				}
+			}
+		}
+		for i, sub := range r.to {
+			if isInterface(sub) {
+				if r.method == nil {
+					printf(sub.(*types.Named).Obj(), "\t%s %s type %s",
+						relation, typeKind(sub), r.qpos.typeString(sub))
+				} else {
+					meth(r.toMethod[i])
+				}
+			}
+		}
+
+		relation = "implements"
+		for i, super := range r.from {
+			if r.method == nil {
+				printf(super.(*types.Named).Obj(), "\t%s %s",
+					relation, r.qpos.typeString(super))
+			} else {
+				meth(r.fromMethod[i])
+			}
+		}
+	} else {
+		relation = "implements"
+
+		if r.from != nil {
+			if r.method == nil {
+				printf(r.pos, "%s type %s",
+					typeKind(r.t), r.qpos.typeString(r.t))
+			} else {
+				printf(r.method, "concrete method %s",
+					r.qpos.objectString(r.method))
+			}
+			for i, super := range r.from {
+				if r.method == nil {
+					printf(super.(*types.Named).Obj(), "\t%s %s",
+						relation, r.qpos.typeString(super))
+				} else {
+					meth(r.fromMethod[i])
+				}
+			}
+		}
+		if r.fromPtr != nil {
+			if r.method == nil {
+				printf(r.pos, "pointer type *%s", r.qpos.typeString(r.t))
+			} else {
+				// TODO(adonovan): de-dup (C).f and (*C).f implementing (I).f.
+				printf(r.method, "concrete method %s",
+					r.qpos.objectString(r.method))
+			}
+
+			for i, psuper := range r.fromPtr {
+				if r.method == nil {
+					printf(psuper.(*types.Named).Obj(), "\t%s %s",
+						relation, r.qpos.typeString(psuper))
+				} else {
+					meth(r.fromPtrMethod[i])
+				}
+			}
+		} else if r.from == nil {
+			printf(r.pos, "%s type %s implements only interface{}",
+				typeKind(r.t), r.qpos.typeString(r.t))
+		}
+	}
+}
+
+func (r *implementsResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	res.Implements = &serial.Implements{
+		T:                       makeImplementsType(r.t, fset),
+		AssignableTo:            makeImplementsTypes(r.to, fset),
+		AssignableFrom:          makeImplementsTypes(r.from, fset),
+		AssignableFromPtr:       makeImplementsTypes(r.fromPtr, fset),
+		AssignableToMethod:      methodsToSerial(r.qpos.info.Pkg, r.toMethod, fset),
+		AssignableFromMethod:    methodsToSerial(r.qpos.info.Pkg, r.fromMethod, fset),
+		AssignableFromPtrMethod: methodsToSerial(r.qpos.info.Pkg, r.fromPtrMethod, fset),
+	}
+	if r.method != nil {
+		res.Implements.Method = &serial.DescribeMethod{
+			Name: r.qpos.objectString(r.method),
+			Pos:  fset.Position(r.method.Pos()).String(),
+		}
+	}
+}
+
+func makeImplementsTypes(tt []types.Type, fset *token.FileSet) []serial.ImplementsType {
+	var r []serial.ImplementsType
+	for _, t := range tt {
+		r = append(r, makeImplementsType(t, fset))
+	}
+	return r
+}
+
+func makeImplementsType(T types.Type, fset *token.FileSet) serial.ImplementsType {
+	var pos token.Pos
+	if nt, ok := deref(T).(*types.Named); ok { // implementsResult.t may be non-named
+		pos = nt.Obj().Pos()
+	}
+	return serial.ImplementsType{
+		Name: T.String(),
+		Pos:  fset.Position(pos).String(),
+		Kind: typeKind(T),
+	}
+}
+
+// typeKind returns a string describing the underlying kind of type,
+// e.g. "slice", "array", "struct".
+func typeKind(T types.Type) string {
+	s := reflect.TypeOf(T.Underlying()).String()
+	return strings.ToLower(strings.TrimPrefix(s, "*types."))
+}
+
+func isInterface(T types.Type) bool { return types.IsInterface(T) }
+
+type typesByString []types.Type
+
+func (p typesByString) Len() int           { return len(p) }
+func (p typesByString) Less(i, j int) bool { return p[i].String() < p[j].String() }
+func (p typesByString) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
diff --git a/go/src/golang.org/x/tools/oracle/oracle.go b/go/src/golang.org/x/tools/oracle/oracle.go
index 544cfa4..794cbe9 100644
--- a/go/src/golang.org/x/tools/oracle/oracle.go
+++ b/go/src/golang.org/x/tools/oracle/oracle.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 // Package oracle contains the implementation of the oracle tool whose
 // command-line is provided by golang.org/x/tools/cmd/oracle.
 //
@@ -25,6 +27,7 @@
 	"go/build"
 	"go/parser"
 	"go/token"
+	"go/types"
 	"io"
 	"path/filepath"
 
@@ -32,7 +35,6 @@
 	"golang.org/x/tools/go/loader"
 	"golang.org/x/tools/go/pointer"
 	"golang.org/x/tools/go/ssa"
-	"golang.org/x/tools/go/types"
 	"golang.org/x/tools/oracle/serial"
 )
 
@@ -190,10 +192,11 @@
 
 // importQueryPackage finds the package P containing the
 // query position and tells conf to import it.
-func importQueryPackage(pos string, conf *loader.Config) error {
+// It returns the package's path.
+func importQueryPackage(pos string, conf *loader.Config) (string, error) {
 	fqpos, err := fastQueryPos(pos)
 	if err != nil {
-		return err // bad query
+		return "", err // bad query
 	}
 	filename := fqpos.fset.File(fqpos.start).Name()
 
@@ -202,10 +205,10 @@
 	// TODO(adonovan): ensure we report a clear error.
 	_, importPath, err := guessImportPath(filename, conf.Build)
 	if err != nil {
-		return err // can't find GOPATH dir
+		return "", err // can't find GOPATH dir
 	}
 	if importPath == "" {
-		return fmt.Errorf("can't guess import path from %s", filename)
+		return "", fmt.Errorf("can't guess import path from %s", filename)
 	}
 
 	// Check that it's possible to load the queried package.
@@ -215,7 +218,7 @@
 	cfg2.CgoEnabled = false
 	bp, err := cfg2.Import(importPath, "", 0)
 	if err != nil {
-		return err // no files for package
+		return "", err // no files for package
 	}
 
 	switch pkgContainsFile(bp, filename) {
@@ -227,13 +230,13 @@
 	case 'G':
 		conf.Import(importPath)
 	default:
-		return fmt.Errorf("package %q doesn't contain file %s",
+		return "", fmt.Errorf("package %q doesn't contain file %s",
 			importPath, filename)
 	}
 
 	conf.TypeCheckFuncBodies = func(p string) bool { return p == importPath }
 
-	return nil
+	return importPath, nil
 }
 
 // pkgContainsFile reports whether file was among the packages Go
diff --git a/go/src/golang.org/x/tools/oracle/oracle14.go b/go/src/golang.org/x/tools/oracle/oracle14.go
new file mode 100644
index 0000000..ed8a166
--- /dev/null
+++ b/go/src/golang.org/x/tools/oracle/oracle14.go
@@ -0,0 +1,367 @@
+// Copyright 2014 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.
+
+// +build !go1.5
+
+// Package oracle contains the implementation of the oracle tool whose
+// command-line is provided by golang.org/x/tools/cmd/oracle.
+//
+// http://golang.org/s/oracle-design
+// http://golang.org/s/oracle-user-manual
+//
+package oracle // import "golang.org/x/tools/oracle"
+
+// This file defines oracle.Query, the entry point for the oracle tool.
+// The actual executable is defined in cmd/oracle.
+
+// TODO(adonovan): new queries
+// - show all statements that may update the selected lvalue
+//   (local, global, field, etc).
+// - show all places where an object of type T is created
+//   (&T{}, var t T, new(T), new(struct{array [3]T}), etc.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/parser"
+	"go/token"
+	"io"
+	"path/filepath"
+
+	"golang.org/x/tools/go/ast/astutil"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/pointer"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/oracle/serial"
+)
+
+type printfFunc func(pos interface{}, format string, args ...interface{})
+
+// queryResult is the interface of each query-specific result type.
+type queryResult interface {
+	toSerial(res *serial.Result, fset *token.FileSet)
+	display(printf printfFunc)
+}
+
+// A QueryPos represents the position provided as input to a query:
+// a textual extent in the program's source code, the AST node it
+// corresponds to, and the package to which it belongs.
+// Instances are created by parseQueryPos.
+type queryPos struct {
+	fset       *token.FileSet
+	start, end token.Pos           // source extent of query
+	path       []ast.Node          // AST path from query node to root of ast.File
+	exact      bool                // 2nd result of PathEnclosingInterval
+	info       *loader.PackageInfo // type info for the queried package (nil for fastQueryPos)
+}
+
+// TypeString prints type T relative to the query position.
+func (qpos *queryPos) typeString(T types.Type) string {
+	return types.TypeString(T, types.RelativeTo(qpos.info.Pkg))
+}
+
+// ObjectString prints object obj relative to the query position.
+func (qpos *queryPos) objectString(obj types.Object) string {
+	return types.ObjectString(obj, types.RelativeTo(qpos.info.Pkg))
+}
+
+// SelectionString prints selection sel relative to the query position.
+func (qpos *queryPos) selectionString(sel *types.Selection) string {
+	return types.SelectionString(sel, types.RelativeTo(qpos.info.Pkg))
+}
+
+// A Query specifies a single oracle query.
+type Query struct {
+	Mode  string         // query mode ("callers", etc)
+	Pos   string         // query position
+	Build *build.Context // package loading configuration
+
+	// pointer analysis options
+	Scope      []string  // main packages in (*loader.Config).FromArgs syntax
+	PTALog     io.Writer // (optional) pointer-analysis log file
+	Reflection bool      // model reflection soundly (currently slow).
+
+	// Populated during Run()
+	Fset   *token.FileSet
+	result queryResult
+}
+
+// Serial returns an instance of serial.Result, which implements the
+// {xml,json}.Marshaler interfaces so that query results can be
+// serialized as JSON or XML.
+//
+func (q *Query) Serial() *serial.Result {
+	resj := &serial.Result{Mode: q.Mode}
+	q.result.toSerial(resj, q.Fset)
+	return resj
+}
+
+// WriteTo writes the oracle query result res to out in a compiler diagnostic format.
+func (q *Query) WriteTo(out io.Writer) {
+	printf := func(pos interface{}, format string, args ...interface{}) {
+		fprintf(out, q.Fset, pos, format, args...)
+	}
+	q.result.display(printf)
+}
+
+// Run runs an oracle query and populates its Fset and Result.
+func Run(q *Query) error {
+	switch q.Mode {
+	case "callees":
+		return callees(q)
+	case "callers":
+		return callers(q)
+	case "callstack":
+		return callstack(q)
+	case "peers":
+		return peers(q)
+	case "pointsto":
+		return pointsto(q)
+	case "whicherrs":
+		return whicherrs(q)
+	case "definition":
+		return definition(q)
+	case "describe":
+		return describe(q)
+	case "freevars":
+		return freevars(q)
+	case "implements":
+		return implements(q)
+	case "referrers":
+		return referrers(q)
+	case "what":
+		return what(q)
+	default:
+		return fmt.Errorf("invalid mode: %q", q.Mode)
+	}
+}
+
+func setPTAScope(lconf *loader.Config, scope []string) error {
+	if len(scope) == 0 {
+		return fmt.Errorf("no packages specified for pointer analysis scope")
+	}
+
+	// Determine initial packages for PTA.
+	args, err := lconf.FromArgs(scope, true)
+	if err != nil {
+		return err
+	}
+	if len(args) > 0 {
+		return fmt.Errorf("surplus arguments: %q", args)
+	}
+	return nil
+}
+
+// Create a pointer.Config whose scope is the initial packages of lprog
+// and their dependencies.
+func setupPTA(prog *ssa.Program, lprog *loader.Program, ptaLog io.Writer, reflection bool) (*pointer.Config, error) {
+	// TODO(adonovan): the body of this function is essentially
+	// duplicated in all go/pointer clients.  Refactor.
+
+	// For each initial package (specified on the command line),
+	// if it has a main function, analyze that,
+	// otherwise analyze its tests, if any.
+	var testPkgs, mains []*ssa.Package
+	for _, info := range lprog.InitialPackages() {
+		initialPkg := prog.Package(info.Pkg)
+
+		// Add package to the pointer analysis scope.
+		if initialPkg.Func("main") != nil {
+			mains = append(mains, initialPkg)
+		} else {
+			testPkgs = append(testPkgs, initialPkg)
+		}
+	}
+	if testPkgs != nil {
+		if p := prog.CreateTestMainPackage(testPkgs...); p != nil {
+			mains = append(mains, p)
+		}
+	}
+	if mains == nil {
+		return nil, fmt.Errorf("analysis scope has no main and no tests")
+	}
+	return &pointer.Config{
+		Log:        ptaLog,
+		Reflection: reflection,
+		Mains:      mains,
+	}, nil
+}
+
+// importQueryPackage finds the package P containing the
+// query position and tells conf to import it.
+// It returns the package's path.
+func importQueryPackage(pos string, conf *loader.Config) (string, error) {
+	fqpos, err := fastQueryPos(pos)
+	if err != nil {
+		return "", err // bad query
+	}
+	filename := fqpos.fset.File(fqpos.start).Name()
+
+	// This will not work for ad-hoc packages
+	// such as $GOROOT/src/net/http/triv.go.
+	// TODO(adonovan): ensure we report a clear error.
+	_, importPath, err := guessImportPath(filename, conf.Build)
+	if err != nil {
+		return "", err // can't find GOPATH dir
+	}
+	if importPath == "" {
+		return "", fmt.Errorf("can't guess import path from %s", filename)
+	}
+
+	// Check that it's possible to load the queried package.
+	// (e.g. oracle tests contain different 'package' decls in same dir.)
+	// Keep consistent with logic in loader/util.go!
+	cfg2 := *conf.Build
+	cfg2.CgoEnabled = false
+	bp, err := cfg2.Import(importPath, "", 0)
+	if err != nil {
+		return "", err // no files for package
+	}
+
+	switch pkgContainsFile(bp, filename) {
+	case 'T':
+		conf.ImportWithTests(importPath)
+	case 'X':
+		conf.ImportWithTests(importPath)
+		importPath += "_test" // for TypeCheckFuncBodies
+	case 'G':
+		conf.Import(importPath)
+	default:
+		return "", fmt.Errorf("package %q doesn't contain file %s",
+			importPath, filename)
+	}
+
+	conf.TypeCheckFuncBodies = func(p string) bool { return p == importPath }
+
+	return importPath, nil
+}
+
+// pkgContainsFile reports whether file was among the packages Go
+// files, Test files, eXternal test files, or not found.
+func pkgContainsFile(bp *build.Package, filename string) byte {
+	for i, files := range [][]string{bp.GoFiles, bp.TestGoFiles, bp.XTestGoFiles} {
+		for _, file := range files {
+			if sameFile(filepath.Join(bp.Dir, file), filename) {
+				return "GTX"[i]
+			}
+		}
+	}
+	return 0 // not found
+}
+
+// ParseQueryPos parses the source query position pos and returns the
+// AST node of the loaded program lprog that it identifies.
+// If needExact, it must identify a single AST subtree;
+// this is appropriate for queries that allow fairly arbitrary syntax,
+// e.g. "describe".
+//
+func parseQueryPos(lprog *loader.Program, posFlag string, needExact bool) (*queryPos, error) {
+	filename, startOffset, endOffset, err := parsePosFlag(posFlag)
+	if err != nil {
+		return nil, err
+	}
+	start, end, err := findQueryPos(lprog.Fset, filename, startOffset, endOffset)
+	if err != nil {
+		return nil, err
+	}
+	info, path, exact := lprog.PathEnclosingInterval(start, end)
+	if path == nil {
+		return nil, fmt.Errorf("no syntax here")
+	}
+	if needExact && !exact {
+		return nil, fmt.Errorf("ambiguous selection within %s", astutil.NodeDescription(path[0]))
+	}
+	return &queryPos{lprog.Fset, start, end, path, exact, info}, nil
+}
+
+// ---------- Utilities ----------
+
+// allowErrors causes type errors to be silently ignored.
+// (Not suitable if SSA construction follows.)
+func allowErrors(lconf *loader.Config) {
+	ctxt := *lconf.Build // copy
+	ctxt.CgoEnabled = false
+	lconf.Build = &ctxt
+	lconf.AllowErrors = true
+	// AllErrors makes the parser always return an AST instead of
+	// bailing out after 10 errors and returning an empty ast.File.
+	lconf.ParserMode = parser.AllErrors
+	lconf.TypeChecker.Error = func(err error) {}
+}
+
+// ptrAnalysis runs the pointer analysis and returns its result.
+func ptrAnalysis(conf *pointer.Config) *pointer.Result {
+	result, err := pointer.Analyze(conf)
+	if err != nil {
+		panic(err) // pointer analysis internal error
+	}
+	return result
+}
+
+func unparen(e ast.Expr) ast.Expr { return astutil.Unparen(e) }
+
+// deref returns a pointer's element type; otherwise it returns typ.
+func deref(typ types.Type) types.Type {
+	if p, ok := typ.Underlying().(*types.Pointer); ok {
+		return p.Elem()
+	}
+	return typ
+}
+
+// fprintf prints to w a message of the form "location: message\n"
+// where location is derived from pos.
+//
+// pos must be one of:
+//    - a token.Pos, denoting a position
+//    - an ast.Node, denoting an interval
+//    - anything with a Pos() method:
+//         ssa.Member, ssa.Value, ssa.Instruction, types.Object, pointer.Label, etc.
+//    - a QueryPos, denoting the extent of the user's query.
+//    - nil, meaning no position at all.
+//
+// The output format is is compatible with the 'gnu'
+// compilation-error-regexp in Emacs' compilation mode.
+// TODO(adonovan): support other editors.
+//
+func fprintf(w io.Writer, fset *token.FileSet, pos interface{}, format string, args ...interface{}) {
+	var start, end token.Pos
+	switch pos := pos.(type) {
+	case ast.Node:
+		start = pos.Pos()
+		end = pos.End()
+	case token.Pos:
+		start = pos
+		end = start
+	case interface {
+		Pos() token.Pos
+	}:
+		start = pos.Pos()
+		end = start
+	case *queryPos:
+		start = pos.start
+		end = pos.end
+	case nil:
+		// no-op
+	default:
+		panic(fmt.Sprintf("invalid pos: %T", pos))
+	}
+
+	if sp := fset.Position(start); start == end {
+		// (prints "-: " for token.NoPos)
+		fmt.Fprintf(w, "%s: ", sp)
+	} else {
+		ep := fset.Position(end)
+		// The -1 below is a concession to Emacs's broken use of
+		// inclusive (not half-open) intervals.
+		// Other editors may not want it.
+		// TODO(adonovan): add an -editor=vim|emacs|acme|auto
+		// flag; auto uses EMACS=t / VIM=... / etc env vars.
+		fmt.Fprintf(w, "%s:%d.%d-%d.%d: ",
+			sp.Filename, sp.Line, sp.Column, ep.Line, ep.Column-1)
+	}
+	fmt.Fprintf(w, format, args...)
+	io.WriteString(w, "\n")
+}
diff --git a/go/src/golang.org/x/tools/oracle/peers.go b/go/src/golang.org/x/tools/oracle/peers.go
index 9c2a497..0564516 100644
--- a/go/src/golang.org/x/tools/oracle/peers.go
+++ b/go/src/golang.org/x/tools/oracle/peers.go
@@ -2,18 +2,20 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package oracle
 
 import (
 	"fmt"
 	"go/ast"
 	"go/token"
+	"go/types"
 	"sort"
 
 	"golang.org/x/tools/go/loader"
 	"golang.org/x/tools/go/ssa"
 	"golang.org/x/tools/go/ssa/ssautil"
-	"golang.org/x/tools/go/types"
 	"golang.org/x/tools/oracle/serial"
 )
 
@@ -55,7 +57,7 @@
 	}
 
 	// Defer SSA construction till after errors are reported.
-	prog.BuildAll()
+	prog.Build()
 
 	var queryOp chanOp // the originating send or receive operation
 	var ops []chanOp   // all sends/receives of opposite direction
diff --git a/go/src/golang.org/x/tools/oracle/peers14.go b/go/src/golang.org/x/tools/oracle/peers14.go
new file mode 100644
index 0000000..9b97cbf
--- /dev/null
+++ b/go/src/golang.org/x/tools/oracle/peers14.go
@@ -0,0 +1,254 @@
+// 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.
+
+// +build !go1.5
+
+package oracle
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"sort"
+
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/ssa/ssautil"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/oracle/serial"
+)
+
+// peers enumerates, for a given channel send (or receive) operation,
+// the set of possible receives (or sends) that correspond to it.
+//
+// TODO(adonovan): support reflect.{Select,Recv,Send,Close}.
+// TODO(adonovan): permit the user to query based on a MakeChan (not send/recv),
+// or the implicit receive in "for v := range ch".
+func peers(q *Query) error {
+	lconf := loader.Config{Build: q.Build}
+
+	if err := setPTAScope(&lconf, q.Scope); err != nil {
+		return err
+	}
+
+	// Load/parse/type-check the program.
+	lprog, err := lconf.Load()
+	if err != nil {
+		return err
+	}
+	q.Fset = lprog.Fset
+
+	qpos, err := parseQueryPos(lprog, q.Pos, false)
+	if err != nil {
+		return err
+	}
+
+	prog := ssautil.CreateProgram(lprog, ssa.GlobalDebug)
+
+	ptaConfig, err := setupPTA(prog, lprog, q.PTALog, q.Reflection)
+	if err != nil {
+		return err
+	}
+
+	opPos := findOp(qpos)
+	if opPos == token.NoPos {
+		return fmt.Errorf("there is no channel operation here")
+	}
+
+	// Defer SSA construction till after errors are reported.
+	prog.Build()
+
+	var queryOp chanOp // the originating send or receive operation
+	var ops []chanOp   // all sends/receives of opposite direction
+
+	// Look at all channel operations in the whole ssa.Program.
+	// Build a list of those of same type as the query.
+	allFuncs := ssautil.AllFunctions(prog)
+	for fn := range allFuncs {
+		for _, b := range fn.Blocks {
+			for _, instr := range b.Instrs {
+				for _, op := range chanOps(instr) {
+					ops = append(ops, op)
+					if op.pos == opPos {
+						queryOp = op // we found the query op
+					}
+				}
+			}
+		}
+	}
+	if queryOp.ch == nil {
+		return fmt.Errorf("ssa.Instruction for send/receive not found")
+	}
+
+	// Discard operations of wrong channel element type.
+	// Build set of channel ssa.Values as query to pointer analysis.
+	// We compare channels by element types, not channel types, to
+	// ignore both directionality and type names.
+	queryType := queryOp.ch.Type()
+	queryElemType := queryType.Underlying().(*types.Chan).Elem()
+	ptaConfig.AddQuery(queryOp.ch)
+	i := 0
+	for _, op := range ops {
+		if types.Identical(op.ch.Type().Underlying().(*types.Chan).Elem(), queryElemType) {
+			ptaConfig.AddQuery(op.ch)
+			ops[i] = op
+			i++
+		}
+	}
+	ops = ops[:i]
+
+	// Run the pointer analysis.
+	ptares := ptrAnalysis(ptaConfig)
+
+	// Find the points-to set.
+	queryChanPtr := ptares.Queries[queryOp.ch]
+
+	// Ascertain which make(chan) labels the query's channel can alias.
+	var makes []token.Pos
+	for _, label := range queryChanPtr.PointsTo().Labels() {
+		makes = append(makes, label.Pos())
+	}
+	sort.Sort(byPos(makes))
+
+	// Ascertain which channel operations can alias the same make(chan) labels.
+	var sends, receives, closes []token.Pos
+	for _, op := range ops {
+		if ptr, ok := ptares.Queries[op.ch]; ok && ptr.MayAlias(queryChanPtr) {
+			switch op.dir {
+			case types.SendOnly:
+				sends = append(sends, op.pos)
+			case types.RecvOnly:
+				receives = append(receives, op.pos)
+			case types.SendRecv:
+				closes = append(closes, op.pos)
+			}
+		}
+	}
+	sort.Sort(byPos(sends))
+	sort.Sort(byPos(receives))
+	sort.Sort(byPos(closes))
+
+	q.result = &peersResult{
+		queryPos:  opPos,
+		queryType: queryType,
+		makes:     makes,
+		sends:     sends,
+		receives:  receives,
+		closes:    closes,
+	}
+	return nil
+}
+
+// findOp returns the position of the enclosing send/receive/close op.
+// For send and receive operations, this is the position of the <- token;
+// for close operations, it's the Lparen of the function call.
+//
+// TODO(adonovan): handle implicit receive operations from 'for...range chan' statements.
+func findOp(qpos *queryPos) token.Pos {
+	for _, n := range qpos.path {
+		switch n := n.(type) {
+		case *ast.UnaryExpr:
+			if n.Op == token.ARROW {
+				return n.OpPos
+			}
+		case *ast.SendStmt:
+			return n.Arrow
+		case *ast.CallExpr:
+			// close function call can only exist as a direct identifier
+			if close, ok := unparen(n.Fun).(*ast.Ident); ok {
+				if b, ok := qpos.info.Info.Uses[close].(*types.Builtin); ok && b.Name() == "close" {
+					return n.Lparen
+				}
+			}
+		}
+	}
+	return token.NoPos
+}
+
+// chanOp abstracts an ssa.Send, ssa.Unop(ARROW), or a SelectState.
+type chanOp struct {
+	ch  ssa.Value
+	dir types.ChanDir // SendOnly=send, RecvOnly=recv, SendRecv=close
+	pos token.Pos
+}
+
+// chanOps returns a slice of all the channel operations in the instruction.
+func chanOps(instr ssa.Instruction) []chanOp {
+	// TODO(adonovan): handle calls to reflect.{Select,Recv,Send,Close} too.
+	var ops []chanOp
+	switch instr := instr.(type) {
+	case *ssa.UnOp:
+		if instr.Op == token.ARROW {
+			ops = append(ops, chanOp{instr.X, types.RecvOnly, instr.Pos()})
+		}
+	case *ssa.Send:
+		ops = append(ops, chanOp{instr.Chan, types.SendOnly, instr.Pos()})
+	case *ssa.Select:
+		for _, st := range instr.States {
+			ops = append(ops, chanOp{st.Chan, st.Dir, st.Pos})
+		}
+	case ssa.CallInstruction:
+		cc := instr.Common()
+		if b, ok := cc.Value.(*ssa.Builtin); ok && b.Name() == "close" {
+			ops = append(ops, chanOp{cc.Args[0], types.SendRecv, cc.Pos()})
+		}
+	}
+	return ops
+}
+
+type peersResult struct {
+	queryPos                       token.Pos   // of queried channel op
+	queryType                      types.Type  // type of queried channel
+	makes, sends, receives, closes []token.Pos // positions of aliased makechan/send/receive/close instrs
+}
+
+func (r *peersResult) display(printf printfFunc) {
+	if len(r.makes) == 0 {
+		printf(r.queryPos, "This channel can't point to anything.")
+		return
+	}
+	printf(r.queryPos, "This channel of type %s may be:", r.queryType)
+	for _, alloc := range r.makes {
+		printf(alloc, "\tallocated here")
+	}
+	for _, send := range r.sends {
+		printf(send, "\tsent to, here")
+	}
+	for _, receive := range r.receives {
+		printf(receive, "\treceived from, here")
+	}
+	for _, clos := range r.closes {
+		printf(clos, "\tclosed, here")
+	}
+}
+
+func (r *peersResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	peers := &serial.Peers{
+		Pos:  fset.Position(r.queryPos).String(),
+		Type: r.queryType.String(),
+	}
+	for _, alloc := range r.makes {
+		peers.Allocs = append(peers.Allocs, fset.Position(alloc).String())
+	}
+	for _, send := range r.sends {
+		peers.Sends = append(peers.Sends, fset.Position(send).String())
+	}
+	for _, receive := range r.receives {
+		peers.Receives = append(peers.Receives, fset.Position(receive).String())
+	}
+	for _, clos := range r.closes {
+		peers.Closes = append(peers.Closes, fset.Position(clos).String())
+	}
+	res.Peers = peers
+}
+
+// -------- utils --------
+
+// NB: byPos is not deterministic across packages since it depends on load order.
+// Use lessPos if the tests need it.
+type byPos []token.Pos
+
+func (p byPos) Len() int           { return len(p) }
+func (p byPos) Less(i, j int) bool { return p[i] < p[j] }
+func (p byPos) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
diff --git a/go/src/golang.org/x/tools/oracle/pointsto.go b/go/src/golang.org/x/tools/oracle/pointsto.go
index d366dd3..9b862f5 100644
--- a/go/src/golang.org/x/tools/oracle/pointsto.go
+++ b/go/src/golang.org/x/tools/oracle/pointsto.go
@@ -2,12 +2,15 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package oracle
 
 import (
 	"fmt"
 	"go/ast"
 	"go/token"
+	"go/types"
 	"sort"
 
 	"golang.org/x/tools/go/ast/astutil"
@@ -15,7 +18,6 @@
 	"golang.org/x/tools/go/pointer"
 	"golang.org/x/tools/go/ssa"
 	"golang.org/x/tools/go/ssa/ssautil"
-	"golang.org/x/tools/go/types"
 	"golang.org/x/tools/oracle/serial"
 )
 
@@ -95,7 +97,7 @@
 	}
 
 	// Defer SSA construction till after errors are reported.
-	prog.BuildAll()
+	prog.Build()
 
 	// Run the pointer analysis.
 	ptrs, err := runPTA(ptaConfig, value, isAddr)
diff --git a/go/src/golang.org/x/tools/oracle/pointsto14.go b/go/src/golang.org/x/tools/oracle/pointsto14.go
new file mode 100644
index 0000000..1e40619
--- /dev/null
+++ b/go/src/golang.org/x/tools/oracle/pointsto14.go
@@ -0,0 +1,293 @@
+// 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.
+
+// +build !go1.5
+
+package oracle
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"sort"
+
+	"golang.org/x/tools/go/ast/astutil"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/pointer"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/ssa/ssautil"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/oracle/serial"
+)
+
+// pointsto runs the pointer analysis on the selected expression,
+// and reports its points-to set (for a pointer-like expression)
+// or its dynamic types (for an interface, reflect.Value, or
+// reflect.Type expression) and their points-to sets.
+//
+// All printed sets are sorted to ensure determinism.
+//
+func pointsto(q *Query) error {
+	lconf := loader.Config{Build: q.Build}
+
+	if err := setPTAScope(&lconf, q.Scope); err != nil {
+		return err
+	}
+
+	// Load/parse/type-check the program.
+	lprog, err := lconf.Load()
+	if err != nil {
+		return err
+	}
+	q.Fset = lprog.Fset
+
+	qpos, err := parseQueryPos(lprog, q.Pos, true) // needs exact pos
+	if err != nil {
+		return err
+	}
+
+	prog := ssautil.CreateProgram(lprog, ssa.GlobalDebug)
+
+	ptaConfig, err := setupPTA(prog, lprog, q.PTALog, q.Reflection)
+	if err != nil {
+		return err
+	}
+
+	path, action := findInterestingNode(qpos.info, qpos.path)
+	if action != actionExpr {
+		return fmt.Errorf("pointer analysis wants an expression; got %s",
+			astutil.NodeDescription(qpos.path[0]))
+	}
+
+	var expr ast.Expr
+	var obj types.Object
+	switch n := path[0].(type) {
+	case *ast.ValueSpec:
+		// ambiguous ValueSpec containing multiple names
+		return fmt.Errorf("multiple value specification")
+	case *ast.Ident:
+		obj = qpos.info.ObjectOf(n)
+		expr = n
+	case ast.Expr:
+		expr = n
+	default:
+		// TODO(adonovan): is this reachable?
+		return fmt.Errorf("unexpected AST for expr: %T", n)
+	}
+
+	// Reject non-pointerlike types (includes all constants---except nil).
+	// TODO(adonovan): reject nil too.
+	typ := qpos.info.TypeOf(expr)
+	if !pointer.CanPoint(typ) {
+		return fmt.Errorf("pointer analysis wants an expression of reference type; got %s", typ)
+	}
+
+	// Determine the ssa.Value for the expression.
+	var value ssa.Value
+	var isAddr bool
+	if obj != nil {
+		// def/ref of func/var object
+		value, isAddr, err = ssaValueForIdent(prog, qpos.info, obj, path)
+	} else {
+		value, isAddr, err = ssaValueForExpr(prog, qpos.info, path)
+	}
+	if err != nil {
+		return err // e.g. trivially dead code
+	}
+
+	// Defer SSA construction till after errors are reported.
+	prog.Build()
+
+	// Run the pointer analysis.
+	ptrs, err := runPTA(ptaConfig, value, isAddr)
+	if err != nil {
+		return err // e.g. analytically unreachable
+	}
+
+	q.result = &pointstoResult{
+		qpos: qpos,
+		typ:  typ,
+		ptrs: ptrs,
+	}
+	return nil
+}
+
+// ssaValueForIdent returns the ssa.Value for the ast.Ident whose path
+// to the root of the AST is path.  isAddr reports whether the
+// ssa.Value is the address denoted by the ast.Ident, not its value.
+//
+func ssaValueForIdent(prog *ssa.Program, qinfo *loader.PackageInfo, obj types.Object, path []ast.Node) (value ssa.Value, isAddr bool, err error) {
+	switch obj := obj.(type) {
+	case *types.Var:
+		pkg := prog.Package(qinfo.Pkg)
+		pkg.Build()
+		if v, addr := prog.VarValue(obj, pkg, path); v != nil {
+			return v, addr, nil
+		}
+		return nil, false, fmt.Errorf("can't locate SSA Value for var %s", obj.Name())
+
+	case *types.Func:
+		fn := prog.FuncValue(obj)
+		if fn == nil {
+			return nil, false, fmt.Errorf("%s is an interface method", obj)
+		}
+		// TODO(adonovan): there's no point running PTA on a *Func ident.
+		// Eliminate this feature.
+		return fn, false, nil
+	}
+	panic(obj)
+}
+
+// ssaValueForExpr returns the ssa.Value of the non-ast.Ident
+// expression whose path to the root of the AST is path.
+//
+func ssaValueForExpr(prog *ssa.Program, qinfo *loader.PackageInfo, path []ast.Node) (value ssa.Value, isAddr bool, err error) {
+	pkg := prog.Package(qinfo.Pkg)
+	pkg.SetDebugMode(true)
+	pkg.Build()
+
+	fn := ssa.EnclosingFunction(pkg, path)
+	if fn == nil {
+		return nil, false, fmt.Errorf("no SSA function built for this location (dead code?)")
+	}
+
+	if v, addr := fn.ValueForExpr(path[0].(ast.Expr)); v != nil {
+		return v, addr, nil
+	}
+
+	return nil, false, fmt.Errorf("can't locate SSA Value for expression in %s", fn)
+}
+
+// runPTA runs the pointer analysis of the selected SSA value or address.
+func runPTA(conf *pointer.Config, v ssa.Value, isAddr bool) (ptrs []pointerResult, err error) {
+	T := v.Type()
+	if isAddr {
+		conf.AddIndirectQuery(v)
+		T = deref(T)
+	} else {
+		conf.AddQuery(v)
+	}
+	ptares := ptrAnalysis(conf)
+
+	var ptr pointer.Pointer
+	if isAddr {
+		ptr = ptares.IndirectQueries[v]
+	} else {
+		ptr = ptares.Queries[v]
+	}
+	if ptr == (pointer.Pointer{}) {
+		return nil, fmt.Errorf("pointer analysis did not find expression (dead code?)")
+	}
+	pts := ptr.PointsTo()
+
+	if pointer.CanHaveDynamicTypes(T) {
+		// Show concrete types for interface/reflect.Value expression.
+		if concs := pts.DynamicTypes(); concs.Len() > 0 {
+			concs.Iterate(func(conc types.Type, pta interface{}) {
+				labels := pta.(pointer.PointsToSet).Labels()
+				sort.Sort(byPosAndString(labels)) // to ensure determinism
+				ptrs = append(ptrs, pointerResult{conc, labels})
+			})
+		}
+	} else {
+		// Show labels for other expressions.
+		labels := pts.Labels()
+		sort.Sort(byPosAndString(labels)) // to ensure determinism
+		ptrs = append(ptrs, pointerResult{T, labels})
+	}
+	sort.Sort(byTypeString(ptrs)) // to ensure determinism
+	return ptrs, nil
+}
+
+type pointerResult struct {
+	typ    types.Type       // type of the pointer (always concrete)
+	labels []*pointer.Label // set of labels
+}
+
+type pointstoResult struct {
+	qpos *queryPos
+	typ  types.Type      // type of expression
+	ptrs []pointerResult // pointer info (typ is concrete => len==1)
+}
+
+func (r *pointstoResult) display(printf printfFunc) {
+	if pointer.CanHaveDynamicTypes(r.typ) {
+		// Show concrete types for interface, reflect.Type or
+		// reflect.Value expression.
+
+		if len(r.ptrs) > 0 {
+			printf(r.qpos, "this %s may contain these dynamic types:", r.qpos.typeString(r.typ))
+			for _, ptr := range r.ptrs {
+				var obj types.Object
+				if nt, ok := deref(ptr.typ).(*types.Named); ok {
+					obj = nt.Obj()
+				}
+				if len(ptr.labels) > 0 {
+					printf(obj, "\t%s, may point to:", r.qpos.typeString(ptr.typ))
+					printLabels(printf, ptr.labels, "\t\t")
+				} else {
+					printf(obj, "\t%s", r.qpos.typeString(ptr.typ))
+				}
+			}
+		} else {
+			printf(r.qpos, "this %s cannot contain any dynamic types.", r.typ)
+		}
+	} else {
+		// Show labels for other expressions.
+		if ptr := r.ptrs[0]; len(ptr.labels) > 0 {
+			printf(r.qpos, "this %s may point to these objects:",
+				r.qpos.typeString(r.typ))
+			printLabels(printf, ptr.labels, "\t")
+		} else {
+			printf(r.qpos, "this %s may not point to anything.",
+				r.qpos.typeString(r.typ))
+		}
+	}
+}
+
+func (r *pointstoResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	var pts []serial.PointsTo
+	for _, ptr := range r.ptrs {
+		var namePos string
+		if nt, ok := deref(ptr.typ).(*types.Named); ok {
+			namePos = fset.Position(nt.Obj().Pos()).String()
+		}
+		var labels []serial.PointsToLabel
+		for _, l := range ptr.labels {
+			labels = append(labels, serial.PointsToLabel{
+				Pos:  fset.Position(l.Pos()).String(),
+				Desc: l.String(),
+			})
+		}
+		pts = append(pts, serial.PointsTo{
+			Type:    r.qpos.typeString(ptr.typ),
+			NamePos: namePos,
+			Labels:  labels,
+		})
+	}
+	res.PointsTo = pts
+}
+
+type byTypeString []pointerResult
+
+func (a byTypeString) Len() int           { return len(a) }
+func (a byTypeString) Less(i, j int) bool { return a[i].typ.String() < a[j].typ.String() }
+func (a byTypeString) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+
+type byPosAndString []*pointer.Label
+
+func (a byPosAndString) Len() int { return len(a) }
+func (a byPosAndString) Less(i, j int) bool {
+	cmp := a[i].Pos() - a[j].Pos()
+	return cmp < 0 || (cmp == 0 && a[i].String() < a[j].String())
+}
+func (a byPosAndString) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+
+func printLabels(printf printfFunc, labels []*pointer.Label, prefix string) {
+	// TODO(adonovan): due to context-sensitivity, many of these
+	// labels may differ only by context, which isn't apparent.
+	for _, label := range labels {
+		printf(label, "%s%s", prefix, label)
+	}
+}
diff --git a/go/src/golang.org/x/tools/oracle/referrers.go b/go/src/golang.org/x/tools/oracle/referrers.go
index 7383d1f..3545406 100644
--- a/go/src/golang.org/x/tools/oracle/referrers.go
+++ b/go/src/golang.org/x/tools/oracle/referrers.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package oracle
 
 import (
@@ -9,11 +11,11 @@
 	"fmt"
 	"go/ast"
 	"go/token"
+	"go/types"
 	"io/ioutil"
 	"sort"
 
 	"golang.org/x/tools/go/loader"
-	"golang.org/x/tools/go/types"
 	"golang.org/x/tools/oracle/serial"
 	"golang.org/x/tools/refactor/importgraph"
 )
@@ -24,7 +26,7 @@
 	lconf := loader.Config{Build: q.Build}
 	allowErrors(&lconf)
 
-	if err := importQueryPackage(q.Pos, &lconf); err != nil {
+	if _, err := importQueryPackage(q.Pos, &lconf); err != nil {
 		return err
 	}
 
@@ -168,29 +170,33 @@
 	// Show referring lines, like grep.
 	type fileinfo struct {
 		refs     []*ast.Ident
-		linenums []int       // line number of refs[i]
-		data     chan []byte // file contents
+		linenums []int            // line number of refs[i]
+		data     chan interface{} // file contents or error
 	}
 	var fileinfos []*fileinfo
 	fileinfosByName := make(map[string]*fileinfo)
 
 	// First pass: start the file reads concurrently.
+	sema := make(chan struct{}, 20) // counting semaphore to limit I/O concurrency
 	for _, ref := range r.refs {
 		posn := r.qpos.fset.Position(ref.Pos())
 		fi := fileinfosByName[posn.Filename]
 		if fi == nil {
-			fi = &fileinfo{data: make(chan []byte)}
+			fi = &fileinfo{data: make(chan interface{})}
 			fileinfosByName[posn.Filename] = fi
 			fileinfos = append(fileinfos, fi)
 
 			// First request for this file:
 			// start asynchronous read.
 			go func() {
+				sema <- struct{}{} // acquire token
 				content, err := ioutil.ReadFile(posn.Filename)
+				<-sema // release token
 				if err != nil {
-					content = []byte(fmt.Sprintf("error: %v", err))
+					fi.data <- err
+				} else {
+					fi.data <- content
 				}
-				fi.data <- content
 			}()
 		}
 		fi.refs = append(fi.refs, ref)
@@ -200,8 +206,20 @@
 	// Second pass: print refs in original order.
 	// One line may have several refs at different columns.
 	for _, fi := range fileinfos {
-		content := <-fi.data // wait for I/O completion
-		lines := bytes.Split(content, []byte("\n"))
+		v := <-fi.data // wait for I/O completion
+
+		// Print one item for all refs in a file that could not
+		// be loaded (perhaps due to //line directives).
+		if err, ok := v.(error); ok {
+			var suffix string
+			if more := len(fi.refs) - 1; more > 0 {
+				suffix = fmt.Sprintf(" (+ %d more refs in this file)", more)
+			}
+			printf(fi.refs[0], "%v%s", err, suffix)
+			continue
+		}
+
+		lines := bytes.Split(v.([]byte), []byte("\n"))
 		for i, ref := range fi.refs {
 			printf(ref, "%s", lines[fi.linenums[i]-1])
 		}
diff --git a/go/src/golang.org/x/tools/oracle/referrers14.go b/go/src/golang.org/x/tools/oracle/referrers14.go
new file mode 100644
index 0000000..17adf02
--- /dev/null
+++ b/go/src/golang.org/x/tools/oracle/referrers14.go
@@ -0,0 +1,243 @@
+// 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.
+
+// +build !go1.5
+
+package oracle
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/token"
+	"io/ioutil"
+	"sort"
+
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/oracle/serial"
+	"golang.org/x/tools/refactor/importgraph"
+)
+
+// Referrers reports all identifiers that resolve to the same object
+// as the queried identifier, within any package in the analysis scope.
+func referrers(q *Query) error {
+	lconf := loader.Config{Build: q.Build}
+	allowErrors(&lconf)
+
+	if _, err := importQueryPackage(q.Pos, &lconf); err != nil {
+		return err
+	}
+
+	var id *ast.Ident
+	var obj types.Object
+	var lprog *loader.Program
+	var pass2 bool
+	var qpos *queryPos
+	for {
+		// Load/parse/type-check the program.
+		var err error
+		lprog, err = lconf.Load()
+		if err != nil {
+			return err
+		}
+		q.Fset = lprog.Fset
+
+		qpos, err = parseQueryPos(lprog, q.Pos, false)
+		if err != nil {
+			return err
+		}
+
+		id, _ = qpos.path[0].(*ast.Ident)
+		if id == nil {
+			return fmt.Errorf("no identifier here")
+		}
+
+		obj = qpos.info.ObjectOf(id)
+		if obj == nil {
+			// Happens for y in "switch y := x.(type)",
+			// the package declaration,
+			// and unresolved identifiers.
+			if _, ok := qpos.path[1].(*ast.File); ok { // package decl?
+				pkg := qpos.info.Pkg
+				obj = types.NewPkgName(id.Pos(), pkg, pkg.Name(), pkg)
+			} else {
+				return fmt.Errorf("no object for identifier: %T", qpos.path[1])
+			}
+		}
+
+		if pass2 {
+			break
+		}
+
+		// If the identifier is exported, we must load all packages that
+		// depend transitively upon the package that defines it.
+		// Treat PkgNames as exported, even though they're lowercase.
+		if _, isPkg := obj.(*types.PkgName); !(isPkg || obj.Exported()) {
+			break // not exported
+		}
+
+		// Scan the workspace and build the import graph.
+		// Ignore broken packages.
+		_, rev, _ := importgraph.Build(q.Build)
+
+		// Re-load the larger program.
+		// Create a new file set so that ...
+		// External test packages are never imported,
+		// so they will never appear in the graph.
+		// (We must reset the Config here, not just reset the Fset field.)
+		lconf = loader.Config{
+			Fset:  token.NewFileSet(),
+			Build: q.Build,
+		}
+		allowErrors(&lconf)
+		for path := range rev.Search(obj.Pkg().Path()) {
+			lconf.ImportWithTests(path)
+		}
+		pass2 = true
+	}
+
+	// Iterate over all go/types' Uses facts for the entire program.
+	var refs []*ast.Ident
+	for _, info := range lprog.AllPackages {
+		for id2, obj2 := range info.Uses {
+			if sameObj(obj, obj2) {
+				refs = append(refs, id2)
+			}
+		}
+	}
+	sort.Sort(byNamePos{q.Fset, refs})
+
+	q.result = &referrersResult{
+		qpos:  qpos,
+		query: id,
+		obj:   obj,
+		refs:  refs,
+	}
+	return nil
+}
+
+// same reports whether x and y are identical, or both are PkgNames
+// that import the same Package.
+//
+func sameObj(x, y types.Object) bool {
+	if x == y {
+		return true
+	}
+	if x, ok := x.(*types.PkgName); ok {
+		if y, ok := y.(*types.PkgName); ok {
+			return x.Imported() == y.Imported()
+		}
+	}
+	return false
+}
+
+// -------- utils --------
+
+// An deterministic ordering for token.Pos that doesn't
+// depend on the order in which packages were loaded.
+func lessPos(fset *token.FileSet, x, y token.Pos) bool {
+	fx := fset.File(x)
+	fy := fset.File(y)
+	if fx != fy {
+		return fx.Name() < fy.Name()
+	}
+	return x < y
+}
+
+type byNamePos struct {
+	fset *token.FileSet
+	ids  []*ast.Ident
+}
+
+func (p byNamePos) Len() int      { return len(p.ids) }
+func (p byNamePos) Swap(i, j int) { p.ids[i], p.ids[j] = p.ids[j], p.ids[i] }
+func (p byNamePos) Less(i, j int) bool {
+	return lessPos(p.fset, p.ids[i].NamePos, p.ids[j].NamePos)
+}
+
+type referrersResult struct {
+	qpos  *queryPos
+	query *ast.Ident   // identifier of query
+	obj   types.Object // object it denotes
+	refs  []*ast.Ident // set of all other references to it
+}
+
+func (r *referrersResult) display(printf printfFunc) {
+	printf(r.obj, "%d references to %s", len(r.refs), r.qpos.objectString(r.obj))
+
+	// Show referring lines, like grep.
+	type fileinfo struct {
+		refs     []*ast.Ident
+		linenums []int            // line number of refs[i]
+		data     chan interface{} // file contents or error
+	}
+	var fileinfos []*fileinfo
+	fileinfosByName := make(map[string]*fileinfo)
+
+	// First pass: start the file reads concurrently.
+	sema := make(chan struct{}, 20) // counting semaphore to limit I/O concurrency
+	for _, ref := range r.refs {
+		posn := r.qpos.fset.Position(ref.Pos())
+		fi := fileinfosByName[posn.Filename]
+		if fi == nil {
+			fi = &fileinfo{data: make(chan interface{})}
+			fileinfosByName[posn.Filename] = fi
+			fileinfos = append(fileinfos, fi)
+
+			// First request for this file:
+			// start asynchronous read.
+			go func() {
+				sema <- struct{}{} // acquire token
+				content, err := ioutil.ReadFile(posn.Filename)
+				<-sema // release token
+				if err != nil {
+					fi.data <- err
+				} else {
+					fi.data <- content
+				}
+			}()
+		}
+		fi.refs = append(fi.refs, ref)
+		fi.linenums = append(fi.linenums, posn.Line)
+	}
+
+	// Second pass: print refs in original order.
+	// One line may have several refs at different columns.
+	for _, fi := range fileinfos {
+		v := <-fi.data // wait for I/O completion
+
+		// Print one item for all refs in a file that could not
+		// be loaded (perhaps due to //line directives).
+		if err, ok := v.(error); ok {
+			var suffix string
+			if more := len(fi.refs) - 1; more > 0 {
+				suffix = fmt.Sprintf(" (+ %d more refs in this file)", more)
+			}
+			printf(fi.refs[0], "%v%s", err, suffix)
+			continue
+		}
+
+		lines := bytes.Split(v.([]byte), []byte("\n"))
+		for i, ref := range fi.refs {
+			printf(ref, "%s", lines[fi.linenums[i]-1])
+		}
+	}
+}
+
+// TODO(adonovan): encode extent, not just Pos info, in Serial form.
+
+func (r *referrersResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	referrers := &serial.Referrers{
+		Pos:  fset.Position(r.query.Pos()).String(),
+		Desc: r.obj.String(),
+	}
+	if pos := r.obj.Pos(); pos != token.NoPos { // Package objects have no Pos()
+		referrers.ObjPos = fset.Position(pos).String()
+	}
+	for _, ref := range r.refs {
+		referrers.Refs = append(referrers.Refs, fset.Position(ref.NamePos).String())
+	}
+	res.Referrers = referrers
+}
diff --git a/go/src/golang.org/x/tools/oracle/testdata/src/calls/main.go b/go/src/golang.org/x/tools/oracle/testdata/src/calls/main.go
index 54bb895..849fb6e 100644
--- a/go/src/golang.org/x/tools/oracle/testdata/src/calls/main.go
+++ b/go/src/golang.org/x/tools/oracle/testdata/src/calls/main.go
@@ -83,6 +83,9 @@
 	fmt.Println() // @callees callees-qualified-call "Println"
 	m := new(method)
 	m.f() // @callees callees-static-method-call "f"
+	g := new(embeddedIface)
+	g.iface = m
+	g.f() // @callees callees-implicit-selection-method-call "f"
 }
 
 type myint int
@@ -96,6 +99,14 @@
 func (method) f() {
 }
 
+type embeddedIface struct {
+	iface
+}
+
+type iface interface {
+	f()
+}
+
 var dynamic = func() {}
 
 func deadcode() {
diff --git a/go/src/golang.org/x/tools/oracle/testdata/src/calls/main.golden b/go/src/golang.org/x/tools/oracle/testdata/src/calls/main.golden
index b5e6547..9159cd6 100644
--- a/go/src/golang.org/x/tools/oracle/testdata/src/calls/main.golden
+++ b/go/src/golang.org/x/tools/oracle/testdata/src/calls/main.golden
@@ -96,6 +96,10 @@
 this static function call dispatches to:
 	(main.method).f
 
+-------- @callees callees-implicit-selection-method-call --------
+this dynamic method call dispatches to:
+	(main.method).f
+
 -------- @callers callers-not-a-wrapper --------
 (main.myint).f is called from these 1 sites:
 	dynamic method call from main.main
diff --git a/go/src/golang.org/x/tools/oracle/testdata/src/describe/main.go b/go/src/golang.org/x/tools/oracle/testdata/src/describe/main.go
index 69e0a75..f48d6d0 100644
--- a/go/src/golang.org/x/tools/oracle/testdata/src/describe/main.go
+++ b/go/src/golang.org/x/tools/oracle/testdata/src/describe/main.go
@@ -6,6 +6,15 @@
 
 // TODO(adonovan): more coverage of the (extensive) logic.
 
+import (
+	"nosuchpkg"            // @describe badimport1 "nosuchpkg"
+	nosuchpkg2 "nosuchpkg" // @describe badimport2 "nosuchpkg2"
+	_ "unsafe"             // @describe unsafe "unsafe"
+)
+
+var _ nosuchpkg.T
+var _ nosuchpkg2.T
+
 type cake float64 // @describe type-ref-builtin "float64"
 
 const c = iota // @describe const-ref-iota "iota"
diff --git a/go/src/golang.org/x/tools/oracle/testdata/src/describe/main.golden b/go/src/golang.org/x/tools/oracle/testdata/src/describe/main.golden
index 33d751a..bc6d9f7 100644
--- a/go/src/golang.org/x/tools/oracle/testdata/src/describe/main.golden
+++ b/go/src/golang.org/x/tools/oracle/testdata/src/describe/main.golden
@@ -10,8 +10,21 @@
 	type  cake   float64
 	var   global *string
 	func  main   func()
-	const pi     untyped float = 3141/1000
-	const pie    cake = 1768225803696341/562949953421312
+	const pi     untyped float = 3.141
+	const pie    cake = 3.141
+
+-------- @describe badimport1 --------
+
+Error: can't import package "nosuchpkg"
+-------- @describe badimport2 --------
+
+Error: can't import package "nosuchpkg"
+-------- @describe unsafe --------
+import of package "unsafe"
+	builtin Alignof 
+	builtin Offsetof
+	type  Pointer  unsafe.Pointer
+	builtin Sizeof  
 
 -------- @describe type-ref-builtin --------
 reference to built-in type float64
@@ -26,7 +39,7 @@
 definition of const pie cake
 
 -------- @describe const-ref-pi --------
-reference to const pi untyped float of constant value 3141/1000
+reference to const pi untyped float of constant value 3.141
 defined here
 
 -------- @describe func-def-main --------
@@ -114,7 +127,7 @@
 definition of const localpie cake
 
 -------- @describe const-ref-localpi --------
-reference to const localpi untyped float of constant value 3141/1000
+reference to const localpi untyped float of constant value 3.141
 defined here
 
 -------- @describe type-def-T --------
diff --git a/go/src/golang.org/x/tools/oracle/testdata/src/implements-methods-json/main.golden b/go/src/golang.org/x/tools/oracle/testdata/src/implements-methods-json/main.golden
index fa117df..831900a 100644
--- a/go/src/golang.org/x/tools/oracle/testdata/src/implements-methods-json/main.golden
+++ b/go/src/golang.org/x/tools/oracle/testdata/src/implements-methods-json/main.golden
@@ -274,6 +274,18 @@
 				"name": "lib.Type",
 				"pos": "testdata/src/lib/lib.go:3:6",
 				"kind": "basic"
+			},
+			{
+				"name": "main.I",
+				"pos": "testdata/src/implements-methods-json/main.go:35:6",
+				"kind": "interface"
+			}
+		],
+		"from": [
+			{
+				"name": "main.I",
+				"pos": "testdata/src/implements-methods-json/main.go:35:6",
+				"kind": "interface"
 			}
 		],
 		"method": {
@@ -284,6 +296,16 @@
 			{
 				"name": "method (lib.Type) Method(x *int) *int",
 				"pos": "testdata/src/lib/lib.go:5:13"
+			},
+			{
+				"name": "method (main.I) Method(*int) *int",
+				"pos": "testdata/src/implements-methods-json/main.go:36:2"
+			}
+		],
+		"from_method": [
+			{
+				"name": "method (main.I) Method(*int) *int",
+				"pos": "testdata/src/implements-methods-json/main.go:36:2"
 			}
 		]
 	}
diff --git a/go/src/golang.org/x/tools/oracle/testdata/src/implements-methods/main.golden b/go/src/golang.org/x/tools/oracle/testdata/src/implements-methods/main.golden
index bd591e8..227d305 100644
--- a/go/src/golang.org/x/tools/oracle/testdata/src/implements-methods/main.golden
+++ b/go/src/golang.org/x/tools/oracle/testdata/src/implements-methods/main.golden
@@ -34,4 +34,6 @@
 -------- @implements I.Method --------
 abstract method func (I).Method(*int) *int
 	is implemented by method (lib.Type).Method
+	is implemented by method (main.I).Method
+	implements method (main.I).Method
 
diff --git a/go/src/golang.org/x/tools/oracle/testdata/src/implements/main.golden b/go/src/golang.org/x/tools/oracle/testdata/src/implements/main.golden
index ee00f3d..cb2f2ac 100644
--- a/go/src/golang.org/x/tools/oracle/testdata/src/implements/main.golden
+++ b/go/src/golang.org/x/tools/oracle/testdata/src/implements/main.golden
@@ -41,4 +41,6 @@
 -------- @implements I --------
 interface type I
 	is implemented by basic type lib.Type
+	is implemented by interface type main.I
+	implements main.I
 
diff --git a/go/src/golang.org/x/tools/oracle/testdata/src/referrers/main.go b/go/src/golang.org/x/tools/oracle/testdata/src/referrers/main.go
index 36cdb7a..fef571a 100644
--- a/go/src/golang.org/x/tools/oracle/testdata/src/referrers/main.go
+++ b/go/src/golang.org/x/tools/oracle/testdata/src/referrers/main.go
@@ -24,3 +24,11 @@
 	var s2 s
 	s2.f = 1
 }
+
+// Test //line directives:
+
+type U int // @referrers ref-type-U "U"
+
+//line nosuchfile.y:123
+var u1 U
+var u2 U
diff --git a/go/src/golang.org/x/tools/oracle/testdata/src/referrers/main.golden b/go/src/golang.org/x/tools/oracle/testdata/src/referrers/main.golden
index 1f04be5..d98d510 100644
--- a/go/src/golang.org/x/tools/oracle/testdata/src/referrers/main.golden
+++ b/go/src/golang.org/x/tools/oracle/testdata/src/referrers/main.golden
@@ -36,3 +36,7 @@
 	_ = s{}.f // @referrers ref-field "f"
 	s2.f = 1
 
+-------- @referrers ref-type-U --------
+2 references to type U int
+open testdata/src/referrers/nosuchfile.y: no such file or directory (+ 1 more refs in this file)
+
diff --git a/go/src/golang.org/x/tools/oracle/whicherrs.go b/go/src/golang.org/x/tools/oracle/whicherrs.go
index aaa6068..be43c39 100644
--- a/go/src/golang.org/x/tools/oracle/whicherrs.go
+++ b/go/src/golang.org/x/tools/oracle/whicherrs.go
@@ -2,19 +2,21 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package oracle
 
 import (
 	"fmt"
 	"go/ast"
 	"go/token"
+	"go/types"
 	"sort"
 
 	"golang.org/x/tools/go/ast/astutil"
 	"golang.org/x/tools/go/loader"
 	"golang.org/x/tools/go/ssa"
 	"golang.org/x/tools/go/ssa/ssautil"
-	"golang.org/x/tools/go/types"
 	"golang.org/x/tools/oracle/serial"
 )
 
@@ -91,7 +93,7 @@
 	}
 
 	// Defer SSA construction till after errors are reported.
-	prog.BuildAll()
+	prog.Build()
 
 	globals := findVisibleErrs(prog, qpos)
 	constants := findVisibleConsts(prog, qpos)
diff --git a/go/src/golang.org/x/tools/oracle/whicherrs14.go b/go/src/golang.org/x/tools/oracle/whicherrs14.go
new file mode 100644
index 0000000..25449f3
--- /dev/null
+++ b/go/src/golang.org/x/tools/oracle/whicherrs14.go
@@ -0,0 +1,328 @@
+// Copyright 2014 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.
+
+// +build !go1.5
+
+package oracle
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"sort"
+
+	"golang.org/x/tools/go/ast/astutil"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/ssa"
+	"golang.org/x/tools/go/ssa/ssautil"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/oracle/serial"
+)
+
+var builtinErrorType = types.Universe.Lookup("error").Type()
+
+// whicherrs takes an position to an error and tries to find all types, constants
+// and global value which a given error can point to and which can be checked from the
+// scope where the error lives.
+// In short, it returns a list of things that can be checked against in order to handle
+// an error properly.
+//
+// TODO(dmorsing): figure out if fields in errors like *os.PathError.Err
+// can be queried recursively somehow.
+func whicherrs(q *Query) error {
+	lconf := loader.Config{Build: q.Build}
+
+	if err := setPTAScope(&lconf, q.Scope); err != nil {
+		return err
+	}
+
+	// Load/parse/type-check the program.
+	lprog, err := lconf.Load()
+	if err != nil {
+		return err
+	}
+	q.Fset = lprog.Fset
+
+	qpos, err := parseQueryPos(lprog, q.Pos, true) // needs exact pos
+	if err != nil {
+		return err
+	}
+
+	prog := ssautil.CreateProgram(lprog, ssa.GlobalDebug)
+
+	ptaConfig, err := setupPTA(prog, lprog, q.PTALog, q.Reflection)
+	if err != nil {
+		return err
+	}
+
+	path, action := findInterestingNode(qpos.info, qpos.path)
+	if action != actionExpr {
+		return fmt.Errorf("whicherrs wants an expression; got %s",
+			astutil.NodeDescription(qpos.path[0]))
+	}
+	var expr ast.Expr
+	var obj types.Object
+	switch n := path[0].(type) {
+	case *ast.ValueSpec:
+		// ambiguous ValueSpec containing multiple names
+		return fmt.Errorf("multiple value specification")
+	case *ast.Ident:
+		obj = qpos.info.ObjectOf(n)
+		expr = n
+	case ast.Expr:
+		expr = n
+	default:
+		return fmt.Errorf("unexpected AST for expr: %T", n)
+	}
+
+	typ := qpos.info.TypeOf(expr)
+	if !types.Identical(typ, builtinErrorType) {
+		return fmt.Errorf("selection is not an expression of type 'error'")
+	}
+	// Determine the ssa.Value for the expression.
+	var value ssa.Value
+	if obj != nil {
+		// def/ref of func/var object
+		value, _, err = ssaValueForIdent(prog, qpos.info, obj, path)
+	} else {
+		value, _, err = ssaValueForExpr(prog, qpos.info, path)
+	}
+	if err != nil {
+		return err // e.g. trivially dead code
+	}
+
+	// Defer SSA construction till after errors are reported.
+	prog.Build()
+
+	globals := findVisibleErrs(prog, qpos)
+	constants := findVisibleConsts(prog, qpos)
+
+	res := &whicherrsResult{
+		qpos:   qpos,
+		errpos: expr.Pos(),
+	}
+
+	// TODO(adonovan): the following code is heavily duplicated
+	// w.r.t.  "pointsto".  Refactor?
+
+	// Find the instruction which initialized the
+	// global error. If more than one instruction has stored to the global
+	// remove the global from the set of values that we want to query.
+	allFuncs := ssautil.AllFunctions(prog)
+	for fn := range allFuncs {
+		for _, b := range fn.Blocks {
+			for _, instr := range b.Instrs {
+				store, ok := instr.(*ssa.Store)
+				if !ok {
+					continue
+				}
+				gval, ok := store.Addr.(*ssa.Global)
+				if !ok {
+					continue
+				}
+				gbl, ok := globals[gval]
+				if !ok {
+					continue
+				}
+				// we already found a store to this global
+				// The normal error define is just one store in the init
+				// so we just remove this global from the set we want to query
+				if gbl != nil {
+					delete(globals, gval)
+				}
+				globals[gval] = store.Val
+			}
+		}
+	}
+
+	ptaConfig.AddQuery(value)
+	for _, v := range globals {
+		ptaConfig.AddQuery(v)
+	}
+
+	ptares := ptrAnalysis(ptaConfig)
+	valueptr := ptares.Queries[value]
+	for g, v := range globals {
+		ptr, ok := ptares.Queries[v]
+		if !ok {
+			continue
+		}
+		if !ptr.MayAlias(valueptr) {
+			continue
+		}
+		res.globals = append(res.globals, g)
+	}
+	pts := valueptr.PointsTo()
+	dedup := make(map[*ssa.NamedConst]bool)
+	for _, label := range pts.Labels() {
+		// These values are either MakeInterfaces or reflect
+		// generated interfaces. For the purposes of this
+		// analysis, we don't care about reflect generated ones
+		makeiface, ok := label.Value().(*ssa.MakeInterface)
+		if !ok {
+			continue
+		}
+		constval, ok := makeiface.X.(*ssa.Const)
+		if !ok {
+			continue
+		}
+		c := constants[*constval]
+		if c != nil && !dedup[c] {
+			dedup[c] = true
+			res.consts = append(res.consts, c)
+		}
+	}
+	concs := pts.DynamicTypes()
+	concs.Iterate(func(conc types.Type, _ interface{}) {
+		// go/types is a bit annoying here.
+		// We want to find all the types that we can
+		// typeswitch or assert to. This means finding out
+		// if the type pointed to can be seen by us.
+		//
+		// For the purposes of this analysis, the type is always
+		// either a Named type or a pointer to one.
+		// There are cases where error can be implemented
+		// by unnamed types, but in that case, we can't assert to
+		// it, so we don't care about it for this analysis.
+		var name *types.TypeName
+		switch t := conc.(type) {
+		case *types.Pointer:
+			named, ok := t.Elem().(*types.Named)
+			if !ok {
+				return
+			}
+			name = named.Obj()
+		case *types.Named:
+			name = t.Obj()
+		default:
+			return
+		}
+		if !isAccessibleFrom(name, qpos.info.Pkg) {
+			return
+		}
+		res.types = append(res.types, &errorType{conc, name})
+	})
+	sort.Sort(membersByPosAndString(res.globals))
+	sort.Sort(membersByPosAndString(res.consts))
+	sort.Sort(sorterrorType(res.types))
+
+	q.result = res
+	return nil
+}
+
+// findVisibleErrs returns a mapping from each package-level variable of type "error" to nil.
+func findVisibleErrs(prog *ssa.Program, qpos *queryPos) map[*ssa.Global]ssa.Value {
+	globals := make(map[*ssa.Global]ssa.Value)
+	for _, pkg := range prog.AllPackages() {
+		for _, mem := range pkg.Members {
+			gbl, ok := mem.(*ssa.Global)
+			if !ok {
+				continue
+			}
+			gbltype := gbl.Type()
+			// globals are always pointers
+			if !types.Identical(deref(gbltype), builtinErrorType) {
+				continue
+			}
+			if !isAccessibleFrom(gbl.Object(), qpos.info.Pkg) {
+				continue
+			}
+			globals[gbl] = nil
+		}
+	}
+	return globals
+}
+
+// findVisibleConsts returns a mapping from each package-level constant assignable to type "error", to nil.
+func findVisibleConsts(prog *ssa.Program, qpos *queryPos) map[ssa.Const]*ssa.NamedConst {
+	constants := make(map[ssa.Const]*ssa.NamedConst)
+	for _, pkg := range prog.AllPackages() {
+		for _, mem := range pkg.Members {
+			obj, ok := mem.(*ssa.NamedConst)
+			if !ok {
+				continue
+			}
+			consttype := obj.Type()
+			if !types.AssignableTo(consttype, builtinErrorType) {
+				continue
+			}
+			if !isAccessibleFrom(obj.Object(), qpos.info.Pkg) {
+				continue
+			}
+			constants[*obj.Value] = obj
+		}
+	}
+
+	return constants
+}
+
+type membersByPosAndString []ssa.Member
+
+func (a membersByPosAndString) Len() int { return len(a) }
+func (a membersByPosAndString) Less(i, j int) bool {
+	cmp := a[i].Pos() - a[j].Pos()
+	return cmp < 0 || cmp == 0 && a[i].String() < a[j].String()
+}
+func (a membersByPosAndString) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+
+type sorterrorType []*errorType
+
+func (a sorterrorType) Len() int { return len(a) }
+func (a sorterrorType) Less(i, j int) bool {
+	cmp := a[i].obj.Pos() - a[j].obj.Pos()
+	return cmp < 0 || cmp == 0 && a[i].typ.String() < a[j].typ.String()
+}
+func (a sorterrorType) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+
+type errorType struct {
+	typ types.Type      // concrete type N or *N that implements error
+	obj *types.TypeName // the named type N
+}
+
+type whicherrsResult struct {
+	qpos    *queryPos
+	errpos  token.Pos
+	globals []ssa.Member
+	consts  []ssa.Member
+	types   []*errorType
+}
+
+func (r *whicherrsResult) display(printf printfFunc) {
+	if len(r.globals) > 0 {
+		printf(r.qpos, "this error may point to these globals:")
+		for _, g := range r.globals {
+			printf(g.Pos(), "\t%s", g.RelString(r.qpos.info.Pkg))
+		}
+	}
+	if len(r.consts) > 0 {
+		printf(r.qpos, "this error may contain these constants:")
+		for _, c := range r.consts {
+			printf(c.Pos(), "\t%s", c.RelString(r.qpos.info.Pkg))
+		}
+	}
+	if len(r.types) > 0 {
+		printf(r.qpos, "this error may contain these dynamic types:")
+		for _, t := range r.types {
+			printf(t.obj.Pos(), "\t%s", r.qpos.typeString(t.typ))
+		}
+	}
+}
+
+func (r *whicherrsResult) toSerial(res *serial.Result, fset *token.FileSet) {
+	we := &serial.WhichErrs{}
+	we.ErrPos = fset.Position(r.errpos).String()
+	for _, g := range r.globals {
+		we.Globals = append(we.Globals, fset.Position(g.Pos()).String())
+	}
+	for _, c := range r.consts {
+		we.Constants = append(we.Constants, fset.Position(c.Pos()).String())
+	}
+	for _, t := range r.types {
+		var et serial.WhichErrsType
+		et.Type = r.qpos.typeString(t.typ)
+		et.Position = fset.Position(t.obj.Pos()).String()
+		we.Types = append(we.Types, et)
+	}
+	res.WhichErrs = we
+}
diff --git a/go/src/golang.org/x/tools/playground/appengine.go b/go/src/golang.org/x/tools/playground/appengine.go
index 073b419..94c5d52 100644
--- a/go/src/golang.org/x/tools/playground/appengine.go
+++ b/go/src/golang.org/x/tools/playground/appengine.go
@@ -13,6 +13,10 @@
 	"appengine/urlfetch"
 )
 
+func init() {
+	onAppengine = !appengine.IsDevAppServer()
+}
+
 func client(r *http.Request) *http.Client {
 	return urlfetch.Client(appengine.NewContext(r))
 }
diff --git a/go/src/golang.org/x/tools/playground/appenginevm.go b/go/src/golang.org/x/tools/playground/appenginevm.go
new file mode 100644
index 0000000..aa3a212
--- /dev/null
+++ b/go/src/golang.org/x/tools/playground/appenginevm.go
@@ -0,0 +1,11 @@
+// Copyright 2015 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.
+
+// +build appenginevm
+
+package playground
+
+func init() {
+	onAppengine = true
+}
diff --git a/go/src/golang.org/x/tools/playground/common.go b/go/src/golang.org/x/tools/playground/common.go
index 3ffce88..d8c2805 100644
--- a/go/src/golang.org/x/tools/playground/common.go
+++ b/go/src/golang.org/x/tools/playground/common.go
@@ -9,6 +9,7 @@
 
 import (
 	"bytes"
+	"errors"
 	"fmt"
 	"io"
 	"net/http"
@@ -32,6 +33,9 @@
 }
 
 func passThru(w io.Writer, req *http.Request) error {
+	if req.URL.Path == "/share" && !allowShare(req) {
+		return errors.New("Forbidden")
+	}
 	defer req.Body.Close()
 	url := baseURL + req.URL.Path
 	r, err := client(req).Post(url, req.Header.Get("Content-type"), req.Body)
@@ -44,3 +48,16 @@
 	}
 	return nil
 }
+
+var onAppengine = false // will be overriden by appengine.go and appenginevm.go
+
+func allowShare(r *http.Request) bool {
+	if !onAppengine {
+		return true
+	}
+	switch r.Header.Get("X-AppEngine-Country") {
+	case "", "ZZ", "CN":
+		return false
+	}
+	return true
+}
diff --git a/go/src/golang.org/x/tools/playground/socket/socket.go b/go/src/golang.org/x/tools/playground/socket/socket.go
index 76527ae..cec842e 100644
--- a/go/src/golang.org/x/tools/playground/socket/socket.go
+++ b/go/src/golang.org/x/tools/playground/socket/socket.go
@@ -31,7 +31,6 @@
 	"runtime"
 	"strconv"
 	"strings"
-	"sync"
 	"time"
 	"unicode/utf8"
 
@@ -129,6 +128,7 @@
 			}
 		}
 	}()
+	defer close(out)
 
 	// Start and kill processes and handle errors.
 	proc := make(map[string]*process)
@@ -139,8 +139,7 @@
 			case "run":
 				log.Println("running snippet from:", c.Request().RemoteAddr)
 				proc[m.Id].Kill()
-				lOut := limiter(in, out)
-				proc[m.Id] = startProcess(m.Id, m.Body, lOut, m.Options)
+				proc[m.Id] = startProcess(m.Id, m.Body, out, m.Options)
 			case "kill":
 				proc[m.Id].Kill()
 			}
@@ -160,7 +159,6 @@
 
 // process represents a running process.
 type process struct {
-	id   string
 	out  chan<- *Message
 	done chan struct{} // closed when wait completes
 	run  *exec.Cmd
@@ -169,12 +167,19 @@
 
 // startProcess builds and runs the given program, sending its output
 // and end event as Messages on the provided channel.
-func startProcess(id, body string, out chan<- *Message, opt *Options) *process {
-	p := &process{
-		id:   id,
-		out:  out,
-		done: make(chan struct{}),
-	}
+func startProcess(id, body string, dest chan<- *Message, opt *Options) *process {
+	var (
+		done = make(chan struct{})
+		out  = make(chan *Message)
+		p    = &process{out: out, done: done}
+	)
+	go func() {
+		defer close(done)
+		for m := range buffer(limiter(out, p)) {
+			m.Id = id
+			dest <- m
+		}
+	}()
 	var err error
 	if path, args := shebang(body); path != "" {
 		if RunScripts {
@@ -189,13 +194,122 @@
 		p.end(err)
 		return nil
 	}
-	go p.wait()
+	go func() {
+		p.end(p.run.Wait())
+	}()
 	return p
 }
 
+// end sends an "end" message to the client, containing the process id and the
+// given error value. It also removes the binary, if present.
+func (p *process) end(err error) {
+	if p.bin != "" {
+		defer os.Remove(p.bin)
+	}
+	m := &Message{Kind: "end"}
+	if err != nil {
+		m.Body = err.Error()
+	}
+	p.out <- m
+	close(p.out)
+}
+
+// A killer provides a mechanism to terminate a process.
+// The Kill method returns only once the process has exited.
+type killer interface {
+	Kill()
+}
+
+// limiter returns a channel that wraps the given channel.
+// It receives Messages from the given channel and sends them to the returned
+// channel until it passes msgLimit messages, at which point it will kill the
+// process and pass only the "end" message.
+// When the given channel is closed, or when the "end" message is received,
+// it closes the returned channel.
+func limiter(in <-chan *Message, p killer) <-chan *Message {
+	out := make(chan *Message)
+	go func() {
+		defer close(out)
+		n := 0
+		for m := range in {
+			switch {
+			case n < msgLimit || m.Kind == "end":
+				out <- m
+				if m.Kind == "end" {
+					return
+				}
+			case n == msgLimit:
+				// Kill in a goroutine as Kill will not return
+				// until the process' output has been
+				// processed, and we're doing that in this loop.
+				go p.Kill()
+			default:
+				continue // don't increment
+			}
+			n++
+		}
+	}()
+	return out
+}
+
+// buffer returns a channel that wraps the given channel. It receives messages
+// from the given channel and sends them to the returned channel.
+// Message bodies are gathered over the period msgDelay and coalesced into a
+// single Message before they are passed on. Messages of the same kind are
+// coalesced; when a message of a different kind is received, any buffered
+// messages are flushed. When the given channel is closed, buffer flushes the
+// remaining buffered messages and closes the returned channel.
+func buffer(in <-chan *Message) <-chan *Message {
+	out := make(chan *Message)
+	go func() {
+		defer close(out)
+		var (
+			t     = time.NewTimer(msgDelay)
+			tc    <-chan time.Time
+			buf   []byte
+			kind  string
+			flush = func() {
+				if len(buf) == 0 {
+					return
+				}
+				out <- &Message{Kind: kind, Body: safeString(buf)}
+				buf = buf[:0] // recycle buffer
+				kind = ""
+			}
+		)
+		for {
+			select {
+			case m, ok := <-in:
+				if !ok {
+					flush()
+					return
+				}
+				if m.Kind == "end" {
+					flush()
+					out <- m
+					return
+				}
+				if kind != m.Kind {
+					flush()
+					kind = m.Kind
+					if tc == nil {
+						tc = t.C
+						t.Reset(msgDelay)
+					}
+				}
+				buf = append(buf, m.Body...)
+			case <-tc:
+				flush()
+				tc = nil
+			}
+		}
+	}()
+	return out
+}
+
 // Kill stops the process if it is running and waits for it to exit.
 func (p *process) Kill() {
-	if p == nil {
+	if p == nil || p.run == nil {
 		return
 	}
 	p.run.Process.Kill()
@@ -224,8 +338,8 @@
 		Path:   path,
 		Args:   args,
 		Stdin:  strings.NewReader(body),
-		Stdout: &messageWriter{id: p.id, kind: "stdout", out: p.out},
-		Stderr: &messageWriter{id: p.id, kind: "stderr", out: p.out},
+		Stdout: &messageWriter{kind: "stdout", out: p.out},
+		Stderr: &messageWriter{kind: "stderr", out: p.out},
 	}
 	if err := cmd.Start(); err != nil {
 		return err
@@ -261,7 +375,7 @@
 	args := []string{"go", "build", "-tags", "OMIT"}
 	if opt != nil && opt.Race {
 		p.out <- &Message{
-			Id: p.id, Kind: "stderr",
+			Kind: "stderr",
 			Body: "Running with race detector.\n",
 		}
 		args = append(args, "-race")
@@ -298,35 +412,14 @@
 	return nil
 }
 
-// wait waits for the running process to complete
-// and sends its error state to the client.
-func (p *process) wait() {
-	p.end(p.run.Wait())
-	close(p.done) // unblock waiting Kill calls
-}
-
-// end sends an "end" message to the client, containing the process id and the
-// given error value. It also removes the binary.
-func (p *process) end(err error) {
-	if p.bin != "" {
-		defer os.Remove(p.bin)
-	}
-	m := &Message{Id: p.id, Kind: "end"}
-	if err != nil {
-		m.Body = err.Error()
-	}
-	// Wait for any outstanding reads to finish (potential race here).
-	time.AfterFunc(4*msgDelay, func() { p.out <- m })
-}
-
 // cmd builds an *exec.Cmd that writes its standard output and error to the
 // process' output channel.
 func (p *process) cmd(dir string, args ...string) *exec.Cmd {
 	cmd := exec.Command(args[0], args[1:]...)
 	cmd.Dir = dir
 	cmd.Env = Environ()
-	cmd.Stdout = &messageWriter{id: p.id, kind: "stdout", out: p.out}
-	cmd.Stderr = &messageWriter{id: p.id, kind: "stderr", out: p.out}
+	cmd.Stdout = &messageWriter{kind: "stdout", out: p.out}
+	cmd.Stderr = &messageWriter{kind: "stderr", out: p.out}
 	return cmd
 }
 
@@ -387,33 +480,15 @@
 // messageWriter is an io.Writer that converts all writes to Message sends on
 // the out channel with the specified id and kind.
 type messageWriter struct {
-	id, kind string
-	out      chan<- *Message
-
-	mu   sync.Mutex
-	buf  []byte
-	send *time.Timer
+	kind string
+	out  chan<- *Message
 }
 
 func (w *messageWriter) Write(b []byte) (n int, err error) {
-	// Buffer writes that occur in a short period to send as one Message.
-	w.mu.Lock()
-	w.buf = append(w.buf, b...)
-	if w.send == nil {
-		w.send = time.AfterFunc(msgDelay, w.sendNow)
-	}
-	w.mu.Unlock()
+	w.out <- &Message{Kind: w.kind, Body: safeString(b)}
 	return len(b), nil
 }
 
-func (w *messageWriter) sendNow() {
-	w.mu.Lock()
-	body := safeString(w.buf)
-	w.buf, w.send = nil, nil
-	w.mu.Unlock()
-	w.out <- &Message{Id: w.id, Kind: w.kind, Body: body}
-}
-
 // safeString returns b as a valid UTF-8 string.
 func safeString(b []byte) string {
 	if utf8.Valid(b) {
@@ -428,30 +503,6 @@
 	return buf.String()
 }
 
-// limiter returns a channel that wraps dest. Messages sent to the channel are
-// sent to dest. After msgLimit Messages have been passed on, a "kill" Message
-// is sent to the kill channel, and only "end" messages are passed.
-func limiter(kill chan<- *Message, dest chan<- *Message) chan<- *Message {
-	ch := make(chan *Message)
-	go func() {
-		n := 0
-		for m := range ch {
-			switch {
-			case n < msgLimit || m.Kind == "end":
-				dest <- m
-				if m.Kind == "end" {
-					return
-				}
-			case n == msgLimit:
-				// process produced too much output. Kill it.
-				kill <- &Message{Id: m.Id, Kind: "kill"}
-			}
-			n++
-		}
-	}()
-	return ch
-}
-
 var tmpdir string
 
 func init() {
diff --git a/go/src/golang.org/x/tools/playground/socket/socket_test.go b/go/src/golang.org/x/tools/playground/socket/socket_test.go
new file mode 100644
index 0000000..5dd2815
--- /dev/null
+++ b/go/src/golang.org/x/tools/playground/socket/socket_test.go
@@ -0,0 +1,73 @@
+// Copyright 2015 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 socket
+
+import (
+	"testing"
+	"time"
+)
+
+func TestBuffer(t *testing.T) {
+	ch := make(chan *Message)
+	go func() {
+		ch <- &Message{Kind: "err", Body: "a"}
+		ch <- &Message{Kind: "err", Body: "b"}
+		ch <- &Message{Kind: "out", Body: "1"}
+		ch <- &Message{Kind: "out", Body: "2"}
+		time.Sleep(msgDelay * 2)
+		ch <- &Message{Kind: "out", Body: "3"}
+		ch <- &Message{Kind: "out", Body: "4"}
+		close(ch)
+	}()
+
+	var ms []*Message
+	for m := range buffer(ch) {
+		ms = append(ms, m)
+	}
+	if len(ms) != 3 {
+		t.Fatalf("got %v messages, want 2", len(ms))
+	}
+	if g, w := ms[0].Body, "ab"; g != w {
+		t.Errorf("message 0 body = %q, want %q", g, w)
+	}
+	if g, w := ms[1].Body, "12"; g != w {
+		t.Errorf("message 1 body = %q, want %q", g, w)
+	}
+	if g, w := ms[2].Body, "34"; g != w {
+		t.Errorf("message 2 body = %q, want %q", g, w)
+	}
+}
+
+type killRecorder chan struct{}
+
+func (k killRecorder) Kill() { close(k) }
+
+func TestLimiter(t *testing.T) {
+	ch := make(chan *Message)
+	go func() {
+		var m Message
+		for i := 0; i < msgLimit+10; i++ {
+			ch <- &m
+		}
+		ch <- &Message{Kind: "end"}
+	}()
+
+	kr := make(killRecorder)
+	n := 0
+	for m := range limiter(ch, kr) {
+		n++
+		if n > msgLimit && m.Kind != "end" {
+			t.Errorf("received non-end message after limit")
+		}
+	}
+	if n != msgLimit+1 {
+		t.Errorf("received %v messages, want %v", n, msgLimit+1)
+	}
+	select {
+	case <-kr:
+	case <-time.After(100 * time.Millisecond):
+		t.Errorf("process wasn't killed after reaching limit")
+	}
+}
diff --git a/go/src/golang.org/x/tools/present/background.go b/go/src/golang.org/x/tools/present/background.go
new file mode 100644
index 0000000..0a6216a
--- /dev/null
+++ b/go/src/golang.org/x/tools/present/background.go
@@ -0,0 +1,25 @@
+// Copyright 2016 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 present
+
+import (
+	"strings"
+)
+
+func init() {
+	Register("background", parseBackground)
+}
+
+type Background struct {
+	URL string
+}
+
+func (i Background) TemplateName() string { return "background" }
+
+func parseBackground(ctx *Context, fileName string, lineno int, text string) (Elem, error) {
+	args := strings.Fields(text)
+	background := Background{URL: args[1]}
+	return background, nil
+}
diff --git a/go/src/golang.org/x/tools/present/doc.go b/go/src/golang.org/x/tools/present/doc.go
index 584e0c1..351c581 100644
--- a/go/src/golang.org/x/tools/present/doc.go
+++ b/go/src/golang.org/x/tools/present/doc.go
@@ -58,6 +58,7 @@
 	.code x.go /^func main/,/^}/
 	.play y.go
 	.image image.jpg
+	.background image.jpg
 	.iframe http://foo
 	.link http://foo label
 	.html file.html
@@ -177,6 +178,28 @@
 
 	.image images/janet.jpg _ 300
 
+video:
+
+The template uses the function "video" to inject video files.
+
+The syntax is simple: 2 or 4 space-separated arguments.
+The first argument is always the file name.
+The second argument is always the file content-type.
+If there are more arguments, they are the height and width;
+both must be present, or substituted with an underscore.
+Replacing a dimension argument with the underscore parameter
+preserves the aspect ratio of the video when scaling.
+
+	.video videos/evangeline.mp4 video/mp4 400 600
+
+	.video videos/mabel.ogg video/ogg 500 _
+
+background:
+
+The template uses the function "background" to set the background image for
+a slide.  The only argument is the file name of the image.
+
+	.background images/susan.jpg
 
 caption:
 
diff --git a/go/src/golang.org/x/tools/present/parse.go b/go/src/golang.org/x/tools/present/parse.go
index 449d5ed..034a83c 100644
--- a/go/src/golang.org/x/tools/present/parse.go
+++ b/go/src/golang.org/x/tools/present/parse.go
@@ -362,6 +362,7 @@
 				var l []string
 				for ok && strings.TrimSpace(text) != "" {
 					if text[0] == '.' { // Command breaks text block.
+						lines.back()
 						break
 					}
 					if strings.HasPrefix(text, `\.`) { // Backslash escapes initial period.
diff --git a/go/src/golang.org/x/tools/present/video.go b/go/src/golang.org/x/tools/present/video.go
new file mode 100644
index 0000000..913822e
--- /dev/null
+++ b/go/src/golang.org/x/tools/present/video.go
@@ -0,0 +1,51 @@
+// Copyright 2016 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 present
+
+import (
+	"fmt"
+	"strings"
+)
+
+func init() {
+	Register("video", parseVideo)
+}
+
+type Video struct {
+	URL        string
+	SourceType string
+	Width      int
+	Height     int
+}
+
+func (v Video) TemplateName() string { return "video" }
+
+func parseVideo(ctx *Context, fileName string, lineno int, text string) (Elem, error) {
+	args := strings.Fields(text)
+	vid := Video{URL: args[1], SourceType: args[2]}
+	a, err := parseArgs(fileName, lineno, args[3:])
+	if err != nil {
+		return nil, err
+	}
+	switch len(a) {
+	case 0:
+		// no size parameters
+	case 2:
+		// If a parameter is empty (underscore) or invalid
+		// leave the field set to zero. The "video" action
+		// template will then omit that vid tag attribute and
+		// the browser will calculate the value to preserve
+		// the aspect ratio.
+		if v, ok := a[0].(int); ok {
+			vid.Height = v
+		}
+		if v, ok := a[1].(int); ok {
+			vid.Width = v
+		}
+	default:
+		return nil, fmt.Errorf("incorrect video invocation: %q", text)
+	}
+	return vid, nil
+}
diff --git a/go/src/golang.org/x/tools/refactor/eg/eg.go b/go/src/golang.org/x/tools/refactor/eg/eg.go
index a609255..4d56824 100644
--- a/go/src/golang.org/x/tools/refactor/eg/eg.go
+++ b/go/src/golang.org/x/tools/refactor/eg/eg.go
@@ -1,3 +1,9 @@
+// Copyright 2014 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.
+
+// +build go1.5
+
 // Package eg implements the example-based refactoring tool whose
 // command-line is defined in golang.org/x/tools/cmd/eg.
 package eg // import "golang.org/x/tools/refactor/eg"
@@ -9,10 +15,8 @@
 	"go/format"
 	"go/printer"
 	"go/token"
+	"go/types"
 	"os"
-
-	"golang.org/x/tools/go/loader"
-	"golang.org/x/tools/go/types"
 )
 
 const Help = `
@@ -131,19 +135,13 @@
 match f'; (4) use eg to rename f' to f in all calls; (5) delete f'.
 `
 
-// TODO(adonovan): allow the tool to be invoked using relative package
-// directory names (./foo).  Requires changes to go/loader.
-
 // TODO(adonovan): expand upon the above documentation as an HTML page.
 
-// TODO(adonovan): eliminate dependency on loader.PackageInfo.
-// Move its TypeOf method into go/types.
-
 // A Transformer represents a single example-based transformation.
 type Transformer struct {
 	fset           *token.FileSet
 	verbose        bool
-	info           loader.PackageInfo // combined type info for template/input/output ASTs
+	info           *types.Info // combined type info for template/input/output ASTs
 	seenInfos      map[*types.Info]bool
 	wildcards      map[*types.Var]bool                // set of parameters in func before()
 	env            map[string]ast.Expr                // maps parameter name to wildcard binding
@@ -157,16 +155,17 @@
 }
 
 // NewTransformer returns a transformer based on the specified template,
-// a package containing "before" and "after" functions as described
-// in the package documentation.
+// a single-file package containing "before" and "after" functions as
+// described in the package documentation.
+// tmplInfo is the type information for tmplFile.
 //
-func NewTransformer(fset *token.FileSet, template *loader.PackageInfo, verbose bool) (*Transformer, error) {
+func NewTransformer(fset *token.FileSet, tmplPkg *types.Package, tmplFile *ast.File, tmplInfo *types.Info, verbose bool) (*Transformer, error) {
 	// Check the template.
-	beforeSig := funcSig(template.Pkg, "before")
+	beforeSig := funcSig(tmplPkg, "before")
 	if beforeSig == nil {
 		return nil, fmt.Errorf("no 'before' func found in template")
 	}
-	afterSig := funcSig(template.Pkg, "after")
+	afterSig := funcSig(tmplPkg, "after")
 	if afterSig == nil {
 		return nil, fmt.Errorf("no 'after' func found in template")
 	}
@@ -177,18 +176,17 @@
 			beforeSig, afterSig)
 	}
 
-	templateFile := template.Files[0]
-	for _, imp := range templateFile.Imports {
+	for _, imp := range tmplFile.Imports {
 		if imp.Name != nil && imp.Name.Name == "." {
 			// Dot imports are currently forbidden.  We
 			// make the simplifying assumption that all
 			// imports are regular, without local renames.
-			//TODO document
+			// TODO(adonovan): document
 			return nil, fmt.Errorf("dot-import (of %s) in template", imp.Path.Value)
 		}
 	}
 	var beforeDecl, afterDecl *ast.FuncDecl
-	for _, decl := range templateFile.Decls {
+	for _, decl := range tmplFile.Decls {
 		if decl, ok := decl.(*ast.FuncDecl); ok {
 			switch decl.Name.Name {
 			case "before":
@@ -228,8 +226,8 @@
 	// of the replacement.  (Consider the rule that array literal keys
 	// must be unique.)  So we cannot hope to prove the safety of a
 	// transformation in general.
-	Tb := template.TypeOf(before)
-	Ta := template.TypeOf(after)
+	Tb := tmplInfo.TypeOf(before)
+	Ta := tmplInfo.TypeOf(after)
 	if types.AssignableTo(Tb, Ta) {
 		// safe: replacement is assignable to pattern.
 	} else if tuple, ok := Tb.(*types.Tuple); ok && tuple.Len() == 0 {
@@ -253,19 +251,16 @@
 	// type info for the synthesized ASTs too.  This saves us
 	// having to book-keep where each ast.Node originated as we
 	// construct the resulting hybrid AST.
-	//
-	// TODO(adonovan): move type utility methods of PackageInfo to
-	// types.Info, or at least into go/types.typeutil.
-	tr.info.Info = types.Info{
+	tr.info = &types.Info{
 		Types:      make(map[ast.Expr]types.TypeAndValue),
 		Defs:       make(map[*ast.Ident]types.Object),
 		Uses:       make(map[*ast.Ident]types.Object),
 		Selections: make(map[*ast.SelectorExpr]*types.Selection),
 	}
-	mergeTypeInfo(&tr.info.Info, &template.Info)
+	mergeTypeInfo(tr.info, tmplInfo)
 
 	// Compute set of imported objects required by after().
-	// TODO reject dot-imports in pattern
+	// TODO(adonovan): reject dot-imports in pattern
 	ast.Inspect(after, func(n ast.Node) bool {
 		if n, ok := n.(*ast.SelectorExpr); ok {
 			if _, ok := tr.info.Selections[n]; !ok {
diff --git a/go/src/golang.org/x/tools/refactor/eg/eg14.go b/go/src/golang.org/x/tools/refactor/eg/eg14.go
new file mode 100644
index 0000000..d6790fe
--- /dev/null
+++ b/go/src/golang.org/x/tools/refactor/eg/eg14.go
@@ -0,0 +1,347 @@
+// Copyright 2014 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.
+
+// +build !go1.5
+
+// Package eg implements the example-based refactoring tool whose
+// command-line is defined in golang.org/x/tools/cmd/eg.
+package eg // import "golang.org/x/tools/refactor/eg"
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/format"
+	"go/printer"
+	"go/token"
+	"os"
+
+	"golang.org/x/tools/go/types"
+)
+
+const Help = `
+This tool implements example-based refactoring of expressions.
+
+The transformation is specified as a Go file defining two functions,
+'before' and 'after', of identical types.  Each function body consists
+of a single statement: either a return statement with a single
+(possibly multi-valued) expression, or an expression statement.  The
+'before' expression specifies a pattern and the 'after' expression its
+replacement.
+
+	package P
+ 	import ( "errors"; "fmt" )
+ 	func before(s string) error { return fmt.Errorf("%s", s) }
+ 	func after(s string)  error { return errors.New(s) }
+
+The expression statement form is useful when the expression has no
+result, for example:
+
+ 	func before(msg string) { log.Fatalf("%s", msg) }
+ 	func after(msg string)  { log.Fatal(msg) }
+
+The parameters of both functions are wildcards that may match any
+expression assignable to that type.  If the pattern contains multiple
+occurrences of the same parameter, each must match the same expression
+in the input for the pattern to match.  If the replacement contains
+multiple occurrences of the same parameter, the expression will be
+duplicated, possibly changing the side-effects.
+
+The tool analyses all Go code in the packages specified by the
+arguments, replacing all occurrences of the pattern with the
+substitution.
+
+So, the transform above would change this input:
+	err := fmt.Errorf("%s", "error: " + msg)
+to this output:
+	err := errors.New("error: " + msg)
+
+Identifiers, including qualified identifiers (p.X) are considered to
+match only if they denote the same object.  This allows correct
+matching even in the presence of dot imports, named imports and
+locally shadowed package names in the input program.
+
+Matching of type syntax is semantic, not syntactic: type syntax in the
+pattern matches type syntax in the input if the types are identical.
+Thus, func(x int) matches func(y int).
+
+This tool was inspired by other example-based refactoring tools,
+'gofmt -r' for Go and Refaster for Java.
+
+
+LIMITATIONS
+===========
+
+EXPRESSIVENESS
+
+Only refactorings that replace one expression with another, regardless
+of the expression's context, may be expressed.  Refactoring arbitrary
+statements (or sequences of statements) is a less well-defined problem
+and is less amenable to this approach.
+
+A pattern that contains a function literal (and hence statements)
+never matches.
+
+There is no way to generalize over related types, e.g. to express that
+a wildcard may have any integer type, for example.
+
+It is not possible to replace an expression by one of a different
+type, even in contexts where this is legal, such as x in fmt.Print(x).
+
+The struct literals T{x} and T{K: x} cannot both be matched by a single
+template.
+
+
+SAFETY
+
+Verifying that a transformation does not introduce type errors is very
+complex in the general case.  An innocuous-looking replacement of one
+constant by another (e.g. 1 to 2) may cause type errors relating to
+array types and indices, for example.  The tool performs only very
+superficial checks of type preservation.
+
+
+IMPORTS
+
+Although the matching algorithm is fully aware of scoping rules, the
+replacement algorithm is not, so the replacement code may contain
+incorrect identifier syntax for imported objects if there are dot
+imports, named imports or locally shadowed package names in the input
+program.
+
+Imports are added as needed, but they are not removed as needed.
+Run 'goimports' on the modified file for now.
+
+Dot imports are forbidden in the template.
+
+
+TIPS
+====
+
+Sometimes a little creativity is required to implement the desired
+migration.  This section lists a few tips and tricks.
+
+To remove the final parameter from a function, temporarily change the
+function signature so that the final parameter is variadic, as this
+allows legal calls both with and without the argument.  Then use eg to
+remove the final argument from all callers, and remove the variadic
+parameter by hand.  The reverse process can be used to add a final
+parameter.
+
+To add or remove parameters other than the final one, you must do it in
+stages: (1) declare a variant function f' with a different name and the
+desired parameters; (2) use eg to transform calls to f into calls to f',
+changing the arguments as needed; (3) change the declaration of f to
+match f'; (4) use eg to rename f' to f in all calls; (5) delete f'.
+`
+
+// TODO(adonovan): expand upon the above documentation as an HTML page.
+
+// A Transformer represents a single example-based transformation.
+type Transformer struct {
+	fset           *token.FileSet
+	verbose        bool
+	info           *types.Info // combined type info for template/input/output ASTs
+	seenInfos      map[*types.Info]bool
+	wildcards      map[*types.Var]bool                // set of parameters in func before()
+	env            map[string]ast.Expr                // maps parameter name to wildcard binding
+	importedObjs   map[types.Object]*ast.SelectorExpr // objects imported by after().
+	before, after  ast.Expr
+	allowWildcards bool
+
+	// Working state of Transform():
+	nsubsts    int            // number of substitutions made
+	currentPkg *types.Package // package of current call
+}
+
+// NewTransformer returns a transformer based on the specified template,
+// a single-file package containing "before" and "after" functions as
+// described in the package documentation.
+// tmplInfo is the type information for tmplFile.
+//
+func NewTransformer(fset *token.FileSet, tmplPkg *types.Package, tmplFile *ast.File, tmplInfo *types.Info, verbose bool) (*Transformer, error) {
+	// Check the template.
+	beforeSig := funcSig(tmplPkg, "before")
+	if beforeSig == nil {
+		return nil, fmt.Errorf("no 'before' func found in template")
+	}
+	afterSig := funcSig(tmplPkg, "after")
+	if afterSig == nil {
+		return nil, fmt.Errorf("no 'after' func found in template")
+	}
+
+	// TODO(adonovan): should we also check the names of the params match?
+	if !types.Identical(afterSig, beforeSig) {
+		return nil, fmt.Errorf("before %s and after %s functions have different signatures",
+			beforeSig, afterSig)
+	}
+
+	for _, imp := range tmplFile.Imports {
+		if imp.Name != nil && imp.Name.Name == "." {
+			// Dot imports are currently forbidden.  We
+			// make the simplifying assumption that all
+			// imports are regular, without local renames.
+			// TODO(adonovan): document
+			return nil, fmt.Errorf("dot-import (of %s) in template", imp.Path.Value)
+		}
+	}
+	var beforeDecl, afterDecl *ast.FuncDecl
+	for _, decl := range tmplFile.Decls {
+		if decl, ok := decl.(*ast.FuncDecl); ok {
+			switch decl.Name.Name {
+			case "before":
+				beforeDecl = decl
+			case "after":
+				afterDecl = decl
+			}
+		}
+	}
+
+	before, err := soleExpr(beforeDecl)
+	if err != nil {
+		return nil, fmt.Errorf("before: %s", err)
+	}
+	after, err := soleExpr(afterDecl)
+	if err != nil {
+		return nil, fmt.Errorf("after: %s", err)
+	}
+
+	wildcards := make(map[*types.Var]bool)
+	for i := 0; i < beforeSig.Params().Len(); i++ {
+		wildcards[beforeSig.Params().At(i)] = true
+	}
+
+	// checkExprTypes returns an error if Tb (type of before()) is not
+	// safe to replace with Ta (type of after()).
+	//
+	// Only superficial checks are performed, and they may result in both
+	// false positives and negatives.
+	//
+	// Ideally, we would only require that the replacement be assignable
+	// to the context of a specific pattern occurrence, but the type
+	// checker doesn't record that information and it's complex to deduce.
+	// A Go type cannot capture all the constraints of a given expression
+	// context, which may include the size, constness, signedness,
+	// namedness or constructor of its type, and even the specific value
+	// of the replacement.  (Consider the rule that array literal keys
+	// must be unique.)  So we cannot hope to prove the safety of a
+	// transformation in general.
+	Tb := tmplInfo.TypeOf(before)
+	Ta := tmplInfo.TypeOf(after)
+	if types.AssignableTo(Tb, Ta) {
+		// safe: replacement is assignable to pattern.
+	} else if tuple, ok := Tb.(*types.Tuple); ok && tuple.Len() == 0 {
+		// safe: pattern has void type (must appear in an ExprStmt).
+	} else {
+		return nil, fmt.Errorf("%s is not a safe replacement for %s", Ta, Tb)
+	}
+
+	tr := &Transformer{
+		fset:           fset,
+		verbose:        verbose,
+		wildcards:      wildcards,
+		allowWildcards: true,
+		seenInfos:      make(map[*types.Info]bool),
+		importedObjs:   make(map[types.Object]*ast.SelectorExpr),
+		before:         before,
+		after:          after,
+	}
+
+	// Combine type info from the template and input packages, and
+	// type info for the synthesized ASTs too.  This saves us
+	// having to book-keep where each ast.Node originated as we
+	// construct the resulting hybrid AST.
+	tr.info = &types.Info{
+		Types:      make(map[ast.Expr]types.TypeAndValue),
+		Defs:       make(map[*ast.Ident]types.Object),
+		Uses:       make(map[*ast.Ident]types.Object),
+		Selections: make(map[*ast.SelectorExpr]*types.Selection),
+	}
+	mergeTypeInfo(tr.info, tmplInfo)
+
+	// Compute set of imported objects required by after().
+	// TODO(adonovan): reject dot-imports in pattern
+	ast.Inspect(after, func(n ast.Node) bool {
+		if n, ok := n.(*ast.SelectorExpr); ok {
+			if _, ok := tr.info.Selections[n]; !ok {
+				// qualified ident
+				obj := tr.info.Uses[n.Sel]
+				tr.importedObjs[obj] = n
+				return false // prune
+			}
+		}
+		return true // recur
+	})
+
+	return tr, nil
+}
+
+// WriteAST is a convenience function that writes AST f to the specified file.
+func WriteAST(fset *token.FileSet, filename string, f *ast.File) (err error) {
+	fh, err := os.Create(filename)
+	if err != nil {
+		return err
+	}
+	defer func() {
+		if err2 := fh.Close(); err != nil {
+			err = err2 // prefer earlier error
+		}
+	}()
+	return format.Node(fh, fset, f)
+}
+
+// -- utilities --------------------------------------------------------
+
+// funcSig returns the signature of the specified package-level function.
+func funcSig(pkg *types.Package, name string) *types.Signature {
+	if f, ok := pkg.Scope().Lookup(name).(*types.Func); ok {
+		return f.Type().(*types.Signature)
+	}
+	return nil
+}
+
+// soleExpr returns the sole expression in the before/after template function.
+func soleExpr(fn *ast.FuncDecl) (ast.Expr, error) {
+	if fn.Body == nil {
+		return nil, fmt.Errorf("no body")
+	}
+	if len(fn.Body.List) != 1 {
+		return nil, fmt.Errorf("must contain a single statement")
+	}
+	switch stmt := fn.Body.List[0].(type) {
+	case *ast.ReturnStmt:
+		if len(stmt.Results) != 1 {
+			return nil, fmt.Errorf("return statement must have a single operand")
+		}
+		return stmt.Results[0], nil
+
+	case *ast.ExprStmt:
+		return stmt.X, nil
+	}
+
+	return nil, fmt.Errorf("must contain a single return or expression statement")
+}
+
+// mergeTypeInfo adds type info from src to dst.
+func mergeTypeInfo(dst, src *types.Info) {
+	for k, v := range src.Types {
+		dst.Types[k] = v
+	}
+	for k, v := range src.Defs {
+		dst.Defs[k] = v
+	}
+	for k, v := range src.Uses {
+		dst.Uses[k] = v
+	}
+	for k, v := range src.Selections {
+		dst.Selections[k] = v
+	}
+}
+
+// (debugging only)
+func astString(fset *token.FileSet, n ast.Node) string {
+	var buf bytes.Buffer
+	printer.Fprint(&buf, fset, n)
+	return buf.String()
+}
diff --git a/go/src/golang.org/x/tools/refactor/eg/eg14_test.go b/go/src/golang.org/x/tools/refactor/eg/eg14_test.go
new file mode 100644
index 0000000..814383e
--- /dev/null
+++ b/go/src/golang.org/x/tools/refactor/eg/eg14_test.go
@@ -0,0 +1,162 @@
+// Copyright 2014 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.
+
+// +build !go1.5
+
+// No testdata on Android.
+
+// +build !android
+
+package eg_test
+
+import (
+	"bytes"
+	"flag"
+	"go/parser"
+	"go/token"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"runtime"
+	"strings"
+	"testing"
+
+	"golang.org/x/tools/go/exact"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/refactor/eg"
+)
+
+// TODO(adonovan): more tests:
+// - of command-line tool
+// - of all parts of syntax
+// - of applying a template to a package it imports:
+//   the replacement syntax should use unqualified names for its objects.
+
+var (
+	updateFlag  = flag.Bool("update", false, "update the golden files")
+	verboseFlag = flag.Bool("verbose", false, "show matcher information")
+)
+
+func Test(t *testing.T) {
+	switch runtime.GOOS {
+	case "windows":
+		t.Skipf("skipping test on %q (no /usr/bin/diff)", runtime.GOOS)
+	}
+
+	conf := loader.Config{
+		Fset:       token.NewFileSet(),
+		ParserMode: parser.ParseComments,
+	}
+
+	// Each entry is a single-file package.
+	// (Multi-file packages aren't interesting for this test.)
+	// Order matters: each non-template package is processed using
+	// the preceding template package.
+	for _, filename := range []string{
+		"testdata/A.template",
+		"testdata/A1.go",
+		"testdata/A2.go",
+
+		"testdata/B.template",
+		"testdata/B1.go",
+
+		"testdata/C.template",
+		"testdata/C1.go",
+
+		"testdata/D.template",
+		"testdata/D1.go",
+
+		"testdata/E.template",
+		"testdata/E1.go",
+
+		"testdata/F.template",
+		"testdata/F1.go",
+
+		"testdata/G.template",
+		"testdata/G1.go",
+
+		"testdata/H.template",
+		"testdata/H1.go",
+
+		"testdata/bad_type.template",
+		"testdata/no_before.template",
+		"testdata/no_after_return.template",
+		"testdata/type_mismatch.template",
+		"testdata/expr_type_mismatch.template",
+	} {
+		pkgname := strings.TrimSuffix(filepath.Base(filename), ".go")
+		conf.CreateFromFilenames(pkgname, filename)
+	}
+	iprog, err := conf.Load()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	var xform *eg.Transformer
+	for _, info := range iprog.Created {
+		file := info.Files[0]
+		filename := iprog.Fset.File(file.Pos()).Name() // foo.go
+
+		if strings.HasSuffix(filename, "template") {
+			// a new template
+			shouldFail, _ := info.Pkg.Scope().Lookup("shouldFail").(*types.Const)
+			xform, err = eg.NewTransformer(iprog.Fset, info.Pkg, file, &info.Info, *verboseFlag)
+			if err != nil {
+				if shouldFail == nil {
+					t.Errorf("NewTransformer(%s): %s", filename, err)
+				} else if want := exact.StringVal(shouldFail.Val()); !strings.Contains(err.Error(), want) {
+					t.Errorf("NewTransformer(%s): got error %q, want error %q", filename, err, want)
+				}
+			} else if shouldFail != nil {
+				t.Errorf("NewTransformer(%s) succeeded unexpectedly; want error %q",
+					filename, shouldFail.Val())
+			}
+			continue
+		}
+
+		if xform == nil {
+			t.Errorf("%s: no previous template", filename)
+			continue
+		}
+
+		// apply previous template to this package
+		n := xform.Transform(&info.Info, info.Pkg, file)
+		if n == 0 {
+			t.Errorf("%s: no matches", filename)
+			continue
+		}
+
+		got := filename + "t"       // foo.got
+		golden := filename + "lden" // foo.golden
+
+		// Write actual output to foo.got.
+		if err := eg.WriteAST(iprog.Fset, got, file); err != nil {
+			t.Error(err)
+		}
+		defer os.Remove(got)
+
+		// Compare foo.got with foo.golden.
+		var cmd *exec.Cmd
+		switch runtime.GOOS {
+		case "plan9":
+			cmd = exec.Command("/bin/diff", "-c", golden, got)
+		default:
+			cmd = exec.Command("/usr/bin/diff", "-u", golden, got)
+		}
+		buf := new(bytes.Buffer)
+		cmd.Stdout = buf
+		cmd.Stderr = os.Stderr
+		if err := cmd.Run(); err != nil {
+			t.Errorf("eg tests for %s failed: %s.\n%s\n", filename, err, buf)
+
+			if *updateFlag {
+				t.Logf("Updating %s...", golden)
+				if err := exec.Command("/bin/cp", got, golden).Run(); err != nil {
+					t.Errorf("Update failed: %s", err)
+				}
+			}
+		}
+	}
+}
diff --git a/go/src/golang.org/x/tools/refactor/eg/eg_test.go b/go/src/golang.org/x/tools/refactor/eg/eg_test.go
index 295e842..c259920 100644
--- a/go/src/golang.org/x/tools/refactor/eg/eg_test.go
+++ b/go/src/golang.org/x/tools/refactor/eg/eg_test.go
@@ -1,7 +1,9 @@
-// Copyright 2015 The Go Authors. All rights reserved.
+// Copyright 2014 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.
 
+// +build go1.5
+
 // No testdata on Android.
 
 // +build !android
@@ -11,8 +13,10 @@
 import (
 	"bytes"
 	"flag"
+	exact "go/constant"
 	"go/parser"
 	"go/token"
+	"go/types"
 	"os"
 	"os/exec"
 	"path/filepath"
@@ -20,9 +24,7 @@
 	"strings"
 	"testing"
 
-	"golang.org/x/tools/go/exact"
 	"golang.org/x/tools/go/loader"
-	"golang.org/x/tools/go/types"
 	"golang.org/x/tools/refactor/eg"
 )
 
@@ -100,7 +102,7 @@
 		if strings.HasSuffix(filename, "template") {
 			// a new template
 			shouldFail, _ := info.Pkg.Scope().Lookup("shouldFail").(*types.Const)
-			xform, err = eg.NewTransformer(iprog.Fset, info, *verboseFlag)
+			xform, err = eg.NewTransformer(iprog.Fset, info.Pkg, file, &info.Info, *verboseFlag)
 			if err != nil {
 				if shouldFail == nil {
 					t.Errorf("NewTransformer(%s): %s", filename, err)
diff --git a/go/src/golang.org/x/tools/refactor/eg/match.go b/go/src/golang.org/x/tools/refactor/eg/match.go
index d8590d4..8d989bc 100644
--- a/go/src/golang.org/x/tools/refactor/eg/match.go
+++ b/go/src/golang.org/x/tools/refactor/eg/match.go
@@ -1,17 +1,22 @@
+// Copyright 2014 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.
+
+// +build go1.5
+
 package eg
 
 import (
 	"fmt"
 	"go/ast"
 	"go/token"
+	"go/types"
 	"log"
 	"os"
 	"reflect"
 
 	"golang.org/x/tools/go/ast/astutil"
 	"golang.org/x/tools/go/exact"
-	"golang.org/x/tools/go/loader"
-	"golang.org/x/tools/go/types"
 )
 
 // matchExpr reports whether pattern x matches y.
@@ -42,8 +47,8 @@
 
 	// Object identifiers (including pkg-qualified ones)
 	// are handled semantically, not syntactically.
-	xobj := isRef(x, &tr.info)
-	yobj := isRef(y, &tr.info)
+	xobj := isRef(x, tr.info)
+	yobj := isRef(y, tr.info)
 	if xobj != nil {
 		return xobj == yobj
 	}
@@ -231,7 +236,7 @@
 
 // isRef returns the object referred to by this (possibly qualified)
 // identifier, or nil if the node is not a referring identifier.
-func isRef(n ast.Node, info *loader.PackageInfo) types.Object {
+func isRef(n ast.Node, info *types.Info) types.Object {
 	switch n := n.(type) {
 	case *ast.Ident:
 		return info.Uses[n]
diff --git a/go/src/golang.org/x/tools/refactor/eg/match14.go b/go/src/golang.org/x/tools/refactor/eg/match14.go
new file mode 100644
index 0000000..10b84ab
--- /dev/null
+++ b/go/src/golang.org/x/tools/refactor/eg/match14.go
@@ -0,0 +1,251 @@
+// Copyright 2014 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.
+
+// +build !go1.5
+
+package eg
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"log"
+	"os"
+	"reflect"
+
+	"golang.org/x/tools/go/ast/astutil"
+	"golang.org/x/tools/go/exact"
+	"golang.org/x/tools/go/types"
+)
+
+// matchExpr reports whether pattern x matches y.
+//
+// If tr.allowWildcards, Idents in x that refer to parameters are
+// treated as wildcards, and match any y that is assignable to the
+// parameter type; matchExpr records this correspondence in tr.env.
+// Otherwise, matchExpr simply reports whether the two trees are
+// equivalent.
+//
+// A wildcard appearing more than once in the pattern must
+// consistently match the same tree.
+//
+func (tr *Transformer) matchExpr(x, y ast.Expr) bool {
+	if x == nil && y == nil {
+		return true
+	}
+	if x == nil || y == nil {
+		return false
+	}
+	x = unparen(x)
+	y = unparen(y)
+
+	// Is x a wildcard?  (a reference to a 'before' parameter)
+	if xobj, ok := tr.wildcardObj(x); ok {
+		return tr.matchWildcard(xobj, y)
+	}
+
+	// Object identifiers (including pkg-qualified ones)
+	// are handled semantically, not syntactically.
+	xobj := isRef(x, tr.info)
+	yobj := isRef(y, tr.info)
+	if xobj != nil {
+		return xobj == yobj
+	}
+	if yobj != nil {
+		return false
+	}
+
+	// TODO(adonovan): audit: we cannot assume these ast.Exprs
+	// contain non-nil pointers.  e.g. ImportSpec.Name may be a
+	// nil *ast.Ident.
+
+	if reflect.TypeOf(x) != reflect.TypeOf(y) {
+		return false
+	}
+	switch x := x.(type) {
+	case *ast.Ident:
+		log.Fatalf("unexpected Ident: %s", astString(tr.fset, x))
+
+	case *ast.BasicLit:
+		y := y.(*ast.BasicLit)
+		xval := exact.MakeFromLiteral(x.Value, x.Kind)
+		yval := exact.MakeFromLiteral(y.Value, y.Kind)
+		return exact.Compare(xval, token.EQL, yval)
+
+	case *ast.FuncLit:
+		// func literals (and thus statement syntax) never match.
+		return false
+
+	case *ast.CompositeLit:
+		y := y.(*ast.CompositeLit)
+		return (x.Type == nil) == (y.Type == nil) &&
+			(x.Type == nil || tr.matchType(x.Type, y.Type)) &&
+			tr.matchExprs(x.Elts, y.Elts)
+
+	case *ast.SelectorExpr:
+		y := y.(*ast.SelectorExpr)
+		return tr.matchSelectorExpr(x, y) &&
+			tr.info.Selections[x].Obj() == tr.info.Selections[y].Obj()
+
+	case *ast.IndexExpr:
+		y := y.(*ast.IndexExpr)
+		return tr.matchExpr(x.X, y.X) &&
+			tr.matchExpr(x.Index, y.Index)
+
+	case *ast.SliceExpr:
+		y := y.(*ast.SliceExpr)
+		return tr.matchExpr(x.X, y.X) &&
+			tr.matchExpr(x.Low, y.Low) &&
+			tr.matchExpr(x.High, y.High) &&
+			tr.matchExpr(x.Max, y.Max) &&
+			x.Slice3 == y.Slice3
+
+	case *ast.TypeAssertExpr:
+		y := y.(*ast.TypeAssertExpr)
+		return tr.matchExpr(x.X, y.X) &&
+			tr.matchType(x.Type, y.Type)
+
+	case *ast.CallExpr:
+		y := y.(*ast.CallExpr)
+		match := tr.matchExpr // function call
+		if tr.info.Types[x.Fun].IsType() {
+			match = tr.matchType // type conversion
+		}
+		return x.Ellipsis.IsValid() == y.Ellipsis.IsValid() &&
+			match(x.Fun, y.Fun) &&
+			tr.matchExprs(x.Args, y.Args)
+
+	case *ast.StarExpr:
+		y := y.(*ast.StarExpr)
+		return tr.matchExpr(x.X, y.X)
+
+	case *ast.UnaryExpr:
+		y := y.(*ast.UnaryExpr)
+		return x.Op == y.Op &&
+			tr.matchExpr(x.X, y.X)
+
+	case *ast.BinaryExpr:
+		y := y.(*ast.BinaryExpr)
+		return x.Op == y.Op &&
+			tr.matchExpr(x.X, y.X) &&
+			tr.matchExpr(x.Y, y.Y)
+
+	case *ast.KeyValueExpr:
+		y := y.(*ast.KeyValueExpr)
+		return tr.matchExpr(x.Key, y.Key) &&
+			tr.matchExpr(x.Value, y.Value)
+	}
+
+	panic(fmt.Sprintf("unhandled AST node type: %T", x))
+}
+
+func (tr *Transformer) matchExprs(xx, yy []ast.Expr) bool {
+	if len(xx) != len(yy) {
+		return false
+	}
+	for i := range xx {
+		if !tr.matchExpr(xx[i], yy[i]) {
+			return false
+		}
+	}
+	return true
+}
+
+// matchType reports whether the two type ASTs denote identical types.
+func (tr *Transformer) matchType(x, y ast.Expr) bool {
+	tx := tr.info.Types[x].Type
+	ty := tr.info.Types[y].Type
+	return types.Identical(tx, ty)
+}
+
+func (tr *Transformer) wildcardObj(x ast.Expr) (*types.Var, bool) {
+	if x, ok := x.(*ast.Ident); ok && x != nil && tr.allowWildcards {
+		if xobj, ok := tr.info.Uses[x].(*types.Var); ok && tr.wildcards[xobj] {
+			return xobj, true
+		}
+	}
+	return nil, false
+}
+
+func (tr *Transformer) matchSelectorExpr(x, y *ast.SelectorExpr) bool {
+	if xobj, ok := tr.wildcardObj(x.X); ok {
+		field := x.Sel.Name
+		yt := tr.info.TypeOf(y.X)
+		o, _, _ := types.LookupFieldOrMethod(yt, true, tr.currentPkg, field)
+		if o != nil {
+			tr.env[xobj.Name()] = y.X // record binding
+			return true
+		}
+	}
+	return tr.matchExpr(x.X, y.X)
+}
+
+func (tr *Transformer) matchWildcard(xobj *types.Var, y ast.Expr) bool {
+	name := xobj.Name()
+
+	if tr.verbose {
+		fmt.Fprintf(os.Stderr, "%s: wildcard %s -> %s?: ",
+			tr.fset.Position(y.Pos()), name, astString(tr.fset, y))
+	}
+
+	// Check that y is assignable to the declared type of the param.
+	yt := tr.info.TypeOf(y)
+	if yt == nil {
+		// y has no type.
+		// Perhaps it is an *ast.Ellipsis in [...]T{}, or
+		// an *ast.KeyValueExpr in T{k: v}.
+		// Clearly these pseudo-expressions cannot match a
+		// wildcard, but it would nice if we had a way to ignore
+		// the difference between T{v} and T{k:v} for structs.
+		return false
+	}
+	if !types.AssignableTo(yt, xobj.Type()) {
+		if tr.verbose {
+			fmt.Fprintf(os.Stderr, "%s not assignable to %s\n", yt, xobj.Type())
+		}
+		return false
+	}
+
+	// A wildcard matches any expression.
+	// If it appears multiple times in the pattern, it must match
+	// the same expression each time.
+	if old, ok := tr.env[name]; ok {
+		// found existing binding
+		tr.allowWildcards = false
+		r := tr.matchExpr(old, y)
+		if tr.verbose {
+			fmt.Fprintf(os.Stderr, "%t secondary match, primary was %s\n",
+				r, astString(tr.fset, old))
+		}
+		tr.allowWildcards = true
+		return r
+	}
+
+	if tr.verbose {
+		fmt.Fprintf(os.Stderr, "primary match\n")
+	}
+
+	tr.env[name] = y // record binding
+	return true
+}
+
+// -- utilities --------------------------------------------------------
+
+func unparen(e ast.Expr) ast.Expr { return astutil.Unparen(e) }
+
+// isRef returns the object referred to by this (possibly qualified)
+// identifier, or nil if the node is not a referring identifier.
+func isRef(n ast.Node, info *types.Info) types.Object {
+	switch n := n.(type) {
+	case *ast.Ident:
+		return info.Uses[n]
+
+	case *ast.SelectorExpr:
+		if _, ok := info.Selections[n]; !ok {
+			// qualified ident
+			return info.Uses[n.Sel]
+		}
+	}
+	return nil
+}
diff --git a/go/src/golang.org/x/tools/refactor/eg/rewrite.go b/go/src/golang.org/x/tools/refactor/eg/rewrite.go
index db9c693..d91a99c 100644
--- a/go/src/golang.org/x/tools/refactor/eg/rewrite.go
+++ b/go/src/golang.org/x/tools/refactor/eg/rewrite.go
@@ -1,3 +1,9 @@
+// Copyright 2014 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.
+
+// +build go1.5
+
 package eg
 
 // This file defines the AST rewriting pass.
@@ -8,6 +14,7 @@
 	"fmt"
 	"go/ast"
 	"go/token"
+	"go/types"
 	"os"
 	"reflect"
 	"sort"
@@ -15,7 +22,6 @@
 	"strings"
 
 	"golang.org/x/tools/go/ast/astutil"
-	"golang.org/x/tools/go/types"
 )
 
 // Transform applies the transformation to the specified parsed file,
@@ -31,7 +37,7 @@
 func (tr *Transformer) Transform(info *types.Info, pkg *types.Package, file *ast.File) int {
 	if !tr.seenInfos[info] {
 		tr.seenInfos[info] = true
-		mergeTypeInfo(&tr.info.Info, info)
+		mergeTypeInfo(tr.info, info)
 	}
 	tr.currentPkg = pkg
 	tr.nsubsts = 0
@@ -234,7 +240,7 @@
 	// denoted by unqualified identifiers.
 	//
 	if tr.importedObjs != nil && pattern.Type() == selectorExprType {
-		obj := isRef(pattern.Interface().(*ast.SelectorExpr), &tr.info)
+		obj := isRef(pattern.Interface().(*ast.SelectorExpr), tr.info)
 		if obj != nil {
 			if sel, ok := tr.importedObjs[obj]; ok {
 				var id ast.Expr
@@ -288,7 +294,7 @@
 		// All ast.Node implementations are *structs,
 		// so this case catches them all.
 		if e := rvToExpr(v); e != nil {
-			updateTypeInfo(&tr.info.Info, e, p.Interface().(ast.Expr))
+			updateTypeInfo(tr.info, e, p.Interface().(ast.Expr))
 		}
 		return v
 
diff --git a/go/src/golang.org/x/tools/refactor/eg/rewrite14.go b/go/src/golang.org/x/tools/refactor/eg/rewrite14.go
new file mode 100644
index 0000000..01b4fe2
--- /dev/null
+++ b/go/src/golang.org/x/tools/refactor/eg/rewrite14.go
@@ -0,0 +1,346 @@
+// Copyright 2014 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.
+
+// +build !go1.5
+
+package eg
+
+// This file defines the AST rewriting pass.
+// Most of it was plundered directly from
+// $GOROOT/src/cmd/gofmt/rewrite.go (after convergent evolution).
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"os"
+	"reflect"
+	"sort"
+	"strconv"
+	"strings"
+
+	"golang.org/x/tools/go/ast/astutil"
+	"golang.org/x/tools/go/types"
+)
+
+// Transform applies the transformation to the specified parsed file,
+// whose type information is supplied in info, and returns the number
+// of replacements that were made.
+//
+// It mutates the AST in place (the identity of the root node is
+// unchanged), and may add nodes for which no type information is
+// available in info.
+//
+// Derived from rewriteFile in $GOROOT/src/cmd/gofmt/rewrite.go.
+//
+func (tr *Transformer) Transform(info *types.Info, pkg *types.Package, file *ast.File) int {
+	if !tr.seenInfos[info] {
+		tr.seenInfos[info] = true
+		mergeTypeInfo(tr.info, info)
+	}
+	tr.currentPkg = pkg
+	tr.nsubsts = 0
+
+	if tr.verbose {
+		fmt.Fprintf(os.Stderr, "before: %s\n", astString(tr.fset, tr.before))
+		fmt.Fprintf(os.Stderr, "after: %s\n", astString(tr.fset, tr.after))
+	}
+
+	var f func(rv reflect.Value) reflect.Value
+	f = func(rv reflect.Value) reflect.Value {
+		// don't bother if val is invalid to start with
+		if !rv.IsValid() {
+			return reflect.Value{}
+		}
+
+		rv = apply(f, rv)
+
+		e := rvToExpr(rv)
+		if e != nil {
+			savedEnv := tr.env
+			tr.env = make(map[string]ast.Expr) // inefficient!  Use a slice of k/v pairs
+
+			if tr.matchExpr(tr.before, e) {
+				if tr.verbose {
+					fmt.Fprintf(os.Stderr, "%s matches %s",
+						astString(tr.fset, tr.before), astString(tr.fset, e))
+					if len(tr.env) > 0 {
+						fmt.Fprintf(os.Stderr, " with:")
+						for name, ast := range tr.env {
+							fmt.Fprintf(os.Stderr, " %s->%s",
+								name, astString(tr.fset, ast))
+						}
+					}
+					fmt.Fprintf(os.Stderr, "\n")
+				}
+				tr.nsubsts++
+
+				// Clone the replacement tree, performing parameter substitution.
+				// We update all positions to n.Pos() to aid comment placement.
+				rv = tr.subst(tr.env, reflect.ValueOf(tr.after),
+					reflect.ValueOf(e.Pos()))
+			}
+			tr.env = savedEnv
+		}
+
+		return rv
+	}
+	file2 := apply(f, reflect.ValueOf(file)).Interface().(*ast.File)
+
+	// By construction, the root node is unchanged.
+	if file != file2 {
+		panic("BUG")
+	}
+
+	// Add any necessary imports.
+	// TODO(adonovan): remove no-longer needed imports too.
+	if tr.nsubsts > 0 {
+		pkgs := make(map[string]*types.Package)
+		for obj := range tr.importedObjs {
+			pkgs[obj.Pkg().Path()] = obj.Pkg()
+		}
+
+		for _, imp := range file.Imports {
+			path, _ := strconv.Unquote(imp.Path.Value)
+			delete(pkgs, path)
+		}
+		delete(pkgs, pkg.Path()) // don't import self
+
+		// NB: AddImport may completely replace the AST!
+		// It thus renders info and tr.info no longer relevant to file.
+		var paths []string
+		for path := range pkgs {
+			paths = append(paths, path)
+		}
+		sort.Strings(paths)
+		for _, path := range paths {
+			astutil.AddImport(tr.fset, file, path)
+		}
+	}
+
+	tr.currentPkg = nil
+
+	return tr.nsubsts
+}
+
+// setValue is a wrapper for x.SetValue(y); it protects
+// the caller from panics if x cannot be changed to y.
+func setValue(x, y reflect.Value) {
+	// don't bother if y is invalid to start with
+	if !y.IsValid() {
+		return
+	}
+	defer func() {
+		if x := recover(); x != nil {
+			if s, ok := x.(string); ok &&
+				(strings.Contains(s, "type mismatch") || strings.Contains(s, "not assignable")) {
+				// x cannot be set to y - ignore this rewrite
+				return
+			}
+			panic(x)
+		}
+	}()
+	x.Set(y)
+}
+
+// Values/types for special cases.
+var (
+	objectPtrNil = reflect.ValueOf((*ast.Object)(nil))
+	scopePtrNil  = reflect.ValueOf((*ast.Scope)(nil))
+
+	identType        = reflect.TypeOf((*ast.Ident)(nil))
+	selectorExprType = reflect.TypeOf((*ast.SelectorExpr)(nil))
+	objectPtrType    = reflect.TypeOf((*ast.Object)(nil))
+	positionType     = reflect.TypeOf(token.NoPos)
+	callExprType     = reflect.TypeOf((*ast.CallExpr)(nil))
+	scopePtrType     = reflect.TypeOf((*ast.Scope)(nil))
+)
+
+// apply replaces each AST field x in val with f(x), returning val.
+// To avoid extra conversions, f operates on the reflect.Value form.
+func apply(f func(reflect.Value) reflect.Value, val reflect.Value) reflect.Value {
+	if !val.IsValid() {
+		return reflect.Value{}
+	}
+
+	// *ast.Objects introduce cycles and are likely incorrect after
+	// rewrite; don't follow them but replace with nil instead
+	if val.Type() == objectPtrType {
+		return objectPtrNil
+	}
+
+	// similarly for scopes: they are likely incorrect after a rewrite;
+	// replace them with nil
+	if val.Type() == scopePtrType {
+		return scopePtrNil
+	}
+
+	switch v := reflect.Indirect(val); v.Kind() {
+	case reflect.Slice:
+		for i := 0; i < v.Len(); i++ {
+			e := v.Index(i)
+			setValue(e, f(e))
+		}
+	case reflect.Struct:
+		for i := 0; i < v.NumField(); i++ {
+			e := v.Field(i)
+			setValue(e, f(e))
+		}
+	case reflect.Interface:
+		e := v.Elem()
+		setValue(v, f(e))
+	}
+	return val
+}
+
+// subst returns a copy of (replacement) pattern with values from env
+// substituted in place of wildcards and pos used as the position of
+// tokens from the pattern.  if env == nil, subst returns a copy of
+// pattern and doesn't change the line number information.
+func (tr *Transformer) subst(env map[string]ast.Expr, pattern, pos reflect.Value) reflect.Value {
+	if !pattern.IsValid() {
+		return reflect.Value{}
+	}
+
+	// *ast.Objects introduce cycles and are likely incorrect after
+	// rewrite; don't follow them but replace with nil instead
+	if pattern.Type() == objectPtrType {
+		return objectPtrNil
+	}
+
+	// similarly for scopes: they are likely incorrect after a rewrite;
+	// replace them with nil
+	if pattern.Type() == scopePtrType {
+		return scopePtrNil
+	}
+
+	// Wildcard gets replaced with map value.
+	if env != nil && pattern.Type() == identType {
+		id := pattern.Interface().(*ast.Ident)
+		if old, ok := env[id.Name]; ok {
+			return tr.subst(nil, reflect.ValueOf(old), reflect.Value{})
+		}
+	}
+
+	// Emit qualified identifiers in the pattern by appropriate
+	// (possibly qualified) identifier in the input.
+	//
+	// The template cannot contain dot imports, so all identifiers
+	// for imported objects are explicitly qualified.
+	//
+	// We assume (unsoundly) that there are no dot or named
+	// imports in the input code, nor are any imported package
+	// names shadowed, so the usual normal qualified identifier
+	// syntax may be used.
+	// TODO(adonovan): fix: avoid this assumption.
+	//
+	// A refactoring may be applied to a package referenced by the
+	// template.  Objects belonging to the current package are
+	// denoted by unqualified identifiers.
+	//
+	if tr.importedObjs != nil && pattern.Type() == selectorExprType {
+		obj := isRef(pattern.Interface().(*ast.SelectorExpr), tr.info)
+		if obj != nil {
+			if sel, ok := tr.importedObjs[obj]; ok {
+				var id ast.Expr
+				if obj.Pkg() == tr.currentPkg {
+					id = sel.Sel // unqualified
+				} else {
+					id = sel // pkg-qualified
+				}
+
+				// Return a clone of id.
+				saved := tr.importedObjs
+				tr.importedObjs = nil // break cycle
+				r := tr.subst(nil, reflect.ValueOf(id), pos)
+				tr.importedObjs = saved
+				return r
+			}
+		}
+	}
+
+	if pos.IsValid() && pattern.Type() == positionType {
+		// use new position only if old position was valid in the first place
+		if old := pattern.Interface().(token.Pos); !old.IsValid() {
+			return pattern
+		}
+		return pos
+	}
+
+	// Otherwise copy.
+	switch p := pattern; p.Kind() {
+	case reflect.Slice:
+		v := reflect.MakeSlice(p.Type(), p.Len(), p.Len())
+		for i := 0; i < p.Len(); i++ {
+			v.Index(i).Set(tr.subst(env, p.Index(i), pos))
+		}
+		return v
+
+	case reflect.Struct:
+		v := reflect.New(p.Type()).Elem()
+		for i := 0; i < p.NumField(); i++ {
+			v.Field(i).Set(tr.subst(env, p.Field(i), pos))
+		}
+		return v
+
+	case reflect.Ptr:
+		v := reflect.New(p.Type()).Elem()
+		if elem := p.Elem(); elem.IsValid() {
+			v.Set(tr.subst(env, elem, pos).Addr())
+		}
+
+		// Duplicate type information for duplicated ast.Expr.
+		// All ast.Node implementations are *structs,
+		// so this case catches them all.
+		if e := rvToExpr(v); e != nil {
+			updateTypeInfo(tr.info, e, p.Interface().(ast.Expr))
+		}
+		return v
+
+	case reflect.Interface:
+		v := reflect.New(p.Type()).Elem()
+		if elem := p.Elem(); elem.IsValid() {
+			v.Set(tr.subst(env, elem, pos))
+		}
+		return v
+	}
+
+	return pattern
+}
+
+// -- utilities -------------------------------------------------------
+
+func rvToExpr(rv reflect.Value) ast.Expr {
+	if rv.CanInterface() {
+		if e, ok := rv.Interface().(ast.Expr); ok {
+			return e
+		}
+	}
+	return nil
+}
+
+// updateTypeInfo duplicates type information for the existing AST old
+// so that it also applies to duplicated AST new.
+func updateTypeInfo(info *types.Info, new, old ast.Expr) {
+	switch new := new.(type) {
+	case *ast.Ident:
+		orig := old.(*ast.Ident)
+		if obj, ok := info.Defs[orig]; ok {
+			info.Defs[new] = obj
+		}
+		if obj, ok := info.Uses[orig]; ok {
+			info.Uses[new] = obj
+		}
+
+	case *ast.SelectorExpr:
+		orig := old.(*ast.SelectorExpr)
+		if sel, ok := info.Selections[orig]; ok {
+			info.Selections[new] = sel
+		}
+	}
+
+	if tv, ok := info.Types[old]; ok {
+		info.Types[new] = tv
+	}
+}
diff --git a/go/src/golang.org/x/tools/refactor/importgraph/graph.go b/go/src/golang.org/x/tools/refactor/importgraph/graph.go
index 8ad8014..1fc0781 100644
--- a/go/src/golang.org/x/tools/refactor/importgraph/graph.go
+++ b/go/src/golang.org/x/tools/refactor/importgraph/graph.go
@@ -53,9 +53,10 @@
 
 // Build scans the specified Go workspace and builds the forward and
 // reverse import dependency graphs for all its packages.
-// It also returns a mapping from import paths to errors for packages
+// It also returns a mapping from canonical import paths to errors for packages
 // whose loading was not entirely successful.
 // A package may appear in the graph and in the errors mapping.
+// All package paths are canonical and may contain "/vendor/".
 func Build(ctxt *build.Context) (forward, reverse Graph, errors map[string]error) {
 	type importEdge struct {
 		from, to string
@@ -67,39 +68,75 @@
 
 	ch := make(chan interface{})
 
-	var wg sync.WaitGroup
-	buildutil.ForEachPackage(ctxt, func(path string, err error) {
-		wg.Add(1)
-		go func() {
-			defer wg.Done()
+	go func() {
+		sema := make(chan int, 20) // I/O concurrency limiting semaphore
+		var wg sync.WaitGroup
+		buildutil.ForEachPackage(ctxt, func(path string, err error) {
 			if err != nil {
 				ch <- pathError{path, err}
 				return
 			}
 
-			bp, err := ctxt.Import(path, "", 0)
-			if err != nil {
-				if _, ok := err.(*build.NoGoError); ok {
-					// empty directory is not an error
-				} else {
-					ch <- pathError{path, err}
+			wg.Add(1)
+			go func() {
+				defer wg.Done()
+
+				sema <- 1
+				bp, err := ctxt.Import(path, "", 0)
+				<-sema
+
+				if err != nil {
+					if _, ok := err.(*build.NoGoError); ok {
+						// empty directory is not an error
+					} else {
+						ch <- pathError{path, err}
+					}
+					// Even in error cases, Import usually returns a package.
 				}
-				// Even in error cases, Import usually returns a package.
-			}
-			if bp != nil {
-				for _, imp := range bp.Imports {
-					ch <- importEdge{path, imp}
+
+				// absolutize resolves an import path relative
+				// to the current package bp.
+				// The absolute form may contain "vendor".
+				//
+				// The vendoring feature slows down Build by 3×.
+				// Here are timings from a 1400 package workspace:
+				//    1100ms: current code (with vendor check)
+				//     880ms: with a nonblocking cache around ctxt.IsDir
+				//     840ms: nonblocking cache with duplicate suppression
+				//     340ms: original code (no vendor check)
+				// TODO(adonovan): optimize, somehow.
+				memo := make(map[string]string)
+				absolutize := func(path string) string {
+					canon, ok := memo[path]
+					if !ok {
+						sema <- 1
+						bp2, _ := ctxt.Import(path, bp.Dir, build.FindOnly)
+						<-sema
+
+						if bp2 != nil {
+							canon = bp2.ImportPath
+						} else {
+							canon = path
+						}
+						memo[path] = canon
+					}
+					return canon
 				}
-				for _, imp := range bp.TestImports {
-					ch <- importEdge{path, imp}
+
+				if bp != nil {
+					for _, imp := range bp.Imports {
+						ch <- importEdge{path, absolutize(imp)}
+					}
+					for _, imp := range bp.TestImports {
+						ch <- importEdge{path, absolutize(imp)}
+					}
+					for _, imp := range bp.XTestImports {
+						ch <- importEdge{path, absolutize(imp)}
+					}
 				}
-				for _, imp := range bp.XTestImports {
-					ch <- importEdge{path, imp}
-				}
-			}
-		}()
-	})
-	go func() {
+
+			}()
+		})
 		wg.Wait()
 		close(ch)
 	}()
diff --git a/go/src/golang.org/x/tools/refactor/importgraph/graph_test.go b/go/src/golang.org/x/tools/refactor/importgraph/graph_test.go
index a486c26..52dd769 100644
--- a/go/src/golang.org/x/tools/refactor/importgraph/graph_test.go
+++ b/go/src/golang.org/x/tools/refactor/importgraph/graph_test.go
@@ -10,7 +10,6 @@
 
 import (
 	"go/build"
-	"runtime"
 	"sort"
 	"testing"
 
@@ -22,15 +21,12 @@
 const this = "golang.org/x/tools/refactor/importgraph"
 
 func TestBuild(t *testing.T) {
-	saved := runtime.GOMAXPROCS(8) // Build is highly parallel
-	defer runtime.GOMAXPROCS(saved)
-
 	forward, reverse, errors := importgraph.Build(&build.Default)
 
 	// Test direct edges.
 	// We throw in crypto/hmac to prove that external test files
 	// (such as this one) are inspected.
-	for _, p := range []string{"go/build", "runtime", "testing", "crypto/hmac"} {
+	for _, p := range []string{"go/build", "testing", "crypto/hmac"} {
 		if !forward[this][p] {
 			t.Errorf("forward[importgraph][%s] not found", p)
 		}
@@ -40,7 +36,7 @@
 	}
 
 	// Test non-existent direct edges
-	for _, p := range []string{"fmt", "errors", "reflect"} {
+	for _, p := range []string{"errors", "reflect"} {
 		if forward[this][p] {
 			t.Errorf("unexpected: forward[importgraph][%s] found", p)
 		}
diff --git a/go/src/golang.org/x/tools/refactor/lexical/lexical.go b/go/src/golang.org/x/tools/refactor/lexical/lexical.go
deleted file mode 100644
index c6567e4..0000000
--- a/go/src/golang.org/x/tools/refactor/lexical/lexical.go
+++ /dev/null
@@ -1,763 +0,0 @@
-// Package lexical computes the structure of the lexical environment,
-// including the definition of and references to all universal,
-// package-level, file-level and function-local entities.  It does not
-// record qualified identifiers, labels, struct fields, or methods.
-//
-// It is intended for renaming and refactoring tools, which need a more
-// precise understanding of identifier resolution than is available from
-// the output of the type-checker alone.
-//
-// THIS INTERFACE IS EXPERIMENTAL AND MAY CHANGE OR BE REMOVED IN FUTURE.
-//
-package lexical // import "golang.org/x/tools/refactor/lexical"
-
-// OVERVIEW
-//
-// As we traverse the AST, we build a "spaghetti stack" of Blocks,
-// i.e. a tree with parent edges pointing to the root.  Each time we
-// visit an identifier that's a reference into the lexical environment,
-// we create and save an Environment, which captures the current mapping
-// state of the Block; these are saved for the client.
-//
-// We don't bother recording non-lexical references.
-
-// TODO(adonovan):
-// - make it robust against syntax errors.  Audit all type assertions, etc.
-// - better still, after the Go 1.4 thaw, move this into go/types.
-//   I don't think it need be a big change since the visitor is already there;
-//   we just need to records Environments.  lexical.Block is analogous
-//   to types.Scope.
-
-import (
-	"fmt"
-	"go/ast"
-	"go/token"
-	"os"
-	"strconv"
-
-	"golang.org/x/tools/go/types"
-)
-
-const trace = false
-
-var logf = func(format string, args ...interface{}) {
-	fmt.Fprintf(os.Stderr, format, args...)
-}
-
-// A Block is a level of the lexical environment, a tree of blocks.
-// It maps names to objects.
-//
-type Block struct {
-	kind   string   // one of universe package file func block if switch typeswitch case for range
-	syntax ast.Node // syntax declaring the block (nil for universe and package) [needed?]
-
-	parent   Environment
-	bindings []types.Object // bindings in lexical order
-	index    map[string]int // maps a name to the index of its binding, for fast lookup
-}
-
-// An Environment is a snapshot of a Block taken at a certain lexical
-// position. It may contain bindings for fewer names than the
-// (completed) block, or different bindings for names that are
-// re-defined later in the block.
-//
-// For example, the lexical Block for the function f below contains a
-// binding for the local var x, but the Environments captured by at the
-// two print(x) calls differ: the first contains this binding, the
-// second does not.  The first Environment contains a different binding
-// for x: the string var defined in the package block, an ancestor.
-//
-//	var x string
-// 	func f() {
-//		print(x)
-//		x := 1
-//		print(x)
-//	}
-//
-type Environment struct {
-	block     *Block
-	nbindings int // length of prefix of block.bindings that's visible
-}
-
-// Depth returns the depth of this block in the block tree.
-// The universal block has depth 1, a package block 2, a file block 3, etc.
-func (b *Block) Depth() int {
-	if b == nil {
-		return 0
-	}
-	return 1 + b.parent.block.Depth()
-}
-
-// env returns an Environment that is a snapshot of b's current state.
-func (b *Block) env() Environment {
-	return Environment{b, len(b.bindings)}
-}
-
-// Lookup returns the definition of name in the environment specified by
-// env, and the Block that defines it, which may be an ancestor.
-func (env Environment) Lookup(name string) (types.Object, *Block) {
-	if env.block == nil {
-		return nil, nil
-	}
-	return lookup(env.block, name, env.nbindings)
-}
-
-// nbindings specifies what prefix of b.bindings should be considered visible.
-func lookup(b *Block, name string, nbindings int) (types.Object, *Block) {
-	if b == nil {
-		return nil, nil
-	}
-	if i, ok := b.index[name]; ok && i < nbindings {
-		return b.bindings[i], b
-	}
-
-	parent := b.parent
-	if parent.block == nil {
-		return nil, nil
-	}
-	return lookup(parent.block, name, parent.nbindings)
-}
-
-// Lookup returns the definition of name in the environment specified by
-// b, and the Block that defines it, which may be an ancestor.
-func (b *Block) Lookup(name string) (types.Object, *Block) {
-	return b.env().Lookup(name)
-}
-
-// Block returns the block of which this environment is a partial view.
-func (env Environment) Block() *Block {
-	return env.block
-}
-
-func (env Environment) String() string {
-	return fmt.Sprintf("%s:%d", env.block, env.nbindings)
-}
-
-func (b *Block) String() string {
-	var s string
-	if b.parent.block != nil {
-		s = b.parent.block.String()
-		s += "."
-	}
-	return s + b.kind
-}
-
-var universe = &Block{kind: "universe", index: make(map[string]int)}
-
-func init() {
-	for i, name := range types.Universe.Names() {
-		obj := types.Universe.Lookup(name)
-		universe.bindings = append(universe.bindings, obj)
-		universe.index[name] = i
-	}
-}
-
-// -- resolver ---------------------------------------------------------
-
-// A Reference provides the lexical environment for a given reference to
-// an object in lexical scope.
-type Reference struct {
-	Id  *ast.Ident
-	Env Environment
-}
-
-// resolver holds the state of the identifier resolution visitation:
-// the package information, the result, and the current block.
-type resolver struct {
-	fset    *token.FileSet
-	imports map[string]*types.Package
-	pkg     *types.Package
-	info    *types.Info
-
-	// visitor state
-	block *Block
-
-	result *Info
-}
-
-func (r *resolver) setBlock(kind string, syntax ast.Node) *Block {
-	b := &Block{
-		kind:   kind,
-		syntax: syntax,
-		parent: r.block.env(),
-		index:  make(map[string]int),
-	}
-	if syntax != nil {
-		r.result.Blocks[syntax] = b
-	}
-	r.block = b
-	return b
-}
-
-func (r *resolver) qualifier(pkg *types.Package) string {
-	if pkg == r.pkg {
-		return "" // unqualified intra-package reference
-	}
-	return pkg.Path()
-}
-
-func (r *resolver) use(id *ast.Ident, env Environment) {
-	if id.Name == "_" {
-		return // an error
-	}
-	obj, _ := env.Lookup(id.Name)
-	if obj == nil {
-		logf("%s: lookup of %s failed\n", r.fset.Position(id.Pos()), id.Name)
-	} else if want := r.info.Uses[id]; obj != want {
-		// sanity check against go/types resolver
-		logf("%s: internal error: lookup of %s yielded wrong object: got %v (%s), want %v\n",
-			r.fset.Position(id.Pos()), id.Name, types.ObjectString(obj, r.qualifier),
-			r.fset.Position(obj.Pos()),
-			want)
-	}
-	if trace {
-		logf("use %s = %v in %s\n", id.Name, types.ObjectString(obj, r.qualifier), env)
-	}
-
-	r.result.Refs[obj] = append(r.result.Refs[obj], Reference{id, env})
-}
-
-func (r *resolver) define(b *Block, id *ast.Ident) {
-	obj := r.info.Defs[id]
-	if obj == nil {
-		logf("%s: internal error: not a defining ident: %s\n",
-			r.fset.Position(id.Pos()), id.Name)
-		panic(id)
-	}
-	r.defineObject(b, id.Name, obj)
-
-	// Objects (other than PkgName) defined at file scope
-	// are also defined in the enclosing package scope.
-	if _, ok := b.syntax.(*ast.File); ok {
-		switch obj.(type) {
-		default:
-			r.defineObject(b.parent.block, id.Name, obj)
-		case nil, *types.PkgName:
-		}
-	}
-}
-
-// Used for implicit objects created by some ImportSpecs and CaseClauses.
-func (r *resolver) defineImplicit(b *Block, n ast.Node, name string) {
-	obj := r.info.Implicits[n]
-	if obj == nil {
-		logf("%s: internal error: not an implicit definition: %T\n",
-			r.fset.Position(n.Pos()), n)
-	}
-	r.defineObject(b, name, obj)
-}
-
-func (r *resolver) defineObject(b *Block, name string, obj types.Object) {
-	if obj.Name() == "_" {
-		return
-	}
-	i := len(b.bindings)
-	b.bindings = append(b.bindings, obj)
-	b.index[name] = i
-	if trace {
-		logf("def %s = %s in %s\n", name, types.ObjectString(obj, r.qualifier), b)
-	}
-	r.result.Defs[obj] = b
-}
-
-func (r *resolver) function(recv *ast.FieldList, typ *ast.FuncType, body *ast.BlockStmt, syntax ast.Node) {
-	// Use all signature types in enclosing block.
-	r.expr(typ)
-	r.fieldList(recv, false)
-
-	savedBlock := r.block // save
-	r.setBlock("func", syntax)
-
-	// Define all parameters/results, and visit the body, within the func block.
-	r.fieldList(typ.Params, true)
-	r.fieldList(typ.Results, true)
-	r.fieldList(recv, true)
-	if body != nil {
-		r.stmtList(body.List)
-	}
-
-	r.block = savedBlock // restore
-}
-
-func (r *resolver) fieldList(list *ast.FieldList, def bool) {
-	if list != nil {
-		for _, f := range list.List {
-			if def {
-				for _, id := range f.Names {
-					r.define(r.block, id)
-				}
-			} else {
-				r.expr(f.Type)
-			}
-		}
-	}
-}
-
-func (r *resolver) exprList(list []ast.Expr) {
-	for _, x := range list {
-		r.expr(x)
-	}
-}
-
-func (r *resolver) expr(n ast.Expr) {
-	switch n := n.(type) {
-	case *ast.BadExpr:
-	case *ast.BasicLit:
-		// no-op
-
-	case *ast.Ident:
-		r.use(n, r.block.env())
-
-	case *ast.Ellipsis:
-		if n.Elt != nil {
-			r.expr(n.Elt)
-		}
-
-	case *ast.FuncLit:
-		r.function(nil, n.Type, n.Body, n)
-
-	case *ast.CompositeLit:
-		if n.Type != nil {
-			r.expr(n.Type)
-		}
-		tv := r.info.Types[n]
-		if _, ok := deref(tv.Type).Underlying().(*types.Struct); ok {
-			for _, elt := range n.Elts {
-				if kv, ok := elt.(*ast.KeyValueExpr); ok {
-					r.expr(kv.Value)
-
-					// Also uses field kv.Key (non-lexical)
-					//  id := kv.Key.(*ast.Ident)
-					//  obj := r.info.Uses[id]
-					//  logf("use %s = %v (field)\n",
-					// 	id.Name, types.ObjectString(obj, r.qualifier))
-					// TODO make a fake FieldVal selection?
-				} else {
-					r.expr(elt)
-				}
-			}
-		} else {
-			r.exprList(n.Elts)
-		}
-
-	case *ast.ParenExpr:
-		r.expr(n.X)
-
-	case *ast.SelectorExpr:
-		r.expr(n.X)
-
-		// Non-lexical reference to field/method, or qualified identifier.
-		// if sel, ok := r.info.Selections[n]; ok { // selection
-		// 	switch sel.Kind() {
-		// 	case types.FieldVal:
-		// 		logf("use %s = %v (field)\n",
-		// 			n.Sel.Name, types.ObjectString(sel.Obj(), r.qualifier))
-		// 	case types.MethodExpr, types.MethodVal:
-		// 		logf("use %s = %v (method)\n",
-		// 			n.Sel.Name, types.ObjectString(sel.Obj(), r.qualifier))
-		// 	}
-		// } else { // qualified identifier
-		// 	obj := r.info.Uses[n.Sel]
-		// 	logf("use %s = %v (qualified)\n", n.Sel.Name, obj)
-		// }
-
-	case *ast.IndexExpr:
-		r.expr(n.X)
-		r.expr(n.Index)
-
-	case *ast.SliceExpr:
-		r.expr(n.X)
-		if n.Low != nil {
-			r.expr(n.Low)
-		}
-		if n.High != nil {
-			r.expr(n.High)
-		}
-		if n.Max != nil {
-			r.expr(n.Max)
-		}
-
-	case *ast.TypeAssertExpr:
-		r.expr(n.X)
-		if n.Type != nil {
-			r.expr(n.Type)
-		}
-
-	case *ast.CallExpr:
-		r.expr(n.Fun)
-		r.exprList(n.Args)
-
-	case *ast.StarExpr:
-		r.expr(n.X)
-
-	case *ast.UnaryExpr:
-		r.expr(n.X)
-
-	case *ast.BinaryExpr:
-		r.expr(n.X)
-		r.expr(n.Y)
-
-	case *ast.KeyValueExpr:
-		r.expr(n.Key)
-		r.expr(n.Value)
-
-	case *ast.ArrayType:
-		if n.Len != nil {
-			r.expr(n.Len)
-		}
-		r.expr(n.Elt)
-
-	case *ast.StructType:
-		// Use all the type names, but don't define any fields.
-		r.fieldList(n.Fields, false)
-
-	case *ast.FuncType:
-		// Use all the type names, but don't define any vars.
-		r.fieldList(n.Params, false)
-		r.fieldList(n.Results, false)
-
-	case *ast.InterfaceType:
-		// Use all the type names, but don't define any methods.
-		r.fieldList(n.Methods, false)
-
-	case *ast.MapType:
-		r.expr(n.Key)
-		r.expr(n.Value)
-
-	case *ast.ChanType:
-		r.expr(n.Value)
-
-	default:
-		panic(n)
-	}
-}
-
-func (r *resolver) stmtList(list []ast.Stmt) {
-	for _, s := range list {
-		r.stmt(s)
-	}
-}
-
-func (r *resolver) stmt(n ast.Stmt) {
-	switch n := n.(type) {
-	case *ast.BadStmt:
-	case *ast.EmptyStmt:
-		// nothing to do
-
-	case *ast.DeclStmt:
-		decl := n.Decl.(*ast.GenDecl)
-		for _, spec := range decl.Specs {
-			switch spec := spec.(type) {
-			case *ast.ValueSpec: // const or var
-				if spec.Type != nil {
-					r.expr(spec.Type)
-				}
-				r.exprList(spec.Values)
-				for _, name := range spec.Names {
-					r.define(r.block, name)
-				}
-
-			case *ast.TypeSpec:
-				r.define(r.block, spec.Name)
-				r.expr(spec.Type)
-			}
-		}
-
-	case *ast.LabeledStmt:
-		// Also defines label n.Label (non-lexical)
-		r.stmt(n.Stmt)
-
-	case *ast.ExprStmt:
-		r.expr(n.X)
-
-	case *ast.SendStmt:
-		r.expr(n.Chan)
-		r.expr(n.Value)
-
-	case *ast.IncDecStmt:
-		r.expr(n.X)
-
-	case *ast.AssignStmt:
-		if n.Tok == token.DEFINE {
-			r.exprList(n.Rhs)
-			for _, lhs := range n.Lhs {
-				id := lhs.(*ast.Ident)
-				if _, ok := r.info.Defs[id]; ok {
-					r.define(r.block, id)
-				} else {
-					r.use(id, r.block.env())
-				}
-			}
-		} else { // ASSIGN
-			r.exprList(n.Lhs)
-			r.exprList(n.Rhs)
-		}
-
-	case *ast.GoStmt:
-		r.expr(n.Call)
-
-	case *ast.DeferStmt:
-		r.expr(n.Call)
-
-	case *ast.ReturnStmt:
-		r.exprList(n.Results)
-
-	case *ast.BranchStmt:
-		if n.Label != nil {
-			// Also uses label n.Label (non-lexical)
-		}
-
-	case *ast.SelectStmt:
-		r.stmtList(n.Body.List)
-
-	case *ast.BlockStmt: // (explicit blocks only)
-		savedBlock := r.block // save
-		r.setBlock("block", n)
-		r.stmtList(n.List)
-		r.block = savedBlock // restore
-
-	case *ast.IfStmt:
-		savedBlock := r.block // save
-		r.setBlock("if", n)
-		if n.Init != nil {
-			r.stmt(n.Init)
-		}
-		r.expr(n.Cond)
-		r.stmt(n.Body) // new block
-		if n.Else != nil {
-			r.stmt(n.Else)
-		}
-		r.block = savedBlock // restore
-
-	case *ast.CaseClause:
-		savedBlock := r.block // save
-		r.setBlock("case", n)
-		if obj, ok := r.info.Implicits[n]; ok {
-			// e.g.
-			//   switch y := x.(type) {
-			//   case T: // we declare an implicit 'var y T' in this block
-			//   }
-			r.defineImplicit(r.block, n, obj.Name())
-		}
-		r.exprList(n.List)
-		r.stmtList(n.Body)
-		r.block = savedBlock // restore
-
-	case *ast.SwitchStmt:
-		savedBlock := r.block // save
-		r.setBlock("switch", n)
-		if n.Init != nil {
-			r.stmt(n.Init)
-		}
-		if n.Tag != nil {
-			r.expr(n.Tag)
-		}
-		r.stmtList(n.Body.List)
-		r.block = savedBlock // restore
-
-	case *ast.TypeSwitchStmt:
-		savedBlock := r.block // save
-		r.setBlock("typeswitch", n)
-		if n.Init != nil {
-			r.stmt(n.Init)
-		}
-		if assign, ok := n.Assign.(*ast.AssignStmt); ok { // y := x.(type)
-			r.expr(assign.Rhs[0]) // skip y: not a defining ident
-		} else {
-			r.stmt(n.Assign)
-		}
-		r.stmtList(n.Body.List)
-		r.block = savedBlock // restore
-
-	case *ast.CommClause:
-		savedBlock := r.block // save
-		r.setBlock("case", n)
-		if n.Comm != nil {
-			r.stmt(n.Comm)
-		}
-		r.stmtList(n.Body)
-		r.block = savedBlock // restore
-
-	case *ast.ForStmt:
-		savedBlock := r.block // save
-		r.setBlock("for", n)
-		if n.Init != nil {
-			r.stmt(n.Init)
-		}
-		if n.Cond != nil {
-			r.expr(n.Cond)
-		}
-		if n.Post != nil {
-			r.stmt(n.Post)
-		}
-		r.stmt(n.Body)
-		r.block = savedBlock // restore
-
-	case *ast.RangeStmt:
-		r.expr(n.X)
-		savedBlock := r.block // save
-		r.setBlock("range", n)
-		if n.Tok == token.DEFINE {
-			if n.Key != nil {
-				r.define(r.block, n.Key.(*ast.Ident))
-			}
-			if n.Value != nil {
-				r.define(r.block, n.Value.(*ast.Ident))
-			}
-		} else {
-			if n.Key != nil {
-				r.expr(n.Key)
-			}
-			if n.Value != nil {
-				r.expr(n.Value)
-			}
-		}
-		r.stmt(n.Body)
-		r.block = savedBlock // restore
-
-	default:
-		panic(n)
-	}
-}
-
-func (r *resolver) doImport(s *ast.ImportSpec, fileBlock *Block) {
-	path, _ := strconv.Unquote(s.Path.Value)
-	pkg := r.imports[path]
-	if s.Name == nil { // normal
-		r.defineImplicit(fileBlock, s, pkg.Name())
-	} else if s.Name.Name == "." { // dot import
-		for _, name := range pkg.Scope().Names() {
-			if ast.IsExported(name) {
-				obj := pkg.Scope().Lookup(name)
-				r.defineObject(fileBlock, name, obj)
-			}
-		}
-	} else { // renaming import
-		r.define(fileBlock, s.Name)
-	}
-}
-
-func (r *resolver) doPackage(pkg *types.Package, files []*ast.File) {
-	r.block = universe
-	r.result.Blocks[nil] = universe
-
-	r.result.PackageBlock = r.setBlock("package", nil)
-
-	var fileBlocks []*Block
-
-	// 1. Insert all package-level objects into file and package blocks.
-	//    (PkgName objects are only inserted into file blocks.)
-	for _, f := range files {
-		r.block = r.result.PackageBlock
-		fileBlock := r.setBlock("file", f) // package is not yet visible to file
-		fileBlocks = append(fileBlocks, fileBlock)
-
-		for _, d := range f.Decls {
-			switch d := d.(type) {
-			case *ast.GenDecl:
-				for _, s := range d.Specs {
-					switch s := s.(type) {
-					case *ast.ImportSpec:
-						r.doImport(s, fileBlock)
-
-					case *ast.ValueSpec: // const or var
-						for _, name := range s.Names {
-							r.define(r.result.PackageBlock, name)
-						}
-
-					case *ast.TypeSpec:
-						r.define(r.result.PackageBlock, s.Name)
-					}
-				}
-
-			case *ast.FuncDecl:
-				if d.Recv == nil { // function
-					if d.Name.Name != "init" {
-						r.define(r.result.PackageBlock, d.Name)
-					}
-				}
-			}
-		}
-	}
-
-	// 2. Now resolve bodies of GenDecls and FuncDecls.
-	for i, f := range files {
-		fileBlock := fileBlocks[i]
-		fileBlock.parent = r.result.PackageBlock.env() // make entire package visible to this file
-
-		for _, d := range f.Decls {
-			r.block = fileBlock
-
-			switch d := d.(type) {
-			case *ast.GenDecl:
-				for _, s := range d.Specs {
-					switch s := s.(type) {
-					case *ast.ValueSpec: // const or var
-						if s.Type != nil {
-							r.expr(s.Type)
-						}
-						r.exprList(s.Values)
-
-					case *ast.TypeSpec:
-						r.expr(s.Type)
-					}
-				}
-
-			case *ast.FuncDecl:
-				r.function(d.Recv, d.Type, d.Body, d)
-			}
-		}
-	}
-
-	r.block = nil
-}
-
-// An Info contains the lexical reference structure of a package.
-type Info struct {
-	Defs         map[types.Object]*Block      // maps each object to its defining lexical block
-	Refs         map[types.Object][]Reference // maps each object to the set of references to it
-	Blocks       map[ast.Node]*Block          // maps declaring syntax to block; nil => universe
-	PackageBlock *Block                       // the package-level lexical block
-}
-
-// Structure computes the structure of the lexical environment of the
-// package specified by (pkg, info, files).
-//
-// The info.{Types,Defs,Uses,Implicits} maps must have been populated
-// by the type-checker
-//
-// fset is used for logging.
-//
-func Structure(fset *token.FileSet, pkg *types.Package, info *types.Info, files []*ast.File) *Info {
-	r := resolver{
-		fset:    fset,
-		imports: make(map[string]*types.Package),
-		result: &Info{
-			Defs:   make(map[types.Object]*Block),
-			Refs:   make(map[types.Object][]Reference),
-			Blocks: make(map[ast.Node]*Block),
-		},
-		pkg:  pkg,
-		info: info,
-	}
-
-	// Build import map for just this package.
-	r.imports["unsafe"] = types.Unsafe
-	for _, imp := range pkg.Imports() {
-		r.imports[imp.Path()] = imp
-	}
-
-	r.doPackage(pkg, files)
-
-	return r.result
-}
-
-// -- Plundered from golang.org/x/tools/go/ssa -----------------
-
-// deref returns a pointer's element type; otherwise it returns typ.
-func deref(typ types.Type) types.Type {
-	if p, ok := typ.Underlying().(*types.Pointer); ok {
-		return p.Elem()
-	}
-	return typ
-}
diff --git a/go/src/golang.org/x/tools/refactor/lexical/lexical_test.go b/go/src/golang.org/x/tools/refactor/lexical/lexical_test.go
deleted file mode 100644
index 77287a4..0000000
--- a/go/src/golang.org/x/tools/refactor/lexical/lexical_test.go
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2014 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.
-
-// Incomplete std lib sources on Android.
-
-// +build !android
-
-package lexical
-
-import (
-	"go/build"
-	"testing"
-
-	"golang.org/x/tools/go/buildutil"
-	"golang.org/x/tools/go/loader"
-)
-
-func TestStdlib(t *testing.T) {
-	defer func(saved func(format string, args ...interface{})) {
-		logf = saved
-	}(logf)
-	logf = t.Errorf
-
-	ctxt := build.Default // copy
-
-	// Enumerate $GOROOT packages.
-	saved := ctxt.GOPATH
-	ctxt.GOPATH = "" // disable GOPATH during AllPackages
-	pkgs := buildutil.AllPackages(&ctxt)
-	ctxt.GOPATH = saved
-
-	// Throw in a number of go.tools packages too.
-	pkgs = append(pkgs,
-		"golang.org/x/tools/cmd/godoc",
-		"golang.org/x/tools/refactor/lexical")
-
-	// Load, parse and type-check the program.
-	conf := loader.Config{Build: &ctxt}
-	for _, path := range pkgs {
-		conf.ImportWithTests(path)
-	}
-	iprog, err := conf.Load()
-	if err != nil {
-		t.Fatalf("Load failed: %v", err)
-	}
-
-	// This test ensures that Structure doesn't panic and that
-	// its internal sanity-checks against go/types don't fail.
-	for pkg, info := range iprog.AllPackages {
-		_ = Structure(iprog.Fset, pkg, &info.Info, info.Files)
-	}
-}
diff --git a/go/src/golang.org/x/tools/refactor/rename/check.go b/go/src/golang.org/x/tools/refactor/rename/check.go
index 017a604..cf1999e 100644
--- a/go/src/golang.org/x/tools/refactor/rename/check.go
+++ b/go/src/golang.org/x/tools/refactor/rename/check.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package rename
 
 // This file defines the safety checks for each kind of renaming.
@@ -10,10 +12,9 @@
 	"fmt"
 	"go/ast"
 	"go/token"
+	"go/types"
 
 	"golang.org/x/tools/go/loader"
-	"golang.org/x/tools/go/types"
-	"golang.org/x/tools/refactor/lexical"
 	"golang.org/x/tools/refactor/satisfy"
 )
 
@@ -101,18 +102,20 @@
 	}
 
 	info := r.packages[from.Pkg()]
-	lexinfo := lexical.Structure(r.iprog.Fset, from.Pkg(), &info.Info, info.Files)
 
 	// Check that in the package block, "init" is a function, and never referenced.
 	if r.to == "init" {
 		kind := objectKind(from)
 		if kind == "func" {
 			// Reject if intra-package references to it exist.
-			if refs := lexinfo.Refs[from]; len(refs) > 0 {
-				r.errorf(from.Pos(),
-					"renaming this func %q to %q would make it a package initializer",
-					from.Name(), r.to)
-				r.errorf(refs[0].Id.Pos(), "\tbut references to it exist")
+			for id, obj := range info.Uses {
+				if obj == from {
+					r.errorf(from.Pos(),
+						"renaming this func %q to %q would make it a package initializer",
+						from.Name(), r.to)
+					r.errorf(id.Pos(), "\tbut references to it exist")
+					break
+				}
 			}
 		} else {
 			r.errorf(from.Pos(), "you cannot have a %s at package level named %q",
@@ -122,7 +125,9 @@
 
 	// Check for conflicts between package block and all file blocks.
 	for _, f := range info.Files {
-		if prev, b := lexinfo.Blocks[f].Lookup(r.to); b == lexinfo.Blocks[f] {
+		fileScope := info.Info.Scopes[f]
+		b, prev := fileScope.LookupParent(r.to, token.NoPos)
+		if b == fileScope {
 			r.errorf(from.Pos(), "renaming this %s %q to %q would conflict",
 				objectKind(from), from.Name(), r.to)
 			r.errorf(prev.Pos(), "\twith this %s",
@@ -205,11 +210,9 @@
 // requires no checks.
 //
 func (r *renamer) checkInLexicalScope(from types.Object, info *loader.PackageInfo) {
-	lexinfo := lexical.Structure(r.iprog.Fset, info.Pkg, &info.Info, info.Files)
-
-	b := lexinfo.Defs[from] // the block defining the 'from' object
+	b := from.Parent() // the block defining the 'from' object
 	if b != nil {
-		to, toBlock := b.Lookup(r.to)
+		toBlock, to := b.LookupParent(r.to, from.Parent().End())
 		if toBlock == b {
 			// same-block conflict
 			r.errorf(from.Pos(), "renaming this %s %q to %q",
@@ -221,42 +224,45 @@
 			// Check for super-block conflict.
 			// The name r.to is defined in a superblock.
 			// Is that name referenced from within this block?
-			for _, ref := range lexinfo.Refs[to] {
-				if obj, _ := ref.Env.Lookup(from.Name()); obj == from {
+			forEachLexicalRef(info, to, func(id *ast.Ident, block *types.Scope) bool {
+				_, obj := lexicalLookup(block, from.Name(), id.Pos())
+				if obj == from {
 					// super-block conflict
 					r.errorf(from.Pos(), "renaming this %s %q to %q",
 						objectKind(from), from.Name(), r.to)
-					r.errorf(ref.Id.Pos(), "\twould shadow this reference")
+					r.errorf(id.Pos(), "\twould shadow this reference")
 					r.errorf(to.Pos(), "\tto the %s declared here",
 						objectKind(to))
-					return
+					return false // stop
 				}
-			}
+				return true
+			})
 		}
 	}
 
 	// Check for sub-block conflict.
 	// Is there an intervening definition of r.to between
 	// the block defining 'from' and some reference to it?
-	for _, ref := range lexinfo.Refs[from] {
-		// TODO(adonovan): think about dot imports.
-		// (Is b == fromBlock an invariant?)
-		_, fromBlock := ref.Env.Lookup(from.Name())
-		fromDepth := fromBlock.Depth()
+	forEachLexicalRef(info, from, func(id *ast.Ident, block *types.Scope) bool {
+		// Find the block that defines the found reference.
+		// It may be an ancestor.
+		fromBlock, _ := lexicalLookup(block, from.Name(), id.Pos())
 
-		to, toBlock := ref.Env.Lookup(r.to)
+		// See what r.to would resolve to in the same scope.
+		toBlock, to := lexicalLookup(block, r.to, id.Pos())
 		if to != nil {
 			// sub-block conflict
-			if toBlock.Depth() > fromDepth {
+			if deeper(toBlock, fromBlock) {
 				r.errorf(from.Pos(), "renaming this %s %q to %q",
 					objectKind(from), from.Name(), r.to)
-				r.errorf(ref.Id.Pos(), "\twould cause this reference to become shadowed")
+				r.errorf(id.Pos(), "\twould cause this reference to become shadowed")
 				r.errorf(to.Pos(), "\tby this intervening %s definition",
 					objectKind(to))
-				return
+				return false // stop
 			}
 		}
-	}
+		return true
+	})
 
 	// Renaming a type that is used as an embedded field
 	// requires renaming the field too. e.g.
@@ -274,6 +280,123 @@
 	}
 }
 
+// lexicalLookup is like (*types.Scope).LookupParent but respects the
+// environment visible at pos.  It assumes the relative position
+// information is correct with each file.
+func lexicalLookup(block *types.Scope, name string, pos token.Pos) (*types.Scope, types.Object) {
+	for b := block; b != nil; b = b.Parent() {
+		obj := b.Lookup(name)
+		// The scope of a package-level object is the entire package,
+		// so ignore pos in that case.
+		// No analogous clause is needed for file-level objects
+		// since no reference can appear before an import decl.
+		if obj != nil && (b == obj.Pkg().Scope() || obj.Pos() < pos) {
+			return b, obj
+		}
+	}
+	return nil, nil
+}
+
+// deeper reports whether block x is lexically deeper than y.
+func deeper(x, y *types.Scope) bool {
+	if x == y || x == nil {
+		return false
+	} else if y == nil {
+		return true
+	} else {
+		return deeper(x.Parent(), y.Parent())
+	}
+}
+
+// forEachLexicalRef calls fn(id, block) for each identifier id in package
+// info that is a reference to obj in lexical scope.  block is the
+// lexical block enclosing the reference.  If fn returns false the
+// iteration is terminated and findLexicalRefs returns false.
+func forEachLexicalRef(info *loader.PackageInfo, obj types.Object, fn func(id *ast.Ident, block *types.Scope) bool) bool {
+	ok := true
+	var stack []ast.Node
+
+	var visit func(n ast.Node) bool
+	visit = func(n ast.Node) bool {
+		if n == nil {
+			stack = stack[:len(stack)-1] // pop
+			return false
+		}
+		if !ok {
+			return false // bail out
+		}
+
+		stack = append(stack, n) // push
+		switch n := n.(type) {
+		case *ast.Ident:
+			if info.Uses[n] == obj {
+				block := enclosingBlock(&info.Info, stack)
+				if !fn(n, block) {
+					ok = false
+				}
+			}
+			return visit(nil) // pop stack
+
+		case *ast.SelectorExpr:
+			// don't visit n.Sel
+			ast.Inspect(n.X, visit)
+			return visit(nil) // pop stack, don't descend
+
+		case *ast.CompositeLit:
+			// Handle recursion ourselves for struct literals
+			// so we don't visit field identifiers.
+			tv := info.Types[n]
+			if _, ok := deref(tv.Type).Underlying().(*types.Struct); ok {
+				if n.Type != nil {
+					ast.Inspect(n.Type, visit)
+				}
+				for _, elt := range n.Elts {
+					if kv, ok := elt.(*ast.KeyValueExpr); ok {
+						ast.Inspect(kv.Value, visit)
+					} else {
+						ast.Inspect(elt, visit)
+					}
+				}
+				return visit(nil) // pop stack, don't descend
+			}
+		}
+		return true
+	}
+
+	for _, f := range info.Files {
+		ast.Inspect(f, visit)
+		if len(stack) != 0 {
+			panic(stack)
+		}
+		if !ok {
+			break
+		}
+	}
+	return ok
+}
+
+// enclosingBlock returns the innermost block enclosing the specified
+// AST node, specified in the form of a path from the root of the file,
+// [file...n].
+func enclosingBlock(info *types.Info, stack []ast.Node) *types.Scope {
+	for i := range stack {
+		n := stack[len(stack)-1-i]
+		// For some reason, go/types always associates a
+		// function's scope with its FuncType.
+		// TODO(adonovan): feature or a bug?
+		switch f := n.(type) {
+		case *ast.FuncDecl:
+			n = f.Type
+		case *ast.FuncLit:
+			n = f.Type
+		}
+		if b := info.Scopes[n]; b != nil {
+			return b
+		}
+	}
+	panic("no Scope for *ast.File")
+}
+
 func (r *renamer) checkLabel(label *types.Label) {
 	// Check there are no identical labels in the function's label block.
 	// (Label blocks don't nest, so this is easy.)
diff --git a/go/src/golang.org/x/tools/refactor/rename/check14.go b/go/src/golang.org/x/tools/refactor/rename/check14.go
new file mode 100644
index 0000000..3f1f7ab
--- /dev/null
+++ b/go/src/golang.org/x/tools/refactor/rename/check14.go
@@ -0,0 +1,860 @@
+// Copyright 2014 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.
+
+// +build !go1.5
+
+package rename
+
+// This file defines the safety checks for each kind of renaming.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/refactor/satisfy"
+)
+
+// errorf reports an error (e.g. conflict) and prevents file modification.
+func (r *renamer) errorf(pos token.Pos, format string, args ...interface{}) {
+	r.hadConflicts = true
+	reportError(r.iprog.Fset.Position(pos), fmt.Sprintf(format, args...))
+}
+
+// check performs safety checks of the renaming of the 'from' object to r.to.
+func (r *renamer) check(from types.Object) {
+	if r.objsToUpdate[from] {
+		return
+	}
+	r.objsToUpdate[from] = true
+
+	// NB: order of conditions is important.
+	if from_, ok := from.(*types.PkgName); ok {
+		r.checkInFileBlock(from_)
+	} else if from_, ok := from.(*types.Label); ok {
+		r.checkLabel(from_)
+	} else if isPackageLevel(from) {
+		r.checkInPackageBlock(from)
+	} else if v, ok := from.(*types.Var); ok && v.IsField() {
+		r.checkStructField(v)
+	} else if f, ok := from.(*types.Func); ok && recv(f) != nil {
+		r.checkMethod(f)
+	} else if isLocal(from) {
+		r.checkInLocalScope(from)
+	} else {
+		r.errorf(from.Pos(), "unexpected %s object %q (please report a bug)\n",
+			objectKind(from), from)
+	}
+}
+
+// checkInFileBlock performs safety checks for renames of objects in the file block,
+// i.e. imported package names.
+func (r *renamer) checkInFileBlock(from *types.PkgName) {
+	// Check import name is not "init".
+	if r.to == "init" {
+		r.errorf(from.Pos(), "%q is not a valid imported package name", r.to)
+	}
+
+	// Check for conflicts between file and package block.
+	if prev := from.Pkg().Scope().Lookup(r.to); prev != nil {
+		r.errorf(from.Pos(), "renaming this %s %q to %q would conflict",
+			objectKind(from), from.Name(), r.to)
+		r.errorf(prev.Pos(), "\twith this package member %s",
+			objectKind(prev))
+		return // since checkInPackageBlock would report redundant errors
+	}
+
+	// Check for conflicts in lexical scope.
+	r.checkInLexicalScope(from, r.packages[from.Pkg()])
+
+	// Finally, modify ImportSpec syntax to add or remove the Name as needed.
+	info, path, _ := r.iprog.PathEnclosingInterval(from.Pos(), from.Pos())
+	if from.Imported().Name() == r.to {
+		// ImportSpec.Name not needed
+		path[1].(*ast.ImportSpec).Name = nil
+	} else {
+		// ImportSpec.Name needed
+		if spec := path[1].(*ast.ImportSpec); spec.Name == nil {
+			spec.Name = &ast.Ident{NamePos: spec.Path.Pos(), Name: r.to}
+			info.Defs[spec.Name] = from
+		}
+	}
+}
+
+// checkInPackageBlock performs safety checks for renames of
+// func/var/const/type objects in the package block.
+func (r *renamer) checkInPackageBlock(from types.Object) {
+	// Check that there are no references to the name from another
+	// package if the renaming would make it unexported.
+	if ast.IsExported(from.Name()) && !ast.IsExported(r.to) {
+		for pkg, info := range r.packages {
+			if pkg == from.Pkg() {
+				continue
+			}
+			if id := someUse(info, from); id != nil &&
+				!r.checkExport(id, pkg, from) {
+				break
+			}
+		}
+	}
+
+	info := r.packages[from.Pkg()]
+
+	// Check that in the package block, "init" is a function, and never referenced.
+	if r.to == "init" {
+		kind := objectKind(from)
+		if kind == "func" {
+			// Reject if intra-package references to it exist.
+			for id, obj := range info.Uses {
+				if obj == from {
+					r.errorf(from.Pos(),
+						"renaming this func %q to %q would make it a package initializer",
+						from.Name(), r.to)
+					r.errorf(id.Pos(), "\tbut references to it exist")
+					break
+				}
+			}
+		} else {
+			r.errorf(from.Pos(), "you cannot have a %s at package level named %q",
+				kind, r.to)
+		}
+	}
+
+	// Check for conflicts between package block and all file blocks.
+	for _, f := range info.Files {
+		fileScope := info.Info.Scopes[f]
+		b, prev := fileScope.LookupParent(r.to, token.NoPos)
+		if b == fileScope {
+			r.errorf(from.Pos(), "renaming this %s %q to %q would conflict",
+				objectKind(from), from.Name(), r.to)
+			r.errorf(prev.Pos(), "\twith this %s",
+				objectKind(prev))
+			return // since checkInPackageBlock would report redundant errors
+		}
+	}
+
+	// Check for conflicts in lexical scope.
+	if from.Exported() {
+		for _, info := range r.packages {
+			r.checkInLexicalScope(from, info)
+		}
+	} else {
+		r.checkInLexicalScope(from, info)
+	}
+}
+
+func (r *renamer) checkInLocalScope(from types.Object) {
+	info := r.packages[from.Pkg()]
+
+	// Is this object an implicit local var for a type switch?
+	// Each case has its own var, whose position is the decl of y,
+	// but Ident in that decl does not appear in the Uses map.
+	//
+	//   switch y := x.(type) {	 // Defs[Ident(y)] is undefined
+	//   case int:    print(y)       // Implicits[CaseClause(int)]    = Var(y_int)
+	//   case string: print(y)       // Implicits[CaseClause(string)] = Var(y_string)
+	//   }
+	//
+	var isCaseVar bool
+	for syntax, obj := range info.Implicits {
+		if _, ok := syntax.(*ast.CaseClause); ok && obj.Pos() == from.Pos() {
+			isCaseVar = true
+			r.check(obj)
+		}
+	}
+
+	r.checkInLexicalScope(from, info)
+
+	// Finally, if this was a type switch, change the variable y.
+	if isCaseVar {
+		_, path, _ := r.iprog.PathEnclosingInterval(from.Pos(), from.Pos())
+		path[0].(*ast.Ident).Name = r.to // path is [Ident AssignStmt TypeSwitchStmt...]
+	}
+}
+
+// checkInLexicalScope performs safety checks that a renaming does not
+// change the lexical reference structure of the specified package.
+//
+// For objects in lexical scope, there are three kinds of conflicts:
+// same-, sub-, and super-block conflicts.  We will illustrate all three
+// using this example:
+//
+//	var x int
+//	var z int
+//
+//	func f(y int) {
+//		print(x)
+//		print(y)
+//	}
+//
+// Renaming x to z encounters a SAME-BLOCK CONFLICT, because an object
+// with the new name already exists, defined in the same lexical block
+// as the old object.
+//
+// Renaming x to y encounters a SUB-BLOCK CONFLICT, because there exists
+// a reference to x from within (what would become) a hole in its scope.
+// The definition of y in an (inner) sub-block would cast a shadow in
+// the scope of the renamed variable.
+//
+// Renaming y to x encounters a SUPER-BLOCK CONFLICT.  This is the
+// converse situation: there is an existing definition of the new name
+// (x) in an (enclosing) super-block, and the renaming would create a
+// hole in its scope, within which there exist references to it.  The
+// new name casts a shadow in scope of the existing definition of x in
+// the super-block.
+//
+// Removing the old name (and all references to it) is always safe, and
+// requires no checks.
+//
+func (r *renamer) checkInLexicalScope(from types.Object, info *loader.PackageInfo) {
+	b := from.Parent() // the block defining the 'from' object
+	if b != nil {
+		toBlock, to := b.LookupParent(r.to, from.Parent().End())
+		if toBlock == b {
+			// same-block conflict
+			r.errorf(from.Pos(), "renaming this %s %q to %q",
+				objectKind(from), from.Name(), r.to)
+			r.errorf(to.Pos(), "\tconflicts with %s in same block",
+				objectKind(to))
+			return
+		} else if toBlock != nil {
+			// Check for super-block conflict.
+			// The name r.to is defined in a superblock.
+			// Is that name referenced from within this block?
+			forEachLexicalRef(info, to, func(id *ast.Ident, block *types.Scope) bool {
+				_, obj := lexicalLookup(block, from.Name(), id.Pos())
+				if obj == from {
+					// super-block conflict
+					r.errorf(from.Pos(), "renaming this %s %q to %q",
+						objectKind(from), from.Name(), r.to)
+					r.errorf(id.Pos(), "\twould shadow this reference")
+					r.errorf(to.Pos(), "\tto the %s declared here",
+						objectKind(to))
+					return false // stop
+				}
+				return true
+			})
+		}
+	}
+
+	// Check for sub-block conflict.
+	// Is there an intervening definition of r.to between
+	// the block defining 'from' and some reference to it?
+	forEachLexicalRef(info, from, func(id *ast.Ident, block *types.Scope) bool {
+		// Find the block that defines the found reference.
+		// It may be an ancestor.
+		fromBlock, _ := lexicalLookup(block, from.Name(), id.Pos())
+
+		// See what r.to would resolve to in the same scope.
+		toBlock, to := lexicalLookup(block, r.to, id.Pos())
+		if to != nil {
+			// sub-block conflict
+			if deeper(toBlock, fromBlock) {
+				r.errorf(from.Pos(), "renaming this %s %q to %q",
+					objectKind(from), from.Name(), r.to)
+				r.errorf(id.Pos(), "\twould cause this reference to become shadowed")
+				r.errorf(to.Pos(), "\tby this intervening %s definition",
+					objectKind(to))
+				return false // stop
+			}
+		}
+		return true
+	})
+
+	// Renaming a type that is used as an embedded field
+	// requires renaming the field too. e.g.
+	// 	type T int // if we rename this to U..
+	// 	var s struct {T}
+	// 	print(s.T) // ...this must change too
+	if _, ok := from.(*types.TypeName); ok {
+		for id, obj := range info.Uses {
+			if obj == from {
+				if field := info.Defs[id]; field != nil {
+					r.check(field)
+				}
+			}
+		}
+	}
+}
+
+// lexicalLookup is like (*types.Scope).LookupParent but respects the
+// environment visible at pos.  It assumes the relative position
+// information is correct with each file.
+func lexicalLookup(block *types.Scope, name string, pos token.Pos) (*types.Scope, types.Object) {
+	for b := block; b != nil; b = b.Parent() {
+		obj := b.Lookup(name)
+		// The scope of a package-level object is the entire package,
+		// so ignore pos in that case.
+		// No analogous clause is needed for file-level objects
+		// since no reference can appear before an import decl.
+		if obj != nil && (b == obj.Pkg().Scope() || obj.Pos() < pos) {
+			return b, obj
+		}
+	}
+	return nil, nil
+}
+
+// deeper reports whether block x is lexically deeper than y.
+func deeper(x, y *types.Scope) bool {
+	if x == y || x == nil {
+		return false
+	} else if y == nil {
+		return true
+	} else {
+		return deeper(x.Parent(), y.Parent())
+	}
+}
+
+// forEachLexicalRef calls fn(id, block) for each identifier id in package
+// info that is a reference to obj in lexical scope.  block is the
+// lexical block enclosing the reference.  If fn returns false the
+// iteration is terminated and findLexicalRefs returns false.
+func forEachLexicalRef(info *loader.PackageInfo, obj types.Object, fn func(id *ast.Ident, block *types.Scope) bool) bool {
+	ok := true
+	var stack []ast.Node
+
+	var visit func(n ast.Node) bool
+	visit = func(n ast.Node) bool {
+		if n == nil {
+			stack = stack[:len(stack)-1] // pop
+			return false
+		}
+		if !ok {
+			return false // bail out
+		}
+
+		stack = append(stack, n) // push
+		switch n := n.(type) {
+		case *ast.Ident:
+			if info.Uses[n] == obj {
+				block := enclosingBlock(&info.Info, stack)
+				if !fn(n, block) {
+					ok = false
+				}
+			}
+			return visit(nil) // pop stack
+
+		case *ast.SelectorExpr:
+			// don't visit n.Sel
+			ast.Inspect(n.X, visit)
+			return visit(nil) // pop stack, don't descend
+
+		case *ast.CompositeLit:
+			// Handle recursion ourselves for struct literals
+			// so we don't visit field identifiers.
+			tv := info.Types[n]
+			if _, ok := deref(tv.Type).Underlying().(*types.Struct); ok {
+				if n.Type != nil {
+					ast.Inspect(n.Type, visit)
+				}
+				for _, elt := range n.Elts {
+					if kv, ok := elt.(*ast.KeyValueExpr); ok {
+						ast.Inspect(kv.Value, visit)
+					} else {
+						ast.Inspect(elt, visit)
+					}
+				}
+				return visit(nil) // pop stack, don't descend
+			}
+		}
+		return true
+	}
+
+	for _, f := range info.Files {
+		ast.Inspect(f, visit)
+		if len(stack) != 0 {
+			panic(stack)
+		}
+		if !ok {
+			break
+		}
+	}
+	return ok
+}
+
+// enclosingBlock returns the innermost block enclosing the specified
+// AST node, specified in the form of a path from the root of the file,
+// [file...n].
+func enclosingBlock(info *types.Info, stack []ast.Node) *types.Scope {
+	for i := range stack {
+		n := stack[len(stack)-1-i]
+		// For some reason, go/types always associates a
+		// function's scope with its FuncType.
+		// TODO(adonovan): feature or a bug?
+		switch f := n.(type) {
+		case *ast.FuncDecl:
+			n = f.Type
+		case *ast.FuncLit:
+			n = f.Type
+		}
+		if b := info.Scopes[n]; b != nil {
+			return b
+		}
+	}
+	panic("no Scope for *ast.File")
+}
+
+func (r *renamer) checkLabel(label *types.Label) {
+	// Check there are no identical labels in the function's label block.
+	// (Label blocks don't nest, so this is easy.)
+	if prev := label.Parent().Lookup(r.to); prev != nil {
+		r.errorf(label.Pos(), "renaming this label %q to %q", label.Name(), prev.Name())
+		r.errorf(prev.Pos(), "\twould conflict with this one")
+	}
+}
+
+// checkStructField checks that the field renaming will not cause
+// conflicts at its declaration, or ambiguity or changes to any selection.
+func (r *renamer) checkStructField(from *types.Var) {
+	// Check that the struct declaration is free of field conflicts,
+	// and field/method conflicts.
+
+	// go/types offers no easy way to get from a field (or interface
+	// method) to its declaring struct (or interface), so we must
+	// ascend the AST.
+	info, path, _ := r.iprog.PathEnclosingInterval(from.Pos(), from.Pos())
+	// path matches this pattern:
+	// [Ident SelectorExpr? StarExpr? Field FieldList StructType ParenExpr* ... File]
+
+	// Ascend to FieldList.
+	var i int
+	for {
+		if _, ok := path[i].(*ast.FieldList); ok {
+			break
+		}
+		i++
+	}
+	i++
+	tStruct := path[i].(*ast.StructType)
+	i++
+	// Ascend past parens (unlikely).
+	for {
+		_, ok := path[i].(*ast.ParenExpr)
+		if !ok {
+			break
+		}
+		i++
+	}
+	if spec, ok := path[i].(*ast.TypeSpec); ok {
+		// This struct is also a named type.
+		// We must check for direct (non-promoted) field/field
+		// and method/field conflicts.
+		named := info.Defs[spec.Name].Type()
+		prev, indices, _ := types.LookupFieldOrMethod(named, true, info.Pkg, r.to)
+		if len(indices) == 1 {
+			r.errorf(from.Pos(), "renaming this field %q to %q",
+				from.Name(), r.to)
+			r.errorf(prev.Pos(), "\twould conflict with this %s",
+				objectKind(prev))
+			return // skip checkSelections to avoid redundant errors
+		}
+	} else {
+		// This struct is not a named type.
+		// We need only check for direct (non-promoted) field/field conflicts.
+		T := info.Types[tStruct].Type.Underlying().(*types.Struct)
+		for i := 0; i < T.NumFields(); i++ {
+			if prev := T.Field(i); prev.Name() == r.to {
+				r.errorf(from.Pos(), "renaming this field %q to %q",
+					from.Name(), r.to)
+				r.errorf(prev.Pos(), "\twould conflict with this field")
+				return // skip checkSelections to avoid redundant errors
+			}
+		}
+	}
+
+	// Renaming an anonymous field requires renaming the type too. e.g.
+	// 	print(s.T)       // if we rename T to U,
+	// 	type T int       // this and
+	// 	var s struct {T} // this must change too.
+	if from.Anonymous() {
+		if named, ok := from.Type().(*types.Named); ok {
+			r.check(named.Obj())
+		} else if named, ok := deref(from.Type()).(*types.Named); ok {
+			r.check(named.Obj())
+		}
+	}
+
+	// Check integrity of existing (field and method) selections.
+	r.checkSelections(from)
+}
+
+// checkSelection checks that all uses and selections that resolve to
+// the specified object would continue to do so after the renaming.
+func (r *renamer) checkSelections(from types.Object) {
+	for pkg, info := range r.packages {
+		if id := someUse(info, from); id != nil {
+			if !r.checkExport(id, pkg, from) {
+				return
+			}
+		}
+
+		for syntax, sel := range info.Selections {
+			// There may be extant selections of only the old
+			// name or only the new name, so we must check both.
+			// (If neither, the renaming is sound.)
+			//
+			// In both cases, we wish to compare the lengths
+			// of the implicit field path (Selection.Index)
+			// to see if the renaming would change it.
+			//
+			// If a selection that resolves to 'from', when renamed,
+			// would yield a path of the same or shorter length,
+			// this indicates ambiguity or a changed referent,
+			// analogous to same- or sub-block lexical conflict.
+			//
+			// If a selection using the name 'to' would
+			// yield a path of the same or shorter length,
+			// this indicates ambiguity or shadowing,
+			// analogous to same- or super-block lexical conflict.
+
+			// TODO(adonovan): fix: derive from Types[syntax.X].Mode
+			// TODO(adonovan): test with pointer, value, addressable value.
+			isAddressable := true
+
+			if sel.Obj() == from {
+				if obj, indices, _ := types.LookupFieldOrMethod(sel.Recv(), isAddressable, from.Pkg(), r.to); obj != nil {
+					// Renaming this existing selection of
+					// 'from' may block access to an existing
+					// type member named 'to'.
+					delta := len(indices) - len(sel.Index())
+					if delta > 0 {
+						continue // no ambiguity
+					}
+					r.selectionConflict(from, delta, syntax, obj)
+					return
+				}
+
+			} else if sel.Obj().Name() == r.to {
+				if obj, indices, _ := types.LookupFieldOrMethod(sel.Recv(), isAddressable, from.Pkg(), from.Name()); obj == from {
+					// Renaming 'from' may cause this existing
+					// selection of the name 'to' to change
+					// its meaning.
+					delta := len(indices) - len(sel.Index())
+					if delta > 0 {
+						continue //  no ambiguity
+					}
+					r.selectionConflict(from, -delta, syntax, sel.Obj())
+					return
+				}
+			}
+		}
+	}
+}
+
+func (r *renamer) selectionConflict(from types.Object, delta int, syntax *ast.SelectorExpr, obj types.Object) {
+	r.errorf(from.Pos(), "renaming this %s %q to %q",
+		objectKind(from), from.Name(), r.to)
+
+	switch {
+	case delta < 0:
+		// analogous to sub-block conflict
+		r.errorf(syntax.Sel.Pos(),
+			"\twould change the referent of this selection")
+		r.errorf(obj.Pos(), "\tof this %s", objectKind(obj))
+	case delta == 0:
+		// analogous to same-block conflict
+		r.errorf(syntax.Sel.Pos(),
+			"\twould make this reference ambiguous")
+		r.errorf(obj.Pos(), "\twith this %s", objectKind(obj))
+	case delta > 0:
+		// analogous to super-block conflict
+		r.errorf(syntax.Sel.Pos(),
+			"\twould shadow this selection")
+		r.errorf(obj.Pos(), "\tof the %s declared here",
+			objectKind(obj))
+	}
+}
+
+// checkMethod performs safety checks for renaming a method.
+// There are three hazards:
+// - declaration conflicts
+// - selection ambiguity/changes
+// - entailed renamings of assignable concrete/interface types.
+//   We reject renamings initiated at concrete methods if it would
+//   change the assignability relation.  For renamings of abstract
+//   methods, we rename all methods transitively coupled to it via
+//   assignability.
+func (r *renamer) checkMethod(from *types.Func) {
+	// e.g. error.Error
+	if from.Pkg() == nil {
+		r.errorf(from.Pos(), "you cannot rename built-in method %s", from)
+		return
+	}
+
+	// ASSIGNABILITY: We reject renamings of concrete methods that
+	// would break a 'satisfy' constraint; but renamings of abstract
+	// methods are allowed to proceed, and we rename affected
+	// concrete and abstract methods as necessary.  It is the
+	// initial method that determines the policy.
+
+	// Check for conflict at point of declaration.
+	// Check to ensure preservation of assignability requirements.
+	R := recv(from).Type()
+	if isInterface(R) {
+		// Abstract method
+
+		// declaration
+		prev, _, _ := types.LookupFieldOrMethod(R, false, from.Pkg(), r.to)
+		if prev != nil {
+			r.errorf(from.Pos(), "renaming this interface method %q to %q",
+				from.Name(), r.to)
+			r.errorf(prev.Pos(), "\twould conflict with this method")
+			return
+		}
+
+		// Check all interfaces that embed this one for
+		// declaration conflicts too.
+		for _, info := range r.packages {
+			// Start with named interface types (better errors)
+			for _, obj := range info.Defs {
+				if obj, ok := obj.(*types.TypeName); ok && isInterface(obj.Type()) {
+					f, _, _ := types.LookupFieldOrMethod(
+						obj.Type(), false, from.Pkg(), from.Name())
+					if f == nil {
+						continue
+					}
+					t, _, _ := types.LookupFieldOrMethod(
+						obj.Type(), false, from.Pkg(), r.to)
+					if t == nil {
+						continue
+					}
+					r.errorf(from.Pos(), "renaming this interface method %q to %q",
+						from.Name(), r.to)
+					r.errorf(t.Pos(), "\twould conflict with this method")
+					r.errorf(obj.Pos(), "\tin named interface type %q", obj.Name())
+				}
+			}
+
+			// Now look at all literal interface types (includes named ones again).
+			for e, tv := range info.Types {
+				if e, ok := e.(*ast.InterfaceType); ok {
+					_ = e
+					_ = tv.Type.(*types.Interface)
+					// TODO(adonovan): implement same check as above.
+				}
+			}
+		}
+
+		// assignability
+		//
+		// Find the set of concrete or abstract methods directly
+		// coupled to abstract method 'from' by some
+		// satisfy.Constraint, and rename them too.
+		for key := range r.satisfy() {
+			// key = (lhs, rhs) where lhs is always an interface.
+
+			lsel := r.msets.MethodSet(key.LHS).Lookup(from.Pkg(), from.Name())
+			if lsel == nil {
+				continue
+			}
+			rmethods := r.msets.MethodSet(key.RHS)
+			rsel := rmethods.Lookup(from.Pkg(), from.Name())
+			if rsel == nil {
+				continue
+			}
+
+			// If both sides have a method of this name,
+			// and one of them is m, the other must be coupled.
+			var coupled *types.Func
+			switch from {
+			case lsel.Obj():
+				coupled = rsel.Obj().(*types.Func)
+			case rsel.Obj():
+				coupled = lsel.Obj().(*types.Func)
+			default:
+				continue
+			}
+
+			// We must treat concrete-to-interface
+			// constraints like an implicit selection C.f of
+			// each interface method I.f, and check that the
+			// renaming leaves the selection unchanged and
+			// unambiguous.
+			//
+			// Fun fact: the implicit selection of C.f
+			// 	type I interface{f()}
+			// 	type C struct{I}
+			// 	func (C) g()
+			//      var _ I = C{} // here
+			// yields abstract method I.f.  This can make error
+			// messages less than obvious.
+			//
+			if !isInterface(key.RHS) {
+				// The logic below was derived from checkSelections.
+
+				rtosel := rmethods.Lookup(from.Pkg(), r.to)
+				if rtosel != nil {
+					rto := rtosel.Obj().(*types.Func)
+					delta := len(rsel.Index()) - len(rtosel.Index())
+					if delta < 0 {
+						continue // no ambiguity
+					}
+
+					// TODO(adonovan): record the constraint's position.
+					keyPos := token.NoPos
+
+					r.errorf(from.Pos(), "renaming this method %q to %q",
+						from.Name(), r.to)
+					if delta == 0 {
+						// analogous to same-block conflict
+						r.errorf(keyPos, "\twould make the %s method of %s invoked via interface %s ambiguous",
+							r.to, key.RHS, key.LHS)
+						r.errorf(rto.Pos(), "\twith (%s).%s",
+							recv(rto).Type(), r.to)
+					} else {
+						// analogous to super-block conflict
+						r.errorf(keyPos, "\twould change the %s method of %s invoked via interface %s",
+							r.to, key.RHS, key.LHS)
+						r.errorf(coupled.Pos(), "\tfrom (%s).%s",
+							recv(coupled).Type(), r.to)
+						r.errorf(rto.Pos(), "\tto (%s).%s",
+							recv(rto).Type(), r.to)
+					}
+					return // one error is enough
+				}
+			}
+
+			if !r.changeMethods {
+				// This should be unreachable.
+				r.errorf(from.Pos(), "internal error: during renaming of abstract method %s", from)
+				r.errorf(coupled.Pos(), "\tchangedMethods=false, coupled method=%s", coupled)
+				r.errorf(from.Pos(), "\tPlease file a bug report")
+				return
+			}
+
+			// Rename the coupled method to preserve assignability.
+			r.check(coupled)
+		}
+	} else {
+		// Concrete method
+
+		// declaration
+		prev, indices, _ := types.LookupFieldOrMethod(R, true, from.Pkg(), r.to)
+		if prev != nil && len(indices) == 1 {
+			r.errorf(from.Pos(), "renaming this method %q to %q",
+				from.Name(), r.to)
+			r.errorf(prev.Pos(), "\twould conflict with this %s",
+				objectKind(prev))
+			return
+		}
+
+		// assignability
+		//
+		// Find the set of abstract methods coupled to concrete
+		// method 'from' by some satisfy.Constraint, and rename
+		// them too.
+		//
+		// Coupling may be indirect, e.g. I.f <-> C.f via type D.
+		//
+		// 	type I interface {f()}
+		//	type C int
+		//	type (C) f()
+		//	type D struct{C}
+		//	var _ I = D{}
+		//
+		for key := range r.satisfy() {
+			// key = (lhs, rhs) where lhs is always an interface.
+			if isInterface(key.RHS) {
+				continue
+			}
+			rsel := r.msets.MethodSet(key.RHS).Lookup(from.Pkg(), from.Name())
+			if rsel == nil || rsel.Obj() != from {
+				continue // rhs does not have the method
+			}
+			lsel := r.msets.MethodSet(key.LHS).Lookup(from.Pkg(), from.Name())
+			if lsel == nil {
+				continue
+			}
+			imeth := lsel.Obj().(*types.Func)
+
+			// imeth is the abstract method (e.g. I.f)
+			// and key.RHS is the concrete coupling type (e.g. D).
+			if !r.changeMethods {
+				r.errorf(from.Pos(), "renaming this method %q to %q",
+					from.Name(), r.to)
+				var pos token.Pos
+				var iface string
+
+				I := recv(imeth).Type()
+				if named, ok := I.(*types.Named); ok {
+					pos = named.Obj().Pos()
+					iface = "interface " + named.Obj().Name()
+				} else {
+					pos = from.Pos()
+					iface = I.String()
+				}
+				r.errorf(pos, "\twould make %s no longer assignable to %s",
+					key.RHS, iface)
+				r.errorf(imeth.Pos(), "\t(rename %s.%s if you intend to change both types)",
+					I, from.Name())
+				return // one error is enough
+			}
+
+			// Rename the coupled interface method to preserve assignability.
+			r.check(imeth)
+		}
+	}
+
+	// Check integrity of existing (field and method) selections.
+	// We skip this if there were errors above, to avoid redundant errors.
+	r.checkSelections(from)
+}
+
+func (r *renamer) checkExport(id *ast.Ident, pkg *types.Package, from types.Object) bool {
+	// Reject cross-package references if r.to is unexported.
+	// (Such references may be qualified identifiers or field/method
+	// selections.)
+	if !ast.IsExported(r.to) && pkg != from.Pkg() {
+		r.errorf(from.Pos(),
+			"renaming this %s %q to %q would make it unexported",
+			objectKind(from), from.Name(), r.to)
+		r.errorf(id.Pos(), "\tbreaking references from packages such as %q",
+			pkg.Path())
+		return false
+	}
+	return true
+}
+
+// satisfy returns the set of interface satisfaction constraints.
+func (r *renamer) satisfy() map[satisfy.Constraint]bool {
+	if r.satisfyConstraints == nil {
+		// Compute on demand: it's expensive.
+		var f satisfy.Finder
+		for _, info := range r.packages {
+			f.Find(&info.Info, info.Files)
+		}
+		r.satisfyConstraints = f.Result
+	}
+	return r.satisfyConstraints
+}
+
+// -- helpers ----------------------------------------------------------
+
+// recv returns the method's receiver.
+func recv(meth *types.Func) *types.Var {
+	return meth.Type().(*types.Signature).Recv()
+}
+
+// someUse returns an arbitrary use of obj within info.
+func someUse(info *loader.PackageInfo, obj types.Object) *ast.Ident {
+	for id, o := range info.Uses {
+		if o == obj {
+			return id
+		}
+	}
+	return nil
+}
+
+// -- Plundered from golang.org/x/tools/go/ssa -----------------
+
+func isInterface(T types.Type) bool { return types.IsInterface(T) }
+
+func deref(typ types.Type) types.Type {
+	if p, _ := typ.(*types.Pointer); p != nil {
+		return p.Elem()
+	}
+	return typ
+}
diff --git a/go/src/golang.org/x/tools/refactor/rename/rename.el b/go/src/golang.org/x/tools/refactor/rename/go-rename.el
similarity index 83%
rename from go/src/golang.org/x/tools/refactor/rename/rename.el
rename to go/src/golang.org/x/tools/refactor/rename/go-rename.el
index 139bb47..8faecc6 100644
--- a/go/src/golang.org/x/tools/refactor/rename/rename.el
+++ b/go/src/golang.org/x/tools/refactor/rename/go-rename.el
@@ -1,16 +1,25 @@
-;;; Copyright 2014 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.
-;;;
-;;; Integration of the 'gorename' tool into Emacs.
-;;;
-;;; To install:
-;;; % go get golang.org/x/tools/cmd/gorename
-;;; % go build golang.org/x/tools/cmd/gorename
-;;; % mv gorename $HOME/bin/         # or elsewhere on $PATH
-;;;
-;;; The go-rename-command variable can be customized to specify an
-;;; alternative location for the installed command.
+;;; go-rename.el --- Integration of the 'gorename' tool into Emacs.
+
+;; Copyright 2014 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.
+
+;; Version: 0.1
+;; Package-Requires: ((go-mode "1.3.1"))
+;; Keywords: tools
+
+;;; Commentary:
+
+;; To install:
+
+;; % go get golang.org/x/tools/cmd/gorename
+;; % go build golang.org/x/tools/cmd/gorename
+;; % mv gorename $HOME/bin/         # or elsewhere on $PATH
+
+;; The go-rename-command variable can be customized to specify an
+;; alternative location for the installed command.
+
+;;; Code:
 
 (require 'compile)
 (require 'go-mode)
@@ -25,6 +34,7 @@
   :type 'string
   :group 'go-rename)
 
+;;;###autoload
 (defun go-rename (new-name &optional force)
   "Rename the entity denoted by the identifier at point, using
 the `gorename' tool. With FORCE, call `gorename' with the
@@ -94,3 +104,5 @@
                             (buffer-substring (point-min) (point-max))))
 
 (provide 'go-rename)
+
+;;; go-rename.el ends here
diff --git a/go/src/golang.org/x/tools/refactor/rename/mvpkg.go b/go/src/golang.org/x/tools/refactor/rename/mvpkg.go
index bb0d9b0..927195c 100644
--- a/go/src/golang.org/x/tools/refactor/rename/mvpkg.go
+++ b/go/src/golang.org/x/tools/refactor/rename/mvpkg.go
@@ -17,6 +17,8 @@
 	"fmt"
 	"go/ast"
 	"go/build"
+	"go/format"
+	"go/token"
 	"log"
 	"os"
 	"os/exec"
@@ -238,6 +240,22 @@
 	}
 	newName := filepath.Base(m.to)
 	for _, f := range pkg.Files {
+		// Update all import comments.
+		for _, cg := range f.Comments {
+			c := cg.List[0]
+			if c.Slash >= f.Name.End() &&
+				sameLine(m.iprog.Fset, c.Slash, f.Name.End()) &&
+				(f.Decls == nil || c.Slash < f.Decls[0].Pos()) {
+				if strings.HasPrefix(c.Text, `// import "`) {
+					c.Text = `// import "` + m.to + `"`
+					break
+				}
+				if strings.HasPrefix(c.Text, `/* import "`) {
+					c.Text = `/* import "` + m.to + `" */`
+					break
+				}
+			}
+		}
 		f.Name.Name = newName // change package decl
 		filesToUpdate[f] = true
 	}
@@ -304,8 +322,13 @@
 	}
 
 	for f := range filesToUpdate {
+		var buf bytes.Buffer
+		if err := format.Node(&buf, m.iprog.Fset, f); err != nil {
+			log.Printf("failed to pretty-print syntax tree: %v", err)
+			continue
+		}
 		tokenFile := m.iprog.Fset.File(f.Pos())
-		rewriteFile(m.iprog.Fset, f, tokenFile.Name())
+		writeFile(tokenFile.Name(), buf.Bytes())
 	}
 
 	// Move the directories.
@@ -338,6 +361,11 @@
 	return moveDirectory(m.fromDir, m.toDir)
 }
 
+// sameLine reports whether two positions in the same file are on the same line.
+func sameLine(fset *token.FileSet, x, y token.Pos) bool {
+	return fset.Position(x).Line == fset.Position(y).Line
+}
+
 var moveDirectory = func(from, to string) error {
 	return os.Rename(from, to)
 }
diff --git a/go/src/golang.org/x/tools/refactor/rename/mvpkg_test.go b/go/src/golang.org/x/tools/refactor/rename/mvpkg_test.go
index 61fa354..e07b6b4 100644
--- a/go/src/golang.org/x/tools/refactor/rename/mvpkg_test.go
+++ b/go/src/golang.org/x/tools/refactor/rename/mvpkg_test.go
@@ -5,12 +5,8 @@
 package rename
 
 import (
-	"bytes"
 	"fmt"
-	"go/ast"
 	"go/build"
-	"go/format"
-	"go/token"
 	"io/ioutil"
 	"path/filepath"
 	"regexp"
@@ -79,12 +75,8 @@
 		ctxt := test.ctxt
 
 		got := make(map[string]string)
-		rewriteFile = func(fset *token.FileSet, f *ast.File, orig string) error {
-			var out bytes.Buffer
-			if err := format.Node(&out, fset, f); err != nil {
-				return err
-			}
-			got[orig] = out.String()
+		writeFile = func(filename string, content []byte) error {
+			got[filename] = string(content)
 			return nil
 		}
 		moveDirectory = func(from, to string) error {
@@ -238,6 +230,43 @@
 `,
 			},
 		},
+		// package import comments
+		{
+			ctxt: fakeContext(map[string][]string{"foo": {`package foo // import "baz"`}}),
+			from: "foo", to: "bar",
+			want: map[string]string{"/go/src/bar/0.go": `package bar // import "bar"
+`},
+		},
+		{
+			ctxt: fakeContext(map[string][]string{"foo": {`package foo /* import "baz" */`}}),
+			from: "foo", to: "bar",
+			want: map[string]string{"/go/src/bar/0.go": `package bar /* import "bar" */
+`},
+		},
+		{
+			ctxt: fakeContext(map[string][]string{"foo": {`package foo       // import "baz"`}}),
+			from: "foo", to: "bar",
+			want: map[string]string{"/go/src/bar/0.go": `package bar // import "bar"
+`},
+		},
+		{
+			ctxt: fakeContext(map[string][]string{"foo": {`package foo
+// import " this is not an import comment`}}),
+			from: "foo", to: "bar",
+			want: map[string]string{"/go/src/bar/0.go": `package bar
+
+// import " this is not an import comment
+`},
+		},
+		{
+			ctxt: fakeContext(map[string][]string{"foo": {`package foo
+/* import " this is not an import comment */`}}),
+			from: "foo", to: "bar",
+			want: map[string]string{"/go/src/bar/0.go": `package bar
+
+/* import " this is not an import comment */
+`},
+		},
 	}
 
 	for _, test := range tests {
@@ -267,12 +296,8 @@
 			}
 			got[path] = string(bytes)
 		})
-		rewriteFile = func(fset *token.FileSet, f *ast.File, orig string) error {
-			var out bytes.Buffer
-			if err := format.Node(&out, fset, f); err != nil {
-				return err
-			}
-			got[orig] = out.String()
+		writeFile = func(filename string, content []byte) error {
+			got[filename] = string(content)
 			return nil
 		}
 		moveDirectory = func(from, to string) error {
diff --git a/go/src/golang.org/x/tools/refactor/rename/rename.go b/go/src/golang.org/x/tools/refactor/rename/rename.go
index a028c21..be47701 100644
--- a/go/src/golang.org/x/tools/refactor/rename/rename.go
+++ b/go/src/golang.org/x/tools/refactor/rename/rename.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 // Package rename contains the implementation of the 'gorename' command
 // whose main function is in golang.org/x/tools/cmd/gorename.
 // See the Usage constant for the command documentation.
@@ -16,15 +18,18 @@
 	"go/format"
 	"go/parser"
 	"go/token"
+	"go/types"
+	"io"
 	"io/ioutil"
+	"log"
 	"os"
+	"os/exec"
 	"path"
 	"sort"
 	"strconv"
 	"strings"
 
 	"golang.org/x/tools/go/loader"
-	"golang.org/x/tools/go/types"
 	"golang.org/x/tools/go/types/typeutil"
 	"golang.org/x/tools/refactor/importgraph"
 	"golang.org/x/tools/refactor/satisfy"
@@ -76,7 +81,7 @@
            (In due course this bug will be fixed by moving certain
            analyses into the type-checker.)
 
--dryrun    causes the tool to report conflicts but not update any files.
+-d         display diffs instead of rewriting files
 
 -v         enables verbose logging.
 
@@ -96,11 +101,11 @@
 
 Examples:
 
-% gorename -offset file.go:#123 -to foo
+$ gorename -offset file.go:#123 -to foo
 
   Rename the object whose identifier is at byte offset 123 within file file.go.
 
-% gorename -from \"bytes\".Buffer.Len' -to Size
+$ gorename -from '"bytes".Buffer.Len' -to Size
 
   Rename the "Len" method of the *bytes.Buffer type to "Size".
 
@@ -137,8 +142,12 @@
 	// It may even cause gorename to crash.  TODO(adonovan): fix that.
 	Force bool
 
-	// DryRun causes the tool to report conflicts but not update any files.
-	DryRun bool
+	// Diff causes the tool to display diffs instead of rewriting files.
+	Diff bool
+
+	// DiffCmd specifies the diff command used by the -d feature.
+	// (The command must accept a -u flag and two filename arguments.)
+	DiffCmd = "diff"
 
 	// ConflictError is returned by Main when it aborts the renaming due to conflicts.
 	// (It is distinguished because the interesting errors are the conflicts themselves.)
@@ -148,6 +157,8 @@
 	Verbose bool
 )
 
+var stdout io.Writer = os.Stdout
+
 type renamer struct {
 	iprog              *loader.Program
 	objsToUpdate       map[types.Object]bool
@@ -212,6 +223,11 @@
 		return fmt.Errorf("-to %q: not a valid identifier", to)
 	}
 
+	if Diff {
+		defer func(saved func(string, []byte) error) { writeFile = saved }(writeFile)
+		writeFile = diff
+	}
+
 	var spec *spec
 	var err error
 	if fromFlag != "" {
@@ -248,7 +264,7 @@
 		// package defining the object, plus their tests.
 
 		if Verbose {
-			fmt.Fprintln(os.Stderr, "Potentially global renaming; scanning workspace...")
+			log.Print("Potentially global renaming; scanning workspace...")
 		}
 
 		// Scan the workspace and build the import graph.
@@ -329,10 +345,6 @@
 	if r.hadConflicts && !Force {
 		return ConflictError
 	}
-	if DryRun {
-		// TODO(adonovan): print the delta?
-		return nil
-	}
 	return r.update()
 }
 
@@ -361,7 +373,7 @@
 		}
 		sort.Strings(list)
 		for _, pkg := range list {
-			fmt.Fprintf(os.Stderr, "Loading package: %s\n", pkg)
+			log.Printf("Loading package: %s", pkg)
 		}
 	}
 
@@ -433,21 +445,30 @@
 					npkgs++
 					first = false
 					if Verbose {
-						fmt.Fprintf(os.Stderr, "Updating package %s\n",
-							info.Pkg.Path())
+						log.Printf("Updating package %s", info.Pkg.Path())
 					}
 				}
-				if err := rewriteFile(r.iprog.Fset, f, tokenFile.Name()); err != nil {
-					fmt.Fprintf(os.Stderr, "gorename: %s\n", err)
+
+				filename := tokenFile.Name()
+				var buf bytes.Buffer
+				if err := format.Node(&buf, r.iprog.Fset, f); err != nil {
+					log.Printf("failed to pretty-print syntax tree: %v", err)
+					nerrs++
+					continue
+				}
+				if err := writeFile(filename, buf.Bytes()); err != nil {
+					log.Print(err)
 					nerrs++
 				}
 			}
 		}
 	}
-	fmt.Fprintf(os.Stderr, "Renamed %d occurrence%s in %d file%s in %d package%s.\n",
-		nidents, plural(nidents),
-		len(filesToUpdate), plural(len(filesToUpdate)),
-		npkgs, plural(npkgs))
+	if !Diff {
+		fmt.Printf("Renamed %d occurrence%s in %d file%s in %d package%s.\n",
+			nidents, plural(nidents),
+			len(filesToUpdate), plural(len(filesToUpdate)),
+			npkgs, plural(npkgs))
+	}
 	if nerrs > 0 {
 		return fmt.Errorf("failed to rewrite %d file%s", nerrs, plural(nerrs))
 	}
@@ -461,15 +482,29 @@
 	return ""
 }
 
-var rewriteFile = func(fset *token.FileSet, f *ast.File, filename string) (err error) {
-	// TODO(adonovan): print packages and filenames in a form useful
-	// to editors (so they can reload files).
-	if Verbose {
-		fmt.Fprintf(os.Stderr, "\t%s\n", filename)
+// writeFile is a seam for testing and for the -d flag.
+var writeFile = reallyWriteFile
+
+func reallyWriteFile(filename string, content []byte) error {
+	return ioutil.WriteFile(filename, content, 0644)
+}
+
+func diff(filename string, content []byte) error {
+	renamed := fmt.Sprintf("%s.%d.renamed", filename, os.Getpid())
+	if err := ioutil.WriteFile(renamed, content, 0644); err != nil {
+		return err
 	}
-	var buf bytes.Buffer
-	if err := format.Node(&buf, fset, f); err != nil {
-		return fmt.Errorf("failed to pretty-print syntax tree: %v", err)
+	defer os.Remove(renamed)
+
+	diff, err := exec.Command(DiffCmd, "-u", filename, renamed).CombinedOutput()
+	if len(diff) > 0 {
+		// diff exits with a non-zero status when the files don't match.
+		// Ignore that failure as long as we get output.
+		stdout.Write(diff)
+		return nil
 	}
-	return ioutil.WriteFile(filename, buf.Bytes(), 0644)
+	if err != nil {
+		return fmt.Errorf("computing diff: %v", err)
+	}
+	return nil
 }
diff --git a/go/src/golang.org/x/tools/refactor/rename/rename14.go b/go/src/golang.org/x/tools/refactor/rename/rename14.go
new file mode 100644
index 0000000..e4ccc06
--- /dev/null
+++ b/go/src/golang.org/x/tools/refactor/rename/rename14.go
@@ -0,0 +1,510 @@
+// Copyright 2014 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.
+
+// +build !go1.5
+
+// Package rename contains the implementation of the 'gorename' command
+// whose main function is in golang.org/x/tools/cmd/gorename.
+// See the Usage constant for the command documentation.
+package rename // import "golang.org/x/tools/refactor/rename"
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/format"
+	"go/parser"
+	"go/token"
+	"io"
+	"io/ioutil"
+	"log"
+	"os"
+	"os/exec"
+	"path"
+	"sort"
+	"strconv"
+	"strings"
+
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/go/types/typeutil"
+	"golang.org/x/tools/refactor/importgraph"
+	"golang.org/x/tools/refactor/satisfy"
+)
+
+const Usage = `gorename: precise type-safe renaming of identifiers in Go source code.
+
+Usage:
+
+ gorename (-from <spec> | -offset <file>:#<byte-offset>) -to <name> [-force]
+
+You must specify the object (named entity) to rename using the -offset
+or -from flag.  Exactly one must be specified.
+
+Flags:
+
+-offset    specifies the filename and byte offset of an identifier to rename.
+           This form is intended for use by text editors.
+
+-from      specifies the object to rename using a query notation;
+           This form is intended for interactive use at the command line.
+           A legal -from query has one of the following forms:
+
+  "encoding/json".Decoder.Decode        method of package-level named type
+  (*"encoding/json".Decoder).Decode     ditto, alternative syntax
+  "encoding/json".Decoder.buf           field of package-level named struct type
+  "encoding/json".HTMLEscape            package member (const, func, var, type)
+  "encoding/json".Decoder.Decode::x     local object x within a method
+  "encoding/json".HTMLEscape::x         local object x within a function
+  "encoding/json"::x                    object x anywhere within a package
+  json.go::x                            object x within file json.go
+
+           Double-quotes must be escaped when writing a shell command.
+           Quotes may be omitted for single-segment import paths such as "fmt".
+
+           For methods, the parens and '*' on the receiver type are both
+           optional.
+
+           It is an error if one of the ::x queries matches multiple
+           objects.
+
+-to        the new name.
+
+-force     causes the renaming to proceed even if conflicts were reported.
+           The resulting program may be ill-formed, or experience a change
+           in behaviour.
+
+           WARNING: this flag may even cause the renaming tool to crash.
+           (In due course this bug will be fixed by moving certain
+           analyses into the type-checker.)
+
+-d         display diffs instead of rewriting files
+
+-v         enables verbose logging.
+
+gorename automatically computes the set of packages that might be
+affected.  For a local renaming, this is just the package specified by
+-from or -offset, but for a potentially exported name, gorename scans
+the workspace ($GOROOT and $GOPATH).
+
+gorename rejects renamings of concrete methods that would change the
+assignability relation between types and interfaces.  If the interface
+change was intentional, initiate the renaming at the interface method.
+
+gorename rejects any renaming that would create a conflict at the point
+of declaration, or a reference conflict (ambiguity or shadowing), or
+anything else that could cause the resulting program not to compile.
+
+
+Examples:
+
+$ gorename -offset file.go:#123 -to foo
+
+  Rename the object whose identifier is at byte offset 123 within file file.go.
+
+$ gorename -from '"bytes".Buffer.Len' -to Size
+
+  Rename the "Len" method of the *bytes.Buffer type to "Size".
+
+---- TODO ----
+
+Correctness:
+- handle dot imports correctly
+- document limitations (reflection, 'implements' algorithm).
+- sketch a proof of exhaustiveness.
+
+Features:
+- support running on packages specified as *.go files on the command line
+- support running on programs containing errors (loader.Config.AllowErrors)
+- allow users to specify a scope other than "global" (to avoid being
+  stuck by neglected packages in $GOPATH that don't build).
+- support renaming the package clause (no object)
+- support renaming an import path (no ident or object)
+  (requires filesystem + SCM updates).
+- detect and reject edits to autogenerated files (cgo, protobufs)
+  and optionally $GOROOT packages.
+- report all conflicts, or at least all qualitatively distinct ones.
+  Sometimes we stop to avoid redundancy, but
+  it may give a disproportionate sense of safety in -force mode.
+- support renaming all instances of a pattern, e.g.
+  all receiver vars of a given type,
+  all local variables of a given type,
+  all PkgNames for a given package.
+- emit JSON output for other editors and tools.
+`
+
+var (
+	// Force enables patching of the source files even if conflicts were reported.
+	// The resulting program may be ill-formed.
+	// It may even cause gorename to crash.  TODO(adonovan): fix that.
+	Force bool
+
+	// Diff causes the tool to display diffs instead of rewriting files.
+	Diff bool
+
+	// DiffCmd specifies the diff command used by the -d feature.
+	// (The command must accept a -u flag and two filename arguments.)
+	DiffCmd = "diff"
+
+	// ConflictError is returned by Main when it aborts the renaming due to conflicts.
+	// (It is distinguished because the interesting errors are the conflicts themselves.)
+	ConflictError = errors.New("renaming aborted due to conflicts")
+
+	// Verbose enables extra logging.
+	Verbose bool
+)
+
+var stdout io.Writer = os.Stdout
+
+type renamer struct {
+	iprog              *loader.Program
+	objsToUpdate       map[types.Object]bool
+	hadConflicts       bool
+	to                 string
+	satisfyConstraints map[satisfy.Constraint]bool
+	packages           map[*types.Package]*loader.PackageInfo // subset of iprog.AllPackages to inspect
+	msets              typeutil.MethodSetCache
+	changeMethods      bool
+}
+
+var reportError = func(posn token.Position, message string) {
+	fmt.Fprintf(os.Stderr, "%s: %s\n", posn, message)
+}
+
+// importName renames imports of the package with the given path in
+// the given package.  If fromName is not empty, only imports as
+// fromName will be renamed.  If the renaming would lead to a conflict,
+// the file is left unchanged.
+func importName(iprog *loader.Program, info *loader.PackageInfo, fromPath, fromName, to string) error {
+	for _, f := range info.Files {
+		var from types.Object
+		for _, imp := range f.Imports {
+			importPath, _ := strconv.Unquote(imp.Path.Value)
+			importName := path.Base(importPath)
+			if imp.Name != nil {
+				importName = imp.Name.Name
+			}
+			if importPath == fromPath && (fromName == "" || importName == fromName) {
+				from = info.Implicits[imp]
+				break
+			}
+		}
+		if from == nil {
+			continue
+		}
+		r := renamer{
+			iprog:        iprog,
+			objsToUpdate: make(map[types.Object]bool),
+			to:           to,
+			packages:     map[*types.Package]*loader.PackageInfo{info.Pkg: info},
+		}
+		r.check(from)
+		if r.hadConflicts {
+			continue // ignore errors; leave the existing name
+		}
+		if err := r.update(); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func Main(ctxt *build.Context, offsetFlag, fromFlag, to string) error {
+	// -- Parse the -from or -offset specifier ----------------------------
+
+	if (offsetFlag == "") == (fromFlag == "") {
+		return fmt.Errorf("exactly one of the -from and -offset flags must be specified")
+	}
+
+	if !isValidIdentifier(to) {
+		return fmt.Errorf("-to %q: not a valid identifier", to)
+	}
+
+	if Diff {
+		defer func(saved func(string, []byte) error) { writeFile = saved }(writeFile)
+		writeFile = diff
+	}
+
+	var spec *spec
+	var err error
+	if fromFlag != "" {
+		spec, err = parseFromFlag(ctxt, fromFlag)
+	} else {
+		spec, err = parseOffsetFlag(ctxt, offsetFlag)
+	}
+	if err != nil {
+		return err
+	}
+
+	if spec.fromName == to {
+		return fmt.Errorf("the old and new names are the same: %s", to)
+	}
+
+	// -- Load the program consisting of the initial package  -------------
+
+	iprog, err := loadProgram(ctxt, map[string]bool{spec.pkg: true})
+	if err != nil {
+		return err
+	}
+
+	fromObjects, err := findFromObjects(iprog, spec)
+	if err != nil {
+		return err
+	}
+
+	// -- Load a larger program, for global renamings ---------------------
+
+	if requiresGlobalRename(fromObjects, to) {
+		// For a local refactoring, we needn't load more
+		// packages, but if the renaming affects the package's
+		// API, we we must load all packages that depend on the
+		// package defining the object, plus their tests.
+
+		if Verbose {
+			log.Print("Potentially global renaming; scanning workspace...")
+		}
+
+		// Scan the workspace and build the import graph.
+		_, rev, errors := importgraph.Build(ctxt)
+		if len(errors) > 0 {
+			// With a large GOPATH tree, errors are inevitable.
+			// Report them but proceed.
+			fmt.Fprintf(os.Stderr, "While scanning Go workspace:\n")
+			for path, err := range errors {
+				fmt.Fprintf(os.Stderr, "Package %q: %s.\n", path, err)
+			}
+		}
+
+		// Enumerate the set of potentially affected packages.
+		affectedPackages := make(map[string]bool)
+		for _, obj := range fromObjects {
+			// External test packages are never imported,
+			// so they will never appear in the graph.
+			for path := range rev.Search(obj.Pkg().Path()) {
+				affectedPackages[path] = true
+			}
+		}
+
+		// TODO(adonovan): allow the user to specify the scope,
+		// or -ignore patterns?  Computing the scope when we
+		// don't (yet) support inputs containing errors can make
+		// the tool rather brittle.
+
+		// Re-load the larger program.
+		iprog, err = loadProgram(ctxt, affectedPackages)
+		if err != nil {
+			return err
+		}
+
+		fromObjects, err = findFromObjects(iprog, spec)
+		if err != nil {
+			return err
+		}
+	}
+
+	// -- Do the renaming -------------------------------------------------
+
+	r := renamer{
+		iprog:        iprog,
+		objsToUpdate: make(map[types.Object]bool),
+		to:           to,
+		packages:     make(map[*types.Package]*loader.PackageInfo),
+	}
+
+	// A renaming initiated at an interface method indicates the
+	// intention to rename abstract and concrete methods as needed
+	// to preserve assignability.
+	for _, obj := range fromObjects {
+		if obj, ok := obj.(*types.Func); ok {
+			recv := obj.Type().(*types.Signature).Recv()
+			if recv != nil && isInterface(recv.Type().Underlying()) {
+				r.changeMethods = true
+				break
+			}
+		}
+	}
+
+	// Only the initially imported packages (iprog.Imported) and
+	// their external tests (iprog.Created) should be inspected or
+	// modified, as only they have type-checked functions bodies.
+	// The rest are just dependencies, needed only for package-level
+	// type information.
+	for _, info := range iprog.Imported {
+		r.packages[info.Pkg] = info
+	}
+	for _, info := range iprog.Created { // (tests)
+		r.packages[info.Pkg] = info
+	}
+
+	for _, from := range fromObjects {
+		r.check(from)
+	}
+	if r.hadConflicts && !Force {
+		return ConflictError
+	}
+	return r.update()
+}
+
+// loadProgram loads the specified set of packages (plus their tests)
+// and all their dependencies, from source, through the specified build
+// context.  Only packages in pkgs will have their functions bodies typechecked.
+func loadProgram(ctxt *build.Context, pkgs map[string]bool) (*loader.Program, error) {
+	conf := loader.Config{
+		Build:      ctxt,
+		ParserMode: parser.ParseComments,
+
+		// TODO(adonovan): enable this.  Requires making a lot of code more robust!
+		AllowErrors: false,
+	}
+
+	// Optimization: don't type-check the bodies of functions in our
+	// dependencies, since we only need exported package members.
+	conf.TypeCheckFuncBodies = func(p string) bool {
+		return pkgs[p] || pkgs[strings.TrimSuffix(p, "_test")]
+	}
+
+	if Verbose {
+		var list []string
+		for pkg := range pkgs {
+			list = append(list, pkg)
+		}
+		sort.Strings(list)
+		for _, pkg := range list {
+			log.Printf("Loading package: %s", pkg)
+		}
+	}
+
+	for pkg := range pkgs {
+		conf.ImportWithTests(pkg)
+	}
+	return conf.Load()
+}
+
+// requiresGlobalRename reports whether this renaming could potentially
+// affect other packages in the Go workspace.
+func requiresGlobalRename(fromObjects []types.Object, to string) bool {
+	var tfm bool
+	for _, from := range fromObjects {
+		if from.Exported() {
+			return true
+		}
+		switch objectKind(from) {
+		case "type", "field", "method":
+			tfm = true
+		}
+	}
+	if ast.IsExported(to) && tfm {
+		// A global renaming may be necessary even if we're
+		// exporting a previous unexported name, since if it's
+		// the name of a type, field or method, this could
+		// change selections in other packages.
+		// (We include "type" in this list because a type
+		// used as an embedded struct field entails a field
+		// renaming.)
+		return true
+	}
+	return false
+}
+
+// update updates the input files.
+func (r *renamer) update() error {
+	// We use token.File, not filename, since a file may appear to
+	// belong to multiple packages and be parsed more than once.
+	// token.File captures this distinction; filename does not.
+	var nidents int
+	var filesToUpdate = make(map[*token.File]bool)
+	for _, info := range r.packages {
+		// Mutate the ASTs and note the filenames.
+		for id, obj := range info.Defs {
+			if r.objsToUpdate[obj] {
+				nidents++
+				id.Name = r.to
+				filesToUpdate[r.iprog.Fset.File(id.Pos())] = true
+			}
+		}
+		for id, obj := range info.Uses {
+			if r.objsToUpdate[obj] {
+				nidents++
+				id.Name = r.to
+				filesToUpdate[r.iprog.Fset.File(id.Pos())] = true
+			}
+		}
+	}
+
+	// TODO(adonovan): don't rewrite cgo + generated files.
+	var nerrs, npkgs int
+	for _, info := range r.packages {
+		first := true
+		for _, f := range info.Files {
+			tokenFile := r.iprog.Fset.File(f.Pos())
+			if filesToUpdate[tokenFile] {
+				if first {
+					npkgs++
+					first = false
+					if Verbose {
+						log.Printf("Updating package %s", info.Pkg.Path())
+					}
+				}
+
+				filename := tokenFile.Name()
+				var buf bytes.Buffer
+				if err := format.Node(&buf, r.iprog.Fset, f); err != nil {
+					log.Printf("failed to pretty-print syntax tree: %v", err)
+					nerrs++
+					continue
+				}
+				if err := writeFile(filename, buf.Bytes()); err != nil {
+					log.Print(err)
+					nerrs++
+				}
+			}
+		}
+	}
+	if !Diff {
+		fmt.Printf("Renamed %d occurrence%s in %d file%s in %d package%s.\n",
+			nidents, plural(nidents),
+			len(filesToUpdate), plural(len(filesToUpdate)),
+			npkgs, plural(npkgs))
+	}
+	if nerrs > 0 {
+		return fmt.Errorf("failed to rewrite %d file%s", nerrs, plural(nerrs))
+	}
+	return nil
+}
+
+func plural(n int) string {
+	if n != 1 {
+		return "s"
+	}
+	return ""
+}
+
+// writeFile is a seam for testing and for the -d flag.
+var writeFile = reallyWriteFile
+
+func reallyWriteFile(filename string, content []byte) error {
+	return ioutil.WriteFile(filename, content, 0644)
+}
+
+func diff(filename string, content []byte) error {
+	renamed := fmt.Sprintf("%s.%d.renamed", filename, os.Getpid())
+	if err := ioutil.WriteFile(renamed, content, 0644); err != nil {
+		return err
+	}
+	defer os.Remove(renamed)
+
+	diff, err := exec.Command(DiffCmd, "-u", filename, renamed).CombinedOutput()
+	if len(diff) > 0 {
+		// diff exits with a non-zero status when the files don't match.
+		// Ignore that failure as long as we get output.
+		stdout.Write(diff)
+		return nil
+	}
+	if err != nil {
+		return fmt.Errorf("computing diff: %v", err)
+	}
+	return nil
+}
diff --git a/go/src/golang.org/x/tools/refactor/rename/rename_test.go b/go/src/golang.org/x/tools/refactor/rename/rename_test.go
index 1d282a1..3670319 100644
--- a/go/src/golang.org/x/tools/refactor/rename/rename_test.go
+++ b/go/src/golang.org/x/tools/refactor/rename/rename_test.go
@@ -7,12 +7,12 @@
 import (
 	"bytes"
 	"fmt"
-	"go/ast"
 	"go/build"
-	"go/format"
 	"go/token"
+	"os"
 	"path/filepath"
 	"regexp"
+	"runtime"
 	"strings"
 	"testing"
 
@@ -22,11 +22,11 @@
 // TODO(adonovan): test reported source positions, somehow.
 
 func TestConflicts(t *testing.T) {
-	defer func(savedDryRun bool, savedReportError func(token.Position, string)) {
-		DryRun = savedDryRun
+	defer func(savedWriteFile func(string, []byte) error, savedReportError func(token.Position, string)) {
+		writeFile = savedWriteFile
 		reportError = savedReportError
-	}(DryRun, reportError)
-	DryRun = true
+	}(writeFile, reportError)
+	writeFile = func(string, []byte) error { return nil }
 
 	var ctxt *build.Context
 	for _, test := range []struct {
@@ -417,9 +417,9 @@
 }
 
 func TestRewrites(t *testing.T) {
-	defer func(savedRewriteFile func(*token.FileSet, *ast.File, string) error) {
-		rewriteFile = savedRewriteFile
-	}(rewriteFile)
+	defer func(savedWriteFile func(string, []byte) error) {
+		writeFile = savedWriteFile
+	}(writeFile)
 
 	var ctxt *build.Context
 	for _, test := range []struct {
@@ -721,6 +721,57 @@
 			},
 		},
 
+		// Renaming of embedded field that is a qualified reference with the '-from' flag.
+		// (Regression test for bug 12038.)
+		{
+			ctxt: fakeContext(map[string][]string{
+				"foo": {`package foo; type T int`},
+				"main": {`package main
+
+import "foo"
+
+type V struct{ *foo.T }
+`},
+			}),
+			from: "(main.V).T", to: "U", // the "T" in *foo.T
+			want: map[string]string{
+				"/go/src/foo/0.go": `package foo
+
+type U int
+`,
+				"/go/src/main/0.go": `package main
+
+import "foo"
+
+type V struct{ *foo.U }
+`,
+			},
+		},
+		{
+			ctxt: fakeContext(map[string][]string{
+				"foo": {`package foo; type T int`},
+				"main": {`package main
+
+import "foo"
+
+type V struct{ foo.T }
+`},
+			}),
+			from: "(main.V).T", to: "U", // the "T" in *foo.T
+			want: map[string]string{
+				"/go/src/foo/0.go": `package foo
+
+type U int
+`,
+				"/go/src/main/0.go": `package main
+
+import "foo"
+
+type V struct{ foo.U }
+`,
+			},
+		},
+
 		// Interface method renaming.
 		{
 			ctxt: fakeContext(map[string][]string{
@@ -977,12 +1028,8 @@
 		}
 
 		got := make(map[string]string)
-		rewriteFile = func(fset *token.FileSet, f *ast.File, orig string) error {
-			var out bytes.Buffer
-			if err := format.Node(&out, fset, f); err != nil {
-				return err
-			}
-			got[filepath.ToSlash(orig)] = out.String()
+		writeFile = func(filename string, content []byte) error {
+			got[filepath.ToSlash(filename)] = string(content)
 			return nil
 		}
 
@@ -1017,6 +1064,38 @@
 	}
 }
 
+func TestDiff(t *testing.T) {
+	if runtime.GOOS == "windows" {
+		t.Skipf("diff tool non-existent for windows on builders")
+	}
+
+	defer func() {
+		Diff = false
+		stdout = os.Stdout
+	}()
+	Diff = true
+	stdout = new(bytes.Buffer)
+
+	if err := Main(&build.Default, "", `"golang.org/x/tools/refactor/rename".justHereForTestingDiff`, "Foo"); err != nil {
+		t.Fatal(err)
+	}
+
+	// NB: there are tabs in the string literal!
+	if !strings.Contains(stdout.(fmt.Stringer).String(), `
+-func justHereForTestingDiff() {
+-	justHereForTestingDiff()
++func Foo() {
++	Foo()
+ }
+`) {
+		t.Errorf("unexpected diff:\n<<%s>>", stdout)
+	}
+}
+
+func justHereForTestingDiff() {
+	justHereForTestingDiff()
+}
+
 // ---------------------------------------------------------------------
 
 // Simplifying wrapper around buildutil.FakeContext for packages whose
diff --git a/go/src/golang.org/x/tools/refactor/rename/spec.go b/go/src/golang.org/x/tools/refactor/rename/spec.go
index 3c73653..259404d 100644
--- a/go/src/golang.org/x/tools/refactor/rename/spec.go
+++ b/go/src/golang.org/x/tools/refactor/rename/spec.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package rename
 
 // This file contains logic related to specifying a renaming: parsing of
@@ -15,6 +17,8 @@
 	"go/build"
 	"go/parser"
 	"go/token"
+	"go/types"
+	"log"
 	"os"
 	"path/filepath"
 	"strconv"
@@ -22,7 +26,6 @@
 
 	"golang.org/x/tools/go/buildutil"
 	"golang.org/x/tools/go/loader"
-	"golang.org/x/tools/go/types"
 )
 
 // A spec specifies an entity to rename.
@@ -113,9 +116,13 @@
 		spec.fromName = spec.searchFor
 	}
 
+	cwd, err := os.Getwd()
+	if err != nil {
+		return nil, err
+	}
+
 	// Sanitize the package.
-	// TODO(adonovan): test with relative packages.  May need loader changes.
-	bp, err := ctxt.Import(spec.pkg, ".", build.FindOnly)
+	bp, err := ctxt.Import(spec.pkg, cwd, build.FindOnly)
 	if err != nil {
 		return nil, fmt.Errorf("can't find package %q", spec.pkg)
 	}
@@ -126,7 +133,7 @@
 	}
 
 	if Verbose {
-		fmt.Fprintf(os.Stderr, "-from spec: %+v\n", spec)
+		log.Printf("-from spec: %+v", spec)
 	}
 
 	return &spec, nil
@@ -271,20 +278,23 @@
 	// for main packages, even though that's not an import path.
 	// Seems like a bug.
 	//
-	// pkgObj := iprog.ImportMap[spec.pkg]
-	// if pkgObj == nil {
+	// pkg := iprog.ImportMap[spec.pkg]
+	// if pkg == nil {
 	// 	return fmt.Errorf("cannot find package %s", spec.pkg) // can't happen?
 	// }
+	// info := iprog.AllPackages[pkg]
 
 	// Workaround: lookup by value.
-	var pkgObj *types.Package
-	for pkg := range iprog.AllPackages {
+	var info *loader.PackageInfo
+	var pkg *types.Package
+	for pkg, info = range iprog.AllPackages {
 		if pkg.Path() == spec.pkg {
-			pkgObj = pkg
 			break
 		}
 	}
-	info := iprog.AllPackages[pkgObj]
+	if info == nil {
+		return nil, fmt.Errorf("package %q was not loaded", spec.pkg)
+	}
 
 	objects, err := findObjects(info, spec)
 	if err != nil {
@@ -451,6 +461,15 @@
 		}
 
 		if spec.searchFor == "" {
+			// If it is an embedded field, return the type of the field.
+			if v, ok := obj.(*types.Var); ok && v.Anonymous() {
+				switch t := v.Type().(type) {
+				case *types.Pointer:
+					return []types.Object{t.Elem().(*types.Named).Obj()}, nil
+				case *types.Named:
+					return []types.Object{t.Obj()}, nil
+				}
+			}
 			return []types.Object{obj}, nil
 		}
 
diff --git a/go/src/golang.org/x/tools/refactor/rename/spec14.go b/go/src/golang.org/x/tools/refactor/rename/spec14.go
new file mode 100644
index 0000000..7634ae8
--- /dev/null
+++ b/go/src/golang.org/x/tools/refactor/rename/spec14.go
@@ -0,0 +1,568 @@
+// Copyright 2014 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.
+
+// +build !go1.5
+
+package rename
+
+// This file contains logic related to specifying a renaming: parsing of
+// the flags as a form of query, and finding the object(s) it denotes.
+// See Usage for flag details.
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/parser"
+	"go/token"
+	"log"
+	"os"
+	"path/filepath"
+	"strconv"
+	"strings"
+
+	"golang.org/x/tools/go/buildutil"
+	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/types"
+)
+
+// A spec specifies an entity to rename.
+//
+// It is populated from an -offset flag or -from query;
+// see Usage for the allowed -from query forms.
+//
+type spec struct {
+	// pkg is the package containing the position
+	// specified by the -from or -offset flag.
+	// If filename == "", our search for the 'from' entity
+	// is restricted to this package.
+	pkg string
+
+	// The original name of the entity being renamed.
+	// If the query had a ::from component, this is that;
+	// otherwise it's the last segment, e.g.
+	//   (encoding/json.Decoder).from
+	//   encoding/json.from
+	fromName string
+
+	// -- The remaining fields are private to this file.  All are optional. --
+
+	// The query's ::x suffix, if any.
+	searchFor string
+
+	// e.g. "Decoder" in "(encoding/json.Decoder).fieldOrMethod"
+	//                or "encoding/json.Decoder
+	pkgMember string
+
+	// e.g. fieldOrMethod in "(encoding/json.Decoder).fieldOrMethod"
+	typeMember string
+
+	// Restricts the query to this file.
+	// Implied by -from="file.go::x" and -offset flags.
+	filename string
+
+	// Byte offset of the 'from' identifier within the file named 'filename'.
+	// -offset mode only.
+	offset int
+}
+
+// parseFromFlag interprets the "-from" flag value as a renaming specification.
+// See Usage in rename.go for valid formats.
+func parseFromFlag(ctxt *build.Context, fromFlag string) (*spec, error) {
+	var spec spec
+	var main string // sans "::x" suffix
+	switch parts := strings.Split(fromFlag, "::"); len(parts) {
+	case 1:
+		main = parts[0]
+	case 2:
+		main = parts[0]
+		spec.searchFor = parts[1]
+		if parts[1] == "" {
+			// error
+		}
+	default:
+		return nil, fmt.Errorf("-from %q: invalid identifier specification (see -help for formats)", fromFlag)
+	}
+
+	if strings.HasSuffix(main, ".go") {
+		// main is "filename.go"
+		if spec.searchFor == "" {
+			return nil, fmt.Errorf("-from: filename %q must have a ::name suffix", main)
+		}
+		spec.filename = main
+		if !buildutil.FileExists(ctxt, spec.filename) {
+			return nil, fmt.Errorf("no such file: %s", spec.filename)
+		}
+
+		bp, err := buildutil.ContainingPackage(ctxt, wd, spec.filename)
+		if err != nil {
+			return nil, err
+		}
+		spec.pkg = bp.ImportPath
+
+	} else {
+		// main is one of:
+		//  "importpath"
+		//  "importpath".member
+		//  (*"importpath".type).fieldormethod           (parens and star optional)
+		if err := parseObjectSpec(&spec, main); err != nil {
+			return nil, err
+		}
+	}
+
+	if spec.searchFor != "" {
+		spec.fromName = spec.searchFor
+	}
+
+	cwd, err := os.Getwd()
+	if err != nil {
+		return nil, err
+	}
+
+	// Sanitize the package.
+	bp, err := ctxt.Import(spec.pkg, cwd, build.FindOnly)
+	if err != nil {
+		return nil, fmt.Errorf("can't find package %q", spec.pkg)
+	}
+	spec.pkg = bp.ImportPath
+
+	if !isValidIdentifier(spec.fromName) {
+		return nil, fmt.Errorf("-from: invalid identifier %q", spec.fromName)
+	}
+
+	if Verbose {
+		log.Printf("-from spec: %+v", spec)
+	}
+
+	return &spec, nil
+}
+
+// parseObjectSpec parses main as one of the non-filename forms of
+// object specification.
+func parseObjectSpec(spec *spec, main string) error {
+	// Parse main as a Go expression, albeit a strange one.
+	e, _ := parser.ParseExpr(main)
+
+	if pkg := parseImportPath(e); pkg != "" {
+		// e.g. bytes or "encoding/json": a package
+		spec.pkg = pkg
+		if spec.searchFor == "" {
+			return fmt.Errorf("-from %q: package import path %q must have a ::name suffix",
+				main, main)
+		}
+		return nil
+	}
+
+	if e, ok := e.(*ast.SelectorExpr); ok {
+		x := unparen(e.X)
+
+		// Strip off star constructor, if any.
+		if star, ok := x.(*ast.StarExpr); ok {
+			x = star.X
+		}
+
+		if pkg := parseImportPath(x); pkg != "" {
+			// package member e.g. "encoding/json".HTMLEscape
+			spec.pkg = pkg              // e.g. "encoding/json"
+			spec.pkgMember = e.Sel.Name // e.g. "HTMLEscape"
+			spec.fromName = e.Sel.Name
+			return nil
+		}
+
+		if x, ok := x.(*ast.SelectorExpr); ok {
+			// field/method of type e.g. ("encoding/json".Decoder).Decode
+			y := unparen(x.X)
+			if pkg := parseImportPath(y); pkg != "" {
+				spec.pkg = pkg               // e.g. "encoding/json"
+				spec.pkgMember = x.Sel.Name  // e.g. "Decoder"
+				spec.typeMember = e.Sel.Name // e.g. "Decode"
+				spec.fromName = e.Sel.Name
+				return nil
+			}
+		}
+	}
+
+	return fmt.Errorf("-from %q: invalid expression", main)
+}
+
+// parseImportPath returns the import path of the package denoted by e.
+// Any import path may be represented as a string literal;
+// single-segment import paths (e.g. "bytes") may also be represented as
+// ast.Ident.  parseImportPath returns "" for all other expressions.
+func parseImportPath(e ast.Expr) string {
+	switch e := e.(type) {
+	case *ast.Ident:
+		return e.Name // e.g. bytes
+
+	case *ast.BasicLit:
+		if e.Kind == token.STRING {
+			pkgname, _ := strconv.Unquote(e.Value)
+			return pkgname // e.g. "encoding/json"
+		}
+	}
+	return ""
+}
+
+// parseOffsetFlag interprets the "-offset" flag value as a renaming specification.
+func parseOffsetFlag(ctxt *build.Context, offsetFlag string) (*spec, error) {
+	var spec spec
+	// Validate -offset, e.g. file.go:#123
+	parts := strings.Split(offsetFlag, ":#")
+	if len(parts) != 2 {
+		return nil, fmt.Errorf("-offset %q: invalid offset specification", offsetFlag)
+	}
+
+	spec.filename = parts[0]
+	if !buildutil.FileExists(ctxt, spec.filename) {
+		return nil, fmt.Errorf("no such file: %s", spec.filename)
+	}
+
+	bp, err := buildutil.ContainingPackage(ctxt, wd, spec.filename)
+	if err != nil {
+		return nil, err
+	}
+	spec.pkg = bp.ImportPath
+
+	for _, r := range parts[1] {
+		if !isDigit(r) {
+			return nil, fmt.Errorf("-offset %q: non-numeric offset", offsetFlag)
+		}
+	}
+	spec.offset, err = strconv.Atoi(parts[1])
+	if err != nil {
+		return nil, fmt.Errorf("-offset %q: non-numeric offset", offsetFlag)
+	}
+
+	// Parse the file and check there's an identifier at that offset.
+	fset := token.NewFileSet()
+	f, err := buildutil.ParseFile(fset, ctxt, nil, wd, spec.filename, parser.ParseComments)
+	if err != nil {
+		return nil, fmt.Errorf("-offset %q: cannot parse file: %s", offsetFlag, err)
+	}
+
+	id := identAtOffset(fset, f, spec.offset)
+	if id == nil {
+		return nil, fmt.Errorf("-offset %q: no identifier at this position", offsetFlag)
+	}
+
+	spec.fromName = id.Name
+
+	return &spec, nil
+}
+
+var wd = func() string {
+	wd, err := os.Getwd()
+	if err != nil {
+		panic("cannot get working directory: " + err.Error())
+	}
+	return wd
+}()
+
+// For source trees built with 'go build', the -from or -offset
+// spec identifies exactly one initial 'from' object to rename ,
+// but certain proprietary build systems allow a single file to
+// appear in multiple packages (e.g. the test package contains a
+// copy of its library), so there may be multiple objects for
+// the same source entity.
+
+func findFromObjects(iprog *loader.Program, spec *spec) ([]types.Object, error) {
+	if spec.filename != "" {
+		return findFromObjectsInFile(iprog, spec)
+	}
+
+	// Search for objects defined in specified package.
+
+	// TODO(adonovan): the iprog.ImportMap has an entry {"main": ...}
+	// for main packages, even though that's not an import path.
+	// Seems like a bug.
+	//
+	// pkg := iprog.ImportMap[spec.pkg]
+	// if pkg == nil {
+	// 	return fmt.Errorf("cannot find package %s", spec.pkg) // can't happen?
+	// }
+	// info := iprog.AllPackages[pkg]
+
+	// Workaround: lookup by value.
+	var info *loader.PackageInfo
+	var pkg *types.Package
+	for pkg, info = range iprog.AllPackages {
+		if pkg.Path() == spec.pkg {
+			break
+		}
+	}
+	if info == nil {
+		return nil, fmt.Errorf("package %q was not loaded", spec.pkg)
+	}
+
+	objects, err := findObjects(info, spec)
+	if err != nil {
+		return nil, err
+	}
+	if len(objects) > 1 {
+		// ambiguous "*" scope query
+		return nil, ambiguityError(iprog.Fset, objects)
+	}
+	return objects, nil
+}
+
+func findFromObjectsInFile(iprog *loader.Program, spec *spec) ([]types.Object, error) {
+	var fromObjects []types.Object
+	for _, info := range iprog.AllPackages {
+		// restrict to specified filename
+		// NB: under certain proprietary build systems, a given
+		// filename may appear in multiple packages.
+		for _, f := range info.Files {
+			thisFile := iprog.Fset.File(f.Pos())
+			if !sameFile(thisFile.Name(), spec.filename) {
+				continue
+			}
+			// This package contains the query file.
+
+			if spec.offset != 0 {
+				// Search for a specific ident by file/offset.
+				id := identAtOffset(iprog.Fset, f, spec.offset)
+				if id == nil {
+					// can't happen?
+					return nil, fmt.Errorf("identifier not found")
+				}
+				obj := info.Uses[id]
+				if obj == nil {
+					obj = info.Defs[id]
+					if obj == nil {
+						// Ident without Object.
+
+						// Package clause?
+						pos := thisFile.Pos(spec.offset)
+						_, path, _ := iprog.PathEnclosingInterval(pos, pos)
+						if len(path) == 2 { // [Ident File]
+							// TODO(adonovan): support this case.
+							return nil, fmt.Errorf("cannot rename %q: renaming package clauses is not yet supported",
+								path[1].(*ast.File).Name.Name)
+						}
+
+						// Implicit y in "switch y := x.(type) {"?
+						if obj := typeSwitchVar(&info.Info, path); obj != nil {
+							return []types.Object{obj}, nil
+						}
+
+						// Probably a type error.
+						return nil, fmt.Errorf("cannot find object for %q", id.Name)
+					}
+				}
+				if obj.Pkg() == nil {
+					return nil, fmt.Errorf("cannot rename predeclared identifiers (%s)", obj)
+
+				}
+
+				fromObjects = append(fromObjects, obj)
+			} else {
+				// do a package-wide query
+				objects, err := findObjects(info, spec)
+				if err != nil {
+					return nil, err
+				}
+
+				// filter results: only objects defined in thisFile
+				var filtered []types.Object
+				for _, obj := range objects {
+					if iprog.Fset.File(obj.Pos()) == thisFile {
+						filtered = append(filtered, obj)
+					}
+				}
+				if len(filtered) == 0 {
+					return nil, fmt.Errorf("no object %q declared in file %s",
+						spec.fromName, spec.filename)
+				} else if len(filtered) > 1 {
+					return nil, ambiguityError(iprog.Fset, filtered)
+				}
+				fromObjects = append(fromObjects, filtered[0])
+			}
+			break
+		}
+	}
+	if len(fromObjects) == 0 {
+		// can't happen?
+		return nil, fmt.Errorf("file %s was not part of the loaded program", spec.filename)
+	}
+	return fromObjects, nil
+}
+
+func typeSwitchVar(info *types.Info, path []ast.Node) types.Object {
+	if len(path) > 3 {
+		// [Ident AssignStmt TypeSwitchStmt...]
+		if sw, ok := path[2].(*ast.TypeSwitchStmt); ok {
+			// choose the first case.
+			if len(sw.Body.List) > 0 {
+				obj := info.Implicits[sw.Body.List[0].(*ast.CaseClause)]
+				if obj != nil {
+					return obj
+				}
+			}
+		}
+	}
+	return nil
+}
+
+// On success, findObjects returns the list of objects named
+// spec.fromName matching the spec.  On success, the result has exactly
+// one element unless spec.searchFor!="", in which case it has at least one
+// element.
+//
+func findObjects(info *loader.PackageInfo, spec *spec) ([]types.Object, error) {
+	if spec.pkgMember == "" {
+		if spec.searchFor == "" {
+			panic(spec)
+		}
+		objects := searchDefs(&info.Info, spec.searchFor)
+		if objects == nil {
+			return nil, fmt.Errorf("no object %q declared in package %q",
+				spec.searchFor, info.Pkg.Path())
+		}
+		return objects, nil
+	}
+
+	pkgMember := info.Pkg.Scope().Lookup(spec.pkgMember)
+	if pkgMember == nil {
+		return nil, fmt.Errorf("package %q has no member %q",
+			info.Pkg.Path(), spec.pkgMember)
+	}
+
+	var searchFunc *types.Func
+	if spec.typeMember == "" {
+		// package member
+		if spec.searchFor == "" {
+			return []types.Object{pkgMember}, nil
+		}
+
+		// Search within pkgMember, which must be a function.
+		searchFunc, _ = pkgMember.(*types.Func)
+		if searchFunc == nil {
+			return nil, fmt.Errorf("cannot search for %q within %s %q",
+				spec.searchFor, objectKind(pkgMember), pkgMember)
+		}
+	} else {
+		// field/method of type
+		// e.g. (encoding/json.Decoder).Decode
+		// or ::x within it.
+
+		tName, _ := pkgMember.(*types.TypeName)
+		if tName == nil {
+			return nil, fmt.Errorf("%s.%s is a %s, not a type",
+				info.Pkg.Path(), pkgMember.Name(), objectKind(pkgMember))
+		}
+
+		// search within named type.
+		obj, _, _ := types.LookupFieldOrMethod(tName.Type(), true, info.Pkg, spec.typeMember)
+		if obj == nil {
+			return nil, fmt.Errorf("cannot find field or method %q of %s %s.%s",
+				spec.typeMember, typeKind(tName.Type()), info.Pkg.Path(), tName.Name())
+		}
+
+		if spec.searchFor == "" {
+			// If it is an embedded field, return the type of the field.
+			if v, ok := obj.(*types.Var); ok && v.Anonymous() {
+				switch t := v.Type().(type) {
+				case *types.Pointer:
+					return []types.Object{t.Elem().(*types.Named).Obj()}, nil
+				case *types.Named:
+					return []types.Object{t.Obj()}, nil
+				}
+			}
+			return []types.Object{obj}, nil
+		}
+
+		searchFunc, _ = obj.(*types.Func)
+		if searchFunc == nil {
+			return nil, fmt.Errorf("cannot search for local name %q within %s (%s.%s).%s; need a function",
+				spec.searchFor, objectKind(obj), info.Pkg.Path(), tName.Name(),
+				obj.Name())
+		}
+		if isInterface(tName.Type()) {
+			return nil, fmt.Errorf("cannot search for local name %q within abstract method (%s.%s).%s",
+				spec.searchFor, info.Pkg.Path(), tName.Name(), searchFunc.Name())
+		}
+	}
+
+	// -- search within function or method --
+
+	decl := funcDecl(info, searchFunc)
+	if decl == nil {
+		return nil, fmt.Errorf("cannot find syntax for %s", searchFunc) // can't happen?
+	}
+
+	var objects []types.Object
+	for _, obj := range searchDefs(&info.Info, spec.searchFor) {
+		// We use positions, not scopes, to determine whether
+		// the obj is within searchFunc.  This is clumsy, but the
+		// alternative, using the types.Scope tree, doesn't
+		// account for non-lexical objects like fields and
+		// interface methods.
+		if decl.Pos() <= obj.Pos() && obj.Pos() < decl.End() && obj != searchFunc {
+			objects = append(objects, obj)
+		}
+	}
+	if objects == nil {
+		return nil, fmt.Errorf("no local definition of %q within %s",
+			spec.searchFor, searchFunc)
+	}
+	return objects, nil
+}
+
+func funcDecl(info *loader.PackageInfo, fn *types.Func) *ast.FuncDecl {
+	for _, f := range info.Files {
+		for _, d := range f.Decls {
+			if d, ok := d.(*ast.FuncDecl); ok && info.Defs[d.Name] == fn {
+				return d
+			}
+		}
+	}
+	return nil
+}
+
+func searchDefs(info *types.Info, name string) []types.Object {
+	var objects []types.Object
+	for id, obj := range info.Defs {
+		if obj == nil {
+			// e.g. blank ident.
+			// TODO(adonovan): but also implicit y in
+			//    switch y := x.(type)
+			// Needs some thought.
+			continue
+		}
+		if id.Name == name {
+			objects = append(objects, obj)
+		}
+	}
+	return objects
+}
+
+func identAtOffset(fset *token.FileSet, f *ast.File, offset int) *ast.Ident {
+	var found *ast.Ident
+	ast.Inspect(f, func(n ast.Node) bool {
+		if id, ok := n.(*ast.Ident); ok {
+			idpos := fset.Position(id.Pos()).Offset
+			if idpos <= offset && offset < idpos+len(id.Name) {
+				found = id
+			}
+		}
+		return found == nil // keep traversing only until found
+	})
+	return found
+}
+
+// ambiguityError returns an error describing an ambiguous "*" scope query.
+func ambiguityError(fset *token.FileSet, objects []types.Object) error {
+	var buf bytes.Buffer
+	for i, obj := range objects {
+		if i > 0 {
+			buf.WriteString(", ")
+		}
+		posn := fset.Position(obj.Pos())
+		fmt.Fprintf(&buf, "%s at %s:%d",
+			objectKind(obj), filepath.Base(posn.Filename), posn.Column)
+	}
+	return fmt.Errorf("ambiguous specifier %s matches %s",
+		objects[0].Name(), buf.String())
+}
diff --git a/go/src/golang.org/x/tools/refactor/rename/util.go b/go/src/golang.org/x/tools/refactor/rename/util.go
index def9399..f0f80f0 100644
--- a/go/src/golang.org/x/tools/refactor/rename/util.go
+++ b/go/src/golang.org/x/tools/refactor/rename/util.go
@@ -2,10 +2,13 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 package rename
 
 import (
 	"go/ast"
+	"go/types"
 	"os"
 	"path/filepath"
 	"reflect"
@@ -14,7 +17,6 @@
 	"unicode"
 
 	"golang.org/x/tools/go/ast/astutil"
-	"golang.org/x/tools/go/types"
 )
 
 func objectKind(obj types.Object) string {
diff --git a/go/src/golang.org/x/tools/refactor/rename/util14.go b/go/src/golang.org/x/tools/refactor/rename/util14.go
new file mode 100644
index 0000000..126d3ee
--- /dev/null
+++ b/go/src/golang.org/x/tools/refactor/rename/util14.go
@@ -0,0 +1,106 @@
+// Copyright 2014 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.
+
+// +build !go1.5
+
+package rename
+
+import (
+	"go/ast"
+	"os"
+	"path/filepath"
+	"reflect"
+	"runtime"
+	"strings"
+	"unicode"
+
+	"golang.org/x/tools/go/ast/astutil"
+	"golang.org/x/tools/go/types"
+)
+
+func objectKind(obj types.Object) string {
+	switch obj := obj.(type) {
+	case *types.PkgName:
+		return "imported package name"
+	case *types.TypeName:
+		return "type"
+	case *types.Var:
+		if obj.IsField() {
+			return "field"
+		}
+	case *types.Func:
+		if obj.Type().(*types.Signature).Recv() != nil {
+			return "method"
+		}
+	}
+	// label, func, var, const
+	return strings.ToLower(strings.TrimPrefix(reflect.TypeOf(obj).String(), "*types."))
+}
+
+func typeKind(T types.Type) string {
+	return strings.ToLower(strings.TrimPrefix(reflect.TypeOf(T.Underlying()).String(), "*types."))
+}
+
+// NB: for renamings, blank is not considered valid.
+func isValidIdentifier(id string) bool {
+	if id == "" || id == "_" {
+		return false
+	}
+	for i, r := range id {
+		if !isLetter(r) && (i == 0 || !isDigit(r)) {
+			return false
+		}
+	}
+	return true
+}
+
+// isLocal reports whether obj is local to some function.
+// Precondition: not a struct field or interface method.
+func isLocal(obj types.Object) bool {
+	// [... 5=stmt 4=func 3=file 2=pkg 1=universe]
+	var depth int
+	for scope := obj.Parent(); scope != nil; scope = scope.Parent() {
+		depth++
+	}
+	return depth >= 4
+}
+
+func isPackageLevel(obj types.Object) bool {
+	return obj.Pkg().Scope().Lookup(obj.Name()) == obj
+}
+
+// -- Plundered from go/scanner: ---------------------------------------
+
+func isLetter(ch rune) bool {
+	return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= 0x80 && unicode.IsLetter(ch)
+}
+
+func isDigit(ch rune) bool {
+	return '0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch)
+}
+
+// -- Plundered from golang.org/x/tools/oracle -----------------
+
+// sameFile returns true if x and y have the same basename and denote
+// the same file.
+//
+func sameFile(x, y string) bool {
+	if runtime.GOOS == "windows" {
+		x = filepath.ToSlash(x)
+		y = filepath.ToSlash(y)
+	}
+	if x == y {
+		return true
+	}
+	if filepath.Base(x) == filepath.Base(y) { // (optimisation)
+		if xi, err := os.Stat(x); err == nil {
+			if yi, err := os.Stat(y); err == nil {
+				return os.SameFile(xi, yi)
+			}
+		}
+	}
+	return false
+}
+
+func unparen(e ast.Expr) ast.Expr { return astutil.Unparen(e) }
diff --git a/go/src/golang.org/x/tools/refactor/satisfy/find.go b/go/src/golang.org/x/tools/refactor/satisfy/find.go
index acbcf62..a346c1a 100644
--- a/go/src/golang.org/x/tools/refactor/satisfy/find.go
+++ b/go/src/golang.org/x/tools/refactor/satisfy/find.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build go1.5
+
 // Package satisfy inspects the type-checked ASTs of Go packages and
 // reports the set of discovered type constraints of the form (lhs, rhs
 // Type) where lhs is a non-trivial interface, rhs satisfies this
@@ -48,9 +50,9 @@
 	"fmt"
 	"go/ast"
 	"go/token"
+	"go/types"
 
 	"golang.org/x/tools/go/ast/astutil"
-	"golang.org/x/tools/go/types"
 	"golang.org/x/tools/go/types/typeutil"
 )
 
diff --git a/go/src/golang.org/x/tools/refactor/satisfy/find14.go b/go/src/golang.org/x/tools/refactor/satisfy/find14.go
new file mode 100644
index 0000000..3b8d1e0
--- /dev/null
+++ b/go/src/golang.org/x/tools/refactor/satisfy/find14.go
@@ -0,0 +1,707 @@
+// Copyright 2014 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.
+
+// +build !go1.5
+
+// Package satisfy inspects the type-checked ASTs of Go packages and
+// reports the set of discovered type constraints of the form (lhs, rhs
+// Type) where lhs is a non-trivial interface, rhs satisfies this
+// interface, and this fact is necessary for the package to be
+// well-typed.
+//
+// THIS PACKAGE IS EXPERIMENTAL AND MAY CHANGE AT ANY TIME.
+//
+// It is provided only for the gorename tool.  Ideally this
+// functionality will become part of the type-checker in due course,
+// since it is computing it anyway, and it is robust for ill-typed
+// inputs, which this package is not.
+//
+package satisfy // import "golang.org/x/tools/refactor/satisfy"
+
+// NOTES:
+//
+// We don't care about numeric conversions, so we don't descend into
+// types or constant expressions.  This is unsound because
+// constant expressions can contain arbitrary statements, e.g.
+//   const x = len([1]func(){func() {
+//     ...
+//   }})
+//
+// TODO(adonovan): make this robust against ill-typed input.
+// Or move it into the type-checker.
+//
+// Assignability conversions are possible in the following places:
+// - in assignments y = x, y := x, var y = x.
+// - from call argument types to formal parameter types
+// - in append and delete calls
+// - from return operands to result parameter types
+// - in composite literal T{k:v}, from k and v to T's field/element/key type
+// - in map[key] from key to the map's key type
+// - in comparisons x==y and switch x { case y: }.
+// - in explicit conversions T(x)
+// - in sends ch <- x, from x to the channel element type
+// - in type assertions x.(T) and switch x.(type) { case T: }
+//
+// The results of this pass provide information equivalent to the
+// ssa.MakeInterface and ssa.ChangeInterface instructions.
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+
+	"golang.org/x/tools/go/ast/astutil"
+	"golang.org/x/tools/go/types"
+	"golang.org/x/tools/go/types/typeutil"
+)
+
+// A Constraint records the fact that the RHS type does and must
+// satisify the LHS type, which is an interface.
+// The names are suggestive of an assignment statement LHS = RHS.
+type Constraint struct {
+	LHS, RHS types.Type
+}
+
+// A Finder inspects the type-checked ASTs of Go packages and
+// accumulates the set of type constraints (x, y) such that x is
+// assignable to y, y is an interface, and both x and y have methods.
+//
+// In other words, it returns the subset of the "implements" relation
+// that is checked during compilation of a package.  Refactoring tools
+// will need to preserve at least this part of the relation to ensure
+// continued compilation.
+//
+type Finder struct {
+	Result    map[Constraint]bool
+	msetcache typeutil.MethodSetCache
+
+	// per-Find state
+	info *types.Info
+	sig  *types.Signature
+}
+
+// Find inspects a single package, populating Result with its pairs of
+// constrained types.
+//
+// The result is non-canonical and thus may contain duplicates (but this
+// tends to preserves names of interface types better).
+//
+// The package must be free of type errors, and
+// info.{Defs,Uses,Selections,Types} must have been populated by the
+// type-checker.
+//
+func (f *Finder) Find(info *types.Info, files []*ast.File) {
+	if f.Result == nil {
+		f.Result = make(map[Constraint]bool)
+	}
+
+	f.info = info
+	for _, file := range files {
+		for _, d := range file.Decls {
+			switch d := d.(type) {
+			case *ast.GenDecl:
+				if d.Tok == token.VAR { // ignore consts
+					for _, spec := range d.Specs {
+						f.valueSpec(spec.(*ast.ValueSpec))
+					}
+				}
+
+			case *ast.FuncDecl:
+				if d.Body != nil {
+					f.sig = f.info.Defs[d.Name].Type().(*types.Signature)
+					f.stmt(d.Body)
+					f.sig = nil
+				}
+			}
+		}
+	}
+	f.info = nil
+}
+
+var (
+	tInvalid     = types.Typ[types.Invalid]
+	tUntypedBool = types.Typ[types.UntypedBool]
+	tUntypedNil  = types.Typ[types.UntypedNil]
+)
+
+// exprN visits an expression in a multi-value context.
+func (f *Finder) exprN(e ast.Expr) types.Type {
+	typ := f.info.Types[e].Type.(*types.Tuple)
+	switch e := e.(type) {
+	case *ast.ParenExpr:
+		return f.exprN(e.X)
+
+	case *ast.CallExpr:
+		// x, err := f(args)
+		sig := f.expr(e.Fun).Underlying().(*types.Signature)
+		f.call(sig, e.Args)
+
+	case *ast.IndexExpr:
+		// y, ok := x[i]
+		x := f.expr(e.X)
+		f.assign(f.expr(e.Index), x.Underlying().(*types.Map).Key())
+
+	case *ast.TypeAssertExpr:
+		// y, ok := x.(T)
+		f.typeAssert(f.expr(e.X), typ.At(0).Type())
+
+	case *ast.UnaryExpr: // must be receive <-
+		// y, ok := <-x
+		f.expr(e.X)
+
+	default:
+		panic(e)
+	}
+	return typ
+}
+
+func (f *Finder) call(sig *types.Signature, args []ast.Expr) {
+	if len(args) == 0 {
+		return
+	}
+
+	// Ellipsis call?  e.g. f(x, y, z...)
+	if _, ok := args[len(args)-1].(*ast.Ellipsis); ok {
+		for i, arg := range args {
+			// The final arg is a slice, and so is the final param.
+			f.assign(sig.Params().At(i).Type(), f.expr(arg))
+		}
+		return
+	}
+
+	var argtypes []types.Type
+
+	// Gather the effective actual parameter types.
+	if tuple, ok := f.info.Types[args[0]].Type.(*types.Tuple); ok {
+		// f(g()) call where g has multiple results?
+		f.expr(args[0])
+		// unpack the tuple
+		for i := 0; i < tuple.Len(); i++ {
+			argtypes = append(argtypes, tuple.At(i).Type())
+		}
+	} else {
+		for _, arg := range args {
+			argtypes = append(argtypes, f.expr(arg))
+		}
+	}
+
+	// Assign the actuals to the formals.
+	if !sig.Variadic() {
+		for i, argtype := range argtypes {
+			f.assign(sig.Params().At(i).Type(), argtype)
+		}
+	} else {
+		// The first n-1 parameters are assigned normally.
+		nnormals := sig.Params().Len() - 1
+		for i, argtype := range argtypes[:nnormals] {
+			f.assign(sig.Params().At(i).Type(), argtype)
+		}
+		// Remaining args are assigned to elements of varargs slice.
+		tElem := sig.Params().At(nnormals).Type().(*types.Slice).Elem()
+		for i := nnormals; i < len(argtypes); i++ {
+			f.assign(tElem, argtypes[i])
+		}
+	}
+}
+
+func (f *Finder) builtin(obj *types.Builtin, sig *types.Signature, args []ast.Expr, T types.Type) types.Type {
+	switch obj.Name() {
+	case "make", "new":
+		// skip the type operand
+		for _, arg := range args[1:] {
+			f.expr(arg)
+		}
+
+	case "append":
+		s := f.expr(args[0])
+		if _, ok := args[len(args)-1].(*ast.Ellipsis); ok && len(args) == 2 {
+			// append(x, y...)   including append([]byte, "foo"...)
+			f.expr(args[1])
+		} else {
+			// append(x, y, z)
+			tElem := s.Underlying().(*types.Slice).Elem()
+			for _, arg := range args[1:] {
+				f.assign(tElem, f.expr(arg))
+			}
+		}
+
+	case "delete":
+		m := f.expr(args[0])
+		k := f.expr(args[1])
+		f.assign(m.Underlying().(*types.Map).Key(), k)
+
+	default:
+		// ordinary call
+		f.call(sig, args)
+	}
+
+	return T
+}
+
+func (f *Finder) extract(tuple types.Type, i int) types.Type {
+	if tuple, ok := tuple.(*types.Tuple); ok && i < tuple.Len() {
+		return tuple.At(i).Type()
+	}
+	return tInvalid
+}
+
+func (f *Finder) valueSpec(spec *ast.ValueSpec) {
+	var T types.Type
+	if spec.Type != nil {
+		T = f.info.Types[spec.Type].Type
+	}
+	switch len(spec.Values) {
+	case len(spec.Names): // e.g. var x, y = f(), g()
+		for _, value := range spec.Values {
+			v := f.expr(value)
+			if T != nil {
+				f.assign(T, v)
+			}
+		}
+
+	case 1: // e.g. var x, y = f()
+		tuple := f.exprN(spec.Values[0])
+		for i := range spec.Names {
+			if T != nil {
+				f.assign(T, f.extract(tuple, i))
+			}
+		}
+	}
+}
+
+// assign records pairs of distinct types that are related by
+// assignability, where the left-hand side is an interface and both
+// sides have methods.
+//
+// It should be called for all assignability checks, type assertions,
+// explicit conversions and comparisons between two types, unless the
+// types are uninteresting (e.g. lhs is a concrete type, or the empty
+// interface; rhs has no methods).
+//
+func (f *Finder) assign(lhs, rhs types.Type) {
+	if types.Identical(lhs, rhs) {
+		return
+	}
+	if !isInterface(lhs) {
+		return
+	}
+
+	if f.msetcache.MethodSet(lhs).Len() == 0 {
+		return
+	}
+	if f.msetcache.MethodSet(rhs).Len() == 0 {
+		return
+	}
+	// record the pair
+	f.Result[Constraint{lhs, rhs}] = true
+}
+
+// typeAssert must be called for each type assertion x.(T) where x has
+// interface type I.
+func (f *Finder) typeAssert(I, T types.Type) {
+	// Type assertions are slightly subtle, because they are allowed
+	// to be "impossible", e.g.
+	//
+	// 	var x interface{f()}
+	//	_ = x.(interface{f()int}) // legal
+	//
+	// (In hindsight, the language spec should probably not have
+	// allowed this, but it's too late to fix now.)
+	//
+	// This means that a type assert from I to T isn't exactly a
+	// constraint that T is assignable to I, but for a refactoring
+	// tool it is a conditional constraint that, if T is assignable
+	// to I before a refactoring, it should remain so after.
+
+	if types.AssignableTo(T, I) {
+		f.assign(I, T)
+	}
+}
+
+// compare must be called for each comparison x==y.
+func (f *Finder) compare(x, y types.Type) {
+	if types.AssignableTo(x, y) {
+		f.assign(y, x)
+	} else if types.AssignableTo(y, x) {
+		f.assign(x, y)
+	}
+}
+
+// expr visits a true expression (not a type or defining ident)
+// and returns its type.
+func (f *Finder) expr(e ast.Expr) types.Type {
+	tv := f.info.Types[e]
+	if tv.Value != nil {
+		return tv.Type // prune the descent for constants
+	}
+
+	// tv.Type may be nil for an ast.Ident.
+
+	switch e := e.(type) {
+	case *ast.BadExpr, *ast.BasicLit:
+		// no-op
+
+	case *ast.Ident:
+		// (referring idents only)
+		if obj, ok := f.info.Uses[e]; ok {
+			return obj.Type()
+		}
+		if e.Name == "_" { // e.g. "for _ = range x"
+			return tInvalid
+		}
+		panic("undefined ident: " + e.Name)
+
+	case *ast.Ellipsis:
+		if e.Elt != nil {
+			f.expr(e.Elt)
+		}
+
+	case *ast.FuncLit:
+		saved := f.sig
+		f.sig = tv.Type.(*types.Signature)
+		f.stmt(e.Body)
+		f.sig = saved
+
+	case *ast.CompositeLit:
+		switch T := deref(tv.Type).Underlying().(type) {
+		case *types.Struct:
+			for i, elem := range e.Elts {
+				if kv, ok := elem.(*ast.KeyValueExpr); ok {
+					f.assign(f.info.Uses[kv.Key.(*ast.Ident)].Type(), f.expr(kv.Value))
+				} else {
+					f.assign(T.Field(i).Type(), f.expr(elem))
+				}
+			}
+
+		case *types.Map:
+			for _, elem := range e.Elts {
+				elem := elem.(*ast.KeyValueExpr)
+				f.assign(T.Key(), f.expr(elem.Key))
+				f.assign(T.Elem(), f.expr(elem.Value))
+			}
+
+		case *types.Array, *types.Slice:
+			tElem := T.(interface {
+				Elem() types.Type
+			}).Elem()
+			for _, elem := range e.Elts {
+				if kv, ok := elem.(*ast.KeyValueExpr); ok {
+					// ignore the key
+					f.assign(tElem, f.expr(kv.Value))
+				} else {
+					f.assign(tElem, f.expr(elem))
+				}
+			}
+
+		default:
+			panic("unexpected composite literal type: " + tv.Type.String())
+		}
+
+	case *ast.ParenExpr:
+		f.expr(e.X)
+
+	case *ast.SelectorExpr:
+		if _, ok := f.info.Selections[e]; ok {
+			f.expr(e.X) // selection
+		} else {
+			return f.info.Uses[e.Sel].Type() // qualified identifier
+		}
+
+	case *ast.IndexExpr:
+		x := f.expr(e.X)
+		i := f.expr(e.Index)
+		if ux, ok := x.Underlying().(*types.Map); ok {
+			f.assign(ux.Key(), i)
+		}
+
+	case *ast.SliceExpr:
+		f.expr(e.X)
+		if e.Low != nil {
+			f.expr(e.Low)
+		}
+		if e.High != nil {
+			f.expr(e.High)
+		}
+		if e.Max != nil {
+			f.expr(e.Max)
+		}
+
+	case *ast.TypeAssertExpr:
+		x := f.expr(e.X)
+		f.typeAssert(x, f.info.Types[e.Type].Type)
+
+	case *ast.CallExpr:
+		if tvFun := f.info.Types[e.Fun]; tvFun.IsType() {
+			// conversion
+			arg0 := f.expr(e.Args[0])
+			f.assign(tvFun.Type, arg0)
+		} else {
+			// function call
+			if id, ok := unparen(e.Fun).(*ast.Ident); ok {
+				if obj, ok := f.info.Uses[id].(*types.Builtin); ok {
+					sig := f.info.Types[id].Type.(*types.Signature)
+					return f.builtin(obj, sig, e.Args, tv.Type)
+				}
+			}
+			// ordinary call
+			f.call(f.expr(e.Fun).Underlying().(*types.Signature), e.Args)
+		}
+
+	case *ast.StarExpr:
+		f.expr(e.X)
+
+	case *ast.UnaryExpr:
+		f.expr(e.X)
+
+	case *ast.BinaryExpr:
+		x := f.expr(e.X)
+		y := f.expr(e.Y)
+		if e.Op == token.EQL || e.Op == token.NEQ {
+			f.compare(x, y)
+		}
+
+	case *ast.KeyValueExpr:
+		f.expr(e.Key)
+		f.expr(e.Value)
+
+	case *ast.ArrayType,
+		*ast.StructType,
+		*ast.FuncType,
+		*ast.InterfaceType,
+		*ast.MapType,
+		*ast.ChanType:
+		panic(e)
+	}
+
+	if tv.Type == nil {
+		panic(fmt.Sprintf("no type for %T", e))
+	}
+
+	return tv.Type
+}
+
+func (f *Finder) stmt(s ast.Stmt) {
+	switch s := s.(type) {
+	case *ast.BadStmt,
+		*ast.EmptyStmt,
+		*ast.BranchStmt:
+		// no-op
+
+	case *ast.DeclStmt:
+		d := s.Decl.(*ast.GenDecl)
+		if d.Tok == token.VAR { // ignore consts
+			for _, spec := range d.Specs {
+				f.valueSpec(spec.(*ast.ValueSpec))
+			}
+		}
+
+	case *ast.LabeledStmt:
+		f.stmt(s.Stmt)
+
+	case *ast.ExprStmt:
+		f.expr(s.X)
+
+	case *ast.SendStmt:
+		ch := f.expr(s.Chan)
+		val := f.expr(s.Value)
+		f.assign(ch.Underlying().(*types.Chan).Elem(), val)
+
+	case *ast.IncDecStmt:
+		f.expr(s.X)
+
+	case *ast.AssignStmt:
+		switch s.Tok {
+		case token.ASSIGN, token.DEFINE:
+			// y := x   or   y = x
+			var rhsTuple types.Type
+			if len(s.Lhs) != len(s.Rhs) {
+				rhsTuple = f.exprN(s.Rhs[0])
+			}
+			for i := range s.Lhs {
+				var lhs, rhs types.Type
+				if rhsTuple == nil {
+					rhs = f.expr(s.Rhs[i]) // 1:1 assignment
+				} else {
+					rhs = f.extract(rhsTuple, i) // n:1 assignment
+				}
+
+				if id, ok := s.Lhs[i].(*ast.Ident); ok {
+					if id.Name != "_" {
+						if obj, ok := f.info.Defs[id]; ok {
+							lhs = obj.Type() // definition
+						}
+					}
+				}
+				if lhs == nil {
+					lhs = f.expr(s.Lhs[i]) // assignment
+				}
+				f.assign(lhs, rhs)
+			}
+
+		default:
+			// y op= x
+			f.expr(s.Lhs[0])
+			f.expr(s.Rhs[0])
+		}
+
+	case *ast.GoStmt:
+		f.expr(s.Call)
+
+	case *ast.DeferStmt:
+		f.expr(s.Call)
+
+	case *ast.ReturnStmt:
+		formals := f.sig.Results()
+		switch len(s.Results) {
+		case formals.Len(): // 1:1
+			for i, result := range s.Results {
+				f.assign(formals.At(i).Type(), f.expr(result))
+			}
+
+		case 1: // n:1
+			tuple := f.exprN(s.Results[0])
+			for i := 0; i < formals.Len(); i++ {
+				f.assign(formals.At(i).Type(), f.extract(tuple, i))
+			}
+		}
+
+	case *ast.SelectStmt:
+		f.stmt(s.Body)
+
+	case *ast.BlockStmt:
+		for _, s := range s.List {
+			f.stmt(s)
+		}
+
+	case *ast.IfStmt:
+		if s.Init != nil {
+			f.stmt(s.Init)
+		}
+		f.expr(s.Cond)
+		f.stmt(s.Body)
+		if s.Else != nil {
+			f.stmt(s.Else)
+		}
+
+	case *ast.SwitchStmt:
+		if s.Init != nil {
+			f.stmt(s.Init)
+		}
+		var tag types.Type = tUntypedBool
+		if s.Tag != nil {
+			tag = f.expr(s.Tag)
+		}
+		for _, cc := range s.Body.List {
+			cc := cc.(*ast.CaseClause)
+			for _, cond := range cc.List {
+				f.compare(tag, f.info.Types[cond].Type)
+			}
+			for _, s := range cc.Body {
+				f.stmt(s)
+			}
+		}
+
+	case *ast.TypeSwitchStmt:
+		if s.Init != nil {
+			f.stmt(s.Init)
+		}
+		var I types.Type
+		switch ass := s.Assign.(type) {
+		case *ast.ExprStmt: // x.(type)
+			I = f.expr(unparen(ass.X).(*ast.TypeAssertExpr).X)
+		case *ast.AssignStmt: // y := x.(type)
+			I = f.expr(unparen(ass.Rhs[0]).(*ast.TypeAssertExpr).X)
+		}
+		for _, cc := range s.Body.List {
+			cc := cc.(*ast.CaseClause)
+			for _, cond := range cc.List {
+				tCase := f.info.Types[cond].Type
+				if tCase != tUntypedNil {
+					f.typeAssert(I, tCase)
+				}
+			}
+			for _, s := range cc.Body {
+				f.stmt(s)
+			}
+		}
+
+	case *ast.CommClause:
+		if s.Comm != nil {
+			f.stmt(s.Comm)
+		}
+		for _, s := range s.Body {
+			f.stmt(s)
+		}
+
+	case *ast.ForStmt:
+		if s.Init != nil {
+			f.stmt(s.Init)
+		}
+		if s.Cond != nil {
+			f.expr(s.Cond)
+		}
+		if s.Post != nil {
+			f.stmt(s.Post)
+		}
+		f.stmt(s.Body)
+
+	case *ast.RangeStmt:
+		x := f.expr(s.X)
+		// No conversions are involved when Tok==DEFINE.
+		if s.Tok == token.ASSIGN {
+			if s.Key != nil {
+				k := f.expr(s.Key)
+				var xelem types.Type
+				// keys of array, *array, slice, string aren't interesting
+				switch ux := x.Underlying().(type) {
+				case *types.Chan:
+					xelem = ux.Elem()
+				case *types.Map:
+					xelem = ux.Key()
+				}
+				if xelem != nil {
+					f.assign(xelem, k)
+				}
+			}
+			if s.Value != nil {
+				val := f.expr(s.Value)
+				var xelem types.Type
+				// values of strings aren't interesting
+				switch ux := x.Underlying().(type) {
+				case *types.Array:
+					xelem = ux.Elem()
+				case *types.Chan:
+					xelem = ux.Elem()
+				case *types.Map:
+					xelem = ux.Elem()
+				case *types.Pointer: // *array
+					xelem = deref(ux).(*types.Array).Elem()
+				case *types.Slice:
+					xelem = ux.Elem()
+				}
+				if xelem != nil {
+					f.assign(xelem, val)
+				}
+			}
+		}
+		f.stmt(s.Body)
+
+	default:
+		panic(s)
+	}
+}
+
+// -- Plundered from golang.org/x/tools/go/ssa -----------------
+
+// deref returns a pointer's element type; otherwise it returns typ.
+func deref(typ types.Type) types.Type {
+	if p, ok := typ.Underlying().(*types.Pointer); ok {
+		return p.Elem()
+	}
+	return typ
+}
+
+func unparen(e ast.Expr) ast.Expr { return astutil.Unparen(e) }
+
+func isInterface(T types.Type) bool { return types.IsInterface(T) }