This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH for c++/63601 (lambda, 'this' outside class)


finish_this_expr needs to be prepared for lambda_expr_this_capture to return NULL_TREE.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit c631290819f1ab3754041c46d351745953fb8319
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Oct 20 09:56:35 2014 -0400

    	PR c++/63601
    	* lambda.c (current_nonlambda_function): New.
    	* semantics.c (finish_this_expr): Use it.
    	* cp-tree.h: Declare it.

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;
-    }
+
+  if (result)
+    /* The keyword 'this' is a prvalue expression.  */
+    return rvalue (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
-    {
-      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);
-
-  return result;
+    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" }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]