[PATCH] D91659: Allow anonymous enum typedefs to be referenced with the 'enum' specifier under MSVC compat mode

Shivanshu Goyal via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Nov 17 21:48:30 PST 2020


shivanshu3 updated this revision to Diff 305971.
shivanshu3 added a reviewer: rsmith.
shivanshu3 added a comment.

Addressing some of rsmith's comments:

- Add a test case where an enum variable is declared in the same scope as the enum definition
- Fix a style issue with parentheses
- Simplify the if condition for the C case
- The C++ case should only apply for TUK_Reference


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D91659/new/

https://reviews.llvm.org/D91659

Files:
  clang/lib/Sema/SemaDecl.cpp
  clang/test/Sema/enum-typedef-msvc.c
  clang/test/Sema/enum-typedef-msvc.cpp


Index: clang/test/Sema/enum-typedef-msvc.cpp
===================================================================
--- /dev/null
+++ clang/test/Sema/enum-typedef-msvc.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -fms-compatibility %s
+
+typedef enum {
+  First,
+  Second
+} MyEnum;
+
+class AMyInterface {
+  virtual void MyFunc(enum MyEnum *param) = 0;
+};
+
+class MyImpl : public AMyInterface {
+  virtual void MyFunc(enum MyEnum *param) override {}
+};
+
+enum MyEnum myEnum;
+
+// expected-no-diagnostics
Index: clang/test/Sema/enum-typedef-msvc.c
===================================================================
--- /dev/null
+++ clang/test/Sema/enum-typedef-msvc.c
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify -fms-compatibility -DUSE_MSVC_COMPAT %s
+
+typedef enum {
+  A
+} Foo;
+
+void func() {
+#ifdef USE_MSVC_COMPAT
+  enum Foo foo; // expected-no-diagnostics
+#else
+  enum Foo foo; // expected-error {{variable has incomplete type 'enum Foo'}} // expected-note {{forward declaration of 'enum Foo'}}
+#endif
+  (void)foo;
+}
+
+#ifdef USE_MSVC_COMPAT
+enum Foo foo2; // expected-no-diagnostics
+#else
+enum Foo foo2;  // expected-error {{tentative definition has type 'enum Foo' that is never completed}}
+                // expected-note at -1 {{forward declaration of 'enum Foo'}}
+#endif
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -15539,6 +15539,21 @@
     // shouldn't be diagnosing.
     LookupName(Previous, S);
 
+    // Under MSVC, the 'enum' specifier can be used for typedef'd enums.
+    // Note that lookup only fails in C, not C++, so this if condition
+    // is only used for C code.
+    if (getLangOpts().MSVCCompat && Kind == TTK_Enum && Previous.empty() &&
+        TUK == TUK_Reference) {
+      LookupResult TypedefEnumLookup(*this, Name, NameLoc, LookupOrdinaryName,
+                                     Redecl);
+      LookupName(TypedefEnumLookup, S);
+
+      if (auto *TD = TypedefEnumLookup.getAsSingle<TypedefNameDecl>())
+        if (auto *ED = dyn_cast_or_null<EnumDecl>(
+                TD->getAnonDeclWithTypedefName(true)))
+          Previous.addDecl(ED);
+    }
+
     // When declaring or defining a tag, ignore ambiguities introduced
     // by types using'ed into this scope.
     if (Previous.isAmbiguous() &&
@@ -15721,9 +15736,12 @@
       if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(PrevDecl)) {
         if (const TagType *TT = TD->getUnderlyingType()->getAs<TagType>()) {
           TagDecl *Tag = TT->getDecl();
-          if (Tag->getDeclName() == Name &&
-              Tag->getDeclContext()->getRedeclContext()
-                          ->Equals(TD->getDeclContext()->getRedeclContext())) {
+          bool AnonymousEnumEligible =
+              getLangOpts().MSVCCompat && TUK == TUK_Reference &&
+              Kind == TTK_Enum && Tag->getDeclName().isEmpty();
+          if ((Tag->getDeclName() == Name || AnonymousEnumEligible) &&
+              Tag->getDeclContext()->getRedeclContext()->Equals(
+                  TD->getDeclContext()->getRedeclContext())) {
             PrevDecl = Tag;
             Previous.clear();
             Previous.addDecl(Tag);


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D91659.305971.patch
Type: text/x-patch
Size: 3338 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20201118/1866f9ad/attachment-0001.bin>


More information about the cfe-commits mailing list