+2015-11-16 Jason Merrill <jason@redhat.com>
+
+ * constexpr.c (cxx_eval_builtin_function_call): Use cp_fully_fold
+ to fold arguments to __builtin_constant_p.
+
2015-11-16 Kirill Yukhin <kirill.yukhin@intel.com>
* parser.c (cp_parser_late_parsing_cilk_simd_fn_info): Look for
int i;
/* Don't fold __builtin_constant_p within a constexpr function. */
- if (DECL_FUNCTION_CODE (fun) == BUILT_IN_CONSTANT_P
+ bool bi_const_p = (DECL_FUNCTION_CODE (fun) == BUILT_IN_CONSTANT_P);
+
+ if (bi_const_p
&& current_function_decl
&& DECL_DECLARED_CONSTEXPR_P (current_function_decl))
{
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);
+ {
+ args[i] = cxx_eval_constant_expression (&new_ctx, CALL_EXPR_ARG (t, i),
+ lval, &dummy1, &dummy2);
+ if (bi_const_p)
+ /* For __built_in_constant_p, fold all expressions with constant values
+ even if they aren't C++ constant-expressions. */
+ args[i] = cp_fully_fold (args[i]);
+ }
bool save_ffbcp = force_folding_builtin_constant_p;
force_folding_builtin_constant_p = true;
int i, m, sv = optimize, nw = sv, changed = 0;
tree callee = get_callee_fndecl (x);
+ /* Some built-in function calls will be evaluated at compile-time in
+ fold (). Set optimize to 1 when folding __builtin_constant_p inside
+ a constexpr function so that fold_builtin_1 doesn't fold it to 0. */
if (callee && DECL_BUILT_IN (callee) && !optimize
&& DECL_IS_BUILTIN_CONSTANT_P (callee)
&& current_function_decl
&& DECL_DECLARED_CONSTEXPR_P (current_function_decl))
nw = 1;
- optimize = nw;
- r = fold (x);
- optimize = sv;
-
- if (TREE_CODE (r) != CALL_EXPR)
- {
- x = cp_fold (r);
- break;
- }
x = copy_node (x);
optimize = nw;
- /* Invoke maybe_constant_value for functions being declared
- constexpr, and are no AGGR_INIT_EXPRs ...
+ /* Invoke maybe_constant_value for functions declared
+ constexpr and not called with AGGR_INIT_EXPRs.
TODO:
- Due issues in maybe_constant_value for CALL_EXPR with
- arguments passed by reference, it is disabled. */
+ Do constexpr expansion of expressions where the call itself is not
+ constant, but the call followed by an INDIRECT_REF is. */
if (callee && DECL_DECLARED_CONSTEXPR_P (callee))
r = maybe_constant_value (x);
optimize = sv;
--- /dev/null
+// { dg-do compile { target c++11 } }
+
+#define SA(X) static_assert ((X),#X)
+
+int i;
+
+SA(__builtin_constant_p (i == 42 && false));
--- /dev/null
+// { dg-do run }
+
+int i;
+
+#define CV(X) (__builtin_constant_p (X) ? (X) : -1)
+
+int ar[] = { CV (i == 42 && false) };
+
+int main()
+{
+ if (ar[0] != 0)
+ __builtin_abort();
+}