Patchwork [C++] Fix __atomic_exchange (PR c++/60689)

login
register
mail settings
Submitter Jakub Jelinek
Date March 28, 2014, 3:24 p.m.
Message ID <20140328152427.GM1817@tucnak.redhat.com>
Download mbox | patch
Permalink /patch/334727/
State New
Headers show

Comments

Jakub Jelinek - March 28, 2014, 3:24 p.m.
On Fri, Mar 28, 2014 at 11:47:52AM +0100, Jakub Jelinek wrote:
> Yet another possibility would be to rename all calls in C FE to
> build_function_call_vec to say c_build_function_call_vec and add that
> function which would call resolve_overloaded_builtin and then tail call to
> build_function_call_vec which wouldn't do that.  Then c-family/ would keep
> its current two calls to that function, which wouldn't recurse anymore, and
> we'd need to change add_atomic_size_parameter to push the argument.

Here is the variant patch, which implements the above.
Also bootstrapped/regtested on x86_64-linux and i686-linux.

2014-03-28  Jakub Jelinek  <jakub@redhat.com>

	PR c++/60689
	* c-tree.h (c_build_function_call_vec): New prototype.
	* c-typeck.c (build_function_call_vec): Don't call
	resolve_overloaded_builtin here.
	(c_build_function_call_vec): New wrapper function around
	build_function_call_vec.  Call resolve_overloaded_builtin here.
	(convert_lvalue_to_rvalue, build_function_call, build_atomic_assign):
	Call c_build_function_call_vec instead of build_function_call_vec.
	* c-parser.c (c_parser_postfix_expression_after_primary): Likewise.
	* c-decl.c (finish_decl): Likewise.

	* c-common.c (add_atomic_size_parameter): When creating new
	params vector, push the size argument first.

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


	Jakub
Richard Henderson - March 28, 2014, 5:56 p.m.
On 03/28/2014 08:24 AM, Jakub Jelinek wrote:
> Here is the variant patch, which implements the above.
> Also bootstrapped/regtested on x86_64-linux and i686-linux.
> 
> 2014-03-28  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR c++/60689
> 	* c-tree.h (c_build_function_call_vec): New prototype.
> 	* c-typeck.c (build_function_call_vec): Don't call
> 	resolve_overloaded_builtin here.
> 	(c_build_function_call_vec): New wrapper function around
> 	build_function_call_vec.  Call resolve_overloaded_builtin here.
> 	(convert_lvalue_to_rvalue, build_function_call, build_atomic_assign):
> 	Call c_build_function_call_vec instead of build_function_call_vec.
> 	* c-parser.c (c_parser_postfix_expression_after_primary): Likewise.
> 	* c-decl.c (finish_decl): Likewise.
> 
> 	* c-common.c (add_atomic_size_parameter): When creating new
> 	params vector, push the size argument first.
> 
> 	* c-c++-common/pr60689.c: New test.

I do prefer this variant.


r~

Patch

--- gcc/c/c-tree.h.jj	2014-02-08 00:53:15.000000000 +0100
+++ gcc/c/c-tree.h	2014-03-28 12:30:49.155395381 +0100
@@ -643,6 +643,8 @@  extern tree c_finish_omp_clauses (tree);
 extern tree c_build_va_arg (location_t, tree, tree);
 extern tree c_finish_transaction (location_t, tree, int);
 extern bool c_tree_equal (tree, tree);
+extern tree c_build_function_call_vec (location_t, vec<location_t>, tree,
+				       vec<tree, va_gc> *, vec<tree, va_gc> *);
 
 /* Set to 0 at beginning of a function definition, set to 1 if
    a return statement that specifies a return value is seen.  */
--- gcc/c/c-typeck.c.jj	2014-03-19 08:14:35.000000000 +0100
+++ gcc/c/c-typeck.c	2014-03-28 12:34:57.803066414 +0100
@@ -2016,7 +2016,7 @@  convert_lvalue_to_rvalue (location_t loc
       params->quick_push (expr_addr);
       params->quick_push (tmp_addr);
       params->quick_push (seq_cst);
-      func_call = build_function_call_vec (loc, vNULL, fndecl, params, NULL);
+      func_call = c_build_function_call_vec (loc, vNULL, fndecl, params, NULL);
 
       /* EXPR is always read.  */
       mark_exp_read (exp.value);
@@ -2801,7 +2801,7 @@  build_function_call (location_t loc, tre
   vec_alloc (v, list_length (params));
   for (; params; params = TREE_CHAIN (params))
     v->quick_push (TREE_VALUE (params));
-  ret = build_function_call_vec (loc, vNULL, function, v, NULL);
+  ret = c_build_function_call_vec (loc, vNULL, function, v, NULL);
   vec_free (v);
   return ret;
 }
@@ -2840,14 +2840,6 @@  build_function_call_vec (location_t loc,
   /* Convert anything with function type to a pointer-to-function.  */
   if (TREE_CODE (function) == FUNCTION_DECL)
     {
-      /* Implement type-directed function overloading for builtins.
-	 resolve_overloaded_builtin and targetm.resolve_overloaded_builtin
-	 handle all the type checking.  The result is a complete expression
-	 that implements this function call.  */
-      tem = resolve_overloaded_builtin (loc, function, params);
-      if (tem)
-	return tem;
-
       name = DECL_NAME (function);
 
       if (flag_tm)
@@ -2970,6 +2962,30 @@  build_function_call_vec (location_t loc,
     }
   return require_complete_type (result);
 }
+
+/* Like build_function_call_vec, but call also resolve_overloaded_builtin.  */
+
+tree
+c_build_function_call_vec (location_t loc, vec<location_t> arg_loc,
+			   tree function, vec<tree, va_gc> *params,
+			   vec<tree, va_gc> *origtypes)
+{
+  /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue.  */
+  STRIP_TYPE_NOPS (function);
+
+  /* Convert anything with function type to a pointer-to-function.  */
+  if (TREE_CODE (function) == FUNCTION_DECL)
+    {
+      /* Implement type-directed function overloading for builtins.
+	 resolve_overloaded_builtin and targetm.resolve_overloaded_builtin
+	 handle all the type checking.  The result is a complete expression
+	 that implements this function call.  */
+      tree tem = resolve_overloaded_builtin (loc, function, params);
+      if (tem)
+	return tem;
+    }
+  return build_function_call_vec (loc, arg_loc, function, params, origtypes);
+}
 
 /* Convert the argument expressions in the vector VALUES
    to the types in the list TYPELIST.
@@ -3634,7 +3650,7 @@  build_atomic_assign (location_t loc, tre
       params->quick_push (lhs_addr);
       params->quick_push (rhs);
       params->quick_push (seq_cst);
-      func_call = build_function_call_vec (loc, vNULL, fndecl, params, NULL);
+      func_call = c_build_function_call_vec (loc, vNULL, fndecl, params, NULL);
       add_stmt (func_call);
 
       /* Finish the compound statement.  */
@@ -3666,7 +3682,7 @@  build_atomic_assign (location_t loc, tre
   params->quick_push (lhs_addr);
   params->quick_push (old_addr);
   params->quick_push (seq_cst);
-  func_call = build_function_call_vec (loc, vNULL, fndecl, params, NULL);
+  func_call = c_build_function_call_vec (loc, vNULL, fndecl, params, NULL);
   add_stmt (func_call);
   params->truncate (0);
 
@@ -3705,7 +3721,7 @@  build_atomic_assign (location_t loc, tre
   params->quick_push (integer_zero_node);
   params->quick_push (seq_cst);
   params->quick_push (seq_cst);
-  func_call = build_function_call_vec (loc, vNULL, fndecl, params, NULL);
+  func_call = c_build_function_call_vec (loc, vNULL, fndecl, params, NULL);
 
   goto_stmt = build1 (GOTO_EXPR, void_type_node, done_decl);
   SET_EXPR_LOCATION (goto_stmt, loc);
--- gcc/c/c-parser.c.jj	2014-03-06 13:05:17.000000000 +0100
+++ gcc/c/c-parser.c	2014-03-28 12:33:54.553404774 +0100
@@ -7703,8 +7703,9 @@  c_parser_postfix_expression_after_primar
 					      expr.value, exprlist,
 					      sizeof_arg,
 					      sizeof_ptr_memacc_comptypes);
-	  expr.value = build_function_call_vec (expr_loc, arg_loc, expr.value,
-						exprlist, origtypes);
+	  expr.value
+	    = c_build_function_call_vec (expr_loc, arg_loc, expr.value,
+					 exprlist, origtypes);
 	  expr.original_code = ERROR_MARK;
 	  if (TREE_CODE (expr.value) == INTEGER_CST
 	      && TREE_CODE (orig_expr.value) == FUNCTION_DECL
--- gcc/c/c-decl.c.jj	2014-03-07 13:57:21.000000000 +0100
+++ gcc/c/c-decl.c	2014-03-28 12:34:12.246309772 +0100
@@ -4568,8 +4568,8 @@  finish_decl (tree decl, location_t init_
 	  cleanup = build_unary_op (input_location, ADDR_EXPR, decl, 0);
 	  vec_alloc (v, 1);
 	  v->quick_push (cleanup);
-	  cleanup = build_function_call_vec (DECL_SOURCE_LOCATION (decl),
-					     vNULL, cleanup_decl, v, NULL);
+	  cleanup = c_build_function_call_vec (DECL_SOURCE_LOCATION (decl),
+					       vNULL, cleanup_decl, v, NULL);
 	  vec_free (v);
 
 	  /* Don't warn about decl unused; the cleanup uses it.  */
--- gcc/testsuite/c-c++-common/pr60689.c.jj	2014-03-28 12:29:05.323950531 +0100
+++ gcc/testsuite/c-c++-common/pr60689.c	2014-03-28 12:29:05.323950531 +0100
@@ -0,0 +1,10 @@ 
+/* PR c++/60689 */
+/* { dg-do compile } */
+
+struct S { char x[9]; };
+
+void
+foo (struct S *x, struct S *y, struct S *z)
+{
+  __atomic_exchange (x, y, z, __ATOMIC_SEQ_CST);
+}
--- gcc/c-family/c-common.c.jj	2014-03-28 11:01:44.000000000 +0100
+++ gcc/c-family/c-common.c	2014-03-28 12:35:40.111840480 +0100
@@ -10453,6 +10453,7 @@  add_atomic_size_parameter (unsigned n, l
 
       len = params->length ();
       vec_alloc (v, len + 1);
+      v->quick_push (build_int_cst (size_type_node, n));
       for (z = 0; z < len; z++)
 	v->quick_push ((*params)[z]);
       f = build_function_call_vec (loc, vNULL, function, v, NULL);