103 lines · python
1# ===----------------------------------------------------------------------===##2#3# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4# See https://llvm.org/LICENSE.txt for license information.5# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6#7# ===----------------------------------------------------------------------===##8 9# Test that we don't remove transitive includes of public C++ headers in the library accidentally.10# When we remove a transitive public include, clients tend to break because they don't always11# properly include what they use. Note that we don't check which system (C) headers are12# included transitively, because that is too unstable across platforms, and hence difficult13# to test for.14#15# This is not meant to block libc++ from removing unused transitive includes16# forever, however we do try to group removals for a couple of releases17# to avoid breaking users at every release.18 19# RUN: %{python} %s %{libcxx-dir}/utils20 21# block Lit from interpreting a RUN/XFAIL/etc inside the generation script22# END.23 24import sys25sys.path.append(sys.argv[1])26from libcxx.header_information import lit_header_restrictions, public_headers27 28import re29 30# To re-generate the list of expected headers, temporarily set this to True, and run this test.31# Note that this needs to be done for all supported language versions of libc++:32# for std in c++03 c++11 c++14 c++17 c++20 c++23 c++26; do <build>/bin/llvm-lit --param std=$std libcxx/test/libcxx/transitive_includes.gen.py; done33regenerate_expected_results = False34 35if regenerate_expected_results:36 print(37 f"""\38//--- generate-transitive-includes.sh.cpp39// RUN: mkdir %t40"""41 )42 43 all_traces = []44 for header in sorted(public_headers):45 if header.is_C_compatibility() or header.is_internal():46 continue47 48 normalized_header = re.sub("/", "_", str(header))49 print(50 f"""\51// RUN: echo "#include <{header}>" | %{{cxx}} -xc++ - %{{flags}} %{{compile_flags}} --trace-includes -fshow-skipped-includes --preprocess > /dev/null 2> %t/trace-includes.{normalized_header}.txt52"""53 )54 all_traces.append(f"%t/trace-includes.{normalized_header}.txt")55 56 print(57 f"""\58// RUN: %{{python}} %{{libcxx-dir}}/test/libcxx/transitive_includes/to_csv.py {' '.join(all_traces)} > %{{libcxx-dir}}/test/libcxx/transitive_includes/%{{cxx_std}}.csv59"""60 )61 62else:63 for header in public_headers:64 if header.is_C_compatibility() or header.is_internal():65 continue66 67 # Escape slashes for the awk command below68 escaped_header = str(header).replace("/", "\\/")69 70 print(71 f"""\72//--- {header}.sh.cpp73{lit_header_restrictions.get(header, '')}74 75// TODO: Fix this test to make it work with localization or wide characters disabled76// UNSUPPORTED: no-localization, no-wide-characters, no-threads, no-filesystem, libcpp-has-no-experimental-tzdb77 78// When built with modules, this test doesn't work because --trace-includes doesn't79// report the stack of includes correctly.80// UNSUPPORTED: clang-modules-build81 82// This test uses --trace-includes, which is not supported by GCC.83// UNSUPPORTED: gcc84 85// This test is not supported when we remove the transitive includes provided for backwards86// compatibility. When we bulk-remove them, we'll adjust the includes that are expected by87// this test instead.88// UNSUPPORTED: transitive-includes-disabled89 90// TODO: Figure out why <stdatomic.h> doesn't work on FreeBSD91// UNSUPPORTED: LIBCXX-FREEBSD-FIXME92 93// UNSUPPORTED: FROZEN-CXX03-HEADERS-FIXME94 95// RUN: mkdir %t96// RUN: %{{cxx}} %s %{{flags}} %{{compile_flags}} --trace-includes -fshow-skipped-includes --preprocess > /dev/null 2> %t/trace-includes.txt97// RUN: %{{python}} %{{libcxx-dir}}/test/libcxx/transitive_includes/to_csv.py %t/trace-includes.txt > %t/actual_transitive_includes.csv98// RUN: cat %{{libcxx-dir}}/test/libcxx/transitive_includes/%{{cxx_std}}.csv | awk '/^{escaped_header} / {{ print }}' > %t/expected_transitive_includes.csv99// RUN: diff -w %t/expected_transitive_includes.csv %t/actual_transitive_includes.csv100#include <{header}>101"""102 )103