2008-06-04 15:37:38 -06:00
|
|
|
// Copyright 2009 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.
|
|
|
|
|
2011-08-25 14:25:10 -06:00
|
|
|
#include <u.h>
|
|
|
|
#include <libc.h>
|
2008-06-04 15:37:38 -06:00
|
|
|
#include "go.h"
|
|
|
|
#include "y.tab.h"
|
|
|
|
|
2011-12-14 07:05:33 -07:00
|
|
|
static void dumpexporttype(Type *t);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2011-12-05 12:40:19 -07:00
|
|
|
// Mark n's symbol as exported
|
2008-09-26 22:27:26 -06:00
|
|
|
void
|
2009-08-04 23:59:23 -06:00
|
|
|
exportsym(Node *n)
|
2008-09-26 22:27:26 -06:00
|
|
|
{
|
2009-08-04 23:59:23 -06:00
|
|
|
if(n == N || n->sym == S)
|
2008-09-26 22:27:26 -06:00
|
|
|
return;
|
2009-08-04 23:59:23 -06:00
|
|
|
if(n->sym->flags & (SymExport|SymPackage)) {
|
|
|
|
if(n->sym->flags & SymPackage)
|
|
|
|
yyerror("export/package mismatch: %S", n->sym);
|
2008-09-26 22:27:26 -06:00
|
|
|
return;
|
2008-11-14 17:35:08 -07:00
|
|
|
}
|
2009-08-04 23:59:23 -06:00
|
|
|
n->sym->flags |= SymExport;
|
2008-09-26 22:27:26 -06:00
|
|
|
|
2010-06-14 12:24:51 -06:00
|
|
|
exportlist = list(exportlist, n);
|
2008-09-26 22:27:26 -06:00
|
|
|
}
|
|
|
|
|
2011-12-05 12:40:19 -07:00
|
|
|
// Mark n's symbol as package-local
|
2010-06-14 12:24:51 -06:00
|
|
|
static void
|
2009-08-04 23:59:23 -06:00
|
|
|
packagesym(Node *n)
|
2008-11-14 17:35:08 -07:00
|
|
|
{
|
2009-08-04 23:59:23 -06:00
|
|
|
if(n == N || n->sym == S)
|
2008-11-14 17:35:08 -07:00
|
|
|
return;
|
2009-08-04 23:59:23 -06:00
|
|
|
if(n->sym->flags & (SymExport|SymPackage)) {
|
|
|
|
if(n->sym->flags & SymExport)
|
|
|
|
yyerror("export/package mismatch: %S", n->sym);
|
2008-11-14 17:35:08 -07:00
|
|
|
return;
|
|
|
|
}
|
2009-08-04 23:59:23 -06:00
|
|
|
n->sym->flags |= SymPackage;
|
2008-11-14 17:35:08 -07:00
|
|
|
|
2010-06-14 12:24:51 -06:00
|
|
|
exportlist = list(exportlist, n);
|
2008-11-14 17:35:08 -07:00
|
|
|
}
|
2008-09-24 15:12:21 -06:00
|
|
|
|
2009-01-15 17:16:52 -07:00
|
|
|
int
|
|
|
|
exportname(char *s)
|
|
|
|
{
|
|
|
|
Rune r;
|
|
|
|
|
|
|
|
if((uchar)s[0] < Runeself)
|
|
|
|
return 'A' <= s[0] && s[0] <= 'Z';
|
|
|
|
chartorune(&r, s);
|
|
|
|
return isupperrune(r);
|
|
|
|
}
|
|
|
|
|
2011-03-02 14:18:17 -07:00
|
|
|
static int
|
|
|
|
initname(char *s)
|
|
|
|
{
|
|
|
|
return strcmp(s, "init") == 0;
|
|
|
|
}
|
|
|
|
|
2009-01-15 17:16:52 -07:00
|
|
|
void
|
2009-08-04 23:59:23 -06:00
|
|
|
autoexport(Node *n, int ctxt)
|
2009-01-15 17:16:52 -07:00
|
|
|
{
|
2009-08-04 23:59:23 -06:00
|
|
|
if(n == N || n->sym == S)
|
2009-01-15 17:16:52 -07:00
|
|
|
return;
|
2009-08-04 23:59:23 -06:00
|
|
|
if((ctxt != PEXTERN && ctxt != PFUNC) || dclcontext != PEXTERN)
|
2009-01-15 17:16:52 -07:00
|
|
|
return;
|
2009-08-07 13:50:26 -06:00
|
|
|
if(n->ntype && n->ntype->op == OTFUNC && n->ntype->left) // method
|
|
|
|
return;
|
2011-03-02 14:18:17 -07:00
|
|
|
if(exportname(n->sym->name) || initname(n->sym->name))
|
2009-08-04 23:59:23 -06:00
|
|
|
exportsym(n);
|
|
|
|
else
|
|
|
|
packagesym(n);
|
2009-01-15 17:16:52 -07:00
|
|
|
}
|
|
|
|
|
2010-06-14 12:24:51 -06:00
|
|
|
static void
|
2010-01-22 18:06:20 -07:00
|
|
|
dumppkg(Pkg *p)
|
|
|
|
{
|
2011-03-14 11:22:34 -06:00
|
|
|
char *suffix;
|
|
|
|
|
2011-12-14 07:05:33 -07:00
|
|
|
if(p == nil || p == localpkg || p->exported || p == builtinpkg)
|
2010-01-22 18:06:20 -07:00
|
|
|
return;
|
|
|
|
p->exported = 1;
|
2011-03-14 11:22:34 -06:00
|
|
|
suffix = "";
|
|
|
|
if(!p->direct)
|
|
|
|
suffix = " // indirect";
|
|
|
|
Bprint(bout, "\timport %s \"%Z\"%s\n", p->name, p->path, suffix);
|
2010-01-22 18:06:20 -07:00
|
|
|
}
|
|
|
|
|
2011-12-14 07:05:33 -07:00
|
|
|
// Look for anything we need for the inline body
|
|
|
|
static void reexportdep(Node *n);
|
|
|
|
static void
|
|
|
|
reexportdeplist(NodeList *ll)
|
|
|
|
{
|
|
|
|
for(; ll ;ll=ll->next)
|
|
|
|
reexportdep(ll->n);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
reexportdep(Node *n)
|
|
|
|
{
|
|
|
|
Type *t;
|
|
|
|
|
|
|
|
if(!n)
|
|
|
|
return;
|
|
|
|
|
2012-01-10 13:24:31 -07:00
|
|
|
// print("reexportdep %+hN\n", n);
|
2011-12-14 07:05:33 -07:00
|
|
|
switch(n->op) {
|
|
|
|
case ONAME:
|
|
|
|
switch(n->class&~PHEAP) {
|
|
|
|
case PFUNC:
|
2012-01-10 13:24:31 -07:00
|
|
|
// methods will be printed along with their type
|
|
|
|
if(!n->type || n->type->thistuple > 0)
|
|
|
|
break;
|
|
|
|
// fallthrough
|
2011-12-14 07:05:33 -07:00
|
|
|
case PEXTERN:
|
|
|
|
if (n->sym && n->sym->pkg != localpkg && n->sym->pkg != builtinpkg)
|
|
|
|
exportlist = list(exportlist, n);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2012-11-01 12:06:52 -06:00
|
|
|
case ODCL:
|
|
|
|
// Local variables in the bodies need their type.
|
|
|
|
t = n->left->type;
|
|
|
|
if(t != types[t->etype] && t != idealbool && t != idealstring) {
|
|
|
|
if(isptr[t->etype])
|
|
|
|
t = t->type;
|
|
|
|
if (t && t->sym && t->sym->def && t->sym->pkg != localpkg && t->sym->pkg != builtinpkg) {
|
|
|
|
exportlist = list(exportlist, t->sym->def);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2012-01-10 13:24:31 -07:00
|
|
|
|
2011-12-14 07:05:33 -07:00
|
|
|
case OLITERAL:
|
2012-01-10 13:24:31 -07:00
|
|
|
t = n->type;
|
2012-02-21 20:54:07 -07:00
|
|
|
if(t != types[n->type->etype] && t != idealbool && t != idealstring) {
|
2012-01-10 13:24:31 -07:00
|
|
|
if(isptr[t->etype])
|
|
|
|
t = t->type;
|
|
|
|
if (t && t->sym && t->sym->def && t->sym->pkg != localpkg && t->sym->pkg != builtinpkg) {
|
|
|
|
// print("reexport literal type %+hN\n", t->sym->def);
|
|
|
|
exportlist = list(exportlist, t->sym->def);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// fallthrough
|
|
|
|
case OTYPE:
|
2011-12-14 07:05:33 -07:00
|
|
|
if (n->sym && n->sym->pkg != localpkg && n->sym->pkg != builtinpkg)
|
|
|
|
exportlist = list(exportlist, n);
|
|
|
|
break;
|
|
|
|
|
|
|
|
// for operations that need a type when rendered, put the type on the export list.
|
|
|
|
case OCONV:
|
|
|
|
case OCONVIFACE:
|
|
|
|
case OCONVNOP:
|
|
|
|
case ODOTTYPE:
|
|
|
|
case OSTRUCTLIT:
|
|
|
|
case OPTRLIT:
|
|
|
|
t = n->type;
|
|
|
|
if(!t->sym && t->type)
|
|
|
|
t = t->type;
|
|
|
|
if (t && t->sym && t->sym->def && t->sym->pkg != localpkg && t->sym->pkg != builtinpkg) {
|
|
|
|
// print("reexport convnop %+hN\n", t->sym->def);
|
|
|
|
exportlist = list(exportlist, t->sym->def);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
reexportdep(n->left);
|
|
|
|
reexportdep(n->right);
|
|
|
|
reexportdeplist(n->list);
|
|
|
|
reexportdeplist(n->rlist);
|
|
|
|
reexportdeplist(n->ninit);
|
|
|
|
reexportdep(n->ntest);
|
|
|
|
reexportdep(n->nincr);
|
|
|
|
reexportdeplist(n->nbody);
|
|
|
|
reexportdeplist(n->nelse);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-06-14 12:24:51 -06:00
|
|
|
static void
|
2008-06-04 15:37:38 -06:00
|
|
|
dumpexportconst(Sym *s)
|
|
|
|
{
|
|
|
|
Node *n;
|
|
|
|
Type *t;
|
|
|
|
|
2009-06-06 13:46:38 -06:00
|
|
|
n = s->def;
|
2009-08-04 17:53:06 -06:00
|
|
|
typecheck(&n, Erv);
|
2008-06-04 15:37:38 -06:00
|
|
|
if(n == N || n->op != OLITERAL)
|
2008-07-27 14:09:15 -06:00
|
|
|
fatal("dumpexportconst: oconst nil: %S", s);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
t = n->type; // may or may not be specified
|
2011-10-31 11:09:40 -06:00
|
|
|
dumpexporttype(t);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2009-09-21 16:45:55 -06:00
|
|
|
if(t != T && !isideal(t))
|
2011-10-31 11:09:40 -06:00
|
|
|
Bprint(bout, "\tconst %#S %#T = %#V\n", s, t, &n->val);
|
|
|
|
else
|
|
|
|
Bprint(bout, "\tconst %#S = %#V\n", s, &n->val);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
2010-06-14 12:24:51 -06:00
|
|
|
static void
|
2008-06-04 15:37:38 -06:00
|
|
|
dumpexportvar(Sym *s)
|
|
|
|
{
|
|
|
|
Node *n;
|
|
|
|
Type *t;
|
|
|
|
|
2009-06-06 13:46:38 -06:00
|
|
|
n = s->def;
|
2012-01-10 13:24:31 -07:00
|
|
|
typecheck(&n, Erv|Ecall);
|
2008-07-05 18:43:25 -06:00
|
|
|
if(n == N || n->type == T) {
|
2008-07-14 21:40:48 -06:00
|
|
|
yyerror("variable exported but not defined: %S", s);
|
2008-07-05 18:43:25 -06:00
|
|
|
return;
|
|
|
|
}
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
t = n->type;
|
2011-10-31 11:09:40 -06:00
|
|
|
dumpexporttype(t);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2011-12-14 07:05:33 -07:00
|
|
|
if(t->etype == TFUNC && n->class == PFUNC) {
|
|
|
|
if (n->inl) {
|
2012-01-10 13:24:31 -07:00
|
|
|
// when lazily typechecking inlined bodies, some re-exported ones may not have been typechecked yet.
|
|
|
|
// currently that can leave unresolved ONONAMEs in import-dot-ed packages in the wrong package
|
|
|
|
if(debug['l'] < 2)
|
|
|
|
typecheckinl(n);
|
2011-12-14 07:05:33 -07:00
|
|
|
Bprint(bout, "\tfunc %#S%#hT { %#H }\n", s, t, n->inl);
|
|
|
|
reexportdeplist(n->inl);
|
|
|
|
} else
|
|
|
|
Bprint(bout, "\tfunc %#S%#hT\n", s, t);
|
|
|
|
} else
|
2011-10-31 11:09:40 -06:00
|
|
|
Bprint(bout, "\tvar %#S %#T\n", s, t);
|
2008-10-03 17:15:55 -06:00
|
|
|
}
|
|
|
|
|
2010-06-08 19:50:02 -06:00
|
|
|
static int
|
|
|
|
methcmp(const void *va, const void *vb)
|
|
|
|
{
|
|
|
|
Type *a, *b;
|
|
|
|
|
|
|
|
a = *(Type**)va;
|
|
|
|
b = *(Type**)vb;
|
|
|
|
return strcmp(a->sym->name, b->sym->name);
|
|
|
|
}
|
|
|
|
|
2010-06-14 12:24:51 -06:00
|
|
|
static void
|
2011-10-31 11:09:40 -06:00
|
|
|
dumpexporttype(Type *t)
|
2008-10-03 17:15:55 -06:00
|
|
|
{
|
2011-10-31 11:09:40 -06:00
|
|
|
Type *f;
|
2010-06-08 19:50:02 -06:00
|
|
|
Type **m;
|
|
|
|
int i, n;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2011-10-31 11:09:40 -06:00
|
|
|
if(t == T)
|
|
|
|
return;
|
2011-11-01 19:46:41 -06:00
|
|
|
if(t->printed || t == types[t->etype] || t == bytetype || t == runetype || t == errortype)
|
2011-10-31 11:09:40 -06:00
|
|
|
return;
|
|
|
|
t->printed = 1;
|
|
|
|
|
|
|
|
if(t->sym != S && t->etype != TFIELD)
|
|
|
|
dumppkg(t->sym->pkg);
|
|
|
|
|
|
|
|
dumpexporttype(t->type);
|
|
|
|
dumpexporttype(t->down);
|
|
|
|
|
|
|
|
if (t->sym == S || t->etype == TFIELD)
|
|
|
|
return;
|
|
|
|
|
|
|
|
n = 0;
|
|
|
|
for(f=t->method; f!=T; f=f->down) {
|
|
|
|
dumpexporttype(f);
|
|
|
|
n++;
|
|
|
|
}
|
|
|
|
|
|
|
|
m = mal(n*sizeof m[0]);
|
|
|
|
i = 0;
|
|
|
|
for(f=t->method; f!=T; f=f->down)
|
|
|
|
m[i++] = f;
|
|
|
|
qsort(m, n, sizeof m[0], methcmp);
|
|
|
|
|
|
|
|
Bprint(bout, "\ttype %#S %#lT\n", t->sym, t);
|
|
|
|
for(i=0; i<n; i++) {
|
|
|
|
f = m[i];
|
2011-12-14 07:05:33 -07:00
|
|
|
if (f->type->nname && f->type->nname->inl) { // nname was set by caninl
|
2012-01-10 13:24:31 -07:00
|
|
|
// when lazily typechecking inlined bodies, some re-exported ones may not have been typechecked yet.
|
|
|
|
// currently that can leave unresolved ONONAMEs in import-dot-ed packages in the wrong package
|
|
|
|
if(debug['l'] < 2)
|
|
|
|
typecheckinl(f->type->nname);
|
cmd/gc, cmd/ld: struct field tracking
This is an experiment in static analysis of Go programs
to understand which struct fields a program might use.
It is not part of the Go language specification, it must
be enabled explicitly when building the toolchain,
and it may be removed at any time.
After building the toolchain with GOEXPERIMENT=fieldtrack,
a specific field can be marked for tracking by including
`go:"track"` in the field tag:
package pkg
type T struct {
F int `go:"track"`
G int // untracked
}
To simplify usage, only named struct types can have
tracked fields, and only exported fields can be tracked.
The implementation works by making each function begin
with a sequence of no-op USEFIELD instructions declaring
which tracked fields are accessed by a specific function.
After the linker's dead code elimination removes unused
functions, the fields referred to by the remaining
USEFIELD instructions are the ones reported as used by
the binary.
The -k option to the linker specifies the fully qualified
symbol name (such as my/pkg.list) of a string variable that
should be initialized with the field tracking information
for the program. The field tracking string is a sequence
of lines, each terminated by a \n and describing a single
tracked field referred to by the program. Each line is made
up of one or more tab-separated fields. The first field is
the name of the tracked field, fully qualified, as in
"my/pkg.T.F". Subsequent fields give a shortest path of
reverse references from that field to a global variable or
function, corresponding to one way in which the program
might reach that field.
A common source of false positives in field tracking is
types with large method sets, because a reference to the
type descriptor carries with it references to all methods.
To address this problem, the CL also introduces a comment
annotation
//go:nointerface
that marks an upcoming method declaration as unavailable
for use in satisfying interfaces, both statically and
dynamically. Such a method is also invisible to package
reflect.
Again, all of this is disabled by default. It only turns on
if you have GOEXPERIMENT=fieldtrack set during make.bash.
R=iant, ken
CC=golang-dev
https://golang.org/cl/6749064
2012-11-01 22:17:21 -06:00
|
|
|
if(f->nointerface)
|
|
|
|
Bprint(bout, "\t//go:nointerface\n");
|
2011-12-14 07:05:33 -07:00
|
|
|
Bprint(bout, "\tfunc (%#T) %#hhS%#hT { %#H }\n", getthisx(f->type)->type, f->sym, f->type, f->type->nname->inl);
|
|
|
|
reexportdeplist(f->type->nname->inl);
|
|
|
|
} else
|
|
|
|
Bprint(bout, "\tfunc (%#T) %#hhS%#hT\n", getthisx(f->type)->type, f->sym, f->type);
|
2011-10-31 11:09:40 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
dumpsym(Sym *s)
|
|
|
|
{
|
2009-08-04 23:59:23 -06:00
|
|
|
if(s->flags & SymExported)
|
2008-06-04 15:37:38 -06:00
|
|
|
return;
|
2009-08-04 23:59:23 -06:00
|
|
|
s->flags |= SymExported;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2009-06-06 13:46:38 -06:00
|
|
|
if(s->def == N) {
|
2008-09-30 14:49:31 -06:00
|
|
|
yyerror("unknown export symbol: %S", s);
|
2009-06-06 13:46:38 -06:00
|
|
|
return;
|
|
|
|
}
|
2012-01-10 13:24:31 -07:00
|
|
|
// print("dumpsym %O %+S\n", s->def->op, s);
|
2010-01-22 18:06:20 -07:00
|
|
|
dumppkg(s->pkg);
|
|
|
|
|
2009-06-06 13:46:38 -06:00
|
|
|
switch(s->def->op) {
|
|
|
|
default:
|
|
|
|
yyerror("unexpected export symbol: %O %S", s->def->op, s);
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
2011-12-05 12:40:19 -07:00
|
|
|
|
2009-06-06 13:46:38 -06:00
|
|
|
case OLITERAL:
|
|
|
|
dumpexportconst(s);
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
2011-12-05 12:40:19 -07:00
|
|
|
|
2009-06-06 13:46:38 -06:00
|
|
|
case OTYPE:
|
2011-10-31 11:09:40 -06:00
|
|
|
if(s->def->type->etype == TFORW)
|
|
|
|
yyerror("export of incomplete type %S", s);
|
|
|
|
else
|
|
|
|
dumpexporttype(s->def->type);
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
2011-12-05 12:40:19 -07:00
|
|
|
|
2009-06-06 13:46:38 -06:00
|
|
|
case ONAME:
|
|
|
|
dumpexportvar(s);
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dumpexport(void)
|
|
|
|
{
|
2009-08-04 23:59:23 -06:00
|
|
|
NodeList *l;
|
2011-03-14 11:22:34 -06:00
|
|
|
int32 i, lno;
|
|
|
|
Pkg *p;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2008-06-26 18:54:44 -06:00
|
|
|
lno = lineno;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2011-10-31 11:09:40 -06:00
|
|
|
Bprint(bout, "\n$$ // exports\n package %s", localpkg->name);
|
2010-06-11 16:28:43 -06:00
|
|
|
if(safemode)
|
|
|
|
Bprint(bout, " safe");
|
|
|
|
Bprint(bout, "\n");
|
2008-06-12 22:48:56 -06:00
|
|
|
|
2011-03-14 11:22:34 -06:00
|
|
|
for(i=0; i<nelem(phash); i++)
|
|
|
|
for(p=phash[i]; p; p=p->link)
|
|
|
|
if(p->direct)
|
|
|
|
dumppkg(p);
|
|
|
|
|
2009-08-04 23:59:23 -06:00
|
|
|
for(l=exportlist; l; l=l->next) {
|
|
|
|
lineno = l->n->lineno;
|
|
|
|
dumpsym(l->n->sym);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
2011-10-31 11:09:40 -06:00
|
|
|
Bprint(bout, "\n$$ // local types\n\n$$\n"); // 6l expects this. (see ld/go.c)
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2008-06-26 18:54:44 -06:00
|
|
|
lineno = lno;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2008-10-03 17:15:55 -06:00
|
|
|
* import
|
2008-06-04 15:37:38 -06:00
|
|
|
*/
|
2008-09-24 15:12:21 -06:00
|
|
|
|
2008-10-03 17:15:55 -06:00
|
|
|
/*
|
|
|
|
* return the sym for ss, which should match lexical
|
|
|
|
*/
|
2008-06-11 22:06:26 -06:00
|
|
|
Sym*
|
2009-06-06 13:46:38 -06:00
|
|
|
importsym(Sym *s, int op)
|
2008-06-11 22:06:26 -06:00
|
|
|
{
|
2012-09-13 10:40:50 -06:00
|
|
|
char *pkgstr;
|
|
|
|
|
|
|
|
if(s->def != N && s->def->op != op) {
|
|
|
|
pkgstr = smprint("during import \"%Z\"", importpkg->path);
|
|
|
|
redeclare(s, pkgstr);
|
|
|
|
}
|
2009-06-29 16:13:37 -06:00
|
|
|
|
|
|
|
// mark the symbol so it is not reexported
|
|
|
|
if(s->def == N) {
|
2011-03-02 14:18:17 -07:00
|
|
|
if(exportname(s->name) || initname(s->name))
|
2009-08-04 23:59:23 -06:00
|
|
|
s->flags |= SymExport;
|
2009-06-29 16:13:37 -06:00
|
|
|
else
|
2009-08-04 23:59:23 -06:00
|
|
|
s->flags |= SymPackage; // package scope
|
2009-06-29 16:13:37 -06:00
|
|
|
}
|
2008-06-11 22:06:26 -06:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
/*
|
2008-10-03 17:15:55 -06:00
|
|
|
* return the type pkg.name, forward declaring if needed
|
2008-06-04 15:37:38 -06:00
|
|
|
*/
|
2008-10-03 17:15:55 -06:00
|
|
|
Type*
|
2009-06-06 13:46:38 -06:00
|
|
|
pkgtype(Sym *s)
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2008-10-03 17:15:55 -06:00
|
|
|
Type *t;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2009-06-06 13:46:38 -06:00
|
|
|
importsym(s, OTYPE);
|
|
|
|
if(s->def == N || s->def->op != OTYPE) {
|
2008-10-03 17:15:55 -06:00
|
|
|
t = typ(TFORW);
|
|
|
|
t->sym = s;
|
2009-06-06 13:46:38 -06:00
|
|
|
s->def = typenod(t);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2009-08-12 14:18:19 -06:00
|
|
|
if(s->def->type == T)
|
2011-10-31 11:09:40 -06:00
|
|
|
yyerror("pkgtype %S", s);
|
2009-06-06 13:46:38 -06:00
|
|
|
return s->def->type;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
2011-12-05 12:40:19 -07:00
|
|
|
void
|
|
|
|
importimport(Sym *s, Strlit *z)
|
2008-11-14 17:35:08 -07:00
|
|
|
{
|
2011-12-05 12:40:19 -07:00
|
|
|
// Informational: record package name
|
|
|
|
// associated with import path, for use in
|
|
|
|
// human-readable messages.
|
|
|
|
Pkg *p;
|
|
|
|
|
2012-10-23 09:16:08 -06:00
|
|
|
if(isbadimport(z))
|
|
|
|
errorexit();
|
2011-12-05 12:40:19 -07:00
|
|
|
p = mkpkg(z);
|
|
|
|
if(p->name == nil) {
|
|
|
|
p->name = s->name;
|
|
|
|
pkglookup(s->name, nil)->npkg++;
|
|
|
|
} else if(strcmp(p->name, s->name) != 0)
|
|
|
|
yyerror("conflicting names %s and %s for package \"%Z\"", p->name, s->name, p->path);
|
|
|
|
|
|
|
|
if(!incannedimport && myimportpath != nil && strcmp(z->s, myimportpath) == 0) {
|
|
|
|
yyerror("import \"%Z\": package depends on \"%Z\" (import cycle)", importpkg->path, z);
|
|
|
|
errorexit();
|
|
|
|
}
|
2008-11-14 17:35:08 -07:00
|
|
|
}
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
void
|
2009-06-06 13:46:38 -06:00
|
|
|
importconst(Sym *s, Type *t, Node *n)
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-08-12 14:18:19 -06:00
|
|
|
Node *n1;
|
|
|
|
|
2009-06-06 13:46:38 -06:00
|
|
|
importsym(s, OLITERAL);
|
2009-07-17 14:38:16 -06:00
|
|
|
convlit(&n, t);
|
2011-12-05 12:40:19 -07:00
|
|
|
|
|
|
|
if(s->def != N) // TODO: check if already the same.
|
2008-10-03 17:15:55 -06:00
|
|
|
return;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2009-08-04 23:59:23 -06:00
|
|
|
if(n->op != OLITERAL) {
|
|
|
|
yyerror("expression must be a constant");
|
|
|
|
return;
|
|
|
|
}
|
2011-12-05 12:40:19 -07:00
|
|
|
|
2009-08-12 14:18:19 -06:00
|
|
|
if(n->sym != S) {
|
|
|
|
n1 = nod(OXXX, N, N);
|
|
|
|
*n1 = *n;
|
|
|
|
n = n1;
|
|
|
|
}
|
2012-01-29 02:35:11 -07:00
|
|
|
n->orig = newname(s);
|
2009-08-04 23:59:23 -06:00
|
|
|
n->sym = s;
|
|
|
|
declare(n, PEXTERN);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2009-03-12 20:04:38 -06:00
|
|
|
if(debug['E'])
|
2008-10-03 17:15:55 -06:00
|
|
|
print("import const %S\n", s);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2011-12-05 12:40:19 -07:00
|
|
|
importvar(Sym *s, Type *t)
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-08-04 23:59:23 -06:00
|
|
|
Node *n;
|
|
|
|
|
2009-06-06 13:46:38 -06:00
|
|
|
importsym(s, ONAME);
|
|
|
|
if(s->def != N && s->def->op == ONAME) {
|
2010-06-08 19:50:02 -06:00
|
|
|
if(eqtype(t, s->def->type))
|
2008-10-03 17:15:55 -06:00
|
|
|
return;
|
2011-10-31 11:09:40 -06:00
|
|
|
yyerror("inconsistent definition for var %S during import\n\t%T\n\t%T", s, s->def->type, t);
|
2008-10-03 17:15:55 -06:00
|
|
|
}
|
2009-08-04 23:59:23 -06:00
|
|
|
n = newname(s);
|
|
|
|
n->type = t;
|
2011-12-05 12:40:19 -07:00
|
|
|
declare(n, PEXTERN);
|
2008-06-15 21:24:30 -06:00
|
|
|
|
2009-03-12 20:04:38 -06:00
|
|
|
if(debug['E'])
|
2008-10-03 17:15:55 -06:00
|
|
|
print("import var %S %lT\n", s, t);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-08-07 13:50:26 -06:00
|
|
|
importtype(Type *pt, Type *t)
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2011-11-29 05:34:08 -07:00
|
|
|
Node *n;
|
|
|
|
|
2011-12-05 12:40:19 -07:00
|
|
|
// override declaration in unsafe.go for Pointer.
|
|
|
|
// there is no way in Go code to define unsafe.Pointer
|
|
|
|
// so we have to supply it.
|
|
|
|
if(incannedimport &&
|
|
|
|
strcmp(importpkg->name, "unsafe") == 0 &&
|
|
|
|
strcmp(pt->nod->sym->name, "Pointer") == 0) {
|
|
|
|
t = types[TUNSAFEPTR];
|
2011-11-29 05:34:08 -07:00
|
|
|
}
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2011-12-05 12:40:19 -07:00
|
|
|
if(pt->etype == TFORW) {
|
|
|
|
n = pt->nod;
|
|
|
|
copytype(pt->nod, t);
|
|
|
|
pt->nod = n; // unzero nod
|
|
|
|
pt->sym->lastlineno = parserline();
|
|
|
|
declare(n, PEXTERN);
|
|
|
|
checkwidth(pt);
|
2012-01-20 15:14:09 -07:00
|
|
|
} else if(!eqtype(pt->orig, t))
|
2012-01-17 02:00:57 -07:00
|
|
|
yyerror("inconsistent definition for type %S during import\n\t%lT\n\t%lT", pt->sym, pt, t);
|
2011-12-05 12:40:19 -07:00
|
|
|
|
2009-03-12 20:04:38 -06:00
|
|
|
if(debug['E'])
|
2009-08-07 13:50:26 -06:00
|
|
|
print("import type %T %lT\n", pt, t);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|