Make __glibcxx_assert constexpr compatible

Message ID 479285f2-79dd-0ecb-7c19-274b5be7d1f9@gmail.com
State New
Headers show
Series
  • Make __glibcxx_assert constexpr compatible
Related show

Commit Message

François Dumont Feb. 11, 2020, 6:35 a.m.
By making __glibcxx_assert constexpr compatible we can get rid of a 
FIXME in basic_string_view and so fix following XPASS in _GLIBCXX_DEBUG 
modes.

XPASS: 21_strings/basic_string_view/element_access/char/2.cc execution test
XPASS: 21_strings/basic_string_view/element_access/wchar_t/2.cc 
execution test

Should I also rename those in 2_neg.cc ?

I had to move the assert block in c++config to benefit from 
_GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED definition. The generation 
of the compilation error is not very nice but it is still better than no 
error and we can see the assertion:

/home/fdt/dev/gcc/git/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/wchar_t/constexpr_neg.cc:31:22: 
erreur: condition non constante pour l'assertion statique
    31 | static_assert(test() == 0); // { dg-error "non-constant 
condition" }
       |               ~~~~~~~^~~~
Dans le fichier inclus depuis 
/home/fdt/dev/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/limits:42,
                  depuis 
/home/fdt/dev/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/string_view:40,
                  depuis 
/home/fdt/dev/gcc/git/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/wchar_t/constexpr_neg.cc:21:
/home/fdt/dev/gcc/git/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/wchar_t/constexpr_neg.cc:31:19: 
dans l'expansion « constexpr » de « test() »
/home/fdt/dev/gcc/git/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/wchar_t/constexpr_neg.cc:28:13: 
dans l'expansion « constexpr » de 
« s.std::basic_string_view<wchar_t>::operator[](4) »
/home/fdt/dev/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/string_view:206:2: 
erreur: inline assembly is not a constant expression
   206 |  __glibcxx_assert(__pos < this->_M_len);
       |  ^~~~~~~~~~~~~~~~
/home/fdt/dev/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/string_view:206:2: 
note: only unevaluated inline assembly is allowed in a « constexpr » 
function in C++2a

             * include/bits/c++config
[_GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED](__glibcxx_assert_impl):
             New.
             * include/std/string_view 
(basic_string_view<>:operator[](size_type)):
             Restore __glibcxx_assert.
             (basic_string_view<>::front()): Likewise.
             (basic_string_view<>::back()): Likewise.
             * 
testsuite/21_strings/basic_string_view/element_access/char/back_constexpr_neg.cc:
             New.
             * 
testsuite/21_strings/basic_string_view/element_access/char/constexpr.cc:
             New.
             * 
testsuite/21_strings/basic_string_view/element_access/char/constexpr_neg.cc:
             New.
             * 
testsuite/21_strings/basic_string_view/element_access/char/front_back_constexpr.cc:
             New.
             * 
testsuite/21_strings/basic_string_view/element_access/char/front_constexpr_neg.cc:
             New.
             * 
testsuite/21_strings/basic_string_view/element_access/wchar_t/constexpr.cc:
             New.
             * 
testsuite/21_strings/basic_string_view/element_access/wchar_t/constexpr_neg.cc:
             New.

Tested under Linux x86_64 normal and debug modes.

Ok to commit ?

François

Patch

diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config
index b1fad59d4b3..4d821627447 100644
--- a/libstdc++-v3/include/bits/c++config
+++ b/libstdc++-v3/include/bits/c++config
@@ -441,37 +441,6 @@  namespace std
 # define _GLIBCXX_EXTERN_TEMPLATE -1
 #endif
 
-// Assert.
-#if defined(_GLIBCXX_ASSERTIONS) \
-  || defined(_GLIBCXX_PARALLEL) || defined(_GLIBCXX_PARALLEL_ASSERTIONS)
-namespace std
-{
-  // Avoid the use of assert, because we're trying to keep the <cassert>
-  // include out of the mix.
-  extern "C++" inline void
-  __replacement_assert(const char* __file, int __line,
-		       const char* __function, const char* __condition)
-  {
-    __builtin_printf("%s:%d: %s: Assertion '%s' failed.\n", __file, __line,
-		     __function, __condition);
-    __builtin_abort();
-  }
-}
-#define __glibcxx_assert_impl(_Condition)				 \
-  do 									 \
-  {							      		 \
-    if (! (_Condition))                                                  \
-      std::__replacement_assert(__FILE__, __LINE__, __PRETTY_FUNCTION__, \
-				#_Condition);				 \
-  } while (false)
-#endif
-
-#if defined(_GLIBCXX_ASSERTIONS)
-# define __glibcxx_assert(_Condition) __glibcxx_assert_impl(_Condition)
-#else
-# define __glibcxx_assert(_Condition)
-#endif
-
 // Macros for race detectors.
 // _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(A) and
 // _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(A) should be used to explain
@@ -663,6 +632,53 @@  namespace std
 # endif
 #endif // GCC
 
+// Assert.
+#if defined(_GLIBCXX_ASSERTIONS) \
+  || defined(_GLIBCXX_PARALLEL) || defined(_GLIBCXX_PARALLEL_ASSERTIONS)
+namespace std
+{
+  // Avoid the use of assert, because we're trying to keep the <cassert>
+  // include out of the mix.
+  extern "C++" inline void
+  __replacement_assert(const char* __file, int __line,
+		       const char* __function, const char* __condition)
+  {
+    __builtin_printf("%s:%d: %s: Assertion '%s' failed.\n", __file, __line,
+		     __function, __condition);
+    __builtin_abort();
+  }
+}
+# ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED
+#  define __glibcxx_assert_impl(_Condition)				\
+  do									\
+    {									\
+      if (__builtin_is_constant_evaluated())				\
+	{								\
+	  if (!(_Condition))						\
+	    /* FIXME Generate compilation error here. */		\
+	    asm("assertion failure");					\
+	}								\
+      else if (! (_Condition))						\
+	std::__replacement_assert(__FILE__, __LINE__, __PRETTY_FUNCTION__, \
+				  #_Condition);				\
+    } while (false)
+# else
+#  define __glibcxx_assert_impl(_Condition)				\
+  do									\
+    {									\
+      if (! (_Condition))						\
+	std::__replacement_assert(__FILE__, __LINE__, __PRETTY_FUNCTION__, \
+				  #_Condition);				\
+    } while (false)
+# endif
+#endif
+
+#if defined(_GLIBCXX_ASSERTIONS)
+# define __glibcxx_assert(_Condition) __glibcxx_assert_impl(_Condition)
+#else
+# define __glibcxx_assert(_Condition)
+#endif
+
 // PSTL configuration
 
 #if __cplusplus >= 201703L
diff --git a/libstdc++-v3/include/std/string_view b/libstdc++-v3/include/std/string_view
index 798cb89a621..84ecb56b5d2 100644
--- a/libstdc++-v3/include/std/string_view
+++ b/libstdc++-v3/include/std/string_view
@@ -203,8 +203,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       constexpr const_reference
       operator[](size_type __pos) const noexcept
       {
-	// TODO: Assert to restore in a way compatible with the constexpr.
-	// __glibcxx_assert(__pos < this->_M_len);
+	__glibcxx_assert(__pos < this->_M_len);
 	return *(this->_M_str + __pos);
       }
 
@@ -221,16 +220,14 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       constexpr const_reference
       front() const noexcept
       {
-	// TODO: Assert to restore in a way compatible with the constexpr.
-	// __glibcxx_assert(this->_M_len > 0);
+	__glibcxx_assert(this->_M_len > 0);
 	return *this->_M_str;
       }
 
       constexpr const_reference
       back() const noexcept
       {
-	// TODO: Assert to restore in a way compatible with the constexpr.
-	// __glibcxx_assert(this->_M_len > 0);
+	__glibcxx_assert(this->_M_len > 0);
 	return *(this->_M_str + this->_M_len - 1);
       }
 
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/char/back_constexpr_neg.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/char/back_constexpr_neg.cc
new file mode 100644
index 00000000000..1bf7f758c57
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/char/back_constexpr_neg.cc
@@ -0,0 +1,35 @@ 
+// Copyright (C) 2020 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-options "-std=gnu++17 -D_GLIBCXX_ASSERTIONS" }
+// { dg-do compile { target c++17 xfail *-*-* } }
+
+#include <string_view>
+
+typedef std::string_view string_view_type;
+
+constexpr char
+back()
+{
+  string_view_type s("");
+  return s.back();
+}
+
+static_assert(back() != 'a'); // { dg-error "non-constant condition" }
+
+// { dg-prune-output "in 'constexpr' expansion" }
+// { dg-prune-output "not a constant expression" }
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/char/constexpr.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/char/constexpr.cc
new file mode 100644
index 00000000000..aa2a08ebe83
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/char/constexpr.cc
@@ -0,0 +1,31 @@ 
+// Copyright (C) 2020 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-options "-std=gnu++17" }
+// { dg-do compile { target c++17 } }
+
+#include <string_view>
+
+constexpr char
+test()
+{
+  typedef std::string_view string_view_type;
+  string_view_type s("abcd");
+  return s[0];
+}
+
+static_assert(test() == 'a');
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/char/constexpr_neg.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/char/constexpr_neg.cc
new file mode 100644
index 00000000000..77ad7ba0aeb
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/char/constexpr_neg.cc
@@ -0,0 +1,34 @@ 
+// Copyright (C) 2020 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-options "-std=gnu++17 -D_GLIBCXX_ASSERTIONS" }
+// { dg-do compile { target c++17 xfail *-*-* } }
+
+#include <string_view>
+
+constexpr char
+test()
+{
+  typedef std::string_view string_view_type;
+  string_view_type s("abcd");
+  return s[s.length()];
+}
+
+static_assert(test() == 0); // { dg-error "non-constant condition" }
+
+// { dg-prune-output "in 'constexpr' expansion" }
+// { dg-prune-output "not a constant expression" }
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/char/front_back_constexpr.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/char/front_back_constexpr.cc
new file mode 100644
index 00000000000..7ead45ddcf6
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/char/front_back_constexpr.cc
@@ -0,0 +1,41 @@ 
+// Copyright (C) 2020 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-options "-std=gnu++17" }
+// { dg-do compile { target c++17 } }
+
+#include <string_view>
+
+typedef std::string_view string_view_type;
+
+constexpr char
+front()
+{
+  string_view_type s("abcd");
+  return s.front();
+}
+
+static_assert(front() == 'a');
+
+constexpr char
+back()
+{
+  string_view_type s("abcd");
+  return s.back();
+}
+
+static_assert(back() == 'd');
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/char/front_constexpr_neg.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/char/front_constexpr_neg.cc
new file mode 100644
index 00000000000..19800739814
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/char/front_constexpr_neg.cc
@@ -0,0 +1,35 @@ 
+// Copyright (C) 2020 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-options "-std=gnu++17 -D_GLIBCXX_ASSERTIONS" }
+// { dg-do compile { target c++17 xfail *-*-* } }
+
+#include <string_view>
+
+typedef std::string_view string_view_type;
+
+constexpr char
+front()
+{
+  string_view_type s("");
+  return s.front();
+}
+
+static_assert(front() != 'a'); // { dg-error "non-constant condition" }
+
+// { dg-prune-output "in 'constexpr' expansion" }
+// { dg-prune-output "not a constant expression" }
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/wchar_t/constexpr.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/wchar_t/constexpr.cc
new file mode 100644
index 00000000000..f4171628e9f
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/wchar_t/constexpr.cc
@@ -0,0 +1,31 @@ 
+// Copyright (C) 2020 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-options "-std=gnu++17" }
+// { dg-do compile { target c++17 } }
+
+#include <string_view>
+
+constexpr wchar_t
+test()
+{
+  typedef std::wstring_view string_view_type;
+  string_view_type s(L"abcd");
+  return s[0];
+}
+
+static_assert(test() == L'a');
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/wchar_t/constexpr_neg.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/wchar_t/constexpr_neg.cc
new file mode 100644
index 00000000000..2b1bc68d11c
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/wchar_t/constexpr_neg.cc
@@ -0,0 +1,34 @@ 
+// Copyright (C) 2020 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-options "-std=gnu++17 -D_GLIBCXX_ASSERTIONS" }
+// { dg-do compile { target c++17 xfail *-*-* } }
+
+#include <string_view>
+
+constexpr wchar_t
+test()
+{
+  typedef std::wstring_view string_view_type;
+  string_view_type s(L"abcd");
+  return s[4];
+}
+
+static_assert(test() == 0); // { dg-error "non-constant condition" }
+
+// { dg-prune-output "in 'constexpr' expansion" }
+// { dg-prune-output "not a constant expression" }