Hi! fold_builtin_atomic_always_lock_free has an assertion that if the 2nd argument isn't INTEGER_CST, it has POINTER_TYPE_P, but additionally for casts to void * it looks through the cast. That means though for invalid code if an integral expression etc. is converted to pointer, we violate the assertion. This patch instead doesn't look through such casts, so type_align is effectively alignment of void and thus it considers objects insufficiently aligned, but doesn't ICE.
Another approach (incomplete) is what I've attached to the PR - instead of prototyping __atomic_{always,is}_lock_free it uses ... and only checks that it has 2 arguments and that the last one is a pointer - that way we don't have to try to undo implicit cast to void * and know the conversion in there is the user conversion. Unfortunately the C++ FE isn't prepared for the check_builtin_function_arguments to change the arguments (unlike C). I've bootstrapped/regtested on x86_64-linux and i686-linux the following fix, ok for trunk, or should I invest more time into the other approach? 2016-09-19 Jakub Jelinek <ja...@redhat.com> PR middle-end/77624 * builtins.c (fold_builtin_atomic_always_lock_free): Only look through cast to void * if the cast is from some other pointer type. * c-c++-common/pr77624-1.c: New test. * c-c++-common/pr77624-2.c: New test. --- gcc/builtins.c.jj 2016-09-16 22:19:38.000000000 +0200 +++ gcc/builtins.c 2016-09-19 15:28:41.100412521 +0200 @@ -5575,8 +5575,10 @@ fold_builtin_atomic_always_lock_free (tr end before anything else has a chance to look at it. The pointer parameter at this point is usually cast to a void *, so check for that and look past the cast. */ - if (CONVERT_EXPR_P (arg1) && POINTER_TYPE_P (ttype) - && VOID_TYPE_P (TREE_TYPE (ttype))) + if (CONVERT_EXPR_P (arg1) + && POINTER_TYPE_P (ttype) + && VOID_TYPE_P (TREE_TYPE (ttype)) + && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (arg1, 0)))) arg1 = TREE_OPERAND (arg1, 0); ttype = TREE_TYPE (arg1); --- gcc/testsuite/c-c++-common/pr77624-1.c.jj 2016-09-19 15:18:09.049394093 +0200 +++ gcc/testsuite/c-c++-common/pr77624-1.c 2016-09-19 15:41:09.972949880 +0200 @@ -0,0 +1,14 @@ +/* PR middle-end/77624 */ +/* { dg-do compile } */ + +int +foo (int a) +{ + return __atomic_is_lock_free (2, a); /* { dg-warning "pointer from integer" "" { target c } } */ +} /* { dg-error "invalid conversion" "" { target c++ } 7 } */ + +int +bar (int a) +{ + return __atomic_always_lock_free (2, a); /* { dg-warning "pointer from integer" "" { target c } } */ +} /* { dg-error "invalid conversion" "" { target c++ } 13 } */ --- gcc/testsuite/c-c++-common/pr77624-2.c.jj 2016-09-19 15:18:12.280353292 +0200 +++ gcc/testsuite/c-c++-common/pr77624-2.c 2016-09-19 15:42:37.441844581 +0200 @@ -0,0 +1,26 @@ +/* PR middle-end/77624 */ +/* { dg-do compile } */ + +void +foo (int *a) +{ + double b = 0; + __atomic_is_lock_free (2, a, 2); /* { dg-error "too many arguments" } */ + __atomic_is_lock_free (2); /* { dg-error "too few arguments" } */ + __atomic_is_lock_free (2, b); /* { dg-error "incompatible type" "" { target c } } */ + /* { dg-message "expected" "" { target c } 10 } */ + /* { dg-error "convert" "" { target c++ } 10 } */ + __atomic_is_lock_free (2, 0); +} + +void +bar (int *a) +{ + double b = 0; + __atomic_always_lock_free (2, a, 2); /* { dg-error "too many arguments" } */ + __atomic_always_lock_free (2); /* { dg-error "too few arguments" } */ + __atomic_always_lock_free (2, b); /* { dg-error "incompatible type" "" { target c } } */ + /* { dg-message "expected" "" { target c } 22 } */ + /* { dg-error "convert" "" { target c++ } 22 } */ + __atomic_always_lock_free (2, 0); +} Jakub