public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* C++ PATCH for c++/49554 (bogus error with lambda in template)
@ 2011-06-29 17:36 Jason Merrill
  2011-06-29 21:41 ` Jason Merrill
  0 siblings, 1 reply; 2+ messages in thread
From: Jason Merrill @ 2011-06-29 17:36 UTC (permalink / raw)
  To: gcc-patches List

[-- Attachment #1: Type: text/plain, Size: 406 bytes --]

The failure in this testcase was happening because we were trying to 
evaluate the capture decltype again when instantiating the lambda 
operator(), but it only works when we're still in the enclosing function 
context.  Fixed by basically waiting to copy the type over at 
instantiation time rather than copy the dependent type at template 
definition time.

Tested x86_64-pc-linux-gnu, applied to trunk.

[-- Attachment #2: 49554.patch --]
[-- Type: text/x-patch, Size: 4622 bytes --]

commit 7493431b3a7c540254aa92cd0e8ea873eace94f8
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Jun 29 11:55:58 2011 -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.

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 7244cc8..55c88e3 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index b3dd85f..d1d8336 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -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);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 4581729..fb984d4 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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;
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
index 0000000..fd6f1d3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template3.C
@@ -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();
+}

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: C++ PATCH for c++/49554 (bogus error with lambda in template)
  2011-06-29 17:36 C++ PATCH for c++/49554 (bogus error with lambda in template) Jason Merrill
@ 2011-06-29 21:41 ` Jason Merrill
  0 siblings, 0 replies; 2+ messages in thread
From: Jason Merrill @ 2011-06-29 21:41 UTC (permalink / raw)
  To: gcc-patches List

[-- Attachment #1: Type: text/plain, Size: 159 bytes --]

While looking at this issue, I also noticed that we were substituting 
into DECL_INITIAL more than we need to.

Tested x86_64-pc-linux-gnu, applying to trunk.

[-- Attachment #2: tsubst-uneval.patch --]
[-- Type: text/x-patch, Size: 1035 bytes --]

commit 327bbebe3243b0423932862d3d12f92928853e9c
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Jun 29 14:21:17 2011 -0400

    	* pt.c (tsubst_decl) [VAR_DECL]: In unevaluated operand,
    	don't tsubst DECL_INITIAL unless our type use auto.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index d1d8336..dc6cd50 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -10138,12 +10138,11 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
 	       scope, such as for a lambda return type.  Don't add it to
 	       local_specializations, do perform auto deduction.  */
 	    tree auto_node = type_uses_auto (type);
-	    tree init
-	      = tsubst_expr (DECL_INITIAL (t), args, complain, in_decl,
-			     /*constant_expression_p=*/false);
-
-	    if (auto_node && init)
+	    if (auto_node)
 	      {
+		tree init
+		  = tsubst_expr (DECL_INITIAL (t), args, complain, in_decl,
+				 /*constant_expression_p=*/false);
 		init = resolve_nondeduced_context (init);
 		TREE_TYPE (r) = type
 		  = do_auto_deduction (type, init, auto_node);

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2011-06-29 21:16 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-06-29 17:36 C++ PATCH for c++/49554 (bogus error with lambda in template) Jason Merrill
2011-06-29 21:41 ` Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).