From patchwork Wed Jun 5 04:45:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andi Kleen X-Patchwork-Id: 1943647 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=PzIYDmKV; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4VvFNd1Y01z20Q5 for ; Wed, 5 Jun 2024 14:49:05 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 5E6093816B1B for ; Wed, 5 Jun 2024 04:49:03 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) by sourceware.org (Postfix) with ESMTPS id 287703816B00 for ; Wed, 5 Jun 2024 04:48:39 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 287703816B00 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=linux.intel.com Authentication-Results: sourceware.org; spf=none smtp.mailfrom=linux.intel.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 287703816B00 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1717562923; cv=none; b=ESqCELDkEbkaECBWBE3+t2XCHu5crT4w32EhRb7Ypm2RJY+D3kOb3gExD0sy4uJb5PDQt3rD/i/WmZfPm0ZvXLxtrNX1Lf1LP2fElHDHXe6SbHDOObRBAlEZz3z3HZjjt7aPgfrQxvTQtgdIixnsuP5Z4FZh0uphRAOMmh/X/VQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1717562923; c=relaxed/simple; bh=7mp3PC4VcKjmLQH5lrzm2mPAXtgfFawtbHI2IzSAntI=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=X7TCB23TLYNSX36f7jM+n+cYf6KjLnjx0udXp6huaw0xPdy4otXhsXfdXTVDEo3XKc29U4ccmbYxMKOZknNQLsVfS9uKK9lOrSg3RrgbHIydVj57+9a32S9haizkcO6GpjezJQv/tLTm5H1E2CR3H3/SPkNxpf22/3sSSoxhg4I= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1717562920; x=1749098920; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=7mp3PC4VcKjmLQH5lrzm2mPAXtgfFawtbHI2IzSAntI=; b=PzIYDmKVm9JrCk0IW92qH75HFR9uWid42JxZlDSwxxCEUkoNgkHRHn27 JkLMinxv55S17sNrj6IarWDOTI3CGDBzZ367pFJsvCvaMuA19TmCFeXiP nNYnD5elDTy1GlA6OAgfDRDgizD/GBHf/hgVjd3rcKkKo089fjtBopmc6 ekOV4MBDCHKtFFD9mXL5CL4TPbQqpsVHF/0KUZDpy4H1tlFRrsb4u4JON 5SECj3nmYXro3du/iFboWCP9SRTY6iv0u4slXdiklMNTYHSnbBOFYrbvq Z4eH7WPkEQBPFMnndzCk6mTxWUWo6u/Lr2p2MZ6zt8pg8L20YMko/GBoI Q==; X-CSE-ConnectionGUID: +4TTGTm/QQ2sYoj6J2jIGA== X-CSE-MsgGUID: s7rrVe9ETROl/MjGBUGhBw== X-IronPort-AV: E=McAfee;i="6600,9927,11093"; a="17969316" X-IronPort-AV: E=Sophos;i="6.08,215,1712646000"; d="scan'208";a="17969316" Received: from fmviesa008.fm.intel.com ([10.60.135.148]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Jun 2024 21:48:38 -0700 X-CSE-ConnectionGUID: Nn9TXHTjRjmnEBOzt+Bupw== X-CSE-MsgGUID: bdX5Bz2hSASgRUMCwfRbeQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.08,215,1712646000"; d="scan'208";a="37463368" Received: from tassilo.jf.intel.com ([10.54.38.190]) by fmviesa008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Jun 2024 21:48:36 -0700 From: Andi Kleen To: gcc-patches@gcc.gnu.org Cc: jason@redhat.com, jakub@redhat.com, Andi Kleen Subject: [PATCH v3 1/2] Factor out static_assert constexpr string extraction for reuse Date: Tue, 4 Jun 2024 21:45:21 -0700 Message-ID: <20240605044827.2697253-2-ak@linux.intel.com> X-Mailer: git-send-email 2.45.1 In-Reply-To: <20240605044827.2697253-1-ak@linux.intel.com> References: <20240605044827.2697253-1-ak@linux.intel.com> MIME-Version: 1.0 X-Spam-Status: No, score=-11.1 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_EF, GIT_PATCH_0, 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 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org The only semantics changes are slightly more vague error messages to generalize. gcc/cp/ChangeLog: * cp-tree.h (class cexpr_str): Add. * semantics.cc (finish_static_assert): Convert to use cexpr_str. (cexpr_str::type_check): Extract constexpr string code to here. (cexpr_str::extract): ... and here. gcc/testsuite/ChangeLog: * g++.dg/cpp26/static_assert1.C: Update to new error message. --- gcc/cp/cp-tree.h | 18 ++ gcc/cp/semantics.cc | 256 +++++++++++--------- gcc/testsuite/g++.dg/cpp0x/udlit-error1.C | 2 +- gcc/testsuite/g++.dg/cpp26/static_assert1.C | 32 +-- 4 files changed, 176 insertions(+), 132 deletions(-) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 565e4a9290e2..3446041937b2 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -9015,6 +9015,24 @@ struct push_access_scope_guard } }; +/* Extracting strings from constexpr. */ + +class cexpr_str +{ +public: + cexpr_str (tree message) : message(message) {} + cexpr_str (const cexpr_str &) = delete; + ~cexpr_str () { XDELETEVEC (buf); } + + bool type_check (location_t location); + bool extract (location_t location, const char * & msg, int &len); + tree message; +private: + tree message_data = NULL_TREE; + tree message_sz = NULL_TREE; + char *buf = nullptr; +}; + /* True if TYPE is an extended floating-point type. */ inline bool diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index f90c304a65b7..5cf698185ba4 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -11558,28 +11558,18 @@ init_cp_semantics (void) } -/* Build a STATIC_ASSERT for a static assertion with the condition - CONDITION and the message text MESSAGE. LOCATION is the location - of the static assertion in the source code. When MEMBER_P, this - static assertion is a member of a class. If SHOW_EXPR_P is true, - print the condition (because it was instantiation-dependent). */ +/* Get constant string from MESSAGE at LOCATION. Returns + true if successfull, otherwise false. */ -void -finish_static_assert (tree condition, tree message, location_t location, - bool member_p, bool show_expr_p) +bool +cexpr_str::type_check (location_t location) { tsubst_flags_t complain = tf_warning_or_error; - tree message_sz = NULL_TREE, message_data = NULL_TREE; if (message == NULL_TREE || message == error_mark_node - || condition == NULL_TREE - || condition == error_mark_node) - return; - - if (check_for_bare_parameter_packs (condition) || check_for_bare_parameter_packs (message)) - return; + return false; if (TREE_CODE (message) != STRING_CST && !type_dependent_expression_p (message)) @@ -11595,10 +11585,10 @@ finish_static_assert (tree condition, tree message, location_t location, false, complain); if (message_sz == error_mark_node || message_data == error_mark_node) { - error_at (location, "% message must be a string " - "literal or object with % and " - "% members"); - return; + error_at (location, "constexpr string must be a string " + "literal or object with % and " + "% members"); + return false; } releasing_vec size_args, data_args; message_sz = finish_call_expr (message_sz, &size_args, false, false, @@ -11606,26 +11596,144 @@ finish_static_assert (tree condition, tree message, location_t location, message_data = finish_call_expr (message_data, &data_args, false, false, complain); if (message_sz == error_mark_node || message_data == error_mark_node) - return; + return false; message_sz = build_converted_constant_expr (size_type_node, message_sz, - complain); + complain); if (message_sz == error_mark_node) { - error_at (location, "% message % " - "must be implicitly convertible to " - "%"); - return; + error_at (location, "constexpr string % " + "must be implicitly convertible to " + "%"); + return false; } message_data = build_converted_constant_expr (const_string_type_node, - message_data, complain); + message_data, complain); if (message_data == error_mark_node) { - error_at (location, "% message % " - "must be implicitly convertible to " - "%"); - return; + error_at (location, "constexpr string % " + "must be implicitly convertible to " + "%"); + return false; } } + return true; +} + +/* Extract constant string at LOCATION into output string MSG without LEN. + Returns true if successfull, otherwise false. */ + +bool +cexpr_str::extract (location_t location, const char * & msg, int &len) +{ + tsubst_flags_t complain = tf_warning_or_error; + + msg = NULL; + if (message_sz && message_data) + { + tree msz = cxx_constant_value (message_sz, NULL_TREE, complain); + if (!tree_fits_uhwi_p (msz)) + { + error_at (location, + "constexpr string % " + "must be a constant expression"); + return false; + } + else if ((unsigned HOST_WIDE_INT) (int) tree_to_uhwi (msz) + != tree_to_uhwi (msz)) + { + error_at (location, + "constexpr string message % " + "%qE too large", msz); + return false; + } + len = tree_to_uhwi (msz); + tree data = maybe_constant_value (message_data, NULL_TREE, + mce_true); + if (!reduced_constant_expression_p (data)) + data = NULL_TREE; + if (len) + { + if (data) + msg = c_getstr (data); + if (msg == NULL) + buf = XNEWVEC (char, len); + for (int i = 0; i < len; ++i) + { + tree t = message_data; + if (i) + t = build2 (POINTER_PLUS_EXPR, + TREE_TYPE (message_data), message_data, + size_int (i)); + t = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (t)), t); + tree t2 = cxx_constant_value (t, NULL_TREE, complain); + if (!tree_fits_shwi_p (t2)) + { + error_at (location, + "constexpr string % " + "must be a constant expression", i); + return false; + } + if (msg == NULL) + buf[i] = tree_to_shwi (t2); + /* If c_getstr worked, just verify the first and + last characters using constant evaluation. */ + else if (len > 2 && i == 0) + i = len - 2; + } + if (msg == NULL) + msg = buf; + } + else if (!data) + { + /* We don't have any function to test whether some + expression is a core constant expression. So, instead + test whether (message.data (), 0) is a constant + expression. */ + data = build2 (COMPOUND_EXPR, integer_type_node, + message_data, integer_zero_node); + tree t = cxx_constant_value (data, NULL_TREE, complain); + if (!integer_zerop (t)) + { + error_at (location, + "constexpr string % " + "must be a core constant expression"); + return false; + } + } + } + else + { + tree eltype = TREE_TYPE (TREE_TYPE (message)); + int sz = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (eltype)); + msg = TREE_STRING_POINTER (message); + len = TREE_STRING_LENGTH (message) / sz - 1; + } + + return true; +} + +/* Build a STATIC_ASSERT for a static assertion with the condition + CONDITION and the message text MESSAGE. LOCATION is the location + of the static assertion in the source code. When MEMBER_P, this + static assertion is a member of a class. If SHOW_EXPR_P is true, + print the condition (because it was instantiation-dependent). */ + +void +finish_static_assert (tree condition, tree message, location_t location, + bool member_p, bool show_expr_p) +{ + tsubst_flags_t complain = tf_warning_or_error; + + if (condition == NULL_TREE + || condition == error_mark_node) + return; + + if (check_for_bare_parameter_packs (condition)) + return; + + cexpr_str cstr(message); + if (!cstr.type_check (location)) + return; /* Save the condition in case it was a concept check. */ tree orig_condition = condition; @@ -11638,7 +11746,7 @@ finish_static_assert (tree condition, tree message, location_t location, defer: tree assertion = make_node (STATIC_ASSERT); STATIC_ASSERT_CONDITION (assertion) = orig_condition; - STATIC_ASSERT_MESSAGE (assertion) = message; + STATIC_ASSERT_MESSAGE (assertion) = cstr.message; STATIC_ASSERT_SOURCE_LOCATION (assertion) = location; if (member_p) @@ -11671,88 +11779,8 @@ finish_static_assert (tree condition, tree message, location_t location, int len; const char *msg = NULL; - char *buf = NULL; - if (message_sz && message_data) - { - tree msz = cxx_constant_value (message_sz, NULL_TREE, complain); - if (!tree_fits_uhwi_p (msz)) - { - error_at (location, - "% message % " - "must be a constant expression"); - return; - } - else if ((unsigned HOST_WIDE_INT) (int) tree_to_uhwi (msz) - != tree_to_uhwi (msz)) - { - error_at (location, - "% message % " - "%qE too large", msz); - return; - } - len = tree_to_uhwi (msz); - tree data = maybe_constant_value (message_data, NULL_TREE, - mce_true); - if (!reduced_constant_expression_p (data)) - data = NULL_TREE; - if (len) - { - if (data) - msg = c_getstr (data); - if (msg == NULL) - buf = XNEWVEC (char, len); - for (int i = 0; i < len; ++i) - { - tree t = message_data; - if (i) - t = build2 (POINTER_PLUS_EXPR, - TREE_TYPE (message_data), message_data, - size_int (i)); - t = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (t)), t); - tree t2 = cxx_constant_value (t, NULL_TREE, complain); - if (!tree_fits_shwi_p (t2)) - { - error_at (location, - "% message % " - "must be a constant expression", i); - XDELETEVEC (buf); - return; - } - if (msg == NULL) - buf[i] = tree_to_shwi (t2); - /* If c_getstr worked, just verify the first and - last characters using constant evaluation. */ - else if (len > 2 && i == 0) - i = len - 2; - } - if (msg == NULL) - msg = buf; - } - else if (!data) - { - /* We don't have any function to test whether some - expression is a core constant expression. So, instead - test whether (message.data (), 0) is a constant - expression. */ - data = build2 (COMPOUND_EXPR, integer_type_node, - message_data, integer_zero_node); - tree t = cxx_constant_value (data, NULL_TREE, complain); - if (!integer_zerop (t)) - { - error_at (location, - "% message % " - "must be a core constant expression"); - return; - } - } - } - else - { - tree eltype = TREE_TYPE (TREE_TYPE (message)); - int sz = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (eltype)); - msg = TREE_STRING_POINTER (message); - len = TREE_STRING_LENGTH (message) / sz - 1; - } + if (!cstr.extract (location, msg, len)) + return; /* See if we can find which clause was failing (for logical AND). */ tree bad = find_failing_clause (NULL, orig_condition); @@ -11768,8 +11796,6 @@ finish_static_assert (tree condition, tree message, location_t location, else error_at (cloc, "static assertion failed: %.*s", len, msg); - XDELETEVEC (buf); - diagnose_failing_condition (bad, cloc, show_expr_p); } else if (condition && condition != error_mark_node) diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-error1.C b/gcc/testsuite/g++.dg/cpp0x/udlit-error1.C index 6d6cd454540a..ea939c52c339 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-error1.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-error1.C @@ -12,7 +12,7 @@ void operator""_x(const char *, decltype(sizeof(0))); extern "C"_x { void g(); } // { dg-error "before user-defined string literal" } static_assert(true, "foo"_x); // { dg-error "'static_assert' with non-string message only available with" "" { target c++23_down } } - // { dg-error "'static_assert' message must be a string literal or object with 'size' and 'data' members" "" { target *-*-* } .-1 } + // { dg-error "constexpr string must be a string literal or object with 'size' and 'data' members" "" { target *-*-* } .-1 } // { dg-error "invalid use of 'void'" "" { target *-*-* } .-2 } [[deprecated("oof"_x)]] // { dg-error "string literal with user-defined suffix is invalid in this context" "" { target c++26 } } diff --git a/gcc/testsuite/g++.dg/cpp26/static_assert1.C b/gcc/testsuite/g++.dg/cpp26/static_assert1.C index 59724ae32ce3..7840b6b04d27 100644 --- a/gcc/testsuite/g++.dg/cpp26/static_assert1.C +++ b/gcc/testsuite/g++.dg/cpp26/static_assert1.C @@ -6,25 +6,25 @@ static_assert (true, ""); static_assert (true, ("")); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } - // { dg-error "'static_assert' message must be a string literal or object with 'size' and 'data' members" "" { target *-*-* } .-1 } + // { dg-error "constexpr string must be a string literal or object with 'size' and 'data' members" "" { target *-*-* } .-1 } // { dg-error "request for member 'size' in '\\\(\\\"\\\"\\\)', which is of non-class type 'const char \\\[1\\\]'" "" { target *-*-* } .-2 } static_assert (true, "" + 0); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } - // { dg-error "'static_assert' message must be a string literal or object with 'size' and 'data' members" "" { target *-*-* } .-1 } + // { dg-error "constexpr string must be a string literal or object with 'size' and 'data' members" "" { target *-*-* } .-1 } // { dg-error "request for member 'size' in '\\\(const char\\\*\\\)\\\"\\\"', which is of non-class type 'const char\\\*'" "" { target *-*-* } .-2 } static_assert (true, 0); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } - // { dg-error "'static_assert' message must be a string literal or object with 'size' and 'data' members" "" { target *-*-* } .-1 } + // { dg-error "constexpr string must be a string literal or object with 'size' and 'data' members" "" { target *-*-* } .-1 } // { dg-error "request for member 'size' in '0', which is of non-class type 'int'" "" { target *-*-* } .-2 } struct A {}; static_assert (true, A {}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } - // { dg-error "'static_assert' message must be a string literal or object with 'size' and 'data' members" "" { target *-*-* } .-1 } + // { dg-error "constexpr string must be a string literal or object with 'size' and 'data' members" "" { target *-*-* } .-1 } // { dg-error "'struct A' has no member named 'size'" "" { target *-*-* } .-2 } struct B { int size; }; static_assert (true, B {}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } - // { dg-error "'static_assert' message must be a string literal or object with 'size' and 'data' members" "" { target *-*-* } .-1 } + // { dg-error "constexpr string must be a string literal or object with 'size' and 'data' members" "" { target *-*-* } .-1 } // { dg-error "'struct B' has no member named 'data'" "" { target *-*-* } .-2 } struct C { constexpr int size () const { return 0; } }; static_assert (true, C {}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } - // { dg-error "'static_assert' message must be a string literal or object with 'size' and 'data' members" "" { target *-*-* } .-1 } + // { dg-error "constexpr string must be a string literal or object with 'size' and 'data' members" "" { target *-*-* } .-1 } // { dg-error "'struct C' has no member named 'data'" "" { target *-*-* } .-2 } struct D { constexpr int size () const { return 0; } int data; }; static_assert (true, D {}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } @@ -37,13 +37,13 @@ static_assert (true, E {}); // { dg-warning "'static_assert' with non-string mes struct F { constexpr const char *size () const { return ""; } constexpr const char *data () const { return ""; } }; static_assert (true, F {}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } - // { dg-error "'static_assert' message 'size\\\(\\\)' must be implicitly convertible to 'std::size_t'" "" { target *-*-* } .-1 } + // { dg-error "constexpr string 'size\\\(\\\)' must be implicitly convertible to 'std::size_t'" "" { target *-*-* } .-1 } // { dg-error "could not convert 'F\\\(\\\).F::size\\\(\\\)' from 'const char\\\*' to '\[^']*'" "" { target *-*-* } .-2 } // { dg-error "conversion from 'const char\\\*' to '\[^']*' in a converted constant expression" "" { target *-*-* } .-3 } struct G { constexpr long size () const { return 0; } constexpr float data () const { return 0.0f; } }; static_assert (true, G {}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } - // { dg-error "'static_assert' message 'data\\\(\\\)' must be implicitly convertible to 'const char\\\*'" "" { target *-*-* } .-1 } + // { dg-error "constexpr string 'data\\\(\\\)' must be implicitly convertible to 'const char\\\*'" "" { target *-*-* } .-1 } // { dg-error "could not convert 'G\\\(\\\).G::data\\\(\\\)' from 'float' to 'const char\\\*'" "" { target *-*-* } .-2 } struct H { short size () const { return 0; } constexpr const char *data () const { return ""; } }; @@ -59,7 +59,7 @@ static_assert (true, J (1)); // { dg-warning "'static_assert' with non-string me static_assert (false, J (0)); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } // { dg-error "static assertion failed" "" { target *-*-* } .-1 } static_assert (false, J (1)); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } - // { dg-error "'static_assert' message 'size\\\(\\\)' must be a constant expression" "" { target *-*-* } .-1 } + // { dg-error "constexpr string 'size\\\(\\\)' must be a constant expression" "" { target *-*-* } .-1 } struct K { constexpr operator int () { return 4; } }; struct L { constexpr operator const char * () { return "test"; } }; struct M { constexpr K size () const { return {}; } @@ -72,7 +72,7 @@ struct N { constexpr int size () const { return 3; } constexpr const char *data () const { return new char[3] { 'b', 'a', 'd' }; } }; // { dg-error "'\\\* N\\\(\\\).N::data\\\(\\\)' is not a constant expression because allocated storage has not been deallocated" "" { target c++20 } } static_assert (true, N {}); // { dg-warning "'static_assert' with non-string message only available with" "" { target { c++20 && c++23_down } } } static_assert (false, N {}); // { dg-warning "'static_assert' with non-string message only available with" "" { target { c++20 && c++23_down } } } - // { dg-error "'static_assert' message 'data\\\(\\\)\\\[0\\\]' must be a constant expression" "" { target c++20 } .-1 } + // { dg-error "constexpr string 'data\\\(\\\)\\\[0\\\]' must be a constant expression" "" { target c++20 } .-1 } #endif constexpr const char a[] = { 't', 'e', 's', 't' }; struct O { constexpr int size () const { return 4; } @@ -133,7 +133,7 @@ static_assert (false, string_view (4, "testwithextrachars")); // { dg-warning "' // { dg-error "static assertion failed: test" "" { target *-*-* } .-1 } static_assert (false, string_view (42, "test")); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } // { dg-error "array subscript value '41' is outside the bounds of array type 'const char \\\[5\\\]'" "" { target *-*-* } .-1 } - // { dg-error "'static_assert' message 'data\\\(\\\)\\\[41\\\]' must be a constant expression" "" { target *-*-* } .-2 } + // { dg-error "constexpr string 'data\\\(\\\)\\\[41\\\]' must be a constant expression" "" { target *-*-* } .-2 } template struct array { @@ -143,7 +143,7 @@ struct array { }; static_assert (true, array { 'O', 'K' }); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } static_assert (true, array { L'O', L'K' }); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } - // { dg-error "'static_assert' message 'data\\\(\\\)' must be implicitly convertible to 'const char\\\*'" "" { target *-*-* } .-1 } + // { dg-error "constexpr string 'data\\\(\\\)' must be implicitly convertible to 'const char\\\*'" "" { target *-*-* } .-1 } // { dg-error "could not convert 'array{const wchar_t \\\[2\\\]{\[0-9]+, \[0-9]+}}.array::data\\\(\\\)' from 'const wchar_t\\\*' to 'const char\\\*'" "" { target *-*-* } .-2 } static_assert (false, array { 't', 'e', 's', 't' }); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } // { dg-error "static assertion failed: test" "" { target *-*-* } .-1 } @@ -235,7 +235,7 @@ namespace NN template struct G { static_assert (false, T{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } - }; // { dg-error "'static_assert' message must be a string literal or object with 'size' and 'data' members" "" { target *-*-* } .-1 } + }; // { dg-error "constexpr string must be a string literal or object with 'size' and 'data' members" "" { target *-*-* } .-1 } // { dg-error "request for member 'size' in '0', which is of non-class type 'long int'" "" { target *-*-* } .-2 } F fe; G gl; @@ -263,7 +263,7 @@ namespace NN static constexpr const char *data (int x = 0) { if (x) return nullptr; else throw 1; } }; // { dg-error "expression '' is not a constant expression" "" { target c++14 } } static_assert (true, J{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target { c++14 && c++23_down } } } static_assert (false, J{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target { c++14 && c++23_down } } } - // { dg-error "'static_assert' message 'data\\\(\\\)' must be a core constant expression" "" { target c++14 } .-1 } + // { dg-error "constexpr string 'data\\\(\\\)' must be a core constant expression" "" { target c++14 } .-1 } #endif #if __cpp_if_consteval >= 202106L struct K { @@ -286,14 +286,14 @@ namespace NN }; static_assert (true, M{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_only } } static_assert (false, M{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_only } } - // { dg-error "'static_assert' message 'size\\\(\\\)' must be a constant expression" "" { target c++23 } .-1 } + // { dg-error "'constexpr string 'size\\\(\\\)' must be a constant expression" "" { target c++23 } .-1 } struct N { static constexpr int size () { return 4; } static constexpr const char *data () { if consteval { throw 1; } else { return "test"; } } // { dg-error "expression '' is not a constant expression" "" { target c++23 } } }; static_assert (true, N{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_only } } static_assert (false, N{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_only } } - // { dg-error "'static_assert' message 'data\\\(\\\)\\\[0\\\]' must be a constant expression" "" { target c++23 } .-1 } + // { dg-error "'constexpr string 'data\\\(\\\)\\\[0\\\]' must be a constant expression" "" { target c++23 } .-1 } #endif struct O { constexpr int operator () () const { return 12; } }; struct P { constexpr const char *operator () () const { return "another test"; } };