Merge pull request #11642 from wilzbach/fix-dtoh

Fix Issue 21208 - C/C++ header generation for {string,enum} enums
This commit is contained in:
Sebastian Wilzbach 2020-08-30 16:54:17 +02:00 committed by GitHub
commit 6cd107f79f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 94 additions and 12 deletions

View file

@ -44,6 +44,7 @@ struct ASTCodegen
alias MODFlags = dmd.mtype.MODFlags;
alias Type = dmd.mtype.Type;
alias Parameter = dmd.mtype.Parameter;
alias Tarray = dmd.mtype.Tarray;
alias Taarray = dmd.mtype.Taarray;
alias Tbool = dmd.mtype.Tbool;
alias Tchar = dmd.mtype.Tchar;

View file

@ -389,6 +389,8 @@ public:
{
Int,
Numeric,
String,
Enum,
Other
}
@ -438,6 +440,12 @@ public:
AST.Tuns32,
AST.Tint64, AST.Tuns64:
return EnumKind.Numeric;
case AST.Tarray:
if (type.isString())
return EnumKind.String;
break;
case AST.Tenum:
return EnumKind.Enum;
default:
break;
}
@ -673,33 +681,41 @@ public:
}
if (vd.storage_class & AST.STC.manifest &&
vd._init && vd._init.isExpInitializer())
vd._init && vd._init.isExpInitializer() && vd.type !is null)
{
AST.Type type = vd.type;
EnumKind kind = getEnumKind(type);
if (kind != EnumKind.Other)
final switch (kind)
{
hasNumericConstant = true;
buf.writestring("ENUM_CONSTANT_NUMERIC(");
}
else
{
hasTypedConstant = true;
buf.writestring("ENUM_CONSTANT(");
case EnumKind.Int, EnumKind.Numeric:
hasNumericConstant = true;
buf.writestring("ENUM_CONSTANT_NUMERIC(");
break;
case EnumKind.String, EnumKind.Enum:
hasTypedConstant = true;
buf.writestring("ENUM_CONSTANT(");
break;
case EnumKind.Other:
buf.printf("// ignoring enum `%s` because type `%s` is currently not supported for enum constants.\n", vd.toPrettyChars(), type.toChars());
return;
}
writeEnumTypeName(type);
buf.writestring(", ");
buf.writestring(vd.ident.toString());
buf.writestring(", ");
auto e = AST.initializerToExpression(vd._init);
if (kind != EnumKind.Other)
if (kind == EnumKind.Int || kind == EnumKind.Numeric)
{
auto ie = e.isIntegerExp();
visitInteger(ie.toInteger(), type);
}
else
{
e.accept(this);
}
buf.writestringln(")");
buf.writenl();
return;
@ -1267,7 +1283,7 @@ public:
buf.writestring("ANON_ENUM_KEY(");
else if (!manifestConstants)
buf.writestring("ANON_ENUM_KEY_NUMERIC(");
else if (manifestConstants && memberKind != EnumKind.Other)
else if (manifestConstants && memberKind == EnumKind.Int || memberKind == EnumKind.Numeric)
{
hasNumericConstant = true;
buf.writestring("ENUM_CONSTANT_NUMERIC(");
@ -1280,7 +1296,7 @@ public:
writeEnumTypeName(memberType);
buf.printf(", %s, ", m.ident.toChars());
if (memberKind != EnumKind.Other)
if (kind == EnumKind.Int || kind == EnumKind.Numeric)
{
auto ie = cast(AST.IntegerExp)m.value;
visitInteger(ie.toInteger(), memberType);

View file

@ -42,6 +42,9 @@ TEST_OUTPUT:
# define ENUM_CONSTANT(type, name, value) static type const name = value;
#endif
struct Foo;
struct FooCpp;
ENUM_CONSTANT_NUMERIC(int32_t, Anon, 10)
ENUM_CONSTANT_NUMERIC(bool, Anon2, true)
@ -86,6 +89,42 @@ END_ENUM_TYPE(const char*, EnumWithImplicitType, ENUMWITHIMPLICITTYPE, enumwithi
ENUM_CONSTANT_NUMERIC(int32_t, AnonMixedOne, 1)
ENUM_CONSTANT_NUMERIC(int64_t, AnonMixedTwo, 2LL)
ENUM_CONSTANT(const char*, AnonMixedA, "a")
BEGIN_ENUM(STC, STC, stc)
ENUM_KEY(int32_t, a, 1, STC, STC, stc, STC)
ENUM_KEY(int32_t, b, 2, STC, STC, stc, STC)
END_ENUM(STC, STC, stc)
ENUM_CONSTANT(STC, STC_D, (STC)3)
// ignoring non-cpp struct Foo because of linkage
BEGIN_ENUM_TYPE(Foo, MyEnum, MYENUM, myenum)
ENUM_KEY_TYPE(Foo, A, Foo(42), MyEnum, MYENUM, myenum, ME)
ENUM_KEY_TYPE(Foo, B, Foo(84), MyEnum, MYENUM, myenum, ME)
END_ENUM_TYPE(Foo, MyEnum, MYENUM, myenum)
ENUM_CONSTANT(MyEnum, test, Foo(42))
struct FooCpp
{
int32_t i;
FooCpp() : i() {}
};
BEGIN_ENUM_TYPE(FooCpp, MyEnumCpp, MYENUMCPP, myenumcpp)
ENUM_KEY_TYPE(FooCpp, A, FooCpp(42), MyEnumCpp, MYENUMCPP, myenumcpp, MEC)
ENUM_KEY_TYPE(FooCpp, B, FooCpp(84), MyEnumCpp, MYENUMCPP, myenumcpp, MEC)
END_ENUM_TYPE(FooCpp, MyEnumCpp, MYENUMCPP, myenumcpp)
ENUM_CONSTANT(MyEnum, testCpp, Foo(42))
// ignoring enum `dtoh_enum.b` because type `int[]` is currently not supported for enum constants.
// ignoring enum `dtoh_enum.c` because type `int[int]` is currently not supported for enum constants.
// ignoring function dtoh_enum.foo because it's extern
// ignoring enum `dtoh_enum.d` because type `extern (C) void function()` is currently not supported for enum constants.
// ignoring variable dtoh_enum.e_b because of linkage
// ignoring enum `dtoh_enum.e` because type `immutable(bool)*` is currently not supported for enum constants.
---
*/
@ -141,3 +180,29 @@ enum
long AnonMixedTwo = 2,
string AnonMixedA = "a"
}
enum STC
{
a = 1,
b = 2,
}
enum STC_D = STC.a | STC.b;
struct Foo { int i; }
enum MyEnum { A = Foo(42), B = Foo(84) }
enum test = MyEnum.A;
extern(C++) struct FooCpp { int i; }
enum MyEnumCpp { A = FooCpp(42), B = FooCpp(84) }
enum testCpp = MyEnum.A;
// currently unsupported enums
enum b = [1, 2, 3];
enum c = [2: 3];
extern(C) void foo();
enum d = &foo;
immutable bool e_b;
enum e = &e_b;