diff mbox

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

Message ID 20150829101410.GA421@x4
State New
Headers show

Commit Message

Markus Trippelsdorf Aug. 29, 2015, 10:14 a.m. UTC
On 2015.08.28 at 22:23 -0400, Jason Merrill wrote:
> 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.

Ok. Thank you for the suggestions.

I've tested the patch below on ppc64le.

OK for trunk?
Thanks.

	PR c++/67371
	* constexpr.c (potential_constant_expression_1): Guard THEN_CLAUSE
	and ELSE_CLAUSE checking. Remove SWITCH_STMT body checking.

Comments

Markus Trippelsdorf Aug. 29, 2015, 10:53 a.m. UTC | #1
On 2015.08.29 at 12:14 +0200, Markus Trippelsdorf wrote:
> index 1eacb8be9a44..29a7f1f22169 100644
> --- a/gcc/cp/constexpr.c
> +++ b/gcc/cp/constexpr.c
> @@ -4276,10 +4276,10 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict,
>      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;
> +      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;

Sorry for messing up the formating of the return statements. I've fixed
this locally already.
Jason Merrill Aug. 29, 2015, 1:08 p.m. UTC | #2
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.

Jason
diff mbox

Patch

diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 1eacb8be9a44..29a7f1f22169 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -4276,10 +4276,10 @@  potential_constant_expression_1 (tree t, bool want_rval, bool strict,
     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;
+      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;
       return true;
 
     case DO_STMT:
@@ -4310,8 +4310,6 @@  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;
       return true;
 
     case STMT_EXPR:
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" }