diff options
author | Jan Hubicka <hubicka@ucw.cz> | 2014-04-03 05:55:59 +0200 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2014-04-03 03:55:59 +0000 |
commit | 3e86c6a8e13389b0e5329154dfb7286be5fbfaf1 (patch) | |
tree | 73709b7b3d27ebdc259dd16d0f15be921c3302dc /gcc | |
parent | 2b9912aa3c48b911e6382355b6756e45002a604e (diff) | |
download | gcc-3e86c6a8e13389b0e5329154dfb7286be5fbfaf1.zip gcc-3e86c6a8e13389b0e5329154dfb7286be5fbfaf1.tar.gz gcc-3e86c6a8e13389b0e5329154dfb7286be5fbfaf1.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/ipa-devirt.c | 39 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/torture/pr60659.C | 58 |
4 files changed, 105 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ec100b2..a566a0f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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) diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c index 6fb1449..c84a26d 100644 --- a/gcc/ipa-devirt.c +++ b/gcc/ipa-devirt.c @@ -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. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index cc26f21..1ffa4b9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 diff --git a/gcc/testsuite/g++.dg/torture/pr60659.C b/gcc/testsuite/g++.dg/torture/pr60659.C new file mode 100644 index 0000000..f0158a5 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr60659.C @@ -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 ()); + |