re PR c++/49554 ([C++0x] lambda capture causes "cannot call member function ... witho...
authorJason Merrill <jason@redhat.com>
Wed, 29 Jun 2011 17:15:06 +0000 (13:15 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 29 Jun 2011 17:15:06 +0000 (13:15 -0400)
PR c++/49554
* semantics.c (lambda_proxy_type): New.
(build_capture_proxy): Use it.
* cp-tree.h (DECLTYPE_FOR_LAMBDA_PROXY): New.
* pt.c (tsubst) [DECLTYPE_TYPE]: Use them.

From-SVN: r175657

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template3.C [new file with mode: 0644]

index db0478a6285f5b9d511a6a267950dea4a2447bc5..083d5459662559e91a01e9ce9d3f53200d61f8c2 100644 (file)
@@ -1,5 +1,11 @@
 2011-06-29  Jason Merrill  <jason@redhat.com>
 
+       PR c++/49554
+       * semantics.c (lambda_proxy_type): New.
+       (build_capture_proxy): Use it.
+       * cp-tree.h (DECLTYPE_FOR_LAMBDA_PROXY): New.
+       * pt.c (tsubst) [DECLTYPE_TYPE]: Use them.
+
        PR c++/45923
        * class.c (explain_non_literal_class): New.
        (finalize_literal_type_property): Call it.
index 7244cc88d4a1480a200dc231608472d0be8036e5..55c88e384821af0afea98dc1ddb7993c7ea3149e 100644 (file)
@@ -3418,11 +3418,13 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
 
 /* These flags indicate that we want different semantics from normal
    decltype: lambda capture just drops references, lambda return also does
-   type decay.  */
+   type decay, lambda proxies look through implicit dereference.  */
 #define DECLTYPE_FOR_LAMBDA_CAPTURE(NODE) \
   TREE_LANG_FLAG_0 (DECLTYPE_TYPE_CHECK (NODE))
 #define DECLTYPE_FOR_LAMBDA_RETURN(NODE) \
   TREE_LANG_FLAG_1 (DECLTYPE_TYPE_CHECK (NODE))
+#define DECLTYPE_FOR_LAMBDA_PROXY(NODE) \
+  TREE_LANG_FLAG_2 (DECLTYPE_TYPE_CHECK (NODE))
 
 /* Nonzero for VAR_DECL and FUNCTION_DECL node means that `extern' was
    specified in its declaration.  This can also be set for an
@@ -5455,6 +5457,7 @@ extern tree build_lambda_object                   (tree);
 extern tree begin_lambda_type                   (tree);
 extern tree lambda_capture_field_type          (tree);
 extern tree lambda_return_type                 (tree);
+extern tree lambda_proxy_type                  (tree);
 extern tree lambda_function                    (tree);
 extern void apply_lambda_return_type            (tree, tree);
 extern tree add_capture                         (tree, tree, tree, bool, bool);
index b3dd85f04a75f0b5dc4862e04bc6bfba3e722764..d1d8336b1bd747d52c1721b1d7ca41ca0a8b9d70 100644 (file)
@@ -11108,6 +11108,8 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
          type = lambda_capture_field_type (type);
        else if (DECLTYPE_FOR_LAMBDA_RETURN (t))
          type = lambda_return_type (type);
+       else if (DECLTYPE_FOR_LAMBDA_PROXY (t))
+         type = lambda_proxy_type (type);
        else
          type = finish_decltype_type
            (type, DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t), complain);
index 458172980b421bd13a8ce65ea72ff488fba6ac59..fb984d4799a5dbe4e224e657b626e541d5657a73 100644 (file)
@@ -8489,6 +8489,27 @@ insert_pending_capture_proxies (void)
   LAMBDA_EXPR_PENDING_PROXIES (lam) = NULL;
 }
 
+/* Given REF, a COMPONENT_REF designating a field in the lambda closure,
+   return the type we want the proxy to have: the type of the field itself,
+   with added const-qualification if the lambda isn't mutable and the
+   capture is by value.  */
+
+tree
+lambda_proxy_type (tree ref)
+{
+  tree type;
+  if (REFERENCE_REF_P (ref))
+    ref = TREE_OPERAND (ref, 0);
+  type = TREE_TYPE (ref);
+  if (!dependent_type_p (type))
+    return type;
+  type = cxx_make_type (DECLTYPE_TYPE);
+  DECLTYPE_TYPE_EXPR (type) = ref;
+  DECLTYPE_FOR_LAMBDA_PROXY (type) = true;
+  SET_TYPE_STRUCTURAL_EQUALITY (type);
+  return type;
+}
+
 /* MEMBER is a capture field in a lambda closure class.  Now that we're
    inside the operator(), build a placeholder var for future lookups and
    debugging.  */
@@ -8496,7 +8517,7 @@ insert_pending_capture_proxies (void)
 tree
 build_capture_proxy (tree member)
 {
-  tree var, object, fn, closure, name, lam;
+  tree var, object, fn, closure, name, lam, type;
 
   closure = DECL_CONTEXT (member);
   fn = lambda_function (closure);
@@ -8511,7 +8532,8 @@ build_capture_proxy (tree member)
   /* Remove the __ inserted by add_capture.  */
   name = get_identifier (IDENTIFIER_POINTER (DECL_NAME (member)) + 2);
 
-  var = build_decl (input_location, VAR_DECL, name, TREE_TYPE (object));
+  type = lambda_proxy_type (object);
+  var = build_decl (input_location, VAR_DECL, name, type);
   SET_DECL_VALUE_EXPR (var, object);
   DECL_HAS_VALUE_EXPR_P (var) = 1;
   DECL_ARTIFICIAL (var) = 1;
index d30d8b053c2fa243c33a677d9debcbd2a3d4dd82..522c41cac6bdb03e37e59a5118b94151d9dd3749 100644 (file)
@@ -1,5 +1,7 @@
 2011-06-29  Jason Merrill  <jason@redhat.com>
 
+       * g++.dg/cpp0x/lambda/lambda-template3.C: New.
+
        PR c++/45923
        * g++.dg/cpp0x/constexpr-diag3.C: New.
        * g++.dg/cpp0x/constexpr-diag1.C: Adjust error message.
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template3.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template3.C
new file mode 100644 (file)
index 0000000..fd6f1d3
--- /dev/null
@@ -0,0 +1,33 @@
+// PR c++/49554
+// { dg-options -std=c++0x }
+
+template<typename T>
+  struct base
+  {
+    struct iterator { };
+
+    iterator begin();
+  };
+
+template<typename T>
+class flist : public base<T>
+{
+  typedef base<T> Base;
+
+  typedef typename Base::iterator Base_iterator;
+public:
+
+  void
+  resize()
+  {
+    Base_iterator b = Base::begin();
+
+    [b](int i) { return i; };
+  }
+};
+
+void test01()
+{
+  flist<int> fl;
+  fl.resize();
+}