re PR ipa/60659 (ICE in get_polymorphic_call_info, at ipa-devirt.c:1292)

PR ipa/60659
	* ipa-devirt.c (get_polymorphic_call_info): Do not ICE on type inconsistent
	code and instead mark the context inconsistent.
	(possible_polymorphic_call_targets): For inconsistent contexts
	return empty complete list.
	* testsuite/g++.dg/torture/pr60659.C: New testcase.

From-SVN: r209048
This commit is contained in:
Jan Hubicka 2014-04-03 05:55:59 +02:00 committed by Jan Hubicka
parent 2b9912aa3c
commit 3e86c6a8e1
4 changed files with 105 additions and 5 deletions

View File

@ -1,3 +1,11 @@
2014-04-02 Jan Hubicka <hubicka@ucw.cz>
PR ipa/60659
* ipa-devirt.c (get_polymorphic_call_info): Do not ICE on type inconsistent
code and instead mark the context inconsistent.
(possible_polymorphic_call_targets): For inconsistent contexts
return empty complete list.
2014-04-02 Anthony Green <green@moxielogic.com>
* config/moxie/moxie.md (zero_extendqisi2, zero_extendhisi2)

View File

@ -1214,7 +1214,13 @@ get_polymorphic_call_info (tree fndecl,
not part of outer type. */
if (!contains_type_p (TREE_TYPE (base),
context->offset + offset2, *otr_type))
return base_pointer;
{
/* Use OTR_TOKEN = INT_MAX as a marker of probably type inconsistent
code sequences; we arrange the calls to be builtin_unreachable
later. */
*otr_token = INT_MAX;
return base_pointer;
}
get_polymorphic_call_info_for_decl (context, base,
context->offset + offset2);
return NULL;
@ -1288,8 +1294,10 @@ get_polymorphic_call_info (tree fndecl,
if (!contains_type_p (context->outer_type, context->offset,
*otr_type))
{
context->outer_type = NULL;
gcc_unreachable ();
/* Use OTR_TOKEN = INT_MAX as a marker of probably type inconsistent
code sequences; we arrange the calls to be builtin_unreachable
later. */
*otr_token = INT_MAX;
return base_pointer;
}
context->maybe_derived_type = false;
@ -1389,6 +1397,9 @@ devirt_variable_node_removal_hook (varpool_node *n,
temporarily change to one of base types. INCLUDE_DERIVER_TYPES make
us to walk the inheritance graph for all derivations.
OTR_TOKEN == INT_MAX is used to mark calls that are provably
undefined and should be redirected to unreachable.
If COMPLETEP is non-NULL, store true if the list is complete.
CACHE_TOKEN (if non-NULL) will get stored to an unique ID of entry
in the target cache. If user needs to visit every target list
@ -1422,6 +1433,7 @@ possible_polymorphic_call_targets (tree otr_type,
bool complete;
bool can_refer;
/* If ODR is not initialized, return empty incomplete list. */
if (!odr_hash.is_created ())
{
if (completep)
@ -1431,11 +1443,28 @@ possible_polymorphic_call_targets (tree otr_type,
return nodes;
}
/* If we hit type inconsistency, just return empty list of targets. */
if (otr_token == INT_MAX)
{
if (completep)
*completep = true;
if (nonconstruction_targetsp)
*nonconstruction_targetsp = 0;
return nodes;
}
type = get_odr_type (otr_type, true);
/* Lookup the outer class type we want to walk. */
if (context.outer_type)
get_class_context (&context, otr_type);
if (context.outer_type
&& !get_class_context (&context, otr_type))
{
if (completep)
*completep = false;
if (nonconstruction_targetsp)
*nonconstruction_targetsp = 0;
return nodes;
}
/* We canonicalize our query, so we do not need extra hashtable entries. */

View File

@ -1,3 +1,8 @@
2014-04-02 Jan Hubicka <hubicka@ucw.cz>
PR ipa/60659
* testsuite/g++.dg/torture/pr60659.C: New testcase.
2014-04-02 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
PR tree-optimization/60733

View File

@ -0,0 +1,58 @@
// { dg-do compile }
template <typename _InputIterator> void __distance (_InputIterator);
template <typename _InputIterator>
void distance (_InputIterator, _InputIterator p2)
{
__distance (p2);
}
namespace boost
{
template <class Iterator> struct A
{
typedef typename Iterator::difference_type type;
};
template <class T> typename T::const_iterator end (T &);
template <class T> typename T::const_iterator begin (T &);
template <class T> struct D : A<typename T::const_iterator>
{
};
template <class T> typename D<T>::type distance (const T &p1)
{
distance (boost::begin (p1), boost::end (p1));
return 0;
}
template <class IteratorT> class B
{
public:
typedef B type;
typedef IteratorT const_iterator;
};
}
typedef int storage_t[];
struct F;
template <template <typename> class> struct G
{
G (const G &p1) { p1.m_fn1 ().m_fn1 (0); }
const F &m_fn1 () const
{
const void *a;
a = &data_m;
return *static_cast<const F *>(a);
}
storage_t *data_m;
};
struct F
{
virtual F *m_fn1 (void *) const;
};
template <typename> struct H;
struct C : G<H>
{
typedef int difference_type;
};
boost::B<C> AllTransVideos ();
int b = boost::distance (AllTransVideos ());