[libcxx-commits] [libcxx] c4ca3a2 - [libc++] Simplify transitive includes test and fix a bug
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Oct 3 13:09:23 PDT 2022
Author: Louis Dionne
Date: 2022-10-03T16:09:07-04:00
New Revision: c4ca3a2c4b00033c393f694c1d92d28ff55c69cd
URL: https://github.com/llvm/llvm-project/commit/c4ca3a2c4b00033c393f694c1d92d28ff55c69cd
DIFF: https://github.com/llvm/llvm-project/commit/c4ca3a2c4b00033c393f694c1d92d28ff55c69cd.diff
LOG: [libc++] Simplify transitive includes test and fix a bug
This patch incorporates the "sanitize" step of the transitive includes
test into the CSV generator itself. In doing so, it removes complexity
in the test but also fixes a bug where we would filter out <__mutex>
from the output, leading to an incorrect list of includes for the
<shared_mutex> header.
Differential Revision: https://reviews.llvm.org/D134830
Added:
Modified:
libcxx/test/libcxx/transitive_includes.sh.cpp
libcxx/test/libcxx/transitive_includes/cxx14.csv
libcxx/test/libcxx/transitive_includes/cxx17.csv
libcxx/test/libcxx/transitive_includes/cxx20.csv
libcxx/test/libcxx/transitive_includes/cxx2b.csv
libcxx/test/libcxx/transitive_includes_to_csv.py
Removed:
libcxx/test/libcxx/transitive_includes.sanitize.py
################################################################################
diff --git a/libcxx/test/libcxx/transitive_includes.sanitize.py b/libcxx/test/libcxx/transitive_includes.sanitize.py
deleted file mode 100755
index f528f8f95907e..0000000000000
--- a/libcxx/test/libcxx/transitive_includes.sanitize.py
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/usr/bin/env python
-# ===----------------------------------------------------------------------===##
-#
-# 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
-#
-# ===----------------------------------------------------------------------===##
-
-# This script reads lines from standard input and looks for the names of public
-# C++ headers. Specifically, it looks for lines of the form 'c++/v1/header'
-# where 'header' is the name of a public C++ header, excluding C compatibility
-# headers. (Note it keeps the libc++ implementation detail .h files.)
-
-# Note --trace-includes removes duplicates of included headers unless they are
-# part of a cycle.
-
-# The input looks like
-# . ${build_dir}/include/c++/v1/algorithm
-# .. ${build_dir}/include/c++/v1/__assert
-# ... ${build_dir}/include/c++/v1/__config
-# .... ${build_dir}/include/c++/v1/__config_site
-# .... /usr/include/features.h
-# ..... /usr/include/stdc-predef.h
-# ..... /usr/include/x86_64-linux-gnu/sys/cdefs.h
-# ...... /usr/include/x86_64-linux-gnu/bits/wordsize.h
-# <snip>
-# .... ${build_dir}/include/c++/v1/version
-# .... ${build_dir}/include/c++/v1/stddef.h
-# ..... /usr/lib/llvm-15/lib/clang/15.0.0/include/stddef.h
-# ...... /usr/lib/llvm-15/lib/clang/15.0.0/include/__stddef_max_align_t.h
-# ... ${build_dir}/include/c++/v1/type_traits
-# <more>
-
-
-# The filtered output will be like:
-# type_traits
-# . algorithm
-# ... cstddef
-# .... __type_traits/enable_if.h
-# .... __type_traits/integral_constant.h
-# .... __type_traits/is_integral.h
-# ..... __type_traits/remove_cv.h
-# ...... __type_traits/remove_const.h
-# ...... __type_traits/remove_volatile.h
-# .... version
-
-import re
-import sys
-
-headers = []
-for line in sys.stdin.readlines():
- # On Windows, the path separators can either be forward slash or backslash.
- # If it is a backslash, Clang prints it escaped as two consecutive
- # backslashes, and they need to be escaped in the RE. (Use a raw string for
- # the pattern to avoid needing another level of escaping on the Python string
- # literal level.)
- match = re.match(r"(\.+).*c\+\+(?:/|\\\\)v[0-9]+(?:/|\\\\)(.+)", line)
- if not match:
- continue
-
- header = match.group(2)
- # Skip C headers, but accept libc++ detail headers.
- if header.startswith("__"):
- if not header.endswith(".h"):
- continue
- elif header.endswith(".h"):
- continue
-
- print(f"{match.group(1)} {match.group(2)}")
diff --git a/libcxx/test/libcxx/transitive_includes.sh.cpp b/libcxx/test/libcxx/transitive_includes.sh.cpp
index 56724094f2b1e..c23e24df9396b 100644
--- a/libcxx/test/libcxx/transitive_includes.sh.cpp
+++ b/libcxx/test/libcxx/transitive_includes.sh.cpp
@@ -63,10 +63,7 @@ for i, header in enumerate(public_headers):
continue
normalized_header = re.sub('/', '_', header)
- trace_includes = "%{{cxx}} %s %{{flags}} %{{compile_flags}} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_{} 2>&1".format(i)
-
- print(f"// {RUN}: {trace_includes} | %{{python}} %S/transitive_includes.sanitize.py > %t/header.{normalized_header}")
-
+ print(f"// {RUN}: %{{cxx}} %s %{{flags}} %{{compile_flags}} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_{i} 2> %t/header.{normalized_header}")
print(f"#if defined(TEST_{i})")
print(f"#include <{header}>")
print("#endif")
@@ -83,479 +80,479 @@ END-SCRIPT
// DO NOT MANUALLY EDIT ANYTHING BETWEEN THE MARKERS BELOW
// GENERATED-MARKER
// RUN: mkdir %t
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_0 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.algorithm
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_0 2> %t/header.algorithm
#if defined(TEST_0)
#include <algorithm>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_1 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.any
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_1 2> %t/header.any
#if defined(TEST_1)
#include <any>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_2 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.array
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_2 2> %t/header.array
#if defined(TEST_2)
#include <array>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_3 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.atomic
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_3 2> %t/header.atomic
#if defined(TEST_3)
#include <atomic>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_4 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.barrier
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_4 2> %t/header.barrier
#if defined(TEST_4)
#include <barrier>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_5 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.bit
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_5 2> %t/header.bit
#if defined(TEST_5)
#include <bit>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_6 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.bitset
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_6 2> %t/header.bitset
#if defined(TEST_6)
#include <bitset>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_7 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.cassert
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_7 2> %t/header.cassert
#if defined(TEST_7)
#include <cassert>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_8 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.ccomplex
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_8 2> %t/header.ccomplex
#if defined(TEST_8)
#include <ccomplex>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_9 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.cctype
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_9 2> %t/header.cctype
#if defined(TEST_9)
#include <cctype>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_10 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.cerrno
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_10 2> %t/header.cerrno
#if defined(TEST_10)
#include <cerrno>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_11 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.cfenv
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_11 2> %t/header.cfenv
#if defined(TEST_11)
#include <cfenv>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_12 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.cfloat
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_12 2> %t/header.cfloat
#if defined(TEST_12)
#include <cfloat>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_13 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.charconv
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_13 2> %t/header.charconv
#if defined(TEST_13)
#include <charconv>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_14 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.chrono
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_14 2> %t/header.chrono
#if defined(TEST_14)
#include <chrono>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_15 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.cinttypes
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_15 2> %t/header.cinttypes
#if defined(TEST_15)
#include <cinttypes>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_16 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.ciso646
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_16 2> %t/header.ciso646
#if defined(TEST_16)
#include <ciso646>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_17 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.climits
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_17 2> %t/header.climits
#if defined(TEST_17)
#include <climits>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_18 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.clocale
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_18 2> %t/header.clocale
#if defined(TEST_18)
#include <clocale>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_19 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.cmath
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_19 2> %t/header.cmath
#if defined(TEST_19)
#include <cmath>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_20 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.codecvt
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_20 2> %t/header.codecvt
#if defined(TEST_20)
#include <codecvt>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_21 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.compare
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_21 2> %t/header.compare
#if defined(TEST_21)
#include <compare>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_22 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.complex
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_22 2> %t/header.complex
#if defined(TEST_22)
#include <complex>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_24 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.concepts
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_24 2> %t/header.concepts
#if defined(TEST_24)
#include <concepts>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_25 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.condition_variable
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_25 2> %t/header.condition_variable
#if defined(TEST_25)
#include <condition_variable>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_26 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.coroutine
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_26 2> %t/header.coroutine
#if defined(TEST_26)
#include <coroutine>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_27 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.csetjmp
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_27 2> %t/header.csetjmp
#if defined(TEST_27)
#include <csetjmp>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_28 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.csignal
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_28 2> %t/header.csignal
#if defined(TEST_28)
#include <csignal>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_29 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.cstdarg
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_29 2> %t/header.cstdarg
#if defined(TEST_29)
#include <cstdarg>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_30 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.cstdbool
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_30 2> %t/header.cstdbool
#if defined(TEST_30)
#include <cstdbool>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_31 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.cstddef
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_31 2> %t/header.cstddef
#if defined(TEST_31)
#include <cstddef>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_32 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.cstdint
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_32 2> %t/header.cstdint
#if defined(TEST_32)
#include <cstdint>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_33 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.cstdio
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_33 2> %t/header.cstdio
#if defined(TEST_33)
#include <cstdio>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_34 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.cstdlib
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_34 2> %t/header.cstdlib
#if defined(TEST_34)
#include <cstdlib>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_35 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.cstring
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_35 2> %t/header.cstring
#if defined(TEST_35)
#include <cstring>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_36 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.ctgmath
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_36 2> %t/header.ctgmath
#if defined(TEST_36)
#include <ctgmath>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_37 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.ctime
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_37 2> %t/header.ctime
#if defined(TEST_37)
#include <ctime>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_39 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.cuchar
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_39 2> %t/header.cuchar
#if defined(TEST_39)
#include <cuchar>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_40 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.cwchar
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_40 2> %t/header.cwchar
#if defined(TEST_40)
#include <cwchar>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_41 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.cwctype
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_41 2> %t/header.cwctype
#if defined(TEST_41)
#include <cwctype>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_42 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.deque
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_42 2> %t/header.deque
#if defined(TEST_42)
#include <deque>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_44 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.exception
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_44 2> %t/header.exception
#if defined(TEST_44)
#include <exception>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_45 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.execution
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_45 2> %t/header.execution
#if defined(TEST_45)
#include <execution>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_47 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.filesystem
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_47 2> %t/header.filesystem
#if defined(TEST_47)
#include <filesystem>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_49 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.format
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_49 2> %t/header.format
#if defined(TEST_49)
#include <format>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_50 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.forward_list
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_50 2> %t/header.forward_list
#if defined(TEST_50)
#include <forward_list>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_51 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.fstream
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_51 2> %t/header.fstream
#if defined(TEST_51)
#include <fstream>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_52 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.functional
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_52 2> %t/header.functional
#if defined(TEST_52)
#include <functional>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_53 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.future
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_53 2> %t/header.future
#if defined(TEST_53)
#include <future>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_54 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.initializer_list
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_54 2> %t/header.initializer_list
#if defined(TEST_54)
#include <initializer_list>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_56 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.iomanip
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_56 2> %t/header.iomanip
#if defined(TEST_56)
#include <iomanip>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_57 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.ios
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_57 2> %t/header.ios
#if defined(TEST_57)
#include <ios>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_58 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.iosfwd
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_58 2> %t/header.iosfwd
#if defined(TEST_58)
#include <iosfwd>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_59 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.iostream
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_59 2> %t/header.iostream
#if defined(TEST_59)
#include <iostream>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_60 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.istream
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_60 2> %t/header.istream
#if defined(TEST_60)
#include <istream>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_61 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.iterator
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_61 2> %t/header.iterator
#if defined(TEST_61)
#include <iterator>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_62 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.latch
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_62 2> %t/header.latch
#if defined(TEST_62)
#include <latch>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_63 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.limits
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_63 2> %t/header.limits
#if defined(TEST_63)
#include <limits>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_65 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.list
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_65 2> %t/header.list
#if defined(TEST_65)
#include <list>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_66 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.locale
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_66 2> %t/header.locale
#if defined(TEST_66)
#include <locale>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_68 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.map
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_68 2> %t/header.map
#if defined(TEST_68)
#include <map>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_70 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.memory
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_70 2> %t/header.memory
#if defined(TEST_70)
#include <memory>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_71 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.mutex
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_71 2> %t/header.mutex
#if defined(TEST_71)
#include <mutex>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_72 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.new
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_72 2> %t/header.new
#if defined(TEST_72)
#include <new>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_73 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.numbers
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_73 2> %t/header.numbers
#if defined(TEST_73)
#include <numbers>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_74 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.numeric
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_74 2> %t/header.numeric
#if defined(TEST_74)
#include <numeric>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_75 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.optional
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_75 2> %t/header.optional
#if defined(TEST_75)
#include <optional>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_76 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.ostream
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_76 2> %t/header.ostream
#if defined(TEST_76)
#include <ostream>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_77 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.queue
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_77 2> %t/header.queue
#if defined(TEST_77)
#include <queue>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_78 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.random
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_78 2> %t/header.random
#if defined(TEST_78)
#include <random>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_79 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.ranges
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_79 2> %t/header.ranges
#if defined(TEST_79)
#include <ranges>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_80 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.ratio
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_80 2> %t/header.ratio
#if defined(TEST_80)
#include <ratio>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_81 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.regex
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_81 2> %t/header.regex
#if defined(TEST_81)
#include <regex>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_82 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.scoped_allocator
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_82 2> %t/header.scoped_allocator
#if defined(TEST_82)
#include <scoped_allocator>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_83 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.semaphore
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_83 2> %t/header.semaphore
#if defined(TEST_83)
#include <semaphore>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_84 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.set
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_84 2> %t/header.set
#if defined(TEST_84)
#include <set>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_86 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.shared_mutex
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_86 2> %t/header.shared_mutex
#if defined(TEST_86)
#include <shared_mutex>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_87 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.span
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_87 2> %t/header.span
#if defined(TEST_87)
#include <span>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_88 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.sstream
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_88 2> %t/header.sstream
#if defined(TEST_88)
#include <sstream>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_89 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.stack
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_89 2> %t/header.stack
#if defined(TEST_89)
#include <stack>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_93 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.stdexcept
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_93 2> %t/header.stdexcept
#if defined(TEST_93)
#include <stdexcept>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_97 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.streambuf
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_97 2> %t/header.streambuf
#if defined(TEST_97)
#include <streambuf>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_98 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.string
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_98 2> %t/header.string
#if defined(TEST_98)
#include <string>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_100 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.string_view
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_100 2> %t/header.string_view
#if defined(TEST_100)
#include <string_view>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_101 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.strstream
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_101 2> %t/header.strstream
#if defined(TEST_101)
#include <strstream>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_102 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.system_error
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_102 2> %t/header.system_error
#if defined(TEST_102)
#include <system_error>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_104 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.thread
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_104 2> %t/header.thread
#if defined(TEST_104)
#include <thread>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_105 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.tuple
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_105 2> %t/header.tuple
#if defined(TEST_105)
#include <tuple>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_106 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.type_traits
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_106 2> %t/header.type_traits
#if defined(TEST_106)
#include <type_traits>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_107 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.typeindex
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_107 2> %t/header.typeindex
#if defined(TEST_107)
#include <typeindex>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_108 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.typeinfo
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_108 2> %t/header.typeinfo
#if defined(TEST_108)
#include <typeinfo>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_110 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.unordered_map
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_110 2> %t/header.unordered_map
#if defined(TEST_110)
#include <unordered_map>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_111 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.unordered_set
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_111 2> %t/header.unordered_set
#if defined(TEST_111)
#include <unordered_set>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_112 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.utility
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_112 2> %t/header.utility
#if defined(TEST_112)
#include <utility>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_113 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.valarray
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_113 2> %t/header.valarray
#if defined(TEST_113)
#include <valarray>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_114 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.variant
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_114 2> %t/header.variant
#if defined(TEST_114)
#include <variant>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_115 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.vector
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_115 2> %t/header.vector
#if defined(TEST_115)
#include <vector>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_116 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.version
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_116 2> %t/header.version
#if defined(TEST_116)
#include <version>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_119 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.experimental_algorithm
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_119 2> %t/header.experimental_algorithm
#if defined(TEST_119)
#include <experimental/algorithm>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_120 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.experimental_coroutine
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_120 2> %t/header.experimental_coroutine
#if defined(TEST_120)
#include <experimental/coroutine>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_121 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.experimental_deque
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_121 2> %t/header.experimental_deque
#if defined(TEST_121)
#include <experimental/deque>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_122 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.experimental_forward_list
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_122 2> %t/header.experimental_forward_list
#if defined(TEST_122)
#include <experimental/forward_list>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_123 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.experimental_functional
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_123 2> %t/header.experimental_functional
#if defined(TEST_123)
#include <experimental/functional>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_124 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.experimental_iterator
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_124 2> %t/header.experimental_iterator
#if defined(TEST_124)
#include <experimental/iterator>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_125 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.experimental_list
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_125 2> %t/header.experimental_list
#if defined(TEST_125)
#include <experimental/list>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_126 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.experimental_map
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_126 2> %t/header.experimental_map
#if defined(TEST_126)
#include <experimental/map>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_127 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.experimental_memory_resource
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_127 2> %t/header.experimental_memory_resource
#if defined(TEST_127)
#include <experimental/memory_resource>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_128 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.experimental_propagate_const
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_128 2> %t/header.experimental_propagate_const
#if defined(TEST_128)
#include <experimental/propagate_const>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_129 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.experimental_regex
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_129 2> %t/header.experimental_regex
#if defined(TEST_129)
#include <experimental/regex>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_130 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.experimental_set
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_130 2> %t/header.experimental_set
#if defined(TEST_130)
#include <experimental/set>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_131 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.experimental_simd
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_131 2> %t/header.experimental_simd
#if defined(TEST_131)
#include <experimental/simd>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_132 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.experimental_string
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_132 2> %t/header.experimental_string
#if defined(TEST_132)
#include <experimental/string>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_133 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.experimental_type_traits
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_133 2> %t/header.experimental_type_traits
#if defined(TEST_133)
#include <experimental/type_traits>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_134 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.experimental_unordered_map
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_134 2> %t/header.experimental_unordered_map
#if defined(TEST_134)
#include <experimental/unordered_map>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_135 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.experimental_unordered_set
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_135 2> %t/header.experimental_unordered_set
#if defined(TEST_135)
#include <experimental/unordered_set>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_136 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.experimental_utility
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_136 2> %t/header.experimental_utility
#if defined(TEST_136)
#include <experimental/utility>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_137 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.experimental_vector
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_137 2> %t/header.experimental_vector
#if defined(TEST_137)
#include <experimental/vector>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_138 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.ext_hash_map
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_138 2> %t/header.ext_hash_map
#if defined(TEST_138)
#include <ext/hash_map>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_139 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t/header.ext_hash_set
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_139 2> %t/header.ext_hash_set
#if defined(TEST_139)
#include <ext/hash_set>
#endif
diff --git a/libcxx/test/libcxx/transitive_includes/cxx14.csv b/libcxx/test/libcxx/transitive_includes/cxx14.csv
index 69a11ec96b84a..5a9fe6a000fba 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx14.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx14.csv
@@ -716,6 +716,12 @@ set optional
set stdexcept
set type_traits
set version
+shared_mutex ctime
+shared_mutex iosfwd
+shared_mutex limits
+shared_mutex ratio
+shared_mutex system_error
+shared_mutex type_traits
shared_mutex version
span array
span concepts
diff --git a/libcxx/test/libcxx/transitive_includes/cxx17.csv b/libcxx/test/libcxx/transitive_includes/cxx17.csv
index 69a11ec96b84a..5a9fe6a000fba 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx17.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx17.csv
@@ -716,6 +716,12 @@ set optional
set stdexcept
set type_traits
set version
+shared_mutex ctime
+shared_mutex iosfwd
+shared_mutex limits
+shared_mutex ratio
+shared_mutex system_error
+shared_mutex type_traits
shared_mutex version
span array
span concepts
diff --git a/libcxx/test/libcxx/transitive_includes/cxx20.csv b/libcxx/test/libcxx/transitive_includes/cxx20.csv
index d5ad19904ed70..346e40b24eb57 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx20.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx20.csv
@@ -726,6 +726,12 @@ set optional
set stdexcept
set type_traits
set version
+shared_mutex ctime
+shared_mutex iosfwd
+shared_mutex limits
+shared_mutex ratio
+shared_mutex system_error
+shared_mutex type_traits
shared_mutex version
span array
span concepts
diff --git a/libcxx/test/libcxx/transitive_includes/cxx2b.csv b/libcxx/test/libcxx/transitive_includes/cxx2b.csv
index a17bc208b654d..e1e57466a6833 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx2b.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx2b.csv
@@ -621,6 +621,12 @@ set optional
set stdexcept
set type_traits
set version
+shared_mutex ctime
+shared_mutex iosfwd
+shared_mutex limits
+shared_mutex ratio
+shared_mutex system_error
+shared_mutex type_traits
shared_mutex version
span array
span concepts
diff --git a/libcxx/test/libcxx/transitive_includes_to_csv.py b/libcxx/test/libcxx/transitive_includes_to_csv.py
index 42ac69fad5234..ad86ca79a06e5 100755
--- a/libcxx/test/libcxx/transitive_includes_to_csv.py
+++ b/libcxx/test/libcxx/transitive_includes_to_csv.py
@@ -10,9 +10,9 @@
from dataclasses import dataclass, field
from typing import List # Needed for python 3.8 compatibility.
import argparse
+import pathlib
import re
import sys
-import pathlib
@dataclass
@@ -22,6 +22,9 @@ class header:
def parse_line(line: str) -> header:
+ """
+ Parse an output line from --trace-include into a `header`.
+ """
match = re.match(r"(\.+) (.+)", line)
if not match:
sys.exit(f"Line {line} contains invalid data.")
@@ -31,59 +34,117 @@ def parse_line(line: str) -> header:
return header(match.group(2), len(match.group(1)))
-# Generates the list of transitive includes of a header.
-#
-# The input contains two kinds of headers
-# * Standard headers (algorithm, string, format, etc)
-# * Detail headers (__algorithm/copy.h, __algorithm/copy_n.h, etc)
-# The output contains the transitive includes of the Standard header being
-# processed. The detail headers are omitted from the output, but their
-# transitive includes are parsed and added, if they are a Standard header.
-#
-# This effectively generates the dependency graph of a Standard header.
+# On Windows, the path separators can either be forward slash or backslash.
+# If it is a backslash, Clang prints it escaped as two consecutive
+# backslashes, and they need to be escaped in the RE. (Use a raw string for
+# the pattern to avoid needing another level of escaping on the Python string
+# literal level.)
+LIBCXX_HEADER_REGEX = r".*c\+\+(?:/|\\\\)v[0-9]+(?:/|\\\\)(.+)"
+
+def is_libcxx_public_header(header : str) -> bool:
+ """
+ Returns whether a header is a C++ public header file.
+ """
+ # Only keep files in the c++/vN directory.
+ match = re.match(LIBCXX_HEADER_REGEX, header)
+ if not match:
+ return False
+
+ # Skip C compatibility headers.
+ if header.endswith(".h"):
+ return False
+
+ # Skip all other detail headers (headers starting with __ or in a subdirectory starting with __).
+ relative = match.group(1)
+ if relative.startswith("__") or re.search(r"(/|\\\\)__", relative):
+ return False
+
+ return True
+
+
+def is_libcxx_header(header : str) -> bool:
+ """
+ Returns whether a header is a libc++ header, excluding the C-compatibility headers.
+ """
+ # Only keep files in the c++/vN directory.
+ match = re.match(LIBCXX_HEADER_REGEX, header)
+ if not match:
+ return False
+
+ # Skip C compatibility headers (in particular, make sure not to skip libc++ detail headers).
+ relative = match.group(1)
+ if relative.endswith(".h") and not (relative.startswith("__") or re.search(r"(/|\\\\)__", relative)):
+ return False
+
+ return True
+
+
def parse_file(file: pathlib.Path) -> List[str]:
+ """
+ Parse a file containing --trace-include output to generate a list of the top-level C++ includes
+ contained in it.
+
+ This effectively generates the dependency graph of C++ Standard Library headers of the header
+ whose --trace-include it is. In order to get the expected result of --trace-include, the
+ -fshow-skipped-includes flag also needs to be passed.
+ """
result = list()
with file.open(encoding="utf-8") as f:
- level = 999
-
- # The first line contains the Standard header being processed.
- # The transitive includes of this Standard header should be processed.
- header = parse_line(f.readline())
- assert header.level == 1
- result.append(header.name)
-
for line in f.readlines():
header = parse_line(line)
- # Skip deeper nested headers for Standard headers.
+ # Skip non-libc++ headers
+ if not is_libcxx_header(header.name):
+ continue
+
+ # Include top-level headers in the output. There's usually exactly one,
+ # except if the compiler is passed a file with `-include`. Top-level
+ # headers are transparent, in the sense that we want to go look at
+ # transitive includes underneath.
+ if header.level == 1:
+ level = 999
+ result.append(header)
+ continue
+
+ # Skip libc++ headers included transitively.
if header.level > level:
continue
- # Process deeper nested headers for detail headers.
- if header.name.startswith("__") or header.name.__contains__("/__"):
+ # Detail headers are transparent too: we attribute all includes of public libc++
+ # headers under a detail header to the last public libc++ header that included it.
+ if header.name.startswith("__") or re.search(r"(/|\\\\)__", header.name):
level = 999
continue
- # Add the Standard header.
+ # Add the non-detail libc++ header to the list.
level = header.level
- result.append(header.name)
-
+ result.append(header)
return result
def create_include_graph(path: pathlib.Path) -> List[str]:
result = list()
for file in sorted(path.glob("header.*")):
- includes = parse_file(file)
- if len(includes) > 1:
- result.append(includes)
+ headers = parse_file(file)
+
+ # Get actual filenames relative to libc++'s installation directory instead of full paths
+ relative = lambda h: re.match(LIBCXX_HEADER_REGEX, h).group(1)
+
+ top_level = relative(next(h.name for h in headers if h.level == 1)) # There should be only one top-level header
+ includes = [relative(h.name) for h in headers if h.level != 1]
+
+ # Remove duplicates in all includes.
+ includes = list(set(includes))
+
+ if len(includes) != 0:
+ result.append([top_level] + includes)
return result
def print_csv(graph: List[str]) -> None:
for includes in graph:
header = includes[0]
- for include in sorted(set(includes[1:])):
+ for include in sorted(includes[1:]):
if header == include:
sys.exit(f"Cycle detected: header {header} includes itself.")
print(f"{header} {include}")
More information about the libcxx-commits
mailing list