This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch] Make vector::at() assertion message more useful (try #2)
- From: Paul Pluzhnikov <ppluzhnikov at google dot com>
- To: gcc-patches at gcc dot gnu dot org, libstdc++ at gcc dot gnu dot org
- Cc: ppluzhnikov at google dot com
- Date: Wed, 04 Sep 2013 13:53:31 -0700
- Subject: [patch] Make vector::at() assertion message more useful (try #2)
- Authentication-results: sourceware.org; auth=none
Greetings,
This is a followup to:
http://gcc.gnu.org/ml/libstdc++/2013-08/msg00096.html
Without this patch, the user on vector::at out of bounds sees:
terminate called after throwing an instance of 'std::out_of_range'
what(): vector::_M_range_check
Aborted (core dumped)
With the patch:
terminate called after throwing an instance of 'std::out_of_range'
what(): vector::_M_range_check: __n (which is 3) >= this->size() (which is 2)
Aborted (core dumped)
I am not at all sure the names I choose here are good ones. Suggestions
welcome.
I also shudder at the idea of repeating _M_range_check code in
e.g. string::at(), and elsewhere. Perhaps we need a snprintf_lite, that
only understands '%zu' and literal characters, e.g.:
snprintf_lite(__s, sizeof(__s),
_N("vector::_M_range_check: __n (which is %zu) >= "
"this->size() (which is %zu)"), __n, this->size());
[The patch also doesn't include libstdc++-v3/libsupc++/Makefile.in,
which I'll regenerate before submitting.]
[Please CC me on any replies.]
--
Paul Pluzhnikov
2013-09-04 Paul Pluzhnikov <ppluzhnikov@google.com>
* libstdc++-v3/config/abi/pre/gnu.ver: Add
_ZN9__gnu_cxx13concat_size_tEPcm
* libstdc++-v3/include/bits/stl_vector.h (_M_range_check): Print
additional assertion details
* libstdc++-v3/libsupc++/Makefile.am: Add support.cc
* libstdc++-v3/libsupc++/support.cc: New
* libstdc++-v3/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.
Index: libstdc++-v3/config/abi/pre/gnu.ver
===================================================================
--- libstdc++-v3/config/abi/pre/gnu.ver (revision 202262)
+++ libstdc++-v3/config/abi/pre/gnu.ver (working copy)
@@ -1365,6 +1365,9 @@
# std::get_unexpected()
_ZSt14get_unexpectedv;
+ # __gnu_cxx::concat_size_t(char*, unsigned long)
+ _ZN9__gnu_cxx13concat_size_tEPcm;
+
} GLIBCXX_3.4.19;
# Symbols in the support library (libsupc++) have their own tag.
Index: libstdc++-v3/include/bits/stl_vector.h
===================================================================
--- libstdc++-v3/include/bits/stl_vector.h (revision 202262)
+++ libstdc++-v3/include/bits/stl_vector.h (working copy)
@@ -63,6 +63,10 @@
#include <initializer_list>
#endif
+namespace __gnu_cxx {
+ int concat_size_t(char *, size_t);
+}
+
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
@@ -791,7 +795,26 @@
_M_range_check(size_type __n) const
{
if (__n >= this->size())
- __throw_out_of_range(__N("vector::_M_range_check"));
+ {
+ const char __p[] = __N("vector::_M_range_check: __n (which is ");
+ const char __q[] = __N(") >= this->size() (which is ");
+
+ // Enough space for __p, __q, size and __n (in decimal).
+ const int __alloc_size =
+ sizeof(__p) + sizeof(__q) + 3 * 2 * sizeof(size_type) + 10;
+
+ char *__s = static_cast<char*>(__builtin_alloca(__alloc_size));
+ char *__ps = __s;
+ __builtin_memcpy(__ps, __p, sizeof(__p));
+ __ps += sizeof(__p) - 1;
+ __ps += __gnu_cxx::concat_size_t(__ps, __n);
+ __builtin_memcpy(__ps, __q, sizeof(__q));
+ __ps += sizeof(__q) - 1;
+ __ps += __gnu_cxx::concat_size_t(__ps, this->size());
+ *(__ps++) = __N(')');
+ *(__ps++) = '\0';
+ __throw_out_of_range(__s);
+ }
}
public:
Index: libstdc++-v3/libsupc++/Makefile.am
===================================================================
--- libstdc++-v3/libsupc++/Makefile.am (revision 202262)
+++ libstdc++-v3/libsupc++/Makefile.am (working copy)
@@ -91,6 +91,7 @@
pointer_type_info.cc \
pure.cc \
si_class_type_info.cc \
+ support.cc \
tinfo.cc \
tinfo2.cc \
vec.cc \
Index: libstdc++-v3/libsupc++/support.cc
===================================================================
--- libstdc++-v3/libsupc++/support.cc (revision 0)
+++ libstdc++-v3/libsupc++/support.cc (revision 0)
@@ -0,0 +1,53 @@
+// 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 <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 {
+
+// Exported routine to append decimal representation of __val to the given
+// buffer, which must be at least 21 characters long in 64-bit mode.
+// Does not NUL-terminate the output buffer.
+// Returns number of characters appended.
+ int concat_size_t(char *__buf, size_t __val)
+ {
+ // Long enough for decimal representation.
+ int __ilen = 3 * sizeof(__val);
+ char *__cs = static_cast<char*>(__builtin_alloca(__ilen));
+ int __len = std::__int_to_char(__cs + __ilen, __val,
+ std::__num_base::_S_atoms_out,
+ std::ios_base::dec, true);
+ __builtin_memcpy(__buf, __cs + __ilen - __len, __len);
+ return __len;
+ }
+
+} // __gnu_cxx
Index: libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc
===================================================================
--- libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc (revision 202262)
+++ libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc (working copy)
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1308 }
+// { dg-error "no matching" "" { target *-*-* } 1331 }
#include <vector>
Index: libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc
===================================================================
--- libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc (revision 202262)
+++ libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc (working copy)
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1349 }
+// { dg-error "no matching" "" { target *-*-* } 1372 }
#include <vector>
Index: libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc
===================================================================
--- libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc (revision 202262)
+++ libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc (working copy)
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1234 }
+// { dg-error "no matching" "" { target *-*-* } 1257 }
#include <vector>
Index: libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc
===================================================================
--- libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc (revision 202262)
+++ libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc (working copy)
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1234 }
+// { dg-error "no matching" "" { target *-*-* } 1257 }
#include <vector>
#include <utility>