aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libcxx/benchmarks/lit.cfg.py14
-rw-r--r--libcxx/docs/conf.py134
-rw-r--r--libcxx/test/libcxx/experimental/lit.local.cfg4
-rw-r--r--libcxx/test/libcxx/gdb/gdb_pretty_printer_test.py16
-rw-r--r--libcxx/test/libcxx/input.output/file.streams/lit.local.cfg5
-rw-r--r--libcxx/test/libcxx/input.output/filesystems/lit.local.cfg7
-rw-r--r--libcxx/test/libcxx/input.output/iostream.format/lit.local.cfg5
-rw-r--r--libcxx/test/libcxx/input.output/iostream.objects/lit.local.cfg5
-rw-r--r--libcxx/test/libcxx/input.output/iostreams.base/lit.local.cfg5
-rw-r--r--libcxx/test/libcxx/input.output/stream.buffers/lit.local.cfg5
-rw-r--r--libcxx/test/libcxx/input.output/string.streams/lit.local.cfg5
-rw-r--r--libcxx/test/libcxx/lint/lint_cmakelists.sh.py16
-rw-r--r--libcxx/test/libcxx/lint/lint_headers.sh.py43
-rwxr-xr-xlibcxx/test/libcxx/lint/lint_modulemap.sh.py36
-rw-r--r--libcxx/test/libcxx/lit.local.cfg3
-rw-r--r--libcxx/test/libcxx/localization/lit.local.cfg5
-rw-r--r--libcxx/test/libcxx/selftest/additional_compile_flags/lit.local.cfg2
-rw-r--r--libcxx/test/libcxx/selftest/dsl/dsl.sh.py356
-rw-r--r--libcxx/test/libcxx/selftest/dsl/lit.local.cfg3
-rwxr-xr-xlibcxx/test/libcxx/transitive_includes_to_csv.py13
-rw-r--r--libcxx/test/lit.cfg.py3
-rw-r--r--libcxx/test/std/depr/depr.ios.members/lit.local.cfg4
-rw-r--r--libcxx/test/std/depr/depr.str.strstreams/lit.local.cfg4
-rw-r--r--libcxx/test/std/experimental/lit.local.cfg4
-rw-r--r--libcxx/test/std/input.output/file.streams/lit.local.cfg8
-rw-r--r--libcxx/test/std/input.output/filesystems/lit.local.cfg6
-rw-r--r--libcxx/test/std/input.output/input.output.general/lit.local.cfg4
-rw-r--r--libcxx/test/std/input.output/iostream.format/lit.local.cfg4
-rw-r--r--libcxx/test/std/input.output/iostream.forward/lit.local.cfg4
-rw-r--r--libcxx/test/std/input.output/iostream.objects/lit.local.cfg4
-rw-r--r--libcxx/test/std/input.output/iostreams.base/lit.local.cfg4
-rw-r--r--libcxx/test/std/input.output/iostreams.requirements/lit.local.cfg4
-rw-r--r--libcxx/test/std/input.output/stream.buffers/lit.local.cfg4
-rw-r--r--libcxx/test/std/input.output/string.streams/lit.local.cfg4
-rw-r--r--libcxx/test/std/iterators/stream.iterators/lit.local.cfg4
-rw-r--r--libcxx/test/std/localization/lit.local.cfg4
-rw-r--r--libcxx/test/std/re/lit.local.cfg4
-rw-r--r--libcxx/test/std/strings/basic.string/string.nonmembers/string.io/lit.local.cfg4
-rwxr-xr-xlibcxx/utils/cat_files.py40
-rw-r--r--libcxx/utils/gdb/libcxx/printers.py115
-rwxr-xr-xlibcxx/utils/generate_abi_list.py33
-rwxr-xr-xlibcxx/utils/generate_feature_test_macro_components.py2235
-rwxr-xr-xlibcxx/utils/generate_header_inclusion_tests.py70
-rwxr-xr-xlibcxx/utils/generate_header_tests.py133
-rw-r--r--libcxx/utils/generate_iwyu_mapping.py110
-rw-r--r--libcxx/utils/generate_width_estimation_table.py5
-rw-r--r--libcxx/utils/libcxx/__init__.py10
-rw-r--r--libcxx/utils/libcxx/sym_check/__init__.py12
-rw-r--r--libcxx/utils/libcxx/sym_check/diff.py65
-rw-r--r--libcxx/utils/libcxx/sym_check/extract.py245
-rw-r--r--libcxx/utils/libcxx/sym_check/match.py14
-rw-r--r--libcxx/utils/libcxx/sym_check/util.py324
-rw-r--r--libcxx/utils/libcxx/test/config.py80
-rw-r--r--libcxx/utils/libcxx/test/dsl.py1199
-rw-r--r--libcxx/utils/libcxx/test/features.py707
-rw-r--r--libcxx/utils/libcxx/test/format.py202
-rw-r--r--libcxx/utils/libcxx/test/googlebenchmark.py70
-rw-r--r--libcxx/utils/libcxx/test/params.py470
-rwxr-xr-xlibcxx/utils/run.py36
-rwxr-xr-xlibcxx/utils/ssh.py61
-rwxr-xr-xlibcxx/utils/sym_diff.py85
-rw-r--r--libcxxabi/test/lit.cfg.py3
-rw-r--r--libcxxabi/test/native/arm-linux-eabi/lit.local.cfg7
-rw-r--r--libunwind/docs/conf.py134
-rw-r--r--libunwind/test/lit.cfg.py3
65 files changed, 4164 insertions, 3063 deletions
diff --git a/libcxx/benchmarks/lit.cfg.py b/libcxx/benchmarks/lit.cfg.py
index 84857d5..7d222dd 100644
--- a/libcxx/benchmarks/lit.cfg.py
+++ b/libcxx/benchmarks/lit.cfg.py
@@ -3,21 +3,21 @@
import os
import site
-site.addsitedir(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'utils'))
+site.addsitedir(os.path.join(os.path.dirname(os.path.dirname(__file__)), "utils"))
from libcxx.test.googlebenchmark import GoogleBenchmark
# Tell pylint that we know config and lit_config exist somewhere.
-if 'PYLINT_IMPORT' in os.environ:
+if "PYLINT_IMPORT" in os.environ:
config = object()
lit_config = object()
# name: The name of this test suite.
-config.name = 'libc++ benchmarks'
+config.name = "libc++ benchmarks"
config.suffixes = []
-config.test_exec_root = os.path.join(config.libcxx_obj_root, 'benchmarks')
+config.test_exec_root = os.path.join(config.libcxx_obj_root, "benchmarks")
config.test_source_root = config.test_exec_root
-config.test_format = GoogleBenchmark(test_sub_dirs='.',
- test_suffix='.libcxx.out',
- benchmark_args=config.benchmark_args) \ No newline at end of file
+config.test_format = GoogleBenchmark(
+ test_sub_dirs=".", test_suffix=".libcxx.out", benchmark_args=config.benchmark_args
+)
diff --git a/libcxx/docs/conf.py b/libcxx/docs/conf.py
index f680969..d24ec63 100644
--- a/libcxx/docs/conf.py
+++ b/libcxx/docs/conf.py
@@ -16,106 +16,106 @@ from datetime import date
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
-#sys.path.insert(0, os.path.abspath('.'))
+# sys.path.insert(0, os.path.abspath('.'))
# -- General configuration -----------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
-#needs_sphinx = '1.0'
+# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['sphinx.ext.intersphinx', 'sphinx.ext.todo']
+extensions = ["sphinx.ext.intersphinx", "sphinx.ext.todo"]
# Add any paths that contain templates here, relative to this directory.
-templates_path = ['_templates']
+templates_path = ["_templates"]
# The suffix of source filenames.
-source_suffix = '.rst'
+source_suffix = ".rst"
# The encoding of source files.
-#source_encoding = 'utf-8-sig'
+# source_encoding = 'utf-8-sig'
# The master toctree document.
-master_doc = 'index'
+master_doc = "index"
# General information about the project.
-project = u'libc++'
-copyright = u'2011-%d, LLVM Project' % date.today().year
+project = "libc++"
+copyright = "2011-%d, LLVM Project" % date.today().year
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
-version = '17.0'
+version = "17.0"
# The full version, including alpha/beta/rc tags.
-release = '17.0'
+release = "17.0"
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
-#language = None
+# language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
-#today = ''
+# today = ''
# Else, today_fmt is used as the format for a strftime call.
-today_fmt = '%Y-%m-%d'
+today_fmt = "%Y-%m-%d"
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
-exclude_patterns = ['_build', 'Helpers']
+exclude_patterns = ["_build", "Helpers"]
# The reST default role (used for this markup: `text`) to use for all documents.
-#default_role = None
+# default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
-#add_function_parentheses = True
+# add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
-#add_module_names = True
+# add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
show_authors = True
# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'friendly'
+pygments_style = "friendly"
# A list of ignored prefixes for module index sorting.
-#modindex_common_prefix = []
+# modindex_common_prefix = []
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
-html_theme = 'haiku'
+html_theme = "haiku"
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
-#html_theme_options = {}
+# html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
-#html_theme_path = []
+# html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
-#html_title = None
+# html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
-#html_short_title = None
+# html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
-#html_logo = None
+# html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
-#html_favicon = None
+# html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
@@ -124,101 +124,95 @@ html_static_path = []
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
-#html_last_updated_fmt = '%b %d, %Y'
+# html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
-#html_use_smartypants = True
+# html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
-#html_sidebars = {}
+# html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
-#html_additional_pages = {}
+# html_additional_pages = {}
# If false, no module index is generated.
-#html_domain_indices = True
+# html_domain_indices = True
# If false, no index is generated.
-#html_use_index = True
+# html_use_index = True
# If true, the index is split into individual pages for each letter.
-#html_split_index = False
+# html_split_index = False
# If true, links to the reST sources are added to the pages.
-#html_show_sourcelink = True
+# html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
-#html_show_sphinx = True
+# html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
-#html_show_copyright = True
+# html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
-#html_use_opensearch = ''
+# html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
-#html_file_suffix = None
+# html_file_suffix = None
# Output file base name for HTML help builder.
-htmlhelp_basename = 'libcxxdoc'
+htmlhelp_basename = "libcxxdoc"
# -- Options for LaTeX output --------------------------------------------------
latex_elements = {
-# The paper size ('letterpaper' or 'a4paper').
-#'papersize': 'letterpaper',
-
-# The font size ('10pt', '11pt' or '12pt').
-#'pointsize': '10pt',
-
-# Additional stuff for the LaTeX preamble.
-#'preamble': '',
+ # The paper size ('letterpaper' or 'a4paper').
+ #'papersize': 'letterpaper',
+ # The font size ('10pt', '11pt' or '12pt').
+ #'pointsize': '10pt',
+ # Additional stuff for the LaTeX preamble.
+ #'preamble': '',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
- ('contents', 'libcxx.tex', u'libcxx Documentation',
- u'LLVM project', 'manual'),
+ ("contents", "libcxx.tex", "libcxx Documentation", "LLVM project", "manual"),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
-#latex_logo = None
+# latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
-#latex_use_parts = False
+# latex_use_parts = False
# If true, show page references after internal links.
-#latex_show_pagerefs = False
+# latex_show_pagerefs = False
# If true, show URL addresses after external links.
-#latex_show_urls = False
+# latex_show_urls = False
# Documents to append as an appendix to all manuals.
-#latex_appendices = []
+# latex_appendices = []
# If false, no module index is generated.
-#latex_domain_indices = True
+# latex_domain_indices = True
# -- Options for manual page output --------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
-man_pages = [
- ('contents', 'libc++', u'libc++ Documentation',
- [u'LLVM project'], 1)
-]
+man_pages = [("contents", "libc++", "libc++ Documentation", ["LLVM project"], 1)]
# If true, show URL addresses after external links.
-#man_show_urls = False
+# man_show_urls = False
# -- Options for Texinfo output ------------------------------------------------
@@ -227,19 +221,25 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
- ('contents', 'libc++', u'libc++ Documentation',
- u'LLVM project', 'libc++', 'One line description of project.',
- 'Miscellaneous'),
+ (
+ "contents",
+ "libc++",
+ "libc++ Documentation",
+ "LLVM project",
+ "libc++",
+ "One line description of project.",
+ "Miscellaneous",
+ ),
]
# Documents to append as an appendix to all manuals.
-#texinfo_appendices = []
+# texinfo_appendices = []
# If false, no module index is generated.
-#texinfo_domain_indices = True
+# texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
-#texinfo_show_urls = 'footnote'
+# texinfo_show_urls = 'footnote'
# FIXME: Define intersphinx configuration.
diff --git a/libcxx/test/libcxx/experimental/lit.local.cfg b/libcxx/test/libcxx/experimental/lit.local.cfg
index 5e2c632..ebfaa02 100644
--- a/libcxx/test/libcxx/experimental/lit.local.cfg
+++ b/libcxx/test/libcxx/experimental/lit.local.cfg
@@ -1,3 +1,3 @@
# Disable all of the experimental tests if the correct feature is not available.
-if 'c++experimental' not in config.available_features:
- config.unsupported = True
+if "c++experimental" not in config.available_features:
+ config.unsupported = True
diff --git a/libcxx/test/libcxx/gdb/gdb_pretty_printer_test.py b/libcxx/test/libcxx/gdb/gdb_pretty_printer_test.py
index c64efa3..ddb58a8 100644
--- a/libcxx/test/libcxx/gdb/gdb_pretty_printer_test.py
+++ b/libcxx/test/libcxx/gdb/gdb_pretty_printer_test.py
@@ -1,10 +1,10 @@
-#===----------------------------------------------------------------------===##
+# ===----------------------------------------------------------------------===##
#
# 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
#
-#===----------------------------------------------------------------------===##
+# ===----------------------------------------------------------------------===##
"""Commands used to automate testing gdb pretty printers.
This script is part of a larger framework to test gdb pretty printers. It
@@ -31,10 +31,8 @@ has_run_tests = False
class CheckResult(gdb.Command):
-
def __init__(self):
- super(CheckResult, self).__init__(
- "print_and_compare", gdb.COMMAND_DATA)
+ super(CheckResult, self).__init__("print_and_compare", gdb.COMMAND_DATA)
def invoke(self, arg, from_tty):
global has_run_tests
@@ -55,7 +53,7 @@ class CheckResult(gdb.Command):
value_str = self._get_value_string(compare_frame, testcase_frame)
# Ignore the convenience variable name and newline
- value = value_str[value_str.find("= ") + 2:-1]
+ value = value_str[value_str.find("= ") + 2 : -1]
gdb.newest_frame().select()
expectation_val = compare_frame.read_var("expectation")
check_literal = expectation_val.string(encoding="utf-8")
@@ -66,16 +64,14 @@ class CheckResult(gdb.Command):
if test_fails:
global test_failures
- print("FAIL: " + test_loc.symtab.filename +
- ":" + str(test_loc.line))
+ print("FAIL: " + test_loc.symtab.filename + ":" + str(test_loc.line))
print("GDB printed:")
print(" " + repr(value))
print("Value should match:")
print(" " + repr(check_literal))
test_failures += 1
else:
- print("PASS: " + test_loc.symtab.filename +
- ":" + str(test_loc.line))
+ print("PASS: " + test_loc.symtab.filename + ":" + str(test_loc.line))
except RuntimeError as e:
# At this point, lots of different things could be wrong, so don't try to
diff --git a/libcxx/test/libcxx/input.output/file.streams/lit.local.cfg b/libcxx/test/libcxx/input.output/file.streams/lit.local.cfg
index b89e35b..495f1cc 100644
--- a/libcxx/test/libcxx/input.output/file.streams/lit.local.cfg
+++ b/libcxx/test/libcxx/input.output/file.streams/lit.local.cfg
@@ -1,6 +1,7 @@
# Load the same local configuration as the corresponding one in libcxx/test/std
import os
-inLibcxx = os.path.join('libcxx', 'test', 'libcxx')
-inStd = os.path.join('libcxx', 'test', 'std')
+
+inLibcxx = os.path.join("libcxx", "test", "libcxx")
+inStd = os.path.join("libcxx", "test", "std")
localConfig = os.path.normpath(os.path.realpath(__file__)).replace(inLibcxx, inStd)
config.load_from_path(localConfig, lit_config)
diff --git a/libcxx/test/libcxx/input.output/filesystems/lit.local.cfg b/libcxx/test/libcxx/input.output/filesystems/lit.local.cfg
index 4eadb33..df91de1 100644
--- a/libcxx/test/libcxx/input.output/filesystems/lit.local.cfg
+++ b/libcxx/test/libcxx/input.output/filesystems/lit.local.cfg
@@ -1,4 +1,7 @@
# Load the same local configuration as the filesystem tests in libcxx/test/std
import os
-std_filesystem_tests = os.path.join(config.test_source_root, 'std', 'input.output', 'filesystems')
-config.load_from_path(os.path.join(std_filesystem_tests, 'lit.local.cfg'), lit_config)
+
+std_filesystem_tests = os.path.join(
+ config.test_source_root, "std", "input.output", "filesystems"
+)
+config.load_from_path(os.path.join(std_filesystem_tests, "lit.local.cfg"), lit_config)
diff --git a/libcxx/test/libcxx/input.output/iostream.format/lit.local.cfg b/libcxx/test/libcxx/input.output/iostream.format/lit.local.cfg
index b89e35b..495f1cc 100644
--- a/libcxx/test/libcxx/input.output/iostream.format/lit.local.cfg
+++ b/libcxx/test/libcxx/input.output/iostream.format/lit.local.cfg
@@ -1,6 +1,7 @@
# Load the same local configuration as the corresponding one in libcxx/test/std
import os
-inLibcxx = os.path.join('libcxx', 'test', 'libcxx')
-inStd = os.path.join('libcxx', 'test', 'std')
+
+inLibcxx = os.path.join("libcxx", "test", "libcxx")
+inStd = os.path.join("libcxx", "test", "std")
localConfig = os.path.normpath(os.path.realpath(__file__)).replace(inLibcxx, inStd)
config.load_from_path(localConfig, lit_config)
diff --git a/libcxx/test/libcxx/input.output/iostream.objects/lit.local.cfg b/libcxx/test/libcxx/input.output/iostream.objects/lit.local.cfg
index b89e35b..495f1cc 100644
--- a/libcxx/test/libcxx/input.output/iostream.objects/lit.local.cfg
+++ b/libcxx/test/libcxx/input.output/iostream.objects/lit.local.cfg
@@ -1,6 +1,7 @@
# Load the same local configuration as the corresponding one in libcxx/test/std
import os
-inLibcxx = os.path.join('libcxx', 'test', 'libcxx')
-inStd = os.path.join('libcxx', 'test', 'std')
+
+inLibcxx = os.path.join("libcxx", "test", "libcxx")
+inStd = os.path.join("libcxx", "test", "std")
localConfig = os.path.normpath(os.path.realpath(__file__)).replace(inLibcxx, inStd)
config.load_from_path(localConfig, lit_config)
diff --git a/libcxx/test/libcxx/input.output/iostreams.base/lit.local.cfg b/libcxx/test/libcxx/input.output/iostreams.base/lit.local.cfg
index b89e35b..495f1cc 100644
--- a/libcxx/test/libcxx/input.output/iostreams.base/lit.local.cfg
+++ b/libcxx/test/libcxx/input.output/iostreams.base/lit.local.cfg
@@ -1,6 +1,7 @@
# Load the same local configuration as the corresponding one in libcxx/test/std
import os
-inLibcxx = os.path.join('libcxx', 'test', 'libcxx')
-inStd = os.path.join('libcxx', 'test', 'std')
+
+inLibcxx = os.path.join("libcxx", "test", "libcxx")
+inStd = os.path.join("libcxx", "test", "std")
localConfig = os.path.normpath(os.path.realpath(__file__)).replace(inLibcxx, inStd)
config.load_from_path(localConfig, lit_config)
diff --git a/libcxx/test/libcxx/input.output/stream.buffers/lit.local.cfg b/libcxx/test/libcxx/input.output/stream.buffers/lit.local.cfg
index b89e35b..495f1cc 100644
--- a/libcxx/test/libcxx/input.output/stream.buffers/lit.local.cfg
+++ b/libcxx/test/libcxx/input.output/stream.buffers/lit.local.cfg
@@ -1,6 +1,7 @@
# Load the same local configuration as the corresponding one in libcxx/test/std
import os
-inLibcxx = os.path.join('libcxx', 'test', 'libcxx')
-inStd = os.path.join('libcxx', 'test', 'std')
+
+inLibcxx = os.path.join("libcxx", "test", "libcxx")
+inStd = os.path.join("libcxx", "test", "std")
localConfig = os.path.normpath(os.path.realpath(__file__)).replace(inLibcxx, inStd)
config.load_from_path(localConfig, lit_config)
diff --git a/libcxx/test/libcxx/input.output/string.streams/lit.local.cfg b/libcxx/test/libcxx/input.output/string.streams/lit.local.cfg
index b89e35b..495f1cc 100644
--- a/libcxx/test/libcxx/input.output/string.streams/lit.local.cfg
+++ b/libcxx/test/libcxx/input.output/string.streams/lit.local.cfg
@@ -1,6 +1,7 @@
# Load the same local configuration as the corresponding one in libcxx/test/std
import os
-inLibcxx = os.path.join('libcxx', 'test', 'libcxx')
-inStd = os.path.join('libcxx', 'test', 'std')
+
+inLibcxx = os.path.join("libcxx", "test", "libcxx")
+inStd = os.path.join("libcxx", "test", "std")
localConfig = os.path.normpath(os.path.realpath(__file__)).replace(inLibcxx, inStd)
config.load_from_path(localConfig, lit_config)
diff --git a/libcxx/test/libcxx/lint/lint_cmakelists.sh.py b/libcxx/test/libcxx/lint/lint_cmakelists.sh.py
index 1a94b44b..417f9ac 100644
--- a/libcxx/test/libcxx/lint/lint_cmakelists.sh.py
+++ b/libcxx/test/libcxx/lint/lint_cmakelists.sh.py
@@ -6,25 +6,25 @@
import os
-if __name__ == '__main__':
+if __name__ == "__main__":
libcxx_test_libcxx_lint = os.path.dirname(os.path.abspath(__file__))
- libcxx = os.path.abspath(os.path.join(libcxx_test_libcxx_lint, '../../..'))
- cmakelists_name = os.path.join(libcxx, 'include/CMakeLists.txt')
+ libcxx = os.path.abspath(os.path.join(libcxx_test_libcxx_lint, "../../.."))
+ cmakelists_name = os.path.join(libcxx, "include/CMakeLists.txt")
assert os.path.isfile(cmakelists_name)
- with open(cmakelists_name, 'r') as f:
+ with open(cmakelists_name, "r") as f:
lines = f.readlines()
- assert lines[0] == 'set(files\n'
+ assert lines[0] == "set(files\n"
okay = True
prevline = lines[1]
for line in lines[2:]:
- if (line == ' )\n'):
+ if line == " )\n":
break
- if (line < prevline):
+ if line < prevline:
okay = False
- print('LINES OUT OF ORDER in libcxx/include/CMakeLists.txt!')
+ print("LINES OUT OF ORDER in libcxx/include/CMakeLists.txt!")
print(prevline)
print(line)
prevline = line
diff --git a/libcxx/test/libcxx/lint/lint_headers.sh.py b/libcxx/test/libcxx/lint/lint_headers.sh.py
index 173f98b..ab237c9 100644
--- a/libcxx/test/libcxx/lint/lint_headers.sh.py
+++ b/libcxx/test/libcxx/lint/lint_headers.sh.py
@@ -10,45 +10,52 @@ import re
def exclude_from_consideration(path):
return (
- path.endswith('.txt') or
- path.endswith('.modulemap.in') or
- os.path.basename(path) == '__config' or
- os.path.basename(path) == '__config_site.in' or
- os.path.basename(path) == 'libcxx.imp' or
- os.path.basename(path).startswith('__pstl') or # TODO: Remove once PSTL integration is finished
- not os.path.isfile(path)
+ path.endswith(".txt")
+ or path.endswith(".modulemap.in")
+ or os.path.basename(path) == "__config"
+ or os.path.basename(path) == "__config_site.in"
+ or os.path.basename(path) == "libcxx.imp"
+ or os.path.basename(path).startswith("__pstl")
+ or not os.path.isfile(path) # TODO: Remove once PSTL integration is finished
)
def check_for_pragma_GCC_system_header(pretty_fname, lines):
- if pretty_fname not in ['__undef_macros']:
+ if pretty_fname not in ["__undef_macros"]:
for line in lines:
- if re.match('# *pragma GCC system_header\n', line):
+ if re.match("# *pragma GCC system_header\n", line):
return True
- print('FAILED TO FIND # pragma GCC system_header in libcxx/include/%s' % pretty_fname)
+ print(
+ "FAILED TO FIND # pragma GCC system_header in libcxx/include/%s"
+ % pretty_fname
+ )
return False
return True
-if __name__ == '__main__':
+if __name__ == "__main__":
libcxx_test_libcxx_lint = os.path.dirname(os.path.abspath(__file__))
- libcxx_include = os.path.abspath(os.path.join(libcxx_test_libcxx_lint, '../../../include'))
+ libcxx_include = os.path.abspath(
+ os.path.join(libcxx_test_libcxx_lint, "../../../include")
+ )
assert os.path.isdir(libcxx_include)
def pretty(path):
- return path[len(libcxx_include) + 1:]
+ return path[len(libcxx_include) + 1 :]
all_headers = [
- p for p in (
- glob.glob(os.path.join(libcxx_include, '*')) +
- glob.glob(os.path.join(libcxx_include, '__*/*.h'))
- ) if not exclude_from_consideration(p)
+ p
+ for p in (
+ glob.glob(os.path.join(libcxx_include, "*"))
+ + glob.glob(os.path.join(libcxx_include, "__*/*.h"))
+ )
+ if not exclude_from_consideration(p)
]
okay = True
for fname in all_headers:
pretty_fname = pretty(fname)
- with open(fname, 'r') as f:
+ with open(fname, "r") as f:
lines = f.readlines()
okay = check_for_pragma_GCC_system_header(pretty_fname, lines) and okay
diff --git a/libcxx/test/libcxx/lint/lint_modulemap.sh.py b/libcxx/test/libcxx/lint/lint_modulemap.sh.py
index 85d2c4b..9610929 100755
--- a/libcxx/test/libcxx/lint/lint_modulemap.sh.py
+++ b/libcxx/test/libcxx/lint/lint_modulemap.sh.py
@@ -7,39 +7,53 @@ import os
import re
-if __name__ == '__main__':
+if __name__ == "__main__":
libcxx_test_libcxx_lint = os.path.dirname(os.path.abspath(__file__))
- libcxx = os.path.abspath(os.path.join(libcxx_test_libcxx_lint, '../../..'))
- modulemap_name = os.path.join(libcxx, 'include/module.modulemap.in')
+ libcxx = os.path.abspath(os.path.join(libcxx_test_libcxx_lint, "../../.."))
+ modulemap_name = os.path.join(libcxx, "include/module.modulemap.in")
assert os.path.isfile(modulemap_name)
okay = True
prevline = None
- with open(modulemap_name, 'r') as f:
+ with open(modulemap_name, "r") as f:
for line in f.readlines():
- if re.match(r'^\s*module.*[{]\s*private', line):
+ if re.match(r"^\s*module.*[{]\s*private", line):
# Check that these lines are all of the expected format.
# This incidentally checks for typos in the module name.
- if re.match(r'^\s*module (\w+)\s+[{] private header "\1(.h)?"\s+export [*] [}]', line):
+ if re.match(
+ r'^\s*module (\w+)\s+[{] private header "\1(.h)?"\s+export [*] [}]',
+ line,
+ ):
# It's a top-level private header, such as <__bit_reference>.
pass
- elif re.match(r'^\s*module (\w+)\s+[{] private (textual )?header "__(\w+/)*\1[.]h" [}]', line):
+ elif re.match(
+ r'^\s*module (\w+)\s+[{] private (textual )?header "__(\w+/)*\1[.]h" [}]',
+ line,
+ ):
# It's a private submodule, such as <__utility/swap.h>.
pass
- elif re.match(r'^\s*module (\w+)_fwd\s+[{] private header "__fwd/\1[.]h" [}]', line):
+ elif re.match(
+ r'^\s*module (\w+)_fwd\s+[{] private header "__fwd/\1[.]h" [}]',
+ line,
+ ):
# It's a private submodule with forward declarations, such as <__fwd/span.h>.
pass
- elif re.match(r'^\s*module (?:\w+_)*(\w+)\s+[{] private (textual )?header "__(\w+/)*\1[.]h" [}]', line):
+ elif re.match(
+ r'^\s*module (?:\w+_)*(\w+)\s+[{] private (textual )?header "__(\w+/)*\1[.]h" [}]',
+ line,
+ ):
# It's a private pstl submodule, such as <__algorithm/pstl_backends/cpu_backend.h>
pass
else:
okay = False
- print("LINE DOESN'T MATCH REGEX in libcxx/include/module.modulemap.in!")
+ print(
+ "LINE DOESN'T MATCH REGEX in libcxx/include/module.modulemap.in!"
+ )
print(line)
# Check that these lines are alphabetized.
if (prevline is not None) and (line < prevline):
okay = False
- print('LINES OUT OF ORDER in libcxx/include/module.modulemap.in!')
+ print("LINES OUT OF ORDER in libcxx/include/module.modulemap.in!")
print(prevline)
print(line)
prevline = line
diff --git a/libcxx/test/libcxx/lit.local.cfg b/libcxx/test/libcxx/lit.local.cfg
index f328db3..1473673 100644
--- a/libcxx/test/libcxx/lit.local.cfg
+++ b/libcxx/test/libcxx/lit.local.cfg
@@ -1,3 +1,4 @@
# The tests in this directory need to run Python
import pipes, sys
-config.substitutions.append(('%{python}', pipes.quote(sys.executable)))
+
+config.substitutions.append(("%{python}", pipes.quote(sys.executable)))
diff --git a/libcxx/test/libcxx/localization/lit.local.cfg b/libcxx/test/libcxx/localization/lit.local.cfg
index b89e35b..495f1cc 100644
--- a/libcxx/test/libcxx/localization/lit.local.cfg
+++ b/libcxx/test/libcxx/localization/lit.local.cfg
@@ -1,6 +1,7 @@
# Load the same local configuration as the corresponding one in libcxx/test/std
import os
-inLibcxx = os.path.join('libcxx', 'test', 'libcxx')
-inStd = os.path.join('libcxx', 'test', 'std')
+
+inLibcxx = os.path.join("libcxx", "test", "libcxx")
+inStd = os.path.join("libcxx", "test", "std")
localConfig = os.path.normpath(os.path.realpath(__file__)).replace(inLibcxx, inStd)
config.load_from_path(localConfig, lit_config)
diff --git a/libcxx/test/libcxx/selftest/additional_compile_flags/lit.local.cfg b/libcxx/test/libcxx/selftest/additional_compile_flags/lit.local.cfg
index 44618de..fdddd89 100644
--- a/libcxx/test/libcxx/selftest/additional_compile_flags/lit.local.cfg
+++ b/libcxx/test/libcxx/selftest/additional_compile_flags/lit.local.cfg
@@ -1,2 +1,2 @@
# Add a Lit feature so we can test conditional addition of compile flags.
-config.available_features.add('some-defined-feature')
+config.available_features.add("some-defined-feature")
diff --git a/libcxx/test/libcxx/selftest/dsl/dsl.sh.py b/libcxx/test/libcxx/selftest/dsl/dsl.sh.py
index 81fb60a..dfe290b 100644
--- a/libcxx/test/libcxx/selftest/dsl/dsl.sh.py
+++ b/libcxx/test/libcxx/selftest/dsl/dsl.sh.py
@@ -1,10 +1,10 @@
-#===----------------------------------------------------------------------===##
+# ===----------------------------------------------------------------------===##
#
# 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
#
-#===----------------------------------------------------------------------===##
+# ===----------------------------------------------------------------------===##
# Note: We prepend arguments with 'x' to avoid thinking there are too few
# arguments in case an argument is an empty string.
@@ -23,15 +23,17 @@ from os.path import dirname
# Allow importing 'lit' and the 'libcxx' module. Make sure we put the lit
# path first so we don't find any system-installed version.
monorepoRoot = dirname(dirname(dirname(dirname(dirname(dirname(__file__))))))
-sys.path = [os.path.join(monorepoRoot, 'libcxx', 'utils'),
- os.path.join(monorepoRoot, 'llvm', 'utils', 'lit')] + sys.path
+sys.path = [
+ os.path.join(monorepoRoot, "libcxx", "utils"),
+ os.path.join(monorepoRoot, "llvm", "utils", "lit"),
+] + sys.path
import libcxx.test.dsl as dsl
import lit.LitConfig
import lit.util
# Steal some parameters from the config running this test so that we can
# bootstrap our own TestingConfig.
-args = list(map(lambda s: s[1:], sys.argv[1:8])) # Remove the leading 'x'
+args = list(map(lambda s: s[1:], sys.argv[1:8])) # Remove the leading 'x'
SOURCE_ROOT, EXEC_PATH, SUBSTITUTIONS = args
sys.argv[1:8] = []
@@ -40,10 +42,12 @@ SUBSTITUTIONS = pickle.loads(base64.b64decode(SUBSTITUTIONS))
for s, sub in SUBSTITUTIONS:
print("Substitution '{}' is '{}'".format(s, sub))
+
class SetupConfigs(unittest.TestCase):
"""
Base class for the tests below -- it creates a fake TestingConfig.
"""
+
def setUp(self):
"""
Create a fake TestingConfig that can be populated however we wish for
@@ -51,7 +55,7 @@ class SetupConfigs(unittest.TestCase):
minimum required substitutions.
"""
self.litConfig = lit.LitConfig.LitConfig(
- progname='lit',
+ progname="lit",
path=[],
quiet=False,
useValgrind=False,
@@ -59,9 +63,10 @@ class SetupConfigs(unittest.TestCase):
valgrindArgs=[],
noExecute=False,
debug=False,
- isWindows=platform.system() == 'Windows',
- order='smart',
- params={})
+ isWindows=platform.system() == "Windows",
+ order="smart",
+ params={},
+ )
self.config = lit.TestingConfig.TestingConfig.fromdefaults(self.litConfig)
self.config.environment = dict(os.environ)
@@ -82,7 +87,7 @@ class SetupConfigs(unittest.TestCase):
def findIndex(list, pred):
"""Finds the index of the first element satisfying 'pred' in a list, or
- 'len(list)' if there is no such element."""
+ 'len(list)' if there is no such element."""
index = 0
for x in list:
if pred(x):
@@ -96,23 +101,27 @@ class TestHasCompileFlag(SetupConfigs):
"""
Tests for libcxx.test.dsl.hasCompileFlag
"""
+
def test_no_flag_should_work(self):
- self.assertTrue(dsl.hasCompileFlag(self.config, ''))
+ self.assertTrue(dsl.hasCompileFlag(self.config, ""))
def test_flag_exists(self):
- self.assertTrue(dsl.hasCompileFlag(self.config, '-O1'))
+ self.assertTrue(dsl.hasCompileFlag(self.config, "-O1"))
def test_nonexistent_flag(self):
- self.assertFalse(dsl.hasCompileFlag(self.config, '-this_is_not_a_flag_any_compiler_has'))
+ self.assertFalse(
+ dsl.hasCompileFlag(self.config, "-this_is_not_a_flag_any_compiler_has")
+ )
def test_multiple_flags(self):
- self.assertTrue(dsl.hasCompileFlag(self.config, '-O1 -Dhello'))
+ self.assertTrue(dsl.hasCompileFlag(self.config, "-O1 -Dhello"))
class TestSourceBuilds(SetupConfigs):
"""
Tests for libcxx.test.dsl.sourceBuilds
"""
+
def test_valid_program_builds(self):
source = """int main(int, char**) { return 0; }"""
self.assertTrue(dsl.sourceBuilds(self.config, source))
@@ -131,6 +140,7 @@ class TestProgramOutput(SetupConfigs):
"""
Tests for libcxx.test.dsl.programOutput
"""
+
def test_valid_program_returns_output(self):
source = """
#include <cstdio>
@@ -156,14 +166,20 @@ class TestProgramOutput(SetupConfigs):
source = """
int main(int, char**) { return 1; }
"""
- self.assertRaises(dsl.ConfigurationRuntimeError, lambda: dsl.programOutput(self.config, source))
+ self.assertRaises(
+ dsl.ConfigurationRuntimeError,
+ lambda: dsl.programOutput(self.config, source),
+ )
def test_program_that_fails_to_compile_raises_compilation_error(self):
# The program doesn't compile
source = """
int main(int, char**) { this doesnt compile }
"""
- self.assertRaises(dsl.ConfigurationCompilationError, lambda: dsl.programOutput(self.config, source))
+ self.assertRaises(
+ dsl.ConfigurationCompilationError,
+ lambda: dsl.programOutput(self.config, source),
+ )
def test_pass_arguments_to_program(self):
source = """
@@ -191,14 +207,22 @@ class TestProgramOutput(SetupConfigs):
return 0;
}
"""
- compileFlagsIndex = findIndex(self.config.substitutions, lambda x: x[0] == '%{compile_flags}')
+ compileFlagsIndex = findIndex(
+ self.config.substitutions, lambda x: x[0] == "%{compile_flags}"
+ )
compileFlags = self.config.substitutions[compileFlagsIndex][1]
- self.config.substitutions[compileFlagsIndex] = ('%{compile_flags}', compileFlags + ' -DMACRO=1')
+ self.config.substitutions[compileFlagsIndex] = (
+ "%{compile_flags}",
+ compileFlags + " -DMACRO=1",
+ )
output1 = dsl.programOutput(self.config, source)
self.assertEqual(output1, "MACRO=1\n")
- self.config.substitutions[compileFlagsIndex] = ('%{compile_flags}', compileFlags + ' -DMACRO=2')
+ self.config.substitutions[compileFlagsIndex] = (
+ "%{compile_flags}",
+ compileFlags + " -DMACRO=2",
+ )
output2 = dsl.programOutput(self.config, source)
self.assertEqual(output2, "MACRO=2\n")
@@ -220,6 +244,7 @@ class TestProgramSucceeds(SetupConfigs):
"""
Tests for libcxx.test.dsl.programSucceeds
"""
+
def test_success(self):
source = """
int main(int, char**) { return 0; }
@@ -236,33 +261,47 @@ class TestProgramSucceeds(SetupConfigs):
source = """
this does not compile
"""
- self.assertRaises(dsl.ConfigurationCompilationError, lambda: dsl.programSucceeds(self.config, source))
+ self.assertRaises(
+ dsl.ConfigurationCompilationError,
+ lambda: dsl.programSucceeds(self.config, source),
+ )
+
class TestHasLocale(SetupConfigs):
"""
Tests for libcxx.test.dsl.hasLocale
"""
+
def test_doesnt_explode(self):
# It's really hard to test that a system has a given locale, so at least
# make sure we don't explode when we try to check it.
try:
- dsl.hasAnyLocale(self.config, ['en_US.UTF-8'])
+ dsl.hasAnyLocale(self.config, ["en_US.UTF-8"])
except subprocess.CalledProcessError:
self.fail("checking for hasLocale should not explode")
def test_nonexistent_locale(self):
- self.assertFalse(dsl.hasAnyLocale(self.config, ['forsurethisisnotanexistinglocale']))
+ self.assertFalse(
+ dsl.hasAnyLocale(self.config, ["forsurethisisnotanexistinglocale"])
+ )
def test_localization_program_doesnt_compile(self):
- compilerIndex = findIndex(self.config.substitutions, lambda x: x[0] == '%{cxx}')
- self.config.substitutions[compilerIndex] = ('%{cxx}', 'this-is-certainly-not-a-valid-compiler!!')
- self.assertRaises(dsl.ConfigurationCompilationError, lambda: dsl.hasAnyLocale(self.config, ['en_US.UTF-8']))
+ compilerIndex = findIndex(self.config.substitutions, lambda x: x[0] == "%{cxx}")
+ self.config.substitutions[compilerIndex] = (
+ "%{cxx}",
+ "this-is-certainly-not-a-valid-compiler!!",
+ )
+ self.assertRaises(
+ dsl.ConfigurationCompilationError,
+ lambda: dsl.hasAnyLocale(self.config, ["en_US.UTF-8"]),
+ )
class TestCompilerMacros(SetupConfigs):
"""
Tests for libcxx.test.dsl.compilerMacros
"""
+
def test_basic(self):
macros = dsl.compilerMacros(self.config)
self.assertIsInstance(macros, dict)
@@ -273,28 +312,29 @@ class TestCompilerMacros(SetupConfigs):
def test_no_flag(self):
macros = dsl.compilerMacros(self.config)
- self.assertIn('__cplusplus', macros.keys())
+ self.assertIn("__cplusplus", macros.keys())
def test_empty_flag(self):
- macros = dsl.compilerMacros(self.config, '')
- self.assertIn('__cplusplus', macros.keys())
+ macros = dsl.compilerMacros(self.config, "")
+ self.assertIn("__cplusplus", macros.keys())
def test_with_flag(self):
- macros = dsl.compilerMacros(self.config, '-DFOO=3')
- self.assertIn('__cplusplus', macros.keys())
- self.assertEqual(macros['FOO'], '3')
+ macros = dsl.compilerMacros(self.config, "-DFOO=3")
+ self.assertIn("__cplusplus", macros.keys())
+ self.assertEqual(macros["FOO"], "3")
def test_with_flags(self):
- macros = dsl.compilerMacros(self.config, '-DFOO=3 -DBAR=hello')
- self.assertIn('__cplusplus', macros.keys())
- self.assertEqual(macros['FOO'], '3')
- self.assertEqual(macros['BAR'], 'hello')
+ macros = dsl.compilerMacros(self.config, "-DFOO=3 -DBAR=hello")
+ self.assertIn("__cplusplus", macros.keys())
+ self.assertEqual(macros["FOO"], "3")
+ self.assertEqual(macros["BAR"], "hello")
class TestFeatureTestMacros(SetupConfigs):
"""
Tests for libcxx.test.dsl.featureTestMacros
"""
+
def test_basic(self):
macros = dsl.featureTestMacros(self.config)
self.assertIsInstance(macros, dict)
@@ -308,21 +348,22 @@ class TestFeature(SetupConfigs):
"""
Tests for libcxx.test.dsl.Feature
"""
+
def test_trivial(self):
- feature = dsl.Feature(name='name')
+ feature = dsl.Feature(name="name")
origSubstitutions = copy.deepcopy(self.config.substitutions)
actions = feature.getActions(self.config)
self.assertTrue(len(actions) == 1)
for a in actions:
a.applyTo(self.config)
self.assertEqual(origSubstitutions, self.config.substitutions)
- self.assertIn('name', self.config.available_features)
+ self.assertIn("name", self.config.available_features)
def test_name_can_be_a_callable(self):
- feature = dsl.Feature(name=lambda cfg: 'name')
+ feature = dsl.Feature(name=lambda cfg: "name")
for a in feature.getActions(self.config):
a.applyTo(self.config)
- self.assertIn('name', self.config.available_features)
+ self.assertIn("name", self.config.available_features)
def test_name_is_not_a_string_1(self):
feature = dsl.Feature(name=None)
@@ -335,159 +376,250 @@ class TestFeature(SetupConfigs):
self.assertRaises(ValueError, lambda: feature.pretty(self.config))
def test_adding_action(self):
- feature = dsl.Feature(name='name', actions=[dsl.AddCompileFlag('-std=c++03')])
- origLinkFlags = copy.deepcopy(self.getSubstitution('%{link_flags}'))
+ feature = dsl.Feature(name="name", actions=[dsl.AddCompileFlag("-std=c++03")])
+ origLinkFlags = copy.deepcopy(self.getSubstitution("%{link_flags}"))
for a in feature.getActions(self.config):
a.applyTo(self.config)
- self.assertIn('name', self.config.available_features)
- self.assertIn('-std=c++03', self.getSubstitution('%{compile_flags}'))
- self.assertEqual(origLinkFlags, self.getSubstitution('%{link_flags}'))
+ self.assertIn("name", self.config.available_features)
+ self.assertIn("-std=c++03", self.getSubstitution("%{compile_flags}"))
+ self.assertEqual(origLinkFlags, self.getSubstitution("%{link_flags}"))
def test_actions_can_be_a_callable(self):
- feature = dsl.Feature(name='name',
- actions=lambda cfg: (
- self.assertIs(self.config, cfg),
- [dsl.AddCompileFlag('-std=c++03')]
- )[1])
+ feature = dsl.Feature(
+ name="name",
+ actions=lambda cfg: (
+ self.assertIs(self.config, cfg),
+ [dsl.AddCompileFlag("-std=c++03")],
+ )[1],
+ )
for a in feature.getActions(self.config):
a.applyTo(self.config)
- self.assertIn('-std=c++03', self.getSubstitution('%{compile_flags}'))
+ self.assertIn("-std=c++03", self.getSubstitution("%{compile_flags}"))
def test_unsupported_feature(self):
- feature = dsl.Feature(name='name', when=lambda _: False)
+ feature = dsl.Feature(name="name", when=lambda _: False)
self.assertEqual(feature.getActions(self.config), [])
def test_is_supported_gets_passed_the_config(self):
- feature = dsl.Feature(name='name', when=lambda cfg: (self.assertIs(self.config, cfg), True)[1])
+ feature = dsl.Feature(
+ name="name", when=lambda cfg: (self.assertIs(self.config, cfg), True)[1]
+ )
self.assertEqual(len(feature.getActions(self.config)), 1)
def _throw():
raise ValueError()
+
class TestParameter(SetupConfigs):
"""
Tests for libcxx.test.dsl.Parameter
"""
+
def test_empty_name_should_blow_up(self):
- self.assertRaises(ValueError, lambda: dsl.Parameter(name='', choices=['c++03'], type=str, help='', actions=lambda _: []))
+ self.assertRaises(
+ ValueError,
+ lambda: dsl.Parameter(
+ name="", choices=["c++03"], type=str, help="", actions=lambda _: []
+ ),
+ )
def test_empty_choices_should_blow_up(self):
- self.assertRaises(ValueError, lambda: dsl.Parameter(name='std', choices=[], type=str, help='', actions=lambda _: []))
+ self.assertRaises(
+ ValueError,
+ lambda: dsl.Parameter(
+ name="std", choices=[], type=str, help="", actions=lambda _: []
+ ),
+ )
def test_no_choices_is_ok(self):
- param = dsl.Parameter(name='triple', type=str, help='', actions=lambda _: [])
- self.assertEqual(param.name, 'triple')
+ param = dsl.Parameter(name="triple", type=str, help="", actions=lambda _: [])
+ self.assertEqual(param.name, "triple")
def test_name_is_set_correctly(self):
- param = dsl.Parameter(name='std', choices=['c++03'], type=str, help='', actions=lambda _: [])
- self.assertEqual(param.name, 'std')
+ param = dsl.Parameter(
+ name="std", choices=["c++03"], type=str, help="", actions=lambda _: []
+ )
+ self.assertEqual(param.name, "std")
def test_no_value_provided_and_no_default_value(self):
- param = dsl.Parameter(name='std', choices=['c++03'], type=str, help='', actions=lambda _: [])
- self.assertRaises(ValueError, lambda: param.getActions(self.config, self.litConfig.params))
+ param = dsl.Parameter(
+ name="std", choices=["c++03"], type=str, help="", actions=lambda _: []
+ )
+ self.assertRaises(
+ ValueError, lambda: param.getActions(self.config, self.litConfig.params)
+ )
def test_no_value_provided_and_default_value(self):
- param = dsl.Parameter(name='std', choices=['c++03'], type=str, help='', default='c++03',
- actions=lambda std: [dsl.AddFeature(std)])
+ param = dsl.Parameter(
+ name="std",
+ choices=["c++03"],
+ type=str,
+ help="",
+ default="c++03",
+ actions=lambda std: [dsl.AddFeature(std)],
+ )
for a in param.getActions(self.config, self.litConfig.params):
a.applyTo(self.config)
- self.assertIn('c++03', self.config.available_features)
+ self.assertIn("c++03", self.config.available_features)
def test_value_provided_on_command_line_and_no_default_value(self):
- self.litConfig.params['std'] = 'c++03'
- param = dsl.Parameter(name='std', choices=['c++03'], type=str, help='',
- actions=lambda std: [dsl.AddFeature(std)])
+ self.litConfig.params["std"] = "c++03"
+ param = dsl.Parameter(
+ name="std",
+ choices=["c++03"],
+ type=str,
+ help="",
+ actions=lambda std: [dsl.AddFeature(std)],
+ )
for a in param.getActions(self.config, self.litConfig.params):
a.applyTo(self.config)
- self.assertIn('c++03', self.config.available_features)
+ self.assertIn("c++03", self.config.available_features)
def test_value_provided_on_command_line_and_default_value(self):
"""The value provided on the command line should override the default value"""
- self.litConfig.params['std'] = 'c++11'
- param = dsl.Parameter(name='std', choices=['c++03', 'c++11'], type=str, default='c++03', help='',
- actions=lambda std: [dsl.AddFeature(std)])
+ self.litConfig.params["std"] = "c++11"
+ param = dsl.Parameter(
+ name="std",
+ choices=["c++03", "c++11"],
+ type=str,
+ default="c++03",
+ help="",
+ actions=lambda std: [dsl.AddFeature(std)],
+ )
for a in param.getActions(self.config, self.litConfig.params):
a.applyTo(self.config)
- self.assertIn('c++11', self.config.available_features)
- self.assertNotIn('c++03', self.config.available_features)
+ self.assertIn("c++11", self.config.available_features)
+ self.assertNotIn("c++03", self.config.available_features)
def test_value_provided_in_config_and_default_value(self):
"""The value provided in the config should override the default value"""
- self.config.std ='c++11'
- param = dsl.Parameter(name='std', choices=['c++03', 'c++11'], type=str, default='c++03', help='',
- actions=lambda std: [dsl.AddFeature(std)])
+ self.config.std = "c++11"
+ param = dsl.Parameter(
+ name="std",
+ choices=["c++03", "c++11"],
+ type=str,
+ default="c++03",
+ help="",
+ actions=lambda std: [dsl.AddFeature(std)],
+ )
for a in param.getActions(self.config, self.litConfig.params):
a.applyTo(self.config)
- self.assertIn('c++11', self.config.available_features)
- self.assertNotIn('c++03', self.config.available_features)
+ self.assertIn("c++11", self.config.available_features)
+ self.assertNotIn("c++03", self.config.available_features)
def test_value_provided_in_config_and_on_command_line(self):
"""The value on the command line should override the one in the config"""
- self.config.std = 'c++11'
- self.litConfig.params['std'] = 'c++03'
- param = dsl.Parameter(name='std', choices=['c++03', 'c++11'], type=str, help='',
- actions=lambda std: [dsl.AddFeature(std)])
+ self.config.std = "c++11"
+ self.litConfig.params["std"] = "c++03"
+ param = dsl.Parameter(
+ name="std",
+ choices=["c++03", "c++11"],
+ type=str,
+ help="",
+ actions=lambda std: [dsl.AddFeature(std)],
+ )
for a in param.getActions(self.config, self.litConfig.params):
a.applyTo(self.config)
- self.assertIn('c++03', self.config.available_features)
- self.assertNotIn('c++11', self.config.available_features)
+ self.assertIn("c++03", self.config.available_features)
+ self.assertNotIn("c++11", self.config.available_features)
def test_no_actions(self):
- self.litConfig.params['std'] = 'c++03'
- param = dsl.Parameter(name='std', choices=['c++03'], type=str, help='',
- actions=lambda _: [])
+ self.litConfig.params["std"] = "c++03"
+ param = dsl.Parameter(
+ name="std", choices=["c++03"], type=str, help="", actions=lambda _: []
+ )
actions = param.getActions(self.config, self.litConfig.params)
self.assertEqual(actions, [])
def test_boolean_value_parsed_from_trueish_string_parameter(self):
- self.litConfig.params['enable_exceptions'] = "True"
- param = dsl.Parameter(name='enable_exceptions', choices=[True, False], type=bool, help='',
- actions=lambda exceptions: [] if exceptions else _throw())
+ self.litConfig.params["enable_exceptions"] = "True"
+ param = dsl.Parameter(
+ name="enable_exceptions",
+ choices=[True, False],
+ type=bool,
+ help="",
+ actions=lambda exceptions: [] if exceptions else _throw(),
+ )
self.assertEqual(param.getActions(self.config, self.litConfig.params), [])
def test_boolean_value_from_true_boolean_parameter(self):
- self.litConfig.params['enable_exceptions'] = True
- param = dsl.Parameter(name='enable_exceptions', choices=[True, False], type=bool, help='',
- actions=lambda exceptions: [] if exceptions else _throw())
+ self.litConfig.params["enable_exceptions"] = True
+ param = dsl.Parameter(
+ name="enable_exceptions",
+ choices=[True, False],
+ type=bool,
+ help="",
+ actions=lambda exceptions: [] if exceptions else _throw(),
+ )
self.assertEqual(param.getActions(self.config, self.litConfig.params), [])
def test_boolean_value_parsed_from_falseish_string_parameter(self):
- self.litConfig.params['enable_exceptions'] = "False"
- param = dsl.Parameter(name='enable_exceptions', choices=[True, False], type=bool, help='',
- actions=lambda exceptions: [] if exceptions else [dsl.AddFeature("-fno-exceptions")])
+ self.litConfig.params["enable_exceptions"] = "False"
+ param = dsl.Parameter(
+ name="enable_exceptions",
+ choices=[True, False],
+ type=bool,
+ help="",
+ actions=lambda exceptions: []
+ if exceptions
+ else [dsl.AddFeature("-fno-exceptions")],
+ )
for a in param.getActions(self.config, self.litConfig.params):
a.applyTo(self.config)
- self.assertIn('-fno-exceptions', self.config.available_features)
+ self.assertIn("-fno-exceptions", self.config.available_features)
def test_boolean_value_from_false_boolean_parameter(self):
- self.litConfig.params['enable_exceptions'] = False
- param = dsl.Parameter(name='enable_exceptions', choices=[True, False], type=bool, help='',
- actions=lambda exceptions: [] if exceptions else [dsl.AddFeature("-fno-exceptions")])
+ self.litConfig.params["enable_exceptions"] = False
+ param = dsl.Parameter(
+ name="enable_exceptions",
+ choices=[True, False],
+ type=bool,
+ help="",
+ actions=lambda exceptions: []
+ if exceptions
+ else [dsl.AddFeature("-fno-exceptions")],
+ )
for a in param.getActions(self.config, self.litConfig.params):
a.applyTo(self.config)
- self.assertIn('-fno-exceptions', self.config.available_features)
+ self.assertIn("-fno-exceptions", self.config.available_features)
def test_list_parsed_from_comma_delimited_string_empty(self):
- self.litConfig.params['additional_features'] = ""
- param = dsl.Parameter(name='additional_features', type=list, help='', actions=lambda f: f)
+ self.litConfig.params["additional_features"] = ""
+ param = dsl.Parameter(
+ name="additional_features", type=list, help="", actions=lambda f: f
+ )
self.assertEqual(param.getActions(self.config, self.litConfig.params), [])
def test_list_parsed_from_comma_delimited_string_1(self):
- self.litConfig.params['additional_features'] = "feature1"
- param = dsl.Parameter(name='additional_features', type=list, help='', actions=lambda f: f)
- self.assertEqual(param.getActions(self.config, self.litConfig.params), ['feature1'])
+ self.litConfig.params["additional_features"] = "feature1"
+ param = dsl.Parameter(
+ name="additional_features", type=list, help="", actions=lambda f: f
+ )
+ self.assertEqual(
+ param.getActions(self.config, self.litConfig.params), ["feature1"]
+ )
def test_list_parsed_from_comma_delimited_string_2(self):
- self.litConfig.params['additional_features'] = "feature1,feature2"
- param = dsl.Parameter(name='additional_features', type=list, help='', actions=lambda f: f)
- self.assertEqual(param.getActions(self.config, self.litConfig.params), ['feature1', 'feature2'])
+ self.litConfig.params["additional_features"] = "feature1,feature2"
+ param = dsl.Parameter(
+ name="additional_features", type=list, help="", actions=lambda f: f
+ )
+ self.assertEqual(
+ param.getActions(self.config, self.litConfig.params),
+ ["feature1", "feature2"],
+ )
def test_list_parsed_from_comma_delimited_string_3(self):
- self.litConfig.params['additional_features'] = "feature1,feature2, feature3"
- param = dsl.Parameter(name='additional_features', type=list, help='', actions=lambda f: f)
- self.assertEqual(param.getActions(self.config, self.litConfig.params), ['feature1', 'feature2', 'feature3'])
+ self.litConfig.params["additional_features"] = "feature1,feature2, feature3"
+ param = dsl.Parameter(
+ name="additional_features", type=list, help="", actions=lambda f: f
+ )
+ self.assertEqual(
+ param.getActions(self.config, self.litConfig.params),
+ ["feature1", "feature2", "feature3"],
+ )
-if __name__ == '__main__':
+if __name__ == "__main__":
unittest.main(verbosity=2)
diff --git a/libcxx/test/libcxx/selftest/dsl/lit.local.cfg b/libcxx/test/libcxx/selftest/dsl/lit.local.cfg
index ce4a323..352719b 100644
--- a/libcxx/test/libcxx/selftest/dsl/lit.local.cfg
+++ b/libcxx/test/libcxx/selftest/dsl/lit.local.cfg
@@ -9,6 +9,7 @@
# to pass it to the test, and we decode and unpickle the substitutions from
# within the test.
import base64, lit.util, pickle
+
base64Encode = lambda s: lit.util.to_string(base64.b64encode(lit.util.to_bytes(s)))
escapedSubstitutions = base64Encode(pickle.dumps(config.substitutions))
-config.substitutions.append(('%{substitutions}', escapedSubstitutions))
+config.substitutions.append(("%{substitutions}", escapedSubstitutions))
diff --git a/libcxx/test/libcxx/transitive_includes_to_csv.py b/libcxx/test/libcxx/transitive_includes_to_csv.py
index ad86ca7..97843ec 100755
--- a/libcxx/test/libcxx/transitive_includes_to_csv.py
+++ b/libcxx/test/libcxx/transitive_includes_to_csv.py
@@ -41,7 +41,8 @@ def parse_line(line: str) -> header:
# literal level.)
LIBCXX_HEADER_REGEX = r".*c\+\+(?:/|\\\\)v[0-9]+(?:/|\\\\)(.+)"
-def is_libcxx_public_header(header : str) -> bool:
+
+def is_libcxx_public_header(header: str) -> bool:
"""
Returns whether a header is a C++ public header file.
"""
@@ -62,7 +63,7 @@ def is_libcxx_public_header(header : str) -> bool:
return True
-def is_libcxx_header(header : str) -> bool:
+def is_libcxx_header(header: str) -> bool:
"""
Returns whether a header is a libc++ header, excluding the C-compatibility headers.
"""
@@ -73,7 +74,9 @@ def is_libcxx_header(header : str) -> bool:
# 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)):
+ if relative.endswith(".h") and not (
+ relative.startswith("__") or re.search(r"(/|\\\\)__", relative)
+ ):
return False
return True
@@ -130,7 +133,9 @@ def create_include_graph(path: pathlib.Path) -> List[str]:
# 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
+ 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.
diff --git a/libcxx/test/lit.cfg.py b/libcxx/test/lit.cfg.py
index 647464a..ea4a9a7 100644
--- a/libcxx/test/lit.cfg.py
+++ b/libcxx/test/lit.cfg.py
@@ -7,4 +7,5 @@
lit_config.fatal(
"You seem to be running Lit directly -- you should be running Lit through "
"<build>/bin/llvm-lit, which will ensure that the right Lit configuration "
- "file is used.")
+ "file is used."
+)
diff --git a/libcxx/test/std/depr/depr.ios.members/lit.local.cfg b/libcxx/test/std/depr/depr.ios.members/lit.local.cfg
index 3d9bcf3..fd1206b 100644
--- a/libcxx/test/std/depr/depr.ios.members/lit.local.cfg
+++ b/libcxx/test/std/depr/depr.ios.members/lit.local.cfg
@@ -1,2 +1,2 @@
-if 'no-localization' in config.available_features:
- config.unsupported = True
+if "no-localization" in config.available_features:
+ config.unsupported = True
diff --git a/libcxx/test/std/depr/depr.str.strstreams/lit.local.cfg b/libcxx/test/std/depr/depr.str.strstreams/lit.local.cfg
index 3d9bcf3..fd1206b 100644
--- a/libcxx/test/std/depr/depr.str.strstreams/lit.local.cfg
+++ b/libcxx/test/std/depr/depr.str.strstreams/lit.local.cfg
@@ -1,2 +1,2 @@
-if 'no-localization' in config.available_features:
- config.unsupported = True
+if "no-localization" in config.available_features:
+ config.unsupported = True
diff --git a/libcxx/test/std/experimental/lit.local.cfg b/libcxx/test/std/experimental/lit.local.cfg
index 5e2c632..ebfaa02 100644
--- a/libcxx/test/std/experimental/lit.local.cfg
+++ b/libcxx/test/std/experimental/lit.local.cfg
@@ -1,3 +1,3 @@
# Disable all of the experimental tests if the correct feature is not available.
-if 'c++experimental' not in config.available_features:
- config.unsupported = True
+if "c++experimental" not in config.available_features:
+ config.unsupported = True
diff --git a/libcxx/test/std/input.output/file.streams/lit.local.cfg b/libcxx/test/std/input.output/file.streams/lit.local.cfg
index c62247c..0abfd8b 100644
--- a/libcxx/test/std/input.output/file.streams/lit.local.cfg
+++ b/libcxx/test/std/input.output/file.streams/lit.local.cfg
@@ -1,6 +1,6 @@
# All non-trivial uses of iostreams require localization support
-if 'no-localization' in config.available_features:
- config.unsupported = True
+if "no-localization" in config.available_features:
+ config.unsupported = True
-if 'no-fstream' in config.available_features:
- config.unsupported = True
+if "no-fstream" in config.available_features:
+ config.unsupported = True
diff --git a/libcxx/test/std/input.output/filesystems/lit.local.cfg b/libcxx/test/std/input.output/filesystems/lit.local.cfg
index c2195962..6091761 100644
--- a/libcxx/test/std/input.output/filesystems/lit.local.cfg
+++ b/libcxx/test/std/input.output/filesystems/lit.local.cfg
@@ -1,5 +1,5 @@
-if 'availability-filesystem-missing' in config.available_features:
- config.unsupported = True
+if "availability-filesystem-missing" in config.available_features:
+ config.unsupported = True
-if 'no-filesystem' in config.available_features:
+if "no-filesystem" in config.available_features:
config.unsupported = True
diff --git a/libcxx/test/std/input.output/input.output.general/lit.local.cfg b/libcxx/test/std/input.output/input.output.general/lit.local.cfg
index 781b508..2cb1001 100644
--- a/libcxx/test/std/input.output/input.output.general/lit.local.cfg
+++ b/libcxx/test/std/input.output/input.output.general/lit.local.cfg
@@ -1,3 +1,3 @@
# All non-trivial uses of iostreams require localization support
-if 'no-localization' in config.available_features:
- config.unsupported = True
+if "no-localization" in config.available_features:
+ config.unsupported = True
diff --git a/libcxx/test/std/input.output/iostream.format/lit.local.cfg b/libcxx/test/std/input.output/iostream.format/lit.local.cfg
index 781b508..2cb1001 100644
--- a/libcxx/test/std/input.output/iostream.format/lit.local.cfg
+++ b/libcxx/test/std/input.output/iostream.format/lit.local.cfg
@@ -1,3 +1,3 @@
# All non-trivial uses of iostreams require localization support
-if 'no-localization' in config.available_features:
- config.unsupported = True
+if "no-localization" in config.available_features:
+ config.unsupported = True
diff --git a/libcxx/test/std/input.output/iostream.forward/lit.local.cfg b/libcxx/test/std/input.output/iostream.forward/lit.local.cfg
index 781b508..2cb1001 100644
--- a/libcxx/test/std/input.output/iostream.forward/lit.local.cfg
+++ b/libcxx/test/std/input.output/iostream.forward/lit.local.cfg
@@ -1,3 +1,3 @@
# All non-trivial uses of iostreams require localization support
-if 'no-localization' in config.available_features:
- config.unsupported = True
+if "no-localization" in config.available_features:
+ config.unsupported = True
diff --git a/libcxx/test/std/input.output/iostream.objects/lit.local.cfg b/libcxx/test/std/input.output/iostream.objects/lit.local.cfg
index 781b508..2cb1001 100644
--- a/libcxx/test/std/input.output/iostream.objects/lit.local.cfg
+++ b/libcxx/test/std/input.output/iostream.objects/lit.local.cfg
@@ -1,3 +1,3 @@
# All non-trivial uses of iostreams require localization support
-if 'no-localization' in config.available_features:
- config.unsupported = True
+if "no-localization" in config.available_features:
+ config.unsupported = True
diff --git a/libcxx/test/std/input.output/iostreams.base/lit.local.cfg b/libcxx/test/std/input.output/iostreams.base/lit.local.cfg
index 781b508..2cb1001 100644
--- a/libcxx/test/std/input.output/iostreams.base/lit.local.cfg
+++ b/libcxx/test/std/input.output/iostreams.base/lit.local.cfg
@@ -1,3 +1,3 @@
# All non-trivial uses of iostreams require localization support
-if 'no-localization' in config.available_features:
- config.unsupported = True
+if "no-localization" in config.available_features:
+ config.unsupported = True
diff --git a/libcxx/test/std/input.output/iostreams.requirements/lit.local.cfg b/libcxx/test/std/input.output/iostreams.requirements/lit.local.cfg
index 781b508..2cb1001 100644
--- a/libcxx/test/std/input.output/iostreams.requirements/lit.local.cfg
+++ b/libcxx/test/std/input.output/iostreams.requirements/lit.local.cfg
@@ -1,3 +1,3 @@
# All non-trivial uses of iostreams require localization support
-if 'no-localization' in config.available_features:
- config.unsupported = True
+if "no-localization" in config.available_features:
+ config.unsupported = True
diff --git a/libcxx/test/std/input.output/stream.buffers/lit.local.cfg b/libcxx/test/std/input.output/stream.buffers/lit.local.cfg
index 781b508..2cb1001 100644
--- a/libcxx/test/std/input.output/stream.buffers/lit.local.cfg
+++ b/libcxx/test/std/input.output/stream.buffers/lit.local.cfg
@@ -1,3 +1,3 @@
# All non-trivial uses of iostreams require localization support
-if 'no-localization' in config.available_features:
- config.unsupported = True
+if "no-localization" in config.available_features:
+ config.unsupported = True
diff --git a/libcxx/test/std/input.output/string.streams/lit.local.cfg b/libcxx/test/std/input.output/string.streams/lit.local.cfg
index 781b508..2cb1001 100644
--- a/libcxx/test/std/input.output/string.streams/lit.local.cfg
+++ b/libcxx/test/std/input.output/string.streams/lit.local.cfg
@@ -1,3 +1,3 @@
# All non-trivial uses of iostreams require localization support
-if 'no-localization' in config.available_features:
- config.unsupported = True
+if "no-localization" in config.available_features:
+ config.unsupported = True
diff --git a/libcxx/test/std/iterators/stream.iterators/lit.local.cfg b/libcxx/test/std/iterators/stream.iterators/lit.local.cfg
index 504efc6..b2119d9 100644
--- a/libcxx/test/std/iterators/stream.iterators/lit.local.cfg
+++ b/libcxx/test/std/iterators/stream.iterators/lit.local.cfg
@@ -1,3 +1,3 @@
# stream iterators rely on the streams library, which requires localization
-if 'no-localization' in config.available_features:
- config.unsupported = True
+if "no-localization" in config.available_features:
+ config.unsupported = True
diff --git a/libcxx/test/std/localization/lit.local.cfg b/libcxx/test/std/localization/lit.local.cfg
index de37401..d47f3e0 100644
--- a/libcxx/test/std/localization/lit.local.cfg
+++ b/libcxx/test/std/localization/lit.local.cfg
@@ -1,3 +1,3 @@
# <locale> tests are obviously not supported when localization support is disabled
-if 'no-localization' in config.available_features:
- config.unsupported = True
+if "no-localization" in config.available_features:
+ config.unsupported = True
diff --git a/libcxx/test/std/re/lit.local.cfg b/libcxx/test/std/re/lit.local.cfg
index 9626384..17db114 100644
--- a/libcxx/test/std/re/lit.local.cfg
+++ b/libcxx/test/std/re/lit.local.cfg
@@ -1,3 +1,3 @@
# Unfortunately, <regex> uses locales in regex_traits
-if 'no-localization' in config.available_features:
- config.unsupported = True
+if "no-localization" in config.available_features:
+ config.unsupported = True
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/lit.local.cfg b/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/lit.local.cfg
index 7780409..42a86f7 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/lit.local.cfg
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/lit.local.cfg
@@ -1,3 +1,3 @@
# These std::string functions require iostreams, which requires localization
-if 'no-localization' in config.available_features:
- config.unsupported = True
+if "no-localization" in config.available_features:
+ config.unsupported = True
diff --git a/libcxx/utils/cat_files.py b/libcxx/utils/cat_files.py
index ac4f386..77127cb 100755
--- a/libcxx/utils/cat_files.py
+++ b/libcxx/utils/cat_files.py
@@ -1,45 +1,51 @@
#!/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
#
-#===----------------------------------------------------------------------===##
+# ===----------------------------------------------------------------------===##
from argparse import ArgumentParser
import sys
+
def print_and_exit(msg):
- sys.stderr.write(msg + '\n')
+ sys.stderr.write(msg + "\n")
sys.exit(1)
+
def main():
- parser = ArgumentParser(
- description="Concatenate two files into a single file")
+ parser = ArgumentParser(description="Concatenate two files into a single file")
parser.add_argument(
- '-o', '--output', dest='output', required=True,
- help='The output file. stdout is used if not given',
- type=str, action='store')
+ "-o",
+ "--output",
+ dest="output",
+ required=True,
+ help="The output file. stdout is used if not given",
+ type=str,
+ action="store",
+ )
parser.add_argument(
- 'files', metavar='files', nargs='+',
- help='The files to concatenate')
+ "files", metavar="files", nargs="+", help="The files to concatenate"
+ )
args = parser.parse_args()
if len(args.files) < 2:
- print_and_exit('fewer than 2 inputs provided')
- data = ''
+ print_and_exit("fewer than 2 inputs provided")
+ data = ""
for filename in args.files:
- with open(filename, 'r') as f:
+ with open(filename, "r") as f:
data += f.read()
- if len(data) != 0 and data[-1] != '\n':
- data += '\n'
+ if len(data) != 0 and data[-1] != "\n":
+ data += "\n"
assert len(data) > 0 and "cannot cat empty files"
- with open(args.output, 'w') as f:
+ with open(args.output, "w") as f:
f.write(data)
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
sys.exit(0)
diff --git a/libcxx/utils/gdb/libcxx/printers.py b/libcxx/utils/gdb/libcxx/printers.py
index e62c367..251761a 100644
--- a/libcxx/utils/gdb/libcxx/printers.py
+++ b/libcxx/utils/gdb/libcxx/printers.py
@@ -1,10 +1,10 @@
-#===----------------------------------------------------------------------===##
+# ===----------------------------------------------------------------------===##
#
# 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
#
-#===----------------------------------------------------------------------===##
+# ===----------------------------------------------------------------------===##
"""GDB pretty-printers for libc++.
These should work for objects compiled with either the stable ABI or the unstable ABI.
@@ -29,6 +29,7 @@ _long_int_type = gdb.lookup_type("unsigned long long")
_libcpp_big_endian = False
+
def addr_as_long(addr):
return int(addr.cast(_long_int_type))
@@ -97,10 +98,11 @@ def _size_field(node):
# Some common substitutions on the types to reduce visual clutter (A user who
# wants to see the actual details can always use print/r).
_common_substitutions = [
- ("std::basic_string<char, std::char_traits<char>, std::allocator<char> >",
- "std::string"),
- ("std::basic_string_view<char, std::char_traits<char> >",
- "std::string_view"),
+ (
+ "std::basic_string<char, std::char_traits<char>, std::allocator<char> >",
+ "std::string",
+ ),
+ ("std::basic_string_view<char, std::char_traits<char> >", "std::string_view"),
]
@@ -116,8 +118,11 @@ def _prettify_typename(gdb_type):
"""
type_without_typedefs = gdb_type.strip_typedefs()
- typename = type_without_typedefs.name or type_without_typedefs.tag or \
- str(type_without_typedefs)
+ typename = (
+ type_without_typedefs.name
+ or type_without_typedefs.tag
+ or str(type_without_typedefs)
+ )
result = _remove_cxx_namespace(typename)
for find_str, subst_str in _common_substitutions:
result = re.sub(find_str, subst_str, result)
@@ -247,18 +252,18 @@ class StdStringViewPrinter(object):
"""Print a std::string_view."""
def __init__(self, val):
- self.val = val
+ self.val = val
def display_hint(self):
- return "string"
+ return "string"
def to_string(self): # pylint: disable=g-bad-name
- """GDB calls this to compute the pretty-printed form."""
+ """GDB calls this to compute the pretty-printed form."""
- ptr = _data_field(self.val)
- ptr = ptr.cast(ptr.type.target().strip_typedefs().pointer())
- size = _size_field(self.val)
- return ptr.lazy_string(length=size)
+ ptr = _data_field(self.val)
+ ptr = ptr.cast(ptr.type.target().strip_typedefs().pointer())
+ size = _size_field(self.val)
+ return ptr.lazy_string(length=size)
class StdUniquePtrPrinter(object):
@@ -273,9 +278,10 @@ class StdUniquePtrPrinter(object):
typename = _remove_generics(_prettify_typename(self.val.type))
if not self.addr:
return "%s is nullptr" % typename
- return ("%s<%s> containing" %
- (typename,
- _remove_generics(_prettify_typename(self.pointee_type))))
+ return "%s<%s> containing" % (
+ typename,
+ _remove_generics(_prettify_typename(self.pointee_type)),
+ )
def __iter__(self):
if self.addr:
@@ -296,7 +302,8 @@ class StdSharedPointerPrinter(object):
"""Returns self as a string."""
typename = _remove_generics(_prettify_typename(self.val.type))
pointee_type = _remove_generics(
- _prettify_typename(self.val.type.template_argument(0)))
+ _prettify_typename(self.val.type.template_argument(0))
+ )
if not self.addr:
return "%s is nullptr" % typename
refcount = self.val["__cntrl_"]
@@ -391,20 +398,24 @@ class StdVectorPrinter(object):
self.typename += "<bool>"
self.length = self.val["__size_"]
bits_per_word = self.val["__bits_per_word"]
- self.capacity = _value_of_pair_first(
- self.val["__cap_alloc_"]) * bits_per_word
- self.iterator = self._VectorBoolIterator(
- begin, self.length, bits_per_word)
+ self.capacity = (
+ _value_of_pair_first(self.val["__cap_alloc_"]) * bits_per_word
+ )
+ self.iterator = self._VectorBoolIterator(begin, self.length, bits_per_word)
else:
end = self.val["__end_"]
self.length = end - begin
- self.capacity = _get_base_subobject(
- self.val["__end_cap_"])["__value_"] - begin
+ self.capacity = (
+ _get_base_subobject(self.val["__end_cap_"])["__value_"] - begin
+ )
self.iterator = self._VectorIterator(begin, end)
def to_string(self):
- return ("%s of length %d, capacity %d" %
- (self.typename, self.length, self.capacity))
+ return "%s of length %d, capacity %d" % (
+ self.typename,
+ self.length,
+ self.capacity,
+ )
def children(self):
return self.iterator
@@ -424,8 +435,9 @@ class StdBitsetPrinter(object):
if self.n_words == 1:
self.values = [int(self.val["__first_"])]
else:
- self.values = [int(self.val["__first_"][index])
- for index in range(self.n_words)]
+ self.values = [
+ int(self.val["__first_"][index]) for index in range(self.n_words)
+ ]
def to_string(self):
typename = _prettify_typename(self.val.type)
@@ -454,8 +466,7 @@ class StdDequePrinter(object):
self.start_ptr = self.val["__map_"]["__begin_"]
self.first_block_start_index = int(self.val["__start_"])
self.node_type = self.start_ptr.type
- self.block_size = self._calculate_block_size(
- val.type.template_argument(0))
+ self.block_size = self._calculate_block_size(val.type.template_argument(0))
def _calculate_block_size(self, element_type):
"""Calculates the number of elements in a full block."""
@@ -473,13 +484,13 @@ class StdDequePrinter(object):
current_addr = self.start_ptr
start_index = self.first_block_start_index
while num_emitted < self.size:
- end_index = min(start_index + self.size -
- num_emitted, self.block_size)
+ end_index = min(start_index + self.size - num_emitted, self.block_size)
for _, elem in self._bucket_it(current_addr, start_index, end_index):
yield "", elem
num_emitted += end_index - start_index
- current_addr = gdb.Value(addr_as_long(current_addr) + _pointer_size) \
- .cast(self.node_type)
+ current_addr = gdb.Value(addr_as_long(current_addr) + _pointer_size).cast(
+ self.node_type
+ )
start_index = 0
def to_string(self):
@@ -507,8 +518,10 @@ class StdListPrinter(object):
self.size = int(_value_of_pair_first(size_alloc_field))
dummy_node = self.val["__end_"]
self.nodetype = gdb.lookup_type(
- re.sub("__list_node_base", "__list_node",
- str(dummy_node.type.strip_typedefs()))).pointer()
+ re.sub(
+ "__list_node_base", "__list_node", str(dummy_node.type.strip_typedefs())
+ )
+ ).pointer()
self.first_node = dummy_node["__next_"]
def to_string(self):
@@ -685,7 +698,8 @@ class StdMapPrinter(AbstractRBTreePrinter):
def _init_cast_type(self, val_type):
map_it_type = gdb.lookup_type(
- str(val_type.strip_typedefs()) + "::iterator").strip_typedefs()
+ str(val_type.strip_typedefs()) + "::iterator"
+ ).strip_typedefs()
tree_it_type = map_it_type.template_argument(0)
node_ptr_type = tree_it_type.template_argument(1)
return node_ptr_type
@@ -703,7 +717,8 @@ class StdSetPrinter(AbstractRBTreePrinter):
def _init_cast_type(self, val_type):
set_it_type = gdb.lookup_type(
- str(val_type.strip_typedefs()) + "::iterator").strip_typedefs()
+ str(val_type.strip_typedefs()) + "::iterator"
+ ).strip_typedefs()
node_ptr_type = set_it_type.template_argument(1)
return node_ptr_type
@@ -730,8 +745,7 @@ class AbstractRBTreeIteratorPrinter(object):
def _is_valid_node(self):
if not self.util.parent(self.addr):
return False
- return self.util.is_left_child(self.addr) or \
- self.util.is_right_child(self.addr)
+ return self.util.is_left_child(self.addr) or self.util.is_right_child(self.addr)
def to_string(self):
if not self.addr:
@@ -756,8 +770,7 @@ class MapIteratorPrinter(AbstractRBTreeIteratorPrinter):
"""Print a std::(multi)map iterator."""
def __init__(self, val):
- self._initialize(val["__i_"],
- _remove_generics(_prettify_typename(val.type)))
+ self._initialize(val["__i_"], _remove_generics(_prettify_typename(val.type)))
def _get_node_value(self, node):
return _cc_field(node)
@@ -976,10 +989,12 @@ class LibcxxPrettyPrinter(object):
# Don't attempt types known to be inside libstdcxx.
typename = val.type.name or val.type.tag or str(val.type)
match = re.match("^std::(__.*?)::", typename)
- if match is not None and match.group(1) in ["__cxx1998",
- "__debug",
- "__7",
- "__g"]:
+ if match is not None and match.group(1) in [
+ "__cxx1998",
+ "__debug",
+ "__7",
+ "__g",
+ ]:
return None
# Handle any using declarations or other typedefs.
@@ -1005,13 +1020,13 @@ def _register_libcxx_printers(event):
# already generated as part of a larger data structure, and there is
# no python api to get the endianness. Mixed-endianness debugging
# rare enough that this workaround should be adequate.
- _libcpp_big_endian = "big endian" in gdb.execute("show endian",
- to_string=True)
+ _libcpp_big_endian = "big endian" in gdb.execute("show endian", to_string=True)
if not getattr(progspace, _libcxx_printer_name, False):
print("Loading libc++ pretty-printers.")
gdb.printing.register_pretty_printer(
- progspace, LibcxxPrettyPrinter(_libcxx_printer_name))
+ progspace, LibcxxPrettyPrinter(_libcxx_printer_name)
+ )
setattr(progspace, _libcxx_printer_name, True)
diff --git a/libcxx/utils/generate_abi_list.py b/libcxx/utils/generate_abi_list.py
index 670300b..94e49dc 100755
--- a/libcxx/utils/generate_abi_list.py
+++ b/libcxx/utils/generate_abi_list.py
@@ -1,11 +1,11 @@
#!/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
#
-#===----------------------------------------------------------------------===##
+# ===----------------------------------------------------------------------===##
import argparse
import io
@@ -14,27 +14,38 @@ import libcxx.sym_check.util
import pprint
import sys
+
def OutputFile(file):
if isinstance(file, io.IOBase):
return file
assert isinstance(file, str), "Got object {} which is not a str".format(file)
- return open(file, 'w', newline='\n')
+ return open(file, "w", newline="\n")
+
def main(argv):
parser = argparse.ArgumentParser(
- description='Extract a list of symbols from a shared library.')
- parser.add_argument('library', metavar='LIB', type=str,
- help='The library to extract symbols from.')
- parser.add_argument('-o', '--output', dest='output', type=OutputFile, default=sys.stdout,
- help='The output file to write the symbols to. It is overwritten if it already exists. '
- 'If no file is specified, the results are written to standard output.')
+ description="Extract a list of symbols from a shared library."
+ )
+ parser.add_argument(
+ "library", metavar="LIB", type=str, help="The library to extract symbols from."
+ )
+ parser.add_argument(
+ "-o",
+ "--output",
+ dest="output",
+ type=OutputFile,
+ default=sys.stdout,
+ help="The output file to write the symbols to. It is overwritten if it already exists. "
+ "If no file is specified, the results are written to standard output.",
+ )
args = parser.parse_args(argv)
symbols = libcxx.sym_check.extract.extract_symbols(args.library)
symbols, _ = libcxx.sym_check.util.filter_stdlib_symbols(symbols)
lines = [pprint.pformat(sym, width=99999) for sym in symbols]
- args.output.writelines('\n'.join(sorted(lines)))
+ args.output.writelines("\n".join(sorted(lines)))
+
-if __name__ == '__main__':
+if __name__ == "__main__":
main(sys.argv[1:])
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index ce02746..abc833d 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -4,30 +4,43 @@ import os
from builtins import range
from functools import reduce
+
def get_libcxx_paths():
- utils_path = os.path.dirname(os.path.abspath(__file__))
- script_name = os.path.basename(__file__)
- assert os.path.exists(utils_path)
- src_root = os.path.dirname(utils_path)
- include_path = os.path.join(src_root, 'include')
- assert os.path.exists(include_path)
- docs_path = os.path.join(src_root, 'docs')
- assert os.path.exists(docs_path)
- macro_test_path = os.path.join(src_root, 'test', 'std', 'language.support',
- 'support.limits', 'support.limits.general')
- assert os.path.exists(macro_test_path)
- assert os.path.exists(os.path.join(macro_test_path, 'version.version.compile.pass.cpp'))
- return script_name, src_root, include_path, docs_path, macro_test_path
+ utils_path = os.path.dirname(os.path.abspath(__file__))
+ script_name = os.path.basename(__file__)
+ assert os.path.exists(utils_path)
+ src_root = os.path.dirname(utils_path)
+ include_path = os.path.join(src_root, "include")
+ assert os.path.exists(include_path)
+ docs_path = os.path.join(src_root, "docs")
+ assert os.path.exists(docs_path)
+ macro_test_path = os.path.join(
+ src_root,
+ "test",
+ "std",
+ "language.support",
+ "support.limits",
+ "support.limits.general",
+ )
+ assert os.path.exists(macro_test_path)
+ assert os.path.exists(
+ os.path.join(macro_test_path, "version.version.compile.pass.cpp")
+ )
+ return script_name, src_root, include_path, docs_path, macro_test_path
+
script_name, source_root, include_path, docs_path, macro_test_path = get_libcxx_paths()
+
def has_header(h):
- h_path = os.path.join(include_path, h)
- return os.path.exists(h_path)
+ h_path = os.path.join(include_path, h)
+ return os.path.exists(h_path)
+
def add_version_header(tc):
- tc["headers"].append("version")
- return tc
+ tc["headers"].append("version")
+ return tc
+
# ================ ============================================================
# Field Description
@@ -59,733 +72,972 @@ def add_version_header(tc):
# you've fully implemented the feature, you should remove
# this field.
# ================ ============================================================
-feature_test_macros = [ add_version_header(x) for x in [
- {
- "name": "__cpp_lib_adaptor_iterator_pair_constructor",
- "values": { "c++23": 202106 },
- "headers": ["queue", "stack"],
- }, {
- "name": "__cpp_lib_addressof_constexpr",
- "values": { "c++17": 201603 },
- "headers": ["memory"],
- }, {
- "name": "__cpp_lib_allocate_at_least",
- "values": { "c++23": 202106 },
- "headers": ["memory"],
- }, {
- "name": "__cpp_lib_allocator_traits_is_always_equal",
- "values": { "c++17": 201411 },
- "headers": ["deque", "forward_list", "list", "map", "memory", "scoped_allocator", "set", "string", "unordered_map", "unordered_set", "vector"],
- }, {
- "name": "__cpp_lib_any",
- "values": { "c++17": 201606 },
- "headers": ["any"],
- }, {
- "name": "__cpp_lib_apply",
- "values": { "c++17": 201603 },
- "headers": ["tuple"],
- }, {
- "name": "__cpp_lib_array_constexpr",
- "values": { "c++17": 201603, "c++20": 201811 },
- "headers": ["array", "iterator"],
- }, {
- "name": "__cpp_lib_as_const",
- "values": { "c++17": 201510 },
- "headers": ["utility"],
- }, {
- "name": "__cpp_lib_associative_heterogeneous_erasure",
- "values": { "c++23": 202110 },
- "headers": ["map", "set", "unordered_map", "unordered_set"],
- "unimplemented": True,
- }, {
- "name": "__cpp_lib_assume_aligned",
- "values": { "c++20": 201811 },
- "headers": ["memory"],
- }, {
- "name": "__cpp_lib_atomic_flag_test",
- "values": { "c++20": 201907 },
- "headers": ["atomic"],
- }, {
- "name": "__cpp_lib_atomic_float",
- "values": { "c++20": 201711 },
- "headers": ["atomic"],
- "unimplemented": True,
- }, {
- "name": "__cpp_lib_atomic_is_always_lock_free",
- "values": { "c++17": 201603 },
- "headers": ["atomic"],
- }, {
- "name": "__cpp_lib_atomic_lock_free_type_aliases",
- "values": { "c++20": 201907 },
- "headers": ["atomic"],
- }, {
- "name": "__cpp_lib_atomic_ref",
- "values": { "c++20": 201806 },
- "headers": ["atomic"],
- "unimplemented": True,
- }, {
- "name": "__cpp_lib_atomic_shared_ptr",
- "values": { "c++20": 201711 },
- "headers": ["atomic"],
- "unimplemented": True,
- }, {
- "name": "__cpp_lib_atomic_value_initialization",
- "values": { "c++20": 201911 },
- "headers": ["atomic", "memory"],
- }, {
- "name": "__cpp_lib_atomic_wait",
- "values": { "c++20": 201907 },
- "headers": ["atomic"],
- "test_suite_guard": "!defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)",
- "libcxx_guard": "!defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)",
- }, {
- "name": "__cpp_lib_barrier",
- "values": { "c++20": 201907 },
- "headers": ["barrier"],
- "test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)",
- "libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)",
- }, {
- "name": "__cpp_lib_bind_back",
- "values": { "c++23": 202202 },
- "headers": ["functional"],
- "unimplemented": True,
- }, {
- "name": "__cpp_lib_bind_front",
- "values": { "c++20": 201907 },
- "headers": ["functional"],
- }, {
- "name": "__cpp_lib_bit_cast",
- "values": { "c++20": 201806 },
- "headers": ["bit"],
- }, {
- "name": "__cpp_lib_bitops",
- "values": { "c++20": 201907 },
- "headers": ["bit"],
- "unimplemented": True,
- }, {
- "name": "__cpp_lib_bool_constant",
- "values": { "c++17": 201505 },
- "headers": ["type_traits"],
- }, {
- "name": "__cpp_lib_bounded_array_traits",
- "values": { "c++20": 201902 },
- "headers": ["type_traits"],
- }, {
- "name": "__cpp_lib_boyer_moore_searcher",
- "values": { "c++17": 201603 },
- "headers": ["functional"],
- }, {
- "name": "__cpp_lib_byte",
- "values": { "c++17": 201603 },
- "headers": ["cstddef"],
- }, {
- "name": "__cpp_lib_byteswap",
- "values": { "c++23": 202110 },
- "headers": ["bit"],
- }, {
- "name": "__cpp_lib_char8_t",
- "values": { "c++20": 201907 },
- "headers": ["atomic", "filesystem", "istream", "limits", "locale", "ostream", "string", "string_view"],
- "test_suite_guard": "defined(__cpp_char8_t)",
- "libcxx_guard": "!defined(_LIBCPP_HAS_NO_CHAR8_T)",
- }, {
- "name": "__cpp_lib_chrono",
- "values": { "c++17": 201611 },
- "headers": ["chrono"],
- }, {
- "name": "__cpp_lib_chrono_udls",
- "values": { "c++14": 201304 },
- "headers": ["chrono"],
- }, {
- "name": "__cpp_lib_clamp",
- "values": { "c++17": 201603 },
- "headers": ["algorithm"],
- }, {
- "name": "__cpp_lib_complex_udls",
- "values": { "c++14": 201309 },
- "headers": ["complex"],
- }, {
- "name": "__cpp_lib_concepts",
- "values": { "c++20": 202002 },
- "headers": ["concepts"],
- }, {
- "name": "__cpp_lib_constexpr_algorithms",
- "values": { "c++20": 201806 },
- "headers": ["algorithm", "utility"],
- }, {
- "name": "__cpp_lib_constexpr_bitset",
- "values": { "c++23": 202207 },
- "headers": ["bitset"],
- }, {
- "name": "__cpp_lib_constexpr_charconv",
- "values": { "c++23": 202207 },
- "headers": ["charconv"],
- }, {
- "name": "__cpp_lib_constexpr_cmath",
- "values": { "c++23": 202202 },
- "headers": ["cmath", "cstdlib"],
- "unimplemented": True,
- }, {
- "name": "__cpp_lib_constexpr_complex",
- "values": { "c++20": 201711 },
- "headers": ["complex"],
- }, {
- "name": "__cpp_lib_constexpr_dynamic_alloc",
- "values": { "c++20": 201907 },
- "headers": ["memory"],
- }, {
- "name": "__cpp_lib_constexpr_functional",
- "values": { "c++20": 201907 },
- "headers": ["functional"],
- }, {
- "name": "__cpp_lib_constexpr_iterator",
- "values": { "c++20": 201811 },
- "headers": ["iterator"],
- }, {
- "name": "__cpp_lib_constexpr_memory",
- "values": { "c++20": 201811, "c++23": 202202 },
- "headers": ["memory"],
- }, {
- "name": "__cpp_lib_constexpr_numeric",
- "values": { "c++20": 201911 },
- "headers": ["numeric"],
- }, {
- "name": "__cpp_lib_constexpr_string",
- "values": { "c++20": 201907 },
- "headers": ["string"],
- }, {
- "name": "__cpp_lib_constexpr_string_view",
- "values": { "c++20": 201811 },
- "headers": ["string_view"],
- }, {
- "name": "__cpp_lib_constexpr_tuple",
- "values": { "c++20": 201811 },
- "headers": ["tuple"],
- }, {
- "name": "__cpp_lib_constexpr_typeinfo",
- "values": { "c++23": 202106 },
- "headers": ["typeinfo"],
- }, {
- "name": "__cpp_lib_constexpr_utility",
- "values": { "c++20": 201811 },
- "headers": ["utility"],
- }, {
- "name": "__cpp_lib_constexpr_vector",
- "values": { "c++20": 201907 },
- "headers": ["vector"],
- }, {
- "name": "__cpp_lib_coroutine",
- "values": { "c++20": 201902 },
- "headers": ["coroutine"],
- }, {
- "name": "__cpp_lib_destroying_delete",
- "values": { "c++20": 201806 },
- "headers": ["new"],
- "test_suite_guard": "TEST_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L",
- "libcxx_guard": "_LIBCPP_STD_VER >= 20 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L",
- }, {
- "name": "__cpp_lib_enable_shared_from_this",
- "values": { "c++17": 201603 },
- "headers": ["memory"],
- }, {
- "name": "__cpp_lib_endian",
- "values": { "c++20": 201907 },
- "headers": ["bit"],
- }, {
- "name": "__cpp_lib_erase_if",
- "values": { "c++20": 202002 },
- "headers": ["deque", "forward_list", "list", "map", "set", "string", "unordered_map", "unordered_set", "vector"],
- }, {
- "name": "__cpp_lib_exchange_function",
- "values": { "c++14": 201304 },
- "headers": ["utility"],
- }, {
- "name": "__cpp_lib_execution",
- "values": { "c++17": 201603, "c++20": 201902 },
- "headers": ["execution"],
- "unimplemented": True,
- }, {
- "name": "__cpp_lib_expected",
- "values": { "c++23": 202211 },
- "headers": ["expected"],
- }, {
- "name": "__cpp_lib_filesystem",
- "values": { "c++17": 201703 },
- "headers": ["filesystem"],
- "test_suite_guard": "!defined(_LIBCPP_AVAILABILITY_HAS_NO_FILESYSTEM)",
- "libcxx_guard": "!defined(_LIBCPP_AVAILABILITY_HAS_NO_FILESYSTEM)"
- }, {
- "name": "__cpp_lib_format",
- "values": {
- # "c++20": 201907 Not implemented P1361R2 Integration of chrono with text formatting
- # "c++20": 202106 Fully implemented
- # "c++20": 202110 Not implemented P2372R3 Fixing locale handling in chrono formatters
- "c++20": 202106,
- # "c++23": 202207, Not implemented P2419R2 Clarify handling of encodings in localized formatting of chrono types
- },
- "headers": ["format"],
- "unimplemented": True,
- }, {
- "name": "__cpp_lib_format_ranges",
- "values": { "c++23": 202207 },
- "headers": ["format"],
- }, {
- "name": "__cpp_lib_formatters",
- "values": { "c++23": 202302 },
- "headers": ["stacktrace", "thread"],
- "unimplemented": True,
- }, {
- "name": "__cpp_lib_forward_like",
- "values": { "c++23": 202207 },
- "headers": ["utility"],
- }, {
- "name": "__cpp_lib_gcd_lcm",
- "values": { "c++17": 201606 },
- "headers": ["numeric"],
- }, {
- "name": "__cpp_lib_generic_associative_lookup",
- "values": { "c++14": 201304 },
- "headers": ["map", "set"],
- }, {
- "name": "__cpp_lib_generic_unordered_lookup",
- "values": { "c++20": 201811 },
- "headers": ["unordered_map", "unordered_set"],
- }, {
- "name": "__cpp_lib_hardware_interference_size",
- "values": { "c++17": 201703 },
- "test_suite_guard": "defined(__GCC_DESTRUCTIVE_SIZE) && defined(__GCC_CONSTRUCTIVE_SIZE)",
- "libcxx_guard": "defined(__GCC_DESTRUCTIVE_SIZE) && defined(__GCC_CONSTRUCTIVE_SIZE)",
- "headers": ["new"],
- }, {
- "name": "__cpp_lib_has_unique_object_representations",
- "values": { "c++17": 201606 },
- "headers": ["type_traits"],
- }, {
- "name": "__cpp_lib_hypot",
- "values": { "c++17": 201603 },
- "headers": ["cmath"],
- }, {
- "name": "__cpp_lib_incomplete_container_elements",
- "values": { "c++17": 201505 },
- "headers": ["forward_list", "list", "vector"],
- }, {
- "name": "__cpp_lib_int_pow2",
- "values": { "c++20": 202002 },
- "headers": ["bit"],
- }, {
- "name": "__cpp_lib_integer_comparison_functions",
- "values": { "c++20": 202002 },
- "headers": ["utility"],
- }, {
- "name": "__cpp_lib_integer_sequence",
- "values": { "c++14": 201304 },
- "headers": ["utility"],
- }, {
- "name": "__cpp_lib_integral_constant_callable",
- "values": { "c++14": 201304 },
- "headers": ["type_traits"],
- }, {
- "name": "__cpp_lib_interpolate",
- "values": { "c++20": 201902 },
- "headers": ["cmath", "numeric"],
- }, {
- "name": "__cpp_lib_invoke",
- "values": { "c++17": 201411 },
- "headers": ["functional"],
- }, {
- "name": "__cpp_lib_invoke_r",
- "values": { "c++23": 202106 },
- "headers": ["functional"],
- }, {
- "name": "__cpp_lib_is_aggregate",
- "values": { "c++17": 201703 },
- "headers": ["type_traits"],
- }, {
- "name": "__cpp_lib_is_constant_evaluated",
- "values": { "c++20": 201811 },
- "headers": ["type_traits"],
- }, {
- "name": "__cpp_lib_is_final",
- "values": { "c++14": 201402 },
- "headers": ["type_traits"],
- }, {
- "name": "__cpp_lib_is_invocable",
- "values": { "c++17": 201703 },
- "headers": ["type_traits"],
- }, {
- "name": "__cpp_lib_is_layout_compatible",
- "values": { "c++20": 201907 },
- "headers": ["type_traits"],
- "unimplemented": True,
- }, {
- "name": "__cpp_lib_is_nothrow_convertible",
- "values": { "c++20": 201806 },
- "headers": ["type_traits"],
- }, {
- "name": "__cpp_lib_is_null_pointer",
- "values": { "c++14": 201309 },
- "headers": ["type_traits"],
- }, {
- "name": "__cpp_lib_is_pointer_interconvertible",
- "values": { "c++20": 201907 },
- "headers": ["type_traits"],
- "unimplemented": True,
- }, {
- "name": "__cpp_lib_is_scoped_enum",
- "values": { "c++23": 202011 },
- "headers": ["type_traits"],
- }, {
- "name": "__cpp_lib_is_swappable",
- "values": { "c++17": 201603 },
- "headers": ["type_traits"],
- }, {
- "name": "__cpp_lib_jthread",
- "values": { "c++20": 201911 },
- "headers": ["stop_token", "thread"],
- "test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS)",
- "libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS)",
- "unimplemented": True,
- }, {
- "name": "__cpp_lib_latch",
- "values": { "c++20": 201907 },
- "headers": ["latch"],
- "test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)",
- "libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)",
- }, {
- "name": "__cpp_lib_launder",
- "values": { "c++17": 201606 },
- "headers": ["new"],
- }, {
- "name": "__cpp_lib_list_remove_return_type",
- "values": { "c++20": 201806 },
- "headers": ["forward_list", "list"],
- }, {
- "name": "__cpp_lib_logical_traits",
- "values": { "c++17": 201510 },
- "headers": ["type_traits"],
- }, {
- "name": "__cpp_lib_make_from_tuple",
- "values": { "c++17": 201606 },
- "headers": ["tuple"],
- }, {
- "name": "__cpp_lib_make_reverse_iterator",
- "values": { "c++14": 201402 },
- "headers": ["iterator"],
- }, {
- "name": "__cpp_lib_make_unique",
- "values": { "c++14": 201304 },
- "headers": ["memory"],
- }, {
- "name": "__cpp_lib_map_try_emplace",
- "values": { "c++17": 201411 },
- "headers": ["map"],
- }, {
- "name": "__cpp_lib_math_constants",
- "values": { "c++20": 201907 },
- "headers": ["numbers"],
- }, {
- "name": "__cpp_lib_math_special_functions",
- "values": { "c++17": 201603 },
- "headers": ["cmath"],
- "unimplemented": True,
- }, {
- "name": "__cpp_lib_mdspan",
- "values": { "c++23": 202207 },
- "headers": ["mdspan"],
- "unimplemented": True,
- }, {
- "name": "__cpp_lib_memory_resource",
- "values": { "c++17": 201603 },
- "headers": ["memory_resource"],
- }, {
- "name": "__cpp_lib_move_iterator_concept",
- "values": { "c++20": 202207 },
- "headers": ["iterator"],
- }, {
- "name": "__cpp_lib_move_only_function",
- "values": { "c++23": 202110 },
- "headers": ["functional"],
- "unimplemented": True,
- }, {
- "name": "__cpp_lib_node_extract",
- "values": { "c++17": 201606 },
- "headers": ["map", "set", "unordered_map", "unordered_set"],
- }, {
- "name": "__cpp_lib_nonmember_container_access",
- "values": { "c++17": 201411 },
- "headers": ["array", "deque", "forward_list", "iterator", "list", "map", "regex", "set", "string", "unordered_map", "unordered_set", "vector"],
- }, {
- "name": "__cpp_lib_not_fn",
- "values": { "c++17": 201603 },
- "headers": ["functional"],
- }, {
- "name": "__cpp_lib_null_iterators",
- "values": { "c++14": 201304 },
- "headers": ["iterator"],
- }, {
- "name": "__cpp_lib_optional",
- "values": { "c++17": 201606, "c++23": 202110 },
- "headers": ["optional"],
- }, {
- "name": "__cpp_lib_out_ptr",
- "values": { "c++23": 202106 },
- "headers": ["memory"],
- "unimplemented": True,
- }, {
- "name": "__cpp_lib_parallel_algorithm",
- "values": { "c++17": 201603 },
- "headers": ["algorithm", "numeric"],
- "unimplemented": True,
- }, {
- "name": "__cpp_lib_polymorphic_allocator",
- "values": { "c++20": 201902 },
- "headers": ["memory_resource"],
- }, {
- "name": "__cpp_lib_quoted_string_io",
- "values": { "c++14": 201304 },
- "headers": ["iomanip"],
- }, {
- "name": "__cpp_lib_ranges",
- "values": { "c++20": 202106 },
- "headers": ["algorithm", "functional", "iterator", "memory", "ranges"],
- }, {
- "name": "__cpp_lib_ranges_as_rvalue",
- "values": { "c++23": 202207 },
- "headers": ["ranges"],
- }, {
- "name": "__cpp_lib_ranges_chunk",
- "values": { "c++23": 202202 },
- "headers": ["ranges"],
- "unimplemented": True,
- }, {
- "name": "__cpp_lib_ranges_chunk_by",
- "values": { "c++23": 202202 },
- "headers": ["ranges"],
- "unimplemented": True,
- }, {
- "name": "__cpp_lib_ranges_iota",
- "values": { "c++23": 202202 },
- "headers": ["numeric"],
- "unimplemented": True,
- }, {
- "name": "__cpp_lib_ranges_join_with",
- "values": { "c++23": 202202 },
- "headers": ["ranges"],
- "unimplemented": True,
- }, {
- "name": "__cpp_lib_ranges_slide",
- "values": { "c++23": 202202 },
- "headers": ["ranges"],
- "unimplemented": True,
- }, {
- "name": "__cpp_lib_ranges_starts_ends_with",
- "values": { "c++23": 202106 },
- "headers": ["algorithm"],
- "unimplemented": True,
- }, {
- "name": "__cpp_lib_ranges_to_container",
- "values": { "c++23": 202202 },
- "headers": ["deque", "forward_list", "list", "map", "priority_queue", "queue", "set", "stack", "string", "unordered_map", "unordered_set", "vector"],
- "unimplemented": True,
- }, {
- "name": "__cpp_lib_ranges_zip",
- "values": { "c++23": 202110 },
- "headers": ["ranges", "tuple", "utility"],
- "unimplemented": True,
- }, {
- "name": "__cpp_lib_raw_memory_algorithms",
- "values": { "c++17": 201606 },
- "headers": ["memory"],
- }, {
- "name": "__cpp_lib_reference_from_temporary",
- "values": { "c++23": 202202 },
- "headers": ["type_traits"],
- "unimplemented": True,
- }, {
- "name": "__cpp_lib_remove_cvref",
- "values": { "c++20": 201711 },
- "headers": ["type_traits"],
- }, {
- "name": "__cpp_lib_result_of_sfinae",
- "values": { "c++14": 201210 },
- "headers": ["functional", "type_traits"],
- }, {
- "name": "__cpp_lib_robust_nonmodifying_seq_ops",
- "values": { "c++14": 201304 },
- "headers": ["algorithm"],
- }, {
- "name": "__cpp_lib_sample",
- "values": { "c++17": 201603 },
- "headers": ["algorithm"],
- }, {
- "name": "__cpp_lib_scoped_lock",
- "values": { "c++17": 201703 },
- "headers": ["mutex"],
- }, {
- "name": "__cpp_lib_semaphore",
- "values": { "c++20": 201907 },
- "headers": ["semaphore"],
- "test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)",
- "libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)",
- }, {
- "name": "__cpp_lib_shared_mutex",
- "values": { "c++17": 201505 },
- "headers": ["shared_mutex"],
- "test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SHARED_MUTEX)",
- "libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SHARED_MUTEX)",
- }, {
- "name": "__cpp_lib_shared_ptr_arrays",
- "values": { "c++17": 201611, "c++20": 201707 },
- "headers": ["memory"],
- }, {
- "name": "__cpp_lib_shared_ptr_weak_type",
- "values": { "c++17": 201606 },
- "headers": ["memory"],
- }, {
- "name": "__cpp_lib_shared_timed_mutex",
- "values": { "c++14": 201402 },
- "headers": ["shared_mutex"],
- "test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SHARED_MUTEX)",
- "libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SHARED_MUTEX)",
- }, {
- "name": "__cpp_lib_shift",
- "values": { "c++20": 201806 },
- "headers": ["algorithm"],
- }, {
- "name": "__cpp_lib_smart_ptr_for_overwrite",
- "values": { "c++20": 202002 },
- "headers": ["memory"],
- "unimplemented": True,
- }, {
- "name": "__cpp_lib_source_location",
- "values": { "c++20": 201907 },
- "headers": ["source_location"],
- "test_suite_guard": "__has_builtin(__builtin_source_location) && !(defined(TEST_APPLE_CLANG_VER) && TEST_APPLE_CLANG_VER <= 1403)",
- "libcxx_guard": "__has_builtin(__builtin_source_location) && !(defined(_LIBCPP_APPLE_CLANG_VER) && _LIBCPP_APPLE_CLANG_VER <= 1403)",
- }, {
- "name": "__cpp_lib_span",
- "values": { "c++20": 202002 },
- "headers": ["span"],
- }, {
- "name": "__cpp_lib_spanstream",
- "values": { "c++23": 202106 },
- "headers": ["spanstream"],
- "unimplemented": True,
- }, {
- "name": "__cpp_lib_ssize",
- "values": { "c++20": 201902 },
- "headers": ["iterator"],
- }, {
- "name": "__cpp_lib_stacktrace",
- "values": { "c++23": 202011 },
- "headers": ["stacktrace"],
- "unimplemented": True,
- }, {
- "name": "__cpp_lib_starts_ends_with",
- "values": { "c++20": 201711 },
- "headers": ["string", "string_view"],
- }, {
- "name": "__cpp_lib_stdatomic_h",
- "values": { "c++23": 202011 },
- "headers": ["stdatomic.h"],
- }, {
- "name": "__cpp_lib_string_contains",
- "values": { "c++23": 202011 },
- "headers": ["string", "string_view"],
- }, {
- "name": "__cpp_lib_string_resize_and_overwrite",
- "values": { "c++23": 202110 },
- "headers": ["string"],
- }, {
- "name": "__cpp_lib_string_udls",
- "values": { "c++14": 201304 },
- "headers": ["string"],
- }, {
- "name": "__cpp_lib_string_view",
- "values": { "c++17": 201606, "c++20": 201803 },
- "headers": ["string", "string_view"],
- }, {
- "name": "__cpp_lib_syncbuf",
- "values": { "c++20": 201803 },
- "headers": ["syncstream"],
- "unimplemented": True,
- }, {
- "name": "__cpp_lib_three_way_comparison",
- "values": { "c++20": 201907 },
- "headers": ["compare"],
- "unimplemented": True,
- }, {
- "name": "__cpp_lib_to_address",
- "values": { "c++20": 201711 },
- "headers": ["memory"],
- }, {
- "name": "__cpp_lib_to_array",
- "values": { "c++20": 201907 },
- "headers": ["array"],
- }, {
- "name": "__cpp_lib_to_chars",
- "values": { "c++17": 201611 },
- "headers": ["charconv"],
- "unimplemented": True,
- }, {
- "name": "__cpp_lib_to_underlying",
- "values": { "c++23": 202102 },
- "headers": ["utility"],
- }, {
- "name": "__cpp_lib_transformation_trait_aliases",
- "values": { "c++14": 201304 },
- "headers": ["type_traits"],
- }, {
- "name": "__cpp_lib_transparent_operators",
- "values": { "c++14": 201210, "c++17": 201510 },
- "headers": ["functional", "memory"],
- }, {
- "name": "__cpp_lib_tuple_element_t",
- "values": { "c++14": 201402 },
- "headers": ["tuple"],
- }, {
- "name": "__cpp_lib_tuples_by_type",
- "values": { "c++14": 201304 },
- "headers": ["tuple", "utility"],
- }, {
- "name": "__cpp_lib_type_identity",
- "values": { "c++20": 201806 },
- "headers": ["type_traits"],
- }, {
- "name": "__cpp_lib_type_trait_variable_templates",
- "values": { "c++17": 201510 },
- "headers": ["type_traits"],
- }, {
- "name": "__cpp_lib_uncaught_exceptions",
- "values": { "c++17": 201411 },
- "headers": ["exception"],
- }, {
- "name": "__cpp_lib_unordered_map_try_emplace",
- "values": { "c++17": 201411 },
- "headers": ["unordered_map"],
- }, {
- "name": "__cpp_lib_unreachable",
- "values": { "c++23": 202202 },
- "headers": ["utility"],
- }, {
- "name": "__cpp_lib_unwrap_ref",
- "values": { "c++20": 201811 },
- "headers": ["functional"],
- }, {
- "name": "__cpp_lib_variant",
- "values": { "c++17": 202102 },
- "headers": ["variant"],
- }, {
- "name": "__cpp_lib_void_t",
- "values": { "c++17": 201411 },
- "headers": ["type_traits"],
- }
-]]
+feature_test_macros = [
+ add_version_header(x)
+ for x in [
+ {
+ "name": "__cpp_lib_adaptor_iterator_pair_constructor",
+ "values": {"c++23": 202106},
+ "headers": ["queue", "stack"],
+ },
+ {
+ "name": "__cpp_lib_addressof_constexpr",
+ "values": {"c++17": 201603},
+ "headers": ["memory"],
+ },
+ {
+ "name": "__cpp_lib_allocate_at_least",
+ "values": {"c++23": 202106},
+ "headers": ["memory"],
+ },
+ {
+ "name": "__cpp_lib_allocator_traits_is_always_equal",
+ "values": {"c++17": 201411},
+ "headers": [
+ "deque",
+ "forward_list",
+ "list",
+ "map",
+ "memory",
+ "scoped_allocator",
+ "set",
+ "string",
+ "unordered_map",
+ "unordered_set",
+ "vector",
+ ],
+ },
+ {
+ "name": "__cpp_lib_any",
+ "values": {"c++17": 201606},
+ "headers": ["any"],
+ },
+ {
+ "name": "__cpp_lib_apply",
+ "values": {"c++17": 201603},
+ "headers": ["tuple"],
+ },
+ {
+ "name": "__cpp_lib_array_constexpr",
+ "values": {"c++17": 201603, "c++20": 201811},
+ "headers": ["array", "iterator"],
+ },
+ {
+ "name": "__cpp_lib_as_const",
+ "values": {"c++17": 201510},
+ "headers": ["utility"],
+ },
+ {
+ "name": "__cpp_lib_associative_heterogeneous_erasure",
+ "values": {"c++23": 202110},
+ "headers": ["map", "set", "unordered_map", "unordered_set"],
+ "unimplemented": True,
+ },
+ {
+ "name": "__cpp_lib_assume_aligned",
+ "values": {"c++20": 201811},
+ "headers": ["memory"],
+ },
+ {
+ "name": "__cpp_lib_atomic_flag_test",
+ "values": {"c++20": 201907},
+ "headers": ["atomic"],
+ },
+ {
+ "name": "__cpp_lib_atomic_float",
+ "values": {"c++20": 201711},
+ "headers": ["atomic"],
+ "unimplemented": True,
+ },
+ {
+ "name": "__cpp_lib_atomic_is_always_lock_free",
+ "values": {"c++17": 201603},
+ "headers": ["atomic"],
+ },
+ {
+ "name": "__cpp_lib_atomic_lock_free_type_aliases",
+ "values": {"c++20": 201907},
+ "headers": ["atomic"],
+ },
+ {
+ "name": "__cpp_lib_atomic_ref",
+ "values": {"c++20": 201806},
+ "headers": ["atomic"],
+ "unimplemented": True,
+ },
+ {
+ "name": "__cpp_lib_atomic_shared_ptr",
+ "values": {"c++20": 201711},
+ "headers": ["atomic"],
+ "unimplemented": True,
+ },
+ {
+ "name": "__cpp_lib_atomic_value_initialization",
+ "values": {"c++20": 201911},
+ "headers": ["atomic", "memory"],
+ },
+ {
+ "name": "__cpp_lib_atomic_wait",
+ "values": {"c++20": 201907},
+ "headers": ["atomic"],
+ "test_suite_guard": "!defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)",
+ "libcxx_guard": "!defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)",
+ },
+ {
+ "name": "__cpp_lib_barrier",
+ "values": {"c++20": 201907},
+ "headers": ["barrier"],
+ "test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)",
+ "libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)",
+ },
+ {
+ "name": "__cpp_lib_bind_back",
+ "values": {"c++23": 202202},
+ "headers": ["functional"],
+ "unimplemented": True,
+ },
+ {
+ "name": "__cpp_lib_bind_front",
+ "values": {"c++20": 201907},
+ "headers": ["functional"],
+ },
+ {
+ "name": "__cpp_lib_bit_cast",
+ "values": {"c++20": 201806},
+ "headers": ["bit"],
+ },
+ {
+ "name": "__cpp_lib_bitops",
+ "values": {"c++20": 201907},
+ "headers": ["bit"],
+ "unimplemented": True,
+ },
+ {
+ "name": "__cpp_lib_bool_constant",
+ "values": {"c++17": 201505},
+ "headers": ["type_traits"],
+ },
+ {
+ "name": "__cpp_lib_bounded_array_traits",
+ "values": {"c++20": 201902},
+ "headers": ["type_traits"],
+ },
+ {
+ "name": "__cpp_lib_boyer_moore_searcher",
+ "values": {"c++17": 201603},
+ "headers": ["functional"],
+ },
+ {
+ "name": "__cpp_lib_byte",
+ "values": {"c++17": 201603},
+ "headers": ["cstddef"],
+ },
+ {
+ "name": "__cpp_lib_byteswap",
+ "values": {"c++23": 202110},
+ "headers": ["bit"],
+ },
+ {
+ "name": "__cpp_lib_char8_t",
+ "values": {"c++20": 201907},
+ "headers": [
+ "atomic",
+ "filesystem",
+ "istream",
+ "limits",
+ "locale",
+ "ostream",
+ "string",
+ "string_view",
+ ],
+ "test_suite_guard": "defined(__cpp_char8_t)",
+ "libcxx_guard": "!defined(_LIBCPP_HAS_NO_CHAR8_T)",
+ },
+ {
+ "name": "__cpp_lib_chrono",
+ "values": {"c++17": 201611},
+ "headers": ["chrono"],
+ },
+ {
+ "name": "__cpp_lib_chrono_udls",
+ "values": {"c++14": 201304},
+ "headers": ["chrono"],
+ },
+ {
+ "name": "__cpp_lib_clamp",
+ "values": {"c++17": 201603},
+ "headers": ["algorithm"],
+ },
+ {
+ "name": "__cpp_lib_complex_udls",
+ "values": {"c++14": 201309},
+ "headers": ["complex"],
+ },
+ {
+ "name": "__cpp_lib_concepts",
+ "values": {"c++20": 202002},
+ "headers": ["concepts"],
+ },
+ {
+ "name": "__cpp_lib_constexpr_algorithms",
+ "values": {"c++20": 201806},
+ "headers": ["algorithm", "utility"],
+ },
+ {
+ "name": "__cpp_lib_constexpr_bitset",
+ "values": {"c++23": 202207},
+ "headers": ["bitset"],
+ },
+ {
+ "name": "__cpp_lib_constexpr_charconv",
+ "values": {"c++23": 202207},
+ "headers": ["charconv"],
+ },
+ {
+ "name": "__cpp_lib_constexpr_cmath",
+ "values": {"c++23": 202202},
+ "headers": ["cmath", "cstdlib"],
+ "unimplemented": True,
+ },
+ {
+ "name": "__cpp_lib_constexpr_complex",
+ "values": {"c++20": 201711},
+ "headers": ["complex"],
+ },
+ {
+ "name": "__cpp_lib_constexpr_dynamic_alloc",
+ "values": {"c++20": 201907},
+ "headers": ["memory"],
+ },
+ {
+ "name": "__cpp_lib_constexpr_functional",
+ "values": {"c++20": 201907},
+ "headers": ["functional"],
+ },
+ {
+ "name": "__cpp_lib_constexpr_iterator",
+ "values": {"c++20": 201811},
+ "headers": ["iterator"],
+ },
+ {
+ "name": "__cpp_lib_constexpr_memory",
+ "values": {"c++20": 201811, "c++23": 202202},
+ "headers": ["memory"],
+ },
+ {
+ "name": "__cpp_lib_constexpr_numeric",
+ "values": {"c++20": 201911},
+ "headers": ["numeric"],
+ },
+ {
+ "name": "__cpp_lib_constexpr_string",
+ "values": {"c++20": 201907},
+ "headers": ["string"],
+ },
+ {
+ "name": "__cpp_lib_constexpr_string_view",
+ "values": {"c++20": 201811},
+ "headers": ["string_view"],
+ },
+ {
+ "name": "__cpp_lib_constexpr_tuple",
+ "values": {"c++20": 201811},
+ "headers": ["tuple"],
+ },
+ {
+ "name": "__cpp_lib_constexpr_typeinfo",
+ "values": {"c++23": 202106},
+ "headers": ["typeinfo"],
+ },
+ {
+ "name": "__cpp_lib_constexpr_utility",
+ "values": {"c++20": 201811},
+ "headers": ["utility"],
+ },
+ {
+ "name": "__cpp_lib_constexpr_vector",
+ "values": {"c++20": 201907},
+ "headers": ["vector"],
+ },
+ {
+ "name": "__cpp_lib_coroutine",
+ "values": {"c++20": 201902},
+ "headers": ["coroutine"],
+ },
+ {
+ "name": "__cpp_lib_destroying_delete",
+ "values": {"c++20": 201806},
+ "headers": ["new"],
+ "test_suite_guard": "TEST_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L",
+ "libcxx_guard": "_LIBCPP_STD_VER >= 20 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L",
+ },
+ {
+ "name": "__cpp_lib_enable_shared_from_this",
+ "values": {"c++17": 201603},
+ "headers": ["memory"],
+ },
+ {
+ "name": "__cpp_lib_endian",
+ "values": {"c++20": 201907},
+ "headers": ["bit"],
+ },
+ {
+ "name": "__cpp_lib_erase_if",
+ "values": {"c++20": 202002},
+ "headers": [
+ "deque",
+ "forward_list",
+ "list",
+ "map",
+ "set",
+ "string",
+ "unordered_map",
+ "unordered_set",
+ "vector",
+ ],
+ },
+ {
+ "name": "__cpp_lib_exchange_function",
+ "values": {"c++14": 201304},
+ "headers": ["utility"],
+ },
+ {
+ "name": "__cpp_lib_execution",
+ "values": {"c++17": 201603, "c++20": 201902},
+ "headers": ["execution"],
+ "unimplemented": True,
+ },
+ {
+ "name": "__cpp_lib_expected",
+ "values": {"c++23": 202211},
+ "headers": ["expected"],
+ },
+ {
+ "name": "__cpp_lib_filesystem",
+ "values": {"c++17": 201703},
+ "headers": ["filesystem"],
+ "test_suite_guard": "!defined(_LIBCPP_AVAILABILITY_HAS_NO_FILESYSTEM)",
+ "libcxx_guard": "!defined(_LIBCPP_AVAILABILITY_HAS_NO_FILESYSTEM)",
+ },
+ {
+ "name": "__cpp_lib_format",
+ "values": {
+ # "c++20": 201907 Not implemented P1361R2 Integration of chrono with text formatting
+ # "c++20": 202106 Fully implemented
+ # "c++20": 202110 Not implemented P2372R3 Fixing locale handling in chrono formatters
+ "c++20": 202106,
+ # "c++23": 202207, Not implemented P2419R2 Clarify handling of encodings in localized formatting of chrono types
+ },
+ "headers": ["format"],
+ "unimplemented": True,
+ },
+ {
+ "name": "__cpp_lib_format_ranges",
+ "values": {"c++23": 202207},
+ "headers": ["format"],
+ },
+ {
+ "name": "__cpp_lib_formatters",
+ "values": {"c++23": 202302},
+ "headers": ["stacktrace", "thread"],
+ "unimplemented": True,
+ },
+ {
+ "name": "__cpp_lib_forward_like",
+ "values": {"c++23": 202207},
+ "headers": ["utility"],
+ },
+ {
+ "name": "__cpp_lib_gcd_lcm",
+ "values": {"c++17": 201606},
+ "headers": ["numeric"],
+ },
+ {
+ "name": "__cpp_lib_generic_associative_lookup",
+ "values": {"c++14": 201304},
+ "headers": ["map", "set"],
+ },
+ {
+ "name": "__cpp_lib_generic_unordered_lookup",
+ "values": {"c++20": 201811},
+ "headers": ["unordered_map", "unordered_set"],
+ },
+ {
+ "name": "__cpp_lib_hardware_interference_size",
+ "values": {"c++17": 201703},
+ "test_suite_guard": "defined(__GCC_DESTRUCTIVE_SIZE) && defined(__GCC_CONSTRUCTIVE_SIZE)",
+ "libcxx_guard": "defined(__GCC_DESTRUCTIVE_SIZE) && defined(__GCC_CONSTRUCTIVE_SIZE)",
+ "headers": ["new"],
+ },
+ {
+ "name": "__cpp_lib_has_unique_object_representations",
+ "values": {"c++17": 201606},
+ "headers": ["type_traits"],
+ },
+ {
+ "name": "__cpp_lib_hypot",
+ "values": {"c++17": 201603},
+ "headers": ["cmath"],
+ },
+ {
+ "name": "__cpp_lib_incomplete_container_elements",
+ "values": {"c++17": 201505},
+ "headers": ["forward_list", "list", "vector"],
+ },
+ {
+ "name": "__cpp_lib_int_pow2",
+ "values": {"c++20": 202002},
+ "headers": ["bit"],
+ },
+ {
+ "name": "__cpp_lib_integer_comparison_functions",
+ "values": {"c++20": 202002},
+ "headers": ["utility"],
+ },
+ {
+ "name": "__cpp_lib_integer_sequence",
+ "values": {"c++14": 201304},
+ "headers": ["utility"],
+ },
+ {
+ "name": "__cpp_lib_integral_constant_callable",
+ "values": {"c++14": 201304},
+ "headers": ["type_traits"],
+ },
+ {
+ "name": "__cpp_lib_interpolate",
+ "values": {"c++20": 201902},
+ "headers": ["cmath", "numeric"],
+ },
+ {
+ "name": "__cpp_lib_invoke",
+ "values": {"c++17": 201411},
+ "headers": ["functional"],
+ },
+ {
+ "name": "__cpp_lib_invoke_r",
+ "values": {"c++23": 202106},
+ "headers": ["functional"],
+ },
+ {
+ "name": "__cpp_lib_is_aggregate",
+ "values": {"c++17": 201703},
+ "headers": ["type_traits"],
+ },
+ {
+ "name": "__cpp_lib_is_constant_evaluated",
+ "values": {"c++20": 201811},
+ "headers": ["type_traits"],
+ },
+ {
+ "name": "__cpp_lib_is_final",
+ "values": {"c++14": 201402},
+ "headers": ["type_traits"],
+ },
+ {
+ "name": "__cpp_lib_is_invocable",
+ "values": {"c++17": 201703},
+ "headers": ["type_traits"],
+ },
+ {
+ "name": "__cpp_lib_is_layout_compatible",
+ "values": {"c++20": 201907},
+ "headers": ["type_traits"],
+ "unimplemented": True,
+ },
+ {
+ "name": "__cpp_lib_is_nothrow_convertible",
+ "values": {"c++20": 201806},
+ "headers": ["type_traits"],
+ },
+ {
+ "name": "__cpp_lib_is_null_pointer",
+ "values": {"c++14": 201309},
+ "headers": ["type_traits"],
+ },
+ {
+ "name": "__cpp_lib_is_pointer_interconvertible",
+ "values": {"c++20": 201907},
+ "headers": ["type_traits"],
+ "unimplemented": True,
+ },
+ {
+ "name": "__cpp_lib_is_scoped_enum",
+ "values": {"c++23": 202011},
+ "headers": ["type_traits"],
+ },
+ {
+ "name": "__cpp_lib_is_swappable",
+ "values": {"c++17": 201603},
+ "headers": ["type_traits"],
+ },
+ {
+ "name": "__cpp_lib_jthread",
+ "values": {"c++20": 201911},
+ "headers": ["stop_token", "thread"],
+ "test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS)",
+ "libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS)",
+ "unimplemented": True,
+ },
+ {
+ "name": "__cpp_lib_latch",
+ "values": {"c++20": 201907},
+ "headers": ["latch"],
+ "test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)",
+ "libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)",
+ },
+ {
+ "name": "__cpp_lib_launder",
+ "values": {"c++17": 201606},
+ "headers": ["new"],
+ },
+ {
+ "name": "__cpp_lib_list_remove_return_type",
+ "values": {"c++20": 201806},
+ "headers": ["forward_list", "list"],
+ },
+ {
+ "name": "__cpp_lib_logical_traits",
+ "values": {"c++17": 201510},
+ "headers": ["type_traits"],
+ },
+ {
+ "name": "__cpp_lib_make_from_tuple",
+ "values": {"c++17": 201606},
+ "headers": ["tuple"],
+ },
+ {
+ "name": "__cpp_lib_make_reverse_iterator",
+ "values": {"c++14": 201402},
+ "headers": ["iterator"],
+ },
+ {
+ "name": "__cpp_lib_make_unique",
+ "values": {"c++14": 201304},
+ "headers": ["memory"],
+ },
+ {
+ "name": "__cpp_lib_map_try_emplace",
+ "values": {"c++17": 201411},
+ "headers": ["map"],
+ },
+ {
+ "name": "__cpp_lib_math_constants",
+ "values": {"c++20": 201907},
+ "headers": ["numbers"],
+ },
+ {
+ "name": "__cpp_lib_math_special_functions",
+ "values": {"c++17": 201603},
+ "headers": ["cmath"],
+ "unimplemented": True,
+ },
+ {
+ "name": "__cpp_lib_mdspan",
+ "values": {"c++23": 202207},
+ "headers": ["mdspan"],
+ "unimplemented": True,
+ },
+ {
+ "name": "__cpp_lib_memory_resource",
+ "values": {"c++17": 201603},
+ "headers": ["memory_resource"],
+ },
+ {
+ "name": "__cpp_lib_move_iterator_concept",
+ "values": {"c++20": 202207},
+ "headers": ["iterator"],
+ },
+ {
+ "name": "__cpp_lib_move_only_function",
+ "values": {"c++23": 202110},
+ "headers": ["functional"],
+ "unimplemented": True,
+ },
+ {
+ "name": "__cpp_lib_node_extract",
+ "values": {"c++17": 201606},
+ "headers": ["map", "set", "unordered_map", "unordered_set"],
+ },
+ {
+ "name": "__cpp_lib_nonmember_container_access",
+ "values": {"c++17": 201411},
+ "headers": [
+ "array",
+ "deque",
+ "forward_list",
+ "iterator",
+ "list",
+ "map",
+ "regex",
+ "set",
+ "string",
+ "unordered_map",
+ "unordered_set",
+ "vector",
+ ],
+ },
+ {
+ "name": "__cpp_lib_not_fn",
+ "values": {"c++17": 201603},
+ "headers": ["functional"],
+ },
+ {
+ "name": "__cpp_lib_null_iterators",
+ "values": {"c++14": 201304},
+ "headers": ["iterator"],
+ },
+ {
+ "name": "__cpp_lib_optional",
+ "values": {"c++17": 201606, "c++23": 202110},
+ "headers": ["optional"],
+ },
+ {
+ "name": "__cpp_lib_out_ptr",
+ "values": {"c++23": 202106},
+ "headers": ["memory"],
+ "unimplemented": True,
+ },
+ {
+ "name": "__cpp_lib_parallel_algorithm",
+ "values": {"c++17": 201603},
+ "headers": ["algorithm", "numeric"],
+ "unimplemented": True,
+ },
+ {
+ "name": "__cpp_lib_polymorphic_allocator",
+ "values": {"c++20": 201902},
+ "headers": ["memory_resource"],
+ },
+ {
+ "name": "__cpp_lib_quoted_string_io",
+ "values": {"c++14": 201304},
+ "headers": ["iomanip"],
+ },
+ {
+ "name": "__cpp_lib_ranges",
+ "values": {"c++20": 202106},
+ "headers": ["algorithm", "functional", "iterator", "memory", "ranges"],
+ },
+ {
+ "name": "__cpp_lib_ranges_as_rvalue",
+ "values": {"c++23": 202207},
+ "headers": ["ranges"],
+ },
+ {
+ "name": "__cpp_lib_ranges_chunk",
+ "values": {"c++23": 202202},
+ "headers": ["ranges"],
+ "unimplemented": True,
+ },
+ {
+ "name": "__cpp_lib_ranges_chunk_by",
+ "values": {"c++23": 202202},
+ "headers": ["ranges"],
+ "unimplemented": True,
+ },
+ {
+ "name": "__cpp_lib_ranges_iota",
+ "values": {"c++23": 202202},
+ "headers": ["numeric"],
+ "unimplemented": True,
+ },
+ {
+ "name": "__cpp_lib_ranges_join_with",
+ "values": {"c++23": 202202},
+ "headers": ["ranges"],
+ "unimplemented": True,
+ },
+ {
+ "name": "__cpp_lib_ranges_slide",
+ "values": {"c++23": 202202},
+ "headers": ["ranges"],
+ "unimplemented": True,
+ },
+ {
+ "name": "__cpp_lib_ranges_starts_ends_with",
+ "values": {"c++23": 202106},
+ "headers": ["algorithm"],
+ "unimplemented": True,
+ },
+ {
+ "name": "__cpp_lib_ranges_to_container",
+ "values": {"c++23": 202202},
+ "headers": [
+ "deque",
+ "forward_list",
+ "list",
+ "map",
+ "priority_queue",
+ "queue",
+ "set",
+ "stack",
+ "string",
+ "unordered_map",
+ "unordered_set",
+ "vector",
+ ],
+ "unimplemented": True,
+ },
+ {
+ "name": "__cpp_lib_ranges_zip",
+ "values": {"c++23": 202110},
+ "headers": ["ranges", "tuple", "utility"],
+ "unimplemented": True,
+ },
+ {
+ "name": "__cpp_lib_raw_memory_algorithms",
+ "values": {"c++17": 201606},
+ "headers": ["memory"],
+ },
+ {
+ "name": "__cpp_lib_reference_from_temporary",
+ "values": {"c++23": 202202},
+ "headers": ["type_traits"],
+ "unimplemented": True,
+ },
+ {
+ "name": "__cpp_lib_remove_cvref",
+ "values": {"c++20": 201711},
+ "headers": ["type_traits"],
+ },
+ {
+ "name": "__cpp_lib_result_of_sfinae",
+ "values": {"c++14": 201210},
+ "headers": ["functional", "type_traits"],
+ },
+ {
+ "name": "__cpp_lib_robust_nonmodifying_seq_ops",
+ "values": {"c++14": 201304},
+ "headers": ["algorithm"],
+ },
+ {
+ "name": "__cpp_lib_sample",
+ "values": {"c++17": 201603},
+ "headers": ["algorithm"],
+ },
+ {
+ "name": "__cpp_lib_scoped_lock",
+ "values": {"c++17": 201703},
+ "headers": ["mutex"],
+ },
+ {
+ "name": "__cpp_lib_semaphore",
+ "values": {"c++20": 201907},
+ "headers": ["semaphore"],
+ "test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)",
+ "libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)",
+ },
+ {
+ "name": "__cpp_lib_shared_mutex",
+ "values": {"c++17": 201505},
+ "headers": ["shared_mutex"],
+ "test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SHARED_MUTEX)",
+ "libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SHARED_MUTEX)",
+ },
+ {
+ "name": "__cpp_lib_shared_ptr_arrays",
+ "values": {"c++17": 201611, "c++20": 201707},
+ "headers": ["memory"],
+ },
+ {
+ "name": "__cpp_lib_shared_ptr_weak_type",
+ "values": {"c++17": 201606},
+ "headers": ["memory"],
+ },
+ {
+ "name": "__cpp_lib_shared_timed_mutex",
+ "values": {"c++14": 201402},
+ "headers": ["shared_mutex"],
+ "test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SHARED_MUTEX)",
+ "libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SHARED_MUTEX)",
+ },
+ {
+ "name": "__cpp_lib_shift",
+ "values": {"c++20": 201806},
+ "headers": ["algorithm"],
+ },
+ {
+ "name": "__cpp_lib_smart_ptr_for_overwrite",
+ "values": {"c++20": 202002},
+ "headers": ["memory"],
+ "unimplemented": True,
+ },
+ {
+ "name": "__cpp_lib_source_location",
+ "values": {"c++20": 201907},
+ "headers": ["source_location"],
+ "test_suite_guard": "__has_builtin(__builtin_source_location) && !(defined(TEST_APPLE_CLANG_VER) && TEST_APPLE_CLANG_VER <= 1403)",
+ "libcxx_guard": "__has_builtin(__builtin_source_location) && !(defined(_LIBCPP_APPLE_CLANG_VER) && _LIBCPP_APPLE_CLANG_VER <= 1403)",
+ },
+ {
+ "name": "__cpp_lib_span",
+ "values": {"c++20": 202002},
+ "headers": ["span"],
+ },
+ {
+ "name": "__cpp_lib_spanstream",
+ "values": {"c++23": 202106},
+ "headers": ["spanstream"],
+ "unimplemented": True,
+ },
+ {
+ "name": "__cpp_lib_ssize",
+ "values": {"c++20": 201902},
+ "headers": ["iterator"],
+ },
+ {
+ "name": "__cpp_lib_stacktrace",
+ "values": {"c++23": 202011},
+ "headers": ["stacktrace"],
+ "unimplemented": True,
+ },
+ {
+ "name": "__cpp_lib_starts_ends_with",
+ "values": {"c++20": 201711},
+ "headers": ["string", "string_view"],
+ },
+ {
+ "name": "__cpp_lib_stdatomic_h",
+ "values": {"c++23": 202011},
+ "headers": ["stdatomic.h"],
+ },
+ {
+ "name": "__cpp_lib_string_contains",
+ "values": {"c++23": 202011},
+ "headers": ["string", "string_view"],
+ },
+ {
+ "name": "__cpp_lib_string_resize_and_overwrite",
+ "values": {"c++23": 202110},
+ "headers": ["string"],
+ },
+ {
+ "name": "__cpp_lib_string_udls",
+ "values": {"c++14": 201304},
+ "headers": ["string"],
+ },
+ {
+ "name": "__cpp_lib_string_view",
+ "values": {"c++17": 201606, "c++20": 201803},
+ "headers": ["string", "string_view"],
+ },
+ {
+ "name": "__cpp_lib_syncbuf",
+ "values": {"c++20": 201803},
+ "headers": ["syncstream"],
+ "unimplemented": True,
+ },
+ {
+ "name": "__cpp_lib_three_way_comparison",
+ "values": {"c++20": 201907},
+ "headers": ["compare"],
+ "unimplemented": True,
+ },
+ {
+ "name": "__cpp_lib_to_address",
+ "values": {"c++20": 201711},
+ "headers": ["memory"],
+ },
+ {
+ "name": "__cpp_lib_to_array",
+ "values": {"c++20": 201907},
+ "headers": ["array"],
+ },
+ {
+ "name": "__cpp_lib_to_chars",
+ "values": {"c++17": 201611},
+ "headers": ["charconv"],
+ "unimplemented": True,
+ },
+ {
+ "name": "__cpp_lib_to_underlying",
+ "values": {"c++23": 202102},
+ "headers": ["utility"],
+ },
+ {
+ "name": "__cpp_lib_transformation_trait_aliases",
+ "values": {"c++14": 201304},
+ "headers": ["type_traits"],
+ },
+ {
+ "name": "__cpp_lib_transparent_operators",
+ "values": {"c++14": 201210, "c++17": 201510},
+ "headers": ["functional", "memory"],
+ },
+ {
+ "name": "__cpp_lib_tuple_element_t",
+ "values": {"c++14": 201402},
+ "headers": ["tuple"],
+ },
+ {
+ "name": "__cpp_lib_tuples_by_type",
+ "values": {"c++14": 201304},
+ "headers": ["tuple", "utility"],
+ },
+ {
+ "name": "__cpp_lib_type_identity",
+ "values": {"c++20": 201806},
+ "headers": ["type_traits"],
+ },
+ {
+ "name": "__cpp_lib_type_trait_variable_templates",
+ "values": {"c++17": 201510},
+ "headers": ["type_traits"],
+ },
+ {
+ "name": "__cpp_lib_uncaught_exceptions",
+ "values": {"c++17": 201411},
+ "headers": ["exception"],
+ },
+ {
+ "name": "__cpp_lib_unordered_map_try_emplace",
+ "values": {"c++17": 201411},
+ "headers": ["unordered_map"],
+ },
+ {
+ "name": "__cpp_lib_unreachable",
+ "values": {"c++23": 202202},
+ "headers": ["utility"],
+ },
+ {
+ "name": "__cpp_lib_unwrap_ref",
+ "values": {"c++20": 201811},
+ "headers": ["functional"],
+ },
+ {
+ "name": "__cpp_lib_variant",
+ "values": {"c++17": 202102},
+ "headers": ["variant"],
+ },
+ {
+ "name": "__cpp_lib_void_t",
+ "values": {"c++17": 201411},
+ "headers": ["type_traits"],
+ },
+ ]
+]
assert feature_test_macros == sorted(feature_test_macros, key=lambda tc: tc["name"])
assert all(tc["headers"] == sorted(tc["headers"]) for tc in feature_test_macros)
-assert all(("libcxx_guard" in tc) == ("test_suite_guard" in tc) for tc in feature_test_macros)
-assert all(all(key in ["name", "values", "headers", "libcxx_guard", "test_suite_guard", "unimplemented"] for key in tc.keys()) for tc in feature_test_macros)
+assert all(
+ ("libcxx_guard" in tc) == ("test_suite_guard" in tc) for tc in feature_test_macros
+)
+assert all(
+ all(
+ key
+ in [
+ "name",
+ "values",
+ "headers",
+ "libcxx_guard",
+ "test_suite_guard",
+ "unimplemented",
+ ]
+ for key in tc.keys()
+ )
+ for tc in feature_test_macros
+)
# Map from each header to the Lit annotations that should be used for
# tests that include that header.
@@ -794,26 +1046,28 @@ assert all(all(key in ["name", "values", "headers", "libcxx_guard", "test_suite_
# <thread> should be marked as UNSUPPORTED, because including <thread>
# is a hard error in that case.
lit_markup = {
- "barrier": ["UNSUPPORTED: no-threads"],
- "filesystem": ["UNSUPPORTED: no-filesystem"],
- "iomanip": ["UNSUPPORTED: no-localization"],
- "ios": ["UNSUPPORTED: no-localization"],
- "iostream": ["UNSUPPORTED: no-localization"],
- "istream": ["UNSUPPORTED: no-localization"],
- "latch": ["UNSUPPORTED: no-threads"],
- "locale": ["UNSUPPORTED: no-localization"],
- "mutex": ["UNSUPPORTED: no-threads"],
- "ostream": ["UNSUPPORTED: no-localization"],
- "regex": ["UNSUPPORTED: no-localization"],
- "semaphore": ["UNSUPPORTED: no-threads"],
- "shared_mutex": ["UNSUPPORTED: no-threads"],
- "stdatomic.h": ["UNSUPPORTED: no-threads"],
- "thread": ["UNSUPPORTED: no-threads"],
+ "barrier": ["UNSUPPORTED: no-threads"],
+ "filesystem": ["UNSUPPORTED: no-filesystem"],
+ "iomanip": ["UNSUPPORTED: no-localization"],
+ "ios": ["UNSUPPORTED: no-localization"],
+ "iostream": ["UNSUPPORTED: no-localization"],
+ "istream": ["UNSUPPORTED: no-localization"],
+ "latch": ["UNSUPPORTED: no-threads"],
+ "locale": ["UNSUPPORTED: no-localization"],
+ "mutex": ["UNSUPPORTED: no-threads"],
+ "ostream": ["UNSUPPORTED: no-localization"],
+ "regex": ["UNSUPPORTED: no-localization"],
+ "semaphore": ["UNSUPPORTED: no-threads"],
+ "shared_mutex": ["UNSUPPORTED: no-threads"],
+ "stdatomic.h": ["UNSUPPORTED: no-threads"],
+ "thread": ["UNSUPPORTED: no-threads"],
}
+
def get_std_dialects():
- std_dialects = ['c++14', 'c++17', 'c++20', 'c++23', 'c++26']
- return list(std_dialects)
+ std_dialects = ["c++14", "c++17", "c++20", "c++23", "c++26"]
+ return list(std_dialects)
+
def get_first_std(d):
for s in get_std_dialects():
@@ -821,128 +1075,147 @@ def get_first_std(d):
return s
return None
+
def get_last_std(d):
- rev_dialects = get_std_dialects()
- rev_dialects.reverse()
- for s in rev_dialects:
- if s in d.keys():
- return s
- return None
+ rev_dialects = get_std_dialects()
+ rev_dialects.reverse()
+ for s in rev_dialects:
+ if s in d.keys():
+ return s
+ return None
+
def get_std_before(d, std):
- std_dialects = get_std_dialects()
- candidates = std_dialects[0:std_dialects.index(std)]
- candidates.reverse()
- for cand in candidates:
- if cand in d.keys():
- return cand
- return None
+ std_dialects = get_std_dialects()
+ candidates = std_dialects[0 : std_dialects.index(std)]
+ candidates.reverse()
+ for cand in candidates:
+ if cand in d.keys():
+ return cand
+ return None
+
def get_value_before(d, std):
- new_std = get_std_before(d, std)
- if new_std is None:
- return None
- return d[new_std]
+ new_std = get_std_before(d, std)
+ if new_std is None:
+ return None
+ return d[new_std]
+
def get_for_std(d, std):
- # This catches the C++11 case for which there should be no defined feature
- # test macros.
- std_dialects = get_std_dialects()
- if std not in std_dialects:
+ # This catches the C++11 case for which there should be no defined feature
+ # test macros.
+ std_dialects = get_std_dialects()
+ if std not in std_dialects:
+ return None
+ # Find the value for the newest C++ dialect between C++14 and std
+ std_list = list(std_dialects[0 : std_dialects.index(std) + 1])
+ std_list.reverse()
+ for s in std_list:
+ if s in d.keys():
+ return d[s]
return None
- # Find the value for the newest C++ dialect between C++14 and std
- std_list = list(std_dialects[0:std_dialects.index(std)+1])
- std_list.reverse()
- for s in std_list:
- if s in d.keys():
- return d[s]
- return None
+
def get_std_number(std):
- return std.replace('c++', '')
+ return std.replace("c++", "")
+
"""
Functions to produce the <version> header
"""
+
def produce_macros_definition_for_std(std):
- result = ""
- indent = 55
- for tc in feature_test_macros:
- if std not in tc["values"]:
- continue
- inner_indent = 1
- if 'test_suite_guard' in tc.keys():
- result += "# if %s\n" % tc["libcxx_guard"]
- inner_indent += 2
- if get_value_before(tc["values"], std) is not None:
- assert 'test_suite_guard' not in tc.keys()
- result += "# undef %s\n" % tc["name"]
- line = "#%sdefine %s" % ((" " * inner_indent), tc["name"])
- line += " " * (indent - len(line))
- line += " %sL" % tc["values"][std]
- if 'unimplemented' in tc.keys():
- line = "// " + line
- result += line
- result += "\n"
- if 'test_suite_guard' in tc.keys():
- result += "# endif\n"
- return result.strip()
+ result = ""
+ indent = 55
+ for tc in feature_test_macros:
+ if std not in tc["values"]:
+ continue
+ inner_indent = 1
+ if "test_suite_guard" in tc.keys():
+ result += "# if %s\n" % tc["libcxx_guard"]
+ inner_indent += 2
+ if get_value_before(tc["values"], std) is not None:
+ assert "test_suite_guard" not in tc.keys()
+ result += "# undef %s\n" % tc["name"]
+ line = "#%sdefine %s" % ((" " * inner_indent), tc["name"])
+ line += " " * (indent - len(line))
+ line += " %sL" % tc["values"][std]
+ if "unimplemented" in tc.keys():
+ line = "// " + line
+ result += line
+ result += "\n"
+ if "test_suite_guard" in tc.keys():
+ result += "# endif\n"
+ return result.strip()
+
def produce_macros_definitions():
- macro_definition_template = """#if _LIBCPP_STD_VER >= {std_number}
+ macro_definition_template = """#if _LIBCPP_STD_VER >= {std_number}
{macro_definition}
#endif"""
- macros_definitions = []
- for std in get_std_dialects():
- macros_definitions.append(
- macro_definition_template.format(std_number=get_std_number(std),
- macro_definition=produce_macros_definition_for_std(std)))
+ macros_definitions = []
+ for std in get_std_dialects():
+ macros_definitions.append(
+ macro_definition_template.format(
+ std_number=get_std_number(std),
+ macro_definition=produce_macros_definition_for_std(std),
+ )
+ )
+
+ return "\n\n".join(macros_definitions)
- return '\n\n'.join(macros_definitions)
def chunks(l, n):
- """Yield successive n-sized chunks from l."""
- for i in range(0, len(l), n):
- yield l[i:i + n]
+ """Yield successive n-sized chunks from l."""
+ for i in range(0, len(l), n):
+ yield l[i : i + n]
+
def produce_version_synopsis():
- indent = 56
- header_indent = 56 + len("20XXYYL ")
- result = ""
- def indent_to(s, val):
- if len(s) >= val:
- return s
- s += " " * (val - len(s))
- return s
- line = indent_to("Macro name", indent) + "Value"
- line = indent_to(line, header_indent) + "Headers"
- result += line + "\n"
- for tc in feature_test_macros:
- prev_defined_std = get_last_std(tc["values"])
- line = "{name: <{indent}}{value}L ".format(name=tc['name'], indent=indent,
- value=tc["values"][prev_defined_std])
- headers = list(tc["headers"])
- headers.remove("version")
- for chunk in chunks(headers, 3):
- line = indent_to(line, header_indent)
- chunk = ['<%s>' % header for header in chunk]
- line += ' '.join(chunk)
- result += line
- result += "\n"
- line = ""
- while True:
- prev_defined_std = get_std_before(tc["values"], prev_defined_std)
- if prev_defined_std is None:
- break
- result += "%s%sL // %s\n" % (indent_to("", indent), tc["values"][prev_defined_std],
- prev_defined_std.replace("c++", "C++"))
- return result
+ indent = 56
+ header_indent = 56 + len("20XXYYL ")
+ result = ""
+
+ def indent_to(s, val):
+ if len(s) >= val:
+ return s
+ s += " " * (val - len(s))
+ return s
+
+ line = indent_to("Macro name", indent) + "Value"
+ line = indent_to(line, header_indent) + "Headers"
+ result += line + "\n"
+ for tc in feature_test_macros:
+ prev_defined_std = get_last_std(tc["values"])
+ line = "{name: <{indent}}{value}L ".format(
+ name=tc["name"], indent=indent, value=tc["values"][prev_defined_std]
+ )
+ headers = list(tc["headers"])
+ headers.remove("version")
+ for chunk in chunks(headers, 3):
+ line = indent_to(line, header_indent)
+ chunk = ["<%s>" % header for header in chunk]
+ line += " ".join(chunk)
+ result += line
+ result += "\n"
+ line = ""
+ while True:
+ prev_defined_std = get_std_before(tc["values"], prev_defined_std)
+ if prev_defined_std is None:
+ break
+ result += "%s%sL // %s\n" % (
+ indent_to("", indent),
+ tc["values"][prev_defined_std],
+ prev_defined_std.replace("c++", "C++"),
+ )
+ return result
def produce_version_header():
- template="""// -*- C++ -*-
+ template = """// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
@@ -977,12 +1250,13 @@ def produce_version_header():
#endif // _LIBCPP_VERSIONH
"""
- version_str = template.format(
- synopsis=produce_version_synopsis().strip(),
- cxx_macros=produce_macros_definitions())
- version_header_path = os.path.join(include_path, 'version')
- with open(version_header_path, 'w', newline='\n') as f:
- f.write(version_str)
+ version_str = template.format(
+ synopsis=produce_version_synopsis().strip(),
+ cxx_macros=produce_macros_definitions(),
+ )
+ version_header_path = os.path.join(include_path, "version")
+ with open(version_header_path, "w", newline="\n") as f:
+ f.write(version_str)
"""
@@ -990,13 +1264,12 @@ def produce_version_header():
"""
test_types = {
- "undefined": """
+ "undefined": """
# ifdef {name}
# error "{name} should not be defined before {std_first}"
# endif
""",
-
- "test_suite_guard": """
+ "test_suite_guard": """
# if {test_suite_guard}
# ifndef {name}
# error "{name} should be defined in {std}"
@@ -1010,8 +1283,7 @@ test_types = {
# endif
# endif
""",
-
- "unimplemented": """
+ "unimplemented": """
# if !defined(_LIBCPP_VERSION)
# ifndef {name}
# error "{name} should be defined in {std}"
@@ -1025,35 +1297,45 @@ test_types = {
# endif
# endif
""",
-
- "defined": """
+ "defined": """
# ifndef {name}
# error "{name} should be defined in {std}"
# endif
# if {name} != {value}
# error "{name} should have the value {value} in {std}"
# endif
-"""
+""",
}
+
def generate_std_test(test_list, std):
- result = ""
- for tc in test_list:
- val = get_for_std(tc["values"], std)
- if val is not None:
- val = "%sL" % val
- if val is None:
- result += test_types["undefined"].format(name=tc["name"], std_first=get_first_std(tc["values"]))
- elif 'unimplemented' in tc.keys():
- result += test_types["unimplemented"].format(name=tc["name"], value=val, std=std)
- elif "test_suite_guard" in tc.keys():
- result += test_types["test_suite_guard"].format(name=tc["name"], value=val, std=std, test_suite_guard=tc["test_suite_guard"])
- else:
- result += test_types["defined"].format(name=tc["name"], value=val, std=std)
- return result.strip()
+ result = ""
+ for tc in test_list:
+ val = get_for_std(tc["values"], std)
+ if val is not None:
+ val = "%sL" % val
+ if val is None:
+ result += test_types["undefined"].format(
+ name=tc["name"], std_first=get_first_std(tc["values"])
+ )
+ elif "unimplemented" in tc.keys():
+ result += test_types["unimplemented"].format(
+ name=tc["name"], value=val, std=std
+ )
+ elif "test_suite_guard" in tc.keys():
+ result += test_types["test_suite_guard"].format(
+ name=tc["name"],
+ value=val,
+ std=std,
+ test_suite_guard=tc["test_suite_guard"],
+ )
+ else:
+ result += test_types["defined"].format(name=tc["name"], value=val, std=std)
+ return result.strip()
+
def generate_std_tests(test_list):
- std_tests_template = """#if TEST_STD_VER < {first_std_number}
+ std_tests_template = """#if TEST_STD_VER < {first_std_number}
{pre_std_test}
@@ -1065,48 +1347,56 @@ def generate_std_tests(test_list):
#endif // TEST_STD_VER > {penultimate_std_number}"""
- std_dialects = get_std_dialects()
+ std_dialects = get_std_dialects()
- other_std_tests = []
- for std in std_dialects[:-1]:
- other_std_tests.append('#elif TEST_STD_VER == ' + get_std_number(std))
- other_std_tests.append(generate_std_test(test_list, std))
+ other_std_tests = []
+ for std in std_dialects[:-1]:
+ other_std_tests.append("#elif TEST_STD_VER == " + get_std_number(std))
+ other_std_tests.append(generate_std_test(test_list, std))
- std_tests = std_tests_template.format(first_std_number=get_std_number(std_dialects[0]),
- pre_std_test=generate_std_test(test_list, 'c++11'),
- other_std_tests='\n\n'.join(other_std_tests),
- penultimate_std_number=get_std_number(std_dialects[-2]),
- last_std_test=generate_std_test(test_list, std_dialects[-1]))
+ std_tests = std_tests_template.format(
+ first_std_number=get_std_number(std_dialects[0]),
+ pre_std_test=generate_std_test(test_list, "c++11"),
+ other_std_tests="\n\n".join(other_std_tests),
+ penultimate_std_number=get_std_number(std_dialects[-2]),
+ last_std_test=generate_std_test(test_list, std_dialects[-1]),
+ )
+
+ return std_tests
- return std_tests
def generate_synopsis(test_list):
max_name_len = max([len(tc["name"]) for tc in test_list])
indent = max_name_len + 8
+
def mk_line(prefix, suffix):
- return "{prefix: <{max_len}}{suffix}\n".format(prefix=prefix, suffix=suffix,
- max_len=indent)
+ return "{prefix: <{max_len}}{suffix}\n".format(
+ prefix=prefix, suffix=suffix, max_len=indent
+ )
+
result = ""
result += mk_line("/* Constant", "Value")
for tc in test_list:
prefix = " %s" % tc["name"]
for std in [s for s in get_std_dialects() if s in tc["values"].keys()]:
- result += mk_line(prefix, "%sL [%s]" % (tc["values"][std], std.replace("c++", "C++")))
+ result += mk_line(
+ prefix, "%sL [%s]" % (tc["values"][std], std.replace("c++", "C++"))
+ )
prefix = ""
result += "*/"
return result
+
def produce_tests():
- headers = set([h for tc in feature_test_macros for h in tc["headers"]])
- for h in headers:
- test_list = [tc for tc in feature_test_macros if h in tc["headers"]]
- if not has_header(h):
- for tc in test_list:
- assert 'unimplemented' in tc.keys()
- continue
- markup = '\n'.join('// ' + tag for tag in lit_markup.get(h, []))
- test_body = \
-"""//===----------------------------------------------------------------------===//
+ headers = set([h for tc in feature_test_macros for h in tc["headers"]])
+ for h in headers:
+ test_list = [tc for tc in feature_test_macros if h in tc["headers"]]
+ if not has_header(h):
+ for tc in test_list:
+ assert "unimplemented" in tc.keys()
+ continue
+ markup = "\n".join("// " + tag for tag in lit_markup.get(h, []))
+ test_body = """//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -1130,75 +1420,87 @@ def produce_tests():
{cxx_tests}
-""".format(script_name=script_name,
- header=h,
- markup=('\n{}\n'.format(markup) if markup else ''),
- synopsis=generate_synopsis(test_list),
- cxx_tests=generate_std_tests(test_list))
- test_name = "{header}.version.compile.pass.cpp".format(header=h)
- out_path = os.path.join(macro_test_path, test_name)
- with open(out_path, 'w', newline='\n') as f:
- f.write(test_body)
+""".format(
+ script_name=script_name,
+ header=h,
+ markup=("\n{}\n".format(markup) if markup else ""),
+ synopsis=generate_synopsis(test_list),
+ cxx_tests=generate_std_tests(test_list),
+ )
+ test_name = "{header}.version.compile.pass.cpp".format(header=h)
+ out_path = os.path.join(macro_test_path, test_name)
+ with open(out_path, "w", newline="\n") as f:
+ f.write(test_body)
+
"""
Produce documentation for the feature test macros
"""
+
def make_widths(grid):
- widths = []
- for i in range(0, len(grid[0])):
- cell_width = 2 + max(reduce(lambda x,y: x+y, [[len(row[i])] for row in grid], []))
- widths += [cell_width]
- return widths
+ widths = []
+ for i in range(0, len(grid[0])):
+ cell_width = 2 + max(
+ reduce(lambda x, y: x + y, [[len(row[i])] for row in grid], [])
+ )
+ widths += [cell_width]
+ return widths
+
def create_table(grid, indent):
- indent_str = ' '*indent
- col_widths = make_widths(grid)
- result = [indent_str + add_divider(col_widths, 2)]
- header_flag = 2
- for row_i in range(0, len(grid)):
- row = grid[row_i]
- line = indent_str + ' '.join([pad_cell(row[i], col_widths[i]) for i in range(0, len(row))])
- result.append(line.rstrip())
- if row_i == len(grid) - 1:
- header_flag = 2
- if row[0].startswith('**'):
- header_flag += 1
- separator = indent_str + add_divider(col_widths, header_flag)
- result.append(separator.rstrip())
- header_flag = 0
- return '\n'.join(result)
+ indent_str = " " * indent
+ col_widths = make_widths(grid)
+ result = [indent_str + add_divider(col_widths, 2)]
+ header_flag = 2
+ for row_i in range(0, len(grid)):
+ row = grid[row_i]
+ line = indent_str + " ".join(
+ [pad_cell(row[i], col_widths[i]) for i in range(0, len(row))]
+ )
+ result.append(line.rstrip())
+ if row_i == len(grid) - 1:
+ header_flag = 2
+ if row[0].startswith("**"):
+ header_flag += 1
+ separator = indent_str + add_divider(col_widths, header_flag)
+ result.append(separator.rstrip())
+ header_flag = 0
+ return "\n".join(result)
+
def add_divider(widths, header_flag):
- if header_flag == 3:
- return '='.join(['='*w for w in widths])
- if header_flag == 2:
- return ' '.join(['='*w for w in widths])
- if header_flag == 1:
- return '-'.join(['-'*w for w in widths])
- else:
- return ' '.join(['-'*w for w in widths])
+ if header_flag == 3:
+ return "=".join(["=" * w for w in widths])
+ if header_flag == 2:
+ return " ".join(["=" * w for w in widths])
+ if header_flag == 1:
+ return "-".join(["-" * w for w in widths])
+ else:
+ return " ".join(["-" * w for w in widths])
+
def pad_cell(s, length, left_align=True):
- padding = ((length - len(s)) * ' ')
- return s + padding
+ padding = (length - len(s)) * " "
+ return s + padding
def get_status_table():
- table = [["Macro Name", "Value"]]
- for std in get_std_dialects():
- table += [["**" + std.replace("c++", "C++ ") + "**", ""]]
- for tc in feature_test_macros:
- if std not in tc["values"].keys():
- continue
- value = "``%sL``" % tc["values"][std]
- if 'unimplemented' in tc.keys():
- value = '*unimplemented*'
- table += [["``%s``" % tc["name"], value]]
- return table
+ table = [["Macro Name", "Value"]]
+ for std in get_std_dialects():
+ table += [["**" + std.replace("c++", "C++ ") + "**", ""]]
+ for tc in feature_test_macros:
+ if std not in tc["values"].keys():
+ continue
+ value = "``%sL``" % tc["values"][std]
+ if "unimplemented" in tc.keys():
+ value = "*unimplemented*"
+ table += [["``%s``" % tc["name"], value]]
+ return table
+
def produce_docs():
- doc_str = """.. _FeatureTestMacroTable:
+ doc_str = """.. _FeatureTestMacroTable:
==========================
Feature Test Macro Support
@@ -1223,17 +1525,20 @@ Status
{status_tables}
-""".format(status_tables=create_table(get_status_table(), 4))
+""".format(
+ status_tables=create_table(get_status_table(), 4)
+ )
+
+ table_doc_path = os.path.join(docs_path, "FeatureTestMacroTable.rst")
+ with open(table_doc_path, "w", newline="\n") as f:
+ f.write(doc_str)
- table_doc_path = os.path.join(docs_path, 'FeatureTestMacroTable.rst')
- with open(table_doc_path, 'w', newline='\n') as f:
- f.write(doc_str)
def main():
- produce_version_header()
- produce_tests()
- produce_docs()
+ produce_version_header()
+ produce_tests()
+ produce_docs()
-if __name__ == '__main__':
- main()
+if __name__ == "__main__":
+ main()
diff --git a/libcxx/utils/generate_header_inclusion_tests.py b/libcxx/utils/generate_header_inclusion_tests.py
index 1262bcd..c5797c4 100755
--- a/libcxx/utils/generate_header_inclusion_tests.py
+++ b/libcxx/utils/generate_header_inclusion_tests.py
@@ -8,9 +8,11 @@ def get_libcxx_paths():
script_name = os.path.basename(__file__)
assert os.path.exists(utils_path)
src_root = os.path.dirname(utils_path)
- test_path = os.path.join(src_root, 'test', 'libcxx', 'inclusions')
+ test_path = os.path.join(src_root, "test", "libcxx", "inclusions")
assert os.path.exists(test_path)
- assert os.path.exists(os.path.join(test_path, 'algorithm.inclusions.compile.pass.cpp'))
+ assert os.path.exists(
+ os.path.join(test_path, "algorithm.inclusions.compile.pass.cpp")
+ )
return script_name, src_root, test_path
@@ -93,46 +95,46 @@ assert all(v == sorted(v) for k, v in mandatory_inclusions.items())
# <thread> should be marked as UNSUPPORTED, because including <thread>
# is a hard error in that case.
lit_markup = {
- "barrier": ["UNSUPPORTED: no-threads"],
- "filesystem": ["UNSUPPORTED: no-filesystem"],
- "iomanip": ["UNSUPPORTED: no-localization"],
- "ios": ["UNSUPPORTED: no-localization"],
- "iostream": ["UNSUPPORTED: no-localization"],
- "istream": ["UNSUPPORTED: no-localization"],
- "latch": ["UNSUPPORTED: no-threads"],
- "locale": ["UNSUPPORTED: no-localization"],
- "mutex": ["UNSUPPORTED: no-threads"],
- "ostream": ["UNSUPPORTED: no-localization"],
- "regex": ["UNSUPPORTED: no-localization"],
- "semaphore": ["UNSUPPORTED: no-threads"],
- "shared_mutex": ["UNSUPPORTED: no-threads"],
- "thread": ["UNSUPPORTED: no-threads"]
+ "barrier": ["UNSUPPORTED: no-threads"],
+ "filesystem": ["UNSUPPORTED: no-filesystem"],
+ "iomanip": ["UNSUPPORTED: no-localization"],
+ "ios": ["UNSUPPORTED: no-localization"],
+ "iostream": ["UNSUPPORTED: no-localization"],
+ "istream": ["UNSUPPORTED: no-localization"],
+ "latch": ["UNSUPPORTED: no-threads"],
+ "locale": ["UNSUPPORTED: no-localization"],
+ "mutex": ["UNSUPPORTED: no-threads"],
+ "ostream": ["UNSUPPORTED: no-localization"],
+ "regex": ["UNSUPPORTED: no-localization"],
+ "semaphore": ["UNSUPPORTED: no-threads"],
+ "shared_mutex": ["UNSUPPORTED: no-threads"],
+ "thread": ["UNSUPPORTED: no-threads"],
}
def get_std_ver_test(includee):
v = new_in_version.get(includee, "03")
if v == "03":
- return ''
+ return ""
versions = ["03", "11", "14", "17", "20"]
- return 'TEST_STD_VER > {} && '.format(max(i for i in versions if i < v))
+ return "TEST_STD_VER > {} && ".format(max(i for i in versions if i < v))
def get_unsupported_line(includee):
v = new_in_version.get(includee, "03")
return {
"03": [],
- "11": ['UNSUPPORTED: c++03'],
- "14": ['UNSUPPORTED: c++03, c++11'],
- "17": ['UNSUPPORTED: c++03, c++11, c++14'],
- "20": ['UNSUPPORTED: c++03, c++11, c++14, c++17'],
- "23": ['UNSUPPORTED: c++03, c++11, c++14, c++17, c++20'],
- "26": ['UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23'],
+ "11": ["UNSUPPORTED: c++03"],
+ "14": ["UNSUPPORTED: c++03, c++11"],
+ "17": ["UNSUPPORTED: c++03, c++11, c++14"],
+ "20": ["UNSUPPORTED: c++03, c++11, c++14, c++17"],
+ "23": ["UNSUPPORTED: c++03, c++11, c++14, c++17, c++20"],
+ "26": ["UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23"],
}[v]
def get_libcpp_header_symbol(header_name):
- return '_LIBCPP_' + header_name.upper().replace('.', '_')
+ return "_LIBCPP_" + header_name.upper().replace(".", "_")
def get_includer_symbol_test(includer):
@@ -157,7 +159,9 @@ def get_ifdef(includer, includee):
""".strip().format(
includee_test=get_std_ver_test(includee),
symbol=symbol,
- message="<{}> should include <{}> in C++{} and later".format(includer, includee, version)
+ message="<{}> should include <{}> in C++{} and later".format(
+ includer, includee, version
+ ),
)
@@ -193,15 +197,19 @@ def produce_tests():
test_body = test_body_template.format(
script_name=script_name,
header=includer,
- markup=('\n' + '\n'.join('// ' + m for m in markup_tags) + '\n') if markup_tags else '',
+ markup=("\n" + "\n".join("// " + m for m in markup_tags) + "\n")
+ if markup_tags
+ else "",
test_includers_symbol=get_includer_symbol_test(includer),
- test_per_includee='\n'.join(get_ifdef(includer, includee) for includee in includees),
+ test_per_includee="\n".join(
+ get_ifdef(includer, includee) for includee in includees
+ ),
)
test_name = "{header}.inclusions.compile.pass.cpp".format(header=includer)
out_path = os.path.join(test_path, test_name)
- with open(out_path, 'w', newline='\n') as f:
- f.write(test_body + '\n')
+ with open(out_path, "w", newline="\n") as f:
+ f.write(test_body + "\n")
-if __name__ == '__main__':
+if __name__ == "__main__":
produce_tests()
diff --git a/libcxx/utils/generate_header_tests.py b/libcxx/utils/generate_header_tests.py
index f1664ad..905e7a4 100755
--- a/libcxx/utils/generate_header_tests.py
+++ b/libcxx/utils/generate_header_tests.py
@@ -16,12 +16,9 @@ header_restrictions = {
"shared_mutex": "!defined(_LIBCPP_HAS_NO_THREADS)",
"stdatomic.h": "__cplusplus > 202002L && !defined(_LIBCPP_HAS_NO_THREADS)",
"thread": "!defined(_LIBCPP_HAS_NO_THREADS)",
-
"filesystem": "!defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY)",
-
# TODO(LLVM-17): simplify this to __cplusplus >= 202002L
"coroutine": "(defined(__cpp_impl_coroutine) && __cpp_impl_coroutine >= 201902L) || (defined(__cpp_coroutines) && __cpp_coroutines >= 201703L)",
-
"clocale": "!defined(_LIBCPP_HAS_NO_LOCALIZATION)",
"codecvt": "!defined(_LIBCPP_HAS_NO_LOCALIZATION)",
"fstream": "!defined(_LIBCPP_HAS_NO_LOCALIZATION) && !defined(_LIBCPP_HAS_NO_FSTREAM)",
@@ -36,12 +33,10 @@ header_restrictions = {
"sstream": "!defined(_LIBCPP_HAS_NO_LOCALIZATION)",
"streambuf": "!defined(_LIBCPP_HAS_NO_LOCALIZATION)",
"strstream": "!defined(_LIBCPP_HAS_NO_LOCALIZATION)",
-
"wctype.h": "!defined(_LIBCPP_HAS_NO_WIDE_CHARACTERS)",
"cwctype": "!defined(_LIBCPP_HAS_NO_WIDE_CHARACTERS)",
"cwchar": "!defined(_LIBCPP_HAS_NO_WIDE_CHARACTERS)",
"wchar.h": "!defined(_LIBCPP_HAS_NO_WIDE_CHARACTERS)",
-
"experimental/algorithm": "__cplusplus >= 201103L",
"experimental/deque": "__cplusplus >= 201103L",
"experimental/forward_list": "__cplusplus >= 201103L",
@@ -64,89 +59,133 @@ header_restrictions = {
}
private_headers_still_public_in_modules = [
- '__assert', '__config',
- '__config_site.in', '__debug', '__hash_table',
- '__threading_support', '__tree', '__undef_macros', '__verbose_abort'
+ "__assert",
+ "__config",
+ "__config_site.in",
+ "__debug",
+ "__hash_table",
+ "__threading_support",
+ "__tree",
+ "__undef_macros",
+ "__verbose_abort",
]
+
def find_script(file):
"""Finds the script used to generate a file inside the file itself. The script is delimited by
- BEGIN-SCRIPT and END-SCRIPT markers.
+ BEGIN-SCRIPT and END-SCRIPT markers.
"""
- with open(file, 'r') as f:
+ with open(file, "r") as f:
content = f.read()
- match = re.search(r'^BEGIN-SCRIPT$(.+)^END-SCRIPT$', content, flags=re.MULTILINE | re.DOTALL)
+ match = re.search(
+ r"^BEGIN-SCRIPT$(.+)^END-SCRIPT$", content, flags=re.MULTILINE | re.DOTALL
+ )
if not match:
- raise RuntimeError("Was unable to find a script delimited with BEGIN-SCRIPT/END-SCRIPT markers in {}".format(test_file))
+ raise RuntimeError(
+ "Was unable to find a script delimited with BEGIN-SCRIPT/END-SCRIPT markers in {}".format(
+ test_file
+ )
+ )
return match.group(1)
+
def execute_script(script, variables):
"""Executes the provided Mako template with the given variables available during the
- evaluation of the script, and returns the result.
+ evaluation of the script, and returns the result.
"""
- code = compile(script, 'fake-filename', 'exec')
+ code = compile(script, "fake-filename", "exec")
output = io.StringIO()
with contextlib.redirect_stdout(output):
exec(code, variables)
output = output.getvalue()
return output
+
def generate_new_file(file, new_content):
"""Generates the new content of the file by inserting the new content in-between
- two '// GENERATED-MARKER' markers located in the file.
+ two '// GENERATED-MARKER' markers located in the file.
"""
- with open(file, 'r') as f:
+ with open(file, "r") as f:
old_content = f.read()
try:
- before, begin_marker, _, end_marker, after = re.split(r'(// GENERATED-MARKER\n)', old_content, flags=re.MULTILINE | re.DOTALL)
+ before, begin_marker, _, end_marker, after = re.split(
+ r"(// GENERATED-MARKER\n)", old_content, flags=re.MULTILINE | re.DOTALL
+ )
except ValueError:
- raise RuntimeError("Failed to split {} based on markers, please make sure the file has exactly two '// GENERATED-MARKER' occurrences".format(file))
+ raise RuntimeError(
+ "Failed to split {} based on markers, please make sure the file has exactly two '// GENERATED-MARKER' occurrences".format(
+ file
+ )
+ )
return before + begin_marker + new_content + end_marker + after
+
def produce(test_file, variables):
script = find_script(test_file)
result = execute_script(script, variables)
new_content = generate_new_file(test_file, result)
- with open(test_file, 'w', newline='\n') as f:
+ with open(test_file, "w", newline="\n") as f:
f.write(new_content)
+
def is_header(file):
"""Returns whether the given file is a header (i.e. not a directory or the modulemap file)."""
- return not file.is_dir() and not file.name == 'module.modulemap.in' and file.name != 'libcxx.imp'
+ return (
+ not file.is_dir()
+ and not file.name == "module.modulemap.in"
+ and file.name != "libcxx.imp"
+ )
def main():
- monorepo_root = pathlib.Path(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
- include = pathlib.Path(os.path.join(monorepo_root, 'libcxx', 'include'))
- test = pathlib.Path(os.path.join(monorepo_root, 'libcxx', 'test'))
- assert(monorepo_root.exists())
-
- toplevel_headers = sorted(str(p.relative_to(include)) for p in include.glob('[a-z]*') if is_header(p))
- experimental_headers = sorted(str(p.relative_to(include)) for p in include.glob('experimental/[a-z]*') if is_header(p))
- public_headers = toplevel_headers + experimental_headers
- private_headers = sorted(str(p.relative_to(include)) for p in include.rglob('*') if is_header(p) and str(p.relative_to(include)).startswith('__') and not p.name.startswith('pstl'))
+ monorepo_root = pathlib.Path(
+ os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+ )
+ include = pathlib.Path(os.path.join(monorepo_root, "libcxx", "include"))
+ test = pathlib.Path(os.path.join(monorepo_root, "libcxx", "test"))
+ assert monorepo_root.exists()
+
+ toplevel_headers = sorted(
+ str(p.relative_to(include)) for p in include.glob("[a-z]*") if is_header(p)
+ )
+ experimental_headers = sorted(
+ str(p.relative_to(include))
+ for p in include.glob("experimental/[a-z]*")
+ if is_header(p)
+ )
+ public_headers = toplevel_headers + experimental_headers
+ private_headers = sorted(
+ str(p.relative_to(include))
+ for p in include.rglob("*")
+ if is_header(p)
+ and str(p.relative_to(include)).startswith("__")
+ and not p.name.startswith("pstl")
+ )
variables = {
- 'toplevel_headers': toplevel_headers,
- 'experimental_headers': experimental_headers,
- 'public_headers': public_headers,
- 'private_headers': private_headers,
- 'header_restrictions': header_restrictions,
- 'private_headers_still_public_in_modules': private_headers_still_public_in_modules
+ "toplevel_headers": toplevel_headers,
+ "experimental_headers": experimental_headers,
+ "public_headers": public_headers,
+ "private_headers": private_headers,
+ "header_restrictions": header_restrictions,
+ "private_headers_still_public_in_modules": private_headers_still_public_in_modules,
}
- produce(test.joinpath('libcxx/assertions/headers_declare_verbose_abort.sh.cpp'), variables)
- produce(test.joinpath('libcxx/clang_tidy.sh.cpp'), variables)
- produce(test.joinpath('libcxx/double_include.sh.cpp'), variables)
- produce(test.joinpath('libcxx/min_max_macros.compile.pass.cpp'), variables)
- produce(test.joinpath('libcxx/modules_include.sh.cpp'), variables)
- produce(test.joinpath('libcxx/nasty_macros.compile.pass.cpp'), variables)
- produce(test.joinpath('libcxx/no_assert_include.compile.pass.cpp'), variables)
- produce(test.joinpath('libcxx/private_headers.verify.cpp'), variables)
- produce(test.joinpath('libcxx/transitive_includes.sh.cpp'), variables)
-
-
-if __name__ == '__main__':
+ produce(
+ test.joinpath("libcxx/assertions/headers_declare_verbose_abort.sh.cpp"),
+ variables,
+ )
+ produce(test.joinpath("libcxx/clang_tidy.sh.cpp"), variables)
+ produce(test.joinpath("libcxx/double_include.sh.cpp"), variables)
+ produce(test.joinpath("libcxx/min_max_macros.compile.pass.cpp"), variables)
+ produce(test.joinpath("libcxx/modules_include.sh.cpp"), variables)
+ produce(test.joinpath("libcxx/nasty_macros.compile.pass.cpp"), variables)
+ produce(test.joinpath("libcxx/no_assert_include.compile.pass.cpp"), variables)
+ produce(test.joinpath("libcxx/private_headers.verify.cpp"), variables)
+ produce(test.joinpath("libcxx/transitive_includes.sh.cpp"), variables)
+
+
+if __name__ == "__main__":
main()
diff --git a/libcxx/utils/generate_iwyu_mapping.py b/libcxx/utils/generate_iwyu_mapping.py
index f8377a9..621eacd 100644
--- a/libcxx/utils/generate_iwyu_mapping.py
+++ b/libcxx/utils/generate_iwyu_mapping.py
@@ -2,13 +2,17 @@
import os, pathlib, sys
+
def generate(private, public):
return f'{{ include: [ "{private}", "private", "<{public}>", "public" ] }}'
def panic(file):
- print(f'========== {__file__} error ==========', file=sys.stderr)
- print(f'\tFile \'{file}\' is a top-level detail header without a mapping', file=sys.stderr)
+ print(f"========== {__file__} error ==========", file=sys.stderr)
+ print(
+ f"\tFile '{file}' is a top-level detail header without a mapping",
+ file=sys.stderr,
+ )
sys.exit(1)
@@ -18,50 +22,75 @@ def generate_map(include):
c_headers = []
for i in include.iterdir():
- if i.is_dir() and i.name.startswith('__'):
- detail_directories.append(f'{i.name}')
+ if i.is_dir() and i.name.startswith("__"):
+ detail_directories.append(f"{i.name}")
continue
- if i.name.startswith('__'):
+ if i.name.startswith("__"):
detail_files.append(i.name)
continue
- if i.name.endswith('.h'):
+ if i.name.endswith(".h"):
c_headers.append(i.name)
result = []
- temporary_mappings = {'__locale_dir' : 'locale'}
+ temporary_mappings = {"__locale_dir": "locale"}
for i in detail_directories:
- public_header = temporary_mappings.get(i, i.lstrip('_'))
+ public_header = temporary_mappings.get(i, i.lstrip("_"))
result.append(f'{generate(f"@<{i}/.*>", public_header)},')
for i in detail_files:
public = []
- if i == '__assert': continue
- elif i == '__availability': continue
- elif i == '__bit_reference': continue
- elif i == '__bits': public = ['bits']
- elif i == '__config_site.in': continue
- elif i == '__config': continue
- elif i == '__debug': continue
- elif i == '__errc': continue
- elif i == '__hash_table': public = ['unordered_map', 'unordered_set']
- elif i == '__locale': public = ['locale']
- elif i == '__mbstate_t.h': continue
- elif i == '__mutex_base': continue
- elif i == '__node_handle': public = ['map', 'set', 'unordered_map', 'unordered_set']
- elif i == '__pstl_algorithm': continue
- elif i == '__pstl_config_site.in': continue
- elif i == '__pstl_execution': continue
- elif i == '__pstl_memory': continue
- elif i == '__pstl_numeric': continue
- elif i == '__split_buffer': public = ['deque', 'vector']
- elif i == '__std_mbstate_t.h': continue
- elif i == '__threading_support': public = ['atomic', 'mutex', 'semaphore', 'thread']
- elif i == '__tree': public = ['map', 'set']
- elif i == '__undef_macros': continue
- elif i == '__verbose_abort': continue
- else: panic(i)
+ if i == "__assert":
+ continue
+ elif i == "__availability":
+ continue
+ elif i == "__bit_reference":
+ continue
+ elif i == "__bits":
+ public = ["bits"]
+ elif i == "__config_site.in":
+ continue
+ elif i == "__config":
+ continue
+ elif i == "__debug":
+ continue
+ elif i == "__errc":
+ continue
+ elif i == "__hash_table":
+ public = ["unordered_map", "unordered_set"]
+ elif i == "__locale":
+ public = ["locale"]
+ elif i == "__mbstate_t.h":
+ continue
+ elif i == "__mutex_base":
+ continue
+ elif i == "__node_handle":
+ public = ["map", "set", "unordered_map", "unordered_set"]
+ elif i == "__pstl_algorithm":
+ continue
+ elif i == "__pstl_config_site.in":
+ continue
+ elif i == "__pstl_execution":
+ continue
+ elif i == "__pstl_memory":
+ continue
+ elif i == "__pstl_numeric":
+ continue
+ elif i == "__split_buffer":
+ public = ["deque", "vector"]
+ elif i == "__std_mbstate_t.h":
+ continue
+ elif i == "__threading_support":
+ public = ["atomic", "mutex", "semaphore", "thread"]
+ elif i == "__tree":
+ public = ["map", "set"]
+ elif i == "__undef_macros":
+ continue
+ elif i == "__verbose_abort":
+ continue
+ else:
+ panic(i)
for p in public:
result.append(f'{generate(f"<{i}>", p)},')
@@ -69,16 +98,19 @@ def generate_map(include):
result.sort()
return result
+
def main():
- monorepo_root = pathlib.Path(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
- assert(monorepo_root.exists())
- include = pathlib.Path(os.path.join(monorepo_root, 'libcxx', 'include'))
+ monorepo_root = pathlib.Path(
+ os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+ )
+ assert monorepo_root.exists()
+ include = pathlib.Path(os.path.join(monorepo_root, "libcxx", "include"))
mapping = generate_map(include)
- data = '[\n ' + '\n '.join(mapping) + '\n]\n'
- with open(f'{include}/libcxx.imp', 'w') as f:
+ data = "[\n " + "\n ".join(mapping) + "\n]\n"
+ with open(f"{include}/libcxx.imp", "w") as f:
f.write(data)
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/libcxx/utils/generate_width_estimation_table.py b/libcxx/utils/generate_width_estimation_table.py
index 0f45d1f..8739cf6 100644
--- a/libcxx/utils/generate_width_estimation_table.py
+++ b/libcxx/utils/generate_width_estimation_table.py
@@ -326,10 +326,7 @@ def generate_data_tables() -> str:
Generate Unicode data for [format.string.std]/12
"""
east_asian_width_path = (
- Path(__file__).absolute().parent
- / "data"
- / "unicode"
- / "EastAsianWidth.txt"
+ Path(__file__).absolute().parent / "data" / "unicode" / "EastAsianWidth.txt"
)
properties = list()
diff --git a/libcxx/utils/libcxx/__init__.py b/libcxx/utils/libcxx/__init__.py
index d2e99ba..e83a441d 100644
--- a/libcxx/utils/libcxx/__init__.py
+++ b/libcxx/utils/libcxx/__init__.py
@@ -1,16 +1,16 @@
-#===----------------------------------------------------------------------===##
+# ===----------------------------------------------------------------------===##
#
# 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
#
-#===----------------------------------------------------------------------===##
+# ===----------------------------------------------------------------------===##
"""libcxx python utilities"""
-__author__ = 'Eric Fiselier'
-__email__ = 'eric@efcs.ca'
+__author__ = "Eric Fiselier"
+__email__ = "eric@efcs.ca"
__versioninfo__ = (0, 1, 0)
-__version__ = ' '.join(str(v) for v in __versioninfo__) + 'dev'
+__version__ = " ".join(str(v) for v in __versioninfo__) + "dev"
__all__ = []
diff --git a/libcxx/utils/libcxx/sym_check/__init__.py b/libcxx/utils/libcxx/sym_check/__init__.py
index 0766df2..bd02778 100644
--- a/libcxx/utils/libcxx/sym_check/__init__.py
+++ b/libcxx/utils/libcxx/sym_check/__init__.py
@@ -1,16 +1,16 @@
-#===----------------------------------------------------------------------===##
+# ===----------------------------------------------------------------------===##
#
# 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
#
-#===----------------------------------------------------------------------===##
+# ===----------------------------------------------------------------------===##
"""libcxx abi symbol checker"""
-__author__ = 'Eric Fiselier'
-__email__ = 'eric@efcs.ca'
+__author__ = "Eric Fiselier"
+__email__ = "eric@efcs.ca"
__versioninfo__ = (0, 1, 0)
-__version__ = ' '.join(str(v) for v in __versioninfo__) + 'dev'
+__version__ = " ".join(str(v) for v in __versioninfo__) + "dev"
-__all__ = ['diff', 'extract', 'util']
+__all__ = ["diff", "extract", "util"]
diff --git a/libcxx/utils/libcxx/sym_check/diff.py b/libcxx/utils/libcxx/sym_check/diff.py
index cba93fa..008c6e9 100644
--- a/libcxx/utils/libcxx/sym_check/diff.py
+++ b/libcxx/utils/libcxx/sym_check/diff.py
@@ -1,11 +1,11 @@
# -*- Python -*- vim: set syntax=python tabstop=4 expandtab cc=80:
-#===----------------------------------------------------------------------===##
+# ===----------------------------------------------------------------------===##
#
# 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
#
-#===----------------------------------------------------------------------===##
+# ===----------------------------------------------------------------------===##
"""
diff - A set of functions for diff-ing two symbol lists.
"""
@@ -14,15 +14,15 @@ from libcxx.sym_check import util
def _symbol_difference(lhs, rhs):
- lhs_names = set(((n['name'], n['type']) for n in lhs))
- rhs_names = set(((n['name'], n['type']) for n in rhs))
+ lhs_names = set(((n["name"], n["type"]) for n in lhs))
+ rhs_names = set(((n["name"], n["type"]) for n in rhs))
diff_names = lhs_names - rhs_names
- return [n for n in lhs if (n['name'], n['type']) in diff_names]
+ return [n for n in lhs if (n["name"], n["type"]) in diff_names]
def _find_by_key(sym_list, k):
for sym in sym_list:
- if sym['name'] == k:
+ if sym["name"] == k:
return sym
return None
@@ -40,9 +40,8 @@ def changed_symbols(old, new):
for old_sym in old:
if old_sym in new:
continue
- new_sym = _find_by_key(new, old_sym['name'])
- if (new_sym is not None and not new_sym in old
- and old_sym != new_sym):
+ new_sym = _find_by_key(new, old_sym["name"])
+ if new_sym is not None and not new_sym in old and old_sym != new_sym:
changed += [(old_sym, new_sym)]
return changed
@@ -54,49 +53,51 @@ def diff(old, new):
return added, removed, changed
-def report_diff(added_syms, removed_syms, changed_syms, names_only=False,
- demangle=True):
+def report_diff(
+ added_syms, removed_syms, changed_syms, names_only=False, demangle=True
+):
def maybe_demangle(name):
return util.demangle_symbol(name) if demangle else name
- report = ''
+ report = ""
for sym in added_syms:
- report += 'Symbol added: %s\n' % maybe_demangle(sym['name'])
+ report += "Symbol added: %s\n" % maybe_demangle(sym["name"])
if not names_only:
- report += ' %s\n\n' % sym
+ report += " %s\n\n" % sym
if added_syms and names_only:
- report += '\n'
+ report += "\n"
for sym in removed_syms:
- report += 'SYMBOL REMOVED: %s\n' % maybe_demangle(sym['name'])
+ report += "SYMBOL REMOVED: %s\n" % maybe_demangle(sym["name"])
if not names_only:
- report += ' %s\n\n' % sym
+ report += " %s\n\n" % sym
if removed_syms and names_only:
- report += '\n'
+ report += "\n"
if not names_only:
for sym_pair in changed_syms:
old_sym, new_sym = sym_pair
- old_str = '\n OLD SYMBOL: %s' % old_sym
- new_str = '\n NEW SYMBOL: %s' % new_sym
- report += ('SYMBOL CHANGED: %s%s%s\n\n' %
- (maybe_demangle(old_sym['name']),
- old_str, new_str))
+ old_str = "\n OLD SYMBOL: %s" % old_sym
+ new_str = "\n NEW SYMBOL: %s" % new_sym
+ report += "SYMBOL CHANGED: %s%s%s\n\n" % (
+ maybe_demangle(old_sym["name"]),
+ old_str,
+ new_str,
+ )
added = bool(len(added_syms) != 0)
abi_break = bool(len(removed_syms))
if not names_only:
abi_break = abi_break or len(changed_syms)
if added or abi_break:
- report += 'Summary\n'
- report += ' Added: %d\n' % len(added_syms)
- report += ' Removed: %d\n' % len(removed_syms)
+ report += "Summary\n"
+ report += " Added: %d\n" % len(added_syms)
+ report += " Removed: %d\n" % len(removed_syms)
if not names_only:
- report += ' Changed: %d\n' % len(changed_syms)
+ report += " Changed: %d\n" % len(changed_syms)
if not abi_break:
- report += 'Symbols added.'
+ report += "Symbols added."
else:
- report += 'ABI BREAKAGE: SYMBOLS ADDED OR REMOVED!'
+ report += "ABI BREAKAGE: SYMBOLS ADDED OR REMOVED!"
else:
- report += 'Symbols match.'
- is_different = abi_break or bool(len(added_syms)) \
- or bool(len(changed_syms))
+ report += "Symbols match."
+ is_different = abi_break or bool(len(added_syms)) or bool(len(changed_syms))
return report, abi_break, is_different
diff --git a/libcxx/utils/libcxx/sym_check/extract.py b/libcxx/utils/libcxx/sym_check/extract.py
index dbf7ab1..abd4aba 100644
--- a/libcxx/utils/libcxx/sym_check/extract.py
+++ b/libcxx/utils/libcxx/sym_check/extract.py
@@ -1,11 +1,11 @@
# -*- Python -*- vim: set syntax=python tabstop=4 expandtab cc=80:
-#===----------------------------------------------------------------------===##
+# ===----------------------------------------------------------------------===##
#
# 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
#
-#===----------------------------------------------------------------------===##
+# ===----------------------------------------------------------------------===##
"""
extract - A set of function that extract symbol lists from shared libraries.
"""
@@ -18,7 +18,8 @@ import sys
from libcxx.sym_check import util
-extract_ignore_names = ['_init', '_fini']
+extract_ignore_names = ["_init", "_fini"]
+
class NMExtractor(object):
"""
@@ -30,7 +31,7 @@ class NMExtractor(object):
"""
Search for the nm executable and return the path.
"""
- return shutil.which('nm')
+ return shutil.which("nm")
def __init__(self, static_lib):
"""
@@ -43,11 +44,10 @@ class NMExtractor(object):
print("ERROR: Could not find nm")
sys.exit(1)
self.static_lib = static_lib
- self.flags = ['-P', '-g']
- if sys.platform.startswith('aix'):
+ self.flags = ["-P", "-g"]
+ if sys.platform.startswith("aix"):
# AIX nm demangles symbols by default, so suppress that.
- self.flags.append('-C')
-
+ self.flags.append("-C")
def extract(self, lib):
"""
@@ -56,8 +56,7 @@ class NMExtractor(object):
"""
cmd = [self.nm_exe] + self.flags + [lib]
out = subprocess.check_output(cmd).decode()
- fmt_syms = (self._extract_sym(l)
- for l in out.splitlines() if l.strip())
+ fmt_syms = (self._extract_sym(l) for l in out.splitlines() if l.strip())
# Cast symbol to string.
final_syms = (repr(s) for s in fmt_syms if self._want_sym(s))
# Make unique and sort strings.
@@ -71,15 +70,15 @@ class NMExtractor(object):
if len(bits) < 2:
return None
new_sym = {
- 'name': bits[0],
- 'type': bits[1],
- 'is_defined': (bits[1].lower() != 'u')
+ "name": bits[0],
+ "type": bits[1],
+ "is_defined": (bits[1].lower() != "u"),
}
- new_sym['name'] = new_sym['name'].replace('@@', '@')
+ new_sym["name"] = new_sym["name"].replace("@@", "@")
new_sym = self._transform_sym_type(new_sym)
# NM types which we want to save the size for.
- if new_sym['type'] == 'OBJECT' and len(bits) > 3:
- new_sym['size'] = int(bits[3], 16)
+ if new_sym["type"] == "OBJECT" and len(bits) > 3:
+ new_sym["size"] = int(bits[3], 16)
return new_sym
@staticmethod
@@ -89,11 +88,14 @@ class NMExtractor(object):
"""
if sym is None or len(sym) < 2:
return False
- if sym['name'] in extract_ignore_names:
+ if sym["name"] in extract_ignore_names:
return False
- bad_types = ['t', 'b', 'r', 'd', 'w']
- return (sym['type'] not in bad_types
- and sym['name'] not in ['__bss_start', '_end', '_edata'])
+ bad_types = ["t", "b", "r", "d", "w"]
+ return sym["type"] not in bad_types and sym["name"] not in [
+ "__bss_start",
+ "_end",
+ "_edata",
+ ]
@staticmethod
def _transform_sym_type(sym):
@@ -101,14 +103,15 @@ class NMExtractor(object):
Map the nm single letter output for type to either FUNC or OBJECT.
If the type is not recognized it is left unchanged.
"""
- func_types = ['T', 'W']
- obj_types = ['B', 'D', 'R', 'V', 'S']
- if sym['type'] in func_types:
- sym['type'] = 'FUNC'
- elif sym['type'] in obj_types:
- sym['type'] = 'OBJECT'
+ func_types = ["T", "W"]
+ obj_types = ["B", "D", "R", "V", "S"]
+ if sym["type"] in func_types:
+ sym["type"] = "FUNC"
+ elif sym["type"] in obj_types:
+ sym["type"] = "OBJECT"
return sym
+
class ReadElfExtractor(object):
"""
ReadElfExtractor - Extract symbol lists from libraries using readelf.
@@ -119,7 +122,7 @@ class ReadElfExtractor(object):
"""
Search for the readelf executable and return the path.
"""
- return shutil.which('readelf')
+ return shutil.which("readelf")
def __init__(self, static_lib):
"""
@@ -133,7 +136,7 @@ class ReadElfExtractor(object):
sys.exit(1)
# TODO: Support readelf for reading symbols from archives
assert not static_lib and "RealElf does not yet support static libs"
- self.flags = ['--wide', '--symbols']
+ self.flags = ["--wide", "--symbols"]
def extract(self, lib):
"""
@@ -155,18 +158,18 @@ class ReadElfExtractor(object):
if len(parts) == 7:
continue
new_sym = {
- 'name': parts[7],
- 'size': int(parts[2]),
- 'type': parts[3],
- 'is_defined': (parts[6] != 'UND')
+ "name": parts[7],
+ "size": int(parts[2]),
+ "type": parts[3],
+ "is_defined": (parts[6] != "UND"),
}
- assert new_sym['type'] in ['OBJECT', 'FUNC', 'NOTYPE', 'TLS']
- if new_sym['name'] in extract_ignore_names:
+ assert new_sym["type"] in ["OBJECT", "FUNC", "NOTYPE", "TLS"]
+ if new_sym["name"] in extract_ignore_names:
continue
- if new_sym['type'] == 'NOTYPE':
+ if new_sym["type"] == "NOTYPE":
continue
- if new_sym['type'] == 'FUNC':
- del new_sym['size']
+ if new_sym["type"] == "FUNC":
+ del new_sym["size"]
new_syms += [new_sym]
return new_syms
@@ -190,98 +193,100 @@ class ReadElfExtractor(object):
end = len(lines)
return lines[start:end]
+
class AIXDumpExtractor(object):
- """
- AIXDumpExtractor - Extract symbol lists from libraries using AIX dump.
- """
+ """
+ AIXDumpExtractor - Extract symbol lists from libraries using AIX dump.
+ """
- @staticmethod
- def find_tool():
- """
- Search for the dump executable and return the path.
- """
- return shutil.which('dump')
+ @staticmethod
+ def find_tool():
+ """
+ Search for the dump executable and return the path.
+ """
+ return shutil.which("dump")
- def __init__(self, static_lib):
- """
- Initialize the dump executable and flags that will be used to
- extract symbols from shared libraries.
- """
- # TODO: Support dump for reading symbols from static libraries
- assert not static_lib and "static libs not yet supported with dump"
- self.tool = self.find_tool()
- if self.tool is None:
- print("ERROR: Could not find dump")
- sys.exit(1)
- self.flags = ['-n', '-v']
- object_mode = environ.get('OBJECT_MODE')
- if object_mode == '32':
- self.flags += ['-X32']
- elif object_mode == '64':
- self.flags += ['-X64']
- else:
- self.flags += ['-X32_64']
+ def __init__(self, static_lib):
+ """
+ Initialize the dump executable and flags that will be used to
+ extract symbols from shared libraries.
+ """
+ # TODO: Support dump for reading symbols from static libraries
+ assert not static_lib and "static libs not yet supported with dump"
+ self.tool = self.find_tool()
+ if self.tool is None:
+ print("ERROR: Could not find dump")
+ sys.exit(1)
+ self.flags = ["-n", "-v"]
+ object_mode = environ.get("OBJECT_MODE")
+ if object_mode == "32":
+ self.flags += ["-X32"]
+ elif object_mode == "64":
+ self.flags += ["-X64"]
+ else:
+ self.flags += ["-X32_64"]
- def extract(self, lib):
- """
- Extract symbols from a library and return the results as a dict of
- parsed symbols.
- """
- cmd = [self.tool] + self.flags + [lib]
- out = subprocess.check_output(cmd).decode()
- loader_syms = self.get_loader_symbol_table(out)
- return self.process_syms(loader_syms)
+ def extract(self, lib):
+ """
+ Extract symbols from a library and return the results as a dict of
+ parsed symbols.
+ """
+ cmd = [self.tool] + self.flags + [lib]
+ out = subprocess.check_output(cmd).decode()
+ loader_syms = self.get_loader_symbol_table(out)
+ return self.process_syms(loader_syms)
- def process_syms(self, sym_list):
- new_syms = []
- for s in sym_list:
- parts = s.split()
- if not parts:
- continue
- assert len(parts) == 8 or len(parts) == 7
- if len(parts) == 7:
- continue
- new_sym = {
- 'name': parts[7],
- 'type': 'FUNC' if parts[4] == 'DS' else 'OBJECT',
- 'is_defined': (parts[5] != 'EXTref'),
- 'storage_mapping_class': parts[4],
- 'import_export': parts[3]
- }
- if new_sym['name'] in extract_ignore_names:
- continue
- new_syms += [new_sym]
- return new_syms
+ def process_syms(self, sym_list):
+ new_syms = []
+ for s in sym_list:
+ parts = s.split()
+ if not parts:
+ continue
+ assert len(parts) == 8 or len(parts) == 7
+ if len(parts) == 7:
+ continue
+ new_sym = {
+ "name": parts[7],
+ "type": "FUNC" if parts[4] == "DS" else "OBJECT",
+ "is_defined": (parts[5] != "EXTref"),
+ "storage_mapping_class": parts[4],
+ "import_export": parts[3],
+ }
+ if new_sym["name"] in extract_ignore_names:
+ continue
+ new_syms += [new_sym]
+ return new_syms
- def get_loader_symbol_table(self, out):
- lines = out.splitlines()
- return filter(lambda n: re.match(r'^\[[0-9]+\]', n), lines)
+ def get_loader_symbol_table(self, out):
+ lines = out.splitlines()
+ return filter(lambda n: re.match(r"^\[[0-9]+\]", n), lines)
- @staticmethod
- def is_shared_lib(lib):
- """
- Check for the shared object flag in XCOFF headers of the input file or
- library archive.
- """
- dump = AIXDumpExtractor.find_tool()
- if dump is None:
- print("ERROR: Could not find dump")
- sys.exit(1)
- cmd = [dump, '-X32_64', '-ov', lib]
- out = subprocess.check_output(cmd).decode()
- return out.find("SHROBJ") != -1
+ @staticmethod
+ def is_shared_lib(lib):
+ """
+ Check for the shared object flag in XCOFF headers of the input file or
+ library archive.
+ """
+ dump = AIXDumpExtractor.find_tool()
+ if dump is None:
+ print("ERROR: Could not find dump")
+ sys.exit(1)
+ cmd = [dump, "-X32_64", "-ov", lib]
+ out = subprocess.check_output(cmd).decode()
+ return out.find("SHROBJ") != -1
def is_static_library(lib_file):
- """
- Determine if a given library is static or shared.
- """
- if sys.platform.startswith('aix'):
- # An AIX library could be both, but for simplicity assume it isn't.
- return not AIXDumpExtractor.is_shared_lib(lib_file)
- else:
- _, ext = os.path.splitext(lib_file)
- return ext == '.a'
+ """
+ Determine if a given library is static or shared.
+ """
+ if sys.platform.startswith("aix"):
+ # An AIX library could be both, but for simplicity assume it isn't.
+ return not AIXDumpExtractor.is_shared_lib(lib_file)
+ else:
+ _, ext = os.path.splitext(lib_file)
+ return ext == ".a"
+
def extract_symbols(lib_file, static_lib=None):
"""
@@ -291,7 +296,7 @@ def extract_symbols(lib_file, static_lib=None):
"""
if static_lib is None:
static_lib = is_static_library(lib_file)
- if sys.platform.startswith('aix'):
+ if sys.platform.startswith("aix"):
extractor = AIXDumpExtractor(static_lib=static_lib)
elif ReadElfExtractor.find_tool() and not static_lib:
extractor = ReadElfExtractor(static_lib=static_lib)
diff --git a/libcxx/utils/libcxx/sym_check/match.py b/libcxx/utils/libcxx/sym_check/match.py
index 636e3ab..39cc0f8 100644
--- a/libcxx/utils/libcxx/sym_check/match.py
+++ b/libcxx/utils/libcxx/sym_check/match.py
@@ -1,11 +1,11 @@
# -*- Python -*- vim: set syntax=python tabstop=4 expandtab cc=80:
-#===----------------------------------------------------------------------===##
+# ===----------------------------------------------------------------------===##
#
# 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
#
-#===----------------------------------------------------------------------===##
+# ===----------------------------------------------------------------------===##
"""
match - A set of functions for matching symbols in a list to a list of regexs
"""
@@ -14,19 +14,19 @@ import re
def find_and_report_matching(symbol_list, regex_list):
- report = ''
+ report = ""
found_count = 0
for regex_str in regex_list:
report += 'Matching regex "%s":\n' % regex_str
matching_list = find_matching_symbols(symbol_list, regex_str)
if not matching_list:
- report += ' No matches found\n\n'
+ report += " No matches found\n\n"
continue
# else
found_count += len(matching_list)
for m in matching_list:
- report += ' MATCHES: %s\n' % m['name']
- report += '\n'
+ report += " MATCHES: %s\n" % m["name"]
+ report += "\n"
return found_count, report
@@ -34,6 +34,6 @@ def find_matching_symbols(symbol_list, regex_str):
regex = re.compile(regex_str)
matching_list = []
for s in symbol_list:
- if regex.match(s['name']):
+ if regex.match(s["name"]):
matching_list += [s]
return matching_list
diff --git a/libcxx/utils/libcxx/sym_check/util.py b/libcxx/utils/libcxx/sym_check/util.py
index 897f992..fc7ba42 100644
--- a/libcxx/utils/libcxx/sym_check/util.py
+++ b/libcxx/utils/libcxx/sym_check/util.py
@@ -1,10 +1,10 @@
-#===----------------------------------------------------------------------===##
+# ===----------------------------------------------------------------------===##
#
# 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
#
-#===----------------------------------------------------------------------===##
+# ===----------------------------------------------------------------------===##
from pprint import pformat
import ast
@@ -26,16 +26,16 @@ def read_syms_from_file(filename):
"""
Read a list of symbols in from a file.
"""
- with open(filename, 'r') as f:
+ with open(filename, "r") as f:
data = f.read()
return read_syms_from_list(data.splitlines())
def read_exclusions(filename):
- with open(filename, 'r') as f:
+ with open(filename, "r") as f:
data = f.read()
lines = [l.strip() for l in data.splitlines() if l.strip()]
- lines = [l for l in lines if not l.startswith('#')]
+ lines = [l for l in lines if not l.startswith("#")]
return lines
@@ -43,24 +43,24 @@ def write_syms(sym_list, out=None, names_only=False, filter=None):
"""
Write a list of symbols to the file named by out.
"""
- out_str = ''
+ out_str = ""
out_list = sym_list
- out_list.sort(key=lambda x: x['name'])
+ out_list.sort(key=lambda x: x["name"])
if filter is not None:
out_list = filter(out_list)
if names_only:
- out_list = [sym['name'] for sym in out_list]
+ out_list = [sym["name"] for sym in out_list]
for sym in out_list:
# Use pformat for consistent ordering of keys.
- out_str += pformat(sym, width=100000) + '\n'
+ out_str += pformat(sym, width=100000) + "\n"
if out is None:
sys.stdout.write(out_str)
else:
- with open(out, 'w') as f:
+ with open(out, "w") as f:
f.write(out_str)
-_cppfilt_exe = shutil.which('c++filt')
+_cppfilt_exe = shutil.which("c++filt")
def demangle_symbol(symbol):
@@ -73,35 +73,37 @@ def demangle_symbol(symbol):
def is_elf(filename):
- with open(filename, 'rb') as f:
+ with open(filename, "rb") as f:
magic_bytes = f.read(4)
- return magic_bytes == b'\x7fELF'
+ return magic_bytes == b"\x7fELF"
def is_mach_o(filename):
- with open(filename, 'rb') as f:
+ with open(filename, "rb") as f:
magic_bytes = f.read(4)
return magic_bytes in [
- b'\xfe\xed\xfa\xce', # MH_MAGIC
- b'\xce\xfa\xed\xfe', # MH_CIGAM
- b'\xfe\xed\xfa\xcf', # MH_MAGIC_64
- b'\xcf\xfa\xed\xfe', # MH_CIGAM_64
- b'\xca\xfe\xba\xbe', # FAT_MAGIC
- b'\xbe\xba\xfe\xca' # FAT_CIGAM
+ b"\xfe\xed\xfa\xce", # MH_MAGIC
+ b"\xce\xfa\xed\xfe", # MH_CIGAM
+ b"\xfe\xed\xfa\xcf", # MH_MAGIC_64
+ b"\xcf\xfa\xed\xfe", # MH_CIGAM_64
+ b"\xca\xfe\xba\xbe", # FAT_MAGIC
+ b"\xbe\xba\xfe\xca", # FAT_CIGAM
]
+
def is_xcoff_or_big_ar(filename):
- with open(filename, 'rb') as f:
+ with open(filename, "rb") as f:
magic_bytes = f.read(7)
- return magic_bytes[:4] in [
- b'\x01DF', # XCOFF32
- b'\x01F7' # XCOFF64
- ] or magic_bytes == b'<bigaf>'
+ return (
+ magic_bytes[:4] in [b"\x01DF", b"\x01F7"] # XCOFF32 # XCOFF64
+ or magic_bytes == b"<bigaf>"
+ )
+
def is_library_file(filename):
- if sys.platform == 'darwin':
+ if sys.platform == "darwin":
return is_mach_o(filename)
- elif sys.platform.startswith('aix'):
+ elif sys.platform.startswith("aix"):
return is_xcoff_or_big_ar(filename)
else:
return is_elf(filename)
@@ -109,169 +111,167 @@ def is_library_file(filename):
def extract_or_load(filename):
import libcxx.sym_check.extract
+
if is_library_file(filename):
return libcxx.sym_check.extract.extract_symbols(filename)
return read_syms_from_file(filename)
+
def adjust_mangled_name(name):
- if not name.startswith('__Z'):
+ if not name.startswith("__Z"):
return name
return name[1:]
-new_delete_std_symbols = [
- '_Znam',
- '_Znwm',
- '_ZdaPv',
- '_ZdaPvm',
- '_ZdlPv',
- '_ZdlPvm'
-]
+
+new_delete_std_symbols = ["_Znam", "_Znwm", "_ZdaPv", "_ZdaPvm", "_ZdlPv", "_ZdlPvm"]
cxxabi_symbols = [
- '___dynamic_cast',
- '___gxx_personality_v0',
- '_ZTIDi',
- '_ZTIDn',
- '_ZTIDs',
- '_ZTIPDi',
- '_ZTIPDn',
- '_ZTIPDs',
- '_ZTIPKDi',
- '_ZTIPKDn',
- '_ZTIPKDs',
- '_ZTIPKa',
- '_ZTIPKb',
- '_ZTIPKc',
- '_ZTIPKd',
- '_ZTIPKe',
- '_ZTIPKf',
- '_ZTIPKh',
- '_ZTIPKi',
- '_ZTIPKj',
- '_ZTIPKl',
- '_ZTIPKm',
- '_ZTIPKs',
- '_ZTIPKt',
- '_ZTIPKv',
- '_ZTIPKw',
- '_ZTIPKx',
- '_ZTIPKy',
- '_ZTIPa',
- '_ZTIPb',
- '_ZTIPc',
- '_ZTIPd',
- '_ZTIPe',
- '_ZTIPf',
- '_ZTIPh',
- '_ZTIPi',
- '_ZTIPj',
- '_ZTIPl',
- '_ZTIPm',
- '_ZTIPs',
- '_ZTIPt',
- '_ZTIPv',
- '_ZTIPw',
- '_ZTIPx',
- '_ZTIPy',
- '_ZTIa',
- '_ZTIb',
- '_ZTIc',
- '_ZTId',
- '_ZTIe',
- '_ZTIf',
- '_ZTIh',
- '_ZTIi',
- '_ZTIj',
- '_ZTIl',
- '_ZTIm',
- '_ZTIs',
- '_ZTIt',
- '_ZTIv',
- '_ZTIw',
- '_ZTIx',
- '_ZTIy',
- '_ZTSDi',
- '_ZTSDn',
- '_ZTSDs',
- '_ZTSPDi',
- '_ZTSPDn',
- '_ZTSPDs',
- '_ZTSPKDi',
- '_ZTSPKDn',
- '_ZTSPKDs',
- '_ZTSPKa',
- '_ZTSPKb',
- '_ZTSPKc',
- '_ZTSPKd',
- '_ZTSPKe',
- '_ZTSPKf',
- '_ZTSPKh',
- '_ZTSPKi',
- '_ZTSPKj',
- '_ZTSPKl',
- '_ZTSPKm',
- '_ZTSPKs',
- '_ZTSPKt',
- '_ZTSPKv',
- '_ZTSPKw',
- '_ZTSPKx',
- '_ZTSPKy',
- '_ZTSPa',
- '_ZTSPb',
- '_ZTSPc',
- '_ZTSPd',
- '_ZTSPe',
- '_ZTSPf',
- '_ZTSPh',
- '_ZTSPi',
- '_ZTSPj',
- '_ZTSPl',
- '_ZTSPm',
- '_ZTSPs',
- '_ZTSPt',
- '_ZTSPv',
- '_ZTSPw',
- '_ZTSPx',
- '_ZTSPy',
- '_ZTSa',
- '_ZTSb',
- '_ZTSc',
- '_ZTSd',
- '_ZTSe',
- '_ZTSf',
- '_ZTSh',
- '_ZTSi',
- '_ZTSj',
- '_ZTSl',
- '_ZTSm',
- '_ZTSs',
- '_ZTSt',
- '_ZTSv',
- '_ZTSw',
- '_ZTSx',
- '_ZTSy'
+ "___dynamic_cast",
+ "___gxx_personality_v0",
+ "_ZTIDi",
+ "_ZTIDn",
+ "_ZTIDs",
+ "_ZTIPDi",
+ "_ZTIPDn",
+ "_ZTIPDs",
+ "_ZTIPKDi",
+ "_ZTIPKDn",
+ "_ZTIPKDs",
+ "_ZTIPKa",
+ "_ZTIPKb",
+ "_ZTIPKc",
+ "_ZTIPKd",
+ "_ZTIPKe",
+ "_ZTIPKf",
+ "_ZTIPKh",
+ "_ZTIPKi",
+ "_ZTIPKj",
+ "_ZTIPKl",
+ "_ZTIPKm",
+ "_ZTIPKs",
+ "_ZTIPKt",
+ "_ZTIPKv",
+ "_ZTIPKw",
+ "_ZTIPKx",
+ "_ZTIPKy",
+ "_ZTIPa",
+ "_ZTIPb",
+ "_ZTIPc",
+ "_ZTIPd",
+ "_ZTIPe",
+ "_ZTIPf",
+ "_ZTIPh",
+ "_ZTIPi",
+ "_ZTIPj",
+ "_ZTIPl",
+ "_ZTIPm",
+ "_ZTIPs",
+ "_ZTIPt",
+ "_ZTIPv",
+ "_ZTIPw",
+ "_ZTIPx",
+ "_ZTIPy",
+ "_ZTIa",
+ "_ZTIb",
+ "_ZTIc",
+ "_ZTId",
+ "_ZTIe",
+ "_ZTIf",
+ "_ZTIh",
+ "_ZTIi",
+ "_ZTIj",
+ "_ZTIl",
+ "_ZTIm",
+ "_ZTIs",
+ "_ZTIt",
+ "_ZTIv",
+ "_ZTIw",
+ "_ZTIx",
+ "_ZTIy",
+ "_ZTSDi",
+ "_ZTSDn",
+ "_ZTSDs",
+ "_ZTSPDi",
+ "_ZTSPDn",
+ "_ZTSPDs",
+ "_ZTSPKDi",
+ "_ZTSPKDn",
+ "_ZTSPKDs",
+ "_ZTSPKa",
+ "_ZTSPKb",
+ "_ZTSPKc",
+ "_ZTSPKd",
+ "_ZTSPKe",
+ "_ZTSPKf",
+ "_ZTSPKh",
+ "_ZTSPKi",
+ "_ZTSPKj",
+ "_ZTSPKl",
+ "_ZTSPKm",
+ "_ZTSPKs",
+ "_ZTSPKt",
+ "_ZTSPKv",
+ "_ZTSPKw",
+ "_ZTSPKx",
+ "_ZTSPKy",
+ "_ZTSPa",
+ "_ZTSPb",
+ "_ZTSPc",
+ "_ZTSPd",
+ "_ZTSPe",
+ "_ZTSPf",
+ "_ZTSPh",
+ "_ZTSPi",
+ "_ZTSPj",
+ "_ZTSPl",
+ "_ZTSPm",
+ "_ZTSPs",
+ "_ZTSPt",
+ "_ZTSPv",
+ "_ZTSPw",
+ "_ZTSPx",
+ "_ZTSPy",
+ "_ZTSa",
+ "_ZTSb",
+ "_ZTSc",
+ "_ZTSd",
+ "_ZTSe",
+ "_ZTSf",
+ "_ZTSh",
+ "_ZTSi",
+ "_ZTSj",
+ "_ZTSl",
+ "_ZTSm",
+ "_ZTSs",
+ "_ZTSt",
+ "_ZTSv",
+ "_ZTSw",
+ "_ZTSx",
+ "_ZTSy",
]
+
def is_stdlib_symbol_name(name, sym):
name = adjust_mangled_name(name)
if re.search("@GLIBC|@GCC", name):
# Only when symbol is defined do we consider it ours
- return sym['is_defined']
- if re.search('(St[0-9])|(__cxa)|(__cxxabi)', name):
+ return sym["is_defined"]
+ if re.search("(St[0-9])|(__cxa)|(__cxxabi)", name):
return True
if name in new_delete_std_symbols:
return True
if name in cxxabi_symbols:
return True
- if name.startswith('_Z'):
+ if name.startswith("_Z"):
return True
return False
+
def filter_stdlib_symbols(syms):
stdlib_symbols = []
other_symbols = []
for s in syms:
- canon_name = adjust_mangled_name(s['name'])
+ canon_name = adjust_mangled_name(s["name"])
if not is_stdlib_symbol_name(canon_name, s):
other_symbols += [s]
else:
diff --git a/libcxx/utils/libcxx/test/config.py b/libcxx/utils/libcxx/test/config.py
index 253f8e8..292c9ca 100644
--- a/libcxx/utils/libcxx/test/config.py
+++ b/libcxx/utils/libcxx/test/config.py
@@ -1,49 +1,55 @@
-#===----------------------------------------------------------------------===##
+# ===----------------------------------------------------------------------===##
#
# 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
#
-#===----------------------------------------------------------------------===##
+# ===----------------------------------------------------------------------===##
import os
def _getSubstitution(substitution, config):
- for (orig, replacement) in config.substitutions:
- if orig == substitution:
- return replacement
- raise ValueError('Substitution {} is not in the config.'.format(substitution))
+ for (orig, replacement) in config.substitutions:
+ if orig == substitution:
+ return replacement
+ raise ValueError("Substitution {} is not in the config.".format(substitution))
+
def configure(parameters, features, config, lit_config):
- note = lambda s: lit_config.note("({}) {}".format(config.name, s))
- config.environment = dict(os.environ)
-
- # Apply the actions supplied by parameters to the configuration first, since
- # parameters are things that we request explicitly and which might influence
- # what features are implicitly made available next.
- for param in parameters:
- actions = param.getActions(config, lit_config.params)
- for action in actions:
- action.applyTo(config)
- if lit_config.debug:
- note("Applied '{}' as a result of parameter '{}'".format(
- action.pretty(config, lit_config.params),
- param.pretty(config, lit_config.params)))
-
- # Then, apply the automatically-detected features.
- for feature in features:
- actions = feature.getActions(config)
- for action in actions:
- action.applyTo(config)
- if lit_config.debug:
- note("Applied '{}' as a result of implicitly detected feature '{}'".format(
- action.pretty(config, lit_config.params),
- feature.pretty(config)))
-
- # Print the basic substitutions
- for sub in ('%{cxx}', '%{flags}', '%{compile_flags}', '%{link_flags}', '%{exec}'):
- note("Using {} substitution: '{}'".format(sub, _getSubstitution(sub, config)))
-
- # Print all available features
- note("All available features: {}".format(', '.join(config.available_features)))
+ note = lambda s: lit_config.note("({}) {}".format(config.name, s))
+ config.environment = dict(os.environ)
+
+ # Apply the actions supplied by parameters to the configuration first, since
+ # parameters are things that we request explicitly and which might influence
+ # what features are implicitly made available next.
+ for param in parameters:
+ actions = param.getActions(config, lit_config.params)
+ for action in actions:
+ action.applyTo(config)
+ if lit_config.debug:
+ note(
+ "Applied '{}' as a result of parameter '{}'".format(
+ action.pretty(config, lit_config.params),
+ param.pretty(config, lit_config.params),
+ )
+ )
+
+ # Then, apply the automatically-detected features.
+ for feature in features:
+ actions = feature.getActions(config)
+ for action in actions:
+ action.applyTo(config)
+ if lit_config.debug:
+ note(
+ "Applied '{}' as a result of implicitly detected feature '{}'".format(
+ action.pretty(config, lit_config.params), feature.pretty(config)
+ )
+ )
+
+ # Print the basic substitutions
+ for sub in ("%{cxx}", "%{flags}", "%{compile_flags}", "%{link_flags}", "%{exec}"):
+ note("Using {} substitution: '{}'".format(sub, _getSubstitution(sub, config)))
+
+ # Print all available features
+ note("All available features: {}".format(", ".join(config.available_features)))
diff --git a/libcxx/utils/libcxx/test/dsl.py b/libcxx/utils/libcxx/test/dsl.py
index d127337..66cf817 100644
--- a/libcxx/utils/libcxx/test/dsl.py
+++ b/libcxx/utils/libcxx/test/dsl.py
@@ -1,10 +1,10 @@
-#===----------------------------------------------------------------------===##
+# ===----------------------------------------------------------------------===##
#
# 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
#
-#===----------------------------------------------------------------------===##
+# ===----------------------------------------------------------------------===##
import os
import pickle
@@ -21,211 +21,252 @@ import lit.Test
import lit.TestRunner
import lit.util
+
class ConfigurationError(Exception):
- pass
+ pass
+
class ConfigurationCompilationError(ConfigurationError):
- pass
+ pass
+
class ConfigurationRuntimeError(ConfigurationError):
- pass
+ pass
+
def _memoizeExpensiveOperation(extractCacheKey):
- """
- Allows memoizing a very expensive operation.
-
- We pickle the cache key to make sure we store an immutable representation
- of it. If we stored an object and the object was referenced elsewhere, it
- could be changed from under our feet, which would break the cache.
-
- We also store the cache for a given function persistently across invocations
- of Lit. This dramatically speeds up the configuration of the test suite when
- invoking Lit repeatedly, which is important for developer workflow. However,
- with the current implementation that does not synchronize updates to the
- persistent cache, this also means that one should not call a memoized
- operation from multiple threads. This should normally not be a problem
- since Lit configuration is single-threaded.
- """
- def decorator(function):
- def f(config, *args, **kwargs):
- cacheRoot = os.path.join(config.test_exec_root, '__config_cache__')
- persistentCache = os.path.join(cacheRoot, function.__name__)
- if not os.path.exists(cacheRoot):
- os.makedirs(cacheRoot)
-
- cache = {}
- # Load a cache from a previous Lit invocation if there is one.
- if os.path.exists(persistentCache):
- with open(persistentCache, 'rb') as cacheFile:
- cache = pickle.load(cacheFile)
-
- cacheKey = pickle.dumps(extractCacheKey(config, *args, **kwargs))
- if cacheKey not in cache:
- cache[cacheKey] = function(config, *args, **kwargs)
- # Update the persistent cache so it knows about the new key
- with open(persistentCache, 'wb') as cacheFile:
- pickle.dump(cache, cacheFile)
- return cache[cacheKey]
- return f
- return decorator
+ """
+ Allows memoizing a very expensive operation.
+
+ We pickle the cache key to make sure we store an immutable representation
+ of it. If we stored an object and the object was referenced elsewhere, it
+ could be changed from under our feet, which would break the cache.
+
+ We also store the cache for a given function persistently across invocations
+ of Lit. This dramatically speeds up the configuration of the test suite when
+ invoking Lit repeatedly, which is important for developer workflow. However,
+ with the current implementation that does not synchronize updates to the
+ persistent cache, this also means that one should not call a memoized
+ operation from multiple threads. This should normally not be a problem
+ since Lit configuration is single-threaded.
+ """
+
+ def decorator(function):
+ def f(config, *args, **kwargs):
+ cacheRoot = os.path.join(config.test_exec_root, "__config_cache__")
+ persistentCache = os.path.join(cacheRoot, function.__name__)
+ if not os.path.exists(cacheRoot):
+ os.makedirs(cacheRoot)
+
+ cache = {}
+ # Load a cache from a previous Lit invocation if there is one.
+ if os.path.exists(persistentCache):
+ with open(persistentCache, "rb") as cacheFile:
+ cache = pickle.load(cacheFile)
+
+ cacheKey = pickle.dumps(extractCacheKey(config, *args, **kwargs))
+ if cacheKey not in cache:
+ cache[cacheKey] = function(config, *args, **kwargs)
+ # Update the persistent cache so it knows about the new key
+ with open(persistentCache, "wb") as cacheFile:
+ pickle.dump(cache, cacheFile)
+ return cache[cacheKey]
+
+ return f
+
+ return decorator
+
def _executeWithFakeConfig(test, commands):
- """
- Returns (stdout, stderr, exitCode, timeoutInfo, parsedCommands)
- """
- litConfig = lit.LitConfig.LitConfig(
- progname='lit',
- path=[],
- quiet=False,
- useValgrind=False,
- valgrindLeakCheck=False,
- valgrindArgs=[],
- noExecute=False,
- debug=False,
- isWindows=platform.system() == 'Windows',
- order='smart',
- params={})
- return libcxx.test.format._executeScriptInternal(test, litConfig, commands)
+ """
+ Returns (stdout, stderr, exitCode, timeoutInfo, parsedCommands)
+ """
+ litConfig = lit.LitConfig.LitConfig(
+ progname="lit",
+ path=[],
+ quiet=False,
+ useValgrind=False,
+ valgrindLeakCheck=False,
+ valgrindArgs=[],
+ noExecute=False,
+ debug=False,
+ isWindows=platform.system() == "Windows",
+ order="smart",
+ params={},
+ )
+ return libcxx.test.format._executeScriptInternal(test, litConfig, commands)
+
def _makeConfigTest(config):
- # Make sure the support directories exist, which is needed to create
- # the temporary file %t below.
- sourceRoot = os.path.join(config.test_exec_root, '__config_src__')
- execRoot = os.path.join(config.test_exec_root, '__config_exec__')
- for supportDir in (sourceRoot, execRoot):
- if not os.path.exists(supportDir):
- os.makedirs(supportDir)
-
- # Create a dummy test suite and single dummy test inside it. As part of
- # the Lit configuration, automatically do the equivalent of 'mkdir %T'
- # and 'rm -r %T' to avoid cluttering the build directory.
- suite = lit.Test.TestSuite('__config__', sourceRoot, execRoot, config)
- tmp = tempfile.NamedTemporaryFile(dir=sourceRoot, delete=False, suffix='.cpp')
- tmp.close()
- pathInSuite = [os.path.relpath(tmp.name, sourceRoot)]
- class TestWrapper(lit.Test.Test):
- def __enter__(self):
- testDir, _ = libcxx.test.format._getTempPaths(self)
- os.makedirs(testDir)
- return self
- def __exit__(self, *args):
- testDir, _ = libcxx.test.format._getTempPaths(self)
- shutil.rmtree(testDir)
- os.remove(tmp.name)
- return TestWrapper(suite, pathInSuite, config)
+ # Make sure the support directories exist, which is needed to create
+ # the temporary file %t below.
+ sourceRoot = os.path.join(config.test_exec_root, "__config_src__")
+ execRoot = os.path.join(config.test_exec_root, "__config_exec__")
+ for supportDir in (sourceRoot, execRoot):
+ if not os.path.exists(supportDir):
+ os.makedirs(supportDir)
+
+ # Create a dummy test suite and single dummy test inside it. As part of
+ # the Lit configuration, automatically do the equivalent of 'mkdir %T'
+ # and 'rm -r %T' to avoid cluttering the build directory.
+ suite = lit.Test.TestSuite("__config__", sourceRoot, execRoot, config)
+ tmp = tempfile.NamedTemporaryFile(dir=sourceRoot, delete=False, suffix=".cpp")
+ tmp.close()
+ pathInSuite = [os.path.relpath(tmp.name, sourceRoot)]
+
+ class TestWrapper(lit.Test.Test):
+ def __enter__(self):
+ testDir, _ = libcxx.test.format._getTempPaths(self)
+ os.makedirs(testDir)
+ return self
+
+ def __exit__(self, *args):
+ testDir, _ = libcxx.test.format._getTempPaths(self)
+ shutil.rmtree(testDir)
+ os.remove(tmp.name)
+
+ return TestWrapper(suite, pathInSuite, config)
+
@_memoizeExpensiveOperation(lambda c, s, f=[]: (c.substitutions, c.environment, s, f))
def sourceBuilds(config, source, additionalFlags=[]):
- """
- Return whether the program in the given string builds successfully.
-
- This is done by compiling and linking a program that consists of the given
- source with the %{cxx} substitution, and seeing whether that succeeds. If
- any additional flags are passed, they are appended to the compiler invocation.
- """
- with _makeConfigTest(config) as test:
- with open(test.getSourcePath(), 'w') as sourceFile:
- sourceFile.write(source)
- _, _, exitCode, _, _ = _executeWithFakeConfig(test, ['%{{build}} {}'.format(' '.join(additionalFlags))])
- return exitCode == 0
+ """
+ Return whether the program in the given string builds successfully.
-@_memoizeExpensiveOperation(lambda c, p, args=None: (c.substitutions, c.environment, p, args))
+ This is done by compiling and linking a program that consists of the given
+ source with the %{cxx} substitution, and seeing whether that succeeds. If
+ any additional flags are passed, they are appended to the compiler invocation.
+ """
+ with _makeConfigTest(config) as test:
+ with open(test.getSourcePath(), "w") as sourceFile:
+ sourceFile.write(source)
+ _, _, exitCode, _, _ = _executeWithFakeConfig(
+ test, ["%{{build}} {}".format(" ".join(additionalFlags))]
+ )
+ return exitCode == 0
+
+
+@_memoizeExpensiveOperation(
+ lambda c, p, args=None: (c.substitutions, c.environment, p, args)
+)
def programOutput(config, program, args=None):
- """
- Compiles a program for the test target, run it on the test target and return
- the output.
+ """
+ Compiles a program for the test target, run it on the test target and return
+ the output.
- Note that execution of the program is done through the %{exec} substitution,
- which means that the program may be run on a remote host depending on what
- %{exec} does.
- """
- if args is None:
- args = []
- with _makeConfigTest(config) as test:
- with open(test.getSourcePath(), 'w') as source:
- source.write(program)
- _, err, exitCode, _, buildcmd = _executeWithFakeConfig(test, ['%{build}'])
- if exitCode != 0:
- raise ConfigurationCompilationError("Failed to build program, cmd:\n{}\nstderr is:\n{}".format(buildcmd, err))
-
- out, err, exitCode, _, runcmd = _executeWithFakeConfig(test, ["%{{run}} {}".format(' '.join(args))])
- if exitCode != 0:
- raise ConfigurationRuntimeError("Failed to run program, cmd:\n{}\nstderr is:\n{}".format(runcmd, err))
-
- actualOut = re.search("# command output:\n(.+)\n$", out, flags=re.DOTALL)
- actualOut = actualOut.group(1) if actualOut else ""
- return actualOut
-
-@_memoizeExpensiveOperation(lambda c, p, args=None: (c.substitutions, c.environment, p, args))
+ Note that execution of the program is done through the %{exec} substitution,
+ which means that the program may be run on a remote host depending on what
+ %{exec} does.
+ """
+ if args is None:
+ args = []
+ with _makeConfigTest(config) as test:
+ with open(test.getSourcePath(), "w") as source:
+ source.write(program)
+ _, err, exitCode, _, buildcmd = _executeWithFakeConfig(test, ["%{build}"])
+ if exitCode != 0:
+ raise ConfigurationCompilationError(
+ "Failed to build program, cmd:\n{}\nstderr is:\n{}".format(
+ buildcmd, err
+ )
+ )
+
+ out, err, exitCode, _, runcmd = _executeWithFakeConfig(
+ test, ["%{{run}} {}".format(" ".join(args))]
+ )
+ if exitCode != 0:
+ raise ConfigurationRuntimeError(
+ "Failed to run program, cmd:\n{}\nstderr is:\n{}".format(runcmd, err)
+ )
+
+ actualOut = re.search("# command output:\n(.+)\n$", out, flags=re.DOTALL)
+ actualOut = actualOut.group(1) if actualOut else ""
+ return actualOut
+
+
+@_memoizeExpensiveOperation(
+ lambda c, p, args=None: (c.substitutions, c.environment, p, args)
+)
def programSucceeds(config, program, args=None):
- """
- Compiles a program for the test target, run it on the test target and return
- whether it completed successfully.
+ """
+ Compiles a program for the test target, run it on the test target and return
+ whether it completed successfully.
+
+ Note that execution of the program is done through the %{exec} substitution,
+ which means that the program may be run on a remote host depending on what
+ %{exec} does.
+ """
+ try:
+ programOutput(config, program, args)
+ except ConfigurationRuntimeError:
+ return False
+ return True
- Note that execution of the program is done through the %{exec} substitution,
- which means that the program may be run on a remote host depending on what
- %{exec} does.
- """
- try:
- programOutput(config, program, args)
- except ConfigurationRuntimeError:
- return False
- return True
@_memoizeExpensiveOperation(lambda c, f: (c.substitutions, c.environment, f))
def hasCompileFlag(config, flag):
- """
- Return whether the compiler in the configuration supports a given compiler flag.
+ """
+ Return whether the compiler in the configuration supports a given compiler flag.
+
+ This is done by executing the %{cxx} substitution with the given flag and
+ checking whether that succeeds.
+ """
+ with _makeConfigTest(config) as test:
+ out, err, exitCode, timeoutInfo, _ = _executeWithFakeConfig(
+ test,
+ [
+ "%{{cxx}} -xc++ {} -Werror -fsyntax-only %{{flags}} %{{compile_flags}} {}".format(
+ os.devnull, flag
+ )
+ ],
+ )
+ return exitCode == 0
- This is done by executing the %{cxx} substitution with the given flag and
- checking whether that succeeds.
- """
- with _makeConfigTest(config) as test:
- out, err, exitCode, timeoutInfo, _ = _executeWithFakeConfig(test, [
- "%{{cxx}} -xc++ {} -Werror -fsyntax-only %{{flags}} %{{compile_flags}} {}".format(os.devnull, flag)
- ])
- return exitCode == 0
@_memoizeExpensiveOperation(lambda c, s: (c.substitutions, c.environment, s))
def runScriptExitCode(config, script):
- """
- Runs the given script as a Lit test, and returns the exit code of the execution.
+ """
+ Runs the given script as a Lit test, and returns the exit code of the execution.
+
+ The script must be a list of commands, each of which being something that
+ could appear on the right-hand-side of a `RUN:` keyword.
+ """
+ with _makeConfigTest(config) as test:
+ _, _, exitCode, _, _ = _executeWithFakeConfig(test, script)
+ return exitCode
- The script must be a list of commands, each of which being something that
- could appear on the right-hand-side of a `RUN:` keyword.
- """
- with _makeConfigTest(config) as test:
- _, _, exitCode, _, _ = _executeWithFakeConfig(test, script)
- return exitCode
@_memoizeExpensiveOperation(lambda c, s: (c.substitutions, c.environment, s))
def commandOutput(config, command):
- """
- Runs the given script as a Lit test, and returns the output.
- If the exit code isn't 0 an exception is raised.
+ """
+ Runs the given script as a Lit test, and returns the output.
+ If the exit code isn't 0 an exception is raised.
+
+ The script must be a list of commands, each of which being something that
+ could appear on the right-hand-side of a `RUN:` keyword.
+ """
+ with _makeConfigTest(config) as test:
+ out, err, exitCode, _, cmd = _executeWithFakeConfig(test, command)
+ if exitCode != 0:
+ raise ConfigurationRuntimeError(
+ "Failed to run command: {}\nstderr is:\n{}".format(cmd, err)
+ )
+ return out
- The script must be a list of commands, each of which being something that
- could appear on the right-hand-side of a `RUN:` keyword.
- """
- with _makeConfigTest(config) as test:
- out, err, exitCode, _, cmd = _executeWithFakeConfig(test, command)
- if exitCode != 0:
- raise ConfigurationRuntimeError("Failed to run command: {}\nstderr is:\n{}".format(cmd, err))
- return out
@_memoizeExpensiveOperation(lambda c, l: (c.substitutions, c.environment, l))
def hasAnyLocale(config, locales):
- """
- Return whether the runtime execution environment supports a given locale.
- Different systems may use different names for a locale, so this function checks
- whether any of the passed locale names is supported by setlocale() and returns
- true if one of them works.
-
- This is done by executing a program that tries to set the given locale using
- %{exec} -- this means that the command may be executed on a remote host
- depending on the %{exec} substitution.
- """
- program = """
+ """
+ Return whether the runtime execution environment supports a given locale.
+ Different systems may use different names for a locale, so this function checks
+ whether any of the passed locale names is supported by setlocale() and returns
+ true if one of them works.
+
+ This is done by executing a program that tries to set the given locale using
+ %{exec} -- this means that the command may be executed on a remote host
+ depending on the %{exec} substitution.
+ """
+ program = """
#include <stddef.h>
#if defined(_LIBCPP_HAS_NO_LOCALIZATION)
int main(int, char**) { return 1; }
@@ -241,460 +282,532 @@ def hasAnyLocale(config, locales):
}
#endif
"""
- return programSucceeds(config, program, args=[pipes.quote(l) for l in locales])
+ return programSucceeds(config, program, args=[pipes.quote(l) for l in locales])
-@_memoizeExpensiveOperation(lambda c, flags='': (c.substitutions, c.environment, flags))
-def compilerMacros(config, flags=''):
- """
- Return a dictionary of predefined compiler macros.
- The keys are strings representing macros, and the values are strings
- representing what each macro is defined to.
+@_memoizeExpensiveOperation(lambda c, flags="": (c.substitutions, c.environment, flags))
+def compilerMacros(config, flags=""):
+ """
+ Return a dictionary of predefined compiler macros.
- If the optional `flags` argument (a string) is provided, these flags will
- be added to the compiler invocation when generating the macros.
- """
- with _makeConfigTest(config) as test:
- with open(test.getSourcePath(), 'w') as sourceFile:
- sourceFile.write("""
+ The keys are strings representing macros, and the values are strings
+ representing what each macro is defined to.
+
+ If the optional `flags` argument (a string) is provided, these flags will
+ be added to the compiler invocation when generating the macros.
+ """
+ with _makeConfigTest(config) as test:
+ with open(test.getSourcePath(), "w") as sourceFile:
+ sourceFile.write(
+ """
#if __has_include(<__config_site>)
# include <__config_site>
#endif
- """)
- unparsedOutput, err, exitCode, _, cmd = _executeWithFakeConfig(test, [
- "%{{cxx}} %s -dM -E %{{flags}} %{{compile_flags}} {}".format(flags)
- ])
- if exitCode != 0:
- raise ConfigurationCompilationError("Failed to retrieve compiler macros, compiler invocation is:\n{}\nstderr is:\n{}".format(cmd, err))
- parsedMacros = dict()
- defines = (l.strip() for l in unparsedOutput.split('\n') if l.startswith('#define '))
- for line in defines:
- line = line[len('#define '):]
- macro, _, value = line.partition(' ')
- parsedMacros[macro] = value
- return parsedMacros
-
-def featureTestMacros(config, flags=''):
- """
- Return a dictionary of feature test macros.
+ """
+ )
+ unparsedOutput, err, exitCode, _, cmd = _executeWithFakeConfig(
+ test, ["%{{cxx}} %s -dM -E %{{flags}} %{{compile_flags}} {}".format(flags)]
+ )
+ if exitCode != 0:
+ raise ConfigurationCompilationError(
+ "Failed to retrieve compiler macros, compiler invocation is:\n{}\nstderr is:\n{}".format(
+ cmd, err
+ )
+ )
+ parsedMacros = dict()
+ defines = (
+ l.strip() for l in unparsedOutput.split("\n") if l.startswith("#define ")
+ )
+ for line in defines:
+ line = line[len("#define ") :]
+ macro, _, value = line.partition(" ")
+ parsedMacros[macro] = value
+ return parsedMacros
+
+
+def featureTestMacros(config, flags=""):
+ """
+ Return a dictionary of feature test macros.
+
+ The keys are strings representing feature test macros, and the values are
+ integers representing the value of the macro.
+ """
+ allMacros = compilerMacros(config, flags)
+ return {
+ m: int(v.rstrip("LlUu"))
+ for (m, v) in allMacros.items()
+ if m.startswith("__cpp_")
+ }
- The keys are strings representing feature test macros, and the values are
- integers representing the value of the macro.
- """
- allMacros = compilerMacros(config, flags)
- return {m: int(v.rstrip('LlUu')) for (m, v) in allMacros.items() if m.startswith('__cpp_')}
def _appendToSubstitution(substitutions, key, value):
- return [(k, v + ' ' + value) if k == key else (k, v) for (k, v) in substitutions]
+ return [(k, v + " " + value) if k == key else (k, v) for (k, v) in substitutions]
+
def _prependToSubstitution(substitutions, key, value):
- return [(k, value + ' ' + v) if k == key else (k, v) for (k, v) in substitutions]
+ return [(k, value + " " + v) if k == key else (k, v) for (k, v) in substitutions]
class ConfigAction(object):
- """
- This class represents an action that can be performed on a Lit TestingConfig
- object.
+ """
+ This class represents an action that can be performed on a Lit TestingConfig
+ object.
- Examples of such actions are adding or modifying substitutions, Lit features,
- etc. This class only provides the interface of such actions, and it is meant
- to be subclassed appropriately to create new actions.
- """
- def applyTo(self, config):
+ Examples of such actions are adding or modifying substitutions, Lit features,
+ etc. This class only provides the interface of such actions, and it is meant
+ to be subclassed appropriately to create new actions.
"""
- Applies the action to the given configuration.
- This should modify the configuration object in place, and return nothing.
+ def applyTo(self, config):
+ """
+ Applies the action to the given configuration.
- If applying the action to the configuration would yield an invalid
- configuration, and it is possible to diagnose it here, this method
- should produce an error. For example, it should be an error to modify
- a substitution in a way that we know for sure is invalid (e.g. adding
- a compiler flag when we know the compiler doesn't support it). Failure
- to do so early may lead to difficult-to-diagnose issues down the road.
- """
- pass
+ This should modify the configuration object in place, and return nothing.
- def pretty(self, config, litParams):
- """
- Returns a short and human-readable string describing what this action does.
+ If applying the action to the configuration would yield an invalid
+ configuration, and it is possible to diagnose it here, this method
+ should produce an error. For example, it should be an error to modify
+ a substitution in a way that we know for sure is invalid (e.g. adding
+ a compiler flag when we know the compiler doesn't support it). Failure
+ to do so early may lead to difficult-to-diagnose issues down the road.
+ """
+ pass
- This is used for logging purposes when running the test suite, so it should
- be kept concise.
- """
- pass
+ def pretty(self, config, litParams):
+ """
+ Returns a short and human-readable string describing what this action does.
+
+ This is used for logging purposes when running the test suite, so it should
+ be kept concise.
+ """
+ pass
class AddFeature(ConfigAction):
- """
- This action defines the given Lit feature when running the test suite.
+ """
+ This action defines the given Lit feature when running the test suite.
- The name of the feature can be a string or a callable, in which case it is
- called with the configuration to produce the feature name (as a string).
- """
- def __init__(self, name):
- self._name = name
+ The name of the feature can be a string or a callable, in which case it is
+ called with the configuration to produce the feature name (as a string).
+ """
- def _getName(self, config):
- name = self._name(config) if callable(self._name) else self._name
- if not isinstance(name, str):
- raise ValueError("Lit feature did not resolve to a string (got {})".format(name))
- return name
+ def __init__(self, name):
+ self._name = name
- def applyTo(self, config):
- config.available_features.add(self._getName(config))
+ def _getName(self, config):
+ name = self._name(config) if callable(self._name) else self._name
+ if not isinstance(name, str):
+ raise ValueError(
+ "Lit feature did not resolve to a string (got {})".format(name)
+ )
+ return name
- def pretty(self, config, litParams):
- return 'add Lit feature {}'.format(self._getName(config))
+ def applyTo(self, config):
+ config.available_features.add(self._getName(config))
+
+ def pretty(self, config, litParams):
+ return "add Lit feature {}".format(self._getName(config))
class AddFlag(ConfigAction):
- """
- This action adds the given flag to the %{flags} substitution.
+ """
+ This action adds the given flag to the %{flags} substitution.
- The flag can be a string or a callable, in which case it is called with the
- configuration to produce the actual flag (as a string).
- """
- def __init__(self, flag):
- self._getFlag = lambda config: flag(config) if callable(flag) else flag
+ The flag can be a string or a callable, in which case it is called with the
+ configuration to produce the actual flag (as a string).
+ """
- def applyTo(self, config):
- flag = self._getFlag(config)
- assert hasCompileFlag(config, flag), "Trying to enable flag {}, which is not supported".format(flag)
- config.substitutions = _appendToSubstitution(config.substitutions, '%{flags}', flag)
+ def __init__(self, flag):
+ self._getFlag = lambda config: flag(config) if callable(flag) else flag
- def pretty(self, config, litParams):
- return 'add {} to %{{flags}}'.format(self._getFlag(config))
+ def applyTo(self, config):
+ flag = self._getFlag(config)
+ assert hasCompileFlag(
+ config, flag
+ ), "Trying to enable flag {}, which is not supported".format(flag)
+ config.substitutions = _appendToSubstitution(
+ config.substitutions, "%{flags}", flag
+ )
+
+ def pretty(self, config, litParams):
+ return "add {} to %{{flags}}".format(self._getFlag(config))
class AddFlagIfSupported(ConfigAction):
- """
- This action adds the given flag to the %{flags} substitution, only if
- the compiler supports the flag.
+ """
+ This action adds the given flag to the %{flags} substitution, only if
+ the compiler supports the flag.
- The flag can be a string or a callable, in which case it is called with the
- configuration to produce the actual flag (as a string).
- """
- def __init__(self, flag):
- self._getFlag = lambda config: flag(config) if callable(flag) else flag
+ The flag can be a string or a callable, in which case it is called with the
+ configuration to produce the actual flag (as a string).
+ """
+
+ def __init__(self, flag):
+ self._getFlag = lambda config: flag(config) if callable(flag) else flag
- def applyTo(self, config):
- flag = self._getFlag(config)
- if hasCompileFlag(config, flag):
- config.substitutions = _appendToSubstitution(config.substitutions, '%{flags}', flag)
+ def applyTo(self, config):
+ flag = self._getFlag(config)
+ if hasCompileFlag(config, flag):
+ config.substitutions = _appendToSubstitution(
+ config.substitutions, "%{flags}", flag
+ )
- def pretty(self, config, litParams):
- return 'add {} to %{{flags}}'.format(self._getFlag(config))
+ def pretty(self, config, litParams):
+ return "add {} to %{{flags}}".format(self._getFlag(config))
class AddCompileFlag(ConfigAction):
- """
- This action adds the given flag to the %{compile_flags} substitution.
+ """
+ This action adds the given flag to the %{compile_flags} substitution.
- The flag can be a string or a callable, in which case it is called with the
- configuration to produce the actual flag (as a string).
- """
- def __init__(self, flag):
- self._getFlag = lambda config: flag(config) if callable(flag) else flag
+ The flag can be a string or a callable, in which case it is called with the
+ configuration to produce the actual flag (as a string).
+ """
+
+ def __init__(self, flag):
+ self._getFlag = lambda config: flag(config) if callable(flag) else flag
- def applyTo(self, config):
- flag = self._getFlag(config)
- assert hasCompileFlag(config, flag), "Trying to enable compile flag {}, which is not supported".format(flag)
- config.substitutions = _appendToSubstitution(config.substitutions, '%{compile_flags}', flag)
+ def applyTo(self, config):
+ flag = self._getFlag(config)
+ assert hasCompileFlag(
+ config, flag
+ ), "Trying to enable compile flag {}, which is not supported".format(flag)
+ config.substitutions = _appendToSubstitution(
+ config.substitutions, "%{compile_flags}", flag
+ )
- def pretty(self, config, litParams):
- return 'add {} to %{{compile_flags}}'.format(self._getFlag(config))
+ def pretty(self, config, litParams):
+ return "add {} to %{{compile_flags}}".format(self._getFlag(config))
class AddLinkFlag(ConfigAction):
- """
- This action appends the given flag to the %{link_flags} substitution.
+ """
+ This action appends the given flag to the %{link_flags} substitution.
- The flag can be a string or a callable, in which case it is called with the
- configuration to produce the actual flag (as a string).
- """
- def __init__(self, flag):
- self._getFlag = lambda config: flag(config) if callable(flag) else flag
+ The flag can be a string or a callable, in which case it is called with the
+ configuration to produce the actual flag (as a string).
+ """
- def applyTo(self, config):
- flag = self._getFlag(config)
- assert hasCompileFlag(config, flag), "Trying to enable link flag {}, which is not supported".format(flag)
- config.substitutions = _appendToSubstitution(config.substitutions, '%{link_flags}', flag)
+ def __init__(self, flag):
+ self._getFlag = lambda config: flag(config) if callable(flag) else flag
- def pretty(self, config, litParams):
- return 'append {} to %{{link_flags}}'.format(self._getFlag(config))
+ def applyTo(self, config):
+ flag = self._getFlag(config)
+ assert hasCompileFlag(
+ config, flag
+ ), "Trying to enable link flag {}, which is not supported".format(flag)
+ config.substitutions = _appendToSubstitution(
+ config.substitutions, "%{link_flags}", flag
+ )
+
+ def pretty(self, config, litParams):
+ return "append {} to %{{link_flags}}".format(self._getFlag(config))
class PrependLinkFlag(ConfigAction):
- """
- This action prepends the given flag to the %{link_flags} substitution.
+ """
+ This action prepends the given flag to the %{link_flags} substitution.
- The flag can be a string or a callable, in which case it is called with the
- configuration to produce the actual flag (as a string).
- """
- def __init__(self, flag):
- self._getFlag = lambda config: flag(config) if callable(flag) else flag
+ The flag can be a string or a callable, in which case it is called with the
+ configuration to produce the actual flag (as a string).
+ """
- def applyTo(self, config):
- flag = self._getFlag(config)
- assert hasCompileFlag(config, flag), "Trying to enable link flag {}, which is not supported".format(flag)
- config.substitutions = _prependToSubstitution(config.substitutions, '%{link_flags}', flag)
+ def __init__(self, flag):
+ self._getFlag = lambda config: flag(config) if callable(flag) else flag
- def pretty(self, config, litParams):
- return 'prepend {} to %{{link_flags}}'.format(self._getFlag(config))
+ def applyTo(self, config):
+ flag = self._getFlag(config)
+ assert hasCompileFlag(
+ config, flag
+ ), "Trying to enable link flag {}, which is not supported".format(flag)
+ config.substitutions = _prependToSubstitution(
+ config.substitutions, "%{link_flags}", flag
+ )
+
+ def pretty(self, config, litParams):
+ return "prepend {} to %{{link_flags}}".format(self._getFlag(config))
class AddOptionalWarningFlag(ConfigAction):
- """
- This action adds the given warning flag to the %{compile_flags} substitution,
- if it is supported by the compiler.
+ """
+ This action adds the given warning flag to the %{compile_flags} substitution,
+ if it is supported by the compiler.
- The flag can be a string or a callable, in which case it is called with the
- configuration to produce the actual flag (as a string).
- """
- def __init__(self, flag):
- self._getFlag = lambda config: flag(config) if callable(flag) else flag
+ The flag can be a string or a callable, in which case it is called with the
+ configuration to produce the actual flag (as a string).
+ """
- def applyTo(self, config):
- flag = self._getFlag(config)
- # Use -Werror to make sure we see an error about the flag being unsupported.
- if hasCompileFlag(config, '-Werror ' + flag):
- config.substitutions = _appendToSubstitution(config.substitutions, '%{compile_flags}', flag)
+ def __init__(self, flag):
+ self._getFlag = lambda config: flag(config) if callable(flag) else flag
- def pretty(self, config, litParams):
- return 'add {} to %{{compile_flags}}'.format(self._getFlag(config))
+ def applyTo(self, config):
+ flag = self._getFlag(config)
+ # Use -Werror to make sure we see an error about the flag being unsupported.
+ if hasCompileFlag(config, "-Werror " + flag):
+ config.substitutions = _appendToSubstitution(
+ config.substitutions, "%{compile_flags}", flag
+ )
+ def pretty(self, config, litParams):
+ return "add {} to %{{compile_flags}}".format(self._getFlag(config))
-class AddSubstitution(ConfigAction):
- """
- This action adds the given substitution to the Lit configuration.
- The substitution can be a string or a callable, in which case it is called
- with the configuration to produce the actual substitution (as a string).
- """
- def __init__(self, key, substitution):
- self._key = key
- self._getSub = lambda config: substitution(config) if callable(substitution) else substitution
+class AddSubstitution(ConfigAction):
+ """
+ This action adds the given substitution to the Lit configuration.
- def applyTo(self, config):
- key = self._key
- sub = self._getSub(config)
- config.substitutions.append((key, sub))
+ The substitution can be a string or a callable, in which case it is called
+ with the configuration to produce the actual substitution (as a string).
+ """
- def pretty(self, config, litParams):
- return 'add substitution {} = {}'.format(self._key, self._getSub(config))
+ def __init__(self, key, substitution):
+ self._key = key
+ self._getSub = (
+ lambda config: substitution(config)
+ if callable(substitution)
+ else substitution
+ )
+ def applyTo(self, config):
+ key = self._key
+ sub = self._getSub(config)
+ config.substitutions.append((key, sub))
-class Feature(object):
- """
- Represents a Lit available feature that is enabled whenever it is supported.
+ def pretty(self, config, litParams):
+ return "add substitution {} = {}".format(self._key, self._getSub(config))
- A feature like this informs the test suite about a capability of the compiler,
- platform, etc. Unlike Parameters, it does not make sense to explicitly
- control whether a Feature is enabled -- it should be enabled whenever it
- is supported.
- """
- def __init__(self, name, actions=None, when=lambda _: True):
- """
- Create a Lit feature for consumption by a test suite.
-
- - name
- The name of the feature. This is what will end up in Lit's available
- features if the feature is enabled. This can be either a string or a
- callable, in which case it is passed the TestingConfig and should
- generate a string representing the name of the feature.
-
- - actions
- An optional list of ConfigActions to apply when the feature is supported.
- An AddFeature action is always created regardless of any actions supplied
- here -- these actions are meant to perform more than setting a corresponding
- Lit feature (e.g. adding compiler flags). If 'actions' is a callable, it
- is called with the current configuration object to generate the actual
- list of actions.
-
- - when
- A callable that gets passed a TestingConfig and should return a
- boolean representing whether the feature is supported in that
- configuration. For example, this can use `hasCompileFlag` to
- check whether the compiler supports the flag that the feature
- represents. If omitted, the feature will always be considered
- supported.
- """
- self._name = name
- self._actions = [] if actions is None else actions
- self._isSupported = when
-
- def _getName(self, config):
- name = self._name(config) if callable(self._name) else self._name
- if not isinstance(name, str):
- raise ValueError("Feature did not resolve to a name that's a string, got {}".format(name))
- return name
-
- def getActions(self, config):
- """
- Return the list of actions associated to this feature.
-
- If the feature is not supported, an empty list is returned.
- If the feature is supported, an `AddFeature` action is automatically added
- to the returned list of actions, in addition to any actions provided on
- construction.
- """
- if not self._isSupported(config):
- return []
- else:
- actions = self._actions(config) if callable(self._actions) else self._actions
- return [AddFeature(self._getName(config))] + actions
- def pretty(self, config):
- """
- Returns the Feature's name.
+class Feature(object):
"""
- return self._getName(config)
-
-
-def _str_to_bool(s):
- """
- Convert a string value to a boolean.
-
- True values are "y", "yes", "t", "true", "on" and "1", regardless of capitalization.
- False values are "n", "no", "f", "false", "off" and "0", regardless of capitalization.
- """
- trueVals = ["y", "yes", "t", "true", "on", "1"]
- falseVals = ["n", "no", "f", "false", "off", "0"]
- lower = s.lower()
- if lower in trueVals:
- return True
- elif lower in falseVals:
- return False
- else:
- raise ValueError("Got string '{}', which isn't a valid boolean".format(s))
-
-def _parse_parameter(s, type):
- if type is bool and isinstance(s, str):
- return _str_to_bool(s)
- elif type is list and isinstance(s, str):
- return [x.strip() for x in s.split(',') if x.strip()]
- return type(s)
+ Represents a Lit available feature that is enabled whenever it is supported.
+ A feature like this informs the test suite about a capability of the compiler,
+ platform, etc. Unlike Parameters, it does not make sense to explicitly
+ control whether a Feature is enabled -- it should be enabled whenever it
+ is supported.
+ """
-class Parameter(object):
- """
- Represents a parameter of a Lit test suite.
-
- Parameters are used to customize the behavior of test suites in a user
- controllable way. There are two ways of setting the value of a Parameter.
- The first one is to pass `--param <KEY>=<VALUE>` when running Lit (or
- equivalently to set `litConfig.params[KEY] = VALUE` somewhere in the
- Lit configuration files. This method will set the parameter globally for
- all test suites being run.
-
- The second method is to set `config.KEY = VALUE` somewhere in the Lit
- configuration files, which sets the parameter only for the test suite(s)
- that use that `config` object.
-
- Parameters can have multiple possible values, and they can have a default
- value when left unspecified. They can also have any number of ConfigActions
- associated to them, in which case the actions will be performed on the
- TestingConfig if the parameter is enabled. Depending on the actions
- associated to a Parameter, it may be an error to enable the Parameter
- if some actions are not supported in the given configuration. For example,
- trying to set the compilation standard to C++23 when `-std=c++23` is not
- supported by the compiler would be an error.
- """
- def __init__(self, name, type, help, actions, choices=None, default=None):
- """
- Create a Lit parameter to customize the behavior of a test suite.
-
- - name
- The name of the parameter that can be used to set it on the command-line.
- On the command-line, the parameter can be set using `--param <name>=<value>`
- when running Lit. This must be non-empty.
-
- - choices
- An optional non-empty set of possible values for this parameter. If provided,
- this must be anything that can be iterated. It is an error if the parameter
- is given a value that is not in that set, whether explicitly or through a
- default value.
-
- - type
- A callable that can be used to parse the value of the parameter given
- on the command-line. As a special case, using the type `bool` also
- allows parsing strings with boolean-like contents, and the type `list`
- will parse a string delimited by commas into a list of the substrings.
-
- - help
- A string explaining the parameter, for documentation purposes.
- TODO: We should be able to surface those from the Lit command-line.
-
- - actions
- A callable that gets passed the parsed value of the parameter (either
- the one passed on the command-line or the default one), and that returns
- a list of ConfigAction to perform given the value of the parameter.
- All the ConfigAction must be supported in the given configuration.
-
- - default
- An optional default value to use for the parameter when no value is
- provided on the command-line. If the default value is a callable, it
- is called with the TestingConfig and should return the default value
- for the parameter. Whether the default value is computed or specified
- directly, it must be in the 'choices' provided for that Parameter.
- """
- self._name = name
- if len(self._name) == 0:
- raise ValueError("Parameter name must not be the empty string")
-
- if choices is not None:
- self._choices = list(choices) # should be finite
- if len(self._choices) == 0:
- raise ValueError("Parameter '{}' must be given at least one possible value".format(self._name))
- else:
- self._choices = None
+ def __init__(self, name, actions=None, when=lambda _: True):
+ """
+ Create a Lit feature for consumption by a test suite.
+
+ - name
+ The name of the feature. This is what will end up in Lit's available
+ features if the feature is enabled. This can be either a string or a
+ callable, in which case it is passed the TestingConfig and should
+ generate a string representing the name of the feature.
+
+ - actions
+ An optional list of ConfigActions to apply when the feature is supported.
+ An AddFeature action is always created regardless of any actions supplied
+ here -- these actions are meant to perform more than setting a corresponding
+ Lit feature (e.g. adding compiler flags). If 'actions' is a callable, it
+ is called with the current configuration object to generate the actual
+ list of actions.
+
+ - when
+ A callable that gets passed a TestingConfig and should return a
+ boolean representing whether the feature is supported in that
+ configuration. For example, this can use `hasCompileFlag` to
+ check whether the compiler supports the flag that the feature
+ represents. If omitted, the feature will always be considered
+ supported.
+ """
+ self._name = name
+ self._actions = [] if actions is None else actions
+ self._isSupported = when
+
+ def _getName(self, config):
+ name = self._name(config) if callable(self._name) else self._name
+ if not isinstance(name, str):
+ raise ValueError(
+ "Feature did not resolve to a name that's a string, got {}".format(name)
+ )
+ return name
+
+ def getActions(self, config):
+ """
+ Return the list of actions associated to this feature.
+
+ If the feature is not supported, an empty list is returned.
+ If the feature is supported, an `AddFeature` action is automatically added
+ to the returned list of actions, in addition to any actions provided on
+ construction.
+ """
+ if not self._isSupported(config):
+ return []
+ else:
+ actions = (
+ self._actions(config) if callable(self._actions) else self._actions
+ )
+ return [AddFeature(self._getName(config))] + actions
+
+ def pretty(self, config):
+ """
+ Returns the Feature's name.
+ """
+ return self._getName(config)
- self._parse = lambda x: _parse_parameter(x, type)
- self._help = help
- self._actions = actions
- self._default = default
- def _getValue(self, config, litParams):
- """
- Return the value of the parameter given the configuration objects.
+def _str_to_bool(s):
"""
- param = getattr(config, self.name, None)
- param = litParams.get(self.name, param)
- if param is None and self._default is None:
- raise ValueError("Parameter {} doesn't have a default value, but it was not specified in the Lit parameters or in the Lit config".format(self.name))
- getDefault = lambda: self._default(config) if callable(self._default) else self._default
+ Convert a string value to a boolean.
- if param is not None:
- (pretty, value) = (param, self._parse(param))
+ True values are "y", "yes", "t", "true", "on" and "1", regardless of capitalization.
+ False values are "n", "no", "f", "false", "off" and "0", regardless of capitalization.
+ """
+ trueVals = ["y", "yes", "t", "true", "on", "1"]
+ falseVals = ["n", "no", "f", "false", "off", "0"]
+ lower = s.lower()
+ if lower in trueVals:
+ return True
+ elif lower in falseVals:
+ return False
else:
- value = getDefault()
- pretty = '{} (default)'.format(value)
+ raise ValueError("Got string '{}', which isn't a valid boolean".format(s))
- if self._choices and value not in self._choices:
- raise ValueError("Got value '{}' for parameter '{}', which is not in the provided set of possible choices: {}".format(value, self.name, self._choices))
- return (pretty, value)
- @property
- def name(self):
- """
- Return the name of the parameter.
+def _parse_parameter(s, type):
+ if type is bool and isinstance(s, str):
+ return _str_to_bool(s)
+ elif type is list and isinstance(s, str):
+ return [x.strip() for x in s.split(",") if x.strip()]
+ return type(s)
- This is the name that can be used to set the parameter on the command-line
- when running Lit.
- """
- return self._name
- def getActions(self, config, litParams):
+class Parameter(object):
"""
- Return the list of actions associated to this value of the parameter.
+ Represents a parameter of a Lit test suite.
+
+ Parameters are used to customize the behavior of test suites in a user
+ controllable way. There are two ways of setting the value of a Parameter.
+ The first one is to pass `--param <KEY>=<VALUE>` when running Lit (or
+ equivalently to set `litConfig.params[KEY] = VALUE` somewhere in the
+ Lit configuration files. This method will set the parameter globally for
+ all test suites being run.
+
+ The second method is to set `config.KEY = VALUE` somewhere in the Lit
+ configuration files, which sets the parameter only for the test suite(s)
+ that use that `config` object.
+
+ Parameters can have multiple possible values, and they can have a default
+ value when left unspecified. They can also have any number of ConfigActions
+ associated to them, in which case the actions will be performed on the
+ TestingConfig if the parameter is enabled. Depending on the actions
+ associated to a Parameter, it may be an error to enable the Parameter
+ if some actions are not supported in the given configuration. For example,
+ trying to set the compilation standard to C++23 when `-std=c++23` is not
+ supported by the compiler would be an error.
"""
- (_, parameterValue) = self._getValue(config, litParams)
- return self._actions(parameterValue)
- def pretty(self, config, litParams):
- """
- Return a pretty representation of the parameter's name and value.
- """
- (prettyParameterValue, _) = self._getValue(config, litParams)
- return "{}={}".format(self.name, prettyParameterValue)
+ def __init__(self, name, type, help, actions, choices=None, default=None):
+ """
+ Create a Lit parameter to customize the behavior of a test suite.
+
+ - name
+ The name of the parameter that can be used to set it on the command-line.
+ On the command-line, the parameter can be set using `--param <name>=<value>`
+ when running Lit. This must be non-empty.
+
+ - choices
+ An optional non-empty set of possible values for this parameter. If provided,
+ this must be anything that can be iterated. It is an error if the parameter
+ is given a value that is not in that set, whether explicitly or through a
+ default value.
+
+ - type
+ A callable that can be used to parse the value of the parameter given
+ on the command-line. As a special case, using the type `bool` also
+ allows parsing strings with boolean-like contents, and the type `list`
+ will parse a string delimited by commas into a list of the substrings.
+
+ - help
+ A string explaining the parameter, for documentation purposes.
+ TODO: We should be able to surface those from the Lit command-line.
+
+ - actions
+ A callable that gets passed the parsed value of the parameter (either
+ the one passed on the command-line or the default one), and that returns
+ a list of ConfigAction to perform given the value of the parameter.
+ All the ConfigAction must be supported in the given configuration.
+
+ - default
+ An optional default value to use for the parameter when no value is
+ provided on the command-line. If the default value is a callable, it
+ is called with the TestingConfig and should return the default value
+ for the parameter. Whether the default value is computed or specified
+ directly, it must be in the 'choices' provided for that Parameter.
+ """
+ self._name = name
+ if len(self._name) == 0:
+ raise ValueError("Parameter name must not be the empty string")
+
+ if choices is not None:
+ self._choices = list(choices) # should be finite
+ if len(self._choices) == 0:
+ raise ValueError(
+ "Parameter '{}' must be given at least one possible value".format(
+ self._name
+ )
+ )
+ else:
+ self._choices = None
+
+ self._parse = lambda x: _parse_parameter(x, type)
+ self._help = help
+ self._actions = actions
+ self._default = default
+
+ def _getValue(self, config, litParams):
+ """
+ Return the value of the parameter given the configuration objects.
+ """
+ param = getattr(config, self.name, None)
+ param = litParams.get(self.name, param)
+ if param is None and self._default is None:
+ raise ValueError(
+ "Parameter {} doesn't have a default value, but it was not specified in the Lit parameters or in the Lit config".format(
+ self.name
+ )
+ )
+ getDefault = (
+ lambda: self._default(config) if callable(self._default) else self._default
+ )
+
+ if param is not None:
+ (pretty, value) = (param, self._parse(param))
+ else:
+ value = getDefault()
+ pretty = "{} (default)".format(value)
+
+ if self._choices and value not in self._choices:
+ raise ValueError(
+ "Got value '{}' for parameter '{}', which is not in the provided set of possible choices: {}".format(
+ value, self.name, self._choices
+ )
+ )
+ return (pretty, value)
+
+ @property
+ def name(self):
+ """
+ Return the name of the parameter.
+
+ This is the name that can be used to set the parameter on the command-line
+ when running Lit.
+ """
+ return self._name
+
+ def getActions(self, config, litParams):
+ """
+ Return the list of actions associated to this value of the parameter.
+ """
+ (_, parameterValue) = self._getValue(config, litParams)
+ return self._actions(parameterValue)
+
+ def pretty(self, config, litParams):
+ """
+ Return a pretty representation of the parameter's name and value.
+ """
+ (prettyParameterValue, _) = self._getValue(config, litParams)
+ return "{}={}".format(self.name, prettyParameterValue)
diff --git a/libcxx/utils/libcxx/test/features.py b/libcxx/utils/libcxx/test/features.py
index a55d242..b4478b5 100644
--- a/libcxx/utils/libcxx/test/features.py
+++ b/libcxx/utils/libcxx/test/features.py
@@ -1,10 +1,10 @@
-#===----------------------------------------------------------------------===##
+# ===----------------------------------------------------------------------===##
#
# 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
#
-#===----------------------------------------------------------------------===##
+# ===----------------------------------------------------------------------===##
from libcxx.test.dsl import *
from lit.BooleanExpression import BooleanExpression
@@ -13,107 +13,176 @@ import shutil
import subprocess
import sys
-_isClang = lambda cfg: '__clang__' in compilerMacros(cfg) and '__apple_build_version__' not in compilerMacros(cfg)
-_isAppleClang = lambda cfg: '__apple_build_version__' in compilerMacros(cfg)
-_isGCC = lambda cfg: '__GNUC__' in compilerMacros(cfg) and '__clang__' not in compilerMacros(cfg)
-_isMSVC = lambda cfg: '_MSC_VER' in compilerMacros(cfg)
-_msvcVersion = lambda cfg: (int(compilerMacros(cfg)['_MSC_VER']) // 100, int(compilerMacros(cfg)['_MSC_VER']) % 100)
+_isClang = lambda cfg: "__clang__" in compilerMacros(
+ cfg
+) and "__apple_build_version__" not in compilerMacros(cfg)
+_isAppleClang = lambda cfg: "__apple_build_version__" in compilerMacros(cfg)
+_isGCC = lambda cfg: "__GNUC__" in compilerMacros(
+ cfg
+) and "__clang__" not in compilerMacros(cfg)
+_isMSVC = lambda cfg: "_MSC_VER" in compilerMacros(cfg)
+_msvcVersion = lambda cfg: (
+ int(compilerMacros(cfg)["_MSC_VER"]) // 100,
+ int(compilerMacros(cfg)["_MSC_VER"]) % 100,
+)
-def _getSuitableClangTidy(cfg):
- try:
- # If we didn't build the libcxx-tidy plugin via CMake, we can't run the clang-tidy tests.
- if runScriptExitCode(cfg, ['stat %{test-tools}/clang_tidy_checks/libcxx-tidy.plugin']) != 0:
- return None
-
- # TODO This should be the last stable release.
- # LLVM RELEASE bump to latest stable version
- if runScriptExitCode(cfg, ['clang-tidy-16 --version']) == 0:
- return 'clang-tidy-16'
- # LLVM RELEASE bump version
- if int(re.search('[0-9]+', commandOutput(cfg, ['clang-tidy --version'])).group()) >= 16:
- return 'clang-tidy'
+def _getSuitableClangTidy(cfg):
+ try:
+ # If we didn't build the libcxx-tidy plugin via CMake, we can't run the clang-tidy tests.
+ if (
+ runScriptExitCode(
+ cfg, ["stat %{test-tools}/clang_tidy_checks/libcxx-tidy.plugin"]
+ )
+ != 0
+ ):
+ return None
+
+ # TODO This should be the last stable release.
+ # LLVM RELEASE bump to latest stable version
+ if runScriptExitCode(cfg, ["clang-tidy-16 --version"]) == 0:
+ return "clang-tidy-16"
+
+ # LLVM RELEASE bump version
+ if (
+ int(
+ re.search(
+ "[0-9]+", commandOutput(cfg, ["clang-tidy --version"])
+ ).group()
+ )
+ >= 16
+ ):
+ return "clang-tidy"
+
+ except ConfigurationRuntimeError:
+ return None
- except ConfigurationRuntimeError:
- return None
DEFAULT_FEATURES = [
- Feature(name='thread-safety',
- when=lambda cfg: hasCompileFlag(cfg, '-Werror=thread-safety'),
- actions=[AddCompileFlag('-Werror=thread-safety')]),
-
- Feature(name='diagnose-if-support',
- when=lambda cfg: hasCompileFlag(cfg, '-Wuser-defined-warnings'),
- actions=[AddCompileFlag('-Wuser-defined-warnings')]),
-
- # Tests to validate whether the compiler has a way to set the maximum number
- # of steps during constant evaluation. Since the flag differs per compiler
- # store the "valid" flag as a feature. This allows passing the proper compile
- # flag to the compiler:
- # // ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=12345678
- # // ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-ops-limit): -fconstexpr-ops-limit=12345678
- Feature(name='has-fconstexpr-steps',
- when=lambda cfg: hasCompileFlag(cfg, '-fconstexpr-steps=1')),
-
- Feature(name='has-fconstexpr-ops-limit',
- when=lambda cfg: hasCompileFlag(cfg, '-fconstexpr-ops-limit=1')),
-
- Feature(name='has-fblocks', when=lambda cfg: hasCompileFlag(cfg, '-fblocks')),
- Feature(name='-fsized-deallocation', when=lambda cfg: hasCompileFlag(cfg, '-fsized-deallocation')),
- Feature(name='-faligned-allocation', when=lambda cfg: hasCompileFlag(cfg, '-faligned-allocation')),
- Feature(name='fdelayed-template-parsing', when=lambda cfg: hasCompileFlag(cfg, '-fdelayed-template-parsing')),
- Feature(name='libcpp-no-coroutines', when=lambda cfg: featureTestMacros(cfg).get('__cpp_impl_coroutine', 0) < 201902),
- Feature(name='has-fobjc-arc', when=lambda cfg: hasCompileFlag(cfg, '-xobjective-c++ -fobjc-arc') and
- sys.platform.lower().strip() == 'darwin'), # TODO: this doesn't handle cross-compiling to Apple platforms.
- Feature(name='objective-c++', when=lambda cfg: hasCompileFlag(cfg, '-xobjective-c++ -fobjc-arc')),
- Feature(name='verify-support', when=lambda cfg: hasCompileFlag(cfg, '-Xclang -verify-ignore-unexpected')),
-
- Feature(name='non-lockfree-atomics',
- when=lambda cfg: sourceBuilds(cfg, """
+ Feature(
+ name="thread-safety",
+ when=lambda cfg: hasCompileFlag(cfg, "-Werror=thread-safety"),
+ actions=[AddCompileFlag("-Werror=thread-safety")],
+ ),
+ Feature(
+ name="diagnose-if-support",
+ when=lambda cfg: hasCompileFlag(cfg, "-Wuser-defined-warnings"),
+ actions=[AddCompileFlag("-Wuser-defined-warnings")],
+ ),
+ # Tests to validate whether the compiler has a way to set the maximum number
+ # of steps during constant evaluation. Since the flag differs per compiler
+ # store the "valid" flag as a feature. This allows passing the proper compile
+ # flag to the compiler:
+ # // ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=12345678
+ # // ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-ops-limit): -fconstexpr-ops-limit=12345678
+ Feature(
+ name="has-fconstexpr-steps",
+ when=lambda cfg: hasCompileFlag(cfg, "-fconstexpr-steps=1"),
+ ),
+ Feature(
+ name="has-fconstexpr-ops-limit",
+ when=lambda cfg: hasCompileFlag(cfg, "-fconstexpr-ops-limit=1"),
+ ),
+ Feature(name="has-fblocks", when=lambda cfg: hasCompileFlag(cfg, "-fblocks")),
+ Feature(
+ name="-fsized-deallocation",
+ when=lambda cfg: hasCompileFlag(cfg, "-fsized-deallocation"),
+ ),
+ Feature(
+ name="-faligned-allocation",
+ when=lambda cfg: hasCompileFlag(cfg, "-faligned-allocation"),
+ ),
+ Feature(
+ name="fdelayed-template-parsing",
+ when=lambda cfg: hasCompileFlag(cfg, "-fdelayed-template-parsing"),
+ ),
+ Feature(
+ name="libcpp-no-coroutines",
+ when=lambda cfg: featureTestMacros(cfg).get("__cpp_impl_coroutine", 0) < 201902,
+ ),
+ Feature(
+ name="has-fobjc-arc",
+ when=lambda cfg: hasCompileFlag(cfg, "-xobjective-c++ -fobjc-arc")
+ and sys.platform.lower().strip() == "darwin",
+ ), # TODO: this doesn't handle cross-compiling to Apple platforms.
+ Feature(
+ name="objective-c++",
+ when=lambda cfg: hasCompileFlag(cfg, "-xobjective-c++ -fobjc-arc"),
+ ),
+ Feature(
+ name="verify-support",
+ when=lambda cfg: hasCompileFlag(cfg, "-Xclang -verify-ignore-unexpected"),
+ ),
+ Feature(
+ name="non-lockfree-atomics",
+ when=lambda cfg: sourceBuilds(
+ cfg,
+ """
#include <atomic>
struct Large { int storage[100]; };
std::atomic<Large> x;
int main(int, char**) { (void)x.load(); return 0; }
- """)),
- # TODO: Remove this feature once compiler-rt includes __atomic_is_lockfree()
- # on all supported platforms.
- Feature(name='is-lockfree-runtime-function',
- when=lambda cfg: sourceBuilds(cfg, """
+ """,
+ ),
+ ),
+ # TODO: Remove this feature once compiler-rt includes __atomic_is_lockfree()
+ # on all supported platforms.
+ Feature(
+ name="is-lockfree-runtime-function",
+ when=lambda cfg: sourceBuilds(
+ cfg,
+ """
#include <atomic>
struct Large { int storage[100]; };
std::atomic<Large> x;
int main(int, char**) { return x.is_lock_free(); }
- """)),
-
- # Some tests rely on creating shared libraries which link in the C++ Standard Library. In some
- # cases, this doesn't work (e.g. if the library was built as a static archive and wasn't compiled
- # as position independent). This feature informs the test suite of whether it's possible to create
- # a shared library in a shell test by using the '-shared' compiler flag.
- #
- # Note: To implement this check properly, we need to make sure that we use something inside the
- # compiled library, not only in the headers. It should be safe to assume that all implementations
- # define `operator new` in the compiled library.
- Feature(name='cant-build-shared-library',
- when=lambda cfg: not sourceBuilds(cfg, """
+ """,
+ ),
+ ),
+ # Some tests rely on creating shared libraries which link in the C++ Standard Library. In some
+ # cases, this doesn't work (e.g. if the library was built as a static archive and wasn't compiled
+ # as position independent). This feature informs the test suite of whether it's possible to create
+ # a shared library in a shell test by using the '-shared' compiler flag.
+ #
+ # Note: To implement this check properly, we need to make sure that we use something inside the
+ # compiled library, not only in the headers. It should be safe to assume that all implementations
+ # define `operator new` in the compiled library.
+ Feature(
+ name="cant-build-shared-library",
+ when=lambda cfg: not sourceBuilds(
+ cfg,
+ """
void f() { new int(3); }
- """, ['-shared'])),
-
- # Check for a Windows UCRT bug (fixed in UCRT/Windows 10.0.20348.0):
- # https://developercommunity.visualstudio.com/t/utf-8-locales-break-ctype-functions-for-wchar-type/1653678
- Feature(name='win32-broken-utf8-wchar-ctype',
- when=lambda cfg: not '_LIBCPP_HAS_NO_LOCALIZATION' in compilerMacros(cfg) and '_WIN32' in compilerMacros(cfg) and not programSucceeds(cfg, """
+ """,
+ ["-shared"],
+ ),
+ ),
+ # Check for a Windows UCRT bug (fixed in UCRT/Windows 10.0.20348.0):
+ # https://developercommunity.visualstudio.com/t/utf-8-locales-break-ctype-functions-for-wchar-type/1653678
+ Feature(
+ name="win32-broken-utf8-wchar-ctype",
+ when=lambda cfg: not "_LIBCPP_HAS_NO_LOCALIZATION" in compilerMacros(cfg)
+ and "_WIN32" in compilerMacros(cfg)
+ and not programSucceeds(
+ cfg,
+ """
#include <locale.h>
#include <wctype.h>
int main(int, char**) {
setlocale(LC_ALL, "en_US.UTF-8");
return towlower(L'\\xDA') != L'\\xFA';
}
- """)),
-
- # Check for a Windows UCRT bug (fixed in UCRT/Windows 10.0.19041.0).
- # https://developercommunity.visualstudio.com/t/printf-formatting-with-g-outputs-too/1660837
- Feature(name='win32-broken-printf-g-precision',
- when=lambda cfg: '_WIN32' in compilerMacros(cfg) and not programSucceeds(cfg, """
+ """,
+ ),
+ ),
+ # Check for a Windows UCRT bug (fixed in UCRT/Windows 10.0.19041.0).
+ # https://developercommunity.visualstudio.com/t/printf-formatting-with-g-outputs-too/1660837
+ Feature(
+ name="win32-broken-printf-g-precision",
+ when=lambda cfg: "_WIN32" in compilerMacros(cfg)
+ and not programSucceeds(
+ cfg,
+ """
#include <stdio.h>
#include <string.h>
int main(int, char**) {
@@ -121,70 +190,126 @@ DEFAULT_FEATURES = [
snprintf(buf, sizeof(buf), "%#.*g", 0, 0.0);
return strcmp(buf, "0.");
}
- """)),
-
- # Check for Glibc < 2.27, where the ru_RU.UTF-8 locale had
- # mon_decimal_point == ".", which our tests don't handle.
- Feature(name='glibc-old-ru_RU-decimal-point',
- when=lambda cfg: not '_LIBCPP_HAS_NO_LOCALIZATION' in compilerMacros(cfg) and not programSucceeds(cfg, """
+ """,
+ ),
+ ),
+ # Check for Glibc < 2.27, where the ru_RU.UTF-8 locale had
+ # mon_decimal_point == ".", which our tests don't handle.
+ Feature(
+ name="glibc-old-ru_RU-decimal-point",
+ when=lambda cfg: not "_LIBCPP_HAS_NO_LOCALIZATION" in compilerMacros(cfg)
+ and not programSucceeds(
+ cfg,
+ """
#include <locale.h>
#include <string.h>
int main(int, char**) {
setlocale(LC_ALL, "ru_RU.UTF-8");
return strcmp(localeconv()->mon_decimal_point, ",");
}
- """)),
-
- Feature(name='has-unix-headers',
- when=lambda cfg: sourceBuilds(cfg, """
+ """,
+ ),
+ ),
+ Feature(
+ name="has-unix-headers",
+ when=lambda cfg: sourceBuilds(
+ cfg,
+ """
#include <unistd.h>
#include <sys/wait.h>
int main(int, char**) {
return 0;
}
- """)),
-
- # Whether Bash can run on the executor.
- # This is not always the case, for example when running on embedded systems.
- #
- # For the corner case of bash existing, but it being missing in the path
- # set in %{exec} as "--env PATH=one-single-dir", the executor does find
- # and executes bash, but bash then can't find any other common shell
- # utilities. Test executing "bash -c 'bash --version'" to see if bash
- # manages to find binaries to execute.
- Feature(name='executor-has-no-bash',
- when=lambda cfg: runScriptExitCode(cfg, ['%{exec} bash -c \'bash --version\'']) != 0),
- Feature(name='has-clang-tidy',
- when=lambda cfg: _getSuitableClangTidy(cfg) is not None,
- actions=[AddSubstitution('%{clang-tidy}', lambda cfg: _getSuitableClangTidy(cfg))]),
-
- Feature(name='apple-clang', when=_isAppleClang),
- Feature(name=lambda cfg: 'apple-clang-{__clang_major__}'.format(**compilerMacros(cfg)), when=_isAppleClang),
- Feature(name=lambda cfg: 'apple-clang-{__clang_major__}.{__clang_minor__}'.format(**compilerMacros(cfg)), when=_isAppleClang),
- Feature(name=lambda cfg: 'apple-clang-{__clang_major__}.{__clang_minor__}.{__clang_patchlevel__}'.format(**compilerMacros(cfg)), when=_isAppleClang),
-
- Feature(name='clang', when=_isClang),
- Feature(name=lambda cfg: 'clang-{__clang_major__}'.format(**compilerMacros(cfg)), when=_isClang),
- Feature(name=lambda cfg: 'clang-{__clang_major__}.{__clang_minor__}'.format(**compilerMacros(cfg)), when=_isClang),
- Feature(name=lambda cfg: 'clang-{__clang_major__}.{__clang_minor__}.{__clang_patchlevel__}'.format(**compilerMacros(cfg)), when=_isClang),
-
- # Note: Due to a GCC bug (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104760), we must disable deprecation warnings
- # on GCC or spurious diagnostics are issued.
- #
- # TODO:
- # - Enable -Wplacement-new with GCC.
- # - Enable -Wclass-memaccess with GCC.
- Feature(name='gcc', when=_isGCC,
- actions=[AddCompileFlag('-D_LIBCPP_DISABLE_DEPRECATION_WARNINGS'),
- AddCompileFlag('-Wno-placement-new'),
- AddCompileFlag('-Wno-class-memaccess')]),
- Feature(name=lambda cfg: 'gcc-{__GNUC__}'.format(**compilerMacros(cfg)), when=_isGCC),
- Feature(name=lambda cfg: 'gcc-{__GNUC__}.{__GNUC_MINOR__}'.format(**compilerMacros(cfg)), when=_isGCC),
- Feature(name=lambda cfg: 'gcc-{__GNUC__}.{__GNUC_MINOR__}.{__GNUC_PATCHLEVEL__}'.format(**compilerMacros(cfg)), when=_isGCC),
-
- Feature(name='msvc', when=_isMSVC),
- Feature(name=lambda cfg: 'msvc-{}'.format(*_msvcVersion(cfg)), when=_isMSVC),
- Feature(name=lambda cfg: 'msvc-{}.{}'.format(*_msvcVersion(cfg)), when=_isMSVC),
+ """,
+ ),
+ ),
+ # Whether Bash can run on the executor.
+ # This is not always the case, for example when running on embedded systems.
+ #
+ # For the corner case of bash existing, but it being missing in the path
+ # set in %{exec} as "--env PATH=one-single-dir", the executor does find
+ # and executes bash, but bash then can't find any other common shell
+ # utilities. Test executing "bash -c 'bash --version'" to see if bash
+ # manages to find binaries to execute.
+ Feature(
+ name="executor-has-no-bash",
+ when=lambda cfg: runScriptExitCode(cfg, ["%{exec} bash -c 'bash --version'"])
+ != 0,
+ ),
+ Feature(
+ name="has-clang-tidy",
+ when=lambda cfg: _getSuitableClangTidy(cfg) is not None,
+ actions=[
+ AddSubstitution("%{clang-tidy}", lambda cfg: _getSuitableClangTidy(cfg))
+ ],
+ ),
+ Feature(name="apple-clang", when=_isAppleClang),
+ Feature(
+ name=lambda cfg: "apple-clang-{__clang_major__}".format(**compilerMacros(cfg)),
+ when=_isAppleClang,
+ ),
+ Feature(
+ name=lambda cfg: "apple-clang-{__clang_major__}.{__clang_minor__}".format(
+ **compilerMacros(cfg)
+ ),
+ when=_isAppleClang,
+ ),
+ Feature(
+ name=lambda cfg: "apple-clang-{__clang_major__}.{__clang_minor__}.{__clang_patchlevel__}".format(
+ **compilerMacros(cfg)
+ ),
+ when=_isAppleClang,
+ ),
+ Feature(name="clang", when=_isClang),
+ Feature(
+ name=lambda cfg: "clang-{__clang_major__}".format(**compilerMacros(cfg)),
+ when=_isClang,
+ ),
+ Feature(
+ name=lambda cfg: "clang-{__clang_major__}.{__clang_minor__}".format(
+ **compilerMacros(cfg)
+ ),
+ when=_isClang,
+ ),
+ Feature(
+ name=lambda cfg: "clang-{__clang_major__}.{__clang_minor__}.{__clang_patchlevel__}".format(
+ **compilerMacros(cfg)
+ ),
+ when=_isClang,
+ ),
+ # Note: Due to a GCC bug (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104760), we must disable deprecation warnings
+ # on GCC or spurious diagnostics are issued.
+ #
+ # TODO:
+ # - Enable -Wplacement-new with GCC.
+ # - Enable -Wclass-memaccess with GCC.
+ Feature(
+ name="gcc",
+ when=_isGCC,
+ actions=[
+ AddCompileFlag("-D_LIBCPP_DISABLE_DEPRECATION_WARNINGS"),
+ AddCompileFlag("-Wno-placement-new"),
+ AddCompileFlag("-Wno-class-memaccess"),
+ ],
+ ),
+ Feature(
+ name=lambda cfg: "gcc-{__GNUC__}".format(**compilerMacros(cfg)), when=_isGCC
+ ),
+ Feature(
+ name=lambda cfg: "gcc-{__GNUC__}.{__GNUC_MINOR__}".format(
+ **compilerMacros(cfg)
+ ),
+ when=_isGCC,
+ ),
+ Feature(
+ name=lambda cfg: "gcc-{__GNUC__}.{__GNUC_MINOR__}.{__GNUC_PATCHLEVEL__}".format(
+ **compilerMacros(cfg)
+ ),
+ when=_isGCC,
+ ),
+ Feature(name="msvc", when=_isMSVC),
+ Feature(name=lambda cfg: "msvc-{}".format(*_msvcVersion(cfg)), when=_isMSVC),
+ Feature(name=lambda cfg: "msvc-{}.{}".format(*_msvcVersion(cfg)), when=_isMSVC),
]
# Deduce and add the test features that that are implied by the #defines in
@@ -198,54 +323,70 @@ DEFAULT_FEATURES = [
# Note that features that are more strongly tied to libc++ are named libcpp-foo,
# while features that are more general in nature are not prefixed with 'libcpp-'.
macros = {
- '_LIBCPP_HAS_NO_MONOTONIC_CLOCK': 'no-monotonic-clock',
- '_LIBCPP_HAS_NO_THREADS': 'no-threads',
- '_LIBCPP_HAS_THREAD_API_EXTERNAL': 'libcpp-has-thread-api-external',
- '_LIBCPP_HAS_THREAD_API_PTHREAD': 'libcpp-has-thread-api-pthread',
- '_LIBCPP_NO_VCRUNTIME': 'libcpp-no-vcruntime',
- '_LIBCPP_ABI_VERSION': 'libcpp-abi-version',
- '_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY': 'no-filesystem',
- '_LIBCPP_HAS_NO_RANDOM_DEVICE': 'no-random-device',
- '_LIBCPP_HAS_NO_LOCALIZATION': 'no-localization',
- '_LIBCPP_HAS_NO_FSTREAM': 'no-fstream',
- '_LIBCPP_HAS_NO_WIDE_CHARACTERS': 'no-wide-characters',
- '_LIBCPP_HAS_NO_UNICODE': 'libcpp-has-no-unicode',
- '_LIBCPP_ENABLE_DEBUG_MODE': 'libcpp-has-debug-mode',
+ "_LIBCPP_HAS_NO_MONOTONIC_CLOCK": "no-monotonic-clock",
+ "_LIBCPP_HAS_NO_THREADS": "no-threads",
+ "_LIBCPP_HAS_THREAD_API_EXTERNAL": "libcpp-has-thread-api-external",
+ "_LIBCPP_HAS_THREAD_API_PTHREAD": "libcpp-has-thread-api-pthread",
+ "_LIBCPP_NO_VCRUNTIME": "libcpp-no-vcruntime",
+ "_LIBCPP_ABI_VERSION": "libcpp-abi-version",
+ "_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY": "no-filesystem",
+ "_LIBCPP_HAS_NO_RANDOM_DEVICE": "no-random-device",
+ "_LIBCPP_HAS_NO_LOCALIZATION": "no-localization",
+ "_LIBCPP_HAS_NO_FSTREAM": "no-fstream",
+ "_LIBCPP_HAS_NO_WIDE_CHARACTERS": "no-wide-characters",
+ "_LIBCPP_HAS_NO_UNICODE": "libcpp-has-no-unicode",
+ "_LIBCPP_ENABLE_DEBUG_MODE": "libcpp-has-debug-mode",
}
for macro, feature in macros.items():
- DEFAULT_FEATURES.append(
- Feature(name=lambda cfg, m=macro, f=feature: f + ('={}'.format(compilerMacros(cfg)[m]) if compilerMacros(cfg)[m] else ''),
- when=lambda cfg, m=macro: m in compilerMacros(cfg))
- )
+ DEFAULT_FEATURES.append(
+ Feature(
+ name=lambda cfg, m=macro, f=feature: f
+ + ("={}".format(compilerMacros(cfg)[m]) if compilerMacros(cfg)[m] else ""),
+ when=lambda cfg, m=macro: m in compilerMacros(cfg),
+ )
+ )
# Mapping from canonical locale names (used in the tests) to possible locale
# names on various systems. Each locale is considered supported if any of the
# alternative names is supported.
locales = {
- 'en_US.UTF-8': ['en_US.UTF-8', 'en_US.utf8', 'English_United States.1252'],
- 'fr_FR.UTF-8': ['fr_FR.UTF-8', 'fr_FR.utf8', 'French_France.1252'],
- 'ja_JP.UTF-8': ['ja_JP.UTF-8', 'ja_JP.utf8', 'Japanese_Japan.923'],
- 'ru_RU.UTF-8': ['ru_RU.UTF-8', 'ru_RU.utf8', 'Russian_Russia.1251'],
- 'zh_CN.UTF-8': ['zh_CN.UTF-8', 'zh_CN.utf8', 'Chinese_China.936'],
- 'fr_CA.ISO8859-1': ['fr_CA.ISO8859-1', 'French_Canada.1252'],
- 'cs_CZ.ISO8859-2': ['cs_CZ.ISO8859-2', 'Czech_Czech Republic.1250']
+ "en_US.UTF-8": ["en_US.UTF-8", "en_US.utf8", "English_United States.1252"],
+ "fr_FR.UTF-8": ["fr_FR.UTF-8", "fr_FR.utf8", "French_France.1252"],
+ "ja_JP.UTF-8": ["ja_JP.UTF-8", "ja_JP.utf8", "Japanese_Japan.923"],
+ "ru_RU.UTF-8": ["ru_RU.UTF-8", "ru_RU.utf8", "Russian_Russia.1251"],
+ "zh_CN.UTF-8": ["zh_CN.UTF-8", "zh_CN.utf8", "Chinese_China.936"],
+ "fr_CA.ISO8859-1": ["fr_CA.ISO8859-1", "French_Canada.1252"],
+ "cs_CZ.ISO8859-2": ["cs_CZ.ISO8859-2", "Czech_Czech Republic.1250"],
}
for locale, alts in locales.items():
- # Note: Using alts directly in the lambda body here will bind it to the value at the
- # end of the loop. Assigning it to a default argument works around this issue.
- DEFAULT_FEATURES.append(Feature(name='locale.{}'.format(locale),
- when=lambda cfg, alts=alts: hasAnyLocale(cfg, alts)))
+ # Note: Using alts directly in the lambda body here will bind it to the value at the
+ # end of the loop. Assigning it to a default argument works around this issue.
+ DEFAULT_FEATURES.append(
+ Feature(
+ name="locale.{}".format(locale),
+ when=lambda cfg, alts=alts: hasAnyLocale(cfg, alts),
+ )
+ )
# Add features representing the target platform name: darwin, linux, windows, etc...
DEFAULT_FEATURES += [
- Feature(name='darwin', when=lambda cfg: '__APPLE__' in compilerMacros(cfg)),
- Feature(name='windows', when=lambda cfg: '_WIN32' in compilerMacros(cfg)),
- Feature(name='windows-dll', when=lambda cfg: '_WIN32' in compilerMacros(cfg) and sourceBuilds(cfg, """
+ Feature(name="darwin", when=lambda cfg: "__APPLE__" in compilerMacros(cfg)),
+ Feature(name="windows", when=lambda cfg: "_WIN32" in compilerMacros(cfg)),
+ Feature(
+ name="windows-dll",
+ when=lambda cfg: "_WIN32" in compilerMacros(cfg)
+ and sourceBuilds(
+ cfg,
+ """
#include <iostream>
int main(int, char**) { return 0; }
- """) and programSucceeds(cfg, """
+ """,
+ )
+ and programSucceeds(
+ cfg,
+ """
#include <iostream>
#include <windows.h>
#include <winnt.h>
@@ -272,57 +413,76 @@ DEFAULT_FEATURES += [
// loaded from a DLL.
return 0;
}
- """), actions=[AddCompileFlag('-DTEST_WINDOWS_DLL')]),
- Feature(name='linux', when=lambda cfg: '__linux__' in compilerMacros(cfg)),
- Feature(name='netbsd', when=lambda cfg: '__NetBSD__' in compilerMacros(cfg)),
- Feature(name='freebsd', when=lambda cfg: '__FreeBSD__' in compilerMacros(cfg)),
- Feature(name='LIBCXX-FREEBSD-FIXME', when=lambda cfg: '__FreeBSD__' in compilerMacros(cfg)),
+ """,
+ ),
+ actions=[AddCompileFlag("-DTEST_WINDOWS_DLL")],
+ ),
+ Feature(name="linux", when=lambda cfg: "__linux__" in compilerMacros(cfg)),
+ Feature(name="netbsd", when=lambda cfg: "__NetBSD__" in compilerMacros(cfg)),
+ Feature(name="freebsd", when=lambda cfg: "__FreeBSD__" in compilerMacros(cfg)),
+ Feature(
+ name="LIBCXX-FREEBSD-FIXME",
+ when=lambda cfg: "__FreeBSD__" in compilerMacros(cfg),
+ ),
]
# Add features representing the build host platform name.
# The build host could differ from the target platform for cross-compilation.
DEFAULT_FEATURES += [
- Feature(name='buildhost={}'.format(sys.platform.lower().strip())),
- # sys.platform can often be represented by a "sub-system", such as 'win32', 'cygwin', 'mingw', freebsd13 & etc.
- # We define a consolidated feature on a few platforms.
- Feature(name='buildhost=windows', when=lambda cfg: platform.system().lower().startswith('windows')),
- Feature(name='buildhost=freebsd', when=lambda cfg: platform.system().lower().startswith('freebsd')),
- Feature(name='buildhost=aix', when=lambda cfg: platform.system().lower().startswith('aix'))
+ Feature(name="buildhost={}".format(sys.platform.lower().strip())),
+ # sys.platform can often be represented by a "sub-system", such as 'win32', 'cygwin', 'mingw', freebsd13 & etc.
+ # We define a consolidated feature on a few platforms.
+ Feature(
+ name="buildhost=windows",
+ when=lambda cfg: platform.system().lower().startswith("windows"),
+ ),
+ Feature(
+ name="buildhost=freebsd",
+ when=lambda cfg: platform.system().lower().startswith("freebsd"),
+ ),
+ Feature(
+ name="buildhost=aix",
+ when=lambda cfg: platform.system().lower().startswith("aix"),
+ ),
]
# Detect whether GDB is on the system, has Python scripting and supports
# adding breakpoint commands. If so add a substitution to access it.
def check_gdb(cfg):
- gdb_path = shutil.which('gdb')
- if gdb_path is None:
- return False
-
- # Check that we can set breakpoint commands, which was added in 8.3.
- # Using the quit command here means that gdb itself exits, not just
- # the "python <...>" command.
- test_src = """\
+ gdb_path = shutil.which("gdb")
+ if gdb_path is None:
+ return False
+
+ # Check that we can set breakpoint commands, which was added in 8.3.
+ # Using the quit command here means that gdb itself exits, not just
+ # the "python <...>" command.
+ test_src = """\
try:
gdb.Breakpoint(\"main\").commands=\"foo\"
except AttributeError:
gdb.execute(\"quit 1\")
gdb.execute(\"quit\")"""
- try:
- stdout = subprocess.check_output(
- [gdb_path, "-ex", "python " + test_src, "--batch"],
- stderr=subprocess.DEVNULL, universal_newlines=True)
- except subprocess.CalledProcessError:
- # We can't set breakpoint commands
- return False
+ try:
+ stdout = subprocess.check_output(
+ [gdb_path, "-ex", "python " + test_src, "--batch"],
+ stderr=subprocess.DEVNULL,
+ universal_newlines=True,
+ )
+ except subprocess.CalledProcessError:
+ # We can't set breakpoint commands
+ return False
+
+ # Check we actually ran the Python
+ return not "Python scripting is not supported" in stdout
- # Check we actually ran the Python
- return not "Python scripting is not supported" in stdout
DEFAULT_FEATURES += [
- Feature(name='host-has-gdb-with-python',
- when=check_gdb,
- actions=[AddSubstitution('%{gdb}', lambda cfg: shutil.which('gdb'))]
- )
+ Feature(
+ name="host-has-gdb-with-python",
+ when=check_gdb,
+ actions=[AddSubstitution("%{gdb}", lambda cfg: shutil.which("gdb"))],
+ )
]
# Define features for back-deployment testing.
@@ -339,56 +499,105 @@ DEFAULT_FEATURES += [
# be achieved by creating a `.verify.cpp` test that checks for the right errors, and
# mark that test as requiring `stdlib=<vendor>-libc++ && target=<target>`.
DEFAULT_FEATURES += [
- # Tests that require std::to_chars(floating-point) in the built library
- Feature(name='availability-fp_to_chars-missing',
- when=lambda cfg: BooleanExpression.evaluate('stdlib=apple-libc++ && target={{.+}}-apple-macosx{{(10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0|12.0|13.0)(.0)?}}', cfg.available_features)),
-
- # Tests that require https://wg21.link/P0482 support in the built library
- Feature(name='availability-char8_t_support-missing',
- when=lambda cfg: BooleanExpression.evaluate('stdlib=apple-libc++ && target={{.+}}-apple-macosx{{(10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0)(.0)?}}', cfg.available_features)),
-
- # Tests that require __libcpp_verbose_abort support in the built library
- Feature(name='availability-verbose_abort-missing',
- when=lambda cfg: BooleanExpression.evaluate('stdlib=apple-libc++ && target={{.+}}-apple-macosx{{(10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0|12.0|13.0)(.0)?}}', cfg.available_features)),
-
- # Tests that require std::bad_variant_access in the built library
- Feature(name='availability-bad_variant_access-missing',
- when=lambda cfg: BooleanExpression.evaluate('stdlib=apple-libc++ && target={{.+}}-apple-macosx10.{{(9|10|11|12)(.0)?}}', cfg.available_features)),
-
- # Tests that require std::bad_optional_access in the built library
- Feature(name='availability-bad_optional_access-missing',
- when=lambda cfg: BooleanExpression.evaluate('stdlib=apple-libc++ && target={{.+}}-apple-macosx10.{{(9|10|11|12)(.0)?}}', cfg.available_features)),
-
- # Tests that require std::bad_any_cast in the built library
- Feature(name='availability-bad_any_cast-missing',
- when=lambda cfg: BooleanExpression.evaluate('stdlib=apple-libc++ && target={{.+}}-apple-macosx10.{{(9|10|11|12)(.0)?}}', cfg.available_features)),
-
- # Tests that require std::pmr support in the built library
- Feature(name='availability-pmr-missing',
- when=lambda cfg: BooleanExpression.evaluate('stdlib=apple-libc++ && target={{.+}}-apple-macosx{{(10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0)(.0)?}}', cfg.available_features)),
-
- # Tests that require std::filesystem support in the built library
- Feature(name='availability-filesystem-missing',
- when=lambda cfg: BooleanExpression.evaluate('stdlib=apple-libc++ && target={{.+}}-apple-macosx10.{{(9|10|11|12|13|14)(.0)?}}', cfg.available_features)),
-
- # Tests that require the C++20 synchronization library (P1135R6 implemented by https://llvm.org/D68480) in the built library
- Feature(name='availability-synchronization_library-missing',
- when=lambda cfg: BooleanExpression.evaluate('stdlib=apple-libc++ && target={{.+}}-apple-macosx10.{{(9|10|11|12|13|14|15)(.0)?}}', cfg.available_features)),
-
- # Tests that require support for std::shared_mutex and std::shared_timed_mutex in the built library
- Feature(name='availability-shared_mutex-missing',
- when=lambda cfg: BooleanExpression.evaluate('stdlib=apple-libc++ && target={{.+}}-apple-macosx10.{{(9|10|11)(.0)?}}', cfg.available_features)),
-
- # Tests that require support for aligned allocation in the built library. This is about `operator new(..., std::align_val_t, ...)` specifically,
- # not other forms of aligned allocation.
- Feature(name='availability-aligned_allocation-missing',
- when=lambda cfg: BooleanExpression.evaluate('stdlib=apple-libc++ && target={{.+}}-apple-macosx10.{{(9|10|11|12)(.0)?}}', cfg.available_features)),
-
- # Tests that require 64-bit architecture
- Feature(name='32-bit-pointer',
- when=lambda cfg: sourceBuilds(cfg, """
+ # Tests that require std::to_chars(floating-point) in the built library
+ Feature(
+ name="availability-fp_to_chars-missing",
+ when=lambda cfg: BooleanExpression.evaluate(
+ "stdlib=apple-libc++ && target={{.+}}-apple-macosx{{(10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0|12.0|13.0)(.0)?}}",
+ cfg.available_features,
+ ),
+ ),
+ # Tests that require https://wg21.link/P0482 support in the built library
+ Feature(
+ name="availability-char8_t_support-missing",
+ when=lambda cfg: BooleanExpression.evaluate(
+ "stdlib=apple-libc++ && target={{.+}}-apple-macosx{{(10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0)(.0)?}}",
+ cfg.available_features,
+ ),
+ ),
+ # Tests that require __libcpp_verbose_abort support in the built library
+ Feature(
+ name="availability-verbose_abort-missing",
+ when=lambda cfg: BooleanExpression.evaluate(
+ "stdlib=apple-libc++ && target={{.+}}-apple-macosx{{(10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0|12.0|13.0)(.0)?}}",
+ cfg.available_features,
+ ),
+ ),
+ # Tests that require std::bad_variant_access in the built library
+ Feature(
+ name="availability-bad_variant_access-missing",
+ when=lambda cfg: BooleanExpression.evaluate(
+ "stdlib=apple-libc++ && target={{.+}}-apple-macosx10.{{(9|10|11|12)(.0)?}}",
+ cfg.available_features,
+ ),
+ ),
+ # Tests that require std::bad_optional_access in the built library
+ Feature(
+ name="availability-bad_optional_access-missing",
+ when=lambda cfg: BooleanExpression.evaluate(
+ "stdlib=apple-libc++ && target={{.+}}-apple-macosx10.{{(9|10|11|12)(.0)?}}",
+ cfg.available_features,
+ ),
+ ),
+ # Tests that require std::bad_any_cast in the built library
+ Feature(
+ name="availability-bad_any_cast-missing",
+ when=lambda cfg: BooleanExpression.evaluate(
+ "stdlib=apple-libc++ && target={{.+}}-apple-macosx10.{{(9|10|11|12)(.0)?}}",
+ cfg.available_features,
+ ),
+ ),
+ # Tests that require std::pmr support in the built library
+ Feature(
+ name="availability-pmr-missing",
+ when=lambda cfg: BooleanExpression.evaluate(
+ "stdlib=apple-libc++ && target={{.+}}-apple-macosx{{(10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0)(.0)?}}",
+ cfg.available_features,
+ ),
+ ),
+ # Tests that require std::filesystem support in the built library
+ Feature(
+ name="availability-filesystem-missing",
+ when=lambda cfg: BooleanExpression.evaluate(
+ "stdlib=apple-libc++ && target={{.+}}-apple-macosx10.{{(9|10|11|12|13|14)(.0)?}}",
+ cfg.available_features,
+ ),
+ ),
+ # Tests that require the C++20 synchronization library (P1135R6 implemented by https://llvm.org/D68480) in the built library
+ Feature(
+ name="availability-synchronization_library-missing",
+ when=lambda cfg: BooleanExpression.evaluate(
+ "stdlib=apple-libc++ && target={{.+}}-apple-macosx10.{{(9|10|11|12|13|14|15)(.0)?}}",
+ cfg.available_features,
+ ),
+ ),
+ # Tests that require support for std::shared_mutex and std::shared_timed_mutex in the built library
+ Feature(
+ name="availability-shared_mutex-missing",
+ when=lambda cfg: BooleanExpression.evaluate(
+ "stdlib=apple-libc++ && target={{.+}}-apple-macosx10.{{(9|10|11)(.0)?}}",
+ cfg.available_features,
+ ),
+ ),
+ # Tests that require support for aligned allocation in the built library. This is about `operator new(..., std::align_val_t, ...)` specifically,
+ # not other forms of aligned allocation.
+ Feature(
+ name="availability-aligned_allocation-missing",
+ when=lambda cfg: BooleanExpression.evaluate(
+ "stdlib=apple-libc++ && target={{.+}}-apple-macosx10.{{(9|10|11|12)(.0)?}}",
+ cfg.available_features,
+ ),
+ ),
+ # Tests that require 64-bit architecture
+ Feature(
+ name="32-bit-pointer",
+ when=lambda cfg: sourceBuilds(
+ cfg,
+ """
int main(int, char**) {
static_assert(sizeof(void *) == 4);
}
- """)),
+ """,
+ ),
+ ),
]
diff --git a/libcxx/utils/libcxx/test/format.py b/libcxx/utils/libcxx/test/format.py
index 2543923..6827b1b7 100644
--- a/libcxx/utils/libcxx/test/format.py
+++ b/libcxx/utils/libcxx/test/format.py
@@ -1,10 +1,10 @@
-#===----------------------------------------------------------------------===##
+# ===----------------------------------------------------------------------===##
#
# 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
#
-#===----------------------------------------------------------------------===##
+# ===----------------------------------------------------------------------===##
import lit
import lit.formats
@@ -13,6 +13,7 @@ import pipes
import re
import shutil
+
def _getTempPaths(test):
"""
Return the values to use for the %T and %t substitutions, respectively.
@@ -22,40 +23,45 @@ def _getTempPaths(test):
"""
tmpDir, _ = lit.TestRunner.getTempPaths(test)
_, testName = os.path.split(test.getExecPath())
- tmpDir = os.path.join(tmpDir, testName + '.dir')
- tmpBase = os.path.join(tmpDir, 't')
+ tmpDir = os.path.join(tmpDir, testName + ".dir")
+ tmpBase = os.path.join(tmpDir, "t")
return tmpDir, tmpBase
+
def _checkBaseSubstitutions(substitutions):
substitutions = [s for (s, _) in substitutions]
- for s in ['%{cxx}', '%{compile_flags}', '%{link_flags}', '%{flags}', '%{exec}']:
+ for s in ["%{cxx}", "%{compile_flags}", "%{link_flags}", "%{flags}", "%{exec}"]:
assert s in substitutions, "Required substitution {} was not provided".format(s)
+
def _executeScriptInternal(test, litConfig, commands):
- """
- Returns (stdout, stderr, exitCode, timeoutInfo, parsedCommands)
-
- TODO: This really should be easier to access from Lit itself
- """
- parsedCommands = parseScript(test, preamble=commands)
-
- _, tmpBase = _getTempPaths(test)
- execDir = os.path.dirname(test.getExecPath())
- res = lit.TestRunner.executeScriptInternal(test, litConfig, tmpBase, parsedCommands, execDir)
- if isinstance(res, lit.Test.Result): # Handle failure to parse the Lit test
- res = ('', res.output, 127, None)
- (out, err, exitCode, timeoutInfo) = res
-
- # TODO: As a temporary workaround until https://reviews.llvm.org/D81892 lands, manually
- # split any stderr output that is included in stdout. It shouldn't be there, but
- # the Lit internal shell conflates stderr and stdout.
- conflatedErrorOutput = re.search("(# command stderr:.+$)", out, flags=re.DOTALL)
- if conflatedErrorOutput:
- conflatedErrorOutput = conflatedErrorOutput.group(0)
- out = out[:-len(conflatedErrorOutput)]
- err += conflatedErrorOutput
-
- return (out, err, exitCode, timeoutInfo, parsedCommands)
+ """
+ Returns (stdout, stderr, exitCode, timeoutInfo, parsedCommands)
+
+ TODO: This really should be easier to access from Lit itself
+ """
+ parsedCommands = parseScript(test, preamble=commands)
+
+ _, tmpBase = _getTempPaths(test)
+ execDir = os.path.dirname(test.getExecPath())
+ res = lit.TestRunner.executeScriptInternal(
+ test, litConfig, tmpBase, parsedCommands, execDir
+ )
+ if isinstance(res, lit.Test.Result): # Handle failure to parse the Lit test
+ res = ("", res.output, 127, None)
+ (out, err, exitCode, timeoutInfo) = res
+
+ # TODO: As a temporary workaround until https://reviews.llvm.org/D81892 lands, manually
+ # split any stderr output that is included in stdout. It shouldn't be there, but
+ # the Lit internal shell conflates stderr and stdout.
+ conflatedErrorOutput = re.search("(# command stderr:.+$)", out, flags=re.DOTALL)
+ if conflatedErrorOutput:
+ conflatedErrorOutput = conflatedErrorOutput.group(0)
+ out = out[: -len(conflatedErrorOutput)]
+ err += conflatedErrorOutput
+
+ return (out, err, exitCode, timeoutInfo, parsedCommands)
+
def parseScript(test, preamble):
"""
@@ -78,32 +84,41 @@ def parseScript(test, preamble):
# Check base substitutions and add the %{build} and %{run} convenience substitutions
_checkBaseSubstitutions(substitutions)
- substitutions.append(('%{build}', '%{cxx} %s %{flags} %{compile_flags} %{link_flags} -o %t.exe'))
- substitutions.append(('%{run}', '%{exec} %t.exe'))
+ substitutions.append(
+ ("%{build}", "%{cxx} %s %{flags} %{compile_flags} %{link_flags} -o %t.exe")
+ )
+ substitutions.append(("%{run}", "%{exec} %t.exe"))
# Parse the test file, including custom directives
additionalCompileFlags = []
fileDependencies = []
parsers = [
- lit.TestRunner.IntegratedTestKeywordParser('FILE_DEPENDENCIES:',
- lit.TestRunner.ParserKind.LIST,
- initial_value=fileDependencies),
- lit.TestRunner.IntegratedTestKeywordParser('ADDITIONAL_COMPILE_FLAGS:',
- lit.TestRunner.ParserKind.LIST,
- initial_value=additionalCompileFlags)
+ lit.TestRunner.IntegratedTestKeywordParser(
+ "FILE_DEPENDENCIES:",
+ lit.TestRunner.ParserKind.LIST,
+ initial_value=fileDependencies,
+ ),
+ lit.TestRunner.IntegratedTestKeywordParser(
+ "ADDITIONAL_COMPILE_FLAGS:",
+ lit.TestRunner.ParserKind.LIST,
+ initial_value=additionalCompileFlags,
+ ),
]
# Add conditional parsers for ADDITIONAL_COMPILE_FLAGS. This should be replaced by first
# class support for conditional keywords in Lit, which would allow evaluating arbitrary
# Lit boolean expressions instead.
for feature in test.config.available_features:
- parser = lit.TestRunner.IntegratedTestKeywordParser('ADDITIONAL_COMPILE_FLAGS({}):'.format(feature),
- lit.TestRunner.ParserKind.LIST,
- initial_value=additionalCompileFlags)
+ parser = lit.TestRunner.IntegratedTestKeywordParser(
+ "ADDITIONAL_COMPILE_FLAGS({}):".format(feature),
+ lit.TestRunner.ParserKind.LIST,
+ initial_value=additionalCompileFlags,
+ )
parsers.append(parser)
- scriptInTest = lit.TestRunner.parseIntegratedTestScript(test, additional_parsers=parsers,
- require_script=not preamble)
+ scriptInTest = lit.TestRunner.parseIntegratedTestScript(
+ test, additional_parsers=parsers, require_script=not preamble
+ )
if isinstance(scriptInTest, lit.Test.Result):
return scriptInTest
@@ -113,17 +128,22 @@ def parseScript(test, preamble):
# that file to the execution directory. Execute the copy from %S to allow
# relative paths from the test directory.
for dep in fileDependencies:
- script += ['%dbg(SETUP) cd %S && cp {} %T'.format(dep)]
+ script += ["%dbg(SETUP) cd %S && cp {} %T".format(dep)]
script += preamble
script += scriptInTest
# Add compile flags specified with ADDITIONAL_COMPILE_FLAGS.
- substitutions = [(s, x + ' ' + ' '.join(additionalCompileFlags)) if s == '%{compile_flags}'
- else (s, x) for (s, x) in substitutions]
+ substitutions = [
+ (s, x + " " + " ".join(additionalCompileFlags))
+ if s == "%{compile_flags}"
+ else (s, x)
+ for (s, x) in substitutions
+ ]
# Perform substitutions in the script itself.
- script = lit.TestRunner.applySubstitutions(script, substitutions,
- recursion_limit=test.config.recursiveExpansionLimit)
+ script = lit.TestRunner.applySubstitutions(
+ script, substitutions, recursion_limit=test.config.recursiveExpansionLimit
+ )
return script
@@ -213,80 +233,100 @@ class CxxStandardLibraryTest(lit.formats.TestFormat):
Equivalent to `%{exec} %t.exe`. This is intended to be used
in conjunction with the %{build} substitution.
"""
+
def getTestsInDirectory(self, testSuite, pathInSuite, litConfig, localConfig):
- SUPPORTED_SUFFIXES = ['[.]pass[.]cpp$', '[.]pass[.]mm$',
- '[.]compile[.]pass[.]cpp$', '[.]compile[.]pass[.]mm$',
- '[.]compile[.]fail[.]cpp$',
- '[.]link[.]pass[.]cpp$', '[.]link[.]pass[.]mm$',
- '[.]link[.]fail[.]cpp$',
- '[.]sh[.][^.]+$',
- '[.]verify[.]cpp$',
- '[.]fail[.]cpp$']
+ SUPPORTED_SUFFIXES = [
+ "[.]pass[.]cpp$",
+ "[.]pass[.]mm$",
+ "[.]compile[.]pass[.]cpp$",
+ "[.]compile[.]pass[.]mm$",
+ "[.]compile[.]fail[.]cpp$",
+ "[.]link[.]pass[.]cpp$",
+ "[.]link[.]pass[.]mm$",
+ "[.]link[.]fail[.]cpp$",
+ "[.]sh[.][^.]+$",
+ "[.]verify[.]cpp$",
+ "[.]fail[.]cpp$",
+ ]
sourcePath = testSuite.getSourcePath(pathInSuite)
for filename in os.listdir(sourcePath):
# Ignore dot files and excluded tests.
- if filename.startswith('.') or filename in localConfig.excludes:
+ if filename.startswith(".") or filename in localConfig.excludes:
continue
filepath = os.path.join(sourcePath, filename)
if not os.path.isdir(filepath):
if any([re.search(ext, filename) for ext in SUPPORTED_SUFFIXES]):
- yield lit.Test.Test(testSuite, pathInSuite + (filename,), localConfig)
+ yield lit.Test.Test(
+ testSuite, pathInSuite + (filename,), localConfig
+ )
def execute(self, test, litConfig):
- VERIFY_FLAGS = '-Xclang -verify -Xclang -verify-ignore-unexpected=note -ferror-limit=0'
- supportsVerify = 'verify-support' in test.config.available_features
+ VERIFY_FLAGS = (
+ "-Xclang -verify -Xclang -verify-ignore-unexpected=note -ferror-limit=0"
+ )
+ supportsVerify = "verify-support" in test.config.available_features
filename = test.path_in_suite[-1]
- if re.search('[.]sh[.][^.]+$', filename):
- steps = [ ] # The steps are already in the script
+ if re.search("[.]sh[.][^.]+$", filename):
+ steps = [] # The steps are already in the script
return self._executeShTest(test, litConfig, steps)
- elif filename.endswith('.compile.pass.cpp') or filename.endswith('.compile.pass.mm'):
+ elif filename.endswith(".compile.pass.cpp") or filename.endswith(
+ ".compile.pass.mm"
+ ):
steps = [
"%dbg(COMPILED WITH) %{cxx} %s %{flags} %{compile_flags} -fsyntax-only"
]
return self._executeShTest(test, litConfig, steps)
- elif filename.endswith('.compile.fail.cpp'):
+ elif filename.endswith(".compile.fail.cpp"):
steps = [
"%dbg(COMPILED WITH) ! %{cxx} %s %{flags} %{compile_flags} -fsyntax-only"
]
return self._executeShTest(test, litConfig, steps)
- elif filename.endswith('.link.pass.cpp') or filename.endswith('.link.pass.mm'):
+ elif filename.endswith(".link.pass.cpp") or filename.endswith(".link.pass.mm"):
steps = [
"%dbg(COMPILED WITH) %{cxx} %s %{flags} %{compile_flags} %{link_flags} -o %t.exe"
]
return self._executeShTest(test, litConfig, steps)
- elif filename.endswith('.link.fail.cpp'):
+ elif filename.endswith(".link.fail.cpp"):
steps = [
"%dbg(COMPILED WITH) %{cxx} %s %{flags} %{compile_flags} -c -o %t.o",
- "%dbg(LINKED WITH) ! %{cxx} %t.o %{flags} %{link_flags} -o %t.exe"
+ "%dbg(LINKED WITH) ! %{cxx} %t.o %{flags} %{link_flags} -o %t.exe",
]
return self._executeShTest(test, litConfig, steps)
- elif filename.endswith('.verify.cpp'):
+ elif filename.endswith(".verify.cpp"):
if not supportsVerify:
- return lit.Test.Result(lit.Test.UNSUPPORTED,
- "Test {} requires support for Clang-verify, which isn't supported by the compiler".format(test.getFullName()))
+ return lit.Test.Result(
+ lit.Test.UNSUPPORTED,
+ "Test {} requires support for Clang-verify, which isn't supported by the compiler".format(
+ test.getFullName()
+ ),
+ )
steps = [
# Note: Use -Wno-error to make sure all diagnostics are not treated as errors,
# which doesn't make sense for clang-verify tests.
- "%dbg(COMPILED WITH) %{{cxx}} %s %{{flags}} %{{compile_flags}} -fsyntax-only -Wno-error {}".format(VERIFY_FLAGS)
+ "%dbg(COMPILED WITH) %{{cxx}} %s %{{flags}} %{{compile_flags}} -fsyntax-only -Wno-error {}".format(
+ VERIFY_FLAGS
+ )
]
return self._executeShTest(test, litConfig, steps)
# Make sure to check these ones last, since they will match other
# suffixes above too.
- elif filename.endswith('.pass.cpp') or filename.endswith('.pass.mm'):
+ elif filename.endswith(".pass.cpp") or filename.endswith(".pass.mm"):
steps = [
"%dbg(COMPILED WITH) %{cxx} %s %{flags} %{compile_flags} %{link_flags} -o %t.exe",
- "%dbg(EXECUTED AS) %{exec} %t.exe"
+ "%dbg(EXECUTED AS) %{exec} %t.exe",
]
return self._executeShTest(test, litConfig, steps)
# This is like a .verify.cpp test when clang-verify is supported,
# otherwise it's like a .compile.fail.cpp test. This is only provided
# for backwards compatibility with the test suite.
- elif filename.endswith('.fail.cpp'):
+ elif filename.endswith(".fail.cpp"):
if supportsVerify:
steps = [
- "%dbg(COMPILED WITH) %{{cxx}} %s %{{flags}} %{{compile_flags}} -fsyntax-only -Wno-error {}".format(VERIFY_FLAGS)
+ "%dbg(COMPILED WITH) %{{cxx}} %s %{{flags}} %{{compile_flags}} -fsyntax-only -Wno-error {}".format(
+ VERIFY_FLAGS
+ )
]
else:
steps = [
@@ -294,19 +334,25 @@ class CxxStandardLibraryTest(lit.formats.TestFormat):
]
return self._executeShTest(test, litConfig, steps)
else:
- return lit.Test.Result(lit.Test.UNRESOLVED, "Unknown test suffix for '{}'".format(filename))
+ return lit.Test.Result(
+ lit.Test.UNRESOLVED, "Unknown test suffix for '{}'".format(filename)
+ )
def _executeShTest(self, test, litConfig, steps):
if test.config.unsupported:
- return lit.Test.Result(lit.Test.UNSUPPORTED, 'Test is unsupported')
+ return lit.Test.Result(lit.Test.UNSUPPORTED, "Test is unsupported")
script = parseScript(test, steps)
if isinstance(script, lit.Test.Result):
return script
if litConfig.noExecute:
- return lit.Test.Result(lit.Test.XFAIL if test.isExpectedToFail() else lit.Test.PASS)
+ return lit.Test.Result(
+ lit.Test.XFAIL if test.isExpectedToFail() else lit.Test.PASS
+ )
else:
_, tmpBase = _getTempPaths(test)
useExternalSh = False
- return lit.TestRunner._runShTest(test, litConfig, useExternalSh, script, tmpBase)
+ return lit.TestRunner._runShTest(
+ test, litConfig, useExternalSh, script, tmpBase
+ )
diff --git a/libcxx/utils/libcxx/test/googlebenchmark.py b/libcxx/utils/libcxx/test/googlebenchmark.py
index d6960a7..d260484 100644
--- a/libcxx/utils/libcxx/test/googlebenchmark.py
+++ b/libcxx/utils/libcxx/test/googlebenchmark.py
@@ -8,20 +8,21 @@ import lit.TestRunner
import lit.util
from lit.formats.base import TestFormat
-kIsWindows = sys.platform in ['win32', 'cygwin']
+kIsWindows = sys.platform in ["win32", "cygwin"]
+
class GoogleBenchmark(TestFormat):
def __init__(self, test_sub_dirs, test_suffix, benchmark_args=[]):
self.benchmark_args = list(benchmark_args)
- self.test_sub_dirs = os.path.normcase(str(test_sub_dirs)).split(';')
+ self.test_sub_dirs = os.path.normcase(str(test_sub_dirs)).split(";")
# On Windows, assume tests will also end in '.exe'.
exe_suffix = str(test_suffix)
if kIsWindows:
- exe_suffix += '.exe'
+ exe_suffix += ".exe"
# Also check for .py files for testing purposes.
- self.test_suffixes = {exe_suffix, test_suffix + '.py'}
+ self.test_suffixes = {exe_suffix, test_suffix + ".py"}
def getBenchmarkTests(self, path, litConfig, localConfig):
"""getBenchmarkTests(path) - [name]
@@ -36,14 +37,14 @@ class GoogleBenchmark(TestFormat):
# TODO: allow splitting tests according to the "benchmark family" so
# the output for a single family of tests all belongs to the same test
# target.
- list_test_cmd = [path, '--benchmark_list_tests']
+ list_test_cmd = [path, "--benchmark_list_tests"]
try:
- output = subprocess.check_output(list_test_cmd,
- env=localConfig.environment)
+ output = subprocess.check_output(list_test_cmd, env=localConfig.environment)
except subprocess.CalledProcessError as exc:
litConfig.warning(
"unable to discover google-benchmarks in %r: %s. Process output: %s"
- % (path, sys.exc_info()[1], exc.output))
+ % (path, sys.exc_info()[1], exc.output)
+ )
raise StopIteration
nested_tests = []
@@ -53,69 +54,72 @@ class GoogleBenchmark(TestFormat):
continue
index = 0
- while ln[index*2:index*2+2] == ' ':
+ while ln[index * 2 : index * 2 + 2] == " ":
index += 1
while len(nested_tests) > index:
nested_tests.pop()
- ln = ln[index*2:]
- if ln.endswith('.'):
+ ln = ln[index * 2 :]
+ if ln.endswith("."):
nested_tests.append(ln)
- elif any([name.startswith('DISABLED_')
- for name in nested_tests + [ln]]):
+ elif any([name.startswith("DISABLED_") for name in nested_tests + [ln]]):
# Gtest will internally skip these tests. No need to launch a
# child process for it.
continue
else:
- yield ''.join(nested_tests) + ln
+ yield "".join(nested_tests) + ln
- def getTestsInDirectory(self, testSuite, path_in_suite,
- litConfig, localConfig):
+ def getTestsInDirectory(self, testSuite, path_in_suite, litConfig, localConfig):
source_path = testSuite.getSourcePath(path_in_suite)
for subdir in self.test_sub_dirs:
dir_path = os.path.join(source_path, subdir)
if not os.path.isdir(dir_path):
continue
- for fn in lit.util.listdir_files(dir_path,
- suffixes=self.test_suffixes):
+ for fn in lit.util.listdir_files(dir_path, suffixes=self.test_suffixes):
# Discover the tests in this executable.
execpath = os.path.join(source_path, subdir, fn)
testnames = self.getBenchmarkTests(execpath, litConfig, localConfig)
for testname in testnames:
testPath = path_in_suite + (subdir, fn, testname)
- yield lit.Test.Test(testSuite, testPath, localConfig,
- file_path=execpath)
+ yield lit.Test.Test(
+ testSuite, testPath, localConfig, file_path=execpath
+ )
def execute(self, test, litConfig):
- testPath,testName = os.path.split(test.getSourcePath())
+ testPath, testName = os.path.split(test.getSourcePath())
while not os.path.exists(testPath):
# Handle GTest parametrized and typed tests, whose name includes
# some '/'s.
testPath, namePrefix = os.path.split(testPath)
- testName = namePrefix + '/' + testName
+ testName = namePrefix + "/" + testName
- cmd = [testPath, '--benchmark_filter=%s$' % testName ] + self.benchmark_args
+ cmd = [testPath, "--benchmark_filter=%s$" % testName] + self.benchmark_args
if litConfig.noExecute:
- return lit.Test.PASS, ''
+ return lit.Test.PASS, ""
try:
out, err, exitCode = lit.util.executeCommand(
- cmd, env=test.config.environment,
- timeout=litConfig.maxIndividualTestTime)
+ cmd,
+ env=test.config.environment,
+ timeout=litConfig.maxIndividualTestTime,
+ )
except lit.util.ExecuteCommandTimeoutException:
- return (lit.Test.TIMEOUT,
- 'Reached timeout of {} seconds'.format(
- litConfig.maxIndividualTestTime)
- )
+ return (
+ lit.Test.TIMEOUT,
+ "Reached timeout of {} seconds".format(litConfig.maxIndividualTestTime),
+ )
if exitCode:
- return lit.Test.FAIL, ('exit code: %d\n' % exitCode) + out + err
+ return lit.Test.FAIL, ("exit code: %d\n" % exitCode) + out + err
passing_test_line = testName
if passing_test_line not in out:
- msg = ('Unable to find %r in google benchmark output:\n\n%s%s' %
- (passing_test_line, out, err))
+ msg = "Unable to find %r in google benchmark output:\n\n%s%s" % (
+ passing_test_line,
+ out,
+ err,
+ )
return lit.Test.UNRESOLVED, msg
return lit.Test.PASS, err + out
diff --git a/libcxx/utils/libcxx/test/params.py b/libcxx/utils/libcxx/test/params.py
index aa42157..052a187 100644
--- a/libcxx/utils/libcxx/test/params.py
+++ b/libcxx/utils/libcxx/test/params.py
@@ -1,126 +1,158 @@
-#===----------------------------------------------------------------------===##
+# ===----------------------------------------------------------------------===##
#
# 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
#
-#===----------------------------------------------------------------------===##
+# ===----------------------------------------------------------------------===##
from libcxx.test.dsl import *
from libcxx.test.features import _isMSVC
import re
_warningFlags = [
- '-Werror',
- '-Wall',
- '-Wctad-maybe-unsupported',
- '-Wextra',
- '-Wshadow',
- '-Wundef',
- '-Wunused-template',
- '-Wno-unused-command-line-argument',
- '-Wno-attributes',
- '-Wno-pessimizing-move',
- '-Wno-c++11-extensions',
- '-Wno-noexcept-type',
- '-Wno-aligned-allocation-unavailable',
- '-Wno-atomic-alignment',
-
- # GCC warns about places where we might want to add sized allocation/deallocation
- # functions, but we know better what we're doing/testing in the test suite.
- '-Wno-sized-deallocation',
-
- # Turn off warnings about user-defined literals with reserved suffixes. Those are
- # just noise since we are testing the Standard Library itself.
- '-Wno-literal-suffix', # GCC
- '-Wno-user-defined-literals', # Clang
-
- # GCC warns about this when TEST_IS_CONSTANT_EVALUATED is used on a non-constexpr
- # function. (This mostely happens in C++11 mode.)
- # TODO(mordante) investigate a solution for this issue.
- '-Wno-tautological-compare',
-
- # -Wstringop-overread and -Wstringop-overflow seem to be a bit buggy currently
- '-Wno-stringop-overread',
- '-Wno-stringop-overflow',
-
- # These warnings should be enabled in order to support the MSVC
- # team using the test suite; They enable the warnings below and
- # expect the test suite to be clean.
- '-Wsign-compare',
- '-Wunused-variable',
- '-Wunused-parameter',
- '-Wunreachable-code',
- '-Wno-unused-local-typedef',
+ "-Werror",
+ "-Wall",
+ "-Wctad-maybe-unsupported",
+ "-Wextra",
+ "-Wshadow",
+ "-Wundef",
+ "-Wunused-template",
+ "-Wno-unused-command-line-argument",
+ "-Wno-attributes",
+ "-Wno-pessimizing-move",
+ "-Wno-c++11-extensions",
+ "-Wno-noexcept-type",
+ "-Wno-aligned-allocation-unavailable",
+ "-Wno-atomic-alignment",
+ # GCC warns about places where we might want to add sized allocation/deallocation
+ # functions, but we know better what we're doing/testing in the test suite.
+ "-Wno-sized-deallocation",
+ # Turn off warnings about user-defined literals with reserved suffixes. Those are
+ # just noise since we are testing the Standard Library itself.
+ "-Wno-literal-suffix", # GCC
+ "-Wno-user-defined-literals", # Clang
+ # GCC warns about this when TEST_IS_CONSTANT_EVALUATED is used on a non-constexpr
+ # function. (This mostely happens in C++11 mode.)
+ # TODO(mordante) investigate a solution for this issue.
+ "-Wno-tautological-compare",
+ # -Wstringop-overread and -Wstringop-overflow seem to be a bit buggy currently
+ "-Wno-stringop-overread",
+ "-Wno-stringop-overflow",
+ # These warnings should be enabled in order to support the MSVC
+ # team using the test suite; They enable the warnings below and
+ # expect the test suite to be clean.
+ "-Wsign-compare",
+ "-Wunused-variable",
+ "-Wunused-parameter",
+ "-Wunreachable-code",
+ "-Wno-unused-local-typedef",
]
-_allStandards = ['c++03', 'c++11', 'c++14', 'c++17', 'c++20', 'c++23', 'c++26']
-def getStdFlag(cfg, std):
- fallbacks = {
- 'c++11': 'c++0x',
- 'c++14': 'c++1y',
- 'c++17': 'c++1z',
- 'c++20': 'c++2a',
- 'c++23': 'c++2b',
- }
- # TODO(LLVM-17) Remove this clang-tidy-16 work-around
- if std == 'c++23':
- std = 'c++2b'
- if hasCompileFlag(cfg, '-std='+std):
- return '-std='+std
- if std in fallbacks and hasCompileFlag(cfg, '-std='+fallbacks[std]):
- return '-std='+fallbacks[std]
- return None
+_allStandards = ["c++03", "c++11", "c++14", "c++17", "c++20", "c++23", "c++26"]
-DEFAULT_PARAMETERS = [
- Parameter(name='target_triple', type=str,
- help="The target triple to compile the test suite for. This must be "
- "compatible with the target that the tests will be run on.",
- actions=lambda triple: filter(None, [
- AddFeature('target={}'.format(triple)),
- AddFlagIfSupported('--target={}'.format(triple)),
- AddSubstitution('%{triple}', triple)
- ])),
- Parameter(name='std', choices=_allStandards, type=str,
- help="The version of the standard to compile the test suite with.",
- default=lambda cfg: next(s for s in reversed(_allStandards) if getStdFlag(cfg, s)),
- actions=lambda std: [
- AddFeature(std),
- AddSubstitution('%{cxx_std}', re.sub('\+','x', std)),
- AddCompileFlag(lambda cfg: getStdFlag(cfg, std)),
- ]),
-
- Parameter(name='enable_modules', choices=[True, False], type=bool, default=False,
- help="Whether to build the test suite with Clang modules enabled.",
- actions=lambda modules: [
- AddFeature('modules-build'),
- AddCompileFlag('-fmodules'),
- AddCompileFlag('-fcxx-modules'), # AppleClang disregards -fmodules entirely when compiling C++. This enables modules for C++.
- ] if modules else []),
-
- Parameter(name='enable_modules_lsv', choices=[True, False], type=bool, default=False,
- help="Whether to enable Local Submodule Visibility in the Modules build.",
- actions=lambda lsv: [
- AddCompileFlag('-Xclang -fmodules-local-submodule-visibility'),
- ] if lsv else []),
-
- Parameter(name='enable_exceptions', choices=[True, False], type=bool, default=True,
- help="Whether to enable exceptions when compiling the test suite.",
- actions=lambda exceptions: [] if exceptions else [
- AddFeature('no-exceptions'),
- AddCompileFlag('-fno-exceptions')
- ]),
+def getStdFlag(cfg, std):
+ fallbacks = {
+ "c++11": "c++0x",
+ "c++14": "c++1y",
+ "c++17": "c++1z",
+ "c++20": "c++2a",
+ "c++23": "c++2b",
+ }
+ # TODO(LLVM-17) Remove this clang-tidy-16 work-around
+ if std == "c++23":
+ std = "c++2b"
+ if hasCompileFlag(cfg, "-std=" + std):
+ return "-std=" + std
+ if std in fallbacks and hasCompileFlag(cfg, "-std=" + fallbacks[std]):
+ return "-std=" + fallbacks[std]
+ return None
- Parameter(name='enable_rtti', choices=[True, False], type=bool, default=True,
- help="Whether to enable RTTI when compiling the test suite.",
- actions=lambda rtti: [] if rtti else [
- AddFeature('no-rtti'),
- AddCompileFlag('-fno-rtti')
- ]),
- Parameter(name='stdlib', choices=['llvm-libc++', 'apple-libc++', 'libstdc++', 'msvc'], type=str, default='llvm-libc++',
- help="""The C++ Standard Library implementation being tested.
+DEFAULT_PARAMETERS = [
+ Parameter(
+ name="target_triple",
+ type=str,
+ help="The target triple to compile the test suite for. This must be "
+ "compatible with the target that the tests will be run on.",
+ actions=lambda triple: filter(
+ None,
+ [
+ AddFeature("target={}".format(triple)),
+ AddFlagIfSupported("--target={}".format(triple)),
+ AddSubstitution("%{triple}", triple),
+ ],
+ ),
+ ),
+ Parameter(
+ name="std",
+ choices=_allStandards,
+ type=str,
+ help="The version of the standard to compile the test suite with.",
+ default=lambda cfg: next(
+ s for s in reversed(_allStandards) if getStdFlag(cfg, s)
+ ),
+ actions=lambda std: [
+ AddFeature(std),
+ AddSubstitution("%{cxx_std}", re.sub("\+", "x", std)),
+ AddCompileFlag(lambda cfg: getStdFlag(cfg, std)),
+ ],
+ ),
+ Parameter(
+ name="enable_modules",
+ choices=[True, False],
+ type=bool,
+ default=False,
+ help="Whether to build the test suite with Clang modules enabled.",
+ actions=lambda modules: [
+ AddFeature("modules-build"),
+ AddCompileFlag("-fmodules"),
+ AddCompileFlag(
+ "-fcxx-modules"
+ ), # AppleClang disregards -fmodules entirely when compiling C++. This enables modules for C++.
+ ]
+ if modules
+ else [],
+ ),
+ Parameter(
+ name="enable_modules_lsv",
+ choices=[True, False],
+ type=bool,
+ default=False,
+ help="Whether to enable Local Submodule Visibility in the Modules build.",
+ actions=lambda lsv: [
+ AddCompileFlag("-Xclang -fmodules-local-submodule-visibility"),
+ ]
+ if lsv
+ else [],
+ ),
+ Parameter(
+ name="enable_exceptions",
+ choices=[True, False],
+ type=bool,
+ default=True,
+ help="Whether to enable exceptions when compiling the test suite.",
+ actions=lambda exceptions: []
+ if exceptions
+ else [AddFeature("no-exceptions"), AddCompileFlag("-fno-exceptions")],
+ ),
+ Parameter(
+ name="enable_rtti",
+ choices=[True, False],
+ type=bool,
+ default=True,
+ help="Whether to enable RTTI when compiling the test suite.",
+ actions=lambda rtti: []
+ if rtti
+ else [AddFeature("no-rtti"), AddCompileFlag("-fno-rtti")],
+ ),
+ Parameter(
+ name="stdlib",
+ choices=["llvm-libc++", "apple-libc++", "libstdc++", "msvc"],
+ type=str,
+ default="llvm-libc++",
+ help="""The C++ Standard Library implementation being tested.
Note that this parameter can also be used to encode different 'flavors' of the same
standard library, such as libc++ as shipped by a different vendor, if it has different
@@ -134,88 +166,148 @@ DEFAULT_PARAMETERS = [
- libstdc++: The GNU C++ library typically shipped with GCC.
- msvc: The Microsoft implementation of the C++ Standard Library.
""",
- actions=lambda stdlib: filter(None, [
- AddFeature('stdlib={}'.format(stdlib)),
- # Also add an umbrella feature 'stdlib=libc++' for all flavors of libc++, to simplify
- # the test suite.
- AddFeature('stdlib=libc++') if re.match('.+-libc\+\+', stdlib) else None
- ])),
-
- Parameter(name='enable_warnings', choices=[True, False], type=bool, default=True,
- help="Whether to enable warnings when compiling the test suite.",
- actions=lambda warnings: [] if not warnings else
- [AddOptionalWarningFlag(w) for w in _warningFlags] +
- [AddCompileFlag('-D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER')]
+ actions=lambda stdlib: filter(
+ None,
+ [
+ AddFeature("stdlib={}".format(stdlib)),
+ # Also add an umbrella feature 'stdlib=libc++' for all flavors of libc++, to simplify
+ # the test suite.
+ AddFeature("stdlib=libc++")
+ if re.match(".+-libc\+\+", stdlib)
+ else None,
+ ],
+ ),
+ ),
+ Parameter(
+ name="enable_warnings",
+ choices=[True, False],
+ type=bool,
+ default=True,
+ help="Whether to enable warnings when compiling the test suite.",
+ actions=lambda warnings: []
+ if not warnings
+ else [AddOptionalWarningFlag(w) for w in _warningFlags]
+ + [AddCompileFlag("-D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER")],
+ ),
+ Parameter(
+ name="use_sanitizer",
+ choices=[
+ "",
+ "Address",
+ "HWAddress",
+ "Undefined",
+ "Memory",
+ "MemoryWithOrigins",
+ "Thread",
+ "DataFlow",
+ "Leaks",
+ ],
+ type=str,
+ default="",
+ help="An optional sanitizer to enable when building and running the test suite.",
+ actions=lambda sanitizer: filter(
+ None,
+ [
+ AddFlag("-g -fno-omit-frame-pointer") if sanitizer else None,
+ AddFlag(
+ "-fsanitize=undefined -fno-sanitize=float-divide-by-zero -fno-sanitize-recover=all"
+ )
+ if sanitizer == "Undefined"
+ else None,
+ AddFeature("ubsan") if sanitizer == "Undefined" else None,
+ AddFlag("-fsanitize=address") if sanitizer == "Address" else None,
+ AddFeature("asan") if sanitizer == "Address" else None,
+ AddFlag("-fsanitize=hwaddress") if sanitizer == "HWAddress" else None,
+ AddFeature("hwasan") if sanitizer == "HWAddress" else None,
+ AddFlag("-fsanitize=memory")
+ if sanitizer in ["Memory", "MemoryWithOrigins"]
+ else None,
+ AddFeature("msan")
+ if sanitizer in ["Memory", "MemoryWithOrigins"]
+ else None,
+ AddFlag("-fsanitize-memory-track-origins")
+ if sanitizer == "MemoryWithOrigins"
+ else None,
+ AddFlag("-fsanitize=thread") if sanitizer == "Thread" else None,
+ AddFeature("tsan") if sanitizer == "Thread" else None,
+ AddFlag("-fsanitize=dataflow") if sanitizer == "DataFlow" else None,
+ AddFlag("-fsanitize=leaks") if sanitizer == "Leaks" else None,
+ AddFeature("sanitizer-new-delete")
+ if sanitizer
+ in ["Address", "HWAddress", "Memory", "MemoryWithOrigins", "Thread"]
+ else None,
+ ],
+ ),
+ ),
+ Parameter(
+ name="enable_experimental",
+ choices=[True, False],
+ type=bool,
+ default=True,
+ help="Whether to enable tests for experimental C++ Library features.",
+ actions=lambda experimental: [
+ # When linking in MSVC mode via the Clang driver, a -l<foo>
+ # maps to <foo>.lib, so we need to use -llibc++experimental here
+ # to make it link against the static libc++experimental.lib.
+ # We can't check for the feature 'msvc' in available_features
+ # as those features are added after processing parameters.
+ AddFeature("c++experimental"),
+ PrependLinkFlag(
+ lambda cfg: "-llibc++experimental"
+ if _isMSVC(cfg)
+ else "-lc++experimental"
),
-
- Parameter(name='use_sanitizer', choices=['', 'Address', 'HWAddress', 'Undefined', 'Memory', 'MemoryWithOrigins', 'Thread', 'DataFlow', 'Leaks'], type=str, default='',
- help="An optional sanitizer to enable when building and running the test suite.",
- actions=lambda sanitizer: filter(None, [
- AddFlag('-g -fno-omit-frame-pointer') if sanitizer else None,
-
- AddFlag('-fsanitize=undefined -fno-sanitize=float-divide-by-zero -fno-sanitize-recover=all') if sanitizer == 'Undefined' else None,
- AddFeature('ubsan') if sanitizer == 'Undefined' else None,
-
- AddFlag('-fsanitize=address') if sanitizer == 'Address' else None,
- AddFeature('asan') if sanitizer == 'Address' else None,
-
- AddFlag('-fsanitize=hwaddress') if sanitizer == 'HWAddress' else None,
- AddFeature('hwasan') if sanitizer == 'HWAddress' else None,
-
- AddFlag('-fsanitize=memory') if sanitizer in ['Memory', 'MemoryWithOrigins'] else None,
- AddFeature('msan') if sanitizer in ['Memory', 'MemoryWithOrigins'] else None,
- AddFlag('-fsanitize-memory-track-origins') if sanitizer == 'MemoryWithOrigins' else None,
-
- AddFlag('-fsanitize=thread') if sanitizer == 'Thread' else None,
- AddFeature('tsan') if sanitizer == 'Thread' else None,
-
- AddFlag('-fsanitize=dataflow') if sanitizer == 'DataFlow' else None,
- AddFlag('-fsanitize=leaks') if sanitizer == 'Leaks' else None,
-
- AddFeature('sanitizer-new-delete') if sanitizer in ['Address', 'HWAddress', 'Memory', 'MemoryWithOrigins', 'Thread'] else None,
- ])),
-
- Parameter(name='enable_experimental', choices=[True, False], type=bool, default=True,
- help="Whether to enable tests for experimental C++ Library features.",
- actions=lambda experimental: [
- # When linking in MSVC mode via the Clang driver, a -l<foo>
- # maps to <foo>.lib, so we need to use -llibc++experimental here
- # to make it link against the static libc++experimental.lib.
- # We can't check for the feature 'msvc' in available_features
- # as those features are added after processing parameters.
- AddFeature('c++experimental'),
- PrependLinkFlag(lambda cfg: '-llibc++experimental' if _isMSVC(cfg) else '-lc++experimental'),
- AddCompileFlag('-D_LIBCPP_ENABLE_EXPERIMENTAL'),
- ] if experimental else [
- AddFeature('libcpp-has-no-incomplete-pstl'),
- ]),
-
- Parameter(name='long_tests', choices=[True, False], type=bool, default=True,
- help="Whether to enable tests that take longer to run. This can be useful when running on a very slow device.",
- actions=lambda enabled: [] if not enabled else [
- AddFeature('long_tests')
- ]),
-
- Parameter(name='enable_assertions', choices=[True, False], type=bool, default=False,
- help="Whether to enable assertions when compiling the test suite. This is only meaningful when "
- "running the tests against libc++.",
- actions=lambda assertions: [
- AddCompileFlag('-D_LIBCPP_ENABLE_ASSERTIONS=1'),
- AddFeature('libcpp-has-assertions')
- ] if assertions else []),
-
- Parameter(name='additional_features', type=list, default=[],
- help="A comma-delimited list of additional features that will be enabled when running the tests. "
- "This should be used sparingly since specifying ad-hoc features manually is error-prone and "
- "brittle in the long run as changes are made to the test suite.",
- actions=lambda features: [AddFeature(f) for f in features]),
-
- Parameter(name='enable_transitive_includes', choices=[True, False], type=bool, default=True,
- help="Whether to enable backwards-compatibility transitive includes when running the tests. This "
- "is provided to ensure that the trimmed-down version of libc++ does not bit-rot in between "
- "points at which we bulk-remove transitive includes.",
- actions=lambda enabled: [] if enabled else [
- AddFeature('transitive-includes-disabled'),
- AddCompileFlag('-D_LIBCPP_REMOVE_TRANSITIVE_INCLUDES')
- ]),
+ AddCompileFlag("-D_LIBCPP_ENABLE_EXPERIMENTAL"),
+ ]
+ if experimental
+ else [
+ AddFeature("libcpp-has-no-incomplete-pstl"),
+ ],
+ ),
+ Parameter(
+ name="long_tests",
+ choices=[True, False],
+ type=bool,
+ default=True,
+ help="Whether to enable tests that take longer to run. This can be useful when running on a very slow device.",
+ actions=lambda enabled: [] if not enabled else [AddFeature("long_tests")],
+ ),
+ Parameter(
+ name="enable_assertions",
+ choices=[True, False],
+ type=bool,
+ default=False,
+ help="Whether to enable assertions when compiling the test suite. This is only meaningful when "
+ "running the tests against libc++.",
+ actions=lambda assertions: [
+ AddCompileFlag("-D_LIBCPP_ENABLE_ASSERTIONS=1"),
+ AddFeature("libcpp-has-assertions"),
+ ]
+ if assertions
+ else [],
+ ),
+ Parameter(
+ name="additional_features",
+ type=list,
+ default=[],
+ help="A comma-delimited list of additional features that will be enabled when running the tests. "
+ "This should be used sparingly since specifying ad-hoc features manually is error-prone and "
+ "brittle in the long run as changes are made to the test suite.",
+ actions=lambda features: [AddFeature(f) for f in features],
+ ),
+ Parameter(
+ name="enable_transitive_includes",
+ choices=[True, False],
+ type=bool,
+ default=True,
+ help="Whether to enable backwards-compatibility transitive includes when running the tests. This "
+ "is provided to ensure that the trimmed-down version of libc++ does not bit-rot in between "
+ "points at which we bulk-remove transitive includes.",
+ actions=lambda enabled: []
+ if enabled
+ else [
+ AddFeature("transitive-includes-disabled"),
+ AddCompileFlag("-D_LIBCPP_REMOVE_TRANSITIVE_INCLUDES"),
+ ],
+ ),
]
diff --git a/libcxx/utils/run.py b/libcxx/utils/run.py
index 347a013..32961d7 100755
--- a/libcxx/utils/run.py
+++ b/libcxx/utils/run.py
@@ -1,11 +1,11 @@
#!/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
#
-#===----------------------------------------------------------------------===##
+# ===----------------------------------------------------------------------===##
"""run.py is a utility for running a program.
@@ -21,10 +21,12 @@ import subprocess
def main():
parser = argparse.ArgumentParser()
- parser.add_argument('--execdir', type=str, required=True)
- parser.add_argument('--codesign_identity', type=str, required=False, default=None)
- parser.add_argument('--env', type=str, nargs='*', required=False, default=[])
- parser.add_argument('--prepend_env', type=str, nargs='*', required=False, default=[])
+ parser.add_argument("--execdir", type=str, required=True)
+ parser.add_argument("--codesign_identity", type=str, required=False, default=None)
+ parser.add_argument("--env", type=str, nargs="*", required=False, default=[])
+ parser.add_argument(
+ "--prepend_env", type=str, nargs="*", required=False, default=[]
+ )
parser.add_argument("command", nargs=argparse.ONE_OR_MORE)
args = parser.parse_args()
commandLine = args.command
@@ -35,35 +37,37 @@ def main():
# below. This allows us to do custom processing like codesigning test-executables.
# It's also possible for there to be no such executable, for example in the case
# of a .sh.cpp test.
- isTestExe = lambda exe: exe.endswith('.tmp.exe') and os.path.exists(exe)
+ isTestExe = lambda exe: exe.endswith(".tmp.exe") and os.path.exists(exe)
# Do any necessary codesigning of test-executables found in the command line.
if args.codesign_identity:
for exe in filter(isTestExe, commandLine):
- subprocess.check_call(['xcrun', 'codesign', '-f', '-s', args.codesign_identity, exe], env={})
+ subprocess.check_call(
+ ["xcrun", "codesign", "-f", "-s", args.codesign_identity, exe], env={}
+ )
# Extract environment variables into a dictionary
- env = {k : v for (k, v) in map(lambda s: s.split('=', 1), args.env)}
+ env = {k: v for (k, v) in map(lambda s: s.split("=", 1), args.env)}
# Set environment variables where we prepend the given value to the
# existing environment variable.
- for (k, v) in map(lambda s: s.split('=', 1), args.prepend_env):
+ for (k, v) in map(lambda s: s.split("=", 1), args.prepend_env):
if k in os.environ:
v = v + os.pathsep + os.environ[k]
env[k] = v
- if platform.system() == 'Windows':
+ if platform.system() == "Windows":
# Pass some extra variables through on Windows:
# COMSPEC is needed for running subprocesses via std::system().
- if 'COMSPEC' in os.environ:
- env['COMSPEC'] = os.environ.get('COMSPEC')
+ if "COMSPEC" in os.environ:
+ env["COMSPEC"] = os.environ.get("COMSPEC")
# TEMP is needed for placing temp files in a sensible directory.
- if 'TEMP' in os.environ:
- env['TEMP'] = os.environ.get('TEMP')
+ if "TEMP" in os.environ:
+ env["TEMP"] = os.environ.get("TEMP")
# Run the command line with the given environment in the execution directory.
return subprocess.call(commandLine, cwd=args.execdir, env=env, shell=False)
-if __name__ == '__main__':
+if __name__ == "__main__":
exit(main())
diff --git a/libcxx/utils/ssh.py b/libcxx/utils/ssh.py
index a5f17d6..dad98c1 100755
--- a/libcxx/utils/ssh.py
+++ b/libcxx/utils/ssh.py
@@ -1,11 +1,11 @@
#!/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
#
-#===----------------------------------------------------------------------===##
+# ===----------------------------------------------------------------------===##
"""
Runs an executable on a remote host.
@@ -25,37 +25,43 @@ import tempfile
from shlex import quote as cmd_quote
+
def ssh(args, command):
- cmd = ['ssh', '-oBatchMode=yes']
+ cmd = ["ssh", "-oBatchMode=yes"]
if args.extra_ssh_args is not None:
cmd.extend(shlex.split(args.extra_ssh_args))
return cmd + [args.host, command]
def scp(args, src, dst):
- cmd = ['scp', '-q', '-oBatchMode=yes']
+ cmd = ["scp", "-q", "-oBatchMode=yes"]
if args.extra_scp_args is not None:
cmd.extend(shlex.split(args.extra_scp_args))
- return cmd + [src, '{}:{}'.format(args.host, dst)]
+ return cmd + [src, "{}:{}".format(args.host, dst)]
def main():
parser = argparse.ArgumentParser()
- parser.add_argument('--host', type=str, required=True)
- parser.add_argument('--execdir', type=str, required=True)
- parser.add_argument('--tempdir', type=str, required=False, default='/tmp')
- parser.add_argument('--extra-ssh-args', type=str, required=False)
- parser.add_argument('--extra-scp-args', type=str, required=False)
- parser.add_argument('--codesign_identity', type=str, required=False, default=None)
- parser.add_argument('--env', type=str, nargs='*', required=False, default=[])
- parser.add_argument('--prepend_env', type=str, nargs='*', required=False, default=[])
+ parser.add_argument("--host", type=str, required=True)
+ parser.add_argument("--execdir", type=str, required=True)
+ parser.add_argument("--tempdir", type=str, required=False, default="/tmp")
+ parser.add_argument("--extra-ssh-args", type=str, required=False)
+ parser.add_argument("--extra-scp-args", type=str, required=False)
+ parser.add_argument("--codesign_identity", type=str, required=False, default=None)
+ parser.add_argument("--env", type=str, nargs="*", required=False, default=[])
+ parser.add_argument(
+ "--prepend_env", type=str, nargs="*", required=False, default=[]
+ )
parser.add_argument("command", nargs=argparse.ONE_OR_MORE)
args = parser.parse_args()
commandLine = args.command
# Create a temporary directory where the test will be run.
# That is effectively the value of %T on the remote host.
- tmp = subprocess.check_output(ssh(args, 'mktemp -d {}/libcxx.XXXXXXXXXX'.format(args.tempdir)), universal_newlines=True).strip()
+ tmp = subprocess.check_output(
+ ssh(args, "mktemp -d {}/libcxx.XXXXXXXXXX".format(args.tempdir)),
+ universal_newlines=True,
+ ).strip()
# HACK:
# If an argument is a file that ends in `.tmp.exe`, assume it is the name
@@ -64,20 +70,23 @@ def main():
# and changing their path when running on the remote host. It's also possible
# for there to be no such executable, for example in the case of a .sh.cpp
# test.
- isTestExe = lambda exe: exe.endswith('.tmp.exe') and os.path.exists(exe)
+ isTestExe = lambda exe: exe.endswith(".tmp.exe") and os.path.exists(exe)
pathOnRemote = lambda file: posixpath.join(tmp, os.path.basename(file))
try:
# Do any necessary codesigning of test-executables found in the command line.
if args.codesign_identity:
for exe in filter(isTestExe, commandLine):
- subprocess.check_call(['xcrun', 'codesign', '-f', '-s', args.codesign_identity, exe], env={})
+ subprocess.check_call(
+ ["xcrun", "codesign", "-f", "-s", args.codesign_identity, exe],
+ env={},
+ )
# tar up the execution directory (which contains everything that's needed
# to run the test), and copy the tarball over to the remote host.
try:
- tmpTar = tempfile.NamedTemporaryFile(suffix='.tar', delete=False)
- with tarfile.open(fileobj=tmpTar, mode='w') as tarball:
+ tmpTar = tempfile.NamedTemporaryFile(suffix=".tar", delete=False)
+ with tarfile.open(fileobj=tmpTar, mode="w") as tarball:
tarball.add(args.execdir, arcname=os.path.basename(args.execdir))
# Make sure we close the file before we scp it, because accessing
@@ -93,22 +102,22 @@ def main():
# Untar the dependencies in the temporary directory and remove the tarball.
remoteCommands = [
- 'tar -xf {} -C {} --strip-components 1'.format(remoteTarball, tmp),
- 'rm {}'.format(remoteTarball)
+ "tar -xf {} -C {} --strip-components 1".format(remoteTarball, tmp),
+ "rm {}".format(remoteTarball),
]
# Make sure all test-executables in the remote command line have 'execute'
# permissions on the remote host. The host that compiled the test-executable
# might not have a notion of 'executable' permissions.
for exe in map(pathOnRemote, filter(isTestExe, commandLine)):
- remoteCommands.append('chmod +x {}'.format(exe))
+ remoteCommands.append("chmod +x {}".format(exe))
# Execute the command through SSH in the temporary directory, with the
# correct environment. We tweak the command line to run it on the remote
# host by transforming the path of test-executables to their path in the
# temporary directory on the remote host.
commandLine = (pathOnRemote(x) if isTestExe(x) else x for x in commandLine)
- remoteCommands.append('cd {}'.format(tmp))
+ remoteCommands.append("cd {}".format(tmp))
if args.prepend_env:
# We can't sensibly know the original value of the env vars
@@ -117,17 +126,17 @@ def main():
if args.env:
env = list(map(cmd_quote, args.env))
- remoteCommands.append('export {}'.format(' '.join(args.env)))
+ remoteCommands.append("export {}".format(" ".join(args.env)))
remoteCommands.append(subprocess.list2cmdline(commandLine))
# Finally, SSH to the remote host and execute all the commands.
- rc = subprocess.call(ssh(args, ' && '.join(remoteCommands)))
+ rc = subprocess.call(ssh(args, " && ".join(remoteCommands)))
return rc
finally:
# Make sure the temporary directory is removed when we're done.
- subprocess.check_call(ssh(args, 'rm -r {}'.format(tmp)))
+ subprocess.check_call(ssh(args, "rm -r {}".format(tmp)))
-if __name__ == '__main__':
+if __name__ == "__main__":
exit(main())
diff --git a/libcxx/utils/sym_diff.py b/libcxx/utils/sym_diff.py
index 6bd1b57..8eaf8b7 100755
--- a/libcxx/utils/sym_diff.py
+++ b/libcxx/utils/sym_diff.py
@@ -1,11 +1,11 @@
#!/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
#
-#===----------------------------------------------------------------------===##
+# ===----------------------------------------------------------------------===##
"""
sym_diff - Compare two symbol lists and output the differences.
"""
@@ -17,34 +17,60 @@ from libcxx.sym_check import diff, util
def main():
parser = ArgumentParser(
- description='Extract a list of symbols from a shared library.')
+ description="Extract a list of symbols from a shared library."
+ )
parser.add_argument(
- '--names-only', dest='names_only',
- help='Only print symbol names',
- action='store_true', default=False)
+ "--names-only",
+ dest="names_only",
+ help="Only print symbol names",
+ action="store_true",
+ default=False,
+ )
parser.add_argument(
- '--removed-only', dest='removed_only',
- help='Only print removed symbols',
- action='store_true', default=False)
- parser.add_argument('--only-stdlib-symbols', dest='only_stdlib',
- help="Filter all symbols not related to the stdlib",
- action='store_true', default=False)
- parser.add_argument('--strict', dest='strict',
- help="Exit with a non-zero status if any symbols "
- "differ",
- action='store_true', default=False)
+ "--removed-only",
+ dest="removed_only",
+ help="Only print removed symbols",
+ action="store_true",
+ default=False,
+ )
parser.add_argument(
- '-o', '--output', dest='output',
- help='The output file. stdout is used if not given',
- type=str, action='store', default=None)
+ "--only-stdlib-symbols",
+ dest="only_stdlib",
+ help="Filter all symbols not related to the stdlib",
+ action="store_true",
+ default=False,
+ )
parser.add_argument(
- '--demangle', dest='demangle', action='store_true', default=False)
+ "--strict",
+ dest="strict",
+ help="Exit with a non-zero status if any symbols " "differ",
+ action="store_true",
+ default=False,
+ )
parser.add_argument(
- 'old_syms', metavar='old-syms', type=str,
- help='The file containing the old symbol list or a library')
+ "-o",
+ "--output",
+ dest="output",
+ help="The output file. stdout is used if not given",
+ type=str,
+ action="store",
+ default=None,
+ )
parser.add_argument(
- 'new_syms', metavar='new-syms', type=str,
- help='The file containing the new symbol list or a library')
+ "--demangle", dest="demangle", action="store_true", default=False
+ )
+ parser.add_argument(
+ "old_syms",
+ metavar="old-syms",
+ type=str,
+ help="The file containing the old symbol list or a library",
+ )
+ parser.add_argument(
+ "new_syms",
+ metavar="new-syms",
+ type=str,
+ help="The file containing the new symbol list or a library",
+ )
args = parser.parse_args()
old_syms_list = util.extract_or_load(args.old_syms)
@@ -58,15 +84,16 @@ def main():
if args.removed_only:
added = {}
report, is_break, is_different = diff.report_diff(
- added, removed, changed, names_only=args.names_only,
- demangle=args.demangle)
+ added, removed, changed, names_only=args.names_only, demangle=args.demangle
+ )
if args.output is None:
print(report)
else:
- with open(args.output, 'w') as f:
- f.write(report + '\n')
+ with open(args.output, "w") as f:
+ f.write(report + "\n")
exit_code = 1 if is_break or (args.strict and is_different) else 0
sys.exit(exit_code)
-if __name__ == '__main__':
+
+if __name__ == "__main__":
main()
diff --git a/libcxxabi/test/lit.cfg.py b/libcxxabi/test/lit.cfg.py
index 647464a..ea4a9a7 100644
--- a/libcxxabi/test/lit.cfg.py
+++ b/libcxxabi/test/lit.cfg.py
@@ -7,4 +7,5 @@
lit_config.fatal(
"You seem to be running Lit directly -- you should be running Lit through "
"<build>/bin/llvm-lit, which will ensure that the right Lit configuration "
- "file is used.")
+ "file is used."
+)
diff --git a/libcxxabi/test/native/arm-linux-eabi/lit.local.cfg b/libcxxabi/test/native/arm-linux-eabi/lit.local.cfg
index d12eb20..fd6b8ad 100644
--- a/libcxxabi/test/native/arm-linux-eabi/lit.local.cfg
+++ b/libcxxabi/test/native/arm-linux-eabi/lit.local.cfg
@@ -1,6 +1,9 @@
def is_arm_linux_eabi(triple):
- return ('arm' in triple) and ('linux' in triple) and ('eabi' in triple)
+ return ("arm" in triple) and ("linux" in triple) and ("eabi" in triple)
-is_native = hasattr(config.root, 'target_triple') and (config.root.host_triple == config.root.target_triple)
+
+is_native = hasattr(config.root, "target_triple") and (
+ config.root.host_triple == config.root.target_triple
+)
if not is_native or not is_arm_linux_eabi(config.root.host_triple):
config.unsupported = True
diff --git a/libunwind/docs/conf.py b/libunwind/docs/conf.py
index 307ece60..29f9c24 100644
--- a/libunwind/docs/conf.py
+++ b/libunwind/docs/conf.py
@@ -16,106 +16,106 @@ from datetime import date
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
-#sys.path.insert(0, os.path.abspath('.'))
+# sys.path.insert(0, os.path.abspath('.'))
# -- General configuration -----------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
-#needs_sphinx = '1.0'
+# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['sphinx.ext.intersphinx', 'sphinx.ext.todo']
+extensions = ["sphinx.ext.intersphinx", "sphinx.ext.todo"]
# Add any paths that contain templates here, relative to this directory.
-templates_path = ['_templates']
+templates_path = ["_templates"]
# The suffix of source filenames.
-source_suffix = '.rst'
+source_suffix = ".rst"
# The encoding of source files.
-#source_encoding = 'utf-8-sig'
+# source_encoding = 'utf-8-sig'
# The master toctree document.
-master_doc = 'index'
+master_doc = "index"
# General information about the project.
-project = u'libunwind'
-copyright = u'2011-%d, LLVM Project' % date.today().year
+project = "libunwind"
+copyright = "2011-%d, LLVM Project" % date.today().year
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
-version = '17.0'
+version = "17.0"
# The full version, including alpha/beta/rc tags.
-release = '17.0'
+release = "17.0"
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
-#language = None
+# language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
-#today = ''
+# today = ''
# Else, today_fmt is used as the format for a strftime call.
-today_fmt = '%Y-%m-%d'
+today_fmt = "%Y-%m-%d"
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
-exclude_patterns = ['_build']
+exclude_patterns = ["_build"]
# The reST default role (used for this markup: `text`) to use for all documents.
-#default_role = None
+# default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
-#add_function_parentheses = True
+# add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
-#add_module_names = True
+# add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
show_authors = True
# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'friendly'
+pygments_style = "friendly"
# A list of ignored prefixes for module index sorting.
-#modindex_common_prefix = []
+# modindex_common_prefix = []
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
-html_theme = 'haiku'
+html_theme = "haiku"
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
-#html_theme_options = {}
+# html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
-#html_theme_path = []
+# html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
-#html_title = None
+# html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
-#html_short_title = None
+# html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
-#html_logo = None
+# html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
-#html_favicon = None
+# html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
@@ -124,101 +124,95 @@ html_static_path = []
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
-#html_last_updated_fmt = '%b %d, %Y'
+# html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
-#html_use_smartypants = True
+# html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
-#html_sidebars = {}
+# html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
-#html_additional_pages = {}
+# html_additional_pages = {}
# If false, no module index is generated.
-#html_domain_indices = True
+# html_domain_indices = True
# If false, no index is generated.
-#html_use_index = True
+# html_use_index = True
# If true, the index is split into individual pages for each letter.
-#html_split_index = False
+# html_split_index = False
# If true, links to the reST sources are added to the pages.
-#html_show_sourcelink = True
+# html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
-#html_show_sphinx = True
+# html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
-#html_show_copyright = True
+# html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
-#html_use_opensearch = ''
+# html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
-#html_file_suffix = None
+# html_file_suffix = None
# Output file base name for HTML help builder.
-htmlhelp_basename = 'libunwinddoc'
+htmlhelp_basename = "libunwinddoc"
# -- Options for LaTeX output --------------------------------------------------
latex_elements = {
-# The paper size ('letterpaper' or 'a4paper').
-#'papersize': 'letterpaper',
-
-# The font size ('10pt', '11pt' or '12pt').
-#'pointsize': '10pt',
-
-# Additional stuff for the LaTeX preamble.
-#'preamble': '',
+ # The paper size ('letterpaper' or 'a4paper').
+ #'papersize': 'letterpaper',
+ # The font size ('10pt', '11pt' or '12pt').
+ #'pointsize': '10pt',
+ # Additional stuff for the LaTeX preamble.
+ #'preamble': '',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
- ('contents', 'libunwind.tex', u'libunwind Documentation',
- u'LLVM project', 'manual'),
+ ("contents", "libunwind.tex", "libunwind Documentation", "LLVM project", "manual"),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
-#latex_logo = None
+# latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
-#latex_use_parts = False
+# latex_use_parts = False
# If true, show page references after internal links.
-#latex_show_pagerefs = False
+# latex_show_pagerefs = False
# If true, show URL addresses after external links.
-#latex_show_urls = False
+# latex_show_urls = False
# Documents to append as an appendix to all manuals.
-#latex_appendices = []
+# latex_appendices = []
# If false, no module index is generated.
-#latex_domain_indices = True
+# latex_domain_indices = True
# -- Options for manual page output --------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
-man_pages = [
- ('contents', 'libunwind', u'libunwind Documentation',
- [u'LLVM project'], 1)
-]
+man_pages = [("contents", "libunwind", "libunwind Documentation", ["LLVM project"], 1)]
# If true, show URL addresses after external links.
-#man_show_urls = False
+# man_show_urls = False
# -- Options for Texinfo output ------------------------------------------------
@@ -227,19 +221,25 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
- ('contents', 'libunwind', u'libunwind Documentation',
- u'LLVM project', 'libunwind', 'LLVM Unwinder',
- 'Miscellaneous'),
+ (
+ "contents",
+ "libunwind",
+ "libunwind Documentation",
+ "LLVM project",
+ "libunwind",
+ "LLVM Unwinder",
+ "Miscellaneous",
+ ),
]
# Documents to append as an appendix to all manuals.
-#texinfo_appendices = []
+# texinfo_appendices = []
# If false, no module index is generated.
-#texinfo_domain_indices = True
+# texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
-#texinfo_show_urls = 'footnote'
+# texinfo_show_urls = 'footnote'
# FIXME: Define intersphinx configuration.
diff --git a/libunwind/test/lit.cfg.py b/libunwind/test/lit.cfg.py
index 647464a..ea4a9a7 100644
--- a/libunwind/test/lit.cfg.py
+++ b/libunwind/test/lit.cfg.py
@@ -7,4 +7,5 @@
lit_config.fatal(
"You seem to be running Lit directly -- you should be running Lit through "
"<build>/bin/llvm-lit, which will ensure that the right Lit configuration "
- "file is used.")
+ "file is used."
+)