From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 365CF3858412 for ; Wed, 28 Jun 2023 03:29:49 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 365CF3858412 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1687922988; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=hBme8+iZThKKd4FFIl0P9tyPMdrufTPO7comB37XtIc=; b=GRAkjtR3q7wxhlzh8iFJn/o0y0j2S9Mc0RCUrAKGyMwPwrQu1KjCrCOn3o3dAKw1ihkXXg 8fGkN994aYGX3q+2YowF7tKvarXLbiFxKXAPp1AxomClm4gVPxIUGTlMA7L9VufEhlEmkZ bMwVjy9ERefyDqbbeLpPaKHdpwqzitc= Received: from mail-qt1-f197.google.com (mail-qt1-f197.google.com [209.85.160.197]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-612-fj5JdqhnO9SdCRR8GdZNMA-1; Tue, 27 Jun 2023 23:29:38 -0400 X-MC-Unique: fj5JdqhnO9SdCRR8GdZNMA-1 Received: by mail-qt1-f197.google.com with SMTP id d75a77b69052e-3fde20eded9so57573601cf.2 for ; Tue, 27 Jun 2023 20:29:38 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1687922978; x=1690514978; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=hBme8+iZThKKd4FFIl0P9tyPMdrufTPO7comB37XtIc=; b=GOk4cmm0PdnR1fHffae0JNoLtf4UyTC3x86HAMCl7QcM7VuiDq5V+Vmu6Jekm+6Vi+ BdpCeTPwWRFNGuOtMd25ipjTPVdw1j91MHRaNodgElGgQq4fcmnFdsWll81PV3WDYho8 3Gzb0DnyRf9txBYS063qEbwn6xAx/1YZW7R2yOzq28B6np1LO9K9vi7Zyjup9kT+sHiY n3ExQ8BRt9rmIc9Zq3xTPVfnY1+Orn5nqIIJiwgOzfOw7tWtCfeNEkP+wCAdIPcG41/y mqnQ2YTM1vKWs5SswZmZkvTgBLOLngUN5KgkEqIsvs3JpY++0kPERi+wi0HzexKkCLyG Bwyw== X-Gm-Message-State: AC+VfDx5bg+oKUngQFDNBU+FiLokf1s6HH8x+uad4OTSmv6U2L+Q/LZQ H4yAbXCoWAfxqKiGbbGOEkjIYcQeYKqJ9i6BhQ3byhesUzihCkiv+IEMq7vERVx73PiRNDldPKk KnCxIWBa7J+H6mpcTD4mNjV3mTEZMXxjeLl1gv5pxmbysDvplfwc/yBdw5POAR1udRStW4khn+w == X-Received: by 2002:a05:622a:1baa:b0:400:80ac:badc with SMTP id bp42-20020a05622a1baa00b0040080acbadcmr19083441qtb.33.1687922977619; Tue, 27 Jun 2023 20:29:37 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ4vWE+QQOI1cuio8SaNjBzmc3v64W8P6W0ogVcT8vk1hFW7KrK+ZzKatFtMjNnyfvfnhUftJA== X-Received: by 2002:a05:622a:1baa:b0:400:80ac:badc with SMTP id bp42-20020a05622a1baa00b0040080acbadcmr19083413qtb.33.1687922976892; Tue, 27 Jun 2023 20:29:36 -0700 (PDT) Received: from jason.com (130-44-146-16.s12558.c3-0.arl-cbr1.sbo-arl.ma.cable.rcncustomer.com. [130.44.146.16]) by smtp.gmail.com with ESMTPSA id f14-20020ac859ce000000b003f9c6a311e1sm3470479qtf.47.2023.06.27.20.29.35 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 27 Jun 2023 20:29:36 -0700 (PDT) From: Jason Merrill To: gcc-patches@gcc.gnu.org Subject: [pushed] c++: C++26 constexpr cast from void* [PR110344] Date: Tue, 27 Jun 2023 23:29:34 -0400 Message-Id: <20230628032934.2615167-1-jason@redhat.com> X-Mailer: git-send-email 2.39.3 MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset="US-ASCII"; x-default=true X-Spam-Status: No, score=-12.7 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H5,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_NONE,TXREP,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: Tested x86_64-pc-linux-gnu, applying to trunk. -- 8< -- P2768 allows static_cast from void* to ob* in constant evaluation if the pointer does in fact point to an object of the appropriate type. cxx_fold_indirect_ref already does the work of finding such an object if it happens to be a subobject rather than the outermost object at that address, as in constexpr-voidptr2.C. P2768 PR c++/110344 gcc/c-family/ChangeLog: * c-cppbuiltin.cc (c_cpp_builtins): Update __cpp_constexpr. gcc/cp/ChangeLog: * constexpr.cc (cxx_eval_constant_expression): In C++26, allow cast from void* to the type of a pointed-to object. gcc/testsuite/ChangeLog: * g++.dg/cpp26/constexpr-voidptr1.C: New test. * g++.dg/cpp26/constexpr-voidptr2.C: New test. * g++.dg/cpp26/feat-cxx26.C: New test. --- gcc/c-family/c-cppbuiltin.cc | 8 +- gcc/cp/constexpr.cc | 11 + .../g++.dg/cpp26/constexpr-voidptr1.C | 35 + .../g++.dg/cpp26/constexpr-voidptr2.C | 15 + gcc/testsuite/g++.dg/cpp26/feat-cxx26.C | 597 ++++++++++++++++++ 5 files changed, 665 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/cpp26/constexpr-voidptr1.C create mode 100644 gcc/testsuite/g++.dg/cpp26/constexpr-voidptr2.C create mode 100644 gcc/testsuite/g++.dg/cpp26/feat-cxx26.C diff --git a/gcc/c-family/c-cppbuiltin.cc b/gcc/c-family/c-cppbuiltin.cc index 5d64625fcd7..6bd4c1261a7 100644 --- a/gcc/c-family/c-cppbuiltin.cc +++ b/gcc/c-family/c-cppbuiltin.cc @@ -1075,12 +1075,18 @@ c_cpp_builtins (cpp_reader *pfile) cpp_define (pfile, "__cpp_size_t_suffix=202011L"); cpp_define (pfile, "__cpp_if_consteval=202106L"); cpp_define (pfile, "__cpp_auto_cast=202110L"); - cpp_define (pfile, "__cpp_constexpr=202211L"); + if (cxx_dialect <= cxx23) + cpp_define (pfile, "__cpp_constexpr=202211L"); cpp_define (pfile, "__cpp_multidimensional_subscript=202211L"); cpp_define (pfile, "__cpp_named_character_escapes=202207L"); cpp_define (pfile, "__cpp_static_call_operator=202207L"); cpp_define (pfile, "__cpp_implicit_move=202207L"); } + if (cxx_dialect > cxx23) + { + /* Set feature test macros for C++26. */ + cpp_define (pfile, "__cpp_constexpr=202306L"); + } if (flag_concepts) { if (cxx_dialect >= cxx20) diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index 432b3a275e8..cca0435bafc 100644 --- a/gcc/cp/constexpr.cc +++ b/gcc/cp/constexpr.cc @@ -7681,6 +7681,17 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, && !is_std_construct_at (ctx->call) && !is_std_allocator_allocate (ctx->call)) { + /* P2738 (C++26): a conversion from a prvalue P of type "pointer to + cv void" to a pointer-to-object type T unless P points to an + object whose type is similar to T. */ + if (cxx_dialect > cxx23) + if (tree ob + = cxx_fold_indirect_ref (ctx, loc, TREE_TYPE (type), op)) + { + r = build1 (ADDR_EXPR, type, ob); + break; + } + /* Likewise, don't error when casting from void* when OP is &heap uninit and similar. */ tree sop = tree_strip_nop_conversions (op); diff --git a/gcc/testsuite/g++.dg/cpp26/constexpr-voidptr1.C b/gcc/testsuite/g++.dg/cpp26/constexpr-voidptr1.C new file mode 100644 index 00000000000..ce0ccbef5f9 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/constexpr-voidptr1.C @@ -0,0 +1,35 @@ +// PR c++/110344 +// { dg-do compile { target c++26 } } + +#include +struct Sheep { + constexpr std::string_view speak() const noexcept { return "Baaaaaa"; } +}; +struct Cow { + constexpr std::string_view speak() const noexcept { return "Mooo"; } +}; +class Animal_View { +private: + const void *animal; + std::string_view (*speak_function)(const void *); +public: + template + constexpr Animal_View(const Animal &a) + : animal{&a}, speak_function{[](const void *object) { + return static_cast(object)->speak(); + }} {} + constexpr std::string_view speak() const noexcept { + return speak_function(animal); + } +}; +// This is the key bit here. This is a single concrete function +// that can take anything that happens to have the "Animal_View" +// interface +constexpr std::string_view do_speak(Animal_View av) { return av.speak(); } +int main() { + // A Cow is a cow. The only think that makes it special + // is that it has a "std::string_view speak() const" member + constexpr Cow cow; + constexpr auto result = do_speak(cow); + return static_cast(result.size()); +} diff --git a/gcc/testsuite/g++.dg/cpp26/constexpr-voidptr2.C b/gcc/testsuite/g++.dg/cpp26/constexpr-voidptr2.C new file mode 100644 index 00000000000..e746301e9f9 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/constexpr-voidptr2.C @@ -0,0 +1,15 @@ +// PR c++/110344 +// { dg-do compile { target c++26 } } + +struct A { int i; }; +struct B { A a; }; + +constexpr int f() +{ + B b { 42 }; + void *p = &b; + A* ap = static_cast(p); + return ap->i; +} + +static_assert (f() == 42); diff --git a/gcc/testsuite/g++.dg/cpp26/feat-cxx26.C b/gcc/testsuite/g++.dg/cpp26/feat-cxx26.C new file mode 100644 index 00000000000..0977d964fe0 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/feat-cxx26.C @@ -0,0 +1,597 @@ +// { dg-options "-std=c++26 -I${srcdir}/g++.dg/cpp1y -I${srcdir}/g++.dg/cpp1y/testinc" } + +// C++98 features: + +#ifndef __cpp_rtti +# error "__cpp_rtti" +#elif __cpp_rtti != 199711 +# error "__cpp_rtti != 199711" +#endif + +#ifndef __cpp_exceptions +# error "__cpp_exceptions" +#elif __cpp_exceptions != 199711 +# error "__cpp_exceptions != 199711" +#endif + +// C++11 features: + +#ifndef __cpp_raw_strings +# error "__cpp_raw_strings" +#elif __cpp_raw_strings != 200710 +# error "__cpp_raw_strings != 200710" +#endif + +#ifndef __cpp_unicode_literals +# error "__cpp_unicode_literals" +#elif __cpp_unicode_literals != 200710 +# error "__cpp_unicode_literals != 200710" +#endif + +#ifndef __cpp_user_defined_literals +# error "__cpp_user_defined_literals" +#elif __cpp_user_defined_literals != 200809 +# error "__cpp_user_defined_literals != 200809" +#endif + +#ifndef __cpp_lambdas +# error "__cpp_lambdas" +#elif __cpp_lambdas != 200907 +# error "__cpp_lambdas != 200907" +#endif + +#ifndef __cpp_range_based_for +# error "__cpp_range_based_for" +#elif __cpp_range_based_for != 201603 +# error "__cpp_range_based_for != 201603" +#endif + +#ifndef __cpp_decltype +# error "__cpp_decltype" +#elif __cpp_decltype != 200707 +# error "__cpp_decltype != 200707" +#endif + +#ifndef __cpp_attributes +# error "__cpp_attributes" +#elif __cpp_attributes != 200809 +# error "__cpp_attributes != 200809" +#endif + +#ifndef __cpp_rvalue_references +# error "__cpp_rvalue_references" +#elif __cpp_rvalue_references != 200610 +# error "__cpp_rvalue_references != 200610" +#endif + +#ifndef __cpp_variadic_templates +# error "__cpp_variadic_templates" +#elif __cpp_variadic_templates != 200704 +# error "__cpp_variadic_templates != 200704" +#endif + +#ifndef __cpp_initializer_lists +# error "__cpp_initializer_lists" +#elif __cpp_initializer_lists != 200806 +# error "__cpp_initializer_lists != 200806" +#endif + +#ifndef __cpp_delegating_constructors +# error "__cpp_delegating_constructors" +#elif __cpp_delegating_constructors != 200604 +# error "__cpp_delegating_constructors != 200604" +#endif + +#ifndef __cpp_nsdmi +# error "__cpp_nsdmi" +#elif __cpp_nsdmi != 200809 +# error "__cpp_nsdmi != 200809" +#endif + +#ifndef __cpp_inheriting_constructors +# error "__cpp_inheriting_constructors" +#elif __cpp_inheriting_constructors!= 201511 +# error "__cpp_inheriting_constructors != 201511" +#endif + +#ifndef __cpp_ref_qualifiers +# error "__cpp_ref_qualifiers" +#elif __cpp_ref_qualifiers != 200710 +# error "__cpp_ref_qualifiers != 200710" +#endif + +#ifndef __cpp_alias_templates +# error "__cpp_alias_templates" +#elif __cpp_alias_templates != 200704 +# error "__cpp_alias_templates != 200704" +#endif + +#ifndef __cpp_threadsafe_static_init +# error "__cpp_threadsafe_static_init" +#elif __cpp_threadsafe_static_init != 200806 +# error "__cpp_threadsafe_static_init != 200806" +#endif + +// C++14 features: + +#ifndef __cpp_binary_literals +# error "__cpp_binary_literals" +#elif __cpp_binary_literals != 201304 +# error "__cpp_binary_literals != 201304" +#endif + +#ifndef __cpp_init_captures +# error "__cpp_init_captures" +#elif __cpp_init_captures != 201803 +# error "__cpp_init_captures != 201803" +#endif + +#ifndef __cpp_generic_lambdas +# error "__cpp_generic_lambdas" +#elif __cpp_generic_lambdas != 201707 +# error "__cpp_generic_lambdas != 201707" +#endif + +#ifndef __cpp_constexpr +# error "__cpp_constexpr" +#elif __cpp_constexpr != 202306L +# error "__cpp_constexpr != 202306L" +#endif + +#ifndef __cpp_decltype_auto +# error "__cpp_decltype_auto" +#elif __cpp_decltype_auto != 201304 +# error "__cpp_decltype_auto != 201304" +#endif + +#ifndef __cpp_return_type_deduction +# error "__cpp_return_type_deduction" +#elif __cpp_return_type_deduction != 201304 +# error "__cpp_return_type_deduction != 201304" +#endif + +#ifndef __cpp_aggregate_nsdmi +# error "__cpp_aggregate_nsdmi" +#elif __cpp_aggregate_nsdmi != 201304 +# error "__cpp_aggregate_nsdmi != 201304" +#endif + +#ifndef __cpp_variable_templates +# error "__cpp_variable_templates" +#elif __cpp_variable_templates != 201304 +# error "__cpp_variable_templates != 201304" +#endif + +#ifndef __cpp_digit_separators +# error "__cpp_digit_separators" +#elif __cpp_digit_separators != 201309 +# error "__cpp_digit_separators != 201309" +#endif + +#ifndef __cpp_sized_deallocation +# error "__cpp_sized_deallocation" +#elif __cpp_sized_deallocation != 201309 +# error "__cpp_sized_deallocation != 201309" +#endif + +// GNU VLA support: + +#ifndef __cpp_runtime_arrays +# error "__cpp_runtime_arrays" +#elif __cpp_runtime_arrays != 198712 +# error "__cpp_runtime_arrays != 198712" +#endif + +// C++11 attributes: + +#ifdef __has_cpp_attribute +# if ! __has_cpp_attribute(noreturn) +# error "__has_cpp_attribute(noreturn)" +# elif __has_cpp_attribute(noreturn) != 200809 +# error "__has_cpp_attribute(noreturn) != 200809" +# endif +#else +# error "__has_cpp_attribute" +#endif + +// Attribute carries_dependency not in yet. +//#ifdef __has_cpp_attribute +//# if ! __has_cpp_attribute(carries_dependency) +//# error "__has_cpp_attribute(carries_dependency)" +//# elif __has_cpp_attribute(carries_dependency) != 200809 +//# error "__has_cpp_attribute(carries_dependency) != 200809" +//# endif +//#else +//# error "__has_cpp_attribute" +//#endif + +// C++14 attributes: + +#ifdef __has_cpp_attribute +# if ! __has_cpp_attribute(deprecated) +# error "__has_cpp_attribute(deprecated)" +# elif __has_cpp_attribute(deprecated) != 201309 +# error "__has_cpp_attribute(deprecated) != 201309" +# endif +#else +# error "__has_cpp_attribute" +#endif + +// Include checks: + +// Check for __has_include macro. +#ifndef __has_include +# error "__has_include" +#endif + +// Try known bracket header (use operator). +#if __has_include () +#else +# error "" +#endif + +// Define and use a macro to invoke the operator. +#define sluggo(TXT) __has_include(TXT) + +#if sluggo() +#else +# error "" +#endif + +#if ! sluggo() +# error "" +#else +#endif + +// Quoted complex.h should find at least the bracket version. +#if __has_include("complex.h") +#else +# error "complex.h" +#endif + +// Try known local quote header. +#if __has_include("complex_literals.h") +#else +# error "\"complex_literals.h\"" +#endif + +// Try nonexistent bracket header. +#if __has_include() +# error "" +#else +#endif + +// Try nonexistent quote header. +#if __has_include("phlegm") +# error "\"phlegm\"" +#else +#endif + +// Test __has_include_next. +#if __has_include("phoobhar.h") +# include "phoobhar.h" +#else +# error "__has_include(\"phoobhar.h\")" +#endif + +// Try a macro. +#define COMPLEX_INC "complex.h" +#if __has_include(COMPLEX_INC) +#else +# error COMPLEX_INC +#endif + +// Realistic use of __has_include. +#if __has_include() +# define STD_ARRAY 1 +# include + template + using array = std::array<_Tp, _Num>; +#elif __has_include() +# define TR1_ARRAY 1 +# include + template + typedef std::tr1::array<_Tp, _Num> array; +#endif + +// C++17 features: + +#ifndef __cpp_unicode_characters +# error "__cpp_unicode_characters" +#elif __cpp_unicode_characters != 201411 +# error "__cpp_unicode_characters != 201411" +#endif + +#ifndef __cpp_static_assert +# error "__cpp_static_assert" +#elif __cpp_static_assert != 201411 +# error "__cpp_static_assert != 201411" +#endif + +#ifndef __cpp_namespace_attributes +# error "__cpp_namespace_attributes" +#elif __cpp_namespace_attributes != 201411 +# error "__cpp_namespace_attributes != 201411" +#endif + +#ifndef __cpp_enumerator_attributes +# error "__cpp_enumerator_attributes" +#elif __cpp_enumerator_attributes != 201411 +# error "__cpp_enumerator_attributes != 201411" +#endif + +#ifndef __cpp_nested_namespace_definitions +# error "__cpp_nested_namespace_definitions" +#elif __cpp_nested_namespace_definitions != 201411 +# error "__cpp_nested_namespace_definitions != 201411" +#endif + +#ifndef __cpp_fold_expressions +# error "__cpp_fold_expressions" +#elif __cpp_fold_expressions != 201603 +# error "__cpp_fold_expressions != 201603" +#endif + +#ifndef __cpp_nontype_template_args +# error "__cpp_nontype_template_args" +#elif __cpp_nontype_template_args != 201911 +# error "__cpp_nontype_template_args != 201911" +#endif + +#ifndef __cpp_hex_float +# error "__cpp_hex_float" +#elif __cpp_hex_float != 201603 +# error "__cpp_hex_float != 201603" +#endif + +#ifndef __cpp_aggregate_bases +# error "__cpp_aggregate_bases" +#elif __cpp_aggregate_bases != 201603 +# error "__cpp_aggregate_bases != 201603" +#endif + +#ifndef __cpp_deduction_guides +# error "__cpp_deduction_guides" +#elif __cpp_deduction_guides != 201907 +# error "__cpp_deduction_guides != 201907" +#endif + +#ifndef __cpp_if_constexpr +# error "__cpp_if_constexpr" +#elif __cpp_if_constexpr != 201606 +# error "__cpp_if_constexpr != 201606" +#endif + +#ifndef __cpp_aligned_new +# error "__cpp_aligned_new" +#elif __cpp_aligned_new != 201606 +# error "__cpp_aligned_new != 201606" +#endif + +#ifndef __cpp_template_auto +# error "__cpp_template_auto" +#elif __cpp_template_auto != 201606 +# error "__cpp_template_auto != 201606" +#endif + +#ifndef __cpp_inline_variables +# error "__cpp_inline_variables" +#elif __cpp_inline_variables != 201606 +# error "__cpp_inline_variables != 201606" +#endif + +#ifndef __cpp_capture_star_this +# error "__cpp_capture_star_this" +#elif __cpp_capture_star_this != 201603 +# error "__cpp_capture_star_this != 201603" +#endif + +#ifndef __cpp_noexcept_function_type +# error "__cpp_noexcept_function_type" +#elif __cpp_noexcept_function_type != 201510 +# error "__cpp_noexcept_function_type != 201510" +#endif + +#ifndef __cpp_structured_bindings +# error "__cpp_structured_bindings" +#elif __cpp_structured_bindings != 201606 +# error "__cpp_structured_bindings != 201606" +#endif + +#ifndef __cpp_template_template_args +# error "__cpp_template_template_args" +#elif __cpp_template_template_args != 201611 +# error "__cpp_template_template_args != 201611" +#endif + +#ifndef __cpp_variadic_using +# error "__cpp_variadic_using" +#elif __cpp_variadic_using != 201611 +# error "__cpp_variadic_using != 201611" +#endif + +#ifndef __cpp_guaranteed_copy_elision +# error "__cpp_guaranteed_copy_elision" +#elif __cpp_guaranteed_copy_elision != 201606 +# error "__cpp_guaranteed_copy_elision != 201606" +#endif + +#ifndef __cpp_nontype_template_parameter_auto +# error "__cpp_nontype_template_parameter_auto" +#elif __cpp_nontype_template_parameter_auto != 201606 +# error "__cpp_nontype_template_parameter_auto != 201606" +#endif + +// C++20 features: + +#ifndef __cpp_conditional_explicit +# error "__cpp_conditional_explicit" +#elif __cpp_conditional_explicit != 201806 +# error "__cpp_conditional_explicit != 201806" +#endif + +#ifndef __cpp_nontype_template_parameter_class +# error "__cpp_nontype_template_parameter_class" +#elif __cpp_nontype_template_parameter_class != 201806 +# error "__cpp_nontype_template_parameter_class != 201806" +#endif + +#ifndef __cpp_impl_destroying_delete +# error "__cpp_impl_destroying_delete" +#elif __cpp_impl_destroying_delete != 201806 +# error "__cpp_impl_destroying_delete != 201806" +#endif + +#ifndef __cpp_constinit +# error "__cpp_constinit" +#elif __cpp_constinit != 201907 +# error "__cpp_constinit != 201907" +#endif + +#ifndef __cpp_constexpr_dynamic_alloc +# error "__cpp_constexpr_dynamic_alloc" +#elif __cpp_constexpr_dynamic_alloc != 201907 +# error "__cpp_constexpr_dynamic_alloc != 201907" +#endif + +#ifndef __cpp_aggregate_paren_init +# error "__cpp_aggregate_paren_init" +#elif __cpp_aggregate_paren_init != 201902 +# error "__cpp_aggregate_paren_init != 201902" +#endif + +#ifndef __cpp_char8_t +# error "__cpp_char8_t" +#elif __cpp_char8_t != 202207 +# error "__cpp_char8_t != 202207" +#endif + +#ifndef __cpp_designated_initializers +# error "__cpp_designated_initializers" +#elif __cpp_designated_initializers != 201707 +# error "__cpp_designated_initializers != 201707" +#endif + +#ifndef __cpp_constexpr_in_decltype +# error "__cpp_constexpr_in_decltype" +#elif __cpp_constexpr_in_decltype != 201711 +# error "__cpp_constexpr_in_decltype != 201711" +#endif + +#ifndef __cpp_consteval +# error "__cpp_consteval" +#elif __cpp_consteval != 201811 +# error "__cpp_consteval != 201811" +#endif + +#ifndef __cpp_concepts +# error "__cpp_concepts" +#elif __cpp_concepts != 202002 +# error "__cpp_concepts != 202002" +#endif + +#ifndef __cpp_using_enum +# error "__cpp_using_enum" +#elif __cpp_using_enum != 201907 +# error "__cpp_using_enum != 201907" +#endif + +// C++20 attributes: + +#ifdef __has_cpp_attribute + +# if ! __has_cpp_attribute(maybe_unused) +# error "__has_cpp_attribute(maybe_unused)" +# elif __has_cpp_attribute(maybe_unused) != 201603 +# error "__has_cpp_attribute(maybe_unused) != 201603" +# endif + +# if ! __has_cpp_attribute(nodiscard) +# error "__has_cpp_attribute(nodiscard)" +# elif __has_cpp_attribute(nodiscard) != 201907 +# error "__has_cpp_attribute(nodiscard) != 201907" +# endif + +# if ! __has_cpp_attribute(fallthrough) +# error "__has_cpp_attribute(fallthrough)" +# elif __has_cpp_attribute(fallthrough) != 201603 +# error "__has_cpp_attribute(fallthrough) != 201603" +# endif + +# if ! __has_cpp_attribute(no_unique_address) +# error "__has_cpp_attribute(no_unique_address)" +# elif __has_cpp_attribute(no_unique_address) != 201803 +# error "__has_cpp_attribute(no_unique_address) != 201803" +# endif + +# if ! __has_cpp_attribute(likely) +# error "__has_cpp_attribute(likely)" +# elif __has_cpp_attribute(likely) != 201803 +# error "__has_cpp_attribute(likely) != 201803" +# endif + +# if ! __has_cpp_attribute(unlikely) +# error "__has_cpp_attribute(unlikely)" +# elif __has_cpp_attribute(unlikely) != 201803 +# error "__has_cpp_attribute(unlikely) != 201803" +# endif + +#else +# error "__has_cpp_attribute" +#endif + +// C++23 features: + +#ifndef __cpp_size_t_suffix +# error "__cpp_size_t_suffix" +#elif __cpp_size_t_suffix != 202011 +# error "__cpp_size_t_suffix != 202011" +#endif + +#ifndef __cpp_if_consteval +# error "__cpp_if_consteval" +#elif __cpp_if_consteval != 202106 +# error "__cpp_if_consteval != 202106" +#endif + +#ifndef __cpp_multidimensional_subscript +# error "__cpp_multidimensional_subscript" +#elif __cpp_multidimensional_subscript != 202211 +# error "__cpp_multidimensional_subscript != 202211" +#endif + +#ifndef __cpp_named_character_escapes +# error "__cpp_named_character_escapes" +#elif __cpp_named_character_escapes != 202207 +# error "__cpp_named_character_escapes != 202207" +#endif + +#ifndef __cpp_static_call_operator +# error "__cpp_static_call_operator" +#elif __cpp_static_call_operator != 202207 +# error "__cpp_static_call_operator != 202207" +#endif + +#ifndef __cpp_implicit_move +# error "__cpp_implicit_move" +#elif __cpp_implicit_move != 202207 +# error "__cpp_implicit_move != 202207" +#endif + +#ifndef __cpp_auto_cast +# error "__cpp_auto_cast" +#elif __cpp_auto_cast != 202110 +# error "__cpp_auto_cast != 202110" +#endif + +// C++23 attributes: + +#ifdef __has_cpp_attribute +# if ! __has_cpp_attribute(assume) +# error "__has_cpp_attribute(assume)" +# elif __has_cpp_attribute(assume) != 202207 +# error "__has_cpp_attribute(assume) != 202207" +# endif +#else +# error "__has_cpp_attribute" +#endif base-commit: ebe7c586f62b1c5218b19c3c6853163287b3c887 prerequisite-patch-id: 8aff665478d425e404ede05fed4c0e4106a063f2 -- 2.39.3