aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2017-08-31 11:39:04 -0400
committerJason Merrill <jason@gcc.gnu.org>2017-08-31 11:39:04 -0400
commitb54d4018b17c8e7be96cedd211e7c9dd5d1c3e43 (patch)
treeb4c0272397b660cccc114bdba77600bbaa9f0269 /gcc
parent28f4ff35247bb085d5de9816c6ced4dc4e14269e (diff)
downloadgcc-b54d4018b17c8e7be96cedd211e7c9dd5d1c3e43.zip
gcc-b54d4018b17c8e7be96cedd211e7c9dd5d1c3e43.tar.gz
gcc-b54d4018b17c8e7be96cedd211e7c9dd5d1c3e43.tar.bz2
PR c++/82029 - __PRETTY_FUNCTION__ in lambda in template
* pt.c (enclosing_instantiation_of, lambda_fn_in_template_p) (regenerated_lambda_fn_p): New. (tsubst_decl) [VAR_DECL]: Use enclosing_instantiation_of. (tsubst_copy) [VAR_DECL]: Likewise. From-SVN: r251567
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/pt.c63
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-__func__2.C13
3 files changed, 78 insertions, 4 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a8c1367..4a791dd 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,11 @@
2017-08-30 Jason Merrill <jason@redhat.com>
+ PR c++/82029 - __PRETTY_FUNCTION__ in lambda in template
+ * pt.c (enclosing_instantiation_of, lambda_fn_in_template_p)
+ (regenerated_lambda_fn_p): New.
+ (tsubst_decl) [VAR_DECL]: Use enclosing_instantiation_of.
+ (tsubst_copy) [VAR_DECL]: Likewise.
+
PR c++/82030 - ICE inheriting from multiple lambdas
PR c++/80767
* call.c (compare_ics): Handle null candidate.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index f4868ab..d5ab939 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -12587,6 +12587,63 @@ tsubst_template_decl (tree t, tree args, tsubst_flags_t complain,
return r;
}
+/* True if FN is the op() for a lambda in an uninstantiated template. */
+
+bool
+lambda_fn_in_template_p (tree fn)
+{
+ if (!LAMBDA_FUNCTION_P (fn))
+ return false;
+ tree closure = DECL_CONTEXT (fn);
+ return CLASSTYPE_TEMPLATE_INFO (closure) != NULL_TREE;
+}
+
+/* True if FN is the op() for a lambda regenerated from a lambda in an
+ uninstantiated template. */
+
+bool
+regenerated_lambda_fn_p (tree fn)
+{
+ return (LAMBDA_FUNCTION_P (fn)
+ && !DECL_TEMPLATE_INSTANTIATION (fn));
+}
+
+/* We're instantiating a variable from template function TCTX. Return the
+ corresponding current enclosing scope. This gets complicated because lambda
+ functions in templates are regenerated rather than instantiated, but generic
+ lambda functions are subsequently instantiated. */
+
+static tree
+enclosing_instantiation_of (tree tctx)
+{
+ tree fn = current_function_decl;
+ int lambda_count = 0;
+
+ for (; tctx && lambda_fn_in_template_p (tctx);
+ tctx = decl_function_context (tctx))
+ ++lambda_count;
+ for (; fn; fn = decl_function_context (fn))
+ {
+ tree lambda = fn;
+ int flambda_count = 0;
+ for (; fn && regenerated_lambda_fn_p (fn);
+ fn = decl_function_context (fn))
+ ++flambda_count;
+ if (DECL_TEMPLATE_INFO (fn)
+ ? most_general_template (fn) != most_general_template (tctx)
+ : fn != tctx)
+ continue;
+ if (lambda_count)
+ {
+ fn = lambda;
+ while (flambda_count-- > lambda_count)
+ fn = decl_function_context (fn);
+ }
+ return fn;
+ }
+ gcc_unreachable ();
+}
+
/* Substitute the ARGS into the T, which is a _DECL. Return the
result of the substitution. Issue error and warning messages under
control of COMPLAIN. */
@@ -12955,7 +13012,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
enclosing function, in which case we need to fill it in now. */
if (TREE_STATIC (t))
{
- tree fn = tsubst (DECL_CONTEXT (t), args, complain, in_decl);
+ tree fn = enclosing_instantiation_of (DECL_CONTEXT (t));
if (fn != current_function_decl)
ctx = fn;
}
@@ -14734,9 +14791,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
if (r && !is_capture_proxy (r))
{
/* Make sure that the one we found is the one we want. */
- tree ctx = DECL_CONTEXT (t);
- if (DECL_LANG_SPECIFIC (ctx) && DECL_TEMPLATE_INFO (ctx))
- ctx = tsubst (ctx, args, complain, in_decl);
+ tree ctx = enclosing_instantiation_of (DECL_CONTEXT (t));
if (ctx != DECL_CONTEXT (r))
r = NULL_TREE;
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-__func__2.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-__func__2.C
new file mode 100644
index 0000000..bc0e3b2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-__func__2.C
@@ -0,0 +1,13 @@
+// PR c++/82029
+// { dg-do compile { target c++11 } }
+
+template <typename> struct A {
+ void m_fn1() {
+ [] { return __func__; }();
+ }
+};
+struct B {
+ A<int> a;
+ void m_fn2();
+};
+void B::m_fn2() { a.m_fn1(); }