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 883C93858D37 for ; Mon, 10 Oct 2022 20:15:08 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 883C93858D37 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=1665432908; 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: in-reply-to:in-reply-to:references:references; bh=5oCOc+JZQTNrmAABjMljn4rNIvTKHgQ/UB+mibZHv0g=; b=MvksnA7ZmApgpts3/ebirUK4m7O6rY97kTeql6OnJH0mRhEu7BxfZwpR4HuJ5t9qYQhxV0 1MZw1BOoZxqVWVwTwDTL6WoOyHHvs+2meBG/2MFGu0RFEcmfQz92PIABhwx4H6CgtWBKHF v2Ehy1tjaCkurrLQEbSGPCgYw3a8f3Y= Received: from mail-qt1-f198.google.com (mail-qt1-f198.google.com [209.85.160.198]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-138-gjCqKkHWPwmHhGZMcFS6TA-1; Mon, 10 Oct 2022 16:15:07 -0400 X-MC-Unique: gjCqKkHWPwmHhGZMcFS6TA-1 Received: by mail-qt1-f198.google.com with SMTP id ff14-20020a05622a4d8e00b00394aaf0f653so7434535qtb.19 for ; Mon, 10 Oct 2022 13:15:07 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:in-reply-to:from:content-language :references:to:subject:user-agent:mime-version:date:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=5oCOc+JZQTNrmAABjMljn4rNIvTKHgQ/UB+mibZHv0g=; b=SJZgYfIYlYYTkf9DH9R88QRwia1juc4UOVSO7mhJvkA7IdUuXlXZhscBVFUXSJQt1o 4HLGAPTvn5S64md5Kd1hl+a+nRXHeZt35EJlMQrK55Q5q8VYP+yH9orbLArUHYT9fDFb pMzm6VMNxCOI248RFdtJIbKjl2O2cZ/aeYSpEZJD1BUnqkl58f0qADPhAbOP80D5LbCy JGUWxCugONJ7gWzuEU/UsF3kmJ72gSwvaUM/0aDpxO9LleWaxFzJG7gfuFT3kmsFUMHb XcgY3VyQIO9jk+cg5JQITkMIV5FDLGCB3qpPv1xd3pBsFiLkzR+Da4NIc2xLc4xwKbH9 O19A== X-Gm-Message-State: ACrzQf1I7dGuz83eIAN9LoU6W3Zxp4hA77qImaB0h6WCKfU09dIWbi8p TuQ3TUZfxU4Lcl/SPAQr+xkgoi5HkFmSNvK15ait28N1n/PrkuSkxBnhDc8CD0vxdM7cWpeIz9Y nG9tPQitvB0NYiQY6rA== X-Received: by 2002:a05:622a:409:b0:35d:5a1e:888d with SMTP id n9-20020a05622a040900b0035d5a1e888dmr16680748qtx.561.1665432906057; Mon, 10 Oct 2022 13:15:06 -0700 (PDT) X-Google-Smtp-Source: AMsMyM4XTQCJ/g28DDUHoQH9FMosRou+BeWoBLlEnaT5tuIrYXcVyVHZt1eTg74M7ipWZLGaDovVhA== X-Received: by 2002:a05:622a:409:b0:35d:5a1e:888d with SMTP id n9-20020a05622a040900b0035d5a1e888dmr16680716qtx.561.1665432905571; Mon, 10 Oct 2022 13:15:05 -0700 (PDT) Received: from [192.168.1.101] (130-44-159-43.s15913.c3-0.arl-cbr1.sbo-arl.ma.cable.rcncustomer.com. [130.44.159.43]) by smtp.gmail.com with ESMTPSA id bs32-20020a05620a472000b006e54251993esm11009518qkb.97.2022.10.10.13.15.04 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 10 Oct 2022 13:15:04 -0700 (PDT) Message-ID: <09e3723a-de8c-edf2-35ce-14471c847805@redhat.com> Date: Mon, 10 Oct 2022 16:15:04 -0400 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.3.2 Subject: Re: [PATCH] c++: Remove maybe-rvalue OR in implicit move To: Marek Polacek , GCC Patches References: <20220928212634.1275032-1-polacek@redhat.com> From: Jason Merrill In-Reply-To: <20220928212634.1275032-1-polacek@redhat.com> X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Language: en-US Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-13.6 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,NICE_REPLY_A,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_NONE,TXREP 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: On 9/28/22 17:26, Marek Polacek wrote: > This patch removes the two-stage overload resolution when performing > implicit move, whereby the compiler does two separate overload resolutions: > one treating the operand as an rvalue, and then (if that resolution fails) > another one treating the operand as an lvalue. In the standard this was > introduced via CWG 1579 and implemented in gcc in r251035. In r11-2412, > we disabled the fallback OR in C++20 (but not in C++17). Then C++23 P2266 > removed the fallback overload resolution, and changed the implicit move rules > once again. So we wound up with three different behaviors. > > The two overload resolutions approach was complicated and quirky, so > users should transition to the newer model. Removing the maybe-rvalue > OR also allows us to simplify our code, for instance, now we can get > rid of LOOKUP_PREFER_RVALUE altogether. > > This change means that code that previously didn't compile in C++17 will > now compile, for example: > > struct S1 { S1(S1 &&); }; > struct S2 : S1 {}; > > S1 > f (S2 s) > { > return s; // OK, derived-to-base, use S1::S1(S1&&) > } > > And conversely, code that used to work in C++17 may not compile anymore: > > struct W { > W(); > }; > > struct F { > F(W&); > F(W&&) = delete; > }; > > F fn () > { > W w; > return w; // use w as rvalue -> use of deleted function F::F(W&&) > } > > I plan to add a note to porting_to.html. It surprises me that this was a change: I guess it depends on how you interpret the old wording's "if the overload resolution fails". I vaguely remember there being a bug report about this, before the new approach made it moot. > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? OK with the comment tweaks below: > gcc/cp/ChangeLog: > > * call.cc (standard_conversion): Remove LOOKUP_PREFER_RVALUE code. > (reference_binding): Honor clk_implicit_rval even pre-C++20. > (implicit_conversion_1): Remove LOOKUP_PREFER_RVALUE code. > (build_user_type_conversion_1): Likewise. > (convert_like_internal): Likewise. > (build_over_call): Likewise. > * cp-tree.h (LOOKUP_PREFER_RVALUE): Remove. > (LOOKUP_NO_NARROWING): Adjust definition. > * except.cc (build_throw): Don't perform two overload resolutions. > * typeck.cc (maybe_warn_pessimizing_move): Don't use > LOOKUP_PREFER_RVALUE. > (check_return_expr): Don't perform two overload resolutions. > > gcc/testsuite/ChangeLog: > > * g++.dg/cpp0x/Wredundant-move10.C: Adjust dg-warning. > * g++.dg/cpp0x/Wredundant-move7.C: Likewise. > * g++.dg/cpp0x/move-return2.C: Remove dg-error. > * g++.dg/cpp0x/move-return4.C: Likewise. > * g++.dg/cpp0x/ref-qual20.C: Adjust expected return value. > * g++.dg/cpp0x/move-return5.C: New test. > --- > gcc/cp/call.cc | 41 ++----------------- > gcc/cp/cp-tree.h | 6 +-- > gcc/cp/except.cc | 23 ++--------- > gcc/cp/typeck.cc | 34 +++------------ > .../g++.dg/cpp0x/Wredundant-move10.C | 2 +- > gcc/testsuite/g++.dg/cpp0x/Wredundant-move7.C | 6 +-- > gcc/testsuite/g++.dg/cpp0x/move-return2.C | 2 +- > gcc/testsuite/g++.dg/cpp0x/move-return4.C | 2 +- > gcc/testsuite/g++.dg/cpp0x/move-return5.C | 20 +++++++++ > gcc/testsuite/g++.dg/cpp0x/ref-qual20.C | 2 +- > 10 files changed, 41 insertions(+), 97 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/cpp0x/move-return5.C > > diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc > index 3506b0fcfbb..e100913ea29 100644 > --- a/gcc/cp/call.cc > +++ b/gcc/cp/call.cc > @@ -1272,9 +1272,6 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p, > } > } > conv = build_conv (ck_rvalue, from, conv); > - if (flags & LOOKUP_PREFER_RVALUE) > - /* Tell convert_like to set LOOKUP_PREFER_RVALUE. */ > - conv->rvaluedness_matches_p = true; > /* If we're performing copy-initialization, remember to skip > explicit constructors. */ > if (flags & LOOKUP_ONLYCONVERTING) > @@ -1572,9 +1569,6 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p, > type. A temporary object is created to hold the result of > the conversion unless we're binding directly to a reference. */ > conv->need_temporary_p = !(flags & LOOKUP_NO_TEMP_BIND); > - if (flags & LOOKUP_PREFER_RVALUE) > - /* Tell convert_like to set LOOKUP_PREFER_RVALUE. */ > - conv->rvaluedness_matches_p = true; > /* If we're performing copy-initialization, remember to skip > explicit constructors. */ > if (flags & LOOKUP_ONLYCONVERTING) > @@ -1883,7 +1877,7 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags, > /* Unless it's really a C++20 lvalue being treated as an xvalue. > But in C++23, such an expression is just an xvalue, not a special > lvalue, so the binding is once again ill-formed. */ > - && !(cxx_dialect == cxx20 > + && !(cxx_dialect <= cxx20 > && (gl_kind & clk_implicit_rval)) > && (!CP_TYPE_CONST_NON_VOLATILE_P (to) > || (flags & LOOKUP_NO_RVAL_BIND)) > @@ -2044,9 +2038,8 @@ implicit_conversion_1 (tree to, tree from, tree expr, bool c_cast_p, > /* Other flags only apply to the primary function in overload > resolution, or after we've chosen one. */ > flags &= (LOOKUP_ONLYCONVERTING|LOOKUP_NO_CONVERSION|LOOKUP_COPY_PARM > - |LOOKUP_NO_TEMP_BIND|LOOKUP_NO_RVAL_BIND|LOOKUP_PREFER_RVALUE > - |LOOKUP_NO_NARROWING|LOOKUP_PROTECT|LOOKUP_NO_NON_INTEGRAL > - |LOOKUP_SHORTCUT_BAD_CONVS); > + |LOOKUP_NO_TEMP_BIND|LOOKUP_NO_RVAL_BIND|LOOKUP_NO_NARROWING > + |LOOKUP_PROTECT|LOOKUP_NO_NON_INTEGRAL|LOOKUP_SHORTCUT_BAD_CONVS); > > /* FIXME: actually we don't want warnings either, but we can't just > have 'complain &= ~(tf_warning|tf_error)' because it would cause > @@ -4451,14 +4444,6 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags, > if (cand->viable == -1) > conv->bad_p = true; > > - /* We're performing the maybe-rvalue overload resolution and > - a conversion function is in play. Reject converting the return > - value of the conversion function to a base class. */ > - if ((flags & LOOKUP_PREFER_RVALUE) && !DECL_CONSTRUCTOR_P (cand->fn)) > - for (conversion *t = cand->second_conv; t; t = next_conversion (t)) > - if (t->kind == ck_base) > - return NULL; > - > /* Remember that this was a list-initialization. */ > if (flags & LOOKUP_NO_NARROWING) > conv->check_narrowing = true; > @@ -8281,9 +8266,6 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum, > explicit constructors. */ > if (convs->copy_init_p) > flags |= LOOKUP_ONLYCONVERTING; > - if (convs->rvaluedness_matches_p) > - /* standard_conversion got LOOKUP_PREFER_RVALUE. */ > - flags |= LOOKUP_PREFER_RVALUE; > expr = build_temp (expr, totype, flags, &diag_kind, complain); > if (diag_kind && complain) > { > @@ -9529,23 +9511,6 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) > ++arg_index; > parm = TREE_CHAIN (parm); > } > - > - if (cxx_dialect < cxx20 > - && (cand->flags & LOOKUP_PREFER_RVALUE)) > - { > - /* The implicit move specified in 15.8.3/3 fails "...if the type of > - the first parameter of the selected constructor is not an rvalue > - reference to the object's type (possibly cv-qualified)...." */ > - gcc_assert (!(complain & tf_error)); > - tree ptype = convs[0]->type; > - /* Allow calling a by-value converting constructor even though it > - isn't permitted by the above, because we've allowed it since GCC 5 > - (PR58051) and it's allowed in C++20. But don't call a copy > - constructor. */ > - if ((TYPE_REF_P (ptype) && !TYPE_REF_IS_RVALUE (ptype)) > - || CONVERSION_RANK (convs[0]) > cr_exact) > - return error_mark_node; > - } > } > /* Bypass access control for 'this' parameter. */ > else if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE) > diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h > index d0f1b18b015..7acb5373513 100644 > --- a/gcc/cp/cp-tree.h > +++ b/gcc/cp/cp-tree.h > @@ -5853,12 +5853,8 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG }; > #define LOOKUP_DESTRUCTOR (1 << 5) > /* Do not permit references to bind to temporaries. */ > #define LOOKUP_NO_TEMP_BIND (1 << 6) > -/* We're trying to treat an lvalue as an rvalue. */ > -/* FIXME remove when we extend the P1825 semantics to all standard modes, the > - C++20 approach uses IMPLICIT_RVALUE_P instead. */ > -#define LOOKUP_PREFER_RVALUE (LOOKUP_NO_TEMP_BIND << 1) > /* We're inside an init-list, so narrowing conversions are ill-formed. */ > -#define LOOKUP_NO_NARROWING (LOOKUP_PREFER_RVALUE << 1) > +#define LOOKUP_NO_NARROWING (LOOKUP_NO_TEMP_BIND << 1) > /* We're looking up a constructor for list-initialization. */ > #define LOOKUP_LIST_INIT_CTOR (LOOKUP_NO_NARROWING << 1) > /* This is the first parameter of a copy constructor. */ > diff --git a/gcc/cp/except.cc b/gcc/cp/except.cc > index 048612de400..1d84b451c9f 100644 > --- a/gcc/cp/except.cc > +++ b/gcc/cp/except.cc > @@ -715,25 +715,10 @@ build_throw (location_t loc, tree exp) > treated as an rvalue for the purposes of overload resolution > to favor move constructors over copy constructors. */ > if (tree moved = treat_lvalue_as_rvalue_p (exp, /*return*/false)) > - { > - if (cxx_dialect < cxx20) > - { > - releasing_vec exp_vec (make_tree_vector_single (moved)); > - moved = (build_special_member_call > - (object, complete_ctor_identifier, &exp_vec, > - TREE_TYPE (object), flags|LOOKUP_PREFER_RVALUE, > - tf_none)); > - if (moved != error_mark_node) > - { > - exp = moved; > - converted = true; > - } > - } > - else > - /* In C++20 we just treat the return value as an rvalue that > - can bind to lvalue refs. */ > - exp = moved; > - } > + /* In C++20 we just treat the return value as an rvalue that Let's remove the above "just" since we're removing the more complicated code it's contrasting with. > + can bind to lvalue refs. In C++23, such an expression is just > + an xvalue. */ > + exp = moved; > > /* Call the copy constructor. */ > if (!converted) > diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc > index 5f16c4d2426..c525e880383 100644 > --- a/gcc/cp/typeck.cc > +++ b/gcc/cp/typeck.cc > @@ -10692,21 +10692,12 @@ maybe_warn_pessimizing_move (tree expr, tree type, bool return_p) > tree t = convert_for_initialization (NULL_TREE, type, > moved, > (LOOKUP_NORMAL > - | LOOKUP_ONLYCONVERTING > - | LOOKUP_PREFER_RVALUE), > + | LOOKUP_ONLYCONVERTING), > ICR_RETURN, NULL_TREE, 0, > tf_none); > /* If this worked, implicit rvalue would work, so the call to > std::move is redundant. */ > - if (t != error_mark_node > - /* Trying to move something const will never succeed unless > - there's T(const T&&), which it almost never is, and if > - so, T wouldn't be error_mark_node now: the above convert_ > - call with LOOKUP_PREFER_RVALUE returns an error if a const T& > - overload is selected. */ > - || (CP_TYPE_CONST_P (TREE_TYPE (arg)) > - && same_type_ignoring_top_level_qualifiers_p > - (TREE_TYPE (arg), type))) > + if (t != error_mark_node) > { > auto_diagnostic_group d; > if (warning_at (loc, OPT_Wredundant_move, > @@ -11049,23 +11040,10 @@ check_return_expr (tree retval, bool *no_warning) > ? CLASS_TYPE_P (functype) > : !SCALAR_TYPE_P (functype) || !SCALAR_TYPE_P (TREE_TYPE (retval))) > && (moved = treat_lvalue_as_rvalue_p (retval, /*return*/true))) > - { > - if (cxx_dialect < cxx20) > - { > - moved = convert_for_initialization > - (NULL_TREE, functype, moved, flags|LOOKUP_PREFER_RVALUE, > - ICR_RETURN, NULL_TREE, 0, tf_none); > - if (moved != error_mark_node) > - { > - retval = moved; > - converted = true; > - } > - } > - else > - /* In C++20 we just treat the return value as an rvalue that > - can bind to lvalue refs. */ > - retval = moved; > - } > + /* In C++20 and earlier we just treat the return value as an rvalue Here, too. > + that can bind to lvalue refs. In C++23, such an expression is just > + an xvalue (see reference_binding). */ > + retval = moved; > > /* The call in a (lambda) thunk needs no conversions. */ > if (TREE_CODE (retval) == CALL_EXPR > diff --git a/gcc/testsuite/g++.dg/cpp0x/Wredundant-move10.C b/gcc/testsuite/g++.dg/cpp0x/Wredundant-move10.C > index a215a4774d6..17dd807aea8 100644 > --- a/gcc/testsuite/g++.dg/cpp0x/Wredundant-move10.C > +++ b/gcc/testsuite/g++.dg/cpp0x/Wredundant-move10.C > @@ -57,5 +57,5 @@ struct S2: S1 {}; > > S1 f3(const S2 s) > { > - return std::move(s); // { dg-warning "redundant move" "" { target c++20 } } > + return std::move(s); // { dg-warning "redundant move" } > } > diff --git a/gcc/testsuite/g++.dg/cpp0x/Wredundant-move7.C b/gcc/testsuite/g++.dg/cpp0x/Wredundant-move7.C > index 3fec525879d..6547777c007 100644 > --- a/gcc/testsuite/g++.dg/cpp0x/Wredundant-move7.C > +++ b/gcc/testsuite/g++.dg/cpp0x/Wredundant-move7.C > @@ -28,7 +28,7 @@ struct S2 : S1 {}; > S1 > f (S2 s) > { > - return std::move(s); // { dg-warning "redundant move in return statement" "" { target c++20 } } > + return std::move(s); // { dg-warning "redundant move in return statement" } > } > > struct R1 { > @@ -40,7 +40,7 @@ struct R2 : R1 {}; > R1 > f2 (const R2 s) > { > - return std::move(s); // { dg-warning "redundant move in return statement" "" { target c++20 } } > + return std::move(s); // { dg-warning "redundant move in return statement" } > } > > struct T1 { > @@ -55,5 +55,5 @@ f3 (const T2 s) > { > // Without std::move: const T1 & > // With std::move: const T1 && > - return std::move(s); // { dg-warning "redundant move in return statement" "" { target c++20 } } > + return std::move(s); // { dg-warning "redundant move in return statement" } > } > diff --git a/gcc/testsuite/g++.dg/cpp0x/move-return2.C b/gcc/testsuite/g++.dg/cpp0x/move-return2.C > index 999f2c95c49..8e750efb870 100644 > --- a/gcc/testsuite/g++.dg/cpp0x/move-return2.C > +++ b/gcc/testsuite/g++.dg/cpp0x/move-return2.C > @@ -7,5 +7,5 @@ struct S2 : S1 {}; > S1 > f (S2 s) > { > - return s; // { dg-error "use of deleted function" "" { target c++17_down } } > + return s; > } > diff --git a/gcc/testsuite/g++.dg/cpp0x/move-return4.C b/gcc/testsuite/g++.dg/cpp0x/move-return4.C > index 3fc58089319..0f0ca1fc253 100644 > --- a/gcc/testsuite/g++.dg/cpp0x/move-return4.C > +++ b/gcc/testsuite/g++.dg/cpp0x/move-return4.C > @@ -13,5 +13,5 @@ struct A : Base > A foo() > { > A v; > - return v; // { dg-error "cannot bind rvalue reference" "" { target c++17_down } } > + return v; > } > diff --git a/gcc/testsuite/g++.dg/cpp0x/move-return5.C b/gcc/testsuite/g++.dg/cpp0x/move-return5.C > new file mode 100644 > index 00000000000..695000b2687 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp0x/move-return5.C > @@ -0,0 +1,20 @@ > +// { dg-do compile { target c++11 } } > +// This used to compile in C++11...17 because we performed two > +// separate overload resolutions: one treating the operand as > +// an rvalue, and then (if that resolution fails) another one > +// treating the operand as an lvalue. > + > +struct W { > + W(); > +}; > + > +struct F { > + F(W&); > + F(W&&) = delete; > +}; > + > +F fn () > +{ > + W w; > + return w; // { dg-error "use of deleted function" } > +} > diff --git a/gcc/testsuite/g++.dg/cpp0x/ref-qual20.C b/gcc/testsuite/g++.dg/cpp0x/ref-qual20.C > index cfbef300226..314f19bb864 100644 > --- a/gcc/testsuite/g++.dg/cpp0x/ref-qual20.C > +++ b/gcc/testsuite/g++.dg/cpp0x/ref-qual20.C > @@ -52,7 +52,7 @@ f5 () > int > main () > { > - int return_lval = __cplusplus > 201703L ? -1 : 2; > + int return_lval = -1; > Y y1 = f (A()); > if (y1.y != return_lval) > __builtin_abort (); > > base-commit: 9f65eecdbef6027722e93aadf3fa6b3cc342eb4f