diff mbox

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

Message ID 20150828120003.GA421@x4
State New
Headers show

Commit Message

Markus Trippelsdorf Aug. 28, 2015, noon UTC
As PR67371 shows gcc currently rejects all throw statements in
constant-expressions, even when they are never executed.

Fix by simply allowing THROW_EXPR in potential_constant_expression_1.

One drawback is that we now accept some ill formed cases, but they 
fall under the "no diagnostic required" rule in the standard, e.g.:

constexpr int f1() {
  throw;
  return 0;
}

or 

constexpr void f2() {
  throw;
}

Tested on ppc64le.
OK for trunk?

Thanks.

	PR c++/67371
	* constexpr.c (potential_constant_expression_1): Allow THROW_EXPR.

Comments

Jason Merrill Aug. 29, 2015, 2:23 a.m. UTC | #1
On 08/28/2015 08:00 AM, Markus Trippelsdorf wrote:
> As PR67371 shows gcc currently rejects all throw statements in
> constant-expressions, even when they are never executed.
>
> Fix by simply allowing THROW_EXPR in potential_constant_expression_1.
>
> One drawback is that we now accept some ill formed cases, but they
> fall under the "no diagnostic required" rule in the standard, e.g.:

I think we can do better.

The handling of IF_STMT in potential_constant_expression_1 currently 
returns false if either the then or the else clauses are problematic, 
but instead it should return true if either of them are OK (or empty).

We could try to analyze the body of a SWITCH_STMT more closely, but if 
you don't want to try it's fine if we just assume that the body is OK.

Jason
diff mbox

Patch

diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 1eacb8be9a44..34c503ab2bc4 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -4043,6 +4043,7 @@  potential_constant_expression_1 (tree t, bool want_rval, bool strict,
     case BREAK_STMT:
     case CONTINUE_STMT:
     case REQUIRES_EXPR:
+    case THROW_EXPR:
       return true;
 
     case AGGR_INIT_EXPR:
@@ -4324,7 +4325,6 @@  potential_constant_expression_1 (tree t, bool want_rval, bool strict,
     case VEC_NEW_EXPR:
     case DELETE_EXPR:
     case VEC_DELETE_EXPR:
-    case THROW_EXPR:
     case OMP_ATOMIC:
     case OMP_ATOMIC_READ:
     case OMP_ATOMIC_CAPTURE_OLD:
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..09a3e618f8a2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-throw.C
@@ -0,0 +1,17 @@ 
+// { dg-do compile { target c++14 } }
+constexpr void f() {
+  if (false)
+    throw;
+}
+
+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 condition" }