PR c++/61566
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 15 Aug 2014 21:59:40 +0000 (21:59 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 15 Aug 2014 21:59:40 +0000 (21:59 +0000)
* pt.c (instantiate_class_template_1): Ignore lambda on
CLASSTYPE_DECL_LIST.
(push_template_decl_real): A lambda is not primary.
(lookup_template_class_1): Don't look for a lambda partial
instantiation.
* lambda.c (maybe_add_lambda_conv_op): Distinguish between being
currently in a function and the lambda living in a function.
* mangle.c (CLASSTYPE_TEMPLATE_ID_P): False for lambda.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@214046 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/lambda.c
gcc/cp/mangle.c
gcc/cp/pt.c
gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template13.C

index e57131f..c926978 100644 (file)
@@ -1,3 +1,15 @@
+2014-08-15  Jason Merrill  <jason@redhat.com>
+
+       PR c++/61566
+       * pt.c (instantiate_class_template_1): Ignore lambda on
+       CLASSTYPE_DECL_LIST.
+       (push_template_decl_real): A lambda is not primary.
+       (lookup_template_class_1): Don't look for a lambda partial
+       instantiation.
+       * lambda.c (maybe_add_lambda_conv_op): Distinguish between being
+       currently in a function and the lambda living in a function.
+       * mangle.c (CLASSTYPE_TEMPLATE_ID_P): False for lambda.
+
 2014-08-15  Richard Biener  <rguenther@suse.de>
            Jason Merrill  <jason@redhat.com>
 
index 169f438..ddaa940 100644 (file)
@@ -824,6 +824,7 @@ void
 maybe_add_lambda_conv_op (tree type)
 {
   bool nested = (current_function_decl != NULL_TREE);
+  bool nested_def = decl_function_context (TYPE_MAIN_DECL (type));
   tree callop = lambda_function (type);
 
   if (LAMBDA_EXPR_CAPTURE_LIST (CLASSTYPE_LAMBDA_EXPR (type)) != NULL_TREE)
@@ -976,7 +977,7 @@ 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)
+  if (nested_def)
     DECL_INTERFACE_KNOWN (fn) = 1;
 
   if (generic_lambda_p)
@@ -1016,7 +1017,7 @@ maybe_add_lambda_conv_op (tree type)
       DECL_NAME (arg) = NULL_TREE;
       DECL_CONTEXT (arg) = fn;
     }
-  if (nested)
+  if (nested_def)
     DECL_INTERFACE_KNOWN (fn) = 1;
 
   if (generic_lambda_p)
index 40508ab..ac165e0 100644 (file)
@@ -87,6 +87,7 @@ along with GCC; see the file COPYING3.  If not see
   (TYPE_LANG_SPECIFIC (NODE) != NULL                                   \
    && (TREE_CODE (NODE) == BOUND_TEMPLATE_TEMPLATE_PARM                        \
        || (CLASSTYPE_TEMPLATE_INFO (NODE) != NULL                      \
+          && !LAMBDA_TYPE_P (NODE)                                     \
           && (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (NODE))))))
 
 /* Things we only need one of.  This module is not reentrant.  */
index 6a7bcb8..611bfd6 100644 (file)
@@ -4722,6 +4722,9 @@ push_template_decl_real (tree decl, bool is_friend)
          template <typename T> friend void A<T>::f();
        is not primary.  */
     is_primary = false;
+  else if (TREE_CODE (decl) == TYPE_DECL
+          && LAMBDA_TYPE_P (TREE_TYPE (decl)))
+    is_primary = false;
   else
     is_primary = template_parm_scope_p ();
 
@@ -7875,6 +7878,8 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
          && TMPL_ARGS_HAVE_MULTIPLE_LEVELS (arglist)
          /* the enclosing class must be an instantiation...  */
          && CLASS_TYPE_P (context)
+         /* We don't do partial instantiation of closures.  */
+         && !LAMBDA_TYPE_P (TREE_TYPE (gen_tmpl))
          && !same_type_p (context, DECL_CONTEXT (gen_tmpl)))
        {
          tree partial_inst_args;
@@ -9237,6 +9242,11 @@ instantiate_class_template_1 (tree type)
                  && DECL_OMP_DECLARE_REDUCTION_P (r))
                cp_check_omp_declare_reduction (r);
            }
+         else if (DECL_CLASS_TEMPLATE_P (t)
+                  && LAMBDA_TYPE_P (TREE_TYPE (t)))
+           /* A closure type for a lambda in a default argument for a
+              member template.  Ignore it; it will be instantiated with
+              the default argument.  */;
          else
            {
              /* Build new TYPE_FIELDS.  */
index adbb4db..2b1a605 100644 (file)
@@ -7,6 +7,7 @@ struct function
   function (_Functor);
 };
 
+template <class U>
 struct C
 {
   template <typename T>
@@ -15,6 +16,9 @@ struct C
 
 void bar ()
 {
-  C c;
+  C<int> c;
   c.foo (1);
 }
+
+// { dg-final { scan-assembler "_ZN8functionC1IZN1CIiE3fooIiEEvT_S_Ed_UlvE_EET_" } }
+// { dg-final { scan-assembler-not "_ZZN1CIiE3fooIiEEvT_8functionEd_NKUlvE_clEv" } }