aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2011-01-21 12:38:02 -0500
committerJason Merrill <jason@gcc.gnu.org>2011-01-21 12:38:02 -0500
commitd6ed1c8903e728f4233122554bab5910853338bd (patch)
tree95871ccf683cdcd1cc68588d8d01c44cb12a7588 /gcc
parente90b336fce3f8e4fe7c65301da0a48da3d9e455c (diff)
downloadgcc-d6ed1c8903e728f4233122554bab5910853338bd.zip
gcc-d6ed1c8903e728f4233122554bab5910853338bd.tar.gz
gcc-d6ed1c8903e728f4233122554bab5910853338bd.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog14
-rw-r--r--gcc/cp/cp-tree.h3
-rw-r--r--gcc/cp/pt.c11
-rw-r--r--gcc/cp/semantics.c194
-rw-r--r--gcc/cp/tree.c10
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-stmtexpr.C8
7 files changed, 188 insertions, 56 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a28d672..dcf8c49 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,17 @@
+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>
PR c++/47303
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 3d39b55..7500826 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5245,7 +5245,8 @@ extern tree validate_constexpr_fundecl (tree);
extern tree register_constexpr_fundef (tree, tree);
extern bool check_constexpr_ctor_body (tree, 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 maybe_constant_value (tree);
extern tree maybe_constant_init (tree);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 01f8cd7..7d39e1c 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -5159,6 +5159,7 @@ fold_non_dependent_expr_sfinae (tree expr, tsubst_flags_t complain)
as two declarations of the same function, for example. */
if (processing_template_decl
&& !type_dependent_expression_p (expr)
+ && potential_constant_expression (expr)
&& !value_dependent_expression_p (expr))
{
HOST_WIDE_INT saved_processing_template_decl;
@@ -17964,11 +17965,11 @@ dependent_scope_p (tree scope)
[temp.dep.constexpr]. EXPRESSION is already known to be a constant
expression. */
-/* FIXME this predicate is not appropriate for general expressions; the
- predicates we want instead are "valid constant expression, value
- dependent or not?", "really constant expression, not value dependent?"
- and "instantiation-dependent?". Try to integrate with
- potential_constant_expression?
+/* Note that this predicate is not appropriate for general expressions;
+ only constant expressions (that satisfy potential_constant_expression)
+ can be tested for value dependence.
+
+ 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.
(what about instantiation-dependent constant-expressions?)
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 285b764..23ff27b 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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))));
/* But if the initializer isn't constexpr, leave it in so we
complain later. */
- if (potential_constant_expression (init, tf_none))
+ if (potential_constant_expression (init))
return true;
}
}
@@ -5658,10 +5658,11 @@ register_constexpr_fundef (tree fun, tree body)
body = unshare_expr (TREE_OPERAND (body, 0));
}
- if (!potential_constant_expression (body, (DECL_TEMPLATE_INSTANTIATION (fun)
- ? tf_none : tf_error)))
+ if (!potential_constant_expression (body))
{
DECL_DECLARED_CONSTEXPR_P (fun) = false;
+ if (!DECL_TEMPLATE_INSTANTIATION (fun))
+ require_potential_constant_expression (body);
return NULL;
}
fundef->body = body;
@@ -7115,8 +7116,7 @@ maybe_constant_value (tree t)
tree r;
if (type_dependent_expression_p (t)
- /* FIXME shouldn't check value-dependence first; see comment before
- value_dependent_expression_p. */
+ || !potential_constant_expression (t)
|| value_dependent_expression_p (t))
return t;
@@ -7148,6 +7148,8 @@ maybe_constant_init (tree 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
local storage. */
@@ -7170,6 +7172,7 @@ check_automatic_or_tls (tree ref)
dk = decl_storage_duration (decl);
return (dk == dk_auto || dk == dk_thread) ? ck_bad : ck_ok;
}
+#endif
/* Return true if the DECL designates a builtin function that is
morally constexpr, in the sense that its parameter types and
@@ -7197,13 +7200,11 @@ morally_constexpr_builtin_function_p (tree decl)
return t != NULL;
}
-/* Return true if T denotes a constant expression, or potential constant
- expression if POTENTIAL is true.
- Issue diagnostic as appropriate under control of flags. Variables
- with static storage duration initialized by constant expressions
- are guaranteed to be statically initialized.
+/* Return true if T denotes a potentially constant expression. Issue
+ diagnostic as appropriate under control of FLAGS. If WANT_RVAL is true,
+ an lvalue-rvalue conversion is implied.
- C++0x [expr.const]
+ C++0x [expr.const] used to say
6 An expression is a potential constant expression if it is
a constant expression where all occurences of function
@@ -7216,13 +7217,23 @@ morally_constexpr_builtin_function_p (tree decl)
logical OR (5.15), and conditional (5.16) operations that are
not evaluated are not considered. */
-bool
-potential_constant_expression (tree t, tsubst_flags_t flags)
+static bool
+potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
{
+ enum { any = false, rval = true };
int i;
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)
return false;
+ if (t == NULL_TREE)
+ return true;
if (TREE_THIS_VOLATILE (t))
{
if (flags & tf_error)
@@ -7235,8 +7246,18 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
switch (TREE_CODE (t))
{
case FUNCTION_DECL:
+ case BASELINK:
+ case OVERLOAD:
+ case TEMPLATE_ID_EXPR:
case LABEL_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;
case PARM_DECL:
@@ -7261,7 +7282,7 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
const int nargs = call_expr_nargs (t);
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. */
return true;
if (flags & tf_error)
@@ -7293,11 +7314,9 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
if (i == 0 && DECL_NONSTATIC_MEMBER_P (fun)
&& !DECL_CONSTRUCTOR_P (fun))
{
- if (TREE_CODE (x) == ADDR_EXPR)
- x = TREE_OPERAND (x, 0);
if (is_this_parameter (x))
/* OK. */;
- else if (!potential_constant_expression (x, flags))
+ else if (!potential_constant_expression_1 (x, rval, flags))
{
if (flags & tf_error)
error ("object argument is not a potential constant "
@@ -7305,7 +7324,7 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
return false;
}
}
- else if (!potential_constant_expression (x, flags))
+ else if (!potential_constant_expression_1 (x, rval, flags))
{
if (flags & tf_error)
error ("argument in position %qP is not a "
@@ -7325,10 +7344,10 @@ potential_constant_expression (tree t, 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 (TREE_OPERAND (t, 0), flags);
+ return potential_constant_expression_1 (TREE_OPERAND (t, 0), rval, flags);
case VAR_DECL:
- if (!decl_constant_var_p (t))
+ if (want_rval && !decl_constant_var_p (t))
{
if (flags & tf_error)
error ("variable %qD is not declared constexpr", t);
@@ -7358,7 +7377,8 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
"cannot yield a constant expression", from);
return false;
}
- return potential_constant_expression (from, flags);
+ return (potential_constant_expression_1
+ (from, TREE_CODE (t) != VIEW_CONVERT_EXPR, flags));
}
case ADDR_EXPR:
@@ -7366,6 +7386,10 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
designates an object with thread or automatic storage
duration; */
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);
if (i == ck_ok)
return true;
@@ -7376,15 +7400,23 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
"automatic storage is not a constant expression", t);
return false;
}
- return potential_constant_expression (t, flags);
+#endif
+ return potential_constant_expression_1 (t, any, flags);
case COMPONENT_REF:
case BIT_FIELD_REF:
+ case ARROW_EXPR:
+ case OFFSET_REF:
/* -- a class member access unless its postfix-expression is
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 (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:
{
@@ -7392,7 +7424,7 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
STRIP_NOPS (x);
if (is_this_parameter (x))
return true;
- return potential_constant_expression (x, flags);
+ return potential_constant_expression_1 (x, rval, flags);
}
case LAMBDA_EXPR:
@@ -7417,6 +7449,10 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
case MUST_NOT_THROW_EXPR:
case TRY_CATCH_EXPR:
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:
if (flags & tf_error)
error ("expression %qE is not a constant-expression", t);
@@ -7427,7 +7463,8 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
class type; */
{
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)
error ("typeid-expression is not a constant expression "
@@ -7447,6 +7484,7 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
"a constant expression");
return false;
}
+ want_rval = true;
goto binary;
case LT_EXPR:
@@ -7465,6 +7503,7 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
"constant expression");
return false;
}
+ want_rval = true;
goto binary;
case REALPART_EXPR:
@@ -7477,22 +7516,41 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
case ABS_EXPR:
case BIT_NOT_EXPR:
case TRUTH_NOT_EXPR:
- case PAREN_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. */
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 TARGET_EXPR:
- return potential_constant_expression (TREE_OPERAND (t, 1), flags);
+ return potential_constant_expression_1 (TREE_OPERAND (t, 1),
+ rval, flags);
case CONSTRUCTOR:
{
VEC(constructor_elt, gc) *v = CONSTRUCTOR_ELTS (t);
constructor_elt *ce;
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 true;
}
@@ -7501,11 +7559,13 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
{
gcc_assert (TREE_PURPOSE (t) == NULL_TREE
|| 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;
if (TREE_CHAIN (t) == NULL_TREE)
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:
@@ -7515,10 +7575,24 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
case TRUNC_MOD_EXPR:
case CEIL_MOD_EXPR:
case ROUND_MOD_EXPR:
- if (integer_zerop (maybe_constant_value (TREE_OPERAND (t, 1))))
- return false;
- else
- goto binary;
+ {
+ 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;
+ }
+ else
+ {
+ want_rval = true;
+ goto binary;
+ }
+ }
case COMPOUND_EXPR:
{
@@ -7530,7 +7604,7 @@ potential_constant_expression (tree t, 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 (op0, flags);
+ return potential_constant_expression_1 (op0, want_rval, flags);
else
goto binary;
}
@@ -7547,12 +7621,10 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
tmp = boolean_false_node;
truth:
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
- 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 MULT_EXPR:
case POINTER_PLUS_EXPR:
@@ -7574,10 +7646,16 @@ potential_constant_expression (tree t, tsubst_flags_t flags)
case UNEQ_EXPR:
case RANGE_EXPR:
case COMPLEX_EXPR:
+ want_rval = true;
+ /* Fall through. */
+ case ARRAY_REF:
+ case ARRAY_RANGE_REF:
+ case MEMBER_REF:
+ case DOTSTAR_EXPR:
binary:
for (i = 0; i < 2; ++i)
- if (!potential_constant_expression (TREE_OPERAND (t, i),
- flags))
+ if (!potential_constant_expression_1 (TREE_OPERAND (t, i),
+ want_rval, flags))
return false;
return true;
@@ -7587,21 +7665,28 @@ potential_constant_expression (tree t, 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 (tmp, flags))
+ if (!potential_constant_expression_1 (tmp, rval, flags))
return false;
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)
- 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)
- 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;
if (flags & tf_error)
error ("expression %qE is not a constant-expression", t);
return false;
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:
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)
}
}
+/* 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. */
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 813b88d..1a1f150 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -513,9 +513,13 @@ build_vec_init_expr (tree type, tree init)
SET_EXPR_LOCATION (init, input_location);
if (current_function_decl
- && DECL_DECLARED_CONSTEXPR_P (current_function_decl)
- && potential_constant_expression (elt_init, tf_warning_or_error))
- VEC_INIT_EXPR_IS_CONSTEXPR (init) = true;
+ && DECL_DECLARED_CONSTEXPR_P (current_function_decl))
+ {
+ if (potential_constant_expression (elt_init))
+ 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;
init = build_target_expr (slot, init);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b8962fe..df43d93 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2011-01-21 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/cpp0x/constexpr-stmtexpr.C: New.
+
2011-01-21 Jeff Law <law@redhat.com>
PR rtl-optimization/41619
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-stmtexpr.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-stmtexpr.C
new file mode 100644
index 0000000..40e0c2d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-stmtexpr.C
@@ -0,0 +1,8 @@
+// PR c++/46977
+// { dg-options "-std=c++0x" }
+
+template < typename > void
+foo ()
+{
+ ({int i;}), 0;
+}