The representation of delete[] causes the constexpr machinery to ICE.
That's a separate bug worth fixing, but for GCC 6 it's simpler to stop
when we see the wrapper, and also gives a better diagnostic.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit 3cf04bc44a26e84e8c88231572baadb465c70ed3
Author: Jason Merrill <ja...@redhat.com>
Date: Tue Mar 1 09:08:37 2016 -0500
PR c++/69203
* cp-tree.h (COND_EXPR_IS_VEC_DELETE): New.
* init.c (build_vec_delete_1): Set it.
* constexpr.c (potential_constant_expression_1) [COND_EXPR]: Check it.
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index d308175..c9f9c47 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -4885,8 +4885,16 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict,
return false;
return true;
+ case COND_EXPR:
+ if (COND_EXPR_IS_VEC_DELETE (t))
+ {
+ if (flags & tf_error)
+ error_at (location_of (t),
+ "%<delete[]%> is not a constant-expression");
+ return false;
+ }
+ /* Fall through. */
case IF_STMT:
- case COND_EXPR:
case VEC_COND_EXPR:
/* If the condition is a known constant, we know which of the legs we
care about; otherwise we only require that the condition and
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index b1dc23c..9c7f0cc 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -107,6 +107,7 @@ operator == (const cp_expr &lhs, tree rhs)
/* Usage of TREE_LANG_FLAG_?:
0: IDENTIFIER_MARKED (IDENTIFIER_NODEs)
NEW_EXPR_USE_GLOBAL (in NEW_EXPR).
+ COND_EXPR_IS_VEC_DELETE (in COND_EXPR).
DELETE_EXPR_USE_GLOBAL (in DELETE_EXPR).
COMPOUND_EXPR_OVERLOADED (in COMPOUND_EXPR).
CLEANUP_P (in TRY_BLOCK)
@@ -404,6 +405,9 @@ typedef struct ptrmem_cst * ptrmem_cst_t;
#define STMT_EXPR_NO_SCOPE(NODE) \
TREE_LANG_FLAG_0 (STMT_EXPR_CHECK (NODE))
+#define COND_EXPR_IS_VEC_DELETE(NODE) \
+ TREE_LANG_FLAG_0 (COND_EXPR_CHECK (NODE))
+
/* Returns nonzero iff TYPE1 and TYPE2 are the same type, in the usual
sense of `same'. */
#define same_type_p(TYPE1, TYPE2) \
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 43f854c..1ba3c59 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -3685,6 +3685,7 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
TREE_NO_WARNING (cond) = 1;
body = build3_loc (input_location, COND_EXPR, void_type_node,
cond, body, integer_zero_node);
+ COND_EXPR_IS_VEC_DELETE (body) = true;
body = build1 (NOP_EXPR, void_type_node, body);
if (controller)
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-delete2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-delete2.C
new file mode 100644
index 0000000..4a453a4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-delete2.C
@@ -0,0 +1,12 @@
+// PR c++/69203
+// { dg-do compile { target c++11 } }
+
+struct A { ~A(); };
+constexpr int f(int i) { return i; }
+constexpr int g(A* ap)
+{
+ return f((delete[] ap, 42)); // { dg-message "" }
+}
+
+A a;
+constexpr int i = g(&a); // { dg-error "" }