Commit c6be04ad by Jason Merrill Committed by Jason Merrill

Make lambda conversion op and op() non-static.

	* semantics.c (maybe_add_lambda_conv_op): Make non-static.
	Also add the thunk function returned by the conversion op.
	Mark the conversion deleted if the op() is variadic.
	* decl2.c (mark_used): Give helpful message about deleted conversion.
	* parser.c (cp_parser_lambda_declarator_opt): Don't make op() static.
	* semantics.c (finish_this_expr): Adjust.
	* mangle.c (write_closure_type_name): Adjust.
	* decl.c (grok_op_properties): Don't allow it.
	* call.c (build_user_type_conversion_1): No static conversion ops.
	(build_op_call): Or op().

	* decl2.c (change_return_type): Fix 'this' quals.

From-SVN: r157681
parent 5b5cfcb3
2010-03-23 Jason Merrill <jason@redhat.com>
Make lambda conversion op and op() non-static.
* semantics.c (maybe_add_lambda_conv_op): Make non-static.
Also add the thunk function returned by the conversion op.
Mark the conversion deleted if the op() is variadic.
* decl2.c (mark_used): Give helpful message about deleted conversion.
* parser.c (cp_parser_lambda_declarator_opt): Don't make op() static.
* semantics.c (finish_this_expr): Adjust.
* mangle.c (write_closure_type_name): Adjust.
* decl.c (grok_op_properties): Don't allow it.
* call.c (build_user_type_conversion_1): No static conversion ops.
(build_op_call): Or op().
* decl2.c (change_return_type): Fix 'this' quals.
2010-03-22 Jason Merrill <jason@redhat.com> 2010-03-22 Jason Merrill <jason@redhat.com>
PR c++/43333 PR c++/43333
......
...@@ -2944,16 +2944,11 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags) ...@@ -2944,16 +2944,11 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
for (fns = TREE_VALUE (conv_fns); fns; fns = OVL_NEXT (fns)) for (fns = TREE_VALUE (conv_fns); fns; fns = OVL_NEXT (fns))
{ {
tree fn = OVL_CURRENT (fns); tree fn = OVL_CURRENT (fns);
tree first = first_arg;
if (DECL_NONCONVERTING_P (fn) if (DECL_NONCONVERTING_P (fn)
&& (flags & LOOKUP_ONLYCONVERTING)) && (flags & LOOKUP_ONLYCONVERTING))
continue; continue;
/* Lambdas have a static conversion op. */
if (DECL_STATIC_FUNCTION_P (fn))
first = NULL_TREE;
/* [over.match.funcs] For conversion functions, the function /* [over.match.funcs] For conversion functions, the function
is considered to be a member of the class of the implicit is considered to be a member of the class of the implicit
object argument for the purpose of defining the type of object argument for the purpose of defining the type of
...@@ -2964,14 +2959,14 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags) ...@@ -2964,14 +2959,14 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
if (TREE_CODE (fn) == TEMPLATE_DECL) if (TREE_CODE (fn) == TEMPLATE_DECL)
cand = add_template_candidate (&candidates, fn, fromtype, cand = add_template_candidate (&candidates, fn, fromtype,
NULL_TREE, NULL_TREE,
first, NULL, totype, first_arg, NULL, totype,
TYPE_BINFO (fromtype), TYPE_BINFO (fromtype),
conversion_path, conversion_path,
flags, flags,
DEDUCE_CONV); DEDUCE_CONV);
else else
cand = add_function_candidate (&candidates, fn, fromtype, cand = add_function_candidate (&candidates, fn, fromtype,
first, NULL, first_arg, NULL,
TYPE_BINFO (fromtype), TYPE_BINFO (fromtype),
conversion_path, conversion_path,
flags); flags);
...@@ -3379,28 +3374,19 @@ build_op_call (tree obj, VEC(tree,gc) **args, tsubst_flags_t complain) ...@@ -3379,28 +3374,19 @@ build_op_call (tree obj, VEC(tree,gc) **args, tsubst_flags_t complain)
{ {
tree fn = OVL_CURRENT (fns); tree fn = OVL_CURRENT (fns);
tree lfirst = first_mem_arg;
if (DECL_STATIC_FUNCTION_P (fn))
lfirst = NULL_TREE;
if (TREE_CODE (fn) == TEMPLATE_DECL) if (TREE_CODE (fn) == TEMPLATE_DECL)
add_template_candidate (&candidates, fn, base, NULL_TREE, add_template_candidate (&candidates, fn, base, NULL_TREE,
lfirst, *args, NULL_TREE, first_mem_arg, *args, NULL_TREE,
TYPE_BINFO (type), TYPE_BINFO (type),
TYPE_BINFO (type), TYPE_BINFO (type),
LOOKUP_NORMAL, DEDUCE_CALL); LOOKUP_NORMAL, DEDUCE_CALL);
else else
add_function_candidate add_function_candidate
(&candidates, fn, base, lfirst, *args, TYPE_BINFO (type), (&candidates, fn, base, first_mem_arg, *args, TYPE_BINFO (type),
TYPE_BINFO (type), LOOKUP_NORMAL); TYPE_BINFO (type), LOOKUP_NORMAL);
} }
} }
/* Rather than mess with handling static conversion ops here, just don't
look at conversions in lambdas. */
if (LAMBDA_TYPE_P (type))
convs = NULL_TREE;
else
convs = lookup_conversions (type, /*lookup_template_convs_p=*/true); convs = lookup_conversions (type, /*lookup_template_convs_p=*/true);
for (; convs; convs = TREE_CHAIN (convs)) for (; convs; convs = TREE_CHAIN (convs))
......
...@@ -10318,14 +10318,9 @@ grok_op_properties (tree decl, bool complain) ...@@ -10318,14 +10318,9 @@ grok_op_properties (tree decl, bool complain)
|| operator_code == ARRAY_REF || operator_code == ARRAY_REF
|| operator_code == NOP_EXPR) || operator_code == NOP_EXPR)
{ {
if (class_type && LAMBDA_TYPE_P (class_type))
/* Lambdas can have static op() and conv ops. */;
else
{
error ("%qD must be a nonstatic member function", decl); error ("%qD must be a nonstatic member function", decl);
return false; return false;
} }
}
else else
{ {
tree p; tree p;
......
...@@ -156,7 +156,8 @@ change_return_type (tree new_ret, tree fntype) ...@@ -156,7 +156,8 @@ change_return_type (tree new_ret, tree fntype)
if (TREE_CODE (fntype) == FUNCTION_TYPE) if (TREE_CODE (fntype) == FUNCTION_TYPE)
newtype = build_function_type (new_ret, args); newtype = build_function_type (new_ret, args);
else else
newtype = build_method_type_directly (TYPE_METHOD_BASETYPE (fntype), newtype = build_method_type_directly
(TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fntype))),
new_ret, TREE_CHAIN (args)); new_ret, TREE_CHAIN (args));
if (raises) if (raises)
newtype = build_exception_variant (newtype, raises); newtype = build_exception_variant (newtype, raises);
...@@ -4006,6 +4007,18 @@ mark_used (tree decl) ...@@ -4006,6 +4007,18 @@ mark_used (tree decl)
if (TREE_CODE (decl) == FUNCTION_DECL if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DELETED_FN (decl)) && DECL_DELETED_FN (decl))
{ {
if (DECL_ARTIFICIAL (decl))
{
if (DECL_OVERLOADED_OPERATOR_P (decl) == TYPE_EXPR
&& LAMBDA_TYPE_P (DECL_CONTEXT (decl)))
{
/* We mark a lambda conversion op as deleted if we can't
generate it properly; see maybe_add_lambda_conv_op. */
sorry ("converting lambda which uses %<...%> to "
"function pointer");
return;
}
}
error ("deleted function %q+D", decl); error ("deleted function %q+D", decl);
error ("used here"); error ("used here");
return; return;
......
...@@ -1331,7 +1331,7 @@ write_closure_type_name (const tree type) ...@@ -1331,7 +1331,7 @@ write_closure_type_name (const tree type)
MANGLE_TRACE_TREE ("closure-type-name", type); MANGLE_TRACE_TREE ("closure-type-name", type);
write_string ("Ul"); write_string ("Ul");
write_method_parms (parms, DECL_NONSTATIC_MEMBER_FUNCTION_P (fn), fn); write_method_parms (parms, /*method_p=*/1, fn);
write_char ('E'); write_char ('E');
write_compact_number (LAMBDA_EXPR_DISCRIMINATOR (lambda)); write_compact_number (LAMBDA_EXPR_DISCRIMINATOR (lambda));
} }
......
...@@ -7390,18 +7390,8 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) ...@@ -7390,18 +7390,8 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
declarator = make_id_declarator (NULL_TREE, ansi_opname (CALL_EXPR), declarator = make_id_declarator (NULL_TREE, ansi_opname (CALL_EXPR),
sfk_none); sfk_none);
quals = TYPE_UNQUALIFIED; quals = (LAMBDA_EXPR_MUTABLE_P (lambda_expr)
if (LAMBDA_EXPR_CAPTURE_LIST (lambda_expr) == NULL_TREE ? TYPE_UNQUALIFIED : TYPE_QUAL_CONST);
&& LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) == CPLD_NONE)
{
/* A lambda with no captures has a static op() and a conversion op
to function type. */
if (LAMBDA_EXPR_MUTABLE_P (lambda_expr))
error ("lambda expression with no captures declared mutable");
return_type_specs.storage_class = sc_static;
}
else if (!LAMBDA_EXPR_MUTABLE_P (lambda_expr))
quals = TYPE_QUAL_CONST;
declarator = make_call_declarator (declarator, param_list, quals, declarator = make_call_declarator (declarator, param_list, quals,
exception_spec, exception_spec,
/*late_return_type=*/NULL_TREE); /*late_return_type=*/NULL_TREE);
......
...@@ -2104,13 +2104,17 @@ finish_this_expr (void) ...@@ -2104,13 +2104,17 @@ finish_this_expr (void)
{ {
tree result; tree result;
if (current_class_ptr)
{
tree type = TREE_TYPE (current_class_ref);
/* In a lambda expression, 'this' refers to the captured 'this'. */ /* In a lambda expression, 'this' refers to the captured 'this'. */
if (current_function_decl if (LAMBDA_TYPE_P (type))
&& LAMBDA_FUNCTION_P (current_function_decl)) result = lambda_expr_this_capture (CLASSTYPE_LAMBDA_EXPR (type));
result = (lambda_expr_this_capture else
(CLASSTYPE_LAMBDA_EXPR (current_class_type)));
else if (current_class_ptr)
result = current_class_ptr; result = current_class_ptr;
}
else if (current_function_decl else if (current_function_decl
&& DECL_STATIC_FUNCTION_P (current_function_decl)) && DECL_STATIC_FUNCTION_P (current_function_decl))
{ {
...@@ -5861,14 +5865,22 @@ maybe_add_lambda_conv_op (tree type) ...@@ -5861,14 +5865,22 @@ maybe_add_lambda_conv_op (tree type)
bool nested = (current_function_decl != NULL_TREE); bool nested = (current_function_decl != NULL_TREE);
tree callop = lambda_function (type); tree callop = lambda_function (type);
tree rettype, name, fntype, fn, body, compound_stmt; tree rettype, name, fntype, fn, body, compound_stmt;
tree thistype, stattype, statfn, convfn, call, arg;
VEC (tree, gc) *argvec;
if (!DECL_STATIC_FUNCTION_P (callop)) if (LAMBDA_EXPR_CAPTURE_LIST (CLASSTYPE_LAMBDA_EXPR (type)) != NULL_TREE)
return; return;
rettype = build_pointer_type (TREE_TYPE (callop)); stattype = build_function_type (TREE_TYPE (TREE_TYPE (callop)),
FUNCTION_ARG_CHAIN (callop));
/* First build up the conversion op. */
rettype = build_pointer_type (stattype);
name = mangle_conv_op_name_for_type (rettype); name = mangle_conv_op_name_for_type (rettype);
fntype = build_function_type (rettype, void_list_node); thistype = cp_build_qualified_type (type, TYPE_QUAL_CONST);
fn = build_lang_decl (FUNCTION_DECL, name, fntype); fntype = build_method_type_directly (thistype, rettype, void_list_node);
fn = convfn = build_lang_decl (FUNCTION_DECL, name, fntype);
DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (callop); DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (callop);
if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn
...@@ -5883,7 +5895,39 @@ maybe_add_lambda_conv_op (tree type) ...@@ -5883,7 +5895,39 @@ maybe_add_lambda_conv_op (tree type)
DECL_ARTIFICIAL (fn) = 1; DECL_ARTIFICIAL (fn) = 1;
DECL_NOT_REALLY_EXTERN (fn) = 1; DECL_NOT_REALLY_EXTERN (fn) = 1;
DECL_DECLARED_INLINE_P (fn) = 1; DECL_DECLARED_INLINE_P (fn) = 1;
DECL_ARGUMENTS (fn) = build_this_parm (fntype, TYPE_QUAL_CONST);
if (nested)
DECL_INTERFACE_KNOWN (fn) = 1;
add_method (type, fn, NULL_TREE);
/* Generic thunk code fails for varargs; we'll complain in mark_used if
the conversion op is used. */
if (varargs_function_p (callop))
{
DECL_DELETED_FN (fn) = 1;
return;
}
/* Now build up the thunk to be returned. */
name = get_identifier ("_FUN");
fn = statfn = build_lang_decl (FUNCTION_DECL, name, stattype);
DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (callop);
if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn
&& DECL_ALIGN (fn) < 2 * BITS_PER_UNIT)
DECL_ALIGN (fn) = 2 * BITS_PER_UNIT;
grokclassfn (type, fn, NO_SPECIAL);
set_linkage_according_to_type (type, fn);
rest_of_decl_compilation (fn, toplevel_bindings_p (), at_eof);
DECL_IN_AGGR_P (fn) = 1;
DECL_ARTIFICIAL (fn) = 1;
DECL_NOT_REALLY_EXTERN (fn) = 1;
DECL_DECLARED_INLINE_P (fn) = 1;
DECL_STATIC_FUNCTION_P (fn) = 1; DECL_STATIC_FUNCTION_P (fn) = 1;
DECL_ARGUMENTS (fn) = copy_list (TREE_CHAIN (DECL_ARGUMENTS (callop)));
for (arg = DECL_ARGUMENTS (fn); arg; arg = TREE_CHAIN (arg))
DECL_CONTEXT (arg) = fn;
if (nested) if (nested)
DECL_INTERFACE_KNOWN (fn) = 1; DECL_INTERFACE_KNOWN (fn) = 1;
...@@ -5891,17 +5935,55 @@ maybe_add_lambda_conv_op (tree type) ...@@ -5891,17 +5935,55 @@ maybe_add_lambda_conv_op (tree type)
if (nested) if (nested)
push_function_context (); push_function_context ();
start_preparsed_function (fn, NULL_TREE,
/* Generate the body of the thunk. */
start_preparsed_function (statfn, NULL_TREE,
SF_PRE_PARSED | SF_INCLASS_INLINE); SF_PRE_PARSED | SF_INCLASS_INLINE);
if (DECL_ONE_ONLY (statfn))
{
/* Put the thunk in the same comdat group as the call op. */
struct cgraph_node *callop_node, *thunk_node;
DECL_COMDAT_GROUP (statfn) = DECL_COMDAT_GROUP (callop);
callop_node = cgraph_node (callop);
thunk_node = cgraph_node (statfn);
gcc_assert (callop_node->same_comdat_group == NULL);
gcc_assert (thunk_node->same_comdat_group == NULL);
callop_node->same_comdat_group = thunk_node;
thunk_node->same_comdat_group = callop_node;
}
body = begin_function_body (); body = begin_function_body ();
compound_stmt = begin_compound_stmt (0); compound_stmt = begin_compound_stmt (0);
finish_return_stmt (decay_conversion (callop)); arg = build1 (NOP_EXPR, TREE_TYPE (DECL_ARGUMENTS (callop)), void_zero_node);
argvec = make_tree_vector ();
VEC_quick_push (tree, argvec, arg);
for (arg = DECL_ARGUMENTS (statfn); arg; arg = TREE_CHAIN (arg))
VEC_safe_push (tree, gc, argvec, arg);
call = build_cxx_call (callop, VEC_length (tree, argvec),
VEC_address (tree, argvec));
CALL_FROM_THUNK_P (call) = 1;
finish_return_stmt (call);
finish_compound_stmt (compound_stmt); finish_compound_stmt (compound_stmt);
finish_function_body (body); finish_function_body (body);
expand_or_defer_fn (finish_function (2)); expand_or_defer_fn (finish_function (2));
/* Generate the body of the conversion op. */
start_preparsed_function (convfn, NULL_TREE,
SF_PRE_PARSED | SF_INCLASS_INLINE);
body = begin_function_body ();
compound_stmt = begin_compound_stmt (0);
finish_return_stmt (decay_conversion (statfn));
finish_compound_stmt (compound_stmt);
finish_function_body (body);
expand_or_defer_fn (finish_function (2));
if (nested) if (nested)
pop_function_context (); pop_function_context ();
} }
......
2010-03-23 Jason Merrill <jason@redhat.com>
* g++.dg/cpp0x/lambda/lambda-const-neg.C: Adjust for non-static op().
* g++.dg/cpp0x/lambda/lambda-conv.C: Likewise.
* g++.dg/cpp0x/lambda/lambda-mangle.C: Likewise.
* g++.dg/cpp0x/lambda/lambda-non-const.C: Likewise.
* g++.dg/cpp0x/lambda/lambda-conv2.C: New.
* g++.dg/cpp0x/lambda/lambda-conv3.C: New.
2010-03-23 Mike Stump <mikestump@comcast.net> 2010-03-23 Mike Stump <mikestump@comcast.net>
PR target/33120 PR target/33120
......
...@@ -7,7 +7,7 @@ void call(const F& f) { f(); } ...@@ -7,7 +7,7 @@ void call(const F& f) { f(); }
int main() { int main() {
call([] () -> void {}); call([] () -> void {});
call([] () mutable -> void {}); // { dg-message "" "declared mutable" } call([] () mutable -> void {});
int i = -1; int i = -1;
call([&i] () -> void { i = 0; }); call([&i] () -> void { i = 0; });
......
// Test for conversion from stateless lambda to function pointer, which is // Test for conversion from stateless lambda to function pointer.
// not yet part of the draft but hopefully will be after the March 2010
// meeting.
// { dg-options -std=c++0x } // { dg-options -std=c++0x }
// { dg-final { scan-assembler "weak\[^\n\r\]*_?_ZZ1fvENUlvE_cvPFvvEEv" { target { ! { *-*-darwin* *-*-mingw* *-*-cygwin } } } } } // { dg-final { scan-assembler "weak\[^\n\r\]*_?_ZZ1fvENKUlvE_cvPFvvEEv" { target { ! { *-*-darwin* *-*-mingw* *-*-cygwin } } } } }
inline void f() inline void f()
{ {
......
// Test for conversion from stateless lambda to function pointer.
// { dg-options -std=c++0x }
// { dg-do run }
typedef int (*pfn)(int);
int main()
{
pfn p = [](int i) { return i-42; };
return p (42);
}
// Conversion to a function pointer uses a generic thunk, which doesn't
// work properly for variadics. Make sure that we can still use the lambda
// normally.
// { dg-options -std=c++0x }
void f()
{
auto l = [](...){};
void (*p1)(...) = l; // { dg-bogus "sorry" "" { xfail *-*-* } }
l(); // OK
}
...@@ -10,8 +10,8 @@ inline void g(int n) { ...@@ -10,8 +10,8 @@ inline void g(int n) {
// The closure type is encoded as Z1giEUlvE_. // The closure type is encoded as Z1giEUlvE_.
// The call operator of that type is _ZZ1giENKUlvE_clEv. // The call operator of that type is _ZZ1giENKUlvE_clEv.
// { dg-final { scan-assembler "_ZZ1giENUlvE_clEv" } } // { dg-final { scan-assembler "_ZZ1giENKUlvE_clEv" } }
// { dg-final { scan-assembler "weak\[^\n\r\]*_?_ZZ1giENUlvE_clEv" { target { ! { *-*-darwin* *-*-mingw* *-*-cygwin } } } } } // { dg-final { scan-assembler "weak\[^\n\r\]*_?_ZZ1giENKUlvE_clEv" { target { ! { *-*-darwin* *-*-mingw* *-*-cygwin } } } } }
algo([=]{return n+bef();}); algo([=]{return n+bef();});
// The captured entities do not participate in <lambda-sig> // The captured entities do not participate in <lambda-sig>
...@@ -32,17 +32,17 @@ struct S { ...@@ -32,17 +32,17 @@ struct S {
void f(int = void f(int =
// Type: ZN1S1fEiiEd0_UlvE_ // Type: ZN1S1fEiiEd0_UlvE_
// Operator: _ZZN1S1fEiiEd0_NKUlvE_clEv // Operator: _ZZN1S1fEiiEd0_NKUlvE_clEv
// { dg-final { scan-assembler "_ZZN1S1fEiiEd0_NUlvE_clEv" } } // { dg-final { scan-assembler "_ZZN1S1fEiiEd0_NKUlvE_clEv" } }
// { dg-final { scan-assembler "weak\[^\n\r\]*_?_ZZN1S1fEiiEd0_NUlvE_clEv" { target { ! { *-*-darwin* *-*-mingw* *-*-cygwin } } } } } // { dg-final { scan-assembler "weak\[^\n\r\]*_?_ZZN1S1fEiiEd0_NKUlvE_clEv" { target { ! { *-*-darwin* *-*-mingw* *-*-cygwin } } } } }
[]{return 1;}() []{return 1;}()
// Type: ZN1S1fEiiEd0_UlvE0_ // Type: ZN1S1fEiiEd0_UlvE0_
// Operator: _ZZN1S1fEiiEd0_NKUlvE0_clEv // Operator: _ZZN1S1fEiiEd0_NKUlvE0_clEv
// { dg-final { scan-assembler "_ZZN1S1fEiiEd0_NUlvE0_clEv" } } // { dg-final { scan-assembler "_ZZN1S1fEiiEd0_NKUlvE0_clEv" } }
+ []{return 2;}(), + []{return 2;}(),
int = int =
// Type: ZN1S1fEiiEd_UlvE_ // Type: ZN1S1fEiiEd_UlvE_
// Operator: _ZZN1S1fEiiEd_NKUlvE_clEv // Operator: _ZZN1S1fEiiEd_NKUlvE_clEv
// { dg-final { scan-assembler "_ZZN1S1fEiiEd_NUlvE_clEv" } } // { dg-final { scan-assembler "_ZZN1S1fEiiEd_NKUlvE_clEv" } }
[]{return 3;}()); []{return 3;}());
}; };
...@@ -53,8 +53,8 @@ template<typename T> int R<T>::x = []{return 1;}(); ...@@ -53,8 +53,8 @@ template<typename T> int R<T>::x = []{return 1;}();
template int R<int>::x; template int R<int>::x;
// Type of lambda in intializer of R<int>::x: N1RIiE1xMUlvE_E // Type of lambda in intializer of R<int>::x: N1RIiE1xMUlvE_E
// Corresponding operator(): _ZNK1RIiE1xMUlvE_clEv // Corresponding operator(): _ZNK1RIiE1xMUlvE_clEv
// { dg-final { scan-assembler "_ZN1RIiE1xMUlvE_clEv" } } // { dg-final { scan-assembler "_ZNK1RIiE1xMUlvE_clEv" } }
// { dg-final { scan-assembler "weak\[^\n\r\]*_?_ZN1RIiE1xMUlvE_clEv" { target { ! { *-*-mingw* *-*-cygwin } } } } } // { dg-final { scan-assembler "weak\[^\n\r\]*_?_ZNK1RIiE1xMUlvE_clEv" { target { ! { *-*-mingw* *-*-cygwin } } } } }
void bar() void bar()
{ {
...@@ -64,7 +64,7 @@ void bar() ...@@ -64,7 +64,7 @@ void bar()
} }
// lambdas used in non-template, non-class body initializers are internal. // lambdas used in non-template, non-class body initializers are internal.
// { dg-final { scan-assembler-not "weak\[^\n\r\]*_ZNUlv" } } // { dg-final { scan-assembler-not "weak\[^\n\r\]*_ZNKUlv" } }
// { dg-final { scan-assembler-not "weak\[^\n\r\]*variable" } } // { dg-final { scan-assembler-not "weak\[^\n\r\]*variable" } }
int variable = []{return 1;}(); int variable = []{return 1;}();
......
...@@ -8,6 +8,7 @@ void call(F f) { f(); } ...@@ -8,6 +8,7 @@ void call(F f) { f(); }
int main() { int main() {
call([] () -> void {}); call([] () -> void {});
call([] () mutable -> void {});
int i = -1; int i = -1;
call([i] () mutable -> void { i = 0; }); call([i] () mutable -> void { i = 0; });
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment