diff --git a/build/jenkins/pipelines/featuretest.Jenkinsfile b/build/jenkins/pipelines/featuretest.Jenkinsfile new file mode 100644 index 0000000000..83e2275a03 --- /dev/null +++ b/build/jenkins/pipelines/featuretest.Jenkinsfile @@ -0,0 +1,129 @@ +/* Copyright (C) 2025 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +// This pipeline collects the c++ features available + +pipeline { + agent none + + stages { + stage('Linux') { + agent { + dockerfile { + label 'LinuxAgent' + customWorkspace 'workspace/featuretest' + dir 'build/jenkins/dockerfiles' + filename 'debian-12.Dockerfile' + // Prevent Jenkins from running commands with the UID of the host's jenkins user + // https://stackoverflow.com/a/42822143 + args '-u root' + } + } + steps { + sh ''' + echo Linux GCC Features > featuretestresults.txt + echo >> featuretestresults.txt + g++-12 --std=c++20 source/tools/featuretest/featuretest.cpp -o featuretest-linux-gcc + ./featuretest-linux-gcc >> featuretestresults.txt + echo >> featuretestresults.txt + + echo Linux Clang Features >> featuretestresults.txt + echo >> featuretestresults.txt + clang++-14 --std=c++20 source/tools/featuretest/featuretest.cpp -o featuretest-linux-clang + ./featuretest-linux-clang >> featuretestresults.txt + echo >> featuretestresults.txt + ''' + stash(name: 'results', includes: 'featuretestresults.txt') + } + } + stage('FreeBSD') { + agent { + node { + label 'FreeBSDAgent' + customWorkspace 'workspace/featuretest' + } + } + steps { + unstash('results') + sh ''' + echo FreeBSD Clang Features >> featuretestresults.txt + echo >> featuretestresults.txt + clang++ --std=c++20 source/tools/featuretest/featuretest.cpp -o featuretest-freebsd-clang + ./featuretest-freebsd-clang >> featuretestresults.txt + echo >> featuretestresults.txt + ''' + stash(name: 'results', includes: 'featuretestresults.txt') + } + } + stage('macOS') { + agent { + node { + label 'macOSAgentVentura' + customWorkspace 'workspace/featuretest' + } + } + steps { + unstash('results') + sh ''' + echo macOS AppleClang Features >> featuretestresults.txt + echo >> featuretestresults.txt + clang++ --std=c++20 source/tools/featuretest/featuretest.cpp -o featuretest-macos-clang + ./featuretest-macos-clang >> featuretestresults.txt + echo >> featuretestresults.txt + ''' + stash(name: 'results', includes: 'featuretestresults.txt') + } + } + stage('Windows') { + agent { + node { + label 'WindowsAgent' + customWorkspace 'workspace/featuretest' + } + } + steps { + unstash('results') + bat ''' + ECHO Windows MSVC Features>>featuretestresults.txt + ECHO.>>featuretestresults.txt + call "C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Auxiliary\\Build\\vcvars64.bat" + cl.exe /std:c++20 /Zc:__cplusplus /Fe:featuretest-win.exe source\\tools\\featuretest\\featuretest.cpp /link /SUBSYSTEM:CONSOLE + featuretest-win.exe>>featuretestresults.txt + ''' + stash(name: 'results', includes: 'featuretestresults.txt') + } + } + stage('Aggregate') { + agent { + node { + label 'macOSAgentVentura' + customWorkspace 'workspace/featuretest' + } + } + steps { + unstash('results') + sh 'source/tools/featuretest/aggregate.py featuretestresults.txt > featuretestsummary.txt' + archiveArtifacts(artifacts: 'featuretestresults.txt,featuretestsummary.txt') + sshPublisher alwaysPublishFromMaster: true, failOnError: true, publishers: [ + sshPublisherDesc(configName: 'docs.wildfiregames.com', transfers: [ + sshTransfer(sourceFiles: 'featuretest*.txt', remoteDirectory: 'cppfeatures'), + ] + )] + } + } + } +} diff --git a/source/tools/featuretest/aggregate.py b/source/tools/featuretest/aggregate.py new file mode 100755 index 0000000000..8fdb9cad86 --- /dev/null +++ b/source/tools/featuretest/aggregate.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0-or-later + +import sys + + +class Date: + def __init__(self, date): + if date.startswith("-"): + self.year = 0 + self.month = 0 + else: + cols = date.split("-") + self.year = int(cols[0]) + self.month = int(cols[1]) + + def __repr__(self): + return f"{self.year}-{self.month}" + + def __str__(self): + return f"{self.year}-{self.month}" + + def __lt__(self, other): + if self.year < other.year: + return True + return self.year == other.year and self.month < other.month + + def __gt__(self, other): + if self.year > other.year: + return True + return self.year == other.year and self.month > other.month + + +core_features = {} +lib_features = {} +attributes = {} + +with open(sys.argv[1]) as file: + state = "discard" + while line := file.readline(): + # discard + if state == "discard": + if line.startswith(("C++11 CORE", "C++14 CORE", "C++17 CORE", "C++20 CORE")): + collection = core_features + state = "collect" + continue + if line.startswith(("C++11 LIB", "C++14 LIB", "C++17 LIB CORE", "C++20 LIB")): + collection = lib_features + state = "collect" + continue + if line.startswith("ATTRIBUTES"): + collection = attributes + state = "collect" + continue + + # collect + if state == "collect": + if line.rstrip() != "": + cols = line.split() + if (key := cols[0]) in collection: + if Date(cols[1]) < Date(collection[key][0]): + collection[key][0] = cols[1] + if Date(cols[3]) > Date(collection[key][2]): + collection[key][2] = cols[3] + else: + collection[key] = cols[1:] + else: + state = "discard" + + +def print_features(features): + for key, value in sorted(features.items()): + if Date(value[0]) < Date(value[2]): + print(value[0], "<", value[2], key) + elif Date(value[0]) > Date(value[2]): + print(value[0], ">", value[2], key) + else: + print(value[0], "=", value[2], key) + + +print("CORE FEATURES") +print("-------------------------------------------------------------------------------") +print_features(core_features) +print() +print() +print("LIB FEATURES") +print("-------------------------------------------------------------------------------") +print_features(lib_features) +print() +print() +print("ATTRIBUTES (MSVC reports garbage here)") +print("-------------------------------------------------------------------------------") +print_features(attributes) diff --git a/source/tools/featuretest/featuretest.cpp b/source/tools/featuretest/featuretest.cpp new file mode 100644 index 0000000000..33d4daeee3 --- /dev/null +++ b/source/tools/featuretest/featuretest.cpp @@ -0,0 +1,711 @@ +// https://en.cppreference.com/w/cpp/experimental/feature_test.html (fetched 2.11.2025) + +static constexpr struct choose_what_and_how_to_print +{ + constexpr static int longest_macro_name { 45 }; + constexpr static bool titles = 1; + constexpr static bool counters = 1; + constexpr static bool attributes = 1; + constexpr static bool standard_values = 1; + constexpr static bool compiler_specific = 1; + constexpr static bool core_features = 1; + constexpr static bool lib_features = 1; + constexpr static bool supported_features = 1; + constexpr static bool unsupported_features = 1; + constexpr static bool sort_by_date = 0; + constexpr static bool separate_year_month = 1; + constexpr static bool separated_revisions = 1; + constexpr static bool latest_revisions = 1; + constexpr static bool cxx98 = 0; + constexpr static bool cxx11 = 1; + constexpr static bool cxx14 = 1; + constexpr static bool cxx17 = 1; + constexpr static bool cxx20 = 1; + constexpr static bool cxx23 = 1; + constexpr static bool cxx26 = 1; + constexpr static bool cxx29 = 0; +} print; + +#if __cplusplus < 201100 +# error "C++11 or better is required" +#endif + +#include +#include +#include +#include +#include + +#ifdef __has_include +# if __has_include() +# include +# endif +# if __has_include() +# include +# endif +#endif + +// Expect a string that starts with 6-decimal-digits or with '_' (if unsupported) +#define COMPILER_VALUE_INT(n) #n [0] == '_' ? 0 : \ + (#n[5] - '0') + (#n[4] - '0') * 10 + (#n[3] - '0') * 100 + \ + (#n[2] - '0') * 1000 + (#n[1] - '0') * 10000 + (#n[0] - '0') * 100000 +#define COMPILER_FEATURE_ENTRY(expect, name) { #name, COMPILER_VALUE_INT(name), expect }, + +#if defined(__has_cpp_attribute) && defined(__GNUG__) +# define COMPILER_ATTRIBUTE(expect, name) { #name, __has_cpp_attribute(name), expect }, +#else +# define COMPILER_ATTRIBUTE(expect, name) { #name, COMPILER_VALUE_INT(name), expect }, +#endif + +#define COMPILER_SPECIFIC_STRING(value) #value +#define COMPILER_SPECIFIC_ENTRY(name) { #name, COMPILER_SPECIFIC_STRING(name) }, + +class CompilerFeature +{ + char const* name_; long data_; long std_; +public: + constexpr CompilerFeature(char const* name, long data, long std) + : name_(name), data_(data), std_(std) {} + constexpr CompilerFeature(CompilerFeature const&) = default; + CompilerFeature& operator=(CompilerFeature const&) = default; + bool operator<(CompilerFeature const& rhs) const + { return std::strcmp(name_, rhs.name_) < 0; } + bool operator==(CompilerFeature const& rhs) const + { return std::strcmp(name_, rhs.name_) == 0; } + constexpr bool supported() const { return data_ >= std_; } + constexpr bool maybe() const { return data_ > 0; } + constexpr char const* name() const { return name_; } + constexpr long std() const { return std_; } + constexpr long data() const { return data_; } + void data(long x) { data_ = x; } +}; + +// Non-FTM macros, including implementation specific ones: +static /*constexpr*/ std::pair compiler[] = { + COMPILER_SPECIFIC_ENTRY(__cplusplus) + COMPILER_SPECIFIC_ENTRY(__clang_major__) + COMPILER_SPECIFIC_ENTRY(__clang_minor__) + COMPILER_SPECIFIC_ENTRY(__clang_patchlevel__) + COMPILER_SPECIFIC_ENTRY(__GNUG__) + COMPILER_SPECIFIC_ENTRY(__GNUC_MINOR__) + COMPILER_SPECIFIC_ENTRY(__GNUC_PATCHLEVEL__) + // Optional fixed width floating-point types (C++23) + COMPILER_SPECIFIC_ENTRY(__STDCPP_FLOAT16_T__) + COMPILER_SPECIFIC_ENTRY(__STDCPP_FLOAT32_T__) + COMPILER_SPECIFIC_ENTRY(__STDCPP_FLOAT64_T__) + COMPILER_SPECIFIC_ENTRY(__STDCPP_FLOAT128_T__) + COMPILER_SPECIFIC_ENTRY(__STDCPP_BFLOAT16_T__) + // C23 => C++26 + COMPILER_SPECIFIC_ENTRY(__STDC_ENDIAN_BIG__) + COMPILER_SPECIFIC_ENTRY(__STDC_ENDIAN_LITTLE__) + COMPILER_SPECIFIC_ENTRY(__STDC_ENDIAN_NATIVE__) + COMPILER_SPECIFIC_ENTRY(__STDC_VERSION_STDBIT_H__) + COMPILER_SPECIFIC_ENTRY(__STDC_VERSION_STDCKDINT_H__) + // Add your favorite implementation specific macros... + COMPILER_SPECIFIC_ENTRY(__STDCPP_DEFAULT_NEW_ALIGNMENT__) + COMPILER_SPECIFIC_ENTRY(__STDCPP_THREADS__) + COMPILER_SPECIFIC_ENTRY(__STDCPP_STRICT_POINTER_SAFETY__) + COMPILER_SPECIFIC_ENTRY(__STDC_EMBED_NOT_FOUND__) + COMPILER_SPECIFIC_ENTRY(__STDC_EMBED_FOUND__) + COMPILER_SPECIFIC_ENTRY(__STDC_EMBED_EMPTY__) + COMPILER_SPECIFIC_ENTRY(__STDC__) + COMPILER_SPECIFIC_ENTRY(__STDC_VERSION__) + COMPILER_SPECIFIC_ENTRY(__STDC_HOSTED__) + COMPILER_SPECIFIC_ENTRY(__STDC_ISO_10646__) + COMPILER_SPECIFIC_ENTRY(__STDC_MB_MIGHT_NEQ_WC__) + COMPILER_SPECIFIC_ENTRY(__DATE__) + COMPILER_SPECIFIC_ENTRY(__TIME__) +}; + +static constexpr CompilerFeature cxx98_core[] = { + COMPILER_FEATURE_ENTRY(199711L, __cpp_exceptions) + COMPILER_FEATURE_ENTRY(199711L, __cpp_rtti) +}; + +static constexpr CompilerFeature cxx11_core[] = { + COMPILER_FEATURE_ENTRY(200704L, __cpp_alias_templates) + COMPILER_FEATURE_ENTRY(200809L, __cpp_attributes) + COMPILER_FEATURE_ENTRY(200704L, __cpp_constexpr) + COMPILER_FEATURE_ENTRY(201711L, __cpp_constexpr_in_decltype) + COMPILER_FEATURE_ENTRY(200707L, __cpp_decltype) + COMPILER_FEATURE_ENTRY(200604L, __cpp_delegating_constructors) + COMPILER_FEATURE_ENTRY(201511L, __cpp_inheriting_constructors) + COMPILER_FEATURE_ENTRY(200806L, __cpp_initializer_lists) + COMPILER_FEATURE_ENTRY(200907L, __cpp_lambdas) + COMPILER_FEATURE_ENTRY(200809L, __cpp_nsdmi) + COMPILER_FEATURE_ENTRY(200907L, __cpp_range_based_for) + COMPILER_FEATURE_ENTRY(200710L, __cpp_raw_strings) + COMPILER_FEATURE_ENTRY(200710L, __cpp_ref_qualifiers) + COMPILER_FEATURE_ENTRY(200610L, __cpp_rvalue_references) + COMPILER_FEATURE_ENTRY(200410L, __cpp_static_assert) + COMPILER_FEATURE_ENTRY(200806L, __cpp_threadsafe_static_init) + COMPILER_FEATURE_ENTRY(200704L, __cpp_unicode_characters) + COMPILER_FEATURE_ENTRY(200710L, __cpp_unicode_literals) + COMPILER_FEATURE_ENTRY(200809L, __cpp_user_defined_literals) + COMPILER_FEATURE_ENTRY(200704L, __cpp_variadic_templates) +}; + +static constexpr CompilerFeature cxx14_core[] = { + COMPILER_FEATURE_ENTRY(201304L, __cpp_aggregate_nsdmi) + COMPILER_FEATURE_ENTRY(201304L, __cpp_binary_literals) + COMPILER_FEATURE_ENTRY(201304L, __cpp_constexpr) + COMPILER_FEATURE_ENTRY(201304L, __cpp_decltype_auto) + COMPILER_FEATURE_ENTRY(201304L, __cpp_generic_lambdas) + COMPILER_FEATURE_ENTRY(201304L, __cpp_init_captures) + COMPILER_FEATURE_ENTRY(201304L, __cpp_return_type_deduction) + COMPILER_FEATURE_ENTRY(201309L, __cpp_sized_deallocation) + COMPILER_FEATURE_ENTRY(201304L, __cpp_variable_templates) +}; +static constexpr CompilerFeature cxx14_lib[] = { + COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_chrono_udls) + COMPILER_FEATURE_ENTRY(201309L, __cpp_lib_complex_udls) + COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_exchange_function) + COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_generic_associative_lookup) + COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_integer_sequence) + COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_integral_constant_callable) + COMPILER_FEATURE_ENTRY(201402L, __cpp_lib_is_final) + COMPILER_FEATURE_ENTRY(201309L, __cpp_lib_is_null_pointer) + COMPILER_FEATURE_ENTRY(201402L, __cpp_lib_make_reverse_iterator) + COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_make_unique) + COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_null_iterators) + COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_quoted_string_io) + COMPILER_FEATURE_ENTRY(201210L, __cpp_lib_result_of_sfinae) + COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_robust_nonmodifying_seq_ops) + COMPILER_FEATURE_ENTRY(201402L, __cpp_lib_shared_timed_mutex) + COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_string_udls) + COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_transformation_trait_aliases) + COMPILER_FEATURE_ENTRY(201210L, __cpp_lib_transparent_operators) + COMPILER_FEATURE_ENTRY(201402L, __cpp_lib_tuple_element_t) + COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_tuples_by_type) +}; + +static constexpr CompilerFeature cxx17_core[] = { + COMPILER_FEATURE_ENTRY(201603L, __cpp_aggregate_bases) + COMPILER_FEATURE_ENTRY(201606L, __cpp_aligned_new) + COMPILER_FEATURE_ENTRY(201603L, __cpp_capture_star_this) + COMPILER_FEATURE_ENTRY(201603L, __cpp_constexpr) + COMPILER_FEATURE_ENTRY(201703L, __cpp_deduction_guides) + COMPILER_FEATURE_ENTRY(201411L, __cpp_enumerator_attributes) + COMPILER_FEATURE_ENTRY(201603L, __cpp_fold_expressions) + COMPILER_FEATURE_ENTRY(201606L, __cpp_guaranteed_copy_elision) + COMPILER_FEATURE_ENTRY(201603L, __cpp_hex_float) + COMPILER_FEATURE_ENTRY(201606L, __cpp_if_constexpr) + COMPILER_FEATURE_ENTRY(201606L, __cpp_inline_variables) + COMPILER_FEATURE_ENTRY(201411L, __cpp_namespace_attributes) + COMPILER_FEATURE_ENTRY(201510L, __cpp_noexcept_function_type) + COMPILER_FEATURE_ENTRY(201411L, __cpp_nontype_template_args) + COMPILER_FEATURE_ENTRY(201606L, __cpp_nontype_template_parameter_auto) + COMPILER_FEATURE_ENTRY(201603L, __cpp_range_based_for) + COMPILER_FEATURE_ENTRY(201411L, __cpp_static_assert) + COMPILER_FEATURE_ENTRY(201606L, __cpp_structured_bindings) + COMPILER_FEATURE_ENTRY(201611L, __cpp_template_template_args) + COMPILER_FEATURE_ENTRY(201611L, __cpp_variadic_using) +}; +static constexpr CompilerFeature cxx17_lib[] = { + COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_addressof_constexpr) + COMPILER_FEATURE_ENTRY(201411L, __cpp_lib_allocator_traits_is_always_equal) + COMPILER_FEATURE_ENTRY(201606L, __cpp_lib_any) + COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_apply) + COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_array_constexpr) + COMPILER_FEATURE_ENTRY(201510L, __cpp_lib_as_const) + COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_atomic_is_always_lock_free) + COMPILER_FEATURE_ENTRY(201505L, __cpp_lib_bool_constant) + COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_boyer_moore_searcher) + COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_byte) + COMPILER_FEATURE_ENTRY(201611L, __cpp_lib_chrono) + COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_clamp) + COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_enable_shared_from_this) + COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_execution) + COMPILER_FEATURE_ENTRY(201703L, __cpp_lib_filesystem) + COMPILER_FEATURE_ENTRY(201606L, __cpp_lib_gcd_lcm) + COMPILER_FEATURE_ENTRY(201703L, __cpp_lib_hardware_interference_size) + COMPILER_FEATURE_ENTRY(201606L, __cpp_lib_has_unique_object_representations) + COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_hypot) + COMPILER_FEATURE_ENTRY(201505L, __cpp_lib_incomplete_container_elements) + COMPILER_FEATURE_ENTRY(201411L, __cpp_lib_invoke) + COMPILER_FEATURE_ENTRY(201703L, __cpp_lib_is_aggregate) + COMPILER_FEATURE_ENTRY(201703L, __cpp_lib_is_invocable) + COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_is_swappable) + COMPILER_FEATURE_ENTRY(201606L, __cpp_lib_launder) + COMPILER_FEATURE_ENTRY(201510L, __cpp_lib_logical_traits) + COMPILER_FEATURE_ENTRY(201606L, __cpp_lib_make_from_tuple) + COMPILER_FEATURE_ENTRY(201411L, __cpp_lib_map_try_emplace) + COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_math_special_functions) + COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_memory_resource) + COMPILER_FEATURE_ENTRY(201606L, __cpp_lib_node_extract) + COMPILER_FEATURE_ENTRY(201411L, __cpp_lib_nonmember_container_access) + COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_not_fn) + COMPILER_FEATURE_ENTRY(201606L, __cpp_lib_optional) + COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_parallel_algorithm) + COMPILER_FEATURE_ENTRY(201606L, __cpp_lib_raw_memory_algorithms) + COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_sample) + COMPILER_FEATURE_ENTRY(201703L, __cpp_lib_scoped_lock) + COMPILER_FEATURE_ENTRY(201505L, __cpp_lib_shared_mutex) + COMPILER_FEATURE_ENTRY(201611L, __cpp_lib_shared_ptr_arrays) + COMPILER_FEATURE_ENTRY(201606L, __cpp_lib_shared_ptr_weak_type) + COMPILER_FEATURE_ENTRY(201606L, __cpp_lib_string_view) + COMPILER_FEATURE_ENTRY(201611L, __cpp_lib_to_chars) + COMPILER_FEATURE_ENTRY(201510L, __cpp_lib_transparent_operators) + COMPILER_FEATURE_ENTRY(201510L, __cpp_lib_type_trait_variable_templates) + COMPILER_FEATURE_ENTRY(201411L, __cpp_lib_uncaught_exceptions) + COMPILER_FEATURE_ENTRY(201411L, __cpp_lib_unordered_map_try_emplace) + COMPILER_FEATURE_ENTRY(202102L, __cpp_lib_variant) + COMPILER_FEATURE_ENTRY(201411L, __cpp_lib_void_t) +}; + +static constexpr CompilerFeature cxx20_core[] = { + COMPILER_FEATURE_ENTRY(201902L, __cpp_aggregate_paren_init) + COMPILER_FEATURE_ENTRY(202207L, __cpp_char8_t) + COMPILER_FEATURE_ENTRY(202002L, __cpp_concepts) + COMPILER_FEATURE_ENTRY(201806L, __cpp_conditional_explicit) + COMPILER_FEATURE_ENTRY(202211L, __cpp_consteval) + COMPILER_FEATURE_ENTRY(202002L, __cpp_constexpr) + COMPILER_FEATURE_ENTRY(201907L, __cpp_constexpr_dynamic_alloc) + COMPILER_FEATURE_ENTRY(201907L, __cpp_constinit) + COMPILER_FEATURE_ENTRY(201907L, __cpp_deduction_guides) + COMPILER_FEATURE_ENTRY(201707L, __cpp_designated_initializers) + COMPILER_FEATURE_ENTRY(201707L, __cpp_generic_lambdas) + COMPILER_FEATURE_ENTRY(201902L, __cpp_impl_coroutine) + COMPILER_FEATURE_ENTRY(201806L, __cpp_impl_destroying_delete) + COMPILER_FEATURE_ENTRY(201907L, __cpp_impl_three_way_comparison) + COMPILER_FEATURE_ENTRY(201803L, __cpp_init_captures) + COMPILER_FEATURE_ENTRY(201907L, __cpp_modules) + COMPILER_FEATURE_ENTRY(201911L, __cpp_nontype_template_args) + COMPILER_FEATURE_ENTRY(201907L, __cpp_using_enum) +}; +static constexpr CompilerFeature cxx20_lib[] = { + COMPILER_FEATURE_ENTRY(201811L, __cpp_lib_array_constexpr) + COMPILER_FEATURE_ENTRY(201811L, __cpp_lib_assume_aligned) + COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_atomic_flag_test) + COMPILER_FEATURE_ENTRY(201711L, __cpp_lib_atomic_float) + COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_atomic_lock_free_type_aliases) + COMPILER_FEATURE_ENTRY(201806L, __cpp_lib_atomic_ref) + COMPILER_FEATURE_ENTRY(201711L, __cpp_lib_atomic_shared_ptr) + COMPILER_FEATURE_ENTRY(201911L, __cpp_lib_atomic_value_initialization) + COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_atomic_wait) + COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_barrier) + COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_bind_front) + COMPILER_FEATURE_ENTRY(201806L, __cpp_lib_bit_cast) + COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_bitops) + COMPILER_FEATURE_ENTRY(201902L, __cpp_lib_bounded_array_traits) + COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_char8_t) + COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_chrono) + COMPILER_FEATURE_ENTRY(202002L, __cpp_lib_concepts) + COMPILER_FEATURE_ENTRY(201806L, __cpp_lib_constexpr_algorithms) + COMPILER_FEATURE_ENTRY(201711L, __cpp_lib_constexpr_complex) + COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_constexpr_dynamic_alloc) + COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_constexpr_functional) + COMPILER_FEATURE_ENTRY(201811L, __cpp_lib_constexpr_iterator) + COMPILER_FEATURE_ENTRY(201811L, __cpp_lib_constexpr_memory) + COMPILER_FEATURE_ENTRY(201911L, __cpp_lib_constexpr_numeric) + COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_constexpr_string) + COMPILER_FEATURE_ENTRY(201811L, __cpp_lib_constexpr_string_view) + COMPILER_FEATURE_ENTRY(201811L, __cpp_lib_constexpr_tuple) + COMPILER_FEATURE_ENTRY(201811L, __cpp_lib_constexpr_utility) + COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_constexpr_vector) + COMPILER_FEATURE_ENTRY(201902L, __cpp_lib_coroutine) + COMPILER_FEATURE_ENTRY(201806L, __cpp_lib_destroying_delete) + COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_endian) + COMPILER_FEATURE_ENTRY(202002L, __cpp_lib_erase_if) + COMPILER_FEATURE_ENTRY(201902L, __cpp_lib_execution) + COMPILER_FEATURE_ENTRY(202110L, __cpp_lib_format) + COMPILER_FEATURE_ENTRY(201811L, __cpp_lib_generic_unordered_lookup) + COMPILER_FEATURE_ENTRY(202002L, __cpp_lib_int_pow2) + COMPILER_FEATURE_ENTRY(202002L, __cpp_lib_integer_comparison_functions) + COMPILER_FEATURE_ENTRY(201902L, __cpp_lib_interpolate) + COMPILER_FEATURE_ENTRY(201811L, __cpp_lib_is_constant_evaluated) + COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_is_layout_compatible) + COMPILER_FEATURE_ENTRY(201806L, __cpp_lib_is_nothrow_convertible) + COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_is_pointer_interconvertible) + COMPILER_FEATURE_ENTRY(201911L, __cpp_lib_jthread) + COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_latch) + COMPILER_FEATURE_ENTRY(201806L, __cpp_lib_list_remove_return_type) + COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_math_constants) + COMPILER_FEATURE_ENTRY(202106L, __cpp_lib_optional) + COMPILER_FEATURE_ENTRY(201902L, __cpp_lib_polymorphic_allocator) + COMPILER_FEATURE_ENTRY(202110L, __cpp_lib_ranges) + COMPILER_FEATURE_ENTRY(201711L, __cpp_lib_remove_cvref) + COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_semaphore) + COMPILER_FEATURE_ENTRY(201707L, __cpp_lib_shared_ptr_arrays) + COMPILER_FEATURE_ENTRY(201806L, __cpp_lib_shift) + COMPILER_FEATURE_ENTRY(202002L, __cpp_lib_smart_ptr_for_overwrite) + COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_source_location) + COMPILER_FEATURE_ENTRY(202002L, __cpp_lib_span) + COMPILER_FEATURE_ENTRY(201902L, __cpp_lib_ssize) + COMPILER_FEATURE_ENTRY(201711L, __cpp_lib_starts_ends_with) + COMPILER_FEATURE_ENTRY(201803L, __cpp_lib_string_view) + COMPILER_FEATURE_ENTRY(201803L, __cpp_lib_syncbuf) + COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_three_way_comparison) + COMPILER_FEATURE_ENTRY(201711L, __cpp_lib_to_address) + COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_to_array) + COMPILER_FEATURE_ENTRY(201806L, __cpp_lib_type_identity) + COMPILER_FEATURE_ENTRY(201811L, __cpp_lib_unwrap_ref) + COMPILER_FEATURE_ENTRY(202106L, __cpp_lib_variant) +}; + +static constexpr CompilerFeature cxx23_core[] = { + COMPILER_FEATURE_ENTRY(202110L, __cpp_auto_cast) + COMPILER_FEATURE_ENTRY(202211L, __cpp_constexpr) + COMPILER_FEATURE_ENTRY(202110L, __cpp_explicit_this_parameter) + COMPILER_FEATURE_ENTRY(202106L, __cpp_if_consteval) + COMPILER_FEATURE_ENTRY(202207L, __cpp_implicit_move) + COMPILER_FEATURE_ENTRY(202211L, __cpp_multidimensional_subscript) + COMPILER_FEATURE_ENTRY(202207L, __cpp_named_character_escapes) + COMPILER_FEATURE_ENTRY(202211L, __cpp_range_based_for) + COMPILER_FEATURE_ENTRY(202011L, __cpp_size_t_suffix) + COMPILER_FEATURE_ENTRY(202207L, __cpp_static_call_operator) +}; +static constexpr CompilerFeature cxx23_lib[] = { + COMPILER_FEATURE_ENTRY(202106L, __cpp_lib_adaptor_iterator_pair_constructor) + COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_algorithm_iterator_requirements) + COMPILER_FEATURE_ENTRY(202302L, __cpp_lib_allocate_at_least) + COMPILER_FEATURE_ENTRY(202110L, __cpp_lib_associative_heterogeneous_erasure) + COMPILER_FEATURE_ENTRY(202302L, __cpp_lib_barrier) + COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_bind_back) + COMPILER_FEATURE_ENTRY(202110L, __cpp_lib_byteswap) + COMPILER_FEATURE_ENTRY(202302L, __cpp_lib_common_reference) + COMPILER_FEATURE_ENTRY(202302L, __cpp_lib_common_reference_wrapper) + COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_concepts) + COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_constexpr_bitset) + COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_constexpr_charconv) + COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_constexpr_cmath) + COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_constexpr_memory) + COMPILER_FEATURE_ENTRY(202106L, __cpp_lib_constexpr_typeinfo) + COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_containers_ranges) + COMPILER_FEATURE_ENTRY(202211L, __cpp_lib_expected) + COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_flat_map) + COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_flat_set) + COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_format) + COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_format_ranges) + COMPILER_FEATURE_ENTRY(202302L, __cpp_lib_formatters) + COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_forward_like) + COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_generator) + COMPILER_FEATURE_ENTRY(202106L, __cpp_lib_invoke_r) + COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_ios_noreplace) + COMPILER_FEATURE_ENTRY(202302L, __cpp_lib_is_implicit_lifetime) + COMPILER_FEATURE_ENTRY(202011L, __cpp_lib_is_scoped_enum) + COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_mdspan) + COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_modules) + COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_move_iterator_concept) + COMPILER_FEATURE_ENTRY(202110L, __cpp_lib_move_only_function) + COMPILER_FEATURE_ENTRY(202110L, __cpp_lib_optional) + COMPILER_FEATURE_ENTRY(202106L, __cpp_lib_out_ptr) + COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_print) + COMPILER_FEATURE_ENTRY(202302L, __cpp_lib_ranges) + COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_ranges_as_const) + COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_ranges_as_rvalue) + COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_ranges_cartesian_product) + COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_ranges_chunk) + COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_ranges_chunk_by) + COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_ranges_contains) + COMPILER_FEATURE_ENTRY(202302L, __cpp_lib_ranges_enumerate) + COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_ranges_find_last) + COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_ranges_fold) + COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_ranges_iota) + COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_ranges_join_with) + COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_ranges_repeat) + COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_ranges_slide) + COMPILER_FEATURE_ENTRY(202106L, __cpp_lib_ranges_starts_ends_with) + COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_ranges_stride) + COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_ranges_to_container) + COMPILER_FEATURE_ENTRY(202110L, __cpp_lib_ranges_zip) + COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_reference_from_temporary) + COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_shift) + COMPILER_FEATURE_ENTRY(202106L, __cpp_lib_spanstream) + COMPILER_FEATURE_ENTRY(202011L, __cpp_lib_stacktrace) + COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_start_lifetime_as) + COMPILER_FEATURE_ENTRY(202011L, __cpp_lib_stdatomic_h) + COMPILER_FEATURE_ENTRY(202011L, __cpp_lib_string_contains) + COMPILER_FEATURE_ENTRY(202110L, __cpp_lib_string_resize_and_overwrite) + COMPILER_FEATURE_ENTRY(202102L, __cpp_lib_to_underlying) + COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_tuple_like) + COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_unreachable) +}; + +static constexpr CompilerFeature cxx26_core[] = { + //< Continue to Populate + COMPILER_FEATURE_ENTRY(202406L, __cpp_constexpr) + COMPILER_FEATURE_ENTRY(202411L, __cpp_constexpr_exceptions) + COMPILER_FEATURE_ENTRY(202502L, __cpp_contracts) + COMPILER_FEATURE_ENTRY(202403L, __cpp_deleted_function) + COMPILER_FEATURE_ENTRY(202406L, __cpp_fold_expressions) + COMPILER_FEATURE_ENTRY(202311L, __cpp_pack_indexing) + COMPILER_FEATURE_ENTRY(202306L, __cpp_placeholder_variables) + COMPILER_FEATURE_ENTRY(202502L, __cpp_pp_embed) + COMPILER_FEATURE_ENTRY(202306L, __cpp_static_assert) + COMPILER_FEATURE_ENTRY(202411L, __cpp_structured_bindings) + COMPILER_FEATURE_ENTRY(202502L, __cpp_template_parameters) + COMPILER_FEATURE_ENTRY(202502L, __cpp_trivial_relocatability) + COMPILER_FEATURE_ENTRY(202502L, __cpp_trivial_union) + COMPILER_FEATURE_ENTRY(202403L, __cpp_variadic_friend) +}; +static constexpr CompilerFeature cxx26_lib[] = { + //< Continue to Populate + COMPILER_FEATURE_ENTRY(202403L, __cpp_lib_algorithm_default_value_type) + COMPILER_FEATURE_ENTRY(202411L, __cpp_lib_aligned_accessor) + COMPILER_FEATURE_ENTRY(202311L, __cpp_lib_associative_heterogeneous_insertion) + COMPILER_FEATURE_ENTRY(202403L, __cpp_lib_atomic_min_max) + COMPILER_FEATURE_ENTRY(202411L, __cpp_lib_atomic_ref) + COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_bind_back) + COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_bind_front) + COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_bitset) + COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_chrono) + COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_constexpr_algorithms) + COMPILER_FEATURE_ENTRY(202411L, __cpp_lib_constexpr_atomic) + COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_constexpr_cmath) + COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_constexpr_complex) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_constexpr_deque) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_constexpr_exceptions) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_constexpr_flat_map) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_constexpr_flat_set) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_constexpr_forward_list) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_constexpr_inplace_vector) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_constexpr_list) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_constexpr_map) + COMPILER_FEATURE_ENTRY(202406L, __cpp_lib_constexpr_new) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_constexpr_queue) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_constexpr_set) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_constexpr_stack) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_constexpr_unordered_map) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_constexpr_unordered_set) + COMPILER_FEATURE_ENTRY(202411L, __cpp_lib_constrained_equality) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_contracts) + COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_copyable_function) + COMPILER_FEATURE_ENTRY(202403L, __cpp_lib_debugging) + COMPILER_FEATURE_ENTRY(202311L, __cpp_lib_format) + COMPILER_FEATURE_ENTRY(202403L, __cpp_lib_format_path) + COMPILER_FEATURE_ENTRY(202311L, __cpp_lib_format_uchar) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_freestanding_algorithm) + COMPILER_FEATURE_ENTRY(202311L, __cpp_lib_freestanding_array) + COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_freestanding_char_traits) + COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_freestanding_charconv) + COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_freestanding_cstdlib) + COMPILER_FEATURE_ENTRY(202311L, __cpp_lib_freestanding_cstring) + COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_freestanding_cwchar) + COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_freestanding_errc) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_freestanding_execution) + COMPILER_FEATURE_ENTRY(202311L, __cpp_lib_freestanding_expected) + COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_freestanding_feature_test_macros) + COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_freestanding_functional) + COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_freestanding_iterator) + COMPILER_FEATURE_ENTRY(202311L, __cpp_lib_freestanding_mdspan) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_freestanding_memory) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_freestanding_numeric) + COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_freestanding_operator_new) + COMPILER_FEATURE_ENTRY(202311L, __cpp_lib_freestanding_optional) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_freestanding_random) + COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_freestanding_ranges) + COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_freestanding_ratio) + COMPILER_FEATURE_ENTRY(202311L, __cpp_lib_freestanding_string_view) + COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_freestanding_tuple) + COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_freestanding_utility) + COMPILER_FEATURE_ENTRY(202311L, __cpp_lib_freestanding_variant) + COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_fstream_native_handle) + COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_function_ref) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_hardened_array) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_hardened_basic_string) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_hardened_basic_string_view) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_hardened_bitset) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_hardened_deque) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_hardened_expected) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_hardened_forward_list) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_hardened_inplace_vector) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_hardened_list) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_hardened_mdspan) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_hardened_optional) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_hardened_span) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_hardened_valarray) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_hardened_vector) + COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_hazard_pointer) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_hive) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_indirect) + COMPILER_FEATURE_ENTRY(202406L, __cpp_lib_inplace_vector) + COMPILER_FEATURE_ENTRY(202411L, __cpp_lib_is_sufficiently_aligned) + COMPILER_FEATURE_ENTRY(202406L, __cpp_lib_is_virtual_base_of) + COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_is_within_lifetime) + COMPILER_FEATURE_ENTRY(202311L, __cpp_lib_linalg) + COMPILER_FEATURE_ENTRY(202406L, __cpp_lib_mdspan) + COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_not_fn) + COMPILER_FEATURE_ENTRY(202406L, __cpp_lib_optional_range_support) + COMPILER_FEATURE_ENTRY(202311L, __cpp_lib_out_ptr) + COMPILER_FEATURE_ENTRY(202406L, __cpp_lib_philox_engine) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_polymorphic) + COMPILER_FEATURE_ENTRY(202403L, __cpp_lib_print) + COMPILER_FEATURE_ENTRY(202406L, __cpp_lib_ranges) + COMPILER_FEATURE_ENTRY(202311L, __cpp_lib_ranges_as_const) + COMPILER_FEATURE_ENTRY(202411L, __cpp_lib_ranges_cache_latest) + COMPILER_FEATURE_ENTRY(202403L, __cpp_lib_ranges_concat) + COMPILER_FEATURE_ENTRY(202403L, __cpp_lib_ranges_generate_random) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_ranges_reserve_hint) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_ranges_to_input) + COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_ratio) + COMPILER_FEATURE_ENTRY(202411L, __cpp_lib_raw_memory_algorithms) + COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_rcu) + COMPILER_FEATURE_ENTRY(202403L, __cpp_lib_reference_wrapper) + COMPILER_FEATURE_ENTRY(202311L, __cpp_lib_saturation_arithmetic) + COMPILER_FEATURE_ENTRY(202406L, __cpp_lib_senders) + COMPILER_FEATURE_ENTRY(202411L, __cpp_lib_simd) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_simd_complex) + COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_smart_ptr_owner_equality) + COMPILER_FEATURE_ENTRY(202311L, __cpp_lib_span) + COMPILER_FEATURE_ENTRY(202311L, __cpp_lib_span_initializer_list) + COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_sstream_from_string_view) + COMPILER_FEATURE_ENTRY(202403L, __cpp_lib_string_view) + COMPILER_FEATURE_ENTRY(202403L, __cpp_lib_submdspan) + COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_text_encoding) + COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_to_chars) + COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_to_string) + COMPILER_FEATURE_ENTRY(202502L, __cpp_lib_trivially_relocatable) + COMPILER_FEATURE_ENTRY(202311L, __cpp_lib_tuple_like) + COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_variant) +}; + +static constexpr CompilerFeature cxx29_core[] = { + //< Continue to Populate + COMPILER_FEATURE_ENTRY(202604L, __cpp_core_TODO) +}; +static constexpr CompilerFeature cxx29_lib[] = { + //< Continue to Populate + COMPILER_FEATURE_ENTRY(202604L, __cpp_lib_TODO) +}; + +static constexpr CompilerFeature attributes[] = { + COMPILER_ATTRIBUTE(202207L, assume) + COMPILER_ATTRIBUTE(200809L, carries_dependency) + COMPILER_ATTRIBUTE(201309L, deprecated) + COMPILER_ATTRIBUTE(201603L, fallthrough) + COMPILER_ATTRIBUTE(202403L, indeterminate) + COMPILER_ATTRIBUTE(201803L, likely) + COMPILER_ATTRIBUTE(201603L, maybe_unused) + COMPILER_ATTRIBUTE(201803L, no_unique_address) + COMPILER_ATTRIBUTE(201907L, nodiscard) + COMPILER_ATTRIBUTE(200809L, noreturn) + COMPILER_ATTRIBUTE(201803L, unlikely) +}; + +inline void show_compiler_specific_info() +{ + std::printf("OTHER MACROS:\n"); + for (auto co : compiler) + if (std::strcmp(co.first, co.second)) + std::printf("%*s %s\n", -print.longest_macro_name, co.first, co.second); +} + +inline void print_compiler_feature(const CompilerFeature& x) +{ + if (not ((print.supported_features and x.maybe()) or + (print.unsupported_features and not x.maybe()))) + return; + auto print_year_month = [](long n) + { + return std::printf("%ld%s%02ld", + n / 100, print.separate_year_month ? "-" : "", n % 100); + }; + std::printf("%*s ", -print.longest_macro_name, x.name()); + x.maybe() ? print_year_month(x.data()) : + std::printf("------%s", print.separate_year_month ? "-" : ""); + if (print.standard_values) + std::printf(" %c ", (x.supported() ? (x.data() > x.std() ? '>' : '=') : '<')), + print_year_month(x.std()); + std::puts(""); +} + +template +inline void show(char const* const title, Container const& co) +{ + if (print.titles) + { + std::printf("%-s (", title); + if (print.counters) + { + std::printf("%zd/", std::count_if(std::begin(co), std::end(co), + [](CompilerFeature x) + { + return x.supported(); + })); + } + std::printf("%td)\n", std::distance(std::begin(co), std::end(co))); + } + if (print.sort_by_date) + { + std::vector v(std::begin(co), std::end(co)); + std::stable_sort(v.begin(), v.end(), + [](CompilerFeature const& lhs, CompilerFeature const& rhs) + { + return lhs.data() < rhs.data(); + }); + std::for_each(v.cbegin(), v.cend(), print_compiler_feature); + } + else + std::for_each(std::begin(co), std::end(co), print_compiler_feature); + std::puts(""); +} + +inline void show_latest() +{ + auto latest_rev = []() -> int + { + return print.cxx29 ? 29 : print.cxx26 ? 26 : print.cxx23 ? 23 : print.cxx20 ? 20 : + print.cxx17 ? 17 : print.cxx14 ? 14 : print.cxx11 ? 11 : 98; + }; + std::vector latest; + auto add = [&latest](CompilerFeature x) + { + auto i = std::lower_bound(latest.begin(), latest.end(), x); + if (i == latest.end() or not (*i == x)) + latest.insert(i, x); + else if (i->data() < x.data()) + i->data(x.data()); + }; + char text[64]; + latest.reserve(512); // max macros + if (print.core_features) + { // preserve reverse revision insertion order! + if (print.cxx29) std::for_each(std::begin(cxx29_core), std::end(cxx29_core), add); + if (print.cxx26) std::for_each(std::begin(cxx26_core), std::end(cxx26_core), add); + if (print.cxx23) std::for_each(std::begin(cxx23_core), std::end(cxx23_core), add); + if (print.cxx20) std::for_each(std::begin(cxx20_core), std::end(cxx20_core), add); + if (print.cxx17) std::for_each(std::begin(cxx17_core), std::end(cxx17_core), add); + if (print.cxx14) std::for_each(std::begin(cxx14_core), std::end(cxx14_core), add); + if (print.cxx11) std::for_each(std::begin(cxx11_core), std::end(cxx11_core), add); + if (print.cxx98) std::for_each(std::begin(cxx98_core), std::end(cxx98_core), add); + std::snprintf(text, sizeof text, "ALL CORE MACROS UP TO C++%02i", latest_rev()); + show(text, latest); + } + latest.clear(); + if (print.lib_features) + { // preserve reverse revision insertion order! + if (print.cxx29) std::for_each(std::begin(cxx29_lib), std::end(cxx29_lib), add); + if (print.cxx26) std::for_each(std::begin(cxx26_lib), std::end(cxx26_lib), add); + if (print.cxx23) std::for_each(std::begin(cxx23_lib), std::end(cxx23_lib), add); + if (print.cxx20) std::for_each(std::begin(cxx20_lib), std::end(cxx20_lib), add); + if (print.cxx17) std::for_each(std::begin(cxx17_lib), std::end(cxx17_lib), add); + if (print.cxx14) std::for_each(std::begin(cxx14_lib), std::end(cxx14_lib), add); + std::snprintf(text, sizeof text, "ALL LIB MACROS UP TO C++%02i", latest_rev()); + show(text, latest); + } +} + +int main() +{ + if (print.separated_revisions) + { + if (print.cxx98 and print.core_features) show("C++98 CORE", cxx98_core); + if (print.cxx11 and print.core_features) show("C++11 CORE", cxx11_core); + if (print.cxx14 and print.core_features) show("C++14 CORE", cxx14_core); + if (print.cxx14 and print.lib_features ) show("C++14 LIB" , cxx14_lib); + if (print.cxx17 and print.core_features) show("C++17 CORE", cxx17_core); + if (print.cxx17 and print.lib_features ) show("C++17 LIB" , cxx17_lib); + if (print.cxx20 and print.core_features) show("C++20 CORE", cxx20_core); + if (print.cxx20 and print.lib_features ) show("C++20 LIB" , cxx20_lib); + if (print.cxx23 and print.core_features) show("C++23 CORE", cxx23_core); + if (print.cxx23 and print.lib_features ) show("C++23 LIB" , cxx23_lib); + if (print.cxx26 and print.core_features) show("C++26 CORE", cxx26_core); + if (print.cxx26 and print.lib_features ) show("C++26 LIB" , cxx26_lib); + if (print.cxx29 and print.core_features) show("C++29 CORE", cxx29_core); + if (print.cxx29 and print.lib_features ) show("C++29 LIB" , cxx29_lib); + } + if (print.latest_revisions) show_latest(); + if (print.attributes) show("ATTRIBUTES", attributes); + if (print.compiler_specific) show_compiler_specific_info(); +}