On 07/26/2018 02:53 AM, Bernd Edlinger wrote:
@@ -567,13 +597,17 @@ string_length (const void *ptr, unsigned eltsize,
unsigned maxelts)
accesses. Note that this implies the result is not going to be emitted
into the instruction stream.
+ When ARR is non-null and the string is not properly nul-terminated,
+ set *ARR to the declaration of the outermost constant object whose
+ initializer (or one of its elements) is not nul-terminated.
+
The value returned is of type `ssizetype'.
Unfortunately, string_constant can't access the values of const char
arrays with initializers, so neither can we do so here. */
Maybe drop that sentence when it is no longer true?
I believe the sentence means is that folding the length of arrays
like this isn't handled:
const char a[] = { 'a', 'b', '\0' };
because they are represented not as STRING_CST but rather as
aggregate CONSTRUCTORs.
Adding this handling has been something I've been meaning to
do for some time and this seems like a good opportunity to do
it. I'm testing a patch with this enhancement.
tree
-c_strlen (tree src, int only_value)
+c_strlen (tree src, int only_value, tree *arr /* = NULL */)
{
STRIP_NOPS (src);
if (TREE_CODE (src) == COND_EXPR
@@ -581,24 +615,31 @@ c_strlen (tree src, int only_value)
{
tree len1, len2;
- len1 = c_strlen (TREE_OPERAND (src, 1), only_value);
- len2 = c_strlen (TREE_OPERAND (src, 2), only_value);
+ len1 = c_strlen (TREE_OPERAND (src, 1), only_value, arr);
+ len2 = c_strlen (TREE_OPERAND (src, 2), only_value, arr);
Wow, what happens here if the first operand is non-zero terminated and the
second is zero-terminated?
It depends on the size of the first array and on the length
of the second. This test case triggers a warning:
const char a[2][3] = { "123", "12" };
int f (int i)
{
return __builtin_strlen (i < 0 ? a[0] : a[1]);
}
warning: ‘__builtin_strlen’ argument missing terminating nul
[-Wstringop-overflow=]
note: referenced argument declared here
const char a[2][3] = { "123", "12" };
^
but this one didn't:
const char a[3] = "123";
const char b[4] = "123";
int f (int i)
{
return __builtin_strlen (i < 0 ? a : b);
}
The usual arguments both for and against issuing a diagnostic
here apply but I think it makes more sense to err on the side
of caution and diagnose them than not so I enhanced the patch
to do that, as well as handle a few more strlen contexts.
Martin