diff options
author | Jason Merrill <jason@redhat.com> | 2011-01-21 12:38:02 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2011-01-21 12:38:02 -0500 |
commit | d6ed1c8903e728f4233122554bab5910853338bd (patch) | |
tree | 95871ccf683cdcd1cc68588d8d01c44cb12a7588 /gcc | |
parent | e90b336fce3f8e4fe7c65301da0a48da3d9e455c (diff) | |
download | gcc-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/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 3 | ||||
-rw-r--r-- | gcc/cp/pt.c | 11 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 194 | ||||
-rw-r--r-- | gcc/cp/tree.c | 10 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/constexpr-stmtexpr.C | 8 |
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; +} |