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 to type_decays_to and lambda in decltype


lambda return deduction uses type_decays_to, and I noticed that said function doesn't completely model the lvalue-to-rvalue conversion: we need to drop cv-quals from non-class types. While trying to write a test for this, I noticed that we weren't properly rejecting lambdas in unevaluated context. Since lambdas can't appear in decltype I don't think it's actually possible to detect the difference in return type deduction in a conforming program, but it's still more correct.

Tested x86_64-unknown-linux-gnu, applied to trunk.
commit 680455311467f57328f239863e3d833972a6e9bc
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Apr 12 16:02:49 2010 -0400

	* call.c (type_decays_to): Call cv_unqualified for non-class type.
    	* parser.c (cp_parser_lambda_expression): Complain about lambda in
    	unevaluated context.
    	* pt.c (iterative_hash_template_arg): Don't crash on lambda.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 5a32b3b..90f84e0 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -2263,6 +2263,8 @@ type_decays_to (tree type)
     return build_pointer_type (TREE_TYPE (type));
   if (TREE_CODE (type) == FUNCTION_TYPE)
     return build_pointer_type (type);
+  if (!MAYBE_CLASS_TYPE_P (type))
+    type = cv_unqualified (type);
   return type;
 }
 
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index e25c280..e41a6d7 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -7081,6 +7081,10 @@ cp_parser_lambda_expression (cp_parser* parser)
   LAMBDA_EXPR_LOCATION (lambda_expr)
     = cp_lexer_peek_token (parser->lexer)->location;
 
+  if (cp_unevaluated_operand)
+    error_at (LAMBDA_EXPR_LOCATION (lambda_expr),
+	      "lambda-expression in unevaluated context");
+
   /* We may be in the middle of deferred access check.  Disable
      it now.  */
   push_deferring_access_checks (dk_no_deferred);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 367608f..29489b6 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -1563,6 +1563,12 @@ iterative_hash_template_arg (tree arg, hashval_t val)
       val = iterative_hash_template_arg (TREE_TYPE (arg), val);
       return iterative_hash_template_arg (TYPE_DOMAIN (arg), val);
 
+    case LAMBDA_EXPR:
+      /* A lambda can't appear in a template arg, but don't crash on
+	 erroneous input.  */
+      gcc_assert (errorcount > 0);
+      return val;
+
     default:
       switch (tclass)
 	{
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-uneval.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-uneval.C
new file mode 100644
index 0000000..33ba7b0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-uneval.C
@@ -0,0 +1,7 @@
+// 5.1.2/2: A lambda-expression shall not appear in an unevaluated operand.
+// { dg-options "-std=c++0x" }
+
+template <class T>
+struct A { };
+A<decltype([]{ return 1; }())> a; // { dg-error "lambda.*unevaluated context" }
+

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