[clang] [clang] Accept empty enum in MSVC compatible C (PR #159981)

via cfe-commits cfe-commits at lists.llvm.org
Tue Oct 28 05:47:45 PDT 2025


https://github.com/yicuixi updated https://github.com/llvm/llvm-project/pull/159981

>From 77fc06c7147e8eec1712f2c8babdb6fd8a48dd94 Mon Sep 17 00:00:00 2001
From: yicuixi <qin_17914 at 126.com>
Date: Sun, 21 Sep 2025 22:22:28 +0800
Subject: [PATCH 1/9] [clang] Accept empty enum in MSVC compatible C

Signed-off-by: yicuixi <qin_17914 at 126.com>
---
 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<Decl *, 32> 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 <qin_17914 at 126.com>
Date: Sun, 21 Sep 2025 23:17:18 +0800
Subject: [PATCH 2/9] Fix test

Signed-off-by: yicuixi <qin_17914 at 126.com>
---
 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 <qin_17914 at 126.com>
Date: Thu, 25 Sep 2025 01:48:13 +0800
Subject: [PATCH 3/9] 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<MicrosoftFixedEnum>;
+def ext_ms_c_empty_enum_type : Extension<
+  "empty enumeration types are a Microsoft extension">,
+  InGroup<MicrosoftEmptyEnum>;
 def ext_c23_enum_fixed_underlying_type : Extension<
   "enumeration types with a fixed underlying type are a C23 extension">,
   InGroup<C23>;
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<Decl *, 32> EnumConstantDecls;
   SmallVector<SuppressAccessChecks, 32> 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 <qin_17914 at 126.com>
Date: Fri, 26 Sep 2025 23:19:08 +0800
Subject: [PATCH 4/9] 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<Decl *, 32> EnumConstantDecls;
   SmallVector<SuppressAccessChecks, 32> EnumAvailabilityDiags;

>From b1cbba58073e44abf9a7d68989f0b66fdb0abc9f Mon Sep 17 00:00:00 2001
From: yicuixi <63290259+yicuixi at users.noreply.github.com>
Date: Wed, 1 Oct 2025 00:53:38 +0800
Subject: [PATCH 5/9] Update clang/docs/ReleaseNotes.rst

address comments

Co-authored-by: Erich Keane <ekeane at nvidia.com>
---
 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 <qin_17914 at 126.com>
Date: Tue, 21 Oct 2025 00:21:13 +0800
Subject: [PATCH 6/9] [clang] Add CodeGen test to check the ABI compatibility

Signed-off-by: yicuixi <qin_17914 at 126.com>
---
 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 <qin_17914 at 126.com>
Date: Thu, 23 Oct 2025 00:32:17 +0800
Subject: [PATCH 7/9] Fix test

Signed-off-by: yicuixi <qin_17914 at 126.com>
---
 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;
 

>From 5db97479f4c3a0fb1ab094ec293dafecdf78f04f Mon Sep 17 00:00:00 2001
From: yicuixi <63290259+yicuixi at users.noreply.github.com>
Date: Tue, 28 Oct 2025 15:13:46 +0800
Subject: [PATCH 8/9] Update clang/docs/LanguageExtensions.rst

Co-authored-by: Aaron Ballman <aaron at aaronballman.com>
---
 clang/docs/LanguageExtensions.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index 37dbcdd59f0aa..179bf78a6fde7 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -2409,7 +2409,7 @@ underlying types is available in C23 and later.
 Enumerations with no enumerators
 -----------------------------------------
 
-Clang provides support for Microsoft extensions to support empty enums.
+Clang provides support for Microsoft extensions to support enumerations with no enumerators.
 
 .. code-block:: c++
 

>From 475b4980861d745cc79459d2db3d26f1005b1a01 Mon Sep 17 00:00:00 2001
From: yicuixi <63290259+yicuixi at users.noreply.github.com>
Date: Tue, 28 Oct 2025 20:45:35 +0800
Subject: [PATCH 9/9] Update clang/docs/LanguageExtensions.rst

Co-authored-by: Aaron Ballman <aaron at aaronballman.com>
---
 clang/docs/LanguageExtensions.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index 179bf78a6fde7..78d6bd97e3840 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -2407,7 +2407,7 @@ 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 enumerations with no enumerators.
 



More information about the cfe-commits mailing list