aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/semantics.c
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2009-10-27 17:58:09 -0400
committerJason Merrill <jason@gcc.gnu.org>2009-10-27 17:58:09 -0400
commitb77068f27bbad156e88352bb1a3382a96b66acbf (patch)
tree000402686698d1995b0a51ccb183ff709533ba84 /gcc/cp/semantics.c
parent73d28034382a7ba65ec46d6a1cebd828f32b16c9 (diff)
downloadgcc-b77068f27bbad156e88352bb1a3382a96b66acbf.zip
gcc-b77068f27bbad156e88352bb1a3382a96b66acbf.tar.gz
gcc-b77068f27bbad156e88352bb1a3382a96b66acbf.tar.bz2
Allow no-capture lambdas to convert to function pointer.
* semantics.c (maybe_add_lambda_conv_op): New. * parser.c (cp_parser_lambda_expression): Call it. (cp_parser_lambda_declarator_opt): Make op() static if no captures. * mangle.c (write_closure_type_name): Adjust. * semantics.c (finish_this_expr): Adjust. * decl.c (grok_op_properties): Allow it. * call.c (build_user_type_conversion_1): Handle static conversion op. (build_op_call): And op(). From-SVN: r153617
Diffstat (limited to 'gcc/cp/semantics.c')
-rw-r--r--gcc/cp/semantics.c69
1 files changed, 58 insertions, 11 deletions
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 417c15f..e270a73 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2063,17 +2063,13 @@ finish_this_expr (void)
{
tree result;
- if (current_class_ptr)
- {
- tree type = TREE_TYPE (current_class_ref);
-
- /* In a lambda expression, 'this' refers to the captured 'this'. */
- if (LAMBDA_TYPE_P (type))
- result = lambda_expr_this_capture (CLASSTYPE_LAMBDA_EXPR (type));
- else
- result = current_class_ptr;
-
- }
+ /* In a lambda expression, 'this' refers to the captured 'this'. */
+ if (current_function_decl
+ && LAMBDA_FUNCTION_P (current_function_decl))
+ result = (lambda_expr_this_capture
+ (CLASSTYPE_LAMBDA_EXPR (current_class_type)));
+ else if (current_class_ptr)
+ result = current_class_ptr;
else if (current_function_decl
&& DECL_STATIC_FUNCTION_P (current_function_decl))
{
@@ -5759,4 +5755,55 @@ lambda_expr_this_capture (tree lambda)
return result;
}
+/* If the closure TYPE has a static op(), also add a conversion to function
+ pointer. */
+
+void
+maybe_add_lambda_conv_op (tree type)
+{
+ bool nested = (current_function_decl != NULL_TREE);
+ tree callop = lambda_function (type);
+ tree rettype, name, fntype, fn, body, compound_stmt;
+
+ if (!DECL_STATIC_FUNCTION_P (callop))
+ return;
+
+ rettype = build_pointer_type (TREE_TYPE (callop));
+ name = mangle_conv_op_name_for_type (rettype);
+ fntype = build_function_type (rettype, void_list_node);
+ fn = build_lang_decl (FUNCTION_DECL, name, fntype);
+ 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;
+
+ SET_OVERLOADED_OPERATOR_CODE (fn, TYPE_EXPR);
+ 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;
+
+ add_method (type, fn, NULL_TREE);
+
+ if (nested)
+ push_function_context ();
+ start_preparsed_function (fn, NULL_TREE,
+ SF_PRE_PARSED | SF_INCLASS_INLINE);
+ body = begin_function_body ();
+ compound_stmt = begin_compound_stmt (0);
+
+ finish_return_stmt (decay_conversion (callop));
+
+ finish_compound_stmt (compound_stmt);
+ finish_function_body (body);
+
+ expand_or_defer_fn (finish_function (2));
+ if (nested)
+ pop_function_context ();
+}
#include "gt-cp-semantics.h"