diff --git a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitStmt.cs b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitStmt.cs index 43e4fce9e..3bdeedc8a 100644 --- a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitStmt.cs +++ b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitStmt.cs @@ -1020,6 +1020,16 @@ private void VisitDeclRefExpr(DeclRefExpr declRefExpr) if (declRefExpr.Decl is EnumConstantDecl enumConstantDecl) { + if (enumConstantDecl.DeclContext is NamedDecl enumTypeDecl) + { + var enumTypeName = GetRemappedCursorName(enumTypeDecl, out _, skipUsing: true); + + if (!IsAnonymousEnum(enumTypeName)) + { + escapedName = EscapeAndStripEnumMemberName(name, enumTypeName); + } + } + if ((declRefExpr.DeclContext != enumConstantDecl.DeclContext) && (enumConstantDecl.DeclContext is NamedDecl namedDecl)) { var enumName = GetRemappedCursorName(namedDecl, out _, skipUsing: true); diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/StripEnumMemberReferenceTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/StripEnumMemberReferenceTest.cs new file mode 100644 index 000000000..47b87ad85 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/StripEnumMemberReferenceTest.cs @@ -0,0 +1,45 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System.Threading.Tasks; +using NUnit.Framework; + +namespace ClangSharp.UnitTests; + +/// +/// Regression test for https://github.com/dotnet/ClangSharp/issues/576. +/// When strip-enum-member-type-name is used, references to sibling enum members inside +/// an initializer expression must be stripped the same way as the member declarations, otherwise +/// the emitted code references undefined names. +/// +[Platform("win")] +public sealed class StripEnumMemberReferenceTest : PInvokeGeneratorTest +{ + [Test] + public Task SiblingReferencesAreStripped() + { + var inputContents = @"typedef enum WGPUInstanceBackend +{ + WGPUInstanceBackend_Vulkan = 1 << 0, + WGPUInstanceBackend_GL = 1 << 1, + WGPUInstanceBackend_Metal = 1 << 2, + WGPUInstanceBackend_Primary = WGPUInstanceBackend_Vulkan | WGPUInstanceBackend_Metal, + WGPUInstanceBackend_Secondary = WGPUInstanceBackend_GL +} WGPUInstanceBackend; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public enum WGPUInstanceBackend + { + Vulkan = 1 << 0, + GL = 1 << 1, + Metal = 1 << 2, + Primary = Vulkan | Metal, + Secondary = GL, + } +} +"; + + return ValidateGeneratedCSharpLatestWindowsBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorConfigurationOptions.StripEnumMemberTypeName); + } +}