mirror of https://github.com/golang/go.git
cmd/gc: do not export useless private symbols.
Fixes #4252. R=rsc, golang-dev, mirtchovski, daniel.morsing, dave, lvd CC=golang-dev https://golang.org/cl/6856126
This commit is contained in:
parent
ec45952670
commit
561edbd63c
|
|
@ -22,22 +22,8 @@ exportsym(Node *n)
|
||||||
}
|
}
|
||||||
n->sym->flags |= SymExport;
|
n->sym->flags |= SymExport;
|
||||||
|
|
||||||
exportlist = list(exportlist, n);
|
if(debug['E'])
|
||||||
}
|
print("export symbol %S\n", n->sym);
|
||||||
|
|
||||||
// Mark n's symbol as package-local
|
|
||||||
static void
|
|
||||||
packagesym(Node *n)
|
|
||||||
{
|
|
||||||
if(n == N || n->sym == S)
|
|
||||||
return;
|
|
||||||
if(n->sym->flags & (SymExport|SymPackage)) {
|
|
||||||
if(n->sym->flags & SymExport)
|
|
||||||
yyerror("export/package mismatch: %S", n->sym);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
n->sym->flags |= SymPackage;
|
|
||||||
|
|
||||||
exportlist = list(exportlist, n);
|
exportlist = list(exportlist, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -58,6 +44,18 @@ initname(char *s)
|
||||||
return strcmp(s, "init") == 0;
|
return strcmp(s, "init") == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// exportedsym returns whether a symbol will be visible
|
||||||
|
// to files that import our package.
|
||||||
|
static int
|
||||||
|
exportedsym(Sym *sym)
|
||||||
|
{
|
||||||
|
// Builtins are visible everywhere.
|
||||||
|
if(sym->pkg == builtinpkg || sym->origpkg == builtinpkg)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return sym->pkg == localpkg && exportname(sym->name);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
autoexport(Node *n, int ctxt)
|
autoexport(Node *n, int ctxt)
|
||||||
{
|
{
|
||||||
|
|
@ -69,8 +67,6 @@ autoexport(Node *n, int ctxt)
|
||||||
return;
|
return;
|
||||||
if(exportname(n->sym->name) || initname(n->sym->name))
|
if(exportname(n->sym->name) || initname(n->sym->name))
|
||||||
exportsym(n);
|
exportsym(n);
|
||||||
else
|
|
||||||
packagesym(n);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -104,17 +100,17 @@ reexportdep(Node *n)
|
||||||
if(!n)
|
if(!n)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// print("reexportdep %+hN\n", n);
|
//print("reexportdep %+hN\n", n);
|
||||||
switch(n->op) {
|
switch(n->op) {
|
||||||
case ONAME:
|
case ONAME:
|
||||||
switch(n->class&~PHEAP) {
|
switch(n->class&~PHEAP) {
|
||||||
case PFUNC:
|
case PFUNC:
|
||||||
// methods will be printed along with their type
|
// methods will be printed along with their type
|
||||||
if(!n->type || n->type->thistuple > 0)
|
if(n->left && n->left->op == OTYPE)
|
||||||
break;
|
break;
|
||||||
// fallthrough
|
// fallthrough
|
||||||
case PEXTERN:
|
case PEXTERN:
|
||||||
if (n->sym && n->sym->pkg != localpkg && n->sym->pkg != builtinpkg)
|
if(n->sym && !exportedsym(n->sym))
|
||||||
exportlist = list(exportlist, n);
|
exportlist = list(exportlist, n);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -125,7 +121,7 @@ reexportdep(Node *n)
|
||||||
if(t != types[t->etype] && t != idealbool && t != idealstring) {
|
if(t != types[t->etype] && t != idealbool && t != idealstring) {
|
||||||
if(isptr[t->etype])
|
if(isptr[t->etype])
|
||||||
t = t->type;
|
t = t->type;
|
||||||
if (t && t->sym && t->sym->def && t->sym->pkg != localpkg && t->sym->pkg != builtinpkg) {
|
if(t && t->sym && t->sym->def && !exportedsym(t->sym)) {
|
||||||
exportlist = list(exportlist, t->sym->def);
|
exportlist = list(exportlist, t->sym->def);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -136,15 +132,19 @@ reexportdep(Node *n)
|
||||||
if(t != types[n->type->etype] && t != idealbool && t != idealstring) {
|
if(t != types[n->type->etype] && t != idealbool && t != idealstring) {
|
||||||
if(isptr[t->etype])
|
if(isptr[t->etype])
|
||||||
t = t->type;
|
t = t->type;
|
||||||
if (t && t->sym && t->sym->def && t->sym->pkg != localpkg && t->sym->pkg != builtinpkg) {
|
if(t && t->sym && t->sym->def && !exportedsym(t->sym)) {
|
||||||
// print("reexport literal type %+hN\n", t->sym->def);
|
if(debug['E'])
|
||||||
|
print("reexport literal type %S\n", t->sym);
|
||||||
exportlist = list(exportlist, t->sym->def);
|
exportlist = list(exportlist, t->sym->def);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// fallthrough
|
// fallthrough
|
||||||
case OTYPE:
|
case OTYPE:
|
||||||
if (n->sym && n->sym->pkg != localpkg && n->sym->pkg != builtinpkg)
|
if(n->sym && !exportedsym(n->sym)) {
|
||||||
|
if(debug['E'])
|
||||||
|
print("reexport literal/type %S\n", n->sym);
|
||||||
exportlist = list(exportlist, n);
|
exportlist = list(exportlist, n);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// for operations that need a type when rendered, put the type on the export list.
|
// for operations that need a type when rendered, put the type on the export list.
|
||||||
|
|
@ -158,8 +158,9 @@ reexportdep(Node *n)
|
||||||
t = n->type;
|
t = n->type;
|
||||||
if(!t->sym && t->type)
|
if(!t->sym && t->type)
|
||||||
t = t->type;
|
t = t->type;
|
||||||
if (t && t->sym && t->sym->def && t->sym->pkg != localpkg && t->sym->pkg != builtinpkg) {
|
if(t && t->sym && t->sym->def && !exportedsym(t->sym)) {
|
||||||
// print("reexport convnop %+hN\n", t->sym->def);
|
if(debug['E'])
|
||||||
|
print("reexport type for convnop %S\n", t->sym);
|
||||||
exportlist = list(exportlist, t->sym->def);
|
exportlist = list(exportlist, t->sym->def);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -2016,8 +2016,10 @@ lexfini(void)
|
||||||
s->lexical = lex;
|
s->lexical = lex;
|
||||||
|
|
||||||
etype = syms[i].etype;
|
etype = syms[i].etype;
|
||||||
if(etype != Txxx && (etype != TANY || debug['A']) && s->def == N)
|
if(etype != Txxx && (etype != TANY || debug['A']) && s->def == N) {
|
||||||
s->def = typenod(types[etype]);
|
s->def = typenod(types[etype]);
|
||||||
|
s->origpkg = builtinpkg;
|
||||||
|
}
|
||||||
|
|
||||||
etype = syms[i].op;
|
etype = syms[i].op;
|
||||||
if(etype != OXXX && s->def == N) {
|
if(etype != OXXX && s->def == N) {
|
||||||
|
|
@ -2025,52 +2027,66 @@ lexfini(void)
|
||||||
s->def->sym = s;
|
s->def->sym = s;
|
||||||
s->def->etype = etype;
|
s->def->etype = etype;
|
||||||
s->def->builtin = 1;
|
s->def->builtin = 1;
|
||||||
|
s->origpkg = builtinpkg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// backend-specific builtin types (e.g. int).
|
||||||
for(i=0; typedefs[i].name; i++) {
|
for(i=0; typedefs[i].name; i++) {
|
||||||
s = lookup(typedefs[i].name);
|
s = lookup(typedefs[i].name);
|
||||||
if(s->def == N)
|
if(s->def == N) {
|
||||||
s->def = typenod(types[typedefs[i].etype]);
|
s->def = typenod(types[typedefs[i].etype]);
|
||||||
|
s->origpkg = builtinpkg;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// there's only so much table-driven we can handle.
|
// there's only so much table-driven we can handle.
|
||||||
// these are special cases.
|
// these are special cases.
|
||||||
s = lookup("byte");
|
s = lookup("byte");
|
||||||
if(s->def == N)
|
if(s->def == N) {
|
||||||
s->def = typenod(bytetype);
|
s->def = typenod(bytetype);
|
||||||
|
s->origpkg = builtinpkg;
|
||||||
|
}
|
||||||
|
|
||||||
s = lookup("error");
|
s = lookup("error");
|
||||||
if(s->def == N)
|
if(s->def == N) {
|
||||||
s->def = typenod(errortype);
|
s->def = typenod(errortype);
|
||||||
|
s->origpkg = builtinpkg;
|
||||||
|
}
|
||||||
|
|
||||||
s = lookup("rune");
|
s = lookup("rune");
|
||||||
if(s->def == N)
|
if(s->def == N) {
|
||||||
s->def = typenod(runetype);
|
s->def = typenod(runetype);
|
||||||
|
s->origpkg = builtinpkg;
|
||||||
|
}
|
||||||
|
|
||||||
s = lookup("nil");
|
s = lookup("nil");
|
||||||
if(s->def == N) {
|
if(s->def == N) {
|
||||||
v.ctype = CTNIL;
|
v.ctype = CTNIL;
|
||||||
s->def = nodlit(v);
|
s->def = nodlit(v);
|
||||||
s->def->sym = s;
|
s->def->sym = s;
|
||||||
|
s->origpkg = builtinpkg;
|
||||||
}
|
}
|
||||||
|
|
||||||
s = lookup("iota");
|
s = lookup("iota");
|
||||||
if(s->def == N) {
|
if(s->def == N) {
|
||||||
s->def = nod(OIOTA, N, N);
|
s->def = nod(OIOTA, N, N);
|
||||||
s->def->sym = s;
|
s->def->sym = s;
|
||||||
|
s->origpkg = builtinpkg;
|
||||||
}
|
}
|
||||||
|
|
||||||
s = lookup("true");
|
s = lookup("true");
|
||||||
if(s->def == N) {
|
if(s->def == N) {
|
||||||
s->def = nodbool(1);
|
s->def = nodbool(1);
|
||||||
s->def->sym = s;
|
s->def->sym = s;
|
||||||
|
s->origpkg = builtinpkg;
|
||||||
}
|
}
|
||||||
|
|
||||||
s = lookup("false");
|
s = lookup("false");
|
||||||
if(s->def == N) {
|
if(s->def == N) {
|
||||||
s->def = nodbool(0);
|
s->def = nodbool(0);
|
||||||
s->def->sym = s;
|
s->def->sym = s;
|
||||||
|
s->origpkg = builtinpkg;
|
||||||
}
|
}
|
||||||
|
|
||||||
nodfp = nod(ONAME, N, N);
|
nodfp = nod(ONAME, N, N);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
// Copyright 2012 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.
|
||||||
|
|
||||||
|
// A package that redeclares common builtin names.
|
||||||
|
package a
|
||||||
|
|
||||||
|
var true = 0 == 1
|
||||||
|
var false = 0 == 0
|
||||||
|
var nil = 1
|
||||||
|
|
||||||
|
const append = 42
|
||||||
|
|
||||||
|
type error bool
|
||||||
|
type int interface{}
|
||||||
|
|
||||||
|
func len(interface{}) int32 { return 42 }
|
||||||
|
|
||||||
|
func Test() {
|
||||||
|
var array [append]int
|
||||||
|
if true {
|
||||||
|
panic("unexpected builtin true instead of redeclared one")
|
||||||
|
}
|
||||||
|
if !false {
|
||||||
|
panic("unexpected builtin false instead of redeclared one")
|
||||||
|
}
|
||||||
|
if len(array) != 42 {
|
||||||
|
println(len(array))
|
||||||
|
panic("unexpected call of builtin len")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func InlinedFakeTrue() error { return error(true) }
|
||||||
|
func InlinedFakeFalse() error { return error(false) }
|
||||||
|
func InlinedFakeNil() int { return nil }
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
// Copyright 2012 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 "./a"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if a.InlinedFakeTrue() {
|
||||||
|
panic("returned true was the real one")
|
||||||
|
}
|
||||||
|
if !a.InlinedFakeFalse() {
|
||||||
|
panic("returned false was the real one")
|
||||||
|
}
|
||||||
|
if a.InlinedFakeNil() == nil {
|
||||||
|
panic("returned nil was the real one")
|
||||||
|
}
|
||||||
|
a.Test()
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
// rundir
|
||||||
|
|
||||||
|
// Copyright 2012 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.
|
||||||
|
|
||||||
|
// Issue 4252: tests that fixing the issue still allow
|
||||||
|
// builtins to be redeclared and are not corrupted
|
||||||
|
// in export data.
|
||||||
|
|
||||||
|
package ignored
|
||||||
Loading…
Reference in New Issue