summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog12
-rw-r--r--gcc/cp/lambda.c5
-rw-r--r--gcc/cp/mangle.c1
-rw-r--r--gcc/cp/pt.c10
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template13.C6
5 files changed, 31 insertions, 3 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index e57131f716e..c926978bdcd 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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>
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index 169f438e562..ddaa9406727 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -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)
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 40508ab0cc3..ac165e021d9 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -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. */
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 6a7bcb819c2..611bfd6b7a1 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -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. */
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template13.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template13.C
index adbb4dbcaac..2b1a605acd0 100644
--- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template13.C
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template13.C
@@ -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" } }