Fix c++/67371 (issues with throw in constexpr)
authortrippels <trippels@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 29 Aug 2015 18:51:26 +0000 (18:51 +0000)
committertrippels <trippels@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 29 Aug 2015 18:51:26 +0000 (18:51 +0000)
As PR67371 shows gcc currently rejects all throw statements in
constant-expressions, even when they are never executed.

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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@227323 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/constexpr.c
gcc/testsuite/g++.dg/cpp1y/constexpr-new.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/constexpr-throw.C [new file with mode: 0644]

index b5a3398..7cbfa65 100644 (file)
@@ -1,3 +1,10 @@
+2015-08-29  Markus Trippelsdorf  <markus@trippelsdorf.de>
+
+       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.
+
 2015-08-22  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/63693
index 1eacb8b..0ff9b08 100644 (file)
@@ -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 (file)
index 0000000..7241fef
--- /dev/null
@@ -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 (file)
index 0000000..ac90051
--- /dev/null
@@ -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" }