[Bug ipa/66223] [5/6 Regression] Diagnostic of pure virtual function call broken, including __cxa_pure_virtual

hubicka at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Tue Jan 19 13:09:00 GMT 2016


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66223

--- Comment #8 from Jan Hubicka <hubicka at gcc dot gnu.org> ---
Well, if you rely on undefined behaviour, you should not be surprised when your
program breaks with optimization.  I am testing the following patch:
Index: ipa-devirt.c
===================================================================
--- ipa-devirt.c        (revision 232555)
+++ ipa-devirt.c        (working copy)
@@ -2326,6 +2326,14 @@ referenced_from_vtable_p (struct cgraph_
       }
   return found;
 }
+static bool
+is_cxa_pure_virtual_p (tree target)
+{
+  return target && TREE_CODE (TREE_TYPE (target)) != METHOD_TYPE
+        && DECL_NAME (target)
+        && !strcmp (IDENTIFIER_POINTER (DECL_NAME (target)),
+                    "__cxa_pure_virtual");
+}

 /* If TARGET has associated node, record it in the NODES array.
    CAN_REFER specify if program can refer to the target directly.
@@ -2341,11 +2349,12 @@ maybe_record_node (vec <cgraph_node *> &
 {
   struct cgraph_node *target_node, *alias_target;
   enum availability avail;
+  bool pure_virtual = is_cxa_pure_virtual_p (target);

-  /* cxa_pure_virtual and __builtin_unreachable do not need to be added into
+  /* __builtin_unreachable do not need to be added into
      list of targets; the runtime effect of calling them is undefined.
      Only "real" virtual methods should be accounted.  */
-  if (target && TREE_CODE (TREE_TYPE (target)) != METHOD_TYPE)
+  if (target && TREE_CODE (TREE_TYPE (target)) != METHOD_TYPE &&
!pure_virtual)
     return;

   if (!can_refer)
@@ -2388,6 +2397,7 @@ maybe_record_node (vec <cgraph_node *> &
      ??? Maybe it would make sense to be more aggressive for LTO even
      elsewhere.  */
   if (!flag_ltrans
+      && !pure_virtual
       && type_in_anonymous_namespace_p (DECL_CONTEXT (target))
       && (!target_node
           || !referenced_from_vtable_p (target_node)))
@@ -2401,6 +2411,20 @@ maybe_record_node (vec <cgraph_node *> &
     {
       gcc_assert (!target_node->global.inlined_to);
       gcc_assert (target_node->real_symbol_p ());
+      /* Only add pure virtual if it is the only possible target.  This way
+        we will preserve the diagnostics about pure virtual called in many
+        cases without disabling optimization in other.  */
+      if (pure_virtual)
+       {
+         if (nodes.length ())
+           return;
+       }
+      /* If we found a real target, take away cxa_pure_virtual.  */
+      else if (!pure_virtual && nodes.length () == 1
+              && is_cxa_pure_virtual_p (nodes[0]->decl))
+       nodes.pop ();
+      if (pure_virtual && nodes.length ())
+       return;
       if (!inserted->add (target))
        {
          cached_polymorphic_call_targets->add (target_node);

which attempts to preserve the call to cxa_pure_virtual in cases it is cheap to
do so (i.e. we know it is the only target of the call).
It is still more expensive to call cxa_pure_virtual compared to
bulitin_unreachable.  I will try to get some stats on firefox how often it
matters in practice.


More information about the Gcc-bugs mailing list