re PR c++/71537 (GCC rejects consetxpr boolean conversions and comparisons on the result of pointer arithmetic.)
2016-12-06 Jakub Jelinek <jakub@redhat.com> PR c++/71537 * fold-const-call.c (fold_const_call_1): Remove memchr handling here. (fold_const_call) <case CFN_BUILT_IN_STRNCMP, case CFN_BUILT_IN_STRNCASECMP>: Formatting improvements. (fold_const_call) <case CFN_BUILT_IN_MEMCMP>: Likewise. If s2 is 0 and arguments have no side-effects, return 0. (fold_const_call): Handle CFN_BUILT_IN_MEMCHR. * g++.dg/cpp0x/constexpr-memchr.C: New test. From-SVN: r243285
This commit is contained in:
parent
bf2d0849a3
commit
66972191ee
|
@ -1,5 +1,13 @@
|
|||
2016-12-06 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c++/71537
|
||||
* fold-const-call.c (fold_const_call_1): Remove memchr handling here.
|
||||
(fold_const_call) <case CFN_BUILT_IN_STRNCMP,
|
||||
case CFN_BUILT_IN_STRNCASECMP>: Formatting improvements.
|
||||
(fold_const_call) <case CFN_BUILT_IN_MEMCMP>: Likewise. If s2 is 0
|
||||
and arguments have no side-effects, return 0.
|
||||
(fold_const_call): Handle CFN_BUILT_IN_MEMCHR.
|
||||
|
||||
PR c++/71537
|
||||
* fold-const-call.c (fold_const_call): Handle
|
||||
CFN_BUILT_IN_{INDEX,STRCHR,RINDEX,STRRCHR}.
|
||||
|
|
|
@ -1491,36 +1491,6 @@ fold_const_call_1 (combined_fn fn, tree type, tree arg0, tree arg1, tree arg2)
|
|||
return NULL_TREE;
|
||||
}
|
||||
|
||||
switch (fn)
|
||||
{
|
||||
case CFN_BUILT_IN_MEMCHR:
|
||||
{
|
||||
char c;
|
||||
if (integer_zerop (arg2)
|
||||
&& !TREE_SIDE_EFFECTS (arg0)
|
||||
&& !TREE_SIDE_EFFECTS (arg1))
|
||||
return build_int_cst (type, 0);
|
||||
|
||||
if (!tree_fits_uhwi_p (arg2) || !target_char_cst_p (arg1, &c))
|
||||
return NULL_TREE;
|
||||
|
||||
unsigned HOST_WIDE_INT length = tree_to_uhwi (arg2);
|
||||
unsigned HOST_WIDE_INT string_length;
|
||||
const char *p1 = c_getstr (arg0, &string_length);
|
||||
if (p1)
|
||||
{
|
||||
const char *r
|
||||
= (const char *)memchr (p1, c, MIN (length, string_length));
|
||||
if (r == NULL && length <= string_length)
|
||||
return build_int_cst (type, 0);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
|
@ -1531,47 +1501,69 @@ tree
|
|||
fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1, tree arg2)
|
||||
{
|
||||
const char *p0, *p1;
|
||||
char c;
|
||||
unsigned HOST_WIDE_INT s0, s1;
|
||||
size_t s2 = 0;
|
||||
switch (fn)
|
||||
{
|
||||
case CFN_BUILT_IN_STRNCMP:
|
||||
{
|
||||
bool const_size_p = host_size_t_cst_p (arg2, &s2);
|
||||
if (const_size_p && s2 == 0
|
||||
&& !TREE_SIDE_EFFECTS (arg0)
|
||||
&& !TREE_SIDE_EFFECTS (arg1))
|
||||
return build_int_cst (type, 0);
|
||||
else if (const_size_p
|
||||
&& (p0 = c_getstr (arg0))
|
||||
&& (p1 = c_getstr (arg1)))
|
||||
return build_int_cst (type, strncmp (p0, p1, s2));
|
||||
if (!host_size_t_cst_p (arg2, &s2))
|
||||
return NULL_TREE;
|
||||
}
|
||||
if (s2 == 0
|
||||
&& !TREE_SIDE_EFFECTS (arg0)
|
||||
&& !TREE_SIDE_EFFECTS (arg1))
|
||||
return build_int_cst (type, 0);
|
||||
else if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
|
||||
return build_int_cst (type, strncmp (p0, p1, s2));
|
||||
return NULL_TREE;
|
||||
|
||||
case CFN_BUILT_IN_STRNCASECMP:
|
||||
{
|
||||
bool const_size_p = host_size_t_cst_p (arg2, &s2);
|
||||
if (const_size_p && s2 == 0
|
||||
&& !TREE_SIDE_EFFECTS (arg0)
|
||||
&& !TREE_SIDE_EFFECTS (arg1))
|
||||
return build_int_cst (type, 0);
|
||||
else if (const_size_p
|
||||
&& (p0 = c_getstr (arg0))
|
||||
&& (p1 = c_getstr (arg1))
|
||||
&& strncmp (p0, p1, s2) == 0)
|
||||
return build_int_cst (type, 0);
|
||||
if (!host_size_t_cst_p (arg2, &s2))
|
||||
return NULL_TREE;
|
||||
}
|
||||
if (s2 == 0
|
||||
&& !TREE_SIDE_EFFECTS (arg0)
|
||||
&& !TREE_SIDE_EFFECTS (arg1))
|
||||
return build_int_cst (type, 0);
|
||||
else if ((p0 = c_getstr (arg0))
|
||||
&& (p1 = c_getstr (arg1))
|
||||
&& strncmp (p0, p1, s2) == 0)
|
||||
return build_int_cst (type, 0);
|
||||
return NULL_TREE;
|
||||
|
||||
case CFN_BUILT_IN_BCMP:
|
||||
case CFN_BUILT_IN_MEMCMP:
|
||||
if (!host_size_t_cst_p (arg2, &s2))
|
||||
return NULL_TREE;
|
||||
if (s2 == 0
|
||||
&& !TREE_SIDE_EFFECTS (arg0)
|
||||
&& !TREE_SIDE_EFFECTS (arg1))
|
||||
return build_int_cst (type, 0);
|
||||
if ((p0 = c_getstr (arg0, &s0))
|
||||
&& (p1 = c_getstr (arg1, &s1))
|
||||
&& host_size_t_cst_p (arg2, &s2)
|
||||
&& s2 <= s0
|
||||
&& s2 <= s1)
|
||||
return build_cmp_result (type, memcmp (p0, p1, s2));
|
||||
return NULL_TREE;
|
||||
|
||||
case CFN_BUILT_IN_MEMCHR:
|
||||
if (!host_size_t_cst_p (arg2, &s2))
|
||||
return NULL_TREE;
|
||||
if (s2 == 0
|
||||
&& !TREE_SIDE_EFFECTS (arg0)
|
||||
&& !TREE_SIDE_EFFECTS (arg1))
|
||||
return build_int_cst (type, 0);
|
||||
if ((p0 = c_getstr (arg0, &s0))
|
||||
&& s2 <= s0
|
||||
&& target_char_cst_p (arg1, &c))
|
||||
{
|
||||
const char *r = (const char *) memchr (p0, c, s2);
|
||||
if (r == NULL)
|
||||
return build_int_cst (type, 0);
|
||||
return fold_convert (type,
|
||||
fold_build_pointer_plus_hwi (arg0, r - p0));
|
||||
}
|
||||
return NULL_TREE;
|
||||
|
||||
default:
|
||||
return fold_const_call_1 (fn, type, arg0, arg1, arg2);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
2016-12-06 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c++/71537
|
||||
* g++.dg/cpp0x/constexpr-memchr.C: New test.
|
||||
|
||||
PR c++/71537
|
||||
* g++.dg/cpp0x/constexpr-strchr.C: New test.
|
||||
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
// { dg-do compile { target c++11 } }
|
||||
|
||||
typedef decltype (sizeof (0)) size_t;
|
||||
constexpr const void *f1 (const char *p, int q) { return __builtin_memchr (p, q, __builtin_strlen (p) + 1); }
|
||||
constexpr const void *f2 (const char *p, int q, size_t r) { return __builtin_memchr (p, q, r); }
|
||||
constexpr const char a[] = "abcdefedcba";
|
||||
static_assert (f1 ("abcde", 'f') == nullptr, "");
|
||||
static_assert (f1 (a, 'g') == nullptr, "");
|
||||
static_assert (f1 (a, 'f') == a + 5, "");
|
||||
static_assert (f1 (a, 'c') == a + 2, "");
|
||||
static_assert (f1 (a, '\0') == a + 11, "");
|
||||
static_assert (f2 ("abcde", 'f', 6) == nullptr, "");
|
||||
static_assert (f2 ("abcde", 'f', 1) == nullptr, "");
|
||||
static_assert (f2 ("abcde", 'f', 0) == nullptr, "");
|
||||
static_assert (f2 (a, 'g', 7) == nullptr, "");
|
||||
static_assert (f2 (a, 'g', 0) == nullptr, "");
|
||||
static_assert (f2 (a, 'f', 6) == a + 5, "");
|
||||
static_assert (f2 (a, 'f', 5) == nullptr, "");
|
||||
static_assert (f2 (a, 'c', 12) == a + 2, "");
|
||||
static_assert (f2 (a, 'c', 3) == a + 2, "");
|
||||
static_assert (f2 (a, 'c', 2) == nullptr, "");
|
||||
static_assert (f2 (a, '\0', 12) == a + 11, "");
|
||||
static_assert (f2 (a, '\0', 11) == nullptr, "");
|
||||
static_assert (f2 (a, '\0', 0) == nullptr, "");
|
Loading…
Reference in New Issue