From patchwork Tue Feb 25 12:40:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Wakely X-Patchwork-Id: 1244147 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-520077-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha1 header.s=default header.b=Vgkperd7; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=guVhV/Cf; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48RdpW2szrz9sPk for ; Tue, 25 Feb 2020 23:41:22 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; q=dns; s= default; b=Uuf3/ZdlFwzsx9KR34M4ZE7UpfM9W/hHeMRZJ7+xMx4D0ijCxZ5MU UvHvNUkvyguqOc+Sho7TCGRsrm9hTpHIEgE0KyOwbtniGl8hoQDPH+LWSZjGdRNr 6uSqhYXV5qGoOwo2vqNrSu60kMQOMXLjACSWX8VCKghScjzA9uFxJU= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; s= default; bh=t5KTKZ00y7lHnaJG7XUdFjIuJSI=; b=Vgkperd73gYxSqNIHRHG mcCX5JjFhB8SF/LrPgwTwUwhK8nZlYNeVFlt3zWp5ER9nOPA/PVXycwNkv/3sanh ht3RtSXFQH0yoDDyeZTa8h7in0PfbFbqMjbLswnZDpNYpfx1/umehg0pMYG4He2+ ccgNrUkvcRx6twCiyBGqwi0= Received: (qmail 95684 invoked by alias); 25 Feb 2020 12:41:09 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 95670 invoked by uid 89); 25 Feb 2020 12:41:08 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-18.2 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 spammy= X-HELO: us-smtp-1.mimecast.com Received: from us-smtp-delivery-1.mimecast.com (HELO us-smtp-1.mimecast.com) (205.139.110.120) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 25 Feb 2020 12:41:04 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1582634463; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type; bh=kYJ5Au7KpyW2e8MaCs2dcSwbCtGN2kmoCoR70yjINY0=; b=guVhV/CfuPmrcjLv4bg9mzsxY05uT9bnEu3iYiVVQb0g1R+Un3XtGH2Cc/VH5/EqtSE84w Gm9xbe+TjapqBnPPJvmrJLzBR9Klux0LHao5rxCZx7pmtQsb2npR1f0AZEap4gqMJ4eFwM RTbmxfLl2LZO97VBrYW0TN+2rqnGnf8= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-160-ND_Nfv-IMEWFTba2_eFrcQ-1; Tue, 25 Feb 2020 07:40:58 -0500 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id F28C4107ACC5; Tue, 25 Feb 2020 12:40:57 +0000 (UTC) Received: from localhost (unknown [10.33.36.96]) by smtp.corp.redhat.com (Postfix) with ESMTP id A0A595C241; Tue, 25 Feb 2020 12:40:57 +0000 (UTC) Date: Tue, 25 Feb 2020 12:40:56 +0000 From: Jonathan Wakely To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [committed] libstdc++: Fix regression in std::move algorithm (PR 93872) Message-ID: <20200225124056.GA2337630@redhat.com> MIME-Version: 1.0 X-Clacks-Overhead: GNU Terry Pratchett X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline The std::move and std::move_backward algorithms dispatch to the std::__memmove helper when appropriate. That function uses a pointer-to-const for the source values, preventing them from being moved. The two callers of that function have the same problem. Rather than altering __memmove and its callers to work with const or non-const source pointers, this takes a more conservative approach of casting away the const at the point where we want to do a move assignment. This relies on the fact that we only use __memmove when the type is trivially copyable, so we know the move assignment doesn't alter the source anyway. PR libstdc++/93872 * include/bits/stl_algobase.h (__memmove): Cast away const before doing move assignment. * testsuite/25_algorithms/move/93872.cc: New test. * testsuite/25_algorithms/move_backward/93872.cc: New test. Tested powerpc64le-linux, committed to master. commit 5b904f175ff26269615f148459a8604f45880591 Author: Jonathan Wakely Date: Tue Feb 25 12:21:44 2020 +0000 libstdc++: Fix regression in std::move algorithm (PR 93872) The std::move and std::move_backward algorithms dispatch to the std::__memmove helper when appropriate. That function uses a pointer-to-const for the source values, preventing them from being moved. The two callers of that function have the same problem. Rather than altering __memmove and its callers to work with const or non-const source pointers, this takes a more conservative approach of casting away the const at the point where we want to do a move assignment. This relies on the fact that we only use __memmove when the type is trivially copyable, so we know the move assignment doesn't alter the source anyway. PR libstdc++/93872 * include/bits/stl_algobase.h (__memmove): Cast away const before doing move assignment. * testsuite/25_algorithms/move/93872.cc: New test. * testsuite/25_algorithms/move_backward/93872.cc: New test. diff --git a/libstdc++-v3/include/bits/stl_algobase.h b/libstdc++-v3/include/bits/stl_algobase.h index efda15f816e..c6b7148b39c 100644 --- a/libstdc++-v3/include/bits/stl_algobase.h +++ b/libstdc++-v3/include/bits/stl_algobase.h @@ -95,7 +95,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION for(; __num > 0; --__num) { if constexpr (_IsMove) - *__dst = std::move(*__src); + // This const_cast looks unsafe, but we only use this function + // for trivially-copyable types, which means this assignment + // is trivial and so doesn't alter the source anyway. + // See PR 93872 for why it's needed. + *__dst = std::move(*const_cast<_Tp*>(__src)); else *__dst = *__src; ++__src; diff --git a/libstdc++-v3/testsuite/25_algorithms/move/93872.cc b/libstdc++-v3/testsuite/25_algorithms/move/93872.cc new file mode 100644 index 00000000000..c4dd43dfb64 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/move/93872.cc @@ -0,0 +1,39 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option) +// any later version. + +// This library 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 this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include + +struct X +{ + X() = default; + + X(const X&) = delete; + X& operator=(const X&) = delete; + + X(X&&) = default; + X& operator=(X&&) = default; +}; + +void +test01() +{ + X a[2], b[2]; + std::move(std::begin(a), std::end(a), std::begin(b)); +}