diff options
author | jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4> | 2015-04-28 14:43:59 +0000 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2016-01-21 11:28:41 -0800 |
commit | 98febdaccce0bb84594056065cc9c642e6f47610 (patch) | |
tree | 939976213d98b5e80a28460d1b21ad08ba2f5944 | |
parent | 440dcd8dd089f0e255c8fcb009c70c3c90ad499c (diff) | |
download | gcc-hjl/pr65656/gcc-5-branch.tar.gz |
Fix C++ __builtin_constant_phjl/pr65656/gcc-5-branch
We have two desires for interaction of __builtin_constant_p with
constexpr: 1) it should be a constant-expression even if its operands
are not, and 2) we shouldn't fold it to false prematurely when parsing a
constexpr function (c++/54021). We were having trouble with both of
these, and this patch fixes #1 without breaking #2.
gcc/cp/
Backport from mainline
2015-04-28 Jason Merrill <jason@redhat.com>
PR c++/65656
* constexpr.c (cxx_eval_builtin_function_call): Fix
__builtin_constant_p.
gcc/testsuite/
Backport from mainline
2015-04-28 Jason Merrill <jason@redhat.com>
PR c++/65656
* g++.dg/cpp0x/constexpr-builtin3.C: New test.
-rw-r--r-- | gcc/cp/constexpr.c | 32 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/constexpr-builtin3.C | 6 |
2 files changed, 28 insertions, 10 deletions
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 4ca99e80550..3c9362eccda 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -1024,7 +1024,7 @@ lookup_parameter_binding (const constexpr_call *call, tree t) represented by _CST nodes. */ static tree -cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, +cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun, bool lval, bool *non_constant_p, bool *overflow_p) { @@ -1032,18 +1032,30 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree *args = (tree *) alloca (nargs * sizeof (tree)); tree new_call; int i; - for (i = 0; i < nargs; ++i) + + /* Don't fold __builtin_constant_p within a constexpr function. */ + if (DECL_FUNCTION_CODE (fun) == BUILT_IN_CONSTANT_P + && current_function_decl + && DECL_DECLARED_CONSTEXPR_P (current_function_decl)) { - args[i] = cxx_eval_constant_expression (ctx, CALL_EXPR_ARG (t, i), - lval, - non_constant_p, overflow_p); - if (ctx->quiet && *non_constant_p) - return t; + *non_constant_p = true; + return t; } - if (*non_constant_p) - return t; + + /* Be permissive for arguments to built-ins; __builtin_constant_p should + return constant false for a non-constant argument. */ + constexpr_ctx new_ctx = *ctx; + new_ctx.quiet = true; + bool dummy1 = false, dummy2 = false; + for (i = 0; i < nargs; ++i) + args[i] = cxx_eval_constant_expression (&new_ctx, CALL_EXPR_ARG (t, i), + lval, &dummy1, &dummy2); + + bool save_ffbcp = force_folding_builtin_constant_p; + force_folding_builtin_constant_p = true; new_call = fold_build_call_array_loc (EXPR_LOCATION (t), TREE_TYPE (t), CALL_EXPR_FN (t), nargs, args); + force_folding_builtin_constant_p = save_ffbcp; VERIFY_CONSTANT (new_call); return new_call; } @@ -1226,7 +1238,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, return void_node; if (is_builtin_fn (fun)) - return cxx_eval_builtin_function_call (ctx, t, + return cxx_eval_builtin_function_call (ctx, t, fun, lval, non_constant_p, overflow_p); if (!DECL_DECLARED_CONSTEXPR_P (fun)) { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-builtin3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-builtin3.C new file mode 100644 index 00000000000..3582525c12d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-builtin3.C @@ -0,0 +1,6 @@ +// PR c++/65656 +// { dg-options "-std=c++11 -O" } + +int main(int argc, char *argv[]) { + constexpr bool x = __builtin_constant_p(argc); +} |