The problem with this testcase was that we were trying to generate the
mangled name of an uninstantiated lambda; we shouldn't ever try to
mangle an uninstantiated template. So I changed
start_preparsed_function to avoid that. After that was fixed, I found
that I also needed to modify maybe_add_lambda_conv_op so that it would
get the right comdat group for op() even if it hasn't been instantiated yet.
To guard against similar problems in future I added an assert to
mangle_decl_string so that we don't try to mangle templates anymore.
This revealed an issue with the #pragma interface code, also fixed.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit acd4876ce7c095f91a4d7a149bc8a7f9bf4ec733
Author: Jason Merrill <ja...@redhat.com>
Date: Fri May 27 16:30:55 2011 -0400
PR c++/47049
* semantics.c (maybe_add_lambda_conv_op): Fix COMDAT sharing.
* decl.c (start_preparsed_function): Don't call comdat_linkage for
a template.
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 3cc25bd..8fe3259 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -12672,6 +12672,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
DECL_EXTERNAL (decl1) = 0;
if (ctx != NULL_TREE && DECL_DECLARED_INLINE_P (ctx)
+ && !processing_template_decl
&& TREE_PUBLIC (ctx))
/* This is a function in a local class in an extern inline
function. */
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 557bf4c..854bac7 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -8578,7 +8578,7 @@ maybe_add_lambda_conv_op (tree type)
{
/* Put the thunk in the same comdat group as the call op. */
struct cgraph_node *callop_node, *thunk_node;
- DECL_COMDAT_GROUP (statfn) = DECL_COMDAT_GROUP (callop);
+ DECL_COMDAT_GROUP (statfn) = cxx_comdat_group (callop);
callop_node = cgraph_get_create_node (callop);
thunk_node = cgraph_get_create_node (statfn);
gcc_assert (callop_node->same_comdat_group == NULL);
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template2.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template2.C
new file mode 100644
index 0000000..12ffde7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template2.C
@@ -0,0 +1,20 @@
+// PR c++/47049
+// { dg-options -std=c++0x }
+
+enum { E = 0, F = 1 };
+template <int N, int M = ((N == 1) ? F : E)> class S {};
+template <int N>
+struct T
+{
+ static void
+ foo (S<N> *p)
+ {
+ S<N> u;
+ [&u] ()->bool {} ();
+ }
+};
+
+int main()
+{
+ T<0>().foo(0);
+}
commit 32da298d587756e13c43b3a5d2a73babdf9f58bc
Author: Jason Merrill <ja...@redhat.com>
Date: Fri May 27 16:31:23 2011 -0400
* mangle.c (mangle_decl_string): Make sure we don't try to mangle
templates.
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 8fe3259..232b5cf 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -12664,7 +12664,9 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
compiler-generated functions. */
&& !DECL_ARTIFICIAL (decl1));
- if (DECL_INTERFACE_KNOWN (decl1))
+ if (processing_template_decl)
+ /* Don't mess with interface flags. */;
+ else if (DECL_INTERFACE_KNOWN (decl1))
{
tree ctx = decl_function_context (decl1);
@@ -12672,7 +12674,6 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
DECL_EXTERNAL (decl1) = 0;
if (ctx != NULL_TREE && DECL_DECLARED_INLINE_P (ctx)
- && !processing_template_decl
&& TREE_PUBLIC (ctx))
/* This is a function in a local class in an extern inline
function. */
@@ -12684,8 +12685,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
else if (!finfo->interface_unknown && honor_interface)
{
if (DECL_DECLARED_INLINE_P (decl1)
- || DECL_TEMPLATE_INSTANTIATION (decl1)
- || processing_template_decl)
+ || DECL_TEMPLATE_INSTANTIATION (decl1))
{
DECL_EXTERNAL (decl1)
= (finfo->interface_only
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 27ef374..7ecfefb 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -3095,6 +3095,9 @@ mangle_decl_string (const tree decl)
tree saved_fn = NULL_TREE;
bool template_p = false;
+ /* We shouldn't be trying to mangle an uninstantiated template. */
+ gcc_assert (!type_dependent_expression_p (decl));
+
if (DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl))
{
struct tinst_level *tl = current_instantiation ();