| Submitter | Jason Merrill |
|---|---|
| Date | Jan. 21, 2011, 5:20 p.m. |
| Message ID | <4D39C06E.9040401@redhat.com> |
| Download | mbox | patch |
| Permalink | /patch/79868/ |
| State | New |
| Headers | show |
Comments
On Fri, Jan 21, 2011 at 9:20 AM, Jason Merrill <jason@redhat.com> wrote: > The crash here came because we were trying to fold_non_dependent_expr the > statement-expression, which meant testing it for value-dependence, which > crashed because value_dependent_expression_p doesn't know how to handle > STMT_EXPR. > > The second patch, which I'm checking in, improves > potential_constant_expression to be a predicate that we can use on template > expressions in C++0x mode to determine whether or not the expression could > possibly be a constant expression. In C++98 mode it always returns true, as > we filtered out unsuitable expressions earlier in the parser. > > Tested x86_64-pc-linux-gnu, applied to trunk. > > diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog > index 2491047..21dce62 100644 > --- a/gcc/cp/ChangeLog > +++ b/gcc/cp/ChangeLog > @@ -1,5 +1,17 @@ > 2011-01-17 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. > + This patch caused: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47511
Patch
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 16bd2a0..32b2520 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -18142,6 +18142,11 @@ value_dependent_expression_p (tree expression) return false; } + case STMT_EXPR: + /* Return true for a statement-expression. FIXME this isn't + value-dependent, it's non-constant. */ + return true; + default: /* A constant expression is value-dependent if any subexpression is value-dependent. */ 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; +}
The crash here came because we were trying to fold_non_dependent_expr the statement-expression, which meant testing it for value-dependence, which crashed because value_dependent_expression_p doesn't know how to handle STMT_EXPR. The simple fix (the first patch) is just to add STMT_EXPR to value_dependent_expression_p so we don't crash. But this is really just papering over the underlying problem: we shouldn't be testing for value-dependence of non-constant-expressions, as value dependence is a property of constant expressions, not expressions in general. The second patch, which I'm checking in, improves potential_constant_expression to be a predicate that we can use on template expressions in C++0x mode to determine whether or not the expression could possibly be a constant expression. In C++98 mode it always returns true, as we filtered out unsuitable expressions earlier in the parser. Tested x86_64-pc-linux-gnu, applied to trunk. commit 44b8b455b98d1152c9f5362e52393f24e7e04841 Author: Jason Merrill <jason@redhat.com> Date: Fri Jan 14 18:30:41 2011 -0500 PR c++/46977 * pt.c (value_dependent_expression_p): Return true for STMT_EXPR. diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 2491047..21dce62 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,17 @@ 2011-01-17 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. + PR c++/47067 * semantics.c (base_field_constructor_elt): New fn. (cxx_eval_bare_aggregate): Use it. 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 16bd2a0..fb12382 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..fa35d4a 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; @@ -7023,6 +7024,7 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t, case NON_DEPENDENT_EXPR: case BASELINK: case EXPR_STMT: + case OFFSET_REF: if (!allow_non_constant) error_at (EXPR_LOC_OR_HERE (t), "expression %qE is not a constant-expression", t); @@ -7115,8 +7117,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 +7149,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 +7173,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 +7201,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 +7218,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 +7247,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 +7283,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 +7315,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 +7325,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 +7345,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 +7378,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 +7387,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 +7401,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 +7425,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 +7450,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 +7464,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 +7485,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 +7504,7 @@ potential_constant_expression (tree t, tsubst_flags_t flags) "constant expression"); return false; } + want_rval = true; goto binary; case REALPART_EXPR: @@ -7477,22 +7517,41 @@ potential_constant_expression (tree t, tsubst_flags_t flags) case ABS_EXPR: case BIT_NOT_EXPR: case TRUTH_NOT_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 FIXED_CONVERT_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 +7560,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 +7576,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 +7605,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,37 +7622,41 @@ 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 PLUS_EXPR: + case MULT_EXPR: + case POINTER_PLUS_EXPR: + case RDIV_EXPR: + case EXACT_DIV_EXPR: + case MIN_EXPR: + case MAX_EXPR: + case LSHIFT_EXPR: + case RSHIFT_EXPR: + case LROTATE_EXPR: + case RROTATE_EXPR: + case BIT_IOR_EXPR: + case BIT_XOR_EXPR: + case BIT_AND_EXPR: + case UNLT_EXPR: + case UNLE_EXPR: + case UNGT_EXPR: + case UNGE_EXPR: + case UNEQ_EXPR: + case RANGE_EXPR: + case COMPLEX_EXPR: + want_rval = true; + /* Fall through. */ case ARRAY_REF: case ARRAY_RANGE_REF: - case PLUS_EXPR: - case MULT_EXPR: - case POINTER_PLUS_EXPR: - case RDIV_EXPR: - case EXACT_DIV_EXPR: - case MIN_EXPR: - case MAX_EXPR: - case LSHIFT_EXPR: - case RSHIFT_EXPR: - case LROTATE_EXPR: - case RROTATE_EXPR: - case BIT_IOR_EXPR: - case BIT_XOR_EXPR: - case BIT_AND_EXPR: - case UNLT_EXPR: - case UNLE_EXPR: - case UNGT_EXPR: - case UNGE_EXPR: - case UNEQ_EXPR: - case RANGE_EXPR: - case COMPLEX_EXPR: + 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 +7666,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 +7696,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 e12ba4c..29d316c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,7 @@ 2011-01-17 Jason Merrill <jason@redhat.com> + * g++.dg/cpp0x/constexpr-stmtexpr.C: New. + * g++.dg/cpp0x/constexpr-virtual.C: New. 2011-01-17 Jakub Jelinek <jakub@redhat.com> 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; +}