]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/cp/parser.c
re PR c++/19894 (pointer-to-void member not rejected in template)
[thirdparty/gcc.git] / gcc / cp / parser.c
index 7f39c91a95a1e7af4fd16b42d125107caaae78a5..cb389d24afe9a6112c27b8535da8d85ba8ad108d 100644 (file)
@@ -4121,10 +4121,34 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
          /* postfix-expression ( expression-list [opt] ) */
          {
            bool koenig_p;
-           tree args = (cp_parser_parenthesized_expression_list
-                        (parser, false, 
-                         /*cast_p=*/false,
-                         /*non_constant_p=*/NULL));
+           bool is_builtin_constant_p;
+           bool saved_integral_constant_expression_p = false;
+           bool saved_non_integral_constant_expression_p = false;
+           tree args;
+
+           is_builtin_constant_p 
+             = DECL_IS_BUILTIN_CONSTANT_P (postfix_expression);
+           if (is_builtin_constant_p)
+             {
+               /* The whole point of __builtin_constant_p is to allow
+                  non-constant expressions to appear as arguments.  */
+               saved_integral_constant_expression_p
+                 = parser->integral_constant_expression_p;
+               saved_non_integral_constant_expression_p
+                 = parser->non_integral_constant_expression_p;
+               parser->integral_constant_expression_p = false;
+             }
+           args = (cp_parser_parenthesized_expression_list
+                   (parser, /*is_attribute_list=*/false, 
+                    /*cast_p=*/false,
+                    /*non_constant_p=*/NULL));
+           if (is_builtin_constant_p)
+             {
+               parser->integral_constant_expression_p
+                 = saved_integral_constant_expression_p;
+               parser->non_integral_constant_expression_p
+                 = saved_non_integral_constant_expression_p;
+             }
 
            if (args == error_mark_node)
              {
@@ -4873,7 +4897,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p)
          non_constant_p = (unary_operator == PREINCREMENT_EXPR
                            ? "`++'" : "`--'");
          /* Fall through.  */
-       case CONVERT_EXPR:
+       case UNARY_PLUS_EXPR:
        case NEGATE_EXPR:
        case TRUTH_NOT_EXPR:
          expression = finish_unary_op_expr (unary_operator, cast_expression);
@@ -4909,7 +4933,7 @@ cp_parser_unary_operator (cp_token* token)
       return ADDR_EXPR;
 
     case CPP_PLUS:
-      return CONVERT_EXPR;
+      return UNARY_PLUS_EXPR;
 
     case CPP_MINUS:
       return NEGATE_EXPR;
@@ -12121,7 +12145,8 @@ cp_parser_parameter_declaration (cp_parser *parser,
              argument.  */
          default_argument = make_node (DEFAULT_ARG);
          DEFARG_TOKENS (default_argument)
-           = cp_token_cache_new (first_token, token);  
+           = cp_token_cache_new (first_token, token);
+         DEFARG_INSTANTIATIONS (default_argument) = NULL;
        }
       /* Outside of a class definition, we can just parse the
          assignment-expression.  */
@@ -14367,7 +14392,10 @@ cp_parser_label_declaration (cp_parser* parser)
 
       /* Look for an identifier.  */
       identifier = cp_parser_identifier (parser);
-      /* Declare it as a lobel.  */
+      /* If we failed, stop.  */
+      if (identifier == error_mark_node)
+       break;
+      /* Declare it as a label.  */
       finish_label_decl (identifier);
       /* If the next token is a `;', stop.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
@@ -15569,19 +15597,34 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
        parm = TREE_CHAIN (parm))
     {
       cp_token_cache *tokens;
+      tree default_arg = TREE_PURPOSE (parm);
+      tree parsed_arg;
+      VEC(tree,gc) *insts;
+      tree copy;
+      unsigned ix;
+      
+      if (!default_arg)
+       continue;
 
-      if (!TREE_PURPOSE (parm)
-         || TREE_CODE (TREE_PURPOSE (parm)) != DEFAULT_ARG)
+      if (TREE_CODE (default_arg) != DEFAULT_ARG)
+       /* This can happen for a friend declaration for a function
+          already declared with default arguments.  */
        continue;
 
        /* Push the saved tokens for the default argument onto the parser's
          lexer stack.  */
-      tokens = DEFARG_TOKENS (TREE_PURPOSE (parm));
+      tokens = DEFARG_TOKENS (default_arg);
       cp_parser_push_lexer_for_tokens (parser, tokens);
 
       /* Parse the assignment-expression.  */
-      TREE_PURPOSE (parm) = cp_parser_assignment_expression (parser,
-                                                            /*cast_p=*/false);
+      parsed_arg = cp_parser_assignment_expression (parser, /*cast_p=*/false);
+
+      TREE_PURPOSE (parm) = parsed_arg;
+
+      /* Update any instantiations we've already created.  */
+      for (insts = DEFARG_INSTANTIATIONS (default_arg), ix = 0;
+          VEC_iterate (tree, insts, ix, copy); ix++)
+       TREE_PURPOSE (copy) = parsed_arg;
 
       /* If the token stream has not been completely used up, then
         there was extra junk after the end of the default