Re: [PATCH] c++, contracts: Fix ICE in create_tmp_var [PR113968]
HI Jason, On Fri, 5 Jul 2024 at 17:31, Jason Merrill wrote: > > On 7/5/24 10:25 AM, Nina Dinka Ranns wrote: > > Certain places in contract parsing currently do not check for errors. > > This results in contracts > > with embedded errors which eventually confuse gimplify. Checks for > > errors added in > > grok_contract() and cp_parser_contract_attribute_spec() to exit early > > if an error is encountered. > > Thanks for the patch! > > > Tested on x86_64-pc-linux-gnu > > --- > > > > PR c++/113968 > > > > gcc/cp/ChangeLog: > > > > * contracts.cc (grok_contract): Check for error_mark_node early > >exit > > These hunks are OK. > > > * parser.cc (cp_parser_contract_attribute_spec): Check for > >error_mark_node early exit > > This seems redundant, since finish_contract_attribute already checks for > error_mark_node and we're returning its result unchanged. good catch, removed. > > Also, the convention is for wrapped lines in ChangeLog entries to line > up with the *, and to finish sentences with a period. done. Tests re-run on x86_64-pc-linux-gnu , no change. --- PR C++/113968 gcc/cp/ChangeLog: * contracts.cc (grok_contract): Check for error_mark_node early exit. gcc/testsuite/ChangeLog: * g++.dg/contracts/pr113968.C: New test. Signed-off-by: Nina Ranns --- gcc/cp/contracts.cc | 7 ++ gcc/testsuite/g++.dg/contracts/pr113968.C | 29 +++ 2 files changed, 36 insertions(+) create mode 100644 gcc/testsuite/g++.dg/contracts/pr113968.C diff --git a/gcc/cp/contracts.cc b/gcc/cp/contracts.cc index 634e3cf4fa9..a7d0fdacf6e 100644 --- a/gcc/cp/contracts.cc +++ b/gcc/cp/contracts.cc @@ -750,6 +750,9 @@ tree grok_contract (tree attribute, tree mode, tree result, cp_expr condition, location_t loc) { + if (condition == error_mark_node) +return error_mark_node; + tree_code code; if (is_attribute_p ("assert", attribute)) code = ASSERTION_STMT; @@ -785,6 +788,10 @@ grok_contract (tree attribute, tree mode, tree result, cp_expr condition, /* The condition is converted to bool. */ condition = finish_contract_condition (condition); + + if (condition == error_mark_node) +return error_mark_node; + CONTRACT_CONDITION (contract) = condition; return contract; diff --git a/gcc/testsuite/g++.dg/contracts/pr113968.C b/gcc/testsuite/g++.dg/contracts/pr113968.C new file mode 100644 index 000..fbaad1c930d --- /dev/null +++ b/gcc/testsuite/g++.dg/contracts/pr113968.C @@ -0,0 +1,29 @@ +// check that an invalid contract condition doesn't cause an ICE +// { dg-do compile } +// { dg-options "-std=c++2a -fcontracts " } + +struct A +{ + A (A&); +}; +struct S +{ + void f(A a) +[[ pre : a]] // { dg-error "could not convert" } +[[ pre : a.b]]// { dg-error "has no member" } +{ + +} +}; +void f(A a) + [[ pre : a]] // { dg-error "could not convert" } + [[ pre : a.b]]// { dg-error "has no member" } + { +[[ assert : a ]]; // { dg-error "could not convert" } +[[ assert : a.b ]];// { dg-error "has no member" } + } + +int +main () +{ +} -- 2.45.2
[PATCH] c++, contracts: Fix ICE in create_tmp_var [PR113968]
Certain places in contract parsing currently do not check for errors. This results in contracts with embedded errors which eventually confuse gimplify. Checks for errors added in grok_contract() and cp_parser_contract_attribute_spec() to exit early if an error is encountered. Tested on x86_64-pc-linux-gnu --- PR c++/113968 gcc/cp/ChangeLog: * contracts.cc (grok_contract): Check for error_mark_node early exit * parser.cc (cp_parser_contract_attribute_spec): Check for error_mark_node early exit gcc/testsuite/ChangeLog: * g++.dg/contracts/pr113968.C: New test. Signed-off-by: Nina Ranns --- gcc/cp/contracts.cc | 7 ++ gcc/cp/parser.cc | 3 +++ gcc/testsuite/g++.dg/contracts/pr113968.C | 29 +++ 3 files changed, 39 insertions(+) create mode 100644 gcc/testsuite/g++.dg/contracts/pr113968.C diff --git a/gcc/cp/contracts.cc b/gcc/cp/contracts.cc index 634e3cf4fa9..a7d0fdacf6e 100644 --- a/gcc/cp/contracts.cc +++ b/gcc/cp/contracts.cc @@ -750,6 +750,9 @@ tree grok_contract (tree attribute, tree mode, tree result, cp_expr condition, location_t loc) { + if (condition == error_mark_node) +return error_mark_node; + tree_code code; if (is_attribute_p ("assert", attribute)) code = ASSERTION_STMT; @@ -785,6 +788,10 @@ grok_contract (tree attribute, tree mode, tree result, cp_expr condition, /* The condition is converted to bool. */ condition = finish_contract_condition (condition); + + if (condition == error_mark_node) +return error_mark_node; + CONTRACT_CONDITION (contract) = condition; return contract; diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 31ae9c2fb54..22c5e760aee 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -30835,6 +30835,9 @@ cp_parser_contract_attribute_spec (cp_parser *parser, tree attribute) return error_mark_node; } + if (contract == error_mark_node) +return error_mark_node; + return finish_contract_attribute (attribute, contract); } diff --git a/gcc/testsuite/g++.dg/contracts/pr113968.C b/gcc/testsuite/g++.dg/contracts/pr113968.C new file mode 100644 index 000..fbaad1c930d --- /dev/null +++ b/gcc/testsuite/g++.dg/contracts/pr113968.C @@ -0,0 +1,29 @@ +// check that an invalid contract condition doesn't cause an ICE +// { dg-do compile } +// { dg-options "-std=c++2a -fcontracts " } + +struct A +{ + A (A&); +}; +struct S +{ + void f(A a) +[[ pre : a]] // { dg-error "could not convert" } +[[ pre : a.b]]// { dg-error "has no member" } +{ + +} +}; +void f(A a) + [[ pre : a]] // { dg-error "could not convert" } + [[ pre : a.b]]// { dg-error "has no member" } + { +[[ assert : a ]]; // { dg-error "could not convert" } +[[ assert : a.b ]];// { dg-error "has no member" } + } + +int +main () +{ +} -- 2.45.2
Re: PR C++/63149
On Wed, 5 Jun 2019 at 19:19, Jason Merrill wrote: > On 6/5/19 1:29 PM, Nina Dinka Ranns wrote: > > Ack. Amended change log is below. Changes are : > > * changed C++ -> c++ > > * fixed the name of added test > > > > There are no changes in the diff, but I attached it to this e-mail for > > reference. > > Applied, thanks! > > For future reference it's also customary to add a bit of discussion of > the rationale for the patch. Also, please include the word "PATCH" on > the subject line. Noted. Thank you, Nina > > Jason >
Re: PR C++/63149
Ack. Amended change log is below. Changes are : * changed C++ -> c++ * fixed the name of added test There are no changes in the diff, but I attached it to this e-mail for reference. Thanks, Nina 2019-06-04 Nina Dinka Ranns gcc/cp PR c++/63149 * pt.c (listify_autos): Use non cv qualified auto_node in std::initializer_list. testsuite/ PR c++/63149 * g++.dg/cpp0x/initlist-deduce2.C: New test. On Wed, 5 Jun 2019 at 13:59, Marek Polacek wrote: > > On Wed, Jun 05, 2019 at 02:50:54PM +0200, Jakub Jelinek wrote: > > On Wed, Jun 05, 2019 at 08:39:56AM -0400, Marek Polacek wrote: > > > On Wed, Jun 05, 2019 at 10:34:05AM +0100, Nina Dinka Ranns wrote: > > > > > PR C++/63149 > > > > > * pt.c (listify_autos): Use non cv qualified auto_node in > > > > > std::initializer_list. > > > > > > > > > > testsuite/ > > > > > > > > > > PR C++/63149 > > > > > > "c++" instead of "C++", thought I don't think anyone would mind. > > > > I would, I have scripts that grab the PR strings from ChangeLog entries > > and need to fix stuff by hand if it is incorrect like this (or if people > > forget to use the component/ part altogether). > > Fair enough. Nina, please adjust that too, then. > > Marek Index: gcc/cp/pt.c === --- gcc/cp/pt.c (revision 271709) +++ gcc/cp/pt.c (working copy) @@ -26836,7 +26836,7 @@ static tree listify_autos (tree type, tree auto_node) { - tree init_auto = listify (auto_node); + tree init_auto = listify (strip_top_quals (auto_node)); tree argvec = make_tree_vec (1); TREE_VEC_ELT (argvec, 0) = init_auto; if (processing_template_decl) Index: gcc/testsuite/g++.dg/cpp0x/initlist-deduce2.C === --- gcc/testsuite/g++.dg/cpp0x/initlist-deduce2.C (nonexistent) +++ gcc/testsuite/g++.dg/cpp0x/initlist-deduce2.C (working copy) @@ -0,0 +1,8 @@ +// Test for PR63149 +// { dg-do compile { target c++11 } } + +#include + +const auto r = { 1, 2, 3 }; +using X = decltype(r); +using X = const std::initializer_list;
Re: PR C++/63149
yes, I forgot to attach the latest patch. :) On Wed, 5 Jun 2019 at 10:24, Nina Dinka Ranns wrote: > > Hi both, > Addressing all comments in this e-mail, as some are duplicate. > > On Tue, 4 Jun 2019 at 20:45, Paolo Carlini wrote: > > > > Hi, > > > > On 04/06/19 21:26, Nina Dinka Ranns wrote: > > > > Good point, dg-do compile is sufficient to demonstrate the issue. > > > > I agree. > > > > A couple of additional nits, sorry for mentioning only now. > > > > > > C++63149_2.diff > > > > Index: gcc/cp/pt.c > > === > > --- gcc/cp/pt.c (revision 271709) > > +++ gcc/cp/pt.c (working copy) > > @@ -26836,7 +26836,7 @@ > > static tree > > listify_autos (tree type, tree auto_node) > > { > > - tree init_auto = listify (auto_node); > > + tree init_auto = listify (strip_top_quals(auto_node)); > > > > You want a space after strip_top_quals. > > fixed. > > > > >tree argvec = make_tree_vec (1); > >TREE_VEC_ELT (argvec, 0) = init_auto; > >if (processing_template_decl) > > Index: gcc/testsuite/g++.dg/cpp0x/initlist-deduce2.C > > === > > --- gcc/testsuite/g++.dg/cpp0x/initlist-deduce2.C (nonexistent) > > +++ gcc/testsuite/g++.dg/cpp0x/initlist-deduce2.C (working copy) > > @@ -0,0 +1,12 @@ > > +// Test for PR63149 > > +// { dg-do compile { target c++11 } } > > + > > +#include > > + > > +const auto r = { 1, 2, 3 }; > > +using X = decltype(r); > > +using X = const std::initializer_list; > > + > > +int main() > > +{ > > +} > > > > With dg-do compile you don't need a main anymore. > > > fixed > > > I seem to remember also a couple of minor formatting issues in the > > ChangeLog entry: just harmonize the format with everything else you find in > > the ChangeLog, in terms of the usual trivial details: upper cases, line > > lenghts and line wraps, etc. > > > > Below is the amended change log. If there is anything else off, I > would need specifics as I've made all the changes I could spot myself. > :) > > Thanks, > Nina > > 2019-06-04 Nina Dinka Ranns > gcc/cp > > PR C++/63149 > * pt.c (listify_autos): Use non cv qualified auto_node in > std::initializer_list. > > testsuite/ > > PR C++/63149 > * g++.dg/cpp0x/initlist-deduce.C: New test. Index: gcc/cp/pt.c === --- gcc/cp/pt.c (revision 271709) +++ gcc/cp/pt.c (working copy) @@ -26836,7 +26836,7 @@ static tree listify_autos (tree type, tree auto_node) { - tree init_auto = listify (auto_node); + tree init_auto = listify (strip_top_quals (auto_node)); tree argvec = make_tree_vec (1); TREE_VEC_ELT (argvec, 0) = init_auto; if (processing_template_decl) Index: gcc/testsuite/g++.dg/cpp0x/initlist-deduce2.C === --- gcc/testsuite/g++.dg/cpp0x/initlist-deduce2.C (nonexistent) +++ gcc/testsuite/g++.dg/cpp0x/initlist-deduce2.C (working copy) @@ -0,0 +1,8 @@ +// Test for PR63149 +// { dg-do compile { target c++11 } } + +#include + +const auto r = { 1, 2, 3 }; +using X = decltype(r); +using X = const std::initializer_list;
Re: PR C++/63149
Hi both, Addressing all comments in this e-mail, as some are duplicate. On Tue, 4 Jun 2019 at 20:45, Paolo Carlini wrote: > > Hi, > > On 04/06/19 21:26, Nina Dinka Ranns wrote: > > Good point, dg-do compile is sufficient to demonstrate the issue. > > I agree. > > A couple of additional nits, sorry for mentioning only now. > > > C++63149_2.diff > > Index: gcc/cp/pt.c > === > --- gcc/cp/pt.c (revision 271709) > +++ gcc/cp/pt.c (working copy) > @@ -26836,7 +26836,7 @@ > static tree > listify_autos (tree type, tree auto_node) > { > - tree init_auto = listify (auto_node); > + tree init_auto = listify (strip_top_quals(auto_node)); > > You want a space after strip_top_quals. fixed. > >tree argvec = make_tree_vec (1); >TREE_VEC_ELT (argvec, 0) = init_auto; >if (processing_template_decl) > Index: gcc/testsuite/g++.dg/cpp0x/initlist-deduce2.C > === > --- gcc/testsuite/g++.dg/cpp0x/initlist-deduce2.C (nonexistent) > +++ gcc/testsuite/g++.dg/cpp0x/initlist-deduce2.C (working copy) > @@ -0,0 +1,12 @@ > +// Test for PR63149 > +// { dg-do compile { target c++11 } } > + > +#include > + > +const auto r = { 1, 2, 3 }; > +using X = decltype(r); > +using X = const std::initializer_list; > + > +int main() > +{ > +} > > With dg-do compile you don't need a main anymore. > fixed > I seem to remember also a couple of minor formatting issues in the ChangeLog > entry: just harmonize the format with everything else you find in the > ChangeLog, in terms of the usual trivial details: upper cases, line lenghts > and line wraps, etc. > Below is the amended change log. If there is anything else off, I would need specifics as I've made all the changes I could spot myself. :) Thanks, Nina 2019-06-04 Nina Dinka Ranns gcc/cp PR C++/63149 * pt.c (listify_autos): Use non cv qualified auto_node in std::initializer_list. testsuite/ PR C++/63149 * g++.dg/cpp0x/initlist-deduce.C: New test.
Re: PR C++/63149
Good point, dg-do compile is sufficient to demonstrate the issue. Amended, new patch attached. Thanks, Nina On Tue, 4 Jun 2019 at 17:53, Paolo Carlini wrote: > > Hi, > > On 04/06/19 18:36, Nina Dinka Ranns wrote: > > +// Test for PR63149 > > +// { dg-do run { target c++11 } } > > Are you sure you want a dg-do run? > > Paolo. > > Index: gcc/cp/pt.c === --- gcc/cp/pt.c (revision 271709) +++ gcc/cp/pt.c (working copy) @@ -26836,7 +26836,7 @@ static tree listify_autos (tree type, tree auto_node) { - tree init_auto = listify (auto_node); + tree init_auto = listify (strip_top_quals(auto_node)); tree argvec = make_tree_vec (1); TREE_VEC_ELT (argvec, 0) = init_auto; if (processing_template_decl) Index: gcc/testsuite/g++.dg/cpp0x/initlist-deduce2.C === --- gcc/testsuite/g++.dg/cpp0x/initlist-deduce2.C (nonexistent) +++ gcc/testsuite/g++.dg/cpp0x/initlist-deduce2.C (working copy) @@ -0,0 +1,12 @@ +// Test for PR63149 +// { dg-do compile { target c++11 } } + +#include + +const auto r = { 1, 2, 3 }; +using X = decltype(r); +using X = const std::initializer_list; + +int main() +{ +}
PR C++/63149
Tested on Linux x86_64 2019-06-04 Nina Dinka Ranns gcc/cp PR c++/63149 * pt.c (listify_autos): use non cv qualified auto_node in std::initializer_list testsuite/ PR c++/63149 * g++.dg/cpp0x/initlist-deduce.C: New Index: gcc/cp/pt.c === --- gcc/cp/pt.c (revision 271709) +++ gcc/cp/pt.c (working copy) @@ -26836,7 +26836,7 @@ static tree listify_autos (tree type, tree auto_node) { - tree init_auto = listify (auto_node); + tree init_auto = listify (strip_top_quals(auto_node)); tree argvec = make_tree_vec (1); TREE_VEC_ELT (argvec, 0) = init_auto; if (processing_template_decl) Index: gcc/testsuite/g++.dg/cpp0x/initlist-deduce2.C === --- gcc/testsuite/g++.dg/cpp0x/initlist-deduce2.C (nonexistent) +++ gcc/testsuite/g++.dg/cpp0x/initlist-deduce2.C (working copy) @@ -0,0 +1,12 @@ +// Test for PR63149 +// { dg-do run { target c++11 } } + +#include + +const auto r = { 1, 2, 3 }; +using X = decltype(r); +using X = const std::initializer_list; + +int main() +{ +}
[v3 PATCH] basic_string spurious use of a default constructible allocator - LWG2788
Tested on Linux x86_64 basic_string spurious use of a default constructible allocator - LWG2788 2019-05-27 Nina Dinka Ranns basic_string spurious use of a default constructible allocator - LWG2788 * bits/basic_string.tcc: (_M_replace_dispatch()): string temporary now constructed with the current allocator * testsuite/21_strings/basic_string/allocator/char/lwg2788.cc: New * testsuite/21_strings/basic_string/allocator/wchar_t/lwg2788.cc: New Index: libstdc++-v3/include/bits/basic_string.tcc === --- libstdc++-v3/include/bits/basic_string.tcc (revision 271509) +++ libstdc++-v3/include/bits/basic_string.tcc (working copy) @@ -381,7 +381,9 @@ _InputIterator __k1, _InputIterator __k2, std::__false_type) { - const basic_string __s(__k1, __k2); +// _GLIBCXX_RESOLVE_LIB_DEFECTS +// 2788. unintentionally require a default constructible allocator + const basic_string __s(__k1, __k2, this->get_allocator()); const size_type __n1 = __i2 - __i1; return _M_replace(__i1 - begin(), __n1, __s._M_data(), __s.size()); Index: libstdc++-v3/testsuite/20_util/nonesuch/nonesuch.cc === --- libstdc++-v3/testsuite/20_util/nonesuch/nonesuch.cc (revision 271509) +++ libstdc++-v3/testsuite/20_util/nonesuch/nonesuch.cc (nonexistent) @@ -1,39 +0,0 @@ -// 2019-05-14 Nina Dinka Ranns -// Copyright (C) 2019 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 -// <http://www.gnu.org/licenses/>. - -// { dg-do compile { target c++14 } } - -#include -// Example taken from LWG2960 - -using std::__nonesuch; -struct such {}; -void f(const such&){}; -void f(const std::__nonesuch&); - -int main(){ - static_assert(!std::is_default_constructible<__nonesuch>::value, - "__nonesuch is default constructible"); - static_assert(!std::is_copy_constructible<__nonesuch>::value, - "__nonesuch is copy constructible"); - static_assert(!std::is_assignable<__nonesuch, __nonesuch>::value, - "__nonesuch is assignable"); - static_assert(!std::is_destructible<__nonesuch>::value, - "__nonesuch is destructible"); - f({}); -} Index: libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/lwg2788.cc === --- libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/lwg2788.cc (nonexistent) +++ libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/lwg2788.cc (working copy) @@ -0,0 +1,84 @@ +//{ dg-do run { target c++11 } } + +// 2019-05-27 Nina Dinka Ranns +// +// Copyright (C) 2015-2019 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 +// <http://www.gnu.org/licenses/>. + +#include +#include + +using C = char; +using traits = std::char_traits; +int constructCount = 0; + +static void resetCounter() +{ + constructCount = 0; +} + +template +struct TestAllocator +{ + typedef Tp value_type; + using size_type = unsigned; + + TestAllocator() noexcept { constructCount++; } + + template + TestAllocator(const TestAllocator&) {} + + Tp *allocate(std::size_t n) + { return std::allocator().allocate(n); } + + void deallocate(Tp *p, std::size_t n) + { std::allocator().deallocate(p, n); } + +}; + +template +bool operator==(const TestAllocator&, const TestAllocator&) +{ return true; } +template +bool operator!=(const TestAllocator&, const TestAllocator&) +{ return false; } + +void test01() +{ + typedef TestAllocator alloc_type; + typedef std::basic_string test_t
Re: [v3 PATCH] nonesuch is insufficiently useless (lwg2996)
That was fast :) I’ll check the changelog for future reference. Thanks, Nina On Tue, 14 May 2019 at 16:50, Jonathan Wakely wrote: > On 14/05/19 15:43 +0100, Nina Dinka Ranns wrote: > >Tested on Linux x86_64 > >nonesuch is insufficiently useless (lwg2996) > > > >2019-05-14 Nina Dinka Ranns > >nonesuch is insufficiently useless (lwg2996) > >* include/std/type_traits > >struct __nonesuch: added private base class to make __nonesuch > >not an aggregate and removed deleted default constructor > >* include/bits/stl_pair.h: > >struct __nonesuch_no_braces: Removed > >(operator=(const pair&)): Use __nonesuch instead of > >__nonesuch_no_braces. > >(operator=(pair&&)): Likewise > >* include/std/tuple > >(operator=(const tuple&)): Use __nonesuch instead of > >__nonesuch_no_braces. > >(operator=(tuple&&)): Likewise > >* include/experimental/type_traits > > struct nonesuch: added private base class to make nonesuch > >not an aggregate and removed deleted default constructor > >* testsuite/20_util/nonesuch/nonesuch.cc: New > >* testsuite/experimental/type_traits/nonesuch.cc: New > > Thanks! > > Tested and committed, again with some changelog edits, and some whitespace > before the opening braces here ... > > >@@ -2769,8 +2769,8 @@ > > __call_is_nothrow_<_Fn, _Args...>>::type > > { }; > > > >- struct __nonesuch { > >-__nonesuch() = delete; > >+ struct __nonesuchbase{}; > >+ struct __nonesuch : private __nonesuchbase{ > > >
[v3 PATCH] nonesuch is insufficiently useless (lwg2996)
Tested on Linux x86_64 nonesuch is insufficiently useless (lwg2996) 2019-05-14 Nina Dinka Ranns nonesuch is insufficiently useless (lwg2996) * include/std/type_traits struct __nonesuch: added private base class to make __nonesuch not an aggregate and removed deleted default constructor * include/bits/stl_pair.h: struct __nonesuch_no_braces: Removed (operator=(const pair&)): Use __nonesuch instead of __nonesuch_no_braces. (operator=(pair&&)): Likewise * include/std/tuple (operator=(const tuple&)): Use __nonesuch instead of __nonesuch_no_braces. (operator=(tuple&&)): Likewise * include/experimental/type_traits struct nonesuch: added private base class to make nonesuch not an aggregate and removed deleted default constructor * testsuite/20_util/nonesuch/nonesuch.cc: New * testsuite/experimental/type_traits/nonesuch.cc: New Index: libstdc++-v3/include/bits/stl_pair.h === --- libstdc++-v3/include/bits/stl_pair.h (revision 270630) +++ libstdc++-v3/include/bits/stl_pair.h (working copy) @@ -178,13 +178,6 @@ return false; } }; - - // PR libstdc++/79141, a utility type for preventing - // initialization of an argument of a disabled assignment - // operator from a pair of empty braces. - struct __nonesuch_no_braces : std::__nonesuch { -explicit __nonesuch_no_braces(const __nonesuch&) = delete; - }; #endif // C++11 template class __pair_base @@ -378,7 +371,7 @@ operator=(typename conditional< __and_, is_copy_assignable<_T2>>::value, - const pair&, const __nonesuch_no_braces&>::type __p) + const pair&, const __nonesuch&>::type __p) { first = __p.first; second = __p.second; @@ -389,7 +382,7 @@ operator=(typename conditional< __and_, is_move_assignable<_T2>>::value, - pair&&, __nonesuch_no_braces&&>::type __p) + pair&&, __nonesuch&&>::type __p) noexcept(__and_, is_nothrow_move_assignable<_T2>>::value) { Index: libstdc++-v3/include/experimental/type_traits === --- libstdc++-v3/include/experimental/type_traits (revision 270630) +++ libstdc++-v3/include/experimental/type_traits (working copy) @@ -226,9 +226,9 @@ template using void_t = void; -struct nonesuch +struct __nonesuchbase{}; +struct nonesuch : private __nonesuchbase { - nonesuch() = delete; ~nonesuch() = delete; nonesuch(nonesuch const&) = delete; void operator=(nonesuch const&) = delete; Index: libstdc++-v3/include/std/tuple === --- libstdc++-v3/include/std/tuple (revision 270630) +++ libstdc++-v3/include/std/tuple (working copy) @@ -816,7 +816,7 @@ tuple& operator=(typename conditional<__assignable(), const tuple&, - const __nonesuch_no_braces&>::type __in) + const __nonesuch&>::type __in) noexcept(__nothrow_assignable()) { this->_M_assign(__in); @@ -826,7 +826,7 @@ tuple& operator=(typename conditional<__assignable<_Elements...>(), tuple&&, - __nonesuch_no_braces&&>::type __in) + __nonesuch&&>::type __in) noexcept(__nothrow_assignable<_Elements...>()) { this->_M_assign(std::move(__in)); @@ -1204,7 +1204,7 @@ tuple& operator=(typename conditional<__assignable(), const tuple&, - const __nonesuch_no_braces&>::type __in) + const __nonesuch&>::type __in) noexcept(__nothrow_assignable()) { this->_M_assign(__in); @@ -1214,7 +1214,7 @@ tuple& operator=(typename conditional<__assignable<_T1, _T2>(), tuple&&, - __nonesuch_no_braces&&>::type __in) + __nonesuch&&>::type __in) noexcept(__nothrow_assignable<_T1, _T2>()) { this->_M_assign(std::move(__in)); Index: libstdc++-v3/include/std/type_traits === --- libstdc++-v3/include/std/type_traits (revision 270630) +++ libstdc++-v3/include/std/type_traits (working copy) @@ -2769,8 +2769,8 @@ __call_is_nothrow_<_Fn, _Args...>>::type { }; - struct __nonesuch { -__nonesuch() = delete; + struct __nonesuchbase{}; + struct __nonesuch : private __nonesuchbase{ ~__nonesuch() = delete; __nonesuch(__nonesuch const&) = delete; void operator=(__nonesuch const&) = delete; Index: libstdc++-v3/testsuite/20_util/nonesuch/nonesuch.cc =
[v3 PATCH] Inconsistency wrt Allocators in basic_string assignment vs. basic_string::assign (LWG2579)
Tested on Linux x86_64 Inconsistency wrt Allocators in basic_string assignment vs. basic_string::assign (LWG2579) 2019-05-09 Nina Dinka Ranns Inconsistency wrt Allocators in basic_string assignment vs. basic_string::assign (LWG2579) * include/bits/basic_string.h: operator=(const basic_string& __str): moved allocator decision from operator= to assign assign(const basic_string& __str): moved allocator decision from operator= to assign * testsuite/21_strings/basic_string/allocator/char/copy_assign.cc: Adding tests * testsuite/21_strings/basic_string/allocator/wchar_t/copy_assign.cc: Adding tests Index: libstdc++-v3/include/bits/basic_string.h === --- libstdc++-v3/include/bits/basic_string.h (revision 270943) +++ libstdc++-v3/include/bits/basic_string.h (working copy) @@ -664,35 +664,6 @@ basic_string& operator=(const basic_string& __str) { -#if __cplusplus >= 201103L - if (_Alloc_traits::_S_propagate_on_copy_assign()) - { - if (!_Alloc_traits::_S_always_equal() && !_M_is_local() - && _M_get_allocator() != __str._M_get_allocator()) - { - // Propagating allocator cannot free existing storage so must - // deallocate it before replacing current allocator. - if (__str.size() <= _S_local_capacity) - { - _M_destroy(_M_allocated_capacity); - _M_data(_M_local_data()); - _M_set_length(0); - } - else - { - const auto __len = __str.size(); - auto __alloc = __str._M_get_allocator(); - // If this allocation throws there are no effects: - auto __ptr = _Alloc_traits::allocate(__alloc, __len + 1); - _M_destroy(_M_allocated_capacity); - _M_data(__ptr); - _M_capacity(__len); - _M_set_length(__len); - } - } - std::__alloc_on_copy(_M_get_allocator(), __str._M_get_allocator()); - } -#endif return this->assign(__str); } @@ -1363,6 +1334,35 @@ basic_string& assign(const basic_string& __str) { +#if __cplusplus >= 201103L + if (_Alloc_traits::_S_propagate_on_copy_assign()) + { + if (!_Alloc_traits::_S_always_equal() && !_M_is_local() + && _M_get_allocator() != __str._M_get_allocator()) + { + // Propagating allocator cannot free existing storage so must + // deallocate it before replacing current allocator. + if (__str.size() <= _S_local_capacity) + { + _M_destroy(_M_allocated_capacity); + _M_data(_M_local_data()); + _M_set_length(0); + } + else + { + const auto __len = __str.size(); + auto __alloc = __str._M_get_allocator(); + // If this allocation throws there are no effects: + auto __ptr = _Alloc_traits::allocate(__alloc, __len + 1); + _M_destroy(_M_allocated_capacity); + _M_data(__ptr); + _M_capacity(__len); + _M_set_length(__len); + } + } + std::__alloc_on_copy(_M_get_allocator(), __str._M_get_allocator()); + } +#endif this->_M_assign(__str); return *this; } Index: libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/copy_assign.cc === --- libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/copy_assign.cc (revision 270943) +++ libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/copy_assign.cc (working copy) @@ -133,10 +133,47 @@ VERIFY( v1.get_allocator() == a2 ); } +void test04() +{ + // LWG2579 + typedef propagating_allocator alloc_type; + + typedef std::basic_string test_type; + + test_type v1("tralalala",alloc_type(1)); + test_type v2("content", alloc_type(2)); + test_type v3("content2", alloc_type(3)); + + v1.assign(v2); + v3 = v2; + VERIFY(2 == v1.get_allocator().get_personality()); + VERIFY(2 == v3.get_allocator().get_personality()); + +} + +void test05() +{ + // LWG2579 + typedef propagating_allocator alloc_type; + + typedef std::basic_string test_type; + + test_type v1("tralalala",alloc_type(1)); + test_type v2("content", alloc_type(2)); + test_type v3("content2", alloc_type(3)); + + v1.assign(v2); + v3 = v2; + VERIFY(1 == v1.get_allocator().get_personality()); + VERIFY(3 == v3.get_allocator().get_personality()); +} + int main() { test01(); test02(); test03(); + test04(); + test05(); return 0; } Index: libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/copy_assign.cc === --- libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/copy_assign.cc (revision 270943) +++ libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/copy_assign.cc (working copy) @@ -133,10 +133,46 @@ VERIFY( v1.get_allocator() == a2 ); } +void test04() +{ + // LWG2579 + typedef propagating_allocator alloc_t
Re: [v3 PATCH] Make stateful allocator propagation more consistent for operator+(basic_string) (P1165R1)
On Tue, 7 May 2019 at 12:22, Jonathan Wakely wrote: > > I can remove that #if and test and commit the result for you though, > no need for another revision of the patch. Thanks ! :) Best, Nina
Re: [v3 PATCH] Make stateful allocator propagation more consistent for operator+(basic_string) (P1165R1)
Ack. I've put the use of _Alloc_traits::is_always_equal within #if __cplusplus >= 201703L block since it is officially a C++17 feature. Let me know if you think that's an overkill. New changelog below. I didn't change the description of operator+(basic_string&&,basic_string&&) as it's still technically always resulting in an allocator from the first parameter. 2019-05-01 Nina Dinka Ranns Make stateful allocator propagation more consistent foroperator+(basic_string) (P1165R1) * include/bits/basic_string.h: (operator+(basic_string&&,basic_string&&) : Changed resulting allocator to always be the one from the first parameter * include/bits/basic_string.tcc: (operator+(const _CharT*, const basic_string&)) : Changed resulting allocator to be SOCCC on the second parameter's allocator (operator+(_CharT, const basic_string&)) : Likewise * testsuite/21_strings/basic_string/allocator/char/operator_plus.cc: New * testsuite/21_strings/basic_string/allocator/wchar_t/operator_plus.cc: New Index: libstdc++-v3/include/bits/basic_string.h === --- libstdc++-v3/include/bits/basic_string.h (revision 270655) +++ libstdc++-v3/include/bits/basic_string.h (working copy) @@ -6097,11 +6097,22 @@ operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs, basic_string<_CharT, _Traits, _Alloc>&& __rhs) { - const auto __size = __lhs.size() + __rhs.size(); - const bool __cond = (__size > __lhs.capacity() - && __size <= __rhs.capacity()); - return __cond ? std::move(__rhs.insert(0, __lhs)) - : std::move(__lhs.append(__rhs)); + using _Alloc_traits = allocator_traits<_Alloc>; + bool __use_rhs = false; +#if __cplusplus >= 201703L + if _GLIBCXX17_CONSTEXPR (typename _Alloc_traits::is_always_equal{}) + __use_rhs = true; + else +#endif + if (__lhs.get_allocator() == __rhs.get_allocator()) + __use_rhs = true; + if (__use_rhs) + { + const auto __size = __lhs.size() + __rhs.size(); + if (__size > __lhs.capacity() && __size <= __rhs.capacity()) + return std::move(__rhs.insert(0, __lhs)); + } + return std::move(__lhs.append(__rhs)); } template Index: libstdc++-v3/include/bits/basic_string.tcc === --- libstdc++-v3/include/bits/basic_string.tcc (revision 270655) +++ libstdc++-v3/include/bits/basic_string.tcc (working copy) @@ -1161,8 +1161,12 @@ __glibcxx_requires_string(__lhs); typedef basic_string<_CharT, _Traits, _Alloc> __string_type; typedef typename __string_type::size_type __size_type; + typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template + rebind<_CharT>::other _Char_alloc_type; + typedef __gnu_cxx::__alloc_traits<_Char_alloc_type> _Alloc_traits; const __size_type __len = _Traits::length(__lhs); - __string_type __str; + __string_type __str(_Alloc_traits::_S_select_on_copy( + __rhs.get_allocator())); __str.reserve(__len + __rhs.size()); __str.append(__lhs, __len); __str.append(__rhs); @@ -1175,7 +1179,11 @@ { typedef basic_string<_CharT, _Traits, _Alloc> __string_type; typedef typename __string_type::size_type __size_type; - __string_type __str; + typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template + rebind<_CharT>::other _Char_alloc_type; + typedef __gnu_cxx::__alloc_traits<_Char_alloc_type> _Alloc_traits; + __string_type __str(_Alloc_traits::_S_select_on_copy( + __rhs.get_allocator())); const __size_type __len = __rhs.size(); __str.reserve(__len + 1); __str.append(__size_type(1), __lhs); Index: libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/operator_plus.cc === --- libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/operator_plus.cc (nonexistent) +++ libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/operator_plus.cc (working copy) @@ -0,0 +1,151 @@ +// 2019-04-30 Nina Dinka Ranns +// Copyright (C) 2019 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 Pub
[v3 PATCH] Make stateful allocator propagation more consistent for operator+(basic_string) (P1165R1)
Tested on Linux x86_64 Make stateful allocator propagation more consistent for operator+(basic_string) (P1165R1) 2019-05-01 Nina Dinka Ranns Make stateful allocator propagation more consistent for operator+(basic_string) (P1165R1) * include/bits/basic_string.tcc: (operator+(const _CharT*, const basic_string&)) : Changed resulting allocator to be SOCCC on the second parameter's allocator (operator+(_CharT, const basic_string&)) : Likewise (operator+(basic_string&&,basic_string&&) : Changed resulting allocator to always be the one from the first parameter * testsuite/21_strings/basic_string/allocator/char/operator_plus.cc: New * testsuite/21_strings/basic_string/allocator/wchar_t/operator_plus.cc : New Index: libstdc++-v3/include/bits/basic_string.h === --- libstdc++-v3/include/bits/basic_string.h (revision 270655) +++ libstdc++-v3/include/bits/basic_string.h (working copy) @@ -6096,13 +6096,7 @@ inline basic_string<_CharT, _Traits, _Alloc> operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs, basic_string<_CharT, _Traits, _Alloc>&& __rhs) -{ - const auto __size = __lhs.size() + __rhs.size(); - const bool __cond = (__size > __lhs.capacity() - && __size <= __rhs.capacity()); - return __cond ? std::move(__rhs.insert(0, __lhs)) - : std::move(__lhs.append(__rhs)); -} +{ return std::move(__lhs.append(__rhs)); } template inline basic_string<_CharT, _Traits, _Alloc> Index: libstdc++-v3/include/bits/basic_string.tcc === --- libstdc++-v3/include/bits/basic_string.tcc (revision 270655) +++ libstdc++-v3/include/bits/basic_string.tcc (working copy) @@ -1161,8 +1161,12 @@ __glibcxx_requires_string(__lhs); typedef basic_string<_CharT, _Traits, _Alloc> __string_type; typedef typename __string_type::size_type __size_type; + typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template + rebind<_CharT>::other _Char_alloc_type; + typedef __gnu_cxx::__alloc_traits<_Char_alloc_type> _Alloc_traits; const __size_type __len = _Traits::length(__lhs); - __string_type __str; + __string_type __str(_Alloc_traits::_S_select_on_copy( + __rhs.get_allocator())); __str.reserve(__len + __rhs.size()); __str.append(__lhs, __len); __str.append(__rhs); @@ -1175,7 +1179,11 @@ { typedef basic_string<_CharT, _Traits, _Alloc> __string_type; typedef typename __string_type::size_type __size_type; - __string_type __str; + typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template + rebind<_CharT>::other _Char_alloc_type; + typedef __gnu_cxx::__alloc_traits<_Char_alloc_type> _Alloc_traits; + __string_type __str(_Alloc_traits::_S_select_on_copy( + __rhs.get_allocator())); const __size_type __len = __rhs.size(); __str.reserve(__len + 1); __str.append(__size_type(1), __lhs); Index: libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/operator_plus.cc === --- libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/operator_plus.cc (nonexistent) +++ libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/operator_plus.cc (working copy) @@ -0,0 +1,151 @@ +// 2019-04-30 Nina Dinka Ranns +// Copyright (C) 2019 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 +// <http://www.gnu.org/licenses/>. + +// { dg-do run { target c++11 } } +// COW strings don't support C++11 allocators: +// { dg-require-effective-target cxx11-abi } + +#include +#include +#include +#include + +using C = char; +using traits = std::char_traits; + +using __gnu_test::propagating_allocator; + +void test01() +{ + typedef propagating_allocator alloc_type; + typedef std::basic_string test_type; + + test_type v1("something",alloc_type(1)); + test_type v2("something",alloc_type(2)); + auto r1 = v1 + v2; + VERIFY(r1.get_allocator().get_personality() == 1); + + auto r2 = v1 + std::
Re: Adding noexcept-specification on tuple constructors (LWG 2899)
noted, thanks :) Best, Nina On Sun, 28 Apr 2019 at 22:46, Jonathan Wakely wrote: > > On 28/04/19 22:44 +0100, Jonathan Wakely wrote: > >On 29/04/19 00:18 +0300, Ville Voutilainen wrote: > >>On Wed, 24 Apr 2019 at 14:53, Jonathan Wakely wrote: > >>> > >>>On 24/04/19 11:21 +0100, Nina Dinka Ranns wrote: > >>>>New diff attached. > >>> > >>>Thanks, this looks great. I think we can apply this as soon as stage 1 > >>>begins (which should be Real Soon Now). > >> > >>Tested on Linux-PPC64, committed to trunk. Congrats, Nina, first patch > >>in, let there be many more. :) > > > >Thanks, Nina, and Ville for taking care of the commit. > > > >Apologies for not noticing it earlier, but the first line of the > >ChangeLog entry was not formatted correctly. There should be two > >spaces either side of the author's name: > > > >2019-04-28 John Doe > > > >not: > > > >2019-04-28 John Doe > > > >I've committed r270633 to fix it. > > > >Thanks again. > > Oh, and the files in the ChangeLog entry should use paths relative to > the ChangeLog file, so no libstdc++-v3/ prefixes. I missed that in the > review too. > >
Re: Adding noexcept-specification on tuple constructors (LWG 2899)
On Tue, 23 Apr 2019 at 21:28, Jonathan Wakely wrote: > > On 23/04/19 18:43 +0100, Nina Dinka Ranns wrote: > >On Thu, 18 Apr 2019 at 21:35, Jonathan Wakely wrote: > >> > >> On 16/04/19 17:59 +0100, Nina Dinka Ranns wrote: > >> >On Tue, 16 Apr 2019 at 15:18, Jonathan Wakely wrote: > >> >> > >> >> On 16/04/19 14:08 +0100, Nina Dinka Ranns wrote: > >> >> >Tested on Linux-PPC64 > >> >> >Adding noexcept-specification on tuple constructors (LWG 2899) > >> >> > >> >> Thanks, Nina! > >> >> > >> >> This looks great, although as I think Ville has explained we won't > >> >> commit it until the next stage 1, after the GCC 9 release. > >> >ack > >> > > >> >> > >> >> The changes look good, I just have some mostly-stylistic comments, > >> >> which are inline below ... > >> >> > >> >> > >> >> >2019-04-13 Nina Dinka Ranns > >> >> > > >> >> >Adding noexcept-specification on tuple constructors (LWG 2899) > >> >> >* libstdc++-v3/include/std/tuple: > >> >> >(tuple()): Add noexcept-specification. > >> >> >(tuple(const _Elements&...)): Likewise > >> >> >(tuple(_UElements&&...)): Likewise > >> >> >(tuple(const tuple<_UElements...>&)): Likewise > >> >> >(tuple(tuple<_UElements...>&&)): Likewise > >> >> >(tuple(const _T1&, const _T2&)): Likewise > >> >> >(tuple(_U1&&, _U2&&)): Likewise > >> >> >(tuple(const tuple<_U1, _U2>&): Likewise > >> >> >(tuple(tuple<_U1, _U2>&&): Likewise > >> >> >(tuple(const pair<_U1, _U2>&): Likewise > >> >> >(tuple(pair<_U1, _U2>&&): Likewise > >> >> > > >> >> > > >> >> > >> >> There should be no blank lines in the changelog entry here. A single > >> >> change should be recorded as a single block in the changelog, with no > >> >> blank lines within it. > >> >ack. Do you need me to do anything about this or is it for future > >> >reference only ? > >> > >> For future reference. Whoever commits the patch can correct the > >> changelog. > >> > >> >> > >> >> >* libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc: > >> >> > New > >> >> >* > >> >> > libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs2.cc: New > >> >> >* > >> >> > libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs3.cc: New > >> >> >* > >> >> > libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs4.cc: New > >> >> >* > >> >> > libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs5.cc: New > >> >> >* > >> >> > libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs6.cc: New > >> >> > >> >> This is a lot of new test files for a small-ish QoI feature. Could > >> >> they be combined into one file? Generally we do want one test file > >> >> per feature, but I think all of these are arguably testing one feature > >> >> (just on different constructors). The downside of lots of smaller > >> >> files is that we have to compile+assemble+link+run each one, which > >> >> adds several fork()s to launch a new process for each step. On some > >> >> platforms that can be quite slow. > >> >I can do that, but there may be an issue. See below. > >> > > >> >> > >> >> > >> >> >@@ -624,6 +634,7 @@ > >> >> > && (sizeof...(_Elements) >= 1), > >> >> > bool>::type=true> > >> >> > constexpr tuple(_UElements&&... __elements) > >> >> >+ > >> >> >noexcept(__and_...>::value) > >> >> > >> >> Can this be __nothrow_constructible<_UElements>() ? > >> >It should have been that in the first place. Apologies. Fixed. > >> > > >> > > >> >>
Re: Adding noexcept-specification on tuple constructors (LWG 2899)
On Thu, 18 Apr 2019 at 21:35, Jonathan Wakely wrote: > > On 16/04/19 17:59 +0100, Nina Dinka Ranns wrote: > >On Tue, 16 Apr 2019 at 15:18, Jonathan Wakely wrote: > >> > >> On 16/04/19 14:08 +0100, Nina Dinka Ranns wrote: > >> >Tested on Linux-PPC64 > >> >Adding noexcept-specification on tuple constructors (LWG 2899) > >> > >> Thanks, Nina! > >> > >> This looks great, although as I think Ville has explained we won't > >> commit it until the next stage 1, after the GCC 9 release. > >ack > > > >> > >> The changes look good, I just have some mostly-stylistic comments, > >> which are inline below ... > >> > >> > >> >2019-04-13 Nina Dinka Ranns > >> > > >> >Adding noexcept-specification on tuple constructors (LWG 2899) > >> >* libstdc++-v3/include/std/tuple: > >> >(tuple()): Add noexcept-specification. > >> >(tuple(const _Elements&...)): Likewise > >> >(tuple(_UElements&&...)): Likewise > >> >(tuple(const tuple<_UElements...>&)): Likewise > >> >(tuple(tuple<_UElements...>&&)): Likewise > >> >(tuple(const _T1&, const _T2&)): Likewise > >> >(tuple(_U1&&, _U2&&)): Likewise > >> >(tuple(const tuple<_U1, _U2>&): Likewise > >> >(tuple(tuple<_U1, _U2>&&): Likewise > >> >(tuple(const pair<_U1, _U2>&): Likewise > >> >(tuple(pair<_U1, _U2>&&): Likewise > >> > > >> > > >> > >> There should be no blank lines in the changelog entry here. A single > >> change should be recorded as a single block in the changelog, with no > >> blank lines within it. > >ack. Do you need me to do anything about this or is it for future > >reference only ? > > For future reference. Whoever commits the patch can correct the > changelog. > > >> > >> >* libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc: New > >> >* libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs2.cc: > >> > New > >> >* libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs3.cc: > >> > New > >> >* libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs4.cc: > >> > New > >> >* libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs5.cc: > >> > New > >> >* libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs6.cc: > >> > New > >> > >> This is a lot of new test files for a small-ish QoI feature. Could > >> they be combined into one file? Generally we do want one test file > >> per feature, but I think all of these are arguably testing one feature > >> (just on different constructors). The downside of lots of smaller > >> files is that we have to compile+assemble+link+run each one, which > >> adds several fork()s to launch a new process for each step. On some > >> platforms that can be quite slow. > >I can do that, but there may be an issue. See below. > > > >> > >> > >> >@@ -624,6 +634,7 @@ > >> > && (sizeof...(_Elements) >= 1), > >> > bool>::type=true> > >> > constexpr tuple(_UElements&&... __elements) > >> >+ > >> >noexcept(__and_...>::value) > >> > >> Can this be __nothrow_constructible<_UElements>() ? > >It should have been that in the first place. Apologies. Fixed. > > > > > >> > >> > : _Inherited(std::forward<_UElements>(__elements)...) { } > >> > > >> > template >> >@@ -635,6 +646,7 @@ > >> > && (sizeof...(_Elements) >= 1), > >> > bool>::type=false> > >> > explicit constexpr tuple(_UElements&&... __elements) > >> >+noexcept(__nothrow_constructible<_UElements&&...>()) > >> > >> The && here is redundant, though harmless. > >> > >> is_constructible is exactly equivalent to is_constructible > >> because U means construction from an rvalue of type U and so does U&&. > >> > >> It's fine to leave the && there though. > >I'm happy to go either way. The only reason I us
Re: Adding noexcept-specification on tuple constructors (LWG 2899)
On Tue, 16 Apr 2019 at 15:18, Jonathan Wakely wrote: > > On 16/04/19 14:08 +0100, Nina Dinka Ranns wrote: > >Tested on Linux-PPC64 > >Adding noexcept-specification on tuple constructors (LWG 2899) > > Thanks, Nina! > > This looks great, although as I think Ville has explained we won't > commit it until the next stage 1, after the GCC 9 release. ack > > The changes look good, I just have some mostly-stylistic comments, > which are inline below ... > > > >2019-04-13 Nina Dinka Ranns > > > >Adding noexcept-specification on tuple constructors (LWG 2899) > >* libstdc++-v3/include/std/tuple: > >(tuple()): Add noexcept-specification. > >(tuple(const _Elements&...)): Likewise > >(tuple(_UElements&&...)): Likewise > >(tuple(const tuple<_UElements...>&)): Likewise > >(tuple(tuple<_UElements...>&&)): Likewise > >(tuple(const _T1&, const _T2&)): Likewise > >(tuple(_U1&&, _U2&&)): Likewise > >(tuple(const tuple<_U1, _U2>&): Likewise > >(tuple(tuple<_U1, _U2>&&): Likewise > >(tuple(const pair<_U1, _U2>&): Likewise > >(tuple(pair<_U1, _U2>&&): Likewise > > > > > > There should be no blank lines in the changelog entry here. A single > change should be recorded as a single block in the changelog, with no > blank lines within it. ack. Do you need me to do anything about this or is it for future reference only ? > > >* libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc: New > >* libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs2.cc: New > >* libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs3.cc: New > >* libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs4.cc: New > >* libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs5.cc: New > >* libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs6.cc: New > > This is a lot of new test files for a small-ish QoI feature. Could > they be combined into one file? Generally we do want one test file > per feature, but I think all of these are arguably testing one feature > (just on different constructors). The downside of lots of smaller > files is that we have to compile+assemble+link+run each one, which > adds several fork()s to launch a new process for each step. On some > platforms that can be quite slow. I can do that, but there may be an issue. See below. > > > >@@ -624,6 +634,7 @@ > > && (sizeof...(_Elements) >= 1), > > bool>::type=true> > > constexpr tuple(_UElements&&... __elements) > >+ > >noexcept(__and_...>::value) > > Can this be __nothrow_constructible<_UElements>() ? It should have been that in the first place. Apologies. Fixed. > > > : _Inherited(std::forward<_UElements>(__elements)...) { } > > > > template >@@ -635,6 +646,7 @@ > > && (sizeof...(_Elements) >= 1), > > bool>::type=false> > > explicit constexpr tuple(_UElements&&... __elements) > >+noexcept(__nothrow_constructible<_UElements&&...>()) > > The && here is redundant, though harmless. > > is_constructible is exactly equivalent to is_constructible > because U means construction from an rvalue of type U and so does U&&. > > It's fine to leave the && there though. I'm happy to go either way. The only reason I used && form is because it mimics the wording in the LWG resolution. > > > >@@ -966,6 +995,7 @@ > > && !is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value, > > bool>::type = true> > > constexpr tuple(_U1&& __a1, _U2&& __a2) > >+noexcept(__nothrow_constructible<_U1&&,_U2&&>()) > > There should be a space after the comma here, and all the later > additions in the file. ack. Fixed > > > >Index: libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc > >=== > >--- libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc > >(nonexistent) > >+++ libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc > >(working copy) > >@@ -0,0 +1,191 @@ > >+// { dg-options { -std=gnu++2a } } > >+// { dg-do run { target c++2a } } > > This new file doesn't use std::is_nothrow_convertible so
Adding noexcept-specification on tuple constructors (LWG 2899)
Tested on Linux-PPC64 Adding noexcept-specification on tuple constructors (LWG 2899) 2019-04-13 Nina Dinka Ranns Adding noexcept-specification on tuple constructors (LWG 2899) * libstdc++-v3/include/std/tuple: (tuple()): Add noexcept-specification. (tuple(const _Elements&...)): Likewise (tuple(_UElements&&...)): Likewise (tuple(const tuple<_UElements...>&)): Likewise (tuple(tuple<_UElements...>&&)): Likewise (tuple(const _T1&, const _T2&)): Likewise (tuple(_U1&&, _U2&&)): Likewise (tuple(const tuple<_U1, _U2>&): Likewise (tuple(tuple<_U1, _U2>&&): Likewise (tuple(const pair<_U1, _U2>&): Likewise (tuple(pair<_U1, _U2>&&): Likewise * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc: New * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs2.cc: New * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs3.cc: New * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs4.cc: New * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs5.cc: New * libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs6.cc: New noexcept_tuple.diff Description: Binary data