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
This commit is contained in:
Martin Liska 2014-10-29 16:17:42 +01:00 committed by Martin Liska
parent 7b310e901c
commit 5cf18d250f
7 changed files with 370 additions and 6 deletions

View File

@ -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

View File

@ -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

View File

@ -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 =

View File

@ -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)

View File

@ -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.

View File

@ -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];
}

View File

@ -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);
}