OSDN Git Service

* gcc-interface/Make-lang.in (GNATLIBFLAGS, GNATLIBCFLAGS, THREAD_KIND,
[pf3gnuchains/gcc-fork.git] / gcc / c-parser.c
index 0d2a1b7..af6cc14 100644 (file)
@@ -621,6 +621,7 @@ c_token_starts_declspecs (c_token *token)
        case RID_REGISTER:
        case RID_TYPEDEF:
        case RID_INLINE:
+       case RID_NORETURN:
        case RID_AUTO:
        case RID_THREAD:
        case RID_UNSIGNED:
@@ -1904,6 +1905,9 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
    C99 6.7.4:
    function-specifier:
      inline
+     _Noreturn
+
+   (_Noreturn is new in C1X.)
 
    C90 6.5.2, C99 6.7.2:
    type-specifier:
@@ -2080,12 +2084,13 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
        case RID_REGISTER:
        case RID_TYPEDEF:
        case RID_INLINE:
+       case RID_NORETURN:
        case RID_AUTO:
        case RID_THREAD:
          if (!scspec_ok)
            goto out;
          attrs_ok = true;
-         /* TODO: Distinguish between function specifiers (inline)
+         /* TODO: Distinguish between function specifiers (inline, noreturn)
             and storage class specifiers, either here or in
             declspecs_add_scspec.  */
          declspecs_add_scspec (specs, c_parser_peek_token (parser)->value);
@@ -3154,10 +3159,19 @@ c_parser_parms_list_declarator (c_parser *parser, tree attrs, tree expr)
   if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
     {
       struct c_arg_info *ret = build_arg_info ();
-      /* Suppress -Wold-style-definition for this case.  */
-      ret->types = error_mark_node;
-      error_at (c_parser_peek_token (parser)->location,
-               "ISO C requires a named argument before %<...%>");
+
+      if (flag_allow_parameterless_variadic_functions)
+        {
+          /* F (...) is allowed.  */
+          ret->types = NULL_TREE;
+        }
+      else
+        {
+          /* Suppress -Wold-style-definition for this case.  */
+          ret->types = error_mark_node;
+          error_at (c_parser_peek_token (parser)->location,
+                    "ISO C requires a named argument before %<...%>");
+        }
       c_parser_consume_token (parser);
       if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
        {
@@ -3428,6 +3442,7 @@ c_parser_attributes (c_parser *parser)
                case RID_TYPEDEF:
                case RID_SHORT:
                case RID_INLINE:
+               case RID_NORETURN:
                case RID_VOLATILE:
                case RID_SIGNED:
                case RID_AUTO:
@@ -5983,6 +5998,52 @@ c_parser_alignof_expression (c_parser *parser)
     }
 }
 
+/* Helper function to read arguments of builtins which are interfaces
+   for the middle-end nodes like COMPLEX_EXPR, VEC_PERM_EXPR and
+   others.  The name of the builtin is passed using BNAME parameter.
+   Function returns true if there were no errors while parsing and
+   stores the arguments in CEXPR_LIST.  */
+static bool
+c_parser_get_builtin_args (c_parser *parser, const char *bname,
+                          VEC(c_expr_t,gc) **ret_cexpr_list)
+{
+  location_t loc = c_parser_peek_token (parser)->location;
+  VEC (c_expr_t,gc) *cexpr_list;
+  c_expr_t expr;
+
+  *ret_cexpr_list = NULL;
+  if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
+    {
+      error_at (loc, "cannot take address of %qs", bname);
+      return false;
+    }
+
+  c_parser_consume_token (parser);
+
+  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+    {
+      c_parser_consume_token (parser);
+      return true;
+    }
+
+  expr = c_parser_expr_no_commas (parser, NULL);
+  cexpr_list = VEC_alloc (c_expr_t, gc, 1);
+  C_EXPR_APPEND (cexpr_list, expr);
+  while (c_parser_next_token_is (parser, CPP_COMMA))
+    {
+      c_parser_consume_token (parser);
+      expr = c_parser_expr_no_commas (parser, NULL);
+      C_EXPR_APPEND (cexpr_list, expr);
+    }
+
+  if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+    return false;
+
+  *ret_cexpr_list = cexpr_list;
+  return true;
+}
+
+
 /* Parse a postfix expression (C90 6.3.1-6.3.2, C99 6.5.1-6.5.2).
 
    postfix-expression:
@@ -6020,6 +6081,11 @@ c_parser_alignof_expression (c_parser *parser)
                             assignment-expression ,
                             assignment-expression )
      __builtin_types_compatible_p ( type-name , type-name )
+     __builtin_complex ( assignment-expression , assignment-expression )
+     __builtin_shuffle ( assignment-expression , assignment-expression )
+     __builtin_shuffle ( assignment-expression , 
+                        assignment-expression ,
+                        assignment-expression, )
 
    offsetof-member-designator:
      identifier
@@ -6040,7 +6106,7 @@ c_parser_alignof_expression (c_parser *parser)
 static struct c_expr
 c_parser_postfix_expression (c_parser *parser)
 {
-  struct c_expr expr, e1, e2, e3;
+  struct c_expr expr, e1;
   struct c_type_name *t1, *t2;
   location_t loc = c_parser_peek_token (parser)->location;;
   expr.original_code = ERROR_MARK;
@@ -6326,45 +6392,44 @@ c_parser_postfix_expression (c_parser *parser)
          }
          break;
        case RID_CHOOSE_EXPR:
-         c_parser_consume_token (parser);
-         if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-           {
-             expr.value = error_mark_node;
-             break;
-           }
-         loc = c_parser_peek_token (parser)->location;
-         e1 = c_parser_expr_no_commas (parser, NULL);
-         if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
-           {
-             c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
-             expr.value = error_mark_node;
-             break;
-           }
-         e2 = c_parser_expr_no_commas (parser, NULL);
-         if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
-           {
-             c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
-             expr.value = error_mark_node;
-             break;
-           }
-         e3 = c_parser_expr_no_commas (parser, NULL);
-         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
-                                    "expected %<)%>");
          {
+           VEC (c_expr_t, gc) *cexpr_list;
+           c_expr_t *e1_p, *e2_p, *e3_p;
            tree c;
 
-           c = e1.value;
-           mark_exp_read (e2.value);
-           mark_exp_read (e3.value);
+           c_parser_consume_token (parser);
+           if (!c_parser_get_builtin_args (parser,
+                                           "__builtin_choose_expr",
+                                           &cexpr_list))
+             {
+               expr.value = error_mark_node;
+               break;
+             }
+
+           if (VEC_length (c_expr_t, cexpr_list) != 3)
+             {
+               error_at (loc, "wrong number of arguments to "
+                              "%<__builtin_choose_expr%>");
+               expr.value = error_mark_node;
+               break;
+             }
+
+           e1_p = VEC_index (c_expr_t, cexpr_list, 0);
+           e2_p = VEC_index (c_expr_t, cexpr_list, 1);
+           e3_p = VEC_index (c_expr_t, cexpr_list, 2);
+
+           c = e1_p->value;
+           mark_exp_read (e2_p->value);
+           mark_exp_read (e3_p->value);
            if (TREE_CODE (c) != INTEGER_CST
                || !INTEGRAL_TYPE_P (TREE_TYPE (c)))
              error_at (loc,
                        "first argument to %<__builtin_choose_expr%> not"
                        " a constant");
            constant_expression_warning (c);
-           expr = integer_zerop (c) ? e3 : e2;
+           expr = integer_zerop (c) ? *e3_p : *e2_p;
+           break;
          }
-         break;
        case RID_TYPES_COMPATIBLE_P:
          c_parser_consume_token (parser);
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
@@ -6402,6 +6467,100 @@ c_parser_postfix_expression (c_parser *parser)
              = comptypes (e1, e2) ? integer_one_node : integer_zero_node;
          }
          break;
+       case RID_BUILTIN_COMPLEX:
+         {
+           VEC(c_expr_t, gc) *cexpr_list;
+           c_expr_t *e1_p, *e2_p;
+
+           c_parser_consume_token (parser);
+           if (!c_parser_get_builtin_args (parser,
+                                           "__builtin_complex",
+                                           &cexpr_list))
+             {
+               expr.value = error_mark_node;
+               break;
+             }
+
+           if (VEC_length (c_expr_t, cexpr_list) != 2)
+             {
+               error_at (loc, "wrong number of arguments to "
+                              "%<__builtin_complex%>");
+               expr.value = error_mark_node;
+               break;
+             }
+
+           e1_p = VEC_index (c_expr_t, cexpr_list, 0);
+           e2_p = VEC_index (c_expr_t, cexpr_list, 1);
+
+           mark_exp_read (e1_p->value);
+           if (TREE_CODE (e1_p->value) == EXCESS_PRECISION_EXPR)
+             e1_p->value = convert (TREE_TYPE (e1_p->value),
+                                    TREE_OPERAND (e1_p->value, 0));
+           mark_exp_read (e2_p->value);
+           if (TREE_CODE (e2_p->value) == EXCESS_PRECISION_EXPR)
+             e2_p->value = convert (TREE_TYPE (e2_p->value),
+                                    TREE_OPERAND (e2_p->value, 0));
+           if (!SCALAR_FLOAT_TYPE_P (TREE_TYPE (e1_p->value))
+               || DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e1_p->value))
+               || !SCALAR_FLOAT_TYPE_P (TREE_TYPE (e2_p->value))
+               || DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e2_p->value)))
+             {
+               error_at (loc, "%<__builtin_complex%> operand "
+                         "not of real binary floating-point type");
+               expr.value = error_mark_node;
+               break;
+             }
+           if (TYPE_MAIN_VARIANT (TREE_TYPE (e1_p->value))
+               != TYPE_MAIN_VARIANT (TREE_TYPE (e2_p->value)))
+             {
+               error_at (loc,
+                         "%<__builtin_complex%> operands of different types");
+               expr.value = error_mark_node;
+               break;
+             }
+           if (!flag_isoc99)
+             pedwarn (loc, OPT_pedantic,
+                      "ISO C90 does not support complex types");
+           expr.value = build2 (COMPLEX_EXPR,
+                                build_complex_type
+                                  (TYPE_MAIN_VARIANT
+                                    (TREE_TYPE (e1_p->value))),
+                                e1_p->value, e2_p->value);
+           break;
+         }
+       case RID_BUILTIN_SHUFFLE:
+         {
+           VEC(c_expr_t,gc) *cexpr_list;
+
+           c_parser_consume_token (parser);
+           if (!c_parser_get_builtin_args (parser,
+                                           "__builtin_shuffle",
+                                           &cexpr_list))
+             {
+               expr.value = error_mark_node;
+               break;
+             }
+
+           if (VEC_length (c_expr_t, cexpr_list) == 2)
+             expr.value =
+               c_build_vec_perm_expr
+                 (loc, VEC_index (c_expr_t, cexpr_list, 0)->value,
+                  NULL_TREE, VEC_index (c_expr_t, cexpr_list, 1)->value);
+
+           else if (VEC_length (c_expr_t, cexpr_list) == 3)
+             expr.value =
+               c_build_vec_perm_expr
+                 (loc, VEC_index (c_expr_t, cexpr_list, 0)->value,
+                  VEC_index (c_expr_t, cexpr_list, 1)->value,
+                  VEC_index (c_expr_t, cexpr_list, 2)->value);
+           else
+             {
+               error_at (loc, "wrong number of arguments to "
+                              "%<__builtin_shuffle%>");
+               expr.value = error_mark_node;
+             }
+           break;
+         }
        case RID_AT_SELECTOR:
          gcc_assert (c_dialect_objc ());
          c_parser_consume_token (parser);