PR 89934 reports yet another ICE due to a call to a library built-in function with invalid arguments. The attached patch does the bare minimum to avoid it. I will commit it to trunk and to GCC 8 later this week if there are no objections.
Martin PS There have been many of these reports (at least three in the wrestrict pass alone, and quite a few elsewhere). Simply avoiding the ICEs as this patch does and as all the others before it have done as well does nothing to help solve the underlying problem in user code: the invalid calls will end up with undefined behavior if they are ever made at runtime. For example, the one in this bug report will most likely cause data corruption or buffer overflow without ever being detected by _FORTIFY_SOURCE. That seems far worse than failing to compile the code (either with an ICE or with some other hard error). For GCC 10 I think a more robust solution should be put in place not just to prevent these invalid built-in calls from tripping up the middle-end, but also to avoid the undefined behavior at runtime. The calls could either be rejected with an error as Clang does, or they could be replaced them with __builtin_trap or perhaps __builtin_unreachable, depending on some command line option.
PR middle-end/89934 - ICE on a call with fewer arguments to strncpy declared without prototype gcc/ChangeLog: PR middle-end/89934 * gimple-ssa-warn-restrict.c (builtin_access::builtin_access): Bail out if the number of arguments is less than expected. gcc/testsuite/ChangeLog: PR middle-end/89934 * gcc.dg/Wrestrict-19.c: New test. * gcc.dg/Wrestrict-5.c: Add comment. Remove unused code. Index: gcc/gimple-ssa-warn-restrict.c =================================================================== --- gcc/gimple-ssa-warn-restrict.c (revision 270061) +++ gcc/gimple-ssa-warn-restrict.c (working copy) @@ -730,6 +730,10 @@ builtin_access::builtin_access (gimple *call, buil offset_int bounds[2] = { maxobjsize, maxobjsize }; if (dstref->strbounded_p) { + unsigned nargs = gimple_call_num_args (call); + if (nargs <= sizeargno) + return; + tree size = gimple_call_arg (call, sizeargno); tree range[2]; if (get_size_range (size, range, true)) Index: gcc/testsuite/gcc.dg/Wrestrict-19.c =================================================================== --- gcc/testsuite/gcc.dg/Wrestrict-19.c (nonexistent) +++ gcc/testsuite/gcc.dg/Wrestrict-19.c (working copy) @@ -0,0 +1,33 @@ +/* PR middle-end/89934 - ICE on a call with fewer arguments to strncpy + declared without prototype + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +typedef __SIZE_TYPE__ size_t; + +char *strncpy (); + +char* f0 (char *s) +{ + return strncpy (); +} + +char* f1 (char *s) +{ + return strncpy (s); +} + +char* f2 (char *s) +{ + return strncpy (s, s + 1); /* ICE here. */ +} + +void f3 (char *s, size_t n, const char *t) +{ + strncpy (s, n, t); + strncpy (n, s, t); +} + +/* { dg-prune-output "\\\[-Wbuiltin-declaration-mismatch]" } + { dg-prune-output "\\\[-Wint-conversion]" } */ + Index: gcc/testsuite/gcc.dg/Wrestrict-5.c =================================================================== --- gcc/testsuite/gcc.dg/Wrestrict-5.c (revision 270061) +++ gcc/testsuite/gcc.dg/Wrestrict-5.c (working copy) @@ -1,20 +1,11 @@ -/* Test to verify that valid calls to common restrict-qualified built-in +/* PR tree-optimization/83655 - ICE on an invalid call to memcpy declared + with no prototype + Test to verify that valid calls to common restrict-qualified built-in functions declared with no prototype are checked for overlap, and that invalid calls are ignored. { dg-do compile } - { dg-prune-output "conflicting types for built-in" } { dg-options "-O2 -Wrestrict" } */ -typedef __SIZE_TYPE__ size_t; - -#if __cplusplus -extern "C" { - -#define NO_PROTO ... -#else -#define NO_PROTO /* empty */ -#endif - void* memcpy (); char* strncpy ();