Skip to content

Commit 19a9de0

Browse files
yicuixierichkeaneAaronBallman
authored
[clang] Accept empty enum in MSVC compatible C (#159981)
Fixes #114402. This patch accept empty enum in C as a microsoft extension and introduce an new warning `-Wmicrosoft-empty-enum`. --------- Signed-off-by: yicuixi <[email protected]> Co-authored-by: Erich Keane <[email protected]> Co-authored-by: Aaron Ballman <[email protected]>
1 parent 4c2a9c4 commit 19a9de0

File tree

7 files changed

+37
-3
lines changed

7 files changed

+37
-3
lines changed

clang/docs/LanguageExtensions.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2409,6 +2409,16 @@ those modes.
24092409
Use ``__has_feature(c_fixed_enum)`` to determine whether support for fixed
24102410
underlying types is available in C23 and later.
24112411
2412+
Enumerations with no enumerators
2413+
--------------------------------
2414+
2415+
Clang provides support for Microsoft extensions to support enumerations with no enumerators.
2416+
2417+
.. code-block:: c++
2418+
2419+
typedef enum empty { } A;
2420+
2421+
24122422
Interoperability with C++11 lambdas
24132423
-----------------------------------
24142424

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,7 @@ Bug Fixes in This Version
444444
- Fixed a failed assertion with empty filename arguments in ``__has_embed``. (#GH159898)
445445
- Fixed a failed assertion with empty filename in ``#embed`` directive. (#GH162951)
446446
- Fixed a crash triggered by unterminated ``__has_embed``. (#GH162953)
447+
- Accept empty enumerations in MSVC-compatible C mode. (#GH114402)
447448

448449
Bug Fixes to Compiler Builtins
449450
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

clang/include/clang/Basic/DiagnosticGroups.td

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1436,6 +1436,7 @@ def MicrosoftDrectveSection : DiagGroup<"microsoft-drectve-section">;
14361436
def MicrosoftInclude : DiagGroup<"microsoft-include">;
14371437
def MicrosoftCppMacro : DiagGroup<"microsoft-cpp-macro">;
14381438
def MicrosoftFixedEnum : DiagGroup<"microsoft-fixed-enum">;
1439+
def MicrosoftEmptyEnum : DiagGroup<"microsoft-empty-enum">;
14391440
def MicrosoftSealed : DiagGroup<"microsoft-sealed">;
14401441
def MicrosoftAbstract : DiagGroup<"microsoft-abstract">;
14411442
def MicrosoftUnqualifiedFriend : DiagGroup<"microsoft-unqualified-friend">;
@@ -1489,7 +1490,8 @@ def Microsoft : DiagGroup<"microsoft",
14891490
MicrosoftConstInit, MicrosoftVoidPseudoDtor, MicrosoftAnonTag,
14901491
MicrosoftCommentPaste, MicrosoftEndOfFile,
14911492
MicrosoftInitFromPredefined, MicrosoftStringLiteralFromPredefined,
1492-
MicrosoftInconsistentDllImport, MicrosoftInlineOnNonFunction]>;
1493+
MicrosoftInconsistentDllImport, MicrosoftInlineOnNonFunction,
1494+
MicrosoftEmptyEnum]>;
14931495

14941496
def ClangClPch : DiagGroup<"clang-cl-pch">;
14951497

clang/include/clang/Basic/DiagnosticParseKinds.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,9 @@ def err_enumerator_unnamed_no_def : Error<
116116
def ext_ms_c_enum_fixed_underlying_type : Extension<
117117
"enumeration types with a fixed underlying type are a Microsoft extension">,
118118
InGroup<MicrosoftFixedEnum>;
119+
def ext_ms_c_empty_enum_type : Extension<
120+
"empty enumeration types are a Microsoft extension">,
121+
InGroup<MicrosoftEmptyEnum>;
119122
def ext_c23_enum_fixed_underlying_type : Extension<
120123
"enumeration types with a fixed underlying type are a C23 extension">,
121124
InGroup<C23>;

clang/lib/Parse/ParseDecl.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5370,8 +5370,13 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl,
53705370
T.consumeOpen();
53715371

53725372
// C does not allow an empty enumerator-list, C++ does [dcl.enum].
5373-
if (Tok.is(tok::r_brace) && !getLangOpts().CPlusPlus)
5374-
Diag(Tok, diag::err_empty_enum);
5373+
if (Tok.is(tok::r_brace) && !getLangOpts().CPlusPlus) {
5374+
if (getLangOpts().MicrosoftExt)
5375+
Diag(T.getOpenLocation(), diag::ext_ms_c_empty_enum_type)
5376+
<< SourceRange(T.getOpenLocation(), Tok.getLocation());
5377+
else
5378+
Diag(Tok, diag::err_empty_enum);
5379+
}
53755380

53765381
SmallVector<Decl *, 32> EnumConstantDecls;
53775382
SmallVector<SuppressAccessChecks, 32> EnumAvailabilityDiags;

clang/test/CodeGen/ms-empty-enum.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// RUN: %clang_cc1 -fms-extensions -triple x86_64-windows-msvc -Wno-implicit-function-declaration -emit-llvm %s -o - | FileCheck %s
2+
// RUN: %clang_cc1 -fms-extensions -triple i386-windows-msvc -Wno-implicit-function-declaration -emit-llvm %s -o - | FileCheck %s
3+
4+
typedef enum tag1 {} A;
5+
6+
// CHECK: void @empty_enum(i32 noundef %a)
7+
void empty_enum(A a) {}

clang/test/Parser/ms-empty-enum.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// RUN: %clang_cc1 %s -fsyntax-only -Wmicrosoft -verify -fms-extensions
2+
3+
typedef enum tag1 { } A; // expected-warning {{empty enumeration types are a Microsoft extension}}
4+
typedef enum tag2 { } B; // expected-warning {{empty enumeration types are a Microsoft extension}}
5+
typedef enum : unsigned { } C; // expected-warning {{enumeration types with a fixed underlying type are a Microsoft extension}}\
6+
// expected-warning {{empty enumeration types are a Microsoft extension}}

0 commit comments

Comments
 (0)