When we're determining the exception-specification of a defaulted dtor,
we need to look at the NSDMIs. During this process we set
cp_unevaluated_operand. But having that set during instantiation of the
lambda breaks things. So let's clear it like we do in other places.
The one tricky bit is that we need to restore the flag before we start
instantiating the capture initializers, since they're properly part of
the enclosing context.
Tested x86_64-pc-linux-gnu, applying to trunk and 5.
commit 5efc32db599c3ef64ee577c13f31ca6038624553
Author: Jason Merrill <ja...@redhat.com>
Date: Fri Jun 19 14:20:57 2015 -0400
PR c++/66585
* pt.c (instantiate_class_template_1): Clear
cp_unevaluated_operand and c_inhibit_evaluation_warnings.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 5dd5bfe..efb90e4 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -9215,12 +9215,20 @@ instantiate_class_template_1 (tree type)
it now. */
push_deferring_access_checks (dk_no_deferred);
+ int saved_unevaluated_operand = cp_unevaluated_operand;
+ int saved_inhibit_evaluation_warnings = c_inhibit_evaluation_warnings;
+
fn_context = decl_function_context (TYPE_MAIN_DECL (type));
/* Also avoid push_to_top_level for a lambda in an NSDMI. */
if (!fn_context && LAMBDA_TYPE_P (type) && TYPE_CLASS_SCOPE_P (type))
fn_context = error_mark_node;
if (!fn_context)
push_to_top_level ();
+ else
+ {
+ cp_unevaluated_operand = 0;
+ c_inhibit_evaluation_warnings = 0;
+ }
/* Use #pragma pack from the template context. */
saved_maximum_field_alignment = maximum_field_alignment;
maximum_field_alignment = TYPE_PRECISION (pattern);
@@ -9636,6 +9644,14 @@ instantiate_class_template_1 (tree type)
}
}
+ if (fn_context)
+ {
+ /* Restore these before substituting into the lambda capture
+ initializers. */
+ cp_unevaluated_operand = saved_unevaluated_operand;
+ c_inhibit_evaluation_warnings = saved_inhibit_evaluation_warnings;
+ }
+
if (tree expr = CLASSTYPE_LAMBDA_EXPR (type))
{
tree decl = lambda_function (type);
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi8.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi8.C
new file mode 100644
index 0000000..8c0adfa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi8.C
@@ -0,0 +1,15 @@
+// PR c++/66585
+// { dg-do compile { target c++11 } }
+
+class A {
+ template <typename, typename> using _Requires = int;
+
+public:
+ template <typename _Functor, typename = _Requires<_Functor, void>>
+ A(_Functor);
+};
+template <class T> class B {
+ A f = [](T) {};
+};
+
+B<int> a;