https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110603
Aldy Hernandez <aldyh at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |amacleod at redhat dot com --- Comment #4 from Aldy Hernandez <aldyh at gcc dot gnu.org> --- (In reply to wierton from comment #0) > The testing program: > ``` > typedef long unsigned int size_t; > void *memcpy(void *, const void *, size_t); > int snprintf(char *restrict, size_t, const char *restrict, ...); > > extern char a[2]; > void test_func_on_line_62(void) { > memcpy(a, "12", sizeof("12") - 1); > const int res = snprintf(0, 0, "%s", a); > if (res <= 3) > do { > extern void f(void); > f(); > } while (0); > } The sprintf pass is ICEing because it's trying to build a nonsensical range of [2,1]. Legacy irange tried harder with swapped ranges, but in the above case it would actually drop to VARYING: - /* There's one corner case, if we had [C+1, C] before we now have - that again. But this represents an empty value range, so drop - to varying in this case. */ Which would cause the sprintf pass to set a global range of VARYING. I can't remember whether this meant nuking the known global range, or ignoring it altogether (the semantics changed in the last release or two). My guess is the later, since set_range_info() improves ranges, never pessimizes them. Now the reason we're passing swapped endpoints seems to originate in get_range_strlen_dynamic(). It is setting a min of 2, courtesy of the nonzero characters in the memcpy: memcpy(a, "12", sizeof("12") - 1); This comes from tree-ssa-strlen.c: if (!pdata->minlen && si->nonzero_chars) { if (TREE_CODE (si->nonzero_chars) == INTEGER_CST) pdata->minlen = si->nonzero_chars; Further down we set a max of 1, stemming from the size of a[2] minus 1 for the terminating null: if (TREE_CODE (size) == INTEGER_CST) { ++off; /* Increment for the terminating nul. */ tree toffset = build_int_cst (size_type_node, off); pdata->maxlen = fold_build2 (MINUS_EXPR, size_type_node, size, toffset); pdata->maxbound = pdata->maxlen; } I don't understand this code enough to opine, but at the worst we could bail if the ends are swapped. It's no worse than what we had before.