Commit 561edbd6 authored by Rémy Oudompheng's avatar Rémy Oudompheng

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
parent ec459526
...@@ -22,22 +22,8 @@ exportsym(Node *n) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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,54 +2027,68 @@ lexfini(void) ...@@ -2025,54 +2027,68 @@ 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);
nodfp->type = types[TINT32]; nodfp->type = types[TINT32];
nodfp->xoffset = 0; nodfp->xoffset = 0;
......
// 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 }
// 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()
}
// 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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment