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 <ja...@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. --- 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); Jakub