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

Reply via email to