diff mbox

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

Message ID CADzB+2kPVNgM7q_j7=P8MKkmQUxBmun+9quArP+URKYoY1yRLQ@mail.gmail.com
State New
Headers show

Commit Message

Jason Merrill Jan. 26, 2017, 3:28 p.m. UTC
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.
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 mbox

Patch

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() {}