aboutsummaryrefslogtreecommitdiff
path: root/gcc/builtins.c
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2016-06-08 19:03:17 +0000
committerJakub Jelinek <jakub@gcc.gnu.org>2016-06-08 21:03:17 +0200
commit44a845ca0e592ca187fbab07ac9e055b20fb11cc (patch)
tree3a15f43474585970a2b22a98bf6ff1b46fcf075f /gcc/builtins.c
parent379aea728edb345f42b19dfade5529f8f9e8a6da (diff)
downloadgcc-44a845ca0e592ca187fbab07ac9e055b20fb11cc.zip
gcc-44a845ca0e592ca187fbab07ac9e055b20fb11cc.tar.gz
gcc-44a845ca0e592ca187fbab07ac9e055b20fb11cc.tar.bz2
re PR c++/70507 (integer overflow builtins not constant expressions)
PR c++/70507 PR c/68120 * builtins.def (BUILT_IN_ADD_OVERFLOW_P, BUILT_IN_SUB_OVERFLOW_P, BUILT_IN_MUL_OVERFLOW_P): New builtins. * builtins.c: Include gimple-fold.h. (fold_builtin_arith_overflow): Handle BUILT_IN_{ADD,SUB,MUL}_OVERFLOW_P. (fold_builtin_3): Likewise. * doc/extend.texi (Integer Overflow Builtins): Document __builtin_{add,sub,mul}_overflow_p. gcc/c/ * c-typeck.c (convert_arguments): Don't promote last argument of BUILT_IN_{ADD,SUB,MUL}_OVERFLOW_P. gcc/cp/ * constexpr.c: Include gimple-fold.h. (cxx_eval_internal_function): New function. (cxx_eval_call_expression): Call it. (potential_constant_expression_1): Handle integer arithmetic overflow built-ins. * tree.c (builtin_valid_in_constant_expr_p): Handle BUILT_IN_{ADD,SUB,MUL}_OVERFLOW_P. gcc/c-family/ * c-common.c (check_builtin_function_arguments): Handle BUILT_IN_{ADD,SUB,MUL}_OVERFLOW_P. gcc/testsuite/ * c-c++-common/builtin-arith-overflow-1.c: Add test cases. * c-c++-common/builtin-arith-overflow-2.c: New test. * g++.dg/ext/builtin-arith-overflow-1.C: New test. * g++.dg/cpp0x/constexpr-arith-overflow.C: New test. * g++.dg/cpp1y/constexpr-arith-overflow.C: New test. Co-Authored-By: Jakub Jelinek <jakub@redhat.com> From-SVN: r237238
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r--gcc/builtins.c54
1 files changed, 51 insertions, 3 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c
index d519176..5d234a5 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -64,6 +64,7 @@ along with GCC; see the file COPYING3. If not see
#include "rtl-chkp.h"
#include "internal-fn.h"
#include "case-cfn-macros.h"
+#include "gimple-fold.h"
struct target_builtins default_target_builtins;
@@ -7943,18 +7944,28 @@ fold_builtin_unordered_cmp (location_t loc, tree fndecl, tree arg0, tree arg1,
/* Fold __builtin_{,s,u}{add,sub,mul}{,l,ll}_overflow, either into normal
arithmetics if it can never overflow, or into internal functions that
return both result of arithmetics and overflowed boolean flag in
- a complex integer result, or some other check for overflow. */
+ a complex integer result, or some other check for overflow.
+ Similarly fold __builtin_{add,sub,mul}_overflow_p to just the overflow
+ checking part of that. */
static tree
fold_builtin_arith_overflow (location_t loc, enum built_in_function fcode,
tree arg0, tree arg1, tree arg2)
{
enum internal_fn ifn = IFN_LAST;
- tree type = TREE_TYPE (TREE_TYPE (arg2));
- tree mem_arg2 = build_fold_indirect_ref_loc (loc, arg2);
+ /* The code of the expression corresponding to the type-generic
+ built-in, or ERROR_MARK for the type-specific ones. */
+ enum tree_code opcode = ERROR_MARK;
+ bool ovf_only = false;
+
switch (fcode)
{
+ case BUILT_IN_ADD_OVERFLOW_P:
+ ovf_only = true;
+ /* FALLTHRU */
case BUILT_IN_ADD_OVERFLOW:
+ opcode = PLUS_EXPR;
+ /* FALLTHRU */
case BUILT_IN_SADD_OVERFLOW:
case BUILT_IN_SADDL_OVERFLOW:
case BUILT_IN_SADDLL_OVERFLOW:
@@ -7963,7 +7974,12 @@ fold_builtin_arith_overflow (location_t loc, enum built_in_function fcode,
case BUILT_IN_UADDLL_OVERFLOW:
ifn = IFN_ADD_OVERFLOW;
break;
+ case BUILT_IN_SUB_OVERFLOW_P:
+ ovf_only = true;
+ /* FALLTHRU */
case BUILT_IN_SUB_OVERFLOW:
+ opcode = MINUS_EXPR;
+ /* FALLTHRU */
case BUILT_IN_SSUB_OVERFLOW:
case BUILT_IN_SSUBL_OVERFLOW:
case BUILT_IN_SSUBLL_OVERFLOW:
@@ -7972,7 +7988,12 @@ fold_builtin_arith_overflow (location_t loc, enum built_in_function fcode,
case BUILT_IN_USUBLL_OVERFLOW:
ifn = IFN_SUB_OVERFLOW;
break;
+ case BUILT_IN_MUL_OVERFLOW_P:
+ ovf_only = true;
+ /* FALLTHRU */
case BUILT_IN_MUL_OVERFLOW:
+ opcode = MULT_EXPR;
+ /* FALLTHRU */
case BUILT_IN_SMUL_OVERFLOW:
case BUILT_IN_SMULL_OVERFLOW:
case BUILT_IN_SMULLL_OVERFLOW:
@@ -7984,6 +8005,25 @@ fold_builtin_arith_overflow (location_t loc, enum built_in_function fcode,
default:
gcc_unreachable ();
}
+
+ /* For the "generic" overloads, the first two arguments can have different
+ types and the last argument determines the target type to use to check
+ for overflow. The arguments of the other overloads all have the same
+ type. */
+ tree type = ovf_only ? TREE_TYPE (arg2) : TREE_TYPE (TREE_TYPE (arg2));
+
+ /* For the __builtin_{add,sub,mul}_overflow_p builtins, when the first two
+ arguments are constant, attempt to fold the built-in call into a constant
+ expression indicating whether or not it detected an overflow. */
+ if (ovf_only
+ && TREE_CODE (arg0) == INTEGER_CST
+ && TREE_CODE (arg1) == INTEGER_CST)
+ /* Perform the computation in the target type and check for overflow. */
+ return omit_one_operand_loc (loc, boolean_type_node,
+ arith_overflowed_p (opcode, type, arg0, arg1)
+ ? boolean_true_node : boolean_false_node,
+ arg2);
+
tree ctype = build_complex_type (type);
tree call = build_call_expr_internal_loc (loc, ifn, ctype,
2, arg0, arg1);
@@ -7991,6 +8031,11 @@ fold_builtin_arith_overflow (location_t loc, enum built_in_function fcode,
tree intres = build1_loc (loc, REALPART_EXPR, type, tgt);
tree ovfres = build1_loc (loc, IMAGPART_EXPR, type, tgt);
ovfres = fold_convert_loc (loc, boolean_type_node, ovfres);
+
+ if (ovf_only)
+ return omit_one_operand_loc (loc, boolean_type_node, ovfres, arg2);
+
+ tree mem_arg2 = build_fold_indirect_ref_loc (loc, arg2);
tree store
= fold_build2_loc (loc, MODIFY_EXPR, void_type_node, mem_arg2, intres);
return build2_loc (loc, COMPOUND_EXPR, boolean_type_node, store, ovfres);
@@ -8340,6 +8385,9 @@ fold_builtin_3 (location_t loc, tree fndecl,
case BUILT_IN_ADD_OVERFLOW:
case BUILT_IN_SUB_OVERFLOW:
case BUILT_IN_MUL_OVERFLOW:
+ case BUILT_IN_ADD_OVERFLOW_P:
+ case BUILT_IN_SUB_OVERFLOW_P:
+ case BUILT_IN_MUL_OVERFLOW_P:
case BUILT_IN_SADD_OVERFLOW:
case BUILT_IN_SADDL_OVERFLOW:
case BUILT_IN_SADDLL_OVERFLOW: