diff options
author | Jakub Jelinek <jakub@redhat.com> | 2016-12-06 10:23:51 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2016-12-06 10:23:51 +0100 |
commit | 66972191ee05c5dd2d02e5d062fe1c942e42fcd7 (patch) | |
tree | 7a92a285d47f865cf7dc7522c6b591159d6a2013 /gcc | |
parent | bf2d0849a360376182b796042fedaa018b87d605 (diff) | |
download | gcc-66972191ee05c5dd2d02e5d062fe1c942e42fcd7.zip gcc-66972191ee05c5dd2d02e5d062fe1c942e42fcd7.tar.gz gcc-66972191ee05c5dd2d02e5d062fe1c942e42fcd7.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/fold-const-call.c | 100 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 3 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/constexpr-memchr.C | 24 |
4 files changed, 81 insertions, 54 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 029dbdc..9ed8f5f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,6 +1,14 @@ 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}. diff --git a/gcc/fold-const-call.c b/gcc/fold-const-call.c index 439988d..c85fb41 100644 --- a/gcc/fold-const-call.c +++ b/gcc/fold-const-call.c @@ -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); } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e6dfcdc..b44993b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,6 +1,9 @@ 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. PR tree-optimization/78675 diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-memchr.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-memchr.C new file mode 100644 index 0000000..e5c07f1 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-memchr.C @@ -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, ""); |