[clang] 085eae6 - [C++20] [Modules] Allow to merge enums with the same underlying interger types

Chuanqi Xu via cfe-commits cfe-commits at lists.llvm.org
Thu Jan 18 01:10:20 PST 2024


Author: Chuanqi Xu
Date: 2024-01-18T17:09:35+08:00
New Revision: 085eae6b863881fb9fda323e5b672b04a00ed19e

URL: https://github.com/llvm/llvm-project/commit/085eae6b863881fb9fda323e5b672b04a00ed19e
DIFF: https://github.com/llvm/llvm-project/commit/085eae6b863881fb9fda323e5b672b04a00ed19e.diff

LOG: [C++20] [Modules] Allow to merge enums with the same underlying interger types

Close https://github.com/llvm/llvm-project/issues/76638. See the issue
for the context of the change.

Added: 
    clang/test/Modules/pr76638.cppm

Modified: 
    clang/lib/AST/ODRHash.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp
index aea1a93ae1fa828..07677d655c5afd6 100644
--- a/clang/lib/AST/ODRHash.cpp
+++ b/clang/lib/AST/ODRHash.cpp
@@ -741,8 +741,55 @@ void ODRHash::AddEnumDecl(const EnumDecl *Enum) {
   if (Enum->isScoped())
     AddBoolean(Enum->isScopedUsingClassTag());
 
-  if (Enum->getIntegerTypeSourceInfo())
-    AddQualType(Enum->getIntegerType());
+  if (Enum->getIntegerTypeSourceInfo()) {
+    // FIMXE: This allows two enums with 
diff erent spellings to have the same
+    // hash.
+    //
+    //  // mod1.cppm
+    //  module;
+    //  extern "C" {
+    //      typedef unsigned __int64 size_t;
+    //  }
+    //  namespace std {
+    //      using :: size_t;
+    //  }
+    //
+    //  extern "C++" {
+    //      namespace std {
+    //          enum class align_val_t : std::size_t {};
+    //      }
+    //  }
+    //
+    //  export module mod1;
+    //  export using std::align_val_t;
+    //
+    //  // mod2.cppm
+    //  module;
+    //  extern "C" {
+    //      typedef unsigned __int64 size_t;
+    //  }
+    //
+    //  extern "C++" {
+    //      namespace std {
+    //          enum class align_val_t : size_t {};
+    //      }
+    //  }
+    //
+    //  export module mod2;
+    //  import mod1;
+    //  export using std::align_val_t;
+    //
+    // The above example should be disallowed since it violates
+    // [basic.def.odr]p14:
+    //
+    //    Each such definition shall consist of the same sequence of tokens
+    //
+    // The definitions of `std::align_val_t` in two module units have 
diff erent
+    // spellings but we failed to give an error here.
+    //
+    // See https://github.com/llvm/llvm-project/issues/76638 for details.
+    AddQualType(Enum->getIntegerType().getCanonicalType());
+  }
 
   // Filter out sub-Decls which will not be processed in order to get an
   // accurate count of Decl's.

diff  --git a/clang/test/Modules/pr76638.cppm b/clang/test/Modules/pr76638.cppm
new file mode 100644
index 000000000000000..8cc807961421b7c
--- /dev/null
+++ b/clang/test/Modules/pr76638.cppm
@@ -0,0 +1,69 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/mod1.cppm -emit-module-interface -o %t/mod1.pcm
+// RUN: %clang_cc1 -std=c++20 %t/mod2.cppm -fmodule-file=mod1=%t/mod1.pcm \
+// RUN:     -fsyntax-only -verify
+//
+// RUN: %clang_cc1 -std=c++20 %t/mod3.cppm -emit-module-interface -o %t/mod3.pcm
+// RUN: %clang_cc1 -std=c++20 %t/mod4.cppm -fmodule-file=mod3=%t/mod3.pcm \
+// RUN:     -fsyntax-only -verify
+
+//--- size_t.h
+
+extern "C" {
+    typedef unsigned int size_t;
+}
+
+//--- csize_t
+namespace std {
+            using :: size_t;
+}
+
+//--- align.h
+namespace std {
+    enum class align_val_t : size_t {};
+}
+
+//--- mod1.cppm
+module;
+#include "size_t.h"
+#include "align.h"
+export module mod1;
+export using std::align_val_t;
+
+//--- mod2.cppm
+// expected-no-diagnostics
+module;
+#include "size_t.h"
+#include "csize_t"
+#include "align.h"
+export module mod2;
+import mod1;
+export using std::align_val_t;
+
+//--- signed_size_t.h
+// Test that we can still find the case if the underlying type is 
diff erent
+extern "C" {
+    typedef signed int size_t;
+}
+
+//--- mod3.cppm
+module;
+#include "size_t.h"
+#include "align.h"
+export module mod3;
+export using std::align_val_t;
+
+//--- mod4.cppm
+module;
+#include "signed_size_t.h"
+#include "csize_t"
+#include "align.h"
+export module mod4;
+import mod3;
+export using std::align_val_t;
+
+// expected-error at align.h:* {{'std::align_val_t' has 
diff erent definitions in 
diff erent modules; defined here first 
diff erence is enum with specified type 'size_t' (aka 'int')}}
+// expected-note at align.h:* {{but in 'mod3.<global>' found enum with specified type 'size_t' (aka 'unsigned int')}}


        


More information about the cfe-commits mailing list