diff options
author | Paul Pluzhnikov <ppluzhnikov@google.com> | 2013-09-21 19:04:13 -0700 |
---|---|---|
committer | Paul Pluzhnikov <ppluzhnikov@gcc.gnu.org> | 2013-09-21 19:04:13 -0700 |
commit | 9779c871afc648329500747748c70b59b47abdf7 (patch) | |
tree | 1807bb351c1ef7b319a9d9f950ffb248e213222c /libstdc++-v3/src | |
parent | 0e2148ad570e2c48e69e1d861a02bb9445719410 (diff) | |
download | gcc-9779c871afc648329500747748c70b59b47abdf7.zip gcc-9779c871afc648329500747748c70b59b47abdf7.tar.gz gcc-9779c871afc648329500747748c70b59b47abdf7.tar.bz2 |
Print additional info when various out-of-range conditions are detected.
2013-09-21 Paul Pluzhnikov <ppluzhnikov@google.com>
* include/bits/functexcept.h (__throw_out_of_range_fmt): New.
* src/c++11/functexcept.cc (__throw_out_of_range_fmt): New.
* src/c++11/snprintf_lite.cc: New.
* src/c++11/Makefile.am: Add snprintf_lite.cc.
* src/c++11/Makefile.in: Regenerate.
* config/abi/pre/gnu.ver: Add _ZSt24__throw_out_of_range_fmtPKcz.
* include/std/array (at): Use __throw_out_of_range_fmt.
* include/debug/array (at): Likewise.
* include/profile/array (at): Likewise.
* include/std/bitset (_M_check_initial_position, _M_check): New.
(bitset::bitset): Use _M_check_initial_position.
(set, reset, flip, test): Use _M_check.
* include/ext/vstring.h (_M_check, at): Use __throw_out_of_range_fmt.
* include/bits/stl_vector.h (_M_range_check): Likewise.
* include/bits/stl_bvector.h (_M_range_check): Likewise.
* include/bits/stl_deque.h (_M_range_check): Likewise.
* include/bits/basic_string.h (_M_check, at): Likewise.
* testsuite/23_containers/vector/requirements/dr438/assign_neg.cc: Adjust.
* testsuite/23_containers/vector/requirements/dr438/insert_neg.cc: Likewise.
* testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc:
Likewise.
* testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc:
Likewise.
* testsuite/23_containers/deque/requirements/dr438/assign_neg.cc: Likewise.
* testsuite/23_containers/deque/requirements/dr438/insert_neg.cc: Likewise.
* testsuite/23_containers/deque/requirements/dr438/constructor_1_neg.cc:
Likewise.
* testsuite/23_containers/deque/requirements/dr438/constructor_2_neg.cc:
Likewise.
* testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc: Likewise.
* testsuite/23_containers/array/tuple_interface/tuple_element_debug_neg.cc:
Likewise.
* testsuite/23_containers/array/tuple_interface/get_neg.cc: Likewise.
* testsuite/23_containers/array/tuple_interface/get_debug_neg.cc: Likewise.
* testsuite/util/exception/safety.h (generate): Use __throw_out_of_range_fmt.
From-SVN: r202818
Diffstat (limited to 'libstdc++-v3/src')
-rw-r--r-- | libstdc++-v3/src/c++11/Makefile.am | 1 | ||||
-rw-r--r-- | libstdc++-v3/src/c++11/Makefile.in | 4 | ||||
-rw-r--r-- | libstdc++-v3/src/c++11/functexcept.cc | 23 | ||||
-rw-r--r-- | libstdc++-v3/src/c++11/snprintf_lite.cc | 152 |
4 files changed, 179 insertions, 1 deletions
diff --git a/libstdc++-v3/src/c++11/Makefile.am b/libstdc++-v3/src/c++11/Makefile.am index 58d3025..7dda948 100644 --- a/libstdc++-v3/src/c++11/Makefile.am +++ b/libstdc++-v3/src/c++11/Makefile.am @@ -42,6 +42,7 @@ sources = \ random.cc \ regex.cc \ shared_ptr.cc \ + snprintf_lite.cc \ system_error.cc \ thread.cc diff --git a/libstdc++-v3/src/c++11/Makefile.in b/libstdc++-v3/src/c++11/Makefile.in index 5daae3e..83b7bd1 100644 --- a/libstdc++-v3/src/c++11/Makefile.in +++ b/libstdc++-v3/src/c++11/Makefile.in @@ -70,7 +70,8 @@ libc__11convenience_la_LIBADD = am__objects_1 = chrono.lo condition_variable.lo debug.lo \ functexcept.lo functional.lo future.lo hash_c++0x.lo \ hashtable_c++0x.lo limits.lo mutex.lo placeholders.lo \ - random.lo regex.lo shared_ptr.lo system_error.lo thread.lo + random.lo regex.lo shared_ptr.lo snprintf_lite.lo \ + system_error.lo thread.lo @ENABLE_EXTERN_TEMPLATE_TRUE@am__objects_2 = fstream-inst.lo \ @ENABLE_EXTERN_TEMPLATE_TRUE@ string-inst.lo wstring-inst.lo am_libc__11convenience_la_OBJECTS = $(am__objects_1) $(am__objects_2) @@ -324,6 +325,7 @@ sources = \ random.cc \ regex.cc \ shared_ptr.cc \ + snprintf_lite.cc \ system_error.cc \ thread.cc diff --git a/libstdc++-v3/src/c++11/functexcept.cc b/libstdc++-v3/src/c++11/functexcept.cc index b0c1804..b18f8ad 100644 --- a/libstdc++-v3/src/c++11/functexcept.cc +++ b/libstdc++-v3/src/c++11/functexcept.cc @@ -31,6 +31,7 @@ #include <future> #include <functional> #include <bits/regex_error.h> +#include <stdarg.h> #ifdef _GLIBCXX_USE_NLS # include <libintl.h> @@ -39,6 +40,12 @@ # define _(msgid) (msgid) #endif +namespace __gnu_cxx +{ + int __snprintf_lite(char *__buf, size_t __bufsize, const char *__fmt, + va_list __ap); +} + namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -80,6 +87,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { _GLIBCXX_THROW_OR_ABORT(out_of_range(_(__s))); } void + __throw_out_of_range_fmt(const char* __fmt, ...) + { + const size_t __len = __builtin_strlen(__fmt); + // We expect at most 2 numbers, and 1 short string. The additional + // 512 bytes should provide more than enough space for expansion. + const size_t __alloca_size = __len + 512; + char *const __s = static_cast<char*>(__builtin_alloca(__alloca_size)); + va_list __ap; + + va_start(__ap, __fmt); + __gnu_cxx::__snprintf_lite(__s, __alloca_size, __fmt, __ap); + _GLIBCXX_THROW_OR_ABORT(out_of_range(_(__s))); + va_end(__ap); // Not reached. + } + + void __throw_runtime_error(const char* __s __attribute__((unused))) { _GLIBCXX_THROW_OR_ABORT(runtime_error(_(__s))); } diff --git a/libstdc++-v3/src/c++11/snprintf_lite.cc b/libstdc++-v3/src/c++11/snprintf_lite.cc new file mode 100644 index 0000000..9509c42 --- /dev/null +++ b/libstdc++-v3/src/c++11/snprintf_lite.cc @@ -0,0 +1,152 @@ +// Debugging support -*- C++ -*- + +// Copyright (C) 2013 Free Software Foundation, Inc. +// +// This file is part of GCC. +// +// GCC 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. +// +// GCC 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. +// +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +#include <stdarg.h> +#include <bits/functexcept.h> +#include <bits/locale_facets.h> + +namespace std { + template<typename _CharT, typename _ValueT> + int + __int_to_char(_CharT* __bufend, _ValueT __v, const _CharT* __lit, + ios_base::fmtflags __flags, bool __dec); +} + +namespace __gnu_cxx { + + // Private helper to throw logic error if snprintf_lite runs out + // of space (which is not expected to ever happen). + // NUL-terminates __buf. + void + __throw_insufficient_space(const char *__buf, const char *__bufend) + __attribute__((__noreturn__)); + + void + __throw_insufficient_space(const char *__buf, const char *__bufend) + { + // Include space for trailing NUL. + const size_t __len = __bufend - __buf + 1; + + const char __err[] = "not enough space for format expansion " + "(Please submit full bug report at http://gcc.gnu.org/bugs.html):\n "; + const size_t __errlen = sizeof(__err) - 1; + + char *const __e + = static_cast<char*>(__builtin_alloca(__errlen + __len)); + + __builtin_memcpy(__e, __err, __errlen); + __builtin_memcpy(__e + __errlen, __buf, __len - 1); + __e[__errlen + __len - 1] = '\0'; + std::__throw_logic_error(__e); + } + + + // Private routine to append decimal representation of VAL to the given + // BUFFER, but not more than BUFSIZE characters. + // Does not NUL-terminate the output buffer. + // Returns number of characters appended, or -1 if BUFSIZE is too small. + int __concat_size_t(char *__buf, size_t __bufsize, size_t __val) + { + // Long enough for decimal representation. + int __ilen = 3 * sizeof(__val); + char *__cs = static_cast<char*>(__builtin_alloca(__ilen)); + size_t __len = std::__int_to_char(__cs + __ilen, __val, + std::__num_base::_S_atoms_out, + std::ios_base::dec, true); + if (__bufsize < __len) + return -1; + + __builtin_memcpy(__buf, __cs + __ilen - __len, __len); + return __len; + } + + + // Private routine to print into __buf arguments according to format, + // not to exceed __bufsize. + // Only '%%', '%s' and '%zu' format specifiers are understood. + // Returns number of characters printed (excluding terminating NUL). + // Always NUL-terminates __buf. + // Throws logic_error on insufficient space. + int __snprintf_lite(char *__buf, size_t __bufsize, const char *__fmt, + va_list __ap) + { + char *__d = __buf; + const char *__s = __fmt; + const char *const __limit = __d + __bufsize - 1; // Leave space for NUL. + + while (__s[0] != '\0' && __d < __limit) + { + if (__s[0] == '%') + switch (__s[1]) + { + default: // Stray '%'. Just print it. + break; + case '%': // '%%' + __s += 1; + break; + case 's': // '%s'. + { + const char *__v = va_arg(__ap, const char *); + + while (__v[0] != '\0' && __d < __limit) + *__d++ = *__v++; + + if (__v[0] != '\0') + // Not enough space for __fmt expansion. + __throw_insufficient_space(__buf, __d); + + __s += 2; // Step over %s. + continue; + } + break; + case 'z': + if (__s[2] == 'u') // '%zu' -- expand next size_t arg. + { + const int __len = __concat_size_t(__d, __limit - __d, + va_arg(__ap, size_t)); + if (__len > 0) + __d += __len; + else + // Not enough space for __fmt expansion. + __throw_insufficient_space(__buf, __d); + + __s += 3; // Step over %zu + continue; + } + // Stray '%zX'. Just print it. + break; + } + *__d++ = *__s++; + } + + if (__s[0] != '\0') + // Not enough space for __fmt expansion. + __throw_insufficient_space(__buf, __d); + + *__d = '\0'; + return __d - __buf; + } + +} // __gnu_cxx |