Hi! __atomic_exchange doesn't work in C++. The problem is that add_atomic_size_parameter, if there is no room in params vector, creates new params vector big enough that the extra argument fixs in, but doesn't add the extra argument in, because it relies on the subsequent build_function_call_vec to call resolve_overloaded_builtin recursively and add the parameter. The C build_function_call_vec does that, but C++ doesn't, there resolve_overloaded_builtin is called from finish_call_expr instead.
My first attempt to fix this - changing add_atomic_size_parameter to add that argument - broke C, where the recursive resolve_overloaded_builtin -> get_atomic_generic_size would complain about too many arguments. Here is one possible fix for this, let the C++ build_function_call_vec (which is only called from two c-family/c-common.c spots that expect this behavior) behave more like the C call. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk (and 4.8)? Another alternative is some static flag in resolve_overloaded_function that would just punt if the function is called recursively, but I think if we can avoid adding global state, we should (otherwise JIT won't like it too much). 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. 2014-03-28 Jakub Jelinek <ja...@redhat.com> PR c++/60689 * typeck.c (build_function_call_vec): Call resolve_overloaded_builtin. * c-c++-common/pr60689.c: New test. --- gcc/cp/typeck.c.jj 2014-03-10 10:50:14.000000000 +0100 +++ gcc/cp/typeck.c 2014-03-28 08:07:49.737656541 +0100 @@ -3363,10 +3363,23 @@ build_function_call (location_t /*loc*/, /* Used by the C-common bits. */ tree -build_function_call_vec (location_t /*loc*/, vec<location_t> /*arg_loc*/, +build_function_call_vec (location_t loc, vec<location_t> /*arg_loc*/, tree function, vec<tree, va_gc> *params, vec<tree, va_gc> * /*origtypes*/) { + /* This call is here to match what the C FE does in its + build_function_call_vec. See PR60689. */ + 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; + } + vec<tree, va_gc> *orig_params = params; tree ret = cp_build_function_call_vec (function, ¶ms, tf_warning_or_error); --- gcc/testsuite/c-c++-common/pr60689.c.jj 2014-03-27 22:06:31.703103613 +0100 +++ gcc/testsuite/c-c++-common/pr60689.c 2014-03-27 22:06:46.542024952 +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); +} Jakub