[clang] [clang][modules] Fix std::initializer_list recognition if it's exported out of a module (PR #118537)

via cfe-commits cfe-commits at lists.llvm.org
Sat Dec 7 08:25:56 PST 2024


https://github.com/jijjijj updated https://github.com/llvm/llvm-project/pull/118537

>From d0a3059a10b7ceeb7e9c27068266f8c41e794203 Mon Sep 17 00:00:00 2001
From: jijjijj <realjijjijj at gmail.com>
Date: Tue, 3 Dec 2024 22:57:34 +0300
Subject: [PATCH 1/2] Fix std::initializer_list recognition if it's exported
 out of a module

If the std::initializer_list is exported out of module, its DeclContext is not a namespace as `Sema::isStdInitializerList` expects, but an `Decl::Kind::Export` and only its parent is a namespace. So this commit makes `Sema::isStdInitializerList` account for that.
---
 clang/lib/Sema/SemaDeclCXX.cpp | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 7e8e321c4b90e6..4572229562ed3b 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -11919,8 +11919,12 @@ bool Sema::isStdInitializerList(QualType Ty, QualType *Element) {
     CXXRecordDecl *TemplateClass = Template->getTemplatedDecl();
     if (TemplateClass->getIdentifier() !=
             &PP.getIdentifierTable().get("initializer_list") ||
-        !getStdNamespace()->InEnclosingNamespaceSetOf(
-            TemplateClass->getDeclContext()))
+        !(getStdNamespace()->InEnclosingNamespaceSetOf(
+            TemplateClass->getDeclContext()) ||
+        // if decl context is an export from module we need to check the parent
+        (TemplateClass->getDeclContext()->getDeclKind() == Decl::Kind::Export &&
+            getStdNamespace()->InEnclosingNamespaceSetOf(
+                TemplateClass->getDeclContext()->getParent()))))
       return false;
     // This is a template called std::initializer_list, but is it the right
     // template?

>From 932764c8eb1b87364ffbcf8311a38cd0b8ff0b9d Mon Sep 17 00:00:00 2001
From: jijjijj <realjijjijj at gmail.com>
Date: Sat, 7 Dec 2024 19:24:29 +0300
Subject: [PATCH 2/2] Fix std::initializer_list recognition if it's exported
 out of a module

- Improve implementation
- Add a regression test
- Add release notes
---
 clang/docs/ReleaseNotes.rst                   |  2 +
 clang/lib/Sema/SemaDeclCXX.cpp                |  8 +---
 ...hrough-export-and-linkage-issue-118218.cpp | 39 +++++++++++++++++++
 3 files changed, 43 insertions(+), 6 deletions(-)
 create mode 100644 clang/test/Modules/initializer-list-recognition-through-export-and-linkage-issue-118218.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 59e3a6609123d2..2e25f487bfb528 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -796,6 +796,8 @@ Bug Fixes to C++ Support
 - Fixed an assertion failure caused by mangled names with invalid identifiers. (#GH112205)
 - Fixed an incorrect lambda scope of generic lambdas that caused Clang to crash when computing potential lambda
   captures at the end of a full expression. (#GH115931)
+- Fixed recognition of ``std::initializer_list`` when it's surrounded with ``extern "C++"`` and exported
+  out of a module. (#GH118218)
 
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 4436b521d21928..d5229143709c03 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -11926,12 +11926,8 @@ bool Sema::isStdInitializerList(QualType Ty, QualType *Element) {
     CXXRecordDecl *TemplateClass = Template->getTemplatedDecl();
     if (TemplateClass->getIdentifier() !=
             &PP.getIdentifierTable().get("initializer_list") ||
-        !(getStdNamespace()->InEnclosingNamespaceSetOf(
-            TemplateClass->getDeclContext()) ||
-        // if decl context is an export from module we need to check the parent
-        (TemplateClass->getDeclContext()->getDeclKind() == Decl::Kind::Export &&
-            getStdNamespace()->InEnclosingNamespaceSetOf(
-                TemplateClass->getDeclContext()->getParent()))))
+        !getStdNamespace()->InEnclosingNamespaceSetOf(
+            TemplateClass->getNonTransparentDeclContext()))
       return false;
     // This is a template called std::initializer_list, but is it the right
     // template?
diff --git a/clang/test/Modules/initializer-list-recognition-through-export-and-linkage-issue-118218.cpp b/clang/test/Modules/initializer-list-recognition-through-export-and-linkage-issue-118218.cpp
new file mode 100644
index 00000000000000..70ad8951e63356
--- /dev/null
+++ b/clang/test/Modules/initializer-list-recognition-through-export-and-linkage-issue-118218.cpp
@@ -0,0 +1,39 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/std.cppm -emit-module-interface -o %t/std.pcm
+// RUN: %clang_cc1 -std=c++20 %t/mod.cppm -fprebuilt-module-path=%t -emit-module-interface -o %t/mod.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -verify %t/main.cpp
+
+//--- std.cppm
+export module std;
+
+extern "C++" {
+  namespace std {
+  export template <class E>
+  class initializer_list {
+    const E* _1;
+    const E* _2;
+  };
+  }
+}
+
+//--- mod.cppm
+export module mod;
+
+import std;
+
+export struct A {
+  void func(std::initializer_list<int>) {}
+};
+
+//--- main.cpp
+// expected-no-diagnostics
+import std;
+import mod;
+
+int main() {
+  A{}.func({1,1});
+  return 0;
+}
\ No newline at end of file



More information about the cfe-commits mailing list