Hi,

On 06/05/2013 04:19 PM, Jason Merrill wrote:
On 06/05/2013 09:19 AM, Jason Merrill wrote:
In any case, the commit doesn't seem like the problem.

Oh, I see, of course it is. The problem is that it commits to all levels, so that if we happen to be in a nested tentative parse we can't commit to the inner one without committing to the outer one, which might not be appropriate. This seems like a basic flaw in our tentative parsing mechanism.
Uhmmm.
What happens if we disable that commit entirely?
Not a disaster, I'm attaching a breakdown of the regressions. Essentially no accept invalid or reject valid, but in some cases the quality of the diagnostic worsen a lot and/or becomes more verbose.

Now, something else I noticed a few days ago is that for C-style casts things work fine in any case: the difference being that in that case we set parser->in_type_id_in_expr_p to true, something we don't do for static_cast (and the other C++ casts) in cp_parser_postfix_expression. If I do that, then all the testcases we are considering pass with no regressions in the testsuite. Is it something we could do? Patch draft attached.

Thanks,
Paolo.

///////////////////////

FAIL: g++.dg/other/pr39060.C -std=c++98  (test for errors, line 19)
FAIL: g++.dg/other/pr39060.C -std=c++98 (test for excess errors)
FAIL: g++.dg/other/pr39060.C -std=c++11  (test for errors, line 19)
FAIL: g++.dg/other/pr39060.C -std=c++11 (test for excess errors)
FAIL: g++.dg/parse/crash50.C -std=c++98  (test for errors, line 5)
FAIL: g++.dg/parse/crash50.C -std=c++98  (test for errors, line 9)
FAIL: g++.dg/parse/crash50.C -std=c++98 (test for excess errors)
FAIL: g++.dg/parse/crash50.C -std=c++11  (test for errors, line 5)
FAIL: g++.dg/parse/crash50.C -std=c++11  (test for errors, line 9)
FAIL: g++.dg/parse/crash50.C -std=c++11 (test for excess errors)
FAIL: g++.dg/parse/error6.C -std=gnu++98  (test for errors, line 4)
FAIL: g++.dg/parse/error6.C -std=gnu++98  (test for errors, line 5)
FAIL: g++.dg/parse/error6.C -std=gnu++98 (test for excess errors)
FAIL: g++.dg/parse/error6.C -std=gnu++11  (test for errors, line 4)
FAIL: g++.dg/parse/error6.C -std=gnu++11  (test for errors, line 5)
FAIL: g++.dg/parse/error6.C -std=gnu++11 (test for excess errors)
FAIL: g++.dg/parse/error7.C -std=gnu++98  (test for errors, line 5)
FAIL: g++.dg/parse/error7.C -std=gnu++98 (test for excess errors)
FAIL: g++.dg/parse/error7.C -std=gnu++11  (test for errors, line 5)
FAIL: g++.dg/parse/error7.C -std=gnu++11 (test for excess errors)
FAIL: g++.dg/parse/varmod1.C -std=c++98 (test for excess errors)
FAIL: g++.dg/parse/varmod1.C -std=c++11 (test for excess errors)
FAIL: g++.dg/template/crash77.C -std=c++98  (test for errors, line 3)
FAIL: g++.dg/template/crash77.C -std=c++11  (test for errors, line 3)
FAIL: g++.old-deja/g++.brendan/crash61.C -std=c++98 (test for excess errors)
FAIL: g++.old-deja/g++.brendan/crash61.C -std=c++11 (test for excess errors)
Index: cp/parser.c
===================================================================
--- cp/parser.c (revision 199690)
+++ cp/parser.c (working copy)
@@ -5546,6 +5546,7 @@ cp_parser_postfix_expression (cp_parser *parser, b
        tree type;
        tree expression;
        const char *saved_message;
+       bool saved_in_type_id_in_expr_p;
 
        /* All of these can be handled in the same way from the point
           of view of parsing.  Begin by consuming the token
@@ -5560,7 +5561,10 @@ cp_parser_postfix_expression (cp_parser *parser, b
        /* Look for the opening `<'.  */
        cp_parser_require (parser, CPP_LESS, RT_LESS);
        /* Parse the type to which we are casting.  */
+       saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p;
+       parser->in_type_id_in_expr_p = true;
        type = cp_parser_type_id (parser);
+       parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
        /* Look for the closing `>'.  */
        cp_parser_require (parser, CPP_GREATER, RT_GREATER);
        /* Restore the old message.  */
Index: testsuite/g++.dg/cpp0x/decltype54.C
===================================================================
--- testsuite/g++.dg/cpp0x/decltype54.C (revision 0)
+++ testsuite/g++.dg/cpp0x/decltype54.C (working copy)
@@ -0,0 +1,26 @@
+// PR c++/51908
+// { dg-do compile { target c++11 } }
+
+struct foo1
+{
+  template <typename Ret, typename... Args>
+  operator decltype(static_cast<Ret (*)(Args...)>(nullptr)) () const;
+};
+
+struct foo2
+{
+  template <typename Ret, typename... Args>
+  operator decltype(static_cast<Ret (*)(Args... args)>(nullptr)) () const;
+};
+
+struct foo3
+{
+  template <typename Ret, typename Arg>
+  operator decltype(static_cast<Ret (*)(Arg)>(nullptr)) () const;
+};
+
+struct foo4
+{
+  template <typename Ret, typename Arg>
+  operator decltype(static_cast<Ret (*)(Arg arg)>(nullptr)) () const;
+};

Reply via email to