From 274d66e23202f1df5a95e243a5b27b8285483a0a Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Mon, 9 Apr 2018 01:55:17 -0700 Subject: [PATCH] use special enums for __c_long, etc. --- src/dmd/cppmangle.d | 9 ++++ src/dmd/cppmanglewin.d | 96 +++++++++++++++++++++++++++--------------- src/dmd/denum.d | 28 ++++++++++++ src/dmd/glue.d | 13 +++++- src/dmd/mtype.d | 13 ++++++ src/dmd/toctype.d | 17 ++++++-- src/dmd/typesem.d | 8 +++- test/runnable/cppa.d | 92 +++++++++++++++++++++++++++++++++------- 8 files changed, 221 insertions(+), 55 deletions(-) diff --git a/src/dmd/cppmangle.d b/src/dmd/cppmangle.d index 12b445166156..6165bf1eda1a 100644 --- a/src/dmd/cppmangle.d +++ b/src/dmd/cppmangle.d @@ -974,6 +974,15 @@ public: if (t.isImmutable() || t.isShared()) return error(t); + /* __c_long and __c_ulong get special mangling + */ + const id = t.sym.ident; + //printf("struct id = '%s'\n", id.toChars()); + if (id == Id.__c_long) + return writeBasicType(t, 0, 'l'); + else if (id == Id.__c_ulong) + return writeBasicType(t, 0, 'm'); + doSymbol(t); } diff --git a/src/dmd/cppmanglewin.d b/src/dmd/cppmanglewin.d index e81a0f4d4611..1e80c029a467 100644 --- a/src/dmd/cppmanglewin.d +++ b/src/dmd/cppmanglewin.d @@ -404,42 +404,70 @@ public: override void visit(TypeEnum type) { //printf("visit(TypeEnum); is_not_top_type = %d\n", (int)(flags & IS_NOT_TOP_TYPE)); - if (checkTypeSaved(type)) - return; - mangleModifier(type); - buf.writeByte('W'); - switch (type.sym.memtype.ty) + const id = type.sym.ident; + char c; + if (id == Id.__c_long_double) + c = 'O'; // VC++ long double + else if (id == Id.__c_long) + c = 'J'; // VC++ long + else if (id == Id.__c_ulong) + c = 'K'; // VC++ unsigned long + else + c = 0; + if (c) { - case Tchar: - case Tint8: - buf.writeByte('0'); - break; - case Tuns8: - buf.writeByte('1'); - break; - case Tint16: - buf.writeByte('2'); - break; - case Tuns16: - buf.writeByte('3'); - break; - case Tint32: - buf.writeByte('4'); - break; - case Tuns32: - buf.writeByte('5'); - break; - case Tint64: - buf.writeByte('6'); - break; - case Tuns64: - buf.writeByte('7'); - break; - default: - visit(cast(Type)type); - break; + if (type.isImmutable() || type.isShared()) + { + visit(cast(Type)type); + return; + } + if (type.isConst() && ((flags & IS_NOT_TOP_TYPE) || (flags & IS_DMC))) + { + if (checkTypeSaved(type)) + return; + } + mangleModifier(type); + buf.writeByte(c); + } + else + { + if (checkTypeSaved(type)) + return; + mangleModifier(type); + buf.writeByte('W'); + switch (type.sym.memtype.ty) + { + case Tchar: + case Tint8: + buf.writeByte('0'); + break; + case Tuns8: + buf.writeByte('1'); + break; + case Tint16: + buf.writeByte('2'); + break; + case Tuns16: + buf.writeByte('3'); + break; + case Tint32: + buf.writeByte('4'); + break; + case Tuns32: + buf.writeByte('5'); + break; + case Tint64: + buf.writeByte('6'); + break; + case Tuns64: + buf.writeByte('7'); + break; + default: + visit(cast(Type)type); + break; + } + mangleIdent(type.sym); } - mangleIdent(type.sym); flags &= ~IS_NOT_TOP_TYPE; flags &= ~IGNORE_CONST; } diff --git a/src/dmd/denum.d b/src/dmd/denum.d index 4eebd266a95a..0b63d3f53abc 100644 --- a/src/dmd/denum.d +++ b/src/dmd/denum.d @@ -12,6 +12,8 @@ module dmd.denum; +import core.stdc.stdio; + import dmd.gluelayer; import dmd.declaration; import dmd.dscope; @@ -195,6 +197,13 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol return errorReturn(); if (semanticRun == PASS.init || !members) { + if (isSpecial()) + { + /* Allow these special enums to not need a member list + */ + return memtype.getProperty(loc, id, 0); + } + error("is forward referenced looking for `.%s`", id.toChars()); return errorReturn(); } @@ -249,6 +258,18 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol return e; } + /**************** + * Determine if enum is a 'special' one. + * Returns: + * true if special + */ + final bool isSpecial() const nothrow @nogc + { + return (ident == Id.__c_long || + ident == Id.__c_ulong || + ident == Id.__c_long_double) && memtype; + } + Expression getDefaultValue(const ref Loc loc) { //printf("EnumDeclaration::getDefaultValue() %p %s\n", this, toChars()); @@ -261,6 +282,13 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol goto Lerrors; if (semanticRun == PASS.init || !members) { + if (isSpecial()) + { + /* Allow these special enums to not need a member list + */ + return memtype.defaultInit(loc); + } + error(loc, "forward reference of `%s.init`", toChars()); goto Lerrors; } diff --git a/src/dmd/glue.d b/src/dmd/glue.d index ac36c1afceec..39f7292ba71e 100644 --- a/src/dmd/glue.d +++ b/src/dmd/glue.d @@ -1434,8 +1434,19 @@ uint totym(Type tx) break; case Tenum: - t = totym(tx.toBasetype()); + { + Type tb = tx.toBasetype(); + const id = tx.toDsymbol(null).ident; + if (id == Id.__c_long) + t = tb.ty == Tint32 ? TYlong : TYllong; + else if (id == Id.__c_ulong) + t = tb.ty == Tuns32 ? TYulong : TYullong; + else if (id == Id.__c_long_double) + t = TYdouble; + else + t = totym(tb); break; + } case Tident: case Ttypeof: diff --git a/src/dmd/mtype.d b/src/dmd/mtype.d index 7534b39b4b0d..f5c51902ce9a 100644 --- a/src/dmd/mtype.d +++ b/src/dmd/mtype.d @@ -3377,6 +3377,19 @@ extern (C++) final class TypeBasic : Type TypeVector tv = cast(TypeVector)to; tob = tv.elementType(); } + else if (to.ty == Tenum) + { + EnumDeclaration ed = (cast(TypeEnum)to).sym; + if (ed.isSpecial()) + { + /* Special enums that allow implicit conversions to them + * with a MATCH.convert + */ + tob = to.toBasetype().isTypeBasic(); + } + else + return MATCH.nomatch; + } else tob = to.isTypeBasic(); if (!tob) diff --git a/src/dmd/toctype.d b/src/dmd/toctype.d index 1be244d46251..62a959c5c334 100644 --- a/src/dmd/toctype.d +++ b/src/dmd/toctype.d @@ -19,6 +19,7 @@ import dmd.backend.ty; import dmd.backend.type; import dmd.declaration; +import dmd.denum; import dmd.dstruct; import dmd.globals; import dmd.glue; @@ -170,18 +171,26 @@ public: //printf("TypeEnum::toCtype() '%s'\n", t.sym.toChars()); if (t.mod == 0) { - if (!t.sym.memtype) + EnumDeclaration sym = t.sym; + auto symMemtype = sym.memtype; + if (!symMemtype) { // https://issues.dlang.org/show_bug.cgi?id=13792 t.ctype = Type_toCtype(Type.tvoid); } - else if (t.sym.memtype.toBasetype().ty == Tint32) + else if (sym.ident == Id.__c_long) { - t.ctype = type_enum(t.sym.toPrettyChars(true), Type_toCtype(t.sym.memtype)); + t.ctype = type_fake(totym(t)); + t.ctype.Tcount++; + return; + } + else if (symMemtype.toBasetype().ty == Tint32) + { + t.ctype = type_enum(sym.toPrettyChars(true), Type_toCtype(symMemtype)); } else { - t.ctype = Type_toCtype(t.sym.memtype); + t.ctype = Type_toCtype(symMemtype); } if (global.params.symdebugref) diff --git a/src/dmd/typesem.d b/src/dmd/typesem.d index 7c0cdab79837..4b8ee1f1095f 100644 --- a/src/dmd/typesem.d +++ b/src/dmd/typesem.d @@ -3380,7 +3380,13 @@ private extern(C++) final class DotExpVisitor : Visitor mt.sym.dsymbolSemantic(null); if (!mt.sym.members) { - if (!(flag & 1)) + if (mt.sym.isSpecial()) + { + /* Special enums forward to the base type + */ + e = mt.sym.memtype.dotExp(sc, e, ident, flag); + } + else if (!(flag & 1)) { mt.sym.error("is forward referenced when looking for `%s`", ident.toChars()); e = new ErrorExp(); diff --git a/test/runnable/cppa.d b/test/runnable/cppa.d index 53279a19046b..d67a7325a036 100644 --- a/test/runnable/cppa.d +++ b/test/runnable/cppa.d @@ -1,4 +1,4 @@ -// PERMUTE_ARGS: -g +// PERMUTE_ARGS: -g -version=PULL8152 // EXTRA_CPP_SOURCES: cppb.cpp import core.stdc.stdio; @@ -605,13 +605,19 @@ extern(C++) version (CRuntime_Microsoft) { - struct __c_long_double + version (PULL8152) { - this(double d) { ld = d; } - double ld; - alias ld this; + enum __c_long_double : double; + } + else + { + struct __c_long_double + { + this(double d) { ld = d; } + double ld; + alias ld this; + } } - alias __c_long_double myld; } else @@ -648,18 +654,26 @@ else } } -struct __c_long +version (PULL8152) { - this(x_long d) { ld = d; } - x_long ld; - alias ld this; + enum __c_long : x_long; + enum __c_ulong : x_ulong; } - -struct __c_ulong +else { - this(x_ulong d) { ld = d; } - x_ulong ld; - alias ld this; + struct __c_long + { + this(x_long d) { ld = d; } + x_long ld; + alias ld this; + } + + struct __c_ulong + { + this(x_ulong d) { ld = d; } + x_ulong ld; + alias ld this; + } } alias __c_long mylong; @@ -674,6 +688,7 @@ void test16() { mylong ld = 5; ld = testl(ld); + printf("ld = %lld, mylong.sizeof = %lld\n", cast(long)ld, cast(long)mylong.sizeof); assert(ld == 5 + mylong.sizeof); } { @@ -681,8 +696,55 @@ void test16() ld = testul(ld); assert(ld == 5 + myulong.sizeof); } + + version (PULL8152) + { + static if (__c_long.sizeof == long.sizeof) + { + static assert(__c_long.max == long.max); + static assert(__c_long.min == long.min); + static assert(__c_long.init == long.init); + + static assert(__c_ulong.max == ulong.max); + static assert(__c_ulong.min == ulong.min); + static assert(__c_ulong.init == ulong.init); + + __c_long cl = 0; + cl = cl + 1; + long l = cl; + cl = l; + + __c_ulong cul = 0; + cul = cul + 1; + ulong ul = cul; + cul = ul; + } + else static if (__c_long.sizeof == int.sizeof) + { + static assert(__c_long.max == int.max); + static assert(__c_long.min == int.min); + static assert(__c_long.init == int.init); + + static assert(__c_ulong.max == uint.max); + static assert(__c_ulong.min == uint.min); + static assert(__c_ulong.init == uint.init); + + __c_long cl = 0; + cl = cl + 1; + int i = cl; + cl = i; + + __c_ulong cul = 0; + cul = cul + 1; + uint u = cul; + cul = u; + } + else + static assert(0); + } } + /****************************************/ struct S13707