Skip to content

[libc++][C++03] Split libc++-specific tests for the frozen headers #144093

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

philnik777
Copy link
Contributor

@philnik777 philnik777 commented Jun 13, 2025

The C++03 headers are essentially a separate implementation, so it doesn't make a ton of sense to try to test two implementations with a single set of implementation-specific tests.

Most of the tests will be removed in a follow-up, since they don't run in C++03 mode. This patch adds them to make as few changes to the copy as possible. The most notable changes are that lit.local.cfg files are touched to change the path from libcxx/test/libcxx to libcxx/test/libcxx-03 in a few places.

This also modifies lit.local.cfg files to run libcxx/test/libcxx-03 only when using the frozen headers and lbcxx/test/libcxx tests only when not using the frozen headers.

This is part of https://discourse.llvm.org/t/rfc-freezing-c-03-headers-in-libc.

@philnik777 philnik777 changed the title [libc++] Split libc++-specific tests for the frozen headers [libc++][C++03] Split libc++-specific tests for the frozen headers Jun 13, 2025
Copy link

github-actions bot commented Jun 13, 2025

⚠️ Python code formatter, darker found issues in your code. ⚠️

You can test this locally with the following command:
darker --check --diff -r HEAD~1...HEAD libcxx/test/libcxx-03/clang_modules_include.gen.py libcxx/test/libcxx-03/clang_tidy.gen.py libcxx/test/libcxx-03/clang_tidy.sh.py libcxx/test/libcxx-03/double_include.gen.py libcxx/test/libcxx-03/feature_test_macro/ftm_metadata.sh.py libcxx/test/libcxx-03/feature_test_macro/generate_header_test.sh.py libcxx/test/libcxx-03/feature_test_macro/implemented_ftms.sh.py libcxx/test/libcxx-03/feature_test_macro/invalid.sh.py libcxx/test/libcxx-03/feature_test_macro/is_implemented.sh.py libcxx/test/libcxx-03/feature_test_macro/standard_ftms.sh.py libcxx/test/libcxx-03/feature_test_macro/standard_library_headers.sh.py libcxx/test/libcxx-03/feature_test_macro/std_dialects.sh.py libcxx/test/libcxx-03/feature_test_macro/version_header.sh.py libcxx/test/libcxx-03/feature_test_macro/version_header_implementation.sh.py libcxx/test/libcxx-03/gdb/gdb_pretty_printer_test.py libcxx/test/libcxx-03/header_inclusions.gen.py libcxx/test/libcxx-03/headers_in_modulemap.sh.py libcxx/test/libcxx-03/libcpp_version.gen.py libcxx/test/libcxx-03/lint/lint_cmakelists.sh.py libcxx/test/libcxx-03/lint/lint_headers.sh.py libcxx/test/libcxx-03/module_std.gen.py libcxx/test/libcxx-03/module_std_compat.gen.py libcxx/test/libcxx-03/no_assert_include.gen.py libcxx/test/libcxx-03/selftest/dsl/dsl.sh.py libcxx/test/libcxx-03/system_reserved_names.gen.py libcxx/test/libcxx-03/transitive_includes.gen.py libcxx/test/libcxx-03/transitive_includes/to_csv.py libcxx/test/libcxx-03/xopen_source.gen.py
View the diff from darker here.
--- clang_modules_include.gen.py	2025-06-18 17:34:03.000000 +0000
+++ clang_modules_include.gen.py	2025-06-18 17:36:00.359267 +0000
@@ -14,10 +14,11 @@
 
 # block Lit from interpreting a RUN/XFAIL/etc inside the generation script
 # END.
 
 import sys
+
 sys.path.append(sys.argv[1])
 from libcxx.header_information import (
     lit_header_restrictions,
     lit_header_undeprecations,
     public_headers,
--- clang_tidy.gen.py	2025-06-18 17:34:03.000000 +0000
+++ clang_tidy.gen.py	2025-06-18 17:36:00.367798 +0000
@@ -13,15 +13,21 @@
 
 # block Lit from interpreting a RUN/XFAIL/etc inside the generation script
 # END.
 
 import sys
+
 sys.path.append(sys.argv[1])
-from libcxx.header_information import lit_header_restrictions, lit_header_undeprecations, public_headers
+from libcxx.header_information import (
+    lit_header_restrictions,
+    lit_header_undeprecations,
+    public_headers,
+)
 
 for header in public_headers:
-  print(f"""\
+    print(
+        f"""\
 //--- {header}.sh.cpp
 
 // REQUIRES: has-clang-tidy
 
 // The frozen headers should not be updated to the latest libc++ style, so don't test.
@@ -35,6 +41,7 @@
 
 // TODO: run clang-tidy with modules enabled once they are supported
 // RUN: %{{clang-tidy}} %s --warnings-as-errors=* -header-filter=.* --config-file=%{{libcxx-dir}}/.clang-tidy --load=%{{test-tools-dir}}/clang_tidy_checks/libcxx-tidy.plugin -- -Wweak-vtables %{{compile_flags}} -fno-modules
 
 #include <{header}>
-""")
+"""
+    )
--- double_include.gen.py	2025-06-18 17:34:03.000000 +0000
+++ double_include.gen.py	2025-06-18 17:36:00.381337 +0000
@@ -12,10 +12,11 @@
 
 # Block Lit from interpreting a RUN/XFAIL/etc inside the generation script.
 # END.
 
 import sys
+
 sys.path.append(sys.argv[1])
 from libcxx.header_information import (
     lit_header_restrictions,
     lit_header_undeprecations,
     public_headers,
--- feature_test_macro/implemented_ftms.sh.py	2025-06-18 17:34:03.000000 +0000
+++ feature_test_macro/implemented_ftms.sh.py	2025-06-18 17:36:00.433084 +0000
@@ -23,11 +23,10 @@
     def setUp(self):
         self.ftm = FeatureTestMacros(TEST_DATA, ["charconv"])
         self.maxDiff = None  # This causes the diff to be printed when the test fails
 
     def test_implementation(self):
-
         expected = {
             "__cpp_lib_any": {
                 "c++17": "201606L",
                 "c++20": "201606L",
                 "c++23": "201606L",
--- headers_in_modulemap.sh.py	2025-06-18 17:34:03.000000 +0000
+++ headers_in_modulemap.sh.py	2025-06-18 17:36:00.570755 +0000
@@ -1,8 +1,9 @@
 # RUN: %{python} %s %{libcxx-dir}/utils
 
 import sys
+
 sys.path.append(sys.argv[1])
 from libcxx.header_information import all_headers, libcxx_include
 
 with open(libcxx_include / "module.modulemap.in") as f:
     modulemap = f.read()
--- libcpp_version.gen.py	2025-06-18 17:34:03.000000 +0000
+++ libcpp_version.gen.py	2025-06-18 17:36:00.578918 +0000
@@ -9,10 +9,11 @@
 # Test that all headers define the _LIBCPP_VERSION macro.
 
 # RUN: %{python} %s %{libcxx-dir}/utils
 
 import sys
+
 sys.path.append(sys.argv[1])
 from libcxx.header_information import (
     lit_header_restrictions,
     lit_header_undeprecations,
     public_headers,
--- selftest/dsl/dsl.sh.py	2025-06-18 17:34:03.000000 +0000
+++ selftest/dsl/dsl.sh.py	2025-06-18 17:36:00.812257 +0000
@@ -308,11 +308,11 @@
 
     def test_basic(self):
         macros = dsl.compilerMacros(self.config)
         self.assertIsInstance(macros, dict)
         self.assertGreater(len(macros), 0)
-        for (k, v) in macros.items():
+        for k, v in macros.items():
             self.assertIsInstance(k, str)
             self.assertIsInstance(v, str)
 
     def test_no_flag(self):
         macros = dsl.compilerMacros(self.config)
@@ -341,11 +341,11 @@
 
     def test_basic(self):
         macros = dsl.featureTestMacros(self.config)
         self.assertIsInstance(macros, dict)
         self.assertGreater(len(macros), 0)
-        for (k, v) in macros.items():
+        for k, v in macros.items():
             self.assertIsInstance(k, str)
             self.assertIsInstance(v, int)
 
 
 class TestFeature(SetupConfigs):
--- transitive_includes/to_csv.py	2025-06-18 17:34:03.000000 +0000
+++ transitive_includes/to_csv.py	2025-06-18 17:36:00.863352 +0000
@@ -14,13 +14,16 @@
 import os
 import pathlib
 import re
 import sys
 
-libcxx_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
+libcxx_root = os.path.dirname(
+    os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+)
 sys.path.append(os.path.join(libcxx_root, "utils"))
 from libcxx.header_information import Header
+
 
 def parse_line(line: str) -> Tuple[int, str]:
     """
     Parse a single line of --trace-includes output.
 
@@ -31,10 +34,11 @@
         raise ArgumentError(f"Line {line} contains invalid data.")
 
     # The number of periods in front of the header name is the nesting level of
     # that header.
     return (len(match.group(1)), match.group(2))
+
 
 def make_cxx_v1_relative(header: str) -> Optional[str]:
     """
     Returns the path of the header as relative to <whatever>/c++/v1, or None if the path
     doesn't contain c++/v1.
@@ -51,10 +55,11 @@
     match = re.match(CXX_V1_REGEX, header)
     if not match:
         return None
     else:
         return match.group(1)
+
 
 def parse_file(file: io.TextIOBase) -> List[Tuple[Header, Header]]:
     """
     Parse a file containing --trace-includes output to generate a list of the
     transitive includes contained in it.
@@ -79,25 +84,27 @@
         else:
             assert includer is not None
             result.append((includer, Header(relative)))
     return result
 
+
 def print_csv(includes: List[Tuple[Header, Header]]) -> None:
     """
     Print the transitive includes as space-delimited CSV.
 
     This function only prints public libc++ headers that are not C compatibility headers.
     """
     # Sort and group by includer
     by_includer = lambda t: t[0]
     includes = itertools.groupby(sorted(includes, key=by_includer), key=by_includer)
 
-    for (includer, includees) in includes:
+    for includer, includees in includes:
         includees = map(lambda t: t[1], includees)
         for h in sorted(set(includees)):
             if h.is_public() and not h.is_C_compatibility():
                 print(f"{includer} {h}")
+
 
 def main(argv):
     parser = argparse.ArgumentParser(
         description="""
         Given a list of headers produced by --trace-includes, produce a list of libc++ headers in that output.
@@ -106,15 +113,22 @@
         information for this script to run.
 
         The output of this script is provided in space-delimited CSV format where each line contains:
 
             <header performing inclusion> <header being included>
-        """)
-    parser.add_argument("inputs", type=argparse.FileType("r"), nargs='+', default=None,
-        help="One or more files containing the result of --trace-includes")
+        """
+    )
+    parser.add_argument(
+        "inputs",
+        type=argparse.FileType("r"),
+        nargs="+",
+        default=None,
+        help="One or more files containing the result of --trace-includes",
+    )
     args = parser.parse_args(argv)
 
     includes = [line for file in args.inputs for line in parse_file(file)]
     print_csv(includes)
 
+
 if __name__ == "__main__":
     main(sys.argv[1:])
--- transitive_includes.gen.py	2025-06-18 17:34:03.000000 +0000
+++ transitive_includes.gen.py	2025-06-18 17:36:00.880194 +0000
@@ -20,10 +20,11 @@
 
 # block Lit from interpreting a RUN/XFAIL/etc inside the generation script
 # END.
 
 import sys
+
 sys.path.append(sys.argv[1])
 from libcxx.header_information import lit_header_restrictions, public_headers
 
 import re
 

@philnik777 philnik777 marked this pull request as ready for review June 14, 2025 16:38
@philnik777 philnik777 requested a review from a team as a code owner June 14, 2025 16:38
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Jun 14, 2025
@llvmbot
Copy link
Member

llvmbot commented Jun 14, 2025

@llvm/pr-subscribers-libcxx

Author: Nikolas Klauser (philnik777)

Changes

The C++03 headers are essentially a separate implementation, so it doesn't make a ton of sense to try to test two implementations with a single set of implementation-specific tests.

Most of the tests will be removed in a follow-up, since they don't run in C++03 mode. This patch adds them to make as few changes to the copy as possible. The most notable changes are that lit.local.cfg files are touched to change the path from libcxx/test/libcxx to libcxx/test/libcxx-03 in a few places.

This also modifies lit.local.cfg files to run libcxx/test/libcxx-03 only when using the frozen headers and lbcxx/test/libcxx tests only when not using the frozen headers.

This is part of https://discourse.llvm.org/t/rfc-freezing-c-03-headers-in-libc.


Patch is 2.92 MiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/144093.diff

921 Files Affected:

  • (added) libcxx/test/libcxx-03/Wnon_modular_include_in_module.compile.pass.cpp (+21)
  • (added) libcxx/test/libcxx-03/algorithms/alg.modifying.operations/alg.random.shuffle/random_shuffle.cxx1z.pass.cpp (+51)
  • (added) libcxx/test/libcxx-03/algorithms/alg.modifying.operations/alg.random.shuffle/random_shuffle.depr_in_cxx14.verify.cpp (+43)
  • (added) libcxx/test/libcxx-03/algorithms/alg.modifying.operations/copy_move_nontrivial.pass.cpp (+331)
  • (added) libcxx/test/libcxx-03/algorithms/alg.modifying.operations/copy_move_trivial.pass.cpp (+334)
  • (added) libcxx/test/libcxx-03/algorithms/alg.modifying.operations/copy_move_unwrap_reverse.pass.cpp (+141)
  • (added) libcxx/test/libcxx-03/algorithms/alg.sorting/alg.heap.operations/make.heap/complexity.pass.cpp (+75)
  • (added) libcxx/test/libcxx-03/algorithms/alg.sorting/assert.min.max.pass.cpp (+30)
  • (added) libcxx/test/libcxx-03/algorithms/alg.sorting/assert.sort.invalid_comparator/assert.sort.invalid_comparator.oob.pass.cpp (+72)
  • (added) libcxx/test/libcxx-03/algorithms/alg.sorting/assert.sort.invalid_comparator/assert.sort.invalid_comparator.pass.cpp (+195)
  • (added) libcxx/test/libcxx-03/algorithms/alg.sorting/assert.sort.invalid_comparator/bad_comparator_values.h (+3565)
  • (added) libcxx/test/libcxx-03/algorithms/alg.sorting/assert.sort.invalid_comparator/invalid_comparator_utilities.h (+85)
  • (added) libcxx/test/libcxx-03/algorithms/alg.sorting/pstl.is_partitioned.pass.cpp (+31)
  • (added) libcxx/test/libcxx-03/algorithms/bad_iterator_traits.verify.cpp (+61)
  • (added) libcxx/test/libcxx-03/algorithms/callable-requirements-rvalue.compile.pass.cpp (+46)
  • (added) libcxx/test/libcxx-03/algorithms/callable-requirements.verify.cpp (+118)
  • (added) libcxx/test/libcxx-03/algorithms/cpp17_iterator_concepts.verify.cpp (+425)
  • (added) libcxx/test/libcxx-03/algorithms/debug_less.inconsistent.pass.cpp (+52)
  • (added) libcxx/test/libcxx-03/algorithms/debug_less.pass.cpp (+260)
  • (added) libcxx/test/libcxx-03/algorithms/debug_three_way_comp.inconsistent.pass.cpp (+56)
  • (added) libcxx/test/libcxx-03/algorithms/half_positive.pass.cpp (+59)
  • (added) libcxx/test/libcxx-03/algorithms/lifetimebound.verify.cpp (+81)
  • (added) libcxx/test/libcxx-03/algorithms/no_specializations.verify.cpp (+28)
  • (added) libcxx/test/libcxx-03/algorithms/nth_element_stability.pass.cpp (+101)
  • (added) libcxx/test/libcxx-03/algorithms/partial_sort_stability.pass.cpp (+102)
  • (added) libcxx/test/libcxx-03/algorithms/pstl.iterator-requirements.verify.cpp (+193)
  • (added) libcxx/test/libcxx-03/algorithms/pstl.libdispatch.chunk_partitions.pass.cpp (+41)
  • (added) libcxx/test/libcxx-03/algorithms/ranges_robust_against_copying_comparators.pass.cpp (+264)
  • (added) libcxx/test/libcxx-03/algorithms/ranges_robust_against_copying_projections.pass.cpp (+278)
  • (added) libcxx/test/libcxx-03/algorithms/robust_against_copying_comparators.pass.cpp (+323)
  • (added) libcxx/test/libcxx-03/algorithms/robust_against_cpp20_hostile_iterators.compile.pass.cpp (+225)
  • (added) libcxx/test/libcxx-03/algorithms/robust_against_using_non_transparent_comparators.pass.cpp (+80)
  • (added) libcxx/test/libcxx-03/algorithms/sort_stability.pass.cpp (+100)
  • (added) libcxx/test/libcxx-03/algorithms/specialized.algorithms/special.mem.concepts/nothrow_forward_iterator.compile.pass.cpp (+27)
  • (added) libcxx/test/libcxx-03/algorithms/specialized.algorithms/special.mem.concepts/nothrow_forward_range.compile.pass.cpp (+29)
  • (added) libcxx/test/libcxx-03/algorithms/specialized.algorithms/special.mem.concepts/nothrow_input_iterator.compile.pass.cpp (+30)
  • (added) libcxx/test/libcxx-03/algorithms/specialized.algorithms/special.mem.concepts/nothrow_input_range.compile.pass.cpp (+32)
  • (added) libcxx/test/libcxx-03/algorithms/specialized.algorithms/special.mem.concepts/nothrow_sentinel_for.compile.pass.cpp (+35)
  • (added) libcxx/test/libcxx-03/algorithms/vectorization.compile.pass.cpp (+34)
  • (added) libcxx/test/libcxx-03/assertions/customize_verbose_abort.compile-time.pass.cpp (+27)
  • (added) libcxx/test/libcxx-03/assertions/customize_verbose_abort.link-time.pass.cpp (+25)
  • (added) libcxx/test/libcxx-03/assertions/default_verbose_abort.pass.cpp (+28)
  • (added) libcxx/test/libcxx-03/assertions/modes/debug.pass.cpp (+26)
  • (added) libcxx/test/libcxx-03/assertions/modes/extensive.pass.cpp (+26)
  • (added) libcxx/test/libcxx-03/assertions/modes/fast.pass.cpp (+26)
  • (added) libcxx/test/libcxx-03/assertions/modes/hardening_mode_incorrect_value.sh.cpp (+26)
  • (added) libcxx/test/libcxx-03/assertions/modes/none.pass.cpp (+32)
  • (added) libcxx/test/libcxx-03/assertions/modes/override_with_debug_mode.pass.cpp (+27)
  • (added) libcxx/test/libcxx-03/assertions/modes/override_with_extensive_mode.pass.cpp (+32)
  • (added) libcxx/test/libcxx-03/assertions/modes/override_with_fast_mode.pass.cpp (+31)
  • (added) libcxx/test/libcxx-03/assertions/modes/override_with_unchecked_mode.pass.cpp (+24)
  • (added) libcxx/test/libcxx-03/assertions/single_expression.pass.cpp (+34)
  • (added) libcxx/test/libcxx-03/atomics/atomics.align/align.pass.cpp (+113)
  • (added) libcxx/test/libcxx-03/atomics/atomics.flag/init_bool.pass.cpp (+43)
  • (added) libcxx/test/libcxx-03/atomics/atomics.order/memory_order.underlying_type.pass.cpp (+34)
  • (added) libcxx/test/libcxx-03/atomics/atomics.ref/assert.compare_exchange_strong.pass.cpp (+59)
  • (added) libcxx/test/libcxx-03/atomics/atomics.ref/assert.compare_exchange_weak.pass.cpp (+59)
  • (added) libcxx/test/libcxx-03/atomics/atomics.ref/assert.ctor.pass.cpp (+41)
  • (added) libcxx/test/libcxx-03/atomics/atomics.ref/assert.load.pass.cpp (+56)
  • (added) libcxx/test/libcxx-03/atomics/atomics.ref/assert.store.pass.cpp (+64)
  • (added) libcxx/test/libcxx-03/atomics/atomics.ref/assert.wait.pass.cpp (+56)
  • (added) libcxx/test/libcxx-03/atomics/atomics.ref/compare_exchange_strong.verify.cpp (+39)
  • (added) libcxx/test/libcxx-03/atomics/atomics.ref/compare_exchange_weak.verify.cpp (+39)
  • (added) libcxx/test/libcxx-03/atomics/atomics.ref/load.verify.cpp (+34)
  • (added) libcxx/test/libcxx-03/atomics/atomics.ref/store.verify.cpp (+36)
  • (added) libcxx/test/libcxx-03/atomics/atomics.ref/wait.verify.cpp (+36)
  • (added) libcxx/test/libcxx-03/atomics/atomics.syn/compatible_with_stdatomic.compile.pass.cpp (+23)
  • (added) libcxx/test/libcxx-03/atomics/atomics.syn/incompatible_with_stdatomic.verify.cpp (+25)
  • (added) libcxx/test/libcxx-03/atomics/atomics.syn/wait.issue_85107.pass.cpp (+54)
  • (added) libcxx/test/libcxx-03/atomics/atomics.types.generic/atomics.types.float/lockfree.pass.cpp (+51)
  • (added) libcxx/test/libcxx-03/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_add.verify.cpp (+76)
  • (added) libcxx/test/libcxx-03/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_add_explicit.verify.cpp (+79)
  • (added) libcxx/test/libcxx-03/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_sub.verify.cpp (+76)
  • (added) libcxx/test/libcxx-03/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_sub_explicit.verify.cpp (+79)
  • (added) libcxx/test/libcxx-03/atomics/bit-int.verify.cpp (+22)
  • (added) libcxx/test/libcxx-03/atomics/diagnose_invalid_memory_order.verify.cpp (+122)
  • (added) libcxx/test/libcxx-03/atomics/stdatomic.h.syn/dont_hijack_header.compile.pass.cpp (+24)
  • (added) libcxx/test/libcxx-03/atomics/stdatomic.h.syn/dont_hijack_header.cxx23.compile.pass.cpp (+28)
  • (added) libcxx/test/libcxx-03/clang_modules_include.gen.py (+97)
  • (added) libcxx/test/libcxx-03/clang_tidy.gen.py (+40)
  • (added) libcxx/test/libcxx-03/clang_tidy.sh.py (+11)
  • (added) libcxx/test/libcxx-03/concepts/concepts.arithmetic/__libcpp_integer.compile.pass.cpp (+63)
  • (added) libcxx/test/libcxx-03/concepts/concepts.arithmetic/__libcpp_signed_integer.compile.pass.cpp (+63)
  • (added) libcxx/test/libcxx-03/concepts/concepts.arithmetic/__libcpp_unsigned_integer.compile.pass.cpp (+63)
  • (added) libcxx/test/libcxx-03/containers/associative/map/at.abort.pass.cpp (+33)
  • (added) libcxx/test/libcxx-03/containers/associative/map/at.const.abort.pass.cpp (+33)
  • (added) libcxx/test/libcxx-03/containers/associative/map/find.modules.compile.pass.mm (+16)
  • (added) libcxx/test/libcxx-03/containers/associative/map/scary.compile.pass.cpp (+26)
  • (added) libcxx/test/libcxx-03/containers/associative/non_const_comparator.incomplete.verify.cpp (+56)
  • (added) libcxx/test/libcxx-03/containers/associative/non_const_comparator.verify.cpp (+48)
  • (added) libcxx/test/libcxx-03/containers/associative/reference_comparator_abi.compile.pass.cpp (+57)
  • (added) libcxx/test/libcxx-03/containers/associative/set/scary.compile.pass.cpp (+26)
  • (added) libcxx/test/libcxx-03/containers/associative/tree_balance_after_insert.pass.cpp (+1612)
  • (added) libcxx/test/libcxx-03/containers/associative/tree_key_value_traits.pass.cpp (+56)
  • (added) libcxx/test/libcxx-03/containers/associative/tree_left_rotate.pass.cpp (+100)
  • (added) libcxx/test/libcxx-03/containers/associative/tree_remove.pass.cpp (+1646)
  • (added) libcxx/test/libcxx-03/containers/associative/tree_right_rotate.pass.cpp (+100)
  • (added) libcxx/test/libcxx-03/containers/associative/unord.map/abi.compile.pass.cpp (+141)
  • (added) libcxx/test/libcxx-03/containers/associative/unord.map/scary.compile.pass.cpp (+28)
  • (added) libcxx/test/libcxx-03/containers/associative/unord.set/abi.compile.pass.cpp (+139)
  • (added) libcxx/test/libcxx-03/containers/associative/unord.set/scary.compile.pass.cpp (+28)
  • (added) libcxx/test/libcxx-03/containers/container.adaptors/flat.map/assert.input_range.pass.cpp (+66)
  • (added) libcxx/test/libcxx-03/containers/container.adaptors/flat.map/assert.sorted_unique.pass.cpp (+225)
  • (added) libcxx/test/libcxx-03/containers/container.adaptors/flat.map/scary.compile.pass.cpp (+33)
  • (added) libcxx/test/libcxx-03/containers/container.adaptors/flat.multimap/assert.input_range.pass.cpp (+66)
  • (added) libcxx/test/libcxx-03/containers/container.adaptors/flat.multimap/assert.sorted_equivalent.pass.cpp (+225)
  • (added) libcxx/test/libcxx-03/containers/container.adaptors/flat.multiset/assert.sorted_unique.pass.cpp (+131)
  • (added) libcxx/test/libcxx-03/containers/container.adaptors/flat.multiset/insert.temporary.pass.cpp (+48)
  • (added) libcxx/test/libcxx-03/containers/container.adaptors/flat.multiset/insert_range.pass.cpp (+46)
  • (added) libcxx/test/libcxx-03/containers/container.adaptors/flat.multiset/iterator.compile.pass.cpp (+42)
  • (added) libcxx/test/libcxx-03/containers/container.adaptors/flat.set/assert.sorted_unique.pass.cpp (+226)
  • (added) libcxx/test/libcxx-03/containers/container.adaptors/flat.set/insert.temporary.pass.cpp (+48)
  • (added) libcxx/test/libcxx-03/containers/container.adaptors/flat.set/insert_range.pass.cpp (+46)
  • (added) libcxx/test/libcxx-03/containers/container.adaptors/flat.set/iterator.compile.pass.cpp (+42)
  • (added) libcxx/test/libcxx-03/containers/container.adaptors/flat.set/scary.compile.pass.cpp (+33)
  • (added) libcxx/test/libcxx-03/containers/container.adaptors/flat_helpers.h (+48)
  • (added) libcxx/test/libcxx-03/containers/container_traits.compile.pass.cpp (+165)
  • (added) libcxx/test/libcxx-03/containers/gnu_cxx/hash_map.pass.cpp (+36)
  • (added) libcxx/test/libcxx-03/containers/gnu_cxx/hash_map_name_lookup.pass.cpp (+36)
  • (added) libcxx/test/libcxx-03/containers/gnu_cxx/hash_set.pass.cpp (+36)
  • (added) libcxx/test/libcxx-03/containers/gnu_cxx/hash_set_name_lookup.pass.cpp (+36)
  • (added) libcxx/test/libcxx-03/containers/sequences/array/triviality.pass.cpp (+51)
  • (added) libcxx/test/libcxx-03/containers/sequences/deque/abi.compile.pass.cpp (+117)
  • (added) libcxx/test/libcxx-03/containers/sequences/deque/asan.pass.cpp (+68)
  • (added) libcxx/test/libcxx-03/containers/sequences/deque/asan_caterpillar.pass.cpp (+53)
  • (added) libcxx/test/libcxx-03/containers/sequences/deque/asan_turning_off.pass.cpp (+77)
  • (added) libcxx/test/libcxx-03/containers/sequences/deque/assert.pass.cpp (+56)
  • (added) libcxx/test/libcxx-03/containers/sequences/deque/assert.pop_back.empty.pass.cpp (+29)
  • (added) libcxx/test/libcxx-03/containers/sequences/deque/incomplete.pass.cpp (+34)
  • (added) libcxx/test/libcxx-03/containers/sequences/deque/segmented_iterator.compile.pass.cpp (+12)
  • (added) libcxx/test/libcxx-03/containers/sequences/deque/spare_block_handling.pass.cpp (+288)
  • (added) libcxx/test/libcxx-03/containers/sequences/forwardlist/assert.pass.cpp (+47)
  • (added) libcxx/test/libcxx-03/containers/sequences/forwardlist/bool-conversion.pass.cpp (+37)
  • (added) libcxx/test/libcxx-03/containers/sequences/list/abi.compile.pass.cpp (+87)
  • (added) libcxx/test/libcxx-03/containers/sequences/list/list.cons/debug.copy.pass.cpp (+30)
  • (added) libcxx/test/libcxx-03/containers/sequences/list/list.modifiers/assert.erase_iter.end.pass.cpp (+29)
  • (added) libcxx/test/libcxx-03/containers/sequences/list/list.modifiers/assert.pop_back.empty.pass.cpp (+35)
  • (added) libcxx/test/libcxx-03/containers/sequences/list/list.modifiers/bool-conversion.pass.cpp (+37)
  • (added) libcxx/test/libcxx-03/containers/sequences/list/list.modifiers/debug.emplace.pass.cpp (+34)
  • (added) libcxx/test/libcxx-03/containers/sequences/list/list.modifiers/debug.erase.iter.pass.cpp (+28)
  • (added) libcxx/test/libcxx-03/containers/sequences/list/list.modifiers/debug.erase.iter_iter.pass.cpp (+57)
  • (added) libcxx/test/libcxx-03/containers/sequences/list/list.modifiers/debug.insert.iter_iter_iter.pass.cpp (+29)
  • (added) libcxx/test/libcxx-03/containers/sequences/list/list.modifiers/debug.insert.iter_rvalue.pass.cpp (+27)
  • (added) libcxx/test/libcxx-03/containers/sequences/list/list.modifiers/debug.insert.iter_size_value.pass.cpp (+27)
  • (added) libcxx/test/libcxx-03/containers/sequences/list/list.modifiers/debug.insert.iter_value.pass.cpp (+28)
  • (added) libcxx/test/libcxx-03/containers/sequences/list/list.ops/debug.splice.pos_list.pass.cpp (+26)
  • (added) libcxx/test/libcxx-03/containers/sequences/list/list.ops/debug.splice.pos_list_iter.pass.cpp (+28)
  • (added) libcxx/test/libcxx-03/containers/sequences/list/list.ops/debug.splice.pos_list_iter_iter.pass.cpp (+28)
  • (added) libcxx/test/libcxx-03/containers/sequences/vector.bool/abi.compile.pass.cpp (+69)
  • (added) libcxx/test/libcxx-03/containers/sequences/vector.bool/assert.pass.cpp (+63)
  • (added) libcxx/test/libcxx-03/containers/sequences/vector.bool/trivial_for_purposes_of_call.pass.cpp (+56)
  • (added) libcxx/test/libcxx-03/containers/sequences/vector/abi.compile.pass.cpp (+95)
  • (added) libcxx/test/libcxx-03/containers/sequences/vector/asan.pass.cpp (+76)
  • (added) libcxx/test/libcxx-03/containers/sequences/vector/asan_throw.pass.cpp (+233)
  • (added) libcxx/test/libcxx-03/containers/sequences/vector/asan_turning_off.pass.cpp (+77)
  • (added) libcxx/test/libcxx-03/containers/sequences/vector/assert.back.empty.pass.cpp (+43)
  • (added) libcxx/test/libcxx-03/containers/sequences/vector/assert.cback.empty.pass.cpp (+39)
  • (added) libcxx/test/libcxx-03/containers/sequences/vector/assert.cfront.empty.pass.cpp (+39)
  • (added) libcxx/test/libcxx-03/containers/sequences/vector/assert.cindex.oob.pass.cpp (+42)
  • (added) libcxx/test/libcxx-03/containers/sequences/vector/assert.front.empty.pass.cpp (+44)
  • (added) libcxx/test/libcxx-03/containers/sequences/vector/assert.index.oob.pass.cpp (+42)
  • (added) libcxx/test/libcxx-03/containers/sequences/vector/assert.iterator.add.pass.cpp (+49)
  • (added) libcxx/test/libcxx-03/containers/sequences/vector/assert.iterator.decrement.pass.cpp (+44)
  • (added) libcxx/test/libcxx-03/containers/sequences/vector/assert.iterator.dereference.pass.cpp (+42)
  • (added) libcxx/test/libcxx-03/containers/sequences/vector/assert.iterator.increment.pass.cpp (+47)
  • (added) libcxx/test/libcxx-03/containers/sequences/vector/assert.iterator.index.pass.cpp (+51)
  • (added) libcxx/test/libcxx-03/containers/sequences/vector/assert.pop_back.empty.pass.cpp (+29)
  • (added) libcxx/test/libcxx-03/containers/sequences/vector/debug.iterator.compare.pass.cpp (+39)
  • (added) libcxx/test/libcxx-03/containers/sequences/vector/debug.iterator.subtract.pass.cpp (+39)
  • (added) libcxx/test/libcxx-03/containers/sequences/vector/erase.modules.compile.pass.mm (+16)
  • (added) libcxx/test/libcxx-03/containers/sequences/vector/exception_safety_exceptions_disabled.pass.cpp (+56)
  • (added) libcxx/test/libcxx-03/containers/sequences/vector/fill_to_capacity.h (+24)
  • (added) libcxx/test/libcxx-03/containers/sequences/vector/invalid_allocator.verify.cpp (+29)
  • (added) libcxx/test/libcxx-03/containers/sequences/vector/robust_against_adl.pass.cpp (+54)
  • (added) libcxx/test/libcxx-03/containers/sequences/vector/vector.cons/construct_iter_iter.pass.cpp (+56)
  • (added) libcxx/test/libcxx-03/containers/sequences/vector/vector.cons/construct_iter_iter_alloc.pass.cpp (+59)
  • (added) libcxx/test/libcxx-03/containers/strings/basic.string/asan.pass.cpp (+56)
  • (added) libcxx/test/libcxx-03/containers/strings/basic.string/asan_deque_integration.pass.cpp (+182)
  • (added) libcxx/test/libcxx-03/containers/strings/basic.string/asan_short.pass.cpp (+56)
  • (added) libcxx/test/libcxx-03/containers/strings/basic.string/asan_turning_off.pass.cpp (+102)
  • (added) libcxx/test/libcxx-03/containers/strings/basic.string/asan_vector_integration.pass.cpp (+182)
  • (added) libcxx/test/libcxx-03/containers/unord/key_value_traits.pass.cpp (+60)
  • (added) libcxx/test/libcxx-03/containers/unord/next_pow2.pass.cpp (+78)
  • (added) libcxx/test/libcxx-03/containers/unord/next_prime.pass.cpp (+51)
  • (added) libcxx/test/libcxx-03/containers/unord/non_const_comparator.incomplete.verify.cpp (+58)
  • (added) libcxx/test/libcxx-03/containers/unord/non_const_comparator.verify.cpp (+58)
  • (added) libcxx/test/libcxx-03/containers/unord/unord.map/assert.bucket.pass.cpp (+29)
  • (added) libcxx/test/libcxx-03/containers/unord/unord.map/assert.bucket_size.pass.cpp (+33)
  • (added) libcxx/test/libcxx-03/containers/unord/unord.map/assert.iterator.dereference.pass.cpp (+52)
  • (added) libcxx/test/libcxx-03/containers/unord/unord.map/assert.iterator.increment.pass.cpp (+59)
  • (added) libcxx/test/libcxx-03/containers/unord/unord.map/assert.local_iterator.dereference.pass.cpp (+50)
  • (added) libcxx/test/libcxx-03/containers/unord/unord.map/assert.local_iterator.increment.pass.cpp (+66)
  • (added) libcxx/test/libcxx-03/containers/unord/unord.map/assert.max_load_factor.pass.cpp (+34)
  • (added) libcxx/test/libcxx-03/containers/unord/unord.map/at.abort.pass.cpp (+32)
  • (added) libcxx/test/libcxx-03/containers/unord/unord.map/at.const.abort.pass.cpp (+32)
  • (added) libcxx/test/libcxx-03/containers/unord/unord.map/debug.insert.hint_const_lvalue.pass.cpp (+41)
  • (added) libcxx/test/libcxx-03/containers/unord/unord.map/debug.insert.hint_rvalue.pass.cpp (+35)
  • (added) libcxx/test/libcxx-03/containers/unord/unord.map/debug.swap.pass.cpp (+38)
  • (added) libcxx/test/libcxx-03/containers/unord/unord.map/unord.map.modifiers/debug.erase.iter.pass.cpp (+43)
  • (added) libcxx/test/libcxx-03/containers/unord/unord.map/unord.map.modifiers/debug.erase.iter_iter.pass.cpp (+64)
  • (added) libcxx/test/libcxx-03/containers/unord/unord.multimap/assert.bucket.pass.cpp (+33)
  • (added) libcxx/test/libcxx-03/containers/unord/unord.multimap/assert.bucket_size.pass.cpp (+33)
  • (added) libcxx/test/libcxx-03/containers/unord/unord.multimap/assert.iterator.dereference.pass.cpp (+52)
  • (added) libcxx/test/libcxx-03/containers/unord/unord.multimap/assert.iterator.increment.pass.cpp (+59)
  • (added) libcxx/test/libcxx-03/containers/unord/unord.multimap/assert.local_iterator.dereference.pass.cpp (+50)
  • (added) libcxx/test/libcxx-03/containers/unord/unord.multimap/assert.local_iterator.increment.pass.cpp (+67)
  • (added) libcxx/test/libcxx-03/containers/unord/unord.multimap/assert.max_load_factor.pass.cpp (+34)
  • (added) libcxx/test/libcxx-03/containers/unord/unord.multimap/debug.insert.hint_const_lvalue.pass.cpp (+33)
  • (added) libcxx/test/libcxx-03/containers/unord/unord.multimap/debug.insert.hint_rvalue.pass.cpp (+34)
  • (added) libcxx/test/libcxx-03/containers/unord/unord.multimap/debug.swap.pass.cpp (+38)
  • (added) libcxx/test/libcxx-03/containers/unord/unord.multimap/unord.multimap.modifiers/debug.erase.iter.pass.cpp (+43)
diff --git a/libcxx/test/libcxx-03/Wnon_modular_include_in_module.compile.pass.cpp b/libcxx/test/libcxx-03/Wnon_modular_include_in_module.compile.pass.cpp
new file mode 100644
index 0000000000000..aa7a6d98d7d68
--- /dev/null
+++ b/libcxx/test/libcxx-03/Wnon_modular_include_in_module.compile.pass.cpp
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: target={{.*}}-apple-{{.*}}
+// UNSUPPORTED: c++03
+
+// This test ensures that libc++ supports being compiled with modules enabled and with
+// -Wnon-modular-include-in-module. This effectively checks that we don't include any
+// non-modular header from the library.
+//
+// Since most underlying platforms are not modularized properly, this test currently only
+// works on Apple platforms.
+
+// ADDITIONAL_COMPILE_FLAGS: -Wnon-modular-include-in-module -Wsystem-headers-in-module=std -fmodules -fcxx-modules
+
+#include <vector>
diff --git a/libcxx/test/libcxx-03/algorithms/alg.modifying.operations/alg.random.shuffle/random_shuffle.cxx1z.pass.cpp b/libcxx/test/libcxx-03/algorithms/alg.modifying.operations/alg.random.shuffle/random_shuffle.cxx1z.pass.cpp
new file mode 100644
index 0000000000000..4e51014f20b18
--- /dev/null
+++ b/libcxx/test/libcxx-03/algorithms/alg.modifying.operations/alg.random.shuffle/random_shuffle.cxx1z.pass.cpp
@@ -0,0 +1,51 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <algorithm>
+
+// template <class RandomAccessIterator>
+//     void
+//     random_shuffle(RandomAccessIterator first, RandomAccessIterator last);
+//
+// template <class RandomAccessIterator, class RandomNumberGenerator>
+//     void
+//     random_shuffle(RandomAccessIterator first, RandomAccessIterator last,
+//                    RandomNumberGenerator& rand);
+
+//
+//  In C++17, random_shuffle has been removed.
+//  However, for backwards compatibility, if _LIBCPP_ENABLE_CXX17_REMOVED_RANDOM_SHUFFLE
+//  is defined before including <algorithm>, then random_shuffle will be restored.
+
+// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX17_REMOVED_RANDOM_SHUFFLE
+// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS
+
+#include <algorithm>
+#include <cstddef>
+#include <vector>
+
+#include "test_macros.h"
+
+struct gen
+{
+    std::ptrdiff_t operator()(std::ptrdiff_t n)
+    {
+        return n-1;
+    }
+};
+
+
+int main(int, char**)
+{
+    std::vector<int> v;
+    std::random_shuffle(v.begin(), v.end());
+    gen r;
+    std::random_shuffle(v.begin(), v.end(), r);
+
+  return 0;
+}
diff --git a/libcxx/test/libcxx-03/algorithms/alg.modifying.operations/alg.random.shuffle/random_shuffle.depr_in_cxx14.verify.cpp b/libcxx/test/libcxx-03/algorithms/alg.modifying.operations/alg.random.shuffle/random_shuffle.depr_in_cxx14.verify.cpp
new file mode 100644
index 0000000000000..057f126a93cfe
--- /dev/null
+++ b/libcxx/test/libcxx-03/algorithms/alg.modifying.operations/alg.random.shuffle/random_shuffle.depr_in_cxx14.verify.cpp
@@ -0,0 +1,43 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <algorithm>
+
+// template <class RandomAccessIterator>
+//     void
+//     random_shuffle(RandomAccessIterator first, RandomAccessIterator last);
+//
+// template <class RandomAccessIterator, class RandomNumberGenerator>
+//     void
+//     random_shuffle(RandomAccessIterator first, RandomAccessIterator last,
+//                    RandomNumberGenerator& rand);
+
+// UNSUPPORTED: c++03, c++11
+
+// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX17_REMOVED_RANDOM_SHUFFLE
+
+#include <algorithm>
+#include <cstddef>
+
+#include "test_macros.h"
+
+struct gen
+{
+    std::ptrdiff_t operator()(std::ptrdiff_t n)
+    {
+        return n-1;
+    }
+};
+
+
+void f() {
+    int v[1] = {1};
+    std::random_shuffle(&v[0], &v[1]); // expected-warning {{'random_shuffle<int *>' is deprecated}}
+    gen r;
+    std::random_shuffle(&v[0], &v[1], r); // expected-warning {{'random_shuffle<int *, gen &>' is deprecated}}
+}
diff --git a/libcxx/test/libcxx-03/algorithms/alg.modifying.operations/copy_move_nontrivial.pass.cpp b/libcxx/test/libcxx-03/algorithms/alg.modifying.operations/copy_move_nontrivial.pass.cpp
new file mode 100644
index 0000000000000..0c5ae84d97700
--- /dev/null
+++ b/libcxx/test/libcxx-03/algorithms/alg.modifying.operations/copy_move_nontrivial.pass.cpp
@@ -0,0 +1,331 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// In the modules build, adding another overload of `memmove` doesn't work.
+// UNSUPPORTED: clang-modules-build
+// GCC complains about "ambiguating" `__builtin_memmove`.
+// UNSUPPORTED: gcc
+
+// <algorithm>
+
+#include <cassert>
+#include <cstddef>
+
+// These tests check that `std::copy` and `std::move` (including their variations like `copy_n`) don't forward to
+// `std::memmove` when doing so would be observable.
+
+// This template is a better match than the actual `builtin_memmove` (it can match the pointer type exactly, without an
+// implicit conversion to `void*`), so it should hijack the call inside `std::copy` and similar algorithms if it's made.
+template <class Dst, class Src>
+constexpr void* __builtin_memmove(Dst*, Src*, std::size_t) {
+  assert(false);
+  return nullptr;
+}
+
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <iterator>
+#include <ranges>
+#include <type_traits>
+
+#include "test_iterators.h"
+#include "test_macros.h"
+
+// S1 and S2 are simple structs that are convertible to each other and have the same bit representation.
+struct S1 {
+  int x;
+
+  constexpr S1() = default;
+  constexpr S1(int set_x) : x(set_x) {}
+
+  friend constexpr bool operator==(const S1& lhs, const S1& rhs) { return lhs.x == rhs.x; }
+};
+
+struct S2 {
+  int x;
+
+  constexpr S2() = default;
+  constexpr S2(int set_x) : x(set_x) {}
+  constexpr S2(S1 from) : x(from.x) {}
+
+  friend constexpr bool operator==(const S1& lhs, const S2& rhs) { return lhs.x == rhs.x; }
+  friend constexpr bool operator==(const S2& lhs, const S2& rhs) { return lhs.x == rhs.x; }
+};
+
+// U1 and U2 are simple unions that are convertible to each other and have the same bit representation.
+union U1 {
+  int x;
+
+  constexpr U1() = default;
+  constexpr U1(int set_x) : x(set_x) {}
+
+  friend constexpr bool operator==(const U1& lhs, const U1& rhs) { return lhs.x == rhs.x; }
+};
+
+union U2 {
+  int x;
+
+  constexpr U2() = default;
+  constexpr U2(int set_x) : x(set_x) {}
+  constexpr U2(U1 from) : x(from.x) {}
+
+  friend constexpr bool operator==(const U1& lhs, const U2& rhs) { return lhs.x == rhs.x; }
+  friend constexpr bool operator==(const U2& lhs, const U2& rhs) { return lhs.x == rhs.x; }
+};
+
+struct NonTrivialMoveAssignment {
+  int i;
+
+  constexpr NonTrivialMoveAssignment() = default;
+  constexpr NonTrivialMoveAssignment(int set_i) : i(set_i) {}
+
+  constexpr NonTrivialMoveAssignment(NonTrivialMoveAssignment&& rhs) = default;
+  constexpr NonTrivialMoveAssignment& operator=(NonTrivialMoveAssignment&& rhs) noexcept {
+    i = rhs.i;
+    return *this;
+  }
+
+  constexpr friend bool operator==(const NonTrivialMoveAssignment&, const NonTrivialMoveAssignment&) = default;
+};
+
+static_assert(!std::is_trivially_move_assignable_v<NonTrivialMoveAssignment>);
+static_assert(!std::is_trivially_assignable<NonTrivialMoveAssignment&, NonTrivialMoveAssignment&>::value);
+
+struct NonTrivialMoveCtr {
+  int i;
+
+  constexpr NonTrivialMoveCtr() = default;
+  constexpr NonTrivialMoveCtr(int set_i) : i(set_i) {}
+
+  constexpr NonTrivialMoveCtr(NonTrivialMoveCtr&& rhs) noexcept : i(rhs.i) {}
+  constexpr NonTrivialMoveCtr& operator=(NonTrivialMoveCtr&& rhs) = default;
+
+  constexpr friend bool operator==(const NonTrivialMoveCtr&, const NonTrivialMoveCtr&) = default;
+};
+
+static_assert(std::is_trivially_move_assignable_v<NonTrivialMoveCtr>);
+static_assert(!std::is_trivially_copyable_v<NonTrivialMoveCtr>);
+
+struct NonTrivialCopyAssignment {
+  int i;
+
+  constexpr NonTrivialCopyAssignment() = default;
+  constexpr NonTrivialCopyAssignment(int set_i) : i(set_i) {}
+
+  constexpr NonTrivialCopyAssignment(const NonTrivialCopyAssignment& rhs) = default;
+  constexpr NonTrivialCopyAssignment& operator=(const NonTrivialCopyAssignment& rhs) {
+    i = rhs.i;
+    return *this;
+  }
+
+  constexpr friend bool operator==(const NonTrivialCopyAssignment&, const NonTrivialCopyAssignment&) = default;
+};
+
+static_assert(!std::is_trivially_copy_assignable_v<NonTrivialCopyAssignment>);
+
+struct NonTrivialCopyCtr {
+  int i;
+
+  constexpr NonTrivialCopyCtr() = default;
+  constexpr NonTrivialCopyCtr(int set_i) : i(set_i) {}
+
+  constexpr NonTrivialCopyCtr(const NonTrivialCopyCtr& rhs) : i(rhs.i) {}
+  constexpr NonTrivialCopyCtr& operator=(const NonTrivialCopyCtr& rhs) = default;
+
+  constexpr friend bool operator==(const NonTrivialCopyCtr&, const NonTrivialCopyCtr&) = default;
+};
+
+static_assert(std::is_trivially_copy_assignable_v<NonTrivialCopyCtr>);
+static_assert(!std::is_trivially_copyable_v<NonTrivialCopyCtr>);
+
+template <class T>
+constexpr T make(int from) {
+  return T(from);
+}
+
+template <typename PtrT, typename T = std::remove_pointer_t<PtrT>>
+static T make_internal_array[5] = {T(), T(), T(), T(), T()};
+
+template <class T>
+requires std::is_pointer_v<T>
+constexpr T make(int i) {
+  if constexpr (!std::same_as<std::remove_pointer_t<T>, void>) {
+    return make_internal_array<T> + i;
+  } else {
+    return make_internal_array<int> + i;
+  }
+}
+
+template <class InIter, template <class> class SentWrapper, class OutIter, class Func>
+constexpr void test_one(Func func) {
+  using From = typename std::iterator_traits<InIter>::value_type;
+  using To = typename std::iterator_traits<OutIter>::value_type;
+
+  {
+    const std::size_t N = 5;
+
+    From input[N] = {make<From>(0), make<From>(1), make<From>(2), make<From>(3), make<From>(4)};
+    To output[N];
+
+    auto in     = InIter(input);
+    auto in_end = InIter(input + N);
+    auto sent   = SentWrapper<decltype(in_end)>(in_end);
+    auto out    = OutIter(output);
+
+    func(in, sent, out, N);
+    if constexpr (!std::same_as<To, bool>) {
+      assert(std::equal(input, input + N, output));
+    } else {
+      bool expected[N] = {false, true, true, true, true};
+      assert(std::equal(output, output + N, expected));
+    }
+  }
+
+  {
+    const std::size_t N = 0;
+
+    From input[1]  = {make<From>(1)};
+    To output[1] = {make<To>(2)};
+
+    auto in     = InIter(input);
+    auto in_end = InIter(input + N);
+    auto sent   = SentWrapper<decltype(in_end)>(in_end);
+    auto out    = OutIter(output);
+
+    func(in, sent, out, N);
+    assert(output[0] == make<To>(2));
+  }
+}
+
+template <class InIter, template <class> class SentWrapper, class OutIter>
+constexpr void test_copy() {
+  // Classic.
+  if constexpr (std::same_as<InIter, SentWrapper<InIter>>) {
+    test_one<InIter, SentWrapper, OutIter>([](auto first, auto last, auto out, std::size_t) {
+      std::copy(first, last, out);
+    });
+    test_one<InIter, SentWrapper, OutIter>([](auto first, auto last, auto out, std::size_t n) {
+      std::copy_backward(first, last, out + n);
+    });
+    test_one<InIter, SentWrapper, OutIter>([](auto first, auto, auto out, std::size_t n) {
+      std::copy_n(first, n, out);
+    });
+  }
+
+  // Ranges.
+  test_one<InIter, SentWrapper, OutIter>([](auto first, auto last, auto out, std::size_t) {
+    std::ranges::copy(first, last, out);
+  });
+  test_one<InIter, SentWrapper, OutIter>([](auto first, auto last, auto out, std::size_t n) {
+    std::ranges::copy_backward(first, last, out + n);
+  });
+  test_one<InIter, SentWrapper, OutIter>([](auto first, auto, auto out, std::size_t n) {
+    std::ranges::copy_n(first, n, out);
+  });
+}
+
+template <class InIter, template <class> class SentWrapper, class OutIter>
+constexpr void test_move() {
+  if constexpr (std::same_as<InIter, SentWrapper<InIter>>) {
+    test_one<InIter, SentWrapper, OutIter>([](auto first, auto last, auto out, std::size_t) {
+      std::move(first, last, out);
+    });
+    test_one<InIter, SentWrapper, OutIter>([](auto first, auto last, auto out, std::size_t n) {
+      std::move_backward(first, last, out + n);
+    });
+  }
+
+  // Ranges.
+  test_one<InIter, SentWrapper, OutIter>([](auto first, auto last, auto out, std::size_t) {
+    std::ranges::move(first, last, out);
+  });
+  test_one<InIter, SentWrapper, OutIter>([](auto first, auto last, auto out, std::size_t n) {
+    std::ranges::move_backward(first, last, out + n);
+  });
+}
+
+template <class From, class To = From>
+constexpr void test_copy_with_type() {
+  using FromIter = contiguous_iterator<From*>;
+  using ToIter = contiguous_iterator<To*>;
+
+  test_copy<FromIter, std::type_identity_t, ToIter>();
+  test_copy<FromIter, sized_sentinel, ToIter>();
+  test_copy<FromIter, std::type_identity_t, To*>();
+  test_copy<From*, std::type_identity_t, To*>();
+  test_copy<From*, std::type_identity_t, ToIter>();
+}
+
+template <class From, class To = From>
+constexpr void test_move_with_type() {
+  using FromIter = contiguous_iterator<From*>;
+  using ToIter = contiguous_iterator<To*>;
+
+  test_move<FromIter, std::type_identity_t, ToIter>();
+  test_move<FromIter, sized_sentinel, ToIter>();
+  test_move<FromIter, std::type_identity_t, To*>();
+  test_move<From*, std::type_identity_t, To*>();
+  test_move<From*, std::type_identity_t, ToIter>();
+}
+
+template <class From, class To>
+constexpr void test_copy_and_move() {
+  test_copy_with_type<From, To>();
+  test_move_with_type<From, To>();
+}
+
+template <class From, class To>
+constexpr void test_both_directions() {
+  test_copy_and_move<From, To>();
+  if (!std::same_as<From, To>) {
+    test_copy_and_move<To, From>();
+  }
+}
+
+constexpr bool test() {
+  test_copy_with_type<NonTrivialCopyAssignment>();
+  test_move_with_type<NonTrivialMoveAssignment>();
+
+  // Copying from a smaller type into a larger type and vice versa.
+  test_both_directions<char, int>();
+  test_both_directions<std::int32_t, std::int64_t>();
+
+  // Copying between types with different representations.
+  test_both_directions<int, float>();
+  // Copying from `bool` to `char` will invoke the optimization, so only check one direction.
+  test_copy_and_move<char, bool>();
+
+  // Copying between different structs with the same representation (there is no way to guarantee the representation is
+  // the same).
+  test_copy_and_move<S1, S2>();
+  // Copying between different unions with the same representation.
+  test_copy_and_move<U1, U2>();
+
+  // Copying from a regular pointer to a void pointer (these are not considered trivially copyable).
+  test_copy_and_move<int*, void*>();
+  // Copying from a non-const pointer to a const pointer (these are not considered trivially copyable).
+  test_copy_and_move<int*, const int*>();
+
+  // `memmove` does not support volatile pointers.
+  // (See also https://github.com/llvm/llvm-project/issues/28901).
+  if (!std::is_constant_evaluated()) {
+    test_both_directions<volatile int, int>();
+    test_both_directions<volatile int, volatile int>();
+  }
+
+  return true;
+}
+
+int main(int, char**) {
+  test();
+  static_assert(test());
+
+  return 0;
+}
diff --git a/libcxx/test/libcxx-03/algorithms/alg.modifying.operations/copy_move_trivial.pass.cpp b/libcxx/test/libcxx-03/algorithms/alg.modifying.operations/copy_move_trivial.pass.cpp
new file mode 100644
index 0000000000000..ff10c7919200d
--- /dev/null
+++ b/libcxx/test/libcxx-03/algorithms/alg.modifying.operations/copy_move_trivial.pass.cpp
@@ -0,0 +1,334 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// In the modules build, adding another overload of `memmove` doesn't work.
+// UNSUPPORTED: clang-modules-build
+// GCC complains about "ambiguating" `__builtin_memmove`.
+// UNSUPPORTED: gcc
+
+// <algorithm>
+
+// These tests check that `std::copy` and `std::move` (including their variations like `copy_n`) forward to
+// `memmove` when possible.
+
+#include <cstddef>
+
+struct Foo {
+  int i = 0;
+
+  Foo() = default;
+  Foo(int set_i) : i(set_i) {}
+
+  friend bool operator==(const Foo&, const Foo&) = default;
+};
+
+static bool memmove_called = false;
+
+// This template is a better match than the actual `builtin_memmove` (it can match the pointer type exactly, without an
+// implicit conversion to `void*`), so it should hijack the call inside `std::copy` and similar algorithms if it's made.
+template <class Dst, class Src>
+constexpr void* __builtin_memmove(Dst* dst, Src* src, std::size_t count) {
+  memmove_called = true;
+  return __builtin_memmove(static_cast<void*>(dst), static_cast<const void*>(src), count);
+}
+
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <iterator>
+#include <limits>
+#include <ranges>
+#include <type_traits>
+
+#include "test_iterators.h"
+
+static_assert(std::is_trivially_copyable_v<Foo>);
+
+// To test pointers to functions.
+void Func() {}
+using FuncPtr = decltype(&Func);
+
+// To test pointers to members.
+struct S {
+  int mem_obj = 0;
+  void MemFunc() {}
+};
+using MemObjPtr = decltype(&S::mem_obj);
+using MemFuncPtr = decltype(&S::MemFunc);
+
+// To test bitfields.
+struct BitfieldS {
+  unsigned char b1 : 3;
+  unsigned char : 2;
+  unsigned char b2 : 5;
+  friend bool operator==(const BitfieldS&, const BitfieldS&) = default;
+};
+
+// To test non-default alignment.
+struct AlignedS {
+  alignas(64) int x;
+  alignas(8) int y;
+  friend bool operator==(const AlignedS&, const AlignedS&) = default;
+};
+
+template <class T>
+T make(int from) {
+  return T(from);
+}
+
+template <class T>
+requires (std::is_pointer_v<T> && !std::is_function_v<std::remove_pointer_t<T>>)
+T make(int i) {
+  static std::remove_pointer_t<T> arr[8];
+  return arr + i;
+}
+
+template <class T>
+requires std::same_as<T, FuncPtr>
+FuncPtr make(int) {
+  return &Func;
+}
+
+template <class T>
+requires std::same_as<T, MemObjPtr>
+MemObjPtr make(int) {
+  return &S::mem_obj;
+}
+
+template <class T>
+requires std::same_as<T, MemFuncPtr>
+MemFuncPtr make(int) {
+  return &S::MemFunc;
+}
+
+template <class T>
+requires std::same_as<T, BitfieldS>
+BitfieldS make(int x) {
+  BitfieldS result = {};
+  result.b1 = x;
+  result.b2 = x;
+  return result;
+}
+
+template <class T>
+requires std::same_as<T, AlignedS>
+AlignedS make(int x) {
+  AlignedS result;
+  result.x = x;
+  result.y = x;
+  return result;
+}
+
+template <class InIter, template <class> class SentWrapper, class OutIter, class Func>
+void test_one(Func func) {
+  using From = std::iter_value_t<InIter>;
+  using To = std::iter_value_t<OutIter>;
+
+  // Normal case.
+  {
+    const std::size_t N = 4;
+
+    From input[N] = {make<From>(1), make<From>(2), make<From>(3), make<From>(4)...
[truncated]

Copy link
Member

@ldionne ldionne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, but please also make a pass to get all of the implementation-detail tests that were removed since the headers were frozen, and re-add those.

Copy link
Member

@ldionne ldionne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After discussing this some more, we decided to reorganize a few parts of libcxx/test/libcxx before we actually make a copy. I have partially reviewed what needs to be split out and marked where I left it at.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's split this out.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be split out.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of these tests should be split out.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be split out.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests too.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be split out.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one should definitely be split out.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be split out.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be split out.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be split out.

CONTINUE HERE

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants