diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 7933e02e57d..90b1671e6f0 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2017-01-26 Jason Merrill + + PR c++/79176 - lambda ICE with -flto -Os + * decl2.c (vague_linkage_p): Handle decloned 'tors. + * tree.c (decl_linkage): Likewise. + 2017-01-25 Martin Sebor * decl.c (grokdeclarator): Fix a typo in a comment. diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 0a4c5671df1..a9a1d2286a8 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 6fbc99ee56b..3ecc2b00fef 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 00000000000..d8c24921116 --- /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() {}