re PR c++/65727 (Segfault With Decltype In Lambda Expression Used To Initialize Stati...
authorJason Merrill <jason@redhat.com>
Wed, 15 Apr 2015 21:17:03 +0000 (17:17 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 15 Apr 2015 21:17:03 +0000 (17:17 -0400)
PR c++/65727
* lambda.c (lambda_expr_this_capture): In unevaluated context go
through the normal loop, just don't capture.
(maybe_resolve_dummy): Handle null return.

Co-Authored-By: Marek Polacek <polacek@redhat.com>
From-SVN: r222132

gcc/cp/ChangeLog
gcc/cp/lambda.c
gcc/testsuite/g++.dg/cpp0x/lambda/lambda-decltype2.C [new file with mode: 0644]

index 0302516186e99a566a3683d653ff4746171aaf92..3534fdb8b2d8456487dde7eafcb11e584a33cf1b 100644 (file)
@@ -1,3 +1,11 @@
+2015-04-15  Jason Merrill  <jason@redhat.com>
+           Marek Polacek  <polacek@redhat.com>
+
+       PR c++/65727
+       * lambda.c (lambda_expr_this_capture): In unevaluated context go
+       through the normal loop, just don't capture.
+       (maybe_resolve_dummy): Handle null return.
+
 2015-04-15  Paolo Carlini  <paolo.carlini@oracle.com>
 
        * call.c (enforce_access): Emit error + inform.
index dd1c2d4337a2ee208e693f5f38a36d7d0a9ea102..174700ffa4e22d91bf13f5dab7a6437c564b7926 100644 (file)
@@ -646,7 +646,7 @@ add_default_capture (tree lambda_stack, tree id, tree initializer)
 
 /* Return the capture pertaining to a use of 'this' in LAMBDA, in the
    form of an INDIRECT_REF, possibly adding it through default
-   capturing, if ADD_CAPTURE_P is false.  */
+   capturing, if ADD_CAPTURE_P is true.  */
 
 tree
 lambda_expr_this_capture (tree lambda, bool add_capture_p)
@@ -655,17 +655,9 @@ lambda_expr_this_capture (tree lambda, bool add_capture_p)
 
   tree this_capture = LAMBDA_EXPR_THIS_CAPTURE (lambda);
 
-  /* In unevaluated context this isn't an odr-use, so just return the
-     nearest 'this'.  */
+  /* In unevaluated context this isn't an odr-use, so don't capture.  */
   if (cp_unevaluated_operand)
-    {
-      /* In an NSDMI the fake 'this' pointer that we're using for
-        parsing is in scope_chain.  */
-      if (LAMBDA_EXPR_EXTRA_SCOPE (lambda)
-         && TREE_CODE (LAMBDA_EXPR_EXTRA_SCOPE (lambda)) == FIELD_DECL)
-       return scope_chain->x_current_class_ptr;
-      return lookup_name (this_identifier);
-    }
+    add_capture_p = false;
 
   /* Try to default capture 'this' if we can.  */
   if (!this_capture
@@ -740,11 +732,17 @@ lambda_expr_this_capture (tree lambda, bool add_capture_p)
         }
     }
 
-  if (!this_capture)
+  if (cp_unevaluated_operand)
+    result = this_capture;
+  else if (!this_capture)
     {
       if (add_capture_p)
-       error ("%<this%> was not captured for this lambda function");
-      result = error_mark_node;
+       {
+         error ("%<this%> was not captured for this lambda function");
+         result = error_mark_node;
+       }
+      else
+       result = NULL_TREE;
     }
   else
     {
@@ -787,7 +785,7 @@ maybe_resolve_dummy (tree object, bool add_capture_p)
       /* In a lambda, need to go through 'this' capture.  */
       tree lam = CLASSTYPE_LAMBDA_EXPR (current_class_type);
       tree cap = lambda_expr_this_capture (lam, add_capture_p);
-      if (cap != error_mark_node)
+      if (cap && cap != error_mark_node)
        object = build_x_indirect_ref (EXPR_LOCATION (object), cap,
                                       RO_NULL, tf_warning_or_error);
     }
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-decltype2.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-decltype2.C
new file mode 100644 (file)
index 0000000..51bf0ec
--- /dev/null
@@ -0,0 +1,25 @@
+// PR c++/65727
+// { dg-do compile { target c++11 } }
+
+struct type_a { void(*cb)(); };
+
+struct type_b
+{
+    type_b(type_a p);
+    void dummy();
+};
+
+template<class T>
+constexpr T function_c(T**t) {return **t;}
+
+class type_d {
+    public:
+        static void dummy();
+};
+class type_e {
+    public:
+        static type_b b;
+        type_d *d[1];
+};
+
+type_b type_e::b = {{[](){decltype(function_c(type_e::d))::dummy();}}};