if (TREE_CODE (idx) != INTEGER_CST && TREE_CODE (argtype) == POINTER_TYPE) { /* From a pointer (but not array) argument extract the variable index to prevent get_addr_base_and_unit_offset() from failing due to it. Use it later to compute the non-constant offset into the string and return it to the caller. */ varidx = idx; ref = TREE_OPERAND (arg, 0);
tree type = TREE_TYPE (arg); if (TREE_CODE (type) == ARRAY_TYPE && TREE_CODE (type) != INTEGER_TYPE) return NULL_TREE; } the condition TREE_CODE(type) == ARRAY_TYPE && TREE_CODE (type) != INTEGER_TYPE looks funny. Check for ARRAY_TYPE should imply != INTEGER_TYPE. else if (DECL_P (arg)) { array = arg; chartype = TREE_TYPE (arg); } chartype is only used in the if (varidx) block, but that is always zero in this case. while (TREE_CODE (chartype) == ARRAY_TYPE || TREE_CODE (chartype) == POINTER_TYPE) chartype = TREE_TYPE (chartype); you multiply sizeof(chartype) with varidx but you should probably use the type of the TREE_OPERAND (arg, 0); above instead. this is not in the patch, but I dont like it at all, because it compares the size of a single initializer against the full size of the array. But it should be the innermost enclosing array: tree array_size = DECL_SIZE_UNIT (array); if (!array_size || TREE_CODE (array_size) != INTEGER_CST) return NULL_TREE; /* Avoid returning a string that doesn't fit in the array it is stored in, like const char a[4] = "abcde"; but do handle those that fit even if they have excess initializers, such as in const char a[4] = "abc\000\000"; The excess elements contribute to TREE_STRING_LENGTH() but not to strlen(). */ unsigned HOST_WIDE_INT length = strnlen (TREE_STRING_POINTER (init), TREE_STRING_LENGTH (init)); if (compare_tree_int (array_size, length + 1) < 0) return NULL_TREE; consider the following test case: $ cat part.c const char a[2][3][8] = { { "a", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", "ccc"}, { "dddd", "eeeee", "ffffff" } }; int main () { int n = __builtin_strlen (&a[0][1][0]); if (n == 30) __builtin_abort (); } 11413 if (!init || TREE_CODE (init) != STRING_CST) (gdb) call debug(init) "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" (gdb) n 11416 tree array_size = DECL_SIZE_UNIT (array); (gdb) n 11417 if (!array_size || TREE_CODE (array_size) != INTEGER_CST) (gdb) call debug(array_size) 48 (gdb) n 11429 = strnlen (TREE_STRING_POINTER (init), TREE_STRING_LENGTH (init)); (gdb) n 11430 if (compare_tree_int (array_size, length + 1) < 0) (gdb) n 11433 *ptr_offset = offset; (gdb) Bernd.