This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH for c++/66320 (ICE with NSDMI)
- From: Jason Merrill <jason at redhat dot com>
- To: gcc-patches List <gcc-patches at gcc dot gnu dot org>
- Date: Sun, 31 May 2015 16:36:05 -0400
- Subject: C++ PATCH for c++/66320 (ICE with NSDMI)
- Authentication-results: sourceware.org; auth=none
When we are actually evaluating an NSDMI in a constexpr constructor,
ctx->ctor has the type of the complete object, but when we're just
checking whether the NSDMI by itself is constant, we ctx->ctor just has
the type of the data member, so references to other data members will
end up looking at a PLACEHOLDER_EXPR with a type that doesn't match
what's expected. We should deal with this in the code we already have
for this context.
The second patch tries to fold away *& before evaluating it.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit 5ee8908ce2d9e6f4d6e3fc00607bfdce5593f094
Author: Jason Merrill <jason@redhat.com>
Date: Thu May 28 13:25:16 2015 -0400
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 f35ec1e..f343ea7 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -3458,7 +3458,9 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
break;
case PLACEHOLDER_EXPR:
- if (!ctx || !ctx->ctor || (lval && !ctx->object))
+ if (!ctx || !ctx->ctor || (lval && !ctx->object)
+ || !(same_type_ignoring_top_level_qualifiers_p
+ (TREE_TYPE (t), TREE_TYPE (ctx->ctor))))
{
/* A placeholder without a referent. We can get here when
checking whether NSDMIs are noexcept, or in massage_init_elt;
@@ -3473,8 +3475,6 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
use ctx->object unconditionally, but using ctx->ctor when we
can is a minor optimization. */
tree ctor = lval ? ctx->object : ctx->ctor;
- gcc_assert (same_type_ignoring_top_level_qualifiers_p
- (TREE_TYPE (t), TREE_TYPE (ctor)));
return cxx_eval_constant_expression
(ctx, ctor, lval,
non_constant_p, overflow_p);
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi11.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi11.C
new file mode 100644
index 0000000..29942b0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi11.C
@@ -0,0 +1,23 @@
+// PR c++/66320
+// { dg-do compile { target c++11 } }
+
+class A
+{
+ virtual int m_fn1 ();
+};
+class B
+{
+public:
+ B (int);
+};
+class D : B
+{
+ struct C
+ {
+ A a;
+ A b = a;
+ };
+ D (int *);
+ C _channels;
+};
+D::D (int *) : B (0) {}
commit 2d17b9feb4cb2a75d3a7f25318a59074be21cf31
Author: Jason Merrill <jason@redhat.com>
Date: Thu May 28 13:50:51 2015 -0400
* constexpr.c (cxx_eval_indirect_ref): Try folding first.
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;
}