Patchwork [C] Don't perform function array conversions on inline asm "m" constrainted inputs (PR c++/55619)

login
register
mail settings
Submitter Jakub Jelinek
Date Dec. 12, 2012, 7:54 p.m.
Message ID <20121212195453.GF2315@tucnak.redhat.com>
Download mbox | patch
Permalink /patch/205636/
State New
Headers show

Comments

Jakub Jelinek - Dec. 12, 2012, 7:54 p.m.
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  <jakub@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.


	Jakub
Joseph S. Myers - Dec. 19, 2012, 5:46 p.m.
On Wed, 12 Dec 2012, Jakub Jelinek wrote:

> 2012-12-12  Jakub Jelinek  <jakub@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.

OK.

Patch

--- 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));
+}