Enhance __gnu_debug::string debug assertion

Message ID e2e0be91-3588-8425-56bd-e13f81f824c2@gmail.com
State New
Headers show
Series
  • Enhance __gnu_debug::string debug assertion
Related show

Commit Message

François Dumont July 5, 2018, 5:28 a.m.
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

Comments

Jonathan Wakely July 5, 2018, 10:15 a.m. | #1
On 05/07/18 07:28 +0200, François Dumont wrote:
>    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.


Looks good - thanks.

Patch

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;
+}