Commit d6ed1c89 by Jason Merrill Committed by Jason Merrill

re PR c++/46977 ([C++0x] ICE: SIGSEGV in htab_find_slot_with_hash (hashtab.c:650))

	PR c++/46977
	* semantics.c (potential_constant_expression_1): Split out from
	potential_constant_expression.  Add want_rval parm.  Handle
	template expression forms.  Don't enforce restriction on address
	of automatic variable here.  Add a couple of diagnostics that
	had been missing.
	(require_potential_constant_expression): New entry point.
	(build_data_member_initialization, register_constexpr_fundef): Adjust.
	(maybe_constant_value): Check potential_constant_expression.
	* pt.c (fold_non_dependent_expr_sfinae): Likewise.
	* tree.c (build_vec_init_expr): Adjust.

From-SVN: r169096
parent e90b336f
2011-01-21 Jason Merrill <jason@redhat.com>
PR c++/46977
* semantics.c (potential_constant_expression_1): Split out from
potential_constant_expression. Add want_rval parm. Handle
template expression forms. Don't enforce restriction on address
of automatic variable here. Add a couple of diagnostics that
had been missing.
(require_potential_constant_expression): New entry point.
(build_data_member_initialization, register_constexpr_fundef): Adjust.
(maybe_constant_value): Check potential_constant_expression.
* pt.c (fold_non_dependent_expr_sfinae): Likewise.
* tree.c (build_vec_init_expr): Adjust.
2011-01-19 Jakub Jelinek <jakub@redhat.com> 2011-01-19 Jakub Jelinek <jakub@redhat.com>
PR c++/47303 PR c++/47303
......
...@@ -5245,7 +5245,8 @@ extern tree validate_constexpr_fundecl (tree); ...@@ -5245,7 +5245,8 @@ extern tree validate_constexpr_fundecl (tree);
extern tree register_constexpr_fundef (tree, tree); extern tree register_constexpr_fundef (tree, tree);
extern bool check_constexpr_ctor_body (tree, tree); extern bool check_constexpr_ctor_body (tree, tree);
extern tree ensure_literal_type_for_constexpr_object (tree); extern tree ensure_literal_type_for_constexpr_object (tree);
extern bool potential_constant_expression (tree, tsubst_flags_t); extern bool potential_constant_expression (tree);
extern bool require_potential_constant_expression (tree);
extern tree cxx_constant_value (tree); extern tree cxx_constant_value (tree);
extern tree maybe_constant_value (tree); extern tree maybe_constant_value (tree);
extern tree maybe_constant_init (tree); extern tree maybe_constant_init (tree);
......
...@@ -5159,6 +5159,7 @@ fold_non_dependent_expr_sfinae (tree expr, tsubst_flags_t complain) ...@@ -5159,6 +5159,7 @@ fold_non_dependent_expr_sfinae (tree expr, tsubst_flags_t complain)
as two declarations of the same function, for example. */ as two declarations of the same function, for example. */
if (processing_template_decl if (processing_template_decl
&& !type_dependent_expression_p (expr) && !type_dependent_expression_p (expr)
&& potential_constant_expression (expr)
&& !value_dependent_expression_p (expr)) && !value_dependent_expression_p (expr))
{ {
HOST_WIDE_INT saved_processing_template_decl; HOST_WIDE_INT saved_processing_template_decl;
...@@ -17964,11 +17965,11 @@ dependent_scope_p (tree scope) ...@@ -17964,11 +17965,11 @@ dependent_scope_p (tree scope)
[temp.dep.constexpr]. EXPRESSION is already known to be a constant [temp.dep.constexpr]. EXPRESSION is already known to be a constant
expression. */ expression. */
/* FIXME this predicate is not appropriate for general expressions; the /* Note that this predicate is not appropriate for general expressions;
predicates we want instead are "valid constant expression, value only constant expressions (that satisfy potential_constant_expression)
dependent or not?", "really constant expression, not value dependent?" can be tested for value dependence.
and "instantiation-dependent?". Try to integrate with
potential_constant_expression? We should really also have a predicate for "instantiation-dependent".
fold_non_dependent_expr: fold if constant and not type-dependent and not value-dependent. fold_non_dependent_expr: fold if constant and not type-dependent and not value-dependent.
(what about instantiation-dependent constant-expressions?) (what about instantiation-dependent constant-expressions?)
......
...@@ -5532,7 +5532,7 @@ build_data_member_initialization (tree t, VEC(constructor_elt,gc) **vec) ...@@ -5532,7 +5532,7 @@ build_data_member_initialization (tree t, VEC(constructor_elt,gc) **vec)
gcc_assert (is_empty_class (TREE_TYPE (TREE_TYPE (member)))); gcc_assert (is_empty_class (TREE_TYPE (TREE_TYPE (member))));
/* But if the initializer isn't constexpr, leave it in so we /* But if the initializer isn't constexpr, leave it in so we
complain later. */ complain later. */
if (potential_constant_expression (init, tf_none)) if (potential_constant_expression (init))
return true; return true;
} }
} }
...@@ -5658,10 +5658,11 @@ register_constexpr_fundef (tree fun, tree body) ...@@ -5658,10 +5658,11 @@ register_constexpr_fundef (tree fun, tree body)
body = unshare_expr (TREE_OPERAND (body, 0)); body = unshare_expr (TREE_OPERAND (body, 0));
} }
if (!potential_constant_expression (body, (DECL_TEMPLATE_INSTANTIATION (fun) if (!potential_constant_expression (body))
? tf_none : tf_error)))
{ {
DECL_DECLARED_CONSTEXPR_P (fun) = false; DECL_DECLARED_CONSTEXPR_P (fun) = false;
if (!DECL_TEMPLATE_INSTANTIATION (fun))
require_potential_constant_expression (body);
return NULL; return NULL;
} }
fundef->body = body; fundef->body = body;
...@@ -7115,8 +7116,7 @@ maybe_constant_value (tree t) ...@@ -7115,8 +7116,7 @@ maybe_constant_value (tree t)
tree r; tree r;
if (type_dependent_expression_p (t) if (type_dependent_expression_p (t)
/* FIXME shouldn't check value-dependence first; see comment before || !potential_constant_expression (t)
value_dependent_expression_p. */
|| value_dependent_expression_p (t)) || value_dependent_expression_p (t))
return t; return t;
...@@ -7148,6 +7148,8 @@ maybe_constant_init (tree t) ...@@ -7148,6 +7148,8 @@ maybe_constant_init (tree t)
return t; return t;
} }
#if 0
/* FIXME see ADDR_EXPR section in potential_constant_expression_1. */
/* Return true if the object referred to by REF has automatic or thread /* Return true if the object referred to by REF has automatic or thread
local storage. */ local storage. */
...@@ -7170,6 +7172,7 @@ check_automatic_or_tls (tree ref) ...@@ -7170,6 +7172,7 @@ check_automatic_or_tls (tree ref)
dk = decl_storage_duration (decl); dk = decl_storage_duration (decl);
return (dk == dk_auto || dk == dk_thread) ? ck_bad : ck_ok; return (dk == dk_auto || dk == dk_thread) ? ck_bad : ck_ok;
} }
#endif
/* Return true if the DECL designates a builtin function that is /* Return true if the DECL designates a builtin function that is
morally constexpr, in the sense that its parameter types and morally constexpr, in the sense that its parameter types and
...@@ -7197,13 +7200,11 @@ morally_constexpr_builtin_function_p (tree decl) ...@@ -7197,13 +7200,11 @@ morally_constexpr_builtin_function_p (tree decl)
return t != NULL; return t != NULL;
} }
/* Return true if T denotes a constant expression, or potential constant /* Return true if T denotes a potentially constant expression. Issue
expression if POTENTIAL is true. diagnostic as appropriate under control of FLAGS. If WANT_RVAL is true,
Issue diagnostic as appropriate under control of flags. Variables an lvalue-rvalue conversion is implied.
with static storage duration initialized by constant expressions
are guaranteed to be statically initialized.
C++0x [expr.const] C++0x [expr.const] used to say
6 An expression is a potential constant expression if it is 6 An expression is a potential constant expression if it is
a constant expression where all occurences of function a constant expression where all occurences of function
...@@ -7216,13 +7217,23 @@ morally_constexpr_builtin_function_p (tree decl) ...@@ -7216,13 +7217,23 @@ morally_constexpr_builtin_function_p (tree decl)
logical OR (5.15), and conditional (5.16) operations that are logical OR (5.15), and conditional (5.16) operations that are
not evaluated are not considered. */ not evaluated are not considered. */
bool static bool
potential_constant_expression (tree t, tsubst_flags_t flags) potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
{ {
enum { any = false, rval = true };
int i; int i;
tree tmp; tree tmp;
/* C++98 has different rules for the form of a constant expression that
are enforced in the parser, so we can assume that anything that gets
this far is suitable. */
if (cxx_dialect < cxx0x)
return true;
if (t == error_mark_node) if (t == error_mark_node)
return false; return false;
if (t == NULL_TREE)
return true;
if (TREE_THIS_VOLATILE (t)) if (TREE_THIS_VOLATILE (t))
{ {
if (flags & tf_error) if (flags & tf_error)
...@@ -7235,8 +7246,18 @@ potential_constant_expression (tree t, tsubst_flags_t flags) ...@@ -7235,8 +7246,18 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
switch (TREE_CODE (t)) switch (TREE_CODE (t))
{ {
case FUNCTION_DECL: case FUNCTION_DECL:
case BASELINK:
case OVERLOAD:
case TEMPLATE_ID_EXPR:
case LABEL_DECL: case LABEL_DECL:
case CONST_DECL: case CONST_DECL:
case SIZEOF_EXPR:
case ALIGNOF_EXPR:
case OFFSETOF_EXPR:
case NOEXCEPT_EXPR:
case TEMPLATE_PARM_INDEX:
case TRAIT_EXPR:
case IDENTIFIER_NODE:
return true; return true;
case PARM_DECL: case PARM_DECL:
...@@ -7261,7 +7282,7 @@ potential_constant_expression (tree t, tsubst_flags_t flags) ...@@ -7261,7 +7282,7 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
const int nargs = call_expr_nargs (t); const int nargs = call_expr_nargs (t);
if (TREE_CODE (fun) != FUNCTION_DECL) if (TREE_CODE (fun) != FUNCTION_DECL)
{ {
if (potential_constant_expression (fun, flags)) if (potential_constant_expression_1 (fun, rval, flags))
/* Might end up being a constant function pointer. */ /* Might end up being a constant function pointer. */
return true; return true;
if (flags & tf_error) if (flags & tf_error)
...@@ -7293,11 +7314,9 @@ potential_constant_expression (tree t, tsubst_flags_t flags) ...@@ -7293,11 +7314,9 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
if (i == 0 && DECL_NONSTATIC_MEMBER_P (fun) if (i == 0 && DECL_NONSTATIC_MEMBER_P (fun)
&& !DECL_CONSTRUCTOR_P (fun)) && !DECL_CONSTRUCTOR_P (fun))
{ {
if (TREE_CODE (x) == ADDR_EXPR)
x = TREE_OPERAND (x, 0);
if (is_this_parameter (x)) if (is_this_parameter (x))
/* OK. */; /* OK. */;
else if (!potential_constant_expression (x, flags)) else if (!potential_constant_expression_1 (x, rval, flags))
{ {
if (flags & tf_error) if (flags & tf_error)
error ("object argument is not a potential constant " error ("object argument is not a potential constant "
...@@ -7305,7 +7324,7 @@ potential_constant_expression (tree t, tsubst_flags_t flags) ...@@ -7305,7 +7324,7 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
return false; return false;
} }
} }
else if (!potential_constant_expression (x, flags)) else if (!potential_constant_expression_1 (x, rval, flags))
{ {
if (flags & tf_error) if (flags & tf_error)
error ("argument in position %qP is not a " error ("argument in position %qP is not a "
...@@ -7325,10 +7344,10 @@ potential_constant_expression (tree t, tsubst_flags_t flags) ...@@ -7325,10 +7344,10 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
-- an lvalue of literal type that refers to non-volatile -- an lvalue of literal type that refers to non-volatile
object defined with constexpr, or that refers to a object defined with constexpr, or that refers to a
sub-object of such an object; */ sub-object of such an object; */
return potential_constant_expression (TREE_OPERAND (t, 0), flags); return potential_constant_expression_1 (TREE_OPERAND (t, 0), rval, flags);
case VAR_DECL: case VAR_DECL:
if (!decl_constant_var_p (t)) if (want_rval && !decl_constant_var_p (t))
{ {
if (flags & tf_error) if (flags & tf_error)
error ("variable %qD is not declared constexpr", t); error ("variable %qD is not declared constexpr", t);
...@@ -7358,7 +7377,8 @@ potential_constant_expression (tree t, tsubst_flags_t flags) ...@@ -7358,7 +7377,8 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
"cannot yield a constant expression", from); "cannot yield a constant expression", from);
return false; return false;
} }
return potential_constant_expression (from, flags); return (potential_constant_expression_1
(from, TREE_CODE (t) != VIEW_CONVERT_EXPR, flags));
} }
case ADDR_EXPR: case ADDR_EXPR:
...@@ -7366,6 +7386,10 @@ potential_constant_expression (tree t, tsubst_flags_t flags) ...@@ -7366,6 +7386,10 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
designates an object with thread or automatic storage designates an object with thread or automatic storage
duration; */ duration; */
t = TREE_OPERAND (t, 0); t = TREE_OPERAND (t, 0);
#if 0
/* FIXME adjust when issue 1197 is fully resolved. For now don't do
any checking here, as we might dereference the pointer later. If
we remove this code, also remove check_automatic_or_tls. */
i = check_automatic_or_tls (t); i = check_automatic_or_tls (t);
if (i == ck_ok) if (i == ck_ok)
return true; return true;
...@@ -7376,15 +7400,23 @@ potential_constant_expression (tree t, tsubst_flags_t flags) ...@@ -7376,15 +7400,23 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
"automatic storage is not a constant expression", t); "automatic storage is not a constant expression", t);
return false; return false;
} }
return potential_constant_expression (t, flags); #endif
return potential_constant_expression_1 (t, any, flags);
case COMPONENT_REF: case COMPONENT_REF:
case BIT_FIELD_REF: case BIT_FIELD_REF:
case ARROW_EXPR:
case OFFSET_REF:
/* -- a class member access unless its postfix-expression is /* -- a class member access unless its postfix-expression is
of literal type or of pointer to literal type. */ of literal type or of pointer to literal type. */
/* This test would be redundant, as it follows from the /* This test would be redundant, as it follows from the
postfix-expression being a potential constant expression. */ postfix-expression being a potential constant expression. */
return potential_constant_expression (TREE_OPERAND (t, 0), flags); return potential_constant_expression_1 (TREE_OPERAND (t, 0),
want_rval, flags);
case EXPR_PACK_EXPANSION:
return potential_constant_expression_1 (PACK_EXPANSION_PATTERN (t),
want_rval, flags);
case INDIRECT_REF: case INDIRECT_REF:
{ {
...@@ -7392,7 +7424,7 @@ potential_constant_expression (tree t, tsubst_flags_t flags) ...@@ -7392,7 +7424,7 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
STRIP_NOPS (x); STRIP_NOPS (x);
if (is_this_parameter (x)) if (is_this_parameter (x))
return true; return true;
return potential_constant_expression (x, flags); return potential_constant_expression_1 (x, rval, flags);
} }
case LAMBDA_EXPR: case LAMBDA_EXPR:
...@@ -7417,6 +7449,10 @@ potential_constant_expression (tree t, tsubst_flags_t flags) ...@@ -7417,6 +7449,10 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
case MUST_NOT_THROW_EXPR: case MUST_NOT_THROW_EXPR:
case TRY_CATCH_EXPR: case TRY_CATCH_EXPR:
case STATEMENT_LIST: case STATEMENT_LIST:
/* Don't bother trying to define a subset of statement-expressions to
be constant-expressions, at least for now. */
case STMT_EXPR:
case EXPR_STMT:
case BIND_EXPR: case BIND_EXPR:
if (flags & tf_error) if (flags & tf_error)
error ("expression %qE is not a constant-expression", t); error ("expression %qE is not a constant-expression", t);
...@@ -7427,7 +7463,8 @@ potential_constant_expression (tree t, tsubst_flags_t flags) ...@@ -7427,7 +7463,8 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
class type; */ class type; */
{ {
tree e = TREE_OPERAND (t, 0); tree e = TREE_OPERAND (t, 0);
if (!TYPE_P (e) && TYPE_POLYMORPHIC_P (TREE_TYPE (e))) if (!TYPE_P (e) && !type_dependent_expression_p (e)
&& TYPE_POLYMORPHIC_P (TREE_TYPE (e)))
{ {
if (flags & tf_error) if (flags & tf_error)
error ("typeid-expression is not a constant expression " error ("typeid-expression is not a constant expression "
...@@ -7447,6 +7484,7 @@ potential_constant_expression (tree t, tsubst_flags_t flags) ...@@ -7447,6 +7484,7 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
"a constant expression"); "a constant expression");
return false; return false;
} }
want_rval = true;
goto binary; goto binary;
case LT_EXPR: case LT_EXPR:
...@@ -7465,6 +7503,7 @@ potential_constant_expression (tree t, tsubst_flags_t flags) ...@@ -7465,6 +7503,7 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
"constant expression"); "constant expression");
return false; return false;
} }
want_rval = true;
goto binary; goto binary;
case REALPART_EXPR: case REALPART_EXPR:
...@@ -7477,22 +7516,41 @@ potential_constant_expression (tree t, tsubst_flags_t flags) ...@@ -7477,22 +7516,41 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
case ABS_EXPR: case ABS_EXPR:
case BIT_NOT_EXPR: case BIT_NOT_EXPR:
case TRUTH_NOT_EXPR: case TRUTH_NOT_EXPR:
case PAREN_EXPR:
case FIXED_CONVERT_EXPR: case FIXED_CONVERT_EXPR:
case UNARY_PLUS_EXPR:
return potential_constant_expression_1 (TREE_OPERAND (t, 0), rval,
flags);
case CAST_EXPR:
case CONST_CAST_EXPR:
case STATIC_CAST_EXPR:
case REINTERPRET_CAST_EXPR:
return (potential_constant_expression_1
(TREE_OPERAND (t, 0),
TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE, flags));
case PAREN_EXPR:
case NON_DEPENDENT_EXPR:
/* For convenience. */ /* For convenience. */
case RETURN_EXPR: case RETURN_EXPR:
return potential_constant_expression (TREE_OPERAND (t, 0), flags); return potential_constant_expression_1 (TREE_OPERAND (t, 0),
want_rval, flags);
case SCOPE_REF:
return potential_constant_expression_1 (TREE_OPERAND (t, 1),
want_rval, flags);
case INIT_EXPR: case INIT_EXPR:
case TARGET_EXPR: case TARGET_EXPR:
return potential_constant_expression (TREE_OPERAND (t, 1), flags); return potential_constant_expression_1 (TREE_OPERAND (t, 1),
rval, flags);
case CONSTRUCTOR: case CONSTRUCTOR:
{ {
VEC(constructor_elt, gc) *v = CONSTRUCTOR_ELTS (t); VEC(constructor_elt, gc) *v = CONSTRUCTOR_ELTS (t);
constructor_elt *ce; constructor_elt *ce;
for (i = 0; VEC_iterate (constructor_elt, v, i, ce); ++i) for (i = 0; VEC_iterate (constructor_elt, v, i, ce); ++i)
if (!potential_constant_expression (ce->value, flags)) if (!potential_constant_expression_1 (ce->value, want_rval, flags))
return false; return false;
return true; return true;
} }
...@@ -7501,11 +7559,13 @@ potential_constant_expression (tree t, tsubst_flags_t flags) ...@@ -7501,11 +7559,13 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
{ {
gcc_assert (TREE_PURPOSE (t) == NULL_TREE gcc_assert (TREE_PURPOSE (t) == NULL_TREE
|| DECL_P (TREE_PURPOSE (t))); || DECL_P (TREE_PURPOSE (t)));
if (!potential_constant_expression (TREE_VALUE (t), flags)) if (!potential_constant_expression_1 (TREE_VALUE (t), want_rval,
flags))
return false; return false;
if (TREE_CHAIN (t) == NULL_TREE) if (TREE_CHAIN (t) == NULL_TREE)
return true; return true;
return potential_constant_expression (TREE_CHAIN (t), flags); return potential_constant_expression_1 (TREE_CHAIN (t), want_rval,
flags);
} }
case TRUNC_DIV_EXPR: case TRUNC_DIV_EXPR:
...@@ -7515,10 +7575,24 @@ potential_constant_expression (tree t, tsubst_flags_t flags) ...@@ -7515,10 +7575,24 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
case TRUNC_MOD_EXPR: case TRUNC_MOD_EXPR:
case CEIL_MOD_EXPR: case CEIL_MOD_EXPR:
case ROUND_MOD_EXPR: case ROUND_MOD_EXPR:
if (integer_zerop (maybe_constant_value (TREE_OPERAND (t, 1)))) {
tree denom = TREE_OPERAND (t, 1);
/* We can't call maybe_constant_value on an expression
that hasn't been through fold_non_dependent_expr yet. */
if (!processing_template_decl)
denom = maybe_constant_value (denom);
if (integer_zerop (denom))
{
if (flags & tf_error)
error ("division by zero is not a constant-expression");
return false; return false;
}
else else
{
want_rval = true;
goto binary; goto binary;
}
}
case COMPOUND_EXPR: case COMPOUND_EXPR:
{ {
...@@ -7530,7 +7604,7 @@ potential_constant_expression (tree t, tsubst_flags_t flags) ...@@ -7530,7 +7604,7 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
STRIP_NOPS (op1); STRIP_NOPS (op1);
if ((TREE_CODE (op0) == TARGET_EXPR && op1 == TARGET_EXPR_SLOT (op0)) if ((TREE_CODE (op0) == TARGET_EXPR && op1 == TARGET_EXPR_SLOT (op0))
|| TREE_CODE (op1) == EMPTY_CLASS_EXPR) || TREE_CODE (op1) == EMPTY_CLASS_EXPR)
return potential_constant_expression (op0, flags); return potential_constant_expression_1 (op0, want_rval, flags);
else else
goto binary; goto binary;
} }
...@@ -7547,12 +7621,10 @@ potential_constant_expression (tree t, tsubst_flags_t flags) ...@@ -7547,12 +7621,10 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
tmp = boolean_false_node; tmp = boolean_false_node;
truth: truth:
if (TREE_OPERAND (t, 0) == tmp) if (TREE_OPERAND (t, 0) == tmp)
return potential_constant_expression (TREE_OPERAND (t, 1), flags); return potential_constant_expression_1 (TREE_OPERAND (t, 1), rval, flags);
else else
return potential_constant_expression (TREE_OPERAND (t, 0), flags); return potential_constant_expression_1 (TREE_OPERAND (t, 0), rval, flags);
case ARRAY_REF:
case ARRAY_RANGE_REF:
case PLUS_EXPR: case PLUS_EXPR:
case MULT_EXPR: case MULT_EXPR:
case POINTER_PLUS_EXPR: case POINTER_PLUS_EXPR:
...@@ -7574,10 +7646,16 @@ potential_constant_expression (tree t, tsubst_flags_t flags) ...@@ -7574,10 +7646,16 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
case UNEQ_EXPR: case UNEQ_EXPR:
case RANGE_EXPR: case RANGE_EXPR:
case COMPLEX_EXPR: case COMPLEX_EXPR:
want_rval = true;
/* Fall through. */
case ARRAY_REF:
case ARRAY_RANGE_REF:
case MEMBER_REF:
case DOTSTAR_EXPR:
binary: binary:
for (i = 0; i < 2; ++i) for (i = 0; i < 2; ++i)
if (!potential_constant_expression (TREE_OPERAND (t, i), if (!potential_constant_expression_1 (TREE_OPERAND (t, i),
flags)) want_rval, flags))
return false; return false;
return true; return true;
...@@ -7587,21 +7665,28 @@ potential_constant_expression (tree t, tsubst_flags_t flags) ...@@ -7587,21 +7665,28 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
care about; otherwise we only require that the condition and care about; otherwise we only require that the condition and
either of the legs be potentially constant. */ either of the legs be potentially constant. */
tmp = TREE_OPERAND (t, 0); tmp = TREE_OPERAND (t, 0);
if (!potential_constant_expression (tmp, flags)) if (!potential_constant_expression_1 (tmp, rval, flags))
return false; return false;
else if (tmp == boolean_true_node) else if (tmp == boolean_true_node)
return potential_constant_expression (TREE_OPERAND (t, 1), flags); return potential_constant_expression_1 (TREE_OPERAND (t, 1),
want_rval, flags);
else if (tmp == boolean_false_node) else if (tmp == boolean_false_node)
return potential_constant_expression (TREE_OPERAND (t, 2), flags); return potential_constant_expression_1 (TREE_OPERAND (t, 2),
want_rval, flags);
for (i = 1; i < 3; ++i) for (i = 1; i < 3; ++i)
if (potential_constant_expression (TREE_OPERAND (t, i), tf_none)) if (potential_constant_expression_1 (TREE_OPERAND (t, i),
want_rval, tf_none))
return true; return true;
if (flags & tf_error) if (flags & tf_error)
error ("expression %qE is not a constant-expression", t); error ("expression %qE is not a constant-expression", t);
return false; return false;
case VEC_INIT_EXPR: case VEC_INIT_EXPR:
return VEC_INIT_EXPR_IS_CONSTEXPR (t); if (VEC_INIT_EXPR_IS_CONSTEXPR (t))
return true;
if (flags & tf_error)
error ("non-constant array initialization");
return false;
default: default:
sorry ("unexpected ast of kind %s", tree_code_name[TREE_CODE (t)]); sorry ("unexpected ast of kind %s", tree_code_name[TREE_CODE (t)]);
...@@ -7610,6 +7695,21 @@ potential_constant_expression (tree t, tsubst_flags_t flags) ...@@ -7610,6 +7695,21 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
} }
} }
/* The main entry point to the above. */
bool
potential_constant_expression (tree t)
{
return potential_constant_expression_1 (t, false, tf_none);
}
/* Like above, but complain about non-constant expressions. */
bool
require_potential_constant_expression (tree t)
{
return potential_constant_expression_1 (t, false, tf_warning_or_error);
}
/* Constructor for a lambda expression. */ /* Constructor for a lambda expression. */
......
...@@ -513,9 +513,13 @@ build_vec_init_expr (tree type, tree init) ...@@ -513,9 +513,13 @@ build_vec_init_expr (tree type, tree init)
SET_EXPR_LOCATION (init, input_location); SET_EXPR_LOCATION (init, input_location);
if (current_function_decl if (current_function_decl
&& DECL_DECLARED_CONSTEXPR_P (current_function_decl) && DECL_DECLARED_CONSTEXPR_P (current_function_decl))
&& potential_constant_expression (elt_init, tf_warning_or_error)) {
if (potential_constant_expression (elt_init))
VEC_INIT_EXPR_IS_CONSTEXPR (init) = true; VEC_INIT_EXPR_IS_CONSTEXPR (init) = true;
else if (!processing_template_decl)
require_potential_constant_expression (elt_init);
}
VEC_INIT_EXPR_VALUE_INIT (init) = value_init; VEC_INIT_EXPR_VALUE_INIT (init) = value_init;
init = build_target_expr (slot, init); init = build_target_expr (slot, init);
......
2011-01-21 Jason Merrill <jason@redhat.com>
* g++.dg/cpp0x/constexpr-stmtexpr.C: New.
2011-01-21 Jeff Law <law@redhat.com> 2011-01-21 Jeff Law <law@redhat.com>
PR rtl-optimization/41619 PR rtl-optimization/41619
......
// PR c++/46977
// { dg-options "-std=c++0x" }
template < typename > void
foo ()
{
({int i;}), 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment