aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMartin Liska <mliska@suse.cz>2014-10-29 16:17:42 +0100
committerMartin Liska <marxin@gcc.gnu.org>2014-10-29 15:17:42 +0000
commit5cf18d250f37b6c86b26d17e0cbb22a0c0d18e03 (patch)
tree987eee494277d54edfb3a37f24a7b598c944ae9e /gcc
parent7b310e901c5b7ad8ad54771b2d69459a496da472 (diff)
downloadgcc-5cf18d250f37b6c86b26d17e0cbb22a0c0d18e03.zip
gcc-5cf18d250f37b6c86b26d17e0cbb22a0c0d18e03.tar.gz
gcc-5cf18d250f37b6c86b26d17e0cbb22a0c0d18e03.tar.bz2
re PR ipa/63587 (ICE : tree check: expected var_decl, have result_decl in add_local_variables, at tree-inline.c:4112)
PR ipa/63587 * g++.dg/ipa/pr63587-1.C: New test * g++.dg/ipa/pr63587-2.C: New test. * 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. From-SVN: r216841
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/cgraphunit.c4
-rw-r--r--gcc/function.c9
-rw-r--r--gcc/function.h6
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/ipa/pr63587-1.C92
-rw-r--r--gcc/testsuite/g++.dg/ipa/pr63587-2.C250
7 files changed, 370 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index da38498..59e562c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2014-10-29 Martin Liska <mliska@suse.cz>
+
+ PR ipa/63587
+ * 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.
+
2014-10-29 Dominik Vogt <vogt@linux.vnet.ibm.com>
* godump.c (go_format_type): Represent "float _Complex" and
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 85cf103..1ef43c4 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 4dfc5bc..08ab761 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/ChangeLog b/gcc/testsuite/ChangeLog
index 45114fa0..2e4073f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2014-10-29 Martin Liska <mliska@suse.cz>
+
+ PR ipa/63587
+ * g++.dg/ipa/pr63587-1.C: New test.
+ * g++.dg/ipa/pr63587-2.C: New test.
+
2014-10-29 Dominik Vogt <vogt@linux.vnet.ibm.com>
* gcc.misc-tests/godump-1.c: Add tests for complex types.
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);
+}