aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2015-05-31 16:36:26 -0400
committerJason Merrill <jason@gcc.gnu.org>2015-05-31 16:36:26 -0400
commit255a48d6419c185cd9daac578a97b22e2c71b596 (patch)
treed2930a0386034be26192a26f7221648d0aeef4a8
parent6ad6af49da1d0e069cb828fa2a8b846b326caada (diff)
downloadgcc-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/ChangeLog2
-rw-r--r--gcc/cp/constexpr.c73
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;
}