C++ PATCH for c++/79176 (ICE with LTO and lambda)

Jason Merrill jason@redhat.com
Thu Jan 26 15:30:00 GMT 2017


vague_linkage_p has been assuming that anything with !TREE_PUBLIC is
internal, and so does not have vague linkage.  That isn't true for
decloned constructors: the decloned variant which is called by the
complete and base variants is !TREE_PUBLIC because it's local to the
comdat group, but it still has vague linkage.  This patch handles this
by checking one of the "clones" (actually thunks) for the real
linkage.

Tested x86_64-pc-linux-gnu, applying to trunk.
-------------- next part --------------
commit 71397ef2ab55861706bd951d4e4f74ee3a31ee91
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Jan 25 12:31:13 2017 -0500

            PR c++/79176 - lambda ICE with -flto -Os
    
            * decl2.c (vague_linkage_p): Handle decloned 'tors.
            * tree.c (decl_linkage): Likewise.

diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 0a4c567..a9a1d22 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -1816,6 +1816,14 @@ vague_linkage_p (tree decl)
 {
   if (!TREE_PUBLIC (decl))
     {
+      /* maybe_thunk_body clears TREE_PUBLIC on the maybe-in-charge 'tor
+	 variants, check one of the "clones" for the real linkage.  */
+      if ((DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl)
+	   || DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl))
+	  && DECL_CHAIN (decl)
+	  && DECL_CLONED_FUNCTION (DECL_CHAIN (decl)))
+	return vague_linkage_p (DECL_CHAIN (decl));
+
       gcc_checking_assert (!DECL_COMDAT (decl));
       return false;
     }
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 6fbc99e..3ecc2b0 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -4418,6 +4418,14 @@ decl_linkage (tree decl)
   if (TREE_PUBLIC (decl))
     return lk_external;
 
+  /* maybe_thunk_body clears TREE_PUBLIC on the maybe-in-charge 'tor variants,
+     check one of the "clones" for the real linkage.  */
+  if ((DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl)
+       || DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl))
+      && DECL_CHAIN (decl)
+      && DECL_CLONED_FUNCTION (DECL_CHAIN (decl)))
+    return decl_linkage (DECL_CHAIN (decl));
+
   if (TREE_CODE (decl) == NAMESPACE_DECL)
     return lk_external;
 
diff --git a/gcc/testsuite/g++.dg/opt/declone3.C b/gcc/testsuite/g++.dg/opt/declone3.C
new file mode 100644
index 0000000..d8c2492
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/declone3.C
@@ -0,0 +1,16 @@
+// PR c++/79176
+// { dg-do compile { target c++11 } }
+// { dg-options "-flto -Os" }
+
+struct A {};
+struct Object {
+  virtual bool m_fn1();
+  virtual ~Object();
+};
+struct Item : Object, virtual A {
+  ~Item() {
+    [] {};
+  }
+  bool m_fn1();
+};
+bool Item::m_fn1() {}


More information about the Gcc-patches mailing list