This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Enhance __gnu_debug::string debug assertion
- From: François Dumont <frs dot dumont at gmail dot com>
- To: "libstdc++ at gcc dot gnu dot org" <libstdc++ at gcc dot gnu dot org>, gcc-patches <gcc-patches at gcc dot gnu dot org>
- Date: Thu, 5 Jul 2018 07:28:18 +0200
- Subject: Enhance __gnu_debug::string debug assertion
This patch improves the assertion message generated in 2
__gnu_debug::string constructors giving the assertion context thanks to
the __FUNCTION__ macro.
Was:
/home/fdt/dev/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/debug/string:56:
const _CharT* __gnu_debug::__check_string(const _CharT*, _Integer, const
char*, unsigned int, const char*) [with _CharT = char; _Integer = long
unsigned int]: Assertion '__s != 0 || __n == 0' failed.
XFAIL: 21_strings/basic_string/debug/1_neg.cc execution test
Now:
/home/fdt/dev/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/debug/string:172:
In function:
__gnu_debug::basic_string<_CharT, _Traits,
_Allocator>::basic_string(const _CharT*,
__gnu_debug::basic_string<_CharT, _Traits, _Allocator>::size_type,
const
_Allocator&) [with _CharT = char; _Traits = std::char_traits<char>;
_Allocator = std::allocator<char>; __gnu_debug::basic_string<_CharT,
_Traits, _Allocator>::size_type = long unsigned int]
Error: __s != 0 || __n == 0.
XFAIL: 21_strings/basic_string/debug/1_neg.cc execution test
Tested under Linux x86_64 normal and debug modes.
If not told otherwise I plan to commit the attached patch tomorrow.
François
diff --git a/libstdc++-v3/include/debug/functions.h b/libstdc++-v3/include/debug/functions.h
index 5c16a45..97b1f94 100644
--- a/libstdc++-v3/include/debug/functions.h
+++ b/libstdc++-v3/include/debug/functions.h
@@ -239,29 +239,6 @@ namespace __gnu_debug
return __foreign_iterator_aux(__it, __other, __other_end, _Integral());
}
- /** Checks that __s is non-NULL or __n == 0, and then returns __s. */
- template<typename _CharT, typename _Integer>
- inline const _CharT*
- __check_string(const _CharT* __s,
- const _Integer& __n __attribute__((__unused__)))
- {
-#ifdef _GLIBCXX_DEBUG_PEDANTIC
- __glibcxx_assert(__s != 0 || __n == 0);
-#endif
- return __s;
- }
-
- /** Checks that __s is non-NULL and then returns __s. */
- template<typename _CharT>
- inline const _CharT*
- __check_string(const _CharT* __s)
- {
-#ifdef _GLIBCXX_DEBUG_PEDANTIC
- __glibcxx_assert(__s != 0);
-#endif
- return __s;
- }
-
// Can't check if an input iterator sequence is sorted, because we
// can't step through the sequence.
template<typename _InputIterator>
diff --git a/libstdc++-v3/include/debug/string b/libstdc++-v3/include/debug/string
index 963b84f..9568f8b 100644
--- a/libstdc++-v3/include/debug/string
+++ b/libstdc++-v3/include/debug/string
@@ -36,8 +36,50 @@
#include <debug/safe_container.h>
#include <debug/safe_iterator.h>
+#define _GLIBCXX_DEBUG_VERIFY_STR_COND_AT(_Cond,_File,_Line,_Func) \
+ if (! (_Cond)) \
+ __gnu_debug::_Error_formatter::_S_at(_File, _Line, _Func) \
+ ._M_message(#_Cond)._M_error()
+
namespace __gnu_debug
{
+ /** Checks that __s is non-NULL or __n == 0, and then returns __s. */
+ template<typename _CharT, typename _Integer>
+ inline const _CharT*
+ __check_string(const _CharT* __s,
+ _Integer __n __attribute__((__unused__)),
+ const char* __file __attribute__((__unused__)),
+ unsigned int __line __attribute__((__unused__)),
+ const char* __function __attribute__((__unused__)))
+ {
+#ifdef _GLIBCXX_DEBUG_PEDANTIC
+ _GLIBCXX_DEBUG_VERIFY_STR_COND_AT(__s != 0 || __n == 0,
+ __file, __line, __function);
+#endif
+ return __s;
+ }
+
+ /** Checks that __s is non-NULL and then returns __s. */
+ template<typename _CharT>
+ inline const _CharT*
+ __check_string(const _CharT* __s,
+ const char* __file __attribute__((__unused__)),
+ unsigned int __line __attribute__((__unused__)),
+ const char* __function __attribute__((__unused__)))
+ {
+#ifdef _GLIBCXX_DEBUG_PEDANTIC
+ _GLIBCXX_DEBUG_VERIFY_STR_COND_AT(__s != 0,
+ __file, __line, __function);
+#endif
+ return __s;
+ }
+
+#define __glibcxx_check_string_n_constructor(_Str, _Size) \
+ __check_string(_Str, _Size, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
+#define __glibcxx_check_string_constructor(_Str) \
+ __check_string(_Str, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
/// Class std::basic_string with safety/checking/debug instrumentation.
template<typename _CharT, typename _Traits = std::char_traits<_CharT>,
typename _Allocator = std::allocator<_CharT> >
@@ -127,10 +169,10 @@ template<typename _CharT, typename _Traits = std::char_traits<_CharT>,
basic_string(const _CharT* __s, size_type __n,
const _Allocator& __a = _Allocator())
- : _Base(__gnu_debug::__check_string(__s, __n), __n, __a) { }
+ : _Base(__glibcxx_check_string_n_constructor(__s, __n), __n, __a) { }
basic_string(const _CharT* __s, const _Allocator& __a = _Allocator())
- : _Base(__gnu_debug::__check_string(__s), __a)
+ : _Base(__glibcxx_check_string_constructor(__s), __a)
{ this->assign(__s); }
basic_string(size_type __n, _CharT __c,
@@ -565,7 +607,8 @@ template<typename _CharT, typename _Traits = std::char_traits<_CharT>,
template<typename _InputIterator>
iterator
- insert(const_iterator __p, _InputIterator __first, _InputIterator __last)
+ insert(const_iterator __p,
+ _InputIterator __first, _InputIterator __last)
{
typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
__glibcxx_check_insert_range(__p, __first, __last, __dist);
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/debug/1_neg.cc b/libstdc++-v3/testsuite/21_strings/basic_string/debug/1_neg.cc
new file mode 100644
index 0000000..5d035d0
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/debug/1_neg.cc
@@ -0,0 +1,34 @@
+// Copyright (C) 2010-2018 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 { xfail *-*-* } }
+
+#define _GLIBCXX_DEBUG_PEDANTIC
+
+#include <debug/string>
+
+void test01()
+{
+ const char* __null_str = 0;
+ __gnu_debug::string str(__null_str, 1);
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/debug/2_neg.cc b/libstdc++-v3/testsuite/21_strings/basic_string/debug/2_neg.cc
new file mode 100644
index 0000000..29caa3d
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/debug/2_neg.cc
@@ -0,0 +1,34 @@
+// Copyright (C) 2010-2018 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 { xfail *-*-* } }
+
+#define _GLIBCXX_DEBUG_PEDANTIC
+
+#include <debug/string>
+
+void test01()
+{
+ const char* __null_str = 0;
+ __gnu_debug::string str(__null_str);
+}
+
+int main()
+{
+ test01();
+ return 0;
+}