PR tree-optimization/83239 - False positive from -Wstringop-overflow
authorMartin Sebor <msebor@redhat.com>
Sat, 16 Dec 2017 22:37:22 +0000 (22:37 +0000)
committerMartin Sebor <msebor@gcc.gnu.org>
Sat, 16 Dec 2017 22:37:22 +0000 (15:37 -0700)
PR tree-optimization/83239 - False positive from -Wstringop-overflow
on simple std::vector code

libstdc++/CHangeLog:
* include/bits/vector.tcc (vector::_M_default_append): Assert
        invariant to generate better code.

gcc/testsuite/ChangeLog:
* g++.dg/pr83239.C: New test case.

From-SVN: r255753

gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/pr83239.C [new file with mode: 0644]
libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/vector.tcc

index 49c26ac0484a9d89dcc7969241e083066455cc6e..f16a1872230ec819c769475b2bd006ef0785ac33 100644 (file)
@@ -1,3 +1,8 @@
+2017-12-16  Martin Sebor  <msebor@redhat.com>
+
+       PR tree-optimization/83239
+       * g++.dg/pr83239.C: New test case.
+
 2017-12-16  Sebastian Peryt  <sebastian.peryt@intel.com>
 
        PR testsuite/82767
diff --git a/gcc/testsuite/g++.dg/pr83239.C b/gcc/testsuite/g++.dg/pr83239.C
new file mode 100644 (file)
index 0000000..b0f31be
--- /dev/null
@@ -0,0 +1,56 @@
+// PR tree-optimization/83239 - False positive from -Wstringop-overflow
+// on simple std::vector code
+// { dg-do compile }
+// { dg-options "-O3 -Wall -fdump-tree-optimized"  }
+
+#include <vector>
+
+// Verify no warnings are issued.
+
+template <class T>
+void test_loop ()
+{
+  std::vector<T> a;
+
+  int num = 2;
+
+  while (num > 0)
+    {
+      const typename std::vector<T>::size_type sz = a.size ();
+
+      if (sz < 3)
+       a.assign (1, 0);
+      else
+       a.resize (sz - 2);
+
+      --num;
+    }
+}
+
+// Verify no warnings are issued here either.
+
+template <class T>
+void test_if (std::vector<T> &a, int num)
+{
+  if (num > 0)
+    {
+      const typename std::vector<T>::size_type sz = a.size ();
+
+      if (sz < 3)
+       a.assign (1, 0);
+      else
+       a.resize (sz - 2);
+    }
+}
+
+// Instantiate each function on a different type to force both
+// to be fully inlined.  Instantiating both on the same type
+// causes the inlining heuristics to outline _M_default_append
+// which, in turn, masks the warning.
+template void test_loop<int>();
+template void test_if<long>(std::vector<long>&, int);
+
+// Verify that std::vector<T>::_M_default_append() has been inlined
+// (the absence of warnings depends on it).
+// { dg-final { scan-tree-dump-not "_ZNSt6vectorIiSaIiEE17_M_default_appendEm"  optimized } }
+// { dg-final { scan-tree-dump-not "_ZNSt6vectorIPvSaIS0_EE17_M_default_appendEm" optimized } }
index 1b4c6e281e671c6be8184bdf0010f42de3c75e47..1275ea5e85f7e33e7266472eecd51000dd10a300 100644 (file)
@@ -1,3 +1,9 @@
+2017-12-16  Martin Sebor  <msebor@redhat.com>
+
+       PR tree-optimization/83239
+       * include/bits/vector.tcc (vector::_M_default_append): Assert
+        invariant to generate better code.
+
 2017-12-14  Jonathan Wakely  <jwakely@redhat.com>
 
        PR libstdc++/83279
index eadce3c75da8959c558d9a757e0c12d380e8caac..595a7f3273507b3288e70e4a104e0b8daf7884e3 100644 (file)
@@ -582,8 +582,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     {
       if (__n != 0)
        {
-         if (size_type(this->_M_impl._M_end_of_storage
-                       - this->_M_impl._M_finish) >= __n)
+         size_type __size = size();
+         size_type __navail = size_type(this->_M_impl._M_end_of_storage
+                                        - this->_M_impl._M_finish);
+
+         if (__size > max_size() || __navail > max_size() - __size)
+           __builtin_unreachable();
+
+         if (__navail >= __n)
            {
              _GLIBCXX_ASAN_ANNOTATE_GROW(__n);
              this->_M_impl._M_finish =
@@ -595,7 +601,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
            {
              const size_type __len =
                _M_check_len(__n, "vector::_M_default_append");
-             const size_type __old_size = this->size();
+             const size_type __old_size = __size;
              pointer __new_start(this->_M_allocate(__len));
              pointer __new_finish(__new_start);
              __try