Fix ICE on invalid calls_comdat_local flag [pr94582]
authorJan Hubicka <jh@suse.cz>
Mon, 20 Apr 2020 13:25:50 +0000 (15:25 +0200)
committerJan Hubicka <jh@suse.cz>
Mon, 20 Apr 2020 13:25:50 +0000 (15:25 +0200)
PR ipa/94582
* tree-inline.c (optimize_inline_calls): Recompute calls_comdat_local
flag.

* g++.dg/torture/pr94582.C: New test.

gcc/ChangeLog
gcc/ipa-comdats.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/torture/pr94582.C [new file with mode: 0644]
gcc/tree-inline.c

index 405037efbedc60dfa5dbbd322808f3140d49222b..cc6c6389b9020b2be4a836d41c526c2ddaf8736b 100644 (file)
@@ -1,3 +1,9 @@
+2020-04-20  Jan Hubicka  <hubicka@ucw.cz>
+
+       PR ipa/94582
+       * tree-inline.c (optimize_inline_calls): Recompute calls_comdat_local
+       flag.
+
 2020-04-20  Martin Liska  <mliska@suse.cz>
 
        * symtab.c (symtab_node::dump_references): Add space after
index ced25723bf8eb27dd56ca65e7604f5dac8151066..feea458ca3f58d090efafac6e017a2f3cfb43572 100644 (file)
@@ -376,6 +376,15 @@ ipa_comdats (void)
                   true);
        }
     }
+
+#if 0
+  /* Recompute calls comdat local flag.  This need to be done after all changes
+     are made.  */
+  cgraph_node *function;
+  FOR_EACH_DEFINED_FUNCTION (function)
+    if (function->get_comdat_group ())
+      function->calls_comdat_local = function->check_calls_comdat_local_p ();
+#endif
   return 0;
 }
 
index 473295dbef397e43d0796ca20e02f736e96ecd95..9ba21a0b7f83ae546c2a007996bbce8cedb6a78d 100644 (file)
@@ -1,3 +1,9 @@
+2020-04-20  Jan Hubicka  <hubicka@ucw.cz>
+
+       PR ipa/94582
+       PR ipa/94582
+       * g++.dg/torture/pr94582.C: New test.
+
 2020-04-20  Harald Anlauf  <anlauf@gmx.de>
 
        PR fortran/93364
diff --git a/gcc/testsuite/g++.dg/torture/pr94582.C b/gcc/testsuite/g++.dg/torture/pr94582.C
new file mode 100644 (file)
index 0000000..b06285a
--- /dev/null
@@ -0,0 +1,87 @@
+// { dg-do compile }
+// { dg-additional-options "-fnon-call-exceptions -fno-inline-functions-called-once -fno-tree-sra --param early-inlining-insns=1" }
+template <typename, typename> struct __replace_first_arg;
+template <template <typename> class _Template, typename _Up, typename _Tp,
+          typename... _Types>
+struct __replace_first_arg<_Template<_Tp, _Types...>, _Up> {
+  using type = _Template<_Up>;
+};
+template <class> class min_pointer;
+struct pointer_traits {
+  template <typename _Up>
+  using rebind = typename __replace_first_arg<min_pointer<int>, _Up>::type;
+};
+template <typename, typename _Tp>
+using __ptr_rebind = pointer_traits::rebind<_Tp>;
+template <typename _Alloc> struct allocator_traits {
+  template <typename _Tp>
+  static auto construct(_Alloc, _Tp) noexcept -> decltype(0);
+};
+template <typename _ForwardIterator, typename _Allocator>
+void _Destroy(_ForwardIterator __last, _Allocator) {
+  _ForwardIterator __first;
+  for (; __first != __last;)
+    ;
+}
+template <typename _ForwardIterator, typename _Allocator>
+void __uninitialized_default_a(_ForwardIterator __last, _Allocator __alloc) {
+  _ForwardIterator __first;
+  try {
+    for (; __first != __last;)
+      allocator_traits<_Allocator>::construct(__alloc, 0);
+  } catch (...) {
+    _Destroy(__first, __alloc);
+  }
+}
+template <typename _Ptr> struct _Deque_iterator {
+  typedef __ptr_rebind<_Ptr, __ptr_rebind<_Ptr, int>> _Map_pointer;
+};
+template <typename _Alloc> class _Deque_base {
+protected:
+  typedef _Alloc _Tp_alloc_type;
+  typedef _Deque_iterator<typename _Tp_alloc_type ::pointer> iterator;
+  _Deque_base(_Alloc, long);
+  typedef typename iterator::_Map_pointer _Map_pointer;
+  _Tp_alloc_type _M_get_Tp_allocator();
+};
+template <typename _Alloc> class deque : _Deque_base<_Alloc> {
+  typedef _Deque_base<_Alloc> _Base;
+  typedef typename _Base::_Map_pointer _Map_pointer;
+  typedef typename _Base::iterator iterator;
+  using _Base::_M_get_Tp_allocator;
+
+public:
+  deque(int, _Alloc __a) : _Base(__a, 0) {
+    _Map_pointer __cur;
+    try {
+      __uninitialized_default_a(__cur, _M_get_Tp_allocator());
+    } catch (...) {
+    }
+    _M_destroy_data(begin(), end(), 0);
+  }
+  iterator begin();
+  iterator end();
+  template <typename _Alloc1>
+  void _M_destroy_data(iterator, iterator, _Alloc1) {
+    for (_Map_pointer __node;;)
+      _Destroy(__node, _M_get_Tp_allocator());
+  }
+};
+template <class T> class min_pointer {
+  T ptr_;
+  friend bool operator==(min_pointer x, min_pointer y) {
+    return x.ptr_ == y.ptr_;
+  }
+  friend bool operator!=(min_pointer x, min_pointer y) { return x == y; }
+};
+template <class> class min_allocator {
+public:
+  typedef int pointer;
+};
+int foo() {
+  int n;
+  min_allocator<int> alloc;
+  deque<min_allocator<int>>(n, alloc);
+  return 1;
+}
+
index 26c23f504be9c2d6cdf474d42d2ee1d1cf116dbb..69ca8e99109ed9bae74f8099789049a251abe9b9 100644 (file)
@@ -5469,6 +5469,7 @@ optimize_inline_calls (tree fn)
   number_blocks (fn);
 
   delete_unreachable_blocks_update_callgraph (id.dst_node, false);
+  id.dst_node->calls_comdat_local = id.dst_node->check_calls_comdat_local_p ();
 
   if (flag_checking)
     id.dst_node->verify ();