]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/65985 (compiler segfault with assert() in constexpr constructor body)
authorJason Merrill <jason@redhat.com>
Thu, 18 Feb 2016 05:08:09 +0000 (00:08 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 18 Feb 2016 05:08:09 +0000 (00:08 -0500)
PR c++/65985
* constexpr.c (build_constexpr_constructor_member_initializers):
Handle an additional STATEMENT_LIST.

From-SVN: r233514

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

index 963ba5a5644e08884d1a2e0ccfb198af6dddf677..18f80729b78c65c024e2fe6828841d7c617cb757 100644 (file)
@@ -1,5 +1,9 @@
 2016-02-17  Jason Merrill  <jason@redhat.com>
 
+       PR c++/65985
+       * constexpr.c (build_constexpr_constructor_member_initializers):
+       Handle an additional STATEMENT_LIST.
+
        PR c++/68585
        * constexpr.c (cxx_eval_bare_aggregate): Fix 'changed' detection.
 
index 0eedfca6663af5a210038055f98250668ca1b462..d3b04b11e803cb0efab4672f7fa052aebc7c4bb2 100644 (file)
@@ -528,21 +528,32 @@ build_constexpr_constructor_member_initializers (tree type, tree body)
 {
   vec<constructor_elt, va_gc> *vec = NULL;
   bool ok = true;
-  if (TREE_CODE (body) == MUST_NOT_THROW_EXPR
-      || TREE_CODE (body) == EH_SPEC_BLOCK)
-    body = TREE_OPERAND (body, 0);
-  if (TREE_CODE (body) == STATEMENT_LIST)
-    {
-      for (tree_stmt_iterator i = tsi_start (body);
-          !tsi_end_p (i); tsi_next (&i))
-       {
-         body = tsi_stmt (i);
-         if (TREE_CODE (body) == BIND_EXPR)
-           break;
-       }
+  while (true)
+    switch (TREE_CODE (body))
+      {
+      case MUST_NOT_THROW_EXPR:
+      case EH_SPEC_BLOCK:
+       body = TREE_OPERAND (body, 0);
+       break;
+
+      case STATEMENT_LIST:
+       for (tree_stmt_iterator i = tsi_start (body);
+            !tsi_end_p (i); tsi_next (&i))
+         {
+           body = tsi_stmt (i);
+           if (TREE_CODE (body) == BIND_EXPR)
+             break;
+         }
+       break;
+
+      case BIND_EXPR:
+       body = BIND_EXPR_BODY (body);
+       goto found;
+
+      default:
+       gcc_unreachable ();
     }
-  if (TREE_CODE (body) == BIND_EXPR)
-    body = BIND_EXPR_BODY (body);
+ found:
   if (TREE_CODE (body) == CLEANUP_POINT_EXPR)
     {
       body = TREE_OPERAND (body, 0);
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-assert2.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-assert2.C
new file mode 100644 (file)
index 0000000..a329101
--- /dev/null
@@ -0,0 +1,31 @@
+// PR c++/65985
+// { dg-do compile { target c++14 } }
+
+#include <cassert>
+
+class Angle
+{
+  int degrees = 0;
+
+  constexpr auto invariant() const noexcept
+  {
+    return 0 <= degrees && degrees < 360;
+  }
+
+public:
+  explicit constexpr Angle(int n) noexcept
+    : degrees{n % 360}
+  {
+    assert(invariant());
+  }
+
+  /* implicit */ constexpr operator auto() const noexcept
+  {
+    return degrees;
+  }
+};
+
+int main()
+{
+  static_assert(Angle{360} == 0, "");
+}