From 69eb4fde588c5c2e4e206aeba9a5a17fcaf5cecb Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Wed, 19 Nov 2014 17:06:17 -0500 Subject: [PATCH] re PR c++/57979 (G++ accepts constant expression defined using floating point non-constexpr glvalue) PR c++/57979 * init.c (decl_really_constant_value): Rename from integral_constant_value. (scalar_constant_value): Similar but limited to scalar results. (decl_constant_value_safe): Remove. (constant_value_1): Respect return_aggregate_cst_ok_p. * typeck.c (decay_conversion): Use scalar_constant_value. * call.c (convert_like_real): Likewise. * cvt.c (ocp_convert): No need to check CLASS_TYPE_P. * typeck.c (decay_conversion): Or ARRAY_TYPE. * constexpr.c (struct constexpr_ctx): Add strict field. (cxx_eval_constant_expression) [VAR_DECL]: Use it to select between decl_constant_value and decl_really_constant_value. (cxx_eval_outermost_constant_expr): Add strict parm. (maybe_constant_init): Not strict. (potential_constant_expression_1): Add strict parm. Shorten most internal calls with RECUR macro. * cp-tree.h, pt.c, semantics.c: Adjust. From-SVN: r217814 --- gcc/cp/ChangeLog | 21 +++ gcc/cp/call.c | 2 +- gcc/cp/constexpr.c | 167 +++++++++--------- gcc/cp/cp-tree.h | 5 +- gcc/cp/cvt.c | 4 +- gcc/cp/decl.c | 2 +- gcc/cp/init.c | 39 ++-- gcc/cp/pt.c | 6 +- gcc/cp/semantics.c | 2 +- gcc/cp/typeck.c | 15 +- .../g++.dg/cpp0x/constexpr-object2.C | 4 +- gcc/testsuite/g++.dg/cpp0x/nullptr06.C | 2 +- 12 files changed, 144 insertions(+), 125 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ac4d2a53f25..6f947b4b811 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,24 @@ +2014-11-19 Jason Merrill + + PR c++/57979 + * init.c (decl_really_constant_value): Rename from + integral_constant_value. + (scalar_constant_value): Similar but limited to scalar results. + (decl_constant_value_safe): Remove. + (constant_value_1): Respect return_aggregate_cst_ok_p. + * typeck.c (decay_conversion): Use scalar_constant_value. + * call.c (convert_like_real): Likewise. + * cvt.c (ocp_convert): No need to check CLASS_TYPE_P. + * typeck.c (decay_conversion): Or ARRAY_TYPE. + * constexpr.c (struct constexpr_ctx): Add strict field. + (cxx_eval_constant_expression) [VAR_DECL]: Use it to select between + decl_constant_value and decl_really_constant_value. + (cxx_eval_outermost_constant_expr): Add strict parm. + (maybe_constant_init): Not strict. + (potential_constant_expression_1): Add strict parm. + Shorten most internal calls with RECUR macro. + * cp-tree.h, pt.c, semantics.c: Adjust. + 2014-11-19 Jason Merrill PR c++/63928 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index c180890b965..5cda1b1ee2b 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -6247,7 +6247,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, leave it as an lvalue. */ if (inner >= 0) { - expr = decl_constant_value_safe (expr); + expr = scalar_constant_value (expr); if (expr == null_node && INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (totype)) /* If __null has been converted to an integer type, we do not want to warn about uses of EXPR as an integer, rather than diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 77f5159a0fd..52685450edf 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -869,6 +869,7 @@ struct constexpr_ctx { tree ctor; tree object; bool quiet; + bool strict; }; /* A table of all constexpr calls that have been evaluated by the @@ -2818,7 +2819,10 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, return t; /* else fall through. */ case CONST_DECL: - r = integral_constant_value (t); + if (ctx->strict) + r = decl_really_constant_value (t); + else + r = decl_constant_value (t); if (TREE_CODE (r) == TARGET_EXPR && TREE_CODE (TARGET_EXPR_INITIAL (r)) == CONSTRUCTOR) r = TARGET_EXPR_INITIAL (r); @@ -3302,11 +3306,11 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, static tree cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant, - tree object = NULL_TREE) + bool strict = true, tree object = NULL_TREE) { bool non_constant_p = false; bool overflow_p = false; - constexpr_ctx ctx = { NULL, NULL, NULL, NULL, allow_non_constant }; + constexpr_ctx ctx = { NULL, NULL, NULL, NULL, allow_non_constant, strict }; hash_map map; ctx.values = ↦ tree type = initialized_type (t); @@ -3415,7 +3419,7 @@ is_sub_constant_expr (tree t) { bool non_constant_p = false; bool overflow_p = false; - constexpr_ctx ctx = { NULL, NULL, NULL, NULL, true }; + constexpr_ctx ctx = { NULL, NULL, NULL, NULL, true, true }; hash_map map; ctx.values = ↦ cxx_eval_constant_expression (&ctx, t, false, &non_constant_p, @@ -3430,7 +3434,7 @@ is_sub_constant_expr (tree t) tree cxx_constant_value (tree t, tree decl) { - return cxx_eval_outermost_constant_expr (t, false, decl); + return cxx_eval_outermost_constant_expr (t, false, true, decl); } /* If T is a constant expression, returns its reduced value. @@ -3455,7 +3459,7 @@ maybe_constant_value (tree t, tree decl) return t; } - r = cxx_eval_outermost_constant_expr (t, true, decl); + r = cxx_eval_outermost_constant_expr (t, true, true, decl); #ifdef ENABLE_CHECKING /* cp_tree_equal looks through NOPs, so allow them. */ gcc_assert (r == t @@ -3515,7 +3519,7 @@ fold_non_dependent_expr (tree t) return t; } - tree r = cxx_eval_outermost_constant_expr (t, true, NULL_TREE); + tree r = cxx_eval_outermost_constant_expr (t, true, true, NULL_TREE); #ifdef ENABLE_CHECKING /* cp_tree_equal looks through NOPs, so allow them. */ gcc_assert (r == t @@ -3550,7 +3554,13 @@ maybe_constant_init (tree t, tree decl) t = TREE_OPERAND (t, 0); if (TREE_CODE (t) == INIT_EXPR) t = TREE_OPERAND (t, 1); - t = maybe_constant_value (t, decl); + if (instantiation_dependent_expression_p (t) + || type_unknown_p (t) + || BRACE_ENCLOSED_INITIALIZER_P (t) + || !potential_static_init_expression (t)) + /* Don't try to evaluate it. */; + else + t = cxx_eval_outermost_constant_expr (t, true, false, decl); if (TREE_CODE (t) == TARGET_EXPR) { tree init = TARGET_EXPR_INITIAL (t); @@ -3604,8 +3614,10 @@ check_automatic_or_tls (tree ref) not evaluated are not considered. */ static bool -potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) +potential_constant_expression_1 (tree t, bool want_rval, bool strict, + tsubst_flags_t flags) { +#define RECUR(T,RV) potential_constant_expression_1 ((T), (RV), strict, flags) enum { any = false, rval = true }; int i; tree tmp; @@ -3698,14 +3710,14 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) tree x = get_nth_callarg (t, 0); if (is_this_parameter (x)) return true; - else if (!potential_constant_expression_1 (x, rval, flags)) + else if (!RECUR (x, rval)) return false; i = 1; } } else { - if (!potential_constant_expression_1 (fun, true, flags)) + if (!RECUR (fun, true)) return false; fun = get_first_fn (fun); } @@ -3716,7 +3728,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) } else { - if (potential_constant_expression_1 (fun, rval, flags)) + if (RECUR (fun, rval)) /* Might end up being a constant function pointer. */; else return false; @@ -3724,7 +3736,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) for (; i < nargs; ++i) { tree x = get_nth_callarg (t, i); - if (!potential_constant_expression_1 (x, rval, flags)) + if (!RECUR (x, rval)) return false; } return true; @@ -3739,10 +3751,14 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) -- an lvalue of literal type that refers to non-volatile object defined with constexpr, or that refers to a sub-object of such an object; */ - return potential_constant_expression_1 (TREE_OPERAND (t, 0), rval, flags); + return RECUR (TREE_OPERAND (t, 0), rval); case VAR_DECL: - if (want_rval && !decl_constant_var_p (t) + if (want_rval + && !decl_constant_var_p (t) + && (strict + || !CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (t)) + || !DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (t)) && !var_in_constexpr_fn (t) && !dependent_type_p (TREE_TYPE (t))) { @@ -3768,8 +3784,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) "reinterpret_cast from integer to pointer"); return false; } - return (potential_constant_expression_1 - (from, TREE_CODE (t) != VIEW_CONVERT_EXPR, flags)); + return (RECUR (from, TREE_CODE (t) != VIEW_CONVERT_EXPR)); } case ADDR_EXPR: @@ -3797,7 +3812,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) return false; } #endif - return potential_constant_expression_1 (t, any, flags); + return RECUR (t, any); case COMPONENT_REF: case BIT_FIELD_REF: @@ -3807,12 +3822,10 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) of literal type or of pointer to literal type. */ /* This test would be redundant, as it follows from the postfix-expression being a potential constant expression. */ - return potential_constant_expression_1 (TREE_OPERAND (t, 0), - want_rval, flags); + return RECUR (TREE_OPERAND (t, 0), want_rval); case EXPR_PACK_EXPANSION: - return potential_constant_expression_1 (PACK_EXPANSION_PATTERN (t), - want_rval, flags); + return RECUR (PACK_EXPANSION_PATTERN (t), want_rval); case INDIRECT_REF: { @@ -3829,7 +3842,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) } return true; } - return potential_constant_expression_1 (x, rval, flags); + return RECUR (x, rval); } case STATEMENT_LIST: @@ -3837,7 +3850,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) tree_stmt_iterator i; for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i)) { - if (!potential_constant_expression_1 (tsi_stmt (i), any, flags)) + if (!RECUR (tsi_stmt (i), any)) return false; } return true; @@ -3847,64 +3860,64 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) case MODIFY_EXPR: if (cxx_dialect < cxx14) goto fail; - if (!potential_constant_expression_1 (TREE_OPERAND (t, 0), any, flags)) + if (!RECUR (TREE_OPERAND (t, 0), any)) return false; - if (!potential_constant_expression_1 (TREE_OPERAND (t, 1), rval, flags)) + if (!RECUR (TREE_OPERAND (t, 1), rval)) return false; return true; case MODOP_EXPR: if (cxx_dialect < cxx14) goto fail; - if (!potential_constant_expression_1 (TREE_OPERAND (t, 0), rval, flags)) + if (!RECUR (TREE_OPERAND (t, 0), rval)) return false; - if (!potential_constant_expression_1 (TREE_OPERAND (t, 2), rval, flags)) + if (!RECUR (TREE_OPERAND (t, 2), rval)) return false; return true; case IF_STMT: - if (!potential_constant_expression_1 (IF_COND (t), rval, flags)) + if (!RECUR (IF_COND (t), rval)) return false; - if (!potential_constant_expression_1 (THEN_CLAUSE (t), any, flags)) + if (!RECUR (THEN_CLAUSE (t), any)) return false; - if (!potential_constant_expression_1 (ELSE_CLAUSE (t), any, flags)) + if (!RECUR (ELSE_CLAUSE (t), any)) return false; return true; case DO_STMT: - if (!potential_constant_expression_1 (DO_COND (t), rval, flags)) + if (!RECUR (DO_COND (t), rval)) return false; - if (!potential_constant_expression_1 (DO_BODY (t), any, flags)) + if (!RECUR (DO_BODY (t), any)) return false; return true; case FOR_STMT: - if (!potential_constant_expression_1 (FOR_INIT_STMT (t), any, flags)) + if (!RECUR (FOR_INIT_STMT (t), any)) return false; - if (!potential_constant_expression_1 (FOR_COND (t), rval, flags)) + if (!RECUR (FOR_COND (t), rval)) return false; - if (!potential_constant_expression_1 (FOR_EXPR (t), any, flags)) + if (!RECUR (FOR_EXPR (t), any)) return false; - if (!potential_constant_expression_1 (FOR_BODY (t), any, flags)) + if (!RECUR (FOR_BODY (t), any)) return false; return true; case WHILE_STMT: - if (!potential_constant_expression_1 (WHILE_COND (t), rval, flags)) + if (!RECUR (WHILE_COND (t), rval)) return false; - if (!potential_constant_expression_1 (WHILE_BODY (t), any, flags)) + if (!RECUR (WHILE_BODY (t), any)) return false; return true; case SWITCH_STMT: - if (!potential_constant_expression_1 (SWITCH_STMT_COND (t), rval, flags)) + if (!RECUR (SWITCH_STMT_COND (t), rval)) return false; - if (!potential_constant_expression_1 (SWITCH_STMT_BODY (t), any, flags)) + if (!RECUR (SWITCH_STMT_BODY (t), any)) return false; return true; case STMT_EXPR: - return potential_constant_expression_1 (STMT_EXPR_STMT (t), rval, flags); + return RECUR (STMT_EXPR_STMT (t), rval); case LAMBDA_EXPR: case DYNAMIC_CAST_EXPR: @@ -4002,8 +4015,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) case FIXED_CONVERT_EXPR: case UNARY_PLUS_EXPR: unary: - return potential_constant_expression_1 (TREE_OPERAND (t, 0), rval, - flags); + return RECUR (TREE_OPERAND (t, 0), rval); case CAST_EXPR: case CONST_CAST_EXPR: @@ -4022,13 +4034,11 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) return false; } - return (potential_constant_expression_1 - (TREE_OPERAND (t, 0), - TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE, flags)); + return (RECUR (TREE_OPERAND (t, 0), + TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE)); case BIND_EXPR: - return potential_constant_expression_1 (BIND_EXPR_BODY (t), - want_rval, flags); + return RECUR (BIND_EXPR_BODY (t), want_rval); case WITH_CLEANUP_EXPR: case CLEANUP_POINT_EXPR: @@ -4041,12 +4051,10 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) case NON_DEPENDENT_EXPR: /* For convenience. */ case RETURN_EXPR: - return potential_constant_expression_1 (TREE_OPERAND (t, 0), - want_rval, flags); + return RECUR (TREE_OPERAND (t, 0), want_rval); case SCOPE_REF: - return potential_constant_expression_1 (TREE_OPERAND (t, 1), - want_rval, flags); + return RECUR (TREE_OPERAND (t, 1), want_rval); case TARGET_EXPR: if (!literal_type_p (TREE_TYPE (t))) @@ -4060,15 +4068,14 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) return false; } case INIT_EXPR: - return potential_constant_expression_1 (TREE_OPERAND (t, 1), - rval, flags); + return RECUR (TREE_OPERAND (t, 1), rval); case CONSTRUCTOR: { vec *v = CONSTRUCTOR_ELTS (t); constructor_elt *ce; for (i = 0; vec_safe_iterate (v, i, &ce); ++i) - if (!potential_constant_expression_1 (ce->value, want_rval, flags)) + if (!RECUR (ce->value, want_rval)) return false; return true; } @@ -4077,13 +4084,11 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) { gcc_assert (TREE_PURPOSE (t) == NULL_TREE || DECL_P (TREE_PURPOSE (t))); - if (!potential_constant_expression_1 (TREE_VALUE (t), want_rval, - flags)) + if (!RECUR (TREE_VALUE (t), want_rval)) return false; if (TREE_CHAIN (t) == NULL_TREE) return true; - return potential_constant_expression_1 (TREE_CHAIN (t), want_rval, - flags); + return RECUR (TREE_CHAIN (t), want_rval); } case TRUNC_DIV_EXPR: @@ -4095,7 +4100,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) case ROUND_MOD_EXPR: { tree denom = TREE_OPERAND (t, 1); - if (!potential_constant_expression_1 (denom, rval, flags)) + if (!RECUR (denom, rval)) return false; /* We can't call cxx_eval_outermost_constant_expr on an expression that hasn't been through instantiate_non_dependent_expr yet. */ @@ -4110,8 +4115,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) else { want_rval = true; - return potential_constant_expression_1 (TREE_OPERAND (t, 0), - want_rval, flags); + return RECUR (TREE_OPERAND (t, 0), want_rval); } } @@ -4125,7 +4129,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) STRIP_NOPS (op1); if ((TREE_CODE (op0) == TARGET_EXPR && op1 == TARGET_EXPR_SLOT (op0)) || TREE_CODE (op1) == EMPTY_CLASS_EXPR) - return potential_constant_expression_1 (op0, want_rval, flags); + return RECUR (op0, want_rval); else goto binary; } @@ -4143,12 +4147,12 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) truth: { tree op = TREE_OPERAND (t, 0); - if (!potential_constant_expression_1 (op, rval, flags)) + if (!RECUR (op, rval)) return false; if (!processing_template_decl) op = cxx_eval_outermost_constant_expr (op, true); if (tree_int_cst_equal (op, tmp)) - return potential_constant_expression_1 (TREE_OPERAND (t, 1), rval, flags); + return RECUR (TREE_OPERAND (t, 1), rval); else return true; } @@ -4186,8 +4190,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) case DOTSTAR_EXPR: binary: for (i = 0; i < 2; ++i) - if (!potential_constant_expression_1 (TREE_OPERAND (t, i), - want_rval, flags)) + if (!RECUR (TREE_OPERAND (t, i), want_rval)) return false; return true; @@ -4199,8 +4202,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) case FMA_EXPR: case VEC_PERM_EXPR: for (i = 0; i < 3; ++i) - if (!potential_constant_expression_1 (TREE_OPERAND (t, i), - true, flags)) + if (!RECUR (TREE_OPERAND (t, i), true)) return false; return true; @@ -4210,19 +4212,17 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) care about; otherwise we only require that the condition and either of the legs be potentially constant. */ tmp = TREE_OPERAND (t, 0); - if (!potential_constant_expression_1 (tmp, rval, flags)) + if (!RECUR (tmp, rval)) return false; if (!processing_template_decl) tmp = cxx_eval_outermost_constant_expr (tmp, true); if (integer_zerop (tmp)) - return potential_constant_expression_1 (TREE_OPERAND (t, 2), - want_rval, flags); + return RECUR (TREE_OPERAND (t, 2), want_rval); else if (TREE_CODE (tmp) == INTEGER_CST) - return potential_constant_expression_1 (TREE_OPERAND (t, 1), - want_rval, flags); + return RECUR (TREE_OPERAND (t, 1), want_rval); for (i = 1; i < 3; ++i) if (potential_constant_expression_1 (TREE_OPERAND (t, i), - want_rval, tf_none)) + want_rval, strict, tf_none)) return true; if (flags & tf_error) error ("expression %qE is not a constant-expression", t); @@ -4246,6 +4246,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) gcc_unreachable(); return false; } +#undef RECUR } /* The main entry point to the above. */ @@ -4253,7 +4254,13 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) bool potential_constant_expression (tree t) { - return potential_constant_expression_1 (t, false, tf_none); + return potential_constant_expression_1 (t, false, true, tf_none); +} + +bool +potential_static_init_expression (tree t) +{ + return potential_constant_expression_1 (t, false, false, tf_none); } /* As above, but require a constant rvalue. */ @@ -4261,7 +4268,7 @@ potential_constant_expression (tree t) bool potential_rvalue_constant_expression (tree t) { - return potential_constant_expression_1 (t, true, tf_none); + return potential_constant_expression_1 (t, true, true, tf_none); } /* Like above, but complain about non-constant expressions. */ @@ -4269,7 +4276,7 @@ potential_rvalue_constant_expression (tree t) bool require_potential_constant_expression (tree t) { - return potential_constant_expression_1 (t, false, tf_warning_or_error); + return potential_constant_expression_1 (t, false, true, tf_warning_or_error); } /* Cross product of the above. */ @@ -4277,7 +4284,7 @@ require_potential_constant_expression (tree t) bool require_potential_rvalue_constant_expression (tree t) { - return potential_constant_expression_1 (t, true, tf_warning_or_error); + return potential_constant_expression_1 (t, true, true, tf_warning_or_error); } #include "gt-cp-constexpr.h" diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 35423442ece..1e09629b4af 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5551,8 +5551,8 @@ extern tree build_vec_delete (tree, tree, extern tree create_temporary_var (tree); extern void initialize_vtbl_ptrs (tree); extern tree build_java_class_ref (tree); -extern tree integral_constant_value (tree); -extern tree decl_constant_value_safe (tree); +extern tree scalar_constant_value (tree); +extern tree decl_really_constant_value (tree); extern int diagnose_uninitialized_cst_or_ref_member (tree, bool, bool); extern tree build_vtbl_address (tree); @@ -6349,6 +6349,7 @@ extern tree register_constexpr_fundef (tree, tree); extern bool check_constexpr_ctor_body (tree, tree, bool); extern tree ensure_literal_type_for_constexpr_object (tree); extern bool potential_constant_expression (tree); +extern bool potential_static_init_expression (tree); extern bool potential_rvalue_constant_expression (tree); extern bool require_potential_constant_expression (tree); extern bool require_potential_rvalue_constant_expression (tree); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index 7be4f311a35..aba75ff13e2 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -675,9 +675,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags, } /* FIXME remove when moving to c_fully_fold model. */ - /* FIXME do we still need this test? */ - if (!CLASS_TYPE_P (type)) - e = integral_constant_value (e); + e = scalar_constant_value (e); if (error_operand_p (e)) return error_mark_node; diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index e69b5217490..899637f68f4 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -12993,7 +12993,7 @@ build_enumerator (tree name, tree value, tree enumtype, location_t loc) tree context; tree type; - /* integral_constant_value will pull out this expression, so make sure + /* scalar_constant_value will pull out this expression, so make sure it's folded as appropriate. */ if (processing_template_decl) value = fold_non_dependent_expr (value); diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 5c61107b7f4..19e2cdd5285 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -2004,16 +2004,16 @@ build_offset_ref (tree type, tree member, bool address_p, /* If DECL is a scalar enumeration constant or variable with a constant initializer, return the initializer (or, its initializers, - recursively); otherwise, return DECL. If INTEGRAL_P, the - initializer is only returned if DECL is an integral + recursively); otherwise, return DECL. If STRICT_P, the + initializer is only returned if DECL is a constant-expression. If RETURN_AGGREGATE_CST_OK_P, it is ok to return an aggregate constant. */ static tree -constant_value_1 (tree decl, bool integral_p, bool return_aggregate_cst_ok_p) +constant_value_1 (tree decl, bool strict_p, bool return_aggregate_cst_ok_p) { while (TREE_CODE (decl) == CONST_DECL - || (integral_p + || (strict_p ? decl_constant_var_p (decl) : (VAR_P (decl) && CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (decl))))) @@ -2047,7 +2047,7 @@ constant_value_1 (tree decl, bool integral_p, bool return_aggregate_cst_ok_p) if (!init || !TREE_TYPE (init) || !TREE_CONSTANT (init) - || (!integral_p && !return_aggregate_cst_ok_p + || (!return_aggregate_cst_ok_p /* Unless RETURN_AGGREGATE_CST_OK_P is true, do not return an aggregate constant (of which string literals are a special case), as we do not want @@ -2062,36 +2062,35 @@ constant_value_1 (tree decl, bool integral_p, bool return_aggregate_cst_ok_p) return decl; } -/* If DECL is a CONST_DECL, or a constant VAR_DECL initialized by - constant of integral or enumeration type, then return that value. - These are those variables permitted in constant expressions by - [5.19/1]. */ +/* If DECL is a CONST_DECL, or a constant VAR_DECL initialized by constant + of integral or enumeration type, or a constexpr variable of scalar type, + then return that value. These are those variables permitted in constant + expressions by [5.19/1]. */ tree -integral_constant_value (tree decl) +scalar_constant_value (tree decl) { - return constant_value_1 (decl, /*integral_p=*/true, + return constant_value_1 (decl, /*strict_p=*/true, /*return_aggregate_cst_ok_p=*/false); } -/* A more relaxed version of integral_constant_value, used by the - common C/C++ code. */ +/* Like scalar_constant_value, but can also return aggregate initializers. */ tree -decl_constant_value (tree decl) +decl_really_constant_value (tree decl) { - return constant_value_1 (decl, /*integral_p=*/processing_template_decl, + return constant_value_1 (decl, /*strict_p=*/true, /*return_aggregate_cst_ok_p=*/true); } -/* A version of integral_constant_value used by the C++ front end for - optimization purposes. */ +/* A more relaxed version of scalar_constant_value, used by the + common C/C++ code. */ tree -decl_constant_value_safe (tree decl) +decl_constant_value (tree decl) { - return constant_value_1 (decl, /*integral_p=*/processing_template_decl, - /*return_aggregate_cst_ok_p=*/false); + return constant_value_1 (decl, /*strict_p=*/processing_template_decl, + /*return_aggregate_cst_ok_p=*/true); } /* Common subroutines of build_new and build_vec_delete. */ diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 6661325aa49..0b8fd7fd37f 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -12805,7 +12805,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) return t; /* If ARGS is NULL, then T is known to be non-dependent. */ if (args == NULL_TREE) - return integral_constant_value (t); + return scalar_constant_value (t); /* Unfortunately, we cannot just call lookup_name here. Consider: @@ -12936,7 +12936,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) else if (decl_constant_var_p (r)) /* A use of a local constant decays to its value. FIXME update for core DR 696. */ - r = integral_constant_value (r); + r = scalar_constant_value (r); } } /* Remember this for subsequent uses. */ @@ -18420,7 +18420,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, case CONST_DECL: if (DECL_TEMPLATE_PARM_P (parm)) return unify (tparms, targs, DECL_INITIAL (parm), arg, strict, explain_p); - if (arg != integral_constant_value (parm)) + if (arg != scalar_constant_value (parm)) return unify_template_argument_mismatch (explain_p, parm, arg); return unify_success (explain_p); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 6888121d5d0..639702a6e62 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -3125,7 +3125,7 @@ process_outer_var_ref (tree decl, tsubst_flags_t complain) form, so wait until instantiation time. */ return decl; else if (decl_constant_var_p (decl)) - return integral_constant_value (decl); + return scalar_constant_value (decl); } if (parsing_nsdmi ()) diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 05bc916cdc7..53fe67afc90 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1936,17 +1936,10 @@ decay_conversion (tree exp, tsubst_flags_t complain) code = TREE_CODE (type); - /* For an array decl decay_conversion should not try to return its - initializer. */ - if (code != ARRAY_TYPE) - { - /* FIXME remove? at least need to remember that this isn't really a - constant expression if EXP isn't decl_constant_var_p, like with - C_MAYBE_CONST_EXPR. */ - exp = decl_constant_value_safe (exp); - if (error_operand_p (exp)) - return error_mark_node; - } + /* FIXME remove for delayed folding. */ + exp = scalar_constant_value (exp); + if (error_operand_p (exp)) + return error_mark_node; if (NULLPTR_TYPE_P (type) && !TREE_SIDE_EFFECTS (exp)) return nullptr_node; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-object2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-object2.C index d52967a7edd..bd146adb702 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-object2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-object2.C @@ -3,9 +3,9 @@ constexpr int verysquare(int x) { return x * x; } const double mass = 9.8; -constexpr double energy = mass * verysquare(56.6); // { dg-error "mass" "" { xfail *-*-* } } +constexpr double energy = mass * verysquare(56.6); // { dg-error "mass" } -int arr[(int)mass]; // { dg-error "mass" "" { xfail *-*-* } } +int arr[(int)mass]; // { dg-error "" } float array[verysquare(9)]; // OK -- not C99 VLA diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr06.C b/gcc/testsuite/g++.dg/cpp0x/nullptr06.C index e933c35287e..396ac3a1fd7 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nullptr06.C +++ b/gcc/testsuite/g++.dg/cpp0x/nullptr06.C @@ -4,7 +4,7 @@ #define assert_true(b) do { char c[2 * bool(b) - 1]; } while(0) -char* const cp1 = nullptr; +constexpr char* cp1 = nullptr; void fun() { -- 2.30.2