The following avoids creating IL that accesses a FUNCTION_DECLs memory directly rather than indirectly through an address based on it.
Bootstrap and regtest running on x86_64-unknown-linux-gnu, ok for trunk? Thanks, Richard. 2016-06-13 Richard Biener <rguent...@suse.de> PR c/71514 c-family/ * c-common.c (resolve_overloaded_atomic_exchange): Convert the pointer and dereference instead of dereferencing and view-converting. (resolve_overloaded_atomic_compare_exchange): Likewise. (resolve_overloaded_atomic_store): Likewise. * gcc.dg/torture/pr71514.c: New testcase. Index: gcc/c-family/c-common.c =================================================================== *** gcc/c-family/c-common.c (revision 237372) --- gcc/c-family/c-common.c (working copy) *************** resolve_overloaded_atomic_exchange (loca *** 11129,11136 **** p0 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p0); (*params)[0] = p0; /* Convert new value to required type, and dereference it. */ p1 = build_indirect_ref (loc, p1, RO_UNARY_STAR); - p1 = build1 (VIEW_CONVERT_EXPR, I_type, p1); (*params)[1] = p1; /* Move memory model to the 3rd position, and end param list. */ --- 11129,11136 ---- p0 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p0); (*params)[0] = p0; /* Convert new value to required type, and dereference it. */ + p1 = fold_convert_loc (loc, I_type_ptr, p1); p1 = build_indirect_ref (loc, p1, RO_UNARY_STAR); (*params)[1] = p1; /* Move memory model to the 3rd position, and end param list. */ *************** resolve_overloaded_atomic_compare_exchan *** 11209,11216 **** (*params)[1] = p1; /* Convert desired value to required type, and dereference it. */ p2 = build_indirect_ref (loc, p2, RO_UNARY_STAR); - p2 = build1 (VIEW_CONVERT_EXPR, I_type, p2); (*params)[2] = p2; /* The rest of the parameters are fine. NULL means no special return value --- 11209,11216 ---- (*params)[1] = p1; /* Convert desired value to required type, and dereference it. */ + p2 = fold_convert_loc (loc, I_type_ptr, p2); p2 = build_indirect_ref (loc, p2, RO_UNARY_STAR); (*params)[2] = p2; /* The rest of the parameters are fine. NULL means no special return value *************** resolve_overloaded_atomic_store (locatio *** 11329,11336 **** (*params)[0] = p0; /* Convert new value to required type, and dereference it. */ p1 = build_indirect_ref (loc, p1, RO_UNARY_STAR); - p1 = build1 (VIEW_CONVERT_EXPR, I_type, p1); (*params)[1] = p1; /* The memory model is in the right spot already. Return is void. */ --- 11329,11336 ---- (*params)[0] = p0; /* Convert new value to required type, and dereference it. */ + p1 = fold_convert_loc (loc, I_type_ptr, p1); p1 = build_indirect_ref (loc, p1, RO_UNARY_STAR); (*params)[1] = p1; /* The memory model is in the right spot already. Return is void. */ Index: gcc/testsuite/gcc.dg/torture/pr71514.c =================================================================== *** gcc/testsuite/gcc.dg/torture/pr71514.c (revision 0) --- gcc/testsuite/gcc.dg/torture/pr71514.c (working copy) *************** *** 0 **** --- 1,11 ---- + /* { dg-do compile } */ + + void foo () {} + + char a, b; + + int main () + { + __atomic_exchange (&a, &foo, &b, __ATOMIC_RELAXED); + return 0; + }