Hi,

I had a look to this rather old PR, which doesn't seem particularly high-priority, to be honest. It's about the error message we produce for things like:

int main()
{
int* p = new foo;
}

where, besides the obvious error message about foo, we also print:

39681.C:3:16: error: expected ‘,’ or ‘;’ before ‘foo’

which seems redundant and boring. The first thing I noticed is that in cp_parser_new_type_id, at variance with cp_parser_type_id, when cp_parser_type_specifier_seq sets error_mark_node as type_specifier_seq.type we don't notice. If change it to also return error_mark_node we have a chance to do something in the immediate callers. That would allow to avoid the above error message. However, I noticed that I could do the check a couple of levels above, that is in cp_parser_init_declarator and cp_parser_late_parse_one_default_arg, and this allows to catch more redundant error messages about expected semicolons (see the ext and c-c++-common testcases below, I like that *a lot* ;): it's just matter of skipping to the end of the statement. I'm not 100% sure about many details of this, eg, whether the diagnostics could somehow regress in some particular situations. But the patch boots and tests fine (the cp_parser_late_parse_one_default_arg bits take care of the C++11 NSDMI case, for example, see error8.C).

Finally, as a last remark, the PR also talks about "expected type-specifier before ‘foo’" not being an optimal error message, or at least not being clear enough. Well, ICC prints something quite similar in this case and related ones (only talks about type instead of type-specifier, less technical). All in all I'm not convinced we should change cp_parser_type_specifier_seq to print something else, but I think it would be just an additional tweak.

Thanks,
Paolo.

/////////////////////////
/cp

        PR c++/39681
        * parser.c (cp_parser_new_type_id): Early return error_mark_node
        if the cp_parser_type_specifier_seq call has type_specifier_seq.type
        error_mark_node; tidy.
        (cp_parser_new_expression): Always initialize nelts to NULL_TREE to
        avoid uninitialized warnings.
        (cp_parser_init_declarator, cp_parser_late_parse_one_default_arg):
        Call cp_parser_skip_to_end_of_statement if cp_parser_initializer
        returns error_mark_node.

/testsuite

        PR c++/39681
        * g++.dg/parse/error48.C: New.
        * g++.dg/cpp0x/error8.C: Likewise.
        * g++.dg/ext/utf-cxx98.C: Adjust dg-error directive.
        * g++.dg/ext/utf-dflt2.C: Likewise.
        * g++.dg/ext/utf-gnuxx98.C: Likewise.
        * g++.dg/ext/utf-dflt.C: Likewise.
        * c-c++-common/raw-string-3.c: Likewise.
        * c-c++-common/raw-string-4.c: Likewise.

Index: testsuite/g++.dg/ext/utf-cxx98.C
===================================================================
--- testsuite/g++.dg/ext/utf-cxx98.C    (revision 187435)
+++ testsuite/g++.dg/ext/utf-cxx98.C    (working copy)
@@ -8,9 +8,7 @@ const static char16_t   c0      = 'a';  /* { dg-error "not
 const static char32_t  c1      = 'a';  /* { dg-error "not name a type" } */
 
 const unsigned short   c2      = u'a'; /* { dg-error "not declared" } */
-       /* { dg-error "expected ',' or ';'" "" { target *-*-* } 10 } */
 const unsigned long    c3      = U'a'; /* { dg-error "not declared" } */
-       /* { dg-error "expected ',' or ';'" "" { target *-*-* } 12 } */
 
 #define u      1 +
 #define U      2 +
Index: testsuite/g++.dg/ext/utf-dflt2.C
===================================================================
--- testsuite/g++.dg/ext/utf-dflt2.C    (revision 187435)
+++ testsuite/g++.dg/ext/utf-dflt2.C    (working copy)
@@ -3,7 +3,6 @@
 // { dg-options "-std=c++98" }
 
 const void     *s0 = u8"a";            // { dg-error "was not declared" }
-               // { dg-error "expected ',' or ';'" "" { target *-*-* } 5 }
 
 #define u8     "a"
 
Index: testsuite/g++.dg/ext/utf-gnuxx98.C
===================================================================
--- testsuite/g++.dg/ext/utf-gnuxx98.C  (revision 187435)
+++ testsuite/g++.dg/ext/utf-gnuxx98.C  (working copy)
@@ -8,9 +8,7 @@ const static char16_t   c0      = 'a';  /* { dg-error "not
 const static char32_t  c1      = 'a';  /* { dg-error "not name a type" } */
 
 const unsigned short   c2      = u'a'; /* { dg-error "not declared" } */
-       /* { dg-error "expected ',' or ';'" "" { target *-*-* } 10 } */
 const unsigned long    c3      = U'a'; /* { dg-error "not declared" } */
-       /* { dg-error "expected ',' or ';'" "" { target *-*-* } 12 } */
 
 #define u      1 +
 #define U      2 +
Index: testsuite/g++.dg/ext/utf-dflt.C
===================================================================
--- testsuite/g++.dg/ext/utf-dflt.C     (revision 187435)
+++ testsuite/g++.dg/ext/utf-dflt.C     (working copy)
@@ -8,9 +8,7 @@ const static char16_t   c0      = 'a';  /* { dg-error "not
 const static char32_t  c1      = 'a';  /* { dg-error "not name a type" } */
 
 const unsigned short   c2      = u'a'; /* { dg-error "not declared" } */
-       /* { dg-error "expected ',' or ';'" "" { target *-*-* } 10 } */
 const unsigned long    c3      = U'a'; /* { dg-error "not declared" } */
-       /* { dg-error "expected ',' or ';'" "" { target *-*-* } 12 } */
 
 #define u      1 +
 #define U      2 +
Index: testsuite/g++.dg/parse/error48.C
===================================================================
--- testsuite/g++.dg/parse/error48.C    (revision 0)
+++ testsuite/g++.dg/parse/error48.C    (revision 0)
@@ -0,0 +1,6 @@
+// PR c++/39681
+
+int main()
+{
+  int* p = new foo; // { dg-error "16:expected type-specifier" }
+}
Index: testsuite/g++.dg/cpp0x/error8.C
===================================================================
--- testsuite/g++.dg/cpp0x/error8.C     (revision 0)
+++ testsuite/g++.dg/cpp0x/error8.C     (revision 0)
@@ -0,0 +1,7 @@
+// PR c++/39681
+// { dg-do compile { target c++11 } }
+
+struct A
+{
+  int* p = new foo; // { dg-error "16:expected type-specifier" }
+};
Index: testsuite/c-c++-common/raw-string-3.c
===================================================================
--- testsuite/c-c++-common/raw-string-3.c       (revision 187435)
+++ testsuite/c-c++-common/raw-string-3.c       (working copy)
@@ -5,26 +5,26 @@
 // { dg-options "-std=c++98" { target c++ } }
 
 const void     *s0     = R"(a)";       // { dg-error "was not 
declared|undeclared" }
-               // { dg-error "expected ',' or ';'" "" { target *-*-* } 7 }
+                // { dg-error "expected ',' or ';'" "" { target c } 7 }
 const void     *s1     = uR"(a)";      // { dg-error "was not 
declared|undeclared" }
-               // { dg-error "expected ',' or ';'" "" { target *-*-* } 9 }
+                // { dg-error "expected ',' or ';'" "" { target c } 9 }
 const void     *s2     = UR"(a)";      // { dg-error "was not 
declared|undeclared" }
-               // { dg-error "expected ',' or ';'" "" { target *-*-* } 11 }
+                // { dg-error "expected ',' or ';'" "" { target c } 11 }
 const void     *s3     = u8R"(a)";     // { dg-error "was not 
declared|undeclared" }
-               // { dg-error "expected ',' or ';'" "" { target *-*-* } 13 }
+                // { dg-error "expected ',' or ';'" "" { target c } 13 }
 const void     *s4     = LR"(a)";      // { dg-error "was not 
declared|undeclared" }
-               // { dg-error "expected ',' or ';'" "" { target *-*-* } 15 }
+                // { dg-error "expected ',' or ';'" "" { target c } 15 }
 
-const int      i0      = R'a';         // { dg-error "expected ',' or ';'" }
-               // { dg-error "was not declared" "" { target c++ } 18 }
-const int      i1      = uR'a';        // { dg-error "expected ',' or ';'" }
-               // { dg-error "was not declared" "" { target c++ } 20 }
-const int      i2      = UR'a';        // { dg-error "expected ',' or ';'" }
-               // { dg-error "was not declared" "" { target c++ } 22 }
-const int      i3      = u8R'a';       // { dg-error "expected ',' or ';'" }
-               // { dg-error "was not declared" "" { target c++ } 24 }
-const int      i4      = LR'a';        // { dg-error "expected ',' or ';'" }
-               // { dg-error "was not declared" "" { target c++ } 26 }
+const int      i0      = R'a';         // { dg-error "was not declared" "" { 
target c++ } }
+                // { dg-error "expected ',' or ';'" "" { target c } 18 }
+const int      i1      = uR'a';        // { dg-error "was not declared" "" { 
target c++ } }
+                // { dg-error "expected ',' or ';'" "" { target c } 20 }
+const int      i2      = UR'a';        // { dg-error "was not declared" "" { 
target c++ } }
+                // { dg-error "expected ',' or ';'" "" { target c } 22 }
+const int      i3      = u8R'a';       // { dg-error "was not declared" "" { 
target c++ } }
+                // { dg-error "expected ',' or ';'" "" { target c } 24 }
+const int      i4      = LR'a';        // { dg-error "was not declared" "" { 
target c++ } }
+                // { dg-error "expected ',' or ';'" "" { target c } 26 }
 
 #define R      "a"
 #define uR     "b"
Index: testsuite/c-c++-common/raw-string-4.c
===================================================================
--- testsuite/c-c++-common/raw-string-4.c       (revision 187435)
+++ testsuite/c-c++-common/raw-string-4.c       (working copy)
@@ -4,15 +4,15 @@
 // { dg-options "-std=c++0x" { target c++ } }
 
 const int      i0      = R'a'; // { dg-error "was not declared|undeclared" }
-               // { dg-error "expected ',' or ';'" "" { target *-*-* } 6 }
+               // { dg-error "expected ',' or ';'" "" { target c } 6 }
 const int      i1      = uR'a';        // { dg-error "was not 
declared|undeclared" }
-               // { dg-error "expected ',' or ';'" "" { target *-*-* } 8 }
+               // { dg-error "expected ',' or ';'" "" { target c } 8 }
 const int      i2      = UR'a';        // { dg-error "was not 
declared|undeclared" }
-               // { dg-error "expected ',' or ';'" "" { target *-*-* } 10 }
+               // { dg-error "expected ',' or ';'" "" { target c } 10 }
 const int      i3      = u8R'a';       // { dg-error "was not 
declared|undeclared" }
-               // { dg-error "expected ',' or ';'" "" { target *-*-* } 12 }
+               // { dg-error "expected ',' or ';'" "" { target c } 12 }
 const int      i4      = LR'a';        // { dg-error "was not 
declared|undeclared" }
-               // { dg-error "expected ',' or ';'" "" { target *-*-* } 14 }
+               // { dg-error "expected ',' or ';'" "" { target c } 14 }
 
 #define R      1 +
 #define uR     2 +
Index: cp/parser.c
===================================================================
--- cp/parser.c (revision 187435)
+++ cp/parser.c (working copy)
@@ -6657,7 +6657,7 @@ cp_parser_new_expression (cp_parser* parser)
   VEC(tree,gc) *placement;
   tree type;
   VEC(tree,gc) *initializer;
-  tree nelts;
+  tree nelts = NULL_TREE;
   tree ret;
 
   /* Look for the optional `::' operator.  */
@@ -6710,7 +6710,6 @@ cp_parser_new_expression (cp_parser* parser)
                  "try removing the parentheses around the type-id");
          cp_parser_direct_new_declarator (parser);
        }
-      nelts = NULL_TREE;
     }
   /* Otherwise, there must be a new-type-id.  */
   else
@@ -6780,7 +6779,6 @@ cp_parser_new_type_id (cp_parser* parser, tree *ne
   cp_declarator *declarator;
   cp_declarator *outer_declarator;
   const char *saved_message;
-  tree type;
 
   /* The type-specifier sequence must not contain type definitions.
      (It cannot contain declarations of new types either, but if they
@@ -6795,6 +6793,10 @@ cp_parser_new_type_id (cp_parser* parser, tree *ne
                                &type_specifier_seq);
   /* Restore the old message.  */
   parser->type_definition_forbidden_message = saved_message;
+
+  if (type_specifier_seq.type == error_mark_node)
+    return error_mark_node;
+
   /* Parse the new-declarator.  */
   new_declarator = cp_parser_new_declarator_opt (parser);
 
@@ -6831,8 +6833,7 @@ cp_parser_new_type_id (cp_parser* parser, tree *ne
        new_declarator = NULL;
     }
 
-  type = groktypename (&type_specifier_seq, new_declarator, false);
-  return type;
+  return groktypename (&type_specifier_seq, new_declarator, false);
 }
 
 /* Parse an (optional) new-declarator.
@@ -15761,6 +15762,8 @@ cp_parser_init_declarator (cp_parser* parser,
                                               &is_non_constant_init);
          if (!member_p && processing_template_decl)
            finish_lambda_scope ();
+         if (initializer == error_mark_node)
+           cp_parser_skip_to_end_of_statement (parser);
        }
     }
 
@@ -21777,6 +21780,9 @@ cp_parser_late_parse_one_default_arg (cp_parser *p
 
   finish_lambda_scope ();
 
+  if (parsed_arg == error_mark_node)
+    cp_parser_skip_to_end_of_statement (parser);
+
   if (!processing_template_decl)
     {
       /* In a non-template class, check conversions now.  In a template,

Reply via email to