Patchwork C++ PATCH for c++/54947 (wrong error with lambda in init-list)

login
register
mail settings
Submitter Jason Merrill
Date Dec. 6, 2012, 2:36 p.m.
Message ID <50C0AD60.5050301@redhat.com>
Download mbox | patch
Permalink /patch/204251/
State New
Headers show

Comments

Jason Merrill - Dec. 6, 2012, 2:36 p.m.
When we're parsing tentatively, we shouldn't do something, like 
requiring a constant-expression, that will produce an error.  This patch 
delays checking whether the expression is constant until we know that 
we're actually looking at a designator.

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

Patch

commit 77da076687dac5f406f4e929497a8b7b747d287a
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Dec 5 17:47:52 2012 -0500

    	PR c++/54947
    	* parser.c (cp_parser_initializer_list): Don't require an
    	expression in [] to be constant until we know it's a C99
    	designator.

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 190b8d9..a010f1f 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -17923,11 +17923,14 @@  cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p)
 	  /* In C++11, [ could start a lambda-introducer.  */
 	  cp_parser_parse_tentatively (parser);
 	  cp_lexer_consume_token (parser->lexer);
-	  designator = cp_parser_constant_expression (parser, false, NULL);
+	  bool non_const = false;
+	  designator = cp_parser_constant_expression (parser, true, &non_const);
 	  cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
 	  cp_parser_require (parser, CPP_EQ, RT_EQ);
 	  if (!cp_parser_parse_definitely (parser))
 	    designator = NULL_TREE;
+	  else if (non_const)
+	    require_potential_rvalue_constant_expression (designator);
 	}
       else
 	designator = NULL_TREE;
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-initlist2.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-initlist2.C
new file mode 100644
index 0000000..daaa339
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-initlist2.C
@@ -0,0 +1,27 @@ 
+// PR c++/54947
+// { dg-options -std=gnu++11 }
+
+struct X
+{
+  template<typename L>
+    X(L)
+    { }
+};
+
+template<typename A>
+  void
+  test()
+  {
+    int i = 0;
+
+    A a_ok_1( [=] { return i; } );  // OK
+    A a_ok_2( [i] { return i; } );  // OK
+
+    A a_err_1{ [i] { return i; } };  // error
+    A a_err_2{ [=] { return i; } };  // error
+  }
+
+int main()
+{
+  test<X>();
+}