From 77fc06c7147e8eec1712f2c8babdb6fd8a48dd94 Mon Sep 17 00:00:00 2001 From: yicuixi Date: Sun, 21 Sep 2025 22:22:28 +0800 Subject: [PATCH 1/7] [clang] Accept empty enum in MSVC compatible C Signed-off-by: yicuixi --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/Parse/ParseDecl.cpp | 3 ++- clang/test/Parser/ms-empty-enum.c | 8 ++++++++ 3 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 clang/test/Parser/ms-empty-enum.c diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 46d56bb3f07f5..c4b5e15b2b4f9 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -366,6 +366,7 @@ Bug Fixes in This Version - Fixed an assertion when an improper use of the ``malloc`` attribute targeting a function without arguments caused us to try to access a non-existent argument. (#GH159080) +- Accept empty enum in MSVC-compatible C. (#GH114402) Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 22c01c4e371f3..17e29b3efc348 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -5360,7 +5360,8 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl, T.consumeOpen(); // C does not allow an empty enumerator-list, C++ does [dcl.enum]. - if (Tok.is(tok::r_brace) && !getLangOpts().CPlusPlus) + if (Tok.is(tok::r_brace) && !getLangOpts().CPlusPlus && + !getLangOpts().MSVCCompat && !getLangOpts().MicrosoftExt) Diag(Tok, diag::err_empty_enum); SmallVector EnumConstantDecls; diff --git a/clang/test/Parser/ms-empty-enum.c b/clang/test/Parser/ms-empty-enum.c new file mode 100644 index 0000000000000..37e34d7c154bf --- /dev/null +++ b/clang/test/Parser/ms-empty-enum.c @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 %s -fsyntax-only -Wmicrosoft -verify -fms-extensions +// RUN: %clang_cc1 %s -fsyntax-only -Wmicrosoft -verify -fms-compatibility +// expected-no-diagnostics + +typedef enum tag1 { } A; +typedef enum tag2 { } B; +typedef enum : unsigned { } C; + From 191eacf08e22c443bd1b091fc97d4a3ca13d9cee Mon Sep 17 00:00:00 2001 From: yicuixi Date: Sun, 21 Sep 2025 23:17:18 +0800 Subject: [PATCH 2/7] Fix test Signed-off-by: yicuixi --- clang/test/Parser/ms-empty-enum.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clang/test/Parser/ms-empty-enum.c b/clang/test/Parser/ms-empty-enum.c index 37e34d7c154bf..7508f7fd0d0d8 100644 --- a/clang/test/Parser/ms-empty-enum.c +++ b/clang/test/Parser/ms-empty-enum.c @@ -1,8 +1,7 @@ // RUN: %clang_cc1 %s -fsyntax-only -Wmicrosoft -verify -fms-extensions // RUN: %clang_cc1 %s -fsyntax-only -Wmicrosoft -verify -fms-compatibility -// expected-no-diagnostics typedef enum tag1 { } A; typedef enum tag2 { } B; -typedef enum : unsigned { } C; +typedef enum : unsigned { } C; // expected-warning {{enumeration types with a fixed underlying type are a Microsoft extension}} From c106aaa0a5657f213b382e0677a7ce22826eeed8 Mon Sep 17 00:00:00 2001 From: yicuixi Date: Thu, 25 Sep 2025 01:48:13 +0800 Subject: [PATCH 3/7] address comments --- clang/include/clang/Basic/DiagnosticGroups.td | 4 +++- clang/include/clang/Basic/DiagnosticParseKinds.td | 3 +++ clang/lib/Parse/ParseDecl.cpp | 10 +++++++--- clang/test/Parser/ms-empty-enum.c | 9 ++++----- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 0c994e0b5ca4d..46bccf9bbd711 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -1435,6 +1435,7 @@ def MicrosoftDrectveSection : DiagGroup<"microsoft-drectve-section">; def MicrosoftInclude : DiagGroup<"microsoft-include">; def MicrosoftCppMacro : DiagGroup<"microsoft-cpp-macro">; def MicrosoftFixedEnum : DiagGroup<"microsoft-fixed-enum">; +def MicrosoftEmptyEnum : DiagGroup<"microsoft-empty-enum">; def MicrosoftSealed : DiagGroup<"microsoft-sealed">; def MicrosoftAbstract : DiagGroup<"microsoft-abstract">; def MicrosoftUnqualifiedFriend : DiagGroup<"microsoft-unqualified-friend">; @@ -1488,7 +1489,8 @@ def Microsoft : DiagGroup<"microsoft", MicrosoftConstInit, MicrosoftVoidPseudoDtor, MicrosoftAnonTag, MicrosoftCommentPaste, MicrosoftEndOfFile, MicrosoftInitFromPredefined, MicrosoftStringLiteralFromPredefined, - MicrosoftInconsistentDllImport, MicrosoftInlineOnNonFunction]>; + MicrosoftInconsistentDllImport, MicrosoftInlineOnNonFunction, + MicrosoftEmptyEnum]>; def ClangClPch : DiagGroup<"clang-cl-pch">; diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 4d9e123eb4ef1..1d027956a9248 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -116,6 +116,9 @@ def err_enumerator_unnamed_no_def : Error< def ext_ms_c_enum_fixed_underlying_type : Extension< "enumeration types with a fixed underlying type are a Microsoft extension">, InGroup; +def ext_ms_c_empty_enum_type : Extension< + "empty enumeration types are a Microsoft extension">, + InGroup; def ext_c23_enum_fixed_underlying_type : Extension< "enumeration types with a fixed underlying type are a C23 extension">, InGroup; diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 17e29b3efc348..5e9867501132e 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -5360,9 +5360,13 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl, T.consumeOpen(); // C does not allow an empty enumerator-list, C++ does [dcl.enum]. - if (Tok.is(tok::r_brace) && !getLangOpts().CPlusPlus && - !getLangOpts().MSVCCompat && !getLangOpts().MicrosoftExt) - Diag(Tok, diag::err_empty_enum); + if (Tok.is(tok::r_brace) && !getLangOpts().CPlusPlus) { + if (getLangOpts().MicrosoftExt) + Diag(T.getOpenLocation(), diag::ext_ms_c_empty_enum_type) + << SourceRange(T.getOpenLocation(), Tok.getLocation()); + else + Diag(Tok, diag::err_empty_enum); + } SmallVector EnumConstantDecls; SmallVector EnumAvailabilityDiags; diff --git a/clang/test/Parser/ms-empty-enum.c b/clang/test/Parser/ms-empty-enum.c index 7508f7fd0d0d8..790547af88bab 100644 --- a/clang/test/Parser/ms-empty-enum.c +++ b/clang/test/Parser/ms-empty-enum.c @@ -1,7 +1,6 @@ // RUN: %clang_cc1 %s -fsyntax-only -Wmicrosoft -verify -fms-extensions -// RUN: %clang_cc1 %s -fsyntax-only -Wmicrosoft -verify -fms-compatibility - -typedef enum tag1 { } A; -typedef enum tag2 { } B; -typedef enum : unsigned { } C; // expected-warning {{enumeration types with a fixed underlying type are a Microsoft extension}} +typedef enum tag1 { } A; // expected-warning {{empty enumeration types are a Microsoft extension}} +typedef enum tag2 { } B; // expected-warning {{empty enumeration types are a Microsoft extension}} +typedef enum : unsigned { } C; // expected-warning {{enumeration types with a fixed underlying type are a Microsoft extension}}\ + // expected-warning {{empty enumeration types are a Microsoft extension}} From 6bb40dae610d20c92d5318aa4338487021443a69 Mon Sep 17 00:00:00 2001 From: yicuixi Date: Fri, 26 Sep 2025 23:19:08 +0800 Subject: [PATCH 4/7] correct format --- clang/lib/Parse/ParseDecl.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 5e9867501132e..a0707f1ea6830 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -5360,13 +5360,13 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl, T.consumeOpen(); // C does not allow an empty enumerator-list, C++ does [dcl.enum]. - if (Tok.is(tok::r_brace) && !getLangOpts().CPlusPlus) { - if (getLangOpts().MicrosoftExt) - Diag(T.getOpenLocation(), diag::ext_ms_c_empty_enum_type) - << SourceRange(T.getOpenLocation(), Tok.getLocation()); - else - Diag(Tok, diag::err_empty_enum); - } + if (Tok.is(tok::r_brace) && !getLangOpts().CPlusPlus) { + if (getLangOpts().MicrosoftExt) + Diag(T.getOpenLocation(), diag::ext_ms_c_empty_enum_type) + << SourceRange(T.getOpenLocation(), Tok.getLocation()); + else + Diag(Tok, diag::err_empty_enum); + } SmallVector EnumConstantDecls; SmallVector EnumAvailabilityDiags; From b1cbba58073e44abf9a7d68989f0b66fdb0abc9f Mon Sep 17 00:00:00 2001 From: yicuixi <63290259+yicuixi@users.noreply.github.com> Date: Wed, 1 Oct 2025 00:53:38 +0800 Subject: [PATCH 5/7] Update clang/docs/ReleaseNotes.rst address comments Co-authored-by: Erich Keane --- clang/docs/ReleaseNotes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 3c085a667688d..169c90089f1f0 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -380,7 +380,7 @@ Bug Fixes in This Version a function without arguments caused us to try to access a non-existent argument. (#GH159080) - Fixed a failed assertion with empty filename arguments in ``__has_embed``. (#GH159898) -- Accept empty enum in MSVC-compatible C. (#GH114402) +- Accept empty enumerations in MSVC-compatible C mode. (#GH114402) Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 259e58d2f1c13d957338635fd2394bd4f62a0f07 Mon Sep 17 00:00:00 2001 From: yicuixi Date: Tue, 21 Oct 2025 00:21:13 +0800 Subject: [PATCH 6/7] [clang] Add CodeGen test to check the ABI compatibility Signed-off-by: yicuixi --- clang/docs/LanguageExtensions.rst | 10 ++++++++++ clang/test/CodeGen/ms-empty-enum.c | 6 ++++++ 2 files changed, 16 insertions(+) create mode 100644 clang/test/CodeGen/ms-empty-enum.c diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 6bb99c757cd19..37dbcdd59f0aa 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -2406,6 +2406,16 @@ those modes. Use ``__has_feature(c_fixed_enum)`` to determine whether support for fixed underlying types is available in C23 and later. +Enumerations with no enumerators +----------------------------------------- + +Clang provides support for Microsoft extensions to support empty enums. + +.. code-block:: c++ + + typedef enum empty { } A; + + Interoperability with C++11 lambdas ----------------------------------- diff --git a/clang/test/CodeGen/ms-empty-enum.c b/clang/test/CodeGen/ms-empty-enum.c new file mode 100644 index 0000000000000..aef20b4bcbcb1 --- /dev/null +++ b/clang/test/CodeGen/ms-empty-enum.c @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fms-extensions -triple x86_64-windows-msvc -Wno-implicit-function-declaration -emit-llvm %s -o - | FileCheck --check-prefix=X64 %s + +typedef enum tag1 {} A; + +// CHECK: void @empty_enum(i32 noundef %a) +void empty_enum(A a) {} From 394ae9c8280727ec31109ccec594e71ba6c1d0bd Mon Sep 17 00:00:00 2001 From: yicuixi Date: Thu, 23 Oct 2025 00:32:17 +0800 Subject: [PATCH 7/7] Fix test Signed-off-by: yicuixi --- clang/test/CodeGen/ms-empty-enum.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clang/test/CodeGen/ms-empty-enum.c b/clang/test/CodeGen/ms-empty-enum.c index aef20b4bcbcb1..6c1c87b756f9a 100644 --- a/clang/test/CodeGen/ms-empty-enum.c +++ b/clang/test/CodeGen/ms-empty-enum.c @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -fms-extensions -triple x86_64-windows-msvc -Wno-implicit-function-declaration -emit-llvm %s -o - | FileCheck --check-prefix=X64 %s +// RUN: %clang_cc1 -fms-extensions -triple x86_64-windows-msvc -Wno-implicit-function-declaration -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -fms-extensions -triple i386-windows-msvc -Wno-implicit-function-declaration -emit-llvm %s -o - | FileCheck %s typedef enum tag1 {} A;