aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2014-11-19 17:06:17 -0500
committerJason Merrill <jason@gcc.gnu.org>2014-11-19 17:06:17 -0500
commit69eb4fde588c5c2e4e206aeba9a5a17fcaf5cecb (patch)
tree7ab8f15cad76cb28be65015b3cbb7153217b4139 /gcc
parent6d06c429dc7effbf2ecc26401c7d43f5ab192dd7 (diff)
downloadgcc-69eb4fde588c5c2e4e206aeba9a5a17fcaf5cecb.zip
gcc-69eb4fde588c5c2e4e206aeba9a5a17fcaf5cecb.tar.gz
gcc-69eb4fde588c5c2e4e206aeba9a5a17fcaf5cecb.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog21
-rw-r--r--gcc/cp/call.c2
-rw-r--r--gcc/cp/constexpr.c167
-rw-r--r--gcc/cp/cp-tree.h5
-rw-r--r--gcc/cp/cvt.c4
-rw-r--r--gcc/cp/decl.c2
-rw-r--r--gcc/cp/init.c39
-rw-r--r--gcc/cp/pt.c6
-rw-r--r--gcc/cp/semantics.c2
-rw-r--r--gcc/cp/typeck.c15
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-object2.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nullptr06.C2
12 files changed, 144 insertions, 125 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index ac4d2a5..6f947b4 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,26 @@
2014-11-19 Jason Merrill <jason@redhat.com>
+ 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 <jason@redhat.com>
+
PR c++/63928
* constexpr.c (cxx_eval_store_expression): Return init, not *valp.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index c180890..5cda1b1 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 77f5159..5268545 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<tree,tree> map;
ctx.values = &map;
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 <tree, tree> map;
ctx.values = &map;
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<constructor_elt, va_gc> *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 3542344..1e09629 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 7be4f31..aba75ff 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 e69b521..899637f 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 5c61107..19e2cdd 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 6661325..0b8fd7f 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 6888121..639702a 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 05bc916..53fe67a 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 d52967a..bd146ad 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 e933c35..396ac3a 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()
{