[PATCH] D91659: Allow 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 Dec 1 15:55:53 PST 2020


shivanshu3 updated this revision to Diff 308803.
shivanshu3 retitled this revision from "Allow anonymous enum typedefs to be referenced with the 'enum' specifier under MSVC compat mode" to "Allow enum typedefs to be referenced with the 'enum' specifier under MSVC compat mode".
shivanshu3 edited the summary of this revision.
shivanshu3 added a comment.

Previously for some reason I thought that MSVC only allowed this behavior for anonymous enums. But now I realize that the enum doesn't have to be anonymous. So the following code should be legal too with '-fms-compatibility':

  typedef enum FooEnum {
    A
  } Foo;
  
  void func() {
    enum Foo foo;
  }


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,17 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -fms-compatibility %s
+
+typedef enum FooEnum {
+  A,
+} Foo;
+
+class AMyInterface {
+  virtual void MyFunc(enum Foo *param) = 0;
+};
+
+class MyImpl : public AMyInterface {
+  virtual void MyFunc(enum Foo *param) override {}
+};
+
+enum Foo 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 FooEnum {
+  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 *TT = TD->getUnderlyingType()->getAs<TagType>())
+          if (auto *ED = dyn_cast_or_null<EnumDecl>(TT->getDecl()))
+            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 AllowLookupUsingTypedefName = getLangOpts().MSVCCompat &&
+                                             TUK == TUK_Reference &&
+                                             Kind == TTK_Enum;
+          if ((Tag->getDeclName() == Name || AllowLookupUsingTypedefName) &&
+              Tag->getDeclContext()->getRedeclContext()->Equals(
+                  TD->getDeclContext()->getRedeclContext())) {
             PrevDecl = Tag;
             Previous.clear();
             Previous.addDecl(Tag);


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D91659.308803.patch
Type: text/x-patch
Size: 3400 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20201201/48b6c4ef/attachment.bin>


More information about the cfe-commits mailing list