view dmd/TypePointer.d @ 135:af1bebfd96a4 dmd2037

dmd 2.038
author Eldar Insafutdinov <e.insafutdinov@gmail.com>
date Mon, 13 Sep 2010 22:19:42 +0100
parents e28b18c23469
children e3afd1303184
line wrap: on
line source

module dmd.TypePointer;

import dmd.common;
import dmd.Type;
import dmd.Loc;
import dmd.Scope;
import dmd.TypeNext;
import dmd.OutBuffer;
import dmd.HdrGenState;
import dmd.MATCH;
import dmd.Expression;
import dmd.NullExp;
import dmd.TypeInfoDeclaration;
import dmd.TypeInfoPointerDeclaration;
import dmd.CppMangleState;
import dmd.TY;
import dmd.Util;
import dmd.MOD;
import dmd.Global;

import dmd.backend.TYPE;
import dmd.backend.Util;
import dmd.backend.TYM;

class TypePointer : TypeNext
{
    this(Type t)
	{
		super(TY.Tpointer, t);
	}
version (DumbClone) {
} else {		
	final TypePointer cloneTo(TypePointer t)
	{
		super.cloneTo(t);
		return t;
	}

	TypePointer clone()
	{
		assert(this.classinfo == TypePointer.classinfo);
		return cloneTo(new TypePointer(next));
	}
}
    override Type syntaxCopy()
	{
		Type t = next.syntaxCopy();
		if (t == next)
			t = this;
		else
		{	
			t = new TypePointer(t);
			t.mod = mod;
		}
		return t;
	}
	
    override Type semantic(Loc loc, Scope sc)
	{
		//printf("TypePointer.semantic()\n");
		if (deco)
			return this;
		Type n = next.semantic(loc, sc);
		switch (n.toBasetype().ty)
		{
			case TY.Ttuple:
				error(loc, "can't have pointer to %s", n.toChars());
				n = tint32;
				break;
			default:
				break;
		}
		if (n !is next)
		{
			deco = null;
		}
		next = n;
		transitive();
		return merge();
	}
	
    override ulong size(Loc loc)
	{
		return PTRSIZE;
	}
	
    override void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod)
	{
		//printf("TypePointer::toCBuffer2() next = %d\n", next->ty);
		if (mod != this.mod)
		{	
			toCBuffer3(buf, hgs, mod);
			return;
		}
		next.toCBuffer2(buf, hgs, this.mod);
		if (next.ty != Tfunction)
			buf.writeByte('*');
	}
	
    override MATCH implicitConvTo(Type to)
	{
		//printf("TypePointer.implicitConvTo(to = %s) %s\n", to.toChars(), toChars());

		if (equals(to))
			return MATCH.MATCHexact;
		if (to.ty == TY.Tpointer)
		{	
			TypePointer tp = cast(TypePointer)to;
			assert(tp.next);

			if (!MODimplicitConv(next.mod, tp.next.mod))
				return MATCH.MATCHnomatch;        // not const-compatible

			/* Alloc conversion to void[]
			 */
			if (next.ty != TY.Tvoid && tp.next.ty == TY.Tvoid)
			{
				return MATCH.MATCHconvert;
			}

			MATCH m = next.constConv(tp.next);
			if (m != MATCH.MATCHnomatch)
			{
				if (m == MATCH.MATCHexact && mod != to.mod)
					m = MATCH.MATCHconst;
				return m;
			}

			/* Conversion of ptr to derived to ptr to base
			 */
			int offset = 0;
			if (tp.next.isBaseOf(next, &offset) && offset == 0)
				return MATCH.MATCHconvert;
		}
		return MATCH.MATCHnomatch;
	}
	
    override bool isscalar()
	{
		return true;
	}
	
    override Expression defaultInit(Loc loc)
	{
	version (LOGDEFAULTINIT) {
		printf("TypePointer::defaultInit() '%s'\n", toChars());
	}
		return new NullExp(loc, this);
	}
	
    override bool isZeroInit(Loc loc)
	{
		return true;
	}
	
    override TypeInfoDeclaration getTypeInfoDeclaration()
	{
		return new TypeInfoPointerDeclaration(this);
	}
	
    override bool hasPointers()
	{
		return true;
	}
	
version (CPP_MANGLE) {
    void toCppMangle(OutBuffer buf, CppMangleState* cms)
	{
		assert(false);
	}
}

    override type* toCtype()
	{
		type* tn;
		type* t;

		//printf("TypePointer.toCtype() %s\n", toChars());
		if (ctype)
			return ctype;

		if (1 || global.params.symdebug)
		{	/* Need to always do this, otherwise C++ name mangling
			 * goes awry.
			 */
			t = type_alloc(TYM.TYnptr);
			ctype = t;
			tn = next.toCtype();
			t.Tnext = tn;
			tn.Tcount++;
		}
		else
			t = type_fake(totym());

		t.Tcount++;
		ctype = t;
		return t;
	}
}