We already deal with PARM_DECLs that aren't available for lookup in a
late-specified return type, but this case needs the same treatment for a
local variable. During normal instantiation of the lambda we find the
local variable fine, but later when we're doing dump_template_bindings
from cxx_print_decl, the variable isn't in scope anymore, and we can
deal with that in the same way we handle PARM_DECLs.
Tested x86_64-cp-linux-gnu, applying to trunk.
commit 6930b77188740b3e1979260ee805b38733b0f698
Author: Jason Merrill <ja...@redhat.com>
Date: Tue Jan 28 16:56:42 2014 -0500
PR c++/59791
* pt.c (tsubst_decl) [VAR_DECL]: Allow in unevaluated context.
(tsubst_copy): Use it if lookup fails.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 011db2c..7f1b6d5 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -10990,9 +10990,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
DECL_TEMPLATE_INFO (r) = build_template_info (tmpl, argvec);
SET_DECL_IMPLICIT_INSTANTIATION (r);
}
- else if (cp_unevaluated_operand)
- gcc_unreachable ();
- else
+ else if (!cp_unevaluated_operand)
register_local_specialization (r, t);
DECL_CHAIN (r) = NULL_TREE;
@@ -12481,6 +12479,11 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
}
else
{
+ /* This can happen for a variable used in a late-specified
+ return type of a local lambda. Just make a dummy decl
+ since it's only used for its type. */
+ if (cp_unevaluated_operand)
+ return tsubst_decl (t, args, complain);
gcc_assert (errorcount || sorrycount);
return error_mark_node;
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-decltype1.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-decltype1.C
new file mode 100644
index 0000000..0ab0cdd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-decltype1.C
@@ -0,0 +1,21 @@
+// PR c++/59791
+// We force the gimple dump to trigger use of lang_decl_name.
+// { dg-options "-std=c++11 -fdump-tree-gimple" }
+// { dg-final { cleanup-tree-dump "gimple" } }
+
+template < class T > void
+f (T t)
+{
+ int i = t;
+ [](int)->decltype (i + t)
+ {
+ return 0;
+ }
+ (0);
+}
+
+void
+foo ()
+{
+ f (0);
+}