aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJan Hubicka <hubicka@ucw.cz>2014-04-03 05:55:59 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2014-04-03 03:55:59 +0000
commit3e86c6a8e13389b0e5329154dfb7286be5fbfaf1 (patch)
tree73709b7b3d27ebdc259dd16d0f15be921c3302dc /gcc
parent2b9912aa3c48b911e6382355b6756e45002a604e (diff)
downloadgcc-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/ChangeLog8
-rw-r--r--gcc/ipa-devirt.c39
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/torture/pr60659.C58
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 ());
+