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