From patchwork Sat Nov 3 14:43:56 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Fran=C3=A7ois_Dumont?= X-Patchwork-Id: 196846 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]) by ozlabs.org (Postfix) with SMTP id 24FFF2C00BE for ; Sun, 4 Nov 2012 01:44:20 +1100 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1352558661; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Received:Message-ID:Date:From:User-Agent:MIME-Version:To:CC: Subject:References:In-Reply-To:Content-Type:Mailing-List: Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:Sender:Delivered-To; bh=LSUhOzOCn6rILFQogxjGzejeSMw=; b=gWhfws9MXuicfbX6LjeTKhlCTH1p/j2nV04Frr/9EclRypu3XzJKLGXBH/IUK8 VeLG5Q/+uslyuRYhlxFr9LXIweC1i6pdBAqpS3vLr8B7Yo3UbImFu8Lz9wGhn3aA rTxssGKBk6bubiExi8+m1XWsU0Yt07MlgrRvg7v+NFH/Q= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:Received:Received:Message-ID:Date:From:User-Agent:MIME-Version:To:CC:Subject:References:In-Reply-To:Content-Type:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=Q+RnVRHT4nR81QY2ITmuMGm4cb/CuEXKJeGY9gG9OYHCWT8HU7ICTBaUNlPe99 mLGLS1PG7ALvfglMkOJsQuHGIi3BViCoCpxgDiVkt1zuEUJKzLbvKz95Cx0/A9Z2 uX+ODTE/m943DJC72A7eOTEIaRIgeFr8tglgcQsKhkdfE=; Received: (qmail 24070 invoked by alias); 3 Nov 2012 14:44:11 -0000 Received: (qmail 24053 invoked by uid 22791); 3 Nov 2012 14:44:10 -0000 X-SWARE-Spam-Status: No, hits=-5.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, KHOP_RCVD_TRUST, KHOP_THREADED, RCVD_IN_DNSWL_LOW, RCVD_IN_HOSTKARMA_YE X-Spam-Check-By: sourceware.org Received: from mail-we0-f175.google.com (HELO mail-we0-f175.google.com) (74.125.82.175) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sat, 03 Nov 2012 14:44:03 +0000 Received: by mail-we0-f175.google.com with SMTP id t44so2097268wey.20 for ; Sat, 03 Nov 2012 07:44:01 -0700 (PDT) Received: by 10.180.84.202 with SMTP id b10mr6559094wiz.13.1351953841598; Sat, 03 Nov 2012 07:44:01 -0700 (PDT) Received: from localhost.localdomain (170.155.119.80.rev.sfr.net. [80.119.155.170]) by mx.google.com with ESMTPS id gm7sm3038576wib.10.2012.11.03.07.43.57 (version=SSLv3 cipher=OTHER); Sat, 03 Nov 2012 07:44:00 -0700 (PDT) Message-ID: <50952DAC.7070909@gmail.com> Date: Sat, 03 Nov 2012 15:43:56 +0100 From: =?ISO-8859-1?Q?Fran=E7ois_Dumont?= User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:15.0) Gecko/20120829 Thunderbird/15.0 MIME-Version: 1.0 To: Jonathan Wakely CC: "libstdc++@gcc.gnu.org" , gcc-patches Subject: Re: exception safety validation References: <50660529.8020306@gmail.com> <506DE590.7090706@gmail.com> <509521C5.1030809@gmail.com> In-Reply-To: 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 On 11/03/2012 03:12 PM, Jonathan Wakely wrote: > On 3 November 2012 14:11, Jonathan Wakely wrote: >> On 3 November 2012 13:53, François Dumont wrote: >>> Here is an updated proposal using default implementations as much as >>> possible. >> Please check the indentation of the "struct emplace_point" specializations. >> >> In testsuite/util/testsuite_container_traits.h >> >> +#ifdef __GXX_EXPERIMENTAL_CXX0X__ >> + typedef std::true_type has_emplace; >> +#endif >> >> true_type isn't even defined unless it's C++11 > My point being that the rest of the file already uses C++11-only features > Ok, it looks like this file is only used in C++11 mode so here is the simplified patch. Note that I run exception tests to validate it and the recently introduced 23_containers/forward_list/allocator/noexcept.cc test doesn't work in debug mode. I think it needs a dg-require-normal-node attribute. François Index: include/ext/throw_allocator.h =================================================================== --- include/ext/throw_allocator.h (revision 193118) +++ include/ext/throw_allocator.h (working copy) @@ -467,6 +467,11 @@ throw_value_base(const throw_value_base& __v) : _M_i(__v._M_i) { throw_conditionally(); } +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + // Shall not throw. + throw_value_base(throw_value_base&&) = default; +#endif + explicit throw_value_base(const std::size_t __i) : _M_i(__i) { throw_conditionally(); } #endif @@ -479,7 +484,13 @@ return *this; } +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + // Shall not throw. throw_value_base& + operator=(throw_value_base&&) = default; +#endif + + throw_value_base& operator++() { throw_conditionally(); @@ -568,8 +579,24 @@ throw_value_limit(const throw_value_limit& __other) : base_type(__other._M_i) { } +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + throw_value_limit(throw_value_limit&&) = default; +#endif + explicit throw_value_limit(const std::size_t __i) : base_type(__i) { } #endif + + throw_value_limit& + operator=(const throw_value_limit& __other) + { + base_type::operator=(__other); + return *this; + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + throw_value_limit& + operator=(throw_value_limit&&) = default; +#endif }; /// Type throwing via random condition. @@ -583,9 +610,24 @@ throw_value_random(const throw_value_random& __other) : base_type(__other._M_i) { } +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + throw_value_random(throw_value_random&&) = default; +#endif explicit throw_value_random(const std::size_t __i) : base_type(__i) { } #endif + + throw_value_random& + operator=(const throw_value_random& __other) + { + base_type::operator=(__other); + return *this; + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + throw_value_random& + operator=(throw_value_random&&) = default; +#endif }; Index: testsuite/util/testsuite_container_traits.h =================================================================== --- testsuite/util/testsuite_container_traits.h (revision 193118) +++ testsuite/util/testsuite_container_traits.h (working copy) @@ -73,6 +73,7 @@ typedef std::true_type has_insert; typedef std::true_type has_push_pop; typedef std::true_type has_size_type_constructor; + typedef std::true_type has_emplace; }; template @@ -85,6 +86,7 @@ typedef std::true_type has_insert_after; typedef std::true_type has_push_pop; typedef std::true_type has_size_type_constructor; + typedef std::true_type has_emplace; }; template @@ -98,6 +100,7 @@ typedef std::true_type has_insert; typedef std::true_type has_push_pop; typedef std::true_type has_size_type_constructor; + typedef std::true_type has_emplace; }; template @@ -111,6 +114,7 @@ typedef std::true_type has_throwing_erase; typedef std::true_type has_insert; typedef std::true_type has_size_type_constructor; + typedef std::true_type has_emplace; }; template @@ -148,9 +152,7 @@ typedef std::true_type has_erase; typedef std::true_type has_insert; -#ifdef __GXX_EXPERIMENTAL_CXX0X__ typedef std::true_type has_emplace; -#endif }; template @@ -164,9 +166,7 @@ typedef std::true_type has_erase; typedef std::true_type has_insert; -#ifdef __GXX_EXPERIMENTAL_CXX0X__ typedef std::true_type has_emplace; -#endif }; template @@ -179,9 +179,7 @@ typedef std::true_type has_erase; typedef std::true_type has_insert; -#ifdef __GXX_EXPERIMENTAL_CXX0X__ typedef std::true_type has_emplace; -#endif }; template @@ -194,9 +192,7 @@ typedef std::true_type has_erase; typedef std::true_type has_insert; -#ifdef __GXX_EXPERIMENTAL_CXX0X__ typedef std::true_type has_emplace; -#endif }; template Index: testsuite/util/exception/safety.h =================================================================== --- testsuite/util/exception/safety.h (revision 193118) +++ testsuite/util/exception/safety.h (working copy) @@ -226,17 +226,22 @@ // compared to the control container. // NB: Should be equivalent to __test != __control, but // computed without equivalence operators - const size_type szt = std::distance(__test.begin(), __test.end()); - const size_type szc = std::distance(__control.begin(), - __control.end()); - bool __equal_size = szt == szc; + const size_type szt + = std::distance(__test.begin(), __test.end()); + const size_type szc + = std::distance(__control.begin(), __control.end()); + if (szt != szc) + throw std::logic_error( + "setup_base::compare containers size not equal"); + // Should test iterator validity before and after exception. bool __equal_it = std::equal(__test.begin(), __test.end(), __control.begin()); - if (!__equal_size || !__equal_it) - throw std::logic_error("setup_base::compare containers not equal"); + if (!__equal_it) + throw std::logic_error( + "setup_base::compare containers iterators not equal"); return true; } @@ -627,7 +632,97 @@ operator()(_Tp&, _Tp&) { } }; + template::has_push_pop::value + && traits<_Tp>::has_emplace::value> + struct emplace_front + { + typedef _Tp container_type; + typedef typename container_type::value_type value_type; + void + operator()(_Tp& __test) + { + try + { + const value_type cv = generate_unique(); + __test.emplace_front(cv); + } + catch(const __gnu_cxx::forced_error&) + { throw; } + } + + // Assumes containers start out equivalent. + void + operator()(_Tp& __control, _Tp& __test) + { + try + { + const value_type cv = generate_unique(); + __test.emplace_front(cv); + } + catch(const __gnu_cxx::forced_error&) + { throw; } + } + }; + + // Specialization, empty. + template + struct emplace_front<_Tp, false> + { + void + operator()(_Tp&) { } + + void + operator()(_Tp&, _Tp&) { } + }; + + + template::has_push_pop::value + && traits<_Tp>::has_emplace::value + && traits<_Tp>::is_reversible::value> + struct emplace_back + { + typedef _Tp container_type; + typedef typename container_type::value_type value_type; + + void + operator()(_Tp& __test) + { + try + { + const value_type cv = generate_unique(); + __test.emplace_back(cv); + } + catch(const __gnu_cxx::forced_error&) + { throw; } + } + + // Assumes containers start out equivalent. + void + operator()(_Tp& __control, _Tp& __test) + { + try + { + const value_type cv = generate_unique(); + __test.push_back(cv); + } + catch(const __gnu_cxx::forced_error&) + { throw; } + } + }; + + // Specialization, empty. + template + struct emplace_back<_Tp, false> + { + void + operator()(_Tp&) { } + + void + operator()(_Tp&, _Tp&) { } + }; + + // Abstract the insert function into two parts: // 1, insert_base_functions == holds function pointer // 2, insert_base == links function pointer to class insert method @@ -726,9 +821,8 @@ insert_base() : _F_insert_point(&container_type::insert_after) { } }; - template::has_insert::value, - bool = traits<_Tp>::has_insert_after::value> + template::has_insert::value, + bool = traits<_Tp>::has_insert_after::value> struct insert_point; // Specialization for most containers. @@ -826,11 +920,12 @@ operator()(_Tp&, _Tp&) { } }; - template::has_emplace::value> + template::has_emplace::value + && (traits<_Tp>::is_associative::value + || traits<_Tp>::is_unordered::value)> struct emplace; - // Specialization for most containers. + // Specialization for associative and unordered containers. template struct emplace<_Tp, true> { @@ -875,13 +970,15 @@ operator()(_Tp&, _Tp&) { } }; - template::has_emplace::value> - struct emplace_hint; + template::has_emplace::value, + bool = traits<_Tp>::is_associative::value + || traits<_Tp>::is_unordered::value, + bool = traits<_Tp>::has_insert_after::value> + struct emplace_point; // Specialization for most containers. template - struct emplace_hint<_Tp, true> + struct emplace_point<_Tp, true, false, false> { typedef _Tp container_type; typedef typename container_type::value_type value_type; @@ -896,6 +993,47 @@ size_type s = generate(sz); auto i = __test.begin(); std::advance(i, s); + __test.emplace(i, cv); + } + catch(const __gnu_cxx::forced_error&) + { throw; } + } + + // Assumes containers start out equivalent. + void + operator()(_Tp& __control, _Tp& __test) + { + try + { + const value_type cv = generate_unique(); + const size_type sz = std::distance(__test.begin(), __test.end()); + size_type s = generate(sz); + auto i = __test.begin(); + std::advance(i, s); + __test.emplace(i, cv); + } + catch(const __gnu_cxx::forced_error&) + { throw; } + } + }; + + // Specialization for associative and unordered containers. + template + struct emplace_point<_Tp, true, true, false> + { + typedef _Tp container_type; + typedef typename container_type::value_type value_type; + + void + operator()(_Tp& __test) + { + try + { + const value_type cv = generate_unique(); + const size_type sz = std::distance(__test.begin(), __test.end()); + size_type s = generate(sz); + auto i = __test.begin(); + std::advance(i, s); __test.emplace_hint(i, cv); } catch(const __gnu_cxx::forced_error&) @@ -920,11 +1058,54 @@ } }; - // Specialization, empty. + // Specialization for forward_list. template - struct emplace_hint<_Tp, false> + struct emplace_point<_Tp, true, false, true> { + typedef _Tp container_type; + typedef typename container_type::value_type value_type; + void + operator()(_Tp& __test) + { + try + { + const value_type cv = generate_unique(); + const size_type sz = std::distance(__test.begin(), __test.end()); + size_type s = generate(sz); + auto i = __test.before_begin(); + std::advance(i, s); + __test.emplace_after(i, cv); + } + catch(const __gnu_cxx::forced_error&) + { throw; } + } + + // Assumes containers start out equivalent. + void + operator()(_Tp& __control, _Tp& __test) + { + try + { + const value_type cv = generate_unique(); + const size_type sz = std::distance(__test.begin(), __test.end()); + size_type s = generate(sz); + auto i = __test.before_begin(); + std::advance(i, s); + __test.emplace_after(i, cv); + } + catch(const __gnu_cxx::forced_error&) + { throw; } + } + }; + + // Specialization, empty. + template + struct emplace_point<_Tp, false, is_associative_or_unordered, + has_insert_after> + { + void operator()(_Tp&) { } void @@ -1128,7 +1309,9 @@ typedef erase_range erase_range; typedef insert_point insert_point; typedef emplace emplace; - typedef emplace_hint emplace_hint; + typedef emplace_point emplace_point; + typedef emplace_front emplace_front; + typedef emplace_back emplace_back; typedef pop_front pop_front; typedef pop_back pop_back; typedef push_front push_front; @@ -1146,7 +1329,9 @@ erase_range _M_eraser; insert_point _M_insertp; emplace _M_emplace; - emplace_hint _M_emplaceh; + emplace_point _M_emplacep; + emplace_front _M_emplacef; + emplace_back _M_emplaceb; pop_front _M_popf; pop_back _M_popb; push_front _M_pushf; @@ -1207,7 +1392,9 @@ _M_functions.push_back(function_type(base_type::_M_eraser)); _M_functions.push_back(function_type(base_type::_M_insertp)); _M_functions.push_back(function_type(base_type::_M_emplace)); - _M_functions.push_back(function_type(base_type::_M_emplaceh)); + _M_functions.push_back(function_type(base_type::_M_emplacep)); + _M_functions.push_back(function_type(base_type::_M_emplacef)); + _M_functions.push_back(function_type(base_type::_M_emplaceb)); _M_functions.push_back(function_type(base_type::_M_popf)); _M_functions.push_back(function_type(base_type::_M_popb)); _M_functions.push_back(function_type(base_type::_M_pushf)); @@ -1328,7 +1515,8 @@ // Test strong exception guarantee. // Run through all member functions with a roll-back, consistent // coherent requirement. - // all: member functions insert of a single element, push_back, push_front + // all: member functions insert and emplace of a single element, push_back, + // push_front // unordered: rehash template struct propagation_consistent : public test_base<_Tp> @@ -1360,9 +1548,12 @@ // Construct containers. populate p(_M_container_control); - sync(); // Construct list of member functions to exercise. + _M_functions.push_back(function_type(base_type::_M_emplace)); + _M_functions.push_back(function_type(base_type::_M_emplacep)); + _M_functions.push_back(function_type(base_type::_M_emplacef)); + _M_functions.push_back(function_type(base_type::_M_emplaceb)); _M_functions.push_back(function_type(base_type::_M_pushf)); _M_functions.push_back(function_type(base_type::_M_pushb)); _M_functions.push_back(function_type(base_type::_M_insertp)); Index: testsuite/23_containers/deque/requirements/exception/propagation_consistent.cc =================================================================== --- testsuite/23_containers/deque/requirements/exception/propagation_consistent.cc (revision 193118) +++ testsuite/23_containers/deque/requirements/exception/propagation_consistent.cc (working copy) @@ -1,6 +1,5 @@ // { dg-options "-std=gnu++0x" } // { dg-require-cstdint "" } -// { dg-do run { xfail *-*-* } } // 2009-09-09 Benjamin Kosnik