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