A change of mine to the strlen pass assumes that the strlen argument points to an object of the correct type and does not correctly handle GIMPLE where the argument has the wrong type such as in:
extern char a[1][2]; n = strlen (*a); where the strlen pass actually sees n = strlen (a); The attached patch corrects the code to use TYPE_SIZE to determine the size of the array argument rather than using TYPE_DOMAIN. Tested on x86_64-linux. Martin
PR tree-optimization/86400 - set<string>::set<char (*)[2]) constructor does not work with array argument gcc/ChangeLog: PR c++/86400 * tree-ssa-strlen.c (maybe_set_strlen_range): Use type size rather than its domain to compute its the upper bound of a char array. gcc/testsuite/ChangeLog: PR c++/86400 * gcc.dg/strlenopt-47.c: New test. Index: gcc/testsuite/gcc.dg/strlenopt-47.c =================================================================== --- gcc/testsuite/gcc.dg/strlenopt-47.c (nonexistent) +++ gcc/testsuite/gcc.dg/strlenopt-47.c (working copy) @@ -0,0 +1,18 @@ +/* PR tree-optimization/86400 - set<string>::set<char (*)[2]) constructor + does not work with array argument - wrong strlen result after prior + strnlen + { dg-do compile } + { dg-options "-O2 -Wall -fdump-tree-optimized" } */ + +#include "strlenopt.h" + +void f (void) +{ + static char root[1][2] = { "/" }; + int len = strlen (*root); + if (len != 1) + abort(); +} + +/* { dg-final { scan-tree-dump-times "= strlen" 1 "optimized" } } + { dg-final { scan-tree-dump-times "abort" 1 "optimized" } } */ Index: gcc/tree-ssa-strlen.c =================================================================== --- gcc/tree-ssa-strlen.c (revision 262418) +++ gcc/tree-ssa-strlen.c (working copy) @@ -1156,22 +1156,17 @@ maybe_set_strlen_range (tree lhs, tree src, tree b if (src_is_array && !array_at_struct_end_p (src)) { tree type = TREE_TYPE (src); - if (tree dom = TYPE_DOMAIN (type)) - { - tree maxval = TYPE_MAX_VALUE (dom); - if (maxval) - max = wi::to_wide (maxval); - else - max = wi::zero (min.get_precision ()); + if (tree size = TYPE_SIZE_UNIT (type)) + if (size && TREE_CODE (size) == INTEGER_CST) + max = wi::to_wide (size); - /* For strlen() the upper bound above is equal to - the longest string that can be stored in the array - (i.e., it accounts for the terminating nul. For - strnlen() bump up the maximum by one since the array - need not be nul-terminated. */ - if (bound) - ++max; - } + /* For strlen() the upper bound above is equal to + the longest string that can be stored in the array + (i.e., it accounts for the terminating nul. For + strnlen() bump up the maximum by one since the array + need not be nul-terminated. */ + if (!bound && max != 0) + --max; } else {