diff mbox

[v3] Fix c++/67371 (issues with throw in constexpr)

Message ID 20150829142038.GC421@x4
State New
Headers show

Commit Message

Markus Trippelsdorf Aug. 29, 2015, 2:20 p.m. UTC
On 2015.08.29 at 09:08 -0400, Jason Merrill wrote:
> On 08/29/2015 06:14 AM, Markus Trippelsdorf wrote:
> > +      if (integer_nonzerop (IF_COND (t)) && !RECUR (THEN_CLAUSE (t), any))
> > +	      return false;
> > +      if (integer_zerop (IF_COND (t)) && !RECUR (ELSE_CLAUSE (t), any))
> > +	      return false;
> 
> Actually, I think we can remove the IF_STMT code entirely and move the 
> case label to the COND_EXPR case.
> 
> Also, please add a comment explaining why we aren't checking 
> SWITCH_STMT_BODY.

Done and tested on ppc64le.

	PR c++/67371
	* constexpr.c (potential_constant_expression_1): Remove IF_STMT
	case. Move label to COND_EXPR case. Remove checking of
	SWITCH_STMT_BODY.

Comments

Jason Merrill Aug. 29, 2015, 6:05 p.m. UTC | #1
OK, thanks!

Jason
diff mbox

Patch

diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 1eacb8be9a44..0ff9b088cc26 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -4273,15 +4273,6 @@  potential_constant_expression_1 (tree t, bool want_rval, bool strict,
 	return false;
       return true;
 
-    case IF_STMT:
-      if (!RECUR (IF_COND (t), rval))
-	return false;
-      if (!RECUR (THEN_CLAUSE (t), any))
-	return false;
-      if (!RECUR (ELSE_CLAUSE (t), any))
-	return false;
-      return true;
-
     case DO_STMT:
       if (!RECUR (DO_COND (t), rval))
 	return false;
@@ -4310,8 +4301,8 @@  potential_constant_expression_1 (tree t, bool want_rval, bool strict,
     case SWITCH_STMT:
       if (!RECUR (SWITCH_STMT_COND (t), rval))
 	return false;
-      if (!RECUR (SWITCH_STMT_BODY (t), any))
-	return false;
+      /* FIXME we don't check SWITCH_STMT_BODY currently, because even
+	 unreachable labels would be checked.  */
       return true;
 
     case STMT_EXPR:
@@ -4592,6 +4583,7 @@  potential_constant_expression_1 (tree t, bool want_rval, bool strict,
 	return false;
      return true;
 
+    case IF_STMT:
     case COND_EXPR:
     case VEC_COND_EXPR:
       /* If the condition is a known constant, we know which of the legs we
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-new.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-new.C
new file mode 100644
index 000000000000..7241fefc41e5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-new.C
@@ -0,0 +1,11 @@ 
+// { dg-do compile { target c++14 } }
+
+constexpr int *f4(bool b) {
+  if (b) {
+    return nullptr;
+  } else {
+    return new int{42}; // { dg-error "call to non-constexpr" }
+  }
+}
+static_assert(f4(true) == nullptr, "");
+static_assert(f4(false) == nullptr, ""); // { dg-error "non-constant condition" }
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-throw.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-throw.C
new file mode 100644
index 000000000000..ac90051d5e99
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-throw.C
@@ -0,0 +1,34 @@ 
+// { dg-do compile { target c++14 } }
+
+constexpr void f1() {
+  if (false)
+    throw;
+}
+
+constexpr void f2() {
+  if (true)
+    throw;
+} // { dg-error "not a constant-expression" }
+
+constexpr void f3() {
+  if (false)
+    ;
+  else
+    throw;
+}// { dg-error "not a constant-expression" }
+
+constexpr void f4() {
+  throw;
+}// { dg-error "not a constant-expression" }
+
+constexpr int fun(int n) {
+  switch (n) {
+  case 0:
+    return 1;
+  default:
+    throw; // { dg-error "not a constant-expression" }
+  }
+}
+
+static_assert(fun(0), "");
+static_assert(fun(1), ""); // { dg-error "non-constant" }