Patchwork C++ PATCH for c++/47049 (ICE with lambda in template)

login
register
mail settings
Submitter Jason Merrill
Date May 28, 2011, 12:52 a.m.
Message ID <4DE04744.9010605@redhat.com>
Download mbox | patch
Permalink /patch/97763/
State New
Headers show

Comments

Jason Merrill - May 28, 2011, 12:52 a.m.
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.

Patch

commit acd4876ce7c095f91a4d7a149bc8a7f9bf4ec733
Author: Jason Merrill <jason@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 <jason@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 ();