On Wed, Jan 17, 2018 at 02:31:29PM -0500, Jason Merrill wrote:
> > First, thanks for your messages. Personally, at this late time for 8, I 
> > vote for something like my most recent grokdeclarator fix and yours above 
> > for 83824. Then, for 9, or even 8.2, the more encompassing change for all 
> > those chainons. Please both of you let me know how shall we proceed, I 
> > could certainly take care of the latter too from now on. Thanks again!
> 
> Let's go ahead with your patch to grokdeclarator.  In the parser,
> let's do what Jakub is suggesting here:
> 
> > So, either we want to go with what Paolo posted even in this case,
> > i.e. turn decl_specs->attributes into error_mark_node if attrs
> > is error_mark_node, and don't chainon anything to it if 
> > decl_specs->attributes
> > is already error_mark_node, e.g. something like:
> > if (attrs == error_mark_node || decl_specs->attributes == error_mark_node)
> >   decl_specs->attributes = error_mark_node;
> > else
> >   decl_specs->attributes = chainon (decl_specs->attributes, attrs);
> 
> without any assert.  Putting this logic in an attr_chainon function sounds 
> good.

So like this?  So far just tested with make check-c++-all on both
x86_64-linux and i686-linux, full bootstrap/regtest scheduled, ok if it
passes?  I gave up on the original idea to return void and have the first
argument pointer, because while many of the calls do x = chainon (x, y);,
there are several ones that assign it to something else, like y = chainon (x, 
y);
etc.

2018-01-17  Jakub Jelinek  <ja...@redhat.com>

        PR c++/83824
        * parser.c (attr_chainon): New function.
        (cp_parser_label_for_labeled_statement, cp_parser_decl_specifier_seq,
        cp_parser_namespace_definition, cp_parser_init_declarator,
        cp_parser_type_specifier_seq, cp_parser_parameter_declaration,
        cp_parser_gnu_attributes_opt): Use it.
        (cp_parser_member_declaration, cp_parser_objc_class_ivars,
        cp_parser_objc_struct_declaration): Likewise.  Don't reset
        prefix_attributes if attributes is error_mark_node.

        * g++.dg/cpp0x/pr83824.C: New test.

--- gcc/cp/parser.c.jj  2018-01-13 17:57:38.115836072 +0100
+++ gcc/cp/parser.c     2018-01-17 20:46:21.809738257 +0100
@@ -10908,6 +10908,18 @@ cp_parser_statement (cp_parser* parser,
                "attributes at the beginning of statement are ignored");
 }
 
+/* Append ATTR to attribute list ATTRS.  */
+
+static tree
+attr_chainon (tree attrs, tree attr)
+{
+  if (attrs == error_mark_node)
+    return error_mark_node;
+  if (attr == error_mark_node)
+    return error_mark_node;
+  return chainon (attrs, attr);
+}
+
 /* Parse the label for a labeled-statement, i.e.
 
    identifier :
@@ -11027,7 +11039,7 @@ cp_parser_label_for_labeled_statement (c
       else if (!cp_parser_parse_definitely (parser))
        ;
       else
-       attributes = chainon (attributes, attrs);
+       attributes = attr_chainon (attributes, attrs);
     }
 
   if (attributes != NULL_TREE)
@@ -13394,8 +13406,7 @@ cp_parser_decl_specifier_seq (cp_parser*
                  else
                    {
                      decl_specs->std_attributes
-                       = chainon (decl_specs->std_attributes,
-                                  attrs);
+                       = attr_chainon (decl_specs->std_attributes, attrs);
                      if (decl_specs->locations[ds_std_attribute] == 0)
                        decl_specs->locations[ds_std_attribute] = 
token->location;
                    }
@@ -13403,9 +13414,8 @@ cp_parser_decl_specifier_seq (cp_parser*
                }
            }
 
-           decl_specs->attributes
-             = chainon (decl_specs->attributes,
-                        attrs);
+         decl_specs->attributes
+           = attr_chainon (decl_specs->attributes, attrs);
          if (decl_specs->locations[ds_attribute] == 0)
            decl_specs->locations[ds_attribute] = token->location;
          continue;
@@ -18471,7 +18481,7 @@ cp_parser_namespace_definition (cp_parse
          identifier = cp_parser_identifier (parser);
 
          /* Parse any attributes specified after the identifier.  */
-         attribs = chainon (attribs, cp_parser_attributes_opt (parser));
+         attribs = attr_chainon (attribs, cp_parser_attributes_opt (parser));
        }
 
       if (cp_lexer_next_token_is_not (parser->lexer, CPP_SCOPE))
@@ -19633,7 +19643,7 @@ cp_parser_init_declarator (cp_parser* pa
       decl = grokfield (declarator, decl_specifiers,
                        initializer, !is_non_constant_init,
                        /*asmspec=*/NULL_TREE,
-                       chainon (attributes, prefix_attributes));
+                       attr_chainon (attributes, prefix_attributes));
       if (decl && TREE_CODE (decl) == FUNCTION_DECL)
        cp_parser_save_default_args (parser, decl);
       cp_finalize_omp_declare_simd (parser, decl);
@@ -21007,9 +21017,9 @@ cp_parser_type_specifier_seq (cp_parser*
       /* Check for attributes first.  */
       if (cp_next_tokens_can_be_attribute_p (parser))
        {
-         type_specifier_seq->attributes =
-           chainon (type_specifier_seq->attributes,
-                    cp_parser_attributes_opt (parser));
+         type_specifier_seq->attributes
+           = attr_chainon (type_specifier_seq->attributes,
+                           cp_parser_attributes_opt (parser));
          continue;
        }
 
@@ -21491,8 +21501,8 @@ cp_parser_parameter_declaration (cp_pars
       parser->default_arg_ok_p = saved_default_arg_ok_p;
       /* After the declarator, allow more attributes.  */
       decl_specifiers.attributes
-       = chainon (decl_specifiers.attributes,
-                  cp_parser_attributes_opt (parser));
+       = attr_chainon (decl_specifiers.attributes,
+                       cp_parser_attributes_opt (parser));
 
       /* If the declarator is a template parameter pack, remember that and
         clear the flag in the declarator itself so we don't get errors
@@ -23653,13 +23663,13 @@ cp_parser_member_declaration (cp_parser*
                  late_attributes = cp_parser_attributes_opt (parser);
                }
 
-             attributes = chainon (attributes, late_attributes);
+             attributes = attr_chainon (attributes, late_attributes);
 
              /* Remember which attributes are prefix attributes and
                 which are not.  */
              first_attribute = attributes;
              /* Combine the attributes.  */
-             attributes = chainon (prefix_attributes, attributes);
+             attributes = attr_chainon (prefix_attributes, attributes);
 
              /* Create the bitfield declaration.  */
              decl = grokbitfield (identifier
@@ -23715,7 +23725,7 @@ cp_parser_member_declaration (cp_parser*
                 which are not.  */
              first_attribute = attributes;
              /* Combine the attributes.  */
-             attributes = chainon (prefix_attributes, attributes);
+             attributes = attr_chainon (prefix_attributes, attributes);
 
              /* If it's an `=', then we have a constant-initializer or a
                 pure-specifier.  It is not correct to parse the
@@ -23837,10 +23847,13 @@ cp_parser_member_declaration (cp_parser*
          cp_finalize_oacc_routine (parser, decl, false);
 
          /* Reset PREFIX_ATTRIBUTES.  */
-         while (attributes && TREE_CHAIN (attributes) != first_attribute)
-           attributes = TREE_CHAIN (attributes);
-         if (attributes)
-           TREE_CHAIN (attributes) = NULL_TREE;
+         if (attributes != error_mark_node)
+           {
+             while (attributes && TREE_CHAIN (attributes) != first_attribute)
+               attributes = TREE_CHAIN (attributes);
+             if (attributes)
+               TREE_CHAIN (attributes) = NULL_TREE;
+           }
 
          /* If there is any qualification still in effect, clear it
             now; we will be starting fresh with the next declarator.  */
@@ -24909,7 +24922,7 @@ cp_parser_gnu_attributes_opt (cp_parser*
        cp_parser_skip_to_end_of_statement (parser);
 
       /* Add these new attributes to the list.  */
-      attributes = chainon (attributes, attribute_list);
+      attributes = attr_chainon (attributes, attribute_list);
     }
 
   return attributes;
@@ -30114,7 +30127,7 @@ cp_parser_objc_class_ivars (cp_parser* p
             which are not.  */
          first_attribute = attributes;
          /* Combine the attributes.  */
-         attributes = chainon (prefix_attributes, attributes);
+         attributes = attr_chainon (prefix_attributes, attributes);
 
          if (width)
            /* Create the bitfield declaration.  */
@@ -30130,10 +30143,13 @@ cp_parser_objc_class_ivars (cp_parser* p
            objc_add_instance_variable (decl);
 
          /* Reset PREFIX_ATTRIBUTES.  */
-         while (attributes && TREE_CHAIN (attributes) != first_attribute)
-           attributes = TREE_CHAIN (attributes);
-         if (attributes)
-           TREE_CHAIN (attributes) = NULL_TREE;
+         if (attributes != error_mark_node)
+           {
+             while (attributes && TREE_CHAIN (attributes) != first_attribute)
+               attributes = TREE_CHAIN (attributes);
+             if (attributes)
+               TREE_CHAIN (attributes) = NULL_TREE;
+           }
 
          token = cp_lexer_peek_token (parser->lexer);
 
@@ -30666,8 +30682,8 @@ cp_parser_objc_struct_declaration (cp_pa
         which are not.  */
       first_attribute = attributes;
       /* Combine the attributes.  */
-      attributes = chainon (prefix_attributes, attributes);
-      
+      attributes = attr_chainon (prefix_attributes, attributes);
+
       decl = grokfield (declarator, &declspecs,
                        NULL_TREE, /*init_const_expr_p=*/false,
                        NULL_TREE, attributes);
@@ -30676,10 +30692,13 @@ cp_parser_objc_struct_declaration (cp_pa
        return error_mark_node;
       
       /* Reset PREFIX_ATTRIBUTES.  */
-      while (attributes && TREE_CHAIN (attributes) != first_attribute)
-       attributes = TREE_CHAIN (attributes);
-      if (attributes)
-       TREE_CHAIN (attributes) = NULL_TREE;
+      if (attributes != error_mark_node)
+       {
+         while (attributes && TREE_CHAIN (attributes) != first_attribute)
+           attributes = TREE_CHAIN (attributes);
+         if (attributes)
+           TREE_CHAIN (attributes) = NULL_TREE;
+       }
 
       DECL_CHAIN (decl) = decls;
       decls = decl;
--- gcc/testsuite/g++.dg/cpp0x/pr83824.C.jj     2018-01-17 20:52:24.224696009 
+0100
+++ gcc/testsuite/g++.dg/cpp0x/pr83824.C        2018-01-17 20:52:03.091698473 
+0100
@@ -0,0 +1,9 @@
+// PR c++/83824
+// { dg-do compile { target c++11 } }
+
+void
+foo ()
+{
+  if (alignas(1 alignas(1)))   // { dg-error "expected" }
+    ;
+}


        Jakub

Reply via email to