diff options
author | Jason Merrill <jason@redhat.com> | 2015-05-31 16:36:26 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2015-05-31 16:36:26 -0400 |
commit | 255a48d6419c185cd9daac578a97b22e2c71b596 (patch) | |
tree | d2930a0386034be26192a26f7221648d0aeef4a8 | |
parent | 6ad6af49da1d0e069cb828fa2a8b846b326caada (diff) | |
download | gcc-255a48d6419c185cd9daac578a97b22e2c71b596.zip gcc-255a48d6419c185cd9daac578a97b22e2c71b596.tar.gz gcc-255a48d6419c185cd9daac578a97b22e2c71b596.tar.bz2 |
* constexpr.c (cxx_eval_indirect_ref): Try folding first.
From-SVN: r223902
-rw-r--r-- | gcc/cp/ChangeLog | 2 | ||||
-rw-r--r-- | gcc/cp/constexpr.c | 73 |
2 files changed, 41 insertions, 34 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5029f83..467449c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,7 @@ 2015-05-31 Jason Merrill <jason@redhat.com> + * constexpr.c (cxx_eval_indirect_ref): Try folding first. + PR c++/66320 * constexpr.c (cxx_eval_constant_expression): Treat a placeholder with the wrong type as non-constant. diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index f343ea7..ff5489f 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -2427,42 +2427,55 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t, bool *non_constant_p, bool *overflow_p) { tree orig_op0 = TREE_OPERAND (t, 0); - tree op0 = cxx_eval_constant_expression (ctx, orig_op0, - /*lval*/false, non_constant_p, - overflow_p); bool empty_base = false; - tree r; - - /* Don't VERIFY_CONSTANT here. */ - if (*non_constant_p) - return t; - - r = cxx_fold_indirect_ref (EXPR_LOCATION (t), TREE_TYPE (t), op0, - &empty_base); - if (r) - r = cxx_eval_constant_expression (ctx, r, - lval, non_constant_p, overflow_p); - else + /* First try to simplify it directly. */ + tree r = cxx_fold_indirect_ref (EXPR_LOCATION (t), TREE_TYPE (t), orig_op0, + &empty_base); + if (!r) { - tree sub = op0; - STRIP_NOPS (sub); - if (TREE_CODE (sub) == ADDR_EXPR) + /* If that didn't work, evaluate the operand first. */ + tree op0 = cxx_eval_constant_expression (ctx, orig_op0, + /*lval*/false, non_constant_p, + overflow_p); + /* Don't VERIFY_CONSTANT here. */ + if (*non_constant_p) + return t; + + r = cxx_fold_indirect_ref (EXPR_LOCATION (t), TREE_TYPE (t), op0, + &empty_base); + if (r == NULL_TREE) { /* We couldn't fold to a constant value. Make sure it's not something we should have been able to fold. */ - gcc_assert (!same_type_ignoring_top_level_qualifiers_p - (TREE_TYPE (TREE_TYPE (sub)), TREE_TYPE (t))); - /* DR 1188 says we don't have to deal with this. */ - if (!ctx->quiet) - error ("accessing value of %qE through a %qT glvalue in a " - "constant expression", build_fold_indirect_ref (sub), - TREE_TYPE (t)); - *non_constant_p = true; + tree sub = op0; + STRIP_NOPS (sub); + if (TREE_CODE (sub) == ADDR_EXPR) + { + gcc_assert (!same_type_ignoring_top_level_qualifiers_p + (TREE_TYPE (TREE_TYPE (sub)), TREE_TYPE (t))); + /* DR 1188 says we don't have to deal with this. */ + if (!ctx->quiet) + error ("accessing value of %qE through a %qT glvalue in a " + "constant expression", build_fold_indirect_ref (sub), + TREE_TYPE (t)); + *non_constant_p = true; + return t; + } + + if (lval && op0 != orig_op0) + return build1 (INDIRECT_REF, TREE_TYPE (t), op0); + if (!lval) + VERIFY_CONSTANT (t); return t; } } + r = cxx_eval_constant_expression (ctx, r, + lval, non_constant_p, overflow_p); + if (*non_constant_p) + return t; + /* If we're pulling out the value of an empty base, make sure that the whole object is constant and then return an empty CONSTRUCTOR. */ @@ -2473,14 +2486,6 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t, TREE_CONSTANT (r) = true; } - if (r == NULL_TREE) - { - if (lval && op0 != orig_op0) - return build1 (INDIRECT_REF, TREE_TYPE (t), op0); - if (!lval) - VERIFY_CONSTANT (t); - return t; - } return r; } |