extern void finish_member_declaration (tree);
extern bool outer_automatic_var_p (tree);
extern bool parsing_lambda_declarator ();
-extern tree process_outer_var_ref (tree, tsubst_flags_t, bool force_use = false);
+extern tree process_outer_var_ref (tree, tsubst_flags_t,
+ bool = false);
extern cp_expr finish_id_expression (tree, tree, tree,
cp_id_kind *,
bool, bool, bool *,
}
}
tree r = mark_rvalue_use (ref, loc, reject_builtin);
+ if (r == error_mark_node)
+ return error_mark_node;
if (r != ref)
{
if (!rvalue_p)
id-expression, and we do lambda capture. */
tree
-process_outer_var_ref (tree decl, tsubst_flags_t complain, bool odr_use)
+process_outer_var_ref (tree decl, tsubst_flags_t complain,
+ bool odr_use/*=false*/)
{
if (cp_unevaluated_operand)
{
constant without odr-use. So don't complain yet. */
else if (!odr_use && decl_constant_var_p (var))
return var;
+ /* Don't complain when DECL is dependent, because it can turn out to
+ be constant (and therefore needing no capture) when instantiating. */
+ else if (VAR_P (var) && instantiation_dependent_expression_p (var))
+ return var;
else if (lambda_expr)
{
if (complain & tf_error)
}
return error_mark_node;
}
- else if (processing_contract_condition && (TREE_CODE (decl) == PARM_DECL))
+ else if (processing_contract_condition && TREE_CODE (decl) == PARM_DECL)
/* Use of a parameter in a contract condition is fine. */
return decl;
else
--- /dev/null
+// PR c++/123536
+// { dg-do compile { target c++11 } }
+
+int g;
+
+struct S {
+ static int static_data_member;
+};
+
+template<int = 1>
+void
+fn1 ()
+{
+ int &c = g;
+ auto l = [] { c++; };
+ l();
+}
+
+template<int N = 1>
+void
+fn2 ()
+{
+ const int &c = N;
+ // TODO This will be valid once we implement P2686.
+ auto l = [] { int i = c; (void) i; }; // { dg-error ".c. is not captured" }
+ l();
+}
+
+void
+fn3 ()
+{
+ int &c = g;
+ auto l = [] { c++; };
+ l();
+}
+
+void
+fn4 ()
+{
+ int n = 42;
+ const int &c = n;
+ auto l = [] { int i = c; (void) i; }; // { dg-error ".c. is not captured" }
+ l();
+}
+
+template<class T>
+void
+fn5 ()
+{
+ int& c = T::static_data_member;
+ auto l = [] { c++; };
+ l();
+}
+
+template<class T>
+void
+fn6 ()
+{
+ int& c = T::static_data_member;
+ [&c] {
+ [] { c++; }();
+ };
+}
+
+void
+bar ()
+{
+ fn1 ();
+ fn2 ();
+ fn3 ();
+ fn4 ();
+ fn5<S>();
+ fn6<S>();
+}
--- /dev/null
+// PR c++/123536
+// { dg-do compile { target c++11 } }
+
+int g;
+
+template<class T>
+void
+fn1 ()
+{
+ T c = g;
+ auto l = [] { c++; };
+ l();
+}
+
+void
+bar ()
+{
+ fn1<int&> ();
+}
--- /dev/null
+// PR c++/123536
+// { dg-do compile { target c++11 } }
+
+template<class T>
+void
+f ()
+{
+ int& c = T::x; // { dg-error ".x. is not a member of .int." }
+ auto l = [] { c++; }; // { dg-error ".c. is not captured" }
+}
+
+void
+g ()
+{
+ f<int>();
+}
--- /dev/null
+// PR c++/123536
+
+int g;
+
+template<class T>
+void
+fn1 ()
+{
+ T c = g;
+ struct A { static void f() { c++; } };
+ A::f();
+}
+
+void
+bar ()
+{
+ fn1<int&> ();
+}