IPA's function_and_variable_visibility is dying, because for a C++ virtual inlined TM clone, we have zapped the DECL_EXTERNAL and TREE_PUBLIC bits while building the clone in ipa_tm_create_version.

The assert fails here in function_and_variable_visibility():

      gcc_assert ((!DECL_WEAK (node->decl) && !DECL_COMDAT (node->decl))
|| TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl));

The TM clone is marked weak as the original decl was weak, but it is no longer external or public. I suggested to just clear the DECL_WEAK bit on the clone, but Jason mentioned that unsetting DECL_EXTERNAL is more optimal-- so that the clone can still be public and comdat.

No regressions.  PR fixed.

OK?
        PR middle-end/51411
        * trans-mem.c (ipa_tm_create_version): Do not zap DECL_EXTERNAL.

Index: testsuite/g++.dg/tm/pr51411.C
===================================================================
--- testsuite/g++.dg/tm/pr51411.C       (revision 0)
+++ testsuite/g++.dg/tm/pr51411.C       (revision 0)
@@ -0,0 +1,7 @@
+// { dg-do compile }
+// { dg-options "-fgnu-tm -O" }
+
+struct A
+{
+  __attribute__ ((transaction_safe)) virtual void virtfoo () { }
+};
Index: trans-mem.c
===================================================================
--- trans-mem.c (revision 182290)
+++ trans-mem.c (working copy)
@@ -4256,10 +4256,7 @@ ipa_tm_create_version (struct cgraph_nod
       /* Remap extern inline to static inline.  */
       /* ??? Is it worth trying to use make_decl_one_only?  */
       if (DECL_DECLARED_INLINE_P (new_decl) && DECL_EXTERNAL (new_decl))
-       {
-         DECL_EXTERNAL (new_decl) = 0;
-         TREE_PUBLIC (new_decl) = 0;
-       }
+       TREE_PUBLIC (new_decl) = 0;
 
       tree_function_versioning (old_decl, new_decl, NULL, false, NULL,
                                NULL, NULL);

Reply via email to