Hi!

This is something I've changed recently on the C++ side, but C has similar
issue as the testcase shows.  For "m" or other constraints that allow memory
and don't allow registers, we want to mark the operand addressable (thus
handle it quite lvalue-ish, except that we know it won't be written to),
but default_function_array_conversion can be a problem for that.

Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for
trunk?

2012-12-12  Jakub Jelinek  <ja...@redhat.com>

        PR c++/55619
        * c-parser.c (c_parser_asm_operands): Remove CONVERT_P
        argument, don't call default_function_array_conversion
        nor c_fully_fold here.
        (c_parser_asm_statement): Adjust callers.
        * c-typeck.c (build_asm_expr): Call c_fully_fold on inputs
        and outputs here, and call default_function_array_conversion
        on inputs that don't need to be addressable.

        * c-c++-common/pr55619.c: New test.

--- gcc/c/c-parser.c.jj 2012-11-19 14:41:12.000000000 +0100
+++ gcc/c/c-parser.c    2012-12-12 14:02:37.062065983 +0100
@@ -1154,7 +1154,7 @@ static void c_parser_while_statement (c_
 static void c_parser_do_statement (c_parser *);
 static void c_parser_for_statement (c_parser *);
 static tree c_parser_asm_statement (c_parser *);
-static tree c_parser_asm_operands (c_parser *, bool);
+static tree c_parser_asm_operands (c_parser *);
 static tree c_parser_asm_goto_operands (c_parser *);
 static tree c_parser_asm_clobbers (c_parser *);
 static struct c_expr c_parser_expr_no_commas (c_parser *, struct c_expr *);
@@ -5150,10 +5150,10 @@ c_parser_asm_statement (c_parser *parser
            /* For asm goto, we don't allow output operands, but reserve
               the slot for a future extension that does allow them.  */
            if (!is_goto)
-             outputs = c_parser_asm_operands (parser, false);
+             outputs = c_parser_asm_operands (parser);
            break;
          case 1:
-           inputs = c_parser_asm_operands (parser, true);
+           inputs = c_parser_asm_operands (parser);
            break;
          case 2:
            clobbers = c_parser_asm_clobbers (parser);
@@ -5191,9 +5191,7 @@ c_parser_asm_statement (c_parser *parser
   goto error;
 }
 
-/* Parse asm operands, a GNU extension.  If CONVERT_P (for inputs but
-   not outputs), apply the default conversion of functions and arrays
-   to pointers.
+/* Parse asm operands, a GNU extension.
 
    asm-operands:
      asm-operand
@@ -5205,10 +5203,9 @@ c_parser_asm_statement (c_parser *parser
 */
 
 static tree
-c_parser_asm_operands (c_parser *parser, bool convert_p)
+c_parser_asm_operands (c_parser *parser)
 {
   tree list = NULL_TREE;
-  location_t loc;
   while (true)
     {
       tree name, str;
@@ -5243,12 +5240,8 @@ c_parser_asm_operands (c_parser *parser,
          parser->lex_untranslated_string = true;
          return NULL_TREE;
        }
-      loc = c_parser_peek_token (parser)->location;
       expr = c_parser_expression (parser);
       mark_exp_read (expr.value);
-      if (convert_p)
-       expr = default_function_array_conversion (loc, expr);
-      expr.value = c_fully_fold (expr.value, false, NULL);
       parser->lex_untranslated_string = true;
       if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
        {
--- gcc/c/c-typeck.c.jj 2012-12-10 08:42:35.000000000 +0100
+++ gcc/c/c-typeck.c    2012-12-12 14:11:55.487236911 +0100
@@ -8500,6 +8500,8 @@ build_asm_expr (location_t loc, tree str
     {
       tree output = TREE_VALUE (tail);
 
+      output = c_fully_fold (output, false, NULL);
+
       /* ??? Really, this should not be here.  Users should be using a
         proper lvalue, dammit.  But there's a long history of using casts
         in the output operands.  In cases like longlong.h, this becomes a
@@ -8557,16 +8559,27 @@ build_asm_expr (location_t loc, tree str
             mark it addressable.  */
          if (!allows_reg && allows_mem)
            {
+             input = c_fully_fold (input, false, NULL);
+
              /* Strip the nops as we allow this case.  FIXME, this really
                 should be rejected or made deprecated.  */
              STRIP_NOPS (input);
              if (!c_mark_addressable (input))
                input = error_mark_node;
            }
-         else if (input != error_mark_node && VOID_TYPE_P (TREE_TYPE (input)))
+         else
            {
-             error_at (loc, "invalid use of void expression");
-             input = error_mark_node;
+             struct c_expr expr;
+             memset (&expr, 0, sizeof (expr));
+             expr.value = input;
+             expr = default_function_array_conversion (loc, expr);
+             input = c_fully_fold (expr.value, false, NULL);
+
+             if (input != error_mark_node && VOID_TYPE_P (TREE_TYPE (input)))
+               {
+                 error_at (loc, "invalid use of void expression");
+                 input = error_mark_node;
+               }
            }
        }
       else
--- gcc/testsuite/c-c++-common/pr55619.c.jj     2012-12-12 14:25:24.514694819 
+0100
+++ gcc/testsuite/c-c++-common/pr55619.c        2012-12-12 14:25:55.183538437 
+0100
@@ -0,0 +1,11 @@
+/* PR c++/55619 */
+/* { dg-do compile } */
+
+int y[4];
+
+void
+f ()
+{
+  int x[4] = { 0, 1, 2, 3 };
+  __asm volatile ("" : : "m" (x), "m" (y));
+}

        Jakub

Reply via email to