public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Fix c++/67371 (issues with throw in constexpr)
@ 2015-08-28 12:25 Markus Trippelsdorf
  2015-08-29  3:44 ` Jason Merrill
  0 siblings, 1 reply; 7+ messages in thread
From: Markus Trippelsdorf @ 2015-08-28 12:25 UTC (permalink / raw)
  To: gcc-patches; +Cc: Jason Merrill

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.

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" }
-- 
Markus

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] Fix c++/67371 (issues with throw in constexpr)
  2015-08-28 12:25 [PATCH] Fix c++/67371 (issues with throw in constexpr) Markus Trippelsdorf
@ 2015-08-29  3:44 ` Jason Merrill
  2015-08-29 10:53   ` [PATCH v2] " Markus Trippelsdorf
  0 siblings, 1 reply; 7+ messages in thread
From: Jason Merrill @ 2015-08-29  3:44 UTC (permalink / raw)
  To: Markus Trippelsdorf, gcc-patches

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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2] Fix c++/67371 (issues with throw in constexpr)
  2015-08-29  3:44 ` Jason Merrill
@ 2015-08-29 10:53   ` Markus Trippelsdorf
  2015-08-29 12:57     ` Markus Trippelsdorf
  2015-08-29 13:20     ` Jason Merrill
  0 siblings, 2 replies; 7+ messages in thread
From: Markus Trippelsdorf @ 2015-08-29 10:53 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches

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.

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" }
-- 
Markus

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2] Fix c++/67371 (issues with throw in constexpr)
  2015-08-29 10:53   ` [PATCH v2] " Markus Trippelsdorf
@ 2015-08-29 12:57     ` Markus Trippelsdorf
  2015-08-29 13:20     ` Jason Merrill
  1 sibling, 0 replies; 7+ messages in thread
From: Markus Trippelsdorf @ 2015-08-29 12:57 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches

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.

-- 
Markus

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2] Fix c++/67371 (issues with throw in constexpr)
  2015-08-29 10:53   ` [PATCH v2] " Markus Trippelsdorf
  2015-08-29 12:57     ` Markus Trippelsdorf
@ 2015-08-29 13:20     ` Jason Merrill
  2015-08-29 15:26       ` [PATCH v3] " Markus Trippelsdorf
  1 sibling, 1 reply; 7+ messages in thread
From: Jason Merrill @ 2015-08-29 13:20 UTC (permalink / raw)
  To: Markus Trippelsdorf; +Cc: gcc-patches

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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3] Fix c++/67371 (issues with throw in constexpr)
  2015-08-29 13:20     ` Jason Merrill
@ 2015-08-29 15:26       ` Markus Trippelsdorf
  2015-08-30  1:04         ` Jason Merrill
  0 siblings, 1 reply; 7+ messages in thread
From: Markus Trippelsdorf @ 2015-08-29 15:26 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches

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.

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" }
-- 
Markus

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3] Fix c++/67371 (issues with throw in constexpr)
  2015-08-29 15:26       ` [PATCH v3] " Markus Trippelsdorf
@ 2015-08-30  1:04         ` Jason Merrill
  0 siblings, 0 replies; 7+ messages in thread
From: Jason Merrill @ 2015-08-30  1:04 UTC (permalink / raw)
  To: Markus Trippelsdorf; +Cc: gcc-patches

OK, thanks!

Jason

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2015-08-29 18:05 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-08-28 12:25 [PATCH] Fix c++/67371 (issues with throw in constexpr) Markus Trippelsdorf
2015-08-29  3:44 ` Jason Merrill
2015-08-29 10:53   ` [PATCH v2] " Markus Trippelsdorf
2015-08-29 12:57     ` Markus Trippelsdorf
2015-08-29 13:20     ` Jason Merrill
2015-08-29 15:26       ` [PATCH v3] " Markus Trippelsdorf
2015-08-30  1:04         ` Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).