diff --git a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs
index 61300722..f3d84dc7 100644
--- a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs
+++ b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs
@@ -2089,12 +2089,58 @@ private void UncheckStmt(string targetTypeName, Stmt stmt)
_outputBuilder.EndUnchecked();
}
+ else if (EnumConstantInitNeedsCast(targetTypeName, stmt))
+ {
+ _outputBuilder.BeginInnerValue();
+ _outputBuilder.BeginInnerCast();
+ _outputBuilder.WriteCastType(targetTypeName);
+ _outputBuilder.EndInnerCast();
+
+ ParenthesizeStmt(stmt);
+
+ _outputBuilder.EndInnerValue();
+ }
else
{
VisitStmt(stmt);
}
}
+ private bool EnumConstantInitNeedsCast(string targetTypeName, Stmt stmt)
+ {
+ // A C# enum member initializer must be implicitly convertible to the enum's underlying
+ // type. The generator forces most enums to `int`, so an unsigned initializer expression
+ // (e.g. `1U << 22`) is not implicitly convertible and needs an explicit cast to the
+ // underlying type to compile. Out-of-range values are handled by the unchecked path.
+
+ if (stmt.DeclContext is not EnumDecl)
+ {
+ return false;
+ }
+
+ // Only cast the top-level initializer, not each nested subexpression, to avoid
+ // recursing back into this path while visiting the parenthesized initializer.
+ if (PreviousContext.Cursor is not EnumConstantDecl)
+ {
+ return false;
+ }
+
+ var expr = stmt as Expr;
+
+ if (expr is ImplicitCastExpr implicitCastExpr)
+ {
+ expr = implicitCastExpr.SubExprAsWritten;
+ }
+
+ if (expr is null)
+ {
+ return false;
+ }
+
+ var sourceTypeName = GetRemappedTypeName(expr, context: null, expr.Type, out _);
+ return IsUnsigned(sourceTypeName) && !IsUnsigned(targetTypeName);
+ }
+
private void Visit(Cursor cursor)
{
var currentContext = _context.AddLast((cursor, null));
diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithAnonymousEnumTest.CSharp.Compatible.Unix.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithAnonymousEnumTest.CSharp.Compatible.Unix.cs
index 1ba5fe8f..90dbb336 100644
--- a/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithAnonymousEnumTest.CSharp.Compatible.Unix.cs
+++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithAnonymousEnumTest.CSharp.Compatible.Unix.cs
@@ -4,7 +4,7 @@ namespace ClangSharp.Test
{
public enum MyEnum2
{
- MyEnum2_Value1 = MyEnum1_Value1,
+ MyEnum2_Value1 = ((int)(MyEnum1_Value1)),
}
public static partial class Methods
diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithAnonymousEnumTest.CSharp.Default.Unix.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithAnonymousEnumTest.CSharp.Default.Unix.cs
index 1ba5fe8f..90dbb336 100644
--- a/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithAnonymousEnumTest.CSharp.Default.Unix.cs
+++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithAnonymousEnumTest.CSharp.Default.Unix.cs
@@ -4,7 +4,7 @@ namespace ClangSharp.Test
{
public enum MyEnum2
{
- MyEnum2_Value1 = MyEnum1_Value1,
+ MyEnum2_Value1 = ((int)(MyEnum1_Value1)),
}
public static partial class Methods
diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithAnonymousEnumTest.CSharp.Latest.Unix.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithAnonymousEnumTest.CSharp.Latest.Unix.cs
index 1ba5fe8f..90dbb336 100644
--- a/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithAnonymousEnumTest.CSharp.Latest.Unix.cs
+++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithAnonymousEnumTest.CSharp.Latest.Unix.cs
@@ -4,7 +4,7 @@ namespace ClangSharp.Test
{
public enum MyEnum2
{
- MyEnum2_Value1 = MyEnum1_Value1,
+ MyEnum2_Value1 = ((int)(MyEnum1_Value1)),
}
public static partial class Methods
diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithAnonymousEnumTest.CSharp.Preview.Unix.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithAnonymousEnumTest.CSharp.Preview.Unix.cs
index 1ba5fe8f..90dbb336 100644
--- a/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithAnonymousEnumTest.CSharp.Preview.Unix.cs
+++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithAnonymousEnumTest.CSharp.Preview.Unix.cs
@@ -4,7 +4,7 @@ namespace ClangSharp.Test
{
public enum MyEnum2
{
- MyEnum2_Value1 = MyEnum1_Value1,
+ MyEnum2_Value1 = ((int)(MyEnum1_Value1)),
}
public static partial class Methods
diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithAnonymousEnumTest.Xml.Compatible.Unix.xml b/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithAnonymousEnumTest.Xml.Compatible.Unix.xml
index 26f7ce06..985c34e4 100644
--- a/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithAnonymousEnumTest.Xml.Compatible.Unix.xml
+++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithAnonymousEnumTest.Xml.Compatible.Unix.xml
@@ -6,7 +6,12 @@
int
- MyEnum1_Value1
+
+ int
+
+ MyEnum1_Value1
+
+
diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithAnonymousEnumTest.Xml.Default.Unix.xml b/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithAnonymousEnumTest.Xml.Default.Unix.xml
index 26f7ce06..985c34e4 100644
--- a/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithAnonymousEnumTest.Xml.Default.Unix.xml
+++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithAnonymousEnumTest.Xml.Default.Unix.xml
@@ -6,7 +6,12 @@
int
- MyEnum1_Value1
+
+ int
+
+ MyEnum1_Value1
+
+
diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithAnonymousEnumTest.Xml.Latest.Unix.xml b/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithAnonymousEnumTest.Xml.Latest.Unix.xml
index 26f7ce06..985c34e4 100644
--- a/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithAnonymousEnumTest.Xml.Latest.Unix.xml
+++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithAnonymousEnumTest.Xml.Latest.Unix.xml
@@ -6,7 +6,12 @@
int
- MyEnum1_Value1
+
+ int
+
+ MyEnum1_Value1
+
+
diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithAnonymousEnumTest.Xml.Preview.Unix.xml b/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithAnonymousEnumTest.Xml.Preview.Unix.xml
index 26f7ce06..985c34e4 100644
--- a/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithAnonymousEnumTest.Xml.Preview.Unix.xml
+++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithAnonymousEnumTest.Xml.Preview.Unix.xml
@@ -6,7 +6,12 @@
int
- MyEnum1_Value1
+
+ int
+
+ MyEnum1_Value1
+
+
diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithUnsignedInitConversionTest.CSharp.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithUnsignedInitConversionTest.CSharp.cs
new file mode 100644
index 00000000..5ad0029a
--- /dev/null
+++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithUnsignedInitConversionTest.CSharp.cs
@@ -0,0 +1,10 @@
+namespace ClangSharp.Test
+{
+ public enum MyEnum
+ {
+ MyEnum_Value0,
+ MyEnum_Value1 = ((int)(1U << 22)),
+ MyEnum_Value2 = ((int)((1U << 22) | (1 << 12))),
+ MyEnum_Value3 = unchecked((int)(0x80000000)),
+ }
+}
diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithUnsignedInitConversionTest.Xml.xml b/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithUnsignedInitConversionTest.Xml.xml
new file mode 100644
index 00000000..0aba1ef2
--- /dev/null
+++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/Baselines/EnumDeclaration/WithUnsignedInitConversionTest.Xml.xml
@@ -0,0 +1,44 @@
+
+
+
+
+ int
+
+ int
+
+
+ int
+
+
+ int
+ (1U << 22)
+
+
+
+
+ int
+
+
+ int
+
+ (1U << 22) | (1 << 12)
+
+
+
+
+
+ int
+
+
+
+ int
+
+ 0x80000000
+
+
+
+
+
+
+
+
diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/EnumDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/EnumDeclarationTest.cs
index 2ec592a8..7867464a 100644
--- a/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/EnumDeclarationTest.cs
+++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/Baseline/EnumDeclarationTest.cs
@@ -231,6 +231,17 @@ public Task WithImplicitConversionTest()
MyEnum_Value1,
MyEnum_Value2 = 0x80000000,
};
+");
+
+ [Test]
+ public Task WithUnsignedInitConversionTest()
+ => ValidateAsync(nameof(WithUnsignedInitConversionTest), @"enum MyEnum : int
+{
+ MyEnum_Value0,
+ MyEnum_Value1 = (1U << 22),
+ MyEnum_Value2 = (1U << 22) | (1 << 12),
+ MyEnum_Value3 = 0x80000000,
+};
");
[Test]