Hi,

in this error recovery issue cp_check_const_attributes and more generally cplus_decl_attributes have lots of troubles handling the error_mark_node returned by cp_parser_std_attribute_spec_seq, as called by cp_parser_direct_declarator. I fiddled quite a bit with these parsing facilities to eventually notice that boldly changing cp_parser_std_attribute_spec_seq to return NULL_TREE instead of error_mark_node when cp_parser_std_attribute_spec returns error_mark_node in the loop cures the bug at issue as a special case.

I also noticed that in cp_parser_std_attribute_spec we are using token_pair::require_open / require_close very peculiarly, issuing a cp_parser_error when the returned bool is false instead of simply bailing out with error_mark_node and that in fact causes duplicate diagnostics about expected '(' / ')', respectively.

Tested x86_64-linux.

Thanks, Paolo.

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


/cp
2017-12-22  Paolo Carlini  <paolo.carl...@oracle.com>

        PR c++/78344
        * parser.c (cp_parser_std_attribute_spec_seq): When
        cp_parser_std_attribute_spec returns error_mark_node return
        back NULL_TREE instead of error_mark_node.

        * parser.c (cp_parser_std_attribute_spec): When
        token_pair::require_open / require_close returns false simply
        return error_mark_node, do not issue a duplicate cp_parser_error
        about expected '(' / ')', respectively.

/testsuite
2017-12-22  Paolo Carlini  <paolo.carl...@oracle.com>

        PR c++/78344
        * g++.dg/cpp0x/alignas13.C: New.
Index: cp/parser.c
===================================================================
--- cp/parser.c (revision 255983)
+++ cp/parser.c (working copy)
@@ -25300,10 +25300,7 @@ cp_parser_std_attribute_spec (cp_parser *parser)
 
       matching_parens parens;
       if (!parens.require_open (parser))
-       {
-         cp_parser_error (parser, "expected %<(%>");
-         return error_mark_node;
-       }
+       return error_mark_node;
 
       cp_parser_parse_tentatively (parser);
       alignas_expr = cp_parser_type_id (parser);
@@ -25333,10 +25330,7 @@ cp_parser_std_attribute_spec (cp_parser *parser)
        return error_mark_node;
 
       if (!parens.require_close (parser))
-       {
-         cp_parser_error (parser, "expected %<)%>");
-         return error_mark_node;
-       }
+       return error_mark_node;
 
       /* Build the C++-11 representation of an 'aligned'
         attribute.  */
@@ -25367,7 +25361,7 @@ cp_parser_std_attribute_spec_seq (cp_parser *parse
       if (attr_spec == NULL_TREE)
        break;
       if (attr_spec == error_mark_node)
-       return error_mark_node;
+       return NULL_TREE;
 
       if (attr_last)
        TREE_CHAIN (attr_last) = attr_spec;
Index: testsuite/g++.dg/cpp0x/alignas13.C
===================================================================
--- testsuite/g++.dg/cpp0x/alignas13.C  (nonexistent)
+++ testsuite/g++.dg/cpp0x/alignas13.C  (working copy)
@@ -0,0 +1,5 @@
+// PR c++/78344
+// { dg-do compile { target c++11 } }
+
+alignas(double) int f alignas;         // { dg-error "30:expected '\\('" }
+alignas(double) int g alignas(double;  // { dg-error "37:expected '\\)'" }

Reply via email to