llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Ivo Popov (ipopov)

<details>
<summary>Changes</summary>

Fixes https://github.com/llvm/llvm-project/issues/207066.

When compiling with C++20 modules, Clang performs ODR merging of class 
definitions across different modules. During this process, 
`ASTContext::isSameEntity` is used to check if member declarations match 
between the definitions.

However, `UsingEnumDecl` (representing C++20 `using enum` declarations) was not 
handled in `ASTContext::isSameEntity`, causing it to default to returning 
`false`. Consequently, identical class definitions containing a `using enum` 
statement failed to merge, resulting in spurious ODR mismatch errors such as: 
`error: 'MyStruct::MyEnum' from module 'ModuleB' is not present in definition 
of 'MyStruct' in module 'ModuleA'`.

This patch implements merging support for `UsingEnumDecl` in 
`ASTContext::isSameEntity` by comparing the nested-name-specifier qualifiers 
and the underlying `EnumDecl` target.

MARKDOWN=true

---
Full diff: https://github.com/llvm/llvm-project/pull/207071.diff


2 Files Affected:

- (modified) clang/lib/AST/ASTContext.cpp (+6) 
- (added) clang/test/Modules/modules-using-enum-class-scope.cppm (+53) 


``````````diff
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index abf0cd5e18c2b..ccdbb82ccc59f 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -7948,6 +7948,12 @@ bool ASTContext::isSameEntity(const NamedDecl *X, const 
NamedDecl *Y) const {
     return NAX->getNamespace()->Equals(NAY->getNamespace());
   }
 
+  if (const auto *UX = dyn_cast<UsingEnumDecl>(X)) {
+    const auto *UY = cast<UsingEnumDecl>(Y);
+    return isSameQualifier(UX->getQualifier(), UY->getQualifier()) &&
+           declaresSameEntity(UX->getEnumDecl(), UY->getEnumDecl());
+  }
+
   return false;
 }
 
diff --git a/clang/test/Modules/modules-using-enum-class-scope.cppm 
b/clang/test/Modules/modules-using-enum-class-scope.cppm
new file mode 100644
index 0000000000000..ca2463b2e74ae
--- /dev/null
+++ b/clang/test/Modules/modules-using-enum-class-scope.cppm
@@ -0,0 +1,53 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+//
+// RUN: %clang_cc1 -std=c++20 -fmodules -fimplicit-module-maps -x c++ -I%t \
+// RUN:   -emit-module -fmodule-name=ModuleA -o %t/ModuleA.pcm \
+// RUN:   %t/module.modulemap
+//
+// RUN: %clang_cc1 -std=c++20 -fmodules -fimplicit-module-maps -x c++ -I%t \
+// RUN:   -emit-module -fmodule-name=ModuleB -o %t/ModuleB.pcm \
+// RUN:   %t/module.modulemap
+//
+// RUN: %clang_cc1 -std=c++20 -fmodules -fimplicit-module-maps -x c++ -I%t \
+// RUN:   -fmodule-file=%t/ModuleA.pcm \
+// RUN:   -fmodule-file=%t/ModuleB.pcm \
+// RUN:   -verify %t/main.cpp
+
+//--- common.h
+#pragma once
+struct MyStruct {
+  enum class MyEnum { A };
+  using enum MyEnum;
+};
+
+//--- a.h
+#pragma once
+#include "common.h"
+
+//--- b.h
+#pragma once
+#include "common.h"
+
+//--- module.modulemap
+module ModuleA {
+  header "a.h"
+  export *
+}
+
+module ModuleB {
+  header "b.h"
+  export *
+}
+
+//--- main.cpp
+#include "a.h"
+#include "b.h"
+
+inline void use() {
+  auto x = MyStruct::A;
+}
+
+// expected-no-diagnostics

``````````

</details>


https://github.com/llvm/llvm-project/pull/207071
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to