https://github.com/ChuanqiXu9 created 
https://github.com/llvm/llvm-project/pull/214121

Close https://github.com/llvm/llvm-project/issues/213299

Ideally, we shall merge the new enum with the old enum when we creating the new 
enum. But the enum is anonymous and the typedef's name come after the enum 
body, it is too late to merge them. This is the choice 10 years ago: 
a523022b5384d7a0901beea7a5f36ee9c09ba339. Actually what we're merging is the 
typedef decls.

Then https://github.com/llvm/llvm-project/pull/114240 removes the logic to 
remove the new ED. This the direct trigger for the above issue of ambiguous 
look ups.

We choose to fix the problem by setting the type of new enum to the type of the 
old enum to fix the ambiguous lookup issue.

>From eea9081311ceec66e0c7c37b494299b18e6c2ddc Mon Sep 17 00:00:00 2001
From: "yedeng.yd" <[email protected]>
Date: Wed, 5 Aug 2026 10:56:28 +0800
Subject: [PATCH] [C++20] [Modules] merge the type for anony enum from import
 and #include

Close https://github.com/llvm/llvm-project/issues/213299

Ideally, we shall merge the new enum with the old enum when we
creating the new enum. But the enum is anonymous and the typedef's name
come after the enum body, it is too late to merge them. This is the choice 10
years ago: a523022b5384d7a0901beea7a5f36ee9c09ba339. Actually what we're
merging is the typedef decls.

Then https://github.com/llvm/llvm-project/pull/114240 removes the logic
to remove the new ED. This the direct trigger for the above issue of
ambiguous look ups.

We choose to fix the problem by setting the type of new enum to the type
of the old enum to fix the ambiguous lookup issue.
---
 clang/docs/ReleaseNotes.md                    |  4 +++
 clang/lib/Sema/SemaDecl.cpp                   | 27 +++++++++++++++++++
 .../Modules/include-after-imports-enums.cppm  |  8 ++++++
 3 files changed, 39 insertions(+)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index a38b99ff8e075..209278f105ea4 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -385,6 +385,10 @@ features cannot lower the translation-unit ABI level;
 
 #### Bug Fixes to C++ Support
 
+- Fixed a false type mismatch when a typedef naming an anonymous enumeration
+  was used through a C++20 named module and its defining header was 
subsequently
+  included. (#GH213299)
+
 - Fixed an issue where `__typeof__` incorrectly rejected cv-qualified function 
types.
 
 - Fixed a bug where top-level CV qualifiers (such as ``const``) were dropped 
from pointers modified by Microsoft pointer attributes (like ``__ptr32`` and 
``__ptr64``) and WebAssembly's ``__funcref``.
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index c46d2d780fad7..a1f1ad65bb79c 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -2667,6 +2667,33 @@ void Sema::MergeTypedefNameDecl(Scope *S, 
TypedefNameDecl *New,
       else
         New->setTypeSourceInfo(OldTD->getTypeSourceInfo());
 
+      // See https://github.com/llvm/llvm-project/issues/213299 for the case.
+      //
+      // Ideally, we shall merge the new enum with the old enum when we
+      // creating the new enum. But the enum is anonymous and the typedef's 
name
+      // come after the enum body, it is too late to merge them. This is the
+      // choice 10 years ago: a523022b5384d7a0901beea7a5f36ee9c09ba339. 
Actually
+      // what we're merging here is the typedef decls.
+      //
+      // Then https://github.com/llvm/llvm-project/pull/114240 removes the 
logic
+      // to remove the new ED. This the direct trigger for the above issue of
+      // ambiguous look ups.
+      //
+      // We choose to fix the problem by setting the type of new enum to the
+      // type of old enums. This is consistent with the above call to
+      // setTypeSourceInfo.
+      //
+      // The check `M && M->isGlobalModule()` is not necessary but we hopt to
+      // limit the impact of this change. We can relax the check when we find
+      // similar issue later in other cases.
+      if (Module *M = OldTag->getOwningModule(); M && M->isGlobalModule())
+        if (auto *NewEnum = dyn_cast<EnumDecl>(NewTag))
+          if (auto *OldEnum = dyn_cast<EnumDecl>(OldTag)) {
+            QualType OldEnumType = Context.getCanonicalTagType(OldEnum);
+            for (auto *ECD : NewEnum->enumerators())
+              ECD->setType(OldEnumType);
+          }
+
       // Make the old tag definition visible.
       makeMergedDefinitionVisible(Hidden);
 
diff --git a/clang/test/Modules/include-after-imports-enums.cppm 
b/clang/test/Modules/include-after-imports-enums.cppm
index 00affd98e299f..260f6d150f46f 100644
--- a/clang/test/Modules/include-after-imports-enums.cppm
+++ b/clang/test/Modules/include-after-imports-enums.cppm
@@ -9,13 +9,19 @@
 // RUN: %clang_cc1 -std=c++20 %t/use.cpp -fprebuilt-module-path=%t -verify 
-fsyntax-only
 
 //--- enum.h
+#pragma once
+
 enum E { Value };
 
+typedef enum { TypedefValue } TypedefEnum;
+void useTypedefEnum(TypedefEnum);
+
 //--- M.cppm
 module;
 #include "enum.h"
 export module M;
 auto e = Value;
+export TypedefEnum typedefEnum;
 
 //--- use.cpp
 // expected-no-diagnostics
@@ -23,3 +29,5 @@ import M;
 #include "enum.h"
 
 auto e = Value;
+static_assert(__is_same(decltype(TypedefValue), TypedefEnum));
+inline void testTypedefEnum() { useTypedefEnum(TypedefValue); }

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

Reply via email to