https://github.com/jeremyd2019 updated 
https://github.com/llvm/llvm-project/pull/140169

>From 47f81a804a36a5b685f130f22d2ab5d330170861 Mon Sep 17 00:00:00 2001
From: kikairoya <kikair...@gmail.com>
Date: Mon, 21 Apr 2025 23:30:13 +0900
Subject: [PATCH 1/4] [Cygwin][MinGW] Internal class in
 explicitly-instantiation-declarated template should be instantiated

In-code comment says "explicit instantiation decl of the outer class
doesn't affect the inner class" but this behavior seems MSVC
specific, MinGW-GCC and Cygwin-GCC does not.
Clang should honor gcc's behavior.

This change fixes std::string compatibilty and resolves strange link
error (statically linked), strange crash (dynamically linked) using
libstdc++ on Cygwin.
---
 clang/lib/Sema/SemaTemplateInstantiate.cpp    |   1 +
 .../CodeGenCXX/mingw-template-dllexport.cpp   | 109 +++++++++++++++---
 2 files changed, 93 insertions(+), 17 deletions(-)

diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp 
b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index d028eea4f8f3e..b7c27b3795f5d 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -4247,6 +4247,7 @@ Sema::InstantiateClassMembers(SourceLocation 
PointOfInstantiation,
         continue;
 
       if (Context.getTargetInfo().getTriple().isOSWindows() &&
+          !Context.getTargetInfo().getTriple().isOSCygMing() &&
           TSK == TSK_ExplicitInstantiationDeclaration) {
         // On Windows, explicit instantiation decl of the outer class doesn't
         // affect the inner class. Typically extern template declarations are
diff --git a/clang/test/CodeGenCXX/mingw-template-dllexport.cpp 
b/clang/test/CodeGenCXX/mingw-template-dllexport.cpp
index de112d6da53db..a6047b5955e96 100644
--- a/clang/test/CodeGenCXX/mingw-template-dllexport.cpp
+++ b/clang/test/CodeGenCXX/mingw-template-dllexport.cpp
@@ -6,46 +6,121 @@
 #define JOIN2(x, y) x##y
 #define JOIN(x, y) JOIN2(x, y)
 #define UNIQ(name) JOIN(name, __LINE__)
-#define USEMEMFUNC(class, func) void (class::*UNIQ(use)())() { return 
&class::func; }
+#define USEMEMFUNC(class, func) auto UNIQ(use) = &class::func;
 
 template <class T>
 class c {
+  // MinGW-GCC does not apply 'dllexport' to inline member function in 
dll-exported template but clang does from long ago.
   void f() {}
+  void g();
+  inline static int u = 0;
+  static int v;
 };
+template <class T> void c<T>::g() {}
+template <class T> int c<T>::v = 0;
 
+// #1
 template class __declspec(dllexport) c<int>;
 
-// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIiE1fEv
-
+// #2
 extern template class __declspec(dllexport) c<char>;
 template class c<char>;
 
-// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIcE1fEv
-
+// #3
 extern template class c<double>;
-template class __declspec(dllexport) c<double>;
+template class __declspec(dllexport) c<double>; // expected-warning {{ 
'dllexport' attribute ignored on explicit instantiation definition }}
 
-// CHECK-NOT: define {{.*}} dllexport {{.*}} @_ZN1cIdE1fEv
 
 template <class T>
 struct outer {
-  void f();
+  void f() {}
+  void g();
+  inline static int u = 0;
+  static int v;
+  // MinGW-GCC and Clang does not apply 'dllexport' to inner type and its 
sub-elements in template class.
   struct inner {
-    void f();
+    void f() {}
+    void g();
+    inline static int u = 0;
+    static int v;
   };
 };
 
-template <class T> void outer<T>::f() {}
-template <class T> void outer<T>::inner::f() {}
+template <class T> void outer<T>::g() {}
+template <class T> void outer<T>::inner::g() {}
+template <class T> int outer<T>::v = 0;
+template <class T> int outer<T>::inner::v = 0;
 
-template class __declspec(dllexport) outer<int>;
+// #4
+template struct __declspec(dllexport) outer<int>;
 
-// CHECK: define {{.*}} dllexport {{.*}} @_ZN5outerIiE1fEv
-// CHECK-NOT: define {{.*}} dllexport {{.*}} @_ZN5outerIiE5inner1fEv
-
-extern template class __declspec(dllimport) outer<char>;
+// #5
+extern template struct __declspec(dllimport) outer<char>;
 USEMEMFUNC(outer<char>, f)
+USEMEMFUNC(outer<char>, g)
+USEMEMFUNC(outer<char>, u)
+USEMEMFUNC(outer<char>, v)
 USEMEMFUNC(outer<char>::inner, f)
+USEMEMFUNC(outer<char>::inner, g)
+USEMEMFUNC(outer<char>::inner, u)
+USEMEMFUNC(outer<char>::inner, v)
+
+
+// #1 variables
+// CHECK: @_ZN1cIiE1uE = {{.*}} dllexport {{.*}}
+// CHECK: @_ZN1cIiE1vE = {{.*}} dllexport {{.*}}
+
+// #2 variables
+// CHECK: @_ZN1cIcE1uE = {{.*}} dllexport {{.*}}
+// CHECK: @_ZN1cIcE1vE = {{.*}} dllexport {{.*}}
+
+// #3 variables
+// CHECK: @_ZN1cIdE1uE = {{.*}}
+// CHECK-NOT: @_ZN1cIcE1uE = {{.*}} dllexport {{.*}}
+// CHECK: @_ZN1cIdE1vE = {{.*}}
+// CHECK-NOT: @_ZN1cIcE1vE = {{.*}} dllexport {{.*}}
+
+// #4 variables
+// CHECK: @_ZN5outerIiE1uE = {{.*}} dllexport {{.*}}
+// CHECK: @_ZN5outerIiE1vE = {{.*}} dllexport {{.*}}
+// CHECK: @_ZN5outerIiE5inner1uE = {{.*}}
+// CHECK-NOT: @_ZN5outerIiE5inner1uE = {{.*}} dllexport {{.*}}
+// CHECK: @_ZN5outerIiE5inner1vE = {{.*}}
+// CHECK-NOT: @_ZN5outerIiE5inner1vE = {{.*}} dllexport {{.*}}
+
+// #5 variables
+// CHECK: @_ZN5outerIcE1uE = external dllimport {{.*}}
+// CHECK: @_ZN5outerIcE1vE = external dllimport {{.*}}
+// CHECK-NOT: @_ZN5outerIcE5inner1uE = dllimport {{.*}}
+// CHECK-NOT: @_ZN5outerIcE5inner1vE = dllimport {{.*}}
+// CHECK: @_ZN5outerIcE5inner1uE = external {{.*}}
+// CHECK: @_ZN5outerIcE5inner1vE = external {{.*}}
+
+
+// #1 functions
+// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIiE1fEv
+// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIiE1gEv
+
+// #2 functions
+// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIcE1fEv
+// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIcE1gEv
+
+// #3 functions
+// CHECK-NOT: define {{.*}} dllexport {{.*}} @_ZN1cIdE1fEv
+// CHECK-NOT: define {{.*}} dllexport {{.*}} @_ZN1cIdE1gEv
+
+// #4 functions
+// CHECK: define {{.*}} dllexport {{.*}} @_ZN5outerIiE1fEv
+// CHECK: define {{.*}} dllexport {{.*}} @_ZN5outerIiE1gEv
+// CHECK-NOT: define {{.*}} dllexport {{.*}} @_ZN5outerIiE5inner1fEv
+// CHECK-NOT: define {{.*}} dllexport {{.*}} @_ZN5outerIiE5inner1gEv
 
+// #5 functions
 // CHECK: declare dllimport {{.*}} @_ZN5outerIcE1fEv
-// CHECK: define {{.*}} @_ZN5outerIcE5inner1fEv
+// CHECK: declare dllimport {{.*}} @_ZN5outerIcE1gEv
+// CHECK-NOT: declare dllimport {{.*}} @_ZN5outerIcE5inner1fEv
+// CHECK-NOT: declare dllimport {{.*}} @_ZN5outerIcE5inner1gEv
+// CHECK-NOT: define {{.*}} @_ZN5outerIcE1fEv
+// CHECK-NOT: define {{.*}} @_ZN5outerIcE5inner1fEv
+// CHECK-NOT: define {{.*}} @_ZN5outerIcE1gEv
+// CHECK-NOT: define {{.*}} @_ZN5outerIcE5inner1gEv

>From 9275c093b51b0dae0b883e0d42c14507f8fc9870 Mon Sep 17 00:00:00 2001
From: Jeremy Drake <git...@jdrake.com>
Date: Mon, 19 May 2025 16:01:57 -0700
Subject: [PATCH 2/4] test _LIBCPP_HIDE_FROM_ABI on sentry methods

---
 libcxx/include/__ostream/basic_ostream.h | 44 ++++++++++--------------
 libcxx/include/istream                   | 41 ++++++++++------------
 2 files changed, 38 insertions(+), 47 deletions(-)

diff --git a/libcxx/include/__ostream/basic_ostream.h 
b/libcxx/include/__ostream/basic_ostream.h
index f7473a36d8ccc..9a3fb4ec1313d 100644
--- a/libcxx/include/__ostream/basic_ostream.h
+++ b/libcxx/include/__ostream/basic_ostream.h
@@ -186,37 +186,31 @@ class basic_ostream<_CharT, _Traits>::sentry {
   basic_ostream<_CharT, _Traits>& __os_;
 
 public:
-  explicit sentry(basic_ostream<_CharT, _Traits>& __os);
-  ~sentry();
-  sentry(const sentry&)            = delete;
-  sentry& operator=(const sentry&) = delete;
-
-  _LIBCPP_HIDE_FROM_ABI explicit operator bool() const { return __ok_; }
-};
-
-template <class _CharT, class _Traits>
-basic_ostream<_CharT, _Traits>::sentry::sentry(basic_ostream<_CharT, _Traits>& 
__os) : __ok_(false), __os_(__os) {
-  if (__os.good()) {
-    if (__os.tie())
-      __os.tie()->flush();
-    __ok_ = true;
+  _LIBCPP_HIDE_FROM_ABI explicit sentry(basic_ostream<_CharT, _Traits>& __os) 
: __ok_(false), __os_(__os) {
+    if (__os.good()) {
+      if (__os.tie())
+        __os.tie()->flush();
+      __ok_ = true;
+    }
   }
-}
-
-template <class _CharT, class _Traits>
-basic_ostream<_CharT, _Traits>::sentry::~sentry() {
-  if (__os_.rdbuf() && __os_.good() && (__os_.flags() & ios_base::unitbuf) && 
uncaught_exceptions() == 0) {
+  _LIBCPP_HIDE_FROM_ABI ~sentry() {
+    if (__os_.rdbuf() && __os_.good() && (__os_.flags() & ios_base::unitbuf) 
&& uncaught_exceptions() == 0) {
 #  if _LIBCPP_HAS_EXCEPTIONS
-    try {
+      try {
 #  endif // _LIBCPP_HAS_EXCEPTIONS
-      if (__os_.rdbuf()->pubsync() == -1)
-        __os_.setstate(ios_base::badbit);
+        if (__os_.rdbuf()->pubsync() == -1)
+          __os_.setstate(ios_base::badbit);
 #  if _LIBCPP_HAS_EXCEPTIONS
-    } catch (...) {
-    }
+      } catch (...) {
+      }
 #  endif // _LIBCPP_HAS_EXCEPTIONS
+    }
   }
-}
+  _LIBCPP_HIDE_FROM_ABI sentry(const sentry&)            = delete;
+  _LIBCPP_HIDE_FROM_ABI sentry& operator=(const sentry&) = delete;
+
+  _LIBCPP_HIDE_FROM_ABI explicit operator bool() const { return __ok_; }
+};
 
 template <class _CharT, class _Traits>
 basic_ostream<_CharT, _Traits>::basic_ostream(basic_ostream&& __rhs) {
diff --git a/libcxx/include/istream b/libcxx/include/istream
index 95340c739c118..3cd4482f6cfd9 100644
--- a/libcxx/include/istream
+++ b/libcxx/include/istream
@@ -309,7 +309,25 @@ class basic_istream<_CharT, _Traits>::sentry {
   bool __ok_;
 
 public:
-  explicit sentry(basic_istream<_CharT, _Traits>& __is, bool __noskipws = 
false);
+  _LIBCPP_HIDE_FROM_ABI explicit sentry(basic_istream<_CharT, _Traits>& __is, 
bool __noskipws = false) : __ok_(false) {
+    if (__is.good()) {
+      if (__is.tie())
+        __is.tie()->flush();
+      if (!__noskipws && (__is.flags() & ios_base::skipws)) {
+        typedef istreambuf_iterator<_CharT, _Traits> _Ip;
+        const ctype<_CharT>& __ct = std::use_facet<ctype<_CharT> 
>(__is.getloc());
+        _Ip __i(__is);
+        _Ip __eof;
+        for (; __i != __eof; ++__i)
+          if (!__ct.is(__ct.space, *__i))
+            break;
+        if (__i == __eof)
+          __is.setstate(ios_base::failbit | ios_base::eofbit);
+      }
+      __ok_ = __is.good();
+    } else
+      __is.setstate(ios_base::failbit);
+  }
   //    ~sentry() = default;
 
   _LIBCPP_HIDE_FROM_ABI explicit operator bool() const { return __ok_; }
@@ -318,27 +336,6 @@ public:
   sentry& operator=(const sentry&) = delete;
 };
 
-template <class _CharT, class _Traits>
-basic_istream<_CharT, _Traits>::sentry::sentry(basic_istream<_CharT, _Traits>& 
__is, bool __noskipws) : __ok_(false) {
-  if (__is.good()) {
-    if (__is.tie())
-      __is.tie()->flush();
-    if (!__noskipws && (__is.flags() & ios_base::skipws)) {
-      typedef istreambuf_iterator<_CharT, _Traits> _Ip;
-      const ctype<_CharT>& __ct = std::use_facet<ctype<_CharT> 
>(__is.getloc());
-      _Ip __i(__is);
-      _Ip __eof;
-      for (; __i != __eof; ++__i)
-        if (!__ct.is(__ct.space, *__i))
-          break;
-      if (__i == __eof)
-        __is.setstate(ios_base::failbit | ios_base::eofbit);
-    }
-    __ok_ = __is.good();
-  } else
-    __is.setstate(ios_base::failbit);
-}
-
 template <class _CharT, class _Traits>
 basic_istream<_CharT, _Traits>::basic_istream(basic_istream&& __rhs) : 
__gc_(__rhs.__gc_) {
   __rhs.__gc_ = 0;

>From 4d0ed6dd482fd9855a8c89759b21a40716df2cd3 Mon Sep 17 00:00:00 2001
From: Jeremy Drake <git...@jdrake.com>
Date: Mon, 19 May 2025 16:31:42 -0700
Subject: [PATCH 3/4] CI: run windows jobs without waiting for stage2

---
 .github/workflows/libcxx-build-and-test.yaml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/libcxx-build-and-test.yaml 
b/.github/workflows/libcxx-build-and-test.yaml
index 3551fc150e59b..49dd6da7c60ee 100644
--- a/.github/workflows/libcxx-build-and-test.yaml
+++ b/.github/workflows/libcxx-build-and-test.yaml
@@ -239,7 +239,7 @@ jobs:
 
   windows:
     runs-on: windows-2022
-    needs: [ stage2 ]
+    #needs: [ stage2 ]
     strategy:
       fail-fast: false
       matrix:

>From ce1573e9e5e1f0630abd6c301902bc301d45507f Mon Sep 17 00:00:00 2001
From: Jeremy Drake <git...@jdrake.com>
Date: Mon, 19 May 2025 17:05:32 -0700
Subject: [PATCH 4/4] CI: use test llvm-mingw toolchain

---
 .github/workflows/libcxx-build-and-test.yaml | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/.github/workflows/libcxx-build-and-test.yaml 
b/.github/workflows/libcxx-build-and-test.yaml
index 49dd6da7c60ee..27e5bd6450495 100644
--- a/.github/workflows/libcxx-build-and-test.yaml
+++ b/.github/workflows/libcxx-build-and-test.yaml
@@ -263,10 +263,24 @@ jobs:
         if: ${{ matrix.mingw != true }}
         run: |
           choco install -y llvm --version=19.1.7 --allow-downgrade
+      - name: Download test llvm-mingw
+        if: ${{ matrix.mingw == true }}
+        shell: bash
+        run: |
+          
ARTIFACT_URL=https://github.com/jeremyd2019/llvm-mingw/actions/runs/15080594305/artifacts/3143907630
+          case "$ARTIFACT_URL" in
+          https://github.com/*/actions/runs/[0-9]*/artifacts/[0-9]*)
+            ARTIFACT_URL="$(echo "$ARTIFACT_URL" |
+              sed 
's|^\(https://\)\(github.com/\)\(.*/actions/\)runs/[0-9]*/\(artifacts/[0-9]*\)$|\1api.\2repos/\3\4/zip|')"
+              ;;
+          esac
+          curl -H "Authorization: token ${{secrets.GITHUB_TOKEN}}" \
+              -fLo artifact.zip "$ARTIFACT_URL"
+          powershell Expand-Archive artifact.zip -DestinationPath .
+          rm -f artifact.zip
       - name: Install llvm-mingw
         if: ${{ matrix.mingw == true }}
         run: |
-          curl -LO 
https://github.com/mstorsjo/llvm-mingw/releases/download/20250114/llvm-mingw-20250114-ucrt-x86_64.zip
           powershell Expand-Archive llvm-mingw*.zip -DestinationPath .
           del llvm-mingw*.zip
           mv llvm-mingw* c:\llvm-mingw

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to