From de54de93fa4bf4740638e58f9aaab1e50026bacb Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Fri, 15 Jul 2016 14:49:38 -0400 Subject: [PATCH] PR c++/71092 - ICE with array and constexpr. * constexpr.c (cxx_eval_call_expression): Fail quietly when cgraph threw away DECL_SAVED_TREE. From-SVN: r238395 --- gcc/cp/ChangeLog | 4 ++ gcc/cp/constexpr.c | 14 ++++- .../g++.dg/cpp0x/constexpr-array17.C | 61 +++++++++++++++++++ 3 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-array17.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index eb96ea3f8db..0c381959310 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,9 @@ 2016-07-15 Jason Merrill + PR c++/71092 + * constexpr.c (cxx_eval_call_expression): Fail quietly when cgraph + threw away DECL_SAVED_TREE. + PR c++/71117 Core 2189 * call.c (add_template_conv_candidate): Disable if there are diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index b9834a7e734..cb8ece0773f 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -1504,9 +1504,19 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, } else { - if (!result || result == error_mark_node) + if (result && result != error_mark_node) + /* OK */; + else if (!DECL_SAVED_TREE (fun)) + { + /* When at_eof >= 2, cgraph has started throwing away + DECL_SAVED_TREE, so fail quietly. FIXME we get here because of + late code generation for VEC_INIT_EXPR, which needs to be + completely reconsidered. */ + gcc_assert (at_eof >= 2 && ctx->quiet); + *non_constant_p = true; + } + else { - gcc_assert (DECL_SAVED_TREE (fun)); tree body, parms, res; /* Reuse or create a new unshared copy of this function's body. */ diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array17.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array17.C new file mode 100644 index 00000000000..c6afa507f02 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array17.C @@ -0,0 +1,61 @@ +// PR c++/71092 +// { dg-do compile { target c++11 } } + +template struct A { using type = _Default; }; +template class> +using __detected_or = A<_Default>; +template class _Op> +using __detected_or_t = typename __detected_or<_Default, _Op>::type; +template struct B { typedef _Tp value_type; }; +struct C { + template using __pointer = typename _Tp::pointer; +}; +template struct J : C { + using pointer = __detected_or_t; +}; +template void _Construct(_T1 *) { new _T1; } +struct D { + template + static _ForwardIterator __uninit_default_n(_ForwardIterator p1, _Size) { + _Construct(p1); + } +}; +template +void __uninitialized_default_n(_ForwardIterator p1, _Size) { + D::__uninit_default_n(p1, 0); +} +template +void __uninitialized_default_n_a(_ForwardIterator p1, _Size, _Tp) { + __uninitialized_default_n(p1, 0); +} +template struct __shared_ptr { + constexpr __shared_ptr() : _M_ptr(), _M_refcount() {} + int _M_ptr; + int _M_refcount; +}; +template struct F { + typedef _Alloc _Tp_alloc_type; + struct G { + typename J<_Tp_alloc_type>::pointer _M_start; + G(_Tp_alloc_type); + }; + F(int, _Alloc p2) : _M_impl(p2) {} + G _M_impl; +}; +template > struct K : F<_Alloc> { + typedef _Alloc allocator_type; + K(int, allocator_type p2 = allocator_type()) : F<_Alloc>(0, p2) { + __uninitialized_default_n_a(this->_M_impl._M_start, 0, 0); + } +}; +struct H { + H(); + struct I { + __shared_ptr trigger[1]; + }; + __shared_ptr resetTrigger_; + K states_; + __shared_ptr triggerManager_; +}; +__shared_ptr a; +H::H() : states_(0), triggerManager_(a) {} -- 2.30.2