Hello. Following patch fixes PR63587, where we put DECL_RESULT in cgraph_node::expand_thunk to local_decls. Patch has been tested on x86_64-linux-pc without any regression and boostrap works correctly.
Ready for thunk? Thanks, Martin
gcc/testsuite/ChangeLog: 2014-10-29 Martin Liska <mli...@suse.cz> * g++.dg/ipa/pr63587-1.C: New test. * g++.dg/ipa/pr63587-2.C: New test. gcc/ChangeLog: 2014-10-29 Martin Liska <mli...@suse.cz> * cgraphunit.c (cgraph_node::expand_thunk): Only VAR_DECLs are put to local declarations. * function.c (add_local_decl): Implementation moved from header file, assert introduced for tree type. * function.h: Likewise.
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index a86bd1b..6f61f5c 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -1550,7 +1550,9 @@ cgraph_node::expand_thunk (bool output_asm_thunks, bool force_gimple_thunk) else if (!is_gimple_reg_type (restype)) { restmp = resdecl; - add_local_decl (cfun, restmp); + + if (TREE_CODE (restmp) == VAR_DECL) + add_local_decl (cfun, restmp); BLOCK_VARS (DECL_INITIAL (current_function_decl)) = restmp; } else diff --git a/gcc/function.c b/gcc/function.c index ee229ad..893ca6f 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -6441,6 +6441,15 @@ match_asm_constraints_1 (rtx_insn *insn, rtx *p_sets, int noutputs) df_insn_rescan (insn); } +/* Add the decl D to the local_decls list of FUN. */ + +void +add_local_decl (struct function *fun, tree d) +{ + gcc_assert (TREE_CODE (d) == VAR_DECL); + vec_safe_push (fun->local_decls, d); +} + namespace { const pass_data pass_data_match_asm_constraints = diff --git a/gcc/function.h b/gcc/function.h index 66384e5..aa47018 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -668,11 +668,7 @@ struct GTY(()) function { /* Add the decl D to the local_decls list of FUN. */ -static inline void -add_local_decl (struct function *fun, tree d) -{ - vec_safe_push (fun->local_decls, d); -} +void add_local_decl (struct function *fun, tree d); #define FOR_EACH_LOCAL_DECL(FUN, I, D) \ FOR_EACH_VEC_SAFE_ELT_REVERSE ((FUN)->local_decls, I, D) diff --git a/gcc/testsuite/g++.dg/ipa/pr63587-1.C b/gcc/testsuite/g++.dg/ipa/pr63587-1.C new file mode 100644 index 0000000..cbf872e --- /dev/null +++ b/gcc/testsuite/g++.dg/ipa/pr63587-1.C @@ -0,0 +1,92 @@ +// PR ipa/63587 +// { dg-do compile { target c++11 } } +// { dg-options "-O2 -fno-strict-aliasing" } + +template <class> struct A +{ +}; +template <typename> struct B +{ + template <typename> struct C; +}; +class D; +template <typename> class F; +struct G +{ + void operator()(const D &, D); +}; +class D +{ +public: + D (int); +}; +struct H +{ + H (int); +}; +template <typename _Key, typename, typename, typename _Compare, typename> +class I +{ + typedef _Key key_type; + template <typename _Key_compare> struct J + { + _Key_compare _M_key_compare; + }; + J<_Compare> _M_impl; + +public: + A<int> _M_get_insert_unique_pos (const key_type &); + A<int> _M_get_insert_hint_unique_pos (H &); + template <typename... _Args> int _M_emplace_hint_unique (H, _Args &&...); +}; +template <typename _Key, typename _Tp, typename _Compare = G, + typename _Alloc = F<A<_Tp> > > +class K +{ + typedef _Key key_type; + typedef _Key value_type; + typedef typename B<_Alloc>::template C<value_type> _Pair_alloc_type; + I<key_type, value_type, int, _Compare, _Pair_alloc_type> _M_t; + +public: + void operator[](key_type) + { + _M_t._M_emplace_hint_unique (0); + } +}; +template <typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc> +A<int> +I<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_get_insert_unique_pos ( + const key_type &p1) +{ + _M_impl._M_key_compare (p1, 0); +} +template <typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc> +A<int> +I<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_get_insert_hint_unique_pos ( + H &) +{ + _M_get_insert_unique_pos (0); +} +template <typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc> +template <typename... _Args> +int +I<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_emplace_hint_unique ( + H p1, _Args &&...) +{ + _M_get_insert_hint_unique_pos (p1); +} +namespace { +struct L; +} +void +fn1 () +{ + K<D, L> a; + a[0]; + K<D, int> b; + b[0]; +} diff --git a/gcc/testsuite/g++.dg/ipa/pr63587-2.C b/gcc/testsuite/g++.dg/ipa/pr63587-2.C new file mode 100644 index 0000000..f31c5bd --- /dev/null +++ b/gcc/testsuite/g++.dg/ipa/pr63587-2.C @@ -0,0 +1,250 @@ +// PR ipa/63587 +// { dg-do compile { target c++11 } } +// { dg-options "-O2" } + +namespace boost { +class basic_cstring +{ +public: + basic_cstring (char *); +}; +template <typename> struct identity +{ +}; +struct make_identity; +struct function_buffer +{ +}; +template <typename FunctionObj> struct function_obj_invoker0 +{ + static int + invoke (function_buffer &) + { + FunctionObj f; + f (); + } +}; +template <typename FunctionObj> struct get_function_obj_invoker0 +{ + typedef function_obj_invoker0<FunctionObj> type; +}; +template <typename FunctionObj> struct apply +{ + typedef typename get_function_obj_invoker0<FunctionObj>::type invoker_type; +}; +struct basic_vtable0 +{ + typedef int (*invoker_type)(function_buffer &); + template <typename F> void assign_to (F, function_buffer); + invoker_type invoker; +}; +class function0 +{ +public: + template <typename Functor> function0 (Functor) + { + typedef typename apply<Functor>::invoker_type invoker_type; + basic_vtable0 stored_vtable { invoker_type::invoke }; + stored_vtable.assign_to (0, functor); + } + function_buffer functor; +}; +class function : function0 +{ +public: + template <typename Functor> function (Functor f) : function0 (f) {} +}; +class test_unit_generator +{ +}; +class test_case +{ +public: + test_case (basic_cstring, basic_cstring, int, function); +}; +struct auto_test_unit_registrar +{ + auto_test_unit_registrar (test_unit_generator); +}; +template <typename F> F unwrap (F, int); +struct for_each_impl +{ + template <typename Iterator, typename LastIterator, typename TransformFunc, + typename F> + static void + execute (Iterator, LastIterator, TransformFunc, F f) + { + identity<char> __trans_tmp_1; + unwrap (f, 0)(__trans_tmp_1); + } +}; +template <typename, typename, typename F> +void +for_each (F f) +{ + for_each_impl::execute (0, 0, 0, f); +} +template <typename TestCaseTemplate> class test_case_template_invoker +{ +public: + void operator()() + { + TestCaseTemplate::run (0); + } +}; +template <typename Generator, typename TestCaseTemplate> +struct generate_test_case_4_type +{ + generate_test_case_4_type (basic_cstring, basic_cstring, int, Generator G) + : m_test_case_name (0), m_test_case_file (0), m_holder (G) + { + } + template <typename TestType> void operator()(identity<TestType>) + { + test_case (0, 0, 0, test_case_template_invoker<TestCaseTemplate> ()); + } + basic_cstring m_test_case_name; + basic_cstring m_test_case_file; + Generator m_holder; +}; +template <typename TestCaseTemplate> +class template_test_case_gen : public test_unit_generator +{ +public: + template_test_case_gen (basic_cstring, basic_cstring, int) + { + for_each<int, make_identity> ( + generate_test_case_4_type<template_test_case_gen, TestCaseTemplate> ( + 0, 0, 0, *this)); + } +}; +class attribute_name +{ + int m_id; + +public: + attribute_name (char); +}; +template <typename> struct term; +namespace exprns_ { +template <typename> struct expr; +} +using exprns_::expr; +template <typename T> struct Trans_NS_proto_terminal +{ + typedef expr<term<T> > type; +}; +namespace exprns_ { +template <typename Arg0> struct expr<term<Arg0> > +{ + Arg0 child0; +}; +} +template <typename Expr> struct actor +{ + typename Trans_NS_proto_terminal<Expr>::type proto_expr_; +}; +template <template <typename> class Actor = actor> struct terminal +{ + typedef Actor<int> type; +}; +namespace log { +struct to_log_fun +{ +}; +class value_extractor; +template <typename, typename = value_extractor, typename = void, + template <typename> class = actor> +class attribute_actor; +class attribute_terminal +{ +public: + attribute_name m_name; + attribute_name + get_name () + { + return m_name; + } +}; +template <typename, typename, typename, template <typename> class ActorT> +class attribute_actor : ActorT<attribute_terminal> +{ +public: + typedef int value_type; + attribute_name + get_name () + { + return this->proto_expr_.child0.get_name (); + } +}; +template <typename AttributeValueT> +attribute_actor<AttributeValueT> attr (attribute_name); +terminal<>::type stream; +template <typename LeftT, typename ImplT> class attribute_output_terminal +{ +public: + template <typename U> + attribute_output_terminal (LeftT, attribute_name, ImplT, U); +}; +template <typename LeftT> struct make_output_expression +{ + typedef attribute_output_terminal<LeftT, to_log_fun> type; + template <typename RightT> + static type + make (LeftT left, RightT &right) + { + type (left, right.get_name (), to_log_fun (), 0); + } +}; +template <typename, typename RightT, typename = typename RightT::value_type> +struct make_output_actor; +template <template <typename> class ActorT, typename LeftExprT, + typename RightT, typename ValueT> +struct make_output_actor<ActorT<LeftExprT>, RightT, ValueT> +{ + typedef make_output_expression<ActorT<LeftExprT> > make_expression; + typedef ActorT<typename make_expression::type> type; + static type + make (ActorT<LeftExprT> left, RightT &right) + { + type { make_expression::make (left, right) }; + } +}; +template <typename LeftExprT, typename T, typename FallbackPolicyT, + typename TagT> +typename make_output_actor<actor<LeftExprT>, attribute_actor<TagT> >::type +operator<<(actor<LeftExprT> left, + attribute_actor<T, FallbackPolicyT, TagT> right) +{ + make_output_actor<actor<LeftExprT>, attribute_actor<T> >::make (left, right); +} +} +} +namespace logging = boost::log; +namespace expr = logging; +namespace { +class my_class; +} +template <typename> struct default_formatting +{ + void test_method (); +}; +struct default_formatting_invoker +{ + static void + run (void *) + { + default_formatting<int> t; + t.test_method (); + } +}; +boost::auto_test_unit_registrar default_formatting_registrar56 ( + boost::template_test_case_gen<default_formatting_invoker> (0, 0, 0)); +template <typename CharT> +void +default_formatting<CharT>::test_method () +{ + expr::stream << expr::attr<my_class> (0); + expr::stream << expr::attr<int> (0) << expr::attr<int> (0) + << expr::attr<int> (0); +}