Mercurial > projects > ddmd
diff dmd/Type.d @ 0:10317f0c89a5
Initial commit
author | korDen |
---|---|
date | Sat, 24 Oct 2009 08:42:06 +0400 |
parents | |
children | 7427ded8caf7 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/Type.d Sat Oct 24 08:42:06 2009 +0400 @@ -0,0 +1,2445 @@ +module dmd.Type; + +import dmd.TY; +import dmd.Argument; +import dmd.TOK; +import dmd.STC; +import dmd.TypeArray; +import dmd.DotVarExp; +import dmd.ErrorExp; +import dmd.StringExp; +import dmd.IntegerExp; +import dmd.VarExp; +import dmd.TemplateParameter; +import dmd.TypeInfoSharedDeclaration; +import dmd.TypeInfoConstDeclaration; +import dmd.TypeInfoInvariantDeclaration; +import dmd.Module; +import dmd.Id; +import dmd.Util; +import dmd.VarDeclaration; +import dmd.Loc; +import dmd.Scope; +import dmd.OutBuffer; +import dmd.Identifier; +import dmd.HdrGenState; +import dmd.Expression; +import dmd.Dsymbol; +import dmd.MATCH; +import dmd.TypeInfoDeclaration; +import dmd.ClassDeclaration; +import dmd.StringTable; +import dmd.ArrayTypes; +import dmd.TypeBasic; +import dmd.DYNCAST; +import dmd.MOD; +import dmd.Lexer; +import dmd.TypeSArray; +import dmd.TypeDArray; +import dmd.TypeAArray; +import dmd.TypePointer; +import dmd.TypeReference; +import dmd.TypeFunction; +import dmd.TypeDelegate; +import dmd.TypeIdentifier; +import dmd.TypeInstance; +import dmd.TypeTypeof; +import dmd.TypeReturn; +import dmd.TypeStruct; +import dmd.TypeEnum; +import dmd.TypeTypedef; +import dmd.TypeClass; +import dmd.TypeTuple; +import dmd.TypeSlice; +import dmd.Global; +import dmd.StringValue; + +import dmd.backend.Symbol; +import dmd.backend.TYPE; +import dmd.backend.dt_t; +import dmd.backend.Util; +import dmd.backend.TYM; +import dmd.backend.mTY; + +import core.stdc.stdio; + +/* These have default values for 32 bit code, they get + * adjusted for 64 bit code. + */ + +int PTRSIZE = 4; + +int Tsize_t; +int Tptrdiff_t; + +/* REALSIZE = size a real consumes in memory + * REALPAD = 'padding' added to the CPU real size to bring it up to REALSIZE + * REALALIGNSIZE = alignment for reals + */ +version (TARGET_OSX) { + int REALSIZE = 16; + int REALPAD = 6; + int REALALIGNSIZE = 16; +} else version (XXX) { /// TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS + int REALSIZE = 12; + int REALPAD = 2; + int REALALIGNSIZE = 4; +} else { + int REALSIZE = 10; + int REALPAD = 0; + int REALALIGNSIZE = 2; +} + +/**** + * Given an identifier, figure out which TemplateParameter it is. + * Return -1 if not found. + */ + +int templateIdentifierLookup(Identifier id, TemplateParameters parameters) +{ + for (size_t i = 0; i < parameters.dim; i++) + { + TemplateParameter tp = cast(TemplateParameter)parameters.data[i]; + + if (tp.ident.equals(id)) + return i; + } + return -1; +} + +int templateParameterLookup(Type tparam, TemplateParameters parameters) +{ + assert(tparam.ty == Tident); + TypeIdentifier tident = cast(TypeIdentifier)tparam; + //printf("\ttident = '%s'\n", tident.toChars()); + if (tident.idents.dim == 0) + { + return templateIdentifierLookup(tident.ident, parameters); + } + return -1; +} + +class Type +{ + TY ty; + MOD mod; // modifiers MODxxxx + /* pick this order of numbers so switch statements work better + */ +/// #define MODconst 1 // type is const +/// #define MODinvariant 4 // type is invariant +/// #define MODshared 2 // type is shared + string deco; + + /* These are cached values that are lazily evaluated by constOf(), invariantOf(), etc. + * They should not be referenced by anybody but mtype.c. + * They can be null if not lazily evaluated yet. + * Note that there is no "shared immutable", because that is just immutable + */ + + Type cto; // MODconst ? mutable version of this type : const version + Type ito; // MODinvariant ? mutable version of this type : invariant version + Type sto; // MODshared ? mutable version of this type : shared mutable version + Type scto; // MODshared|MODconst ? mutable version of this type : shared const version + + Type pto; // merged pointer to this type + Type rto; // reference to this type + Type arrayof; // array of this type + TypeInfoDeclaration vtinfo; // TypeInfo object for this Type + + type* ctype; // for back end + + static ClassDeclaration typeinfo; + static ClassDeclaration typeinfoclass; + static ClassDeclaration typeinfointerface; + static ClassDeclaration typeinfostruct; + static ClassDeclaration typeinfotypedef; + static ClassDeclaration typeinfopointer; + static ClassDeclaration typeinfoarray; + static ClassDeclaration typeinfostaticarray; + static ClassDeclaration typeinfoassociativearray; + static ClassDeclaration typeinfoenum; + static ClassDeclaration typeinfofunction; + static ClassDeclaration typeinfodelegate; + static ClassDeclaration typeinfotypelist; + static ClassDeclaration typeinfoconst; + static ClassDeclaration typeinfoinvariant; + static ClassDeclaration typeinfoshared; + + static Type basic[TY.TMAX]; + static ubyte mangleChar[TY.TMAX]; + static ubyte sizeTy[TY.TMAX]; + static StringTable stringtable; + + // These tables are for implicit conversion of binary ops; + // the indices are the type of operand one, followed by operand two. + static ubyte impcnvResult[TY.TMAX][TY.TMAX] = [ + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,29,30,31,37,19,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,29,30,31,37,19,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,29,30,31,37,19,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,29,30,31,37,19,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,29,30,31,37,19,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,20,20,20,20,20,20,21,22,23,24,25,23,24,25,29,30,31,37,20,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,21,21,21,21,21,21,21,22,23,24,25,23,24,25,29,30,31,37,21,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,22,22,22,22,22,22,22,22,23,24,25,23,24,25,29,30,31,37,22,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,23,23,23,23,23,23,23,23,23,24,25,23,24,25,29,30,31,37,23,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,24,24,24,24,24,24,24,24,24,24,25,24,24,25,30,30,31,37,24,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,25,25,25,25,25,25,25,25,25,25,25,25,25,25,31,31,31,37,25,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,23,23,23,23,23,23,23,23,23,24,25,26,27,28,29,30,31,37,23,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,24,24,24,24,24,24,24,24,24,24,25,27,27,28,30,30,31,37,24,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,25,25,25,25,25,25,25,25,25,25,25,28,28,28,31,31,31,37,25,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,29,29,29,29,29,29,29,29,29,30,31,29,30,31,29,30,31,37,29,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,30,30,30,30,30,30,30,30,30,30,31,30,30,31,30,30,31,37,30,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,37,31,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,29,30,31,37,33,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + ]; + + static ubyte impcnvType1[TY.TMAX][TY.TMAX] = [ + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,23,24,25,37,19,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,23,24,25,37,19,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,23,24,25,37,19,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,23,24,25,37,19,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,23,24,25,37,19,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,20,20,20,20,20,20,21,22,23,24,25,23,24,25,23,24,25,37,20,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,21,21,21,21,21,21,21,22,23,24,25,23,24,25,23,24,25,37,21,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,22,22,22,22,22,22,22,22,23,24,25,23,24,25,23,24,25,37,22,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,23,23,23,23,23,23,23,23,23,24,25,23,24,25,23,24,25,37,23,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,24,24,24,24,24,24,24,24,24,24,25,24,24,25,24,24,25,37,24,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,37,25,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,26,26,26,26,26,26,26,26,26,27,28,26,27,28,26,27,28,37,26,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,27,27,27,27,27,27,27,27,27,27,28,27,27,28,27,27,28,37,27,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,37,28,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,29,29,29,29,29,29,29,29,29,30,31,29,30,31,29,30,31,37,29,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,30,30,30,30,30,30,30,30,30,30,31,30,30,31,30,30,31,37,30,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,37,31,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,23,24,25,37,33,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + ]; + + static ubyte impcnvType2[TY.TMAX][TY.TMAX] = [ + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,26,27,28,29,30,31,37,19,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,26,27,28,29,30,31,37,19,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,26,27,28,29,30,31,37,19,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,26,27,28,29,30,31,37,19,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,26,27,28,29,30,31,37,19,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,20,20,20,20,20,20,21,22,23,24,25,26,27,28,29,30,31,37,20,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,21,21,21,21,21,21,21,22,23,24,25,26,27,28,29,30,31,37,21,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,22,22,22,22,22,22,22,22,23,24,25,26,27,28,29,30,31,37,22,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,23,23,23,23,23,23,23,23,23,24,25,26,27,28,29,30,31,37,23,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,24,24,24,24,24,24,24,24,24,24,25,27,27,28,30,30,31,37,24,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,25,25,25,25,25,25,25,25,25,25,25,28,28,28,31,31,31,37,25,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,23,23,23,23,23,23,23,23,23,24,25,26,27,28,29,30,31,37,23,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,24,24,24,24,24,24,24,24,24,24,25,27,27,28,30,30,31,37,24,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,25,25,25,25,25,25,25,25,25,25,25,28,28,28,31,31,31,37,25,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,23,23,23,23,23,23,23,23,23,24,25,26,27,28,29,30,31,37,23,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,24,24,24,24,24,24,24,24,24,24,25,27,27,28,30,30,31,37,24,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,25,25,25,25,25,25,25,25,25,25,25,28,28,28,31,31,31,37,25,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,26,27,28,29,30,31,37,33,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + [37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37], + ]; + + // If !=0, give warning on implicit conversion + static const(bool) impcnvWarn[TY.TMAX][TY.TMAX] = [ + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + ]; + + static this() + { + stringtable = new StringTable(); + } + + static ~this() + { + delete stringtable; + } + + this(TY ty) + { + this.ty = ty; + } + + Type syntaxCopy() + { + assert(false); + } + + int equals(Object o) + { + Type t = cast(Type)o; + //printf("Type.equals(%s, %s)\n", toChars(), t.toChars()); + if (this is o || (t && deco == t.deco) && // deco strings are unique + deco !is null) // and semantic() has been run + { + //printf("deco = '%s', t.deco = '%s'\n", deco, t.deco); + return 1; + } + //if (deco && t && t.deco) printf("deco = '%s', t.deco = '%s'\n", deco, t.deco); + return 0; + } + + DYNCAST dyncast() { return DYNCAST.DYNCAST_TYPE; } // kludge for template.isType() + + /******************************* + * Returns: + * 0 types are distinct + * 1 this is covariant with t + * 2 arguments match as far as overloading goes, + * but types are not covariant + * 3 cannot determine covariance because of forward references + */ + int covariant(Type t) + { +static if (false) { + printf("Type.covariant(t = %s) %s\n", t.toChars(), toChars()); + printf("deco = %p, %p\n", deco, t.deco); + // printf("ty = %d\n", next.ty); + printf("mod = %x, %x\n", mod, t.mod); +} + + int inoutmismatch = 0; + + TypeFunction t1; + TypeFunction t2; + + if (equals(t)) + return 1; // covariant + + if (ty != TY.Tfunction || t.ty != TY.Tfunction) + goto Ldistinct; + + t1 = cast(TypeFunction)this; + t2 = cast(TypeFunction)t; + + if (t1.varargs != t2.varargs) + goto Ldistinct; + + if (t1.parameters && t2.parameters) + { + size_t dim = Argument.dim(t1.parameters); + if (dim != Argument.dim(t2.parameters)) + goto Ldistinct; + + for (size_t i = 0; i < dim; i++) + { + Argument arg1 = Argument.getNth(t1.parameters, i); + Argument arg2 = Argument.getNth(t2.parameters, i); + + if (!arg1.type.equals(arg2.type)) + { +///static if (false) { +/// // turn on this for contravariant argument types, see bugzilla 3075 +/// // We can add const, but not subtract it +/// if (arg2.type.implicitConvTo(arg1.type) < MATCH.MATCHconst) +///} + goto Ldistinct; + } + if ((arg1.storageClass & ~STC.STCscope) != (arg2.storageClass & ~STC.STCscope)) + inoutmismatch = 1; + // We can add scope, but not subtract it + if (!(arg1.storageClass & STC.STCscope) && (arg2.storageClass & STC.STCscope)) + inoutmismatch = 1; + } + } + else if (t1.parameters != t2.parameters) + goto Ldistinct; + + // The argument lists match + if (inoutmismatch) + goto Lnotcovariant; + if (t1.linkage != t2.linkage) + goto Lnotcovariant; + + { + // Return types + Type t1n = t1.next; + Type t2n = t2.next; + + if (t1n.equals(t2n)) + goto Lcovariant; + if (t1n.ty == TY.Tclass && t2n.ty == TY.Tclass) + { + /* If same class type, but t2n is const, then it's + * covariant. Do this test first because it can work on + * forward references. + */ + if ((cast(TypeClass)t1n).sym == (cast(TypeClass)t2n).sym && + t2n.mod == MOD.MODconst) + goto Lcovariant; + + // If t1n is forward referenced: + ClassDeclaration cd = (cast(TypeClass)t1n).sym; + if (!cd.baseClass && cd.baseclasses.dim && !cd.isInterfaceDeclaration()) + { + return 3; + } + } + if (t1n.implicitConvTo(t2n)) + goto Lcovariant; + } + + goto Lnotcovariant; + + Lcovariant: + /* Can convert mutable to const + */ + if (t1.mod != t2.mod) + { + if (!(t1.mod & MOD.MODconst) && (t2.mod & MOD.MODconst)) + goto Lnotcovariant; + if (!(t1.mod & MOD.MODshared) && (t2.mod & MOD.MODshared)) + goto Lnotcovariant; + } + + /* Can convert pure to impure, and nothrow to throw + */ + if (!t1.ispure && t2.ispure) + goto Lnotcovariant; + + if (!t1.isnothrow && t2.isnothrow) + goto Lnotcovariant; + + if (t1.isref != t2.isref) + goto Lnotcovariant; + + //printf("\tcovaraint: 1\n"); + return 1; + + Ldistinct: + //printf("\tcovaraint: 0\n"); + return 0; + + Lnotcovariant: + //printf("\tcovaraint: 2\n"); + return 2; + } + + string toChars() + { + scope OutBuffer buf = new OutBuffer(); + + HdrGenState hgs; + toCBuffer(buf, null, &hgs); + return buf.toChars(); + } + + static char needThisPrefix() + { + return 'M'; // name mangling prefix for functions needing 'this' + } + + static void init() + { + Lexer.initKeywords(); + + for (int i = 0; i < TY.TMAX; i++) + sizeTy[i] = TypeBasic.sizeof; + + sizeTy[TY.Tsarray] = TypeSArray.sizeof; + sizeTy[TY.Tarray] = TypeDArray.sizeof; + //sizeTy[TY.Tnarray] = TypeNArray.sizeof; + sizeTy[TY.Taarray] = TypeAArray.sizeof; + sizeTy[TY.Tpointer] = TypePointer.sizeof; + sizeTy[TY.Treference] = TypeReference.sizeof; + sizeTy[TY.Tfunction] = TypeFunction.sizeof; + sizeTy[TY.Tdelegate] = TypeDelegate.sizeof; + sizeTy[TY.Tident] = TypeIdentifier.sizeof; + sizeTy[TY.Tinstance] = TypeInstance.sizeof; + sizeTy[TY.Ttypeof] = TypeTypeof.sizeof; + sizeTy[TY.Tenum] = TypeEnum.sizeof; + sizeTy[TY.Ttypedef] = TypeTypedef.sizeof; + sizeTy[TY.Tstruct] = TypeStruct.sizeof; + sizeTy[TY.Tclass] = TypeClass.sizeof; + sizeTy[TY.Ttuple] = TypeTuple.sizeof; + sizeTy[TY.Tslice] = TypeSlice.sizeof; + sizeTy[TY.Treturn] = TypeReturn.sizeof; + + mangleChar[TY.Tarray] = 'A'; + mangleChar[TY.Tsarray] = 'G'; + mangleChar[TY.Tnarray] = '@'; + mangleChar[TY.Taarray] = 'H'; + mangleChar[TY.Tpointer] = 'P'; + mangleChar[TY.Treference] = 'R'; + mangleChar[TY.Tfunction] = 'F'; + mangleChar[TY.Tident] = 'I'; + mangleChar[TY.Tclass] = 'C'; + mangleChar[TY.Tstruct] = 'S'; + mangleChar[TY.Tenum] = 'E'; + mangleChar[TY.Ttypedef] = 'T'; + mangleChar[TY.Tdelegate] = 'D'; + + mangleChar[TY.Tnone] = 'n'; + mangleChar[TY.Tvoid] = 'v'; + mangleChar[TY.Tint8] = 'g'; + mangleChar[TY.Tuns8] = 'h'; + mangleChar[TY.Tint16] = 's'; + mangleChar[TY.Tuns16] = 't'; + mangleChar[TY.Tint32] = 'i'; + mangleChar[TY.Tuns32] = 'k'; + mangleChar[TY.Tint64] = 'l'; + mangleChar[TY.Tuns64] = 'm'; + mangleChar[TY.Tfloat32] = 'f'; + mangleChar[TY.Tfloat64] = 'd'; + mangleChar[TY.Tfloat80] = 'e'; + + mangleChar[TY.Timaginary32] = 'o'; + mangleChar[TY.Timaginary64] = 'p'; + mangleChar[TY.Timaginary80] = 'j'; + mangleChar[TY.Tcomplex32] = 'q'; + mangleChar[TY.Tcomplex64] = 'r'; + mangleChar[TY.Tcomplex80] = 'c'; + + mangleChar[TY.Tbool] = 'b'; + mangleChar[TY.Tascii] = 'a'; + mangleChar[TY.Twchar] = 'u'; + mangleChar[TY.Tdchar] = 'w'; + + mangleChar[TY.Tbit] = '@'; + mangleChar[TY.Tinstance] = '@'; + mangleChar[TY.Terror] = '@'; + mangleChar[TY.Ttypeof] = '@'; + mangleChar[TY.Ttuple] = 'B'; + mangleChar[TY.Tslice] = '@'; + mangleChar[TY.Treturn] = '@'; + +debug { + for (int i = 0; i < TY.TMAX; i++) { + if (!mangleChar[i]) { + writef("ty = %d\n", i); + } + assert(mangleChar[i]); + } +} + // Set basic types + static TY[] basetab = [ + TY.Tvoid, TY.Tint8, TY.Tuns8, TY.Tint16, TY.Tuns16, TY.Tint32, TY.Tuns32, TY.Tint64, TY.Tuns64, + TY.Tfloat32, TY.Tfloat64, TY.Tfloat80, + TY.Timaginary32, TY.Timaginary64, TY.Timaginary80, + TY.Tcomplex32, TY.Tcomplex64, TY.Tcomplex80, + TY.Tbool, + TY.Tascii, TY.Twchar, TY.Tdchar + ]; + + foreach (bt; basetab) { + Type t = new TypeBasic(bt); + t = t.merge(); + basic[bt] = t; + } + + basic[TY.Terror] = basic[TY.Tint32]; + + tvoidptr = tvoid.pointerTo(); + + if (global.params.isX86_64) { + PTRSIZE = 8; + if (global.params.isLinux || global.params.isFreeBSD || global.params.isSolaris) + REALSIZE = 10; + else + REALSIZE = 8; + Tsize_t = TY.Tuns64; + Tptrdiff_t = TY.Tint64; + } + else + { + PTRSIZE = 4; +version (TARGET_OSX) { + REALSIZE = 16; + REALPAD = 6; +} else version (XXX) { //#elif TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS + REALSIZE = 12; + REALPAD = 2; +} else { + REALSIZE = 10; + REALPAD = 0; +} + Tsize_t = TY.Tuns32; + Tptrdiff_t = TY.Tint32; + } + } + + ulong size() + { + return size(Loc(0)); + } + + ulong size(Loc loc) + { + error(loc, "no size for type %s", toChars()); + return 1; + } + + uint alignsize() + { + return cast(uint)size(Loc(0)); /// + } + + Type semantic(Loc loc, Scope sc) + { + return merge(); + } + + Type trySemantic(Loc loc, Scope sc) + { + uint errors = global.errors; + global.gag++; // suppress printing of error messages + Type t = semantic(loc, sc); + global.gag--; + if (errors != global.errors) // if any errors happened + { + global.errors = errors; + t = null; + } + return t; + } + + /******************************** + * Name mangling. + * Input: + * flag 0x100 do not do const/invariant + */ + void toDecoBuffer(OutBuffer buf, int flag = 0) + { + if (flag != mod && flag != 0x100) + { + if (mod & MOD.MODshared) + buf.writeByte('O'); + + if (mod & MOD.MODconst) + buf.writeByte('x'); + else if (mod & MOD.MODinvariant) + buf.writeByte('y'); + + // Cannot be both const and invariant + assert((mod & (MOD.MODconst | MOD.MODinvariant)) != (MOD.MODconst | MOD.MODinvariant)); + } + buf.writeByte(mangleChar[ty]); + } + + Type merge() + { + Type t = this; + assert(t); + + //printf("merge(%s)\n", toChars()); + if (deco is null) + { + OutBuffer buf = new OutBuffer(); + + //if (next) + //next = next.merge(); + toDecoBuffer(buf); + StringValue* sv = stringtable.update(buf.extractString()); + if (sv.ptrvalue) + { + t = cast(Type) sv.ptrvalue; +debug { + if (!t.deco) + writef("t = %s\n", t.toChars()); +} + assert(t.deco); + //printf("old value, deco = '%s' %p\n", t.deco, t.deco); + } + else + { + sv.ptrvalue = cast(void*)this; + deco = sv.lstring.string_; + //printf("new value, deco = '%s' %p\n", t.deco, t.deco); + } + } + return t; + } + + /************************************* + * This version does a merge even if the deco is already computed. + * Necessary for types that have a deco, but are not merged. + */ + Type merge2() + { + //printf("merge2(%s)\n", toChars()); + Type t = this; + assert(t); + if (!t.deco) + return t.merge(); + + StringValue* sv = stringtable.lookup(t.deco); + if (sv && sv.ptrvalue) + { + t = cast(Type)sv.ptrvalue; + assert(t.deco); + } + else + assert(0); + + return t; + } + + void toCBuffer(OutBuffer buf, Identifier ident, HdrGenState* hgs) + { + toCBuffer2(buf, hgs, MOD.MODundefined); + if (ident) + { + buf.writeByte(' '); + buf.writestring(ident.toChars()); + } + } + + void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod) + { + if (mod != this.mod) + { + toCBuffer3(buf, hgs, mod); + return; + } + buf.writestring(toChars()); + } + + void toCBuffer3(OutBuffer buf, HdrGenState* hgs, MOD mod) + { + if (mod != this.mod) + { + string p; + + if (this.mod & MOD.MODshared) + buf.writestring("shared("); + + switch (this.mod & (MOD.MODconst | MOD.MODinvariant)) + { + case MOD.MODundefined: + toCBuffer2(buf, hgs, this.mod); + break; + case MOD.MODconst: + p = "const("; + goto L1; + case MOD.MODinvariant: + p = "immutable("; + L1: buf.writestring(p); + toCBuffer2(buf, hgs, this.mod); + buf.writeByte(')'); + break; + } + + if (this.mod & MOD.MODshared) + buf.writeByte(')'); + } + } + + void modToBuffer(OutBuffer buf) + { + if (mod & MOD.MODshared) + buf.writestring(" shared"); + if (mod & MOD.MODconst) + buf.writestring(" const"); + if (mod & MOD.MODinvariant) + buf.writestring(" immutable"); + } + +version (CPP_MANGLE) { + void toCppMangle(OutBuffer buf, CppMangleState* cms) + { + assert(false); + } +} + bool isintegral() + { + return false; + } + + bool isfloating() // real, imaginary, or complex + { + return false; + } + + bool isreal() + { + return false; + } + + bool isimaginary() + { + return false; + } + + bool iscomplex() + { + return false; + } + + bool isscalar() + { + return false; + } + + bool isunsigned() + { + return false; + } + + bool isauto() + { + return false; + } + + int isString() + { + return false; + } + + /************************** + * Given: + * T a, b; + * Can we assign: + * a = b; + * ? + */ + int isAssignable() + { + return true; + } + + bool checkBoolean() // if can be converted to boolean value + { + return isscalar(); + } + + /********************************* + * Check type to see if it is based on a deprecated symbol. + */ + void checkDeprecated(Loc loc, Scope sc) + { + Dsymbol s = toDsymbol(sc); + if (s) + s.checkDeprecated(loc, sc); + } + + bool isConst() { return (mod & MOD.MODconst) != 0; } + + int isInvariant() { return mod & MOD.MODinvariant; } + + int isMutable() { return !(mod & (MOD.MODconst | MOD.MODinvariant)); } + + int isShared() { return mod & MOD.MODshared; } + + int isSharedConst() { return mod == (MOD.MODshared | MOD.MODconst); } + + /******************************** + * Convert to 'const'. + */ + Type constOf() + { +static if (false) { + //printf("Type.constOf() %p %s\n", this, toChars()); + if (isConst()) + return this; + if (cto) + return cto; + Type t = makeConst(); + t = t.merge(); + cto = t; + if (ito) + ito.cto = t; + //if (t.nextOf()) assert(t.nextOf().isConst()); + //printf("-Type.constOf() %p %s\n", t, toChars()); + return t; +} else { + //printf("Type.constOf() %p %s\n", this, toChars()); + if (mod == MOD.MODconst) + return this; + if (cto) + { + assert(cto.mod == MOD.MODconst); + return cto; + } + Type t = makeConst(); + t = t.merge(); + t.fixTo(this); + //printf("-Type.constOf() %p %s\n", t, toChars()); + return t; +} + } + + /******************************** + * Convert to 'immutable'. + */ + Type invariantOf() + { +static if (false) { + //printf("Type.invariantOf() %p %s\n", this, toChars()); + if (isInvariant()) + { + return this; + } + if (ito) + { + //if (!ito.isInvariant()) printf("\tito is %p %s\n", ito, ito.toChars()); + assert(ito.isInvariant()); + return ito; + } + Type t = makeInvariant(); + t = t.merge(); + ito = t; + if (cto) + cto.ito = t; +static if (false) {// fails for function types + if (t.nextOf() && !t.nextOf().isInvariant()) + { + assert(0); + } +} + //printf("\t%p\n", t); + return t; +} else { + //printf("Type.invariantOf() %p %s\n", this, toChars()); + if (isInvariant()) + { + return this; + } + if (ito) + { + assert(ito.isInvariant()); + return ito; + } + Type t = makeInvariant(); + t = t.merge(); + t.fixTo(this); + //printf("\t%p\n", t); + return t; +} + } + + Type mutableOf() + { + static if (false) { + //printf("Type.mutableOf() %p, %s\n", this, toChars()); + Type t = this; + if (isConst()) + { + t = cto; + assert(!t || t.isMutable()); + } + else if (isInvariant()) + { + t = ito; + assert(!t || t.isMutable()); + } + if (!t) + { + uint sz = this.classinfo.init.length; + t = cast(Type)malloc(sz); + memcpy(cast(void*)t, cast(void*)this, sz); + t.mod = 0; + t.deco = null; + t.arrayof = null; + t.pto = null; + t.rto = null; + t.cto = null; + t.ito = null; + t.sto = null; + t.scto = null; + t.vtinfo = null; + if (ty == Tsarray) + { + TypeSArray ta = cast(TypeSArray)t; + //ta.next = ta.next.mutableOf(); + } + t = t.merge(); + if (isConst()) + { cto = t; + t.cto = this; + if (ito) + ito.cto = this; + } + else if (isInvariant()) + { ito = t; + t.ito = this; + if (cto) + cto.ito = this; + } + } + return t; + } else { + //printf("Type.mutableOf() %p, %s\n", this, toChars()); + Type t = this; + if (isConst()) + { + if (isShared()) + t = sto; // shared const => shared + else + t = cto; + assert(!t || t.isMutable()); + } + else if (isInvariant()) + { + t = ito; + assert(!t || (t.isMutable() && !t.isShared())); + } + if (!t) + { + uint sz = this.classinfo.init.length; + t = cast(Type)malloc(sz); + memcpy(cast(void*)t, cast(void*)this, sz); + t.mod = MODundefined; + t.deco = null; + t.arrayof = null; + t.pto = null; + t.rto = null; + t.cto = null; + t.ito = null; + t.sto = null; + t.scto = null; + t.vtinfo = null; + t = t.merge(); + + t.fixTo(this); + + switch (mod) + { + case MODconst: + t.cto = this; + break; + + case MODinvariant: + t.ito = this; + break; + + case MODshared: + t.sto = this; + break; + + case MODshared | MODconst: + t.scto = this; + break; + + default: + assert(0); + } + } + return t; + } + } + + Type sharedOf() + { + //printf("Type.sharedOf() %p, %s\n", this, toChars()); + if (mod == MOD.MODshared) + { + return this; + } + if (sto) + { + assert(sto.isShared()); + return sto; + } + + Type t = makeShared(); + t = t.merge(); + t.fixTo(this); + + //printf("\t%p\n", t); + return t; + } + + Type sharedConstOf() + { + //printf("Type.sharedConstOf() %p, %s\n", this, toChars()); + if (mod == (MODshared | MODconst)) + { + return this; + } + if (scto) + { + assert(scto.mod == (MODshared | MODconst)); + return scto; + } + + Type t = makeSharedConst(); + t = t.merge(); + t.fixTo(this); + //printf("\t%p\n", t); + + return t; + } + + static uint X(MOD m, MOD n) + { + return (((m) << 3) | (n)); + } + + /********************************** + * For our new type 'this', which is type-constructed from t, + * fill in the cto, ito, sto, scto shortcuts. + */ + void fixTo(Type t) + { + ito = t.ito; +static if (false) { + /* Cannot do these because these are not fully transitive: + * there can be a shared ptr to immutable, for example. + * Immutable subtypes are always immutable, though. + */ + cto = t.cto; + sto = t.sto; + scto = t.scto; +} + + assert(mod != t.mod); + + switch (X(mod, t.mod)) + { + case X(MOD.MODundefined, MOD.MODconst): + cto = t; + break; + + case X(MOD.MODundefined, MOD.MODinvariant): + ito = t; + break; + + case X(MOD.MODundefined, MOD.MODshared): + sto = t; + break; + + case X(MOD.MODundefined, MOD.MODshared | MOD.MODconst): + scto = t; + break; + + + case X(MOD.MODconst, MOD.MODundefined): + cto = null; + goto L2; + + case X(MOD.MODconst, MOD.MODinvariant): + ito = t; + goto L2; + + case X(MOD.MODconst, MOD.MODshared): + sto = t; + goto L2; + + case X(MOD.MODconst, MOD.MODshared | MOD.MODconst): + scto = t; + L2: + t.cto = this; + break; + + + case X(MOD.MODinvariant, MOD.MODundefined): + ito = null; + goto L3; + + case X(MOD.MODinvariant, MOD.MODconst): + cto = t; + goto L3; + + case X(MOD.MODinvariant, MOD.MODshared): + sto = t; + goto L3; + + case X(MOD.MODinvariant, MOD.MODshared | MOD.MODconst): + scto = t; + L3: + t.ito = this; + if (t.cto) t.cto.ito = this; + if (t.sto) t.sto.ito = this; + if (t.scto) t.scto.ito = this; + break; + + + case X(MOD.MODshared, MOD.MODundefined): + sto = null; + goto L4; + + case X(MOD.MODshared, MOD.MODconst): + cto = t; + goto L4; + + case X(MOD.MODshared, MOD.MODinvariant): + ito = t; + goto L4; + + case X(MOD.MODshared, MOD.MODshared | MOD.MODconst): + scto = t; + L4: + t.sto = this; + break; + + + case X(MOD.MODshared | MOD.MODconst, MOD.MODundefined): + scto = null; + break; + + case X(MOD.MODshared | MOD.MODconst, MOD.MODconst): + cto = t; + break; + + case X(MOD.MODshared | MOD.MODconst, MOD.MODinvariant): + ito = t; + break; + + case X(MOD.MODshared | MOD.MODconst, MOD.MODshared): + sto = t; + L5: + t.scto = this; + break; + } + + check(); + t.check(); + //printf("fixTo: %s, %s\n", toChars(), t.toChars()); + } + + /*************************** + * Look for bugs in constructing types. + */ + void check() + { + switch (mod) + { + case MOD.MODundefined: + if (cto) assert(cto.mod == MOD.MODconst); + if (ito) assert(ito.mod == MOD.MODinvariant); + if (sto) assert(sto.mod == MOD.MODshared); + if (scto) assert(scto.mod == (MOD.MODshared | MOD.MODconst)); + break; + + case MOD.MODconst: + if (cto) assert(cto.mod == MOD.MODundefined); + if (ito) assert(ito.mod == MOD.MODinvariant); + if (sto) assert(sto.mod == MOD.MODshared); + if (scto) assert(scto.mod == (MOD.MODshared | MOD.MODconst)); + break; + + case MOD.MODinvariant: + if (cto) assert(cto.mod == MOD.MODconst); + if (ito) assert(ito.mod == MOD.MODundefined); + if (sto) assert(sto.mod == MOD.MODshared); + if (scto) assert(scto.mod == (MOD.MODshared | MOD.MODconst)); + break; + + case MOD.MODshared: + if (cto) assert(cto.mod == MOD.MODconst); + if (ito) assert(ito.mod == MOD.MODinvariant); + if (sto) assert(sto.mod == MOD.MODundefined); + if (scto) assert(scto.mod == (MOD.MODshared | MOD.MODconst)); + break; + + case MOD.MODshared | MOD.MODconst: + if (cto) assert(cto.mod == MOD.MODconst); + if (ito) assert(ito.mod == MOD.MODinvariant); + if (sto) assert(sto.mod == MOD.MODshared); + if (scto) assert(scto.mod == MOD.MODundefined); + break; + } + + Type tn = nextOf(); + if (tn && ty != TY.Tfunction && ty != TY.Tdelegate) + { + // Verify transitivity + switch (mod) + { + case MOD.MODundefined: + break; + + case MOD.MODconst: + assert(tn.mod & MOD.MODinvariant || tn.mod & MOD.MODconst); + break; + + case MOD.MODinvariant: + assert(tn.mod == MOD.MODinvariant); + break; + + case MOD.MODshared: + assert(tn.mod & MOD.MODinvariant || tn.mod & MOD.MODshared); + break; + + case MOD.MODshared | MOD.MODconst: + assert(tn.mod & MOD.MODinvariant || tn.mod & (MOD.MODshared | MOD.MODconst)); + break; + } + tn.check(); + } + } + + Type castMod(uint mod) + { + assert(false); + } + + /************************************ + * Add MODxxxx bits to existing type. + * We're adding, not replacing, so adding const to + * a shared type => "shared const" + */ + Type addMod(MOD mod) + { + Type t = this; + + /* Add anything to immutable, and it remains immutable + */ + if (!t.isInvariant()) + { + switch (mod) + { + case MOD.MODundefined: + break; + + case MOD.MODconst: + if (isShared()) + t = sharedConstOf(); + else + t = constOf(); + break; + + case MOD.MODinvariant: + t = invariantOf(); + break; + + case MOD.MODshared: + if (isConst()) + t = sharedConstOf(); + else + t = sharedOf(); + break; + + case MOD.MODshared | MOD.MODconst: + t = sharedConstOf(); + break; + } + } + return t; + } + + Type addStorageClass(STC stc) + { + /* Just translate to MOD bits and let addMod() do the work + */ + MOD mod = MOD.MODundefined; + + if (stc & STC.STCimmutable) + mod = MOD.MODinvariant; + else + { + if (stc & (STC.STCconst | STC.STCin)) + mod = MOD.MODconst; + if (stc & STC.STCshared) + mod |= MOD.MODshared; + } + + return addMod(mod); + } + + Type pointerTo() + { + if (pto is null) + { + Type t = new TypePointer(this); + pto = t.merge(); + } + + return pto; + } + + Type referenceTo() + { + assert(false); + } + +version (DumbClone) { + final Type clone() + { + auto size = this.classinfo.init.length; + auto ptr = malloc(size); + memcpy(ptr, cast(void*)this, size); + + return cast(Type)ptr; + } +} else { + final Type cloneTo(Type t) + { + t.ctype = ctype; + return t; + } + + Type clone() + { + assert(this.classinfo is Type.classinfo); + return cloneTo(new Type(ty)); + } +} + + Type arrayOf() + { + if (!arrayof) + { + Type t = new TypeDArray(this); + arrayof = t.merge(); + } + return arrayof; + } + + Type makeConst() + { + //printf("Type.makeConst() %p, %s\n", this, toChars()); + if (cto) + return cto; + + Type t = clone(); + t.mod = MOD.MODconst; + + t.deco = null; + t.arrayof = null; + t.pto = null; + t.rto = null; + t.cto = null; + t.ito = null; + t.sto = null; + t.scto = null; + t.vtinfo = null; + + //printf("-Type.makeConst() %p, %s\n", t, toChars()); + return t; + } + + Type makeInvariant() + { + if (ito) { + return ito; + } + + Type t = clone(); + t.mod = MOD.MODinvariant; + + t.deco = null; + t.arrayof = null; + t.pto = null; + t.rto = null; + t.cto = null; + t.ito = null; + t.sto = null; + t.scto = null; + t.vtinfo = null; + + return t; + } + + Type makeShared() + { + if (sto) + return sto; + + Type t = clone(); + t.mod = MOD.MODshared; + + t.deco = null; + t.arrayof = null; + t.pto = null; + t.rto = null; + t.cto = null; + t.ito = null; + t.sto = null; + t.scto = null; + t.vtinfo = null; + + return t; + } + + Type makeSharedConst() + { + if (scto) + return scto; + + Type t = clone(); + t.mod = MODshared | MODconst; + + t.deco = null; + t.arrayof = null; + t.pto = null; + t.rto = null; + t.cto = null; + t.ito = null; + t.sto = null; + t.scto = null; + t.vtinfo = null; + + return t; + } + + Dsymbol toDsymbol(Scope sc) + { + return null; + } + + /******************************* + * If this is a shell around another type, + * get that other type. + */ + + Type toBasetype() + { + return this; + } + + /************************** + * Return type with the top level of it being mutable. + */ + Type toHeadMutable() + { + if (!mod) + return this; + + return mutableOf(); + } + + bool isBaseOf(Type t, int* poffset) + { + return false; // assume not + } + + /******************************* + * Determine if converting 'this' to 'to' is an identity operation, + * a conversion to const operation, or the types aren't the same. + * Returns: + * MATCHequal 'this' == 'to' + * MATCHconst 'to' is const + * MATCHnomatch conversion to mutable or invariant + */ + MATCH constConv(Type to) + { + if (equals(to)) + return MATCH.MATCHexact; + if (ty == to.ty && to.mod == MOD.MODconst) + return MATCH.MATCHconst; + return MATCH.MATCHnomatch; + } + + /******************************** + * Determine if 'this' can be implicitly converted + * to type 'to'. + * Returns: + * MATCHnomatch, MATCHconvert, MATCHconst, MATCHexact + */ + MATCH implicitConvTo(Type to) + { + //printf("Type.implicitConvTo(this=%p, to=%p)\n", this, to); + //printf("from: %s\n", toChars()); + //printf("to : %s\n", to.toChars()); + if (this is to) + return MATCHexact; + + return MATCHnomatch; + } + + ClassDeclaration isClassHandle() + { + return null; + } + + Expression getProperty(Loc loc, Identifier ident) + { + Expression e; + +version (LOGDOTEXP) { + printf("Type.getProperty(type = '%s', ident = '%s')\n", toChars(), ident.toChars()); +} + if (ident == Id.__sizeof) + { + e = new IntegerExp(loc, size(loc), Type.tsize_t); + } + else if (ident == Id.size) + { + error(loc, ".size property should be replaced with .sizeof"); + e = new ErrorExp(); + } + else if (ident is Id.alignof_) + { + e = new IntegerExp(loc, alignsize(), Type.tsize_t); + } + else if (ident == Id.typeinfo_) + { + if (!global.params.useDeprecated) + error(loc, ".typeinfo deprecated, use typeid(type)"); + e = getTypeInfo(null); + } + else if (ident == Id.init_) + { + if (ty == TY.Tvoid) + error(loc, "void does not have an initializer"); + e = defaultInit(loc); + } + else if (ident is Id.mangleof_) + { + string s; + if (!deco) { + s = toChars(); + error(loc, "forward reference of type %s.mangleof", s); + } else { + s = deco; + } + + e = new StringExp(loc, s, 'c'); + Scope sc = new Scope(); + e = e.semantic(sc); + } + else if (ident is Id.stringof_) + { + string s = toChars(); + e = new StringExp(loc, s, 'c'); + Scope sc = new Scope(); + e = e.semantic(sc); + } + else + { + error(loc, "no property '%s' for type '%s'", ident.toChars(), toChars()); + e = new ErrorExp(); + } + return e; + } + + Expression dotExp(Scope sc, Expression e, Identifier ident) + { + VarDeclaration v = null; + +version (LOGDOTEXP) { + printf("Type.dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars()); +} + if (e.op == TOK.TOKdotvar) + { + DotVarExp dv = cast(DotVarExp)e; + v = dv.var.isVarDeclaration(); + } + else if (e.op == TOK.TOKvar) + { + VarExp ve = cast(VarExp)e; + v = ve.var.isVarDeclaration(); + } + if (v) + { + if (ident is Id.offset) + { + if (!global.params.useDeprecated) + error(e.loc, ".offset deprecated, use .offsetof"); + goto Loffset; + } + else if (ident is Id.offsetof) + { + Loffset: + if (v.storage_class & STC.STCfield) + { + e = new IntegerExp(e.loc, v.offset, Type.tsize_t); + return e; + } + } + else if (ident is Id.init_) + { +static if (false) { + if (v.init) + { + if (v.init.isVoidInitializer()) + error(e.loc, "%s.init is void", v.toChars()); + else + { Loc loc = e.loc; + e = v.init.toExpression(); + if (e.op == TOK.TOKassign || e.op == TOK.TOKconstruct || e.op == TOK.TOKblit) + { + e = (cast(AssignExp)e).e2; + + /* Take care of case where we used a 0 + * to initialize the struct. + */ + if (e.type == Type.tint32 && + e.isBool(0) && + v.type.toBasetype().ty == TY.Tstruct) + { + e = v.type.defaultInit(e.loc); + } + } + e = e.optimize(WANTvalue | WANTinterpret); + // if (!e.isConst()) + // error(loc, ".init cannot be evaluated at compile time"); + } + return e; + } +} + Expression ex = defaultInit(e.loc); + return ex; + } + } + if (ident is Id.typeinfo_) + { + if (!global.params.useDeprecated) + error(e.loc, ".typeinfo deprecated, use typeid(type)"); + e = getTypeInfo(sc); + return e; + } + if (ident is Id.stringof_) + { + string s = e.toChars(); + e = new StringExp(e.loc, s, 'c'); + Scope sc2 = new Scope(); /// + e = e.semantic(sc2); + return e; + } + return getProperty(e.loc, ident); + } + + uint memalign(uint salign) + { + return salign; + } + + ///Expression defaultInit(Loc loc = Loc(0)) + Expression defaultInit(Loc loc) + { + assert(false); + } + + ///bool isZeroInit(Loc loc = Loc(0)) // if initializer is 0 + bool isZeroInit(Loc loc) // if initializer is 0 + { + assert(false); + } + + dt_t** toDt(dt_t** pdt) + { + //printf("Type.toDt()\n"); + Expression e = defaultInit(Loc(0)); + return e.toDt(pdt); + } + + Identifier getTypeInfoIdent(int internal) + { + // _init_10TypeInfo_%s + scope OutBuffer buf = new OutBuffer(); + Identifier id; + char* name; + int len; + + if (internal) + { + buf.writeByte(mangleChar[ty]); + if (ty == TY.Tarray) + buf.writeByte(mangleChar[(cast(TypeArray)this).next.ty]); + } + else + toDecoBuffer(buf); + + len = buf.offset; + name = cast(char*)alloca(19 + len.sizeof * 3 + len + 1); + buf.writeByte(0); + version (TARGET_OSX) { + // The LINKc will prepend the _ + len = sprintf(name, "D%dTypeInfo_%s6__initZ".ptr, 9 + len, buf.data); + } else { + len = sprintf(name, "_D%dTypeInfo_%s6__initZ".ptr, 9 + len, buf.data); + } + if (global.params.isWindows) + name++; // C mangling will add it back in + //printf("name = %s\n", name); + id = Lexer.idPool(name[0..len-1].idup); + return id; + } + + /* These form the heart of template argument deduction. + * Given 'this' being the type argument to the template instance, + * it is matched against the template declaration parameter specialization + * 'tparam' to determine the type to be used for the parameter. + * Example: + * template Foo(T:T*) // template declaration + * Foo!(int*) // template instantiation + * Input: + * this = int* + * tparam = T + * parameters = [ T:T* ] // Array of TemplateParameter's + * Output: + * dedtypes = [ int ] // Array of Expression/Type's + */ + MATCH deduceType(Scope sc, Type tparam, TemplateParameters parameters, Objects dedtypes) + { + static if (false) { + printf("Type.deduceType()\n"); + printf("\tthis = %d, ", ty); print(); + printf("\ttparam = %d, ", tparam.ty); tparam.print(); + } + if (!tparam) + goto Lnomatch; + + if (this == tparam) + goto Lexact; + + if (tparam.ty == Tident) + { + // Determine which parameter tparam is + int i = templateParameterLookup(tparam, parameters); + if (i == -1) + { + if (!sc) + goto Lnomatch; + + /* Need a loc to go with the semantic routine. + */ + Loc loc; + if (parameters.dim) + { + TemplateParameter tp = cast(TemplateParameter)parameters.data[0]; + loc = tp.loc; + } + + /* BUG: what if tparam is a template instance, that + * has as an argument another Tident? + */ + tparam = tparam.semantic(loc, sc); + assert(tparam.ty != Tident); + return deduceType(sc, tparam, parameters, dedtypes); + } + + TemplateParameter tp = cast(TemplateParameter)parameters.data[i]; + + // Found the corresponding parameter tp + if (!tp.isTemplateTypeParameter()) + goto Lnomatch; + Type tt = this; + Type at = cast(Type)dedtypes.data[i]; + + // 3*3 == 9 cases + if (tparam.isMutable()) + { // foo(U:U) T => T + // foo(U:U) const(T) => const(T) + // foo(U:U) invariant(T) => invariant(T) + if (!at) + { + dedtypes.data[i] = cast(void*)this; + goto Lexact; + } + } + else if (mod == tparam.mod) + { // foo(U:const(U)) const(T) => T + // foo(U:invariant(U)) invariant(T) => T + tt = mutableOf(); + if (!at) + { + dedtypes.data[i] = cast(void*)tt; + goto Lexact; + } + } + else if (tparam.isConst()) + { // foo(U:const(U)) T => T + // foo(U:const(U)) invariant(T) => T + tt = mutableOf(); + if (!at) + { + dedtypes.data[i] = cast(void*)tt; + goto Lconst; + } + } + else + { // foo(U:invariant(U)) T => nomatch + // foo(U:invariant(U)) const(T) => nomatch + if (!at) + goto Lnomatch; + } + + if (tt.equals(at)) + goto Lexact; + else if (tt.ty == Tclass && at.ty == Tclass) + { + return tt.implicitConvTo(at); + } + else if (tt.ty == Tsarray && at.ty == Tarray && + tt.nextOf().implicitConvTo(at.nextOf()) >= MATCHconst) + { + goto Lexact; + } + else + goto Lnomatch; + } + + if (ty != tparam.ty) + return implicitConvTo(tparam); + // goto Lnomatch; + + if (nextOf()) + return nextOf().deduceType(sc, tparam.nextOf(), parameters, dedtypes); + + Lexact: + return MATCHexact; + + Lnomatch: + return MATCHnomatch; + + version (DMDV2) { + Lconst: + return MATCHconst; + } + } + + void resolve(Loc loc, Scope sc, Expression* pe, Type* pt, Dsymbol* ps) + { + //printf("Type.resolve() %s, %d\n", toChars(), ty); + Type t = semantic(loc, sc); + *pt = t; + *pe = null; + *ps = null; + } + + /******************************************* + * Get a canonicalized form of the TypeInfo for use with the internal + * runtime library routines. Canonicalized in that static arrays are + * represented as dynamic arrays, enums are represented by their + * underlying type, etc. This reduces the number of TypeInfo's needed, + * so we can use the custom internal ones more. + */ + Expression getInternalTypeInfo(Scope sc) + { + TypeInfoDeclaration tid; + Expression e; + Type t; + static TypeInfoDeclaration internalTI[TMAX]; + + //printf("Type.getInternalTypeInfo() %s\n", toChars()); + t = toBasetype(); + switch (t.ty) + { + case Tsarray: + static if (false) { + // convert to corresponding dynamic array type + t = t.nextOf().mutableOf().arrayOf(); + } + break; + + case Tclass: + if ((cast(TypeClass)t).sym.isInterfaceDeclaration()) + break; + goto Linternal; + + case Tarray: + // convert to corresponding dynamic array type + t = t.nextOf().mutableOf().arrayOf(); + if (t.nextOf().ty != Tclass) + break; + goto Linternal; + + case Tfunction: + case Tdelegate: + case Tpointer: + Linternal: + tid = internalTI[t.ty]; + if (!tid) + { + tid = new TypeInfoDeclaration(t, 1); + internalTI[t.ty] = tid; + } + e = new VarExp(Loc(0), tid); + e = e.addressOf(sc); + e.type = tid.type; // do this so we don't get redundant dereference + return e; + + default: + break; + } + //printf("\tcalling getTypeInfo() %s\n", t.toChars()); + return t.getTypeInfo(sc); + } + + /**************************************************** + * Get the exact TypeInfo. + */ + Expression getTypeInfo(Scope sc) + { + Expression e; + Type t; + + //printf("Type.getTypeInfo() %p, %s\n", this, toChars()); + t = merge2(); // do this since not all Type's are merge'd + if (!t.vtinfo) + { +version (DMDV2) { + if (t.isShared()) // does both 'shared' and 'shared const' + t.vtinfo = new TypeInfoSharedDeclaration(t); + else if (t.isConst()) + t.vtinfo = new TypeInfoConstDeclaration(t); + else if (t.isInvariant()) + t.vtinfo = new TypeInfoInvariantDeclaration(t); + else + t.vtinfo = t.getTypeInfoDeclaration(); +} else { + t.vtinfo = t.getTypeInfoDeclaration(); +} + assert(t.vtinfo); + vtinfo = t.vtinfo; + + /* If this has a custom implementation in std/typeinfo, then + * do not generate a COMDAT for it. + */ + if (!t.builtinTypeInfo()) + { + // Generate COMDAT + if (sc) // if in semantic() pass + { + // Find module that will go all the way to an object file + Module m = sc.module_.importedFrom; + m.members.push(cast(void*)t.vtinfo); + } + else // if in obj generation pass + { + t.vtinfo.toObjFile(global.params.multiobj); + } + } + } + e = new VarExp(Loc(0), t.vtinfo); + e = e.addressOf(sc); + e.type = t.vtinfo.type; // do this so we don't get redundant dereference + return e; + } + + TypeInfoDeclaration getTypeInfoDeclaration() + { + //printf("Type.getTypeInfoDeclaration() %s\n", toChars()); + return new TypeInfoDeclaration(this, 0); + } + + /* These decide if there's an instance for them already in std.typeinfo, + * because then the compiler doesn't need to build one. + */ + bool builtinTypeInfo() + { + return false; + } + + /******************************* + * If one of the subtypes of this type is a TypeIdentifier, + * i.e. it's an unresolved type, return that type. + */ + Type reliesOnTident() + { + return null; + } + + Expression toExpression() + { + assert(false); + } + + /*************************************** + * Return true if type has pointers that need to + * be scanned by the GC during a collection cycle. + */ + bool hasPointers() + { + return false; + } + + /************************************* + * If this is a type of something, return that something. + */ + Type nextOf() + { + return null; + } + + ulong sizemask() + { + assert(false); + } + + static void error(T...)(Loc loc, string format, T t) + { + .error(loc, format, t); + } + + static void warning(T...)(Loc loc, string format, T t) + { + assert(false); + } + + // For backend + /***************************** + * Return back end type corresponding to D front end type. + */ + TYM totym() + { + TYM t; + + switch (ty) + { + case TY.Tvoid: t = TYM.TYvoid; break; + case TY.Tint8: t = TYM.TYschar; break; + case TY.Tuns8: t = TYM.TYuchar; break; + case TY.Tint16: t = TYM.TYshort; break; + case TY.Tuns16: t = TYM.TYushort; break; + case TY.Tint32: t = TYM.TYint; break; + case TY.Tuns32: t = TYM.TYuint; break; + case TY.Tint64: t = TYM.TYllong; break; + case TY.Tuns64: t = TYM.TYullong; break; + case TY.Tfloat32: t = TYM.TYfloat; break; + case TY.Tfloat64: t = TYM.TYdouble; break; + case TY.Tfloat80: t = TYM.TYldouble; break; + case TY.Timaginary32: t = TYM.TYifloat; break; + case TY.Timaginary64: t = TYM.TYidouble; break; + case TY.Timaginary80: t = TYM.TYildouble; break; + case TY.Tcomplex32: t = TYM.TYcfloat; break; + case TY.Tcomplex64: t = TYM.TYcdouble; break; + case TY.Tcomplex80: t = TYM.TYcldouble; break; + //case Tbit: t = TYM.TYuchar; break; + case TY.Tbool: t = TYM.TYbool; break; + case TY.Tchar: t = TYM.TYchar; break; + version (XXX) { ///TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS + case TY.Twchar: t = TYM.TYwchar_t; break; + case TY.Tdchar: t = TYM.TYdchar; break; + } else { + case TY.Twchar: t = TYM.TYwchar_t; break; + case TY.Tdchar: + t = (global.params.symdebug == 1) ? TYM.TYdchar : TYM.TYulong; + break; + } + + case TY.Taarray: t = TYM.TYaarray; break; + case TY.Tclass: + case TY.Treference: + case TY.Tpointer: t = TYM.TYnptr; break; + case TY.Tdelegate: t = TYM.TYdelegate; break; + case TY.Tarray: t = TYM.TYdarray; break; + case TY.Tsarray: t = TYM.TYarray; break; + case TY.Tstruct: t = TYM.TYstruct; break; + + case TY.Tenum: + case TY.Ttypedef: + t = toBasetype().totym(); + break; + + case TY.Tident: + case TY.Ttypeof: + debug { + writef("ty = %d, '%s'\n", ty, toChars()); + } + error (Loc(0), "forward reference of %s", toChars()); + t = TYM.TYint; + break; + + default: + debug { + writef("ty = %d, '%s'\n", ty, toChars()); + } + assert(0); + } + + version (DMDV2) { + // Add modifiers + switch (mod) + { + case MOD.MODundefined: + break; + case MOD.MODconst: + t |= mTY.mTYconst; + break; + case MOD.MODinvariant: + t |= mTY.mTYimmutable; + break; + case MOD.MODshared: + t |= mTY.mTYshared; + break; + case MOD.MODshared | MOD.MODconst: + t |= mTY.mTYshared | mTY.mTYconst; + break; + default: + assert(0); + } + } + + return t; + } + + /*************************************** + * Convert from D type to C type. + * This is done so C debug info can be generated. + */ + type* toCtype() + { + if (!ctype) + { + ctype = type_fake(totym()); + ctype.Tcount++; + } + return ctype; + } + + type* toCParamtype() + { + return toCtype(); + } + + Symbol* toSymbol() + { + assert(false); + } + + // For eliminating dynamic_cast + TypeBasic isTypeBasic() + { + return null; + } + + static Type tvoid() + { + return basic[TY.Tvoid]; + } + + static Type tint8() + { + return basic[TY.Tint8]; + } + + static Type tuns8() + { + return basic[TY.Tuns8]; + } + + static Type tint16() + { + return basic[TY.Tint16]; + } + + static Type tuns16() + { + return basic[TY.Tuns16]; + } + + static Type tint32() + { + return basic[TY.Tint32]; + } + + static Type tuns32() + { + return basic[TY.Tuns32]; + } + + static Type tint64() + { + return basic[TY.Tint64]; + } + + static Type tuns64() + { + return basic[TY.Tuns64]; + } + + static Type tfloat32() + { + return basic[TY.Tfloat32]; + } + + static Type tfloat64() + { + return basic[TY.Tfloat64]; + } + + static Type tfloat80() + { + return basic[TY.Tfloat80]; + } + + static Type timaginary32() + { + return basic[TY.Timaginary32]; + } + + static Type timaginary64() + { + return basic[TY.Timaginary64]; + } + + static Type timaginary80() + { + return basic[TY.Timaginary80]; + } + + static Type tcomplex32() + { + return basic[TY.Tcomplex32]; + } + + static Type tcomplex64() + { + return basic[TY.Tcomplex64]; + } + + static Type tcomplex80() + { + return basic[TY.Tcomplex80]; + } + + static Type tbit() + { + return basic[TY.Tbit]; + } + + static Type tbool() + { + return basic[TY.Tbool]; + } + + static Type tchar() + { + return basic[TY.Tchar]; + } + + static Type twchar() + { + return basic[TY.Twchar]; + } + + static Type tdchar() + { + return basic[TY.Tdchar]; + } + + // Some special types + static Type tshiftcnt() + { + return tint32; // right side of shift expression + } + +// #define tboolean tint32 // result of boolean expression + static Type tboolean() + { + return tbool; // result of boolean expression + } + + static Type tindex() + { + return tint32; // array/ptr index + } + + static Type tvoidptr; // void* + + static Type terror() + { + return basic[TY.Terror]; // for error recovery + } + + static Type tsize_t() + { + return basic[Tsize_t]; // matches size_t alias + } + + static Type tptrdiff_t() + { + return basic[Tptrdiff_t]; // matches ptrdiff_t alias + } + + static Type thash_t() + { + return tsize_t; // matches hash_t alias + } +} \ No newline at end of file