From 885e812159dcbf83f790eee9d839f91daa553eb3 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Sun, 9 Sep 2012 17:56:51 +0000 Subject: [PATCH] re PR libstdc++/54388 (std::array.at() const results in undefined behaviour) PR libstdc++/54388 * include/std/array (array::at() const): Ensure lvalue result. * testsuite/23_containers/array/element_access/54388.cc: New. * testsuite/23_containers/array/tuple_interface/get_neg.cc: Adjust dg-error line numbers. * testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc: Likewise. From-SVN: r191114 --- libstdc++-v3/ChangeLog | 10 +++++ libstdc++-v3/include/std/array | 16 ++----- .../array/element_access/54388.cc | 42 +++++++++++++++++++ .../array/tuple_interface/get_neg.cc | 2 +- .../tuple_interface/tuple_element_neg.cc | 2 +- 5 files changed, 58 insertions(+), 14 deletions(-) create mode 100644 libstdc++-v3/testsuite/23_containers/array/element_access/54388.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 34a9d76db1d..fd47591c8bb 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,13 @@ +2012-09-08 Jonathan Wakely + + PR libstdc++/54388 + * include/std/array (array::at() const): Ensure lvalue result. + * testsuite/23_containers/array/element_access/54388.cc: New. + * testsuite/23_containers/array/tuple_interface/get_neg.cc: Adjust + dg-error line numbers. + * testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc: + Likewise. + 2012-09-09 Ulrich Drepper Dominique d'Humieres Jack Howarth diff --git a/libstdc++-v3/include/std/array b/libstdc++-v3/include/std/array index 58263ce418a..4ee21998b01 100644 --- a/libstdc++-v3/include/std/array +++ b/libstdc++-v3/include/std/array @@ -164,22 +164,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return _M_instance[__n]; } -#ifdef __EXCEPTIONS constexpr const_reference at(size_type __n) const { - return __n < _Nm ? - _M_instance[__n] : throw out_of_range(__N("array::at")); + // Result of conditional expression must be an lvalue so use + // boolean ? lvalue : (throw-expr, lvalue) + return __n < _Nm ? _M_instance[__n] + : (std::__throw_out_of_range(__N("array::at")), _M_instance[0]); } -#else - const_reference - at(size_type __n) const - { - if (__n >= _Nm) - std::__throw_out_of_range(__N("array::at")); - return _M_instance[__n]; - } -#endif reference front() diff --git a/libstdc++-v3/testsuite/23_containers/array/element_access/54388.cc b/libstdc++-v3/testsuite/23_containers/array/element_access/54388.cc new file mode 100644 index 00000000000..a69a5edb6a0 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/array/element_access/54388.cc @@ -0,0 +1,42 @@ +// { dg-options "-std=gnu++0x" } +// +// Copyright (C) 2012 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 +// . + +#include +#include + +struct A +{ + bool valid = true; + ~A() { valid = false; } +}; + +void +test01() +{ + bool test __attribute__((unused)) = true; + + const std::array a; + const A& aa = a.at(0); + VERIFY(aa.valid); +} + +int main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/23_containers/array/tuple_interface/get_neg.cc b/libstdc++-v3/testsuite/23_containers/array/tuple_interface/get_neg.cc index ecc25bf8387..2fc443edad6 100644 --- a/libstdc++-v3/testsuite/23_containers/array/tuple_interface/get_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/array/tuple_interface/get_neg.cc @@ -29,4 +29,4 @@ int n3 = std::get<1>(ca); // { dg-error "static assertion failed" "" { target *-*-* } 275 } // { dg-error "static assertion failed" "" { target *-*-* } 283 } -// { dg-error "static assertion failed" "" { target *-*-* } 291 } +// { dg-error "static assertion failed" "" { target *-*-* } 267 } diff --git a/libstdc++-v3/testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc b/libstdc++-v3/testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc index 72638138106..97938ba669a 100644 --- a/libstdc++-v3/testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc @@ -22,4 +22,4 @@ typedef std::tuple_element<1, std::array>::type type; -// { dg-error "static assertion failed" "" { target *-*-* } 267 } +// { dg-error "static assertion failed" "" { target *-*-* } 259 }