From 2bf492a1a4526f143064e41001f34fc1874feea7 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Mon, 20 Oct 2014 13:29:02 -0400 Subject: [PATCH] re PR c++/63601 (Segfault on usage of 'this' in unevaluated context inside lambda) PR c++/63601 * lambda.c (current_nonlambda_function): New. * semantics.c (finish_this_expr): Use it. * cp-tree.h: Declare it. From-SVN: r216488 --- gcc/cp/ChangeLog | 7 +++++ gcc/cp/cp-tree.h | 1 + gcc/cp/lambda.c | 11 +++++++ gcc/cp/semantics.c | 30 ++++++++----------- .../g++.dg/cpp0x/lambda/lambda-this20.C | 4 +++ 5 files changed, 35 insertions(+), 18 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this20.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1148e9566ad..e61ae2bfa83 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2014-10-20 Jason Merrill + + PR c++/63601 + * lambda.c (current_nonlambda_function): New. + * semantics.c (finish_this_expr): Use it. + * cp-tree.h: Declare it. + 2014-10-17 Alan Modra PR middle-end/61848 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index b6afc311fe0..0923d9f0f7c 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5961,6 +5961,7 @@ extern bool is_normal_capture_proxy (tree); extern void register_capture_members (tree); extern tree lambda_expr_this_capture (tree, bool); extern tree maybe_resolve_dummy (tree, bool); +extern tree current_nonlambda_function (void); extern tree nonlambda_method_basetype (void); extern void maybe_add_lambda_conv_op (tree); extern bool is_lambda_ignored_entity (tree); diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c index 17fd0377eb9..d4030e332e7 100644 --- a/gcc/cp/lambda.c +++ b/gcc/cp/lambda.c @@ -777,6 +777,17 @@ maybe_resolve_dummy (tree object, bool add_capture_p) return object; } +/* Returns the innermost non-lambda function. */ + +tree +current_nonlambda_function (void) +{ + tree fn = current_function_decl; + while (fn && LAMBDA_FUNCTION_P (fn)) + fn = decl_function_context (fn); + return fn; +} + /* Returns the method basetype of the innermost non-lambda function, or NULL_TREE if none. */ diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 0e675a3a3f2..26e66f512cf 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2438,7 +2438,7 @@ finish_increment_expr (tree expr, enum tree_code code) tree finish_this_expr (void) { - tree result; + tree result = NULL_TREE; if (current_class_ptr) { @@ -2450,25 +2450,19 @@ finish_this_expr (void) else result = current_class_ptr; } - else if (current_function_decl - && DECL_STATIC_FUNCTION_P (current_function_decl)) - { - error ("% is unavailable for static member functions"); - result = error_mark_node; - } - else - { - if (current_function_decl) - error ("invalid use of % in non-member function"); - else - error ("invalid use of % at top level"); - result = error_mark_node; - } - /* The keyword 'this' is a prvalue expression. */ - result = rvalue (result); + if (result) + /* The keyword 'this' is a prvalue expression. */ + return rvalue (result); - return result; + tree fn = current_nonlambda_function (); + if (fn && DECL_STATIC_FUNCTION_P (fn)) + error ("% is unavailable for static member functions"); + else if (fn) + error ("invalid use of % in non-member function"); + else + error ("invalid use of % at top level"); + return error_mark_node; } /* Finish a pseudo-destructor expression. If SCOPE is NULL, the diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this20.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this20.C new file mode 100644 index 00000000000..0d273202bfb --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this20.C @@ -0,0 +1,4 @@ +// PR c++/63601 +// { dg-do compile { target c++11 } } + +auto f = []{ sizeof(this); }; // { dg-error "this" } -- 2.30.2