From patchwork Sat Nov 9 12:38:23 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Wakely X-Patchwork-Id: 289990 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 691922C0095 for ; Sat, 9 Nov 2013 23:39:03 +1100 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:date:message-id:subject:from:to:content-type; q= dns; s=default; b=gVV5+QoeJ+F72MGo9acl02XChq+PeYSwQdLojzFRSShYzA CyjqxMojNrsql0EAzXsXZcJTRMsdRPB/sDPQj3+W36USq17zoKCA+VmPrGN7reRN hqOd4wIJwS1VfpA+OQ7WJEz5eH7UMp9ZE4uIHL1ehBlw4l03xPKf+n5JfYaNQ= 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 :mime-version:date:message-id:subject:from:to:content-type; s= default; bh=7n0JixDeymqKbhW3ES8T1DKCAag=; b=YjSgOII6GWwFVZf5dWOq 30nWlNCGL/Z3jkiDub3It7vyyoVpmfrQqPa8YGxPFLI7Zo9hfPUvt+JrxrX9aJob +V8eeCb5k7bsXdc8+7fdVSofG1CLiD73JBJ3fR2doAUCMPcCU3XRjoXGLM6O9yOs GvhcbivIzqxkUrXYcYhuc4g= Received: (qmail 32043 invoked by alias); 9 Nov 2013 12:38:53 -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 32024 invoked by uid 89); 9 Nov 2013 12:38:53 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.0 required=5.0 tests=AWL, BAYES_40, FREEMAIL_FROM, RDNS_NONE, SPF_PASS, URIBL_BLOCKED autolearn=no version=3.3.2 X-Spam-User: qpsmtpd, 2 recipients X-HELO: mail-lb0-f170.google.com Received: from Unknown (HELO mail-lb0-f170.google.com) (209.85.217.170) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Sat, 09 Nov 2013 12:38:33 +0000 Received: by mail-lb0-f170.google.com with SMTP id u14so2191625lbd.29 for ; Sat, 09 Nov 2013 04:38:23 -0800 (PST) MIME-Version: 1.0 X-Received: by 10.112.154.129 with SMTP id vo1mr3626583lbb.31.1384000703527; Sat, 09 Nov 2013 04:38:23 -0800 (PST) Received: by 10.112.173.195 with HTTP; Sat, 9 Nov 2013 04:38:23 -0800 (PST) Date: Sat, 9 Nov 2013 12:38:23 +0000 Message-ID: Subject: [patch] fix libstdc++/58982 From: Jonathan Wakely To: "libstdc++" , gcc-patches This ensures we do not optimize a std::copy() of trivial types to memmove() if the unoptimized form would be ill-formed because the type isn't assignable, and similarly does not optimize std::uninitialized_xxx() on trivial types to simple assignment when the type isn't assignable. This fixes the regression with std::vector> v(1). 2013-11-09 Jonathan Wakely PR libstdc++/58982 * include/bits/stl_algobase.h (__copy_move::__copy_m): Use assertion to prevent using memmove() on non-assignable types. (__copy_move_backward::__copy_move_b): Likewise. * include/bits/stl_uninitialized.h (uninitialized_copy uninitialized_copy_n, uninitialized_fill, uninitialized_fill_n, __uninitialized_default, __uninitialized_default_n): Check for assignable as well as trivial. * testsuite/20_util/specialized_algorithms/uninitialized_copy/ 58982.cc: New. * testsuite/20_util/specialized_algorithms/uninitialized_copy_n/ 58982.cc: New. * testsuite/20_util/specialized_algorithms/uninitialized_fill/ 58982.cc: New. * testsuite/20_util/specialized_algorithms/uninitialized_fill_n/ 58982.cc: New. * testsuite/25_algorithms/copy/58982.cc: New. * testsuite/25_algorithms/copy_n/58982.cc: New. Tested x86_64-linux, committed to trunk. commit 95e9f1601e94f168cf4594d3d7854c0ed8c285b8 Author: Jonathan Wakely Date: Sat Nov 9 12:14:00 2013 +0000 PR libstdc++/58982 * include/bits/stl_algobase.h (__copy_move::__copy_m): Use assertion to prevent using memmove() on non-assignable types. (__copy_move_backward::__copy_move_b): Likewise. * include/bits/stl_uninitialized.h (uninitialized_copy uninitialized_copy_n, uninitialized_fill, uninitialized_fill_n, __uninitialized_default, __uninitialized_default_n): Check for assignable as well as trivial. * testsuite/20_util/specialized_algorithms/uninitialized_copy/ 58982.cc: New. * testsuite/20_util/specialized_algorithms/uninitialized_copy_n/ 58982.cc: New. * testsuite/20_util/specialized_algorithms/uninitialized_fill/ 58982.cc: New. * testsuite/20_util/specialized_algorithms/uninitialized_fill_n/ 58982.cc: New. * testsuite/25_algorithms/copy/58982.cc: New. * testsuite/25_algorithms/copy_n/58982.cc: New. diff --git a/libstdc++-v3/include/bits/stl_algobase.h b/libstdc++-v3/include/bits/stl_algobase.h index a7432da..5c7db5b 100644 --- a/libstdc++-v3/include/bits/stl_algobase.h +++ b/libstdc++-v3/include/bits/stl_algobase.h @@ -368,6 +368,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static _Tp* __copy_m(const _Tp* __first, const _Tp* __last, _Tp* __result) { +#if __cplusplus >= 201103L + // trivial types can have deleted assignment + static_assert( is_copy_assignable<_Tp>::value, + "type is not assignable" ); +#endif const ptrdiff_t _Num = __last - __first; if (_Num) __builtin_memmove(__result, __first, sizeof(_Tp) * _Num); @@ -563,6 +568,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static _Tp* __copy_move_b(const _Tp* __first, const _Tp* __last, _Tp* __result) { +#if __cplusplus >= 201103L + // trivial types can have deleted assignment + static_assert( is_copy_assignable<_Tp>::value, + "type is not assignable" ); +#endif const ptrdiff_t _Num = __last - __first; if (_Num) __builtin_memmove(__result - _Num, __first, sizeof(_Tp) * _Num); diff --git a/libstdc++-v3/include/bits/stl_uninitialized.h b/libstdc++-v3/include/bits/stl_uninitialized.h index 310b162..e45046b 100644 --- a/libstdc++-v3/include/bits/stl_uninitialized.h +++ b/libstdc++-v3/include/bits/stl_uninitialized.h @@ -111,9 +111,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _ValueType1; typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType2; +#if __cplusplus < 201103L + const bool __assignable = true; +#else + // trivial types can have deleted assignment + typedef typename iterator_traits<_InputIterator>::reference _RefType; + const bool __assignable = is_assignable<_ValueType1, _RefType>::value; +#endif - return std::__uninitialized_copy<(__is_trivial(_ValueType1) - && __is_trivial(_ValueType2))>:: + return std::__uninitialized_copy<__is_trivial(_ValueType1) + && __is_trivial(_ValueType2) + && __assignable>:: __uninit_copy(__first, __last, __result); } @@ -166,8 +174,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; +#if __cplusplus < 201103L + const bool __assignable = true; +#else + // trivial types can have deleted assignment + const bool __assignable = is_copy_assignable<_ValueType>::value; +#endif - std::__uninitialized_fill<__is_trivial(_ValueType)>:: + std::__uninitialized_fill<__is_trivial(_ValueType) && __assignable>:: __uninit_fill(__first, __last, __x); } @@ -219,8 +233,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; +#if __cplusplus < 201103L + const bool __assignable = true; +#else + // trivial types can have deleted assignment + const bool __assignable = is_copy_assignable<_ValueType>::value; +#endif - std::__uninitialized_fill_n<__is_trivial(_ValueType)>:: + std::__uninitialized_fill_n<__is_trivial(_ValueType) && __assignable>:: __uninit_fill_n(__first, __n, __x); } @@ -526,8 +546,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; + // trivial types can have deleted assignment + const bool __assignable = is_copy_assignable<_ValueType>::value; - std::__uninitialized_default_1<__is_trivial(_ValueType)>:: + std::__uninitialized_default_1<__is_trivial(_ValueType) + && __assignable>:: __uninit_default(__first, __last); } @@ -539,8 +562,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; + // trivial types can have deleted assignment + const bool __assignable = is_copy_assignable<_ValueType>::value; - std::__uninitialized_default_n_1<__is_trivial(_ValueType)>:: + std::__uninitialized_default_n_1<__is_trivial(_ValueType) + && __assignable>:: __uninit_default_n(__first, __n); } diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/58982.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/58982.cc new file mode 100644 index 0000000..7e059a3 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/58982.cc @@ -0,0 +1,41 @@ +// Copyright (C) 2013 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 +// . + +// 20.7.12 specialized algorithms + +// { dg-options "-std=gnu++11" } +// { dg-do compile } + +#include + +// libstdc++/58982 + +// trivial class that is not assignable +struct T +{ + T() = default; + ~T() = default; + + T& operator=(const T&) = delete; +}; + +void +test01(T* result) +{ + T t[1]; + std::uninitialized_copy(t, t+1, result); +} diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy_n/58982.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy_n/58982.cc new file mode 100644 index 0000000..e10b31a --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy_n/58982.cc @@ -0,0 +1,41 @@ +// Copyright (C) 2013 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 +// . + +// 20.7.12 specialized algorithms + +// { dg-options "-std=gnu++11" } +// { dg-do compile } + +#include + +// libstdc++/58982 + +// trivial class that is not assignable +struct T +{ + T() = default; + ~T() = default; + + T& operator=(const T&) = delete; +}; + +void +test01(T* result) +{ + T t[1]; + std::uninitialized_copy_n(t, 1, result); +} diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_fill/58982.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_fill/58982.cc new file mode 100644 index 0000000..012e2c6 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_fill/58982.cc @@ -0,0 +1,41 @@ +// Copyright (C) 2013 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 +// . + +// 20.7.12 specialized algorithms + +// { dg-options "-std=gnu++11" } +// { dg-do compile } + +#include + +// libstdc++/58982 + +// trivial class that is not assignable +struct T +{ + T() = default; + ~T() = default; + + T& operator=(const T&) = delete; +}; + +void +test01(T* first, T* last) +{ + T t; + std::uninitialized_fill(first, last, t); +} diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_fill_n/58982.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_fill_n/58982.cc new file mode 100644 index 0000000..606c632 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_fill_n/58982.cc @@ -0,0 +1,41 @@ +// Copyright (C) 2013 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 +// . + +// 20.7.12 specialized algorithms + +// { dg-options "-std=gnu++11" } +// { dg-do compile } + +#include + +// libstdc++/58982 + +// trivial class that is not assignable +struct T +{ + T() = default; + ~T() = default; + + T& operator=(const T&) = delete; +}; + +void +test01(T* first) +{ + T t; + std::uninitialized_fill_n(first, 1, t); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/copy/58982.cc b/libstdc++-v3/testsuite/25_algorithms/copy/58982.cc new file mode 100644 index 0000000..58ece1b --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/copy/58982.cc @@ -0,0 +1,42 @@ +// Copyright (C) 2013 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 +// . + +// 25.3.1 copy + +// { dg-options "-std=gnu++11" } +// { dg-do compile } + +#include + +// libstdc++/58982 + +// trivial class that is not assignable +struct T +{ + T() = default; + ~T() = default; + + T& operator=(const T&) = delete; +}; + +void +test01(T* result) +{ + T t[1]; + std::copy(t, t+1, result); // { dg-error "here" } +} +// { dg-prune-output "not assignable" } diff --git a/libstdc++-v3/testsuite/25_algorithms/copy_n/58982.cc b/libstdc++-v3/testsuite/25_algorithms/copy_n/58982.cc new file mode 100644 index 0000000..f7dfa59 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/copy_n/58982.cc @@ -0,0 +1,42 @@ +// Copyright (C) 2013 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 +// . + +// 25.3.1 copy + +// { dg-options "-std=gnu++11" } +// { dg-do compile } + +#include + +// libstdc++/58982 + +// trivial class that is not assignable +struct T +{ + T() = default; + ~T() = default; + + T& operator=(const T&) = delete; +}; + +void +test01(T* result) +{ + T t[1]; + std::copy_n(t, 1, result); // { dg-error "here" } +} +// { dg-prune-output "not assignable" }