re PR c++/63601 (Segfault on usage of 'this' in unevaluated context inside lambda)
authorJason Merrill <jason@redhat.com>
Mon, 20 Oct 2014 17:29:02 +0000 (13:29 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 20 Oct 2014 17:29:02 +0000 (13:29 -0400)
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
gcc/cp/cp-tree.h
gcc/cp/lambda.c
gcc/cp/semantics.c
gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this20.C [new file with mode: 0644]

index 1148e9566adb464cb7f64d1abb52ef50a1959047..e61ae2bfa8359861e70fcb9fb8240b6a5b69d3fc 100644 (file)
@@ -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
index b6afc311fe04efc21b67803ded67f5033aa361e6..0923d9f0f7cfc2ebc41efb8c92b9e9b929401729 100644 (file)
@@ -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);
index 17fd0377eb9cde7b977c48c1170944007b21d6aa..d4030e332e7e0c179046d934b65b7afd0998c2e7 100644 (file)
@@ -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.  */
 
index 0e675a3a3f231ffba7a2adcfcff9d1b179d57b76..26e66f512cf4bb6e01e606f5bb8660326ebbb081 100644 (file)
@@ -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 (file)
index 0000000..0d27320
--- /dev/null
@@ -0,0 +1,4 @@
+// PR c++/63601
+// { dg-do compile { target c++11 } }
+
+auto f = []{ sizeof(this); };  // { dg-error "this" }