diff options
author | Jason Merrill <jason@redhat.com> | 2014-10-20 13:29:02 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2014-10-20 13:29:02 -0400 |
commit | 2bf492a1a4526f143064e41001f34fc1874feea7 (patch) | |
tree | d36f2c6f7a0499a4eebd7a3cca9991eda2ffdf69 /gcc | |
parent | 64dbfdec39c675bd644748af3cd712418bd11135 (diff) | |
download | gcc-2bf492a1a4526f143064e41001f34fc1874feea7.zip gcc-2bf492a1a4526f143064e41001f34fc1874feea7.tar.gz gcc-2bf492a1a4526f143064e41001f34fc1874feea7.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
-rw-r--r-- | gcc/cp/lambda.c | 11 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 30 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this20.C | 4 |
5 files changed, 35 insertions, 18 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1148e95..e61ae2b 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2014-10-20 Jason Merrill <jason@redhat.com> + + 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 <amodra@gmail.com> PR middle-end/61848 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index b6afc31..0923d9f 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 17fd037..d4030e3 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 0e675a3..26e66f5 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 ("%<this%> is unavailable for static member functions"); - result = error_mark_node; - } - else - { - if (current_function_decl) - error ("invalid use of %<this%> in non-member function"); - else - error ("invalid use of %<this%> 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 ("%<this%> is unavailable for static member functions"); + else if (fn) + error ("invalid use of %<this%> in non-member function"); + else + error ("invalid use of %<this%> 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 0000000..0d27320 --- /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" } |