re PR ipa/60659 (ICE in get_polymorphic_call_info, at ipa-devirt.c:1292)
authorJan Hubicka <hubicka@ucw.cz>
Thu, 3 Apr 2014 03:55:59 +0000 (05:55 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Thu, 3 Apr 2014 03:55:59 +0000 (03:55 +0000)
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

gcc/ChangeLog
gcc/ipa-devirt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/torture/pr60659.C [new file with mode: 0644]

index ec100b2..a566a0f 100644 (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)
index 6fb1449..c84a26d 100644 (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.  */
 
index cc26f21..1ffa4b9 100644 (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
diff --git a/gcc/testsuite/g++.dg/torture/pr60659.C b/gcc/testsuite/g++.dg/torture/pr60659.C
new file mode 100644 (file)
index 0000000..f0158a5
--- /dev/null
@@ -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 ());
+