Hi! Kees, any progress on this?
On Mon, Jan 06, 2025 at 04:34:27PM -0500, Marek Polacek wrote: > > - pedwarn_init (init_loc, 0, > > - ("initializer-string for array of %qT " > > - "is too long"), typ1); > > - else if (warn_unterminated_string_initialization > > - && compare_tree_int (TYPE_SIZE_UNIT (type), len) < 0) > > - warning_at (init_loc, OPT_Wunterminated_string_initialization, > > - ("initializer-string for array of %qT " > > - "is too long"), typ1); > > + > > if (compare_tree_int (TYPE_SIZE_UNIT (type), len) < 0) > > { > > - unsigned HOST_WIDE_INT size > > - = tree_to_uhwi (TYPE_SIZE_UNIT (type)); > > - const char *p = TREE_STRING_POINTER (inside_init); > > - > > - inside_init = build_string (size, p); > > + unsigned HOST_WIDE_INT avail > > + = tree_to_uhwi (TYPE_SIZE_UNIT (type)); > > + unsigned unit = TYPE_PRECISION (typ1) / BITS_PER_UNIT; > > + const char *p = TREE_STRING_POINTER (inside_init); > > + > > + /* Construct truncated string. */ > > + inside_init = build_string (avail, p); > > + > > + /* Subtract the size of a single (possibly wide) character > > + because it may be ok to ignore the terminating NUL char > > + that is counted in the length of the constant. */ > > + if (warn_cxx_compat || len - unit > avail) > > + { > > + pedwarn_init (init_loc, 0, > > + ("initializer-string for array of %qT " > > + "is too long (%lu chars into %lu " > > + "available)"), typ1, len, avail); > > + } > > No need for the { } here. The indentation is wrong in the whole block. The { after compare_tree_int is indented by 2 tabs (so 16 columns), but unsigned HOST_WIDE_INT avail already by 2 tabs and 3 spaces rather than 2 tabs and 2 spaces. So it is one column more right than it should be. Anyway, more importantly, the "warn_cxx_compat || " part looks wrong. For -Wc++-compat we should (perhaps with slightly different wording) preserve the GCC 14 behavior, which was /* Subtract the size of a single (possibly wide) character because it's ok to ignore the terminating null char that is counted in the length of the constant. */ if (compare_tree_int (TYPE_SIZE_UNIT (type), len - unit) < 0) pedwarn_init (init_loc, 0, ("initializer-string for array of %qT " "is too long"), typ1); else if (warn_cxx_compat && compare_tree_int (TYPE_SIZE_UNIT (type), len) < 0) warning_at (init_loc, OPT_Wc___compat, ("initializer-string for array of %qT " "is too long for C++"), typ1); So, if (len - unit > avail) do the pedwarn_init (also note that %lu is wrong for unsigned HOST_WIDE_INT, one should use %wu instead; or for the avail case one could just print %E and pass it TYPE_SIZE_UNIT (type); unsigned HOST_WIDE_INT doesn't have to be unsigned long, it can be also unsigned long long). And if warn_cxx_compat, do warning_at, IMNSHO with OPT_Wc___compat, with the "is too long for C++" substring in it and perhaps some more details (len and avail too). Though, perhaps we should also change C ObjC Var(warn_unterminated_string_initialization) Warning LangEnabledBy(C ObjC,Wextra || Wc++-compat) to C ObjC Var(warn_unterminated_string_initialization) Warning LangEnabledBy(C ObjC,Wextra) and adjust documentation, because say -Wno-unterminated-string-initialization will no longer turn off that warning, essentially -Wc++-compat and -Wunterminated-string-initialization are then independent warnings with -Wc++-compat having priority over the latter. Or we could guard it with warn_cxx_compat && warn_unterminated_string_initialization but then the question is what to pass to second warning_at option, because one needs both. So, I think it is better to keep -Wc++-compat working as before (perhaps with the extra descriptions of the two lengths) and then have this new -Wunterminated-string-initialization warning implied by -Wextra which does nothing in the rare case when -Wc++-compat is on, and otherwise does the new stuff of warning except when initializing nonstring objects. Jakub