This adds __realpart / __imagpart handling as well as simple
-> and . handling (it doesn't nest yet).

Tested on x86_64-unknown-linux-gnu, applied.

Richard.

2016-10-27  Richard Biener  <rguent...@suse.de>

        c/
        * gimple-parser.c (c_parser_gimple_compound_statement): Simplify.
        Do not allow mixed declarations and stmts nor empty stmts.
        (c_parser_gimple_expression): Remove odd pointer handling.
        Use a switch.
        (c_parser_gimple_unary_expression): Adjust SSA name check.
        Add missing __realpart and __imagpart handling.
        (c_parser_gimple_postfix_expression_after_primary): Handle
        missing -> and . handling.

        * gcc.dg/gimplefe-15.c: New testcase.

diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c
index f109745..3924e6f 100644
--- a/gcc/c/gimple-parser.c
+++ b/gcc/c/gimple-parser.c
@@ -143,17 +143,12 @@ c_parser_gimple_compound_statement (c_parser *parser, 
gimple_seq *seq)
   if (! c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
     return false;
 
-  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+  /* A compund statement starts with optional declarations.  */
+  while (c_parser_next_tokens_start_declaration (parser))
     {
-      c_parser_consume_token (parser);
-      return false;
-    }
-
-  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
-    {
-      c_parser_error (parser, "expected declaration or statement");
-      c_parser_consume_token (parser);
-      return false;
+      c_parser_gimple_declaration (parser);
+      if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+       return false;
     }
 
   while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
@@ -163,70 +158,64 @@ c_parser_gimple_compound_statement (c_parser *parser, 
gimple_seq *seq)
          c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
          return return_p;
        }
-
-      if (c_parser_next_token_is (parser, CPP_NAME)
-         && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
-       c_parser_gimple_label (parser, seq);
-
-      else if (c_parser_next_tokens_start_declaration (parser))
-       c_parser_gimple_declaration (parser);
-
       else if (c_parser_next_token_is (parser, CPP_EOF))
        {
          c_parser_error (parser, "expected declaration or statement");
          return return_p;
        }
 
-      else
+      switch (c_parser_peek_token (parser)->type)
        {
-         switch (c_parser_peek_token (parser)->type)
+       case CPP_KEYWORD:
+         switch (c_parser_peek_token (parser)->keyword)
            {
-           case CPP_KEYWORD:
-             switch (c_parser_peek_token (parser)->keyword)
-               {
-               case RID_IF:
-                 c_parser_gimple_if_stmt (parser, seq);
-                 break;
-               case RID_SWITCH:
-                 c_parser_gimple_switch_stmt (parser, seq);
-                 break;
-               case RID_GOTO:
-                   {
-                     location_t loc = c_parser_peek_token (parser)->location;
-                     c_parser_consume_token (parser);
-                     if (c_parser_next_token_is (parser, CPP_NAME))
-                       {
-                         c_parser_gimple_goto_stmt (loc,
-                                                    c_parser_peek_token
-                                                      (parser)->value,
-                                                    seq);
-                         c_parser_consume_token (parser);
-                         if (! c_parser_require (parser, CPP_SEMICOLON,
-                                                 "expected %<;%>"))
-                           return return_p;
-                       }
-                   }
-                 break;
-               case RID_RETURN:
-                 return_p = true;
-                 c_parser_gimple_return_stmt (parser, seq);
-                 if (! c_parser_require (parser, CPP_SEMICOLON,
-                                         "expected %<;%>"))
-                   return return_p;
-                 break;
-               default:
-                 goto expr_stmt;
+           case RID_IF:
+             c_parser_gimple_if_stmt (parser, seq);
+             break;
+           case RID_SWITCH:
+             c_parser_gimple_switch_stmt (parser, seq);
+             break;
+           case RID_GOTO:
+             {
+               location_t loc = c_parser_peek_token (parser)->location;
+               c_parser_consume_token (parser);
+               if (c_parser_next_token_is (parser, CPP_NAME))
+                 {
+                   c_parser_gimple_goto_stmt (loc,
+                                              c_parser_peek_token
+                                              (parser)->value,
+                                              seq);
+                   c_parser_consume_token (parser);
+                   if (! c_parser_require (parser, CPP_SEMICOLON,
+                                           "expected %<;%>"))
+                     return return_p;
+                 }
                }
              break;
-           case CPP_SEMICOLON:
-             c_parser_consume_token (parser);
+           case RID_RETURN:
+             return_p = true;
+             c_parser_gimple_return_stmt (parser, seq);
+             if (! c_parser_require (parser, CPP_SEMICOLON,
+                                     "expected %<;%>"))
+               return return_p;
              break;
            default:
-           expr_stmt:
-             c_parser_gimple_expression (parser, seq);
-             if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
-               return return_p;
+             goto expr_stmt;
+           }
+         break;
+       case CPP_NAME:
+         if (c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+           {
+             c_parser_gimple_label (parser, seq);
+             break;
            }
+         goto expr_stmt;
+
+       default:
+expr_stmt:
+         c_parser_gimple_expression (parser, seq);
+         if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+           return return_p;
        }
     }
   c_parser_consume_token (parser);
@@ -289,14 +278,6 @@ c_parser_gimple_expression (c_parser *parser, gimple_seq 
*seq)
        }
     }
 
-  if (POINTER_TYPE_P (TREE_TYPE (lhs.value)))
-    {
-      STRIP_USELESS_TYPE_CONVERSION (rhs.value);
-      if (! useless_type_conversion_p (TREE_TYPE (lhs.value),
-                                      TREE_TYPE (rhs.value)))
-       rhs.value = fold_convert_loc (loc, TREE_TYPE (lhs.value), rhs.value);
-    }
-
   /* Pointer expression.  */
   if (TREE_CODE (lhs.value) == INDIRECT_REF)
     {
@@ -317,18 +298,21 @@ c_parser_gimple_expression (c_parser *parser, gimple_seq 
*seq)
        }
     }
 
-  if (c_parser_next_token_is (parser, CPP_AND)
-      || c_parser_next_token_is (parser, CPP_MULT)
-      || c_parser_next_token_is (parser, CPP_PLUS)
-      || c_parser_next_token_is (parser, CPP_MINUS)
-      || c_parser_next_token_is (parser, CPP_COMPL)
-      || c_parser_next_token_is (parser, CPP_NOT))
+  switch (c_parser_peek_token (parser)->type)
     {
+    case CPP_AND:
+    case CPP_PLUS:
+    case CPP_MINUS:
+    case CPP_COMPL:
+    case CPP_NOT:
+    case CPP_MULT: /* pointer deref */
       rhs = c_parser_gimple_unary_expression (parser);
       assign = gimple_build_assign (lhs.value, rhs.value);
       gimple_set_location (assign, loc);
       gimple_seq_add_stmt (seq, assign);
       return;
+
+    default:;
     }
 
   /* GIMPLE PHI expression.  */
@@ -591,7 +575,7 @@ static c_expr
 c_parser_gimple_unary_expression (c_parser *parser)
 {
   struct c_expr ret, op;
-  if (c_parser_peek_token (parser)->value
+  if (c_parser_peek_token (parser)->type == CPP_NAME
       && TREE_CODE (c_parser_peek_token (parser)->value) == IDENTIFIER_NODE
       && ! lookup_name (c_parser_peek_token (parser)->value))
     return c_parser_parse_ssa_names (parser);
@@ -635,6 +619,20 @@ c_parser_gimple_unary_expression (c_parser *parser)
       c_parser_consume_token (parser);
       op = c_parser_cast_expression (parser, NULL);
       return parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op);
+    case CPP_KEYWORD:
+      switch (c_parser_peek_token (parser)->keyword)
+       {
+       case RID_REALPART:
+         c_parser_consume_token (parser);
+         op = c_parser_cast_expression (parser, NULL);
+         return parser_build_unary_op (op_loc, REALPART_EXPR, op);
+       case RID_IMAGPART:
+         c_parser_consume_token (parser);
+         op = c_parser_cast_expression (parser, NULL);
+         return parser_build_unary_op (op_loc, IMAGPART_EXPR, op);
+       default:
+         return c_parser_gimple_postfix_expression (parser);
+       }
     default:
       return c_parser_gimple_postfix_expression (parser);
     }
@@ -711,6 +709,8 @@ c_parser_parse_ssa_names (c_parser *parser)
      gimple-primary-expression
      gimple-primary-xpression [ gimple-primary-expression ]
      gimple-primary-expression ( gimple-argument-expression-list[opt] )
+     postfix-expression . identifier
+     postfix-expression -> identifier
 
    gimple-argument-expression-list:
      gimple-unary-expression
@@ -853,9 +853,91 @@ c_parser_gimple_postfix_expression_after_primary (c_parser 
*parser,
          }
        arg_loc.release ();
        break;
-      default:
-       return expr;
       }
+    case CPP_DOT:
+      {
+       /* Structure element reference.  */
+       tree ident;
+       location_t comp_loc;
+       c_parser_consume_token (parser);
+       if (c_parser_next_token_is (parser, CPP_NAME))
+         {
+           c_token *comp_tok = c_parser_peek_token (parser);
+           ident = comp_tok->value;
+           comp_loc = comp_tok->location;
+         }
+       else
+         {
+           c_parser_error (parser, "expected identifier");
+           expr.set_error ();
+           expr.original_code = ERROR_MARK;
+           expr.original_type = NULL;
+           return expr;
+         }
+       start = expr.get_start ();
+       finish = c_parser_peek_token (parser)->get_finish ();
+       c_parser_consume_token (parser);
+       expr.value = build_component_ref (op_loc, expr.value, ident,
+                                         comp_loc);
+       set_c_expr_source_range (&expr, start, finish);
+       expr.original_code = ERROR_MARK;
+       if (TREE_CODE (expr.value) != COMPONENT_REF)
+         expr.original_type = NULL;
+       else
+         {
+           /* Remember the original type of a bitfield.  */
+           tree field = TREE_OPERAND (expr.value, 1);
+           if (TREE_CODE (field) != FIELD_DECL)
+             expr.original_type = NULL;
+           else
+             expr.original_type = DECL_BIT_FIELD_TYPE (field);
+         }
+       break;
+      }
+    case CPP_DEREF:
+      {
+       /* Structure element reference.  */
+       tree ident;
+       location_t comp_loc;
+       c_parser_consume_token (parser);
+       if (c_parser_next_token_is (parser, CPP_NAME))
+         {
+           c_token *comp_tok = c_parser_peek_token (parser);
+           ident = comp_tok->value;
+           comp_loc = comp_tok->location;
+         }
+       else
+         {
+           c_parser_error (parser, "expected identifier");
+           expr.set_error ();
+           expr.original_code = ERROR_MARK;
+           expr.original_type = NULL;
+           return expr;
+         }
+       start = expr.get_start ();
+       finish = c_parser_peek_token (parser)->get_finish ();
+       c_parser_consume_token (parser);
+       expr.value = build_component_ref (op_loc,
+                                         build_simple_mem_ref_loc (op_loc,
+                                                                   expr.value),
+                                         ident, comp_loc);
+       set_c_expr_source_range (&expr, start, finish);
+       expr.original_code = ERROR_MARK;
+       if (TREE_CODE (expr.value) != COMPONENT_REF)
+         expr.original_type = NULL;
+       else
+         {
+           /* Remember the original type of a bitfield.  */
+           tree field = TREE_OPERAND (expr.value, 1);
+           if (TREE_CODE (field) != FIELD_DECL)
+             expr.original_type = NULL;
+           else
+             expr.original_type = DECL_BIT_FIELD_TYPE (field);
+         }
+       break;
+      }
+    default:
+      return expr;
     }
   return expr;
 }
diff --git a/gcc/testsuite/gcc.dg/gimplefe-15.c 
b/gcc/testsuite/gcc.dg/gimplefe-15.c
new file mode 100644
index 0000000..0c4b4d2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-15.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fgimple" } */
+
+struct X { int a; };
+struct X x;
+
+int __GIMPLE ()
+foo (struct X *p, _Complex int q)
+{
+  int b;
+  b = __real q;
+  p->a = b;
+  x.a = b;
+  b = p->a;
+  b = x.a;
+  return b;
+}

Reply via email to