From patchwork Thu Dec 6 14:34:27 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: C++ PATCH for c++/55015 (undefined lambda conv op) Date: Thu, 06 Dec 2012 04:34:27 -0000 From: Jason Merrill X-Patchwork-Id: 204249 Message-Id: <50C0ACF3.1020603@redhat.com> To: gcc-patches List My earlier patch to change the linkage of the lambda conversion operator was wrong; the problem was that we were failing to mark members of a local class in a template as comdat. So I've fixed that and reverted the earlier change. Tested x86_64-pc-linux-gnu, applying to trunk and 4.7. commit 98abf95dad4ba214f04fb30d2e8c756b9d209797 Author: Jason Merrill Date: Wed Dec 5 17:33:27 2012 -0500 PR c++/55015 PR c++/53821 * semantics.c (maybe_add_lambda_conv_op): Revert earlier change. * decl.c (start_preparsed_function): Make local class methods comdat in templates, too. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index bae48ce..cdda2f4 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -13199,10 +13199,9 @@ start_preparsed_function (tree decl1, tree attrs, int flags) if (DECL_NOT_REALLY_EXTERN (decl1)) DECL_EXTERNAL (decl1) = 0; - if (ctx != NULL_TREE && DECL_DECLARED_INLINE_P (ctx) - && TREE_PUBLIC (ctx)) + if (ctx != NULL_TREE && vague_linkage_p (ctx)) /* This is a function in a local class in an extern inline - function. */ + or template function. */ comdat_linkage (decl1); } /* If this function belongs to an interface, it is public. diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index eaf7069..53e849a 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -9419,6 +9419,8 @@ maybe_add_lambda_conv_op (tree type) DECL_NOT_REALLY_EXTERN (fn) = 1; DECL_DECLARED_INLINE_P (fn) = 1; DECL_ARGUMENTS (fn) = build_this_parm (fntype, TYPE_QUAL_CONST); + if (nested) + DECL_INTERFACE_KNOWN (fn) = 1; add_method (type, fn, NULL_TREE); @@ -9449,6 +9451,8 @@ maybe_add_lambda_conv_op (tree type) DECL_ARGUMENTS (fn) = copy_list (DECL_CHAIN (DECL_ARGUMENTS (callop))); for (arg = DECL_ARGUMENTS (fn); arg; arg = DECL_CHAIN (arg)) DECL_CONTEXT (arg) = fn; + if (nested) + DECL_INTERFACE_KNOWN (fn) = 1; add_method (type, fn, NULL_TREE); diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-conv6.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-conv6.C new file mode 100644 index 0000000..bd90437 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-conv6.C @@ -0,0 +1,7 @@ +// PR c++/55015 +// { dg-do link } +// { dg-options -std=c++11 } + +typedef void (*VoidFunc)(); +inline VoidFunc GetFunc() { return [](){}; } +int main() { VoidFunc func = GetFunc(); }