diff options
| author | Michael Stapelberg <stapelberg@debian.org> | 2013-05-14 18:39:35 +0200 | 
|---|---|---|
| committer | Michael Stapelberg <michael@stapelberg.de> | 2013-05-14 18:39:35 +0200 | 
| commit | efcc50dfdc94c82ee0292bf71992ecb7c0123061 (patch) | |
| tree | 17dca99d1dc7fc4e9fe49c2cf6a99d337d4c039f /src/cmd/gc/unsafe.c | |
| parent | 04b08da9af0c450d645ab7389d1467308cfc2db8 (diff) | |
| download | golang-efcc50dfdc94c82ee0292bf71992ecb7c0123061.tar.gz | |
Imported Upstream version 1.1upstream/1.1
Diffstat (limited to 'src/cmd/gc/unsafe.c')
| -rw-r--r-- | src/cmd/gc/unsafe.c | 42 | 
1 files changed, 37 insertions, 5 deletions
| diff --git a/src/cmd/gc/unsafe.c b/src/cmd/gc/unsafe.c index 95200ad41..ff08c0eef 100644 --- a/src/cmd/gc/unsafe.c +++ b/src/cmd/gc/unsafe.c @@ -16,10 +16,10 @@  Node*  unsafenmagic(Node *nn)  { -	Node *r, *n; +	Node *r, *n, *base, *r1;  	Sym *s;  	Type *t, *tr; -	long v; +	vlong v;  	Val val;  	Node *fn;  	NodeList *args; @@ -49,11 +49,43 @@ unsafenmagic(Node *nn)  		goto yes;  	}  	if(strcmp(s->name, "Offsetof") == 0) { -		typecheck(&r, Erv); -		if(r->op != ODOT && r->op != ODOTPTR) +		// must be a selector. +		if(r->op != OXDOT)  			goto bad; +		// Remember base of selector to find it back after dot insertion. +		// Since r->left may be mutated by typechecking, check it explicitly +		// first to track it correctly. +		typecheck(&r->left, Erv); +		base = r->left;  		typecheck(&r, Erv); -		v = r->xoffset; +		switch(r->op) { +		case ODOT: +		case ODOTPTR: +			break; +		case OCALLPART: +			yyerror("invalid expression %N: argument is a method value", nn); +			v = 0; +			goto ret; +		default: +			goto bad; +		} +		v = 0; +		// add offsets for inserted dots. +		for(r1=r; r1->left!=base; r1=r1->left) { +			switch(r1->op) { +			case ODOT: +				v += r1->xoffset; +				break; +			case ODOTPTR: +				yyerror("invalid expression %N: selector implies indirection of embedded %N", nn, r1->left); +				goto ret; +			default: +				dump("unsafenmagic", r); +				fatal("impossible %#O node after dot insertion", r1->op); +				goto bad; +			} +		} +		v += r1->xoffset;  		goto yes;  	}  	if(strcmp(s->name, "Alignof") == 0) { | 
