[llvm] [libcxx] [clang] "Reapply "[Sema] Fix crash on invalid code with parenthesized aggrega… (PR #76833)

Mark de Wever via cfe-commits cfe-commits at lists.llvm.org
Wed Jan 3 10:33:26 PST 2024


https://github.com/mordante updated https://github.com/llvm/llvm-project/pull/76833

>From 77abc737eebd5cf62b52248a6e35e4c74fbeca80 Mon Sep 17 00:00:00 2001
From: Mark de Wever <koraq at xs4all.nl>
Date: Wed, 3 Jan 2024 18:00:43 +0100
Subject: [PATCH 1/4] "Reapply "[Sema] Fix crash on invalid code with
 parenthesized aggregate initialization" (#76272)""

With updates the libc++ tests.

This reverts commit 2205d23 and relands
86dc6e1 and
7ab16fb.

Original commit was reverted because of failing libc++ tests, see #76232 for
the discussion.

The errors in the tests are spurious in the first place (coming from initialization
of invalid classes), so update the tests to match new behavior that does
not show those errors.
---
 clang/lib/Sema/SemaInit.cpp                   |  8 ++++++
 clang/test/SemaCXX/crash-GH76228.cpp          | 28 +++++++++++++++++++
 clang/test/SemaCXX/paren-list-agg-init.cpp    |  2 +-
 .../transform_error.mandates.verify.cpp       |  8 ------
 .../transform_error.mandates.verify.cpp       |  8 ------
 5 files changed, 37 insertions(+), 17 deletions(-)
 create mode 100644 clang/test/SemaCXX/crash-GH76228.cpp

diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 61d244f3bb9798..cc9db5ded1149a 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -5512,6 +5512,14 @@ static void TryOrBuildParenListInitialization(
   } else if (auto *RT = Entity.getType()->getAs<RecordType>()) {
     bool IsUnion = RT->isUnionType();
     const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+    if (RD->isInvalidDecl()) {
+      // Exit early to avoid confusion when processing members.
+      // We do the same for braced list initialization in
+      // `CheckStructUnionTypes`.
+      Sequence.SetFailed(
+          clang::InitializationSequence::FK_ParenthesizedListInitFailed);
+      return;
+    }
 
     if (!IsUnion) {
       for (const CXXBaseSpecifier &Base : RD->bases()) {
diff --git a/clang/test/SemaCXX/crash-GH76228.cpp b/clang/test/SemaCXX/crash-GH76228.cpp
new file mode 100644
index 00000000000000..33a9395823127e
--- /dev/null
+++ b/clang/test/SemaCXX/crash-GH76228.cpp
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -std=c++20 -verify %s
+// Check we don't crash on incomplete members and bases when handling parenthesized initialization.
+class incomplete; // expected-note at -0 3  {{forward declaration of 'incomplete'}}
+struct foo {
+  int a;
+  incomplete b;
+  // expected-error at -1 {{incomplete type}}
+};
+foo a1(0);
+
+struct one_int {
+    int a;
+};
+struct bar : one_int, incomplete {};
+// expected-error at -1 {{incomplete type}}
+bar a2(0);
+
+incomplete a3[3](1,2,3);
+// expected-error at -1 {{incomplete type}}
+
+struct qux : foo {
+};
+qux a4(0);
+
+struct fred {
+    foo a[3];
+};
+fred a5(0);
diff --git a/clang/test/SemaCXX/paren-list-agg-init.cpp b/clang/test/SemaCXX/paren-list-agg-init.cpp
index f60b20e0d46568..c1964a5a9eb005 100644
--- a/clang/test/SemaCXX/paren-list-agg-init.cpp
+++ b/clang/test/SemaCXX/paren-list-agg-init.cpp
@@ -289,7 +289,7 @@ int test() {
   // used to crash
   S a(0, 1);
   S b(0);
-  S c(0, 0, 1); // beforecxx20-warning {{aggregate initialization of type 'S' from a parenthesized list of values is a C++20 extension}}
+  S c(0, 0, 1);
 
   S d {0, 1};
   S e {0};
diff --git a/libcxx/test/libcxx/utilities/expected/expected.expected/transform_error.mandates.verify.cpp b/libcxx/test/libcxx/utilities/expected/expected.expected/transform_error.mandates.verify.cpp
index 965e82a7b40346..3260a8cbc7f8e6 100644
--- a/libcxx/test/libcxx/utilities/expected/expected.expected/transform_error.mandates.verify.cpp
+++ b/libcxx/test/libcxx/utilities/expected/expected.expected/transform_error.mandates.verify.cpp
@@ -46,11 +46,9 @@ void test() {
   {
     std::expected<int, int> e;
     e.transform_error(return_unexpected<int&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
-    // expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
     // expected-error-re@*:* {{static assertion failed {{.*}}[expected.object.general] A program that instantiates the definition of template expected<T, E> for {{.*}} is ill-formed.}}
 
     e.transform_error(return_no_object<int&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
-    // expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
     // expected-error-re@*:* {{static assertion failed {{.*}}[expected.object.general] A program that instantiates the definition of template expected<T, E> for {{.*}} is ill-formed.}}
   }
 
@@ -58,27 +56,21 @@ void test() {
   {
     const std::expected<int, int> e;
     e.transform_error(return_unexpected<const int &>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
-    // expected-error-re@*:* 2 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
     e.transform_error(return_no_object<const int &>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
-    // expected-error-re@*:* 2 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
   }
 
   // Test && overload
   {
     std::expected<int, int> e;
     std::move(e).transform_error(return_unexpected<int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
-    // expected-error-re@*:* 2 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
     std::move(e).transform_error(return_no_object<int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
-    // expected-error-re@*:* 2 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
   }
 
   // Test const&& overload
   {
     const std::expected<int, int> e;
     std::move(e).transform_error(return_unexpected<const int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
-    // expected-error-re@*:* 2 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
     std::move(e).transform_error(return_no_object<const int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
-    // expected-error-re@*:* 2 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
   }
 }
 // clang-format on
diff --git a/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp b/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp
index 09aa1332e98000..21dc2476879186 100644
--- a/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp
+++ b/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp
@@ -46,11 +46,9 @@ void test() {
   {
     std::expected<void, int> e;
     e.transform_error(return_unexpected<int&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
-    // expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
     // expected-error-re@*:* {{static assertion failed {{.*}}A program that instantiates expected<T, E> with a E that is not a valid argument for unexpected<E> is ill-formed}}
 
     e.transform_error(return_no_object<int&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
-    // expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
     // expected-error-re@*:* {{static assertion failed {{.*}}A program that instantiates expected<T, E> with a E that is not a valid argument for unexpected<E> is ill-formed}}
   }
 
@@ -58,27 +56,21 @@ void test() {
   {
     const std::expected<void, int> e;
     e.transform_error(return_unexpected<const int &>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
-    // expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
     e.transform_error(return_no_object<const int &>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
-    // expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
   }
 
   // Test && overload
   {
     std::expected<void, int> e;
     std::move(e).transform_error(return_unexpected<int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
-    // expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
     std::move(e).transform_error(return_no_object<int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
-    // expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
   }
 
   // Test const&& overload
   {
     const std::expected<void, int> e;
     std::move(e).transform_error(return_unexpected<const int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
-    // expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
     std::move(e).transform_error(return_no_object<const int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
-    // expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
   }
 }
 // clang-format on

>From 9e32e29c3413139db312f360e2d3930ccd8679f8 Mon Sep 17 00:00:00 2001
From: Mark de Wever <koraq at xs4all.nl>
Date: Wed, 3 Jan 2024 18:27:48 +0100
Subject: [PATCH 2/4] Test the bootstrap build.

---
 .github/workflows/libcxx-build-and-test.yaml | 110 -------------------
 1 file changed, 110 deletions(-)

diff --git a/.github/workflows/libcxx-build-and-test.yaml b/.github/workflows/libcxx-build-and-test.yaml
index 25e8c8c1ef21aa..65997d9c1ca411 100644
--- a/.github/workflows/libcxx-build-and-test.yaml
+++ b/.github/workflows/libcxx-build-and-test.yaml
@@ -48,124 +48,14 @@ env:
 
 
 jobs:
-  stage1:
-    if: github.repository_owner == 'llvm'
-    runs-on: libcxx-runners-8-set
-    continue-on-error: false
-    strategy:
-      fail-fast: false
-      matrix:
-        config: [
-          'generic-cxx03',
-          'generic-cxx26',
-          'generic-modules'
-        ]
-        cc: [  'clang-18' ]
-        cxx: [ 'clang++-18' ]
-        clang_tidy: [ 'ON' ]
-        include:
-          - config: 'generic-gcc'
-            cc: 'gcc-13'
-            cxx: 'g++-13'
-            clang_tidy: 'OFF'
-    steps:
-      - uses: actions/checkout at v4
-      - name: ${{ matrix.config }}.${{ matrix.cxx }}
-        run: libcxx/utils/ci/run-buildbot ${{ matrix.config }}
-        env:
-          CC: ${{ matrix.cc }}
-          CXX: ${{ matrix.cxx }}
-          ENABLE_CLANG_TIDY: ${{ matrix.clang_tidy }}
-      - uses: actions/upload-artifact at v3
-        if: always()
-        with:
-          name: ${{ matrix.config }}-${{ matrix.cxx }}-results
-          path: |
-            **/test-results.xml
-            **/*.abilist
-            **/CMakeError.log
-            **/CMakeOutput.log
-            **/crash_diagnostics/*
-  stage2:
-    if: github.repository_owner == 'llvm'
-    runs-on: libcxx-runners-8-set
-    needs: [ stage1 ]
-    continue-on-error: false
-    strategy:
-      fail-fast: false
-      matrix:
-        config: [
-          'generic-cxx11',
-          'generic-cxx14',
-          'generic-cxx17',
-          'generic-cxx20',
-          'generic-cxx23'
-        ]
-        cc: [ 'clang-18' ]
-        cxx: [ 'clang++-18' ]
-        clang_tidy: [ 'ON' ]
-        include:
-          - config: 'generic-gcc-cxx11'
-            cc: 'gcc-13'
-            cxx: 'g++-13'
-            clang_tidy: 'OFF'
-          - config: 'generic-cxx23'
-            cc: 'clang-16'
-            cxx: 'clang++-16'
-            clang_tidy: 'OFF'
-          - config: 'generic-cxx23'
-            cc: 'clang-17'
-            cxx: 'clang++-17'
-            clang_tidy: 'OFF'
-    steps:
-      - uses: actions/checkout at v4
-      - name: ${{ matrix.config }}
-        run: libcxx/utils/ci/run-buildbot ${{ matrix.config }}
-        env:
-          CC: ${{ matrix.cc }}
-          CXX: ${{ matrix.cxx }}
-          ENABLE_CLANG_TIDY: ${{ matrix.clang_tidy }}
-      - uses: actions/upload-artifact at v3
-        if: always()  # Upload artifacts even if the build or test suite fails
-        with:
-          name: ${{ matrix.config }}-results
-          path: |
-            **/test-results.xml
-            **/*.abilist
-            **/CMakeError.log
-            **/CMakeOutput.log
-            **/crash_diagnostics/*
   stage3:
     if: github.repository_owner == 'llvm'
-    needs: [ stage1, stage2 ]
     continue-on-error: false
     strategy:
       fail-fast: false
       max-parallel: 8
       matrix:
         config: [
-          'generic-abi-unstable',
-          'generic-hardening-mode-debug',
-          'generic-hardening-mode-extensive',
-          'generic-hardening-mode-fast',
-          'generic-hardening-mode-fast-with-abi-breaks',
-          'generic-merged',
-          'generic-modules-lsv',
-          'generic-no-exceptions',
-          'generic-no-experimental',
-          'generic-no-filesystem',
-          'generic-no-localization',
-          'generic-no-random_device',
-          'generic-no-threads',
-          'generic-no-tzdb',
-          'generic-no-unicode',
-          'generic-no-wide-characters',
-          'generic-no-rtti',
-          'generic-static',
-          'generic-with_llvm_unwinder',
-          # TODO Find a better place for the benchmark and bootstrapping builds to live. They're either very expensive
-          # or don't provide much value since the benchmark run results are too noise on the bots.
-          'benchmarks',
           'bootstrapping-build'
         ]
         machine: [ 'libcxx-runners-8-set' ]

>From d03dd4e7ea98126e259828a969df466624366c7b Mon Sep 17 00:00:00 2001
From: Mark de Wever <koraq at xs4all.nl>
Date: Wed, 3 Jan 2024 19:24:18 +0100
Subject: [PATCH 3/4] Revert "Test the bootstrap build."

This reverts commit 9e32e29c3413139db312f360e2d3930ccd8679f8.
---
 .github/workflows/libcxx-build-and-test.yaml | 110 +++++++++++++++++++
 1 file changed, 110 insertions(+)

diff --git a/.github/workflows/libcxx-build-and-test.yaml b/.github/workflows/libcxx-build-and-test.yaml
index 65997d9c1ca411..25e8c8c1ef21aa 100644
--- a/.github/workflows/libcxx-build-and-test.yaml
+++ b/.github/workflows/libcxx-build-and-test.yaml
@@ -48,14 +48,124 @@ env:
 
 
 jobs:
+  stage1:
+    if: github.repository_owner == 'llvm'
+    runs-on: libcxx-runners-8-set
+    continue-on-error: false
+    strategy:
+      fail-fast: false
+      matrix:
+        config: [
+          'generic-cxx03',
+          'generic-cxx26',
+          'generic-modules'
+        ]
+        cc: [  'clang-18' ]
+        cxx: [ 'clang++-18' ]
+        clang_tidy: [ 'ON' ]
+        include:
+          - config: 'generic-gcc'
+            cc: 'gcc-13'
+            cxx: 'g++-13'
+            clang_tidy: 'OFF'
+    steps:
+      - uses: actions/checkout at v4
+      - name: ${{ matrix.config }}.${{ matrix.cxx }}
+        run: libcxx/utils/ci/run-buildbot ${{ matrix.config }}
+        env:
+          CC: ${{ matrix.cc }}
+          CXX: ${{ matrix.cxx }}
+          ENABLE_CLANG_TIDY: ${{ matrix.clang_tidy }}
+      - uses: actions/upload-artifact at v3
+        if: always()
+        with:
+          name: ${{ matrix.config }}-${{ matrix.cxx }}-results
+          path: |
+            **/test-results.xml
+            **/*.abilist
+            **/CMakeError.log
+            **/CMakeOutput.log
+            **/crash_diagnostics/*
+  stage2:
+    if: github.repository_owner == 'llvm'
+    runs-on: libcxx-runners-8-set
+    needs: [ stage1 ]
+    continue-on-error: false
+    strategy:
+      fail-fast: false
+      matrix:
+        config: [
+          'generic-cxx11',
+          'generic-cxx14',
+          'generic-cxx17',
+          'generic-cxx20',
+          'generic-cxx23'
+        ]
+        cc: [ 'clang-18' ]
+        cxx: [ 'clang++-18' ]
+        clang_tidy: [ 'ON' ]
+        include:
+          - config: 'generic-gcc-cxx11'
+            cc: 'gcc-13'
+            cxx: 'g++-13'
+            clang_tidy: 'OFF'
+          - config: 'generic-cxx23'
+            cc: 'clang-16'
+            cxx: 'clang++-16'
+            clang_tidy: 'OFF'
+          - config: 'generic-cxx23'
+            cc: 'clang-17'
+            cxx: 'clang++-17'
+            clang_tidy: 'OFF'
+    steps:
+      - uses: actions/checkout at v4
+      - name: ${{ matrix.config }}
+        run: libcxx/utils/ci/run-buildbot ${{ matrix.config }}
+        env:
+          CC: ${{ matrix.cc }}
+          CXX: ${{ matrix.cxx }}
+          ENABLE_CLANG_TIDY: ${{ matrix.clang_tidy }}
+      - uses: actions/upload-artifact at v3
+        if: always()  # Upload artifacts even if the build or test suite fails
+        with:
+          name: ${{ matrix.config }}-results
+          path: |
+            **/test-results.xml
+            **/*.abilist
+            **/CMakeError.log
+            **/CMakeOutput.log
+            **/crash_diagnostics/*
   stage3:
     if: github.repository_owner == 'llvm'
+    needs: [ stage1, stage2 ]
     continue-on-error: false
     strategy:
       fail-fast: false
       max-parallel: 8
       matrix:
         config: [
+          'generic-abi-unstable',
+          'generic-hardening-mode-debug',
+          'generic-hardening-mode-extensive',
+          'generic-hardening-mode-fast',
+          'generic-hardening-mode-fast-with-abi-breaks',
+          'generic-merged',
+          'generic-modules-lsv',
+          'generic-no-exceptions',
+          'generic-no-experimental',
+          'generic-no-filesystem',
+          'generic-no-localization',
+          'generic-no-random_device',
+          'generic-no-threads',
+          'generic-no-tzdb',
+          'generic-no-unicode',
+          'generic-no-wide-characters',
+          'generic-no-rtti',
+          'generic-static',
+          'generic-with_llvm_unwinder',
+          # TODO Find a better place for the benchmark and bootstrapping builds to live. They're either very expensive
+          # or don't provide much value since the benchmark run results are too noise on the bots.
+          'benchmarks',
           'bootstrapping-build'
         ]
         machine: [ 'libcxx-runners-8-set' ]

>From 7549e6c4cf48934bde3d25ea366eb01936f4621b Mon Sep 17 00:00:00 2001
From: Mark de Wever <koraq at xs4all.nl>
Date: Wed, 3 Jan 2024 19:32:36 +0100
Subject: [PATCH 4/4] Revert the tests and disable them temporary for clang-18.

---
 .../transform_error.mandates.verify.cpp         | 17 +++++++++++++++++
 .../transform_error.mandates.verify.cpp         | 17 +++++++++++++++++
 2 files changed, 34 insertions(+)

diff --git a/libcxx/test/libcxx/utilities/expected/expected.expected/transform_error.mandates.verify.cpp b/libcxx/test/libcxx/utilities/expected/expected.expected/transform_error.mandates.verify.cpp
index 3260a8cbc7f8e6..318435660c3652 100644
--- a/libcxx/test/libcxx/utilities/expected/expected.expected/transform_error.mandates.verify.cpp
+++ b/libcxx/test/libcxx/utilities/expected/expected.expected/transform_error.mandates.verify.cpp
@@ -6,6 +6,15 @@
 //
 //===----------------------------------------------------------------------===//
 
+// https://github.com/llvm/llvm-project/pull/76232 breaks this libc++ test.
+// The fix would be to update this file. The issue is that the CI uses 2
+// versions of Clang-18
+// - An older nightly build as the main compiler
+// - A freshly bootstrap build
+// This means the test can't be used until the nightly build is updated.
+// TODO(mordante) Reenable clang-18.
+// UNSUPPORTED: clang-18
+
 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
 
 // Test the mandates
@@ -46,9 +55,11 @@ void test() {
   {
     std::expected<int, int> e;
     e.transform_error(return_unexpected<int&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
+    // expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
     // expected-error-re@*:* {{static assertion failed {{.*}}[expected.object.general] A program that instantiates the definition of template expected<T, E> for {{.*}} is ill-formed.}}
 
     e.transform_error(return_no_object<int&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
+    // expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
     // expected-error-re@*:* {{static assertion failed {{.*}}[expected.object.general] A program that instantiates the definition of template expected<T, E> for {{.*}} is ill-formed.}}
   }
 
@@ -56,21 +67,27 @@ void test() {
   {
     const std::expected<int, int> e;
     e.transform_error(return_unexpected<const int &>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
+    // expected-error-re@*:* 2 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
     e.transform_error(return_no_object<const int &>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
+    // expected-error-re@*:* 2 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
   }
 
   // Test && overload
   {
     std::expected<int, int> e;
     std::move(e).transform_error(return_unexpected<int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
+    // expected-error-re@*:* 2 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
     std::move(e).transform_error(return_no_object<int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
+    // expected-error-re@*:* 2 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
   }
 
   // Test const&& overload
   {
     const std::expected<int, int> e;
     std::move(e).transform_error(return_unexpected<const int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
+    // expected-error-re@*:* 2 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
     std::move(e).transform_error(return_no_object<const int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
+    // expected-error-re@*:* 2 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
   }
 }
 // clang-format on
diff --git a/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp b/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp
index 21dc2476879186..d9f65e9f5919cd 100644
--- a/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp
+++ b/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp
@@ -6,6 +6,15 @@
 //
 //===----------------------------------------------------------------------===//
 
+// https://github.com/llvm/llvm-project/pull/76232 breaks this libc++ test.
+// The fix would be to update this file. The issue is that the CI uses 2
+// versions of Clang-18
+// - An older nightly build as the main compiler
+// - A freshly bootstrap build
+// This means the test can't be used until the nightly build is updated.
+// TODO(mordante) Reenable clang-18.
+// UNSUPPORTED: clang-18
+
 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
 
 // Test the mandates
@@ -46,9 +55,11 @@ void test() {
   {
     std::expected<void, int> e;
     e.transform_error(return_unexpected<int&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
+    // expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
     // expected-error-re@*:* {{static assertion failed {{.*}}A program that instantiates expected<T, E> with a E that is not a valid argument for unexpected<E> is ill-formed}}
 
     e.transform_error(return_no_object<int&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
+    // expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
     // expected-error-re@*:* {{static assertion failed {{.*}}A program that instantiates expected<T, E> with a E that is not a valid argument for unexpected<E> is ill-formed}}
   }
 
@@ -56,21 +67,27 @@ void test() {
   {
     const std::expected<void, int> e;
     e.transform_error(return_unexpected<const int &>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
+    // expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
     e.transform_error(return_no_object<const int &>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
+    // expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
   }
 
   // Test && overload
   {
     std::expected<void, int> e;
     std::move(e).transform_error(return_unexpected<int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
+    // expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
     std::move(e).transform_error(return_no_object<int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
+    // expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
   }
 
   // Test const&& overload
   {
     const std::expected<void, int> e;
     std::move(e).transform_error(return_unexpected<const int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
+    // expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
     std::move(e).transform_error(return_no_object<const int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
+    // expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
   }
 }
 // clang-format on



More information about the cfe-commits mailing list